Allow duplicate __proto__ keys in patterns, simple case (#6705) (#10532)

* Allow duplicate __proto__ keys in patterns, simple case (#6705)

* Update test262 whitelist

* Rename checkDuplicatedProto's parameter and adjust type

* Store first __proto__ redefinition's position
This commit is contained in:
Alejandro Sánchez 2019-10-14 16:18:33 -06:00 committed by Nicolò Ribaudo
parent dcf7d89b8e
commit 06313a6288
5 changed files with 230 additions and 17 deletions

View File

@ -67,14 +67,13 @@ export default class ExpressionParser extends LValParser {
+parseFunctionParams: (node: N.Function, allowModifiers?: boolean) => void; +parseFunctionParams: (node: N.Function, allowModifiers?: boolean) => void;
+takeDecorators: (node: N.HasDecorators) => void; +takeDecorators: (node: N.HasDecorators) => void;
// Check if property name clashes with already added. // Check if property __proto__ has been used more than once.
// Object/class getters and setters are not allowed to clash — // If the expression is a destructuring assignment, then __proto__ may appear
// either with each other or with an init property — and in // multiple times. Otherwise, __proto__ is a duplicated key.
// strict mode, init properties are also not allowed to be repeated.
checkPropClash( checkDuplicatedProto(
prop: N.ObjectMember | N.SpreadElement, prop: N.ObjectMember | N.SpreadElement,
propHash: { [key: string]: boolean }, protoRef: { used: boolean, start?: number },
): void { ): void {
if ( if (
prop.type === "SpreadElement" || prop.type === "SpreadElement" ||
@ -91,10 +90,12 @@ export default class ExpressionParser extends LValParser {
const name = key.type === "Identifier" ? key.name : String(key.value); const name = key.type === "Identifier" ? key.name : String(key.value);
if (name === "__proto__") { if (name === "__proto__") {
if (propHash.proto) { // Store the first redefinition's position
this.raise(key.start, "Redefinition of __proto__ property"); if (protoRef.used && !protoRef.start) {
protoRef.start = key.start;
} }
propHash.proto = true;
protoRef.used = true;
} }
} }
@ -1515,7 +1516,7 @@ export default class ExpressionParser extends LValParser {
const prop = this.parseObjectMember(isPattern, refShorthandDefaultPos); const prop = this.parseObjectMember(isPattern, refShorthandDefaultPos);
// $FlowIgnore RestElement will never be returned if !isPattern // $FlowIgnore RestElement will never be returned if !isPattern
if (!isPattern) this.checkPropClash(prop, propHash); if (!isPattern) this.checkDuplicatedProto(prop, propHash);
// $FlowIgnore // $FlowIgnore
if (prop.shorthand) { if (prop.shorthand) {
@ -1525,6 +1526,10 @@ export default class ExpressionParser extends LValParser {
node.properties.push(prop); node.properties.push(prop);
} }
if (!this.match(tt.eq) && propHash.start !== undefined) {
this.raise(propHash.start, "Redefinition of __proto__ property");
}
return this.finishNode( return this.finishNode(
node, node,
isPattern ? "ObjectPattern" : "ObjectExpression", isPattern ? "ObjectPattern" : "ObjectExpression",

View File

@ -125,9 +125,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
} }
} }
checkPropClash( checkDuplicatedProto(
prop: N.ObjectMember | N.SpreadElement, prop: N.ObjectMember | N.SpreadElement,
propHash: { [key: string]: boolean }, protoRef: { used: boolean, start?: number },
): void { ): void {
if ( if (
prop.type === "SpreadElement" || prop.type === "SpreadElement" ||
@ -144,10 +144,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
const name = key.type === "Identifier" ? key.name : String(key.value); const name = key.type === "Identifier" ? key.name : String(key.value);
if (name === "__proto__" && prop.kind === "init") { if (name === "__proto__" && prop.kind === "init") {
if (propHash.proto) { // Store the first redefinition's position
this.raise(key.start, "Redefinition of __proto__ property"); if (protoRef.used && !protoRef.start) {
protoRef.start = key.start;
} }
propHash.proto = true;
protoRef.used = true;
} }
} }

View File

@ -0,0 +1 @@
({ __proto__: x, __proto__: y } = {});

View File

@ -0,0 +1,207 @@
{
"type": "File",
"start": 0,
"end": 38,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 38
}
},
"program": {
"type": "Program",
"start": 0,
"end": 38,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 38
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 38,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 38
}
},
"expression": {
"type": "AssignmentExpression",
"start": 1,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 1
},
"end": {
"line": 1,
"column": 36
}
},
"operator": "=",
"left": {
"type": "ObjectPattern",
"start": 1,
"end": 31,
"loc": {
"start": {
"line": 1,
"column": 1
},
"end": {
"line": 1,
"column": 31
}
},
"properties": [
{
"type": "ObjectProperty",
"start": 3,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 3
},
"end": {
"line": 1,
"column": 15
}
},
"method": false,
"key": {
"type": "Identifier",
"start": 3,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 3
},
"end": {
"line": 1,
"column": 12
},
"identifierName": "__proto__"
},
"name": "__proto__"
},
"computed": false,
"shorthand": false,
"value": {
"type": "Identifier",
"start": 14,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 1,
"column": 15
},
"identifierName": "x"
},
"name": "x"
}
},
{
"type": "ObjectProperty",
"start": 17,
"end": 29,
"loc": {
"start": {
"line": 1,
"column": 17
},
"end": {
"line": 1,
"column": 29
}
},
"method": false,
"key": {
"type": "Identifier",
"start": 17,
"end": 26,
"loc": {
"start": {
"line": 1,
"column": 17
},
"end": {
"line": 1,
"column": 26
},
"identifierName": "__proto__"
},
"name": "__proto__"
},
"computed": false,
"shorthand": false,
"value": {
"type": "Identifier",
"start": 28,
"end": 29,
"loc": {
"start": {
"line": 1,
"column": 28
},
"end": {
"line": 1,
"column": 29
},
"identifierName": "y"
},
"name": "y"
}
}
]
},
"right": {
"type": "ObjectExpression",
"start": 34,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 34
},
"end": {
"line": 1,
"column": 36
}
},
"properties": []
},
"extra": {
"parenthesized": true,
"parenStart": 0
}
}
}
],
"directives": []
}
}

View File

@ -1,5 +1,3 @@
language/expressions/assignment/destructuring/obj-prop-__proto__dup.js(default)
language/expressions/assignment/destructuring/obj-prop-__proto__dup.js(strict mode)
language/expressions/class/elements/fields-duplicate-privatenames.js(default) language/expressions/class/elements/fields-duplicate-privatenames.js(default)
language/expressions/class/elements/fields-duplicate-privatenames.js(strict mode) language/expressions/class/elements/fields-duplicate-privatenames.js(strict mode)
language/expressions/class/elements/syntax/early-errors/grammar-private-environment-on-class-heritage-chained-usage.js(default) language/expressions/class/elements/syntax/early-errors/grammar-private-environment-on-class-heritage-chained-usage.js(default)