From 18596690b3bcf9a50557bc92db985e8b5198ece4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Fri, 19 Nov 2021 11:49:19 -0500 Subject: [PATCH] add tokenIsTemplate --- .../babel-parser/src/parser/expression.js | 27 ++++++++++--------- packages/babel-parser/src/parser/statement.js | 3 ++- .../src/plugins/typescript/index.js | 6 ++--- packages/babel-parser/src/tokenizer/types.js | 6 +++++ 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index eb956a83987c..abba6101bf0f 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -27,6 +27,7 @@ import { tokenIsPostfix, tokenIsPrefix, tokenIsRightAssociative, + tokenIsTemplate, tokenKeywordOrIdentifierIsKeyword, tokenLabelName, tokenOperatorPrecedence, @@ -706,9 +707,10 @@ export default class ExpressionParser extends LValParser { noCalls: ?boolean, state: N.ParseSubscriptState, ): N.Expression { - if (!noCalls && this.eat(tt.doubleColon)) { + const { type } = this.state; + if (!noCalls && type === tt.doubleColon) { return this.parseBind(base, startPos, startLoc, noCalls, state); - } else if (this.match(tt.templateNonTail) || this.match(tt.templateTail)) { + } else if (tokenIsTemplate(type)) { return this.parseTaggedTemplateExpression( base, startPos, @@ -719,7 +721,7 @@ export default class ExpressionParser extends LValParser { let optional = false; - if (this.match(tt.questionDot)) { + if (type === tt.questionDot) { if (noCalls && this.lookaheadCharCode() === charCodes.leftParenthesis) { // stop at `?.` when parsing `new a?.()` state.stop = true; @@ -801,6 +803,7 @@ export default class ExpressionParser extends LValParser { ): N.Expression { const node = this.startNodeAt(startPos, startLoc); node.object = base; + this.next(); // eat '::' node.callee = this.parseNoCallExpr(); state.stop = true; return this.parseSubscripts( @@ -2691,22 +2694,22 @@ export default class ExpressionParser extends LValParser { } isAmbiguousAwait(): boolean { + if (this.hasPrecedingLineBreak()) return true; + const { type } = this.state; return ( - this.hasPrecedingLineBreak() || // All the following expressions are ambiguous: // await + 0, await - 0, await ( 0 ), await [ 0 ], await / 0 /u, await `` - this.match(tt.plusMin) || - this.match(tt.parenL) || - this.match(tt.bracketL) || - this.match(tt.templateNonTail) || - this.match(tt.templateTail) || + type === tt.plusMin || + type === tt.parenL || + type === tt.bracketL || + tokenIsTemplate(type) || // Sometimes the tokenizer generates tt.slash for regexps, and this is // handler by parseExprAtom - this.match(tt.regexp) || - this.match(tt.slash) || + type === tt.regexp || + type === tt.slash || // This code could be parsed both as a modulo operator or as an intrinsic: // await %x(0) - (this.hasPlugin("v8intrinsic") && this.match(tt.modulo)) + (this.hasPlugin("v8intrinsic") && type === tt.modulo) ); } diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index fb76dea08504..2b02804400f9 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -4,6 +4,7 @@ import * as N from "../types"; import { tokenIsIdentifier, tokenIsLoop, + tokenIsTemplate, tt, type TokenType, getExportedToken, @@ -96,7 +97,7 @@ function babel7CompatTokens(tokens) { continue; } } - if (type === tt.templateNonTail || type === tt.templateTail) { + if (tokenIsTemplate(type)) { if (!process.env.BABEL_8_BREAKING) { const { loc, start, value, end } = token; const backquoteEnd = start + 1; diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index 2129fc8f967b..8fb93cddda71 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -14,6 +14,7 @@ import { tokenIsKeywordOrIdentifier, tt, type TokenType, + tokenIsTemplate, } from "../../tokenizer/types"; import { types as tc } from "../../tokenizer/context"; import * as N from "../../types"; @@ -2197,10 +2198,7 @@ export default (superClass: Class): Class => } return this.finishCallExpression(node, state.optionalChainMember); - } else if ( - this.match(tt.templateNonTail) || - this.match(tt.templateTail) - ) { + } else if (tokenIsTemplate(this.state.type)) { const result = this.parseTaggedTemplateExpression( base, startPos, diff --git a/packages/babel-parser/src/tokenizer/types.js b/packages/babel-parser/src/tokenizer/types.js index 0d2606063c8b..7e3744f0da87 100644 --- a/packages/babel-parser/src/tokenizer/types.js +++ b/packages/babel-parser/src/tokenizer/types.js @@ -158,8 +158,10 @@ export const tt: { [name: string]: TokenType } = { ellipsis: createToken("...", { beforeExpr }), backQuote: createToken("`", { startsExpr }), dollarBraceL: createToken("${", { beforeExpr, startsExpr }), + // start: isTemplate templateTail: createToken("...`", { startsExpr }), templateNonTail: createToken("...${", { beforeExpr, startsExpr }), + // end: isTemplate at: createToken("@"), hash: createToken("#", { startsExpr }), @@ -404,6 +406,10 @@ export function tokenIsRightAssociative(token: TokenType): boolean { return token === tt.exponent; } +export function tokenIsTemplate(token: TokenType): boolean { + return token >= tt.templateTail && token <= tt.templateNonTail; +} + export function getExportedToken(token: TokenType): ExportedTokenType { return tokenTypes[token]; }