diff --git a/README.md b/README.md index 09043be5..feab715e 100644 --- a/README.md +++ b/README.md @@ -477,7 +477,8 @@ webidl2js is implementing an ever-growing subset of the Web IDL specification. S - `FrozenArray<>` types - Buffer source types - `typedef`s -- Partial interfaces and dictionaries +- Namespaces +- Partial interfaces, namespaces, and dictionaries - Interface mixins - Basic types (via [webidl-conversions][]) - Overload resolution (although [tricky cases are not easy on the implementation class](#overloaded-operations)) @@ -508,7 +509,6 @@ Supported Web IDL extensions defined in HTML: Notable missing features include: -- Namespaces - `maplike<>` and `setlike<>` - `async_sequence<>` types - `ObservableArray<>` types diff --git a/lib/constructs/attribute.js b/lib/constructs/attribute.js index b96afc39..0ccfc4e3 100644 --- a/lib/constructs/attribute.js +++ b/lib/constructs/attribute.js @@ -11,6 +11,7 @@ class Attribute { this.interface = I; this.idl = idl; this.static = idl.special === "static"; + this.namespace = I.type === "namespace"; } getWhence() { @@ -27,10 +28,11 @@ class Attribute { generate() { const requires = new utils.RequiresMap(this.ctx); - const whence = this.getWhence(); + const whence = this.namespace ? null : this.getWhence(); const configurable = whence !== "unforgeables"; const shouldReflect = - this.idl.extAttrs.some(attr => attr.name.startsWith("Reflect")) && this.ctx.processReflect !== null; + !this.namespace && this.idl.extAttrs.some(attr => attr.name.startsWith("Reflect")) && + this.ctx.processReflect !== null; const sameObject = utils.getExtAttr(this.idl.extAttrs, "SameObject"); const async = this.idl.idlType.generic === "Promise"; @@ -48,13 +50,15 @@ class Attribute { getterBody = `return esValue[implSymbol]["${this.idl.name}"];`; } - const addMethod = this.static ? + const addMethod = this.static || this.namespace ? this.interface.addStaticMethod.bind(this.interface) : this.interface.addMethod.bind(this.interface, whence); - if (this.static) { + if (this.static || this.namespace) { brandCheck = ""; - getterBody = `return Impl.implementation["${this.idl.name}"];`; + getterBody = conversions[this.idl.idlType.idlType] ? + `return Impl.implementation["${this.idl.name}"];` : + `return utils.tryWrapperForImpl(Impl.implementation["${this.idl.name}"]);`; setterBody = `Impl.implementation["${this.idl.name}"] = V;`; } else if (shouldReflect) { const processedOutput = this.ctx.invokeProcessReflect(this.idl, "esValue[implSymbol]", { requires }); @@ -75,7 +79,8 @@ class Attribute { } if (sameObject) { - getterBody = `return utils.getSameObject(this, "${this.idl.name}", () => { ${getterBody} });`; + const cacheKey = this.namespace ? "namespaceObject" : "this"; + getterBody = `return utils.getSameObject(${cacheKey}, "${this.idl.name}", () => { ${getterBody} });`; } if (utils.hasCEReactions(this.idl)) { @@ -85,9 +90,13 @@ class Attribute { setterBody = this.ctx.invokeProcessCEReactions(setterBody, processorConfig); } + const esValueSetup = this.static || this.namespace ? + "" : + "const esValue = this !== null && this !== undefined ? this : globalObject;"; + addMethod(this.idl.name, [], ` ${promiseHandlingBefore} - const esValue = this !== null && this !== undefined ? this : globalObject; + ${esValueSetup} ${brandCheck.replace("$KEYWORD$", "get")} ${getterBody} ${promiseHandlingAfter} @@ -124,7 +133,7 @@ class Attribute { } addMethod(this.idl.name, ["V"], ` - const esValue = this !== null && this !== undefined ? this : globalObject; + ${esValueSetup} ${brandCheck} ${idlConversion} ${setterBody} @@ -160,7 +169,7 @@ class Attribute { if (setterBody) { addMethod(this.idl.name, ["V"], ` - const esValue = this !== null && this !== undefined ? this : globalObject; + ${esValueSetup} ${brandCheck} ${setterBody} `, "set", { configurable }); @@ -176,7 +185,7 @@ class Attribute { } } - if (!this.static && this.idl.special === "stringifier") { + if (!this.static && !this.namespace && this.idl.special === "stringifier") { addMethod("toString", [], ` const esValue = this; if (!exports.is(esValue)) { diff --git a/lib/constructs/constant.js b/lib/constructs/constant.js index df696229..1f925196 100644 --- a/lib/constructs/constant.js +++ b/lib/constructs/constant.js @@ -16,6 +16,9 @@ class Constant { configurable: false, writable: false }); + if (this.interface.type === "namespace") { + return { requires: new utils.RequiresMap(this.ctx) }; + } this.interface.addProperty(this.interface.defaultWhence, this.idl.name, utils.getDefault(this.idl.value), { configurable: false, writable: false diff --git a/lib/constructs/namespace.js b/lib/constructs/namespace.js new file mode 100644 index 00000000..4a19a6a4 --- /dev/null +++ b/lib/constructs/namespace.js @@ -0,0 +1,244 @@ +"use strict"; + +const utils = require("../utils"); +const Attribute = require("./attribute"); +const Constant = require("./constant"); +const Operation = require("./operation"); + +const defaultObjectLiteralDescriptor = { + configurable: true, + enumerable: true, + writable: true +}; + +class Namespace { + constructor(ctx, idl, opts) { + this.ctx = ctx; + this.idl = idl; + this.name = idl.name; + this.opts = opts; + + this.str = null; + this.requires = new utils.RequiresMap(ctx); + + this.operations = new Map(); + this.attributes = new Map(); + this.constants = new Map(); + + this._analyzed = false; + this._outputStaticMethods = new Map(); + this._outputStaticProperties = new Map(); + + const exposed = utils.getExtAttr(this.idl.extAttrs, "Exposed"); + if (!exposed) { + throw new Error(`Namespace ${this.name} lacks [Exposed]`); + } + + if (!exposed.rhs || (exposed.rhs.type !== "identifier" && exposed.rhs.type !== "identifier-list")) { + throw new Error(`[Exposed] must take an identifier or an identifier list in namespace ${this.name}`); + } + + if (exposed.rhs.type === "identifier") { + this.exposed = new Set([exposed.rhs.value]); + } else { + this.exposed = new Set(exposed.rhs.value.map(token => token.value)); + } + } + + // type is either "regular", "get", or "set" + addStaticMethod(propName, args, body, type = "regular", { + configurable = true, + enumerable = typeof propName === "string", + writable = type === "regular" ? true : undefined + } = {}) { + if (type !== "regular") { + const existing = this._outputStaticMethods.get(propName); + if (existing !== undefined) { + if (type === "get") { + existing.body[0] = body; + } else { + existing.args = args; + existing.body[1] = body; + } + return; + } + + const pair = new Array(2); + pair[type === "get" ? 0 : 1] = body; + body = pair; + type = "accessor"; + } + + const descriptor = { configurable, enumerable, writable }; + this._outputStaticMethods.set(propName, { type, args, body, descriptor }); + } + + addStaticProperty(propName, str, { + configurable = true, + enumerable = typeof propName === "string", + writable = true + } = {}) { + const descriptor = { configurable, enumerable, writable }; + this._outputStaticProperties.set(propName, { body: str, descriptor }); + } + + _analyzeMembers() { + for (const member of this.idl.members) { + switch (member.type) { + case "operation": + if (!member.name) { + if (!this.ctx.options.suppressErrors) { + throw new Error(`Unnamed operation in namespace ${this.name}`); + } + break; + } + if (!this.operations.has(member.name)) { + this.operations.set(member.name, new Operation(this.ctx, this, member)); + } else { + this.operations.get(member.name).idls.push(member); + } + break; + case "attribute": + if (!member.readonly) { + if (!this.ctx.options.suppressErrors) { + throw new Error(`Namespace attribute "${member.name}" on ${this.name} must be readonly`); + } + break; + } + this.attributes.set(member.name, new Attribute(this.ctx, this, member)); + break; + case "const": + this.constants.set(member.name, new Constant(this.ctx, this, member)); + break; + default: + if (!this.ctx.options.suppressErrors) { + throw new Error(`Unknown IDL member type "${member.type}" in namespace ${this.name}`); + } + } + } + } + + addAllMethodsProperties() { + this.addStaticProperty(Symbol.toStringTag, JSON.stringify(this.name), { + writable: false + }); + + for (const member of this.operations.values()) { + const data = member.generate(); + this.requires.merge(data.requires); + } + + for (const member of [...this.attributes.values(), ...this.constants.values()]) { + const data = member.generate(); + this.requires.merge(data.requires); + } + } + + generateNamespaceObject() { + const members = []; + const props = new Map(); + + function addOne(name, args, body) { + members.push(` + ${name}(${utils.formatArgs(args)}) {${body}} + `); + } + + for (const [name, { type, args, body, descriptor }] of this._outputStaticMethods) { + const propName = utils.stringifyPropertyKey(name); + if (type === "regular") { + addOne(propName, args, body); + } else { + if (body[0] !== undefined) { + addOne(`get ${propName}`, [], body[0]); + } + if (body[1] !== undefined) { + addOne(`set ${propName}`, args, body[1]); + } + } + + const descriptorModifier = utils.getPropertyDescriptorModifier(defaultObjectLiteralDescriptor, descriptor, type); + if (descriptorModifier === undefined) { + continue; + } + props.set(propName, descriptorModifier); + } + + for (const [name, { body, descriptor }] of this._outputStaticProperties) { + const descriptorModifier = + utils.getPropertyDescriptorModifier(utils.defaultDefinePropertyDescriptor, descriptor, "regular", body); + props.set(utils.stringifyPropertyKey(name), descriptorModifier); + } + + const propStrs = [...props].map(([name, body]) => `${name}: ${body}`); + + this.str += ` + const namespaceObject = Object.create(globalObject.Object.prototype); + `; + if (members.length > 0) { + this.str += ` + utils.define(namespaceObject, { + ${members.join(", ")} + }); + `; + } + if (propStrs.length > 0) { + this.str += ` + Object.defineProperties(namespaceObject, { + ${propStrs.join(", ")} + }); + `; + } + } + + generateInstall() { + this.str += ` + const namespaceName = "${this.name}"; + const exposed = new Set(${JSON.stringify([...this.exposed])}); + + exports.install = (globalObject, globalNames) => { + if (!globalNames.some(globalName => exposed.has(globalName))) { + return; + } + `; + + this.generateNamespaceObject(); + + this.str += ` + Object.defineProperty(globalObject, namespaceName, { + configurable: true, + writable: true, + value: namespaceObject + }); + }; + `; + } + + generateRequires() { + this.str = ` + ${this.requires.generate()} + + ${this.str} + `; + } + + generate() { + this.generateInstall(); + this.generateRequires(); + } + + toString() { + this.str = ""; + if (!this._analyzed) { + this._analyzed = true; + this._analyzeMembers(); + } + this.addAllMethodsProperties(); + this.generate(); + return this.str; + } +} + +Namespace.prototype.type = "namespace"; + +module.exports = Namespace; diff --git a/lib/constructs/operation.js b/lib/constructs/operation.js index 8fe867ba..5aff44da 100644 --- a/lib/constructs/operation.js +++ b/lib/constructs/operation.js @@ -13,6 +13,7 @@ class Operation { this.idls = [idl]; this.name = idl.name; this.static = idl.special === "static"; + this.namespace = I.type === "namespace"; } getWhence() { @@ -55,9 +56,10 @@ class Operation { const { idls } = this; const hasCallWithGlobal = Boolean(utils.getExtAttr(idls[0].extAttrs, "WebIDL2JSCallWithGlobal")); - if (hasCallWithGlobal && !this.static) { + if (hasCallWithGlobal && !this.static && !this.namespace) { throw new Error( - `[WebIDL2JSCallWithGlobal] is only valid for static operations: "${this.name}" on ${this.interface.name}` + `[WebIDL2JSCallWithGlobal] is only valid for static or namespace operations: ` + + `"${this.name}" on ${this.interface.name}` ); } @@ -94,7 +96,7 @@ class Operation { throw new Error(`Internal error: this operation does not have a name (in interface ${this.interface.name})`); } - const whence = this.getWhence(); + const whence = this.namespace ? null : this.getWhence(); const async = this.isAsync(); const promiseHandlingBefore = async ? `try {` : ``; const promiseHandlingAfter = async ? `} catch (e) { return globalObject.Promise.reject(e); }` : ``; @@ -111,7 +113,7 @@ class Operation { const argNames = minOp.nameList; - if (!this.static) { + if (!this.static && !this.namespace) { str += ` const esValue = this !== null && this !== undefined ? this : globalObject; if (!exports.is(esValue)) { @@ -120,7 +122,7 @@ class Operation { `; } - const callOn = this.static ? "Impl.implementation" : `esValue[implSymbol]`; + const callOn = this.static || this.namespace ? "Impl.implementation" : `esValue[implSymbol]`; // In case of stringifiers, use the named implementation function rather than hardcoded "toString". // All overloads will have the same name, so pick the first one. const implFunc = this.idls[0].name || this.name; @@ -164,7 +166,7 @@ class Operation { str = promiseHandlingBefore + str + promiseHandlingAfter; - if (this.static) { + if (this.static || this.namespace) { this.interface.addStaticMethod(this.name, argNames, str); } else { const forgeable = whence !== "unforgeables"; diff --git a/lib/context.js b/lib/context.js index 09a1004e..687816fa 100644 --- a/lib/context.js +++ b/lib/context.js @@ -39,6 +39,7 @@ class Context { initialize() { this.typedefs = new Map(); this.interfaces = new Map(); + this.namespaces = new Map(); this.interfaceMixins = new Map(); this.callbackInterfaces = new Map(); this.callbackFunctions = new Map(); @@ -64,6 +65,9 @@ class Context { if (this.interfaces.has(name)) { return "interface"; } + if (this.namespaces.has(name)) { + return "namespace"; + } if (this.callbackInterfaces.has(name)) { return "callback interface"; } diff --git a/lib/transformer.js b/lib/transformer.js index b41dd823..eb158e9e 100644 --- a/lib/transformer.js +++ b/lib/transformer.js @@ -9,6 +9,7 @@ const { format } = require("oxfmt"); const Context = require("./context"); const Typedef = require("./constructs/typedef"); const Interface = require("./constructs/interface"); +const Namespace = require("./constructs/namespace"); const InterfaceMixin = require("./constructs/interface-mixin"); const CallbackInterface = require("./constructs/callback-interface.js"); const CallbackFunction = require("./constructs/callback-function"); @@ -92,6 +93,7 @@ class Transformer { this.ctx.initialize(); const { interfaces, + namespaces, interfaceMixins, callbackInterfaces, callbackFunctions, @@ -100,7 +102,7 @@ class Transformer { typedefs } = this.ctx; - // first we're gathering all full interfaces and ignore partial ones + // first we're gathering all full definitions and ignore partial ones for (const file of parsed) { for (const instruction of file.idl) { let obj; @@ -115,6 +117,16 @@ class Transformer { }); interfaces.set(obj.name, obj); break; + case "namespace": + if (instruction.partial) { + break; + } + + obj = new Namespace(this.ctx, instruction, { + implDir: file.impl + }); + namespaces.set(obj.name, obj); + break; case "interface mixin": if (instruction.partial) { break; @@ -175,6 +187,19 @@ class Transformer { extAttrs = interfaces.get(instruction.name).idl.extAttrs; extAttrs.push(...instruction.extAttrs); break; + case "namespace": + if (!instruction.partial) { + break; + } + + if (this.ctx.options.suppressErrors && !namespaces.has(instruction.name)) { + break; + } + oldMembers = namespaces.get(instruction.name).idl.members; + oldMembers.push(...instruction.members); + extAttrs = namespaces.get(instruction.name).idl.extAttrs; + extAttrs.push(...instruction.extAttrs); + break; case "interface mixin": if (!instruction.partial) { break; @@ -215,7 +240,7 @@ class Transformer { const utilsText = await fs.readFile(path.resolve(__dirname, "output/utils.js")); await fs.writeFile(this.utilPath, utilsText); - const { interfaces, callbackInterfaces, callbackFunctions, dictionaries, enumerations } = this.ctx; + const { interfaces, namespaces, callbackInterfaces, callbackFunctions, dictionaries, enumerations } = this.ctx; let relativeUtils = path.relative(outputDir, this.utilPath).replaceAll("\\", "/"); if (relativeUtils[0] !== ".") { @@ -245,6 +270,29 @@ class Transformer { await fs.writeFile(path.join(outputDir, `${obj.name}.js`), source); })); + await Promise.all(namespaces.values().map(async obj => { + let source = obj.toString(); + + let implFile = path.relative(outputDir, path.resolve(obj.opts.implDir, obj.name + this.ctx.implSuffix)); + implFile = implFile.replaceAll("\\", "/"); // fix windows file paths + if (implFile[0] !== ".") { + implFile = `./${implFile}`; + } + + source = ` + "use strict"; + + const conversions = require("webidl-conversions"); + const utils = require("${relativeUtils}"); + ${source} + const Impl = require("${implFile}.js"); + `; + + source = await this._prettify(source); + + await fs.writeFile(path.join(outputDir, `${obj.name}.js`), source); + })); + await Promise.all( [...callbackInterfaces.values(), ...callbackFunctions.values(), ...dictionaries.values()].map(async obj => { let source = obj.toString(); diff --git a/test/cases/Namespace.webidl b/test/cases/Namespace.webidl new file mode 100644 index 00000000..88d836be --- /dev/null +++ b/test/cases/Namespace.webidl @@ -0,0 +1,13 @@ +[Exposed=(Window,Worker)] +namespace Namespace { + readonly attribute DOMString version; + [SameObject] readonly attribute Static staticObject; + const unsigned short VALUE = 7; + [CEReactions] undefined configure(DOMString value); + undefined overloaded(DOMString value); + undefined overloaded(unsigned long value); +}; + +partial namespace Namespace { + [WebIDL2JSCallWithGlobal] Static createStatic(); +}; diff --git a/test/snapshots/with-processors/Global.js b/test/snapshots/with-processors/Global.js index f7923d64..a37deb74 100644 --- a/test/snapshots/with-processors/Global.js +++ b/test/snapshots/with-processors/Global.js @@ -199,14 +199,10 @@ exports.install = (globalObject, globalNames) => { } static get staticAttr() { - const esValue = this !== null && this !== undefined ? this : globalObject; - return Impl.implementation["staticAttr"]; } static set staticAttr(V) { - const esValue = this !== null && this !== undefined ? this : globalObject; - V = conversions["DOMString"](V, { context: "Failed to set the 'staticAttr' property on 'Global': The provided value", globals: globalObject diff --git a/test/snapshots/with-processors/Namespace.js b/test/snapshots/with-processors/Namespace.js new file mode 100644 index 00000000..465797c2 --- /dev/null +++ b/test/snapshots/with-processors/Namespace.js @@ -0,0 +1,97 @@ +"use strict"; + +const conversions = require("webidl-conversions"); +const utils = require("./utils.js"); + +const CEReactions = require("../CEReactions.js"); + +const namespaceName = "Namespace"; +const exposed = new Set(["Window", "Worker"]); + +exports.install = (globalObject, globalNames) => { + if (!globalNames.some(globalName => exposed.has(globalName))) { + return; + } + + const namespaceObject = Object.create(globalObject.Object.prototype); + + utils.define(namespaceObject, { + configure(value) { + if (arguments.length < 1) { + throw new globalObject.TypeError( + `Failed to execute 'configure' on 'Namespace': 1 argument required, but only ${arguments.length} present.` + ); + } + const args = []; + { + let curArg = arguments[0]; + curArg = conversions["DOMString"](curArg, { + context: "Failed to execute 'configure' on 'Namespace': parameter 1", + globals: globalObject + }); + args.push(curArg); + } + CEReactions.preSteps(globalObject); + try { + return Impl.implementation.configure(...args); + } finally { + CEReactions.postSteps(globalObject); + } + }, + overloaded(value) { + if (arguments.length < 1) { + throw new globalObject.TypeError( + `Failed to execute 'overloaded' on 'Namespace': 1 argument required, but only ${arguments.length} present.` + ); + } + const args = []; + { + let curArg = arguments[0]; + if (typeof curArg === "number") { + { + let curArg = arguments[0]; + curArg = conversions["unsigned long"](curArg, { + context: "Failed to execute 'overloaded' on 'Namespace': parameter 1", + globals: globalObject + }); + args.push(curArg); + } + } else { + { + let curArg = arguments[0]; + curArg = conversions["DOMString"](curArg, { + context: "Failed to execute 'overloaded' on 'Namespace': parameter 1", + globals: globalObject + }); + args.push(curArg); + } + } + } + return Impl.implementation.overloaded(...args); + }, + createStatic() { + return utils.tryWrapperForImpl(Impl.implementation.createStatic(globalObject)); + }, + get version() { + return Impl.implementation["version"]; + }, + get staticObject() { + return utils.getSameObject(namespaceObject, "staticObject", () => { + return utils.tryWrapperForImpl(Impl.implementation["staticObject"]); + }); + } + }); + + Object.defineProperties(namespaceObject, { + [Symbol.toStringTag]: { value: "Namespace", configurable: true }, + VALUE: { value: 7, enumerable: true } + }); + + Object.defineProperty(globalObject, namespaceName, { + configurable: true, + writable: true, + value: namespaceObject + }); +}; + +const Impl = require("../implementations/Namespace.js"); diff --git a/test/snapshots/with-processors/PromiseTypes.js b/test/snapshots/with-processors/PromiseTypes.js index f7e0e009..48e08578 100644 --- a/test/snapshots/with-processors/PromiseTypes.js +++ b/test/snapshots/with-processors/PromiseTypes.js @@ -223,9 +223,7 @@ exports.install = (globalObject, globalNames) => { static get staticPromiseAttribute() { try { - const esValue = this !== null && this !== undefined ? this : globalObject; - - return Impl.implementation["staticPromiseAttribute"]; + return utils.tryWrapperForImpl(Impl.implementation["staticPromiseAttribute"]); } catch (e) { return globalObject.Promise.reject(e); } diff --git a/test/snapshots/with-processors/Static.js b/test/snapshots/with-processors/Static.js index f3ebff76..66b0d91e 100644 --- a/test/snapshots/with-processors/Static.js +++ b/test/snapshots/with-processors/Static.js @@ -130,14 +130,10 @@ exports.install = (globalObject, globalNames) => { } static get abc() { - const esValue = this !== null && this !== undefined ? this : globalObject; - return Impl.implementation["abc"]; } static set abc(V) { - const esValue = this !== null && this !== undefined ? this : globalObject; - V = conversions["DOMString"](V, { context: "Failed to set the 'abc' property on 'Static': The provided value", globals: globalObject diff --git a/test/snapshots/without-processors/Global.js b/test/snapshots/without-processors/Global.js index f7923d64..a37deb74 100644 --- a/test/snapshots/without-processors/Global.js +++ b/test/snapshots/without-processors/Global.js @@ -199,14 +199,10 @@ exports.install = (globalObject, globalNames) => { } static get staticAttr() { - const esValue = this !== null && this !== undefined ? this : globalObject; - return Impl.implementation["staticAttr"]; } static set staticAttr(V) { - const esValue = this !== null && this !== undefined ? this : globalObject; - V = conversions["DOMString"](V, { context: "Failed to set the 'staticAttr' property on 'Global': The provided value", globals: globalObject diff --git a/test/snapshots/without-processors/Namespace.js b/test/snapshots/without-processors/Namespace.js new file mode 100644 index 00000000..5250f244 --- /dev/null +++ b/test/snapshots/without-processors/Namespace.js @@ -0,0 +1,90 @@ +"use strict"; + +const conversions = require("webidl-conversions"); +const utils = require("./utils.js"); + +const namespaceName = "Namespace"; +const exposed = new Set(["Window", "Worker"]); + +exports.install = (globalObject, globalNames) => { + if (!globalNames.some(globalName => exposed.has(globalName))) { + return; + } + + const namespaceObject = Object.create(globalObject.Object.prototype); + + utils.define(namespaceObject, { + configure(value) { + if (arguments.length < 1) { + throw new globalObject.TypeError( + `Failed to execute 'configure' on 'Namespace': 1 argument required, but only ${arguments.length} present.` + ); + } + const args = []; + { + let curArg = arguments[0]; + curArg = conversions["DOMString"](curArg, { + context: "Failed to execute 'configure' on 'Namespace': parameter 1", + globals: globalObject + }); + args.push(curArg); + } + return Impl.implementation.configure(...args); + }, + overloaded(value) { + if (arguments.length < 1) { + throw new globalObject.TypeError( + `Failed to execute 'overloaded' on 'Namespace': 1 argument required, but only ${arguments.length} present.` + ); + } + const args = []; + { + let curArg = arguments[0]; + if (typeof curArg === "number") { + { + let curArg = arguments[0]; + curArg = conversions["unsigned long"](curArg, { + context: "Failed to execute 'overloaded' on 'Namespace': parameter 1", + globals: globalObject + }); + args.push(curArg); + } + } else { + { + let curArg = arguments[0]; + curArg = conversions["DOMString"](curArg, { + context: "Failed to execute 'overloaded' on 'Namespace': parameter 1", + globals: globalObject + }); + args.push(curArg); + } + } + } + return Impl.implementation.overloaded(...args); + }, + createStatic() { + return utils.tryWrapperForImpl(Impl.implementation.createStatic(globalObject)); + }, + get version() { + return Impl.implementation["version"]; + }, + get staticObject() { + return utils.getSameObject(namespaceObject, "staticObject", () => { + return utils.tryWrapperForImpl(Impl.implementation["staticObject"]); + }); + } + }); + + Object.defineProperties(namespaceObject, { + [Symbol.toStringTag]: { value: "Namespace", configurable: true }, + VALUE: { value: 7, enumerable: true } + }); + + Object.defineProperty(globalObject, namespaceName, { + configurable: true, + writable: true, + value: namespaceObject + }); +}; + +const Impl = require("../implementations/Namespace.js"); diff --git a/test/snapshots/without-processors/PromiseTypes.js b/test/snapshots/without-processors/PromiseTypes.js index f7e0e009..48e08578 100644 --- a/test/snapshots/without-processors/PromiseTypes.js +++ b/test/snapshots/without-processors/PromiseTypes.js @@ -223,9 +223,7 @@ exports.install = (globalObject, globalNames) => { static get staticPromiseAttribute() { try { - const esValue = this !== null && this !== undefined ? this : globalObject; - - return Impl.implementation["staticPromiseAttribute"]; + return utils.tryWrapperForImpl(Impl.implementation["staticPromiseAttribute"]); } catch (e) { return globalObject.Promise.reject(e); } diff --git a/test/snapshots/without-processors/Static.js b/test/snapshots/without-processors/Static.js index f3ebff76..66b0d91e 100644 --- a/test/snapshots/without-processors/Static.js +++ b/test/snapshots/without-processors/Static.js @@ -130,14 +130,10 @@ exports.install = (globalObject, globalNames) => { } static get abc() { - const esValue = this !== null && this !== undefined ? this : globalObject; - return Impl.implementation["abc"]; } static set abc(V) { - const esValue = this !== null && this !== undefined ? this : globalObject; - V = conversions["DOMString"](V, { context: "Failed to set the 'abc' property on 'Static': The provided value", globals: globalObject