Socket
Socket
Sign inDemoInstall

webidl2js

Package Overview
Dependencies
3
Maintainers
6
Versions
57
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 16.1.0 to 16.2.0

lib/constructs/async-iterable.js

8

lib/constructs/attribute.js

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

if (!exports.is(esValue)) {
throw new TypeError("Illegal invocation");
throw new TypeError("'$KEYWORD$ ${this.idl.name}' called on an object that is not a valid instance of ${this.interface.name}.");
}

@@ -82,3 +82,3 @@ `;

const esValue = this !== null && this !== undefined ? this : globalObject;
${brandCheck}
${brandCheck.replace("$KEYWORD$", "get")}
${getterBody}

@@ -88,2 +88,4 @@ ${promiseHandlingAfter}

brandCheck = brandCheck.replace("$KEYWORD$", "set");
if (!this.idl.readonly) {

@@ -165,3 +167,3 @@ if (async) {

if (!exports.is(esValue)) {
throw new TypeError("Illegal invocation");
throw new TypeError("'toString' called on an object that is not a valid instance of ${this.interface.name}.");
}

@@ -168,0 +170,0 @@

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

const Iterable = require("./iterable");
const AsyncIterable = require("./async-iterable");
const Operation = require("./operation");

@@ -12,3 +13,2 @@ const Types = require("../types");

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

@@ -22,6 +22,2 @@ function isNamed(idl) {

function formatArgs(args) {
return args.map(name => name + (keywords.has(name) ? "_" : "")).join(", ");
}
const defaultObjectLiteralDescriptor = {

@@ -317,3 +313,5 @@ configurable: true,

}
this.iterable = new Iterable(this.ctx, this, member);
this.iterable = member.async ?
new AsyncIterable(this.ctx, this, member) :
new Iterable(this.ctx, this, member);
break;

@@ -380,9 +378,11 @@ default:

if (this.iterable) {
if (this.iterable.isValue) {
if (!this.supportsIndexedProperties) {
throw new Error(`A value iterator cannot be declared on ${this.name} which does not support indexed ` +
"properties");
if (!this.iterable.isAsync) {
if (this.iterable.isValue) {
if (!this.supportsIndexedProperties) {
throw new Error(`A value iterator cannot be declared on ${this.name} which does not support indexed ` +
"properties");
}
} else if (this.iterable.isPair && this.supportsIndexedProperties) {
throw new Error(`A pair iterator cannot be declared on ${this.name} which supports indexed properties`);
}
} else if (this.iterable.isPair && this.supportsIndexedProperties) {
throw new Error(`A pair iterator cannot be declared on ${this.name} which supports indexed properties`);
}

@@ -429,8 +429,98 @@ for (const n of ["entries", "forEach", "keys", "values"]) {

generateIterator() {
if (this.iterable && this.iterable.isPair) {
if (!this.iterable) {
return;
}
if (this.iterable.isAsync) {
this.str += `
const AsyncIteratorPrototype = Object.create(utils.AsyncIteratorPrototype, {
[Symbol.toStringTag]: {
value: "${this.name} AsyncIterator",
configurable: true
}
});
Object.assign(AsyncIteratorPrototype, {
next() {
const internal = this && this[utils.iterInternalSymbol];
if (!internal) {
return Promise.reject(new TypeError("next() called on a value that is not an async iterator prototype object"));
}
const nextSteps = () => {
if (internal.isFinished) {
return Promise.resolve({ value: undefined, done: true });
}
const nextPromise = internal.target[implSymbol][utils.asyncIteratorNext](this);
return nextPromise.then(
next => {
internal.ongoingPromise = null;
if (next === utils.asyncIteratorEOI) {
internal.isFinished = true;
return { value: undefined, done: true };
}`;
if (this.iterable.isPair) {
this.str += `
return utils.iteratorResult(next.map(utils.tryWrapperForImpl), kind);
`;
} else {
this.str += `
return { value: utils.tryWrapperForImpl(next), done: false };
`;
}
this.str += `
},
reason => {
internal.ongoingPromise = null;
internal.isFinished = true;
throw reason;
}
);
};
internal.ongoingPromise = internal.ongoingPromise ?
internal.ongoingPromise.then(nextSteps, nextSteps) :
nextSteps();
return internal.ongoingPromise;
},
`;
if (this.iterable.hasReturnSteps) {
this.str += `
return(value) {
const internal = this && this[utils.iterInternalSymbol];
if (!internal) {
return Promise.reject(new TypeError("return() called on a value that is not an async iterator prototype object"));
}
const returnSteps = () => {
if (internal.isFinished) {
return Promise.resolve({ value, done: true });
}
internal.isFinished = true;
return internal.target[implSymbol][utils.asyncIteratorReturn](this, value);
};
const returnPromise = internal.ongoingPromise ?
internal.ongoingPromise.then(returnSteps, returnSteps) :
returnSteps();
return returnPromise.then(() => ({ value, done: true }));
}
`;
}
this.str += `
});
`;
} else if (this.iterable.isPair) {
this.str += `
const IteratorPrototype = Object.create(utils.IteratorPrototype, {
next: {
value: function next() {
const internal = this[utils.iterInternalSymbol];
const internal = this && this[utils.iterInternalSymbol];
if (!internal) {
throw new TypeError("next() called on a value that is not an iterator prototype object");
}
const { target, kind, index } = internal;

@@ -445,17 +535,3 @@ const values = Array.from(target[implSymbol]);

internal.index = index + 1;
const [key, value] = pair.map(utils.tryWrapperForImpl);
let result;
switch (kind) {
case "key":
result = key;
break;
case "value":
result = value;
break;
case "key+value":
result = [key, value];
break;
}
return { value: result, done: false };
return utils.iteratorResult(pair.map(utils.tryWrapperForImpl), kind);
},

@@ -547,13 +623,26 @@ writable: true,

if (this.iterable && this.iterable.isPair) {
this.str += `
exports.createDefaultIterator = (target, kind) => {
const iterator = Object.create(IteratorPrototype);
Object.defineProperty(iterator, utils.iterInternalSymbol, {
value: { target, kind, index: 0 },
configurable: true
});
return iterator;
};
`;
if (this.iterable) {
if (this.iterable.isAsync) {
this.str += `
exports.createDefaultAsyncIterator = (target, kind) => {
const iterator = Object.create(AsyncIteratorPrototype);
Object.defineProperty(iterator, utils.iterInternalSymbol, {
value: { target, kind, ongoingPromise: null, isFinished: false },
configurable: true
});
return iterator;
};
`;
} else if (this.iterable.isPair) {
this.str += `
exports.createDefaultIterator = (target, kind) => {
const iterator = Object.create(IteratorPrototype);
Object.defineProperty(iterator, utils.iterInternalSymbol, {
value: { target, kind, index: 0 },
configurable: true
});
return iterator;
};
`;
}
}

@@ -857,3 +946,5 @@ }

}
if (target === receiver) {
// The \`receiver\` argument refers to the Proxy exotic object or an object
// that inherits from it, whereas \`target\` refers to the Proxy target:
if (target[implSymbol][utils.wrapperSymbol] === receiver) {
`;

@@ -867,31 +958,17 @@

if (this.supportsIndexedProperties) {
if (hasIndexedSetter) {
this.str += `
if (utils.isArrayIndexPropName(P)) {
${invokeIndexedSetter("target", "P", "V")}
return true;
}
`;
} else {
// Side-effects
this.str += `
utils.isArrayIndexPropName(P);
`;
}
if (this.supportsIndexedProperties && hasIndexedSetter) {
this.str += `
if (utils.isArrayIndexPropName(P)) {
${invokeIndexedSetter("target", "P", "V")}
return true;
}
`;
}
if (this.supportsNamedProperties) {
if (hasNamedSetter) {
this.str += `
if (typeof P === "string" && !utils.isArrayIndexPropName(P)) {
${invokeNamedSetter("target", "P", "V")}
return true;
}
`;
} else {
// Side-effects
this.str += `
typeof P === "string" && !utils.isArrayIndexPropName(P);
`;
}
if (this.supportsNamedProperties && hasNamedSetter) {
this.str += `
if (typeof P === "string") {
${invokeNamedSetter("target", "P", "V")}
return true;
}
`;
}

@@ -1262,3 +1339,3 @@

${conversions.body}
return exports.setup(${formatArgs(setupArgs)});
return exports.setup(${utils.formatArgs(setupArgs)});
`;

@@ -1333,3 +1410,3 @@ } else {

this.str += `
${name}(${formatArgs(args)}) {${body}}
${name}(${utils.formatArgs(args)}) {${body}}
`;

@@ -1430,3 +1507,3 @@ };

methods.push(`
${name}(${formatArgs(args)}) {${body}}
${name}(${utils.formatArgs(args)}) {${body}}
`);

@@ -1433,0 +1510,0 @@ }

@@ -21,6 +21,10 @@ "use strict";

get isAsync() {
return false;
}
generateFunction(key, kind) {
this.interface.addMethod(this.interface.defaultWhence, key, [], `
if (!this || !exports.is(this)) {
throw new TypeError("Illegal invocation");
if (!exports.is(this)) {
throw new TypeError("'${key}' called on an object that is not a valid instance of ${this.interface.name}.");
}

@@ -41,4 +45,4 @@ return exports.createDefaultIterator(this, "${kind}");

this.interface.addMethod(whence, "forEach", ["callback"], `
if (!this || !exports.is(this)) {
throw new TypeError("Illegal invocation");
if (!exports.is(this)) {
throw new TypeError("'forEach' called on an object that is not a valid instance of ${this.interface.name}.");
}

@@ -45,0 +49,0 @@ if (arguments.length < 1) {

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

hasCallWithGlobal() {
const { idls } = this;
const hasCallWithGlobal = Boolean(utils.getExtAttr(idls[0].extAttrs, "WebIDL2JSCallWithGlobal"));
if (hasCallWithGlobal && !this.static) {
throw new Error(
`[WebIDL2JSCallWithGlobal] is only valid for static operations: "${this.name}" on ${this.interface.name}`
);
}
for (let i = 1; i < idls.length; i++) {
if (hasCallWithGlobal !== Boolean(utils.getExtAttr(idls[i].extAttrs, "WebIDL2JSCallWithGlobal"))) {
throw new Error(
`[WebIDL2JSCallWithGlobal] is not applied uniformly to operation "${this.name}" on ${this.interface.name}`
);
}
}
return hasCallWithGlobal;
}
fixUpArgsExtAttrs() {

@@ -73,2 +94,3 @@ for (const idl of this.idls) {

const promiseHandlingAfter = async ? `} catch (e) { return Promise.reject(e); }` : ``;
const hasCallWithGlobal = this.hasCallWithGlobal();

@@ -90,3 +112,3 @@ const type = this.static ? "static operation" : "regular operation";

if (!exports.is(esValue)) {
throw new TypeError("Illegal invocation");
throw new TypeError("'${this.name}' called on an object that is not a valid instance of ${this.interface.name}.");
}

@@ -103,14 +125,22 @@ `;

this.ctx, type, this.name, this.interface, `Failed to execute '${this.name}' on '${this.interface.name}': `);
const argsSpread = parameterConversions.hasArgs ? "...args" : "";
const args = [];
requires.merge(parameterConversions.requires);
str += parameterConversions.body;
if (hasCallWithGlobal) {
args.push("globalObject");
}
if (parameterConversions.hasArgs) {
args.push("...args");
}
let invocation;
if (overloads.every(overload => conversions[overload.operation.idlType.idlType])) {
invocation = `
return ${callOn}.${implFunc}(${argsSpread});
return ${callOn}.${implFunc}(${utils.formatArgs(args)});
`;
} else {
invocation = `
return utils.tryWrapperForImpl(${callOn}.${implFunc}(${argsSpread}));
return utils.tryWrapperForImpl(${callOn}.${implFunc}(${utils.formatArgs(args)}));
`;

@@ -117,0 +147,0 @@ }

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

const IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
const AsyncIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(async function* () {}).prototype);

@@ -76,2 +77,18 @@ function isArrayIndexPropName(P) {

function iteratorResult([key, value], kind) {
let result;
switch (kind) {
case "key":
result = key;
break;
case "value":
result = value;
break;
case "key+value":
result = [key, value];
break;
}
return { value: result, done: false };
}
const supportsPropertyIndex = Symbol("supports property index");

@@ -89,2 +106,7 @@ const supportedPropertyIndices = Symbol("supported property indices");

const asyncIteratorNext = Symbol("async iterator get the next iteration result");
const asyncIteratorReturn = Symbol("async iterator return steps");
const asyncIteratorInit = Symbol("async iterator initialization steps");
const asyncIteratorEOI = Symbol("async iterator end of iteration");
module.exports = exports = {

@@ -103,2 +125,3 @@ isObject,

IteratorPrototype,
AsyncIteratorPrototype,
isArrayBuffer,

@@ -116,3 +139,8 @@ isArrayIndexPropName,

namedSetExisting,
namedDelete
namedDelete,
asyncIteratorNext,
asyncIteratorReturn,
asyncIteratorInit,
asyncIteratorEOI,
iteratorResult
};

@@ -17,3 +17,10 @@ "use strict";

// Always (try to) force-convert dictionaries
const optional = overload.optionalityList[i] === "optional" && !ctx.dictionaries.has(idlType.idlType);
const isDefaultedDictionary = overload.operation.arguments[i].default &&
overload.operation.arguments[i].default.type === "dictionary";
if (isDefaultedDictionary && !ctx.dictionaries.has(idlType.idlType)) {
throw new Error(
`The parameter ${overload.operation.arguments[i].name} was defaulted to {}, but no dictionary named ` +
`${idlType.idlType} exists`);
}
const optional = overload.optionalityList[i] === "optional" && !isDefaultedDictionary;
let str = `{ let curArg = arguments[${targetIdx}];`;

@@ -50,2 +57,52 @@ if (optional) {

module.exports.generateAsyncIteratorArgConversions = (ctx, idl, parent, errPrefix) => {
const requires = new utils.RequiresMap(ctx);
let str = "const args = [];";
for (let i = 0; i < idl.arguments.length; ++i) {
const idlArg = idl.arguments[i];
if (!idlArg.optional) {
throw new Error("All async iterable arguments must be optional");
}
const isDefaultedDictionary = idlArg.default && idlArg.default.type === "dictionary";
if (isDefaultedDictionary && !ctx.dictionaries.has(idlArg.idlType.idlType)) {
throw new Error(
`The dictionary ${idlArg.idlType.idlType} was referenced in an argument list, but doesn't exist`);
}
const msg = `"${errPrefix}parameter ${i + 1}"`;
const conv = Types.generateTypeConversion(ctx, `args[${i}]`, idlArg.idlType, [], parent.name, msg);
requires.merge(conv.requires);
if (isDefaultedDictionary) {
str += `args[${i}] = arguments[${i}];${conv.body}`;
} else {
str += `
if (arguments[${i}] !== undefined) {
args[${i}] = arguments[${i}];${conv.body}
}
`;
if (idlArg.default) {
str += `
else {
args[${i}] = ${utils.getDefault(idlArg.default)};
}
`;
} else {
str += `
else {
args[${i}] = undefined;
}
`;
}
}
}
return {
requires,
body: str
};
};
module.exports.generateOverloadConversions = function (ctx, typeOfOp, name, parent, errPrefix) {

@@ -52,0 +109,0 @@ const requires = new utils.RequiresMap(ctx);

"use strict";
const { extname } = require("path");
const keywords = require("./keywords.js");

@@ -98,2 +99,9 @@ function getDefault(dflt) {

function formatArgs(args) {
return args
.filter(name => name !== null && name !== undefined && name !== "")
.map(name => name + (keywords.has(name) ? "_" : ""))
.join(", ");
}
function toKey(type, func = "") {

@@ -172,3 +180,4 @@ return String(func + type).replace(/[./-]+/g, " ").trim().replace(/ /g, "_");

defaultDefinePropertyDescriptor,
formatArgs,
RequiresMap
};
{
"name": "webidl2js",
"version": "16.1.0",
"version": "16.2.0",
"description": "Auto-generates class structures for WebIDL specifications",

@@ -10,3 +10,3 @@ "main": "lib/transformer.js",

"webidl-conversions": "^6.1.0",
"webidl2": "^23.11.0"
"webidl2": "^23.12.1"
},

@@ -13,0 +13,0 @@ "devDependencies": {

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

The first is the getters, (optional) setters, and (optional) deleters operations. Much like stringifiers, getters, setters, and deleters can either be standalone or aliased to a named operation (though not an attribute). If an operation is standalone, then the implementation class must implement following symbol-named methods. The `utils` object below refers to the default export from the generated utilities file `utils.js`.
The first is the getters, (optional) setters, and (optional) deleters operations. Much like stringifiers, getters, setters, and deleters can either be standalone or aliased to a named operation (though not an attribute). If an operation is standalone, then the implementation class must implement the following symbol-named methods. The `utils` object below refers to the default export from the generated utilities file `utils.js`.

@@ -399,2 +399,16 @@ - Getters: `utils.indexedGet`, `utils.namedGet`

### Iterables
For synchronous value iterable declarations, there is no need to add implementation-class code: they will be automatically generated based on the indexed property getter and `length` property.
For synchronous pair iterable declarations, the implementation class needs to implement the `[Symbol.iterator]()` property, returning an iterable of `[key, value]` pairs. These can be impls; the generated code will convert them into wrappers as necessary.
### Async iterables
[Asynchronous iterable declarations](https://heycam.github.io/webidl/#idl-async-iterable) require the implementation class to implement the following symbol-named methods, corresponding to algorithms from the Web IDL specification. The `utils` object below refers to the default export from the generated utilities file `utils.js`.
- `utils.asyncIteratorNext`: corresponds to the [get the next iteration result](https://heycam.github.io/webidl/#dfn-get-the-next-iteration-result) algorithm, and receives a single argument containing an instance of the generated async iterator. For pair asynchronous iterables, the return value must be a `[key, value]` pair array, or `utils.asyncIteratorEOI` to signal the end of the iteration. For value asynchronous iterables, the return value must be the value, or `utils.asyncIteratorEOI` to signal the end of the iteration.
- `utils.asyncIteratorInit`: corresponds to the [asynchronous iterator initialization steps](https://heycam.github.io/webidl/#asynchronous-iterator-initialization-steps), and receives two arguments: the instance of the generated async iterator, and an array containing the post-conversion arguments. This method is optional.
- `utils.asyncIteratorReturn`: corresponds to the [asynchronous iterator return](https://heycam.github.io/webidl/#asynchronous-iterator-return) algorithm, and receives two arguments: the instance of the generated async iterator, and the argument passed to the `return()` method. This method is optional. Note that if you include it, you need to annote the async iterable declaration with [`[WebIDL2JSHasReturnSteps]`](#webidl2jshasreturnsteps).
### Other, non-exposed data and functionality

@@ -454,2 +468,3 @@

- `iterable<>` declarations
- `async iterable<>` declarations
- Class strings (with the semantics of [heycam/webidl#357](https://github.com/heycam/webidl/pull/357))

@@ -508,4 +523,14 @@ - Dictionary types

One non-standard extended attribute is baked in to webidl2js:
A couple of non-standard extended attributes are baked in to webidl2js:
### `[WebIDL2JSCallWithGlobal]`
When the `[WebIDL2JSCallWithGlobal]` extended attribute is specified on static IDL operations, the generated interface code passes the [current global object](https://html.spec.whatwg.org/multipage/webappapis.html#current-global-object) as the first parameter to the implementation code. All other parameters follow `globalObject` and are unchanged. This could be used to implement factory functions that create objects in the current realm.
### `[WebIDL2JSHasReturnSteps]`
This extended attribute can be applied to async iterable declarations. It declares that the implementation class will implement the `[idlUtils.asyncIteratorReturn]()` method.
This is necessary because we need to figure out at code-generation time whether to generate a `return()` method on the async iterator prototype. At that point, only the Web IDL is available, not the implementation class properties. So, we need a signal in the Web IDL itself.
### `[WebIDL2JSValueAsUnsupported=value]`

@@ -512,0 +537,0 @@

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc