Skip to content

Commit

Permalink
Implement support for [LegacyWindowAlias] and [NoInterfaceObject]
Browse files Browse the repository at this point in the history
Fixed #187.
  • Loading branch information
ExE-Boss authored Apr 4, 2020
1 parent 1455648 commit 5af205c
Show file tree
Hide file tree
Showing 8 changed files with 676 additions and 70 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,8 @@ webidl2js is implementing an ever-growing subset of the Web IDL specification. S
- `[EnforceRange]`
- `[LegacyArrayClass]`
- `[LegacyUnenumerableNamedProperties]`
- `[LegacyWindowAlias]`
- `[NoInterfaceObject]`
- `[OverrideBuiltins]`
- `[PutForwards]`
- `[Replaceable]`
Expand All @@ -477,7 +479,6 @@ Notable missing features include:
- `[Default]` (for `toJSON()` operations)
- `[Global]`'s various consequences, including the named properties object and `[[SetPrototypeOf]]`
- `[Exposed]`
- `[LegacyWindowAlias]`
- `[LenientSetter]`
- `[LenientThis]`
- `[NamedConstructor]`
Expand Down
72 changes: 71 additions & 1 deletion lib/constructs/interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,49 @@ class Interface {
if (global && !global.rhs) {
throw new Error(`[Global] must take an identifier or an identifier list in interface ${this.name}`);
}

const exposed = utils.getExtAttr(this.idl.extAttrs, "Exposed");
if (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 interface ${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));
}
} else {
this.exposed = new Set();
}

if (!exposed && !utils.getExtAttr(this.idl.extAttrs, "NoInterfaceObject")) {
throw new Error(`Interface ${this.name} has neither [Exposed] nor [NoInterfaceObject]`);
}

const legacyWindowAlias = utils.getExtAttr(this.idl.extAttrs, "LegacyWindowAlias");
if (legacyWindowAlias) {
if (utils.getExtAttr(this.idl.extAttrs, "NoInterfaceObject")) {
throw new Error(`Interface ${this.name} has [LegacyWindowAlias] and [NoInterfaceObject]`);
}

if (!this.exposed.has("Window")) {
throw new Error(`Interface ${this.name} has [LegacyWindowAlias] without [Exposed=Window]`);
}

if (!legacyWindowAlias.rhs ||
(legacyWindowAlias.rhs.type !== "identifier" && legacyWindowAlias.rhs.type !== "identifier-list")) {
throw new Error(`[LegacyWindowAlias] must take an identifier or an identifier list in interface ${this.name}`);
}

if (legacyWindowAlias.rhs.type === "identifier") {
this.legacyWindowAliases = new Set([legacyWindowAlias.rhs.value]);
} else {
this.legacyWindowAliases = new Set(legacyWindowAlias.rhs.value.map(token => token.value));
}
} else {
this.legacyWindowAliases = null;
}
}

// whence is either "instance" or "prototype"
Expand Down Expand Up @@ -1420,7 +1463,7 @@ class Interface {
const { idl, name } = this;

this.str += `
exports.install = function install(globalObject) {
exports.install = (globalObject, globalName) => {
`;

if (idl.inheritance) {
Expand All @@ -1444,12 +1487,39 @@ class Interface {
globalObject[ctorRegistrySymbol] = Object.create(null);
}
globalObject[ctorRegistrySymbol][interfaceName] = ${name};
`;

if (!utils.getExtAttr(this.idl.extAttrs, "NoInterfaceObject")) {
this.str += `
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: ${name}
});
`;

if (this.legacyWindowAliases) {
this.str += `
if (globalName === "Window") {
`;

for (const legacyWindowAlias of this.legacyWindowAliases) {
this.str += `
Object.defineProperty(globalObject, "${legacyWindowAlias}", {
configurable: true,
writable: true,
value: ${name}
});
`;
}

this.str += `
}
`;
}
}

this.str += `
};
`;
}
Expand Down
Loading

0 comments on commit 5af205c

Please sign in to comment.