From 310c520fbca17dee7a2b1bc70e1c2d15e381455f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Fri, 7 Aug 2020 16:35:11 -0400 Subject: [PATCH 1/2] refactor: track [In] parameter in prodParam --- .../babel-parser/src/parser/expression.js | 169 +++++++++++------- packages/babel-parser/src/parser/lval.js | 10 +- packages/babel-parser/src/parser/statement.js | 16 +- packages/babel-parser/src/plugins/flow.js | 11 +- .../babel-parser/src/plugins/jsx/index.js | 2 +- .../src/plugins/typescript/index.js | 17 +- .../src/util/production-parameter.js | 16 +- 7 files changed, 135 insertions(+), 106 deletions(-) diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 0fa3849f2f28..9cf2c3c788ef 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -44,6 +44,7 @@ import { import { ExpressionErrors } from "./util"; import { PARAM_AWAIT, + PARAM_IN, PARAM_RETURN, PARAM, functionFlags, @@ -153,11 +154,9 @@ export default class ExpressionParser extends LValParser { // the AST node that the inner parser gave them in another node. // Parse a full expression. - // - `noIn` + // - `disallowIn` // is used to forbid the `in` operator (in for loops initialization expressions) - // When `noIn` 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. + // When `disallowIn` is true, the production parameter [In] is not present. // - `refExpressionErrors ` // 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 // delayed syntax error at correct position). - // https://tc39.es/ecma262/#prod-Expression parseExpression( - noIn?: boolean, + disallowIn?: boolean, refExpressionErrors?: ExpressionErrors, ): 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 startLoc = this.state.startLoc; - const expr = this.parseMaybeAssign(noIn, refExpressionErrors); + const expr = this.parseMaybeAssign(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, refExpressionErrors)); + node.expressions.push(this.parseMaybeAssign(refExpressionErrors)); } this.toReferencedList(node.expressions); return this.finishNode(node, "SequenceExpression"); @@ -185,12 +193,41 @@ export default class ExpressionParser extends LValParser { return expr; } + // Setting [~In] parameter for assignment expression + parseMaybeAssignDisallowIn( + refExpressionErrors?: ?ExpressionErrors, + afterLeftParse?: Function, + refNeedsArrowPos?: ?Pos, + ) { + return this.disallowInAnd(() => + this.parseMaybeAssign( + refExpressionErrors, + afterLeftParse, + refNeedsArrowPos, + ), + ); + } + + // Setting [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 // operators like `+=`. // https://tc39.es/ecma262/#prod-AssignmentExpression parseMaybeAssign( - noIn?: ?boolean, refExpressionErrors?: ?ExpressionErrors, afterLeftParse?: Function, refNeedsArrowPos?: ?Pos, @@ -199,7 +236,7 @@ export default class ExpressionParser extends LValParser { const startLoc = this.state.startLoc; if (this.isContextual("yield")) { if (this.prodParam.hasYield) { - let left = this.parseYield(noIn); + let left = this.parseYield(); if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } @@ -224,7 +261,6 @@ export default class ExpressionParser extends LValParser { } let left = this.parseMaybeConditional( - noIn, refExpressionErrors, refNeedsArrowPos, ); @@ -250,7 +286,7 @@ export default class ExpressionParser extends LValParser { this.checkLVal(left, undefined, undefined, "assignment expression"); this.next(); - node.right = this.parseMaybeAssign(noIn); + node.right = this.parseMaybeAssign(); return this.finishNode(node, "AssignmentExpression"); } else if (ownExpressionErrors) { this.checkExpressionErrors(refExpressionErrors, true); @@ -263,31 +299,23 @@ export default class ExpressionParser extends LValParser { // https://tc39.es/ecma262/#prod-ConditionalExpression parseMaybeConditional( - noIn: ?boolean, 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, refExpressionErrors); + const expr = this.parseExprOps(refExpressionErrors); if (this.shouldExitDescending(expr, potentialArrowAt)) { return expr; } - return this.parseConditional( - expr, - noIn, - startPos, - startLoc, - refNeedsArrowPos, - ); + return this.parseConditional(expr, startPos, startLoc, refNeedsArrowPos); } parseConditional( expr: N.Expression, - noIn: ?boolean, startPos: number, startLoc: Position, // 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)) { const node = this.startNodeAt(startPos, startLoc); node.test = expr; - node.consequent = this.parseMaybeAssign(); + node.consequent = this.parseMaybeAssignAllowIn(); this.expect(tt.colon); - node.alternate = this.parseMaybeAssign(noIn); + node.alternate = this.parseMaybeAssign(); return this.finishNode(node, "ConditionalExpression"); } return expr; @@ -308,10 +336,7 @@ export default class ExpressionParser extends LValParser { // Start the precedence parser. // https://tc39.es/ecma262/#prod-ShortCircuitExpression - parseExprOps( - noIn: ?boolean, - refExpressionErrors: ExpressionErrors, - ): N.Expression { + parseExprOps(refExpressionErrors: ExpressionErrors): N.Expression { const startPos = this.state.start; const startLoc = this.state.startLoc; const potentialArrowAt = this.state.potentialArrowAt; @@ -321,7 +346,7 @@ export default class ExpressionParser extends LValParser { 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 @@ -335,10 +360,9 @@ export default class ExpressionParser extends LValParser { leftStartPos: number, leftStartLoc: Position, minPrec: number, - noIn: ?boolean, ): N.Expression { 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) { const op = this.state.type; 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( node, logical || coalesce ? "LogicalExpression" : "BinaryExpression", @@ -409,13 +433,7 @@ export default class ExpressionParser extends LValParser { throw this.raise(this.state.start, Errors.MixingCoalesceWithLogical); } - return this.parseExprOp( - node, - leftStartPos, - leftStartLoc, - minPrec, - noIn, - ); + return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec); } } return left; @@ -424,11 +442,7 @@ export default class ExpressionParser extends LValParser { // Helper function for `parseExprOp`. Parse the right-hand side of binary- // operator expressions, then apply any operator-specific functions. - parseExprOpRightExpr( - op: TokenType, - prec: number, - noIn: ?boolean, - ): N.Expression { + parseExprOpRightExpr(op: TokenType, prec: number): N.Expression { const startPos = this.state.start; const startLoc = this.state.startLoc; switch (op) { @@ -437,31 +451,27 @@ export default class ExpressionParser extends LValParser { case "smart": return this.withTopicPermittingContext(() => { return this.parseSmartPipelineBody( - this.parseExprOpBaseRightExpr(op, prec, noIn), + this.parseExprOpBaseRightExpr(op, prec), startPos, startLoc, ); }); case "fsharp": return this.withSoloAwaitPermittingContext(() => { - return this.parseFSharpPipelineBody(prec, noIn); + return this.parseFSharpPipelineBody(prec); }); } // falls through default: - return this.parseExprOpBaseRightExpr(op, prec, noIn); + return this.parseExprOpBaseRightExpr(op, prec); } } // Helper function for `parseExprOpRightExpr`. Parse the right-hand side of // binary-operator expressions without applying any operator-specific functions. - parseExprOpBaseRightExpr( - op: TokenType, - prec: number, - noIn: ?boolean, - ): N.Expression { + parseExprOpBaseRightExpr(op: TokenType, prec: number): N.Expression { const startPos = this.state.start; const startLoc = this.state.startLoc; @@ -470,7 +480,6 @@ export default class ExpressionParser extends LValParser { startPos, startLoc, op.rightAssociative ? prec - 1 : prec, - noIn, ); } @@ -1415,8 +1424,7 @@ export default class ExpressionParser extends LValParser { break; } else { exprList.push( - this.parseMaybeAssign( - false, + this.parseMaybeAssignAllowIn( refExpressionErrors, this.parseParenItem, refNeedsArrowPos, @@ -1858,7 +1866,7 @@ export default class ExpressionParser extends LValParser { if (this.eat(tt.colon)) { prop.value = isPattern ? this.parseMaybeDefault(this.state.start, this.state.startLoc) - : this.parseMaybeAssign(false, refExpressionErrors); + : this.parseMaybeAssignAllowIn(refExpressionErrors); return this.finishNode(prop, "ObjectProperty"); } @@ -1932,7 +1940,7 @@ export default class ExpressionParser extends LValParser { ): N.Expression | N.Identifier { if (this.eat(tt.bracketL)) { (prop: $FlowSubtype).computed = true; - prop.key = this.parseMaybeAssign(); + prop.key = this.parseMaybeAssignAllowIn(); this.expect(tt.bracketR); } else { const oldInPropertyName = this.state.inPropertyName; @@ -2049,7 +2057,12 @@ export default class ExpressionParser extends LValParser { trailingCommaPos: ?number, ): N.ArrowFunctionExpression { 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); const oldMaybeInArrowParameters = this.state.maybeInArrowParameters; const oldYieldPos = this.state.yieldPos; @@ -2102,7 +2115,7 @@ export default class ExpressionParser extends LValParser { this.state.inParameters = false; if (isExpression) { - node.body = this.parseMaybeAssign(); + node.body = this.parseMaybeAssignAllowIn(); this.checkParams(node, false, allowExpression, false); } else { const oldStrict = this.state.strict; @@ -2261,8 +2274,7 @@ export default class ExpressionParser extends LValParser { this.next(); elt = this.finishNode(node, "ArgumentPlaceholder"); } else { - elt = this.parseMaybeAssign( - false, + elt = this.parseMaybeAssignAllowIn( refExpressionErrors, this.parseParenItem, refNeedsArrowPos, @@ -2440,7 +2452,7 @@ export default class ExpressionParser extends LValParser { // Parses yield expression inside generator. - parseYield(noIn?: ?boolean): N.YieldExpression { + parseYield(): N.YieldExpression { const node = this.startNode(); if (this.state.inParameters) { @@ -2459,7 +2471,7 @@ export default class ExpressionParser extends LValParser { node.argument = null; } else { node.delegate = this.eat(tt.star); - node.argument = this.parseMaybeAssign(noIn); + node.argument = this.parseMaybeAssign(); } return this.finishNode(node, "YieldExpression"); } @@ -2594,6 +2606,34 @@ export default class ExpressionParser extends LValParser { } } + allowInAnd(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(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 // topic context. 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 startLoc = this.state.startLoc; @@ -2624,7 +2664,6 @@ export default class ExpressionParser extends LValParser { startPos, startLoc, prec, - noIn, ); this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody; diff --git a/packages/babel-parser/src/parser/lval.js b/packages/babel-parser/src/parser/lval.js index d286259fa24f..42c094b76203 100644 --- a/packages/babel-parser/src/parser/lval.js +++ b/packages/babel-parser/src/parser/lval.js @@ -34,13 +34,12 @@ export default class LValParser extends NodeUtils { // Forward-declaration: defined in expression.js /*:: +parseIdentifier: (liberal?: boolean) => Identifier; - +parseMaybeAssign: ( - noIn?: ?boolean, + +parseMaybeAssignAllowIn: ( refExpressionErrors?: ?ExpressionErrors, afterLeftParse?: Function, refNeedsArrowPos?: ?Pos, ) => Expression; - +parseObj: ( + +parseObjectLike: ( close: TokenType, isPattern: boolean, isRecord?: ?boolean, @@ -226,8 +225,7 @@ export default class LValParser extends NodeUtils { ): SpreadElement { const node = this.startNode(); this.next(); - node.argument = this.parseMaybeAssign( - false, + node.argument = this.parseMaybeAssignAllowIn( refExpressionErrors, undefined, refNeedsArrowPos, @@ -340,7 +338,7 @@ export default class LValParser extends NodeUtils { const node = this.startNodeAt(startPos, startLoc); node.left = left; - node.right = this.parseMaybeAssign(); + node.right = this.parseMaybeAssignAllowIn(); return this.finishNode(node, "AssignmentPattern"); } diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 732214851535..28cd5d97fe39 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -973,7 +973,9 @@ export default class StatementParser extends ExpressionParser { } node.left = init; - node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign(); + node.right = isForIn + ? this.parseExpression() + : this.parseMaybeAssignAllowIn(); this.expect(tt.parenR); node.body = @@ -1005,7 +1007,9 @@ export default class StatementParser extends ExpressionParser { const decl = this.startNode(); this.parseVarId(decl, kind); if (this.eat(tt.eq)) { - decl.init = this.parseMaybeAssign(isFor); + decl.init = isFor + ? this.parseMaybeAssignDisallowIn() + : this.parseMaybeAssignAllowIn(); } else { if ( kind === "const" && @@ -1618,10 +1622,9 @@ export default class StatementParser extends ExpressionParser { node: N.ClassPrivateProperty, ): N.ClassPrivateProperty { this.scope.enter(SCOPE_CLASS | SCOPE_SUPER); - // [In] production parameter is tracked in parseMaybeAssign 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.prodParam.exit(); @@ -1636,13 +1639,12 @@ export default class StatementParser extends ExpressionParser { } this.scope.enter(SCOPE_CLASS | SCOPE_SUPER); - // [In] production parameter is tracked in parseMaybeAssign this.prodParam.enter(PARAM); if (this.match(tt.eq)) { this.expectPlugin("classProperties"); this.next(); - node.value = this.parseMaybeAssign(); + node.value = this.parseMaybeAssignAllowIn(); } else { 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()) { throw this.raise(this.state.start, Errors.UnsupportedDefaultExport); } else { - const res = this.parseMaybeAssign(); + const res = this.parseMaybeAssignAllowIn(); this.semicolon(); return res; } diff --git a/packages/babel-parser/src/plugins/flow.js b/packages/babel-parser/src/plugins/flow.js index 1887cfa68a60..20d09c4d22dc 100644 --- a/packages/babel-parser/src/plugins/flow.js +++ b/packages/babel-parser/src/plugins/flow.js @@ -1816,7 +1816,6 @@ export default (superClass: Class): Class => parseConditional( expr: N.Expression, - noIn: ?boolean, startPos: number, startLoc: Position, refNeedsArrowPos?: ?Pos, @@ -1827,7 +1826,7 @@ export default (superClass: Class): Class => // and if we come from inside parens if (refNeedsArrowPos) { const result = this.tryParse(() => - super.parseConditional(expr, noIn, startPos, startLoc), + super.parseConditional(expr, startPos, startLoc), ); if (!result.node) { @@ -1886,7 +1885,7 @@ export default (superClass: Class): Class => node.test = expr; node.consequent = consequent; node.alternate = this.forwardNoArrowParamsConversionAt(node, () => - this.parseMaybeAssign(noIn, undefined, undefined, undefined), + this.parseMaybeAssign(undefined, undefined, undefined), ); return this.finishNode(node, "ConditionalExpression"); @@ -1898,7 +1897,7 @@ export default (superClass: Class): Class => } { this.state.noArrowParamsConversionAt.push(this.state.start); - const consequent = this.parseMaybeAssign(); + const consequent = this.parseMaybeAssignAllowIn(); const failed = !this.match(tt.colon); this.state.noArrowParamsConversionAt.pop(); @@ -2632,7 +2631,6 @@ export default (superClass: Class): Class => // there // 3. This is neither. Just call the super method parseMaybeAssign( - noIn?: ?boolean, refExpressionErrors?: ?ExpressionErrors, afterLeftParse?: Function, refNeedsArrowPos?: ?Pos, @@ -2650,7 +2648,6 @@ export default (superClass: Class): Class => jsx = this.tryParse( () => super.parseMaybeAssign( - noIn, refExpressionErrors, afterLeftParse, refNeedsArrowPos, @@ -2684,7 +2681,6 @@ export default (superClass: Class): Class => typeParameters, () => super.parseMaybeAssign( - noIn, refExpressionErrors, afterLeftParse, refNeedsArrowPos, @@ -2730,7 +2726,6 @@ export default (superClass: Class): Class => } return super.parseMaybeAssign( - noIn, refExpressionErrors, afterLeftParse, refNeedsArrowPos, diff --git a/packages/babel-parser/src/plugins/jsx/index.js b/packages/babel-parser/src/plugins/jsx/index.js index c8a44b1f78e3..923223b97601 100644 --- a/packages/babel-parser/src/plugins/jsx/index.js +++ b/packages/babel-parser/src/plugins/jsx/index.js @@ -356,7 +356,7 @@ export default (superClass: Class): Class => const node = this.startNode(); if (this.eat(tt.braceL)) { this.expect(tt.ellipsis); - node.argument = this.parseMaybeAssign(); + node.argument = this.parseMaybeAssignAllowIn(); this.expect(tt.braceR); return this.finishNode(node, "JSXSpreadAttribute"); } diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index a101638448e0..1b8c80eac6c5 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -1285,7 +1285,7 @@ export default (superClass: Class): Class => ? this.parseExprAtom() : this.parseIdentifier(/* liberal */ true); if (this.eat(tt.eq)) { - node.initializer = this.parseMaybeAssign(); + node.initializer = this.parseMaybeAssignAllowIn(); } return this.finishNode(node, "TSEnumMember"); } @@ -1865,7 +1865,6 @@ export default (superClass: Class): Class => leftStartPos: number, leftStartLoc: Position, minPrec: number, - noIn: ?boolean, ) { if ( nonNull(tt._in.binop) > minPrec && @@ -1886,16 +1885,10 @@ export default (superClass: Class): Class => this.finishNode(node, "TSAsExpression"); // rescan `<`, `>` because they were scanned when this.state.inType was true this.reScan_lt_gt(); - return this.parseExprOp( - node, - leftStartPos, - leftStartLoc, - minPrec, - noIn, - ); + return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec); } - return super.parseExprOp(left, leftStartPos, leftStartLoc, minPrec, noIn); + return super.parseExprOp(left, leftStartPos, leftStartLoc, minPrec); } checkReservedWord( @@ -2135,7 +2128,6 @@ export default (superClass: Class): Class => // An apparent conditional expression could actually be an optional parameter in an arrow function. parseConditional( expr: N.Expression, - noIn: ?boolean, startPos: number, startLoc: Position, refNeedsArrowPos?: ?Pos, @@ -2145,7 +2137,6 @@ export default (superClass: Class): Class => if (!refNeedsArrowPos || !this.match(tt.question)) { return super.parseConditional( expr, - noIn, startPos, startLoc, refNeedsArrowPos, @@ -2153,7 +2144,7 @@ export default (superClass: Class): Class => } const result = this.tryParse(() => - super.parseConditional(expr, noIn, startPos, startLoc), + super.parseConditional(expr, startPos, startLoc), ); if (!result.node) { diff --git a/packages/babel-parser/src/util/production-parameter.js b/packages/babel-parser/src/util/production-parameter.js index 43644f6131ce..feaf6a960d40 100644 --- a/packages/babel-parser/src/util/production-parameter.js +++ b/packages/babel-parser/src/util/production-parameter.js @@ -1,13 +1,13 @@ // @flow -export const PARAM = 0b000, // Initial Parameter flags - PARAM_YIELD = 0b001, // track [Yield] production parameter - PARAM_AWAIT = 0b010, // track [Await] production parameter - PARAM_RETURN = 0b100; // track [Return] production parameter +export const PARAM = 0b0000, // Initial Parameter flags + PARAM_YIELD = 0b0001, // track [Yield] production parameter + PARAM_AWAIT = 0b0010, // track [Await] production parameter + PARAM_RETURN = 0b0100, // track [Return] production parameter + PARAM_IN = 0b1000; // track [In] production parameter // ProductionParameterHandler is a stack fashioned production parameter tracker // https://tc39.es/ecma262/#sec-grammar-notation -// The tracked parameters are defined above. Note that the [In] parameter is -// tracked in `noIn` argument of `parseExpression`. +// The tracked parameters are defined above. // // Whenever [+Await]/[+Yield] appears in the right-hand sides of a production, // we must enter a new tracking stack. For example when parsing @@ -53,6 +53,10 @@ export default class ProductionParameterHandler { get hasReturn(): boolean { return (this.currentFlags() & PARAM_RETURN) > 0; } + + get hasIn(): boolean { + return (this.currentFlags() & PARAM_IN) > 0; + } } export function functionFlags( From 3547b55f43bc05a7f282b64535983b28962f5a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Sat, 8 Aug 2020 16:23:58 -0400 Subject: [PATCH 2/2] Apply suggestions from code review --- packages/babel-parser/src/parser/expression.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 9cf2c3c788ef..74d09fd8a05f 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -193,7 +193,7 @@ export default class ExpressionParser extends LValParser { return expr; } - // Setting [~In] parameter for assignment expression + // Set [~In] parameter for assignment expression parseMaybeAssignDisallowIn( refExpressionErrors?: ?ExpressionErrors, afterLeftParse?: Function, @@ -208,7 +208,7 @@ export default class ExpressionParser extends LValParser { ); } - // Setting [In] parameter for assignment expression + // Set [+In] parameter for assignment expression parseMaybeAssignAllowIn( refExpressionErrors?: ?ExpressionErrors, afterLeftParse?: Function,