diff options
| author | Philipp Tanlak <philipp.tanlak@gmail.com> | 2025-11-24 20:54:57 +0100 |
|---|---|---|
| committer | Philipp Tanlak <philipp.tanlak@gmail.com> | 2025-11-24 20:57:48 +0100 |
| commit | b1e2c8fd5cb5dfa46bc440a12eafaf56cd844b1c (patch) | |
| tree | 49d360fd6cbc6a2754efe93524ac47ff0fbe0f7d /node_modules/sucrase/dist/esm/parser | |
Docs
Diffstat (limited to 'node_modules/sucrase/dist/esm/parser')
21 files changed, 8554 insertions, 0 deletions
diff --git a/node_modules/sucrase/dist/esm/parser/index.js b/node_modules/sucrase/dist/esm/parser/index.js new file mode 100644 index 0000000..5074ae4 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/index.js @@ -0,0 +1,31 @@ + + +import {augmentError, initParser, state} from "./traverser/base"; +import {parseFile} from "./traverser/index"; + +export class File { + + + + constructor(tokens, scopes) { + this.tokens = tokens; + this.scopes = scopes; + } +} + +export function parse( + input, + isJSXEnabled, + isTypeScriptEnabled, + isFlowEnabled, +) { + if (isFlowEnabled && isTypeScriptEnabled) { + throw new Error("Cannot combine flow and typescript plugins."); + } + initParser(input, isJSXEnabled, isTypeScriptEnabled, isFlowEnabled); + const result = parseFile(); + if (state.error) { + throw augmentError(state.error); + } + return result; +} diff --git a/node_modules/sucrase/dist/esm/parser/plugins/flow.js b/node_modules/sucrase/dist/esm/parser/plugins/flow.js new file mode 100644 index 0000000..66295d1 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/plugins/flow.js @@ -0,0 +1,1105 @@ +/* eslint max-len: 0 */ + +import { + eat, + lookaheadType, + lookaheadTypeAndKeyword, + match, + next, + popTypeContext, + pushTypeContext, + +} from "../tokenizer/index"; +import {ContextualKeyword} from "../tokenizer/keywords"; +import {TokenType, TokenType as tt} from "../tokenizer/types"; +import {input, state} from "../traverser/base"; +import { + baseParseMaybeAssign, + baseParseSubscript, + baseParseSubscripts, + parseArrow, + parseArrowExpression, + parseCallExpressionArguments, + parseExprAtom, + parseExpression, + parseFunctionBody, + parseIdentifier, + parseLiteral, + +} from "../traverser/expression"; +import { + baseParseExportStar, + parseExport, + parseExportFrom, + parseExportSpecifiers, + parseFunctionParams, + parseImport, + parseStatement, +} from "../traverser/statement"; +import { + canInsertSemicolon, + eatContextual, + expect, + expectContextual, + isContextual, + isLookaheadContextual, + semicolon, + unexpected, +} from "../traverser/util"; + +function isMaybeDefaultImport(lookahead) { + return ( + (lookahead.type === tt.name || !!(lookahead.type & TokenType.IS_KEYWORD)) && + lookahead.contextualKeyword !== ContextualKeyword._from + ); +} + +function flowParseTypeInitialiser(tok) { + const oldIsType = pushTypeContext(0); + expect(tok || tt.colon); + flowParseType(); + popTypeContext(oldIsType); +} + +function flowParsePredicate() { + expect(tt.modulo); + expectContextual(ContextualKeyword._checks); + if (eat(tt.parenL)) { + parseExpression(); + expect(tt.parenR); + } +} + +function flowParseTypeAndPredicateInitialiser() { + const oldIsType = pushTypeContext(0); + expect(tt.colon); + if (match(tt.modulo)) { + flowParsePredicate(); + } else { + flowParseType(); + if (match(tt.modulo)) { + flowParsePredicate(); + } + } + popTypeContext(oldIsType); +} + +function flowParseDeclareClass() { + next(); + flowParseInterfaceish(/* isClass */ true); +} + +function flowParseDeclareFunction() { + next(); + parseIdentifier(); + + if (match(tt.lessThan)) { + flowParseTypeParameterDeclaration(); + } + + expect(tt.parenL); + flowParseFunctionTypeParams(); + expect(tt.parenR); + + flowParseTypeAndPredicateInitialiser(); + + semicolon(); +} + +function flowParseDeclare() { + if (match(tt._class)) { + flowParseDeclareClass(); + } else if (match(tt._function)) { + flowParseDeclareFunction(); + } else if (match(tt._var)) { + flowParseDeclareVariable(); + } else if (eatContextual(ContextualKeyword._module)) { + if (eat(tt.dot)) { + flowParseDeclareModuleExports(); + } else { + flowParseDeclareModule(); + } + } else if (isContextual(ContextualKeyword._type)) { + flowParseDeclareTypeAlias(); + } else if (isContextual(ContextualKeyword._opaque)) { + flowParseDeclareOpaqueType(); + } else if (isContextual(ContextualKeyword._interface)) { + flowParseDeclareInterface(); + } else if (match(tt._export)) { + flowParseDeclareExportDeclaration(); + } else { + unexpected(); + } +} + +function flowParseDeclareVariable() { + next(); + flowParseTypeAnnotatableIdentifier(); + semicolon(); +} + +function flowParseDeclareModule() { + if (match(tt.string)) { + parseExprAtom(); + } else { + parseIdentifier(); + } + + expect(tt.braceL); + while (!match(tt.braceR) && !state.error) { + if (match(tt._import)) { + next(); + parseImport(); + } else { + unexpected(); + } + } + expect(tt.braceR); +} + +function flowParseDeclareExportDeclaration() { + expect(tt._export); + + if (eat(tt._default)) { + if (match(tt._function) || match(tt._class)) { + // declare export default class ... + // declare export default function ... + flowParseDeclare(); + } else { + // declare export default [type]; + flowParseType(); + semicolon(); + } + } else if ( + match(tt._var) || // declare export var ... + match(tt._function) || // declare export function ... + match(tt._class) || // declare export class ... + isContextual(ContextualKeyword._opaque) // declare export opaque .. + ) { + flowParseDeclare(); + } else if ( + match(tt.star) || // declare export * from '' + match(tt.braceL) || // declare export {} ... + isContextual(ContextualKeyword._interface) || // declare export interface ... + isContextual(ContextualKeyword._type) || // declare export type ... + isContextual(ContextualKeyword._opaque) // declare export opaque type ... + ) { + parseExport(); + } else { + unexpected(); + } +} + +function flowParseDeclareModuleExports() { + expectContextual(ContextualKeyword._exports); + flowParseTypeAnnotation(); + semicolon(); +} + +function flowParseDeclareTypeAlias() { + next(); + flowParseTypeAlias(); +} + +function flowParseDeclareOpaqueType() { + next(); + flowParseOpaqueType(true); +} + +function flowParseDeclareInterface() { + next(); + flowParseInterfaceish(); +} + +// Interfaces + +function flowParseInterfaceish(isClass = false) { + flowParseRestrictedIdentifier(); + + if (match(tt.lessThan)) { + flowParseTypeParameterDeclaration(); + } + + if (eat(tt._extends)) { + do { + flowParseInterfaceExtends(); + } while (!isClass && eat(tt.comma)); + } + + if (isContextual(ContextualKeyword._mixins)) { + next(); + do { + flowParseInterfaceExtends(); + } while (eat(tt.comma)); + } + + if (isContextual(ContextualKeyword._implements)) { + next(); + do { + flowParseInterfaceExtends(); + } while (eat(tt.comma)); + } + + flowParseObjectType(isClass, false, isClass); +} + +function flowParseInterfaceExtends() { + flowParseQualifiedTypeIdentifier(false); + if (match(tt.lessThan)) { + flowParseTypeParameterInstantiation(); + } +} + +function flowParseInterface() { + flowParseInterfaceish(); +} + +function flowParseRestrictedIdentifier() { + parseIdentifier(); +} + +function flowParseTypeAlias() { + flowParseRestrictedIdentifier(); + + if (match(tt.lessThan)) { + flowParseTypeParameterDeclaration(); + } + + flowParseTypeInitialiser(tt.eq); + semicolon(); +} + +function flowParseOpaqueType(declare) { + expectContextual(ContextualKeyword._type); + flowParseRestrictedIdentifier(); + + if (match(tt.lessThan)) { + flowParseTypeParameterDeclaration(); + } + + // Parse the supertype + if (match(tt.colon)) { + flowParseTypeInitialiser(tt.colon); + } + + if (!declare) { + flowParseTypeInitialiser(tt.eq); + } + semicolon(); +} + +function flowParseTypeParameter() { + flowParseVariance(); + flowParseTypeAnnotatableIdentifier(); + + if (eat(tt.eq)) { + flowParseType(); + } +} + +export function flowParseTypeParameterDeclaration() { + const oldIsType = pushTypeContext(0); + // istanbul ignore else: this condition is already checked at all call sites + if (match(tt.lessThan) || match(tt.typeParameterStart)) { + next(); + } else { + unexpected(); + } + + do { + flowParseTypeParameter(); + if (!match(tt.greaterThan)) { + expect(tt.comma); + } + } while (!match(tt.greaterThan) && !state.error); + expect(tt.greaterThan); + popTypeContext(oldIsType); +} + +function flowParseTypeParameterInstantiation() { + const oldIsType = pushTypeContext(0); + expect(tt.lessThan); + while (!match(tt.greaterThan) && !state.error) { + flowParseType(); + if (!match(tt.greaterThan)) { + expect(tt.comma); + } + } + expect(tt.greaterThan); + popTypeContext(oldIsType); +} + +function flowParseInterfaceType() { + expectContextual(ContextualKeyword._interface); + if (eat(tt._extends)) { + do { + flowParseInterfaceExtends(); + } while (eat(tt.comma)); + } + flowParseObjectType(false, false, false); +} + +function flowParseObjectPropertyKey() { + if (match(tt.num) || match(tt.string)) { + parseExprAtom(); + } else { + parseIdentifier(); + } +} + +function flowParseObjectTypeIndexer() { + // Note: bracketL has already been consumed + if (lookaheadType() === tt.colon) { + flowParseObjectPropertyKey(); + flowParseTypeInitialiser(); + } else { + flowParseType(); + } + expect(tt.bracketR); + flowParseTypeInitialiser(); +} + +function flowParseObjectTypeInternalSlot() { + // Note: both bracketL have already been consumed + flowParseObjectPropertyKey(); + expect(tt.bracketR); + expect(tt.bracketR); + if (match(tt.lessThan) || match(tt.parenL)) { + flowParseObjectTypeMethodish(); + } else { + eat(tt.question); + flowParseTypeInitialiser(); + } +} + +function flowParseObjectTypeMethodish() { + if (match(tt.lessThan)) { + flowParseTypeParameterDeclaration(); + } + + expect(tt.parenL); + while (!match(tt.parenR) && !match(tt.ellipsis) && !state.error) { + flowParseFunctionTypeParam(); + if (!match(tt.parenR)) { + expect(tt.comma); + } + } + + if (eat(tt.ellipsis)) { + flowParseFunctionTypeParam(); + } + expect(tt.parenR); + flowParseTypeInitialiser(); +} + +function flowParseObjectTypeCallProperty() { + flowParseObjectTypeMethodish(); +} + +function flowParseObjectType(allowStatic, allowExact, allowProto) { + let endDelim; + if (allowExact && match(tt.braceBarL)) { + expect(tt.braceBarL); + endDelim = tt.braceBarR; + } else { + expect(tt.braceL); + endDelim = tt.braceR; + } + + while (!match(endDelim) && !state.error) { + if (allowProto && isContextual(ContextualKeyword._proto)) { + const lookahead = lookaheadType(); + if (lookahead !== tt.colon && lookahead !== tt.question) { + next(); + allowStatic = false; + } + } + if (allowStatic && isContextual(ContextualKeyword._static)) { + const lookahead = lookaheadType(); + if (lookahead !== tt.colon && lookahead !== tt.question) { + next(); + } + } + + flowParseVariance(); + + if (eat(tt.bracketL)) { + if (eat(tt.bracketL)) { + flowParseObjectTypeInternalSlot(); + } else { + flowParseObjectTypeIndexer(); + } + } else if (match(tt.parenL) || match(tt.lessThan)) { + flowParseObjectTypeCallProperty(); + } else { + if (isContextual(ContextualKeyword._get) || isContextual(ContextualKeyword._set)) { + const lookahead = lookaheadType(); + if (lookahead === tt.name || lookahead === tt.string || lookahead === tt.num) { + next(); + } + } + + flowParseObjectTypeProperty(); + } + + flowObjectTypeSemicolon(); + } + + expect(endDelim); +} + +function flowParseObjectTypeProperty() { + if (match(tt.ellipsis)) { + expect(tt.ellipsis); + if (!eat(tt.comma)) { + eat(tt.semi); + } + // Explicit inexact object syntax. + if (match(tt.braceR)) { + return; + } + flowParseType(); + } else { + flowParseObjectPropertyKey(); + if (match(tt.lessThan) || match(tt.parenL)) { + // This is a method property + flowParseObjectTypeMethodish(); + } else { + eat(tt.question); + flowParseTypeInitialiser(); + } + } +} + +function flowObjectTypeSemicolon() { + if (!eat(tt.semi) && !eat(tt.comma) && !match(tt.braceR) && !match(tt.braceBarR)) { + unexpected(); + } +} + +function flowParseQualifiedTypeIdentifier(initialIdAlreadyParsed) { + if (!initialIdAlreadyParsed) { + parseIdentifier(); + } + while (eat(tt.dot)) { + parseIdentifier(); + } +} + +function flowParseGenericType() { + flowParseQualifiedTypeIdentifier(true); + if (match(tt.lessThan)) { + flowParseTypeParameterInstantiation(); + } +} + +function flowParseTypeofType() { + expect(tt._typeof); + flowParsePrimaryType(); +} + +function flowParseTupleType() { + expect(tt.bracketL); + // We allow trailing commas + while (state.pos < input.length && !match(tt.bracketR)) { + flowParseType(); + if (match(tt.bracketR)) { + break; + } + expect(tt.comma); + } + expect(tt.bracketR); +} + +function flowParseFunctionTypeParam() { + const lookahead = lookaheadType(); + if (lookahead === tt.colon || lookahead === tt.question) { + parseIdentifier(); + eat(tt.question); + flowParseTypeInitialiser(); + } else { + flowParseType(); + } +} + +function flowParseFunctionTypeParams() { + while (!match(tt.parenR) && !match(tt.ellipsis) && !state.error) { + flowParseFunctionTypeParam(); + if (!match(tt.parenR)) { + expect(tt.comma); + } + } + if (eat(tt.ellipsis)) { + flowParseFunctionTypeParam(); + } +} + +// The parsing of types roughly parallels the parsing of expressions, and +// primary types are kind of like primary expressions...they're the +// primitives with which other types are constructed. +function flowParsePrimaryType() { + let isGroupedType = false; + const oldNoAnonFunctionType = state.noAnonFunctionType; + + switch (state.type) { + case tt.name: { + if (isContextual(ContextualKeyword._interface)) { + flowParseInterfaceType(); + return; + } + parseIdentifier(); + flowParseGenericType(); + return; + } + + case tt.braceL: + flowParseObjectType(false, false, false); + return; + + case tt.braceBarL: + flowParseObjectType(false, true, false); + return; + + case tt.bracketL: + flowParseTupleType(); + return; + + case tt.lessThan: + flowParseTypeParameterDeclaration(); + expect(tt.parenL); + flowParseFunctionTypeParams(); + expect(tt.parenR); + expect(tt.arrow); + flowParseType(); + return; + + case tt.parenL: + next(); + + // Check to see if this is actually a grouped type + if (!match(tt.parenR) && !match(tt.ellipsis)) { + if (match(tt.name)) { + const token = lookaheadType(); + isGroupedType = token !== tt.question && token !== tt.colon; + } else { + isGroupedType = true; + } + } + + if (isGroupedType) { + state.noAnonFunctionType = false; + flowParseType(); + state.noAnonFunctionType = oldNoAnonFunctionType; + + // A `,` or a `) =>` means this is an anonymous function type + if ( + state.noAnonFunctionType || + !(match(tt.comma) || (match(tt.parenR) && lookaheadType() === tt.arrow)) + ) { + expect(tt.parenR); + return; + } else { + // Eat a comma if there is one + eat(tt.comma); + } + } + + flowParseFunctionTypeParams(); + + expect(tt.parenR); + expect(tt.arrow); + flowParseType(); + return; + + case tt.minus: + next(); + parseLiteral(); + return; + + case tt.string: + case tt.num: + case tt._true: + case tt._false: + case tt._null: + case tt._this: + case tt._void: + case tt.star: + next(); + return; + + default: + if (state.type === tt._typeof) { + flowParseTypeofType(); + return; + } else if (state.type & TokenType.IS_KEYWORD) { + next(); + state.tokens[state.tokens.length - 1].type = tt.name; + return; + } + } + + unexpected(); +} + +function flowParsePostfixType() { + flowParsePrimaryType(); + while (!canInsertSemicolon() && (match(tt.bracketL) || match(tt.questionDot))) { + eat(tt.questionDot); + expect(tt.bracketL); + if (eat(tt.bracketR)) { + // Array type + } else { + // Indexed access type + flowParseType(); + expect(tt.bracketR); + } + } +} + +function flowParsePrefixType() { + if (eat(tt.question)) { + flowParsePrefixType(); + } else { + flowParsePostfixType(); + } +} + +function flowParseAnonFunctionWithoutParens() { + flowParsePrefixType(); + if (!state.noAnonFunctionType && eat(tt.arrow)) { + flowParseType(); + } +} + +function flowParseIntersectionType() { + eat(tt.bitwiseAND); + flowParseAnonFunctionWithoutParens(); + while (eat(tt.bitwiseAND)) { + flowParseAnonFunctionWithoutParens(); + } +} + +function flowParseUnionType() { + eat(tt.bitwiseOR); + flowParseIntersectionType(); + while (eat(tt.bitwiseOR)) { + flowParseIntersectionType(); + } +} + +function flowParseType() { + flowParseUnionType(); +} + +export function flowParseTypeAnnotation() { + flowParseTypeInitialiser(); +} + +function flowParseTypeAnnotatableIdentifier() { + parseIdentifier(); + if (match(tt.colon)) { + flowParseTypeAnnotation(); + } +} + +export function flowParseVariance() { + if (match(tt.plus) || match(tt.minus)) { + next(); + state.tokens[state.tokens.length - 1].isType = true; + } +} + +// ================================== +// Overrides +// ================================== + +export function flowParseFunctionBodyAndFinish(funcContextId) { + // For arrow functions, `parseArrow` handles the return type itself. + if (match(tt.colon)) { + flowParseTypeAndPredicateInitialiser(); + } + + parseFunctionBody(false, funcContextId); +} + +export function flowParseSubscript( + startTokenIndex, + noCalls, + stopState, +) { + if (match(tt.questionDot) && lookaheadType() === tt.lessThan) { + if (noCalls) { + stopState.stop = true; + return; + } + next(); + flowParseTypeParameterInstantiation(); + expect(tt.parenL); + parseCallExpressionArguments(); + return; + } else if (!noCalls && match(tt.lessThan)) { + const snapshot = state.snapshot(); + flowParseTypeParameterInstantiation(); + expect(tt.parenL); + parseCallExpressionArguments(); + if (state.error) { + state.restoreFromSnapshot(snapshot); + } else { + return; + } + } + baseParseSubscript(startTokenIndex, noCalls, stopState); +} + +export function flowStartParseNewArguments() { + if (match(tt.lessThan)) { + const snapshot = state.snapshot(); + flowParseTypeParameterInstantiation(); + if (state.error) { + state.restoreFromSnapshot(snapshot); + } + } +} + +// interfaces +export function flowTryParseStatement() { + if (match(tt.name) && state.contextualKeyword === ContextualKeyword._interface) { + const oldIsType = pushTypeContext(0); + next(); + flowParseInterface(); + popTypeContext(oldIsType); + return true; + } else if (isContextual(ContextualKeyword._enum)) { + flowParseEnumDeclaration(); + return true; + } + return false; +} + +export function flowTryParseExportDefaultExpression() { + if (isContextual(ContextualKeyword._enum)) { + flowParseEnumDeclaration(); + return true; + } + return false; +} + +// declares, interfaces and type aliases +export function flowParseIdentifierStatement(contextualKeyword) { + if (contextualKeyword === ContextualKeyword._declare) { + if ( + match(tt._class) || + match(tt.name) || + match(tt._function) || + match(tt._var) || + match(tt._export) + ) { + const oldIsType = pushTypeContext(1); + flowParseDeclare(); + popTypeContext(oldIsType); + } + } else if (match(tt.name)) { + if (contextualKeyword === ContextualKeyword._interface) { + const oldIsType = pushTypeContext(1); + flowParseInterface(); + popTypeContext(oldIsType); + } else if (contextualKeyword === ContextualKeyword._type) { + const oldIsType = pushTypeContext(1); + flowParseTypeAlias(); + popTypeContext(oldIsType); + } else if (contextualKeyword === ContextualKeyword._opaque) { + const oldIsType = pushTypeContext(1); + flowParseOpaqueType(false); + popTypeContext(oldIsType); + } + } + semicolon(); +} + +// export type +export function flowShouldParseExportDeclaration() { + return ( + isContextual(ContextualKeyword._type) || + isContextual(ContextualKeyword._interface) || + isContextual(ContextualKeyword._opaque) || + isContextual(ContextualKeyword._enum) + ); +} + +export function flowShouldDisallowExportDefaultSpecifier() { + return ( + match(tt.name) && + (state.contextualKeyword === ContextualKeyword._type || + state.contextualKeyword === ContextualKeyword._interface || + state.contextualKeyword === ContextualKeyword._opaque || + state.contextualKeyword === ContextualKeyword._enum) + ); +} + +export function flowParseExportDeclaration() { + if (isContextual(ContextualKeyword._type)) { + const oldIsType = pushTypeContext(1); + next(); + + if (match(tt.braceL)) { + // export type { foo, bar }; + parseExportSpecifiers(); + parseExportFrom(); + } else { + // export type Foo = Bar; + flowParseTypeAlias(); + } + popTypeContext(oldIsType); + } else if (isContextual(ContextualKeyword._opaque)) { + const oldIsType = pushTypeContext(1); + next(); + // export opaque type Foo = Bar; + flowParseOpaqueType(false); + popTypeContext(oldIsType); + } else if (isContextual(ContextualKeyword._interface)) { + const oldIsType = pushTypeContext(1); + next(); + flowParseInterface(); + popTypeContext(oldIsType); + } else { + parseStatement(true); + } +} + +export function flowShouldParseExportStar() { + return match(tt.star) || (isContextual(ContextualKeyword._type) && lookaheadType() === tt.star); +} + +export function flowParseExportStar() { + if (eatContextual(ContextualKeyword._type)) { + const oldIsType = pushTypeContext(2); + baseParseExportStar(); + popTypeContext(oldIsType); + } else { + baseParseExportStar(); + } +} + +// parse a the super class type parameters and implements +export function flowAfterParseClassSuper(hasSuper) { + if (hasSuper && match(tt.lessThan)) { + flowParseTypeParameterInstantiation(); + } + if (isContextual(ContextualKeyword._implements)) { + const oldIsType = pushTypeContext(0); + next(); + state.tokens[state.tokens.length - 1].type = tt._implements; + do { + flowParseRestrictedIdentifier(); + if (match(tt.lessThan)) { + flowParseTypeParameterInstantiation(); + } + } while (eat(tt.comma)); + popTypeContext(oldIsType); + } +} + +// parse type parameters for object method shorthand +export function flowStartParseObjPropValue() { + // method shorthand + if (match(tt.lessThan)) { + flowParseTypeParameterDeclaration(); + if (!match(tt.parenL)) unexpected(); + } +} + +export function flowParseAssignableListItemTypes() { + const oldIsType = pushTypeContext(0); + eat(tt.question); + if (match(tt.colon)) { + flowParseTypeAnnotation(); + } + popTypeContext(oldIsType); +} + +// parse typeof and type imports +export function flowStartParseImportSpecifiers() { + if (match(tt._typeof) || isContextual(ContextualKeyword._type)) { + const lh = lookaheadTypeAndKeyword(); + if (isMaybeDefaultImport(lh) || lh.type === tt.braceL || lh.type === tt.star) { + next(); + } + } +} + +// parse import-type/typeof shorthand +export function flowParseImportSpecifier() { + const isTypeKeyword = + state.contextualKeyword === ContextualKeyword._type || state.type === tt._typeof; + if (isTypeKeyword) { + next(); + } else { + parseIdentifier(); + } + + if (isContextual(ContextualKeyword._as) && !isLookaheadContextual(ContextualKeyword._as)) { + parseIdentifier(); + if (isTypeKeyword && !match(tt.name) && !(state.type & TokenType.IS_KEYWORD)) { + // `import {type as ,` or `import {type as }` + } else { + // `import {type as foo` + parseIdentifier(); + } + } else { + if (isTypeKeyword && (match(tt.name) || !!(state.type & TokenType.IS_KEYWORD))) { + // `import {type foo` + parseIdentifier(); + } + if (eatContextual(ContextualKeyword._as)) { + parseIdentifier(); + } + } +} + +// parse function type parameters - function foo<T>() {} +export function flowStartParseFunctionParams() { + // Originally this checked if the method is a getter/setter, but if it was, we'd crash soon + // anyway, so don't try to propagate that information. + if (match(tt.lessThan)) { + const oldIsType = pushTypeContext(0); + flowParseTypeParameterDeclaration(); + popTypeContext(oldIsType); + } +} + +// parse flow type annotations on variable declarator heads - let foo: string = bar +export function flowAfterParseVarHead() { + if (match(tt.colon)) { + flowParseTypeAnnotation(); + } +} + +// parse the return type of an async arrow function - let foo = (async (): number => {}); +export function flowStartParseAsyncArrowFromCallExpression() { + if (match(tt.colon)) { + const oldNoAnonFunctionType = state.noAnonFunctionType; + state.noAnonFunctionType = true; + flowParseTypeAnnotation(); + state.noAnonFunctionType = oldNoAnonFunctionType; + } +} + +// We need to support type parameter declarations for arrow functions. This +// is tricky. There are three situations we need to handle +// +// 1. This is either JSX or an arrow function. We'll try JSX first. If that +// fails, we'll try an arrow function. If that fails, we'll throw the JSX +// error. +// 2. This is an arrow function. We'll parse the type parameter declaration, +// parse the rest, make sure the rest is an arrow function, and go from +// there +// 3. This is neither. Just call the super method +export function flowParseMaybeAssign(noIn, isWithinParens) { + if (match(tt.lessThan)) { + const snapshot = state.snapshot(); + let wasArrow = baseParseMaybeAssign(noIn, isWithinParens); + if (state.error) { + state.restoreFromSnapshot(snapshot); + state.type = tt.typeParameterStart; + } else { + return wasArrow; + } + + const oldIsType = pushTypeContext(0); + flowParseTypeParameterDeclaration(); + popTypeContext(oldIsType); + wasArrow = baseParseMaybeAssign(noIn, isWithinParens); + if (wasArrow) { + return true; + } + unexpected(); + } + + return baseParseMaybeAssign(noIn, isWithinParens); +} + +// handle return types for arrow functions +export function flowParseArrow() { + if (match(tt.colon)) { + const oldIsType = pushTypeContext(0); + const snapshot = state.snapshot(); + + const oldNoAnonFunctionType = state.noAnonFunctionType; + state.noAnonFunctionType = true; + flowParseTypeAndPredicateInitialiser(); + state.noAnonFunctionType = oldNoAnonFunctionType; + + if (canInsertSemicolon()) unexpected(); + if (!match(tt.arrow)) unexpected(); + + if (state.error) { + state.restoreFromSnapshot(snapshot); + } + popTypeContext(oldIsType); + } + return eat(tt.arrow); +} + +export function flowParseSubscripts(startTokenIndex, noCalls = false) { + if ( + state.tokens[state.tokens.length - 1].contextualKeyword === ContextualKeyword._async && + match(tt.lessThan) + ) { + const snapshot = state.snapshot(); + const wasArrow = parseAsyncArrowWithTypeParameters(); + if (wasArrow && !state.error) { + return; + } + state.restoreFromSnapshot(snapshot); + } + + baseParseSubscripts(startTokenIndex, noCalls); +} + +// Returns true if there was an arrow function here. +function parseAsyncArrowWithTypeParameters() { + state.scopeDepth++; + const startTokenIndex = state.tokens.length; + parseFunctionParams(); + if (!parseArrow()) { + return false; + } + parseArrowExpression(startTokenIndex); + return true; +} + +function flowParseEnumDeclaration() { + expectContextual(ContextualKeyword._enum); + state.tokens[state.tokens.length - 1].type = tt._enum; + parseIdentifier(); + flowParseEnumBody(); +} + +function flowParseEnumBody() { + if (eatContextual(ContextualKeyword._of)) { + next(); + } + expect(tt.braceL); + flowParseEnumMembers(); + expect(tt.braceR); +} + +function flowParseEnumMembers() { + while (!match(tt.braceR) && !state.error) { + if (eat(tt.ellipsis)) { + break; + } + flowParseEnumMember(); + if (!match(tt.braceR)) { + expect(tt.comma); + } + } +} + +function flowParseEnumMember() { + parseIdentifier(); + if (eat(tt.eq)) { + // Flow enum values are always just one token (a string, number, or boolean literal). + next(); + } +} diff --git a/node_modules/sucrase/dist/esm/parser/plugins/jsx/index.js b/node_modules/sucrase/dist/esm/parser/plugins/jsx/index.js new file mode 100644 index 0000000..83f3983 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/plugins/jsx/index.js @@ -0,0 +1,367 @@ +import { + eat, + finishToken, + getTokenFromCode, + IdentifierRole, + JSXRole, + match, + next, + skipSpace, + Token, +} from "../../tokenizer/index"; +import {TokenType as tt} from "../../tokenizer/types"; +import {input, isTypeScriptEnabled, state} from "../../traverser/base"; +import {parseExpression, parseMaybeAssign} from "../../traverser/expression"; +import {expect, unexpected} from "../../traverser/util"; +import {charCodes} from "../../util/charcodes"; +import {IS_IDENTIFIER_CHAR, IS_IDENTIFIER_START} from "../../util/identifier"; +import {tsTryParseJSXTypeArgument} from "../typescript"; + +/** + * Read token with JSX contents. + * + * In addition to detecting jsxTagStart and also regular tokens that might be + * part of an expression, this code detects the start and end of text ranges + * within JSX children. In order to properly count the number of children, we + * distinguish jsxText from jsxEmptyText, which is a text range that simplifies + * to the empty string after JSX whitespace trimming. + * + * It turns out that a JSX text range will simplify to the empty string if and + * only if both of these conditions hold: + * - The range consists entirely of whitespace characters (only counting space, + * tab, \r, and \n). + * - The range has at least one newline. + * This can be proven by analyzing any implementation of whitespace trimming, + * e.g. formatJSXTextLiteral in Sucrase or cleanJSXElementLiteralChild in Babel. + */ +function jsxReadToken() { + let sawNewline = false; + let sawNonWhitespace = false; + while (true) { + if (state.pos >= input.length) { + unexpected("Unterminated JSX contents"); + return; + } + + const ch = input.charCodeAt(state.pos); + if (ch === charCodes.lessThan || ch === charCodes.leftCurlyBrace) { + if (state.pos === state.start) { + if (ch === charCodes.lessThan) { + state.pos++; + finishToken(tt.jsxTagStart); + return; + } + getTokenFromCode(ch); + return; + } + if (sawNewline && !sawNonWhitespace) { + finishToken(tt.jsxEmptyText); + } else { + finishToken(tt.jsxText); + } + return; + } + + // This is part of JSX text. + if (ch === charCodes.lineFeed) { + sawNewline = true; + } else if (ch !== charCodes.space && ch !== charCodes.carriageReturn && ch !== charCodes.tab) { + sawNonWhitespace = true; + } + state.pos++; + } +} + +function jsxReadString(quote) { + state.pos++; + for (;;) { + if (state.pos >= input.length) { + unexpected("Unterminated string constant"); + return; + } + + const ch = input.charCodeAt(state.pos); + if (ch === quote) { + state.pos++; + break; + } + state.pos++; + } + finishToken(tt.string); +} + +// Read a JSX identifier (valid tag or attribute name). +// +// Optimized version since JSX identifiers can't contain +// escape characters and so can be read as single slice. +// Also assumes that first character was already checked +// by isIdentifierStart in readToken. + +function jsxReadWord() { + let ch; + do { + if (state.pos > input.length) { + unexpected("Unexpectedly reached the end of input."); + return; + } + ch = input.charCodeAt(++state.pos); + } while (IS_IDENTIFIER_CHAR[ch] || ch === charCodes.dash); + finishToken(tt.jsxName); +} + +// Parse next token as JSX identifier +function jsxParseIdentifier() { + nextJSXTagToken(); +} + +// Parse namespaced identifier. +function jsxParseNamespacedName(identifierRole) { + jsxParseIdentifier(); + if (!eat(tt.colon)) { + // Plain identifier, so this is an access. + state.tokens[state.tokens.length - 1].identifierRole = identifierRole; + return; + } + // Process the second half of the namespaced name. + jsxParseIdentifier(); +} + +// Parses element name in any form - namespaced, member +// or single identifier. +function jsxParseElementName() { + const firstTokenIndex = state.tokens.length; + jsxParseNamespacedName(IdentifierRole.Access); + let hadDot = false; + while (match(tt.dot)) { + hadDot = true; + nextJSXTagToken(); + jsxParseIdentifier(); + } + // For tags like <div> with a lowercase letter and no dots, the name is + // actually *not* an identifier access, since it's referring to a built-in + // tag name. Remove the identifier role in this case so that it's not + // accidentally transformed by the imports transform when preserving JSX. + if (!hadDot) { + const firstToken = state.tokens[firstTokenIndex]; + const firstChar = input.charCodeAt(firstToken.start); + if (firstChar >= charCodes.lowercaseA && firstChar <= charCodes.lowercaseZ) { + firstToken.identifierRole = null; + } + } +} + +// Parses any type of JSX attribute value. +function jsxParseAttributeValue() { + switch (state.type) { + case tt.braceL: + next(); + parseExpression(); + nextJSXTagToken(); + return; + + case tt.jsxTagStart: + jsxParseElement(); + nextJSXTagToken(); + return; + + case tt.string: + nextJSXTagToken(); + return; + + default: + unexpected("JSX value should be either an expression or a quoted JSX text"); + } +} + +// Parse JSX spread child, after already processing the { +// Does not parse the closing } +function jsxParseSpreadChild() { + expect(tt.ellipsis); + parseExpression(); +} + +// Parses JSX opening tag starting after "<". +// Returns true if the tag was self-closing. +// Does not parse the last token. +function jsxParseOpeningElement(initialTokenIndex) { + if (match(tt.jsxTagEnd)) { + // This is an open-fragment. + return false; + } + jsxParseElementName(); + if (isTypeScriptEnabled) { + tsTryParseJSXTypeArgument(); + } + let hasSeenPropSpread = false; + while (!match(tt.slash) && !match(tt.jsxTagEnd) && !state.error) { + if (eat(tt.braceL)) { + hasSeenPropSpread = true; + expect(tt.ellipsis); + parseMaybeAssign(); + // } + nextJSXTagToken(); + continue; + } + if ( + hasSeenPropSpread && + state.end - state.start === 3 && + input.charCodeAt(state.start) === charCodes.lowercaseK && + input.charCodeAt(state.start + 1) === charCodes.lowercaseE && + input.charCodeAt(state.start + 2) === charCodes.lowercaseY + ) { + state.tokens[initialTokenIndex].jsxRole = JSXRole.KeyAfterPropSpread; + } + jsxParseNamespacedName(IdentifierRole.ObjectKey); + if (match(tt.eq)) { + nextJSXTagToken(); + jsxParseAttributeValue(); + } + } + const isSelfClosing = match(tt.slash); + if (isSelfClosing) { + // / + nextJSXTagToken(); + } + return isSelfClosing; +} + +// Parses JSX closing tag starting after "</". +// Does not parse the last token. +function jsxParseClosingElement() { + if (match(tt.jsxTagEnd)) { + // Fragment syntax, so we immediately have a tag end. + return; + } + jsxParseElementName(); +} + +// Parses entire JSX element, including its opening tag +// (starting after "<"), attributes, contents and closing tag. +// Does not parse the last token. +function jsxParseElementAt() { + const initialTokenIndex = state.tokens.length - 1; + state.tokens[initialTokenIndex].jsxRole = JSXRole.NoChildren; + let numExplicitChildren = 0; + const isSelfClosing = jsxParseOpeningElement(initialTokenIndex); + if (!isSelfClosing) { + nextJSXExprToken(); + while (true) { + switch (state.type) { + case tt.jsxTagStart: + nextJSXTagToken(); + if (match(tt.slash)) { + nextJSXTagToken(); + jsxParseClosingElement(); + // Key after prop spread takes precedence over number of children, + // since it means we switch to createElement, which doesn't care + // about number of children. + if (state.tokens[initialTokenIndex].jsxRole !== JSXRole.KeyAfterPropSpread) { + if (numExplicitChildren === 1) { + state.tokens[initialTokenIndex].jsxRole = JSXRole.OneChild; + } else if (numExplicitChildren > 1) { + state.tokens[initialTokenIndex].jsxRole = JSXRole.StaticChildren; + } + } + return; + } + numExplicitChildren++; + jsxParseElementAt(); + nextJSXExprToken(); + break; + + case tt.jsxText: + numExplicitChildren++; + nextJSXExprToken(); + break; + + case tt.jsxEmptyText: + nextJSXExprToken(); + break; + + case tt.braceL: + next(); + if (match(tt.ellipsis)) { + jsxParseSpreadChild(); + nextJSXExprToken(); + // Spread children are a mechanism to explicitly mark children as + // static, so count it as 2 children to satisfy the "more than one + // child" condition. + numExplicitChildren += 2; + } else { + // If we see {}, this is an empty pseudo-expression that doesn't + // count as a child. + if (!match(tt.braceR)) { + numExplicitChildren++; + parseExpression(); + } + nextJSXExprToken(); + } + + break; + + // istanbul ignore next - should never happen + default: + unexpected(); + return; + } + } + } +} + +// Parses entire JSX element from current position. +// Does not parse the last token. +export function jsxParseElement() { + nextJSXTagToken(); + jsxParseElementAt(); +} + +// ================================== +// Overrides +// ================================== + +export function nextJSXTagToken() { + state.tokens.push(new Token()); + skipSpace(); + state.start = state.pos; + const code = input.charCodeAt(state.pos); + + if (IS_IDENTIFIER_START[code]) { + jsxReadWord(); + } else if (code === charCodes.quotationMark || code === charCodes.apostrophe) { + jsxReadString(code); + } else { + // The following tokens are just one character each. + ++state.pos; + switch (code) { + case charCodes.greaterThan: + finishToken(tt.jsxTagEnd); + break; + case charCodes.lessThan: + finishToken(tt.jsxTagStart); + break; + case charCodes.slash: + finishToken(tt.slash); + break; + case charCodes.equalsTo: + finishToken(tt.eq); + break; + case charCodes.leftCurlyBrace: + finishToken(tt.braceL); + break; + case charCodes.dot: + finishToken(tt.dot); + break; + case charCodes.colon: + finishToken(tt.colon); + break; + default: + unexpected(); + } + } +} + +function nextJSXExprToken() { + state.tokens.push(new Token()); + state.start = state.pos; + jsxReadToken(); +} diff --git a/node_modules/sucrase/dist/esm/parser/plugins/jsx/xhtml.js b/node_modules/sucrase/dist/esm/parser/plugins/jsx/xhtml.js new file mode 100644 index 0000000..c6a0741 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/plugins/jsx/xhtml.js @@ -0,0 +1,256 @@ +// Use a Map rather than object to avoid unexpected __proto__ access. +export default new Map([ + ["quot", "\u0022"], + ["amp", "&"], + ["apos", "\u0027"], + ["lt", "<"], + ["gt", ">"], + ["nbsp", "\u00A0"], + ["iexcl", "\u00A1"], + ["cent", "\u00A2"], + ["pound", "\u00A3"], + ["curren", "\u00A4"], + ["yen", "\u00A5"], + ["brvbar", "\u00A6"], + ["sect", "\u00A7"], + ["uml", "\u00A8"], + ["copy", "\u00A9"], + ["ordf", "\u00AA"], + ["laquo", "\u00AB"], + ["not", "\u00AC"], + ["shy", "\u00AD"], + ["reg", "\u00AE"], + ["macr", "\u00AF"], + ["deg", "\u00B0"], + ["plusmn", "\u00B1"], + ["sup2", "\u00B2"], + ["sup3", "\u00B3"], + ["acute", "\u00B4"], + ["micro", "\u00B5"], + ["para", "\u00B6"], + ["middot", "\u00B7"], + ["cedil", "\u00B8"], + ["sup1", "\u00B9"], + ["ordm", "\u00BA"], + ["raquo", "\u00BB"], + ["frac14", "\u00BC"], + ["frac12", "\u00BD"], + ["frac34", "\u00BE"], + ["iquest", "\u00BF"], + ["Agrave", "\u00C0"], + ["Aacute", "\u00C1"], + ["Acirc", "\u00C2"], + ["Atilde", "\u00C3"], + ["Auml", "\u00C4"], + ["Aring", "\u00C5"], + ["AElig", "\u00C6"], + ["Ccedil", "\u00C7"], + ["Egrave", "\u00C8"], + ["Eacute", "\u00C9"], + ["Ecirc", "\u00CA"], + ["Euml", "\u00CB"], + ["Igrave", "\u00CC"], + ["Iacute", "\u00CD"], + ["Icirc", "\u00CE"], + ["Iuml", "\u00CF"], + ["ETH", "\u00D0"], + ["Ntilde", "\u00D1"], + ["Ograve", "\u00D2"], + ["Oacute", "\u00D3"], + ["Ocirc", "\u00D4"], + ["Otilde", "\u00D5"], + ["Ouml", "\u00D6"], + ["times", "\u00D7"], + ["Oslash", "\u00D8"], + ["Ugrave", "\u00D9"], + ["Uacute", "\u00DA"], + ["Ucirc", "\u00DB"], + ["Uuml", "\u00DC"], + ["Yacute", "\u00DD"], + ["THORN", "\u00DE"], + ["szlig", "\u00DF"], + ["agrave", "\u00E0"], + ["aacute", "\u00E1"], + ["acirc", "\u00E2"], + ["atilde", "\u00E3"], + ["auml", "\u00E4"], + ["aring", "\u00E5"], + ["aelig", "\u00E6"], + ["ccedil", "\u00E7"], + ["egrave", "\u00E8"], + ["eacute", "\u00E9"], + ["ecirc", "\u00EA"], + ["euml", "\u00EB"], + ["igrave", "\u00EC"], + ["iacute", "\u00ED"], + ["icirc", "\u00EE"], + ["iuml", "\u00EF"], + ["eth", "\u00F0"], + ["ntilde", "\u00F1"], + ["ograve", "\u00F2"], + ["oacute", "\u00F3"], + ["ocirc", "\u00F4"], + ["otilde", "\u00F5"], + ["ouml", "\u00F6"], + ["divide", "\u00F7"], + ["oslash", "\u00F8"], + ["ugrave", "\u00F9"], + ["uacute", "\u00FA"], + ["ucirc", "\u00FB"], + ["uuml", "\u00FC"], + ["yacute", "\u00FD"], + ["thorn", "\u00FE"], + ["yuml", "\u00FF"], + ["OElig", "\u0152"], + ["oelig", "\u0153"], + ["Scaron", "\u0160"], + ["scaron", "\u0161"], + ["Yuml", "\u0178"], + ["fnof", "\u0192"], + ["circ", "\u02C6"], + ["tilde", "\u02DC"], + ["Alpha", "\u0391"], + ["Beta", "\u0392"], + ["Gamma", "\u0393"], + ["Delta", "\u0394"], + ["Epsilon", "\u0395"], + ["Zeta", "\u0396"], + ["Eta", "\u0397"], + ["Theta", "\u0398"], + ["Iota", "\u0399"], + ["Kappa", "\u039A"], + ["Lambda", "\u039B"], + ["Mu", "\u039C"], + ["Nu", "\u039D"], + ["Xi", "\u039E"], + ["Omicron", "\u039F"], + ["Pi", "\u03A0"], + ["Rho", "\u03A1"], + ["Sigma", "\u03A3"], + ["Tau", "\u03A4"], + ["Upsilon", "\u03A5"], + ["Phi", "\u03A6"], + ["Chi", "\u03A7"], + ["Psi", "\u03A8"], + ["Omega", "\u03A9"], + ["alpha", "\u03B1"], + ["beta", "\u03B2"], + ["gamma", "\u03B3"], + ["delta", "\u03B4"], + ["epsilon", "\u03B5"], + ["zeta", "\u03B6"], + ["eta", "\u03B7"], + ["theta", "\u03B8"], + ["iota", "\u03B9"], + ["kappa", "\u03BA"], + ["lambda", "\u03BB"], + ["mu", "\u03BC"], + ["nu", "\u03BD"], + ["xi", "\u03BE"], + ["omicron", "\u03BF"], + ["pi", "\u03C0"], + ["rho", "\u03C1"], + ["sigmaf", "\u03C2"], + ["sigma", "\u03C3"], + ["tau", "\u03C4"], + ["upsilon", "\u03C5"], + ["phi", "\u03C6"], + ["chi", "\u03C7"], + ["psi", "\u03C8"], + ["omega", "\u03C9"], + ["thetasym", "\u03D1"], + ["upsih", "\u03D2"], + ["piv", "\u03D6"], + ["ensp", "\u2002"], + ["emsp", "\u2003"], + ["thinsp", "\u2009"], + ["zwnj", "\u200C"], + ["zwj", "\u200D"], + ["lrm", "\u200E"], + ["rlm", "\u200F"], + ["ndash", "\u2013"], + ["mdash", "\u2014"], + ["lsquo", "\u2018"], + ["rsquo", "\u2019"], + ["sbquo", "\u201A"], + ["ldquo", "\u201C"], + ["rdquo", "\u201D"], + ["bdquo", "\u201E"], + ["dagger", "\u2020"], + ["Dagger", "\u2021"], + ["bull", "\u2022"], + ["hellip", "\u2026"], + ["permil", "\u2030"], + ["prime", "\u2032"], + ["Prime", "\u2033"], + ["lsaquo", "\u2039"], + ["rsaquo", "\u203A"], + ["oline", "\u203E"], + ["frasl", "\u2044"], + ["euro", "\u20AC"], + ["image", "\u2111"], + ["weierp", "\u2118"], + ["real", "\u211C"], + ["trade", "\u2122"], + ["alefsym", "\u2135"], + ["larr", "\u2190"], + ["uarr", "\u2191"], + ["rarr", "\u2192"], + ["darr", "\u2193"], + ["harr", "\u2194"], + ["crarr", "\u21B5"], + ["lArr", "\u21D0"], + ["uArr", "\u21D1"], + ["rArr", "\u21D2"], + ["dArr", "\u21D3"], + ["hArr", "\u21D4"], + ["forall", "\u2200"], + ["part", "\u2202"], + ["exist", "\u2203"], + ["empty", "\u2205"], + ["nabla", "\u2207"], + ["isin", "\u2208"], + ["notin", "\u2209"], + ["ni", "\u220B"], + ["prod", "\u220F"], + ["sum", "\u2211"], + ["minus", "\u2212"], + ["lowast", "\u2217"], + ["radic", "\u221A"], + ["prop", "\u221D"], + ["infin", "\u221E"], + ["ang", "\u2220"], + ["and", "\u2227"], + ["or", "\u2228"], + ["cap", "\u2229"], + ["cup", "\u222A"], + ["int", "\u222B"], + ["there4", "\u2234"], + ["sim", "\u223C"], + ["cong", "\u2245"], + ["asymp", "\u2248"], + ["ne", "\u2260"], + ["equiv", "\u2261"], + ["le", "\u2264"], + ["ge", "\u2265"], + ["sub", "\u2282"], + ["sup", "\u2283"], + ["nsub", "\u2284"], + ["sube", "\u2286"], + ["supe", "\u2287"], + ["oplus", "\u2295"], + ["otimes", "\u2297"], + ["perp", "\u22A5"], + ["sdot", "\u22C5"], + ["lceil", "\u2308"], + ["rceil", "\u2309"], + ["lfloor", "\u230A"], + ["rfloor", "\u230B"], + ["lang", "\u2329"], + ["rang", "\u232A"], + ["loz", "\u25CA"], + ["spades", "\u2660"], + ["clubs", "\u2663"], + ["hearts", "\u2665"], + ["diams", "\u2666"], +]); diff --git a/node_modules/sucrase/dist/esm/parser/plugins/types.js b/node_modules/sucrase/dist/esm/parser/plugins/types.js new file mode 100644 index 0000000..78e4af4 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/plugins/types.js @@ -0,0 +1,37 @@ +import {eatTypeToken, lookaheadType, match} from "../tokenizer/index"; +import {TokenType as tt} from "../tokenizer/types"; +import {isFlowEnabled, isTypeScriptEnabled} from "../traverser/base"; +import {baseParseConditional} from "../traverser/expression"; +import {flowParseTypeAnnotation} from "./flow"; +import {tsParseTypeAnnotation} from "./typescript"; + +/** + * Common parser code for TypeScript and Flow. + */ + +// An apparent conditional expression could actually be an optional parameter in an arrow function. +export function typedParseConditional(noIn) { + // If we see ?:, this can't possibly be a valid conditional. typedParseParenItem will be called + // later to finish off the arrow parameter. We also need to handle bare ? tokens for optional + // parameters without type annotations, i.e. ?, and ?) . + if (match(tt.question)) { + const nextType = lookaheadType(); + if (nextType === tt.colon || nextType === tt.comma || nextType === tt.parenR) { + return; + } + } + baseParseConditional(noIn); +} + +// Note: These "type casts" are *not* valid TS expressions. +// But we parse them here and change them when completing the arrow function. +export function typedParseParenItem() { + eatTypeToken(tt.question); + if (match(tt.colon)) { + if (isTypeScriptEnabled) { + tsParseTypeAnnotation(); + } else if (isFlowEnabled) { + flowParseTypeAnnotation(); + } + } +} diff --git a/node_modules/sucrase/dist/esm/parser/plugins/typescript.js b/node_modules/sucrase/dist/esm/parser/plugins/typescript.js new file mode 100644 index 0000000..f64ca67 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/plugins/typescript.js @@ -0,0 +1,1632 @@ +import { + eat, + finishToken, + IdentifierRole, + lookaheadType, + lookaheadTypeAndKeyword, + match, + next, + nextTemplateToken, + popTypeContext, + pushTypeContext, + rescan_gt, +} from "../tokenizer/index"; +import {ContextualKeyword} from "../tokenizer/keywords"; +import {TokenType, TokenType as tt} from "../tokenizer/types"; +import {isJSXEnabled, state} from "../traverser/base"; +import { + atPossibleAsync, + baseParseMaybeAssign, + baseParseSubscript, + parseCallExpressionArguments, + parseExprAtom, + parseExpression, + parseFunctionBody, + parseIdentifier, + parseLiteral, + parseMaybeAssign, + parseMaybeUnary, + parsePropertyName, + parseTemplate, + +} from "../traverser/expression"; +import {parseBindingIdentifier, parseBindingList, parseImportedIdentifier} from "../traverser/lval"; +import { + baseParseMaybeDecoratorArguments, + parseBlockBody, + parseClass, + parseFunction, + parseFunctionParams, + parseStatement, + parseVarStatement, +} from "../traverser/statement"; +import { + canInsertSemicolon, + eatContextual, + expect, + expectContextual, + hasPrecedingLineBreak, + isContextual, + isLineTerminator, + isLookaheadContextual, + semicolon, + unexpected, +} from "../traverser/util"; +import {nextJSXTagToken} from "./jsx"; + +function tsIsIdentifier() { + // TODO: actually a bit more complex in TypeScript, but shouldn't matter. + // See https://github.com/Microsoft/TypeScript/issues/15008 + return match(tt.name); +} + +function isLiteralPropertyName() { + return ( + match(tt.name) || + Boolean(state.type & TokenType.IS_KEYWORD) || + match(tt.string) || + match(tt.num) || + match(tt.bigint) || + match(tt.decimal) + ); +} + +function tsNextTokenCanFollowModifier() { + // Note: TypeScript's implementation is much more complicated because + // more things are considered modifiers there. + // This implementation only handles modifiers not handled by babylon itself. And "static". + // TODO: Would be nice to avoid lookahead. Want a hasLineBreakUpNext() method... + const snapshot = state.snapshot(); + + next(); + const canFollowModifier = + (match(tt.bracketL) || + match(tt.braceL) || + match(tt.star) || + match(tt.ellipsis) || + match(tt.hash) || + isLiteralPropertyName()) && + !hasPrecedingLineBreak(); + + if (canFollowModifier) { + return true; + } else { + state.restoreFromSnapshot(snapshot); + return false; + } +} + +export function tsParseModifiers(allowedModifiers) { + while (true) { + const modifier = tsParseModifier(allowedModifiers); + if (modifier === null) { + break; + } + } +} + +/** Parses a modifier matching one the given modifier names. */ +export function tsParseModifier( + allowedModifiers, +) { + if (!match(tt.name)) { + return null; + } + + const modifier = state.contextualKeyword; + if (allowedModifiers.indexOf(modifier) !== -1 && tsNextTokenCanFollowModifier()) { + switch (modifier) { + case ContextualKeyword._readonly: + state.tokens[state.tokens.length - 1].type = tt._readonly; + break; + case ContextualKeyword._abstract: + state.tokens[state.tokens.length - 1].type = tt._abstract; + break; + case ContextualKeyword._static: + state.tokens[state.tokens.length - 1].type = tt._static; + break; + case ContextualKeyword._public: + state.tokens[state.tokens.length - 1].type = tt._public; + break; + case ContextualKeyword._private: + state.tokens[state.tokens.length - 1].type = tt._private; + break; + case ContextualKeyword._protected: + state.tokens[state.tokens.length - 1].type = tt._protected; + break; + case ContextualKeyword._override: + state.tokens[state.tokens.length - 1].type = tt._override; + break; + case ContextualKeyword._declare: + state.tokens[state.tokens.length - 1].type = tt._declare; + break; + default: + break; + } + return modifier; + } + return null; +} + +function tsParseEntityName() { + parseIdentifier(); + while (eat(tt.dot)) { + parseIdentifier(); + } +} + +function tsParseTypeReference() { + tsParseEntityName(); + if (!hasPrecedingLineBreak() && match(tt.lessThan)) { + tsParseTypeArguments(); + } +} + +function tsParseThisTypePredicate() { + next(); + tsParseTypeAnnotation(); +} + +function tsParseThisTypeNode() { + next(); +} + +function tsParseTypeQuery() { + expect(tt._typeof); + if (match(tt._import)) { + tsParseImportType(); + } else { + tsParseEntityName(); + } + if (!hasPrecedingLineBreak() && match(tt.lessThan)) { + tsParseTypeArguments(); + } +} + +function tsParseImportType() { + expect(tt._import); + expect(tt.parenL); + expect(tt.string); + expect(tt.parenR); + if (eat(tt.dot)) { + tsParseEntityName(); + } + if (match(tt.lessThan)) { + tsParseTypeArguments(); + } +} + +function tsParseTypeParameter() { + eat(tt._const); + const hadIn = eat(tt._in); + const hadOut = eatContextual(ContextualKeyword._out); + eat(tt._const); + if ((hadIn || hadOut) && !match(tt.name)) { + // The "in" or "out" keyword must have actually been the type parameter + // name, so set it as the name. + state.tokens[state.tokens.length - 1].type = tt.name; + } else { + parseIdentifier(); + } + + if (eat(tt._extends)) { + tsParseType(); + } + if (eat(tt.eq)) { + tsParseType(); + } +} + +export function tsTryParseTypeParameters() { + if (match(tt.lessThan)) { + tsParseTypeParameters(); + } +} + +function tsParseTypeParameters() { + const oldIsType = pushTypeContext(0); + if (match(tt.lessThan) || match(tt.typeParameterStart)) { + next(); + } else { + unexpected(); + } + + while (!eat(tt.greaterThan) && !state.error) { + tsParseTypeParameter(); + eat(tt.comma); + } + popTypeContext(oldIsType); +} + +// Note: In TypeScript implementation we must provide `yieldContext` and `awaitContext`, +// but here it's always false, because this is only used for types. +function tsFillSignature(returnToken) { + // Arrow fns *must* have return token (`=>`). Normal functions can omit it. + const returnTokenRequired = returnToken === tt.arrow; + tsTryParseTypeParameters(); + expect(tt.parenL); + // Create a scope even though we're doing type parsing so we don't accidentally + // treat params as top-level bindings. + state.scopeDepth++; + tsParseBindingListForSignature(false /* isBlockScope */); + state.scopeDepth--; + if (returnTokenRequired) { + tsParseTypeOrTypePredicateAnnotation(returnToken); + } else if (match(returnToken)) { + tsParseTypeOrTypePredicateAnnotation(returnToken); + } +} + +function tsParseBindingListForSignature(isBlockScope) { + parseBindingList(tt.parenR, isBlockScope); +} + +function tsParseTypeMemberSemicolon() { + if (!eat(tt.comma)) { + semicolon(); + } +} + +function tsParseSignatureMember() { + tsFillSignature(tt.colon); + tsParseTypeMemberSemicolon(); +} + +function tsIsUnambiguouslyIndexSignature() { + const snapshot = state.snapshot(); + next(); // Skip '{' + const isIndexSignature = eat(tt.name) && match(tt.colon); + state.restoreFromSnapshot(snapshot); + return isIndexSignature; +} + +function tsTryParseIndexSignature() { + if (!(match(tt.bracketL) && tsIsUnambiguouslyIndexSignature())) { + return false; + } + + const oldIsType = pushTypeContext(0); + + expect(tt.bracketL); + parseIdentifier(); + tsParseTypeAnnotation(); + expect(tt.bracketR); + + tsTryParseTypeAnnotation(); + tsParseTypeMemberSemicolon(); + + popTypeContext(oldIsType); + return true; +} + +function tsParsePropertyOrMethodSignature(isReadonly) { + eat(tt.question); + + if (!isReadonly && (match(tt.parenL) || match(tt.lessThan))) { + tsFillSignature(tt.colon); + tsParseTypeMemberSemicolon(); + } else { + tsTryParseTypeAnnotation(); + tsParseTypeMemberSemicolon(); + } +} + +function tsParseTypeMember() { + if (match(tt.parenL) || match(tt.lessThan)) { + // call signature + tsParseSignatureMember(); + return; + } + if (match(tt._new)) { + next(); + if (match(tt.parenL) || match(tt.lessThan)) { + // constructor signature + tsParseSignatureMember(); + } else { + tsParsePropertyOrMethodSignature(false); + } + return; + } + const readonly = !!tsParseModifier([ContextualKeyword._readonly]); + + const found = tsTryParseIndexSignature(); + if (found) { + return; + } + if ( + (isContextual(ContextualKeyword._get) || isContextual(ContextualKeyword._set)) && + tsNextTokenCanFollowModifier() + ) { + // This is a getter/setter on a type. The tsNextTokenCanFollowModifier + // function already called next() for us, so continue parsing the name. + } + parsePropertyName(-1 /* Types don't need context IDs. */); + tsParsePropertyOrMethodSignature(readonly); +} + +function tsParseTypeLiteral() { + tsParseObjectTypeMembers(); +} + +function tsParseObjectTypeMembers() { + expect(tt.braceL); + while (!eat(tt.braceR) && !state.error) { + tsParseTypeMember(); + } +} + +function tsLookaheadIsStartOfMappedType() { + const snapshot = state.snapshot(); + const isStartOfMappedType = tsIsStartOfMappedType(); + state.restoreFromSnapshot(snapshot); + return isStartOfMappedType; +} + +function tsIsStartOfMappedType() { + next(); + if (eat(tt.plus) || eat(tt.minus)) { + return isContextual(ContextualKeyword._readonly); + } + if (isContextual(ContextualKeyword._readonly)) { + next(); + } + if (!match(tt.bracketL)) { + return false; + } + next(); + if (!tsIsIdentifier()) { + return false; + } + next(); + return match(tt._in); +} + +function tsParseMappedTypeParameter() { + parseIdentifier(); + expect(tt._in); + tsParseType(); +} + +function tsParseMappedType() { + expect(tt.braceL); + if (match(tt.plus) || match(tt.minus)) { + next(); + expectContextual(ContextualKeyword._readonly); + } else { + eatContextual(ContextualKeyword._readonly); + } + expect(tt.bracketL); + tsParseMappedTypeParameter(); + if (eatContextual(ContextualKeyword._as)) { + tsParseType(); + } + expect(tt.bracketR); + if (match(tt.plus) || match(tt.minus)) { + next(); + expect(tt.question); + } else { + eat(tt.question); + } + tsTryParseType(); + semicolon(); + expect(tt.braceR); +} + +function tsParseTupleType() { + expect(tt.bracketL); + while (!eat(tt.bracketR) && !state.error) { + // Do not validate presence of either none or only labeled elements + tsParseTupleElementType(); + eat(tt.comma); + } +} + +function tsParseTupleElementType() { + // parses `...TsType[]` + if (eat(tt.ellipsis)) { + tsParseType(); + } else { + // parses `TsType?` + tsParseType(); + eat(tt.question); + } + + // The type we parsed above was actually a label + if (eat(tt.colon)) { + // Labeled tuple types must affix the label with `...` or `?`, so no need to handle those here + tsParseType(); + } +} + +function tsParseParenthesizedType() { + expect(tt.parenL); + tsParseType(); + expect(tt.parenR); +} + +function tsParseTemplateLiteralType() { + // Finish `, read quasi + nextTemplateToken(); + // Finish quasi, read ${ + nextTemplateToken(); + while (!match(tt.backQuote) && !state.error) { + expect(tt.dollarBraceL); + tsParseType(); + // Finish }, read quasi + nextTemplateToken(); + // Finish quasi, read either ${ or ` + nextTemplateToken(); + } + next(); +} + +var FunctionType; (function (FunctionType) { + const TSFunctionType = 0; FunctionType[FunctionType["TSFunctionType"] = TSFunctionType] = "TSFunctionType"; + const TSConstructorType = TSFunctionType + 1; FunctionType[FunctionType["TSConstructorType"] = TSConstructorType] = "TSConstructorType"; + const TSAbstractConstructorType = TSConstructorType + 1; FunctionType[FunctionType["TSAbstractConstructorType"] = TSAbstractConstructorType] = "TSAbstractConstructorType"; +})(FunctionType || (FunctionType = {})); + +function tsParseFunctionOrConstructorType(type) { + if (type === FunctionType.TSAbstractConstructorType) { + expectContextual(ContextualKeyword._abstract); + } + if (type === FunctionType.TSConstructorType || type === FunctionType.TSAbstractConstructorType) { + expect(tt._new); + } + const oldInDisallowConditionalTypesContext = state.inDisallowConditionalTypesContext; + state.inDisallowConditionalTypesContext = false; + tsFillSignature(tt.arrow); + state.inDisallowConditionalTypesContext = oldInDisallowConditionalTypesContext; +} + +function tsParseNonArrayType() { + switch (state.type) { + case tt.name: + tsParseTypeReference(); + return; + case tt._void: + case tt._null: + next(); + return; + case tt.string: + case tt.num: + case tt.bigint: + case tt.decimal: + case tt._true: + case tt._false: + parseLiteral(); + return; + case tt.minus: + next(); + parseLiteral(); + return; + case tt._this: { + tsParseThisTypeNode(); + if (isContextual(ContextualKeyword._is) && !hasPrecedingLineBreak()) { + tsParseThisTypePredicate(); + } + return; + } + case tt._typeof: + tsParseTypeQuery(); + return; + case tt._import: + tsParseImportType(); + return; + case tt.braceL: + if (tsLookaheadIsStartOfMappedType()) { + tsParseMappedType(); + } else { + tsParseTypeLiteral(); + } + return; + case tt.bracketL: + tsParseTupleType(); + return; + case tt.parenL: + tsParseParenthesizedType(); + return; + case tt.backQuote: + tsParseTemplateLiteralType(); + return; + default: + if (state.type & TokenType.IS_KEYWORD) { + next(); + state.tokens[state.tokens.length - 1].type = tt.name; + return; + } + break; + } + + unexpected(); +} + +function tsParseArrayTypeOrHigher() { + tsParseNonArrayType(); + while (!hasPrecedingLineBreak() && eat(tt.bracketL)) { + if (!eat(tt.bracketR)) { + // If we hit ] immediately, this is an array type, otherwise it's an indexed access type. + tsParseType(); + expect(tt.bracketR); + } + } +} + +function tsParseInferType() { + expectContextual(ContextualKeyword._infer); + parseIdentifier(); + if (match(tt._extends)) { + // Infer type constraints introduce an ambiguity about whether the "extends" + // is a constraint for this infer type or is another conditional type. + const snapshot = state.snapshot(); + expect(tt._extends); + const oldInDisallowConditionalTypesContext = state.inDisallowConditionalTypesContext; + state.inDisallowConditionalTypesContext = true; + tsParseType(); + state.inDisallowConditionalTypesContext = oldInDisallowConditionalTypesContext; + if (state.error || (!state.inDisallowConditionalTypesContext && match(tt.question))) { + state.restoreFromSnapshot(snapshot); + } + } +} + +function tsParseTypeOperatorOrHigher() { + if ( + isContextual(ContextualKeyword._keyof) || + isContextual(ContextualKeyword._unique) || + isContextual(ContextualKeyword._readonly) + ) { + next(); + tsParseTypeOperatorOrHigher(); + } else if (isContextual(ContextualKeyword._infer)) { + tsParseInferType(); + } else { + const oldInDisallowConditionalTypesContext = state.inDisallowConditionalTypesContext; + state.inDisallowConditionalTypesContext = false; + tsParseArrayTypeOrHigher(); + state.inDisallowConditionalTypesContext = oldInDisallowConditionalTypesContext; + } +} + +function tsParseIntersectionTypeOrHigher() { + eat(tt.bitwiseAND); + tsParseTypeOperatorOrHigher(); + if (match(tt.bitwiseAND)) { + while (eat(tt.bitwiseAND)) { + tsParseTypeOperatorOrHigher(); + } + } +} + +function tsParseUnionTypeOrHigher() { + eat(tt.bitwiseOR); + tsParseIntersectionTypeOrHigher(); + if (match(tt.bitwiseOR)) { + while (eat(tt.bitwiseOR)) { + tsParseIntersectionTypeOrHigher(); + } + } +} + +function tsIsStartOfFunctionType() { + if (match(tt.lessThan)) { + return true; + } + return match(tt.parenL) && tsLookaheadIsUnambiguouslyStartOfFunctionType(); +} + +function tsSkipParameterStart() { + if (match(tt.name) || match(tt._this)) { + next(); + return true; + } + // If this is a possible array/object destructure, walk to the matching bracket/brace. + // The next token after will tell us definitively whether this is a function param. + if (match(tt.braceL) || match(tt.bracketL)) { + let depth = 1; + next(); + while (depth > 0 && !state.error) { + if (match(tt.braceL) || match(tt.bracketL)) { + depth++; + } else if (match(tt.braceR) || match(tt.bracketR)) { + depth--; + } + next(); + } + return true; + } + return false; +} + +function tsLookaheadIsUnambiguouslyStartOfFunctionType() { + const snapshot = state.snapshot(); + const isUnambiguouslyStartOfFunctionType = tsIsUnambiguouslyStartOfFunctionType(); + state.restoreFromSnapshot(snapshot); + return isUnambiguouslyStartOfFunctionType; +} + +function tsIsUnambiguouslyStartOfFunctionType() { + next(); + if (match(tt.parenR) || match(tt.ellipsis)) { + // ( ) + // ( ... + return true; + } + if (tsSkipParameterStart()) { + if (match(tt.colon) || match(tt.comma) || match(tt.question) || match(tt.eq)) { + // ( xxx : + // ( xxx , + // ( xxx ? + // ( xxx = + return true; + } + if (match(tt.parenR)) { + next(); + if (match(tt.arrow)) { + // ( xxx ) => + return true; + } + } + } + return false; +} + +function tsParseTypeOrTypePredicateAnnotation(returnToken) { + const oldIsType = pushTypeContext(0); + expect(returnToken); + const finishedReturn = tsParseTypePredicateOrAssertsPrefix(); + if (!finishedReturn) { + tsParseType(); + } + popTypeContext(oldIsType); +} + +function tsTryParseTypeOrTypePredicateAnnotation() { + if (match(tt.colon)) { + tsParseTypeOrTypePredicateAnnotation(tt.colon); + } +} + +export function tsTryParseTypeAnnotation() { + if (match(tt.colon)) { + tsParseTypeAnnotation(); + } +} + +function tsTryParseType() { + if (eat(tt.colon)) { + tsParseType(); + } +} + +/** + * Detect a few special return syntax cases: `x is T`, `asserts x`, `asserts x is T`, + * `asserts this is T`. + * + * Returns true if we parsed the return type, false if there's still a type to be parsed. + */ +function tsParseTypePredicateOrAssertsPrefix() { + const snapshot = state.snapshot(); + if (isContextual(ContextualKeyword._asserts)) { + // Normally this is `asserts x is T`, but at this point, it might be `asserts is T` (a user- + // defined type guard on the `asserts` variable) or just a type called `asserts`. + next(); + if (eatContextual(ContextualKeyword._is)) { + // If we see `asserts is`, then this must be of the form `asserts is T`, since + // `asserts is is T` isn't valid. + tsParseType(); + return true; + } else if (tsIsIdentifier() || match(tt._this)) { + next(); + if (eatContextual(ContextualKeyword._is)) { + // If we see `is`, then this is `asserts x is T`. Otherwise, it's `asserts x`. + tsParseType(); + } + return true; + } else { + // Regular type, so bail out and start type parsing from scratch. + state.restoreFromSnapshot(snapshot); + return false; + } + } else if (tsIsIdentifier() || match(tt._this)) { + // This is a regular identifier, which may or may not have "is" after it. + next(); + if (isContextual(ContextualKeyword._is) && !hasPrecedingLineBreak()) { + next(); + tsParseType(); + return true; + } else { + // Regular type, so bail out and start type parsing from scratch. + state.restoreFromSnapshot(snapshot); + return false; + } + } + return false; +} + +export function tsParseTypeAnnotation() { + const oldIsType = pushTypeContext(0); + expect(tt.colon); + tsParseType(); + popTypeContext(oldIsType); +} + +export function tsParseType() { + tsParseNonConditionalType(); + if (state.inDisallowConditionalTypesContext || hasPrecedingLineBreak() || !eat(tt._extends)) { + return; + } + // extends type + const oldInDisallowConditionalTypesContext = state.inDisallowConditionalTypesContext; + state.inDisallowConditionalTypesContext = true; + tsParseNonConditionalType(); + state.inDisallowConditionalTypesContext = oldInDisallowConditionalTypesContext; + + expect(tt.question); + // true type + tsParseType(); + expect(tt.colon); + // false type + tsParseType(); +} + +function isAbstractConstructorSignature() { + return isContextual(ContextualKeyword._abstract) && lookaheadType() === tt._new; +} + +export function tsParseNonConditionalType() { + if (tsIsStartOfFunctionType()) { + tsParseFunctionOrConstructorType(FunctionType.TSFunctionType); + return; + } + if (match(tt._new)) { + // As in `new () => Date` + tsParseFunctionOrConstructorType(FunctionType.TSConstructorType); + return; + } else if (isAbstractConstructorSignature()) { + // As in `abstract new () => Date` + tsParseFunctionOrConstructorType(FunctionType.TSAbstractConstructorType); + return; + } + tsParseUnionTypeOrHigher(); +} + +export function tsParseTypeAssertion() { + const oldIsType = pushTypeContext(1); + tsParseType(); + expect(tt.greaterThan); + popTypeContext(oldIsType); + parseMaybeUnary(); +} + +export function tsTryParseJSXTypeArgument() { + if (eat(tt.jsxTagStart)) { + state.tokens[state.tokens.length - 1].type = tt.typeParameterStart; + const oldIsType = pushTypeContext(1); + while (!match(tt.greaterThan) && !state.error) { + tsParseType(); + eat(tt.comma); + } + // Process >, but the one after needs to be parsed JSX-style. + nextJSXTagToken(); + popTypeContext(oldIsType); + } +} + +function tsParseHeritageClause() { + while (!match(tt.braceL) && !state.error) { + tsParseExpressionWithTypeArguments(); + eat(tt.comma); + } +} + +function tsParseExpressionWithTypeArguments() { + // Note: TS uses parseLeftHandSideExpressionOrHigher, + // then has grammar errors later if it's not an EntityName. + tsParseEntityName(); + if (match(tt.lessThan)) { + tsParseTypeArguments(); + } +} + +function tsParseInterfaceDeclaration() { + parseBindingIdentifier(false); + tsTryParseTypeParameters(); + if (eat(tt._extends)) { + tsParseHeritageClause(); + } + tsParseObjectTypeMembers(); +} + +function tsParseTypeAliasDeclaration() { + parseBindingIdentifier(false); + tsTryParseTypeParameters(); + expect(tt.eq); + tsParseType(); + semicolon(); +} + +function tsParseEnumMember() { + // Computed property names are grammar errors in an enum, so accept just string literal or identifier. + if (match(tt.string)) { + parseLiteral(); + } else { + parseIdentifier(); + } + if (eat(tt.eq)) { + const eqIndex = state.tokens.length - 1; + parseMaybeAssign(); + state.tokens[eqIndex].rhsEndIndex = state.tokens.length; + } +} + +function tsParseEnumDeclaration() { + parseBindingIdentifier(false); + expect(tt.braceL); + while (!eat(tt.braceR) && !state.error) { + tsParseEnumMember(); + eat(tt.comma); + } +} + +function tsParseModuleBlock() { + expect(tt.braceL); + parseBlockBody(/* end */ tt.braceR); +} + +function tsParseModuleOrNamespaceDeclaration() { + parseBindingIdentifier(false); + if (eat(tt.dot)) { + tsParseModuleOrNamespaceDeclaration(); + } else { + tsParseModuleBlock(); + } +} + +function tsParseAmbientExternalModuleDeclaration() { + if (isContextual(ContextualKeyword._global)) { + parseIdentifier(); + } else if (match(tt.string)) { + parseExprAtom(); + } else { + unexpected(); + } + + if (match(tt.braceL)) { + tsParseModuleBlock(); + } else { + semicolon(); + } +} + +export function tsParseImportEqualsDeclaration() { + parseImportedIdentifier(); + expect(tt.eq); + tsParseModuleReference(); + semicolon(); +} + +function tsIsExternalModuleReference() { + return isContextual(ContextualKeyword._require) && lookaheadType() === tt.parenL; +} + +function tsParseModuleReference() { + if (tsIsExternalModuleReference()) { + tsParseExternalModuleReference(); + } else { + tsParseEntityName(); + } +} + +function tsParseExternalModuleReference() { + expectContextual(ContextualKeyword._require); + expect(tt.parenL); + if (!match(tt.string)) { + unexpected(); + } + parseLiteral(); + expect(tt.parenR); +} + +// Utilities + +// Returns true if a statement matched. +function tsTryParseDeclare() { + if (isLineTerminator()) { + return false; + } + switch (state.type) { + case tt._function: { + const oldIsType = pushTypeContext(1); + next(); + // We don't need to precisely get the function start here, since it's only used to mark + // the function as a type if it's bodiless, and it's already a type here. + const functionStart = state.start; + parseFunction(functionStart, /* isStatement */ true); + popTypeContext(oldIsType); + return true; + } + case tt._class: { + const oldIsType = pushTypeContext(1); + parseClass(/* isStatement */ true, /* optionalId */ false); + popTypeContext(oldIsType); + return true; + } + case tt._const: { + if (match(tt._const) && isLookaheadContextual(ContextualKeyword._enum)) { + const oldIsType = pushTypeContext(1); + // `const enum = 0;` not allowed because "enum" is a strict mode reserved word. + expect(tt._const); + expectContextual(ContextualKeyword._enum); + state.tokens[state.tokens.length - 1].type = tt._enum; + tsParseEnumDeclaration(); + popTypeContext(oldIsType); + return true; + } + } + // falls through + case tt._var: + case tt._let: { + const oldIsType = pushTypeContext(1); + parseVarStatement(state.type !== tt._var); + popTypeContext(oldIsType); + return true; + } + case tt.name: { + const oldIsType = pushTypeContext(1); + const contextualKeyword = state.contextualKeyword; + let matched = false; + if (contextualKeyword === ContextualKeyword._global) { + tsParseAmbientExternalModuleDeclaration(); + matched = true; + } else { + matched = tsParseDeclaration(contextualKeyword, /* isBeforeToken */ true); + } + popTypeContext(oldIsType); + return matched; + } + default: + return false; + } +} + +// Note: this won't be called unless the keyword is allowed in `shouldParseExportDeclaration`. +// Returns true if it matched a declaration. +function tsTryParseExportDeclaration() { + return tsParseDeclaration(state.contextualKeyword, /* isBeforeToken */ true); +} + +// Returns true if it matched a statement. +function tsParseExpressionStatement(contextualKeyword) { + switch (contextualKeyword) { + case ContextualKeyword._declare: { + const declareTokenIndex = state.tokens.length - 1; + const matched = tsTryParseDeclare(); + if (matched) { + state.tokens[declareTokenIndex].type = tt._declare; + return true; + } + break; + } + case ContextualKeyword._global: + // `global { }` (with no `declare`) may appear inside an ambient module declaration. + // Would like to use tsParseAmbientExternalModuleDeclaration here, but already ran past "global". + if (match(tt.braceL)) { + tsParseModuleBlock(); + return true; + } + break; + + default: + return tsParseDeclaration(contextualKeyword, /* isBeforeToken */ false); + } + return false; +} + +/** + * Common code for parsing a declaration. + * + * isBeforeToken indicates that the current parser state is at the contextual + * keyword (and that it is not yet emitted) rather than reading the token after + * it. When isBeforeToken is true, we may be preceded by an `export` token and + * should include that token in a type context we create, e.g. to handle + * `export interface` or `export type`. (This is a bit of a hack and should be + * cleaned up at some point.) + * + * Returns true if it matched a declaration. + */ +function tsParseDeclaration(contextualKeyword, isBeforeToken) { + switch (contextualKeyword) { + case ContextualKeyword._abstract: + if (tsCheckLineTerminator(isBeforeToken) && match(tt._class)) { + state.tokens[state.tokens.length - 1].type = tt._abstract; + parseClass(/* isStatement */ true, /* optionalId */ false); + return true; + } + break; + + case ContextualKeyword._enum: + if (tsCheckLineTerminator(isBeforeToken) && match(tt.name)) { + state.tokens[state.tokens.length - 1].type = tt._enum; + tsParseEnumDeclaration(); + return true; + } + break; + + case ContextualKeyword._interface: + if (tsCheckLineTerminator(isBeforeToken) && match(tt.name)) { + // `next` is true in "export" and "declare" contexts, so we want to remove that token + // as well. + const oldIsType = pushTypeContext(isBeforeToken ? 2 : 1); + tsParseInterfaceDeclaration(); + popTypeContext(oldIsType); + return true; + } + break; + + case ContextualKeyword._module: + if (tsCheckLineTerminator(isBeforeToken)) { + if (match(tt.string)) { + const oldIsType = pushTypeContext(isBeforeToken ? 2 : 1); + tsParseAmbientExternalModuleDeclaration(); + popTypeContext(oldIsType); + return true; + } else if (match(tt.name)) { + const oldIsType = pushTypeContext(isBeforeToken ? 2 : 1); + tsParseModuleOrNamespaceDeclaration(); + popTypeContext(oldIsType); + return true; + } + } + break; + + case ContextualKeyword._namespace: + if (tsCheckLineTerminator(isBeforeToken) && match(tt.name)) { + const oldIsType = pushTypeContext(isBeforeToken ? 2 : 1); + tsParseModuleOrNamespaceDeclaration(); + popTypeContext(oldIsType); + return true; + } + break; + + case ContextualKeyword._type: + if (tsCheckLineTerminator(isBeforeToken) && match(tt.name)) { + const oldIsType = pushTypeContext(isBeforeToken ? 2 : 1); + tsParseTypeAliasDeclaration(); + popTypeContext(oldIsType); + return true; + } + break; + + default: + break; + } + return false; +} + +function tsCheckLineTerminator(isBeforeToken) { + if (isBeforeToken) { + // Babel checks hasFollowingLineBreak here and returns false, but this + // doesn't actually come up, e.g. `export interface` can never be on its own + // line in valid code. + next(); + return true; + } else { + return !isLineTerminator(); + } +} + +// Returns true if there was a generic async arrow function. +function tsTryParseGenericAsyncArrowFunction() { + const snapshot = state.snapshot(); + + tsParseTypeParameters(); + parseFunctionParams(); + tsTryParseTypeOrTypePredicateAnnotation(); + expect(tt.arrow); + + if (state.error) { + state.restoreFromSnapshot(snapshot); + return false; + } + + parseFunctionBody(true); + return true; +} + +/** + * If necessary, hack the tokenizer state so that this bitshift was actually a + * less-than token, then keep parsing. This should only be used in situations + * where we restore from snapshot on error (which reverts this change) or + * where bitshift would be illegal anyway (e.g. in a class "extends" clause). + * + * This hack is useful to handle situations like foo<<T>() => void>() where + * there can legitimately be two open-angle-brackets in a row in TS. + */ +function tsParseTypeArgumentsWithPossibleBitshift() { + if (state.type === tt.bitShiftL) { + state.pos -= 1; + finishToken(tt.lessThan); + } + tsParseTypeArguments(); +} + +function tsParseTypeArguments() { + const oldIsType = pushTypeContext(0); + expect(tt.lessThan); + while (!match(tt.greaterThan) && !state.error) { + tsParseType(); + eat(tt.comma); + } + if (!oldIsType) { + // If the type arguments are present in an expression context, e.g. + // f<number>(), then the > sign should be tokenized as a non-type token. + // In particular, f(a < b, c >= d) should parse the >= as a single token, + // resulting in a syntax error and fallback to the non-type-args + // interpretation. In the success case, even though the > is tokenized as a + // non-type token, it still must be marked as a type token so that it is + // erased. + popTypeContext(oldIsType); + rescan_gt(); + expect(tt.greaterThan); + state.tokens[state.tokens.length - 1].isType = true; + } else { + expect(tt.greaterThan); + popTypeContext(oldIsType); + } +} + +export function tsIsDeclarationStart() { + if (match(tt.name)) { + switch (state.contextualKeyword) { + case ContextualKeyword._abstract: + case ContextualKeyword._declare: + case ContextualKeyword._enum: + case ContextualKeyword._interface: + case ContextualKeyword._module: + case ContextualKeyword._namespace: + case ContextualKeyword._type: + return true; + default: + break; + } + } + + return false; +} + +// ====================================================== +// OVERRIDES +// ====================================================== + +export function tsParseFunctionBodyAndFinish(functionStart, funcContextId) { + // For arrow functions, `parseArrow` handles the return type itself. + if (match(tt.colon)) { + tsParseTypeOrTypePredicateAnnotation(tt.colon); + } + + // The original code checked the node type to make sure this function type allows a missing + // body, but we skip that to avoid sending around the node type. We instead just use the + // allowExpressionBody boolean to make sure it's not an arrow function. + if (!match(tt.braceL) && isLineTerminator()) { + // Retroactively mark the function declaration as a type. + let i = state.tokens.length - 1; + while ( + i >= 0 && + (state.tokens[i].start >= functionStart || + state.tokens[i].type === tt._default || + state.tokens[i].type === tt._export) + ) { + state.tokens[i].isType = true; + i--; + } + return; + } + + parseFunctionBody(false, funcContextId); +} + +export function tsParseSubscript( + startTokenIndex, + noCalls, + stopState, +) { + if (!hasPrecedingLineBreak() && eat(tt.bang)) { + state.tokens[state.tokens.length - 1].type = tt.nonNullAssertion; + return; + } + + if (match(tt.lessThan) || match(tt.bitShiftL)) { + // There are number of things we are going to "maybe" parse, like type arguments on + // tagged template expressions. If any of them fail, walk it back and continue. + const snapshot = state.snapshot(); + + if (!noCalls && atPossibleAsync()) { + // Almost certainly this is a generic async function `async <T>() => ... + // But it might be a call with a type argument `async<T>();` + const asyncArrowFn = tsTryParseGenericAsyncArrowFunction(); + if (asyncArrowFn) { + return; + } + } + tsParseTypeArgumentsWithPossibleBitshift(); + if (!noCalls && eat(tt.parenL)) { + // With f<T>(), the subscriptStartIndex marker is on the ( token. + state.tokens[state.tokens.length - 1].subscriptStartIndex = startTokenIndex; + parseCallExpressionArguments(); + } else if (match(tt.backQuote)) { + // Tagged template with a type argument. + parseTemplate(); + } else if ( + // The remaining possible case is an instantiation expression, e.g. + // Array<number> . Check for a few cases that would disqualify it and + // cause us to bail out. + // a<b>>c is not (a<b>)>c, but a<(b>>c) + state.type === tt.greaterThan || + // a<b>c is (a<b)>c + (state.type !== tt.parenL && + Boolean(state.type & TokenType.IS_EXPRESSION_START) && + !hasPrecedingLineBreak()) + ) { + // Bail out. We have something like a<b>c, which is not an expression with + // type arguments but an (a < b) > c comparison. + unexpected(); + } + + if (state.error) { + state.restoreFromSnapshot(snapshot); + } else { + return; + } + } else if (!noCalls && match(tt.questionDot) && lookaheadType() === tt.lessThan) { + // If we see f?.<, then this must be an optional call with a type argument. + next(); + state.tokens[startTokenIndex].isOptionalChainStart = true; + // With f?.<T>(), the subscriptStartIndex marker is on the ?. token. + state.tokens[state.tokens.length - 1].subscriptStartIndex = startTokenIndex; + + tsParseTypeArguments(); + expect(tt.parenL); + parseCallExpressionArguments(); + } + baseParseSubscript(startTokenIndex, noCalls, stopState); +} + +export function tsTryParseExport() { + if (eat(tt._import)) { + // One of these cases: + // export import A = B; + // export import type A = require("A"); + if (isContextual(ContextualKeyword._type) && lookaheadType() !== tt.eq) { + // Eat a `type` token, unless it's actually an identifier name. + expectContextual(ContextualKeyword._type); + } + tsParseImportEqualsDeclaration(); + return true; + } else if (eat(tt.eq)) { + // `export = x;` + parseExpression(); + semicolon(); + return true; + } else if (eatContextual(ContextualKeyword._as)) { + // `export as namespace A;` + // See `parseNamespaceExportDeclaration` in TypeScript's own parser + expectContextual(ContextualKeyword._namespace); + parseIdentifier(); + semicolon(); + return true; + } else { + if (isContextual(ContextualKeyword._type)) { + const nextType = lookaheadType(); + // export type {foo} from 'a'; + // export type * from 'a';' + // export type * as ns from 'a';' + if (nextType === tt.braceL || nextType === tt.star) { + next(); + } + } + return false; + } +} + +/** + * Parse a TS import specifier, which may be prefixed with "type" and may be of + * the form `foo as bar`. + * + * The number of identifier-like tokens we see happens to be enough to uniquely + * identify the form, so simply count the number of identifiers rather than + * matching the words `type` or `as`. This is particularly important because + * `type` and `as` could each actually be plain identifiers rather than + * keywords. + */ +export function tsParseImportSpecifier() { + parseIdentifier(); + if (match(tt.comma) || match(tt.braceR)) { + // import {foo} + state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ImportDeclaration; + return; + } + parseIdentifier(); + if (match(tt.comma) || match(tt.braceR)) { + // import {type foo} + state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ImportDeclaration; + state.tokens[state.tokens.length - 2].isType = true; + state.tokens[state.tokens.length - 1].isType = true; + return; + } + parseIdentifier(); + if (match(tt.comma) || match(tt.braceR)) { + // import {foo as bar} + state.tokens[state.tokens.length - 3].identifierRole = IdentifierRole.ImportAccess; + state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ImportDeclaration; + return; + } + parseIdentifier(); + // import {type foo as bar} + state.tokens[state.tokens.length - 3].identifierRole = IdentifierRole.ImportAccess; + state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ImportDeclaration; + state.tokens[state.tokens.length - 4].isType = true; + state.tokens[state.tokens.length - 3].isType = true; + state.tokens[state.tokens.length - 2].isType = true; + state.tokens[state.tokens.length - 1].isType = true; +} + +/** + * Just like named import specifiers, export specifiers can have from 1 to 4 + * tokens, inclusive, and the number of tokens determines the role of each token. + */ +export function tsParseExportSpecifier() { + parseIdentifier(); + if (match(tt.comma) || match(tt.braceR)) { + // export {foo} + state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ExportAccess; + return; + } + parseIdentifier(); + if (match(tt.comma) || match(tt.braceR)) { + // export {type foo} + state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ExportAccess; + state.tokens[state.tokens.length - 2].isType = true; + state.tokens[state.tokens.length - 1].isType = true; + return; + } + parseIdentifier(); + if (match(tt.comma) || match(tt.braceR)) { + // export {foo as bar} + state.tokens[state.tokens.length - 3].identifierRole = IdentifierRole.ExportAccess; + return; + } + parseIdentifier(); + // export {type foo as bar} + state.tokens[state.tokens.length - 3].identifierRole = IdentifierRole.ExportAccess; + state.tokens[state.tokens.length - 4].isType = true; + state.tokens[state.tokens.length - 3].isType = true; + state.tokens[state.tokens.length - 2].isType = true; + state.tokens[state.tokens.length - 1].isType = true; +} + +export function tsTryParseExportDefaultExpression() { + if (isContextual(ContextualKeyword._abstract) && lookaheadType() === tt._class) { + state.type = tt._abstract; + next(); // Skip "abstract" + parseClass(true, true); + return true; + } + if (isContextual(ContextualKeyword._interface)) { + // Make sure "export default" are considered type tokens so the whole thing is removed. + const oldIsType = pushTypeContext(2); + tsParseDeclaration(ContextualKeyword._interface, true); + popTypeContext(oldIsType); + return true; + } + return false; +} + +export function tsTryParseStatementContent() { + if (state.type === tt._const) { + const ahead = lookaheadTypeAndKeyword(); + if (ahead.type === tt.name && ahead.contextualKeyword === ContextualKeyword._enum) { + expect(tt._const); + expectContextual(ContextualKeyword._enum); + state.tokens[state.tokens.length - 1].type = tt._enum; + tsParseEnumDeclaration(); + return true; + } + } + return false; +} + +export function tsTryParseClassMemberWithIsStatic(isStatic) { + const memberStartIndexAfterStatic = state.tokens.length; + tsParseModifiers([ + ContextualKeyword._abstract, + ContextualKeyword._readonly, + ContextualKeyword._declare, + ContextualKeyword._static, + ContextualKeyword._override, + ]); + + const modifiersEndIndex = state.tokens.length; + const found = tsTryParseIndexSignature(); + if (found) { + // Index signatures are type declarations, so set the modifier tokens as + // type tokens. Most tokens could be assumed to be type tokens, but `static` + // is ambiguous unless we set it explicitly here. + const memberStartIndex = isStatic + ? memberStartIndexAfterStatic - 1 + : memberStartIndexAfterStatic; + for (let i = memberStartIndex; i < modifiersEndIndex; i++) { + state.tokens[i].isType = true; + } + return true; + } + return false; +} + +// Note: The reason we do this in `parseIdentifierStatement` and not `parseStatement` +// is that e.g. `type()` is valid JS, so we must try parsing that first. +// If it's really a type, we will parse `type` as the statement, and can correct it here +// by parsing the rest. +export function tsParseIdentifierStatement(contextualKeyword) { + const matched = tsParseExpressionStatement(contextualKeyword); + if (!matched) { + semicolon(); + } +} + +export function tsParseExportDeclaration() { + // "export declare" is equivalent to just "export". + const isDeclare = eatContextual(ContextualKeyword._declare); + if (isDeclare) { + state.tokens[state.tokens.length - 1].type = tt._declare; + } + + let matchedDeclaration = false; + if (match(tt.name)) { + if (isDeclare) { + const oldIsType = pushTypeContext(2); + matchedDeclaration = tsTryParseExportDeclaration(); + popTypeContext(oldIsType); + } else { + matchedDeclaration = tsTryParseExportDeclaration(); + } + } + if (!matchedDeclaration) { + if (isDeclare) { + const oldIsType = pushTypeContext(2); + parseStatement(true); + popTypeContext(oldIsType); + } else { + parseStatement(true); + } + } +} + +export function tsAfterParseClassSuper(hasSuper) { + if (hasSuper && (match(tt.lessThan) || match(tt.bitShiftL))) { + tsParseTypeArgumentsWithPossibleBitshift(); + } + if (eatContextual(ContextualKeyword._implements)) { + state.tokens[state.tokens.length - 1].type = tt._implements; + const oldIsType = pushTypeContext(1); + tsParseHeritageClause(); + popTypeContext(oldIsType); + } +} + +export function tsStartParseObjPropValue() { + tsTryParseTypeParameters(); +} + +export function tsStartParseFunctionParams() { + tsTryParseTypeParameters(); +} + +// `let x: number;` +export function tsAfterParseVarHead() { + const oldIsType = pushTypeContext(0); + if (!hasPrecedingLineBreak()) { + eat(tt.bang); + } + tsTryParseTypeAnnotation(); + popTypeContext(oldIsType); +} + +// parse the return type of an async arrow function - let foo = (async (): number => {}); +export function tsStartParseAsyncArrowFromCallExpression() { + if (match(tt.colon)) { + tsParseTypeAnnotation(); + } +} + +// Returns true if the expression was an arrow function. +export function tsParseMaybeAssign(noIn, isWithinParens) { + // Note: When the JSX plugin is on, type assertions (`<T> x`) aren't valid syntax. + if (isJSXEnabled) { + return tsParseMaybeAssignWithJSX(noIn, isWithinParens); + } else { + return tsParseMaybeAssignWithoutJSX(noIn, isWithinParens); + } +} + +export function tsParseMaybeAssignWithJSX(noIn, isWithinParens) { + if (!match(tt.lessThan)) { + return baseParseMaybeAssign(noIn, isWithinParens); + } + + // Prefer to parse JSX if possible. But may be an arrow fn. + const snapshot = state.snapshot(); + let wasArrow = baseParseMaybeAssign(noIn, isWithinParens); + if (state.error) { + state.restoreFromSnapshot(snapshot); + } else { + return wasArrow; + } + + // Otherwise, try as type-parameterized arrow function. + state.type = tt.typeParameterStart; + // This is similar to TypeScript's `tryParseParenthesizedArrowFunctionExpression`. + tsParseTypeParameters(); + wasArrow = baseParseMaybeAssign(noIn, isWithinParens); + if (!wasArrow) { + unexpected(); + } + + return wasArrow; +} + +export function tsParseMaybeAssignWithoutJSX(noIn, isWithinParens) { + if (!match(tt.lessThan)) { + return baseParseMaybeAssign(noIn, isWithinParens); + } + + const snapshot = state.snapshot(); + // This is similar to TypeScript's `tryParseParenthesizedArrowFunctionExpression`. + tsParseTypeParameters(); + const wasArrow = baseParseMaybeAssign(noIn, isWithinParens); + if (!wasArrow) { + unexpected(); + } + if (state.error) { + state.restoreFromSnapshot(snapshot); + } else { + return wasArrow; + } + + // Try parsing a type cast instead of an arrow function. + // This will start with a type assertion (via parseMaybeUnary). + // But don't directly call `tsParseTypeAssertion` because we want to handle any binary after it. + return baseParseMaybeAssign(noIn, isWithinParens); +} + +export function tsParseArrow() { + if (match(tt.colon)) { + // This is different from how the TS parser does it. + // TS uses lookahead. Babylon parses it as a parenthesized expression and converts. + const snapshot = state.snapshot(); + + tsParseTypeOrTypePredicateAnnotation(tt.colon); + if (canInsertSemicolon()) unexpected(); + if (!match(tt.arrow)) unexpected(); + + if (state.error) { + state.restoreFromSnapshot(snapshot); + } + } + return eat(tt.arrow); +} + +// Allow type annotations inside of a parameter list. +export function tsParseAssignableListItemTypes() { + const oldIsType = pushTypeContext(0); + eat(tt.question); + tsTryParseTypeAnnotation(); + popTypeContext(oldIsType); +} + +export function tsParseMaybeDecoratorArguments() { + if (match(tt.lessThan) || match(tt.bitShiftL)) { + tsParseTypeArgumentsWithPossibleBitshift(); + } + baseParseMaybeDecoratorArguments(); +} diff --git a/node_modules/sucrase/dist/esm/parser/tokenizer/index.js b/node_modules/sucrase/dist/esm/parser/tokenizer/index.js new file mode 100644 index 0000000..69f286a --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/tokenizer/index.js @@ -0,0 +1,1004 @@ +/* eslint max-len: 0 */ + +import {input, isFlowEnabled, state} from "../traverser/base"; +import {unexpected} from "../traverser/util"; +import {charCodes} from "../util/charcodes"; +import {IS_IDENTIFIER_CHAR, IS_IDENTIFIER_START} from "../util/identifier"; +import {IS_WHITESPACE, skipWhiteSpace} from "../util/whitespace"; +import {ContextualKeyword} from "./keywords"; +import readWord from "./readWord"; +import { TokenType as tt} from "./types"; + +export var IdentifierRole; (function (IdentifierRole) { + const Access = 0; IdentifierRole[IdentifierRole["Access"] = Access] = "Access"; + const ExportAccess = Access + 1; IdentifierRole[IdentifierRole["ExportAccess"] = ExportAccess] = "ExportAccess"; + const TopLevelDeclaration = ExportAccess + 1; IdentifierRole[IdentifierRole["TopLevelDeclaration"] = TopLevelDeclaration] = "TopLevelDeclaration"; + const FunctionScopedDeclaration = TopLevelDeclaration + 1; IdentifierRole[IdentifierRole["FunctionScopedDeclaration"] = FunctionScopedDeclaration] = "FunctionScopedDeclaration"; + const BlockScopedDeclaration = FunctionScopedDeclaration + 1; IdentifierRole[IdentifierRole["BlockScopedDeclaration"] = BlockScopedDeclaration] = "BlockScopedDeclaration"; + const ObjectShorthandTopLevelDeclaration = BlockScopedDeclaration + 1; IdentifierRole[IdentifierRole["ObjectShorthandTopLevelDeclaration"] = ObjectShorthandTopLevelDeclaration] = "ObjectShorthandTopLevelDeclaration"; + const ObjectShorthandFunctionScopedDeclaration = ObjectShorthandTopLevelDeclaration + 1; IdentifierRole[IdentifierRole["ObjectShorthandFunctionScopedDeclaration"] = ObjectShorthandFunctionScopedDeclaration] = "ObjectShorthandFunctionScopedDeclaration"; + const ObjectShorthandBlockScopedDeclaration = ObjectShorthandFunctionScopedDeclaration + 1; IdentifierRole[IdentifierRole["ObjectShorthandBlockScopedDeclaration"] = ObjectShorthandBlockScopedDeclaration] = "ObjectShorthandBlockScopedDeclaration"; + const ObjectShorthand = ObjectShorthandBlockScopedDeclaration + 1; IdentifierRole[IdentifierRole["ObjectShorthand"] = ObjectShorthand] = "ObjectShorthand"; + // Any identifier bound in an import statement, e.g. both A and b from + // `import A, * as b from 'A';` + const ImportDeclaration = ObjectShorthand + 1; IdentifierRole[IdentifierRole["ImportDeclaration"] = ImportDeclaration] = "ImportDeclaration"; + const ObjectKey = ImportDeclaration + 1; IdentifierRole[IdentifierRole["ObjectKey"] = ObjectKey] = "ObjectKey"; + // The `foo` in `import {foo as bar} from "./abc";`. + const ImportAccess = ObjectKey + 1; IdentifierRole[IdentifierRole["ImportAccess"] = ImportAccess] = "ImportAccess"; +})(IdentifierRole || (IdentifierRole = {})); + +/** + * Extra information on jsxTagStart tokens, used to determine which of the three + * jsx functions are called in the automatic transform. + */ +export var JSXRole; (function (JSXRole) { + // The element is self-closing or has a body that resolves to empty. We + // shouldn't emit children at all in this case. + const NoChildren = 0; JSXRole[JSXRole["NoChildren"] = NoChildren] = "NoChildren"; + // The element has a single explicit child, which might still be an arbitrary + // expression like an array. We should emit that expression as the children. + const OneChild = NoChildren + 1; JSXRole[JSXRole["OneChild"] = OneChild] = "OneChild"; + // The element has at least two explicitly-specified children or has spread + // children, so child positions are assumed to be "static". We should wrap + // these children in an array. + const StaticChildren = OneChild + 1; JSXRole[JSXRole["StaticChildren"] = StaticChildren] = "StaticChildren"; + // The element has a prop named "key" after a prop spread, so we should fall + // back to the createElement function. + const KeyAfterPropSpread = StaticChildren + 1; JSXRole[JSXRole["KeyAfterPropSpread"] = KeyAfterPropSpread] = "KeyAfterPropSpread"; +})(JSXRole || (JSXRole = {})); + +export function isDeclaration(token) { + const role = token.identifierRole; + return ( + role === IdentifierRole.TopLevelDeclaration || + role === IdentifierRole.FunctionScopedDeclaration || + role === IdentifierRole.BlockScopedDeclaration || + role === IdentifierRole.ObjectShorthandTopLevelDeclaration || + role === IdentifierRole.ObjectShorthandFunctionScopedDeclaration || + role === IdentifierRole.ObjectShorthandBlockScopedDeclaration + ); +} + +export function isNonTopLevelDeclaration(token) { + const role = token.identifierRole; + return ( + role === IdentifierRole.FunctionScopedDeclaration || + role === IdentifierRole.BlockScopedDeclaration || + role === IdentifierRole.ObjectShorthandFunctionScopedDeclaration || + role === IdentifierRole.ObjectShorthandBlockScopedDeclaration + ); +} + +export function isTopLevelDeclaration(token) { + const role = token.identifierRole; + return ( + role === IdentifierRole.TopLevelDeclaration || + role === IdentifierRole.ObjectShorthandTopLevelDeclaration || + role === IdentifierRole.ImportDeclaration + ); +} + +export function isBlockScopedDeclaration(token) { + const role = token.identifierRole; + // Treat top-level declarations as block scope since the distinction doesn't matter here. + return ( + role === IdentifierRole.TopLevelDeclaration || + role === IdentifierRole.BlockScopedDeclaration || + role === IdentifierRole.ObjectShorthandTopLevelDeclaration || + role === IdentifierRole.ObjectShorthandBlockScopedDeclaration + ); +} + +export function isFunctionScopedDeclaration(token) { + const role = token.identifierRole; + return ( + role === IdentifierRole.FunctionScopedDeclaration || + role === IdentifierRole.ObjectShorthandFunctionScopedDeclaration + ); +} + +export function isObjectShorthandDeclaration(token) { + return ( + token.identifierRole === IdentifierRole.ObjectShorthandTopLevelDeclaration || + token.identifierRole === IdentifierRole.ObjectShorthandBlockScopedDeclaration || + token.identifierRole === IdentifierRole.ObjectShorthandFunctionScopedDeclaration + ); +} + +// Object type used to represent tokens. Note that normally, tokens +// simply exist as properties on the parser object. This is only +// used for the onToken callback and the external tokenizer. +export class Token { + constructor() { + this.type = state.type; + this.contextualKeyword = state.contextualKeyword; + this.start = state.start; + this.end = state.end; + this.scopeDepth = state.scopeDepth; + this.isType = state.isType; + this.identifierRole = null; + this.jsxRole = null; + this.shadowsGlobal = false; + this.isAsyncOperation = false; + this.contextId = null; + this.rhsEndIndex = null; + this.isExpression = false; + this.numNullishCoalesceStarts = 0; + this.numNullishCoalesceEnds = 0; + this.isOptionalChainStart = false; + this.isOptionalChainEnd = false; + this.subscriptStartIndex = null; + this.nullishStartIndex = null; + } + + + + + + + + + + // Initially false for all tokens, then may be computed in a follow-up step that does scope + // analysis. + + // Initially false for all tokens, but may be set during transform to mark it as containing an + // await operation. + + + // For assignments, the index of the RHS. For export tokens, the end of the export. + + // For class tokens, records if the class is a class expression or a class statement. + + // Number of times to insert a `nullishCoalesce(` snippet before this token. + + // Number of times to insert a `)` snippet after this token. + + // If true, insert an `optionalChain([` snippet before this token. + + // If true, insert a `])` snippet after this token. + + // Tag for `.`, `?.`, `[`, `?.[`, `(`, and `?.(` to denote the "root" token for this + // subscript chain. This can be used to determine if this chain is an optional chain. + + // Tag for `??` operators to denote the root token for this nullish coalescing call. + +} + +// ## Tokenizer + +// Move to the next token +export function next() { + state.tokens.push(new Token()); + nextToken(); +} + +// Call instead of next when inside a template, since that needs to be handled differently. +export function nextTemplateToken() { + state.tokens.push(new Token()); + state.start = state.pos; + readTmplToken(); +} + +// The tokenizer never parses regexes by default. Instead, the parser is responsible for +// instructing it to parse a regex when we see a slash at the start of an expression. +export function retokenizeSlashAsRegex() { + if (state.type === tt.assign) { + --state.pos; + } + readRegexp(); +} + +export function pushTypeContext(existingTokensInType) { + for (let i = state.tokens.length - existingTokensInType; i < state.tokens.length; i++) { + state.tokens[i].isType = true; + } + const oldIsType = state.isType; + state.isType = true; + return oldIsType; +} + +export function popTypeContext(oldIsType) { + state.isType = oldIsType; +} + +export function eat(type) { + if (match(type)) { + next(); + return true; + } else { + return false; + } +} + +export function eatTypeToken(tokenType) { + const oldIsType = state.isType; + state.isType = true; + eat(tokenType); + state.isType = oldIsType; +} + +export function match(type) { + return state.type === type; +} + +export function lookaheadType() { + const snapshot = state.snapshot(); + next(); + const type = state.type; + state.restoreFromSnapshot(snapshot); + return type; +} + +export class TypeAndKeyword { + + + constructor(type, contextualKeyword) { + this.type = type; + this.contextualKeyword = contextualKeyword; + } +} + +export function lookaheadTypeAndKeyword() { + const snapshot = state.snapshot(); + next(); + const type = state.type; + const contextualKeyword = state.contextualKeyword; + state.restoreFromSnapshot(snapshot); + return new TypeAndKeyword(type, contextualKeyword); +} + +export function nextTokenStart() { + return nextTokenStartSince(state.pos); +} + +export function nextTokenStartSince(pos) { + skipWhiteSpace.lastIndex = pos; + const skip = skipWhiteSpace.exec(input); + return pos + skip[0].length; +} + +export function lookaheadCharCode() { + return input.charCodeAt(nextTokenStart()); +} + +// Read a single token, updating the parser object's token-related +// properties. +export function nextToken() { + skipSpace(); + state.start = state.pos; + if (state.pos >= input.length) { + const tokens = state.tokens; + // We normally run past the end a bit, but if we're way past the end, avoid an infinite loop. + // Also check the token positions rather than the types since sometimes we rewrite the token + // type to something else. + if ( + tokens.length >= 2 && + tokens[tokens.length - 1].start >= input.length && + tokens[tokens.length - 2].start >= input.length + ) { + unexpected("Unexpectedly reached the end of input."); + } + finishToken(tt.eof); + return; + } + readToken(input.charCodeAt(state.pos)); +} + +function readToken(code) { + // Identifier or keyword. '\uXXXX' sequences are allowed in + // identifiers, so '\' also dispatches to that. + if ( + IS_IDENTIFIER_START[code] || + code === charCodes.backslash || + (code === charCodes.atSign && input.charCodeAt(state.pos + 1) === charCodes.atSign) + ) { + readWord(); + } else { + getTokenFromCode(code); + } +} + +function skipBlockComment() { + while ( + input.charCodeAt(state.pos) !== charCodes.asterisk || + input.charCodeAt(state.pos + 1) !== charCodes.slash + ) { + state.pos++; + if (state.pos > input.length) { + unexpected("Unterminated comment", state.pos - 2); + return; + } + } + state.pos += 2; +} + +export function skipLineComment(startSkip) { + let ch = input.charCodeAt((state.pos += startSkip)); + if (state.pos < input.length) { + while ( + ch !== charCodes.lineFeed && + ch !== charCodes.carriageReturn && + ch !== charCodes.lineSeparator && + ch !== charCodes.paragraphSeparator && + ++state.pos < input.length + ) { + ch = input.charCodeAt(state.pos); + } + } +} + +// Called at the start of the parse and after every token. Skips +// whitespace and comments. +export function skipSpace() { + while (state.pos < input.length) { + const ch = input.charCodeAt(state.pos); + switch (ch) { + case charCodes.carriageReturn: + if (input.charCodeAt(state.pos + 1) === charCodes.lineFeed) { + ++state.pos; + } + + case charCodes.lineFeed: + case charCodes.lineSeparator: + case charCodes.paragraphSeparator: + ++state.pos; + break; + + case charCodes.slash: + switch (input.charCodeAt(state.pos + 1)) { + case charCodes.asterisk: + state.pos += 2; + skipBlockComment(); + break; + + case charCodes.slash: + skipLineComment(2); + break; + + default: + return; + } + break; + + default: + if (IS_WHITESPACE[ch]) { + ++state.pos; + } else { + return; + } + } + } +} + +// Called at the end of every token. Sets various fields, and skips the space after the token, so +// that the next one's `start` will point at the right position. +export function finishToken( + type, + contextualKeyword = ContextualKeyword.NONE, +) { + state.end = state.pos; + state.type = type; + state.contextualKeyword = contextualKeyword; +} + +// ### Token reading + +// This is the function that is called to fetch the next token. It +// is somewhat obscure, because it works in character codes rather +// than characters, and because operator parsing has been inlined +// into it. +// +// All in the name of speed. +function readToken_dot() { + const nextChar = input.charCodeAt(state.pos + 1); + if (nextChar >= charCodes.digit0 && nextChar <= charCodes.digit9) { + readNumber(true); + return; + } + + if (nextChar === charCodes.dot && input.charCodeAt(state.pos + 2) === charCodes.dot) { + state.pos += 3; + finishToken(tt.ellipsis); + } else { + ++state.pos; + finishToken(tt.dot); + } +} + +function readToken_slash() { + const nextChar = input.charCodeAt(state.pos + 1); + if (nextChar === charCodes.equalsTo) { + finishOp(tt.assign, 2); + } else { + finishOp(tt.slash, 1); + } +} + +function readToken_mult_modulo(code) { + // '%*' + let tokenType = code === charCodes.asterisk ? tt.star : tt.modulo; + let width = 1; + let nextChar = input.charCodeAt(state.pos + 1); + + // Exponentiation operator ** + if (code === charCodes.asterisk && nextChar === charCodes.asterisk) { + width++; + nextChar = input.charCodeAt(state.pos + 2); + tokenType = tt.exponent; + } + + // Match *= or %=, disallowing *=> which can be valid in flow. + if ( + nextChar === charCodes.equalsTo && + input.charCodeAt(state.pos + 2) !== charCodes.greaterThan + ) { + width++; + tokenType = tt.assign; + } + + finishOp(tokenType, width); +} + +function readToken_pipe_amp(code) { + // '|&' + const nextChar = input.charCodeAt(state.pos + 1); + + if (nextChar === code) { + if (input.charCodeAt(state.pos + 2) === charCodes.equalsTo) { + // ||= or &&= + finishOp(tt.assign, 3); + } else { + // || or && + finishOp(code === charCodes.verticalBar ? tt.logicalOR : tt.logicalAND, 2); + } + return; + } + + if (code === charCodes.verticalBar) { + // '|>' + if (nextChar === charCodes.greaterThan) { + finishOp(tt.pipeline, 2); + return; + } else if (nextChar === charCodes.rightCurlyBrace && isFlowEnabled) { + // '|}' + finishOp(tt.braceBarR, 2); + return; + } + } + + if (nextChar === charCodes.equalsTo) { + finishOp(tt.assign, 2); + return; + } + + finishOp(code === charCodes.verticalBar ? tt.bitwiseOR : tt.bitwiseAND, 1); +} + +function readToken_caret() { + // '^' + const nextChar = input.charCodeAt(state.pos + 1); + if (nextChar === charCodes.equalsTo) { + finishOp(tt.assign, 2); + } else { + finishOp(tt.bitwiseXOR, 1); + } +} + +function readToken_plus_min(code) { + // '+-' + const nextChar = input.charCodeAt(state.pos + 1); + + if (nextChar === code) { + // Tentatively call this a prefix operator, but it might be changed to postfix later. + finishOp(tt.preIncDec, 2); + return; + } + + if (nextChar === charCodes.equalsTo) { + finishOp(tt.assign, 2); + } else if (code === charCodes.plusSign) { + finishOp(tt.plus, 1); + } else { + finishOp(tt.minus, 1); + } +} + +function readToken_lt() { + const nextChar = input.charCodeAt(state.pos + 1); + + if (nextChar === charCodes.lessThan) { + if (input.charCodeAt(state.pos + 2) === charCodes.equalsTo) { + finishOp(tt.assign, 3); + return; + } + // We see <<, but need to be really careful about whether to treat it as a + // true left-shift or as two < tokens. + if (state.isType) { + // Within a type, << might come up in a snippet like `Array<<T>() => void>`, + // so treat it as two < tokens. Importantly, this should only override << + // rather than other tokens like <= . If we treated <= as < in a type + // context, then the snippet `a as T <= 1` would incorrectly start parsing + // a type argument on T. We don't need to worry about `a as T << 1` + // because TypeScript disallows that syntax. + finishOp(tt.lessThan, 1); + } else { + // Outside a type, this might be a true left-shift operator, or it might + // still be two open-type-arg tokens, such as in `f<<T>() => void>()`. We + // look at the token while considering the `f`, so we don't yet know that + // we're in a type context. In this case, we initially tokenize as a + // left-shift and correct after-the-fact as necessary in + // tsParseTypeArgumentsWithPossibleBitshift . + finishOp(tt.bitShiftL, 2); + } + return; + } + + if (nextChar === charCodes.equalsTo) { + // <= + finishOp(tt.relationalOrEqual, 2); + } else { + finishOp(tt.lessThan, 1); + } +} + +function readToken_gt() { + if (state.isType) { + // Avoid right-shift for things like `Array<Array<string>>` and + // greater-than-or-equal for things like `const a: Array<number>=[];`. + finishOp(tt.greaterThan, 1); + return; + } + + const nextChar = input.charCodeAt(state.pos + 1); + + if (nextChar === charCodes.greaterThan) { + const size = input.charCodeAt(state.pos + 2) === charCodes.greaterThan ? 3 : 2; + if (input.charCodeAt(state.pos + size) === charCodes.equalsTo) { + finishOp(tt.assign, size + 1); + return; + } + finishOp(tt.bitShiftR, size); + return; + } + + if (nextChar === charCodes.equalsTo) { + // >= + finishOp(tt.relationalOrEqual, 2); + } else { + finishOp(tt.greaterThan, 1); + } +} + +/** + * Reinterpret a possible > token when transitioning from a type to a non-type + * context. + * + * This comes up in two situations where >= needs to be treated as one token: + * - After an `as` expression, like in the code `a as T >= 1`. + * - In a type argument in an expression context, e.g. `f(a < b, c >= d)`, we + * need to see the token as >= so that we get an error and backtrack to + * normal expression parsing. + * + * Other situations require >= to be seen as two tokens, e.g. + * `const x: Array<T>=[];`, so it's important to treat > as its own token in + * typical type parsing situations. + */ +export function rescan_gt() { + if (state.type === tt.greaterThan) { + state.pos -= 1; + readToken_gt(); + } +} + +function readToken_eq_excl(code) { + // '=!' + const nextChar = input.charCodeAt(state.pos + 1); + if (nextChar === charCodes.equalsTo) { + finishOp(tt.equality, input.charCodeAt(state.pos + 2) === charCodes.equalsTo ? 3 : 2); + return; + } + if (code === charCodes.equalsTo && nextChar === charCodes.greaterThan) { + // '=>' + state.pos += 2; + finishToken(tt.arrow); + return; + } + finishOp(code === charCodes.equalsTo ? tt.eq : tt.bang, 1); +} + +function readToken_question() { + // '?' + const nextChar = input.charCodeAt(state.pos + 1); + const nextChar2 = input.charCodeAt(state.pos + 2); + if ( + nextChar === charCodes.questionMark && + // In Flow (but not TypeScript), ??string is a valid type that should be + // tokenized as two individual ? tokens. + !(isFlowEnabled && state.isType) + ) { + if (nextChar2 === charCodes.equalsTo) { + // '??=' + finishOp(tt.assign, 3); + } else { + // '??' + finishOp(tt.nullishCoalescing, 2); + } + } else if ( + nextChar === charCodes.dot && + !(nextChar2 >= charCodes.digit0 && nextChar2 <= charCodes.digit9) + ) { + // '.' not followed by a number + state.pos += 2; + finishToken(tt.questionDot); + } else { + ++state.pos; + finishToken(tt.question); + } +} + +export function getTokenFromCode(code) { + switch (code) { + case charCodes.numberSign: + ++state.pos; + finishToken(tt.hash); + return; + + // The interpretation of a dot depends on whether it is followed + // by a digit or another two dots. + + case charCodes.dot: + readToken_dot(); + return; + + // Punctuation tokens. + case charCodes.leftParenthesis: + ++state.pos; + finishToken(tt.parenL); + return; + case charCodes.rightParenthesis: + ++state.pos; + finishToken(tt.parenR); + return; + case charCodes.semicolon: + ++state.pos; + finishToken(tt.semi); + return; + case charCodes.comma: + ++state.pos; + finishToken(tt.comma); + return; + case charCodes.leftSquareBracket: + ++state.pos; + finishToken(tt.bracketL); + return; + case charCodes.rightSquareBracket: + ++state.pos; + finishToken(tt.bracketR); + return; + + case charCodes.leftCurlyBrace: + if (isFlowEnabled && input.charCodeAt(state.pos + 1) === charCodes.verticalBar) { + finishOp(tt.braceBarL, 2); + } else { + ++state.pos; + finishToken(tt.braceL); + } + return; + + case charCodes.rightCurlyBrace: + ++state.pos; + finishToken(tt.braceR); + return; + + case charCodes.colon: + if (input.charCodeAt(state.pos + 1) === charCodes.colon) { + finishOp(tt.doubleColon, 2); + } else { + ++state.pos; + finishToken(tt.colon); + } + return; + + case charCodes.questionMark: + readToken_question(); + return; + case charCodes.atSign: + ++state.pos; + finishToken(tt.at); + return; + + case charCodes.graveAccent: + ++state.pos; + finishToken(tt.backQuote); + return; + + case charCodes.digit0: { + const nextChar = input.charCodeAt(state.pos + 1); + // '0x', '0X', '0o', '0O', '0b', '0B' + if ( + nextChar === charCodes.lowercaseX || + nextChar === charCodes.uppercaseX || + nextChar === charCodes.lowercaseO || + nextChar === charCodes.uppercaseO || + nextChar === charCodes.lowercaseB || + nextChar === charCodes.uppercaseB + ) { + readRadixNumber(); + return; + } + } + // Anything else beginning with a digit is an integer, octal + // number, or float. + case charCodes.digit1: + case charCodes.digit2: + case charCodes.digit3: + case charCodes.digit4: + case charCodes.digit5: + case charCodes.digit6: + case charCodes.digit7: + case charCodes.digit8: + case charCodes.digit9: + readNumber(false); + return; + + // Quotes produce strings. + case charCodes.quotationMark: + case charCodes.apostrophe: + readString(code); + return; + + // Operators are parsed inline in tiny state machines. '=' (charCodes.equalsTo) is + // often referred to. `finishOp` simply skips the amount of + // characters it is given as second argument, and returns a token + // of the type given by its first argument. + + case charCodes.slash: + readToken_slash(); + return; + + case charCodes.percentSign: + case charCodes.asterisk: + readToken_mult_modulo(code); + return; + + case charCodes.verticalBar: + case charCodes.ampersand: + readToken_pipe_amp(code); + return; + + case charCodes.caret: + readToken_caret(); + return; + + case charCodes.plusSign: + case charCodes.dash: + readToken_plus_min(code); + return; + + case charCodes.lessThan: + readToken_lt(); + return; + + case charCodes.greaterThan: + readToken_gt(); + return; + + case charCodes.equalsTo: + case charCodes.exclamationMark: + readToken_eq_excl(code); + return; + + case charCodes.tilde: + finishOp(tt.tilde, 1); + return; + + default: + break; + } + + unexpected(`Unexpected character '${String.fromCharCode(code)}'`, state.pos); +} + +function finishOp(type, size) { + state.pos += size; + finishToken(type); +} + +function readRegexp() { + const start = state.pos; + let escaped = false; + let inClass = false; + for (;;) { + if (state.pos >= input.length) { + unexpected("Unterminated regular expression", start); + return; + } + const code = input.charCodeAt(state.pos); + if (escaped) { + escaped = false; + } else { + if (code === charCodes.leftSquareBracket) { + inClass = true; + } else if (code === charCodes.rightSquareBracket && inClass) { + inClass = false; + } else if (code === charCodes.slash && !inClass) { + break; + } + escaped = code === charCodes.backslash; + } + ++state.pos; + } + ++state.pos; + // Need to use `skipWord` because '\uXXXX' sequences are allowed here (don't ask). + skipWord(); + + finishToken(tt.regexp); +} + +/** + * Read a decimal integer. Note that this can't be unified with the similar code + * in readRadixNumber (which also handles hex digits) because "e" needs to be + * the end of the integer so that we can properly handle scientific notation. + */ +function readInt() { + while (true) { + const code = input.charCodeAt(state.pos); + if ((code >= charCodes.digit0 && code <= charCodes.digit9) || code === charCodes.underscore) { + state.pos++; + } else { + break; + } + } +} + +function readRadixNumber() { + state.pos += 2; // 0x + + // Walk to the end of the number, allowing hex digits. + while (true) { + const code = input.charCodeAt(state.pos); + if ( + (code >= charCodes.digit0 && code <= charCodes.digit9) || + (code >= charCodes.lowercaseA && code <= charCodes.lowercaseF) || + (code >= charCodes.uppercaseA && code <= charCodes.uppercaseF) || + code === charCodes.underscore + ) { + state.pos++; + } else { + break; + } + } + + const nextChar = input.charCodeAt(state.pos); + if (nextChar === charCodes.lowercaseN) { + ++state.pos; + finishToken(tt.bigint); + } else { + finishToken(tt.num); + } +} + +// Read an integer, octal integer, or floating-point number. +function readNumber(startsWithDot) { + let isBigInt = false; + let isDecimal = false; + + if (!startsWithDot) { + readInt(); + } + + let nextChar = input.charCodeAt(state.pos); + if (nextChar === charCodes.dot) { + ++state.pos; + readInt(); + nextChar = input.charCodeAt(state.pos); + } + + if (nextChar === charCodes.uppercaseE || nextChar === charCodes.lowercaseE) { + nextChar = input.charCodeAt(++state.pos); + if (nextChar === charCodes.plusSign || nextChar === charCodes.dash) { + ++state.pos; + } + readInt(); + nextChar = input.charCodeAt(state.pos); + } + + if (nextChar === charCodes.lowercaseN) { + ++state.pos; + isBigInt = true; + } else if (nextChar === charCodes.lowercaseM) { + ++state.pos; + isDecimal = true; + } + + if (isBigInt) { + finishToken(tt.bigint); + return; + } + + if (isDecimal) { + finishToken(tt.decimal); + return; + } + + finishToken(tt.num); +} + +function readString(quote) { + state.pos++; + for (;;) { + if (state.pos >= input.length) { + unexpected("Unterminated string constant"); + return; + } + const ch = input.charCodeAt(state.pos); + if (ch === charCodes.backslash) { + state.pos++; + } else if (ch === quote) { + break; + } + state.pos++; + } + state.pos++; + finishToken(tt.string); +} + +// Reads template string tokens. +function readTmplToken() { + for (;;) { + if (state.pos >= input.length) { + unexpected("Unterminated template"); + return; + } + const ch = input.charCodeAt(state.pos); + if ( + ch === charCodes.graveAccent || + (ch === charCodes.dollarSign && input.charCodeAt(state.pos + 1) === charCodes.leftCurlyBrace) + ) { + if (state.pos === state.start && match(tt.template)) { + if (ch === charCodes.dollarSign) { + state.pos += 2; + finishToken(tt.dollarBraceL); + return; + } else { + ++state.pos; + finishToken(tt.backQuote); + return; + } + } + finishToken(tt.template); + return; + } + if (ch === charCodes.backslash) { + state.pos++; + } + state.pos++; + } +} + +// Skip to the end of the current word. Note that this is the same as the snippet at the end of +// readWord, but calling skipWord from readWord seems to slightly hurt performance from some rough +// measurements. +export function skipWord() { + while (state.pos < input.length) { + const ch = input.charCodeAt(state.pos); + if (IS_IDENTIFIER_CHAR[ch]) { + state.pos++; + } else if (ch === charCodes.backslash) { + // \u + state.pos += 2; + if (input.charCodeAt(state.pos) === charCodes.leftCurlyBrace) { + while ( + state.pos < input.length && + input.charCodeAt(state.pos) !== charCodes.rightCurlyBrace + ) { + state.pos++; + } + state.pos++; + } + } else { + break; + } + } +} diff --git a/node_modules/sucrase/dist/esm/parser/tokenizer/keywords.js b/node_modules/sucrase/dist/esm/parser/tokenizer/keywords.js new file mode 100644 index 0000000..0dcf1b0 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/tokenizer/keywords.js @@ -0,0 +1,43 @@ +export var ContextualKeyword; (function (ContextualKeyword) { + const NONE = 0; ContextualKeyword[ContextualKeyword["NONE"] = NONE] = "NONE"; + const _abstract = NONE + 1; ContextualKeyword[ContextualKeyword["_abstract"] = _abstract] = "_abstract"; + const _accessor = _abstract + 1; ContextualKeyword[ContextualKeyword["_accessor"] = _accessor] = "_accessor"; + const _as = _accessor + 1; ContextualKeyword[ContextualKeyword["_as"] = _as] = "_as"; + const _assert = _as + 1; ContextualKeyword[ContextualKeyword["_assert"] = _assert] = "_assert"; + const _asserts = _assert + 1; ContextualKeyword[ContextualKeyword["_asserts"] = _asserts] = "_asserts"; + const _async = _asserts + 1; ContextualKeyword[ContextualKeyword["_async"] = _async] = "_async"; + const _await = _async + 1; ContextualKeyword[ContextualKeyword["_await"] = _await] = "_await"; + const _checks = _await + 1; ContextualKeyword[ContextualKeyword["_checks"] = _checks] = "_checks"; + const _constructor = _checks + 1; ContextualKeyword[ContextualKeyword["_constructor"] = _constructor] = "_constructor"; + const _declare = _constructor + 1; ContextualKeyword[ContextualKeyword["_declare"] = _declare] = "_declare"; + const _enum = _declare + 1; ContextualKeyword[ContextualKeyword["_enum"] = _enum] = "_enum"; + const _exports = _enum + 1; ContextualKeyword[ContextualKeyword["_exports"] = _exports] = "_exports"; + const _from = _exports + 1; ContextualKeyword[ContextualKeyword["_from"] = _from] = "_from"; + const _get = _from + 1; ContextualKeyword[ContextualKeyword["_get"] = _get] = "_get"; + const _global = _get + 1; ContextualKeyword[ContextualKeyword["_global"] = _global] = "_global"; + const _implements = _global + 1; ContextualKeyword[ContextualKeyword["_implements"] = _implements] = "_implements"; + const _infer = _implements + 1; ContextualKeyword[ContextualKeyword["_infer"] = _infer] = "_infer"; + const _interface = _infer + 1; ContextualKeyword[ContextualKeyword["_interface"] = _interface] = "_interface"; + const _is = _interface + 1; ContextualKeyword[ContextualKeyword["_is"] = _is] = "_is"; + const _keyof = _is + 1; ContextualKeyword[ContextualKeyword["_keyof"] = _keyof] = "_keyof"; + const _mixins = _keyof + 1; ContextualKeyword[ContextualKeyword["_mixins"] = _mixins] = "_mixins"; + const _module = _mixins + 1; ContextualKeyword[ContextualKeyword["_module"] = _module] = "_module"; + const _namespace = _module + 1; ContextualKeyword[ContextualKeyword["_namespace"] = _namespace] = "_namespace"; + const _of = _namespace + 1; ContextualKeyword[ContextualKeyword["_of"] = _of] = "_of"; + const _opaque = _of + 1; ContextualKeyword[ContextualKeyword["_opaque"] = _opaque] = "_opaque"; + const _out = _opaque + 1; ContextualKeyword[ContextualKeyword["_out"] = _out] = "_out"; + const _override = _out + 1; ContextualKeyword[ContextualKeyword["_override"] = _override] = "_override"; + const _private = _override + 1; ContextualKeyword[ContextualKeyword["_private"] = _private] = "_private"; + const _protected = _private + 1; ContextualKeyword[ContextualKeyword["_protected"] = _protected] = "_protected"; + const _proto = _protected + 1; ContextualKeyword[ContextualKeyword["_proto"] = _proto] = "_proto"; + const _public = _proto + 1; ContextualKeyword[ContextualKeyword["_public"] = _public] = "_public"; + const _readonly = _public + 1; ContextualKeyword[ContextualKeyword["_readonly"] = _readonly] = "_readonly"; + const _require = _readonly + 1; ContextualKeyword[ContextualKeyword["_require"] = _require] = "_require"; + const _satisfies = _require + 1; ContextualKeyword[ContextualKeyword["_satisfies"] = _satisfies] = "_satisfies"; + const _set = _satisfies + 1; ContextualKeyword[ContextualKeyword["_set"] = _set] = "_set"; + const _static = _set + 1; ContextualKeyword[ContextualKeyword["_static"] = _static] = "_static"; + const _symbol = _static + 1; ContextualKeyword[ContextualKeyword["_symbol"] = _symbol] = "_symbol"; + const _type = _symbol + 1; ContextualKeyword[ContextualKeyword["_type"] = _type] = "_type"; + const _unique = _type + 1; ContextualKeyword[ContextualKeyword["_unique"] = _unique] = "_unique"; + const _using = _unique + 1; ContextualKeyword[ContextualKeyword["_using"] = _using] = "_using"; +})(ContextualKeyword || (ContextualKeyword = {})); diff --git a/node_modules/sucrase/dist/esm/parser/tokenizer/readWord.js b/node_modules/sucrase/dist/esm/parser/tokenizer/readWord.js new file mode 100644 index 0000000..cf3df89 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/tokenizer/readWord.js @@ -0,0 +1,64 @@ +import {input, state} from "../traverser/base"; +import {charCodes} from "../util/charcodes"; +import {IS_IDENTIFIER_CHAR} from "../util/identifier"; +import {finishToken} from "./index"; +import {READ_WORD_TREE} from "./readWordTree"; +import {TokenType as tt} from "./types"; + +/** + * Read an identifier, producing either a name token or matching on one of the existing keywords. + * For performance, we pre-generate big decision tree that we traverse. Each node represents a + * prefix and has 27 values, where the first value is the token or contextual token, if any (-1 if + * not), and the other 26 values are the transitions to other nodes, or -1 to stop. + */ +export default function readWord() { + let treePos = 0; + let code = 0; + let pos = state.pos; + while (pos < input.length) { + code = input.charCodeAt(pos); + if (code < charCodes.lowercaseA || code > charCodes.lowercaseZ) { + break; + } + const next = READ_WORD_TREE[treePos + (code - charCodes.lowercaseA) + 1]; + if (next === -1) { + break; + } else { + treePos = next; + pos++; + } + } + + const keywordValue = READ_WORD_TREE[treePos]; + if (keywordValue > -1 && !IS_IDENTIFIER_CHAR[code]) { + state.pos = pos; + if (keywordValue & 1) { + finishToken(keywordValue >>> 1); + } else { + finishToken(tt.name, keywordValue >>> 1); + } + return; + } + + while (pos < input.length) { + const ch = input.charCodeAt(pos); + if (IS_IDENTIFIER_CHAR[ch]) { + pos++; + } else if (ch === charCodes.backslash) { + // \u + pos += 2; + if (input.charCodeAt(pos) === charCodes.leftCurlyBrace) { + while (pos < input.length && input.charCodeAt(pos) !== charCodes.rightCurlyBrace) { + pos++; + } + pos++; + } + } else if (ch === charCodes.atSign && input.charCodeAt(pos + 1) === charCodes.atSign) { + pos += 2; + } else { + break; + } + } + state.pos = pos; + finishToken(tt.name); +} diff --git a/node_modules/sucrase/dist/esm/parser/tokenizer/readWordTree.js b/node_modules/sucrase/dist/esm/parser/tokenizer/readWordTree.js new file mode 100644 index 0000000..ffb8cac --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/tokenizer/readWordTree.js @@ -0,0 +1,671 @@ +// Generated file, do not edit! Run "yarn generate" to re-generate this file. +import {ContextualKeyword} from "./keywords"; +import {TokenType as tt} from "./types"; + +// prettier-ignore +export const READ_WORD_TREE = new Int32Array([ + // "" + -1, 27, 783, 918, 1755, 2376, 2862, 3483, -1, 3699, -1, 4617, 4752, 4833, 5130, 5508, 5940, -1, 6480, 6939, 7749, 8181, 8451, 8613, -1, 8829, -1, + // "a" + -1, -1, 54, 243, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 432, -1, -1, -1, 675, -1, -1, -1, + // "ab" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, + // "abs" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 108, -1, -1, -1, -1, -1, -1, + // "abst" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 135, -1, -1, -1, -1, -1, -1, -1, -1, + // "abstr" + -1, 162, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "abstra" + -1, -1, -1, 189, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "abstrac" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 216, -1, -1, -1, -1, -1, -1, + // "abstract" + ContextualKeyword._abstract << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ac" + -1, -1, -1, 270, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "acc" + -1, -1, -1, -1, -1, 297, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "acce" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 324, -1, -1, -1, -1, -1, -1, -1, + // "acces" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 351, -1, -1, -1, -1, -1, -1, -1, + // "access" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 378, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "accesso" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 405, -1, -1, -1, -1, -1, -1, -1, -1, + // "accessor" + ContextualKeyword._accessor << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "as" + ContextualKeyword._as << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 459, -1, -1, -1, -1, -1, 594, -1, + // "ass" + -1, -1, -1, -1, -1, 486, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "asse" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 513, -1, -1, -1, -1, -1, -1, -1, -1, + // "asser" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 540, -1, -1, -1, -1, -1, -1, + // "assert" + ContextualKeyword._assert << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 567, -1, -1, -1, -1, -1, -1, -1, + // "asserts" + ContextualKeyword._asserts << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "asy" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 621, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "asyn" + -1, -1, -1, 648, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "async" + ContextualKeyword._async << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "aw" + -1, 702, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "awa" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 729, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "awai" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 756, -1, -1, -1, -1, -1, -1, + // "await" + ContextualKeyword._await << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "b" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 810, -1, -1, -1, -1, -1, -1, -1, -1, + // "br" + -1, -1, -1, -1, -1, 837, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "bre" + -1, 864, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "brea" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 891, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "break" + (tt._break << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "c" + -1, 945, -1, -1, -1, -1, -1, -1, 1107, -1, -1, -1, 1242, -1, -1, 1350, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ca" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 972, 1026, -1, -1, -1, -1, -1, -1, + // "cas" + -1, -1, -1, -1, -1, 999, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "case" + (tt._case << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "cat" + -1, -1, -1, 1053, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "catc" + -1, -1, -1, -1, -1, -1, -1, -1, 1080, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "catch" + (tt._catch << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ch" + -1, -1, -1, -1, -1, 1134, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "che" + -1, -1, -1, 1161, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "chec" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1188, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "check" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1215, -1, -1, -1, -1, -1, -1, -1, + // "checks" + ContextualKeyword._checks << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "cl" + -1, 1269, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "cla" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1296, -1, -1, -1, -1, -1, -1, -1, + // "clas" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1323, -1, -1, -1, -1, -1, -1, -1, + // "class" + (tt._class << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "co" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1377, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "con" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1404, 1620, -1, -1, -1, -1, -1, -1, + // "cons" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1431, -1, -1, -1, -1, -1, -1, + // "const" + (tt._const << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1458, -1, -1, -1, -1, -1, -1, -1, -1, + // "constr" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1485, -1, -1, -1, -1, -1, + // "constru" + -1, -1, -1, 1512, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "construc" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1539, -1, -1, -1, -1, -1, -1, + // "construct" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1566, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "constructo" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1593, -1, -1, -1, -1, -1, -1, -1, -1, + // "constructor" + ContextualKeyword._constructor << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "cont" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 1647, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "conti" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1674, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "contin" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1701, -1, -1, -1, -1, -1, + // "continu" + -1, -1, -1, -1, -1, 1728, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "continue" + (tt._continue << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "d" + -1, -1, -1, -1, -1, 1782, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2349, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "de" + -1, -1, 1809, 1971, -1, -1, 2106, -1, -1, -1, -1, -1, 2241, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "deb" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1836, -1, -1, -1, -1, -1, + // "debu" + -1, -1, -1, -1, -1, -1, -1, 1863, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "debug" + -1, -1, -1, -1, -1, -1, -1, 1890, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "debugg" + -1, -1, -1, -1, -1, 1917, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "debugge" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1944, -1, -1, -1, -1, -1, -1, -1, -1, + // "debugger" + (tt._debugger << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "dec" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1998, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "decl" + -1, 2025, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "decla" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2052, -1, -1, -1, -1, -1, -1, -1, -1, + // "declar" + -1, -1, -1, -1, -1, 2079, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "declare" + ContextualKeyword._declare << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "def" + -1, 2133, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "defa" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2160, -1, -1, -1, -1, -1, + // "defau" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2187, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "defaul" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2214, -1, -1, -1, -1, -1, -1, + // "default" + (tt._default << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "del" + -1, -1, -1, -1, -1, 2268, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "dele" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2295, -1, -1, -1, -1, -1, -1, + // "delet" + -1, -1, -1, -1, -1, 2322, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "delete" + (tt._delete << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "do" + (tt._do << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "e" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2403, -1, 2484, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2565, -1, -1, + // "el" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2430, -1, -1, -1, -1, -1, -1, -1, + // "els" + -1, -1, -1, -1, -1, 2457, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "else" + (tt._else << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "en" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2511, -1, -1, -1, -1, -1, + // "enu" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2538, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "enum" + ContextualKeyword._enum << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ex" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2592, -1, -1, -1, 2727, -1, -1, -1, -1, -1, -1, + // "exp" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2619, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "expo" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2646, -1, -1, -1, -1, -1, -1, -1, -1, + // "expor" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2673, -1, -1, -1, -1, -1, -1, + // "export" + (tt._export << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2700, -1, -1, -1, -1, -1, -1, -1, + // "exports" + ContextualKeyword._exports << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ext" + -1, -1, -1, -1, -1, 2754, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "exte" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2781, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "exten" + -1, -1, -1, -1, 2808, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "extend" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2835, -1, -1, -1, -1, -1, -1, -1, + // "extends" + (tt._extends << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "f" + -1, 2889, -1, -1, -1, -1, -1, -1, -1, 2997, -1, -1, -1, -1, -1, 3159, -1, -1, 3213, -1, -1, 3294, -1, -1, -1, -1, -1, + // "fa" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2916, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "fal" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2943, -1, -1, -1, -1, -1, -1, -1, + // "fals" + -1, -1, -1, -1, -1, 2970, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "false" + (tt._false << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "fi" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3024, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "fin" + -1, 3051, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "fina" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3078, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "final" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3105, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "finall" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3132, -1, + // "finally" + (tt._finally << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "fo" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3186, -1, -1, -1, -1, -1, -1, -1, -1, + // "for" + (tt._for << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "fr" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "fro" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3267, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "from" + ContextualKeyword._from << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "fu" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3321, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "fun" + -1, -1, -1, 3348, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "func" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3375, -1, -1, -1, -1, -1, -1, + // "funct" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 3402, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "functi" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3429, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "functio" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3456, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "function" + (tt._function << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "g" + -1, -1, -1, -1, -1, 3510, -1, -1, -1, -1, -1, -1, 3564, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ge" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3537, -1, -1, -1, -1, -1, -1, + // "get" + ContextualKeyword._get << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "gl" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3591, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "glo" + -1, -1, 3618, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "glob" + -1, 3645, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "globa" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3672, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "global" + ContextualKeyword._global << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "i" + -1, -1, -1, -1, -1, -1, 3726, -1, -1, -1, -1, -1, -1, 3753, 4077, -1, -1, -1, -1, 4590, -1, -1, -1, -1, -1, -1, -1, + // "if" + (tt._if << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "im" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3780, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "imp" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3807, -1, -1, 3996, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "impl" + -1, -1, -1, -1, -1, 3834, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "imple" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3861, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "implem" + -1, -1, -1, -1, -1, 3888, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "impleme" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3915, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "implemen" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3942, -1, -1, -1, -1, -1, -1, + // "implement" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3969, -1, -1, -1, -1, -1, -1, -1, + // "implements" + ContextualKeyword._implements << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "impo" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4023, -1, -1, -1, -1, -1, -1, -1, -1, + // "impor" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4050, -1, -1, -1, -1, -1, -1, + // "import" + (tt._import << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "in" + (tt._in << 1) + 1, -1, -1, -1, -1, -1, 4104, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4185, 4401, -1, -1, -1, -1, -1, -1, + // "inf" + -1, -1, -1, -1, -1, 4131, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "infe" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4158, -1, -1, -1, -1, -1, -1, -1, -1, + // "infer" + ContextualKeyword._infer << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ins" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4212, -1, -1, -1, -1, -1, -1, + // "inst" + -1, 4239, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "insta" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4266, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "instan" + -1, -1, -1, 4293, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "instanc" + -1, -1, -1, -1, -1, 4320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "instance" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4347, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "instanceo" + -1, -1, -1, -1, -1, -1, 4374, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "instanceof" + (tt._instanceof << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "int" + -1, -1, -1, -1, -1, 4428, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "inte" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4455, -1, -1, -1, -1, -1, -1, -1, -1, + // "inter" + -1, -1, -1, -1, -1, -1, 4482, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "interf" + -1, 4509, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "interfa" + -1, -1, -1, 4536, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "interfac" + -1, -1, -1, -1, -1, 4563, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "interface" + ContextualKeyword._interface << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "is" + ContextualKeyword._is << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "k" + -1, -1, -1, -1, -1, 4644, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ke" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4671, -1, + // "key" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4698, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "keyo" + -1, -1, -1, -1, -1, -1, 4725, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "keyof" + ContextualKeyword._keyof << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "l" + -1, -1, -1, -1, -1, 4779, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "le" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4806, -1, -1, -1, -1, -1, -1, + // "let" + (tt._let << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "m" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 4860, -1, -1, -1, -1, -1, 4995, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "mi" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4887, -1, -1, + // "mix" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 4914, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "mixi" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4941, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "mixin" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4968, -1, -1, -1, -1, -1, -1, -1, + // "mixins" + ContextualKeyword._mixins << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "mo" + -1, -1, -1, -1, 5022, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "mod" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5049, -1, -1, -1, -1, -1, + // "modu" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5076, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "modul" + -1, -1, -1, -1, -1, 5103, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "module" + ContextualKeyword._module << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "n" + -1, 5157, -1, -1, -1, 5373, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5427, -1, -1, -1, -1, -1, + // "na" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5184, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "nam" + -1, -1, -1, -1, -1, 5211, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "name" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5238, -1, -1, -1, -1, -1, -1, -1, + // "names" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5265, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "namesp" + -1, 5292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "namespa" + -1, -1, -1, 5319, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "namespac" + -1, -1, -1, -1, -1, 5346, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "namespace" + ContextualKeyword._namespace << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ne" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5400, -1, -1, -1, + // "new" + (tt._new << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "nu" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5454, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "nul" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5481, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "null" + (tt._null << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "o" + -1, -1, -1, -1, -1, -1, 5535, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5562, -1, -1, -1, -1, 5697, 5751, -1, -1, -1, -1, + // "of" + ContextualKeyword._of << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "op" + -1, 5589, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "opa" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5616, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "opaq" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5643, -1, -1, -1, -1, -1, + // "opaqu" + -1, -1, -1, -1, -1, 5670, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "opaque" + ContextualKeyword._opaque << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ou" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5724, -1, -1, -1, -1, -1, -1, + // "out" + ContextualKeyword._out << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ov" + -1, -1, -1, -1, -1, 5778, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ove" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5805, -1, -1, -1, -1, -1, -1, -1, -1, + // "over" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5832, -1, -1, -1, -1, -1, -1, -1, -1, + // "overr" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 5859, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "overri" + -1, -1, -1, -1, 5886, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "overrid" + -1, -1, -1, -1, -1, 5913, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "override" + ContextualKeyword._override << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "p" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5967, -1, -1, 6345, -1, -1, -1, -1, -1, + // "pr" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 5994, -1, -1, -1, -1, -1, 6129, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "pri" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6021, -1, -1, -1, -1, + // "priv" + -1, 6048, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "priva" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6075, -1, -1, -1, -1, -1, -1, + // "privat" + -1, -1, -1, -1, -1, 6102, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "private" + ContextualKeyword._private << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "pro" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6156, -1, -1, -1, -1, -1, -1, + // "prot" + -1, -1, -1, -1, -1, 6183, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6318, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "prote" + -1, -1, -1, 6210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "protec" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6237, -1, -1, -1, -1, -1, -1, + // "protect" + -1, -1, -1, -1, -1, 6264, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "protecte" + -1, -1, -1, -1, 6291, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "protected" + ContextualKeyword._protected << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "proto" + ContextualKeyword._proto << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "pu" + -1, -1, 6372, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "pub" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6399, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "publ" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 6426, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "publi" + -1, -1, -1, 6453, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "public" + ContextualKeyword._public << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "r" + -1, -1, -1, -1, -1, 6507, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "re" + -1, 6534, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6696, -1, -1, 6831, -1, -1, -1, -1, -1, -1, + // "rea" + -1, -1, -1, -1, 6561, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "read" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6588, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "reado" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6615, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "readon" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6642, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "readonl" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6669, -1, + // "readonly" + ContextualKeyword._readonly << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "req" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6723, -1, -1, -1, -1, -1, + // "requ" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 6750, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "requi" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6777, -1, -1, -1, -1, -1, -1, -1, -1, + // "requir" + -1, -1, -1, -1, -1, 6804, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "require" + ContextualKeyword._require << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ret" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6858, -1, -1, -1, -1, -1, + // "retu" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6885, -1, -1, -1, -1, -1, -1, -1, -1, + // "retur" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6912, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "return" + (tt._return << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "s" + -1, 6966, -1, -1, -1, 7182, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7236, 7371, -1, 7479, -1, 7614, -1, + // "sa" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6993, -1, -1, -1, -1, -1, -1, + // "sat" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 7020, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "sati" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7047, -1, -1, -1, -1, -1, -1, -1, + // "satis" + -1, -1, -1, -1, -1, -1, 7074, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "satisf" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 7101, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "satisfi" + -1, -1, -1, -1, -1, 7128, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "satisfie" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7155, -1, -1, -1, -1, -1, -1, -1, + // "satisfies" + ContextualKeyword._satisfies << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "se" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7209, -1, -1, -1, -1, -1, -1, + // "set" + ContextualKeyword._set << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "st" + -1, 7263, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "sta" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7290, -1, -1, -1, -1, -1, -1, + // "stat" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 7317, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "stati" + -1, -1, -1, 7344, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "static" + ContextualKeyword._static << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "su" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7398, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "sup" + -1, -1, -1, -1, -1, 7425, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "supe" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7452, -1, -1, -1, -1, -1, -1, -1, -1, + // "super" + (tt._super << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "sw" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 7506, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "swi" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7533, -1, -1, -1, -1, -1, -1, + // "swit" + -1, -1, -1, 7560, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "switc" + -1, -1, -1, -1, -1, -1, -1, -1, 7587, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "switch" + (tt._switch << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "sy" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7641, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "sym" + -1, -1, 7668, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "symb" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7695, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "symbo" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7722, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "symbol" + ContextualKeyword._symbol << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "t" + -1, -1, -1, -1, -1, -1, -1, -1, 7776, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7938, -1, -1, -1, -1, -1, -1, 8046, -1, + // "th" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 7803, -1, -1, -1, -1, -1, -1, -1, -1, 7857, -1, -1, -1, -1, -1, -1, -1, -1, + // "thi" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7830, -1, -1, -1, -1, -1, -1, -1, + // "this" + (tt._this << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "thr" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7884, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "thro" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7911, -1, -1, -1, + // "throw" + (tt._throw << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "tr" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7965, -1, -1, -1, 8019, -1, + // "tru" + -1, -1, -1, -1, -1, 7992, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "true" + (tt._true << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "try" + (tt._try << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "ty" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8073, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "typ" + -1, -1, -1, -1, -1, 8100, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "type" + ContextualKeyword._type << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8127, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "typeo" + -1, -1, -1, -1, -1, -1, 8154, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "typeof" + (tt._typeof << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "u" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8208, -1, -1, -1, -1, 8343, -1, -1, -1, -1, -1, -1, -1, + // "un" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 8235, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "uni" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8262, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "uniq" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8289, -1, -1, -1, -1, -1, + // "uniqu" + -1, -1, -1, -1, -1, 8316, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "unique" + ContextualKeyword._unique << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "us" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 8370, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "usi" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8397, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "usin" + -1, -1, -1, -1, -1, -1, -1, 8424, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "using" + ContextualKeyword._using << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "v" + -1, 8478, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8532, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "va" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8505, -1, -1, -1, -1, -1, -1, -1, -1, + // "var" + (tt._var << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "vo" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 8559, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "voi" + -1, -1, -1, -1, 8586, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "void" + (tt._void << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "w" + -1, -1, -1, -1, -1, -1, -1, -1, 8640, 8748, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "wh" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 8667, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "whi" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8694, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "whil" + -1, -1, -1, -1, -1, 8721, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "while" + (tt._while << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "wi" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8775, -1, -1, -1, -1, -1, -1, + // "wit" + -1, -1, -1, -1, -1, -1, -1, -1, 8802, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "with" + (tt._with << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "y" + -1, -1, -1, -1, -1, -1, -1, -1, -1, 8856, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "yi" + -1, -1, -1, -1, -1, 8883, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "yie" + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8910, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "yiel" + -1, -1, -1, -1, 8937, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + // "yield" + (tt._yield << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +]); diff --git a/node_modules/sucrase/dist/esm/parser/tokenizer/state.js b/node_modules/sucrase/dist/esm/parser/tokenizer/state.js new file mode 100644 index 0000000..940cde0 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/tokenizer/state.js @@ -0,0 +1,106 @@ + +import {ContextualKeyword} from "./keywords"; +import { TokenType as tt} from "./types"; + +export class Scope { + + + + + constructor(startTokenIndex, endTokenIndex, isFunctionScope) { + this.startTokenIndex = startTokenIndex; + this.endTokenIndex = endTokenIndex; + this.isFunctionScope = isFunctionScope; + } +} + +export class StateSnapshot { + constructor( + potentialArrowAt, + noAnonFunctionType, + inDisallowConditionalTypesContext, + tokensLength, + scopesLength, + pos, + type, + contextualKeyword, + start, + end, + isType, + scopeDepth, + error, + ) {;this.potentialArrowAt = potentialArrowAt;this.noAnonFunctionType = noAnonFunctionType;this.inDisallowConditionalTypesContext = inDisallowConditionalTypesContext;this.tokensLength = tokensLength;this.scopesLength = scopesLength;this.pos = pos;this.type = type;this.contextualKeyword = contextualKeyword;this.start = start;this.end = end;this.isType = isType;this.scopeDepth = scopeDepth;this.error = error;} +} + +export default class State {constructor() { State.prototype.__init.call(this);State.prototype.__init2.call(this);State.prototype.__init3.call(this);State.prototype.__init4.call(this);State.prototype.__init5.call(this);State.prototype.__init6.call(this);State.prototype.__init7.call(this);State.prototype.__init8.call(this);State.prototype.__init9.call(this);State.prototype.__init10.call(this);State.prototype.__init11.call(this);State.prototype.__init12.call(this);State.prototype.__init13.call(this); } + // Used to signify the start of a potential arrow function + __init() {this.potentialArrowAt = -1} + + // Used by Flow to handle an edge case involving function type parsing. + __init2() {this.noAnonFunctionType = false} + + // Used by TypeScript to handle ambiguities when parsing conditional types. + __init3() {this.inDisallowConditionalTypesContext = false} + + // Token store. + __init4() {this.tokens = []} + + // Array of all observed scopes, ordered by their ending position. + __init5() {this.scopes = []} + + // The current position of the tokenizer in the input. + __init6() {this.pos = 0} + + // Information about the current token. + __init7() {this.type = tt.eof} + __init8() {this.contextualKeyword = ContextualKeyword.NONE} + __init9() {this.start = 0} + __init10() {this.end = 0} + + __init11() {this.isType = false} + __init12() {this.scopeDepth = 0} + + /** + * If the parser is in an error state, then the token is always tt.eof and all functions can + * keep executing but should be written so they don't get into an infinite loop in this situation. + * + * This approach, combined with the ability to snapshot and restore state, allows us to implement + * backtracking without exceptions and without needing to explicitly propagate error states + * everywhere. + */ + __init13() {this.error = null} + + snapshot() { + return new StateSnapshot( + this.potentialArrowAt, + this.noAnonFunctionType, + this.inDisallowConditionalTypesContext, + this.tokens.length, + this.scopes.length, + this.pos, + this.type, + this.contextualKeyword, + this.start, + this.end, + this.isType, + this.scopeDepth, + this.error, + ); + } + + restoreFromSnapshot(snapshot) { + this.potentialArrowAt = snapshot.potentialArrowAt; + this.noAnonFunctionType = snapshot.noAnonFunctionType; + this.inDisallowConditionalTypesContext = snapshot.inDisallowConditionalTypesContext; + this.tokens.length = snapshot.tokensLength; + this.scopes.length = snapshot.scopesLength; + this.pos = snapshot.pos; + this.type = snapshot.type; + this.contextualKeyword = snapshot.contextualKeyword; + this.start = snapshot.start; + this.end = snapshot.end; + this.isType = snapshot.isType; + this.scopeDepth = snapshot.scopeDepth; + this.error = snapshot.error; + } +} diff --git a/node_modules/sucrase/dist/esm/parser/tokenizer/types.js b/node_modules/sucrase/dist/esm/parser/tokenizer/types.js new file mode 100644 index 0000000..9746ad6 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/tokenizer/types.js @@ -0,0 +1,361 @@ +// Generated file, do not edit! Run "yarn generate" to re-generate this file. +/* istanbul ignore file */ +/** + * Enum of all token types, with bit fields to signify meaningful properties. + */ +export var TokenType; (function (TokenType) { + // Precedence 0 means not an operator; otherwise it is a positive number up to 12. + const PRECEDENCE_MASK = 0xf; TokenType[TokenType["PRECEDENCE_MASK"] = PRECEDENCE_MASK] = "PRECEDENCE_MASK"; + const IS_KEYWORD = 1 << 4; TokenType[TokenType["IS_KEYWORD"] = IS_KEYWORD] = "IS_KEYWORD"; + const IS_ASSIGN = 1 << 5; TokenType[TokenType["IS_ASSIGN"] = IS_ASSIGN] = "IS_ASSIGN"; + const IS_RIGHT_ASSOCIATIVE = 1 << 6; TokenType[TokenType["IS_RIGHT_ASSOCIATIVE"] = IS_RIGHT_ASSOCIATIVE] = "IS_RIGHT_ASSOCIATIVE"; + const IS_PREFIX = 1 << 7; TokenType[TokenType["IS_PREFIX"] = IS_PREFIX] = "IS_PREFIX"; + const IS_POSTFIX = 1 << 8; TokenType[TokenType["IS_POSTFIX"] = IS_POSTFIX] = "IS_POSTFIX"; + const IS_EXPRESSION_START = 1 << 9; TokenType[TokenType["IS_EXPRESSION_START"] = IS_EXPRESSION_START] = "IS_EXPRESSION_START"; + + const num = 512; TokenType[TokenType["num"] = num] = "num"; // num startsExpr + const bigint = 1536; TokenType[TokenType["bigint"] = bigint] = "bigint"; // bigint startsExpr + const decimal = 2560; TokenType[TokenType["decimal"] = decimal] = "decimal"; // decimal startsExpr + const regexp = 3584; TokenType[TokenType["regexp"] = regexp] = "regexp"; // regexp startsExpr + const string = 4608; TokenType[TokenType["string"] = string] = "string"; // string startsExpr + const name = 5632; TokenType[TokenType["name"] = name] = "name"; // name startsExpr + const eof = 6144; TokenType[TokenType["eof"] = eof] = "eof"; // eof + const bracketL = 7680; TokenType[TokenType["bracketL"] = bracketL] = "bracketL"; // [ startsExpr + const bracketR = 8192; TokenType[TokenType["bracketR"] = bracketR] = "bracketR"; // ] + const braceL = 9728; TokenType[TokenType["braceL"] = braceL] = "braceL"; // { startsExpr + const braceBarL = 10752; TokenType[TokenType["braceBarL"] = braceBarL] = "braceBarL"; // {| startsExpr + const braceR = 11264; TokenType[TokenType["braceR"] = braceR] = "braceR"; // } + const braceBarR = 12288; TokenType[TokenType["braceBarR"] = braceBarR] = "braceBarR"; // |} + const parenL = 13824; TokenType[TokenType["parenL"] = parenL] = "parenL"; // ( startsExpr + const parenR = 14336; TokenType[TokenType["parenR"] = parenR] = "parenR"; // ) + const comma = 15360; TokenType[TokenType["comma"] = comma] = "comma"; // , + const semi = 16384; TokenType[TokenType["semi"] = semi] = "semi"; // ; + const colon = 17408; TokenType[TokenType["colon"] = colon] = "colon"; // : + const doubleColon = 18432; TokenType[TokenType["doubleColon"] = doubleColon] = "doubleColon"; // :: + const dot = 19456; TokenType[TokenType["dot"] = dot] = "dot"; // . + const question = 20480; TokenType[TokenType["question"] = question] = "question"; // ? + const questionDot = 21504; TokenType[TokenType["questionDot"] = questionDot] = "questionDot"; // ?. + const arrow = 22528; TokenType[TokenType["arrow"] = arrow] = "arrow"; // => + const template = 23552; TokenType[TokenType["template"] = template] = "template"; // template + const ellipsis = 24576; TokenType[TokenType["ellipsis"] = ellipsis] = "ellipsis"; // ... + const backQuote = 25600; TokenType[TokenType["backQuote"] = backQuote] = "backQuote"; // ` + const dollarBraceL = 27136; TokenType[TokenType["dollarBraceL"] = dollarBraceL] = "dollarBraceL"; // ${ startsExpr + const at = 27648; TokenType[TokenType["at"] = at] = "at"; // @ + const hash = 29184; TokenType[TokenType["hash"] = hash] = "hash"; // # startsExpr + const eq = 29728; TokenType[TokenType["eq"] = eq] = "eq"; // = isAssign + const assign = 30752; TokenType[TokenType["assign"] = assign] = "assign"; // _= isAssign + const preIncDec = 32640; TokenType[TokenType["preIncDec"] = preIncDec] = "preIncDec"; // ++/-- prefix postfix startsExpr + const postIncDec = 33664; TokenType[TokenType["postIncDec"] = postIncDec] = "postIncDec"; // ++/-- prefix postfix startsExpr + const bang = 34432; TokenType[TokenType["bang"] = bang] = "bang"; // ! prefix startsExpr + const tilde = 35456; TokenType[TokenType["tilde"] = tilde] = "tilde"; // ~ prefix startsExpr + const pipeline = 35841; TokenType[TokenType["pipeline"] = pipeline] = "pipeline"; // |> prec:1 + const nullishCoalescing = 36866; TokenType[TokenType["nullishCoalescing"] = nullishCoalescing] = "nullishCoalescing"; // ?? prec:2 + const logicalOR = 37890; TokenType[TokenType["logicalOR"] = logicalOR] = "logicalOR"; // || prec:2 + const logicalAND = 38915; TokenType[TokenType["logicalAND"] = logicalAND] = "logicalAND"; // && prec:3 + const bitwiseOR = 39940; TokenType[TokenType["bitwiseOR"] = bitwiseOR] = "bitwiseOR"; // | prec:4 + const bitwiseXOR = 40965; TokenType[TokenType["bitwiseXOR"] = bitwiseXOR] = "bitwiseXOR"; // ^ prec:5 + const bitwiseAND = 41990; TokenType[TokenType["bitwiseAND"] = bitwiseAND] = "bitwiseAND"; // & prec:6 + const equality = 43015; TokenType[TokenType["equality"] = equality] = "equality"; // ==/!= prec:7 + const lessThan = 44040; TokenType[TokenType["lessThan"] = lessThan] = "lessThan"; // < prec:8 + const greaterThan = 45064; TokenType[TokenType["greaterThan"] = greaterThan] = "greaterThan"; // > prec:8 + const relationalOrEqual = 46088; TokenType[TokenType["relationalOrEqual"] = relationalOrEqual] = "relationalOrEqual"; // <=/>= prec:8 + const bitShiftL = 47113; TokenType[TokenType["bitShiftL"] = bitShiftL] = "bitShiftL"; // << prec:9 + const bitShiftR = 48137; TokenType[TokenType["bitShiftR"] = bitShiftR] = "bitShiftR"; // >>/>>> prec:9 + const plus = 49802; TokenType[TokenType["plus"] = plus] = "plus"; // + prec:10 prefix startsExpr + const minus = 50826; TokenType[TokenType["minus"] = minus] = "minus"; // - prec:10 prefix startsExpr + const modulo = 51723; TokenType[TokenType["modulo"] = modulo] = "modulo"; // % prec:11 startsExpr + const star = 52235; TokenType[TokenType["star"] = star] = "star"; // * prec:11 + const slash = 53259; TokenType[TokenType["slash"] = slash] = "slash"; // / prec:11 + const exponent = 54348; TokenType[TokenType["exponent"] = exponent] = "exponent"; // ** prec:12 rightAssociative + const jsxName = 55296; TokenType[TokenType["jsxName"] = jsxName] = "jsxName"; // jsxName + const jsxText = 56320; TokenType[TokenType["jsxText"] = jsxText] = "jsxText"; // jsxText + const jsxEmptyText = 57344; TokenType[TokenType["jsxEmptyText"] = jsxEmptyText] = "jsxEmptyText"; // jsxEmptyText + const jsxTagStart = 58880; TokenType[TokenType["jsxTagStart"] = jsxTagStart] = "jsxTagStart"; // jsxTagStart startsExpr + const jsxTagEnd = 59392; TokenType[TokenType["jsxTagEnd"] = jsxTagEnd] = "jsxTagEnd"; // jsxTagEnd + const typeParameterStart = 60928; TokenType[TokenType["typeParameterStart"] = typeParameterStart] = "typeParameterStart"; // typeParameterStart startsExpr + const nonNullAssertion = 61440; TokenType[TokenType["nonNullAssertion"] = nonNullAssertion] = "nonNullAssertion"; // nonNullAssertion + const _break = 62480; TokenType[TokenType["_break"] = _break] = "_break"; // break keyword + const _case = 63504; TokenType[TokenType["_case"] = _case] = "_case"; // case keyword + const _catch = 64528; TokenType[TokenType["_catch"] = _catch] = "_catch"; // catch keyword + const _continue = 65552; TokenType[TokenType["_continue"] = _continue] = "_continue"; // continue keyword + const _debugger = 66576; TokenType[TokenType["_debugger"] = _debugger] = "_debugger"; // debugger keyword + const _default = 67600; TokenType[TokenType["_default"] = _default] = "_default"; // default keyword + const _do = 68624; TokenType[TokenType["_do"] = _do] = "_do"; // do keyword + const _else = 69648; TokenType[TokenType["_else"] = _else] = "_else"; // else keyword + const _finally = 70672; TokenType[TokenType["_finally"] = _finally] = "_finally"; // finally keyword + const _for = 71696; TokenType[TokenType["_for"] = _for] = "_for"; // for keyword + const _function = 73232; TokenType[TokenType["_function"] = _function] = "_function"; // function keyword startsExpr + const _if = 73744; TokenType[TokenType["_if"] = _if] = "_if"; // if keyword + const _return = 74768; TokenType[TokenType["_return"] = _return] = "_return"; // return keyword + const _switch = 75792; TokenType[TokenType["_switch"] = _switch] = "_switch"; // switch keyword + const _throw = 77456; TokenType[TokenType["_throw"] = _throw] = "_throw"; // throw keyword prefix startsExpr + const _try = 77840; TokenType[TokenType["_try"] = _try] = "_try"; // try keyword + const _var = 78864; TokenType[TokenType["_var"] = _var] = "_var"; // var keyword + const _let = 79888; TokenType[TokenType["_let"] = _let] = "_let"; // let keyword + const _const = 80912; TokenType[TokenType["_const"] = _const] = "_const"; // const keyword + const _while = 81936; TokenType[TokenType["_while"] = _while] = "_while"; // while keyword + const _with = 82960; TokenType[TokenType["_with"] = _with] = "_with"; // with keyword + const _new = 84496; TokenType[TokenType["_new"] = _new] = "_new"; // new keyword startsExpr + const _this = 85520; TokenType[TokenType["_this"] = _this] = "_this"; // this keyword startsExpr + const _super = 86544; TokenType[TokenType["_super"] = _super] = "_super"; // super keyword startsExpr + const _class = 87568; TokenType[TokenType["_class"] = _class] = "_class"; // class keyword startsExpr + const _extends = 88080; TokenType[TokenType["_extends"] = _extends] = "_extends"; // extends keyword + const _export = 89104; TokenType[TokenType["_export"] = _export] = "_export"; // export keyword + const _import = 90640; TokenType[TokenType["_import"] = _import] = "_import"; // import keyword startsExpr + const _yield = 91664; TokenType[TokenType["_yield"] = _yield] = "_yield"; // yield keyword startsExpr + const _null = 92688; TokenType[TokenType["_null"] = _null] = "_null"; // null keyword startsExpr + const _true = 93712; TokenType[TokenType["_true"] = _true] = "_true"; // true keyword startsExpr + const _false = 94736; TokenType[TokenType["_false"] = _false] = "_false"; // false keyword startsExpr + const _in = 95256; TokenType[TokenType["_in"] = _in] = "_in"; // in prec:8 keyword + const _instanceof = 96280; TokenType[TokenType["_instanceof"] = _instanceof] = "_instanceof"; // instanceof prec:8 keyword + const _typeof = 97936; TokenType[TokenType["_typeof"] = _typeof] = "_typeof"; // typeof keyword prefix startsExpr + const _void = 98960; TokenType[TokenType["_void"] = _void] = "_void"; // void keyword prefix startsExpr + const _delete = 99984; TokenType[TokenType["_delete"] = _delete] = "_delete"; // delete keyword prefix startsExpr + const _async = 100880; TokenType[TokenType["_async"] = _async] = "_async"; // async keyword startsExpr + const _get = 101904; TokenType[TokenType["_get"] = _get] = "_get"; // get keyword startsExpr + const _set = 102928; TokenType[TokenType["_set"] = _set] = "_set"; // set keyword startsExpr + const _declare = 103952; TokenType[TokenType["_declare"] = _declare] = "_declare"; // declare keyword startsExpr + const _readonly = 104976; TokenType[TokenType["_readonly"] = _readonly] = "_readonly"; // readonly keyword startsExpr + const _abstract = 106000; TokenType[TokenType["_abstract"] = _abstract] = "_abstract"; // abstract keyword startsExpr + const _static = 107024; TokenType[TokenType["_static"] = _static] = "_static"; // static keyword startsExpr + const _public = 107536; TokenType[TokenType["_public"] = _public] = "_public"; // public keyword + const _private = 108560; TokenType[TokenType["_private"] = _private] = "_private"; // private keyword + const _protected = 109584; TokenType[TokenType["_protected"] = _protected] = "_protected"; // protected keyword + const _override = 110608; TokenType[TokenType["_override"] = _override] = "_override"; // override keyword + const _as = 112144; TokenType[TokenType["_as"] = _as] = "_as"; // as keyword startsExpr + const _enum = 113168; TokenType[TokenType["_enum"] = _enum] = "_enum"; // enum keyword startsExpr + const _type = 114192; TokenType[TokenType["_type"] = _type] = "_type"; // type keyword startsExpr + const _implements = 115216; TokenType[TokenType["_implements"] = _implements] = "_implements"; // implements keyword startsExpr +})(TokenType || (TokenType = {})); +export function formatTokenType(tokenType) { + switch (tokenType) { + case TokenType.num: + return "num"; + case TokenType.bigint: + return "bigint"; + case TokenType.decimal: + return "decimal"; + case TokenType.regexp: + return "regexp"; + case TokenType.string: + return "string"; + case TokenType.name: + return "name"; + case TokenType.eof: + return "eof"; + case TokenType.bracketL: + return "["; + case TokenType.bracketR: + return "]"; + case TokenType.braceL: + return "{"; + case TokenType.braceBarL: + return "{|"; + case TokenType.braceR: + return "}"; + case TokenType.braceBarR: + return "|}"; + case TokenType.parenL: + return "("; + case TokenType.parenR: + return ")"; + case TokenType.comma: + return ","; + case TokenType.semi: + return ";"; + case TokenType.colon: + return ":"; + case TokenType.doubleColon: + return "::"; + case TokenType.dot: + return "."; + case TokenType.question: + return "?"; + case TokenType.questionDot: + return "?."; + case TokenType.arrow: + return "=>"; + case TokenType.template: + return "template"; + case TokenType.ellipsis: + return "..."; + case TokenType.backQuote: + return "`"; + case TokenType.dollarBraceL: + return "${"; + case TokenType.at: + return "@"; + case TokenType.hash: + return "#"; + case TokenType.eq: + return "="; + case TokenType.assign: + return "_="; + case TokenType.preIncDec: + return "++/--"; + case TokenType.postIncDec: + return "++/--"; + case TokenType.bang: + return "!"; + case TokenType.tilde: + return "~"; + case TokenType.pipeline: + return "|>"; + case TokenType.nullishCoalescing: + return "??"; + case TokenType.logicalOR: + return "||"; + case TokenType.logicalAND: + return "&&"; + case TokenType.bitwiseOR: + return "|"; + case TokenType.bitwiseXOR: + return "^"; + case TokenType.bitwiseAND: + return "&"; + case TokenType.equality: + return "==/!="; + case TokenType.lessThan: + return "<"; + case TokenType.greaterThan: + return ">"; + case TokenType.relationalOrEqual: + return "<=/>="; + case TokenType.bitShiftL: + return "<<"; + case TokenType.bitShiftR: + return ">>/>>>"; + case TokenType.plus: + return "+"; + case TokenType.minus: + return "-"; + case TokenType.modulo: + return "%"; + case TokenType.star: + return "*"; + case TokenType.slash: + return "/"; + case TokenType.exponent: + return "**"; + case TokenType.jsxName: + return "jsxName"; + case TokenType.jsxText: + return "jsxText"; + case TokenType.jsxEmptyText: + return "jsxEmptyText"; + case TokenType.jsxTagStart: + return "jsxTagStart"; + case TokenType.jsxTagEnd: + return "jsxTagEnd"; + case TokenType.typeParameterStart: + return "typeParameterStart"; + case TokenType.nonNullAssertion: + return "nonNullAssertion"; + case TokenType._break: + return "break"; + case TokenType._case: + return "case"; + case TokenType._catch: + return "catch"; + case TokenType._continue: + return "continue"; + case TokenType._debugger: + return "debugger"; + case TokenType._default: + return "default"; + case TokenType._do: + return "do"; + case TokenType._else: + return "else"; + case TokenType._finally: + return "finally"; + case TokenType._for: + return "for"; + case TokenType._function: + return "function"; + case TokenType._if: + return "if"; + case TokenType._return: + return "return"; + case TokenType._switch: + return "switch"; + case TokenType._throw: + return "throw"; + case TokenType._try: + return "try"; + case TokenType._var: + return "var"; + case TokenType._let: + return "let"; + case TokenType._const: + return "const"; + case TokenType._while: + return "while"; + case TokenType._with: + return "with"; + case TokenType._new: + return "new"; + case TokenType._this: + return "this"; + case TokenType._super: + return "super"; + case TokenType._class: + return "class"; + case TokenType._extends: + return "extends"; + case TokenType._export: + return "export"; + case TokenType._import: + return "import"; + case TokenType._yield: + return "yield"; + case TokenType._null: + return "null"; + case TokenType._true: + return "true"; + case TokenType._false: + return "false"; + case TokenType._in: + return "in"; + case TokenType._instanceof: + return "instanceof"; + case TokenType._typeof: + return "typeof"; + case TokenType._void: + return "void"; + case TokenType._delete: + return "delete"; + case TokenType._async: + return "async"; + case TokenType._get: + return "get"; + case TokenType._set: + return "set"; + case TokenType._declare: + return "declare"; + case TokenType._readonly: + return "readonly"; + case TokenType._abstract: + return "abstract"; + case TokenType._static: + return "static"; + case TokenType._public: + return "public"; + case TokenType._private: + return "private"; + case TokenType._protected: + return "protected"; + case TokenType._override: + return "override"; + case TokenType._as: + return "as"; + case TokenType._enum: + return "enum"; + case TokenType._type: + return "type"; + case TokenType._implements: + return "implements"; + default: + return ""; + } +} diff --git a/node_modules/sucrase/dist/esm/parser/traverser/base.js b/node_modules/sucrase/dist/esm/parser/traverser/base.js new file mode 100644 index 0000000..df24ff7 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/traverser/base.js @@ -0,0 +1,60 @@ +import State from "../tokenizer/state"; +import {charCodes} from "../util/charcodes"; + +export let isJSXEnabled; +export let isTypeScriptEnabled; +export let isFlowEnabled; +export let state; +export let input; +export let nextContextId; + +export function getNextContextId() { + return nextContextId++; +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function augmentError(error) { + if ("pos" in error) { + const loc = locationForIndex(error.pos); + error.message += ` (${loc.line}:${loc.column})`; + error.loc = loc; + } + return error; +} + +export class Loc { + + + constructor(line, column) { + this.line = line; + this.column = column; + } +} + +export function locationForIndex(pos) { + let line = 1; + let column = 1; + for (let i = 0; i < pos; i++) { + if (input.charCodeAt(i) === charCodes.lineFeed) { + line++; + column = 1; + } else { + column++; + } + } + return new Loc(line, column); +} + +export function initParser( + inputCode, + isJSXEnabledArg, + isTypeScriptEnabledArg, + isFlowEnabledArg, +) { + input = inputCode; + state = new State(); + nextContextId = 1; + isJSXEnabled = isJSXEnabledArg; + isTypeScriptEnabled = isTypeScriptEnabledArg; + isFlowEnabled = isFlowEnabledArg; +} diff --git a/node_modules/sucrase/dist/esm/parser/traverser/expression.js b/node_modules/sucrase/dist/esm/parser/traverser/expression.js new file mode 100644 index 0000000..aa6717f --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/traverser/expression.js @@ -0,0 +1,1022 @@ +/* eslint max-len: 0 */ + +// A recursive descent parser operates by defining functions for all +// syntactic elements, and recursively calling those, each function +// advancing the input stream and returning an AST node. Precedence +// of constructs (for example, the fact that `!x[1]` means `!(x[1])` +// instead of `(!x)[1]` is handled by the fact that the parser +// function that parses unary prefix operators is called first, and +// in turn calls the function that parses `[]` subscripts — that +// way, it'll receive the node for `x[1]` already parsed, and wraps +// *that* in the unary operator node. +// +// Acorn uses an [operator precedence parser][opp] to handle binary +// operator precedence, because it is much more compact than using +// the technique outlined above, which uses different, nesting +// functions to specify precedence, for all of the ten binary +// precedence levels that JavaScript defines. +// +// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser + +import { + flowParseArrow, + flowParseFunctionBodyAndFinish, + flowParseMaybeAssign, + flowParseSubscript, + flowParseSubscripts, + flowParseVariance, + flowStartParseAsyncArrowFromCallExpression, + flowStartParseNewArguments, + flowStartParseObjPropValue, +} from "../plugins/flow"; +import {jsxParseElement} from "../plugins/jsx/index"; +import {typedParseConditional, typedParseParenItem} from "../plugins/types"; +import { + tsParseArrow, + tsParseFunctionBodyAndFinish, + tsParseMaybeAssign, + tsParseSubscript, + tsParseType, + tsParseTypeAssertion, + tsStartParseAsyncArrowFromCallExpression, + tsStartParseObjPropValue, +} from "../plugins/typescript"; +import { + eat, + IdentifierRole, + lookaheadCharCode, + lookaheadType, + match, + next, + nextTemplateToken, + popTypeContext, + pushTypeContext, + rescan_gt, + retokenizeSlashAsRegex, +} from "../tokenizer/index"; +import {ContextualKeyword} from "../tokenizer/keywords"; +import {Scope} from "../tokenizer/state"; +import {TokenType, TokenType as tt} from "../tokenizer/types"; +import {charCodes} from "../util/charcodes"; +import {IS_IDENTIFIER_START} from "../util/identifier"; +import {getNextContextId, isFlowEnabled, isJSXEnabled, isTypeScriptEnabled, state} from "./base"; +import { + markPriorBindingIdentifier, + parseBindingIdentifier, + parseMaybeDefault, + parseRest, + parseSpread, +} from "./lval"; +import { + parseBlock, + parseBlockBody, + parseClass, + parseDecorators, + parseFunction, + parseFunctionParams, +} from "./statement"; +import { + canInsertSemicolon, + eatContextual, + expect, + expectContextual, + hasFollowingLineBreak, + hasPrecedingLineBreak, + isContextual, + unexpected, +} from "./util"; + +export class StopState { + + constructor(stop) { + this.stop = stop; + } +} + +// ### Expression parsing + +// These nest, from the most general expression type at the top to +// 'atomic', nondivisible expression types at the bottom. Most of +// the functions will simply let the function (s) below them parse, +// and, *if* the syntactic construct they handle is present, wrap +// the AST node that the inner parser gave them in another node. +export function parseExpression(noIn = false) { + parseMaybeAssign(noIn); + if (match(tt.comma)) { + while (eat(tt.comma)) { + parseMaybeAssign(noIn); + } + } +} + +/** + * noIn is used when parsing a for loop so that we don't interpret a following "in" as the binary + * operatior. + * isWithinParens is used to indicate that we're parsing something that might be a comma expression + * or might be an arrow function or might be a Flow type assertion (which requires explicit parens). + * In these cases, we should allow : and ?: after the initial "left" part. + */ +export function parseMaybeAssign(noIn = false, isWithinParens = false) { + if (isTypeScriptEnabled) { + return tsParseMaybeAssign(noIn, isWithinParens); + } else if (isFlowEnabled) { + return flowParseMaybeAssign(noIn, isWithinParens); + } else { + return baseParseMaybeAssign(noIn, isWithinParens); + } +} + +// Parse an assignment expression. This includes applications of +// operators like `+=`. +// Returns true if the expression was an arrow function. +export function baseParseMaybeAssign(noIn, isWithinParens) { + if (match(tt._yield)) { + parseYield(); + return false; + } + + if (match(tt.parenL) || match(tt.name) || match(tt._yield)) { + state.potentialArrowAt = state.start; + } + + const wasArrow = parseMaybeConditional(noIn); + if (isWithinParens) { + parseParenItem(); + } + if (state.type & TokenType.IS_ASSIGN) { + next(); + parseMaybeAssign(noIn); + return false; + } + return wasArrow; +} + +// Parse a ternary conditional (`?:`) operator. +// Returns true if the expression was an arrow function. +function parseMaybeConditional(noIn) { + const wasArrow = parseExprOps(noIn); + if (wasArrow) { + return true; + } + parseConditional(noIn); + return false; +} + +function parseConditional(noIn) { + if (isTypeScriptEnabled || isFlowEnabled) { + typedParseConditional(noIn); + } else { + baseParseConditional(noIn); + } +} + +export function baseParseConditional(noIn) { + if (eat(tt.question)) { + parseMaybeAssign(); + expect(tt.colon); + parseMaybeAssign(noIn); + } +} + +// Start the precedence parser. +// Returns true if this was an arrow function +function parseExprOps(noIn) { + const startTokenIndex = state.tokens.length; + const wasArrow = parseMaybeUnary(); + if (wasArrow) { + return true; + } + parseExprOp(startTokenIndex, -1, noIn); + return false; +} + +// Parse binary operators with the operator precedence parsing +// algorithm. `left` is the left-hand side of the operator. +// `minPrec` provides context that allows the function to stop and +// defer further parser to one of its callers when it encounters an +// operator that has a lower precedence than the set it is parsing. +function parseExprOp(startTokenIndex, minPrec, noIn) { + if ( + isTypeScriptEnabled && + (tt._in & TokenType.PRECEDENCE_MASK) > minPrec && + !hasPrecedingLineBreak() && + (eatContextual(ContextualKeyword._as) || eatContextual(ContextualKeyword._satisfies)) + ) { + const oldIsType = pushTypeContext(1); + tsParseType(); + popTypeContext(oldIsType); + rescan_gt(); + parseExprOp(startTokenIndex, minPrec, noIn); + return; + } + + const prec = state.type & TokenType.PRECEDENCE_MASK; + if (prec > 0 && (!noIn || !match(tt._in))) { + if (prec > minPrec) { + const op = state.type; + next(); + if (op === tt.nullishCoalescing) { + state.tokens[state.tokens.length - 1].nullishStartIndex = startTokenIndex; + } + + const rhsStartTokenIndex = state.tokens.length; + parseMaybeUnary(); + // Extend the right operand of this operator if possible. + parseExprOp(rhsStartTokenIndex, op & TokenType.IS_RIGHT_ASSOCIATIVE ? prec - 1 : prec, noIn); + if (op === tt.nullishCoalescing) { + state.tokens[startTokenIndex].numNullishCoalesceStarts++; + state.tokens[state.tokens.length - 1].numNullishCoalesceEnds++; + } + // Continue with any future operator holding this expression as the left operand. + parseExprOp(startTokenIndex, minPrec, noIn); + } + } +} + +// Parse unary operators, both prefix and postfix. +// Returns true if this was an arrow function. +export function parseMaybeUnary() { + if (isTypeScriptEnabled && !isJSXEnabled && eat(tt.lessThan)) { + tsParseTypeAssertion(); + return false; + } + if ( + isContextual(ContextualKeyword._module) && + lookaheadCharCode() === charCodes.leftCurlyBrace && + !hasFollowingLineBreak() + ) { + parseModuleExpression(); + return false; + } + if (state.type & TokenType.IS_PREFIX) { + next(); + parseMaybeUnary(); + return false; + } + + const wasArrow = parseExprSubscripts(); + if (wasArrow) { + return true; + } + while (state.type & TokenType.IS_POSTFIX && !canInsertSemicolon()) { + // The tokenizer calls everything a preincrement, so make it a postincrement when + // we see it in that context. + if (state.type === tt.preIncDec) { + state.type = tt.postIncDec; + } + next(); + } + return false; +} + +// Parse call, dot, and `[]`-subscript expressions. +// Returns true if this was an arrow function. +export function parseExprSubscripts() { + const startTokenIndex = state.tokens.length; + const wasArrow = parseExprAtom(); + if (wasArrow) { + return true; + } + parseSubscripts(startTokenIndex); + // If there was any optional chain operation, the start token would be marked + // as such, so also mark the end now. + if (state.tokens.length > startTokenIndex && state.tokens[startTokenIndex].isOptionalChainStart) { + state.tokens[state.tokens.length - 1].isOptionalChainEnd = true; + } + return false; +} + +function parseSubscripts(startTokenIndex, noCalls = false) { + if (isFlowEnabled) { + flowParseSubscripts(startTokenIndex, noCalls); + } else { + baseParseSubscripts(startTokenIndex, noCalls); + } +} + +export function baseParseSubscripts(startTokenIndex, noCalls = false) { + const stopState = new StopState(false); + do { + parseSubscript(startTokenIndex, noCalls, stopState); + } while (!stopState.stop && !state.error); +} + +function parseSubscript(startTokenIndex, noCalls, stopState) { + if (isTypeScriptEnabled) { + tsParseSubscript(startTokenIndex, noCalls, stopState); + } else if (isFlowEnabled) { + flowParseSubscript(startTokenIndex, noCalls, stopState); + } else { + baseParseSubscript(startTokenIndex, noCalls, stopState); + } +} + +/** Set 'state.stop = true' to indicate that we should stop parsing subscripts. */ +export function baseParseSubscript( + startTokenIndex, + noCalls, + stopState, +) { + if (!noCalls && eat(tt.doubleColon)) { + parseNoCallExpr(); + stopState.stop = true; + // Propagate startTokenIndex so that `a::b?.()` will keep `a` as the first token. We may want + // to revisit this in the future when fully supporting bind syntax. + parseSubscripts(startTokenIndex, noCalls); + } else if (match(tt.questionDot)) { + state.tokens[startTokenIndex].isOptionalChainStart = true; + if (noCalls && lookaheadType() === tt.parenL) { + stopState.stop = true; + return; + } + next(); + state.tokens[state.tokens.length - 1].subscriptStartIndex = startTokenIndex; + + if (eat(tt.bracketL)) { + parseExpression(); + expect(tt.bracketR); + } else if (eat(tt.parenL)) { + parseCallExpressionArguments(); + } else { + parseMaybePrivateName(); + } + } else if (eat(tt.dot)) { + state.tokens[state.tokens.length - 1].subscriptStartIndex = startTokenIndex; + parseMaybePrivateName(); + } else if (eat(tt.bracketL)) { + state.tokens[state.tokens.length - 1].subscriptStartIndex = startTokenIndex; + parseExpression(); + expect(tt.bracketR); + } else if (!noCalls && match(tt.parenL)) { + if (atPossibleAsync()) { + // We see "async", but it's possible it's a usage of the name "async". Parse as if it's a + // function call, and if we see an arrow later, backtrack and re-parse as a parameter list. + const snapshot = state.snapshot(); + const asyncStartTokenIndex = state.tokens.length; + next(); + state.tokens[state.tokens.length - 1].subscriptStartIndex = startTokenIndex; + + const callContextId = getNextContextId(); + + state.tokens[state.tokens.length - 1].contextId = callContextId; + parseCallExpressionArguments(); + state.tokens[state.tokens.length - 1].contextId = callContextId; + + if (shouldParseAsyncArrow()) { + // We hit an arrow, so backtrack and start again parsing function parameters. + state.restoreFromSnapshot(snapshot); + stopState.stop = true; + state.scopeDepth++; + + parseFunctionParams(); + parseAsyncArrowFromCallExpression(asyncStartTokenIndex); + } + } else { + next(); + state.tokens[state.tokens.length - 1].subscriptStartIndex = startTokenIndex; + const callContextId = getNextContextId(); + state.tokens[state.tokens.length - 1].contextId = callContextId; + parseCallExpressionArguments(); + state.tokens[state.tokens.length - 1].contextId = callContextId; + } + } else if (match(tt.backQuote)) { + // Tagged template expression. + parseTemplate(); + } else { + stopState.stop = true; + } +} + +export function atPossibleAsync() { + // This was made less strict than the original version to avoid passing around nodes, but it + // should be safe to have rare false positives here. + return ( + state.tokens[state.tokens.length - 1].contextualKeyword === ContextualKeyword._async && + !canInsertSemicolon() + ); +} + +export function parseCallExpressionArguments() { + let first = true; + while (!eat(tt.parenR) && !state.error) { + if (first) { + first = false; + } else { + expect(tt.comma); + if (eat(tt.parenR)) { + break; + } + } + + parseExprListItem(false); + } +} + +function shouldParseAsyncArrow() { + return match(tt.colon) || match(tt.arrow); +} + +function parseAsyncArrowFromCallExpression(startTokenIndex) { + if (isTypeScriptEnabled) { + tsStartParseAsyncArrowFromCallExpression(); + } else if (isFlowEnabled) { + flowStartParseAsyncArrowFromCallExpression(); + } + expect(tt.arrow); + parseArrowExpression(startTokenIndex); +} + +// Parse a no-call expression (like argument of `new` or `::` operators). + +function parseNoCallExpr() { + const startTokenIndex = state.tokens.length; + parseExprAtom(); + parseSubscripts(startTokenIndex, true); +} + +// Parse an atomic expression — either a single token that is an +// expression, an expression started by a keyword like `function` or +// `new`, or an expression wrapped in punctuation like `()`, `[]`, +// or `{}`. +// Returns true if the parsed expression was an arrow function. +export function parseExprAtom() { + if (eat(tt.modulo)) { + // V8 intrinsic expression. Just parse the identifier, and the function invocation is parsed + // naturally. + parseIdentifier(); + return false; + } + + if (match(tt.jsxText) || match(tt.jsxEmptyText)) { + parseLiteral(); + return false; + } else if (match(tt.lessThan) && isJSXEnabled) { + state.type = tt.jsxTagStart; + jsxParseElement(); + next(); + return false; + } + + const canBeArrow = state.potentialArrowAt === state.start; + switch (state.type) { + case tt.slash: + case tt.assign: + retokenizeSlashAsRegex(); + // Fall through. + + case tt._super: + case tt._this: + case tt.regexp: + case tt.num: + case tt.bigint: + case tt.decimal: + case tt.string: + case tt._null: + case tt._true: + case tt._false: + next(); + return false; + + case tt._import: + next(); + if (match(tt.dot)) { + // import.meta + state.tokens[state.tokens.length - 1].type = tt.name; + next(); + parseIdentifier(); + } + return false; + + case tt.name: { + const startTokenIndex = state.tokens.length; + const functionStart = state.start; + const contextualKeyword = state.contextualKeyword; + parseIdentifier(); + if (contextualKeyword === ContextualKeyword._await) { + parseAwait(); + return false; + } else if ( + contextualKeyword === ContextualKeyword._async && + match(tt._function) && + !canInsertSemicolon() + ) { + next(); + parseFunction(functionStart, false); + return false; + } else if ( + canBeArrow && + contextualKeyword === ContextualKeyword._async && + !canInsertSemicolon() && + match(tt.name) + ) { + state.scopeDepth++; + parseBindingIdentifier(false); + expect(tt.arrow); + // let foo = async bar => {}; + parseArrowExpression(startTokenIndex); + return true; + } else if (match(tt._do) && !canInsertSemicolon()) { + next(); + parseBlock(); + return false; + } + + if (canBeArrow && !canInsertSemicolon() && match(tt.arrow)) { + state.scopeDepth++; + markPriorBindingIdentifier(false); + expect(tt.arrow); + parseArrowExpression(startTokenIndex); + return true; + } + + state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.Access; + return false; + } + + case tt._do: { + next(); + parseBlock(); + return false; + } + + case tt.parenL: { + const wasArrow = parseParenAndDistinguishExpression(canBeArrow); + return wasArrow; + } + + case tt.bracketL: + next(); + parseExprList(tt.bracketR, true); + return false; + + case tt.braceL: + parseObj(false, false); + return false; + + case tt._function: + parseFunctionExpression(); + return false; + + case tt.at: + parseDecorators(); + // Fall through. + + case tt._class: + parseClass(false); + return false; + + case tt._new: + parseNew(); + return false; + + case tt.backQuote: + parseTemplate(); + return false; + + case tt.doubleColon: { + next(); + parseNoCallExpr(); + return false; + } + + case tt.hash: { + const code = lookaheadCharCode(); + if (IS_IDENTIFIER_START[code] || code === charCodes.backslash) { + parseMaybePrivateName(); + } else { + next(); + } + // Smart pipeline topic reference. + return false; + } + + default: + unexpected(); + return false; + } +} + +function parseMaybePrivateName() { + eat(tt.hash); + parseIdentifier(); +} + +function parseFunctionExpression() { + const functionStart = state.start; + parseIdentifier(); + if (eat(tt.dot)) { + // function.sent + parseIdentifier(); + } + parseFunction(functionStart, false); +} + +export function parseLiteral() { + next(); +} + +export function parseParenExpression() { + expect(tt.parenL); + parseExpression(); + expect(tt.parenR); +} + +// Returns true if this was an arrow expression. +function parseParenAndDistinguishExpression(canBeArrow) { + // Assume this is a normal parenthesized expression, but if we see an arrow, we'll bail and + // start over as a parameter list. + const snapshot = state.snapshot(); + + const startTokenIndex = state.tokens.length; + expect(tt.parenL); + + let first = true; + + while (!match(tt.parenR) && !state.error) { + if (first) { + first = false; + } else { + expect(tt.comma); + if (match(tt.parenR)) { + break; + } + } + + if (match(tt.ellipsis)) { + parseRest(false /* isBlockScope */); + parseParenItem(); + break; + } else { + parseMaybeAssign(false, true); + } + } + + expect(tt.parenR); + + if (canBeArrow && shouldParseArrow()) { + const wasArrow = parseArrow(); + if (wasArrow) { + // It was an arrow function this whole time, so start over and parse it as params so that we + // get proper token annotations. + state.restoreFromSnapshot(snapshot); + state.scopeDepth++; + // Don't specify a context ID because arrow functions don't need a context ID. + parseFunctionParams(); + parseArrow(); + parseArrowExpression(startTokenIndex); + if (state.error) { + // Nevermind! This must have been something that looks very much like an + // arrow function but where its "parameter list" isn't actually a valid + // parameter list. Force non-arrow parsing. + // See https://github.com/alangpierce/sucrase/issues/666 for an example. + state.restoreFromSnapshot(snapshot); + parseParenAndDistinguishExpression(false); + return false; + } + return true; + } + } + + return false; +} + +function shouldParseArrow() { + return match(tt.colon) || !canInsertSemicolon(); +} + +// Returns whether there was an arrow token. +export function parseArrow() { + if (isTypeScriptEnabled) { + return tsParseArrow(); + } else if (isFlowEnabled) { + return flowParseArrow(); + } else { + return eat(tt.arrow); + } +} + +function parseParenItem() { + if (isTypeScriptEnabled || isFlowEnabled) { + typedParseParenItem(); + } +} + +// New's precedence is slightly tricky. It must allow its argument to +// be a `[]` or dot subscript expression, but not a call — at least, +// not without wrapping it in parentheses. Thus, it uses the noCalls +// argument to parseSubscripts to prevent it from consuming the +// argument list. +function parseNew() { + expect(tt._new); + if (eat(tt.dot)) { + // new.target + parseIdentifier(); + return; + } + parseNewCallee(); + if (isFlowEnabled) { + flowStartParseNewArguments(); + } + if (eat(tt.parenL)) { + parseExprList(tt.parenR); + } +} + +function parseNewCallee() { + parseNoCallExpr(); + eat(tt.questionDot); +} + +export function parseTemplate() { + // Finish `, read quasi + nextTemplateToken(); + // Finish quasi, read ${ + nextTemplateToken(); + while (!match(tt.backQuote) && !state.error) { + expect(tt.dollarBraceL); + parseExpression(); + // Finish }, read quasi + nextTemplateToken(); + // Finish quasi, read either ${ or ` + nextTemplateToken(); + } + next(); +} + +// Parse an object literal or binding pattern. +export function parseObj(isPattern, isBlockScope) { + // Attach a context ID to the object open and close brace and each object key. + const contextId = getNextContextId(); + let first = true; + + next(); + state.tokens[state.tokens.length - 1].contextId = contextId; + + while (!eat(tt.braceR) && !state.error) { + if (first) { + first = false; + } else { + expect(tt.comma); + if (eat(tt.braceR)) { + break; + } + } + + let isGenerator = false; + if (match(tt.ellipsis)) { + const previousIndex = state.tokens.length; + parseSpread(); + if (isPattern) { + // Mark role when the only thing being spread over is an identifier. + if (state.tokens.length === previousIndex + 2) { + markPriorBindingIdentifier(isBlockScope); + } + if (eat(tt.braceR)) { + break; + } + } + continue; + } + + if (!isPattern) { + isGenerator = eat(tt.star); + } + + if (!isPattern && isContextual(ContextualKeyword._async)) { + if (isGenerator) unexpected(); + + parseIdentifier(); + if ( + match(tt.colon) || + match(tt.parenL) || + match(tt.braceR) || + match(tt.eq) || + match(tt.comma) + ) { + // This is a key called "async" rather than an async function. + } else { + if (match(tt.star)) { + next(); + isGenerator = true; + } + parsePropertyName(contextId); + } + } else { + parsePropertyName(contextId); + } + + parseObjPropValue(isPattern, isBlockScope, contextId); + } + + state.tokens[state.tokens.length - 1].contextId = contextId; +} + +function isGetterOrSetterMethod(isPattern) { + // We go off of the next and don't bother checking if the node key is actually "get" or "set". + // This lets us avoid generating a node, and should only make the validation worse. + return ( + !isPattern && + (match(tt.string) || // get "string"() {} + match(tt.num) || // get 1() {} + match(tt.bracketL) || // get ["string"]() {} + match(tt.name) || // get foo() {} + !!(state.type & TokenType.IS_KEYWORD)) // get debugger() {} + ); +} + +// Returns true if this was a method. +function parseObjectMethod(isPattern, objectContextId) { + // We don't need to worry about modifiers because object methods can't have optional bodies, so + // the start will never be used. + const functionStart = state.start; + if (match(tt.parenL)) { + if (isPattern) unexpected(); + parseMethod(functionStart, /* isConstructor */ false); + return true; + } + + if (isGetterOrSetterMethod(isPattern)) { + parsePropertyName(objectContextId); + parseMethod(functionStart, /* isConstructor */ false); + return true; + } + return false; +} + +function parseObjectProperty(isPattern, isBlockScope) { + if (eat(tt.colon)) { + if (isPattern) { + parseMaybeDefault(isBlockScope); + } else { + parseMaybeAssign(false); + } + return; + } + + // Since there's no colon, we assume this is an object shorthand. + + // If we're in a destructuring, we've now discovered that the key was actually an assignee, so + // we need to tag it as a declaration with the appropriate scope. Otherwise, we might need to + // transform it on access, so mark it as a normal object shorthand. + let identifierRole; + if (isPattern) { + if (state.scopeDepth === 0) { + identifierRole = IdentifierRole.ObjectShorthandTopLevelDeclaration; + } else if (isBlockScope) { + identifierRole = IdentifierRole.ObjectShorthandBlockScopedDeclaration; + } else { + identifierRole = IdentifierRole.ObjectShorthandFunctionScopedDeclaration; + } + } else { + identifierRole = IdentifierRole.ObjectShorthand; + } + state.tokens[state.tokens.length - 1].identifierRole = identifierRole; + + // Regardless of whether we know this to be a pattern or if we're in an ambiguous context, allow + // parsing as if there's a default value. + parseMaybeDefault(isBlockScope, true); +} + +function parseObjPropValue( + isPattern, + isBlockScope, + objectContextId, +) { + if (isTypeScriptEnabled) { + tsStartParseObjPropValue(); + } else if (isFlowEnabled) { + flowStartParseObjPropValue(); + } + const wasMethod = parseObjectMethod(isPattern, objectContextId); + if (!wasMethod) { + parseObjectProperty(isPattern, isBlockScope); + } +} + +export function parsePropertyName(objectContextId) { + if (isFlowEnabled) { + flowParseVariance(); + } + if (eat(tt.bracketL)) { + state.tokens[state.tokens.length - 1].contextId = objectContextId; + parseMaybeAssign(); + expect(tt.bracketR); + state.tokens[state.tokens.length - 1].contextId = objectContextId; + } else { + if (match(tt.num) || match(tt.string) || match(tt.bigint) || match(tt.decimal)) { + parseExprAtom(); + } else { + parseMaybePrivateName(); + } + + state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ObjectKey; + state.tokens[state.tokens.length - 1].contextId = objectContextId; + } +} + +// Parse object or class method. +export function parseMethod(functionStart, isConstructor) { + const funcContextId = getNextContextId(); + + state.scopeDepth++; + const startTokenIndex = state.tokens.length; + const allowModifiers = isConstructor; // For TypeScript parameter properties + parseFunctionParams(allowModifiers, funcContextId); + parseFunctionBodyAndFinish(functionStart, funcContextId); + const endTokenIndex = state.tokens.length; + state.scopes.push(new Scope(startTokenIndex, endTokenIndex, true)); + state.scopeDepth--; +} + +// Parse arrow function expression. +// If the parameters are provided, they will be converted to an +// assignable list. +export function parseArrowExpression(startTokenIndex) { + parseFunctionBody(true); + const endTokenIndex = state.tokens.length; + state.scopes.push(new Scope(startTokenIndex, endTokenIndex, true)); + state.scopeDepth--; +} + +export function parseFunctionBodyAndFinish(functionStart, funcContextId = 0) { + if (isTypeScriptEnabled) { + tsParseFunctionBodyAndFinish(functionStart, funcContextId); + } else if (isFlowEnabled) { + flowParseFunctionBodyAndFinish(funcContextId); + } else { + parseFunctionBody(false, funcContextId); + } +} + +export function parseFunctionBody(allowExpression, funcContextId = 0) { + const isExpression = allowExpression && !match(tt.braceL); + + if (isExpression) { + parseMaybeAssign(); + } else { + parseBlock(true /* isFunctionScope */, funcContextId); + } +} + +// Parses a comma-separated list of expressions, and returns them as +// an array. `close` is the token type that ends the list, and +// `allowEmpty` can be turned on to allow subsequent commas with +// nothing in between them to be parsed as `null` (which is needed +// for array literals). + +function parseExprList(close, allowEmpty = false) { + let first = true; + while (!eat(close) && !state.error) { + if (first) { + first = false; + } else { + expect(tt.comma); + if (eat(close)) break; + } + parseExprListItem(allowEmpty); + } +} + +function parseExprListItem(allowEmpty) { + if (allowEmpty && match(tt.comma)) { + // Empty item; nothing more to parse for this item. + } else if (match(tt.ellipsis)) { + parseSpread(); + parseParenItem(); + } else if (match(tt.question)) { + // Partial function application proposal. + next(); + } else { + parseMaybeAssign(false, true); + } +} + +// Parse the next token as an identifier. +export function parseIdentifier() { + next(); + state.tokens[state.tokens.length - 1].type = tt.name; +} + +// Parses await expression inside async function. +function parseAwait() { + parseMaybeUnary(); +} + +// Parses yield expression inside generator. +function parseYield() { + next(); + if (!match(tt.semi) && !canInsertSemicolon()) { + eat(tt.star); + parseMaybeAssign(); + } +} + +// https://github.com/tc39/proposal-js-module-blocks +function parseModuleExpression() { + expectContextual(ContextualKeyword._module); + expect(tt.braceL); + // For now, just call parseBlockBody to parse the block. In the future when we + // implement full support, we'll want to emit scopes and possibly other + // information. + parseBlockBody(tt.braceR); +} diff --git a/node_modules/sucrase/dist/esm/parser/traverser/index.js b/node_modules/sucrase/dist/esm/parser/traverser/index.js new file mode 100644 index 0000000..eb8c990 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/traverser/index.js @@ -0,0 +1,18 @@ + +import {nextToken, skipLineComment} from "../tokenizer/index"; +import {charCodes} from "../util/charcodes"; +import {input, state} from "./base"; +import {parseTopLevel} from "./statement"; + +export function parseFile() { + // If enabled, skip leading hashbang line. + if ( + state.pos === 0 && + input.charCodeAt(0) === charCodes.numberSign && + input.charCodeAt(1) === charCodes.exclamationMark + ) { + skipLineComment(2); + } + nextToken(); + return parseTopLevel(); +} diff --git a/node_modules/sucrase/dist/esm/parser/traverser/lval.js b/node_modules/sucrase/dist/esm/parser/traverser/lval.js new file mode 100644 index 0000000..f5c4855 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/traverser/lval.js @@ -0,0 +1,159 @@ +import {flowParseAssignableListItemTypes} from "../plugins/flow"; +import {tsParseAssignableListItemTypes, tsParseModifiers} from "../plugins/typescript"; +import { + eat, + IdentifierRole, + match, + next, + popTypeContext, + pushTypeContext, +} from "../tokenizer/index"; +import {ContextualKeyword} from "../tokenizer/keywords"; +import {TokenType, TokenType as tt} from "../tokenizer/types"; +import {isFlowEnabled, isTypeScriptEnabled, state} from "./base"; +import {parseIdentifier, parseMaybeAssign, parseObj} from "./expression"; +import {expect, unexpected} from "./util"; + +export function parseSpread() { + next(); + parseMaybeAssign(false); +} + +export function parseRest(isBlockScope) { + next(); + parseBindingAtom(isBlockScope); +} + +export function parseBindingIdentifier(isBlockScope) { + parseIdentifier(); + markPriorBindingIdentifier(isBlockScope); +} + +export function parseImportedIdentifier() { + parseIdentifier(); + state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ImportDeclaration; +} + +export function markPriorBindingIdentifier(isBlockScope) { + let identifierRole; + if (state.scopeDepth === 0) { + identifierRole = IdentifierRole.TopLevelDeclaration; + } else if (isBlockScope) { + identifierRole = IdentifierRole.BlockScopedDeclaration; + } else { + identifierRole = IdentifierRole.FunctionScopedDeclaration; + } + state.tokens[state.tokens.length - 1].identifierRole = identifierRole; +} + +// Parses lvalue (assignable) atom. +export function parseBindingAtom(isBlockScope) { + switch (state.type) { + case tt._this: { + // In TypeScript, "this" may be the name of a parameter, so allow it. + const oldIsType = pushTypeContext(0); + next(); + popTypeContext(oldIsType); + return; + } + + case tt._yield: + case tt.name: { + state.type = tt.name; + parseBindingIdentifier(isBlockScope); + return; + } + + case tt.bracketL: { + next(); + parseBindingList(tt.bracketR, isBlockScope, true /* allowEmpty */); + return; + } + + case tt.braceL: + parseObj(true, isBlockScope); + return; + + default: + unexpected(); + } +} + +export function parseBindingList( + close, + isBlockScope, + allowEmpty = false, + allowModifiers = false, + contextId = 0, +) { + let first = true; + + let hasRemovedComma = false; + const firstItemTokenIndex = state.tokens.length; + + while (!eat(close) && !state.error) { + if (first) { + first = false; + } else { + expect(tt.comma); + state.tokens[state.tokens.length - 1].contextId = contextId; + // After a "this" type in TypeScript, we need to set the following comma (if any) to also be + // a type token so that it will be removed. + if (!hasRemovedComma && state.tokens[firstItemTokenIndex].isType) { + state.tokens[state.tokens.length - 1].isType = true; + hasRemovedComma = true; + } + } + if (allowEmpty && match(tt.comma)) { + // Empty item; nothing further to parse for this item. + } else if (eat(close)) { + break; + } else if (match(tt.ellipsis)) { + parseRest(isBlockScope); + parseAssignableListItemTypes(); + // Support rest element trailing commas allowed by TypeScript <2.9. + eat(TokenType.comma); + expect(close); + break; + } else { + parseAssignableListItem(allowModifiers, isBlockScope); + } + } +} + +function parseAssignableListItem(allowModifiers, isBlockScope) { + if (allowModifiers) { + tsParseModifiers([ + ContextualKeyword._public, + ContextualKeyword._protected, + ContextualKeyword._private, + ContextualKeyword._readonly, + ContextualKeyword._override, + ]); + } + + parseMaybeDefault(isBlockScope); + parseAssignableListItemTypes(); + parseMaybeDefault(isBlockScope, true /* leftAlreadyParsed */); +} + +function parseAssignableListItemTypes() { + if (isFlowEnabled) { + flowParseAssignableListItemTypes(); + } else if (isTypeScriptEnabled) { + tsParseAssignableListItemTypes(); + } +} + +// Parses assignment pattern around given atom if possible. +export function parseMaybeDefault(isBlockScope, leftAlreadyParsed = false) { + if (!leftAlreadyParsed) { + parseBindingAtom(isBlockScope); + } + if (!eat(tt.eq)) { + return; + } + const eqIndex = state.tokens.length - 1; + parseMaybeAssign(); + state.tokens[eqIndex].rhsEndIndex = state.tokens.length; +} diff --git a/node_modules/sucrase/dist/esm/parser/traverser/statement.js b/node_modules/sucrase/dist/esm/parser/traverser/statement.js new file mode 100644 index 0000000..34a6511 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/traverser/statement.js @@ -0,0 +1,1332 @@ +/* eslint max-len: 0 */ + +import {File} from "../index"; +import { + flowAfterParseClassSuper, + flowAfterParseVarHead, + flowParseExportDeclaration, + flowParseExportStar, + flowParseIdentifierStatement, + flowParseImportSpecifier, + flowParseTypeAnnotation, + flowParseTypeParameterDeclaration, + flowShouldDisallowExportDefaultSpecifier, + flowShouldParseExportDeclaration, + flowShouldParseExportStar, + flowStartParseFunctionParams, + flowStartParseImportSpecifiers, + flowTryParseExportDefaultExpression, + flowTryParseStatement, +} from "../plugins/flow"; +import { + tsAfterParseClassSuper, + tsAfterParseVarHead, + tsIsDeclarationStart, + tsParseExportDeclaration, + tsParseExportSpecifier, + tsParseIdentifierStatement, + tsParseImportEqualsDeclaration, + tsParseImportSpecifier, + tsParseMaybeDecoratorArguments, + tsParseModifiers, + tsStartParseFunctionParams, + tsTryParseClassMemberWithIsStatic, + tsTryParseExport, + tsTryParseExportDefaultExpression, + tsTryParseStatementContent, + tsTryParseTypeAnnotation, + tsTryParseTypeParameters, +} from "../plugins/typescript"; +import { + eat, + eatTypeToken, + IdentifierRole, + lookaheadType, + lookaheadTypeAndKeyword, + match, + next, + nextTokenStart, + nextTokenStartSince, + popTypeContext, + pushTypeContext, +} from "../tokenizer"; +import {ContextualKeyword} from "../tokenizer/keywords"; +import {Scope} from "../tokenizer/state"; +import { TokenType as tt} from "../tokenizer/types"; +import {charCodes} from "../util/charcodes"; +import {getNextContextId, input, isFlowEnabled, isTypeScriptEnabled, state} from "./base"; +import { + parseCallExpressionArguments, + parseExprAtom, + parseExpression, + parseExprSubscripts, + parseFunctionBodyAndFinish, + parseIdentifier, + parseMaybeAssign, + parseMethod, + parseObj, + parseParenExpression, + parsePropertyName, +} from "./expression"; +import { + parseBindingAtom, + parseBindingIdentifier, + parseBindingList, + parseImportedIdentifier, +} from "./lval"; +import { + canInsertSemicolon, + eatContextual, + expect, + expectContextual, + hasFollowingLineBreak, + hasPrecedingLineBreak, + isContextual, + isLineTerminator, + isLookaheadContextual, + semicolon, + unexpected, +} from "./util"; + +export function parseTopLevel() { + parseBlockBody(tt.eof); + state.scopes.push(new Scope(0, state.tokens.length, true)); + if (state.scopeDepth !== 0) { + throw new Error(`Invalid scope depth at end of file: ${state.scopeDepth}`); + } + return new File(state.tokens, state.scopes); +} + +// Parse a single statement. +// +// If expecting a statement and finding a slash operator, parse a +// regular expression literal. This is to handle cases like +// `if (foo) /blah/.exec(foo)`, where looking at the previous token +// does not help. + +export function parseStatement(declaration) { + if (isFlowEnabled) { + if (flowTryParseStatement()) { + return; + } + } + if (match(tt.at)) { + parseDecorators(); + } + parseStatementContent(declaration); +} + +function parseStatementContent(declaration) { + if (isTypeScriptEnabled) { + if (tsTryParseStatementContent()) { + return; + } + } + + const starttype = state.type; + + // Most types of statements are recognized by the keyword they + // start with. Many are trivial to parse, some require a bit of + // complexity. + + switch (starttype) { + case tt._break: + case tt._continue: + parseBreakContinueStatement(); + return; + case tt._debugger: + parseDebuggerStatement(); + return; + case tt._do: + parseDoStatement(); + return; + case tt._for: + parseForStatement(); + return; + case tt._function: + if (lookaheadType() === tt.dot) break; + if (!declaration) unexpected(); + parseFunctionStatement(); + return; + + case tt._class: + if (!declaration) unexpected(); + parseClass(true); + return; + + case tt._if: + parseIfStatement(); + return; + case tt._return: + parseReturnStatement(); + return; + case tt._switch: + parseSwitchStatement(); + return; + case tt._throw: + parseThrowStatement(); + return; + case tt._try: + parseTryStatement(); + return; + + case tt._let: + case tt._const: + if (!declaration) unexpected(); // NOTE: falls through to _var + + case tt._var: + parseVarStatement(starttype !== tt._var); + return; + + case tt._while: + parseWhileStatement(); + return; + case tt.braceL: + parseBlock(); + return; + case tt.semi: + parseEmptyStatement(); + return; + case tt._export: + case tt._import: { + const nextType = lookaheadType(); + if (nextType === tt.parenL || nextType === tt.dot) { + break; + } + next(); + if (starttype === tt._import) { + parseImport(); + } else { + parseExport(); + } + return; + } + case tt.name: + if (state.contextualKeyword === ContextualKeyword._async) { + const functionStart = state.start; + // peek ahead and see if next token is a function + const snapshot = state.snapshot(); + next(); + if (match(tt._function) && !canInsertSemicolon()) { + expect(tt._function); + parseFunction(functionStart, true); + return; + } else { + state.restoreFromSnapshot(snapshot); + } + } else if ( + state.contextualKeyword === ContextualKeyword._using && + !hasFollowingLineBreak() && + // Statements like `using[0]` and `using in foo` aren't actual using + // declarations. + lookaheadType() === tt.name + ) { + parseVarStatement(true); + return; + } else if (startsAwaitUsing()) { + expectContextual(ContextualKeyword._await); + parseVarStatement(true); + return; + } + default: + // Do nothing. + break; + } + + // If the statement does not start with a statement keyword or a + // brace, it's an ExpressionStatement or LabeledStatement. We + // simply start parsing an expression, and afterwards, if the + // next token is a colon and the expression was a simple + // Identifier node, we switch to interpreting it as a label. + const initialTokensLength = state.tokens.length; + parseExpression(); + let simpleName = null; + if (state.tokens.length === initialTokensLength + 1) { + const token = state.tokens[state.tokens.length - 1]; + if (token.type === tt.name) { + simpleName = token.contextualKeyword; + } + } + if (simpleName == null) { + semicolon(); + return; + } + if (eat(tt.colon)) { + parseLabeledStatement(); + } else { + // This was an identifier, so we might want to handle flow/typescript-specific cases. + parseIdentifierStatement(simpleName); + } +} + +/** + * Determine if we're positioned at an `await using` declaration. + * + * Note that this can happen either in place of a regular variable declaration + * or in a loop body, and in both places, there are similar-looking cases where + * we need to return false. + * + * Examples returning true: + * await using foo = bar(); + * for (await using a of b) {} + * + * Examples returning false: + * await using + * await using + 1 + * await using instanceof T + * for (await using;;) {} + * + * For now, we early return if we don't see `await`, then do a simple + * backtracking-based lookahead for the `using` and identifier tokens. In the + * future, this could be optimized with a character-based approach. + */ +function startsAwaitUsing() { + if (!isContextual(ContextualKeyword._await)) { + return false; + } + const snapshot = state.snapshot(); + // await + next(); + if (!isContextual(ContextualKeyword._using) || hasPrecedingLineBreak()) { + state.restoreFromSnapshot(snapshot); + return false; + } + // using + next(); + if (!match(tt.name) || hasPrecedingLineBreak()) { + state.restoreFromSnapshot(snapshot); + return false; + } + state.restoreFromSnapshot(snapshot); + return true; +} + +export function parseDecorators() { + while (match(tt.at)) { + parseDecorator(); + } +} + +function parseDecorator() { + next(); + if (eat(tt.parenL)) { + parseExpression(); + expect(tt.parenR); + } else { + parseIdentifier(); + while (eat(tt.dot)) { + parseIdentifier(); + } + parseMaybeDecoratorArguments(); + } +} + +function parseMaybeDecoratorArguments() { + if (isTypeScriptEnabled) { + tsParseMaybeDecoratorArguments(); + } else { + baseParseMaybeDecoratorArguments(); + } +} + +export function baseParseMaybeDecoratorArguments() { + if (eat(tt.parenL)) { + parseCallExpressionArguments(); + } +} + +function parseBreakContinueStatement() { + next(); + if (!isLineTerminator()) { + parseIdentifier(); + semicolon(); + } +} + +function parseDebuggerStatement() { + next(); + semicolon(); +} + +function parseDoStatement() { + next(); + parseStatement(false); + expect(tt._while); + parseParenExpression(); + eat(tt.semi); +} + +function parseForStatement() { + state.scopeDepth++; + const startTokenIndex = state.tokens.length; + parseAmbiguousForStatement(); + const endTokenIndex = state.tokens.length; + state.scopes.push(new Scope(startTokenIndex, endTokenIndex, false)); + state.scopeDepth--; +} + +/** + * Determine if this token is a `using` declaration (explicit resource + * management) as part of a loop. + * https://github.com/tc39/proposal-explicit-resource-management + */ +function isUsingInLoop() { + if (!isContextual(ContextualKeyword._using)) { + return false; + } + // This must be `for (using of`, where `using` is the name of the loop + // variable. + if (isLookaheadContextual(ContextualKeyword._of)) { + return false; + } + return true; +} + +// Disambiguating between a `for` and a `for`/`in` or `for`/`of` +// loop is non-trivial. Basically, we have to parse the init `var` +// statement or expression, disallowing the `in` operator (see +// the second parameter to `parseExpression`), and then check +// whether the next token is `in` or `of`. When there is no init +// part (semicolon immediately after the opening parenthesis), it +// is a regular `for` loop. +function parseAmbiguousForStatement() { + next(); + + let forAwait = false; + if (isContextual(ContextualKeyword._await)) { + forAwait = true; + next(); + } + expect(tt.parenL); + + if (match(tt.semi)) { + if (forAwait) { + unexpected(); + } + parseFor(); + return; + } + + const isAwaitUsing = startsAwaitUsing(); + if (isAwaitUsing || match(tt._var) || match(tt._let) || match(tt._const) || isUsingInLoop()) { + if (isAwaitUsing) { + expectContextual(ContextualKeyword._await); + } + next(); + parseVar(true, state.type !== tt._var); + if (match(tt._in) || isContextual(ContextualKeyword._of)) { + parseForIn(forAwait); + return; + } + parseFor(); + return; + } + + parseExpression(true); + if (match(tt._in) || isContextual(ContextualKeyword._of)) { + parseForIn(forAwait); + return; + } + if (forAwait) { + unexpected(); + } + parseFor(); +} + +function parseFunctionStatement() { + const functionStart = state.start; + next(); + parseFunction(functionStart, true); +} + +function parseIfStatement() { + next(); + parseParenExpression(); + parseStatement(false); + if (eat(tt._else)) { + parseStatement(false); + } +} + +function parseReturnStatement() { + next(); + + // In `return` (and `break`/`continue`), the keywords with + // optional arguments, we eagerly look for a semicolon or the + // possibility to insert one. + + if (!isLineTerminator()) { + parseExpression(); + semicolon(); + } +} + +function parseSwitchStatement() { + next(); + parseParenExpression(); + state.scopeDepth++; + const startTokenIndex = state.tokens.length; + expect(tt.braceL); + + // Don't bother validation; just go through any sequence of cases, defaults, and statements. + while (!match(tt.braceR) && !state.error) { + if (match(tt._case) || match(tt._default)) { + const isCase = match(tt._case); + next(); + if (isCase) { + parseExpression(); + } + expect(tt.colon); + } else { + parseStatement(true); + } + } + next(); // Closing brace + const endTokenIndex = state.tokens.length; + state.scopes.push(new Scope(startTokenIndex, endTokenIndex, false)); + state.scopeDepth--; +} + +function parseThrowStatement() { + next(); + parseExpression(); + semicolon(); +} + +function parseCatchClauseParam() { + parseBindingAtom(true /* isBlockScope */); + + if (isTypeScriptEnabled) { + tsTryParseTypeAnnotation(); + } +} + +function parseTryStatement() { + next(); + + parseBlock(); + + if (match(tt._catch)) { + next(); + let catchBindingStartTokenIndex = null; + if (match(tt.parenL)) { + state.scopeDepth++; + catchBindingStartTokenIndex = state.tokens.length; + expect(tt.parenL); + parseCatchClauseParam(); + expect(tt.parenR); + } + parseBlock(); + if (catchBindingStartTokenIndex != null) { + // We need a special scope for the catch binding which includes the binding itself and the + // catch block. + const endTokenIndex = state.tokens.length; + state.scopes.push(new Scope(catchBindingStartTokenIndex, endTokenIndex, false)); + state.scopeDepth--; + } + } + if (eat(tt._finally)) { + parseBlock(); + } +} + +export function parseVarStatement(isBlockScope) { + next(); + parseVar(false, isBlockScope); + semicolon(); +} + +function parseWhileStatement() { + next(); + parseParenExpression(); + parseStatement(false); +} + +function parseEmptyStatement() { + next(); +} + +function parseLabeledStatement() { + parseStatement(true); +} + +/** + * Parse a statement starting with an identifier of the given name. Subclasses match on the name + * to handle statements like "declare". + */ +function parseIdentifierStatement(contextualKeyword) { + if (isTypeScriptEnabled) { + tsParseIdentifierStatement(contextualKeyword); + } else if (isFlowEnabled) { + flowParseIdentifierStatement(contextualKeyword); + } else { + semicolon(); + } +} + +// Parse a semicolon-enclosed block of statements. +export function parseBlock(isFunctionScope = false, contextId = 0) { + const startTokenIndex = state.tokens.length; + state.scopeDepth++; + expect(tt.braceL); + if (contextId) { + state.tokens[state.tokens.length - 1].contextId = contextId; + } + parseBlockBody(tt.braceR); + if (contextId) { + state.tokens[state.tokens.length - 1].contextId = contextId; + } + const endTokenIndex = state.tokens.length; + state.scopes.push(new Scope(startTokenIndex, endTokenIndex, isFunctionScope)); + state.scopeDepth--; +} + +export function parseBlockBody(end) { + while (!eat(end) && !state.error) { + parseStatement(true); + } +} + +// Parse a regular `for` loop. The disambiguation code in +// `parseStatement` will already have parsed the init statement or +// expression. + +function parseFor() { + expect(tt.semi); + if (!match(tt.semi)) { + parseExpression(); + } + expect(tt.semi); + if (!match(tt.parenR)) { + parseExpression(); + } + expect(tt.parenR); + parseStatement(false); +} + +// Parse a `for`/`in` and `for`/`of` loop, which are almost +// same from parser's perspective. + +function parseForIn(forAwait) { + if (forAwait) { + eatContextual(ContextualKeyword._of); + } else { + next(); + } + parseExpression(); + expect(tt.parenR); + parseStatement(false); +} + +// Parse a list of variable declarations. + +function parseVar(isFor, isBlockScope) { + while (true) { + parseVarHead(isBlockScope); + if (eat(tt.eq)) { + const eqIndex = state.tokens.length - 1; + parseMaybeAssign(isFor); + state.tokens[eqIndex].rhsEndIndex = state.tokens.length; + } + if (!eat(tt.comma)) { + break; + } + } +} + +function parseVarHead(isBlockScope) { + parseBindingAtom(isBlockScope); + if (isTypeScriptEnabled) { + tsAfterParseVarHead(); + } else if (isFlowEnabled) { + flowAfterParseVarHead(); + } +} + +// Parse a function declaration or literal (depending on the +// `isStatement` parameter). + +export function parseFunction( + functionStart, + isStatement, + optionalId = false, +) { + if (match(tt.star)) { + next(); + } + + if (isStatement && !optionalId && !match(tt.name) && !match(tt._yield)) { + unexpected(); + } + + let nameScopeStartTokenIndex = null; + + if (match(tt.name)) { + // Expression-style functions should limit their name's scope to the function body, so we make + // a new function scope to enforce that. + if (!isStatement) { + nameScopeStartTokenIndex = state.tokens.length; + state.scopeDepth++; + } + parseBindingIdentifier(false); + } + + const startTokenIndex = state.tokens.length; + state.scopeDepth++; + parseFunctionParams(); + parseFunctionBodyAndFinish(functionStart); + const endTokenIndex = state.tokens.length; + // In addition to the block scope of the function body, we need a separate function-style scope + // that includes the params. + state.scopes.push(new Scope(startTokenIndex, endTokenIndex, true)); + state.scopeDepth--; + if (nameScopeStartTokenIndex !== null) { + state.scopes.push(new Scope(nameScopeStartTokenIndex, endTokenIndex, true)); + state.scopeDepth--; + } +} + +export function parseFunctionParams( + allowModifiers = false, + funcContextId = 0, +) { + if (isTypeScriptEnabled) { + tsStartParseFunctionParams(); + } else if (isFlowEnabled) { + flowStartParseFunctionParams(); + } + + expect(tt.parenL); + if (funcContextId) { + state.tokens[state.tokens.length - 1].contextId = funcContextId; + } + parseBindingList( + tt.parenR, + false /* isBlockScope */, + false /* allowEmpty */, + allowModifiers, + funcContextId, + ); + if (funcContextId) { + state.tokens[state.tokens.length - 1].contextId = funcContextId; + } +} + +// Parse a class declaration or literal (depending on the +// `isStatement` parameter). + +export function parseClass(isStatement, optionalId = false) { + // Put a context ID on the class keyword, the open-brace, and the close-brace, so that later + // code can easily navigate to meaningful points on the class. + const contextId = getNextContextId(); + + next(); + state.tokens[state.tokens.length - 1].contextId = contextId; + state.tokens[state.tokens.length - 1].isExpression = !isStatement; + // Like with functions, we declare a special "name scope" from the start of the name to the end + // of the class, but only with expression-style classes, to represent the fact that the name is + // available to the body of the class but not an outer declaration. + let nameScopeStartTokenIndex = null; + if (!isStatement) { + nameScopeStartTokenIndex = state.tokens.length; + state.scopeDepth++; + } + parseClassId(isStatement, optionalId); + parseClassSuper(); + const openBraceIndex = state.tokens.length; + parseClassBody(contextId); + if (state.error) { + return; + } + state.tokens[openBraceIndex].contextId = contextId; + state.tokens[state.tokens.length - 1].contextId = contextId; + if (nameScopeStartTokenIndex !== null) { + const endTokenIndex = state.tokens.length; + state.scopes.push(new Scope(nameScopeStartTokenIndex, endTokenIndex, false)); + state.scopeDepth--; + } +} + +function isClassProperty() { + return match(tt.eq) || match(tt.semi) || match(tt.braceR) || match(tt.bang) || match(tt.colon); +} + +function isClassMethod() { + return match(tt.parenL) || match(tt.lessThan); +} + +function parseClassBody(classContextId) { + expect(tt.braceL); + + while (!eat(tt.braceR) && !state.error) { + if (eat(tt.semi)) { + continue; + } + + if (match(tt.at)) { + parseDecorator(); + continue; + } + const memberStart = state.start; + parseClassMember(memberStart, classContextId); + } +} + +function parseClassMember(memberStart, classContextId) { + if (isTypeScriptEnabled) { + tsParseModifiers([ + ContextualKeyword._declare, + ContextualKeyword._public, + ContextualKeyword._protected, + ContextualKeyword._private, + ContextualKeyword._override, + ]); + } + let isStatic = false; + if (match(tt.name) && state.contextualKeyword === ContextualKeyword._static) { + parseIdentifier(); // eats 'static' + if (isClassMethod()) { + parseClassMethod(memberStart, /* isConstructor */ false); + return; + } else if (isClassProperty()) { + parseClassProperty(); + return; + } + // otherwise something static + state.tokens[state.tokens.length - 1].type = tt._static; + isStatic = true; + + if (match(tt.braceL)) { + // This is a static block. Mark the word "static" with the class context ID for class element + // detection and parse as a regular block. + state.tokens[state.tokens.length - 1].contextId = classContextId; + parseBlock(); + return; + } + } + + parseClassMemberWithIsStatic(memberStart, isStatic, classContextId); +} + +function parseClassMemberWithIsStatic( + memberStart, + isStatic, + classContextId, +) { + if (isTypeScriptEnabled) { + if (tsTryParseClassMemberWithIsStatic(isStatic)) { + return; + } + } + if (eat(tt.star)) { + // a generator + parseClassPropertyName(classContextId); + parseClassMethod(memberStart, /* isConstructor */ false); + return; + } + + // Get the identifier name so we can tell if it's actually a keyword like "async", "get", or + // "set". + parseClassPropertyName(classContextId); + let isConstructor = false; + const token = state.tokens[state.tokens.length - 1]; + // We allow "constructor" as either an identifier or a string. + if (token.contextualKeyword === ContextualKeyword._constructor) { + isConstructor = true; + } + parsePostMemberNameModifiers(); + + if (isClassMethod()) { + parseClassMethod(memberStart, isConstructor); + } else if (isClassProperty()) { + parseClassProperty(); + } else if (token.contextualKeyword === ContextualKeyword._async && !isLineTerminator()) { + state.tokens[state.tokens.length - 1].type = tt._async; + // an async method + const isGenerator = match(tt.star); + if (isGenerator) { + next(); + } + + // The so-called parsed name would have been "async": get the real name. + parseClassPropertyName(classContextId); + parsePostMemberNameModifiers(); + parseClassMethod(memberStart, false /* isConstructor */); + } else if ( + (token.contextualKeyword === ContextualKeyword._get || + token.contextualKeyword === ContextualKeyword._set) && + !(isLineTerminator() && match(tt.star)) + ) { + if (token.contextualKeyword === ContextualKeyword._get) { + state.tokens[state.tokens.length - 1].type = tt._get; + } else { + state.tokens[state.tokens.length - 1].type = tt._set; + } + // `get\n*` is an uninitialized property named 'get' followed by a generator. + // a getter or setter + // The so-called parsed name would have been "get/set": get the real name. + parseClassPropertyName(classContextId); + parseClassMethod(memberStart, /* isConstructor */ false); + } else if (token.contextualKeyword === ContextualKeyword._accessor && !isLineTerminator()) { + parseClassPropertyName(classContextId); + parseClassProperty(); + } else if (isLineTerminator()) { + // an uninitialized class property (due to ASI, since we don't otherwise recognize the next token) + parseClassProperty(); + } else { + unexpected(); + } +} + +function parseClassMethod(functionStart, isConstructor) { + if (isTypeScriptEnabled) { + tsTryParseTypeParameters(); + } else if (isFlowEnabled) { + if (match(tt.lessThan)) { + flowParseTypeParameterDeclaration(); + } + } + parseMethod(functionStart, isConstructor); +} + +// Return the name of the class property, if it is a simple identifier. +export function parseClassPropertyName(classContextId) { + parsePropertyName(classContextId); +} + +export function parsePostMemberNameModifiers() { + if (isTypeScriptEnabled) { + const oldIsType = pushTypeContext(0); + eat(tt.question); + popTypeContext(oldIsType); + } +} + +export function parseClassProperty() { + if (isTypeScriptEnabled) { + eatTypeToken(tt.bang); + tsTryParseTypeAnnotation(); + } else if (isFlowEnabled) { + if (match(tt.colon)) { + flowParseTypeAnnotation(); + } + } + + if (match(tt.eq)) { + const equalsTokenIndex = state.tokens.length; + next(); + parseMaybeAssign(); + state.tokens[equalsTokenIndex].rhsEndIndex = state.tokens.length; + } + semicolon(); +} + +function parseClassId(isStatement, optionalId = false) { + if ( + isTypeScriptEnabled && + (!isStatement || optionalId) && + isContextual(ContextualKeyword._implements) + ) { + return; + } + + if (match(tt.name)) { + parseBindingIdentifier(true); + } + + if (isTypeScriptEnabled) { + tsTryParseTypeParameters(); + } else if (isFlowEnabled) { + if (match(tt.lessThan)) { + flowParseTypeParameterDeclaration(); + } + } +} + +// Returns true if there was a superclass. +function parseClassSuper() { + let hasSuper = false; + if (eat(tt._extends)) { + parseExprSubscripts(); + hasSuper = true; + } else { + hasSuper = false; + } + if (isTypeScriptEnabled) { + tsAfterParseClassSuper(hasSuper); + } else if (isFlowEnabled) { + flowAfterParseClassSuper(hasSuper); + } +} + +// Parses module export declaration. + +export function parseExport() { + const exportIndex = state.tokens.length - 1; + if (isTypeScriptEnabled) { + if (tsTryParseExport()) { + return; + } + } + // export * from '...' + if (shouldParseExportStar()) { + parseExportStar(); + } else if (isExportDefaultSpecifier()) { + // export default from + parseIdentifier(); + if (match(tt.comma) && lookaheadType() === tt.star) { + expect(tt.comma); + expect(tt.star); + expectContextual(ContextualKeyword._as); + parseIdentifier(); + } else { + parseExportSpecifiersMaybe(); + } + parseExportFrom(); + } else if (eat(tt._default)) { + // export default ... + parseExportDefaultExpression(); + } else if (shouldParseExportDeclaration()) { + parseExportDeclaration(); + } else { + // export { x, y as z } [from '...'] + parseExportSpecifiers(); + parseExportFrom(); + } + state.tokens[exportIndex].rhsEndIndex = state.tokens.length; +} + +function parseExportDefaultExpression() { + if (isTypeScriptEnabled) { + if (tsTryParseExportDefaultExpression()) { + return; + } + } + if (isFlowEnabled) { + if (flowTryParseExportDefaultExpression()) { + return; + } + } + const functionStart = state.start; + if (eat(tt._function)) { + parseFunction(functionStart, true, true); + } else if (isContextual(ContextualKeyword._async) && lookaheadType() === tt._function) { + // async function declaration + eatContextual(ContextualKeyword._async); + eat(tt._function); + parseFunction(functionStart, true, true); + } else if (match(tt._class)) { + parseClass(true, true); + } else if (match(tt.at)) { + parseDecorators(); + parseClass(true, true); + } else { + parseMaybeAssign(); + semicolon(); + } +} + +function parseExportDeclaration() { + if (isTypeScriptEnabled) { + tsParseExportDeclaration(); + } else if (isFlowEnabled) { + flowParseExportDeclaration(); + } else { + parseStatement(true); + } +} + +function isExportDefaultSpecifier() { + if (isTypeScriptEnabled && tsIsDeclarationStart()) { + return false; + } else if (isFlowEnabled && flowShouldDisallowExportDefaultSpecifier()) { + return false; + } + if (match(tt.name)) { + return state.contextualKeyword !== ContextualKeyword._async; + } + + if (!match(tt._default)) { + return false; + } + + const _next = nextTokenStart(); + const lookahead = lookaheadTypeAndKeyword(); + const hasFrom = + lookahead.type === tt.name && lookahead.contextualKeyword === ContextualKeyword._from; + if (lookahead.type === tt.comma) { + return true; + } + // lookahead again when `export default from` is seen + if (hasFrom) { + const nextAfterFrom = input.charCodeAt(nextTokenStartSince(_next + 4)); + return nextAfterFrom === charCodes.quotationMark || nextAfterFrom === charCodes.apostrophe; + } + return false; +} + +function parseExportSpecifiersMaybe() { + if (eat(tt.comma)) { + parseExportSpecifiers(); + } +} + +export function parseExportFrom() { + if (eatContextual(ContextualKeyword._from)) { + parseExprAtom(); + maybeParseImportAttributes(); + } + semicolon(); +} + +function shouldParseExportStar() { + if (isFlowEnabled) { + return flowShouldParseExportStar(); + } else { + return match(tt.star); + } +} + +function parseExportStar() { + if (isFlowEnabled) { + flowParseExportStar(); + } else { + baseParseExportStar(); + } +} + +export function baseParseExportStar() { + expect(tt.star); + + if (isContextual(ContextualKeyword._as)) { + parseExportNamespace(); + } else { + parseExportFrom(); + } +} + +function parseExportNamespace() { + next(); + state.tokens[state.tokens.length - 1].type = tt._as; + parseIdentifier(); + parseExportSpecifiersMaybe(); + parseExportFrom(); +} + +function shouldParseExportDeclaration() { + return ( + (isTypeScriptEnabled && tsIsDeclarationStart()) || + (isFlowEnabled && flowShouldParseExportDeclaration()) || + state.type === tt._var || + state.type === tt._const || + state.type === tt._let || + state.type === tt._function || + state.type === tt._class || + isContextual(ContextualKeyword._async) || + match(tt.at) + ); +} + +// Parses a comma-separated list of module exports. +export function parseExportSpecifiers() { + let first = true; + + // export { x, y as z } [from '...'] + expect(tt.braceL); + + while (!eat(tt.braceR) && !state.error) { + if (first) { + first = false; + } else { + expect(tt.comma); + if (eat(tt.braceR)) { + break; + } + } + parseExportSpecifier(); + } +} + +function parseExportSpecifier() { + if (isTypeScriptEnabled) { + tsParseExportSpecifier(); + return; + } + parseIdentifier(); + state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ExportAccess; + if (eatContextual(ContextualKeyword._as)) { + parseIdentifier(); + } +} + +/** + * Starting at the `module` token in an import, determine if it was truly an + * import reflection token or just looks like one. + * + * Returns true for: + * import module foo from "foo"; + * import module from from "foo"; + * + * Returns false for: + * import module from "foo"; + * import module, {bar} from "foo"; + */ +function isImportReflection() { + const snapshot = state.snapshot(); + expectContextual(ContextualKeyword._module); + if (eatContextual(ContextualKeyword._from)) { + if (isContextual(ContextualKeyword._from)) { + state.restoreFromSnapshot(snapshot); + return true; + } else { + state.restoreFromSnapshot(snapshot); + return false; + } + } else if (match(tt.comma)) { + state.restoreFromSnapshot(snapshot); + return false; + } else { + state.restoreFromSnapshot(snapshot); + return true; + } +} + +/** + * Eat the "module" token from the import reflection proposal. + * https://github.com/tc39/proposal-import-reflection + */ +function parseMaybeImportReflection() { + // isImportReflection does snapshot/restore, so only run it if we see the word + // "module". + if (isContextual(ContextualKeyword._module) && isImportReflection()) { + next(); + } +} + +// Parses import declaration. + +export function parseImport() { + if (isTypeScriptEnabled && match(tt.name) && lookaheadType() === tt.eq) { + tsParseImportEqualsDeclaration(); + return; + } + if (isTypeScriptEnabled && isContextual(ContextualKeyword._type)) { + const lookahead = lookaheadTypeAndKeyword(); + if (lookahead.type === tt.name && lookahead.contextualKeyword !== ContextualKeyword._from) { + // One of these `import type` cases: + // import type T = require('T'); + // import type A from 'A'; + expectContextual(ContextualKeyword._type); + if (lookaheadType() === tt.eq) { + tsParseImportEqualsDeclaration(); + return; + } + // If this is an `import type...from` statement, then we already ate the + // type token, so proceed to the regular import parser. + } else if (lookahead.type === tt.star || lookahead.type === tt.braceL) { + // One of these `import type` cases, in which case we can eat the type token + // and proceed as normal: + // import type * as A from 'A'; + // import type {a} from 'A'; + expectContextual(ContextualKeyword._type); + } + // Otherwise, we are importing the name "type". + } + + // import '...' + if (match(tt.string)) { + parseExprAtom(); + } else { + parseMaybeImportReflection(); + parseImportSpecifiers(); + expectContextual(ContextualKeyword._from); + parseExprAtom(); + } + maybeParseImportAttributes(); + semicolon(); +} + +// eslint-disable-next-line no-unused-vars +function shouldParseDefaultImport() { + return match(tt.name); +} + +function parseImportSpecifierLocal() { + parseImportedIdentifier(); +} + +// Parses a comma-separated list of module imports. +function parseImportSpecifiers() { + if (isFlowEnabled) { + flowStartParseImportSpecifiers(); + } + + let first = true; + if (shouldParseDefaultImport()) { + // import defaultObj, { x, y as z } from '...' + parseImportSpecifierLocal(); + + if (!eat(tt.comma)) return; + } + + if (match(tt.star)) { + next(); + expectContextual(ContextualKeyword._as); + + parseImportSpecifierLocal(); + + return; + } + + expect(tt.braceL); + while (!eat(tt.braceR) && !state.error) { + if (first) { + first = false; + } else { + // Detect an attempt to deep destructure + if (eat(tt.colon)) { + unexpected( + "ES2015 named imports do not destructure. Use another statement for destructuring after the import.", + ); + } + + expect(tt.comma); + if (eat(tt.braceR)) { + break; + } + } + + parseImportSpecifier(); + } +} + +function parseImportSpecifier() { + if (isTypeScriptEnabled) { + tsParseImportSpecifier(); + return; + } + if (isFlowEnabled) { + flowParseImportSpecifier(); + return; + } + parseImportedIdentifier(); + if (isContextual(ContextualKeyword._as)) { + state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ImportAccess; + next(); + parseImportedIdentifier(); + } +} + +/** + * Parse import attributes like `with {type: "json"}`, or the legacy form + * `assert {type: "json"}`. + * + * Import attributes technically have their own syntax, but are always parseable + * as a plain JS object, so just do that for simplicity. + */ +function maybeParseImportAttributes() { + if (match(tt._with) || (isContextual(ContextualKeyword._assert) && !hasPrecedingLineBreak())) { + next(); + parseObj(false, false); + } +} diff --git a/node_modules/sucrase/dist/esm/parser/traverser/util.js b/node_modules/sucrase/dist/esm/parser/traverser/util.js new file mode 100644 index 0000000..6a2b2d9 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/traverser/util.js @@ -0,0 +1,104 @@ +import {eat, finishToken, lookaheadTypeAndKeyword, match, nextTokenStart} from "../tokenizer/index"; + +import {formatTokenType, TokenType as tt} from "../tokenizer/types"; +import {charCodes} from "../util/charcodes"; +import {input, state} from "./base"; + +// ## Parser utilities + +// Tests whether parsed token is a contextual keyword. +export function isContextual(contextualKeyword) { + return state.contextualKeyword === contextualKeyword; +} + +export function isLookaheadContextual(contextualKeyword) { + const l = lookaheadTypeAndKeyword(); + return l.type === tt.name && l.contextualKeyword === contextualKeyword; +} + +// Consumes contextual keyword if possible. +export function eatContextual(contextualKeyword) { + return state.contextualKeyword === contextualKeyword && eat(tt.name); +} + +// Asserts that following token is given contextual keyword. +export function expectContextual(contextualKeyword) { + if (!eatContextual(contextualKeyword)) { + unexpected(); + } +} + +// Test whether a semicolon can be inserted at the current position. +export function canInsertSemicolon() { + return match(tt.eof) || match(tt.braceR) || hasPrecedingLineBreak(); +} + +export function hasPrecedingLineBreak() { + const prevToken = state.tokens[state.tokens.length - 1]; + const lastTokEnd = prevToken ? prevToken.end : 0; + for (let i = lastTokEnd; i < state.start; i++) { + const code = input.charCodeAt(i); + if ( + code === charCodes.lineFeed || + code === charCodes.carriageReturn || + code === 0x2028 || + code === 0x2029 + ) { + return true; + } + } + return false; +} + +export function hasFollowingLineBreak() { + const nextStart = nextTokenStart(); + for (let i = state.end; i < nextStart; i++) { + const code = input.charCodeAt(i); + if ( + code === charCodes.lineFeed || + code === charCodes.carriageReturn || + code === 0x2028 || + code === 0x2029 + ) { + return true; + } + } + return false; +} + +export function isLineTerminator() { + return eat(tt.semi) || canInsertSemicolon(); +} + +// Consume a semicolon, or, failing that, see if we are allowed to +// pretend that there is a semicolon at this position. +export function semicolon() { + if (!isLineTerminator()) { + unexpected('Unexpected token, expected ";"'); + } +} + +// Expect a token of a given type. If found, consume it, otherwise, +// raise an unexpected token error at given pos. +export function expect(type) { + const matched = eat(type); + if (!matched) { + unexpected(`Unexpected token, expected "${formatTokenType(type)}"`); + } +} + +/** + * Transition the parser to an error state. All code needs to be written to naturally unwind in this + * state, which allows us to backtrack without exceptions and without error plumbing everywhere. + */ +export function unexpected(message = "Unexpected token", pos = state.start) { + if (state.error) { + return; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const err = new SyntaxError(message); + err.pos = pos; + state.error = err; + state.pos = input.length; + finishToken(tt.eof); +} diff --git a/node_modules/sucrase/dist/esm/parser/util/charcodes.js b/node_modules/sucrase/dist/esm/parser/util/charcodes.js new file mode 100644 index 0000000..36ea667 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/util/charcodes.js @@ -0,0 +1,115 @@ +export var charCodes; (function (charCodes) { + const backSpace = 8; charCodes[charCodes["backSpace"] = backSpace] = "backSpace"; + const lineFeed = 10; charCodes[charCodes["lineFeed"] = lineFeed] = "lineFeed"; // '\n' + const tab = 9; charCodes[charCodes["tab"] = tab] = "tab"; // '\t' + const carriageReturn = 13; charCodes[charCodes["carriageReturn"] = carriageReturn] = "carriageReturn"; // '\r' + const shiftOut = 14; charCodes[charCodes["shiftOut"] = shiftOut] = "shiftOut"; + const space = 32; charCodes[charCodes["space"] = space] = "space"; + const exclamationMark = 33; charCodes[charCodes["exclamationMark"] = exclamationMark] = "exclamationMark"; // '!' + const quotationMark = 34; charCodes[charCodes["quotationMark"] = quotationMark] = "quotationMark"; // '"' + const numberSign = 35; charCodes[charCodes["numberSign"] = numberSign] = "numberSign"; // '#' + const dollarSign = 36; charCodes[charCodes["dollarSign"] = dollarSign] = "dollarSign"; // '$' + const percentSign = 37; charCodes[charCodes["percentSign"] = percentSign] = "percentSign"; // '%' + const ampersand = 38; charCodes[charCodes["ampersand"] = ampersand] = "ampersand"; // '&' + const apostrophe = 39; charCodes[charCodes["apostrophe"] = apostrophe] = "apostrophe"; // ''' + const leftParenthesis = 40; charCodes[charCodes["leftParenthesis"] = leftParenthesis] = "leftParenthesis"; // '(' + const rightParenthesis = 41; charCodes[charCodes["rightParenthesis"] = rightParenthesis] = "rightParenthesis"; // ')' + const asterisk = 42; charCodes[charCodes["asterisk"] = asterisk] = "asterisk"; // '*' + const plusSign = 43; charCodes[charCodes["plusSign"] = plusSign] = "plusSign"; // '+' + const comma = 44; charCodes[charCodes["comma"] = comma] = "comma"; // ',' + const dash = 45; charCodes[charCodes["dash"] = dash] = "dash"; // '-' + const dot = 46; charCodes[charCodes["dot"] = dot] = "dot"; // '.' + const slash = 47; charCodes[charCodes["slash"] = slash] = "slash"; // '/' + const digit0 = 48; charCodes[charCodes["digit0"] = digit0] = "digit0"; // '0' + const digit1 = 49; charCodes[charCodes["digit1"] = digit1] = "digit1"; // '1' + const digit2 = 50; charCodes[charCodes["digit2"] = digit2] = "digit2"; // '2' + const digit3 = 51; charCodes[charCodes["digit3"] = digit3] = "digit3"; // '3' + const digit4 = 52; charCodes[charCodes["digit4"] = digit4] = "digit4"; // '4' + const digit5 = 53; charCodes[charCodes["digit5"] = digit5] = "digit5"; // '5' + const digit6 = 54; charCodes[charCodes["digit6"] = digit6] = "digit6"; // '6' + const digit7 = 55; charCodes[charCodes["digit7"] = digit7] = "digit7"; // '7' + const digit8 = 56; charCodes[charCodes["digit8"] = digit8] = "digit8"; // '8' + const digit9 = 57; charCodes[charCodes["digit9"] = digit9] = "digit9"; // '9' + const colon = 58; charCodes[charCodes["colon"] = colon] = "colon"; // ':' + const semicolon = 59; charCodes[charCodes["semicolon"] = semicolon] = "semicolon"; // ';' + const lessThan = 60; charCodes[charCodes["lessThan"] = lessThan] = "lessThan"; // '<' + const equalsTo = 61; charCodes[charCodes["equalsTo"] = equalsTo] = "equalsTo"; // '=' + const greaterThan = 62; charCodes[charCodes["greaterThan"] = greaterThan] = "greaterThan"; // '>' + const questionMark = 63; charCodes[charCodes["questionMark"] = questionMark] = "questionMark"; // '?' + const atSign = 64; charCodes[charCodes["atSign"] = atSign] = "atSign"; // '@' + const uppercaseA = 65; charCodes[charCodes["uppercaseA"] = uppercaseA] = "uppercaseA"; // 'A' + const uppercaseB = 66; charCodes[charCodes["uppercaseB"] = uppercaseB] = "uppercaseB"; // 'B' + const uppercaseC = 67; charCodes[charCodes["uppercaseC"] = uppercaseC] = "uppercaseC"; // 'C' + const uppercaseD = 68; charCodes[charCodes["uppercaseD"] = uppercaseD] = "uppercaseD"; // 'D' + const uppercaseE = 69; charCodes[charCodes["uppercaseE"] = uppercaseE] = "uppercaseE"; // 'E' + const uppercaseF = 70; charCodes[charCodes["uppercaseF"] = uppercaseF] = "uppercaseF"; // 'F' + const uppercaseG = 71; charCodes[charCodes["uppercaseG"] = uppercaseG] = "uppercaseG"; // 'G' + const uppercaseH = 72; charCodes[charCodes["uppercaseH"] = uppercaseH] = "uppercaseH"; // 'H' + const uppercaseI = 73; charCodes[charCodes["uppercaseI"] = uppercaseI] = "uppercaseI"; // 'I' + const uppercaseJ = 74; charCodes[charCodes["uppercaseJ"] = uppercaseJ] = "uppercaseJ"; // 'J' + const uppercaseK = 75; charCodes[charCodes["uppercaseK"] = uppercaseK] = "uppercaseK"; // 'K' + const uppercaseL = 76; charCodes[charCodes["uppercaseL"] = uppercaseL] = "uppercaseL"; // 'L' + const uppercaseM = 77; charCodes[charCodes["uppercaseM"] = uppercaseM] = "uppercaseM"; // 'M' + const uppercaseN = 78; charCodes[charCodes["uppercaseN"] = uppercaseN] = "uppercaseN"; // 'N' + const uppercaseO = 79; charCodes[charCodes["uppercaseO"] = uppercaseO] = "uppercaseO"; // 'O' + const uppercaseP = 80; charCodes[charCodes["uppercaseP"] = uppercaseP] = "uppercaseP"; // 'P' + const uppercaseQ = 81; charCodes[charCodes["uppercaseQ"] = uppercaseQ] = "uppercaseQ"; // 'Q' + const uppercaseR = 82; charCodes[charCodes["uppercaseR"] = uppercaseR] = "uppercaseR"; // 'R' + const uppercaseS = 83; charCodes[charCodes["uppercaseS"] = uppercaseS] = "uppercaseS"; // 'S' + const uppercaseT = 84; charCodes[charCodes["uppercaseT"] = uppercaseT] = "uppercaseT"; // 'T' + const uppercaseU = 85; charCodes[charCodes["uppercaseU"] = uppercaseU] = "uppercaseU"; // 'U' + const uppercaseV = 86; charCodes[charCodes["uppercaseV"] = uppercaseV] = "uppercaseV"; // 'V' + const uppercaseW = 87; charCodes[charCodes["uppercaseW"] = uppercaseW] = "uppercaseW"; // 'W' + const uppercaseX = 88; charCodes[charCodes["uppercaseX"] = uppercaseX] = "uppercaseX"; // 'X' + const uppercaseY = 89; charCodes[charCodes["uppercaseY"] = uppercaseY] = "uppercaseY"; // 'Y' + const uppercaseZ = 90; charCodes[charCodes["uppercaseZ"] = uppercaseZ] = "uppercaseZ"; // 'Z' + const leftSquareBracket = 91; charCodes[charCodes["leftSquareBracket"] = leftSquareBracket] = "leftSquareBracket"; // '[' + const backslash = 92; charCodes[charCodes["backslash"] = backslash] = "backslash"; // '\ ' + const rightSquareBracket = 93; charCodes[charCodes["rightSquareBracket"] = rightSquareBracket] = "rightSquareBracket"; // ']' + const caret = 94; charCodes[charCodes["caret"] = caret] = "caret"; // '^' + const underscore = 95; charCodes[charCodes["underscore"] = underscore] = "underscore"; // '_' + const graveAccent = 96; charCodes[charCodes["graveAccent"] = graveAccent] = "graveAccent"; // '`' + const lowercaseA = 97; charCodes[charCodes["lowercaseA"] = lowercaseA] = "lowercaseA"; // 'a' + const lowercaseB = 98; charCodes[charCodes["lowercaseB"] = lowercaseB] = "lowercaseB"; // 'b' + const lowercaseC = 99; charCodes[charCodes["lowercaseC"] = lowercaseC] = "lowercaseC"; // 'c' + const lowercaseD = 100; charCodes[charCodes["lowercaseD"] = lowercaseD] = "lowercaseD"; // 'd' + const lowercaseE = 101; charCodes[charCodes["lowercaseE"] = lowercaseE] = "lowercaseE"; // 'e' + const lowercaseF = 102; charCodes[charCodes["lowercaseF"] = lowercaseF] = "lowercaseF"; // 'f' + const lowercaseG = 103; charCodes[charCodes["lowercaseG"] = lowercaseG] = "lowercaseG"; // 'g' + const lowercaseH = 104; charCodes[charCodes["lowercaseH"] = lowercaseH] = "lowercaseH"; // 'h' + const lowercaseI = 105; charCodes[charCodes["lowercaseI"] = lowercaseI] = "lowercaseI"; // 'i' + const lowercaseJ = 106; charCodes[charCodes["lowercaseJ"] = lowercaseJ] = "lowercaseJ"; // 'j' + const lowercaseK = 107; charCodes[charCodes["lowercaseK"] = lowercaseK] = "lowercaseK"; // 'k' + const lowercaseL = 108; charCodes[charCodes["lowercaseL"] = lowercaseL] = "lowercaseL"; // 'l' + const lowercaseM = 109; charCodes[charCodes["lowercaseM"] = lowercaseM] = "lowercaseM"; // 'm' + const lowercaseN = 110; charCodes[charCodes["lowercaseN"] = lowercaseN] = "lowercaseN"; // 'n' + const lowercaseO = 111; charCodes[charCodes["lowercaseO"] = lowercaseO] = "lowercaseO"; // 'o' + const lowercaseP = 112; charCodes[charCodes["lowercaseP"] = lowercaseP] = "lowercaseP"; // 'p' + const lowercaseQ = 113; charCodes[charCodes["lowercaseQ"] = lowercaseQ] = "lowercaseQ"; // 'q' + const lowercaseR = 114; charCodes[charCodes["lowercaseR"] = lowercaseR] = "lowercaseR"; // 'r' + const lowercaseS = 115; charCodes[charCodes["lowercaseS"] = lowercaseS] = "lowercaseS"; // 's' + const lowercaseT = 116; charCodes[charCodes["lowercaseT"] = lowercaseT] = "lowercaseT"; // 't' + const lowercaseU = 117; charCodes[charCodes["lowercaseU"] = lowercaseU] = "lowercaseU"; // 'u' + const lowercaseV = 118; charCodes[charCodes["lowercaseV"] = lowercaseV] = "lowercaseV"; // 'v' + const lowercaseW = 119; charCodes[charCodes["lowercaseW"] = lowercaseW] = "lowercaseW"; // 'w' + const lowercaseX = 120; charCodes[charCodes["lowercaseX"] = lowercaseX] = "lowercaseX"; // 'x' + const lowercaseY = 121; charCodes[charCodes["lowercaseY"] = lowercaseY] = "lowercaseY"; // 'y' + const lowercaseZ = 122; charCodes[charCodes["lowercaseZ"] = lowercaseZ] = "lowercaseZ"; // 'z' + const leftCurlyBrace = 123; charCodes[charCodes["leftCurlyBrace"] = leftCurlyBrace] = "leftCurlyBrace"; // '{' + const verticalBar = 124; charCodes[charCodes["verticalBar"] = verticalBar] = "verticalBar"; // '|' + const rightCurlyBrace = 125; charCodes[charCodes["rightCurlyBrace"] = rightCurlyBrace] = "rightCurlyBrace"; // '}' + const tilde = 126; charCodes[charCodes["tilde"] = tilde] = "tilde"; // '~' + const nonBreakingSpace = 160; charCodes[charCodes["nonBreakingSpace"] = nonBreakingSpace] = "nonBreakingSpace"; + // eslint-disable-next-line no-irregular-whitespace + const oghamSpaceMark = 5760; charCodes[charCodes["oghamSpaceMark"] = oghamSpaceMark] = "oghamSpaceMark"; // ' ' + const lineSeparator = 8232; charCodes[charCodes["lineSeparator"] = lineSeparator] = "lineSeparator"; + const paragraphSeparator = 8233; charCodes[charCodes["paragraphSeparator"] = paragraphSeparator] = "paragraphSeparator"; +})(charCodes || (charCodes = {})); + +export function isDigit(code) { + return ( + (code >= charCodes.digit0 && code <= charCodes.digit9) || + (code >= charCodes.lowercaseA && code <= charCodes.lowercaseF) || + (code >= charCodes.uppercaseA && code <= charCodes.uppercaseF) + ); +} diff --git a/node_modules/sucrase/dist/esm/parser/util/identifier.js b/node_modules/sucrase/dist/esm/parser/util/identifier.js new file mode 100644 index 0000000..33a6bb1 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/util/identifier.js @@ -0,0 +1,34 @@ +import {charCodes} from "./charcodes"; +import {WHITESPACE_CHARS} from "./whitespace"; + +function computeIsIdentifierChar(code) { + if (code < 48) return code === 36; + if (code < 58) return true; + if (code < 65) return false; + if (code < 91) return true; + if (code < 97) return code === 95; + if (code < 123) return true; + if (code < 128) return false; + throw new Error("Should not be called with non-ASCII char code."); +} + +export const IS_IDENTIFIER_CHAR = new Uint8Array(65536); +for (let i = 0; i < 128; i++) { + IS_IDENTIFIER_CHAR[i] = computeIsIdentifierChar(i) ? 1 : 0; +} +for (let i = 128; i < 65536; i++) { + IS_IDENTIFIER_CHAR[i] = 1; +} +// Aside from whitespace and newlines, all characters outside the ASCII space are either +// identifier characters or invalid. Since we're not performing code validation, we can just +// treat all invalid characters as identifier characters. +for (const whitespaceChar of WHITESPACE_CHARS) { + IS_IDENTIFIER_CHAR[whitespaceChar] = 0; +} +IS_IDENTIFIER_CHAR[0x2028] = 0; +IS_IDENTIFIER_CHAR[0x2029] = 0; + +export const IS_IDENTIFIER_START = IS_IDENTIFIER_CHAR.slice(); +for (let numChar = charCodes.digit0; numChar <= charCodes.digit9; numChar++) { + IS_IDENTIFIER_START[numChar] = 0; +} diff --git a/node_modules/sucrase/dist/esm/parser/util/whitespace.js b/node_modules/sucrase/dist/esm/parser/util/whitespace.js new file mode 100644 index 0000000..303b8a6 --- /dev/null +++ b/node_modules/sucrase/dist/esm/parser/util/whitespace.js @@ -0,0 +1,33 @@ +import {charCodes} from "./charcodes"; + +// https://tc39.github.io/ecma262/#sec-white-space +export const WHITESPACE_CHARS = [ + 0x0009, + 0x000b, + 0x000c, + charCodes.space, + charCodes.nonBreakingSpace, + charCodes.oghamSpaceMark, + 0x2000, // EN QUAD + 0x2001, // EM QUAD + 0x2002, // EN SPACE + 0x2003, // EM SPACE + 0x2004, // THREE-PER-EM SPACE + 0x2005, // FOUR-PER-EM SPACE + 0x2006, // SIX-PER-EM SPACE + 0x2007, // FIGURE SPACE + 0x2008, // PUNCTUATION SPACE + 0x2009, // THIN SPACE + 0x200a, // HAIR SPACE + 0x202f, // NARROW NO-BREAK SPACE + 0x205f, // MEDIUM MATHEMATICAL SPACE + 0x3000, // IDEOGRAPHIC SPACE + 0xfeff, // ZERO WIDTH NO-BREAK SPACE +]; + +export const skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; + +export const IS_WHITESPACE = new Uint8Array(65536); +for (const char of WHITESPACE_CHARS) { + IS_WHITESPACE[char] = 1; +} |