Socket
Socket
Sign inDemoInstall

webidl2js

Package Overview
Dependencies
Maintainers
6
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

webidl2js - npm Package Compare versions

Comparing version 9.0.0 to 9.0.1

106

lib/constructs/attribute.js

@@ -18,3 +18,2 @@ "use strict";

generate() {
let str = "";
const requires = new utils.RequiresMap(this.ctx);

@@ -26,7 +25,7 @@

const onInstance = utils.isOnInstance(this.idl, this.interface.idl);
let objName = `this`;
let definedOn = this.interface.name + (this.static ? "" : ".prototype");
if (utils.isOnInstance(this.idl, this.interface.idl)) { // we're in a setup method
if (onInstance) { // we're in a setup method
objName = `obj`;
definedOn = `obj`;
}

@@ -44,2 +43,6 @@ let brandCheck = `

const addMethod = this.static ?
this.interface.addStaticMethod.bind(this.interface) :
this.interface.addMethod.bind(this.interface, onInstance ? "instance" : "prototype");
if (this.static) {

@@ -66,9 +69,7 @@ brandCheck = "";

str += `
Object.defineProperty(${definedOn}, "${this.idl.name}", {
get() {
${brandCheck}
${getterBody}
},
`;
addMethod(this.idl.name, [], `
${brandCheck}
${getterBody}
`, "get", { configurable });
if (!this.idl.readonly) {

@@ -92,66 +93,35 @@ let idlConversion;

}
str += `
set(V) {
${brandCheck}
${idlConversion}
${setterBody}
},
`;
addMethod(this.idl.name, ["V"], `
${brandCheck}
${idlConversion}
${setterBody}
`, "set", { configurable });
} else if (utils.getExtAttr(this.idl.extAttrs, "PutForwards")) {
str += `
set(V) {
${brandCheck}
this.${this.idl.name}.${utils.getExtAttr(this.idl.extAttrs, "PutForwards").rhs.value} = V;
},
`;
addMethod(this.idl.name, ["V"], `
${brandCheck}
this.${this.idl.name}.${utils.getExtAttr(this.idl.extAttrs, "PutForwards").rhs.value} = V;
`, "set", { configurable });
} else if (utils.getExtAttr(this.idl.extAttrs, "Replaceable")) {
str += `
set(V) {
${brandCheck}
Object.defineProperty(this, "${this.idl.name}", {
configurable: true,
enumerable: true,
value: V,
writable: true
});
},
`;
addMethod(this.idl.name, ["V"], `
${brandCheck}
Object.defineProperty(this, "${this.idl.name}", {
configurable: true,
enumerable: true,
value: V,
writable: true
});
`, "set", { configurable });
}
str += `
enumerable: true,
configurable: ${JSON.stringify(configurable)}
});
`;
if (this.idl.stringifier) {
const functionExpression = `
function toString() {
if (!this || !module.exports.is(this)) {
throw new TypeError("Illegal invocation");
}
${getterBody};
if (!this.static && this.idl.stringifier) {
addMethod("toString", [], `
if (!this || !module.exports.is(this)) {
throw new TypeError("Illegal invocation");
}
`;
if (utils.getExtAttr(this.idl.extAttrs, "Unforgeable")) {
str += `
Object.defineProperty(${definedOn}, "toString", {
writable: false,
enumerable: true,
configurable: false,
value: ${functionExpression}
});
`;
} else {
str += `
${definedOn}.toString = ${functionExpression};
`;
}
str += "\n";
${getterBody};
`, "regular", { configurable, writable: configurable });
}
return {
requires,
body: str
};
return { requires };
}

@@ -158,0 +128,0 @@ }

@@ -15,16 +15,11 @@ "use strict";

generate() {
const body = `
Object.defineProperty(${this.interface.name}, "${this.idl.name}", {
value: ${utils.getDefault(this.idl.value)},
enumerable: true
});
Object.defineProperty(${this.interface.name}.prototype, "${this.idl.name}", {
value: ${utils.getDefault(this.idl.value)},
enumerable: true
});
`;
return {
requires: new utils.RequiresMap(this.ctx),
body
};
this.interface.addStaticProperty(this.idl.name, utils.getDefault(this.idl.value), {
configurable: false,
writable: false
});
this.interface.addProperty(this.interface.defaultWhence, this.idl.name, utils.getDefault(this.idl.value), {
configurable: false,
writable: false
});
return { requires: new utils.RequiresMap(this.ctx) };
}

@@ -31,0 +26,0 @@ }

@@ -20,2 +20,46 @@ "use strict";

function formatArgs(args) {
return args.map(name => name + (keywords.has(name) ? "_" : "")).join(", ");
}
const defaultDefinePropertyDescriptor = {
configurable: false,
enumerable: false,
writable: false
};
const defaultObjectLiteralDescriptor = {
configurable: true,
enumerable: true,
writable: true
};
const defaultClassMethodDescriptor = {
configurable: true,
enumerable: false,
writable: true
};
// type can be "accessor" or "regular"
function getPropertyDescriptorModifier(currentDesc, targetDesc, type, value = undefined) {
const changes = [];
if (value !== undefined) {
changes.push(`value: ${value}`);
}
if (currentDesc.configurable !== targetDesc.configurable) {
changes.push(`configurable: ${targetDesc.configurable}`);
}
if (currentDesc.enumerable !== targetDesc.enumerable) {
changes.push(`enumerable: ${targetDesc.enumerable}`);
}
if (type !== "accessor" && currentDesc.writable !== targetDesc.writable) {
changes.push(`writable: ${targetDesc.writable}`);
}
if (changes.length === 0) {
return undefined;
}
return `{ ${changes.join(", ")} }`;
}
class Interface {

@@ -51,4 +95,97 @@ constructor(ctx, idl, opts) {

this._analyzed = false;
this._outputMethods = new Map();
this._outputStaticMethods = new Map();
this._outputProperties = new Map();
this._outputStaticProperties = new Map();
const global = utils.getExtAttr(this.idl.extAttrs, "Global");
this.isGlobal = Boolean(global);
if (global && (!global.rhs || global.arguments)) {
throw new Error(`[Global] must take an identifier or an identifier list in interface ${this.name}`);
}
}
// whence is either "instance" or "prototype"
// type is either "regular", "get", or "set"
addMethod(whence, propName, args, body, type = "regular", {
configurable = true,
enumerable = typeof propName === "string",
writable = type === "regular" ? true : undefined
} = {}) {
if (whence !== "instance" && whence !== "prototype") {
throw new Error(`Internal error: Invalid whence ${whence}`);
}
if (type !== "regular") {
const existing = this._outputMethods.get(propName);
if (existing !== undefined) {
if (type === "get") {
existing.body[0] = body;
} else {
existing.args = args;
existing.body[1] = body;
}
return;
}
const pair = new Array(2);
pair[type === "get" ? 0 : 1] = body;
body = pair;
type = "accessor";
}
const descriptor = { configurable, enumerable, writable };
this._outputMethods.set(propName, { whence, type, args, body, descriptor });
}
// type is either "regular", "get", or "set"
addStaticMethod(propName, args, body, type = "regular", {
configurable = true,
enumerable = typeof propName === "string",
writable = type === "regular" ? true : undefined
} = {}) {
if (type !== "regular") {
const existing = this._outputStaticMethods.get(propName);
if (existing !== undefined) {
if (type === "get") {
existing.body[0] = body;
} else {
existing.args = args;
existing.body[1] = body;
}
return;
}
const pair = new Array(2);
pair[type === "get" ? 0 : 1] = body;
body = pair;
type = "accessor";
}
const descriptor = { configurable, enumerable, writable };
this._outputStaticMethods.set(propName, { type, args, body, descriptor });
}
// whence is either "instance" or "prototype"
addProperty(whence, propName, str, {
configurable = true,
enumerable = typeof propName === "string",
writable = true
} = {}) {
if (whence !== "instance" && whence !== "prototype") {
throw new Error(`Internal error: Invalid whence ${whence}`);
}
const descriptor = { configurable, enumerable, writable };
this._outputProperties.set(propName, { whence, body: str, descriptor });
}
addStaticProperty(propName, str, {
configurable = true,
enumerable = typeof propName === "string",
writable = true
} = {}) {
const descriptor = { configurable, enumerable, writable };
this._outputStaticProperties.set(propName, { body: str, descriptor });
}
_analyzeMembers() {

@@ -63,8 +200,7 @@ const handleSpecialOperations = member => {

msg += ": ";
if (member.arguments.length < 1 ||
(!this.ctx.options.suppressErrors && member.arguments.length !== 1)) {
if (member.arguments.length !== 1) {
throw new Error(msg + `1 argument should be present, found ${member.arguments.length}`);
}
if (isIndexed(member)) {
if (!this.ctx.options.suppressErrors && this.indexedGetter) {
if (this.indexedGetter) {
throw new Error(msg + "duplicated indexed getter");

@@ -74,3 +210,3 @@ }

} else if (isNamed(member)) {
if (!this.ctx.options.suppressErrors && this.namedGetter) {
if (this.namedGetter) {
throw new Error(msg + "duplicated named getter");

@@ -90,8 +226,7 @@ }

if (member.arguments.length < 2 ||
(!this.ctx.options.suppressErrors && member.arguments.length !== 2)) {
if (member.arguments.length !== 2) {
throw new Error(msg + `2 arguments should be present, found ${member.arguments.length}`);
}
if (isIndexed(member)) {
if (!this.ctx.options.suppressErrors && this.indexedSetter) {
if (this.indexedSetter) {
throw new Error(msg + "duplicated indexed setter");

@@ -101,3 +236,3 @@ }

} else if (isNamed(member)) {
if (!this.ctx.options.suppressErrors && this.namedSetter) {
if (this.namedSetter) {
throw new Error(msg + "duplicated named setter");

@@ -117,8 +252,7 @@ }

if (member.arguments.length < 1 ||
(!this.ctx.options.suppressErrors && member.arguments.length !== 1)) {
if (member.arguments.length !== 1) {
throw new Error(msg + `1 arguments should be present, found ${member.arguments.length}`);
}
if (isNamed(member)) {
if (!this.ctx.options.suppressErrors && this.namedDeleter) {
if (this.namedDeleter) {
throw new Error(msg + "duplicated named deleter");

@@ -182,13 +316,11 @@ }

}
if (!this.ctx.options.suppressErrors) {
if (member.arguments.length > 0) {
throw new Error(msg + "takes more than zero arguments");
}
if (member.idlType.idlType !== "DOMString" || member.idlType.nullable) {
throw new Error(msg + "returns something other than a plain DOMString");
}
if (this.stringifier) {
throw new Error(msg + "duplicated stringifier");
}
if (member.arguments.length > 0) {
throw new Error(msg + "takes more than zero arguments");
}
if (member.idlType.idlType !== "DOMString" || member.idlType.nullable) {
throw new Error(msg + "returns something other than a plain DOMString");
}
if (this.stringifier) {
throw new Error(msg + "duplicated stringifier");
}
const op = new Operation(this.ctx, this, member);

@@ -201,7 +333,5 @@ op.name = "toString";

}
if (!this.ctx.options.suppressErrors) {
if (member.idlType.idlType !== "DOMString" && member.idlType.idlType !== "USVString" ||
member.idlType.nullable) {
throw new Error(msg + "attribute can only be of type DOMString or USVString");
}
if (member.idlType.idlType !== "DOMString" && member.idlType.idlType !== "USVString" ||
member.idlType.nullable) {
throw new Error(msg + "attribute can only be of type DOMString or USVString");
}

@@ -259,3 +389,3 @@ // Implemented in Attribute class.

get isLegacyPlatformObj() {
return !utils.isGlobal(this.idl) && (this.supportsIndexedProperties || this.supportsNamedProperties);
return !this.isGlobal && (this.supportsIndexedProperties || this.supportsNamedProperties);
}

@@ -312,5 +442,3 @@

[Symbol.toStringTag]: {
value: "${this.name}Iterator",
writable: false,
enumerable: false,
value: "${this.name} Iterator",
configurable: true

@@ -323,61 +451,2 @@ }

generateConstructor() {
const overloads = Overloads.getEffectiveOverloads("constructor", this.name, 0, this);
if (overloads.length !== 0) {
let minConstructor = overloads[0];
for (let i = 1; i < overloads.length; ++i) {
if (overloads[i].nameList.length < minConstructor.nameList.length) {
minConstructor = overloads[i];
}
}
const conversions = Parameters.generateOverloadConversions(
this.ctx, "constructor", this.name, this, `Failed to construct '${this.name}': `);
this.requires.merge(conversions.requires);
const argNames = minConstructor.nameList.map(name => (keywords.has(name) ? "_" : "") + name);
this.str += `
function ${this.name}(${argNames.join(", ")}) {
if (new.target === undefined) {
throw new TypeError("Failed to construct '${this.name}'. Please use the 'new' operator; this constructor " +
"cannot be called as a function.");
}
`;
this.str += conversions.body + "\n";
const passArgs = conversions.hasArgs ? ", args" : "";
this.str += `
iface.setup(this${passArgs});
}
`;
} else {
this.str += `
function ${this.name}() {
throw new TypeError("Illegal constructor");
}
`;
}
if (this.idl.inheritance) {
this.str += `
Object.setPrototypeOf(${this.name}.prototype, ${this.idl.inheritance}.interface.prototype);
Object.setPrototypeOf(${this.name}, ${this.idl.inheritance}.interface);
`;
} else if (utils.getExtAttr(this.idl.extAttrs, "LegacyArrayClass")) {
this.str += `
Object.setPrototypeOf(${this.name}.prototype, Array.prototype);
`;
}
this.str += `
Object.defineProperty(${this.name}, "prototype", {
value: ${this.name}.prototype,
writable: false,
enumerable: false,
configurable: false
});
`;
}
// https://heycam.github.io/webidl/#dfn-consequential-interfaces

@@ -507,4 +576,2 @@ * consequentialInterfaces(seen = new Set([this.name]), root = this.name) {

value: { target, kind, index: 0 },
writable: false,
enumerable: false,
configurable: true

@@ -918,3 +985,3 @@ });

let needFallback = false;
if (this.supportsNamedProperties && !utils.isGlobal(this.idl)) {
if (this.supportsNamedProperties && !this.isGlobal) {
const unforgeable = new Set();

@@ -965,3 +1032,3 @@ for (const m of this.allMembers()) {

// Spec says to set configurable to true, but doing so will make Proxy's trap throw and also fail WPT.
// if (!utils.isGlobal(this.idl)) {
// if (!this.isGlobal) {
// this.str += `

@@ -994,3 +1061,3 @@ // desc.configurable = true;

}
if (this.supportsNamedProperties && !utils.isGlobal(this.idl)) {
if (this.supportsNamedProperties && !this.isGlobal) {
this.str += `

@@ -1025,4 +1092,2 @@ if (${namedPropertyVisible("P", "target")}) {

// TODO: Implement [[Call]] / legacycallers.
// [[PreventExtensions]]

@@ -1087,16 +1152,3 @@ this.str += `

for (const member of this.operations.values()) {
if (member.isOnInstance()) {
const data = member.generate();
this.requires.merge(data.requires);
this.str += data.body;
}
}
for (const member of this.attributes.values()) {
if (utils.isOnInstance(member.idl, this.idl)) {
const data = member.generate();
this.requires.merge(data.requires);
this.str += data.body;
}
}
this.generateOnInstance();

@@ -1125,4 +1177,2 @@ this.str += `

value: new Impl.implementation(constructorArgs, privateData),
writable: false,
enumerable: false,
configurable: true

@@ -1150,118 +1200,250 @@ });

generateOperations() {
addConstructor() {
const overloads = Overloads.getEffectiveOverloads("constructor", this.name, 0, this);
let body;
let argNames = [];
if (overloads.length !== 0) {
let minConstructor = overloads[0];
for (let i = 1; i < overloads.length; ++i) {
if (overloads[i].nameList.length < minConstructor.nameList.length) {
minConstructor = overloads[i];
}
}
argNames = minConstructor.nameList;
const conversions = Parameters.generateOverloadConversions(
this.ctx, "constructor", this.name, this, `Failed to construct '${this.name}': `);
this.requires.merge(conversions.requires);
const passArgs = conversions.hasArgs ? ", args" : "";
body = `
${conversions.body}
return iface.setup(Object.create(new.target.prototype)${passArgs});
`;
} else {
body = `
throw new TypeError("Illegal constructor");
`;
}
this.addMethod("prototype", "constructor", argNames, body, "regular", { enumerable: false });
}
get defaultWhence() {
return this.isGlobal ? "instance" : "prototype";
}
addIteratorMethod() {
// TODO maplike setlike
// Don't bother checking "length" attribute as interfaces that support indexed properties must implement one.
// "Has value iterator" implies "supports indexed properties".
if (this.supportsIndexedProperties || this.iterable && this.iterable.isPair) {
let expr;
if (this.supportsIndexedProperties) {
this.addProperty(this.defaultWhence, Symbol.iterator, "Array.prototype[Symbol.iterator]");
}
}
if (this.supportsIndexedProperties) {
expr = "Array.prototype[Symbol.iterator]";
addAllMethodsProperties() {
this.addConstructor();
this.addProperty("prototype", Symbol.toStringTag, JSON.stringify(this.name), {
writable: false
});
const unscopables = Object.create(null);
for (const member of this.idl.members) {
if (utils.getExtAttr(member.extAttrs, "Unscopable")) {
unscopables[member.name] = true;
}
}
if (Object.keys(unscopables).length > 0) {
this.addProperty("prototype", Symbol.unscopables, JSON.stringify(unscopables), {
writable: false
});
}
for (const member of [...this.operations.values(), ...this.staticOperations.values()]) {
const data = member.generate();
this.requires.merge(data.requires);
}
this.addIteratorMethod();
if (this.iterable) {
const data = this.iterable.generate();
this.requires.merge(data.requires);
}
for (const member of [...this.attributes.values(), ...this.staticAttributes.values(), ...this.constants.values()]) {
const data = member.generate();
this.requires.merge(data.requires);
}
}
generateOffInstanceMethods() {
const addOne = (name, args, body) => {
this.str += `
${name}(${formatArgs(args)}) {${body}}
`;
};
for (const [name, { whence, type, args, body }] of this._outputMethods) {
if (whence !== "prototype") {
continue;
}
const propName = utils.stringifyPropertyName(name);
if (type === "regular") {
addOne(propName, args, body);
} else {
expr = `
function entries() {
if (!this || !module.exports.is(this)) {
throw new TypeError("Illegal invocation");
}
return module.exports.createDefaultIterator(this, "key+value");
}
`;
if (body[0] !== undefined) {
addOne(`get ${propName}`, [], body[0]);
}
if (body[1] !== undefined) {
addOne(`set ${propName}`, args, body[1]);
}
}
}
for (const [name, { type, args, body }] of this._outputStaticMethods) {
const propName = utils.stringifyPropertyName(name);
if (type === "regular") {
addOne(`static ${propName}`, args, body);
} else {
if (body[0] !== undefined) {
addOne(`static get ${propName}`, [], body[0]);
}
if (body[1] !== undefined) {
addOne(`static set ${propName}`, args, body[0]);
}
}
}
}
generateOffInstanceAfterClass() {
// Inheritance is taken care of by "extends" clause in class declaration.
if (utils.getExtAttr(this.idl.extAttrs, "LegacyArrayClass")) {
if (this.idl.inheritance) {
throw new Error(`Interface ${this.name} has [LegacyArrayClass] but inherits from ${this.idl.inheritance}`);
}
this.str += `
Object.defineProperty(${this.name}.prototype, Symbol.iterator, {
writable: true,
enumerable: false,
configurable: true,
value: ${expr}
});
Object.setPrototypeOf(${this.name}.prototype, Array.prototype);
`;
}
if (this.iterable) {
let expr;
const protoProps = new Map();
const classProps = new Map();
if (this.iterable.isValue) {
expr = "Array.prototype.forEach";
} else {
expr = `
function forEach(callback) {
if (!this || !module.exports.is(this)) {
throw new TypeError("Illegal invocation");
}
if (arguments.length < 1) {
throw new TypeError("Failed to execute 'forEach' on '${this.name}': 1 argument required, " +
"but only 0 present.");
}
if (typeof callback !== "function") {
throw new TypeError("Failed to execute 'forEach' on '${this.name}': The callback provided " +
"as parameter 1 is not a function.");
}
const thisArg = arguments[1];
let pairs = Array.from(this[impl]);
let i = 0;
while (i < pairs.length) {
const [key, value] = pairs[i].map(utils.tryWrapperForImpl);
callback.call(thisArg, value, key, this);
pairs = Array.from(this[impl]);
i++;
}
}
`;
for (const [name, { whence, type, descriptor }] of this._outputMethods) {
if (whence !== "prototype") {
continue;
}
this.str += `${this.name}.prototype.forEach = ${expr};`;
const descriptorModifier = getPropertyDescriptorModifier(defaultClassMethodDescriptor, descriptor, type);
if (descriptorModifier === undefined) {
continue;
}
protoProps.set(utils.stringifyPropertyName(name), descriptorModifier);
}
for (const member of [...this.operations.values(), ...this.staticOperations.values()]) {
if (!member.isOnInstance()) {
const data = member.generate();
this.requires.merge(data.requires);
this.str += data.body;
for (const [name, { type, descriptor }] of this._outputStaticMethods) {
const descriptorModifier = getPropertyDescriptorModifier(defaultClassMethodDescriptor, descriptor, type);
if (descriptorModifier === undefined) {
continue;
}
classProps.set(utils.stringifyPropertyName(name), descriptorModifier);
}
if (this.iterable) {
const data = this.iterable.generate();
this.requires.merge(data.requires);
this.str += data.body;
for (const [name, { whence, body, descriptor }] of this._outputProperties) {
if (whence !== "prototype") {
continue;
}
const descriptorModifier =
getPropertyDescriptorModifier(defaultDefinePropertyDescriptor, descriptor, "regular", body);
protoProps.set(utils.stringifyPropertyName(name), descriptorModifier);
}
for (const [name, { body, descriptor }] of this._outputStaticProperties) {
const descriptorModifier =
getPropertyDescriptorModifier(defaultDefinePropertyDescriptor, descriptor, "regular", body);
classProps.set(utils.stringifyPropertyName(name), descriptorModifier);
}
if (protoProps.size > 0) {
const props = [...protoProps].map(([name, body]) => `${name}: ${body}`);
this.str += `Object.defineProperties(${this.name}.prototype, { ${props.join(", ")} });`;
}
if (classProps.size > 0) {
const props = [...classProps].map(([name, body]) => `${name}: ${body}`);
this.str += `Object.defineProperties(${this.name}, { ${props.join(", ")} });`;
}
}
generateAttributes() {
for (const member of [...this.attributes.values(), ...this.staticAttributes.values(), ...this.constants.values()]) {
if (member instanceof Attribute && utils.isOnInstance(member.idl, this.idl)) {
generateOnInstance() {
const methods = [];
const props = new Map();
function addOne(name, args, body) {
methods.push(`
${name}(${formatArgs(args)}) {${body}}
`);
}
for (const [name, { whence, type, args, body, descriptor }] of this._outputMethods) {
if (whence !== "instance") {
continue;
}
const data = member.generate();
this.requires.merge(data.requires);
this.str += data.body;
const propName = utils.stringifyPropertyName(name);
if (type === "regular") {
addOne(propName, args, body);
} else {
if (body[0] !== undefined) {
addOne(`get ${propName}`, [], body[0]);
}
if (body[1] !== undefined) {
addOne(`set ${propName}`, args, body[1]);
}
}
const descriptorModifier = getPropertyDescriptorModifier(defaultObjectLiteralDescriptor, descriptor, type);
if (descriptorModifier === undefined) {
continue;
}
props.set(utils.stringifyPropertyName(name), descriptorModifier);
}
}
generateSymbols() {
const unscopables = Object.create(null);
for (const member of this.idl.members) {
if (utils.getExtAttr(member.extAttrs, "Unscopable")) {
unscopables[member.name] = true;
for (const [name, { whence, body, descriptor }] of this._outputProperties) {
if (whence !== "instance") {
continue;
}
const propName = utils.stringifyPropertyName(name);
methods.push(`${propName}: ${body}`);
const descriptorModifier = getPropertyDescriptorModifier(defaultObjectLiteralDescriptor, descriptor, "regular");
if (descriptorModifier === undefined) {
continue;
}
props.set(propName, descriptorModifier);
}
if (Object.keys(unscopables).length) {
const propStrs = [...props].map(([name, body]) => `${name}: ${body}`);
if (methods.length > 0) {
this.str += `
Object.defineProperty(${this.name}.prototype, Symbol.unscopables, {
value: ${JSON.stringify(unscopables, null, " ")},
writable: false,
enumerable: false,
configurable: true
});
Object.defineProperties(
obj,
utils.getOwnPropertyDescriptors({ ${methods.join(", ")} })
);
`;
}
this.str += `
Object.defineProperty(${this.name}.prototype, Symbol.toStringTag, {
value: "${this.name}",
writable: false,
enumerable: false,
configurable: true
});
`;
if (propStrs.length > 0) {
this.str += `
Object.defineProperties(
obj,
{ ${propStrs.join(", ")} }
);
`;
}
}

@@ -1279,9 +1461,11 @@

this.generateConstructor();
const ext = this.idl.inheritance ? ` extends ${this.idl.inheritance}.interface` : "";
this.str += `class ${this.name}${ext} {`;
this.generateOperations();
this.generateAttributes();
this.generateOffInstanceMethods();
this.generateSymbols();
this.str += "}";
this.generateOffInstanceAfterClass();
this.str += `

@@ -1321,2 +1505,3 @@ const iface = {

}
this.addAllMethodsProperties();
this.generate();

@@ -1323,0 +1508,0 @@ return this.str;

"use strict";
const keywords = require("../keywords");
const utils = require("../utils");

@@ -15,50 +14,57 @@

get isValue() {
return !Array.isArray(this.idl.idlType);
return this.idl.idlType.length === 1;
}
get isPair() {
return Array.isArray(this.idl.idlType) && this.idl.idlType.length === 2;
return this.idl.idlType.length === 2;
}
generateFunction(key, kind, keyExpr, fnName) {
if (fnName === undefined) {
if (typeof key === "symbol") {
fnName = "";
} else {
fnName = keywords.has(key) ? "_" : key;
generateFunction(key, kind) {
this.interface.addMethod(this.interface.defaultWhence, key, [], `
if (!this || !module.exports.is(this)) {
throw new TypeError("Illegal invocation");
}
}
return module.exports.createDefaultIterator(this, "${kind}");
`);
}
const propExpr = typeof key === "symbol" ? `[${keyExpr}]` : `.${key}`;
return `
${this.interface.name}.prototype${propExpr} = function ${fnName}() {
generate() {
const whence = this.interface.defaultWhence;
if (this.isPair) {
this.generateFunction("keys", "key");
this.generateFunction("values", "value");
this.generateFunction("entries", "key+value");
this.interface.addProperty(whence, Symbol.iterator, `${this.interface.name}.prototype.entries`);
this.interface.addMethod(whence, "forEach", ["callback"], `
if (!this || !module.exports.is(this)) {
throw new TypeError("Illegal invocation");
}
return module.exports.createDefaultIterator(this, "${kind}");
};
`;
}
generate() {
let str = "";
if (this.isPair) {
str += `
${this.interface.name}.prototype.entries = ${this.interface.name}.prototype[Symbol.iterator];
${this.generateFunction("keys", "key")}
${this.generateFunction("values", "value")}
`;
if (arguments.length < 1) {
throw new TypeError("Failed to execute 'forEach' on '${this.name}': 1 argument required, " +
"but only 0 present.");
}
if (typeof callback !== "function") {
throw new TypeError("Failed to execute 'forEach' on '${this.name}': The callback provided " +
"as parameter 1 is not a function.");
}
const thisArg = arguments[1];
let pairs = Array.from(this[impl]);
let i = 0;
while (i < pairs.length) {
const [key, value] = pairs[i].map(utils.tryWrapperForImpl);
callback.call(thisArg, value, key, this);
pairs = Array.from(this[impl]);
i++;
}
`);
} else {
str += `
${this.interface.name}.prototype.entries = Array.prototype.entries;
${this.interface.name}.prototype.keys = Array.prototype.keys;
${this.interface.name}.prototype.values = Array.prototype[Symbol.iterator];
`;
this.interface.addProperty(whence, "keys", "Array.prototype.keys");
this.interface.addProperty(whence, "values", "Array.prototype[Symbol.iterator]");
this.interface.addProperty(whence, "entries", "Array.prototype.entries");
this.interface.addProperty(whence, "forEach", "Array.prototype.forEach");
// @@iterator is added in Interface class.
}
return {
requires: new utils.RequiresMap(this.ctx),
body: str
requires: new utils.RequiresMap(this.ctx)
};

@@ -65,0 +71,0 @@ }

@@ -8,3 +8,2 @@ "use strict";

const Parameters = require("../parameters");
const keywords = require("../keywords");

@@ -52,6 +51,3 @@ class Operation {

let targetObj = this.interface.name + (this.static ? "" : ".prototype");
if (this.isOnInstance()) {
targetObj = "obj";
}
const onInstance = this.isOnInstance();

@@ -67,8 +63,4 @@ const type = this.static ? "static operation" : "regular operation";

const fnName = (keywords.has(this.name) ? "_" : "") + this.name;
const argNames = minOp.nameList.map(name => (keywords.has(name) ? "_" : "") + name);
const argNames = minOp.nameList;
str += `
${targetObj}.${this.name} = function ${fnName}(${argNames.join(", ")}) {
`;
if (!this.static) {

@@ -95,16 +87,25 @@ str += `

str += `
return ${callOn}.${implFunc}(${argsSpread});
};
return ${callOn}.${implFunc}(${argsSpread});
`;
} else {
str += `
return utils.tryWrapperForImpl(${callOn}.${implFunc}(${argsSpread}));
};
return utils.tryWrapperForImpl(${callOn}.${implFunc}(${argsSpread}));
`;
}
return {
requires,
body: str
};
if (this.static) {
this.interface.addStaticMethod(this.name, argNames, str);
} else {
const forgeable = !utils.getExtAttr(this.idls[0].extAttrs, "Unforgeable");
this.interface.addMethod(
onInstance ? "instance" : "prototype",
this.name,
argNames,
str,
"regular",
{ configurable: forgeable, writable: forgeable }
);
}
return { requires };
}

@@ -111,0 +112,0 @@ }

@@ -12,2 +12,27 @@ "use strict";

const getOwnPropertyDescriptors = typeof Object.getOwnPropertyDescriptors === "function" ?
Object.getOwnPropertyDescriptors :
// Polyfill exists until we require Node.js v8.x
// https://tc39.github.io/ecma262/#sec-object.getownpropertydescriptors
obj => {
if (obj === undefined || obj === null) {
throw new TypeError("Cannot convert undefined or null to object");
}
obj = Object(obj);
const ownKeys = Reflect.ownKeys(obj);
const descriptors = {};
for (const key of ownKeys) {
const descriptor = Reflect.getOwnPropertyDescriptor(obj, key);
if (descriptor !== undefined) {
Reflect.defineProperty(descriptors, key, {
value: descriptor,
writable: true,
enumerable: true,
configurable: true
});
}
}
return descriptors;
};
const wrapperSymbol = Symbol("wrapper");

@@ -81,2 +106,3 @@ const implSymbol = Symbol("impl");

hasOwn,
getOwnPropertyDescriptors,
wrapperSymbol,

@@ -83,0 +109,0 @@ implSymbol,

@@ -235,3 +235,4 @@ "use strict";

return prettier.format(source, {
printWidth: 120
printWidth: 120,
parser: "babylon"
});

@@ -238,0 +239,0 @@ }

@@ -32,4 +32,3 @@ "use strict";

function isGlobal(idl) {
return Boolean(getExtAttr(idl.extAttrs, "Global")) ||
Boolean(getExtAttr(idl.extAttrs, "PrimaryGlobal"));
return Boolean(getExtAttr(idl.extAttrs, "Global"));
}

@@ -41,2 +40,19 @@

function stringifyPropertyName(propName) {
if (typeof propName === "symbol") {
const desc = String(propName).replace(/^Symbol\((.*)\)$/, "$1");
if (!desc.startsWith("Symbol.")) {
throw new Error(`Internal error: Unsupported property name ${String(propName)}`);
}
return `[${desc}]`;
}
// All Web IDL identifiers are valid JavaScript PropertyNames, other than those with '-'.
const isJSIdentifier = !propName.includes("-");
if (isJSIdentifier) {
return propName;
}
return JSON.stringify(propName);
}
class RequiresMap extends Map {

@@ -83,3 +99,4 @@ constructor(ctx) {

isOnInstance,
stringifyPropertyName,
RequiresMap
};
{
"name": "webidl2js",
"version": "9.0.0",
"version": "9.0.1",
"description": "Auto-generates class structures for WebIDL specifications",
"main": "lib/transformer.js",
"repository": "github:jsdom/webidl2js",
"dependencies": {
"co": "^4.6.0",
"pn": "^1.0.0",
"prettier": "^1.5.3",
"pn": "^1.1.0",
"prettier": "^1.14.0",
"webidl-conversions": "^4.0.0",
"webidl2": "^8.1.0"
"webidl2": "^9.0.0"
},
"devDependencies": {
"eslint": "^4.3.0",
"jest": "^21.2.1"
"eslint": "^4.13.1",
"jest": "^23.4.2"
},

@@ -22,4 +23,7 @@ "scripts": {

},
"jest": {
"testEnvironment": "node"
},
"author": "Sebastian Mayr <npm@smayr.name>",
"license": "MIT"
}

@@ -12,3 +12,3 @@ # JavaScript bindings generator for Web IDL

unsigned long long add(unsigned long x, unsigned long y);
}
};
```

@@ -19,3 +19,3 @@

```js
exports.implementation = class {
exports.implementation = class SomeInterfaceImpl {
add(x, y) {

@@ -35,34 +35,34 @@ return x + y;

function SomeInterface() {
throw new TypeError("Illegal constructor");
}
SomeInterface.prototype.add = function add(x, y) {
if (!exports.is(this)) {
throw new TypeError("Illegal invocation");
class SomeInterface {
constructor() {
throw new TypeError("Illegal constructor");
}
if (arguments.length < 2) {
throw new TypeError(
"Failed to execute 'add' on 'SomeInterface': 2 arguments required, but only " +
arguments.length +
" present."
);
}
const args = [];
args[0] = conversions["unsigned long"](arguments[0], {
context: "Failed to execute 'add' on 'SomeInterface': parameter 1"
});
args[1] = conversions["unsigned long"](arguments[1], {
context: "Failed to execute 'add' on 'SomeInterface': parameter 2"
});
add(x, y) {
if (!exports.is(this)) {
throw new TypeError("Illegal invocation");
}
if (arguments.length < 2) {
throw new TypeError(
"Failed to execute 'add' on 'SomeInterface': 2 arguments required, but only " +
arguments.length +
" present."
);
}
this[impl].add(...args);
};
const args = [];
args[0] = conversions["unsigned long"](arguments[0], {
context: "Failed to execute 'add' on 'SomeInterface': parameter 1"
});
args[1] = conversions["unsigned long"](arguments[1], {
context: "Failed to execute 'add' on 'SomeInterface': parameter 2"
});
Object.defineProperty(SomeInterface.prototype, Symbol.toStringTag, {
value: "SomeInterface",
writable: false,
enumerable: false,
configurable: true
return this[impl].add(...args);
}
}
Object.defineProperties(SomeInterface.prototype, {
add: { enumerable: true },
[Symbol.toStringTag]: { value: "SomeInterface", configurable: true }
});

@@ -88,2 +88,3 @@

- Argument conversion according to the rules specified in Web IDL for given argument types
- Enumerability of operations
- @@toStringTag semantics to make `Object.prototype.toString.call()` behave correctly

@@ -291,2 +292,6 @@ - After performing Web IDL-related processing, webidl2js delegates to the implementation class for the non-boilerplate parts of `add()`. This allows you to focus on writing the interesting parts of the implementation without worrying about types, brand-checking, parameter-processing, etc.

### Other requirements
The generated interface wrapper files use modern JavaScript features such as `class` definitions and `Proxy`. They will not work on JavaScript runtimes that do not support the ECMAScript 2015 standard.
## The generated utilities file

@@ -293,0 +298,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc