Refactor [In] production parameter tracking (#11930)
* refactor: track [In] parameter in prodParam * Apply suggestions from code review
This commit is contained in:
parent
fccf31aca6
commit
4bb1e164da
@ -44,6 +44,7 @@ import {
|
|||||||
import { ExpressionErrors } from "./util";
|
import { ExpressionErrors } from "./util";
|
||||||
import {
|
import {
|
||||||
PARAM_AWAIT,
|
PARAM_AWAIT,
|
||||||
|
PARAM_IN,
|
||||||
PARAM_RETURN,
|
PARAM_RETURN,
|
||||||
PARAM,
|
PARAM,
|
||||||
functionFlags,
|
functionFlags,
|
||||||
@ -153,11 +154,9 @@ export default class ExpressionParser extends LValParser {
|
|||||||
// the AST node that the inner parser gave them in another node.
|
// the AST node that the inner parser gave them in another node.
|
||||||
|
|
||||||
// Parse a full expression.
|
// Parse a full expression.
|
||||||
// - `noIn`
|
// - `disallowIn`
|
||||||
// is used to forbid the `in` operator (in for loops initialization expressions)
|
// is used to forbid the `in` operator (in for loops initialization expressions)
|
||||||
// When `noIn` is true, the production parameter [In] is not present.
|
// When `disallowIn` is true, the production parameter [In] is not present.
|
||||||
// Whenever [?In] appears in the right-hand sides of a production, we pass
|
|
||||||
// `noIn` to the subroutine calls.
|
|
||||||
|
|
||||||
// - `refExpressionErrors `
|
// - `refExpressionErrors `
|
||||||
// provides reference for storing '=' operator inside shorthand
|
// provides reference for storing '=' operator inside shorthand
|
||||||
@ -165,19 +164,28 @@ export default class ExpressionParser extends LValParser {
|
|||||||
// and object pattern might appear (so it's possible to raise
|
// and object pattern might appear (so it's possible to raise
|
||||||
// delayed syntax error at correct position).
|
// delayed syntax error at correct position).
|
||||||
|
|
||||||
// https://tc39.es/ecma262/#prod-Expression
|
|
||||||
parseExpression(
|
parseExpression(
|
||||||
noIn?: boolean,
|
disallowIn?: boolean,
|
||||||
refExpressionErrors?: ExpressionErrors,
|
refExpressionErrors?: ExpressionErrors,
|
||||||
): N.Expression {
|
): N.Expression {
|
||||||
|
if (disallowIn) {
|
||||||
|
return this.disallowInAnd(() =>
|
||||||
|
this.parseExpressionBase(refExpressionErrors),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.allowInAnd(() => this.parseExpressionBase(refExpressionErrors));
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://tc39.es/ecma262/#prod-Expression
|
||||||
|
parseExpressionBase(refExpressionErrors?: ExpressionErrors): N.Expression {
|
||||||
const startPos = this.state.start;
|
const startPos = this.state.start;
|
||||||
const startLoc = this.state.startLoc;
|
const startLoc = this.state.startLoc;
|
||||||
const expr = this.parseMaybeAssign(noIn, refExpressionErrors);
|
const expr = this.parseMaybeAssign(refExpressionErrors);
|
||||||
if (this.match(tt.comma)) {
|
if (this.match(tt.comma)) {
|
||||||
const node = this.startNodeAt(startPos, startLoc);
|
const node = this.startNodeAt(startPos, startLoc);
|
||||||
node.expressions = [expr];
|
node.expressions = [expr];
|
||||||
while (this.eat(tt.comma)) {
|
while (this.eat(tt.comma)) {
|
||||||
node.expressions.push(this.parseMaybeAssign(noIn, refExpressionErrors));
|
node.expressions.push(this.parseMaybeAssign(refExpressionErrors));
|
||||||
}
|
}
|
||||||
this.toReferencedList(node.expressions);
|
this.toReferencedList(node.expressions);
|
||||||
return this.finishNode(node, "SequenceExpression");
|
return this.finishNode(node, "SequenceExpression");
|
||||||
@ -185,12 +193,41 @@ export default class ExpressionParser extends LValParser {
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set [~In] parameter for assignment expression
|
||||||
|
parseMaybeAssignDisallowIn(
|
||||||
|
refExpressionErrors?: ?ExpressionErrors,
|
||||||
|
afterLeftParse?: Function,
|
||||||
|
refNeedsArrowPos?: ?Pos,
|
||||||
|
) {
|
||||||
|
return this.disallowInAnd(() =>
|
||||||
|
this.parseMaybeAssign(
|
||||||
|
refExpressionErrors,
|
||||||
|
afterLeftParse,
|
||||||
|
refNeedsArrowPos,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set [+In] parameter for assignment expression
|
||||||
|
parseMaybeAssignAllowIn(
|
||||||
|
refExpressionErrors?: ?ExpressionErrors,
|
||||||
|
afterLeftParse?: Function,
|
||||||
|
refNeedsArrowPos?: ?Pos,
|
||||||
|
) {
|
||||||
|
return this.allowInAnd(() =>
|
||||||
|
this.parseMaybeAssign(
|
||||||
|
refExpressionErrors,
|
||||||
|
afterLeftParse,
|
||||||
|
refNeedsArrowPos,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Parse an assignment expression. This includes applications of
|
// Parse an assignment expression. This includes applications of
|
||||||
// operators like `+=`.
|
// operators like `+=`.
|
||||||
|
|
||||||
// https://tc39.es/ecma262/#prod-AssignmentExpression
|
// https://tc39.es/ecma262/#prod-AssignmentExpression
|
||||||
parseMaybeAssign(
|
parseMaybeAssign(
|
||||||
noIn?: ?boolean,
|
|
||||||
refExpressionErrors?: ?ExpressionErrors,
|
refExpressionErrors?: ?ExpressionErrors,
|
||||||
afterLeftParse?: Function,
|
afterLeftParse?: Function,
|
||||||
refNeedsArrowPos?: ?Pos,
|
refNeedsArrowPos?: ?Pos,
|
||||||
@ -199,7 +236,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
const startLoc = this.state.startLoc;
|
const startLoc = this.state.startLoc;
|
||||||
if (this.isContextual("yield")) {
|
if (this.isContextual("yield")) {
|
||||||
if (this.prodParam.hasYield) {
|
if (this.prodParam.hasYield) {
|
||||||
let left = this.parseYield(noIn);
|
let left = this.parseYield();
|
||||||
if (afterLeftParse) {
|
if (afterLeftParse) {
|
||||||
left = afterLeftParse.call(this, left, startPos, startLoc);
|
left = afterLeftParse.call(this, left, startPos, startLoc);
|
||||||
}
|
}
|
||||||
@ -224,7 +261,6 @@ export default class ExpressionParser extends LValParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let left = this.parseMaybeConditional(
|
let left = this.parseMaybeConditional(
|
||||||
noIn,
|
|
||||||
refExpressionErrors,
|
refExpressionErrors,
|
||||||
refNeedsArrowPos,
|
refNeedsArrowPos,
|
||||||
);
|
);
|
||||||
@ -250,7 +286,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
this.checkLVal(left, undefined, undefined, "assignment expression");
|
this.checkLVal(left, undefined, undefined, "assignment expression");
|
||||||
|
|
||||||
this.next();
|
this.next();
|
||||||
node.right = this.parseMaybeAssign(noIn);
|
node.right = this.parseMaybeAssign();
|
||||||
return this.finishNode(node, "AssignmentExpression");
|
return this.finishNode(node, "AssignmentExpression");
|
||||||
} else if (ownExpressionErrors) {
|
} else if (ownExpressionErrors) {
|
||||||
this.checkExpressionErrors(refExpressionErrors, true);
|
this.checkExpressionErrors(refExpressionErrors, true);
|
||||||
@ -263,31 +299,23 @@ export default class ExpressionParser extends LValParser {
|
|||||||
// https://tc39.es/ecma262/#prod-ConditionalExpression
|
// https://tc39.es/ecma262/#prod-ConditionalExpression
|
||||||
|
|
||||||
parseMaybeConditional(
|
parseMaybeConditional(
|
||||||
noIn: ?boolean,
|
|
||||||
refExpressionErrors: ExpressionErrors,
|
refExpressionErrors: ExpressionErrors,
|
||||||
refNeedsArrowPos?: ?Pos,
|
refNeedsArrowPos?: ?Pos,
|
||||||
): N.Expression {
|
): N.Expression {
|
||||||
const startPos = this.state.start;
|
const startPos = this.state.start;
|
||||||
const startLoc = this.state.startLoc;
|
const startLoc = this.state.startLoc;
|
||||||
const potentialArrowAt = this.state.potentialArrowAt;
|
const potentialArrowAt = this.state.potentialArrowAt;
|
||||||
const expr = this.parseExprOps(noIn, refExpressionErrors);
|
const expr = this.parseExprOps(refExpressionErrors);
|
||||||
|
|
||||||
if (this.shouldExitDescending(expr, potentialArrowAt)) {
|
if (this.shouldExitDescending(expr, potentialArrowAt)) {
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.parseConditional(
|
return this.parseConditional(expr, startPos, startLoc, refNeedsArrowPos);
|
||||||
expr,
|
|
||||||
noIn,
|
|
||||||
startPos,
|
|
||||||
startLoc,
|
|
||||||
refNeedsArrowPos,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parseConditional(
|
parseConditional(
|
||||||
expr: N.Expression,
|
expr: N.Expression,
|
||||||
noIn: ?boolean,
|
|
||||||
startPos: number,
|
startPos: number,
|
||||||
startLoc: Position,
|
startLoc: Position,
|
||||||
// FIXME: Disabling this for now since can't seem to get it to play nicely
|
// FIXME: Disabling this for now since can't seem to get it to play nicely
|
||||||
@ -297,9 +325,9 @@ export default class ExpressionParser extends LValParser {
|
|||||||
if (this.eat(tt.question)) {
|
if (this.eat(tt.question)) {
|
||||||
const node = this.startNodeAt(startPos, startLoc);
|
const node = this.startNodeAt(startPos, startLoc);
|
||||||
node.test = expr;
|
node.test = expr;
|
||||||
node.consequent = this.parseMaybeAssign();
|
node.consequent = this.parseMaybeAssignAllowIn();
|
||||||
this.expect(tt.colon);
|
this.expect(tt.colon);
|
||||||
node.alternate = this.parseMaybeAssign(noIn);
|
node.alternate = this.parseMaybeAssign();
|
||||||
return this.finishNode(node, "ConditionalExpression");
|
return this.finishNode(node, "ConditionalExpression");
|
||||||
}
|
}
|
||||||
return expr;
|
return expr;
|
||||||
@ -308,10 +336,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
// Start the precedence parser.
|
// Start the precedence parser.
|
||||||
// https://tc39.es/ecma262/#prod-ShortCircuitExpression
|
// https://tc39.es/ecma262/#prod-ShortCircuitExpression
|
||||||
|
|
||||||
parseExprOps(
|
parseExprOps(refExpressionErrors: ExpressionErrors): N.Expression {
|
||||||
noIn: ?boolean,
|
|
||||||
refExpressionErrors: ExpressionErrors,
|
|
||||||
): N.Expression {
|
|
||||||
const startPos = this.state.start;
|
const startPos = this.state.start;
|
||||||
const startLoc = this.state.startLoc;
|
const startLoc = this.state.startLoc;
|
||||||
const potentialArrowAt = this.state.potentialArrowAt;
|
const potentialArrowAt = this.state.potentialArrowAt;
|
||||||
@ -321,7 +346,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.parseExprOp(expr, startPos, startLoc, -1, noIn);
|
return this.parseExprOp(expr, startPos, startLoc, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse binary operators with the operator precedence parsing
|
// Parse binary operators with the operator precedence parsing
|
||||||
@ -335,10 +360,9 @@ export default class ExpressionParser extends LValParser {
|
|||||||
leftStartPos: number,
|
leftStartPos: number,
|
||||||
leftStartLoc: Position,
|
leftStartLoc: Position,
|
||||||
minPrec: number,
|
minPrec: number,
|
||||||
noIn: ?boolean,
|
|
||||||
): N.Expression {
|
): N.Expression {
|
||||||
let prec = this.state.type.binop;
|
let prec = this.state.type.binop;
|
||||||
if (prec != null && (!noIn || !this.match(tt._in))) {
|
if (prec != null && (this.prodParam.hasIn || !this.match(tt._in))) {
|
||||||
if (prec > minPrec) {
|
if (prec > minPrec) {
|
||||||
const op = this.state.type;
|
const op = this.state.type;
|
||||||
if (op === tt.pipeline) {
|
if (op === tt.pipeline) {
|
||||||
@ -391,7 +415,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node.right = this.parseExprOpRightExpr(op, prec, noIn);
|
node.right = this.parseExprOpRightExpr(op, prec);
|
||||||
this.finishNode(
|
this.finishNode(
|
||||||
node,
|
node,
|
||||||
logical || coalesce ? "LogicalExpression" : "BinaryExpression",
|
logical || coalesce ? "LogicalExpression" : "BinaryExpression",
|
||||||
@ -409,13 +433,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
throw this.raise(this.state.start, Errors.MixingCoalesceWithLogical);
|
throw this.raise(this.state.start, Errors.MixingCoalesceWithLogical);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.parseExprOp(
|
return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec);
|
||||||
node,
|
|
||||||
leftStartPos,
|
|
||||||
leftStartLoc,
|
|
||||||
minPrec,
|
|
||||||
noIn,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return left;
|
return left;
|
||||||
@ -424,11 +442,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
// Helper function for `parseExprOp`. Parse the right-hand side of binary-
|
// Helper function for `parseExprOp`. Parse the right-hand side of binary-
|
||||||
// operator expressions, then apply any operator-specific functions.
|
// operator expressions, then apply any operator-specific functions.
|
||||||
|
|
||||||
parseExprOpRightExpr(
|
parseExprOpRightExpr(op: TokenType, prec: number): N.Expression {
|
||||||
op: TokenType,
|
|
||||||
prec: number,
|
|
||||||
noIn: ?boolean,
|
|
||||||
): N.Expression {
|
|
||||||
const startPos = this.state.start;
|
const startPos = this.state.start;
|
||||||
const startLoc = this.state.startLoc;
|
const startLoc = this.state.startLoc;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@ -437,31 +451,27 @@ export default class ExpressionParser extends LValParser {
|
|||||||
case "smart":
|
case "smart":
|
||||||
return this.withTopicPermittingContext(() => {
|
return this.withTopicPermittingContext(() => {
|
||||||
return this.parseSmartPipelineBody(
|
return this.parseSmartPipelineBody(
|
||||||
this.parseExprOpBaseRightExpr(op, prec, noIn),
|
this.parseExprOpBaseRightExpr(op, prec),
|
||||||
startPos,
|
startPos,
|
||||||
startLoc,
|
startLoc,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
case "fsharp":
|
case "fsharp":
|
||||||
return this.withSoloAwaitPermittingContext(() => {
|
return this.withSoloAwaitPermittingContext(() => {
|
||||||
return this.parseFSharpPipelineBody(prec, noIn);
|
return this.parseFSharpPipelineBody(prec);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// falls through
|
// falls through
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return this.parseExprOpBaseRightExpr(op, prec, noIn);
|
return this.parseExprOpBaseRightExpr(op, prec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function for `parseExprOpRightExpr`. Parse the right-hand side of
|
// Helper function for `parseExprOpRightExpr`. Parse the right-hand side of
|
||||||
// binary-operator expressions without applying any operator-specific functions.
|
// binary-operator expressions without applying any operator-specific functions.
|
||||||
|
|
||||||
parseExprOpBaseRightExpr(
|
parseExprOpBaseRightExpr(op: TokenType, prec: number): N.Expression {
|
||||||
op: TokenType,
|
|
||||||
prec: number,
|
|
||||||
noIn: ?boolean,
|
|
||||||
): N.Expression {
|
|
||||||
const startPos = this.state.start;
|
const startPos = this.state.start;
|
||||||
const startLoc = this.state.startLoc;
|
const startLoc = this.state.startLoc;
|
||||||
|
|
||||||
@ -470,7 +480,6 @@ export default class ExpressionParser extends LValParser {
|
|||||||
startPos,
|
startPos,
|
||||||
startLoc,
|
startLoc,
|
||||||
op.rightAssociative ? prec - 1 : prec,
|
op.rightAssociative ? prec - 1 : prec,
|
||||||
noIn,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1415,8 +1424,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
exprList.push(
|
exprList.push(
|
||||||
this.parseMaybeAssign(
|
this.parseMaybeAssignAllowIn(
|
||||||
false,
|
|
||||||
refExpressionErrors,
|
refExpressionErrors,
|
||||||
this.parseParenItem,
|
this.parseParenItem,
|
||||||
refNeedsArrowPos,
|
refNeedsArrowPos,
|
||||||
@ -1858,7 +1866,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
if (this.eat(tt.colon)) {
|
if (this.eat(tt.colon)) {
|
||||||
prop.value = isPattern
|
prop.value = isPattern
|
||||||
? this.parseMaybeDefault(this.state.start, this.state.startLoc)
|
? this.parseMaybeDefault(this.state.start, this.state.startLoc)
|
||||||
: this.parseMaybeAssign(false, refExpressionErrors);
|
: this.parseMaybeAssignAllowIn(refExpressionErrors);
|
||||||
|
|
||||||
return this.finishNode(prop, "ObjectProperty");
|
return this.finishNode(prop, "ObjectProperty");
|
||||||
}
|
}
|
||||||
@ -1932,7 +1940,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
): N.Expression | N.Identifier {
|
): N.Expression | N.Identifier {
|
||||||
if (this.eat(tt.bracketL)) {
|
if (this.eat(tt.bracketL)) {
|
||||||
(prop: $FlowSubtype<N.ObjectOrClassMember>).computed = true;
|
(prop: $FlowSubtype<N.ObjectOrClassMember>).computed = true;
|
||||||
prop.key = this.parseMaybeAssign();
|
prop.key = this.parseMaybeAssignAllowIn();
|
||||||
this.expect(tt.bracketR);
|
this.expect(tt.bracketR);
|
||||||
} else {
|
} else {
|
||||||
const oldInPropertyName = this.state.inPropertyName;
|
const oldInPropertyName = this.state.inPropertyName;
|
||||||
@ -2049,7 +2057,12 @@ export default class ExpressionParser extends LValParser {
|
|||||||
trailingCommaPos: ?number,
|
trailingCommaPos: ?number,
|
||||||
): N.ArrowFunctionExpression {
|
): N.ArrowFunctionExpression {
|
||||||
this.scope.enter(SCOPE_FUNCTION | SCOPE_ARROW);
|
this.scope.enter(SCOPE_FUNCTION | SCOPE_ARROW);
|
||||||
this.prodParam.enter(functionFlags(isAsync, false));
|
let flags = functionFlags(isAsync, false);
|
||||||
|
// ConciseBody and AsyncConciseBody inherit [In]
|
||||||
|
if (!this.match(tt.bracketL) && this.prodParam.hasIn) {
|
||||||
|
flags |= PARAM_IN;
|
||||||
|
}
|
||||||
|
this.prodParam.enter(flags);
|
||||||
this.initFunction(node, isAsync);
|
this.initFunction(node, isAsync);
|
||||||
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
|
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
|
||||||
const oldYieldPos = this.state.yieldPos;
|
const oldYieldPos = this.state.yieldPos;
|
||||||
@ -2102,7 +2115,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
this.state.inParameters = false;
|
this.state.inParameters = false;
|
||||||
|
|
||||||
if (isExpression) {
|
if (isExpression) {
|
||||||
node.body = this.parseMaybeAssign();
|
node.body = this.parseMaybeAssignAllowIn();
|
||||||
this.checkParams(node, false, allowExpression, false);
|
this.checkParams(node, false, allowExpression, false);
|
||||||
} else {
|
} else {
|
||||||
const oldStrict = this.state.strict;
|
const oldStrict = this.state.strict;
|
||||||
@ -2261,8 +2274,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
this.next();
|
this.next();
|
||||||
elt = this.finishNode(node, "ArgumentPlaceholder");
|
elt = this.finishNode(node, "ArgumentPlaceholder");
|
||||||
} else {
|
} else {
|
||||||
elt = this.parseMaybeAssign(
|
elt = this.parseMaybeAssignAllowIn(
|
||||||
false,
|
|
||||||
refExpressionErrors,
|
refExpressionErrors,
|
||||||
this.parseParenItem,
|
this.parseParenItem,
|
||||||
refNeedsArrowPos,
|
refNeedsArrowPos,
|
||||||
@ -2440,7 +2452,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
|
|
||||||
// Parses yield expression inside generator.
|
// Parses yield expression inside generator.
|
||||||
|
|
||||||
parseYield(noIn?: ?boolean): N.YieldExpression {
|
parseYield(): N.YieldExpression {
|
||||||
const node = this.startNode();
|
const node = this.startNode();
|
||||||
|
|
||||||
if (this.state.inParameters) {
|
if (this.state.inParameters) {
|
||||||
@ -2459,7 +2471,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
node.argument = null;
|
node.argument = null;
|
||||||
} else {
|
} else {
|
||||||
node.delegate = this.eat(tt.star);
|
node.delegate = this.eat(tt.star);
|
||||||
node.argument = this.parseMaybeAssign(noIn);
|
node.argument = this.parseMaybeAssign();
|
||||||
}
|
}
|
||||||
return this.finishNode(node, "YieldExpression");
|
return this.finishNode(node, "YieldExpression");
|
||||||
}
|
}
|
||||||
@ -2594,6 +2606,34 @@ export default class ExpressionParser extends LValParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allowInAnd<T>(callback: () => T): T {
|
||||||
|
const flags = this.prodParam.currentFlags();
|
||||||
|
const prodParamToSet = PARAM_IN & ~flags;
|
||||||
|
if (prodParamToSet) {
|
||||||
|
this.prodParam.enter(flags | PARAM_IN);
|
||||||
|
try {
|
||||||
|
return callback();
|
||||||
|
} finally {
|
||||||
|
this.prodParam.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
disallowInAnd<T>(callback: () => T): T {
|
||||||
|
const flags = this.prodParam.currentFlags();
|
||||||
|
const prodParamToClear = PARAM_IN & flags;
|
||||||
|
if (prodParamToClear) {
|
||||||
|
this.prodParam.enter(flags & ~PARAM_IN);
|
||||||
|
try {
|
||||||
|
return callback();
|
||||||
|
} finally {
|
||||||
|
this.prodParam.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
// Register the use of a primary topic reference (`#`) within the current
|
// Register the use of a primary topic reference (`#`) within the current
|
||||||
// topic context.
|
// topic context.
|
||||||
registerTopicReference(): void {
|
registerTopicReference(): void {
|
||||||
@ -2611,7 +2651,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseFSharpPipelineBody(prec: number, noIn: ?boolean): N.Expression {
|
parseFSharpPipelineBody(prec: number): N.Expression {
|
||||||
const startPos = this.state.start;
|
const startPos = this.state.start;
|
||||||
const startLoc = this.state.startLoc;
|
const startLoc = this.state.startLoc;
|
||||||
|
|
||||||
@ -2624,7 +2664,6 @@ export default class ExpressionParser extends LValParser {
|
|||||||
startPos,
|
startPos,
|
||||||
startLoc,
|
startLoc,
|
||||||
prec,
|
prec,
|
||||||
noIn,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody;
|
this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody;
|
||||||
|
|||||||
@ -34,13 +34,12 @@ export default class LValParser extends NodeUtils {
|
|||||||
// Forward-declaration: defined in expression.js
|
// Forward-declaration: defined in expression.js
|
||||||
/*::
|
/*::
|
||||||
+parseIdentifier: (liberal?: boolean) => Identifier;
|
+parseIdentifier: (liberal?: boolean) => Identifier;
|
||||||
+parseMaybeAssign: (
|
+parseMaybeAssignAllowIn: (
|
||||||
noIn?: ?boolean,
|
|
||||||
refExpressionErrors?: ?ExpressionErrors,
|
refExpressionErrors?: ?ExpressionErrors,
|
||||||
afterLeftParse?: Function,
|
afterLeftParse?: Function,
|
||||||
refNeedsArrowPos?: ?Pos,
|
refNeedsArrowPos?: ?Pos,
|
||||||
) => Expression;
|
) => Expression;
|
||||||
+parseObj: <T: ObjectPattern | ObjectExpression>(
|
+parseObjectLike: <T: ObjectPattern | ObjectExpression>(
|
||||||
close: TokenType,
|
close: TokenType,
|
||||||
isPattern: boolean,
|
isPattern: boolean,
|
||||||
isRecord?: ?boolean,
|
isRecord?: ?boolean,
|
||||||
@ -226,8 +225,7 @@ export default class LValParser extends NodeUtils {
|
|||||||
): SpreadElement {
|
): SpreadElement {
|
||||||
const node = this.startNode();
|
const node = this.startNode();
|
||||||
this.next();
|
this.next();
|
||||||
node.argument = this.parseMaybeAssign(
|
node.argument = this.parseMaybeAssignAllowIn(
|
||||||
false,
|
|
||||||
refExpressionErrors,
|
refExpressionErrors,
|
||||||
undefined,
|
undefined,
|
||||||
refNeedsArrowPos,
|
refNeedsArrowPos,
|
||||||
@ -340,7 +338,7 @@ export default class LValParser extends NodeUtils {
|
|||||||
|
|
||||||
const node = this.startNodeAt(startPos, startLoc);
|
const node = this.startNodeAt(startPos, startLoc);
|
||||||
node.left = left;
|
node.left = left;
|
||||||
node.right = this.parseMaybeAssign();
|
node.right = this.parseMaybeAssignAllowIn();
|
||||||
return this.finishNode(node, "AssignmentPattern");
|
return this.finishNode(node, "AssignmentPattern");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -973,7 +973,9 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
node.left = init;
|
node.left = init;
|
||||||
node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign();
|
node.right = isForIn
|
||||||
|
? this.parseExpression()
|
||||||
|
: this.parseMaybeAssignAllowIn();
|
||||||
this.expect(tt.parenR);
|
this.expect(tt.parenR);
|
||||||
|
|
||||||
node.body =
|
node.body =
|
||||||
@ -1005,7 +1007,9 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
const decl = this.startNode();
|
const decl = this.startNode();
|
||||||
this.parseVarId(decl, kind);
|
this.parseVarId(decl, kind);
|
||||||
if (this.eat(tt.eq)) {
|
if (this.eat(tt.eq)) {
|
||||||
decl.init = this.parseMaybeAssign(isFor);
|
decl.init = isFor
|
||||||
|
? this.parseMaybeAssignDisallowIn()
|
||||||
|
: this.parseMaybeAssignAllowIn();
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (
|
||||||
kind === "const" &&
|
kind === "const" &&
|
||||||
@ -1618,10 +1622,9 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
node: N.ClassPrivateProperty,
|
node: N.ClassPrivateProperty,
|
||||||
): N.ClassPrivateProperty {
|
): N.ClassPrivateProperty {
|
||||||
this.scope.enter(SCOPE_CLASS | SCOPE_SUPER);
|
this.scope.enter(SCOPE_CLASS | SCOPE_SUPER);
|
||||||
// [In] production parameter is tracked in parseMaybeAssign
|
|
||||||
this.prodParam.enter(PARAM);
|
this.prodParam.enter(PARAM);
|
||||||
|
|
||||||
node.value = this.eat(tt.eq) ? this.parseMaybeAssign() : null;
|
node.value = this.eat(tt.eq) ? this.parseMaybeAssignAllowIn() : null;
|
||||||
this.semicolon();
|
this.semicolon();
|
||||||
this.prodParam.exit();
|
this.prodParam.exit();
|
||||||
|
|
||||||
@ -1636,13 +1639,12 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.scope.enter(SCOPE_CLASS | SCOPE_SUPER);
|
this.scope.enter(SCOPE_CLASS | SCOPE_SUPER);
|
||||||
// [In] production parameter is tracked in parseMaybeAssign
|
|
||||||
this.prodParam.enter(PARAM);
|
this.prodParam.enter(PARAM);
|
||||||
|
|
||||||
if (this.match(tt.eq)) {
|
if (this.match(tt.eq)) {
|
||||||
this.expectPlugin("classProperties");
|
this.expectPlugin("classProperties");
|
||||||
this.next();
|
this.next();
|
||||||
node.value = this.parseMaybeAssign();
|
node.value = this.parseMaybeAssignAllowIn();
|
||||||
} else {
|
} else {
|
||||||
node.value = null;
|
node.value = null;
|
||||||
}
|
}
|
||||||
@ -1841,7 +1843,7 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
} else if (this.match(tt._const) || this.match(tt._var) || this.isLet()) {
|
} else if (this.match(tt._const) || this.match(tt._var) || this.isLet()) {
|
||||||
throw this.raise(this.state.start, Errors.UnsupportedDefaultExport);
|
throw this.raise(this.state.start, Errors.UnsupportedDefaultExport);
|
||||||
} else {
|
} else {
|
||||||
const res = this.parseMaybeAssign();
|
const res = this.parseMaybeAssignAllowIn();
|
||||||
this.semicolon();
|
this.semicolon();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1816,7 +1816,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
|
|
||||||
parseConditional(
|
parseConditional(
|
||||||
expr: N.Expression,
|
expr: N.Expression,
|
||||||
noIn: ?boolean,
|
|
||||||
startPos: number,
|
startPos: number,
|
||||||
startLoc: Position,
|
startLoc: Position,
|
||||||
refNeedsArrowPos?: ?Pos,
|
refNeedsArrowPos?: ?Pos,
|
||||||
@ -1827,7 +1826,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
// and if we come from inside parens
|
// and if we come from inside parens
|
||||||
if (refNeedsArrowPos) {
|
if (refNeedsArrowPos) {
|
||||||
const result = this.tryParse(() =>
|
const result = this.tryParse(() =>
|
||||||
super.parseConditional(expr, noIn, startPos, startLoc),
|
super.parseConditional(expr, startPos, startLoc),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!result.node) {
|
if (!result.node) {
|
||||||
@ -1886,7 +1885,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
node.test = expr;
|
node.test = expr;
|
||||||
node.consequent = consequent;
|
node.consequent = consequent;
|
||||||
node.alternate = this.forwardNoArrowParamsConversionAt(node, () =>
|
node.alternate = this.forwardNoArrowParamsConversionAt(node, () =>
|
||||||
this.parseMaybeAssign(noIn, undefined, undefined, undefined),
|
this.parseMaybeAssign(undefined, undefined, undefined),
|
||||||
);
|
);
|
||||||
|
|
||||||
return this.finishNode(node, "ConditionalExpression");
|
return this.finishNode(node, "ConditionalExpression");
|
||||||
@ -1898,7 +1897,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
} {
|
} {
|
||||||
this.state.noArrowParamsConversionAt.push(this.state.start);
|
this.state.noArrowParamsConversionAt.push(this.state.start);
|
||||||
|
|
||||||
const consequent = this.parseMaybeAssign();
|
const consequent = this.parseMaybeAssignAllowIn();
|
||||||
const failed = !this.match(tt.colon);
|
const failed = !this.match(tt.colon);
|
||||||
|
|
||||||
this.state.noArrowParamsConversionAt.pop();
|
this.state.noArrowParamsConversionAt.pop();
|
||||||
@ -2632,7 +2631,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
// there
|
// there
|
||||||
// 3. This is neither. Just call the super method
|
// 3. This is neither. Just call the super method
|
||||||
parseMaybeAssign(
|
parseMaybeAssign(
|
||||||
noIn?: ?boolean,
|
|
||||||
refExpressionErrors?: ?ExpressionErrors,
|
refExpressionErrors?: ?ExpressionErrors,
|
||||||
afterLeftParse?: Function,
|
afterLeftParse?: Function,
|
||||||
refNeedsArrowPos?: ?Pos,
|
refNeedsArrowPos?: ?Pos,
|
||||||
@ -2650,7 +2648,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
jsx = this.tryParse(
|
jsx = this.tryParse(
|
||||||
() =>
|
() =>
|
||||||
super.parseMaybeAssign(
|
super.parseMaybeAssign(
|
||||||
noIn,
|
|
||||||
refExpressionErrors,
|
refExpressionErrors,
|
||||||
afterLeftParse,
|
afterLeftParse,
|
||||||
refNeedsArrowPos,
|
refNeedsArrowPos,
|
||||||
@ -2684,7 +2681,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
typeParameters,
|
typeParameters,
|
||||||
() =>
|
() =>
|
||||||
super.parseMaybeAssign(
|
super.parseMaybeAssign(
|
||||||
noIn,
|
|
||||||
refExpressionErrors,
|
refExpressionErrors,
|
||||||
afterLeftParse,
|
afterLeftParse,
|
||||||
refNeedsArrowPos,
|
refNeedsArrowPos,
|
||||||
@ -2730,7 +2726,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
return super.parseMaybeAssign(
|
return super.parseMaybeAssign(
|
||||||
noIn,
|
|
||||||
refExpressionErrors,
|
refExpressionErrors,
|
||||||
afterLeftParse,
|
afterLeftParse,
|
||||||
refNeedsArrowPos,
|
refNeedsArrowPos,
|
||||||
|
|||||||
@ -356,7 +356,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
const node = this.startNode();
|
const node = this.startNode();
|
||||||
if (this.eat(tt.braceL)) {
|
if (this.eat(tt.braceL)) {
|
||||||
this.expect(tt.ellipsis);
|
this.expect(tt.ellipsis);
|
||||||
node.argument = this.parseMaybeAssign();
|
node.argument = this.parseMaybeAssignAllowIn();
|
||||||
this.expect(tt.braceR);
|
this.expect(tt.braceR);
|
||||||
return this.finishNode(node, "JSXSpreadAttribute");
|
return this.finishNode(node, "JSXSpreadAttribute");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1285,7 +1285,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
? this.parseExprAtom()
|
? this.parseExprAtom()
|
||||||
: this.parseIdentifier(/* liberal */ true);
|
: this.parseIdentifier(/* liberal */ true);
|
||||||
if (this.eat(tt.eq)) {
|
if (this.eat(tt.eq)) {
|
||||||
node.initializer = this.parseMaybeAssign();
|
node.initializer = this.parseMaybeAssignAllowIn();
|
||||||
}
|
}
|
||||||
return this.finishNode(node, "TSEnumMember");
|
return this.finishNode(node, "TSEnumMember");
|
||||||
}
|
}
|
||||||
@ -1865,7 +1865,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
leftStartPos: number,
|
leftStartPos: number,
|
||||||
leftStartLoc: Position,
|
leftStartLoc: Position,
|
||||||
minPrec: number,
|
minPrec: number,
|
||||||
noIn: ?boolean,
|
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
nonNull(tt._in.binop) > minPrec &&
|
nonNull(tt._in.binop) > minPrec &&
|
||||||
@ -1886,16 +1885,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
this.finishNode(node, "TSAsExpression");
|
this.finishNode(node, "TSAsExpression");
|
||||||
// rescan `<`, `>` because they were scanned when this.state.inType was true
|
// rescan `<`, `>` because they were scanned when this.state.inType was true
|
||||||
this.reScan_lt_gt();
|
this.reScan_lt_gt();
|
||||||
return this.parseExprOp(
|
return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec);
|
||||||
node,
|
|
||||||
leftStartPos,
|
|
||||||
leftStartLoc,
|
|
||||||
minPrec,
|
|
||||||
noIn,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.parseExprOp(left, leftStartPos, leftStartLoc, minPrec, noIn);
|
return super.parseExprOp(left, leftStartPos, leftStartLoc, minPrec);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkReservedWord(
|
checkReservedWord(
|
||||||
@ -2135,7 +2128,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
// An apparent conditional expression could actually be an optional parameter in an arrow function.
|
// An apparent conditional expression could actually be an optional parameter in an arrow function.
|
||||||
parseConditional(
|
parseConditional(
|
||||||
expr: N.Expression,
|
expr: N.Expression,
|
||||||
noIn: ?boolean,
|
|
||||||
startPos: number,
|
startPos: number,
|
||||||
startLoc: Position,
|
startLoc: Position,
|
||||||
refNeedsArrowPos?: ?Pos,
|
refNeedsArrowPos?: ?Pos,
|
||||||
@ -2145,7 +2137,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
if (!refNeedsArrowPos || !this.match(tt.question)) {
|
if (!refNeedsArrowPos || !this.match(tt.question)) {
|
||||||
return super.parseConditional(
|
return super.parseConditional(
|
||||||
expr,
|
expr,
|
||||||
noIn,
|
|
||||||
startPos,
|
startPos,
|
||||||
startLoc,
|
startLoc,
|
||||||
refNeedsArrowPos,
|
refNeedsArrowPos,
|
||||||
@ -2153,7 +2144,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = this.tryParse(() =>
|
const result = this.tryParse(() =>
|
||||||
super.parseConditional(expr, noIn, startPos, startLoc),
|
super.parseConditional(expr, startPos, startLoc),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!result.node) {
|
if (!result.node) {
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
// @flow
|
// @flow
|
||||||
export const PARAM = 0b000, // Initial Parameter flags
|
export const PARAM = 0b0000, // Initial Parameter flags
|
||||||
PARAM_YIELD = 0b001, // track [Yield] production parameter
|
PARAM_YIELD = 0b0001, // track [Yield] production parameter
|
||||||
PARAM_AWAIT = 0b010, // track [Await] production parameter
|
PARAM_AWAIT = 0b0010, // track [Await] production parameter
|
||||||
PARAM_RETURN = 0b100; // track [Return] production parameter
|
PARAM_RETURN = 0b0100, // track [Return] production parameter
|
||||||
|
PARAM_IN = 0b1000; // track [In] production parameter
|
||||||
|
|
||||||
// ProductionParameterHandler is a stack fashioned production parameter tracker
|
// ProductionParameterHandler is a stack fashioned production parameter tracker
|
||||||
// https://tc39.es/ecma262/#sec-grammar-notation
|
// https://tc39.es/ecma262/#sec-grammar-notation
|
||||||
// The tracked parameters are defined above. Note that the [In] parameter is
|
// The tracked parameters are defined above.
|
||||||
// tracked in `noIn` argument of `parseExpression`.
|
|
||||||
//
|
//
|
||||||
// Whenever [+Await]/[+Yield] appears in the right-hand sides of a production,
|
// Whenever [+Await]/[+Yield] appears in the right-hand sides of a production,
|
||||||
// we must enter a new tracking stack. For example when parsing
|
// we must enter a new tracking stack. For example when parsing
|
||||||
@ -53,6 +53,10 @@ export default class ProductionParameterHandler {
|
|||||||
get hasReturn(): boolean {
|
get hasReturn(): boolean {
|
||||||
return (this.currentFlags() & PARAM_RETURN) > 0;
|
return (this.currentFlags() & PARAM_RETURN) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get hasIn(): boolean {
|
||||||
|
return (this.currentFlags() & PARAM_IN) > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function functionFlags(
|
export function functionFlags(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user