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:
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user