Skip to content

Commit 1165da8

Browse files
committed
refactor(interface): Share named property visibility algorithm
1 parent ff61f8d commit 1165da8

File tree

1 file changed

+60
-89
lines changed

1 file changed

+60
-89
lines changed

lib/constructs/interface.js

Lines changed: 60 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ class Interface {
104104
if (global && !global.rhs) {
105105
throw new Error(`[Global] must take an identifier or an identifier list in interface ${this.name}`);
106106
}
107+
108+
this.overrideBuiltins = Boolean(utils.getExtAttr(this.idl.extAttrs, "OverrideBuiltins"));
107109
}
108110

109111
// whence is either "instance" or "prototype"
@@ -587,53 +589,52 @@ class Interface {
587589
}
588590
}
589591

592+
supportsPropertyIndex(O, index, indexedValue) {
593+
let unsupportedValue = utils.getExtAttr(this.indexedGetter.extAttrs, "WebIDL2JSValueAsUnsupported");
594+
if (unsupportedValue) {
595+
unsupportedValue = unsupportedValue.rhs.value;
596+
}
597+
if (unsupportedValue) {
598+
const func = this.indexedGetter.name ? `.${this.indexedGetter.name}` : "[utils.indexedGet]";
599+
const value = indexedValue || `${O}[impl]${func}(${index})`;
600+
return `${value} !== ${unsupportedValue}`;
601+
}
602+
return `${O}[impl][utils.supportsPropertyIndex](${index})`;
603+
}
604+
605+
supportsPropertyName(O, P, namedValue) {
606+
let unsupportedValue = utils.getExtAttr(this.namedGetter.extAttrs, "WebIDL2JSValueAsUnsupported");
607+
if (unsupportedValue) {
608+
unsupportedValue = unsupportedValue.rhs.value;
609+
}
610+
if (unsupportedValue) {
611+
const func = this.namedGetter.name ? `.${this.namedGetter.name}` : "[utils.namedGet]";
612+
const value = namedValue || `${O}[impl]${func}(${P})`;
613+
return `${value} !== ${unsupportedValue}`;
614+
}
615+
return `${O}[impl][utils.supportsPropertyName](${P})`;
616+
}
617+
618+
// "named property visibility algorithm"
619+
// If `supports` is true then skip the supportsPropertyName check.
620+
namedPropertyVisible(P, O, supports = false) {
621+
const conditions = [];
622+
if (!supports) {
623+
conditions.push(this.supportsPropertyName(O, P));
624+
}
625+
if (this.overrideBuiltins) {
626+
conditions.push(`!utils.hasOwn(${O}, ${P})`);
627+
} else {
628+
conditions.push(`!(${P} in ${O})`);
629+
}
630+
return conditions.join(" && ");
631+
}
632+
590633
generateLegacyProxyHandler() {
591634
const hasIndexedSetter = this.indexedSetter !== null;
592635
const hasNamedSetter = this.namedSetter !== null;
593636
const hasNamedDeleter = this.namedDeleter !== null;
594-
const overrideBuiltins = Boolean(utils.getExtAttr(this.idl.extAttrs, "OverrideBuiltins"));
595-
596-
const supportsPropertyIndex = (O, index, indexedValue) => {
597-
let unsupportedValue = utils.getExtAttr(this.indexedGetter.extAttrs, "WebIDL2JSValueAsUnsupported");
598-
if (unsupportedValue) {
599-
unsupportedValue = unsupportedValue.rhs.value;
600-
}
601-
if (unsupportedValue) {
602-
const func = this.indexedGetter.name ? `.${this.indexedGetter.name}` : "[utils.indexedGet]";
603-
const value = indexedValue || `${O}[impl]${func}(${index})`;
604-
return `${value} !== ${unsupportedValue}`;
605-
}
606-
return `${O}[impl][utils.supportsPropertyIndex](${index})`;
607-
};
608-
609-
const supportsPropertyName = (O, P, namedValue) => {
610-
let unsupportedValue = utils.getExtAttr(this.namedGetter.extAttrs, "WebIDL2JSValueAsUnsupported");
611-
if (unsupportedValue) {
612-
unsupportedValue = unsupportedValue.rhs.value;
613-
}
614-
if (unsupportedValue) {
615-
const func = this.namedGetter.name ? `.${this.namedGetter.name}` : "[utils.namedGet]";
616-
const value = namedValue || `${O}[impl]${func}(${P})`;
617-
return `${value} !== ${unsupportedValue}`;
618-
}
619-
return `${O}[impl][utils.supportsPropertyName](${P})`;
620-
};
621-
622-
// "named property visibility algorithm"
623-
// If `supports` is true then skip the supportsPropertyName check.
624-
function namedPropertyVisible(P, O, supports = false) {
625-
const conditions = [];
626-
if (!supports) {
627-
conditions.push(supportsPropertyName(O, P));
628-
}
629-
if (overrideBuiltins) {
630-
conditions.push(`!utils.hasOwn(${O}, ${P})`);
631-
} else {
632-
// TODO: create a named properties object.
633-
conditions.push(`!(${P} in ${O})`);
634-
}
635-
return conditions.join(" && ");
636-
}
637+
const { overrideBuiltins } = this;
637638

638639
// "invoke an indexed property setter"
639640
const invokeIndexedSetter = (O, P, V) => {
@@ -652,7 +653,7 @@ class Interface {
652653
let invocation;
653654
if (!this.indexedSetter.name) {
654655
invocation = `
655-
const creating = !(${supportsPropertyIndex(O, "index")});
656+
const creating = !(${this.supportsPropertyIndex(O, "index")});
656657
if (creating) {
657658
${O}[impl][utils.indexedSetNew](index, indexedValue);
658659
} else {
@@ -691,7 +692,7 @@ class Interface {
691692
let invocation;
692693
if (!this.namedSetter.name) {
693694
invocation = `
694-
const creating = !(${supportsPropertyName(O, P)});
695+
const creating = !(${this.supportsPropertyName(O, P)});
695696
if (creating) {
696697
${O}[impl][utils.namedSetNew](${P}, namedValue);
697698
} else {
@@ -777,7 +778,7 @@ class Interface {
777778
if (this.supportsNamedProperties) {
778779
this.str += `
779780
for (const key of target[impl][utils.supportedPropertyNames]) {
780-
if (${namedPropertyVisible("key", "target", true)}) {
781+
if (${this.namedPropertyVisible("key", "target", true)}) {
781782
keys.add(\`\${key}\`);
782783
}
783784
}
@@ -810,10 +811,10 @@ class Interface {
810811
let condition;
811812
if (utils.getExtAttr(this.indexedGetter.extAttrs, "WebIDL2JSValueAsUnsupported")) {
812813
this.str += `const indexedValue = target[impl]${func}(index);`;
813-
condition = supportsPropertyIndex("target", "index", "indexedValue");
814+
condition = this.supportsPropertyIndex("target", "index", "indexedValue");
814815
} else {
815816
preamble = `const indexedValue = target[impl]${func}(index);`;
816-
condition = supportsPropertyIndex("target", "index");
817+
condition = this.supportsPropertyIndex("target", "index");
817818
}
818819

819820
this.str += `
@@ -839,13 +840,13 @@ class Interface {
839840
this.str += `
840841
const namedValue = target[impl]${func}(P);
841842
`;
842-
conditions.push(supportsPropertyName("target", "index", "namedValue"));
843-
conditions.push(namedPropertyVisible("P", "target", true));
843+
conditions.push(this.supportsPropertyName("target", "index", "namedValue"));
844+
conditions.push(this.namedPropertyVisible("P", "target", true));
844845
} else {
845846
preamble = `
846847
const namedValue = target[impl]${func}(P);
847848
`;
848-
conditions.push(namedPropertyVisible("P", "target", false));
849+
conditions.push(this.namedPropertyVisible("P", "target", false));
849850
}
850851
conditions.push("!ignoreNamedProps");
851852
this.str += `
@@ -920,10 +921,10 @@ class Interface {
920921
let condition;
921922
if (utils.getExtAttr(this.indexedGetter.extAttrs, "WebIDL2JSValueAsUnsupported")) {
922923
this.str += `const indexedValue = target[impl]${func}(index);`;
923-
condition = supportsPropertyIndex("target", "index", "indexedValue");
924+
condition = this.supportsPropertyIndex("target", "index", "indexedValue");
924925
} else {
925926
preamble = `const indexedValue = target[impl]${func}(index);`;
926-
condition = supportsPropertyIndex("target", "index");
927+
condition = this.supportsPropertyIndex("target", "index");
927928
}
928929

929930
this.str += `
@@ -1022,7 +1023,7 @@ class Interface {
10221023
if (!hasNamedSetter) {
10231024
needFallback = true;
10241025
this.str += `
1025-
const creating = !(${supportsPropertyName("target", "P")});
1026+
const creating = !(${this.supportsPropertyName("target", "P")});
10261027
if (!creating) {
10271028
return false;
10281029
}
@@ -1072,13 +1073,13 @@ class Interface {
10721073
this.str += `
10731074
if (utils.isArrayIndexPropName(P)) {
10741075
const index = P >>> 0;
1075-
return !(${supportsPropertyIndex("target", "index")});
1076+
return !(${this.supportsPropertyIndex("target", "index")});
10761077
}
10771078
`;
10781079
}
10791080
if (this.supportsNamedProperties && !this.isGlobal) {
10801081
this.str += `
1081-
if (${namedPropertyVisible("P", "target")}) {
1082+
if (${this.namedPropertyVisible("P", "target")}) {
10821083
`;
10831084
if (!hasNamedDeleter) {
10841085
this.str += `
@@ -1131,36 +1132,6 @@ class Interface {
11311132
// https://heycam.github.io/webidl/#named-properties-object
11321133
generateNamedPropertiesObject() {
11331134
const { idl, name, namedGetter } = this;
1134-
const overrideBuiltins = Boolean(utils.getExtAttr(idl.extAttrs, "OverrideBuiltins"));
1135-
1136-
function supportsPropertyName(O, P, namedValue) {
1137-
let unsupportedValue = utils.getExtAttr(namedGetter.extAttrs, "WebIDL2JSValueAsUnsupported");
1138-
if (unsupportedValue) {
1139-
unsupportedValue = unsupportedValue.rhs.value;
1140-
}
1141-
if (unsupportedValue) {
1142-
const func = namedGetter.name ? `.${namedGetter.name}` : "[utils.namedGet]";
1143-
const value = namedValue || `${O}[impl]${func}(${P})`;
1144-
return `${value} !== ${unsupportedValue}`;
1145-
}
1146-
return `${O}[impl][utils.supportsPropertyName](${P})`;
1147-
}
1148-
1149-
// "named property visibility algorithm"
1150-
// If `supports` is true then skip the supportsPropertyName check.
1151-
function namedPropertyVisible(P, O, supports = false) {
1152-
const conditions = [];
1153-
if (!supports) {
1154-
conditions.push(supportsPropertyName(O, P));
1155-
}
1156-
if (overrideBuiltins) {
1157-
conditions.push(`!utils.hasOwn(${O}, ${P})`);
1158-
} else {
1159-
// TODO: create a named properties object.
1160-
conditions.push(`!(${P} in ${O})`);
1161-
}
1162-
return conditions.join(" && ");
1163-
}
11641135

11651136
this.str += `
11661137
const NamedPropertiesObject = new Proxy(
@@ -1231,13 +1202,13 @@ class Interface {
12311202
this.str += `
12321203
const namedValue = object[impl]${func}(P);
12331204
`;
1234-
conditions.push(supportsPropertyName("object", "index", "namedValue"));
1235-
conditions.push(namedPropertyVisible("P", "object", true));
1205+
conditions.push(this.supportsPropertyName("object", "index", "namedValue"));
1206+
conditions.push(this.namedPropertyVisible("P", "object", true));
12361207
} else {
12371208
preamble = `
12381209
const namedValue = object[impl]${func}(P);
12391210
`;
1240-
conditions.push(namedPropertyVisible("P", "object"));
1211+
conditions.push(this.namedPropertyVisible("P", "object"));
12411212
}
12421213
this.str += `
12431214
if (${conditions.join(" && ")}) {

0 commit comments

Comments
 (0)