diff --git a/lib/constructs/interface.js b/lib/constructs/interface.js index 574636c2..8526b883 100644 --- a/lib/constructs/interface.js +++ b/lib/constructs/interface.js @@ -424,13 +424,15 @@ class Interface { } if (iterable.isAsync) { + this.requires.addRaw("newObjectInRealm", "utils.newObjectInRealm"); this.str += ` - ctorRegistry["${this.name} AsyncIterator"] = Object.create(utils.AsyncIteratorPrototype, { - [Symbol.toStringTag]: { - value: "${this.name} AsyncIterator", - configurable: true - } - }); + ctorRegistry["${this.name} AsyncIterator"] = + Object.create(ctorRegistry["%AsyncIteratorPrototype%"], { + [Symbol.toStringTag]: { + value: "${this.name} AsyncIterator", + configurable: true + } + }); utils.define(ctorRegistry["${this.name} AsyncIterator"], { next() { const internal = this && this[utils.iterInternalSymbol]; @@ -440,7 +442,7 @@ class Interface { const nextSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value: undefined, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value: undefined, done: true })); } const nextPromise = internal.target[implSymbol][utils.asyncIteratorNext](this); @@ -449,15 +451,15 @@ class Interface { internal.ongoingPromise = null; if (next === utils.asyncIteratorEOI) { internal.isFinished = true; - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); }`; if (iterable.isPair) { this.str += ` - return utils.iteratorResult(next.map(utils.tryWrapperForImpl), kind); + return newObjectInRealm(globalObject, utils.iteratorResult(next.map(utils.tryWrapperForImpl), kind)); `; } else { this.str += ` - return { value: utils.tryWrapperForImpl(next), done: false }; + return newObjectInRealm(globalObject, { value: utils.tryWrapperForImpl(next), done: false }); `; } this.str += ` @@ -487,7 +489,7 @@ class Interface { const returnSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value, done: true })); } internal.isFinished = true; @@ -497,7 +499,7 @@ class Interface { const returnPromise = internal.ongoingPromise ? internal.ongoingPromise.then(returnSteps, returnSteps) : returnSteps(); - return returnPromise.then(() => ({ value, done: true })); + return returnPromise.then(() => newObjectInRealm(globalObject, { value, done: true })); } `; } @@ -505,6 +507,7 @@ class Interface { }); `; } else if (iterable.isPair) { + this.requires.addRaw("newObjectInRealm", "utils.newObjectInRealm"); this.str += ` ctorRegistry["${this.name} Iterator"] = Object.create(ctorRegistry["%IteratorPrototype%"], { @@ -526,12 +529,12 @@ class Interface { const values = Array.from(target[implSymbol]); const len = values.length; if (index >= len) { - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } const pair = values[index]; internal.index = index + 1; - return utils.iteratorResult(pair.map(utils.tryWrapperForImpl), kind); + return newObjectInRealm(globalObject, utils.iteratorResult(pair.map(utils.tryWrapperForImpl), kind)); } } ); diff --git a/lib/output/utils.js b/lib/output/utils.js index d6ddefd0..dbfe68ff 100644 --- a/lib/output/utils.js +++ b/lib/output/utils.js @@ -18,6 +18,14 @@ function define(target, source) { } } +function newObjectInRealm(globalObject, object) { + const ctorRegistry = initCtorRegistry(globalObject); + return Object.defineProperties( + Object.create(ctorRegistry["%Object.prototype%"]), + Object.getOwnPropertyDescriptors(object) + ); +} + const wrapperSymbol = Symbol("wrapper"); const implSymbol = Symbol("impl"); const sameObjectCaches = Symbol("SameObject caches"); @@ -26,6 +34,8 @@ const ctorRegistrySymbol = Symbol.for("[webidl2js] constructor registry"); // This only contains the intrinsic names that are referenced from the `ctorRegistry`: const intrinsicConstructors = ["Array"]; +const AsyncIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(async function* () {}).prototype); + function initCtorRegistry(globalObject) { if (hasOwn(globalObject, ctorRegistrySymbol)) { return globalObject[ctorRegistrySymbol]; @@ -36,11 +46,21 @@ function initCtorRegistry(globalObject) { ctorRegistry[`%${intrinsic}%`] = globalObject[intrinsic]; } - // TODO: Also capture `%AsyncIteratorPrototype%` + ctorRegistry["%Object.prototype%"] = globalObject.Object.prototype; ctorRegistry["%IteratorPrototype%"] = Object.getPrototypeOf( Object.getPrototypeOf(new ctorRegistry["%Array%"]()[Symbol.iterator]()) ); + try { + ctorRegistry["%AsyncIteratorPrototype%"] = Object.getPrototypeOf( + Object.getPrototypeOf( + globalObject.eval("(async function* () {})").prototype + ) + ); + } catch { + ctorRegistry["%AsyncIteratorPrototype%"] = AsyncIteratorPrototype; + } + globalObject[ctorRegistrySymbol] = ctorRegistry; return ctorRegistry; } @@ -77,8 +97,6 @@ function tryImplForWrapper(wrapper) { } const iterInternalSymbol = Symbol("internal"); -const IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())); -const AsyncIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(async function* () {}).prototype); function isArrayIndexPropName(P) { if (typeof P !== "string") { @@ -143,6 +161,7 @@ module.exports = exports = { isObject, hasOwn, define, + newObjectInRealm, wrapperSymbol, implSymbol, getSameObject, @@ -153,8 +172,6 @@ module.exports = exports = { tryWrapperForImpl, tryImplForWrapper, iterInternalSymbol, - IteratorPrototype, - AsyncIteratorPrototype, isArrayBuffer, isArrayIndexPropName, supportsPropertyIndex, diff --git a/test/__snapshots__/test.js.snap b/test/__snapshots__/test.js.snap index 3c3bf118..ad9e5754 100644 --- a/test/__snapshots__/test.js.snap +++ b/test/__snapshots__/test.js.snap @@ -167,6 +167,7 @@ const conversions = require(\\"webidl-conversions\\"); const utils = require(\\"./utils.js\\"); const Dictionary = require(\\"./Dictionary.js\\"); +const newObjectInRealm = utils.newObjectInRealm; const implSymbol = utils.implSymbol; const ctorRegistrySymbol = utils.ctorRegistrySymbol; @@ -380,7 +381,7 @@ exports.install = (globalObject, globalNames) => { }); ctorRegistry[interfaceName] = AsyncIterablePairArgs; - ctorRegistry[\\"AsyncIterablePairArgs AsyncIterator\\"] = Object.create(utils.AsyncIteratorPrototype, { + ctorRegistry[\\"AsyncIterablePairArgs AsyncIterator\\"] = Object.create(ctorRegistry[\\"%AsyncIteratorPrototype%\\"], { [Symbol.toStringTag]: { value: \\"AsyncIterablePairArgs AsyncIterator\\", configurable: true @@ -397,7 +398,7 @@ exports.install = (globalObject, globalNames) => { const nextSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value: undefined, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value: undefined, done: true })); } const nextPromise = internal.target[implSymbol][utils.asyncIteratorNext](this); @@ -406,9 +407,9 @@ exports.install = (globalObject, globalNames) => { internal.ongoingPromise = null; if (next === utils.asyncIteratorEOI) { internal.isFinished = true; - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } - return utils.iteratorResult(next.map(utils.tryWrapperForImpl), kind); + return newObjectInRealm(globalObject, utils.iteratorResult(next.map(utils.tryWrapperForImpl), kind)); }, reason => { internal.ongoingPromise = null; @@ -442,6 +443,7 @@ exports[`generation with processors AsyncIterablePairNoArgs.webidl 1`] = ` const conversions = require(\\"webidl-conversions\\"); const utils = require(\\"./utils.js\\"); +const newObjectInRealm = utils.newObjectInRealm; const implSymbol = utils.implSymbol; const ctorRegistrySymbol = utils.ctorRegistrySymbol; @@ -592,7 +594,7 @@ exports.install = (globalObject, globalNames) => { }); ctorRegistry[interfaceName] = AsyncIterablePairNoArgs; - ctorRegistry[\\"AsyncIterablePairNoArgs AsyncIterator\\"] = Object.create(utils.AsyncIteratorPrototype, { + ctorRegistry[\\"AsyncIterablePairNoArgs AsyncIterator\\"] = Object.create(ctorRegistry[\\"%AsyncIteratorPrototype%\\"], { [Symbol.toStringTag]: { value: \\"AsyncIterablePairNoArgs AsyncIterator\\", configurable: true @@ -609,7 +611,7 @@ exports.install = (globalObject, globalNames) => { const nextSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value: undefined, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value: undefined, done: true })); } const nextPromise = internal.target[implSymbol][utils.asyncIteratorNext](this); @@ -618,9 +620,9 @@ exports.install = (globalObject, globalNames) => { internal.ongoingPromise = null; if (next === utils.asyncIteratorEOI) { internal.isFinished = true; - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } - return utils.iteratorResult(next.map(utils.tryWrapperForImpl), kind); + return newObjectInRealm(globalObject, utils.iteratorResult(next.map(utils.tryWrapperForImpl), kind)); }, reason => { internal.ongoingPromise = null; @@ -655,6 +657,7 @@ const conversions = require(\\"webidl-conversions\\"); const utils = require(\\"./utils.js\\"); const URL = require(\\"./URL.js\\"); +const newObjectInRealm = utils.newObjectInRealm; const implSymbol = utils.implSymbol; const ctorRegistrySymbol = utils.ctorRegistrySymbol; @@ -783,7 +786,7 @@ exports.install = (globalObject, globalNames) => { }); ctorRegistry[interfaceName] = AsyncIterableValueArgs; - ctorRegistry[\\"AsyncIterableValueArgs AsyncIterator\\"] = Object.create(utils.AsyncIteratorPrototype, { + ctorRegistry[\\"AsyncIterableValueArgs AsyncIterator\\"] = Object.create(ctorRegistry[\\"%AsyncIteratorPrototype%\\"], { [Symbol.toStringTag]: { value: \\"AsyncIterableValueArgs AsyncIterator\\", configurable: true @@ -800,7 +803,7 @@ exports.install = (globalObject, globalNames) => { const nextSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value: undefined, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value: undefined, done: true })); } const nextPromise = internal.target[implSymbol][utils.asyncIteratorNext](this); @@ -809,9 +812,9 @@ exports.install = (globalObject, globalNames) => { internal.ongoingPromise = null; if (next === utils.asyncIteratorEOI) { internal.isFinished = true; - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } - return { value: utils.tryWrapperForImpl(next), done: false }; + return newObjectInRealm(globalObject, { value: utils.tryWrapperForImpl(next), done: false }); }, reason => { internal.ongoingPromise = null; @@ -845,6 +848,7 @@ exports[`generation with processors AsyncIterableValueNoArgs.webidl 1`] = ` const conversions = require(\\"webidl-conversions\\"); const utils = require(\\"./utils.js\\"); +const newObjectInRealm = utils.newObjectInRealm; const implSymbol = utils.implSymbol; const ctorRegistrySymbol = utils.ctorRegistrySymbol; @@ -965,7 +969,7 @@ exports.install = (globalObject, globalNames) => { }); ctorRegistry[interfaceName] = AsyncIterableValueNoArgs; - ctorRegistry[\\"AsyncIterableValueNoArgs AsyncIterator\\"] = Object.create(utils.AsyncIteratorPrototype, { + ctorRegistry[\\"AsyncIterableValueNoArgs AsyncIterator\\"] = Object.create(ctorRegistry[\\"%AsyncIteratorPrototype%\\"], { [Symbol.toStringTag]: { value: \\"AsyncIterableValueNoArgs AsyncIterator\\", configurable: true @@ -982,7 +986,7 @@ exports.install = (globalObject, globalNames) => { const nextSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value: undefined, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value: undefined, done: true })); } const nextPromise = internal.target[implSymbol][utils.asyncIteratorNext](this); @@ -991,9 +995,9 @@ exports.install = (globalObject, globalNames) => { internal.ongoingPromise = null; if (next === utils.asyncIteratorEOI) { internal.isFinished = true; - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } - return { value: utils.tryWrapperForImpl(next), done: false }; + return newObjectInRealm(globalObject, { value: utils.tryWrapperForImpl(next), done: false }); }, reason => { internal.ongoingPromise = null; @@ -1028,6 +1032,7 @@ const conversions = require(\\"webidl-conversions\\"); const utils = require(\\"./utils.js\\"); const Dictionary = require(\\"./Dictionary.js\\"); +const newObjectInRealm = utils.newObjectInRealm; const implSymbol = utils.implSymbol; const ctorRegistrySymbol = utils.ctorRegistrySymbol; @@ -1152,7 +1157,7 @@ exports.install = (globalObject, globalNames) => { }); ctorRegistry[interfaceName] = AsyncIterableWithReturn; - ctorRegistry[\\"AsyncIterableWithReturn AsyncIterator\\"] = Object.create(utils.AsyncIteratorPrototype, { + ctorRegistry[\\"AsyncIterableWithReturn AsyncIterator\\"] = Object.create(ctorRegistry[\\"%AsyncIteratorPrototype%\\"], { [Symbol.toStringTag]: { value: \\"AsyncIterableWithReturn AsyncIterator\\", configurable: true @@ -1169,7 +1174,7 @@ exports.install = (globalObject, globalNames) => { const nextSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value: undefined, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value: undefined, done: true })); } const nextPromise = internal.target[implSymbol][utils.asyncIteratorNext](this); @@ -1178,9 +1183,9 @@ exports.install = (globalObject, globalNames) => { internal.ongoingPromise = null; if (next === utils.asyncIteratorEOI) { internal.isFinished = true; - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } - return { value: utils.tryWrapperForImpl(next), done: false }; + return newObjectInRealm(globalObject, { value: utils.tryWrapperForImpl(next), done: false }); }, reason => { internal.ongoingPromise = null; @@ -1206,7 +1211,7 @@ exports.install = (globalObject, globalNames) => { const returnSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value, done: true })); } internal.isFinished = true; @@ -1216,7 +1221,7 @@ exports.install = (globalObject, globalNames) => { const returnPromise = internal.ongoingPromise ? internal.ongoingPromise.then(returnSteps, returnSteps) : returnSteps(); - return returnPromise.then(() => ({ value, done: true })); + return returnPromise.then(() => newObjectInRealm(globalObject, { value, done: true })); } }); @@ -8448,6 +8453,7 @@ const conversions = require(\\"webidl-conversions\\"); const utils = require(\\"./utils.js\\"); const Function = require(\\"./Function.js\\"); +const newObjectInRealm = utils.newObjectInRealm; const implSymbol = utils.implSymbol; const ctorRegistrySymbol = utils.ctorRegistrySymbol; @@ -8880,12 +8886,12 @@ exports.install = (globalObject, globalNames) => { const values = Array.from(target[implSymbol]); const len = values.length; if (index >= len) { - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } const pair = values[index]; internal.index = index + 1; - return utils.iteratorResult(pair.map(utils.tryWrapperForImpl), kind); + return newObjectInRealm(globalObject, utils.iteratorResult(pair.map(utils.tryWrapperForImpl), kind)); } }); @@ -10431,6 +10437,7 @@ const conversions = require(\\"webidl-conversions\\"); const utils = require(\\"./utils.js\\"); const Dictionary = require(\\"./Dictionary.js\\"); +const newObjectInRealm = utils.newObjectInRealm; const implSymbol = utils.implSymbol; const ctorRegistrySymbol = utils.ctorRegistrySymbol; @@ -10644,7 +10651,7 @@ exports.install = (globalObject, globalNames) => { }); ctorRegistry[interfaceName] = AsyncIterablePairArgs; - ctorRegistry[\\"AsyncIterablePairArgs AsyncIterator\\"] = Object.create(utils.AsyncIteratorPrototype, { + ctorRegistry[\\"AsyncIterablePairArgs AsyncIterator\\"] = Object.create(ctorRegistry[\\"%AsyncIteratorPrototype%\\"], { [Symbol.toStringTag]: { value: \\"AsyncIterablePairArgs AsyncIterator\\", configurable: true @@ -10661,7 +10668,7 @@ exports.install = (globalObject, globalNames) => { const nextSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value: undefined, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value: undefined, done: true })); } const nextPromise = internal.target[implSymbol][utils.asyncIteratorNext](this); @@ -10670,9 +10677,9 @@ exports.install = (globalObject, globalNames) => { internal.ongoingPromise = null; if (next === utils.asyncIteratorEOI) { internal.isFinished = true; - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } - return utils.iteratorResult(next.map(utils.tryWrapperForImpl), kind); + return newObjectInRealm(globalObject, utils.iteratorResult(next.map(utils.tryWrapperForImpl), kind)); }, reason => { internal.ongoingPromise = null; @@ -10706,6 +10713,7 @@ exports[`generation without processors AsyncIterablePairNoArgs.webidl 1`] = ` const conversions = require(\\"webidl-conversions\\"); const utils = require(\\"./utils.js\\"); +const newObjectInRealm = utils.newObjectInRealm; const implSymbol = utils.implSymbol; const ctorRegistrySymbol = utils.ctorRegistrySymbol; @@ -10856,7 +10864,7 @@ exports.install = (globalObject, globalNames) => { }); ctorRegistry[interfaceName] = AsyncIterablePairNoArgs; - ctorRegistry[\\"AsyncIterablePairNoArgs AsyncIterator\\"] = Object.create(utils.AsyncIteratorPrototype, { + ctorRegistry[\\"AsyncIterablePairNoArgs AsyncIterator\\"] = Object.create(ctorRegistry[\\"%AsyncIteratorPrototype%\\"], { [Symbol.toStringTag]: { value: \\"AsyncIterablePairNoArgs AsyncIterator\\", configurable: true @@ -10873,7 +10881,7 @@ exports.install = (globalObject, globalNames) => { const nextSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value: undefined, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value: undefined, done: true })); } const nextPromise = internal.target[implSymbol][utils.asyncIteratorNext](this); @@ -10882,9 +10890,9 @@ exports.install = (globalObject, globalNames) => { internal.ongoingPromise = null; if (next === utils.asyncIteratorEOI) { internal.isFinished = true; - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } - return utils.iteratorResult(next.map(utils.tryWrapperForImpl), kind); + return newObjectInRealm(globalObject, utils.iteratorResult(next.map(utils.tryWrapperForImpl), kind)); }, reason => { internal.ongoingPromise = null; @@ -10919,6 +10927,7 @@ const conversions = require(\\"webidl-conversions\\"); const utils = require(\\"./utils.js\\"); const URL = require(\\"./URL.js\\"); +const newObjectInRealm = utils.newObjectInRealm; const implSymbol = utils.implSymbol; const ctorRegistrySymbol = utils.ctorRegistrySymbol; @@ -11047,7 +11056,7 @@ exports.install = (globalObject, globalNames) => { }); ctorRegistry[interfaceName] = AsyncIterableValueArgs; - ctorRegistry[\\"AsyncIterableValueArgs AsyncIterator\\"] = Object.create(utils.AsyncIteratorPrototype, { + ctorRegistry[\\"AsyncIterableValueArgs AsyncIterator\\"] = Object.create(ctorRegistry[\\"%AsyncIteratorPrototype%\\"], { [Symbol.toStringTag]: { value: \\"AsyncIterableValueArgs AsyncIterator\\", configurable: true @@ -11064,7 +11073,7 @@ exports.install = (globalObject, globalNames) => { const nextSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value: undefined, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value: undefined, done: true })); } const nextPromise = internal.target[implSymbol][utils.asyncIteratorNext](this); @@ -11073,9 +11082,9 @@ exports.install = (globalObject, globalNames) => { internal.ongoingPromise = null; if (next === utils.asyncIteratorEOI) { internal.isFinished = true; - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } - return { value: utils.tryWrapperForImpl(next), done: false }; + return newObjectInRealm(globalObject, { value: utils.tryWrapperForImpl(next), done: false }); }, reason => { internal.ongoingPromise = null; @@ -11109,6 +11118,7 @@ exports[`generation without processors AsyncIterableValueNoArgs.webidl 1`] = ` const conversions = require(\\"webidl-conversions\\"); const utils = require(\\"./utils.js\\"); +const newObjectInRealm = utils.newObjectInRealm; const implSymbol = utils.implSymbol; const ctorRegistrySymbol = utils.ctorRegistrySymbol; @@ -11229,7 +11239,7 @@ exports.install = (globalObject, globalNames) => { }); ctorRegistry[interfaceName] = AsyncIterableValueNoArgs; - ctorRegistry[\\"AsyncIterableValueNoArgs AsyncIterator\\"] = Object.create(utils.AsyncIteratorPrototype, { + ctorRegistry[\\"AsyncIterableValueNoArgs AsyncIterator\\"] = Object.create(ctorRegistry[\\"%AsyncIteratorPrototype%\\"], { [Symbol.toStringTag]: { value: \\"AsyncIterableValueNoArgs AsyncIterator\\", configurable: true @@ -11246,7 +11256,7 @@ exports.install = (globalObject, globalNames) => { const nextSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value: undefined, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value: undefined, done: true })); } const nextPromise = internal.target[implSymbol][utils.asyncIteratorNext](this); @@ -11255,9 +11265,9 @@ exports.install = (globalObject, globalNames) => { internal.ongoingPromise = null; if (next === utils.asyncIteratorEOI) { internal.isFinished = true; - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } - return { value: utils.tryWrapperForImpl(next), done: false }; + return newObjectInRealm(globalObject, { value: utils.tryWrapperForImpl(next), done: false }); }, reason => { internal.ongoingPromise = null; @@ -11292,6 +11302,7 @@ const conversions = require(\\"webidl-conversions\\"); const utils = require(\\"./utils.js\\"); const Dictionary = require(\\"./Dictionary.js\\"); +const newObjectInRealm = utils.newObjectInRealm; const implSymbol = utils.implSymbol; const ctorRegistrySymbol = utils.ctorRegistrySymbol; @@ -11416,7 +11427,7 @@ exports.install = (globalObject, globalNames) => { }); ctorRegistry[interfaceName] = AsyncIterableWithReturn; - ctorRegistry[\\"AsyncIterableWithReturn AsyncIterator\\"] = Object.create(utils.AsyncIteratorPrototype, { + ctorRegistry[\\"AsyncIterableWithReturn AsyncIterator\\"] = Object.create(ctorRegistry[\\"%AsyncIteratorPrototype%\\"], { [Symbol.toStringTag]: { value: \\"AsyncIterableWithReturn AsyncIterator\\", configurable: true @@ -11433,7 +11444,7 @@ exports.install = (globalObject, globalNames) => { const nextSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value: undefined, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value: undefined, done: true })); } const nextPromise = internal.target[implSymbol][utils.asyncIteratorNext](this); @@ -11442,9 +11453,9 @@ exports.install = (globalObject, globalNames) => { internal.ongoingPromise = null; if (next === utils.asyncIteratorEOI) { internal.isFinished = true; - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } - return { value: utils.tryWrapperForImpl(next), done: false }; + return newObjectInRealm(globalObject, { value: utils.tryWrapperForImpl(next), done: false }); }, reason => { internal.ongoingPromise = null; @@ -11470,7 +11481,7 @@ exports.install = (globalObject, globalNames) => { const returnSteps = () => { if (internal.isFinished) { - return Promise.resolve({ value, done: true }); + return Promise.resolve(newObjectInRealm(globalObject, { value, done: true })); } internal.isFinished = true; @@ -11480,7 +11491,7 @@ exports.install = (globalObject, globalNames) => { const returnPromise = internal.ongoingPromise ? internal.ongoingPromise.then(returnSteps, returnSteps) : returnSteps(); - return returnPromise.then(() => ({ value, done: true })); + return returnPromise.then(() => newObjectInRealm(globalObject, { value, done: true })); } }); @@ -18655,6 +18666,7 @@ const conversions = require(\\"webidl-conversions\\"); const utils = require(\\"./utils.js\\"); const Function = require(\\"./Function.js\\"); +const newObjectInRealm = utils.newObjectInRealm; const implSymbol = utils.implSymbol; const ctorRegistrySymbol = utils.ctorRegistrySymbol; @@ -19087,12 +19099,12 @@ exports.install = (globalObject, globalNames) => { const values = Array.from(target[implSymbol]); const len = values.length; if (index >= len) { - return { value: undefined, done: true }; + return newObjectInRealm(globalObject, { value: undefined, done: true }); } const pair = values[index]; internal.index = index + 1; - return utils.iteratorResult(pair.map(utils.tryWrapperForImpl), kind); + return newObjectInRealm(globalObject, utils.iteratorResult(pair.map(utils.tryWrapperForImpl), kind)); } }); diff --git a/test/utils.test.js b/test/utils.test.js index f8d81d03..1cb4fa66 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -31,4 +31,22 @@ describe("utils.js", () => { expect(utils.isObject(() => {})).toBe(true); }); }); + + describe("newObjectInRealm", () => { + test("creates a new object in the given realm with the properties of the given object", () => { + const realm = { Object: function Object() {}, Array }; + const object = utils.newObjectInRealm(realm, { foo: 42 }); + expect(object).toBeInstanceOf(realm.Object); + expect(object).toEqual({ foo: 42 }); + }); + + test("uses the captured intrinsic Object, not the current realm.Object", () => { + const realm = { Object, Array }; + utils.initCtorRegistry(realm); + realm.Object = function Object() {}; + const object = utils.newObjectInRealm(realm, {}); + expect(object).toBeInstanceOf(Object); + expect(object).not.toBeInstanceOf(realm.Object); + }); + }); });