diff options
author | Leo Kettmeir <crowlkats@toaxl.com> | 2023-02-07 20:22:46 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-07 20:22:46 +0100 |
commit | b4aa1530970f7b9cc4e6f2f27e077852c4e178d3 (patch) | |
tree | 3d008912affe8550692183bd2697a386db5e3c79 /ext/webidl | |
parent | 65500f36e870b4ada3996b06aa287e30177d21a3 (diff) |
refactor: Use ES modules for internal runtime code (#17648)
This PR refactors all internal js files (except core) to be written as
ES modules.
`__bootstrap`has been mostly replaced with static imports in form in
`internal:[path to file from repo root]`.
To specify if files are ESM, an `esm` method has been added to
`Extension`, similar to the `js` method.
A new ModuleLoader called `InternalModuleLoader` has been added to
enable the loading of internal specifiers, which is used in all
situations except when a snapshot is only loaded, and not a new one is
created from it.
---------
Co-authored-by: Bartek IwaĆczuk <biwanczuk@gmail.com>
Diffstat (limited to 'ext/webidl')
-rw-r--r-- | ext/webidl/00_webidl.js | 1992 | ||||
-rw-r--r-- | ext/webidl/benches/dict.js | 7 | ||||
-rw-r--r-- | ext/webidl/benches/dict.rs | 2 | ||||
-rw-r--r-- | ext/webidl/internal.d.ts | 630 | ||||
-rw-r--r-- | ext/webidl/lib.rs | 2 |
5 files changed, 1315 insertions, 1318 deletions
diff --git a/ext/webidl/00_webidl.js b/ext/webidl/00_webidl.js index bb90d973e..1357d308e 100644 --- a/ext/webidl/00_webidl.js +++ b/ext/webidl/00_webidl.js @@ -6,1186 +6,1182 @@ /// <reference path="../../core/internal.d.ts" /> -"use strict"; - -((window) => { - const core = window.Deno.core; - const { - ArrayBufferPrototype, - ArrayBufferIsView, - ArrayPrototypeForEach, - ArrayPrototypePush, - ArrayPrototypeSort, - ArrayIteratorPrototype, - BigInt, - BigIntAsIntN, - BigIntAsUintN, - Float32Array, - Float64Array, - FunctionPrototypeBind, - Int16Array, - Int32Array, - Int8Array, - isNaN, - MathFloor, - MathFround, - MathMax, - MathMin, - MathPow, - MathRound, - MathTrunc, - Number, - NumberIsFinite, - NumberIsNaN, - // deno-lint-ignore camelcase - NumberMAX_SAFE_INTEGER, - // deno-lint-ignore camelcase - NumberMIN_SAFE_INTEGER, - ObjectAssign, - ObjectCreate, - ObjectDefineProperties, - ObjectDefineProperty, - ObjectGetOwnPropertyDescriptor, - ObjectGetOwnPropertyDescriptors, - ObjectGetPrototypeOf, - ObjectPrototypeHasOwnProperty, - ObjectPrototypeIsPrototypeOf, - ObjectIs, - PromisePrototypeThen, - PromiseReject, - PromiseResolve, - ReflectApply, - ReflectDefineProperty, - ReflectGetOwnPropertyDescriptor, - ReflectHas, - ReflectOwnKeys, - RegExpPrototypeTest, - Set, - SetPrototypeEntries, - SetPrototypeForEach, - SetPrototypeKeys, - SetPrototypeValues, - SetPrototypeHas, - SetPrototypeClear, - SetPrototypeDelete, - SetPrototypeAdd, - // TODO(lucacasonato): add SharedArrayBuffer to primordials - // SharedArrayBufferPrototype - String, - StringFromCodePoint, - StringPrototypeCharCodeAt, - Symbol, - SymbolIterator, - SymbolToStringTag, - TypedArrayPrototypeGetSymbolToStringTag, - TypeError, - Uint16Array, - Uint32Array, - Uint8Array, - Uint8ClampedArray, - } = window.__bootstrap.primordials; +const core = globalThis.Deno.core; +const primordials = globalThis.__bootstrap.primordials; +const { + ArrayBufferPrototype, + ArrayBufferIsView, + ArrayPrototypeForEach, + ArrayPrototypePush, + ArrayPrototypeSort, + ArrayIteratorPrototype, + BigInt, + BigIntAsIntN, + BigIntAsUintN, + Float32Array, + Float64Array, + FunctionPrototypeBind, + Int16Array, + Int32Array, + Int8Array, + isNaN, + MathFloor, + MathFround, + MathMax, + MathMin, + MathPow, + MathRound, + MathTrunc, + Number, + NumberIsFinite, + NumberIsNaN, + // deno-lint-ignore camelcase + NumberMAX_SAFE_INTEGER, + // deno-lint-ignore camelcase + NumberMIN_SAFE_INTEGER, + ObjectAssign, + ObjectCreate, + ObjectDefineProperties, + ObjectDefineProperty, + ObjectGetOwnPropertyDescriptor, + ObjectGetOwnPropertyDescriptors, + ObjectGetPrototypeOf, + ObjectPrototypeHasOwnProperty, + ObjectPrototypeIsPrototypeOf, + ObjectIs, + PromisePrototypeThen, + PromiseReject, + PromiseResolve, + ReflectApply, + ReflectDefineProperty, + ReflectGetOwnPropertyDescriptor, + ReflectHas, + ReflectOwnKeys, + RegExpPrototypeTest, + Set, + SetPrototypeEntries, + SetPrototypeForEach, + SetPrototypeKeys, + SetPrototypeValues, + SetPrototypeHas, + SetPrototypeClear, + SetPrototypeDelete, + SetPrototypeAdd, + // TODO(lucacasonato): add SharedArrayBuffer to primordials + // SharedArrayBufferPrototype + String, + StringFromCodePoint, + StringPrototypeCharCodeAt, + Symbol, + SymbolIterator, + SymbolToStringTag, + TypedArrayPrototypeGetSymbolToStringTag, + TypeError, + Uint16Array, + Uint32Array, + Uint8Array, + Uint8ClampedArray, +} = primordials; + +function makeException(ErrorType, message, opts = {}) { + return new ErrorType( + `${opts.prefix ? opts.prefix + ": " : ""}${ + opts.context ? opts.context : "Value" + } ${message}`, + ); +} - function makeException(ErrorType, message, opts = {}) { - return new ErrorType( - `${opts.prefix ? opts.prefix + ": " : ""}${ - opts.context ? opts.context : "Value" - } ${message}`, - ); +function toNumber(value) { + if (typeof value === "bigint") { + throw TypeError("Cannot convert a BigInt value to a number"); } + return Number(value); +} - function toNumber(value) { - if (typeof value === "bigint") { - throw TypeError("Cannot convert a BigInt value to a number"); - } - return Number(value); +function type(V) { + if (V === null) { + return "Null"; } + switch (typeof V) { + case "undefined": + return "Undefined"; + case "boolean": + return "Boolean"; + case "number": + return "Number"; + case "string": + return "String"; + case "symbol": + return "Symbol"; + case "bigint": + return "BigInt"; + case "object": + // Falls through + case "function": + // Falls through + default: + // Per ES spec, typeof returns an implemention-defined value that is not any of the existing ones for + // uncallable non-standard exotic objects. Yet Type() which the Web IDL spec depends on returns Object for + // such cases. So treat the default case as an object. + return "Object"; + } +} - function type(V) { - if (V === null) { - return "Null"; - } - switch (typeof V) { - case "undefined": - return "Undefined"; - case "boolean": - return "Boolean"; - case "number": - return "Number"; - case "string": - return "String"; - case "symbol": - return "Symbol"; - case "bigint": - return "BigInt"; - case "object": - // Falls through - case "function": - // Falls through - default: - // Per ES spec, typeof returns an implemention-defined value that is not any of the existing ones for - // uncallable non-standard exotic objects. Yet Type() which the Web IDL spec depends on returns Object for - // such cases. So treat the default case as an object. - return "Object"; - } +// Round x to the nearest integer, choosing the even integer if it lies halfway between two. +function evenRound(x) { + // There are four cases for numbers with fractional part being .5: + // + // case | x | floor(x) | round(x) | expected | x <> 0 | x % 1 | x & 1 | example + // 1 | 2n + 0.5 | 2n | 2n + 1 | 2n | > | 0.5 | 0 | 0.5 -> 0 + // 2 | 2n + 1.5 | 2n + 1 | 2n + 2 | 2n + 2 | > | 0.5 | 1 | 1.5 -> 2 + // 3 | -2n - 0.5 | -2n - 1 | -2n | -2n | < | -0.5 | 0 | -0.5 -> 0 + // 4 | -2n - 1.5 | -2n - 2 | -2n - 1 | -2n - 2 | < | -0.5 | 1 | -1.5 -> -2 + // (where n is a non-negative integer) + // + // Branch here for cases 1 and 4 + if ( + (x > 0 && x % 1 === +0.5 && (x & 1) === 0) || + (x < 0 && x % 1 === -0.5 && (x & 1) === 1) + ) { + return censorNegativeZero(MathFloor(x)); } - // Round x to the nearest integer, choosing the even integer if it lies halfway between two. - function evenRound(x) { - // There are four cases for numbers with fractional part being .5: - // - // case | x | floor(x) | round(x) | expected | x <> 0 | x % 1 | x & 1 | example - // 1 | 2n + 0.5 | 2n | 2n + 1 | 2n | > | 0.5 | 0 | 0.5 -> 0 - // 2 | 2n + 1.5 | 2n + 1 | 2n + 2 | 2n + 2 | > | 0.5 | 1 | 1.5 -> 2 - // 3 | -2n - 0.5 | -2n - 1 | -2n | -2n | < | -0.5 | 0 | -0.5 -> 0 - // 4 | -2n - 1.5 | -2n - 2 | -2n - 1 | -2n - 2 | < | -0.5 | 1 | -1.5 -> -2 - // (where n is a non-negative integer) - // - // Branch here for cases 1 and 4 - if ( - (x > 0 && x % 1 === +0.5 && (x & 1) === 0) || - (x < 0 && x % 1 === -0.5 && (x & 1) === 1) - ) { - return censorNegativeZero(MathFloor(x)); - } + return censorNegativeZero(MathRound(x)); +} - return censorNegativeZero(MathRound(x)); - } +function integerPart(n) { + return censorNegativeZero(MathTrunc(n)); +} - function integerPart(n) { - return censorNegativeZero(MathTrunc(n)); - } +function sign(x) { + return x < 0 ? -1 : 1; +} - function sign(x) { - return x < 0 ? -1 : 1; +function modulo(x, y) { + // https://tc39.github.io/ecma262/#eqn-modulo + // Note that http://stackoverflow.com/a/4467559/3191 does NOT work for large modulos + const signMightNotMatch = x % y; + if (sign(y) !== sign(signMightNotMatch)) { + return signMightNotMatch + y; } - - function modulo(x, y) { - // https://tc39.github.io/ecma262/#eqn-modulo - // Note that http://stackoverflow.com/a/4467559/3191 does NOT work for large modulos - const signMightNotMatch = x % y; - if (sign(y) !== sign(signMightNotMatch)) { - return signMightNotMatch + y; - } - return signMightNotMatch; + return signMightNotMatch; +} + +function censorNegativeZero(x) { + return x === 0 ? 0 : x; +} + +function createIntegerConversion(bitLength, typeOpts) { + const isSigned = !typeOpts.unsigned; + + let lowerBound; + let upperBound; + if (bitLength === 64) { + upperBound = NumberMAX_SAFE_INTEGER; + lowerBound = !isSigned ? 0 : NumberMIN_SAFE_INTEGER; + } else if (!isSigned) { + lowerBound = 0; + upperBound = MathPow(2, bitLength) - 1; + } else { + lowerBound = -MathPow(2, bitLength - 1); + upperBound = MathPow(2, bitLength - 1) - 1; } - function censorNegativeZero(x) { - return x === 0 ? 0 : x; - } + const twoToTheBitLength = MathPow(2, bitLength); + const twoToOneLessThanTheBitLength = MathPow(2, bitLength - 1); - function createIntegerConversion(bitLength, typeOpts) { - const isSigned = !typeOpts.unsigned; - - let lowerBound; - let upperBound; - if (bitLength === 64) { - upperBound = NumberMAX_SAFE_INTEGER; - lowerBound = !isSigned ? 0 : NumberMIN_SAFE_INTEGER; - } else if (!isSigned) { - lowerBound = 0; - upperBound = MathPow(2, bitLength) - 1; - } else { - lowerBound = -MathPow(2, bitLength - 1); - upperBound = MathPow(2, bitLength - 1) - 1; + return (V, opts = {}) => { + let x = toNumber(V); + x = censorNegativeZero(x); + + if (opts.enforceRange) { + if (!NumberIsFinite(x)) { + throw makeException(TypeError, "is not a finite number", opts); + } + + x = integerPart(x); + + if (x < lowerBound || x > upperBound) { + throw makeException( + TypeError, + `is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`, + opts, + ); + } + + return x; } - const twoToTheBitLength = MathPow(2, bitLength); - const twoToOneLessThanTheBitLength = MathPow(2, bitLength - 1); + if (!NumberIsNaN(x) && opts.clamp) { + x = MathMin(MathMax(x, lowerBound), upperBound); + x = evenRound(x); + return x; + } - return (V, opts = {}) => { - let x = toNumber(V); - x = censorNegativeZero(x); + if (!NumberIsFinite(x) || x === 0) { + return 0; + } + x = integerPart(x); - if (opts.enforceRange) { - if (!NumberIsFinite(x)) { - throw makeException(TypeError, "is not a finite number", opts); - } + // Math.pow(2, 64) is not accurately representable in JavaScript, so try to avoid these per-spec operations if + // possible. Hopefully it's an optimization for the non-64-bitLength cases too. + if (x >= lowerBound && x <= upperBound) { + return x; + } - x = integerPart(x); + // These will not work great for bitLength of 64, but oh well. See the README for more details. + x = modulo(x, twoToTheBitLength); + if (isSigned && x >= twoToOneLessThanTheBitLength) { + return x - twoToTheBitLength; + } + return x; + }; +} - if (x < lowerBound || x > upperBound) { - throw makeException( - TypeError, - `is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`, - opts, - ); - } +function createLongLongConversion(bitLength, { unsigned }) { + const upperBound = NumberMAX_SAFE_INTEGER; + const lowerBound = unsigned ? 0 : NumberMIN_SAFE_INTEGER; + const asBigIntN = unsigned ? BigIntAsUintN : BigIntAsIntN; - return x; - } + return (V, opts = {}) => { + let x = toNumber(V); + x = censorNegativeZero(x); - if (!NumberIsNaN(x) && opts.clamp) { - x = MathMin(MathMax(x, lowerBound), upperBound); - x = evenRound(x); - return x; + if (opts.enforceRange) { + if (!NumberIsFinite(x)) { + throw makeException(TypeError, "is not a finite number", opts); } - if (!NumberIsFinite(x) || x === 0) { - return 0; - } x = integerPart(x); - // Math.pow(2, 64) is not accurately representable in JavaScript, so try to avoid these per-spec operations if - // possible. Hopefully it's an optimization for the non-64-bitLength cases too. - if (x >= lowerBound && x <= upperBound) { - return x; + if (x < lowerBound || x > upperBound) { + throw makeException( + TypeError, + `is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`, + opts, + ); } - // These will not work great for bitLength of 64, but oh well. See the README for more details. - x = modulo(x, twoToTheBitLength); - if (isSigned && x >= twoToOneLessThanTheBitLength) { - return x - twoToTheBitLength; - } return x; - }; - } + } - function createLongLongConversion(bitLength, { unsigned }) { - const upperBound = NumberMAX_SAFE_INTEGER; - const lowerBound = unsigned ? 0 : NumberMIN_SAFE_INTEGER; - const asBigIntN = unsigned ? BigIntAsUintN : BigIntAsIntN; + if (!NumberIsNaN(x) && opts.clamp) { + x = MathMin(MathMax(x, lowerBound), upperBound); + x = evenRound(x); + return x; + } - return (V, opts = {}) => { - let x = toNumber(V); - x = censorNegativeZero(x); + if (!NumberIsFinite(x) || x === 0) { + return 0; + } - if (opts.enforceRange) { - if (!NumberIsFinite(x)) { - throw makeException(TypeError, "is not a finite number", opts); - } + let xBigInt = BigInt(integerPart(x)); + xBigInt = asBigIntN(bitLength, xBigInt); + return Number(xBigInt); + }; +} - x = integerPart(x); +const converters = []; - if (x < lowerBound || x > upperBound) { - throw makeException( - TypeError, - `is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`, - opts, - ); - } +converters.any = (V) => { + return V; +}; - return x; - } +converters.boolean = function (val) { + return !!val; +}; - if (!NumberIsNaN(x) && opts.clamp) { - x = MathMin(MathMax(x, lowerBound), upperBound); - x = evenRound(x); - return x; - } +converters.byte = createIntegerConversion(8, { unsigned: false }); +converters.octet = createIntegerConversion(8, { unsigned: true }); - if (!NumberIsFinite(x) || x === 0) { - return 0; - } +converters.short = createIntegerConversion(16, { unsigned: false }); +converters["unsigned short"] = createIntegerConversion(16, { + unsigned: true, +}); - let xBigInt = BigInt(integerPart(x)); - xBigInt = asBigIntN(bitLength, xBigInt); - return Number(xBigInt); - }; +converters.long = createIntegerConversion(32, { unsigned: false }); +converters["unsigned long"] = createIntegerConversion(32, { unsigned: true }); + +converters["long long"] = createLongLongConversion(64, { unsigned: false }); +converters["unsigned long long"] = createLongLongConversion(64, { + unsigned: true, +}); + +converters.float = (V, opts) => { + const x = toNumber(V); + + if (!NumberIsFinite(x)) { + throw makeException( + TypeError, + "is not a finite floating-point value", + opts, + ); } - const converters = []; + if (ObjectIs(x, -0)) { + return x; + } - converters.any = (V) => { - return V; - }; + const y = MathFround(x); - converters.boolean = function (val) { - return !!val; - }; + if (!NumberIsFinite(y)) { + throw makeException( + TypeError, + "is outside the range of a single-precision floating-point value", + opts, + ); + } - converters.byte = createIntegerConversion(8, { unsigned: false }); - converters.octet = createIntegerConversion(8, { unsigned: true }); + return y; +}; - converters.short = createIntegerConversion(16, { unsigned: false }); - converters["unsigned short"] = createIntegerConversion(16, { - unsigned: true, - }); +converters["unrestricted float"] = (V, _opts) => { + const x = toNumber(V); - converters.long = createIntegerConversion(32, { unsigned: false }); - converters["unsigned long"] = createIntegerConversion(32, { unsigned: true }); + if (isNaN(x)) { + return x; + } - converters["long long"] = createLongLongConversion(64, { unsigned: false }); - converters["unsigned long long"] = createLongLongConversion(64, { - unsigned: true, - }); + if (ObjectIs(x, -0)) { + return x; + } - converters.float = (V, opts) => { - const x = toNumber(V); + return MathFround(x); +}; - if (!NumberIsFinite(x)) { - throw makeException( - TypeError, - "is not a finite floating-point value", - opts, - ); - } +converters.double = (V, opts) => { + const x = toNumber(V); - if (ObjectIs(x, -0)) { - return x; - } + if (!NumberIsFinite(x)) { + throw makeException( + TypeError, + "is not a finite floating-point value", + opts, + ); + } - const y = MathFround(x); + return x; +}; - if (!NumberIsFinite(y)) { - throw makeException( - TypeError, - "is outside the range of a single-precision floating-point value", - opts, - ); - } +converters["unrestricted double"] = (V, _opts) => { + const x = toNumber(V); - return y; - }; + return x; +}; - converters["unrestricted float"] = (V, _opts) => { - const x = toNumber(V); +converters.DOMString = function (V, opts = {}) { + if (typeof V === "string") { + return V; + } else if (V === null && opts.treatNullAsEmptyString) { + return ""; + } else if (typeof V === "symbol") { + throw makeException( + TypeError, + "is a symbol, which cannot be converted to a string", + opts, + ); + } - if (isNaN(x)) { - return x; - } + return String(V); +}; - if (ObjectIs(x, -0)) { - return x; +// deno-lint-ignore no-control-regex +const IS_BYTE_STRING = /^[\x00-\xFF]*$/; +converters.ByteString = (V, opts) => { + const x = converters.DOMString(V, opts); + if (!RegExpPrototypeTest(IS_BYTE_STRING, x)) { + throw makeException(TypeError, "is not a valid ByteString", opts); + } + return x; +}; + +converters.USVString = (V, opts) => { + const S = converters.DOMString(V, opts); + const n = S.length; + let U = ""; + for (let i = 0; i < n; ++i) { + const c = StringPrototypeCharCodeAt(S, i); + if (c < 0xd800 || c > 0xdfff) { + U += StringFromCodePoint(c); + } else if (0xdc00 <= c && c <= 0xdfff) { + U += StringFromCodePoint(0xfffd); + } else if (i === n - 1) { + U += StringFromCodePoint(0xfffd); + } else { + const d = StringPrototypeCharCodeAt(S, i + 1); + if (0xdc00 <= d && d <= 0xdfff) { + const a = c & 0x3ff; + const b = d & 0x3ff; + U += StringFromCodePoint((2 << 15) + (2 << 9) * a + b); + ++i; + } else { + U += StringFromCodePoint(0xfffd); + } } + } + return U; +}; - return MathFround(x); - }; +converters.object = (V, opts) => { + if (type(V) !== "Object") { + throw makeException(TypeError, "is not an object", opts); + } - converters.double = (V, opts) => { - const x = toNumber(V); + return V; +}; - if (!NumberIsFinite(x)) { +// Not exported, but used in Function and VoidFunction. + +// Neither Function nor VoidFunction is defined with [TreatNonObjectAsNull], so +// handling for that is omitted. +function convertCallbackFunction(V, opts) { + if (typeof V !== "function") { + throw makeException(TypeError, "is not a function", opts); + } + return V; +} + +function isDataView(V) { + return ArrayBufferIsView(V) && + TypedArrayPrototypeGetSymbolToStringTag(V) === undefined; +} + +function isNonSharedArrayBuffer(V) { + return ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V); +} + +function isSharedArrayBuffer(V) { + // deno-lint-ignore prefer-primordials + return ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, V); +} + +converters.ArrayBuffer = (V, opts = {}) => { + if (!isNonSharedArrayBuffer(V)) { + if (opts.allowShared && !isSharedArrayBuffer(V)) { throw makeException( TypeError, - "is not a finite floating-point value", + "is not an ArrayBuffer or SharedArrayBuffer", opts, ); } + throw makeException(TypeError, "is not an ArrayBuffer", opts); + } - return x; - }; + return V; +}; - converters["unrestricted double"] = (V, _opts) => { - const x = toNumber(V); +converters.DataView = (V, opts = {}) => { + if (!isDataView(V)) { + throw makeException(TypeError, "is not a DataView", opts); + } - return x; - }; + if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { + throw makeException( + TypeError, + "is backed by a SharedArrayBuffer, which is not allowed", + opts, + ); + } + + return V; +}; + +// Returns the unforgeable `TypedArray` constructor name or `undefined`, +// if the `this` value isn't a valid `TypedArray` object. +// +// https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag +const typedArrayNameGetter = ObjectGetOwnPropertyDescriptor( + ObjectGetPrototypeOf(Uint8Array).prototype, + SymbolToStringTag, +).get; +ArrayPrototypeForEach( + [ + Int8Array, + Int16Array, + Int32Array, + Uint8Array, + Uint16Array, + Uint32Array, + Uint8ClampedArray, + Float32Array, + Float64Array, + ], + (func) => { + const name = func.name; + const article = RegExpPrototypeTest(/^[AEIOU]/, name) ? "an" : "a"; + converters[name] = (V, opts = {}) => { + if (!ArrayBufferIsView(V) || typedArrayNameGetter.call(V) !== name) { + throw makeException( + TypeError, + `is not ${article} ${name} object`, + opts, + ); + } + if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { + throw makeException( + TypeError, + "is a view on a SharedArrayBuffer, which is not allowed", + opts, + ); + } - converters.DOMString = function (V, opts = {}) { - if (typeof V === "string") { return V; - } else if (V === null && opts.treatNullAsEmptyString) { - return ""; - } else if (typeof V === "symbol") { + }; + }, +); + +// Common definitions + +converters.ArrayBufferView = (V, opts = {}) => { + if (!ArrayBufferIsView(V)) { + throw makeException( + TypeError, + "is not a view on an ArrayBuffer or SharedArrayBuffer", + opts, + ); + } + + if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { + throw makeException( + TypeError, + "is a view on a SharedArrayBuffer, which is not allowed", + opts, + ); + } + + return V; +}; + +converters.BufferSource = (V, opts = {}) => { + if (ArrayBufferIsView(V)) { + if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { throw makeException( TypeError, - "is a symbol, which cannot be converted to a string", + "is a view on a SharedArrayBuffer, which is not allowed", opts, ); } - return String(V); - }; + return V; + } + + if (!opts.allowShared && !isNonSharedArrayBuffer(V)) { + throw makeException( + TypeError, + "is not an ArrayBuffer or a view on one", + opts, + ); + } + if ( + opts.allowShared && + !isSharedArrayBuffer(V) && + !isNonSharedArrayBuffer(V) + ) { + throw makeException( + TypeError, + "is not an ArrayBuffer, SharedArrayBuffer, or a view on one", + opts, + ); + } - // deno-lint-ignore no-control-regex - const IS_BYTE_STRING = /^[\x00-\xFF]*$/; - converters.ByteString = (V, opts) => { - const x = converters.DOMString(V, opts); - if (!RegExpPrototypeTest(IS_BYTE_STRING, x)) { - throw makeException(TypeError, "is not a valid ByteString", opts); + return V; +}; + +converters.DOMTimeStamp = converters["unsigned long long"]; +converters.DOMHighResTimeStamp = converters["double"]; + +converters.Function = convertCallbackFunction; + +converters.VoidFunction = convertCallbackFunction; + +converters["UVString?"] = createNullableConverter( + converters.USVString, +); +converters["sequence<double>"] = createSequenceConverter( + converters.double, +); +converters["sequence<object>"] = createSequenceConverter( + converters.object, +); +converters["Promise<undefined>"] = createPromiseConverter(() => undefined); + +converters["sequence<ByteString>"] = createSequenceConverter( + converters.ByteString, +); +converters["sequence<sequence<ByteString>>"] = createSequenceConverter( + converters["sequence<ByteString>"], +); +converters["record<ByteString, ByteString>"] = createRecordConverter( + converters.ByteString, + converters.ByteString, +); + +converters["sequence<USVString>"] = createSequenceConverter( + converters.USVString, +); +converters["sequence<sequence<USVString>>"] = createSequenceConverter( + converters["sequence<USVString>"], +); +converters["record<USVString, USVString>"] = createRecordConverter( + converters.USVString, + converters.USVString, +); + +converters["sequence<DOMString>"] = createSequenceConverter( + converters.DOMString, +); + +function requiredArguments(length, required, opts = {}) { + if (length < required) { + const errMsg = `${ + opts.prefix ? opts.prefix + ": " : "" + }${required} argument${ + required === 1 ? "" : "s" + } required, but only ${length} present.`; + throw new TypeError(errMsg); + } +} + +function createDictionaryConverter(name, ...dictionaries) { + let hasRequiredKey = false; + const allMembers = []; + for (let i = 0; i < dictionaries.length; ++i) { + const members = dictionaries[i]; + for (let j = 0; j < members.length; ++j) { + const member = members[j]; + if (member.required) { + hasRequiredKey = true; + } + ArrayPrototypePush(allMembers, member); } - return x; - }; + } + ArrayPrototypeSort(allMembers, (a, b) => { + if (a.key == b.key) { + return 0; + } + return a.key < b.key ? -1 : 1; + }); - converters.USVString = (V, opts) => { - const S = converters.DOMString(V, opts); - const n = S.length; - let U = ""; - for (let i = 0; i < n; ++i) { - const c = StringPrototypeCharCodeAt(S, i); - if (c < 0xd800 || c > 0xdfff) { - U += StringFromCodePoint(c); - } else if (0xdc00 <= c && c <= 0xdfff) { - U += StringFromCodePoint(0xfffd); - } else if (i === n - 1) { - U += StringFromCodePoint(0xfffd); + const defaultValues = {}; + for (let i = 0; i < allMembers.length; ++i) { + const member = allMembers[i]; + if (ReflectHas(member, "defaultValue")) { + const idlMemberValue = member.defaultValue; + const imvType = typeof idlMemberValue; + // Copy by value types can be directly assigned, copy by reference types + // need to be re-created for each allocation. + if ( + imvType === "number" || imvType === "boolean" || + imvType === "string" || imvType === "bigint" || + imvType === "undefined" + ) { + defaultValues[member.key] = member.converter(idlMemberValue, {}); } else { - const d = StringPrototypeCharCodeAt(S, i + 1); - if (0xdc00 <= d && d <= 0xdfff) { - const a = c & 0x3ff; - const b = d & 0x3ff; - U += StringFromCodePoint((2 << 15) + (2 << 9) * a + b); - ++i; - } else { - U += StringFromCodePoint(0xfffd); - } + ObjectDefineProperty(defaultValues, member.key, { + get() { + return member.converter(idlMemberValue, member.defaultValue); + }, + enumerable: true, + }); } } - return U; - }; + } - converters.object = (V, opts) => { - if (type(V) !== "Object") { - throw makeException(TypeError, "is not an object", opts); + return function (V, opts = {}) { + const typeV = type(V); + switch (typeV) { + case "Undefined": + case "Null": + case "Object": + break; + default: + throw makeException( + TypeError, + "can not be converted to a dictionary", + opts, + ); } + const esDict = V; - return V; - }; - - // Not exported, but used in Function and VoidFunction. + const idlDict = ObjectAssign({}, defaultValues); - // Neither Function nor VoidFunction is defined with [TreatNonObjectAsNull], so - // handling for that is omitted. - function convertCallbackFunction(V, opts) { - if (typeof V !== "function") { - throw makeException(TypeError, "is not a function", opts); + // NOTE: fast path Null and Undefined. + if ((V === undefined || V === null) && !hasRequiredKey) { + return idlDict; } - return V; - } - - function isDataView(V) { - return ArrayBufferIsView(V) && - TypedArrayPrototypeGetSymbolToStringTag(V) === undefined; - } - function isNonSharedArrayBuffer(V) { - return ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V); - } + for (let i = 0; i < allMembers.length; ++i) { + const member = allMembers[i]; + const key = member.key; - function isSharedArrayBuffer(V) { - // deno-lint-ignore prefer-primordials - return ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, V); - } + let esMemberValue; + if (typeV === "Undefined" || typeV === "Null") { + esMemberValue = undefined; + } else { + esMemberValue = esDict[key]; + } - converters.ArrayBuffer = (V, opts = {}) => { - if (!isNonSharedArrayBuffer(V)) { - if (opts.allowShared && !isSharedArrayBuffer(V)) { + if (esMemberValue !== undefined) { + const context = `'${key}' of '${name}'${ + opts.context ? ` (${opts.context})` : "" + }`; + const converter = member.converter; + const idlMemberValue = converter(esMemberValue, { ...opts, context }); + idlDict[key] = idlMemberValue; + } else if (member.required) { throw makeException( TypeError, - "is not an ArrayBuffer or SharedArrayBuffer", + `can not be converted to '${name}' because '${key}' is required in '${name}'.`, opts, ); } - throw makeException(TypeError, "is not an ArrayBuffer", opts); } - return V; + return idlDict; }; +} - converters.DataView = (V, opts = {}) => { - if (!isDataView(V)) { - throw makeException(TypeError, "is not a DataView", opts); - } +// https://heycam.github.io/webidl/#es-enumeration +function createEnumConverter(name, values) { + const E = new Set(values); - if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { - throw makeException( - TypeError, - "is backed by a SharedArrayBuffer, which is not allowed", - opts, + return function (V, opts = {}) { + const S = String(V); + + if (!E.has(S)) { + throw new TypeError( + `${ + opts.prefix ? opts.prefix + ": " : "" + }The provided value '${S}' is not a valid enum value of type ${name}.`, ); } - return V; + return S; }; +} + +function createNullableConverter(converter) { + return (V, opts = {}) => { + // FIXME: If Type(V) is not Object, and the conversion to an IDL value is + // being performed due to V being assigned to an attribute whose type is a + // nullable callback function that is annotated with + // [LegacyTreatNonObjectAsNull], then return the IDL nullable type T? + // value null. + + if (V === null || V === undefined) return null; + return converter(V, opts); + }; +} - // Returns the unforgeable `TypedArray` constructor name or `undefined`, - // if the `this` value isn't a valid `TypedArray` object. - // - // https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag - const typedArrayNameGetter = ObjectGetOwnPropertyDescriptor( - ObjectGetPrototypeOf(Uint8Array).prototype, - SymbolToStringTag, - ).get; - ArrayPrototypeForEach( - [ - Int8Array, - Int16Array, - Int32Array, - Uint8Array, - Uint16Array, - Uint32Array, - Uint8ClampedArray, - Float32Array, - Float64Array, - ], - (func) => { - const name = func.name; - const article = RegExpPrototypeTest(/^[AEIOU]/, name) ? "an" : "a"; - converters[name] = (V, opts = {}) => { - if (!ArrayBufferIsView(V) || typedArrayNameGetter.call(V) !== name) { - throw makeException( - TypeError, - `is not ${article} ${name} object`, - opts, - ); - } - if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { - throw makeException( - TypeError, - "is a view on a SharedArrayBuffer, which is not allowed", - opts, - ); - } - - return V; - }; - }, - ); - - // Common definitions - - converters.ArrayBufferView = (V, opts = {}) => { - if (!ArrayBufferIsView(V)) { +// https://heycam.github.io/webidl/#es-sequence +function createSequenceConverter(converter) { + return function (V, opts = {}) { + if (type(V) !== "Object") { throw makeException( TypeError, - "is not a view on an ArrayBuffer or SharedArrayBuffer", + "can not be converted to sequence.", opts, ); } - - if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { + const iter = V?.[SymbolIterator]?.(); + if (iter === undefined) { throw makeException( TypeError, - "is a view on a SharedArrayBuffer, which is not allowed", + "can not be converted to sequence.", opts, ); } - - return V; - }; - - converters.BufferSource = (V, opts = {}) => { - if (ArrayBufferIsView(V)) { - if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { + const array = []; + while (true) { + const res = iter?.next?.(); + if (res === undefined) { throw makeException( TypeError, - "is a view on a SharedArrayBuffer, which is not allowed", + "can not be converted to sequence.", opts, ); } - - return V; + if (res.done === true) break; + const val = converter(res.value, { + ...opts, + context: `${opts.context}, index ${array.length}`, + }); + ArrayPrototypePush(array, val); } + return array; + }; +} - if (!opts.allowShared && !isNonSharedArrayBuffer(V)) { - throw makeException( - TypeError, - "is not an ArrayBuffer or a view on one", - opts, - ); - } - if ( - opts.allowShared && - !isSharedArrayBuffer(V) && - !isNonSharedArrayBuffer(V) - ) { +function createRecordConverter(keyConverter, valueConverter) { + return (V, opts) => { + if (type(V) !== "Object") { throw makeException( TypeError, - "is not an ArrayBuffer, SharedArrayBuffer, or a view on one", + "can not be converted to dictionary.", opts, ); } - - return V; - }; - - converters.DOMTimeStamp = converters["unsigned long long"]; - converters.DOMHighResTimeStamp = converters["double"]; - - converters.Function = convertCallbackFunction; - - converters.VoidFunction = convertCallbackFunction; - - converters["UVString?"] = createNullableConverter( - converters.USVString, - ); - converters["sequence<double>"] = createSequenceConverter( - converters.double, - ); - converters["sequence<object>"] = createSequenceConverter( - converters.object, - ); - converters["Promise<undefined>"] = createPromiseConverter(() => undefined); - - converters["sequence<ByteString>"] = createSequenceConverter( - converters.ByteString, - ); - converters["sequence<sequence<ByteString>>"] = createSequenceConverter( - converters["sequence<ByteString>"], - ); - converters["record<ByteString, ByteString>"] = createRecordConverter( - converters.ByteString, - converters.ByteString, - ); - - converters["sequence<USVString>"] = createSequenceConverter( - converters.USVString, - ); - converters["sequence<sequence<USVString>>"] = createSequenceConverter( - converters["sequence<USVString>"], - ); - converters["record<USVString, USVString>"] = createRecordConverter( - converters.USVString, - converters.USVString, - ); - - converters["sequence<DOMString>"] = createSequenceConverter( - converters.DOMString, - ); - - function requiredArguments(length, required, opts = {}) { - if (length < required) { - const errMsg = `${ - opts.prefix ? opts.prefix + ": " : "" - }${required} argument${ - required === 1 ? "" : "s" - } required, but only ${length} present.`; - throw new TypeError(errMsg); - } - } - - function createDictionaryConverter(name, ...dictionaries) { - let hasRequiredKey = false; - const allMembers = []; - for (let i = 0; i < dictionaries.length; ++i) { - const members = dictionaries[i]; - for (let j = 0; j < members.length; ++j) { - const member = members[j]; - if (member.required) { - hasRequiredKey = true; + const result = {}; + // Fast path for common case (not a Proxy) + if (!core.isProxy(V)) { + for (const key in V) { + if (!ObjectPrototypeHasOwnProperty(V, key)) { + continue; } - ArrayPrototypePush(allMembers, member); + const typedKey = keyConverter(key, opts); + const value = V[key]; + const typedValue = valueConverter(value, opts); + result[typedKey] = typedValue; } + return result; } - ArrayPrototypeSort(allMembers, (a, b) => { - if (a.key == b.key) { - return 0; + // Slow path if Proxy (e.g: in WPT tests) + const keys = ReflectOwnKeys(V); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + const desc = ObjectGetOwnPropertyDescriptor(V, key); + if (desc !== undefined && desc.enumerable === true) { + const typedKey = keyConverter(key, opts); + const value = V[key]; + const typedValue = valueConverter(value, opts); + result[typedKey] = typedValue; } - return a.key < b.key ? -1 : 1; + } + return result; + }; +} + +function createPromiseConverter(converter) { + return (V, opts) => + PromisePrototypeThen(PromiseResolve(V), (V) => converter(V, opts)); +} + +function invokeCallbackFunction( + callable, + args, + thisArg, + returnValueConverter, + opts, +) { + try { + const rv = ReflectApply(callable, thisArg, args); + return returnValueConverter(rv, { + prefix: opts.prefix, + context: "return value", }); - - const defaultValues = {}; - for (let i = 0; i < allMembers.length; ++i) { - const member = allMembers[i]; - if (ReflectHas(member, "defaultValue")) { - const idlMemberValue = member.defaultValue; - const imvType = typeof idlMemberValue; - // Copy by value types can be directly assigned, copy by reference types - // need to be re-created for each allocation. - if ( - imvType === "number" || imvType === "boolean" || - imvType === "string" || imvType === "bigint" || - imvType === "undefined" - ) { - defaultValues[member.key] = member.converter(idlMemberValue, {}); - } else { - ObjectDefineProperty(defaultValues, member.key, { - get() { - return member.converter(idlMemberValue, member.defaultValue); - }, - enumerable: true, - }); - } - } + } catch (err) { + if (opts.returnsPromise === true) { + return PromiseReject(err); } + throw err; + } +} - return function (V, opts = {}) { - const typeV = type(V); - switch (typeV) { - case "Undefined": - case "Null": - case "Object": - break; - default: - throw makeException( - TypeError, - "can not be converted to a dictionary", - opts, - ); - } - const esDict = V; - - const idlDict = ObjectAssign({}, defaultValues); - - // NOTE: fast path Null and Undefined. - if ((V === undefined || V === null) && !hasRequiredKey) { - return idlDict; - } - - for (let i = 0; i < allMembers.length; ++i) { - const member = allMembers[i]; - const key = member.key; - - let esMemberValue; - if (typeV === "Undefined" || typeV === "Null") { - esMemberValue = undefined; - } else { - esMemberValue = esDict[key]; - } - - if (esMemberValue !== undefined) { - const context = `'${key}' of '${name}'${ - opts.context ? ` (${opts.context})` : "" - }`; - const converter = member.converter; - const idlMemberValue = converter(esMemberValue, { ...opts, context }); - idlDict[key] = idlMemberValue; - } else if (member.required) { - throw makeException( - TypeError, - `can not be converted to '${name}' because '${key}' is required in '${name}'.`, - opts, - ); - } - } +const brand = Symbol("[[webidl.brand]]"); - return idlDict; - }; +function createInterfaceConverter(name, prototype) { + return (V, opts) => { + if (!ObjectPrototypeIsPrototypeOf(prototype, V) || V[brand] !== brand) { + throw makeException(TypeError, `is not of type ${name}.`, opts); + } + return V; + }; +} + +// TODO(lucacasonato): have the user pass in the prototype, and not the type. +function createBranded(Type) { + const t = ObjectCreate(Type.prototype); + t[brand] = brand; + return t; +} + +function assertBranded(self, prototype) { + if ( + !ObjectPrototypeIsPrototypeOf(prototype, self) || self[brand] !== brand + ) { + throw new TypeError("Illegal invocation"); + } +} + +function illegalConstructor() { + throw new TypeError("Illegal constructor"); +} + +function define(target, source) { + const keys = ReflectOwnKeys(source); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + const descriptor = ReflectGetOwnPropertyDescriptor(source, key); + if (descriptor && !ReflectDefineProperty(target, key, descriptor)) { + throw new TypeError(`Cannot redefine property: ${String(key)}`); + } } +} - // https://heycam.github.io/webidl/#es-enumeration - function createEnumConverter(name, values) { - const E = new Set(values); +const _iteratorInternal = Symbol("iterator internal"); - return function (V, opts = {}) { - const S = String(V); +const globalIteratorPrototype = ObjectGetPrototypeOf(ArrayIteratorPrototype); - if (!E.has(S)) { +function mixinPairIterable(name, prototype, dataSymbol, keyKey, valueKey) { + const iteratorPrototype = ObjectCreate(globalIteratorPrototype, { + [SymbolToStringTag]: { configurable: true, value: `${name} Iterator` }, + }); + define(iteratorPrototype, { + next() { + const internal = this && this[_iteratorInternal]; + if (!internal) { throw new TypeError( - `${ - opts.prefix ? opts.prefix + ": " : "" - }The provided value '${S}' is not a valid enum value of type ${name}.`, + `next() called on a value that is not a ${name} iterator object`, ); } - - return S; - }; + const { target, kind, index } = internal; + const values = target[dataSymbol]; + const len = values.length; + if (index >= len) { + return { value: undefined, done: true }; + } + const pair = values[index]; + internal.index = index + 1; + let result; + switch (kind) { + case "key": + result = pair[keyKey]; + break; + case "value": + result = pair[valueKey]; + break; + case "key+value": + result = [pair[keyKey], pair[valueKey]]; + break; + } + return { value: result, done: false }; + }, + }); + function createDefaultIterator(target, kind) { + const iterator = ObjectCreate(iteratorPrototype); + ObjectDefineProperty(iterator, _iteratorInternal, { + value: { target, kind, index: 0 }, + configurable: true, + }); + return iterator; } - function createNullableConverter(converter) { - return (V, opts = {}) => { - // FIXME: If Type(V) is not Object, and the conversion to an IDL value is - // being performed due to V being assigned to an attribute whose type is a - // nullable callback function that is annotated with - // [LegacyTreatNonObjectAsNull], then return the IDL nullable type T? - // value null. - - if (V === null || V === undefined) return null; - return converter(V, opts); - }; + function entries() { + assertBranded(this, prototype.prototype); + return createDefaultIterator(this, "key+value"); } - // https://heycam.github.io/webidl/#es-sequence - function createSequenceConverter(converter) { - return function (V, opts = {}) { - if (type(V) !== "Object") { - throw makeException( - TypeError, - "can not be converted to sequence.", - opts, - ); - } - const iter = V?.[SymbolIterator]?.(); - if (iter === undefined) { - throw makeException( - TypeError, - "can not be converted to sequence.", - opts, - ); - } - const array = []; - while (true) { - const res = iter?.next?.(); - if (res === undefined) { - throw makeException( - TypeError, - "can not be converted to sequence.", - opts, - ); - } - if (res.done === true) break; - const val = converter(res.value, { - ...opts, - context: `${opts.context}, index ${array.length}`, + const properties = { + entries: { + value: entries, + writable: true, + enumerable: true, + configurable: true, + }, + [SymbolIterator]: { + value: entries, + writable: true, + enumerable: false, + configurable: true, + }, + keys: { + value: function keys() { + assertBranded(this, prototype.prototype); + return createDefaultIterator(this, "key"); + }, + writable: true, + enumerable: true, + configurable: true, + }, + values: { + value: function values() { + assertBranded(this, prototype.prototype); + return createDefaultIterator(this, "value"); + }, + writable: true, + enumerable: true, + configurable: true, + }, + forEach: { + value: function forEach(idlCallback, thisArg = undefined) { + assertBranded(this, prototype.prototype); + const prefix = `Failed to execute 'forEach' on '${name}'`; + requiredArguments(arguments.length, 1, { prefix }); + idlCallback = converters["Function"](idlCallback, { + prefix, + context: "Argument 1", }); - ArrayPrototypePush(array, val); - } - return array; - }; - } - - function createRecordConverter(keyConverter, valueConverter) { - return (V, opts) => { - if (type(V) !== "Object") { - throw makeException( - TypeError, - "can not be converted to dictionary.", - opts, + idlCallback = FunctionPrototypeBind( + idlCallback, + thisArg ?? globalThis, ); - } - const result = {}; - // Fast path for common case (not a Proxy) - if (!core.isProxy(V)) { - for (const key in V) { - if (!ObjectPrototypeHasOwnProperty(V, key)) { - continue; - } - const typedKey = keyConverter(key, opts); - const value = V[key]; - const typedValue = valueConverter(value, opts); - result[typedKey] = typedValue; + const pairs = this[dataSymbol]; + for (let i = 0; i < pairs.length; i++) { + const entry = pairs[i]; + idlCallback(entry[valueKey], entry[keyKey], this); } - return result; - } - // Slow path if Proxy (e.g: in WPT tests) - const keys = ReflectOwnKeys(V); - for (let i = 0; i < keys.length; ++i) { - const key = keys[i]; - const desc = ObjectGetOwnPropertyDescriptor(V, key); - if (desc !== undefined && desc.enumerable === true) { - const typedKey = keyConverter(key, opts); - const value = V[key]; - const typedValue = valueConverter(value, opts); - result[typedKey] = typedValue; - } - } - return result; - }; - } - - function createPromiseConverter(converter) { - return (V, opts) => - PromisePrototypeThen(PromiseResolve(V), (V) => converter(V, opts)); - } - - function invokeCallbackFunction( - callable, - args, - thisArg, - returnValueConverter, - opts, - ) { - try { - const rv = ReflectApply(callable, thisArg, args); - return returnValueConverter(rv, { - prefix: opts.prefix, - context: "return value", - }); - } catch (err) { - if (opts.returnsPromise === true) { - return PromiseReject(err); - } - throw err; + }, + writable: true, + enumerable: true, + configurable: true, + }, + }; + return ObjectDefineProperties(prototype.prototype, properties); +} + +function configurePrototype(prototype) { + const descriptors = ObjectGetOwnPropertyDescriptors(prototype.prototype); + for (const key in descriptors) { + if (!ObjectPrototypeHasOwnProperty(descriptors, key)) { + continue; } - } - - const brand = Symbol("[[webidl.brand]]"); - - function createInterfaceConverter(name, prototype) { - return (V, opts) => { - if (!ObjectPrototypeIsPrototypeOf(prototype, V) || V[brand] !== brand) { - throw makeException(TypeError, `is not of type ${name}.`, opts); - } - return V; - }; - } - - // TODO(lucacasonato): have the user pass in the prototype, and not the type. - function createBranded(Type) { - const t = ObjectCreate(Type.prototype); - t[brand] = brand; - return t; - } - - function assertBranded(self, prototype) { + if (key === "constructor") continue; + const descriptor = descriptors[key]; if ( - !ObjectPrototypeIsPrototypeOf(prototype, self) || self[brand] !== brand + ReflectHas(descriptor, "value") && + typeof descriptor.value === "function" ) { - throw new TypeError("Illegal invocation"); - } - } - - function illegalConstructor() { - throw new TypeError("Illegal constructor"); - } - - function define(target, source) { - const keys = ReflectOwnKeys(source); - for (let i = 0; i < keys.length; ++i) { - const key = keys[i]; - const descriptor = ReflectGetOwnPropertyDescriptor(source, key); - if (descriptor && !ReflectDefineProperty(target, key, descriptor)) { - throw new TypeError(`Cannot redefine property: ${String(key)}`); - } - } - } - - const _iteratorInternal = Symbol("iterator internal"); - - const globalIteratorPrototype = ObjectGetPrototypeOf(ArrayIteratorPrototype); - - function mixinPairIterable(name, prototype, dataSymbol, keyKey, valueKey) { - const iteratorPrototype = ObjectCreate(globalIteratorPrototype, { - [SymbolToStringTag]: { configurable: true, value: `${name} Iterator` }, - }); - define(iteratorPrototype, { - next() { - const internal = this && this[_iteratorInternal]; - if (!internal) { - throw new TypeError( - `next() called on a value that is not a ${name} iterator object`, - ); - } - const { target, kind, index } = internal; - const values = target[dataSymbol]; - const len = values.length; - if (index >= len) { - return { value: undefined, done: true }; - } - const pair = values[index]; - internal.index = index + 1; - let result; - switch (kind) { - case "key": - result = pair[keyKey]; - break; - case "value": - result = pair[valueKey]; - break; - case "key+value": - result = [pair[keyKey], pair[valueKey]]; - break; - } - return { value: result, done: false }; - }, - }); - function createDefaultIterator(target, kind) { - const iterator = ObjectCreate(iteratorPrototype); - ObjectDefineProperty(iterator, _iteratorInternal, { - value: { target, kind, index: 0 }, + ObjectDefineProperty(prototype.prototype, key, { + enumerable: true, + writable: true, + configurable: true, + }); + } else if (ReflectHas(descriptor, "get")) { + ObjectDefineProperty(prototype.prototype, key, { + enumerable: true, configurable: true, }); - return iterator; } + } + ObjectDefineProperty(prototype.prototype, SymbolToStringTag, { + value: prototype.name, + enumerable: false, + configurable: true, + writable: false, + }); +} - function entries() { - assertBranded(this, prototype.prototype); - return createDefaultIterator(this, "key+value"); - } +const setlikeInner = Symbol("[[set]]"); - const properties = { - entries: { - value: entries, - writable: true, - enumerable: true, - configurable: true, +// Ref: https://webidl.spec.whatwg.org/#es-setlike +function setlike(obj, objPrototype, readonly) { + ObjectDefineProperties(obj, { + size: { + configurable: true, + enumerable: true, + get() { + assertBranded(this, objPrototype); + return obj[setlikeInner].size; }, - [SymbolIterator]: { - value: entries, - writable: true, - enumerable: false, - configurable: true, + }, + [SymbolIterator]: { + configurable: true, + enumerable: false, + writable: true, + value() { + assertBranded(this, objPrototype); + return obj[setlikeInner][SymbolIterator](); }, - keys: { - value: function keys() { - assertBranded(this, prototype.prototype); - return createDefaultIterator(this, "key"); - }, - writable: true, - enumerable: true, - configurable: true, + }, + entries: { + configurable: true, + enumerable: true, + writable: true, + value() { + assertBranded(this, objPrototype); + return SetPrototypeEntries(obj[setlikeInner]); }, - values: { - value: function values() { - assertBranded(this, prototype.prototype); - return createDefaultIterator(this, "value"); - }, - writable: true, - enumerable: true, - configurable: true, + }, + keys: { + configurable: true, + enumerable: true, + writable: true, + value() { + assertBranded(this, objPrototype); + return SetPrototypeKeys(obj[setlikeInner]); }, - forEach: { - value: function forEach(idlCallback, thisArg = undefined) { - assertBranded(this, prototype.prototype); - const prefix = `Failed to execute 'forEach' on '${name}'`; - requiredArguments(arguments.length, 1, { prefix }); - idlCallback = converters["Function"](idlCallback, { - prefix, - context: "Argument 1", - }); - idlCallback = FunctionPrototypeBind( - idlCallback, - thisArg ?? globalThis, - ); - const pairs = this[dataSymbol]; - for (let i = 0; i < pairs.length; i++) { - const entry = pairs[i]; - idlCallback(entry[valueKey], entry[keyKey], this); - } - }, - writable: true, - enumerable: true, - configurable: true, + }, + values: { + configurable: true, + enumerable: true, + writable: true, + value() { + assertBranded(this, objPrototype); + return SetPrototypeValues(obj[setlikeInner]); }, - }; - return ObjectDefineProperties(prototype.prototype, properties); - } - - function configurePrototype(prototype) { - const descriptors = ObjectGetOwnPropertyDescriptors(prototype.prototype); - for (const key in descriptors) { - if (!ObjectPrototypeHasOwnProperty(descriptors, key)) { - continue; - } - if (key === "constructor") continue; - const descriptor = descriptors[key]; - if ( - ReflectHas(descriptor, "value") && - typeof descriptor.value === "function" - ) { - ObjectDefineProperty(prototype.prototype, key, { - enumerable: true, - writable: true, - configurable: true, - }); - } else if (ReflectHas(descriptor, "get")) { - ObjectDefineProperty(prototype.prototype, key, { - enumerable: true, - configurable: true, - }); - } - } - ObjectDefineProperty(prototype.prototype, SymbolToStringTag, { - value: prototype.name, - enumerable: false, + }, + forEach: { configurable: true, - writable: false, - }); - } - - const setlikeInner = Symbol("[[set]]"); - - // Ref: https://webidl.spec.whatwg.org/#es-setlike - function setlike(obj, objPrototype, readonly) { - ObjectDefineProperties(obj, { - size: { - configurable: true, - enumerable: true, - get() { - assertBranded(this, objPrototype); - return obj[setlikeInner].size; - }, + enumerable: true, + writable: true, + value(callbackfn, thisArg) { + assertBranded(this, objPrototype); + return SetPrototypeForEach(obj[setlikeInner], callbackfn, thisArg); }, - [SymbolIterator]: { - configurable: true, - enumerable: false, - writable: true, - value() { - assertBranded(this, objPrototype); - return obj[setlikeInner][SymbolIterator](); - }, + }, + has: { + configurable: true, + enumerable: true, + writable: true, + value(value) { + assertBranded(this, objPrototype); + return SetPrototypeHas(obj[setlikeInner], value); }, - entries: { + }, + }); + + if (!readonly) { + ObjectDefineProperties(obj, { + add: { configurable: true, enumerable: true, writable: true, - value() { + value(value) { assertBranded(this, objPrototype); - return SetPrototypeEntries(obj[setlikeInner]); + return SetPrototypeAdd(obj[setlikeInner], value); }, }, - keys: { + delete: { configurable: true, enumerable: true, writable: true, - value() { + value(value) { assertBranded(this, objPrototype); - return SetPrototypeKeys(obj[setlikeInner]); + return SetPrototypeDelete(obj[setlikeInner], value); }, }, - values: { + clear: { configurable: true, enumerable: true, writable: true, value() { assertBranded(this, objPrototype); - return SetPrototypeValues(obj[setlikeInner]); - }, - }, - forEach: { - configurable: true, - enumerable: true, - writable: true, - value(callbackfn, thisArg) { - assertBranded(this, objPrototype); - return SetPrototypeForEach(obj[setlikeInner], callbackfn, thisArg); - }, - }, - has: { - configurable: true, - enumerable: true, - writable: true, - value(value) { - assertBranded(this, objPrototype); - return SetPrototypeHas(obj[setlikeInner], value); + return SetPrototypeClear(obj[setlikeInner]); }, }, }); - - if (!readonly) { - ObjectDefineProperties(obj, { - add: { - configurable: true, - enumerable: true, - writable: true, - value(value) { - assertBranded(this, objPrototype); - return SetPrototypeAdd(obj[setlikeInner], value); - }, - }, - delete: { - configurable: true, - enumerable: true, - writable: true, - value(value) { - assertBranded(this, objPrototype); - return SetPrototypeDelete(obj[setlikeInner], value); - }, - }, - clear: { - configurable: true, - enumerable: true, - writable: true, - value() { - assertBranded(this, objPrototype); - return SetPrototypeClear(obj[setlikeInner]); - }, - }, - }); - } } - - window.__bootstrap ??= {}; - window.__bootstrap.webidl = { - type, - makeException, - converters, - requiredArguments, - createDictionaryConverter, - createEnumConverter, - createNullableConverter, - createSequenceConverter, - createRecordConverter, - createPromiseConverter, - invokeCallbackFunction, - createInterfaceConverter, - brand, - createBranded, - assertBranded, - illegalConstructor, - mixinPairIterable, - configurePrototype, - setlike, - setlikeInner, - }; -})(this); +} + +export { + assertBranded, + brand, + configurePrototype, + converters, + createBranded, + createDictionaryConverter, + createEnumConverter, + createInterfaceConverter, + createNullableConverter, + createPromiseConverter, + createRecordConverter, + createSequenceConverter, + illegalConstructor, + invokeCallbackFunction, + makeException, + mixinPairIterable, + requiredArguments, + setlike, + setlikeInner, + type, +}; diff --git a/ext/webidl/benches/dict.js b/ext/webidl/benches/dict.js index 353a630eb..b53326de9 100644 --- a/ext/webidl/benches/dict.js +++ b/ext/webidl/benches/dict.js @@ -2,7 +2,10 @@ // deno-lint-ignore-file -const { createDictionaryConverter, converters } = globalThis.__bootstrap.webidl; +import { + converters, + createDictionaryConverter, +} from "internal:ext/webidl/00_webidl.js"; const TextDecodeOptions = createDictionaryConverter( "TextDecodeOptions", @@ -14,6 +17,7 @@ const TextDecodeOptions = createDictionaryConverter( }, ], ); +globalThis.TextDecodeOptions = TextDecodeOptions; // Sanity check { @@ -33,3 +37,4 @@ function handwrittenConverter(V) { } return defaultValue; } +globalThis.handwrittenConverter = handwrittenConverter; diff --git a/ext/webidl/benches/dict.rs b/ext/webidl/benches/dict.rs index e7df8af62..1400a00ed 100644 --- a/ext/webidl/benches/dict.rs +++ b/ext/webidl/benches/dict.rs @@ -11,7 +11,7 @@ fn setup() -> Vec<Extension> { vec![ deno_webidl::init(), Extension::builder("deno_webidl_bench") - .js(vec![("setup", include_str!("dict.js"))]) + .esm(vec![("internal:setup", include_str!("dict.js"))]) .build(), ] } diff --git a/ext/webidl/internal.d.ts b/ext/webidl/internal.d.ts index 4ab9e33a9..9f47c42e5 100644 --- a/ext/webidl/internal.d.ts +++ b/ext/webidl/internal.d.ts @@ -4,338 +4,334 @@ /// <reference no-default-lib="true" /> /// <reference lib="esnext" /> -declare namespace globalThis { - declare namespace __bootstrap { - declare namespace webidl { - declare interface ConverterOpts { - /** - * The prefix for error messages created by this converter. - * Examples: - * - `Failed to construct 'Event'` - * - `Failed to execute 'removeEventListener' on 'EventTarget'` - */ - prefix: string; - } - declare interface ValueConverterOpts extends ConverterOpts { - /** - * The context of this value error messages created by this converter. - * Examples: - * - `Argument 1` - * - `Argument 3` - */ - context: string; - } - declare function makeException( - ErrorType: any, - message: string, - opts: ValueConverterOpts, - ): any; - declare interface IntConverterOpts extends ValueConverterOpts { - /** - * Wether to throw if the number is outside of the acceptable values for - * this type. - */ - enforceRange?: boolean; - /** - * Wether to clamp this number to the acceptable values for this type. - */ - clamp?: boolean; - } - declare interface StringConverterOpts extends ValueConverterOpts { - /** - * Wether to treat `null` value as an empty string. - */ - treatNullAsEmptyString?: boolean; - } - declare interface BufferConverterOpts extends ValueConverterOpts { - /** - * Wether to allow `SharedArrayBuffer` (not just `ArrayBuffer`). - */ - allowShared?: boolean; - } - declare const converters: { - any(v: any): any; - /** - * Convert a value into a `boolean` (bool). - */ - boolean(v: any, opts?: IntConverterOpts): boolean; - /** - * Convert a value into a `byte` (int8). - */ - byte(v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `octet` (uint8). - */ - octet(v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `short` (int16). - */ - short(v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `unsigned short` (uint16). - */ - ["unsigned short"](v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `long` (int32). - */ - long(v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `unsigned long` (uint32). - */ - ["unsigned long"](v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `long long` (int64). - * **Note this is truncated to a JS number (53 bit precision).** - */ - ["long long"](v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `unsigned long long` (uint64). - * **Note this is truncated to a JS number (53 bit precision).** - */ - ["unsigned long long"](v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `float` (f32). - */ - float(v: any, opts?: ValueConverterOpts): number; - /** - * Convert a value into a `unrestricted float` (f32, infinity, or NaN). - */ - ["unrestricted float"](v: any, opts?: ValueConverterOpts): number; - /** - * Convert a value into a `double` (f64). - */ - double(v: any, opts?: ValueConverterOpts): number; - /** - * Convert a value into a `unrestricted double` (f64, infinity, or NaN). - */ - ["unrestricted double"](v: any, opts?: ValueConverterOpts): number; - /** - * Convert a value into a `DOMString` (string). - */ - DOMString(v: any, opts?: StringConverterOpts): string; - /** - * Convert a value into a `ByteString` (string with only u8 codepoints). - */ - ByteString(v: any, opts?: StringConverterOpts): string; - /** - * Convert a value into a `USVString` (string with only valid non - * surrogate Unicode code points). - */ - USVString(v: any, opts?: StringConverterOpts): string; - /** - * Convert a value into an `object` (object). - */ - object(v: any, opts?: ValueConverterOpts): object; - /** - * Convert a value into an `ArrayBuffer` (ArrayBuffer). - */ - ArrayBuffer(v: any, opts?: BufferConverterOpts): ArrayBuffer; - /** - * Convert a value into a `DataView` (ArrayBuffer). - */ - DataView(v: any, opts?: BufferConverterOpts): DataView; - /** - * Convert a value into a `Int8Array` (Int8Array). - */ - Int8Array(v: any, opts?: BufferConverterOpts): Int8Array; - /** - * Convert a value into a `Int16Array` (Int16Array). - */ - Int16Array(v: any, opts?: BufferConverterOpts): Int16Array; - /** - * Convert a value into a `Int32Array` (Int32Array). - */ - Int32Array(v: any, opts?: BufferConverterOpts): Int32Array; - /** - * Convert a value into a `Uint8Array` (Uint8Array). - */ - Uint8Array(v: any, opts?: BufferConverterOpts): Uint8Array; - /** - * Convert a value into a `Uint16Array` (Uint16Array). - */ - Uint16Array(v: any, opts?: BufferConverterOpts): Uint16Array; - /** - * Convert a value into a `Uint32Array` (Uint32Array). - */ - Uint32Array(v: any, opts?: BufferConverterOpts): Uint32Array; - /** - * Convert a value into a `Uint8ClampedArray` (Uint8ClampedArray). - */ - Uint8ClampedArray( - v: any, - opts?: BufferConverterOpts, - ): Uint8ClampedArray; - /** - * Convert a value into a `Float32Array` (Float32Array). - */ - Float32Array(v: any, opts?: BufferConverterOpts): Float32Array; - /** - * Convert a value into a `Float64Array` (Float64Array). - */ - Float64Array(v: any, opts?: BufferConverterOpts): Float64Array; - /** - * Convert a value into an `ArrayBufferView` (ArrayBufferView). - */ - ArrayBufferView(v: any, opts?: BufferConverterOpts): ArrayBufferView; - /** - * Convert a value into a `BufferSource` (ArrayBuffer or ArrayBufferView). - */ - BufferSource( - v: any, - opts?: BufferConverterOpts, - ): ArrayBuffer | ArrayBufferView; - /** - * Convert a value into a `DOMTimeStamp` (u64). Alias for unsigned long long - */ - DOMTimeStamp(v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `Function` ((...args: any[]) => any). - */ - Function(v: any, opts?: ValueConverterOpts): (...args: any) => any; - /** - * Convert a value into a `VoidFunction` (() => void). - */ - VoidFunction(v: any, opts?: ValueConverterOpts): () => void; - ["UVString?"](v: any, opts?: ValueConverterOpts): string | null; - ["sequence<double>"](v: any, opts?: ValueConverterOpts): number[]; +declare module "internal:ext/webidl/00_webidl.js" { + interface ConverterOpts { + /** + * The prefix for error messages created by this converter. + * Examples: + * - `Failed to construct 'Event'` + * - `Failed to execute 'removeEventListener' on 'EventTarget'` + */ + prefix: string; + } + interface ValueConverterOpts extends ConverterOpts { + /** + * The context of this value error messages created by this converter. + * Examples: + * - `Argument 1` + * - `Argument 3` + */ + context: string; + } + function makeException( + ErrorType: any, + message: string, + opts: ValueConverterOpts, + ): any; + interface IntConverterOpts extends ValueConverterOpts { + /** + * Wether to throw if the number is outside of the acceptable values for + * this type. + */ + enforceRange?: boolean; + /** + * Wether to clamp this number to the acceptable values for this type. + */ + clamp?: boolean; + } + interface StringConverterOpts extends ValueConverterOpts { + /** + * Wether to treat `null` value as an empty string. + */ + treatNullAsEmptyString?: boolean; + } + interface BufferConverterOpts extends ValueConverterOpts { + /** + * Wether to allow `SharedArrayBuffer` (not just `ArrayBuffer`). + */ + allowShared?: boolean; + } + const converters: { + any(v: any): any; + /** + * Convert a value into a `boolean` (bool). + */ + boolean(v: any, opts?: IntConverterOpts): boolean; + /** + * Convert a value into a `byte` (int8). + */ + byte(v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `octet` (uint8). + */ + octet(v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `short` (int16). + */ + short(v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `unsigned short` (uint16). + */ + ["unsigned short"](v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `long` (int32). + */ + long(v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `unsigned long` (uint32). + */ + ["unsigned long"](v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `long long` (int64). + * **Note this is truncated to a JS number (53 bit precision).** + */ + ["long long"](v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `unsigned long long` (uint64). + * **Note this is truncated to a JS number (53 bit precision).** + */ + ["unsigned long long"](v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `float` (f32). + */ + float(v: any, opts?: ValueConverterOpts): number; + /** + * Convert a value into a `unrestricted float` (f32, infinity, or NaN). + */ + ["unrestricted float"](v: any, opts?: ValueConverterOpts): number; + /** + * Convert a value into a `double` (f64). + */ + double(v: any, opts?: ValueConverterOpts): number; + /** + * Convert a value into a `unrestricted double` (f64, infinity, or NaN). + */ + ["unrestricted double"](v: any, opts?: ValueConverterOpts): number; + /** + * Convert a value into a `DOMString` (string). + */ + DOMString(v: any, opts?: StringConverterOpts): string; + /** + * Convert a value into a `ByteString` (string with only u8 codepoints). + */ + ByteString(v: any, opts?: StringConverterOpts): string; + /** + * Convert a value into a `USVString` (string with only valid non + * surrogate Unicode code points). + */ + USVString(v: any, opts?: StringConverterOpts): string; + /** + * Convert a value into an `object` (object). + */ + object(v: any, opts?: ValueConverterOpts): object; + /** + * Convert a value into an `ArrayBuffer` (ArrayBuffer). + */ + ArrayBuffer(v: any, opts?: BufferConverterOpts): ArrayBuffer; + /** + * Convert a value into a `DataView` (ArrayBuffer). + */ + DataView(v: any, opts?: BufferConverterOpts): DataView; + /** + * Convert a value into a `Int8Array` (Int8Array). + */ + Int8Array(v: any, opts?: BufferConverterOpts): Int8Array; + /** + * Convert a value into a `Int16Array` (Int16Array). + */ + Int16Array(v: any, opts?: BufferConverterOpts): Int16Array; + /** + * Convert a value into a `Int32Array` (Int32Array). + */ + Int32Array(v: any, opts?: BufferConverterOpts): Int32Array; + /** + * Convert a value into a `Uint8Array` (Uint8Array). + */ + Uint8Array(v: any, opts?: BufferConverterOpts): Uint8Array; + /** + * Convert a value into a `Uint16Array` (Uint16Array). + */ + Uint16Array(v: any, opts?: BufferConverterOpts): Uint16Array; + /** + * Convert a value into a `Uint32Array` (Uint32Array). + */ + Uint32Array(v: any, opts?: BufferConverterOpts): Uint32Array; + /** + * Convert a value into a `Uint8ClampedArray` (Uint8ClampedArray). + */ + Uint8ClampedArray( + v: any, + opts?: BufferConverterOpts, + ): Uint8ClampedArray; + /** + * Convert a value into a `Float32Array` (Float32Array). + */ + Float32Array(v: any, opts?: BufferConverterOpts): Float32Array; + /** + * Convert a value into a `Float64Array` (Float64Array). + */ + Float64Array(v: any, opts?: BufferConverterOpts): Float64Array; + /** + * Convert a value into an `ArrayBufferView` (ArrayBufferView). + */ + ArrayBufferView(v: any, opts?: BufferConverterOpts): ArrayBufferView; + /** + * Convert a value into a `BufferSource` (ArrayBuffer or ArrayBufferView). + */ + BufferSource( + v: any, + opts?: BufferConverterOpts, + ): ArrayBuffer | ArrayBufferView; + /** + * Convert a value into a `DOMTimeStamp` (u64). Alias for unsigned long long + */ + DOMTimeStamp(v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `Function` ((...args: any[]) => any). + */ + Function(v: any, opts?: ValueConverterOpts): (...args: any) => any; + /** + * Convert a value into a `VoidFunction` (() => void). + */ + VoidFunction(v: any, opts?: ValueConverterOpts): () => void; + ["UVString?"](v: any, opts?: ValueConverterOpts): string | null; + ["sequence<double>"](v: any, opts?: ValueConverterOpts): number[]; - [type: string]: (v: any, opts: ValueConverterOpts) => any; - }; + [type: string]: (v: any, opts: ValueConverterOpts) => any; + }; - /** - * Assert that the a function has at least a required amount of arguments. - */ - declare function requiredArguments( - length: number, - required: number, - opts: ConverterOpts, - ): void; - declare type Dictionary = DictionaryMember[]; - declare interface DictionaryMember { - key: string; - converter: (v: any, opts: ValueConverterOpts) => any; - defaultValue?: any; - required?: boolean; - } + /** + * Assert that the a function has at least a required amount of arguments. + */ + function requiredArguments( + length: number, + required: number, + opts: ConverterOpts, + ): void; + type Dictionary = DictionaryMember[]; + interface DictionaryMember { + key: string; + converter: (v: any, opts: ValueConverterOpts) => any; + defaultValue?: any; + required?: boolean; + } - /** - * Create a converter for dictionaries. - */ - declare function createDictionaryConverter<T>( - name: string, - ...dictionaries: Dictionary[] - ): (v: any, opts: ValueConverterOpts) => T; + /** + * Create a converter for dictionaries. + */ + function createDictionaryConverter<T>( + name: string, + ...dictionaries: Dictionary[] + ): (v: any, opts: ValueConverterOpts) => T; - /** - * Create a converter for enums. - */ - declare function createEnumConverter( - name: string, - values: string[], - ): (v: any, opts: ValueConverterOpts) => string; + /** + * Create a converter for enums. + */ + function createEnumConverter( + name: string, + values: string[], + ): (v: any, opts: ValueConverterOpts) => string; - /** - * Create a converter that makes the contained type nullable. - */ - declare function createNullableConverter<T>( - converter: (v: any, opts: ValueConverterOpts) => T, - ): (v: any, opts: ValueConverterOpts) => T | null; + /** + * Create a converter that makes the contained type nullable. + */ + function createNullableConverter<T>( + converter: (v: any, opts: ValueConverterOpts) => T, + ): (v: any, opts: ValueConverterOpts) => T | null; - /** - * Create a converter that converts a sequence of the inner type. - */ - declare function createSequenceConverter<T>( - converter: (v: any, opts: ValueConverterOpts) => T, - ): (v: any, opts: ValueConverterOpts) => T[]; + /** + * Create a converter that converts a sequence of the inner type. + */ + function createSequenceConverter<T>( + converter: (v: any, opts: ValueConverterOpts) => T, + ): (v: any, opts: ValueConverterOpts) => T[]; - /** - * Create a converter that converts a Promise of the inner type. - */ - declare function createPromiseConverter<T>( - converter: (v: any, opts: ValueConverterOpts) => T, - ): (v: any, opts: ValueConverterOpts) => Promise<T>; + /** + * Create a converter that converts a Promise of the inner type. + */ + function createPromiseConverter<T>( + converter: (v: any, opts: ValueConverterOpts) => T, + ): (v: any, opts: ValueConverterOpts) => Promise<T>; - /** - * Invoke a callback function. - */ - declare function invokeCallbackFunction<T>( - callable: (...args: any) => any, - args: any[], - thisArg: any, - returnValueConverter: (v: any, opts: ValueConverterOpts) => T, - opts: ConverterOpts & { returnsPromise?: boolean }, - ): T; + /** + * Invoke a callback function. + */ + function invokeCallbackFunction<T>( + callable: (...args: any) => any, + args: any[], + thisArg: any, + returnValueConverter: (v: any, opts: ValueConverterOpts) => T, + opts: ConverterOpts & { returnsPromise?: boolean }, + ): T; - /** - * Throw an illegal constructor error. - */ - declare function illegalConstructor(): never; + /** + * Throw an illegal constructor error. + */ + function illegalConstructor(): never; - /** - * The branding symbol. - */ - declare const brand: unique symbol; + /** + * The branding symbol. + */ + const brand: unique symbol; - /** - * Create a branded instance of an interface. - */ - declare function createBranded(self: any): any; + /** + * Create a branded instance of an interface. + */ + function createBranded(self: any): any; - /** - * Assert that self is branded. - */ - declare function assertBranded(self: any, type: any): void; + /** + * Assert that self is branded. + */ + function assertBranded(self: any, type: any): void; - /** - * Create a converter for interfaces. - */ - declare function createInterfaceConverter( - name: string, - prototype: any, - ): (v: any, opts: ValueConverterOpts) => any; + /** + * Create a converter for interfaces. + */ + function createInterfaceConverter( + name: string, + prototype: any, + ): (v: any, opts: ValueConverterOpts) => any; - declare function createRecordConverter< - K extends string | number | symbol, - V, - >( - keyConverter: (v: any, opts: ValueConverterOpts) => K, - valueConverter: (v: any, opts: ValueConverterOpts) => V, - ): ( - v: Record<K, V>, - opts: ValueConverterOpts, - ) => any; + function createRecordConverter< + K extends string | number | symbol, + V, + >( + keyConverter: (v: any, opts: ValueConverterOpts) => K, + valueConverter: (v: any, opts: ValueConverterOpts) => V, + ): ( + v: Record<K, V>, + opts: ValueConverterOpts, + ) => any; - /** - * Mix in the iterable declarations defined in WebIDL. - * https://heycam.github.io/webidl/#es-iterable - */ - declare function mixinPairIterable( - name: string, - prototype: any, - dataSymbol: symbol, - keyKey: string | number | symbol, - valueKey: string | number | symbol, - ): void; + /** + * Mix in the iterable declarations defined in WebIDL. + * https://heycam.github.io/webidl/#es-iterable + */ + function mixinPairIterable( + name: string, + prototype: any, + dataSymbol: symbol, + keyKey: string | number | symbol, + valueKey: string | number | symbol, + ): void; - /** - * Configure prototype properties enumerability / writability / configurability. - */ - declare function configurePrototype(prototype: any); + /** + * Configure prototype properties enumerability / writability / configurability. + */ + function configurePrototype(prototype: any); - /** - * Get the WebIDL / ES type of a value. - */ - declare function type( - v: any, - ): - | "Null" - | "Undefined" - | "Boolean" - | "Number" - | "String" - | "Symbol" - | "BigInt" - | "Object"; - } - } + /** + * Get the WebIDL / ES type of a value. + */ + function type( + v: any, + ): + | "Null" + | "Undefined" + | "Boolean" + | "Number" + | "String" + | "Symbol" + | "BigInt" + | "Object"; } diff --git a/ext/webidl/lib.rs b/ext/webidl/lib.rs index ae25f04c7..4e21ef796 100644 --- a/ext/webidl/lib.rs +++ b/ext/webidl/lib.rs @@ -6,7 +6,7 @@ use deno_core::Extension; /// Load and execute the javascript code. pub fn init() -> Extension { Extension::builder(env!("CARGO_PKG_NAME")) - .js(include_js_files!( + .esm(include_js_files!( prefix "internal:ext/webidl", "00_webidl.js", )) |