Duplicate __proto__ key should be allowed in object patterns (#10987)

* refactor: replace refShorthandDefaultPos by refExpressionErrors

* fix: duplicate __proto__ keys should be allowed in patterns

* docs: add comments for ExpressionErrors.doubleProto [ci-skip]

* test: add more test for coverage
This commit is contained in:
Huáng Jùnliàng
2020-01-14 22:53:45 -05:00
committed by GitHub
parent a0a9c64a47
commit 9df70b4505
16 changed files with 820 additions and 96 deletions

View File

@@ -4,8 +4,9 @@
import { types as tt, TokenType } from "../tokenizer/types";
import type Parser from "../parser";
import type { ExpressionErrors } from "../parser/util";
import * as N from "../types";
import type { Pos, Position } from "../util/location";
import type { Position } from "../util/location";
import { type BindingTypes, BIND_NONE } from "../util/scopeflags";
function isSimpleProperty(node: N.Node): boolean {
@@ -148,7 +149,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
checkDuplicatedProto(
prop: N.ObjectMember | N.SpreadElement,
protoRef: { used: boolean, start?: number },
protoRef: { used: boolean },
refExpressionErrors: ?ExpressionErrors,
): void {
if (
prop.type === "SpreadElement" ||
@@ -166,8 +168,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (name === "__proto__" && prop.kind === "init") {
// Store the first redefinition's position
if (protoRef.used && !protoRef.start) {
protoRef.start = key.start;
if (protoRef.used) {
if (refExpressionErrors && refExpressionErrors.doubleProto === -1) {
refExpressionErrors.doubleProto = key.start;
} else {
this.raise(key.start, "Redefinition of __proto__ property");
}
}
protoRef.used = true;
@@ -234,7 +240,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
classBody.body.push(method);
}
parseExprAtom(refShorthandDefaultPos?: ?Pos): N.Expression {
parseExprAtom(refExpressionErrors?: ?ExpressionErrors): N.Expression {
switch (this.state.type) {
case tt.num:
case tt.string:
@@ -256,7 +262,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.estreeParseLiteral(false);
default:
return super.parseExprAtom(refShorthandDefaultPos);
return super.parseExprAtom(refExpressionErrors);
}
}
@@ -340,14 +346,14 @@ export default (superClass: Class<Parser>): Class<Parser> =>
startPos: ?number,
startLoc: ?Position,
isPattern: boolean,
refShorthandDefaultPos: ?Pos,
refExpressionErrors: ?ExpressionErrors,
): ?N.ObjectProperty {
const node: N.EstreeProperty = (super.parseObjectProperty(
prop,
startPos,
startLoc,
isPattern,
refShorthandDefaultPos,
refExpressionErrors,
): any);
if (node) {

View File

@@ -21,6 +21,7 @@ import {
SCOPE_ARROW,
SCOPE_OTHER,
} from "../util/scopeflags";
import type { ExpressionErrors } from "../parser/util";
const reservedTypes = new Set([
"_",
@@ -2283,7 +2284,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
isGenerator: boolean,
isAsync: boolean,
isPattern: boolean,
refShorthandDefaultPos: ?Pos,
refExpressionErrors: ?ExpressionErrors,
containsEsc: boolean,
): void {
if ((prop: $FlowFixMe).variance) {
@@ -2306,7 +2307,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
isGenerator,
isAsync,
isPattern,
refShorthandDefaultPos,
refExpressionErrors,
containsEsc,
);
@@ -2559,7 +2560,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
// 3. This is neither. Just call the super method
parseMaybeAssign(
noIn?: ?boolean,
refShorthandDefaultPos?: ?Pos,
refExpressionErrors?: ?ExpressionErrors,
afterLeftParse?: Function,
refNeedsArrowPos?: ?Pos,
): N.Expression {
@@ -2577,7 +2578,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
() =>
super.parseMaybeAssign(
noIn,
refShorthandDefaultPos,
refExpressionErrors,
afterLeftParse,
refNeedsArrowPos,
),
@@ -2611,7 +2612,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
() =>
super.parseMaybeAssign(
noIn,
refShorthandDefaultPos,
refExpressionErrors,
afterLeftParse,
refNeedsArrowPos,
),
@@ -2659,7 +2660,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return super.parseMaybeAssign(
noIn,
refShorthandDefaultPos,
refExpressionErrors,
afterLeftParse,
refNeedsArrowPos,
);

View File

@@ -4,11 +4,12 @@ import * as charCodes from "charcodes";
import XHTMLEntities from "./xhtml";
import type Parser from "../../parser";
import type { ExpressionErrors } from "../../parser/util";
import { TokenType, types as tt } from "../../tokenizer/types";
import { TokContext, types as tc } from "../../tokenizer/context";
import * as N from "../../types";
import { isIdentifierChar, isIdentifierStart } from "../../util/identifier";
import type { Pos, Position } from "../../util/location";
import type { Position } from "../../util/location";
import { isNewLine } from "../../util/whitespace";
const HEX_NUMBER = /^[\da-fA-F]+$/;
@@ -510,7 +511,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
// Overrides
// ==================================
parseExprAtom(refShortHandDefaultPos: ?Pos): N.Expression {
parseExprAtom(refExpressionErrors: ?ExpressionErrors): N.Expression {
if (this.match(tt.jsxText)) {
return this.parseLiteral(this.state.value, "JSXText");
} else if (this.match(tt.jsxTagStart)) {
@@ -524,7 +525,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.finishToken(tt.jsxTagStart);
return this.jsxParseElement();
} else {
return super.parseExprAtom(refShortHandDefaultPos);
return super.parseExprAtom(refExpressionErrors);
}
}

View File

@@ -25,6 +25,7 @@ import {
} from "../../util/scopeflags";
import TypeScriptScopeHandler from "./scope";
import * as charCodes from "charcodes";
import type { ExpressionErrors } from "../../parser/util";
type TsModifier =
| "readonly"
@@ -2340,11 +2341,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
// Handle type assertions
parseMaybeUnary(refShorthandDefaultPos?: ?Pos): N.Expression {
parseMaybeUnary(refExpressionErrors?: ?ExpressionErrors): N.Expression {
if (!this.hasPlugin("jsx") && this.isRelational("<")) {
return this.tsParseTypeAssertion();
} else {
return super.parseMaybeUnary(refShorthandDefaultPos);
return super.parseMaybeUnary(refExpressionErrors);
}
}