Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ webidl2js is implementing an ever-growing subset of the Web IDL specification. S
- Variadic arguments
- `[Clamp]`
- `[EnforceRange]`
- `[Exposed]`
Comment thread
ExE-Boss marked this conversation as resolved.
- `[LegacyArrayClass]`
- `[LegacyUnenumerableNamedProperties]`
- `[LegacyWindowAlias]`
Expand Down
50 changes: 49 additions & 1 deletion lib/constructs/callback-interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,25 @@ class CallbackInterface {

this._analyzed = false;
this._outputStaticProperties = new Map();

const exposed = utils.getExtAttr(this.idl.extAttrs, "Exposed");
if (this.idl.members.some(member => member.type === "const") && !exposed) {
throw new Error(`Callback interface ${this.name} with defined constants lacks the [Exposed] extended attribute`);
}

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 callback 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();
}
}

_analyzeMembers() {
Expand Down Expand Up @@ -178,14 +197,41 @@ class CallbackInterface {
}

generateInstall() {
if (this.constants.size > 0) {
this.str += `
const exposed = new Set([
`;

for (const globalName of this.exposed) {
this.str += `"${globalName}",\n`;
}

this.str += `
]);
`;
Comment thread
ExE-Boss marked this conversation as resolved.
}

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

if (this.constants.size > 0) {
const { name } = this;

this.str += `
let isExposed = false;

for (const globalName of globalNames) {
if (exposed.has(globalName)) {
isExposed = true;
break;
}
}

if (!isExposed) {
return;
}
Comment thread
TimothyGu marked this conversation as resolved.

const ${name} = () => {
throw new TypeError("Illegal invocation");
};
Expand Down Expand Up @@ -234,4 +280,6 @@ class CallbackInterface {
}
}

CallbackInterface.prototype.type = "callback interface";

module.exports = CallbackInterface;
44 changes: 42 additions & 2 deletions lib/constructs/interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -1463,7 +1463,47 @@ class Interface {
const { idl, name } = this;

this.str += `
exports.install = (globalObject, globalName) => {
const exposed = new Set([
`;

for (const globalName of this.exposed) {
this.str += `"${globalName}",\n`;
}

this.str += `
]);
Comment thread
ExE-Boss marked this conversation as resolved.
Outdated

exports.install = (globalObject, globalNames) => {
let isExposed = false;
`;

if (this.legacyWindowAliases) {
this.str += "let isWindow = false;\n";
}

this.str += `
for (const globalName of globalNames) {
if (exposed.has(globalName)) {
isExposed = true;
`;

if (this.legacyWindowAliases) {
this.str += `
if (globalName === "Window") {
isWindow = true;
}
Comment thread
TimothyGu marked this conversation as resolved.
Outdated
`;
} else {
this.str += "break;";
}

this.str += `
}
}

if (!isExposed) {
return;
}
`;

if (idl.inheritance) {
Expand Down Expand Up @@ -1500,7 +1540,7 @@ class Interface {

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

for (const legacyWindowAlias of this.legacyWindowAliases) {
Expand Down
Loading