Skip to content

Commit 851b047

Browse files
committed
Start building the named properties object
1 parent 7d0bf50 commit 851b047

File tree

3 files changed

+108
-2
lines changed

3 files changed

+108
-2
lines changed

lib/constructs/interface.js

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,105 @@ const IteratorPrototype = Object.create(utils.IteratorPrototype, {
7676
}
7777
});`;
7878
}
79+
}
80+
81+
Interface.prototype.generateNamedPropertiesObject = function () {
82+
if (!utils.isGlobal(this.idl)) {
83+
return;
84+
}
85+
86+
let overrideBuiltins = false;
87+
let parent = this.idl;
88+
while (parent) {
89+
if (utils.getExtAttr(parent.extAttrs, 'OverrideBuiltins')) {
90+
overrideBuiltins = true;
91+
}
92+
93+
const members = parent.members.filter((m) =>
94+
m.type === 'attribute' && utils.getExtAttr(m.extAttrs, 'Unforgeable')
95+
);
96+
const parentInterface = this.opts.interfaces[parent.inheritance];
97+
parent = parentInterface && parentInterface.idl;
98+
}
99+
100+
this.str += `
101+
function namedPropertiesIsVisible(P, O) {
102+
if (!true) { // is supported
103+
return false;
104+
}
105+
106+
if (Object.getOwnPropertyDescriptor(O, P)) {
107+
return false;
108+
}
109+
`;
110+
111+
if (overrideBuiltins) {
112+
this.str += `
113+
return true;`;
114+
}
115+
116+
this.str += `
117+
let prototype = Object.getPrototypeOf(O);
118+
while (prototype) {
119+
if (prototype.constructor.name.endsWith("PropertiesConstructor") && Object.getOwnPropertyDescriptor(prototype, P)) {
120+
return false;
121+
}
122+
prototype = Object.getPrototypeOf(prototype);
123+
}`;
124+
this.str += `
125+
return true;
126+
}`;
127+
128+
this.str += `var ${this.name}PropertiesConstructor = function () {
129+
throw new TypeError("Illegal constructor");
130+
}\n`;
131+
132+
if (this.idl.inheritance) {
133+
this.str += `${this.name}PropertiesConstructor.prototype = Object.create(${this.idl.inheritance}.interface.prototype);
134+
${this.name}PropertiesConstructor.prototype.constructor = ${this.name}PropertiesConstructor;\n`;
135+
} else if (utils.getExtAttr(this.idl.extAttrs, 'LegacyArrayClass')) {
136+
this.str += `${this.name}PropertiesConstructor.prototype = Object.create(Array.prototype);
137+
${this.name}PropertiesConstructor.prototype.constructor = ${this.name}PropertiesConstructor;\n`;
138+
}
139+
140+
const getter = this.idl.members.filter((m) => m.getter)[0].name;
141+
this.str += `
142+
const ${this.name}Properties = new Proxy(${this.name}PropertiesConstructor.prototype, {
143+
defineProperty() {
144+
return false;
145+
},
146+
deleteProperty() {
147+
return false;
148+
},
149+
getOwnPropertyDescriptor(target, key) {
150+
if (namedPropertiesIsVisible(key, target)) { // is visible
151+
const value = target${getter ? "." + getter : "[utils.anonymousGetter]"}(key);
152+
return {
153+
value,
154+
enumerable: true,
155+
writable: true,
156+
configurable: true
157+
};
158+
} else {
159+
return Object.getOwnPropertyDescriptor(target, key);
160+
}
161+
},
162+
get(target, key) {
163+
if (namedPropertiesIsVisible(key, target)) { // is visible
164+
const value = target${getter ? "." + getter : "[utils.anonymousGetter]"}(key);
165+
return value;
166+
} else {
167+
return target[key];
168+
}
169+
},
170+
has(target, key) {
171+
if (namedPropertiesIsVisible(key, target)) { // is visible
172+
return true;
173+
} else {
174+
return key in target;
175+
}
176+
}
177+
});\n\n`;
79178
};
80179

81180
Interface.prototype.generateConstructor = function () {
@@ -116,9 +215,11 @@ Interface.prototype.generateConstructor = function () {
116215
}\n`;
117216
}
118217

119-
if (this.idl.inheritance) {
218+
if (this.idl.inheritance && !utils.isGlobal(this.idl)) {
120219
this.str += `${this.name}.prototype = Object.create(${this.idl.inheritance}.interface.prototype);
121220
${this.name}.prototype.constructor = ${this.name};\n`;
221+
} else if (utils.isGlobal(this.idl)) {
222+
this.str += `Object.setPrototypeOf(${this.name}.prototype, ${this.name}Properties);\n`;
122223
}
123224
};
124225

@@ -406,6 +507,7 @@ module.exports = {
406507
defaultPrivateData = defaultPrivateData === undefined ? {} : defaultPrivateData;\n\n`;
407508
}
408509

510+
this.generateNamedPropertiesObject();
409511
this.generateConstructor();
410512
this.generateMixins();
411513

lib/output/utils.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,6 @@ module.exports.tryWrapperForImpl = tryWrapperForImpl;
4343
module.exports.tryImplForWrapper = tryImplForWrapper;
4444
module.exports.iterInternalSymbol = iterInternalSymbol;
4545
module.exports.IteratorPrototype = IteratorPrototype;
46+
47+
module.exports.anonymousGetter = Symbol("anonymousGetter");
48+
module.exports.anonymousSetter = Symbol("anonymousSetter");

lib/transformer.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ class Transformer {
9292
obj = new Interface(instruction, {
9393
implDir: path.resolve(outputDir, file.impl),
9494
implSuffix: this.options.implSuffix,
95-
customTypes
95+
customTypes,
96+
interfaces
9697
});
9798
interfaces[obj.name] = obj;
9899
break;

0 commit comments

Comments
 (0)