{"version":3,"names":["_location","require","_comments","_identifier","_types","_parseError","_whitespace","_state","_helperStringParser","_excluded","_excluded2","_objectWithoutPropertiesLoose","source","excluded","target","sourceKeys","Object","keys","key","i","length","indexOf","buildPosition","pos","lineStart","curLine","Position","VALID_REGEX_FLAGS","Set","Token","constructor","state","type","value","start","end","loc","SourceLocation","startLoc","endLoc","exports","Tokenizer","CommentsParser","options","input","isLookahead","tokens","errorHandlers_readInt","invalidDigit","radix","errorRecovery","raise","Errors","InvalidDigit","at","numericSeparatorInEscapeSequence","errorBuilder","NumericSeparatorInEscapeSequence","unexpectedNumericSeparator","UnexpectedNumericSeparator","errorHandlers_readCodePoint","assign","invalidEscapeSequence","InvalidEscapeSequence","invalidCodePoint","InvalidCodePoint","errorHandlers_readStringContents_string","strictNumericEscape","recordStrictModeErrors","StrictNumericEscape","unterminated","UnterminatedString","errorHandlers_readStringContents_template","UnterminatedTemplate","State","init","pushToken","token","tokensLength","push","next","checkKeywordEscapes","lastTokStart","lastTokEndLoc","lastTokStartLoc","nextToken","eat","match","createLookaheadState","context","curContext","inType","curPosition","lookahead","old","curr","nextTokenStart","nextTokenStartSince","skipWhiteSpace","lastIndex","test","lookaheadCharCode","charCodeAt","nextTokenInLineStart","nextTokenInLineStartSince","skipWhiteSpaceInLine","lookaheadInLineCharCode","codePointAtPos","cp","trail","setStrict","strict","strictErrors","forEach","toParseError","clear","skipSpace","finishToken","getTokenFromCode","skipBlockComment","commentEnd","UnterminatedComment","lineBreakG","comment","slice","skipLineComment","startSkip","ch","isNewLine","spaceStart","comments","loop","undefined","addComment","attachComment","isWhitespace","inModule","annexB","commentWhitespace","leadingNode","trailingNode","containingNode","commentStack","val","prevType","updateContext","replaceToken","readToken_numberSign","readToken_interpreter","nextPos","UnexpectedDigitAfterHash","hasPlugin","expectPlugin","getPluginOption","RecordExpressionHashIncorrectStartSyntaxType","TupleExpressionHashIncorrectStartSyntaxType","isIdentifierStart","readWord1","finishOp","readToken_dot","readNumber","readToken_slash","readToken_mult_modulo","code","width","readToken_pipe_amp","RecordExpressionBarIncorrectEndSyntaxType","TupleExpressionBarIncorrectEndSyntaxType","readToken_caret","proposal","topicToken","lookaheadCh","codePointAt","unexpected","readToken_atSign","readToken_plus_min","readToken_lt","readToken_gt","size","readToken_eq_excl","readToken_question","next2","TupleExpressionBarIncorrectStartSyntaxType","RecordExpressionBarIncorrectStartSyntaxType","readTemplateToken","readRadixNumber","readString","readWord","InvalidOrUnexpectedToken","String","fromCodePoint","str","readRegexp","escaped","inClass","UnterminatedRegExp","createPositionWithColumnOffset","content","mods","char","fromCharCode","has","includes","IncompatibleRegExpUVFlags","DuplicateRegExpFlags","isIdentifierChar","MalformedRegExpFlags","pattern","flags","readInt","len","forceLen","allowNumSeparator","n","isBigInt","InvalidDecimal","NumberIdentifier","index","replace","startsWithDot","isFloat","isDecimal","hasExponent","isOctal","InvalidNumber","hasLeadingZero","integer","StrictOctalLiteral","underscorePos","ZeroDigitNumericSeparator","InvalidOrMissingExponent","InvalidBigIntLiteral","parseInt","parseFloat","readCodePoint","throwOnInvalid","quote","readStringContents","readTemplateContinuation","opening","firstInvalidLoc","firstInvalidTemplateEscapePos","set","firstCode","containsEsc","word","chunkStart","escStart","identifierCheck","MissingUnicodeEscape","esc","EscapedCharNotAnIdentifier","keywordTypes","get","tokenLabelName","tokenIsKeyword","InvalidEscapedReservedWord","reservedWord","raiseProperties","details","error","errors","raiseOverwrite","UnexpectedToken","expected","pluginName","MissingPlugin","missingPlugin","expectOnePlugin","pluginNames","some","name","MissingOneOfPlugins","default"],"sources":["../../src/tokenizer/index.ts"],"sourcesContent":["/*:: declare var invariant; */\n\nimport type { Options } from \"../options\";\nimport {\n Position,\n SourceLocation,\n createPositionWithColumnOffset,\n} from \"../util/location\";\nimport CommentsParser, { type CommentWhitespace } from \"../parser/comments\";\nimport type * as N from \"../types\";\nimport * as charCodes from \"charcodes\";\nimport { isIdentifierStart, isIdentifierChar } from \"../util/identifier\";\nimport {\n tokenIsKeyword,\n tokenLabelName,\n tt,\n keywords as keywordTypes,\n type TokenType,\n} from \"./types\";\nimport type { TokContext } from \"./context\";\nimport {\n Errors,\n type ParseError,\n type ParseErrorConstructor,\n type RaiseProperties,\n} from \"../parse-error\";\nimport {\n lineBreakG,\n isNewLine,\n isWhitespace,\n skipWhiteSpace,\n skipWhiteSpaceInLine,\n} from \"../util/whitespace\";\nimport State from \"./state\";\nimport type { LookaheadState, DeferredStrictError } from \"./state\";\n\nimport {\n readInt,\n readCodePoint,\n readStringContents,\n type IntErrorHandlers,\n type CodePointErrorHandlers,\n type StringContentsErrorHandlers,\n} from \"@babel/helper-string-parser\";\n\nimport type { Plugin } from \"../typings\";\n\nfunction buildPosition(pos: number, lineStart: number, curLine: number) {\n return new Position(curLine, pos - lineStart, pos);\n}\n\nconst VALID_REGEX_FLAGS = new Set([\n charCodes.lowercaseG,\n charCodes.lowercaseM,\n charCodes.lowercaseS,\n charCodes.lowercaseI,\n charCodes.lowercaseY,\n charCodes.lowercaseU,\n charCodes.lowercaseD,\n charCodes.lowercaseV,\n]);\n\n// Object type used to represent tokens. Note that normally, tokens\n// simply exist as properties on the parser object. This is only\n// used for the onToken callback and the external tokenizer.\n\nexport class Token {\n constructor(state: State) {\n this.type = state.type;\n this.value = state.value;\n this.start = state.start;\n this.end = state.end;\n this.loc = new SourceLocation(state.startLoc, state.endLoc);\n }\n\n declare type: TokenType;\n declare value: any;\n declare start: number;\n declare end: number;\n declare loc: SourceLocation;\n}\n\n// ## Tokenizer\n\nexport default abstract class Tokenizer extends CommentsParser {\n isLookahead: boolean;\n\n // Token store.\n tokens: Array = [];\n\n constructor(options: Options, input: string) {\n super();\n this.state = new State();\n this.state.init(options);\n this.input = input;\n this.length = input.length;\n this.isLookahead = false;\n }\n\n pushToken(token: Token | N.Comment) {\n // Pop out invalid tokens trapped by try-catch parsing.\n // Those parsing branches are mainly created by typescript and flow plugins.\n this.tokens.length = this.state.tokensLength;\n this.tokens.push(token);\n ++this.state.tokensLength;\n }\n\n // Move to the next token\n\n next(): void {\n this.checkKeywordEscapes();\n if (this.options.tokens) {\n this.pushToken(new Token(this.state));\n }\n\n this.state.lastTokStart = this.state.start;\n this.state.lastTokEndLoc = this.state.endLoc;\n this.state.lastTokStartLoc = this.state.startLoc;\n this.nextToken();\n }\n\n eat(type: TokenType): boolean {\n if (this.match(type)) {\n this.next();\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Whether current token matches given type\n */\n match(type: TokenType): boolean {\n return this.state.type === type;\n }\n\n /**\n * Create a LookaheadState from current parser state\n */\n createLookaheadState(state: State): LookaheadState {\n return {\n pos: state.pos,\n value: null,\n type: state.type,\n start: state.start,\n end: state.end,\n context: [this.curContext()],\n inType: state.inType,\n startLoc: state.startLoc,\n lastTokEndLoc: state.lastTokEndLoc,\n curLine: state.curLine,\n lineStart: state.lineStart,\n curPosition: state.curPosition,\n };\n }\n\n /**\n * lookahead peeks the next token, skipping changes to token context and\n * comment stack. For performance it returns a limited LookaheadState\n * instead of full parser state.\n *\n * The { column, line } Loc info is not included in lookahead since such usage\n * is rare. Although it may return other location properties e.g. `curLine` and\n * `lineStart`, these properties are not listed in the LookaheadState interface\n * and thus the returned value is _NOT_ reliable.\n *\n * The tokenizer should make best efforts to avoid using any parser state\n * other than those defined in LookaheadState\n */\n lookahead(): LookaheadState {\n const old = this.state;\n // @ts-expect-error For performance we use a simplified tokenizer state structure\n this.state = this.createLookaheadState(old);\n\n this.isLookahead = true;\n this.nextToken();\n this.isLookahead = false;\n\n const curr = this.state;\n this.state = old;\n return curr;\n }\n\n nextTokenStart(): number {\n return this.nextTokenStartSince(this.state.pos);\n }\n\n nextTokenStartSince(pos: number): number {\n skipWhiteSpace.lastIndex = pos;\n return skipWhiteSpace.test(this.input) ? skipWhiteSpace.lastIndex : pos;\n }\n\n lookaheadCharCode(): number {\n return this.input.charCodeAt(this.nextTokenStart());\n }\n\n /**\n * Similar to nextToken, but it will stop at line break when it is seen before the next token\n *\n * @returns {number} position of the next token start or line break, whichever is seen first.\n * @memberof Tokenizer\n */\n nextTokenInLineStart(): number {\n return this.nextTokenInLineStartSince(this.state.pos);\n }\n\n nextTokenInLineStartSince(pos: number): number {\n skipWhiteSpaceInLine.lastIndex = pos;\n return skipWhiteSpaceInLine.test(this.input)\n ? skipWhiteSpaceInLine.lastIndex\n : pos;\n }\n\n /**\n * Similar to lookaheadCharCode, but it will return the char code of line break if it is\n * seen before the next token\n *\n * @returns {number} char code of the next token start or line break, whichever is seen first.\n * @memberof Tokenizer\n */\n lookaheadInLineCharCode(): number {\n return this.input.charCodeAt(this.nextTokenInLineStart());\n }\n\n codePointAtPos(pos: number): number {\n // The implementation is based on\n // https://source.chromium.org/chromium/chromium/src/+/master:v8/src/builtins/builtins-string-gen.cc;l=1455;drc=221e331b49dfefadbc6fa40b0c68e6f97606d0b3;bpv=0;bpt=1\n // We reimplement `codePointAt` because `codePointAt` is a V8 builtin which is not inlined by TurboFan (as of M91)\n // since `input` is mostly ASCII, an inlined `charCodeAt` wins here\n let cp = this.input.charCodeAt(pos);\n if ((cp & 0xfc00) === 0xd800 && ++pos < this.input.length) {\n const trail = this.input.charCodeAt(pos);\n if ((trail & 0xfc00) === 0xdc00) {\n cp = 0x10000 + ((cp & 0x3ff) << 10) + (trail & 0x3ff);\n }\n }\n return cp;\n }\n\n // Toggle strict mode. Re-reads the next number or string to please\n // pedantic tests (`\"use strict\"; 010;` should fail).\n\n setStrict(strict: boolean): void {\n this.state.strict = strict;\n if (strict) {\n // Throw an error for any string decimal escape found before/immediately\n // after a \"use strict\" directive. Strict mode will be set at parse\n // time for any literals that occur after the next node of the strict\n // directive.\n this.state.strictErrors.forEach(([toParseError, at]) =>\n this.raise(toParseError, { at }),\n );\n this.state.strictErrors.clear();\n }\n }\n\n curContext(): TokContext {\n return this.state.context[this.state.context.length - 1];\n }\n\n // Read a single token, updating the parser object's token-related properties.\n nextToken(): void {\n this.skipSpace();\n this.state.start = this.state.pos;\n if (!this.isLookahead) this.state.startLoc = this.state.curPosition();\n if (this.state.pos >= this.length) {\n this.finishToken(tt.eof);\n return;\n }\n\n this.getTokenFromCode(this.codePointAtPos(this.state.pos));\n }\n\n // Skips a block comment, whose end is marked by commentEnd.\n // *-/ is used by the Flow plugin, when parsing block comments nested\n // inside Flow comments.\n skipBlockComment(commentEnd: \"*/\" | \"*-/\"): N.CommentBlock | undefined {\n let startLoc;\n if (!this.isLookahead) startLoc = this.state.curPosition();\n const start = this.state.pos;\n const end = this.input.indexOf(commentEnd, start + 2);\n if (end === -1) {\n // We have to call this again here because startLoc may not be set...\n // This seems to be for performance reasons:\n // https://github.com/babel/babel/commit/acf2a10899f696a8aaf34df78bf9725b5ea7f2da\n throw this.raise(Errors.UnterminatedComment, {\n at: this.state.curPosition(),\n });\n }\n\n this.state.pos = end + commentEnd.length;\n lineBreakG.lastIndex = start + 2;\n while (lineBreakG.test(this.input) && lineBreakG.lastIndex <= end) {\n ++this.state.curLine;\n this.state.lineStart = lineBreakG.lastIndex;\n }\n\n // If we are doing a lookahead right now we need to advance the position (above code)\n // but we do not want to push the comment to the state.\n if (this.isLookahead) return;\n /*:: invariant(startLoc) */\n\n const comment: N.CommentBlock = {\n type: \"CommentBlock\",\n value: this.input.slice(start + 2, end),\n start,\n end: end + commentEnd.length,\n loc: new SourceLocation(startLoc, this.state.curPosition()),\n };\n if (this.options.tokens) this.pushToken(comment);\n return comment;\n }\n\n skipLineComment(startSkip: number): N.CommentLine | undefined {\n const start = this.state.pos;\n let startLoc;\n if (!this.isLookahead) startLoc = this.state.curPosition();\n let ch = this.input.charCodeAt((this.state.pos += startSkip));\n if (this.state.pos < this.length) {\n while (!isNewLine(ch) && ++this.state.pos < this.length) {\n ch = this.input.charCodeAt(this.state.pos);\n }\n }\n\n // If we are doing a lookahead right now we need to advance the position (above code)\n // but we do not want to push the comment to the state.\n if (this.isLookahead) return;\n /*:: invariant(startLoc) */\n\n const end = this.state.pos;\n const value = this.input.slice(start + startSkip, end);\n\n const comment: N.CommentLine = {\n type: \"CommentLine\",\n value,\n start,\n end,\n loc: new SourceLocation(startLoc, this.state.curPosition()),\n };\n if (this.options.tokens) this.pushToken(comment);\n return comment;\n }\n\n // Called at the start of the parse and after every token. Skips\n // whitespace and comments, and.\n\n skipSpace(): void {\n const spaceStart = this.state.pos;\n const comments = [];\n loop: while (this.state.pos < this.length) {\n const ch = this.input.charCodeAt(this.state.pos);\n switch (ch) {\n case charCodes.space:\n case charCodes.nonBreakingSpace:\n case charCodes.tab:\n ++this.state.pos;\n break;\n case charCodes.carriageReturn:\n if (\n this.input.charCodeAt(this.state.pos + 1) === charCodes.lineFeed\n ) {\n ++this.state.pos;\n }\n // fall through\n case charCodes.lineFeed:\n case charCodes.lineSeparator:\n case charCodes.paragraphSeparator:\n ++this.state.pos;\n ++this.state.curLine;\n this.state.lineStart = this.state.pos;\n break;\n\n case charCodes.slash:\n switch (this.input.charCodeAt(this.state.pos + 1)) {\n case charCodes.asterisk: {\n const comment = this.skipBlockComment(\"*/\");\n if (comment !== undefined) {\n this.addComment(comment);\n if (this.options.attachComment) comments.push(comment);\n }\n break;\n }\n\n case charCodes.slash: {\n const comment = this.skipLineComment(2);\n if (comment !== undefined) {\n this.addComment(comment);\n if (this.options.attachComment) comments.push(comment);\n }\n break;\n }\n\n default:\n break loop;\n }\n break;\n\n default:\n if (isWhitespace(ch)) {\n ++this.state.pos;\n } else if (\n ch === charCodes.dash &&\n !this.inModule &&\n this.options.annexB\n ) {\n const pos = this.state.pos;\n if (\n this.input.charCodeAt(pos + 1) === charCodes.dash &&\n this.input.charCodeAt(pos + 2) === charCodes.greaterThan &&\n (spaceStart === 0 || this.state.lineStart > spaceStart)\n ) {\n // A `-->` line comment\n const comment = this.skipLineComment(3);\n if (comment !== undefined) {\n this.addComment(comment);\n if (this.options.attachComment) comments.push(comment);\n }\n } else {\n break loop;\n }\n } else if (\n ch === charCodes.lessThan &&\n !this.inModule &&\n this.options.annexB\n ) {\n const pos = this.state.pos;\n if (\n this.input.charCodeAt(pos + 1) === charCodes.exclamationMark &&\n this.input.charCodeAt(pos + 2) === charCodes.dash &&\n this.input.charCodeAt(pos + 3) === charCodes.dash\n ) {\n // `