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

@@ -41,6 +41,7 @@ import {
SCOPE_PROGRAM,
SCOPE_ASYNC,
} from "../util/scopeflags";
import { ExpressionErrors } from "./util";
export default class ExpressionParser extends LValParser {
// Forward-declaration: defined in statement.js
@@ -69,7 +70,8 @@ export default class ExpressionParser extends LValParser {
checkDuplicatedProto(
prop: N.ObjectMember | N.SpreadElement,
protoRef: { used: boolean, start?: number },
protoRef: { used: boolean },
refExpressionErrors: ?ExpressionErrors,
): void {
if (
prop.type === "SpreadElement" ||
@@ -87,8 +89,12 @@ export default class ExpressionParser extends LValParser {
if (name === "__proto__") {
// 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;
@@ -127,17 +133,18 @@ export default class ExpressionParser extends LValParser {
// and object pattern might appear (so it's possible to raise
// delayed syntax error at correct position).
parseExpression(noIn?: boolean, refShorthandDefaultPos?: Pos): N.Expression {
parseExpression(
noIn?: boolean,
refExpressionErrors?: ExpressionErrors,
): N.Expression {
const startPos = this.state.start;
const startLoc = this.state.startLoc;
const expr = this.parseMaybeAssign(noIn, refShorthandDefaultPos);
const expr = this.parseMaybeAssign(noIn, refExpressionErrors);
if (this.match(tt.comma)) {
const node = this.startNodeAt(startPos, startLoc);
node.expressions = [expr];
while (this.eat(tt.comma)) {
node.expressions.push(
this.parseMaybeAssign(noIn, refShorthandDefaultPos),
);
node.expressions.push(this.parseMaybeAssign(noIn, refExpressionErrors));
}
this.toReferencedList(node.expressions);
return this.finishNode(node, "SequenceExpression");
@@ -150,7 +157,7 @@ export default class ExpressionParser extends LValParser {
parseMaybeAssign(
noIn?: ?boolean,
refShorthandDefaultPos?: ?Pos,
refExpressionErrors?: ?ExpressionErrors,
afterLeftParse?: Function,
refNeedsArrowPos?: ?Pos,
): N.Expression {
@@ -170,12 +177,12 @@ export default class ExpressionParser extends LValParser {
}
}
let failOnShorthandAssign;
if (refShorthandDefaultPos) {
failOnShorthandAssign = false;
let ownExpressionErrors;
if (refExpressionErrors) {
ownExpressionErrors = false;
} else {
refShorthandDefaultPos = { start: 0 };
failOnShorthandAssign = true;
refExpressionErrors = new ExpressionErrors();
ownExpressionErrors = true;
}
if (this.match(tt.parenL) || this.match(tt.name)) {
@@ -184,7 +191,7 @@ export default class ExpressionParser extends LValParser {
let left = this.parseMaybeConditional(
noIn,
refShorthandDefaultPos,
refExpressionErrors,
refNeedsArrowPos,
);
if (afterLeftParse) {
@@ -201,12 +208,15 @@ export default class ExpressionParser extends LValParser {
if (operator === "||=" || operator === "&&=") {
this.expectPlugin("logicalAssignment");
}
node.left = this.match(tt.eq)
? this.toAssignable(left, undefined, "assignment expression")
: left;
if (this.match(tt.eq)) {
node.left = this.toAssignable(left, undefined, "assignment expression");
refExpressionErrors.doubleProto = -1; // reset because double __proto__ is valid in assignment expression
} else {
node.left = left;
}
if (refShorthandDefaultPos.start >= node.left.start) {
refShorthandDefaultPos.start = 0; // reset because shorthand default was used correctly
if (refExpressionErrors.shorthandAssign >= node.left.start) {
refExpressionErrors.shorthandAssign = -1; // reset because shorthand default was used correctly
}
this.checkLVal(left, undefined, undefined, "assignment expression");
@@ -214,8 +224,8 @@ export default class ExpressionParser extends LValParser {
this.next();
node.right = this.parseMaybeAssign(noIn);
return this.finishNode(node, "AssignmentExpression");
} else if (failOnShorthandAssign && refShorthandDefaultPos.start) {
this.unexpected(refShorthandDefaultPos.start);
} else if (ownExpressionErrors) {
this.checkExpressionErrors(refExpressionErrors, true);
}
return left;
@@ -225,13 +235,13 @@ export default class ExpressionParser extends LValParser {
parseMaybeConditional(
noIn: ?boolean,
refShorthandDefaultPos: Pos,
refExpressionErrors: ExpressionErrors,
refNeedsArrowPos?: ?Pos,
): N.Expression {
const startPos = this.state.start;
const startLoc = this.state.startLoc;
const potentialArrowAt = this.state.potentialArrowAt;
const expr = this.parseExprOps(noIn, refShorthandDefaultPos);
const expr = this.parseExprOps(noIn, refExpressionErrors);
if (
expr.type === "ArrowFunctionExpression" &&
@@ -239,7 +249,7 @@ export default class ExpressionParser extends LValParser {
) {
return expr;
}
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
if (this.checkExpressionErrors(refExpressionErrors, false)) return expr;
return this.parseConditional(
expr,
@@ -272,11 +282,14 @@ export default class ExpressionParser extends LValParser {
// Start the precedence parser.
parseExprOps(noIn: ?boolean, refShorthandDefaultPos: Pos): N.Expression {
parseExprOps(
noIn: ?boolean,
refExpressionErrors: ExpressionErrors,
): N.Expression {
const startPos = this.state.start;
const startLoc = this.state.startLoc;
const potentialArrowAt = this.state.potentialArrowAt;
const expr = this.parseMaybeUnary(refShorthandDefaultPos);
const expr = this.parseMaybeUnary(refExpressionErrors);
if (
expr.type === "ArrowFunctionExpression" &&
@@ -284,7 +297,7 @@ export default class ExpressionParser extends LValParser {
) {
return expr;
}
if (refShorthandDefaultPos && refShorthandDefaultPos.start) {
if (this.checkExpressionErrors(refExpressionErrors, false)) {
return expr;
}
@@ -463,7 +476,7 @@ export default class ExpressionParser extends LValParser {
// Parse unary operators, both prefix and postfix.
parseMaybeUnary(refShorthandDefaultPos: ?Pos): N.Expression {
parseMaybeUnary(refExpressionErrors: ?ExpressionErrors): N.Expression {
if (this.isContextual("await") && this.isAwaitAllowed()) {
return this.parseAwait();
} else if (this.state.type.prefix) {
@@ -479,9 +492,7 @@ export default class ExpressionParser extends LValParser {
node.argument = this.parseMaybeUnary();
if (refShorthandDefaultPos && refShorthandDefaultPos.start) {
this.unexpected(refShorthandDefaultPos.start);
}
this.checkExpressionErrors(refExpressionErrors, true);
if (update) {
this.checkLVal(node.argument, undefined, undefined, "prefix operation");
@@ -506,8 +517,8 @@ export default class ExpressionParser extends LValParser {
const startPos = this.state.start;
const startLoc = this.state.startLoc;
let expr = this.parseExprSubscripts(refShorthandDefaultPos);
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
let expr = this.parseExprSubscripts(refExpressionErrors);
if (this.checkExpressionErrors(refExpressionErrors, false)) return expr;
while (this.state.type.postfix && !this.canInsertSemicolon()) {
const node = this.startNodeAt(startPos, startLoc);
node.operator = this.state.value;
@@ -522,11 +533,11 @@ export default class ExpressionParser extends LValParser {
// Parse call, dot, and `[]`-subscript expressions.
parseExprSubscripts(refShorthandDefaultPos: ?Pos): N.Expression {
parseExprSubscripts(refExpressionErrors: ?ExpressionErrors): N.Expression {
const startPos = this.state.start;
const startLoc = this.state.startLoc;
const potentialArrowAt = this.state.potentialArrowAt;
const expr = this.parseExprAtom(refShorthandDefaultPos);
const expr = this.parseExprAtom(refExpressionErrors);
if (
expr.type === "ArrowFunctionExpression" &&
@@ -535,7 +546,7 @@ export default class ExpressionParser extends LValParser {
return expr;
}
if (refShorthandDefaultPos && refShorthandDefaultPos.start) {
if (this.checkExpressionErrors(refExpressionErrors, false)) {
return expr;
}
@@ -816,7 +827,7 @@ export default class ExpressionParser extends LValParser {
elts.push(
this.parseExprListItem(
false,
possibleAsyncArrow ? { start: 0 } : undefined,
possibleAsyncArrow ? new ExpressionErrors() : undefined,
possibleAsyncArrow ? { start: 0 } : undefined,
allowPlaceholder,
),
@@ -864,7 +875,7 @@ export default class ExpressionParser extends LValParser {
// `new`, or an expression wrapped in punctuation like `()`, `[]`,
// or `{}`.
parseExprAtom(refShorthandDefaultPos?: ?Pos): N.Expression {
parseExprAtom(refExpressionErrors?: ?ExpressionErrors): N.Expression {
// If a division operator appears in an expression position, the
// tokenizer got confused, and we force it to read a regexp instead.
if (this.state.type === tt.slash) this.readRegexp();
@@ -1038,7 +1049,7 @@ export default class ExpressionParser extends LValParser {
node.elements = this.parseExprList(
tt.bracketR,
true,
refShorthandDefaultPos,
refExpressionErrors,
node,
);
if (!this.state.maybeInArrowParameters) {
@@ -1056,7 +1067,7 @@ export default class ExpressionParser extends LValParser {
const oldInFSharpPipelineDirectBody = this.state
.inFSharpPipelineDirectBody;
this.state.inFSharpPipelineDirectBody = false;
const ret = this.parseObj(false, refShorthandDefaultPos);
const ret = this.parseObj(false, refExpressionErrors);
this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody;
return ret;
}
@@ -1263,7 +1274,7 @@ export default class ExpressionParser extends LValParser {
const innerStartPos = this.state.start;
const innerStartLoc = this.state.startLoc;
const exprList = [];
const refShorthandDefaultPos = { start: 0 };
const refExpressionErrors = new ExpressionErrors();
const refNeedsArrowPos = { start: 0 };
let first = true;
let spreadStart;
@@ -1299,7 +1310,7 @@ export default class ExpressionParser extends LValParser {
exprList.push(
this.parseMaybeAssign(
false,
refShorthandDefaultPos,
refExpressionErrors,
this.parseParenItem,
refNeedsArrowPos,
),
@@ -1343,9 +1354,7 @@ export default class ExpressionParser extends LValParser {
}
if (optionalCommaStart) this.unexpected(optionalCommaStart);
if (spreadStart) this.unexpected(spreadStart);
if (refShorthandDefaultPos.start) {
this.unexpected(refShorthandDefaultPos.start);
}
this.checkExpressionErrors(refExpressionErrors, true);
if (refNeedsArrowPos.start) this.unexpected(refNeedsArrowPos.start);
this.toReferencedListDeep(exprList, /* isParenthesizedExpr */ true);
@@ -1490,7 +1499,7 @@ export default class ExpressionParser extends LValParser {
parseObj<T: N.ObjectPattern | N.ObjectExpression>(
isPattern: boolean,
refShorthandDefaultPos?: ?Pos,
refExpressionErrors?: ?ExpressionErrors,
): T {
const propHash: any = Object.create(null);
let first = true;
@@ -1511,9 +1520,11 @@ export default class ExpressionParser extends LValParser {
}
}
const prop = this.parseObjectMember(isPattern, refShorthandDefaultPos);
// $FlowIgnore RestElement will never be returned if !isPattern
if (!isPattern) this.checkDuplicatedProto(prop, propHash);
const prop = this.parseObjectMember(isPattern, refExpressionErrors);
if (!isPattern) {
// $FlowIgnore RestElement will never be returned if !isPattern
this.checkDuplicatedProto(prop, propHash, refExpressionErrors);
}
// $FlowIgnore
if (prop.shorthand) {
@@ -1523,10 +1534,6 @@ export default class ExpressionParser extends LValParser {
node.properties.push(prop);
}
if (!this.match(tt.eq) && propHash.start !== undefined) {
this.raise(propHash.start, "Redefinition of __proto__ property");
}
return this.finishNode(
node,
isPattern ? "ObjectPattern" : "ObjectExpression",
@@ -1550,7 +1557,7 @@ export default class ExpressionParser extends LValParser {
parseObjectMember(
isPattern: boolean,
refShorthandDefaultPos: ?Pos,
refExpressionErrors?: ?ExpressionErrors,
): N.ObjectMember | N.SpreadElement | N.RestElement {
let decorators = [];
if (this.match(tt.at)) {
@@ -1594,7 +1601,7 @@ export default class ExpressionParser extends LValParser {
prop.method = false;
if (isPattern || refShorthandDefaultPos) {
if (isPattern || refExpressionErrors) {
startPos = this.state.start;
startLoc = this.state.startLoc;
}
@@ -1621,7 +1628,7 @@ export default class ExpressionParser extends LValParser {
isGenerator,
isAsync,
isPattern,
refShorthandDefaultPos,
refExpressionErrors,
containsEsc,
);
@@ -1715,14 +1722,14 @@ export default class ExpressionParser extends LValParser {
startPos: ?number,
startLoc: ?Position,
isPattern: boolean,
refShorthandDefaultPos: ?Pos,
refExpressionErrors: ?ExpressionErrors,
): ?N.ObjectProperty {
prop.shorthand = false;
if (this.eat(tt.colon)) {
prop.value = isPattern
? this.parseMaybeDefault(this.state.start, this.state.startLoc)
: this.parseMaybeAssign(false, refShorthandDefaultPos);
: this.parseMaybeAssign(false, refExpressionErrors);
return this.finishNode(prop, "ObjectProperty");
}
@@ -1736,9 +1743,9 @@ export default class ExpressionParser extends LValParser {
startLoc,
prop.key.__clone(),
);
} else if (this.match(tt.eq) && refShorthandDefaultPos) {
if (!refShorthandDefaultPos.start) {
refShorthandDefaultPos.start = this.state.start;
} else if (this.match(tt.eq) && refExpressionErrors) {
if (refExpressionErrors.shorthandAssign === -1) {
refExpressionErrors.shorthandAssign = this.state.start;
}
prop.value = this.parseMaybeDefault(
startPos,
@@ -1761,7 +1768,7 @@ export default class ExpressionParser extends LValParser {
isGenerator: boolean,
isAsync: boolean,
isPattern: boolean,
refShorthandDefaultPos: ?Pos,
refExpressionErrors?: ?ExpressionErrors,
containsEsc: boolean,
): void {
const node =
@@ -1777,7 +1784,7 @@ export default class ExpressionParser extends LValParser {
startPos,
startLoc,
isPattern,
refShorthandDefaultPos,
refExpressionErrors,
);
if (!node) this.unexpected();
@@ -2019,7 +2026,7 @@ export default class ExpressionParser extends LValParser {
parseExprList(
close: TokenType,
allowEmpty?: boolean,
refShorthandDefaultPos?: ?Pos,
refExpressionErrors?: ?ExpressionErrors,
nodeForExtra?: ?N.Node,
): $ReadOnlyArray<?N.Expression> {
const elts = [];
@@ -2043,14 +2050,14 @@ export default class ExpressionParser extends LValParser {
}
}
elts.push(this.parseExprListItem(allowEmpty, refShorthandDefaultPos));
elts.push(this.parseExprListItem(allowEmpty, refExpressionErrors));
}
return elts;
}
parseExprListItem(
allowEmpty: ?boolean,
refShorthandDefaultPos: ?Pos,
refExpressionErrors?: ?ExpressionErrors,
refNeedsArrowPos: ?Pos,
allowPlaceholder: ?boolean,
): ?N.Expression {
@@ -2061,7 +2068,7 @@ export default class ExpressionParser extends LValParser {
const spreadNodeStartPos = this.state.start;
const spreadNodeStartLoc = this.state.startLoc;
elt = this.parseParenItem(
this.parseSpread(refShorthandDefaultPos, refNeedsArrowPos),
this.parseSpread(refExpressionErrors, refNeedsArrowPos),
spreadNodeStartPos,
spreadNodeStartLoc,
);
@@ -2076,7 +2083,7 @@ export default class ExpressionParser extends LValParser {
} else {
elt = this.parseMaybeAssign(
false,
refShorthandDefaultPos,
refExpressionErrors,
this.parseParenItem,
refNeedsArrowPos,
);

View File

@@ -21,6 +21,7 @@ import {
} from "../util/identifier";
import { NodeUtils } from "./node";
import { type BindingTypes, BIND_NONE } from "../util/scopeflags";
import { ExpressionErrors } from "./util";
const unwrapParenthesizedExpression = (node: Node) => {
return node.type === "ParenthesizedExpression"
@@ -33,13 +34,13 @@ export default class LValParser extends NodeUtils {
+parseIdentifier: (liberal?: boolean) => Identifier;
+parseMaybeAssign: (
noIn?: ?boolean,
refShorthandDefaultPos?: ?Pos,
refExpressionErrors?: ?ExpressionErrors,
afterLeftParse?: Function,
refNeedsArrowPos?: ?Pos,
) => Expression;
+parseObj: <T: ObjectPattern | ObjectExpression>(
isPattern: boolean,
refShorthandDefaultPos?: ?Pos,
refExpressionErrors?: ?ExpressionErrors,
) => T;
// Forward-declaration: defined in statement.js
+parseDecorator: () => Decorator;
@@ -241,14 +242,14 @@ export default class LValParser extends NodeUtils {
// Parses spread element.
parseSpread(
refShorthandDefaultPos: ?Pos,
refExpressionErrors: ?ExpressionErrors,
refNeedsArrowPos?: ?Pos,
): SpreadElement {
const node = this.startNode();
this.next();
node.argument = this.parseMaybeAssign(
false,
refShorthandDefaultPos,
refExpressionErrors,
undefined,
refNeedsArrowPos,
);

View File

@@ -27,6 +27,7 @@ import {
CLASS_ELEMENT_STATIC_SETTER,
type BindingTypes,
} from "../util/scopeflags";
import { ExpressionErrors } from "./util";
const loopLabel = { kind: "loop" },
switchLabel = { kind: "switch" };
@@ -533,8 +534,8 @@ export default class StatementParser extends ExpressionParser {
return this.parseFor(node, init);
}
const refShorthandDefaultPos = { start: 0 };
const init = this.parseExpression(true, refShorthandDefaultPos);
const refExpressionErrors = new ExpressionErrors();
const init = this.parseExpression(true, refExpressionErrors);
if (this.match(tt._in) || this.isContextual("of")) {
const description = this.isContextual("of")
? "for-of statement"
@@ -542,8 +543,8 @@ export default class StatementParser extends ExpressionParser {
this.toAssignable(init, undefined, description);
this.checkLVal(init, undefined, undefined, description);
return this.parseForIn(node, init, awaitAt);
} else if (refShorthandDefaultPos.start) {
this.unexpected(refShorthandDefaultPos.start);
} else {
this.checkExpressionErrors(refExpressionErrors, true);
}
if (awaitAt > -1) {
this.unexpected(awaitAt);

View File

@@ -268,4 +268,35 @@ export default class UtilParser extends Tokenizer {
throw error;
}
}
checkExpressionErrors(
refExpressionErrors: ?ExpressionErrors,
andThrow: boolean,
) {
if (!refExpressionErrors) return false;
const { shorthandAssign, doubleProto } = refExpressionErrors;
if (!andThrow) return shorthandAssign >= 0 || doubleProto >= 0;
if (shorthandAssign >= 0) {
this.unexpected(shorthandAssign);
}
if (doubleProto >= 0) {
this.raise(doubleProto, "Redefinition of __proto__ property");
}
}
}
/**
* The ExpressionErrors is a context struct used to track
* - **shorthandAssign**: track initializer `=` position when parsing ambiguous
* patterns. When we are sure the parsed pattern is a RHS, which means it is
* not a pattern, we will throw on this position on invalid assign syntax,
* otherwise it will be reset to -1
* - **doubleProto**: track the duplicate `__proto__` key position when parsing
* ambiguous object patterns. When we are sure the parsed pattern is a RHS,
* which means it is an object literal, we will throw on this position for
* __proto__ redefinition, otherwise it will be reset to -1
*/
export class ExpressionErrors {
shorthandAssign = -1;
doubleProto = -1;
}

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);
}
}