diff options
Diffstat (limited to 'node_modules/meriyah/src')
20 files changed, 16448 insertions, 0 deletions
diff --git a/node_modules/meriyah/src/chars.ts b/node_modules/meriyah/src/chars.ts new file mode 100644 index 0000000..cbd292c --- /dev/null +++ b/node_modules/meriyah/src/chars.ts @@ -0,0 +1,155 @@ +/** + * A list of character constants with much more human-readable names. + */ +export const enum Chars { + + Null = 0x00, + + Backspace = 0x08, + Tab = 0x09, + LineFeed = 0x0A, + VerticalTab = 0x0B, + FormFeed = 0x0C, + CarriageReturn = 0x0D, + + Space = 0x20, + Exclamation = 0x21, + DoubleQuote = 0x22, + Hash = 0x23, + Dollar = 0x24, + Percent = 0x25, + Ampersand = 0x26, + SingleQuote = 0x27, + LeftParen = 0x28, + RightParen = 0x29, + Asterisk = 0x2A, + Plus = 0x2B, + Comma = 0x2C, + Hyphen = 0x2D, + Period = 0x2E, + Slash = 0x2F, + + Zero = 0x30, + One = 0x31, + Two = 0x32, + Three = 0x33, + Four = 0x34, + Five = 0x35, + Six = 0x36, + Seven = 0x37, + Eight = 0x38, + Nine = 0x39, + Colon = 0x3A, + Semicolon = 0x3B, + LessThan = 0x3C, + EqualSign = 0x3D, + GreaterThan = 0x3E, + QuestionMark = 0x3F, + + UpperA = 0x41, + UpperB = 0x42, + UpperC = 0x43, + UpperD = 0x44, + UpperE = 0x45, + UpperF = 0x46, + UpperG = 0x47, + UpperH = 0x48, + UpperI = 0x49, + UpperJ = 0x4A, + UpperK = 0x4B, + UpperL = 0x4C, + UpperM = 0x4D, + UpperN = 0x4E, + UpperO = 0x4F, + + UpperP = 0x50, + UpperQ = 0x51, + UpperR = 0x52, + UpperS = 0x53, + UpperT = 0x54, + UpperU = 0x55, + UpperV = 0x56, + UpperW = 0x57, + UpperX = 0x58, + UpperY = 0x59, + UpperZ = 0x5A, + LeftBracket = 0x5B, + Backslash = 0x5C, + RightBracket = 0x5D, + Caret = 0x5E, + Underscore = 0x5F, + + Backtick = 0x60, + LowerA = 0x61, + LowerB = 0x62, + LowerC = 0x63, + LowerD = 0x64, + LowerE = 0x65, + LowerF = 0x66, + LowerG = 0x67, + LowerH = 0x68, + LowerI = 0x69, + LowerJ = 0x6A, + LowerK = 0x6B, + LowerL = 0x6C, + LowerM = 0x6D, + LowerN = 0x6E, + LowerO = 0x6F, + + LowerP = 0x70, + LowerQ = 0x71, + LowerR = 0x72, + LowerS = 0x73, + LowerT = 0x74, + LowerU = 0x75, + LowerV = 0x76, + LowerW = 0x77, + LowerX = 0x78, + LowerY = 0x79, + LowerZ = 0x7A, + LeftBrace = 0x7B, + VerticalBar = 0x7C, + RightBrace = 0x7D, + Tilde = 0x7E, + Delete = 0x7F, + + NextLine = 0x85, + NonBreakingSpace = 0xA0, + + Ogham = 0x1680, + + EnQuad = 0x2000, + EmQuad = 0x2001, + EnSpace = 0x2002, + EmSpace = 0x2003, + ThreePerEmSpace = 0x2004, + FourPerEmSpace = 0x2005, + SixPerEmSpace = 0x2006, + FigureSpace = 0x2007, + PunctuationSpace = 0x2008, + ThinSpace = 0x2009, + HairSpace = 0x200A, + ZeroWidthSpace = 0x200B, + ZeroWidthJoiner = 0x200C, + ZeroWidthNonJoiner = 0x200D, + + LineSeparator = 0x2028, + ParagraphSeparator = 0x2029, + + NarrowNoBreakSpace = 0x202F, + MathematicalSpace = 0x205F, + IdeographicSpace = 0x3000, + + ZeroWidthNoBreakSpace = 0xFEFF, + + ByteOrderMark = 0xFFEF, + + NonBMPMax = 0x10FFFF, + + LeadSurrogateMin = 0xD800, + LeadSurrogateMax = 0xDBFF, + TrailSurrogateMin = 0xDC00, + TrailSurrogateMax = 0xDFFF, + UTF16Max = 0xFFFF, + NonBMPMin = 0x10000, +} diff --git a/node_modules/meriyah/src/common.ts b/node_modules/meriyah/src/common.ts new file mode 100644 index 0000000..333bb9d --- /dev/null +++ b/node_modules/meriyah/src/common.ts @@ -0,0 +1,835 @@ +import { Token, KeywordDescTable } from './token'; +import { Errors, report } from './errors'; +import { Node, Comment, Decorator, SourceLocation } from './estree'; +import { nextToken } from './lexer/scan'; + +/** + * The core context, passed around everywhere as a simple immutable bit set + */ +export const enum Context { + None = 0, + OptionsNext = 1 << 0, + OptionsRanges = 1 << 1, + OptionsLoc = 1 << 2, + OptionsDirectives = 1 << 3, + OptionsJSX = 1 << 4, + OptionsGlobalReturn = 1 << 5, + OptionsLexical = 1 << 6, + OptionsPreserveParens = 1 << 7, + OptionsWebCompat = 1 << 8, + OptionsRaw = 1 << 9, + Strict = 1 << 10, + Module = 1 << 11, // Current code should be parsed as a module body + InSwitch = 1 << 12, + InGlobal = 1 << 13, + InClass = 1 << 14, + AllowRegExp = 1 << 15, + TaggedTemplate = 1 << 16, + InIteration = 1 << 17, + SuperProperty = 1 << 18, + SuperCall = 1 << 19, + InYieldContext = 1 << 21, + InAwaitContext = 1 << 22, + InArgumentList = 1 << 23, + InConstructor = 1 << 24, + InMethod = 1 << 25, + AllowNewTarget = 1 << 26, + DisallowIn = 1 << 27, + OptionsIdentifierPattern = 1 << 28, + OptionsSpecDeviation = 1 << 29, + AllowEscapedKeyword = 1 << 30, + OptionsUniqueKeyInPattern = 1 << 31, +} + +/** + * Masks to track the property kind + */ +export const enum PropertyKind { + None = 0, + Method = 1 << 0, + Computed = 1 << 1, + Shorthand = 1 << 2, + Generator = 1 << 3, + Async = 1 << 4, + Static = 1 << 5, + Constructor = 1 << 6, + ClassField = 1 << 7, + Getter = 1 << 8, + Setter = 1 << 9, + Extends = 1 << 10, + Literal = 1 << 11, + PrivateField = 1 << 12, + GetSet = Getter | Setter +} + +/** + * Masks to track the binding kind + */ +export const enum BindingKind { + None = 0, + ArgumentList = 1 << 0, + Empty = 1 << 1, + Variable = 1 << 2, + Let = 1 << 3, + Const = 1 << 4, + Class = 1 << 5, + FunctionLexical = 1 << 6, + FunctionStatement = 1 << 7, + CatchPattern = 1 << 8, + CatchIdentifier = 1 << 9, + CatchIdentifierOrPattern = CatchIdentifier | CatchPattern, + LexicalOrFunction = Variable | FunctionLexical, + LexicalBinding = Let | Const | FunctionLexical | FunctionStatement | Class +} + +/** + * The masks to track where something begins. E.g. statements, declarations or arrows. + */ +export const enum Origin { + None = 0, + Statement = 1 << 0, + BlockStatement = 1 << 1, + TopLevel = 1 << 2, + Declaration = 1 << 3, + Arrow = 1 << 4, + ForStatement = 1 << 5, + Export = 1 << 6, +} + +/** + * Masks to track the assignment kind + */ +export const enum AssignmentKind { + None = 0, + Assignable = 1 << 0, + CannotAssign = 1 << 1 +} + +/** + * Masks to track the destructuring kind + */ +export const enum DestructuringKind { + None = 0, + HasToDestruct = 1 << 3, + // "Cannot" rather than "can" so that this flag can be ORed together across + // multiple characters. + CannotDestruct = 1 << 4, + // Only destructible if assignable + Assignable = 1 << 5, + // `__proto__` is a special case and only valid to parse if destructible + SeenProto = 1 << 6, + Await = 1 << 7, + Yield = 1 << 8 +} + +/** + * The mutable parser flags, in case any flags need passed by reference. + */ +export const enum Flags { + None = 0, + NewLine = 1 << 0, + HasConstructor = 1 << 5, + Octals = 1 << 6, + SimpleParameterList = 1 << 7, + HasStrictReserved = 1 << 8, + StrictEvalArguments = 1 << 9, + DisallowCall = 1 << 10, + HasOptionalChaining = 1 << 11 +} + +export const enum HoistedClassFlags { + None, + Hoisted = 1 << 0, + Export = 1 << 1 +} + +export const enum HoistedFunctionFlags { + None, + Hoisted = 1 << 0, + Export = 1 << 1 +} + +/** + * Scope kinds + */ +export const enum ScopeKind { + None = 0, + ForStatement = 1 << 0, + Block = 1 << 1, + CatchStatement = 1 << 2, + SwitchStatement = 1 << 3, + ArgList = 1 << 4, + TryStatement = 1 << 5, + CatchBlock = 1 << 6, + FunctionBody = 1 << 7, + FunctionRoot = 1 << 8, + FunctionParams = 1 << 9, + ArrowParams = 1 << 10, + CatchIdentifier = 1 << 11, +} + +/** + * The type of the `onComment` option. + */ +export type OnComment = void | Comment[] | ((type: string, value: string, start: number, end: number, loc: SourceLocation) => any); + +/** + * The type of the `onToken` option. + */ +export type OnToken = void | Token[] | ((token: string, start: number, end: number, loc: SourceLocation) => any); + +/** + * Lexical scope interface + */ +export interface ScopeState { + parent: ScopeState | undefined; + type: ScopeKind; + scopeError?: ScopeError | null; +} + +/** Scope error interface */ +export interface ScopeError { + type: Errors; + params: string[]; + index: number; + line: number; + column: number; +} + +/** + * The parser interface. + */ +export interface ParserState { + source: string; + flags: Flags; + index: number; + line: number; + column: number; + tokenPos: number; + startPos: number; + startColumn: number; + startLine: number; + colPos: number; + linePos: number; + end: number; + token: Token; + onComment: any; + onToken: any; + tokenValue: any; + tokenRaw: string; + tokenRegExp: void | { + pattern: string; + flags: string; + }; + sourceFile: string | void; + assignable: AssignmentKind | DestructuringKind; + destructible: AssignmentKind | DestructuringKind; + currentChar: number; + exportedNames: any; + exportedBindings: any; + leadingDecorators: Decorator[]; +} + +/** + * Check for automatic semicolon insertion according to the rules + * given in `ECMA-262, section 11.9`. + * + * @param parser Parser object + * @param context Context masks + */ + +export function matchOrInsertSemicolon(parser: ParserState, context: Context, specDeviation?: number): void { + + if ( + (parser.flags & Flags.NewLine) === 0 && + (parser.token & Token.IsAutoSemicolon) !== Token.IsAutoSemicolon && + !specDeviation + ) { + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + } + consumeOpt(parser, context, Token.Semicolon); +} + +export function isValidStrictMode(parser: ParserState, index: number, tokenPos: number, tokenValue: string): 0 | 1 { + if (index - tokenPos < 13 && tokenValue === 'use strict') { + if ((parser.token & Token.IsAutoSemicolon) === Token.IsAutoSemicolon || parser.flags & Flags.NewLine) { + return 1; + } + } + return 0; +} + +/** + * Consumes the current token if the current token kind is + * the specified `kind` and returns `0`. Otherwise returns `1`. + * + * @param parser Parser state + * @param context Context masks + * @param token The type of token to consume + */ +export function optionalBit(parser: ParserState, context: Context, t: Token): 0 | 1 { + if (parser.token !== t) return 0; + nextToken(parser, context); + return 1; +} + +/** Consumes the current token if the current token kind is + * the specified `kind` and returns `true`. Otherwise returns + * `false`. + * + * @param parser Parser state + * @param context Context masks + * @param token The type of token to consume + */ +export function consumeOpt(parser: ParserState, context: Context, t: Token): boolean { + if (parser.token !== t) return false; + nextToken(parser, context); + return true; +} + +/** + * Consumes the current token. If the current token kind is not + * the specified `kind`, an error will be reported. + * + * @param parser Parser state + * @param context Context masks + * @param t The type of token to consume + */ +export function consume(parser: ParserState, context: Context, t: Token): void { + if (parser.token !== t) report(parser, Errors.ExpectedToken, KeywordDescTable[t & Token.Type]); + nextToken(parser, context); +} + +/** + * Transforms a `LeftHandSideExpression` into a `AssignmentPattern` if possible, + * otherwise it returns the original tree. + * + * @param parser Parser state + * @param {*} node + */ +export function reinterpretToPattern(state: ParserState, node: any): void { + switch (node.type) { + case 'ArrayExpression': + node.type = 'ArrayPattern'; + const elements = node.elements; + for (let i = 0, n = elements.length; i < n; ++i) { + const element = elements[i]; + if (element) reinterpretToPattern(state, element); + } + return; + case 'ObjectExpression': + node.type = 'ObjectPattern'; + const properties = node.properties; + for (let i = 0, n = properties.length; i < n; ++i) { + reinterpretToPattern(state, properties[i]); + } + return; + case 'AssignmentExpression': + node.type = 'AssignmentPattern'; + if (node.operator !== '=') report(state, Errors.InvalidDestructuringTarget); + delete node.operator; + reinterpretToPattern(state, node.left); + return; + case 'Property': + reinterpretToPattern(state, node.value); + return; + case 'SpreadElement': + node.type = 'RestElement'; + reinterpretToPattern(state, node.argument); + default: // ignore + } +} + +/** + * Validates binding identifier + * + * @param parser Parser state + * @param context Context masks + * @param type Binding type + * @param token Token + */ + +export function validateBindingIdentifier( + parser: ParserState, + context: Context, + kind: BindingKind, + t: Token, + skipEvalArgCheck: 0 | 1 +): void { + + if (context & Context.Strict) { + + if ((t & Token.FutureReserved) === Token.FutureReserved) { + report(parser, Errors.UnexpectedStrictReserved); + } + + if (!skipEvalArgCheck && (t & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) { + report(parser, Errors.StrictEvalArguments); + } + } + + if ((t & Token.Reserved) === Token.Reserved) { + report(parser, Errors.KeywordNotId); + } + + // The BoundNames of LexicalDeclaration and ForDeclaration must not + // contain 'let'. (CatchParameter is the only lexical binding form + // without this restriction.) + if (kind & (BindingKind.Let | BindingKind.Const) && t === Token.LetKeyword) { + report(parser, Errors.InvalidLetConstBinding); + } + + if (context & (Context.InAwaitContext | Context.Module) && t === Token.AwaitKeyword) { + report(parser, Errors.AwaitOutsideAsync); + } + + if (context & (Context.InYieldContext | Context.Strict) && t === Token.YieldKeyword) { + report(parser, Errors.DisallowedInContext, 'yield'); + } +} + +export function validateFunctionName( + parser: ParserState, + context: Context, + t: Token +): void { + + if (context & Context.Strict) { + + if ((t & Token.FutureReserved) === Token.FutureReserved) { + report(parser, Errors.UnexpectedStrictReserved); + } + + if ((t & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) { + report(parser, Errors.StrictEvalArguments); + } + + if (t === Token.EscapedFutureReserved) { + report(parser, Errors.InvalidEscapedKeyword); + } + + if (t === Token.EscapedReserved) { + report(parser, Errors.InvalidEscapedKeyword); + } + } + + if ((t & Token.Reserved) === Token.Reserved) { + report(parser, Errors.KeywordNotId); + } + + if (context & (Context.InAwaitContext | Context.Module) && t === Token.AwaitKeyword) { + report(parser, Errors.AwaitOutsideAsync); + } + + if (context & (Context.InYieldContext | Context.Strict) && t === Token.YieldKeyword) { + report(parser, Errors.DisallowedInContext, 'yield'); + } +} + +/** + * Validates binding identifier + * + * @param parser Parser state + * @param context Context masks + * @param t Token + */ + +export function isStrictReservedWord(parser: ParserState, context: Context, t: Token): boolean { + if (t === Token.AwaitKeyword) { + if (context & (Context.InAwaitContext | Context.Module)) report(parser, Errors.AwaitOutsideAsync); + parser.destructible |= DestructuringKind.Await; + } + + if (t === Token.YieldKeyword && context & Context.InYieldContext) report(parser, Errors.DisallowedInContext, 'yield'); + + return ( + (t & Token.Reserved) === Token.Reserved || + (t & Token.FutureReserved) === Token.FutureReserved || + t == Token.EscapedFutureReserved + ); +} + +/** + * Checks if the property has any private field key + * + * @param parser Parser object + * @param context Context masks + */ +export function isPropertyWithPrivateFieldKey(expr: any): boolean { + return !expr.property ? false : expr.property.type === 'PrivateIdentifier'; +} + +/** + * Checks if a label in `LabelledStatement` are valid or not + * + * @param parser Parser state + * @param labels Object holding the labels + * @param name Current label + * @param isIterationStatement + */ +export function isValidLabel(parser: ParserState, labels: any, name: string, isIterationStatement: 0 | 1): 0 | 1 { + while (labels) { + if (labels['$' + name]) { + if (isIterationStatement) report(parser, Errors.InvalidNestedStatement); + return 1; + } + if (isIterationStatement && labels.loop) isIterationStatement = 0; + labels = labels['$']; + } + + return 0; +} + +/** + * Checks if current label already have been declrared, and if not + * declare it + * + * @param parser Parser state + * @param labels Object holding the labels + * @param name Current label + */ +export function validateAndDeclareLabel(parser: ParserState, labels: any, name: string): void { + let set = labels; + while (set) { + if (set['$' + name]) report(parser, Errors.LabelRedeclaration, name); + set = set['$']; + } + + labels['$' + name] = 1; +} + +export function finishNode<T extends Node>( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number, + node: T +): T { + if (context & Context.OptionsRanges) { + node.start = start; + node.end = parser.startPos; + node.range = [start, parser.startPos]; + } + + if (context & Context.OptionsLoc) { + node.loc = { + start: { + line, + column + }, + end: { + line: parser.startLine, + column: parser.startColumn + } + }; + + if (parser.sourceFile) { + node.loc.source = parser.sourceFile; + } + } + + return node; +} + +/** @internal */ +export function isEqualTagName(elementName: any): any { + switch (elementName.type) { + case 'JSXIdentifier': + return elementName.name; + case 'JSXNamespacedName': + return elementName.namespace + ':' + elementName.name; + case 'JSXMemberExpression': + return isEqualTagName(elementName.object) + '.' + isEqualTagName(elementName.property); + /* istanbul ignore next */ + default: + // ignore + } +} + +/** + * Create a parsing scope for arrow head, and add lexical binding + * + * @param parser Parser state + * @param context Context masks + * @param value Binding name to be declared + */ +export function createArrowHeadParsingScope(parser: ParserState, context: Context, value: string): ScopeState { + const scope = addChildScope(createScope(), ScopeKind.ArrowParams); + addBlockName(parser, context, scope, value, BindingKind.ArgumentList, Origin.None); + return scope; +} + +/** + * Record duplicate binding errors that may occur in a arrow head or function parameters +* + * @param parser Parser state + * @param type Errors type + */ +export function recordScopeError(parser: ParserState, type: Errors, ...params: string[]): ScopeError { + const { index, line, column } = parser; + return { + type, + params, + index, + line, + column + }; +} + +/** + * Creates a block scope + */ +export function createScope(): ScopeState { + return { + parent: void 0, + type: ScopeKind.Block + }; +} + +/** + * Inherit scope + * + * @param scope Parser object + * @param type Scope kind + */ +export function addChildScope(parent: ScopeState | undefined, type: ScopeKind): ScopeState { + return { + parent, + type, + scopeError: void 0 + }; +} + +/** + * Adds either a var binding or a block scoped binding. + * + * @param parser Parser state + * @param context Context masks + * @param scope Scope state + * @param name Binding name + * @param type Binding kind + * @param origin Binding Origin + */ +export function addVarOrBlock( + parser: ParserState, + context: Context, + scope: ScopeState, + name: string, + kind: BindingKind, + origin: Origin +) { + if (kind & BindingKind.Variable) { + addVarName(parser, context, scope, name, kind); + } else { + addBlockName(parser, context, scope, name, kind, origin); + } + if (origin & Origin.Export) { + declareUnboundVariable(parser, name); + } +} + +/** + * Adds block scoped binding + * + * @param parser Parser state + * @param context Context masks + * @param scope Scope state + * @param name Binding name + * @param type Binding kind + * @param origin Binding Origin + */ +export function addBlockName( + parser: ParserState, + context: Context, + scope: any, + name: string, + kind: BindingKind, + origin: Origin +) { + const value = (scope as any)['#' + name]; + + if (value && (value & BindingKind.Empty) === 0) { + if (kind & BindingKind.ArgumentList) { + scope.scopeError = recordScopeError(parser, Errors.DuplicateBinding, name); + } else if ( + context & Context.OptionsWebCompat && + value & BindingKind.FunctionLexical && + origin & Origin.BlockStatement + ) { + } else { + report(parser, Errors.DuplicateBinding, name); + } + } + + if ( + scope.type & ScopeKind.FunctionBody && + ((scope as any).parent['#' + name] && ((scope as any).parent['#' + name] & BindingKind.Empty) === 0) + ) { + report(parser, Errors.DuplicateBinding, name); + } + + if (scope.type & ScopeKind.ArrowParams && value && (value & BindingKind.Empty) === 0) { + if (kind & BindingKind.ArgumentList) { + scope.scopeError = recordScopeError(parser, Errors.DuplicateBinding, name); + } + } + + if (scope.type & ScopeKind.CatchBlock) { + if ((scope as any).parent['#' + name] & BindingKind.CatchIdentifierOrPattern) + report(parser, Errors.ShadowedCatchClause, name); + } + + (scope as any)['#' + name] = kind; +} + +/** + * Adds a variable binding + * + * @param parser Parser state + * @param context Context masks + * @param scope Scope state + * @param name Binding name + * @param type Binding kind + */ +export function addVarName( + parser: ParserState, + context: Context, + scope: ScopeState, + name: string, + kind: BindingKind +): void { + let currentScope: any = scope; + + while (currentScope && (currentScope.type & ScopeKind.FunctionRoot) === 0) { + const value: ScopeKind = currentScope['#' + name]; + + if (value & BindingKind.LexicalBinding) { + if ( + context & Context.OptionsWebCompat && + (context & Context.Strict) === 0 && + ((kind & BindingKind.FunctionStatement && value & BindingKind.LexicalOrFunction) || + (value & BindingKind.FunctionStatement && kind & BindingKind.LexicalOrFunction)) + ) { + } else { + report(parser, Errors.DuplicateBinding, name); + } + } + if (currentScope === scope) { + if (value & BindingKind.ArgumentList && kind & BindingKind.ArgumentList) { + currentScope.scopeError = recordScopeError(parser, Errors.DuplicateBinding, name); + } + } + if (value & (BindingKind.CatchIdentifier | BindingKind.CatchPattern)) { + if ( + (value & BindingKind.CatchIdentifier) === 0 || + (context & Context.OptionsWebCompat) === 0 || + context & Context.Strict + ) { + report(parser, Errors.DuplicateBinding, name); + } + } + + currentScope['#' + name] = kind; + + currentScope = currentScope.parent; + } +} + +/** + * Appends a name to the `ExportedNames` of the `ExportsList`, and checks + * for duplicates + * + * @see [Link](https://tc39.github.io/ecma262/$sec-exports-static-semantics-exportednames) + * + * @param parser Parser object + * @param name Exported name + */ +export function declareUnboundVariable(parser: ParserState, name: string): void { + if (parser.exportedNames !== void 0 && name !== '') { + if (parser.exportedNames['#' + name]) { + report(parser, Errors.DuplicateExportBinding, name); + } + parser.exportedNames['#' + name] = 1; + } +} + +/** + * Appends a name to the `ExportedBindings` of the `ExportsList`, + * + * @see [Link](https://tc39.es/ecma262/$sec-exports-static-semantics-exportedbindings) + * + * @param parser Parser object + * @param name Exported binding name + */ +export function addBindingToExports(parser: ParserState, name: string): void { + if (parser.exportedBindings !== void 0 && name !== '') { + parser.exportedBindings['#' + name] = 1; + } +} + +export function pushComment(context: Context, array: any[]): any { + return function(type: string, value: string, start: number, end: number, loc: SourceLocation) { + const comment: any = { + type, + value + }; + + if (context & Context.OptionsRanges) { + comment.start = start; + comment.end = end; + comment.range = [start, end]; + } + if (context & Context.OptionsLoc) { + comment.loc = loc; + } + array.push(comment); + }; +} + +export function pushToken(context: Context, array: any[]): any { + return function(token: string, start: number, end: number, loc: SourceLocation) { + const tokens: any = { + token + }; + + if (context & Context.OptionsRanges) { + tokens.start = start; + tokens.end = end; + tokens.range = [start, end]; + } + if (context & Context.OptionsLoc) { + tokens.loc = loc; + } + array.push(tokens); + }; +} + +export function isValidIdentifier(context: Context, t: Token): boolean { + if (context & (Context.Strict | Context.InYieldContext)) { + // Module code is also "strict mode code" + if (context & Context.Module && t === Token.AwaitKeyword) return false; + if (context & Context.InYieldContext && t === Token.YieldKeyword) return false; + return (t & Token.IsIdentifier) === Token.IsIdentifier || (t & Token.Contextual) === Token.Contextual; + } + + return ( + (t & Token.IsIdentifier) === Token.IsIdentifier || + (t & Token.Contextual) === Token.Contextual || + (t & Token.FutureReserved) === Token.FutureReserved + ); +} + +export function classifyIdentifier( + parser: ParserState, + context: Context, + t: Token, + isArrow: 0 | 1 +): any { + if ((t & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) { + if (context & Context.Strict) report(parser, Errors.StrictEvalArguments); + if (isArrow) parser.flags |= Flags.StrictEvalArguments; + } + + if (!isValidIdentifier(context, t)) report(parser, Errors.Unexpected); +} diff --git a/node_modules/meriyah/src/errors.ts b/node_modules/meriyah/src/errors.ts new file mode 100644 index 0000000..8424b6f --- /dev/null +++ b/node_modules/meriyah/src/errors.ts @@ -0,0 +1,417 @@ +import { ParserState } from './common'; + +export const enum Errors { + Unexpected, + StrictOctalEscape, + TemplateOctalLiteral, + InvalidPrivateIdentifier, + InvalidUnicodeEscapeSequence, + InvalidCodePoint, + InvalidHexEscapeSequence, + StrictDecimalWithLeadingZero, + StrictOctalLiteral, + ExpectedNumberInRadix, + MissingExponent, + InvalidBigInt, + IDStartAfterNumber, + InvalidEightAndNine, + UnterminatedString, + UnterminatedTemplate, + UnterminatedComment, + InvalidDynamicUnicode, + IllegalCharacter, + MissingHexDigits, + InvalidImplicitOctals, + InvalidStringLT, + InvalidEscapeIdentifier, + ExpectedToken, + CantAssignTo, + InvalidLHSAsyncArrow, + SuperNoConstructor, + InvalidSuperProperty, + UnexpectedToken, + AwaitInParameter, + YieldInParameter, + InvalidExponentiationLHS, + UnterminatedRegExp, + UnexpectedTokenRegExpFlag, + DuplicateRegExpFlag, + AccessorWrongArgs, + BadSetterRestParameter, + DeclNoName, + StrictFunctionName, + RestMissingArg, + InvalidGeneratorGetter, + InvalidComputedPropName, + InvalidGetSetGenerator, + InvalidAsyncGetter, + InvalidGenMethodShorthand, + InvalidLineBreak, + InvalidArrowDestructLHS, + InvalidBindingDestruct, + InvalidAsyncArrow, + StaticPrototype, + InvalidConstructor, + DuplicateConstructor, + InvalidIncDecTarget, + InvalidIncDecNew, + InvalidAssignmentTarget, + InvalidRestTrailing, + DeclarationMissingInitializer, + ForInOfLoopInitializer, + ForInOfLoopMultiBindings, + InvalidShorthandPropInit, + DuplicateProto, + InvalidLetBoundName, + InvalidNewUnary, + IllegalUseStrict, + DisallowedLetInStrict, + IllegalContinue, + IllegalBreak, + InvalidLetBracket, + InvalidDestructuringTarget, + RestDefaultInitializer, + InvalidRestNotLast, + InvalidRestArg, + InvalidRestDefault, + StrictFunction, + SloppyFunction, + WebCompatFunction, + ClassForbiddenAsStatement, + CantAssignToInOfForLoop, + InvalidAssignmentInOfForLoop, + InvalidForAwait, + InvalidTemplateContinuation, + RestrictedLetProduction, + UnexpectedLetStrictReserved, + InvalidCatchParams, + InvalidCatchParamDefault, + NoCatchOrFinally, + MultipleDefaultsInSwitch, + NewlineAfterThrow, + StrictWith, + IllegalReturn, + InvalidForLHSBinding, + InvalidNewTarget, + InvalidEscapedKeyword, + MissingPrivateIdentifier, + DisallowedInContext, + AwaitOutsideAsync, + InvalidStrictLet, + InvalidLetConstBinding, + InvalidLetClassName, + KeywordNotId, + InvalidImportExportSloppy, + UnicodeOverflow, + InvalidExportImportSource, + InvalidKeywordAsAlias, + InvalidDefaultImport, + TrailingDecorators, + GeneratorConstructor, + AwaitOrYieldIdentInModule, + HtmlCommentInWebCompat, + StrictInvalidLetInExprPos, + NotAssignableLetArgs, + ForOfLet, + InvalidInvokedBlockBodyArrow, + InvalidAccessedBlockBodyArrow, + UnexpectedStrictReserved, + StrictEvalArguments, + InvalidDecoratorSemicolon, + StrictDelete, + InvalidPatternTail, + AsyncFunctionInSingleStatementContext, + InvalidTernaryYield, + InvalidArrowPostfix, + InvalidObjLitKeyStar, + DeletePrivateField, + InvalidStaticClassFieldConstructor, + InvalidClassFieldConstructor, + InvalidClassFieldArgEval, + InvalidGeneratorFunction, + AsyncRestrictedProd, + UnexpectedCharAfterObjLit, + InvalidObjLitKey, + InvalidKeyToken, + LabelRedeclaration, + InvalidNestedStatement, + UnknownLabel, + InvalidImportTail, + ImportNotOneArg, + InvalidImportNew, + InvalidSpreadInImport, + UncompleteArrow, + DuplicateBinding, + DuplicateExportBinding, + UndeclaredExportedBinding, + UnexpectedPrivateField, + DuplicateLetConstBinding, + CantAssignToValidRHS, + ContinuousNumericSeparator, + TrailingNumericSeparator, + InvalidJSXAttributeValue, + ExpectedJSXClosingTag, + AdjacentJSXElements, + InvalidNonEmptyJSXExpr, + DuplicateIdentifier, + ShadowedCatchClause, + InvalidDotProperty, + UnclosedSpreadElement, + CatchWithoutTry, + FinallyWithoutTry, + UnCorrespondingFragmentTag, + InvalidCoalescing, + OptionalChainingNoTemplate, + OptionalChainingNoSuper, + OptionalChainingNoNew, + ImportMetaOutsideModule, + InvalidLeadingDecorator +} + +export const errorMessages: { + [key: string]: string; +} = { + [Errors.Unexpected]: 'Unexpected token', + [Errors.UnexpectedToken]: "Unexpected token: '%0'", + [Errors.StrictOctalEscape]: 'Octal escape sequences are not allowed in strict mode', + [Errors.TemplateOctalLiteral]: 'Octal escape sequences are not allowed in template strings', + [Errors.InvalidPrivateIdentifier]: 'Unexpected token `#`', + [Errors.InvalidUnicodeEscapeSequence]: 'Illegal Unicode escape sequence', + [Errors.InvalidCodePoint]: 'Invalid code point %0', + [Errors.InvalidHexEscapeSequence]: 'Invalid hexadecimal escape sequence', + [Errors.StrictOctalLiteral]: 'Octal literals are not allowed in strict mode', + [Errors.StrictDecimalWithLeadingZero]: 'Decimal integer literals with a leading zero are forbidden in strict mode', + [Errors.ExpectedNumberInRadix]: 'Expected number in radix %0', + [Errors.CantAssignToValidRHS]: 'Invalid left-hand side assignment to a destructible right-hand side', + [Errors.MissingExponent]: 'Non-number found after exponent indicator', + [Errors.InvalidBigInt]: 'Invalid BigIntLiteral', + [Errors.IDStartAfterNumber]: 'No identifiers allowed directly after numeric literal', + [Errors.InvalidEightAndNine]: 'Escapes \\8 or \\9 are not syntactically valid escapes', + [Errors.UnterminatedString]: 'Unterminated string literal', + [Errors.UnterminatedTemplate]: 'Unterminated template literal', + [Errors.UnterminatedComment]: 'Multiline comment was not closed properly', + [Errors.InvalidDynamicUnicode]: 'The identifier contained dynamic unicode escape that was not closed', + [Errors.IllegalCharacter]: "Illegal character '%0'", + [Errors.MissingHexDigits]: 'Missing hexadecimal digits', + [Errors.InvalidImplicitOctals]: 'Invalid implicit octal', + [Errors.InvalidStringLT]: 'Invalid line break in string literal', + [Errors.InvalidEscapeIdentifier]: 'Only unicode escapes are legal in identifier names', + [Errors.ExpectedToken]: "Expected '%0'", + [Errors.CantAssignTo]: 'Invalid left-hand side in assignment', + [Errors.InvalidLHSAsyncArrow]: 'Invalid left-hand side in async arrow', + [Errors.SuperNoConstructor]: + 'Calls to super must be in the "constructor" method of a class expression or class declaration that has a superclass', + [Errors.InvalidSuperProperty]: 'Member access on super must be in a method', + [Errors.AwaitInParameter]: 'Await expression not allowed in formal parameter', + [Errors.YieldInParameter]: 'Yield expression not allowed in formal parameter', + [Errors.InvalidEscapedKeyword]: "Unexpected token: 'escaped keyword'", + [Errors.InvalidExponentiationLHS]: + 'Unary expressions as the left operand of an exponentiation expression must be disambiguated with parentheses', + [Errors.AsyncFunctionInSingleStatementContext]: + 'Async functions can only be declared at the top level or inside a block', + [Errors.UnterminatedRegExp]: 'Unterminated regular expression', + [Errors.UnexpectedTokenRegExpFlag]: 'Unexpected regular expression flag', + [Errors.DuplicateRegExpFlag]: "Duplicate regular expression flag '%0'", + [Errors.AccessorWrongArgs]: '%0 functions must have exactly %1 argument%2', + [Errors.BadSetterRestParameter]: 'Setter function argument must not be a rest parameter', + [Errors.DeclNoName]: '%0 declaration must have a name in this context', + [Errors.StrictFunctionName]: + 'Function name may not contain any reserved words or be eval or arguments in strict mode', + [Errors.RestMissingArg]: 'The rest operator is missing an argument', + [Errors.InvalidGeneratorGetter]: 'A getter cannot be a generator', + [Errors.InvalidComputedPropName]: 'A computed property name must be followed by a colon or paren', + [Errors.InvalidObjLitKey]: 'Object literal keys that are strings or numbers must be a method or have a colon', + [Errors.InvalidAsyncGetter]: 'Found `* async x(){}` but this should be `async * x(){}`', + [Errors.InvalidGetSetGenerator]: 'Getters and setters can not be generators', + [Errors.InvalidGenMethodShorthand]: "'%0' can not be generator method", + [Errors.InvalidLineBreak]: "No line break is allowed after '=>'", + [Errors.InvalidArrowDestructLHS]: 'The left-hand side of the arrow can only be destructed through assignment', + [Errors.InvalidBindingDestruct]: 'The binding declaration is not destructible', + [Errors.InvalidAsyncArrow]: 'Async arrow can not be followed by new expression', + [Errors.StaticPrototype]: "Classes may not have a static property named 'prototype'", + [Errors.InvalidConstructor]: 'Class constructor may not be a %0', + [Errors.DuplicateConstructor]: 'Duplicate constructor method in class', + [Errors.InvalidIncDecTarget]: 'Invalid increment/decrement operand', + [Errors.InvalidIncDecNew]: 'Invalid use of `new` keyword on an increment/decrement expression', + [Errors.InvalidAssignmentTarget]: '`=>` is an invalid assignment target', + [Errors.InvalidRestTrailing]: 'Rest element may not have a trailing comma', + [Errors.DeclarationMissingInitializer]: 'Missing initializer in %0 declaration', + [Errors.ForInOfLoopInitializer]: "'for-%0' loop head declarations can not have an initializer", + [Errors.ForInOfLoopMultiBindings]: 'Invalid left-hand side in for-%0 loop: Must have a single binding', + [Errors.InvalidShorthandPropInit]: 'Invalid shorthand property initializer', + [Errors.DuplicateProto]: 'Property name __proto__ appears more than once in object literal', + [Errors.InvalidLetBoundName]: 'Let is disallowed as a lexically bound name', + [Errors.InvalidNewUnary]: "Invalid use of '%0' inside new expression", + [Errors.IllegalUseStrict]: "Illegal 'use strict' directive in function with non-simple parameter list", + [Errors.DisallowedLetInStrict]: 'Identifier "let" disallowed as left-hand side expression in strict mode', + [Errors.IllegalContinue]: 'Illegal continue statement', + [Errors.IllegalBreak]: 'Illegal break statement', + [Errors.InvalidLetBracket]: 'Cannot have `let[...]` as a var name in strict mode', + [Errors.InvalidDestructuringTarget]: 'Invalid destructuring assignment target', + [Errors.RestDefaultInitializer]: 'Rest parameter may not have a default initializer', + [Errors.InvalidRestNotLast]: 'The rest argument must the be last parameter', + [Errors.InvalidRestArg]: 'Invalid rest argument', + [Errors.StrictFunction]: 'In strict mode code, functions can only be declared at top level or inside a block', + [Errors.SloppyFunction]: + 'In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement', + [Errors.WebCompatFunction]: + 'Without web compatibility enabled functions can not be declared at top level, inside a block, or as the body of an if statement', + [Errors.ClassForbiddenAsStatement]: "Class declaration can't appear in single-statement context", + [Errors.CantAssignToInOfForLoop]: 'Invalid left-hand side in for-%0', + [Errors.InvalidAssignmentInOfForLoop]: 'Invalid assignment in for-%0', + [Errors.InvalidForAwait]: 'for await (... of ...) is only valid in async functions and async generators', + [Errors.InvalidTemplateContinuation]: + 'The first token after the template expression should be a continuation of the template', + [Errors.UnexpectedLetStrictReserved]: + '`let` declaration not allowed here and `let` cannot be a regular var name in strict mode', + [Errors.RestrictedLetProduction]: '`let \n [` is a restricted production at the start of a statement', + [Errors.InvalidCatchParams]: 'Catch clause requires exactly one parameter, not more (and no trailing comma)', + [Errors.InvalidCatchParamDefault]: 'Catch clause parameter does not support default values', + [Errors.NoCatchOrFinally]: 'Missing catch or finally after try', + [Errors.MultipleDefaultsInSwitch]: 'More than one default clause in switch statement', + [Errors.NewlineAfterThrow]: 'Illegal newline after throw', + [Errors.StrictWith]: 'Strict mode code may not include a with statement', + [Errors.IllegalReturn]: 'Illegal return statement', + [Errors.InvalidForLHSBinding]: 'The left hand side of the for-header binding declaration is not destructible', + [Errors.InvalidNewTarget]: 'new.target only allowed within functions', + [Errors.MissingPrivateIdentifier]: "'#' not followed by identifier", + [Errors.KeywordNotId]: 'Invalid keyword', + [Errors.InvalidLetClassName]: "Can not use 'let' as a class name", + [Errors.InvalidLetConstBinding]: "'A lexical declaration can't define a 'let' binding", + [Errors.InvalidStrictLet]: 'Can not use `let` as variable name in strict mode', + [Errors.DisallowedInContext]: "'%0' may not be used as an identifier in this context", + [Errors.AwaitOutsideAsync]: 'Await is only valid in async functions', + [Errors.InvalidImportExportSloppy]: 'The %0 keyword can only be used with the module goal', + [Errors.UnicodeOverflow]: 'Unicode codepoint must not be greater than 0x10FFFF', + [Errors.InvalidExportImportSource]: '%0 source must be string', + [Errors.InvalidKeywordAsAlias]: 'Only a identifier can be used to indicate alias', + [Errors.InvalidDefaultImport]: "Only '*' or '{...}' can be imported after default", + [Errors.TrailingDecorators]: 'Trailing decorator may be followed by method', + [Errors.GeneratorConstructor]: "Decorators can't be used with a constructor", + [Errors.HtmlCommentInWebCompat]: 'HTML comments are only allowed with web compatibility (Annex B)', + [Errors.StrictInvalidLetInExprPos]: "The identifier 'let' must not be in expression position in strict mode", + [Errors.NotAssignableLetArgs]: 'Cannot assign to `eval` and `arguments` in strict mode', + [Errors.ForOfLet]: "The left-hand side of a for-of loop may not start with 'let'", + [Errors.InvalidInvokedBlockBodyArrow]: 'Block body arrows can not be immediately invoked without a group', + [Errors.InvalidAccessedBlockBodyArrow]: 'Block body arrows can not be immediately accessed without a group', + [Errors.UnexpectedStrictReserved]: 'Unexpected strict mode reserved word', + [Errors.StrictEvalArguments]: 'Unexpected eval or arguments in strict mode', + [Errors.InvalidDecoratorSemicolon]: 'Decorators must not be followed by a semicolon', + [Errors.StrictDelete]: 'Calling delete on expression not allowed in strict mode', + [Errors.InvalidPatternTail]: 'Pattern can not have a tail', + [Errors.InvalidTernaryYield]: 'Can not have a `yield` expression on the left side of a ternary', + [Errors.InvalidArrowPostfix]: 'An arrow function can not have a postfix update operator', + [Errors.InvalidObjLitKeyStar]: 'Invalid object literal key character after generator star', + [Errors.DeletePrivateField]: 'Private fields can not be deleted', + [Errors.InvalidClassFieldConstructor]: 'Classes may not have a field called constructor', + [Errors.InvalidStaticClassFieldConstructor]: 'Classes may not have a private element named constructor', + [Errors.InvalidClassFieldArgEval]: 'A class field initializer may not contain arguments', + [Errors.InvalidGeneratorFunction]: 'Generators can only be declared at the top level or inside a block', + [Errors.AsyncRestrictedProd]: 'Async methods are a restricted production and cannot have a newline following it', + [Errors.UnexpectedCharAfterObjLit]: 'Unexpected character after object literal property name', + [Errors.InvalidKeyToken]: 'Invalid key token', + [Errors.LabelRedeclaration]: "Label '%0' has already been declared", + [Errors.InvalidNestedStatement]: 'continue statement must be nested within an iteration statement', + [Errors.UnknownLabel]: "Undefined label '%0'", + [Errors.InvalidImportTail]: 'Trailing comma is disallowed inside import(...) arguments', + [Errors.ImportNotOneArg]: 'import() requires exactly one argument', + [Errors.InvalidImportNew]: 'Cannot use new with import(...)', + [Errors.InvalidSpreadInImport]: '... is not allowed in import()', + [Errors.UncompleteArrow]: "Expected '=>'", + [Errors.DuplicateBinding]: "Duplicate binding '%0'", + [Errors.DuplicateExportBinding]: "Cannot export a duplicate name '%0'", + [Errors.DuplicateLetConstBinding]: 'Duplicate %0 for-binding', + [Errors.UndeclaredExportedBinding]: "Exported binding '%0' needs to refer to a top-level declared variable", + [Errors.UnexpectedPrivateField]: 'Unexpected private field', + [Errors.TrailingNumericSeparator]: 'Numeric separators are not allowed at the end of numeric literals', + [Errors.ContinuousNumericSeparator]: 'Only one underscore is allowed as numeric separator', + [Errors.InvalidJSXAttributeValue]: 'JSX value should be either an expression or a quoted JSX text', + [Errors.ExpectedJSXClosingTag]: 'Expected corresponding JSX closing tag for %0', + [Errors.AdjacentJSXElements]: 'Adjacent JSX elements must be wrapped in an enclosing tag', + [Errors.InvalidNonEmptyJSXExpr]: "JSX attributes must only be assigned a non-empty 'expression'", + [Errors.DuplicateIdentifier]: "'%0' has already been declared", + [Errors.ShadowedCatchClause]: "'%0' shadowed a catch clause binding", + [Errors.InvalidDotProperty]: 'Dot property must be an identifier', + [Errors.UnclosedSpreadElement]: 'Encountered invalid input after spread/rest argument', + [Errors.CatchWithoutTry]: 'Catch without try', + [Errors.FinallyWithoutTry]: 'Finally without try', + [Errors.UnCorrespondingFragmentTag]: 'Expected corresponding closing tag for JSX fragment', + [Errors.InvalidCoalescing]: + 'Coalescing and logical operators used together in the same expression must be disambiguated with parentheses', + [Errors.OptionalChainingNoTemplate]: 'Invalid tagged template on optional chain', + [Errors.OptionalChainingNoSuper]: 'Invalid optional chain from super property', + [Errors.OptionalChainingNoNew]: 'Invalid optional chain from new expression', + [Errors.ImportMetaOutsideModule]: 'Cannot use "import.meta" outside a module', + [Errors.InvalidLeadingDecorator]: 'Leading decorators must be attached to a class declaration' +}; + +export class ParseError extends SyntaxError { + public loc: { + line: ParseError['line']; + column: ParseError['column']; + }; + public index: number; + public line: number; + public column: number; + public description: string; + /*eslint-disable*/ + constructor(startindex: number, line: number, column: number, type: Errors, ...params: string[]) { + const message = + '[' + line + ':' + column + ']: ' + errorMessages[type].replace(/%(\d+)/g, (_: string, i: number) => params[i]); + super(`${message}`); + this.index = startindex; + this.line = line; + this.column = column; + this.description = message; + /* Acorn compat */ + this.loc = { + line, + column + } as any; + } +} +/** + * Throws an error + * + * @export + * @param {ParserState} state + * @param {Errors} type + * @param {...string[]} params + * @returns {never} + */ +export function report(parser: ParserState, type: Errors, ...params: string[]): never { + throw new ParseError(parser.index, parser.line, parser.column, type, ...params); +} + +export function reportScopeError(scope: any): never { + throw new ParseError(scope.index, scope.line, scope.column, scope.type, scope.params); +} + +/** + * Throws an error at a given position + * + * @export + * @param {ParserState} state + * @param {number} index + * @param {number} line + * @param {number} column + * @param {Errors} type + * @param {...string[]} params + */ +export function reportMessageAt(index: number, line: number, column: number, type: Errors, ...params: string[]): never { + throw new ParseError(index, line, column, type, ...params); +} + +/** + * Throws an error at a given position + * + * @export + * @param {ParserState} state + * @param {number} index + * @param {number} line + * @param {number} column + * @param {Errors} type + */ +export function reportScannerError(index: number, line: number, column: number, type: Errors): never { + throw new ParseError(index, line, column, type); +} diff --git a/node_modules/meriyah/src/estree.ts b/node_modules/meriyah/src/estree.ts new file mode 100644 index 0000000..31d8416 --- /dev/null +++ b/node_modules/meriyah/src/estree.ts @@ -0,0 +1,809 @@ +export interface _Node { + start?: number; + end?: number; + range?: [number, number]; + loc?: SourceLocation | null; +} + +export interface SourceLocation { + source?: string | null; + start: Position; + end: Position; +} + +export interface Position { + /** >= 1 */ + line: number; + /** >= 0 */ + column: number; +} + +export type Labels = any; + +export type IdentifierOrExpression = Identifier | Expression | ArrowFunctionExpression; + +export type ArgumentExpression = + | ArrayExpression + | AssignmentExpression + | ConditionalExpression + | Literal + | SpreadElement + | BinaryExpression + | LogicalExpression + | SequenceExpression; + +export type CommentType = 'SingleLine' | 'MultiLine' | 'HTMLOpen' | 'HTMLClose' | 'HashbangComment'; + +export interface Comment { + type: CommentType; + value: string; + start?: number; + end?: number; + loc?: SourceLocation | null; +} + +export type Node = + | ArrayExpression + | ArrayPattern + | ArrowFunctionExpression + | AssignmentExpression + | AssignmentPattern + | AwaitExpression + | BigIntLiteral + | BinaryExpression + | BlockStatement + | BreakStatement + | CallExpression + | ChainExpression + | ImportExpression + | CatchClause + | ClassBody + | ClassDeclaration + | ClassExpression + | ConditionalExpression + | ContinueStatement + | DebuggerStatement + | Decorator + | DoWhileStatement + | EmptyStatement + | ExportAllDeclaration + | ExportDefaultDeclaration + | ExportNamedDeclaration + | ExportSpecifier + | ExpressionStatement + | PropertyDefinition + | ForInStatement + | ForOfStatement + | ForStatement + | FunctionDeclaration + | FunctionExpression + | Identifier + | IfStatement + | Import + | ImportDeclaration + | ImportDefaultSpecifier + | ImportNamespaceSpecifier + | ImportSpecifier + | JSXNamespacedName + | JSXAttribute + | JSXClosingElement + | JSXClosingFragment + | JSXElement + | JSXEmptyExpression + | JSXExpressionContainer + | JSXFragment + | JSXIdentifier + | JSXOpeningElement + | JSXOpeningFragment + | JSXSpreadAttribute + | JSXSpreadChild + | JSXMemberExpression + | JSXText + | LabeledStatement + | Literal + | LogicalExpression + | MemberExpression + | MetaProperty + | MethodDefinition + | NewExpression + | ObjectExpression + | ObjectPattern + | ParenthesizedExpression + | PrivateIdentifier + | Program + | Property + | RegExpLiteral + | RestElement + | ReturnStatement + | SequenceExpression + | SpreadElement + | Super + | SwitchCase + | SwitchStatement + | TaggedTemplateExpression + | TemplateElement + | TemplateLiteral + | ThisExpression + | ThrowStatement + | TryStatement + | UpdateExpression + | UnaryExpression + | VariableDeclaration + | VariableDeclarator + | WhileStatement + | WithStatement + | YieldExpression; +export type BindingPattern = ArrayPattern | ObjectPattern | Identifier; +export type ClassElement = FunctionExpression | MethodDefinition; +export type DeclarationStatement = + | ClassDeclaration + | ClassExpression + | ExportDefaultDeclaration + | ExportAllDeclaration + | ExportNamedDeclaration + | FunctionDeclaration; +export type EntityName = Identifier; +export type ExportDeclaration = ClassDeclaration | ClassExpression | FunctionDeclaration | VariableDeclaration; +export type Expression = + | ArrowFunctionExpression + | AssignmentExpression + | BinaryExpression + | ConditionalExpression + | MetaProperty + | ChainExpression + | JSXClosingElement + | JSXClosingFragment + | JSXExpressionContainer + | JSXOpeningElement + | JSXOpeningFragment + | JSXSpreadChild + | LogicalExpression + | NewExpression + | RestElement + | SequenceExpression + | SpreadElement + | AwaitExpression + | LeftHandSideExpression + | UnaryExpression + | UpdateExpression + | YieldExpression; +export type ForInitialiser = Expression | VariableDeclaration; +export type ImportClause = ImportDefaultSpecifier | ImportNamespaceSpecifier | ImportSpecifier; +export type IterationStatement = DoWhileStatement | ForInStatement | ForOfStatement | ForStatement | WhileStatement; +export type JSXChild = JSXElement | JSXExpression | JSXFragment | JSXText; +export type JSXExpression = JSXEmptyExpression | JSXSpreadChild | JSXExpressionContainer; +export type JSXTagNameExpression = JSXIdentifier | JSXMemberExpression | JSXNamespacedName; +export type LeftHandSideExpression = + | CallExpression + | ChainExpression + | ImportExpression + | ClassExpression + | ClassDeclaration + | FunctionExpression + | LiteralExpression + | MemberExpression + | PrimaryExpression + | TaggedTemplateExpression; +export type LiteralExpression = Literal | TemplateLiteral; +export type ObjectLiteralElementLike = MethodDefinition | Property | RestElement | SpreadElement; +export type Parameter = AssignmentPattern | RestElement | ArrayPattern | ObjectPattern | Identifier; +export type PrimaryExpression = + | ArrayExpression + | ArrayPattern + | ClassExpression + | FunctionExpression + | Identifier + | Import + | JSXElement + | JSXFragment + | JSXOpeningElement + | Literal + | LiteralExpression + | MetaProperty + | ObjectExpression + | ObjectPattern + | Super + | TemplateLiteral + | ThisExpression; +export type PrimaryExpressionExtended = + | ArrayExpression + | ArrowFunctionExpression + | ArrayPattern + | AwaitExpression + | Expression + | ClassExpression + | FunctionExpression + | Identifier + | Import + | JSXElement + | JSXFragment + | JSXOpeningElement + | Literal + | LiteralExpression + | MetaProperty + | ObjectExpression + | ObjectPattern + | PrivateIdentifier + | NewExpression + | Super + | TemplateLiteral + | ThisExpression + | UnaryExpression + | UpdateExpression; +export type PropertyName = Identifier | Literal; +export type Statement = + | BlockStatement + | BreakStatement + | ContinueStatement + | DebuggerStatement + | DeclarationStatement + | EmptyStatement + | ExpressionStatement + | IfStatement + | IterationStatement + | ImportDeclaration + | LabeledStatement + | ReturnStatement + | SwitchStatement + | ThrowStatement + | TryStatement + | VariableDeclaration + | WithStatement; + +interface ClassDeclarationBase extends _Node { + id: Identifier | null; + body: ClassBody; + superClass: Expression | null; + decorators?: Decorator[]; +} + +interface FunctionDeclarationBase extends _Node { + id: Identifier | null; + generator: boolean; + async: boolean; + params: Parameter[]; + body?: BlockStatement | null; +} + +interface MethodDefinitionBase extends _Node { + key: Expression | PrivateIdentifier | null; + value: FunctionExpression; + computed: boolean; + static: boolean; + kind: 'method' | 'get' | 'set' | 'constructor'; + decorators?: Decorator[]; +} + +export interface ArrayExpression extends _Node { + type: 'ArrayExpression'; + elements: (Expression | SpreadElement | null)[]; +} + +export interface ArrayPattern extends _Node { + type: 'ArrayPattern'; + elements: Expression[]; +} + +export interface ArrowFunctionExpression extends _Node { + type: 'ArrowFunctionExpression'; + params: Parameter[]; + body: Expression | BlockStatement; + async: boolean; + expression: boolean; +} + +export interface AssignmentExpression extends _Node { + type: 'AssignmentExpression'; + operator: string; + left: Expression; + right: Expression; +} + +export interface AssignmentPattern extends _Node { + type: 'AssignmentPattern'; + left: BindingPattern | Identifier; + right?: Expression; +} + +export interface AwaitExpression extends _Node { + type: 'AwaitExpression'; + argument: Expression; +} + +export interface BigIntLiteral extends Literal { + bigint: string; +} + +export interface BinaryExpression extends _Node { + type: 'BinaryExpression'; + operator: string; + left: Expression; + right: Expression; +} + +export interface BlockStatement extends _Node { + type: 'BlockStatement'; + body: Statement[]; +} + +export interface BreakStatement extends _Node { + type: 'BreakStatement'; + label: Identifier | null; +} + +export interface ImportExpression extends _Node { + type: 'ImportExpression'; + source: Expression; +} + +export interface ChainExpression extends _Node { + type: 'ChainExpression'; + expression: CallExpression | MemberExpression; +} + +export interface CallExpression extends _Node { + type: 'CallExpression'; + callee: any; //Expression | Super; + arguments: (Expression | SpreadElement)[]; + optional?: boolean; +} + +export interface CatchClause extends _Node { + type: 'CatchClause'; + param: BindingPattern | Identifier | null; + body: BlockStatement; +} + +export interface ClassBody extends _Node { + type: 'ClassBody'; + body: (ClassElement | PropertyDefinition)[]; +} + +export interface PropertyDefinition extends _Node { + type: 'PropertyDefinition'; + key: PrivateIdentifier | Expression; + value: any; + decorators?: Decorator[] | null; + computed: boolean; + static: boolean; +} + +export interface PrivateIdentifier extends _Node { + type: 'PrivateIdentifier'; + name: string; +} + +export interface ClassDeclaration extends ClassDeclarationBase { + type: 'ClassDeclaration'; +} + +export interface ClassExpression extends ClassDeclarationBase { + type: 'ClassExpression'; +} + +export interface ConditionalExpression extends _Node { + type: 'ConditionalExpression'; + test: Expression; + consequent: Expression; + alternate: Expression; +} + +export interface ContinueStatement extends _Node { + type: 'ContinueStatement'; + label: Identifier | null; +} + +export interface DebuggerStatement extends _Node { + type: 'DebuggerStatement'; +} + +export interface Decorator extends _Node { + type: 'Decorator'; + expression: LeftHandSideExpression; +} + +export interface DoWhileStatement extends _Node { + type: 'DoWhileStatement'; + test: Expression; + body: Statement; +} + +export interface EmptyStatement extends _Node { + type: 'EmptyStatement'; +} + +export interface ExportAllDeclaration extends _Node { + type: 'ExportAllDeclaration'; + source: Literal; + exported: Identifier | null; +} + +export interface ExportDefaultDeclaration extends _Node { + type: 'ExportDefaultDeclaration'; + declaration: ExportDeclaration | Expression; +} + +export interface ExportNamedDeclaration extends _Node { + type: 'ExportNamedDeclaration'; + declaration: ExportDeclaration | null; + specifiers: ExportSpecifier[]; + source: Literal | null; +} + +export interface ExportSpecifier extends _Node { + type: 'ExportSpecifier'; + local: Identifier; + exported: Identifier; +} + +export interface ExpressionStatement extends _Node { + type: 'ExpressionStatement'; + expression: Expression; +} + +export interface ForInStatement extends _Node { + type: 'ForInStatement'; + left: ForInitialiser; + right: Expression; + body: Statement; +} + +export interface ForOfStatement extends _Node { + type: 'ForOfStatement'; + left: ForInitialiser; + right: Expression; + body: Statement; + await: boolean; +} + +export interface ForStatement extends _Node { + type: 'ForStatement'; + init: Expression | ForInitialiser | null; + test: Expression | null; + update: Expression | null; + body: Statement; +} + +export interface FunctionDeclaration extends FunctionDeclarationBase { + type: 'FunctionDeclaration'; +} + +export interface FunctionExpression extends FunctionDeclarationBase { + type: 'FunctionExpression'; +} + +export interface Identifier extends _Node { + type: 'Identifier'; + name: string; +} + +export interface IfStatement extends _Node { + type: 'IfStatement'; + test: Expression; + consequent: Statement; + alternate: Statement | null; +} + +export interface Import extends _Node { + type: 'Import'; +} + +export interface ImportDeclaration extends _Node { + type: 'ImportDeclaration'; + source: Literal; + specifiers: ImportClause[]; +} + +export interface ImportDefaultSpecifier extends _Node { + type: 'ImportDefaultSpecifier'; + local: Identifier; +} + +export interface ImportNamespaceSpecifier extends _Node { + type: 'ImportNamespaceSpecifier'; + local: Identifier; +} + +export interface ImportSpecifier extends _Node { + type: 'ImportSpecifier'; + local: Identifier; + imported: Identifier; +} + +export interface JSXNamespacedName extends _Node { + type: 'JSXNamespacedName'; + namespace: JSXIdentifier | JSXMemberExpression; + name: JSXIdentifier; +} + +export type JSXAttributeValue = + | JSXIdentifier + | Literal + | JSXElement + | JSXFragment + | JSXExpressionContainer + | JSXSpreadChild + | null; + +export interface JSXAttribute extends _Node { + type: 'JSXAttribute'; + name: JSXNamespacedName | JSXIdentifier; + value: JSXAttributeValue; +} + +export interface JSXClosingElement extends _Node { + type: 'JSXClosingElement'; + name: JSXTagNameExpression; +} + +export interface JSXClosingFragment extends _Node { + type: 'JSXClosingFragment'; +} + +export interface JSXElement extends _Node { + type: 'JSXElement'; + openingElement: JSXOpeningElement; + closingElement: JSXClosingElement | null; + children: JSXChild[]; +} + +export interface JSXEmptyExpression extends _Node { + type: 'JSXEmptyExpression'; +} + +export interface JSXExpressionContainer extends _Node { + type: 'JSXExpressionContainer'; + expression: Expression | JSXEmptyExpression; +} + +export interface JSXFragment extends _Node { + type: 'JSXFragment'; + openingFragment: JSXOpeningFragment; + closingFragment: JSXClosingFragment; + children: JSXChild[]; +} + +export interface JSXIdentifier extends _Node { + type: 'JSXIdentifier'; + name: string; +} + +export interface JSXMemberExpression extends _Node { + type: 'JSXMemberExpression'; + object: JSXTagNameExpression; + property: JSXIdentifier; +} + +export interface JSXOpeningElement extends _Node { + type: 'JSXOpeningElement'; + selfClosing: boolean; + name: JSXTagNameExpression; + attributes: (JSXAttribute | JSXSpreadAttribute)[]; +} + +export interface JSXOpeningFragment extends _Node { + type: 'JSXOpeningFragment'; +} + +export interface JSXSpreadAttribute extends _Node { + type: 'JSXSpreadAttribute'; + argument: Expression; +} + +export interface JSXSpreadChild extends _Node { + type: 'JSXSpreadChild'; + expression: Expression | JSXEmptyExpression; +} + +export interface JSXText extends _Node { + type: 'JSXText'; + value: string; + raw?: string; +} + +export interface LabeledStatement extends _Node { + type: 'LabeledStatement'; + label: Identifier; + body: Statement; +} + +export interface Literal extends _Node { + type: 'Literal'; + value: boolean | number | string | null | RegExp | bigint; + raw?: string; +} + +export interface LogicalExpression extends _Node { + type: 'LogicalExpression'; + operator: string; + left: Expression; + right: Expression; +} + +export interface MemberExpression extends _Node { + type: 'MemberExpression'; + object: Expression | Super; + property: Expression | PrivateIdentifier; + computed?: boolean; + optional?: boolean; +} + +export type Pattern = Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression; + +export interface MetaProperty extends _Node { + type: 'MetaProperty'; + meta: Identifier; + property: Identifier; +} + +export interface MethodDefinition extends MethodDefinitionBase { + type: 'MethodDefinition'; +} + +export interface NewExpression extends _Node { + type: 'NewExpression'; + callee: LeftHandSideExpression; + arguments: Expression[]; +} + +export interface ObjectExpression extends _Node { + type: 'ObjectExpression'; + properties: ObjectLiteralElementLike[]; +} + +export interface ObjectPattern extends _Node { + type: 'ObjectPattern'; + properties: ObjectLiteralElementLike[]; +} + +export interface Program extends _Node { + type: 'Program'; + body: Statement[]; + sourceType: 'module' | 'script'; +} + +export interface ParenthesizedExpression extends _Node { + type: 'ParenthesizedExpression'; + expression: Expression; +} + +export interface Property extends _Node { + type: 'Property'; + key: Expression; + value: Expression | AssignmentPattern | BindingPattern | Identifier; + computed: boolean; + method: boolean; + shorthand: boolean; + kind: 'init' | 'get' | 'set'; +} + +export interface RegExpLiteral extends Literal { + regex: { + pattern: string; + flags: string; + }; +} + +export interface RestElement extends _Node { + type: 'RestElement'; + argument: BindingPattern | Identifier | Expression | PropertyName; + value?: AssignmentPattern; +} + +export interface ReturnStatement extends _Node { + type: 'ReturnStatement'; + argument: Expression | null; +} + +export interface SequenceExpression extends _Node { + type: 'SequenceExpression'; + expressions: Expression[]; +} + +export type SpreadArgument = BindingPattern | Identifier | Expression | PropertyName | SpreadElement; + +export interface SpreadElement extends _Node { + type: 'SpreadElement'; + argument: SpreadArgument; +} + +export interface Super extends _Node { + type: 'Super'; +} + +export interface SwitchCase extends _Node { + type: 'SwitchCase'; + test: Expression | null; + consequent: Statement[]; +} + +export interface SwitchStatement extends _Node { + type: 'SwitchStatement'; + discriminant: Expression; + cases: SwitchCase[]; +} + +export interface TaggedTemplateExpression extends _Node { + type: 'TaggedTemplateExpression'; + tag: Expression; + quasi: TemplateLiteral; +} + +export interface TemplateElement extends _Node { + type: 'TemplateElement'; + value: { + raw: string; + cooked: string | null; + }; + tail: boolean; +} + +export interface TemplateLiteral extends _Node { + type: 'TemplateLiteral'; + quasis: TemplateElement[]; + expressions: Expression[]; +} + +export interface ThisExpression extends _Node { + type: 'ThisExpression'; +} + +export interface ThrowStatement extends _Node { + type: 'ThrowStatement'; + argument: Expression; +} + +export interface TryStatement extends _Node { + type: 'TryStatement'; + block: BlockStatement; + handler: CatchClause | null; + finalizer: BlockStatement | null; +} + +export type UnaryOperator = '-' | '+' | '!' | '~' | 'typeof' | 'void' | 'delete'; +export type UpdateOperator = '++' | '--'; + +export interface UpdateExpression extends _Node { + type: 'UpdateExpression'; + operator: UpdateOperator; + argument: Expression; + prefix: boolean; +} + +export interface UnaryExpression extends _Node { + type: 'UnaryExpression'; + operator: UnaryOperator; + prefix: true; + argument: Expression; +} + +export interface VariableDeclaration extends _Node { + type: 'VariableDeclaration'; + declarations: VariableDeclarator[]; + kind: 'let' | 'const' | 'var'; +} + +export interface VariableDeclarator extends _Node { + type: 'VariableDeclarator'; + id: Expression | BindingPattern | Identifier; + init: Expression | null; + definite?: boolean; +} + +export interface WhileStatement extends _Node { + type: 'WhileStatement'; + test: Expression; + body: Statement; +} + +export interface WithStatement extends _Node { + type: 'WithStatement'; + object: Expression; + body: Statement; +} + +export interface YieldExpression extends _Node { + type: 'YieldExpression'; + delegate: boolean; + argument?: Expression | null; +} diff --git a/node_modules/meriyah/src/lexer/charClassifier.ts b/node_modules/meriyah/src/lexer/charClassifier.ts new file mode 100644 index 0000000..eb31389 --- /dev/null +++ b/node_modules/meriyah/src/lexer/charClassifier.ts @@ -0,0 +1,449 @@ +import { unicodeLookup } from '../unicode'; +import { Chars } from '../chars'; + +export const enum CharFlags { + None = 0, + IdentifierStart = 1 << 0, + IdentifierPart = 1 << 1, + KeywordCandidate = 1 << 2, + LineTerminator = 1 << 3, // ECMA-262 11.3 Line Terminators + Decimal = 1 << 4, + Octal = 1 << 5, + Hex = 1 << 6, + Binary = 1 << 7, + Exponent = 1 << 8, + ImplicitOctalDigits = 1 << 9, + CarriageReturn = 1 << 10, + LineFeed = 1 << 11, + Underscore = 1 << 12, + StringLiteral = 1 << 13, + JSXToken = 1 << 14, + Hyphen = 1 << 15, +} + +/** + * Lookup table for mapping a codepoint to a set of flags + */ +export const CharTypes = [ + CharFlags.None /* 0x00 */, + CharFlags.None /* 0x01 */, + CharFlags.None /* 0x02 */, + CharFlags.None /* 0x03 */, + CharFlags.None /* 0x04 */, + CharFlags.None /* 0x05 */, + CharFlags.None /* 0x06 */, + CharFlags.None /* 0x07 */, + CharFlags.None /* 0x08 */, + CharFlags.None /* 0x09 */, + CharFlags.LineTerminator | CharFlags.CarriageReturn /* 0x0A */, + CharFlags.None /* 0x0B */, + CharFlags.None /* 0x0C */, + CharFlags.LineTerminator | CharFlags.LineFeed /* 0x0D */, + CharFlags.None /* 0x0E */, + CharFlags.None /* 0x0F */, + CharFlags.None /* 0x10 */, + CharFlags.None /* 0x11 */, + CharFlags.None /* 0x12 */, + CharFlags.None /* 0x13 */, + CharFlags.None /* 0x14 */, + CharFlags.None /* 0x15 */, + CharFlags.None /* 0x16 */, + CharFlags.None /* 0x17 */, + CharFlags.None /* 0x18 */, + CharFlags.None /* 0x19 */, + CharFlags.None /* 0x1A */, + CharFlags.None /* 0x1B */, + CharFlags.None /* 0x1C */, + CharFlags.None /* 0x1D */, + CharFlags.None /* 0x1E */, + CharFlags.None /* 0x1F */, + CharFlags.None /* 0x20 */, + CharFlags.None /* 0x21 ! */, + CharFlags.StringLiteral /* 0x22 */, + CharFlags.None /* 0x23 # */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x24 $ */, + CharFlags.None /* 0x25 % */, + CharFlags.None /* 0x26 & */, + CharFlags.StringLiteral /* 0x27 */, + CharFlags.None /* 0x28 */, + CharFlags.None /* 0x29 */, + CharFlags.None /* 0x2A */, + CharFlags.Exponent /* 0x2B */, + CharFlags.None /* 0x2C */, + CharFlags.Exponent | CharFlags.Hyphen /* 0x2D */, + CharFlags.None /* 0x2E */, + CharFlags.None /* 0x2F */, + CharFlags.IdentifierPart | CharFlags.Decimal | CharFlags.Binary | CharFlags.Octal | CharFlags.Hex /* 0x30 0 */, + CharFlags.IdentifierPart | CharFlags.Decimal | CharFlags.Binary | CharFlags.Octal | CharFlags.Hex /* 0x31 1 */, + CharFlags.IdentifierPart | CharFlags.Decimal | CharFlags.Octal | CharFlags.Hex /* 0x32 2 */, + CharFlags.IdentifierPart | CharFlags.Decimal | CharFlags.Octal | CharFlags.Hex /* 0x33 3 */, + CharFlags.IdentifierPart | CharFlags.Decimal | CharFlags.Octal | CharFlags.Hex /* 0x34 4 */, + CharFlags.IdentifierPart | CharFlags.Decimal | CharFlags.Octal | CharFlags.Hex /* 0x35 5 */, + CharFlags.IdentifierPart | CharFlags.Decimal | CharFlags.Octal | CharFlags.Hex /* 0x36 6 */, + CharFlags.IdentifierPart | CharFlags.Decimal | CharFlags.Octal | CharFlags.Hex /* 0x37 7 */, + CharFlags.IdentifierPart | CharFlags.Decimal | CharFlags.ImplicitOctalDigits | CharFlags.Hex /* 0x38 8 */, + CharFlags.IdentifierPart | CharFlags.Decimal | CharFlags.ImplicitOctalDigits | CharFlags.Hex /* 0x39 9 */, + CharFlags.None /* 0x3A */, + CharFlags.None /* 0x3B */, + CharFlags.JSXToken /* 0x3C < */, + CharFlags.None /* 0x3D = */, + CharFlags.None /* 0x3E > */, + CharFlags.None /* 0x3F */, + CharFlags.None /* 0x40 @ */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.Hex /* 0x41 A */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.Hex /* 0x42 B */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.Hex /* 0x43 C */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.Hex /* 0x44 D */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.Hex /* 0x45 E */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.Hex /* 0x46 F */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x47 G */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x48 H */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x49 I */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x4A J */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x4B K */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x4C L */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x4D M */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x4E N */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x4F O */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x50 P */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x51 Q */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x52 R */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x53 S */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x54 T */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x55 U */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x56 V */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x57 W */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x58 X */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x59 Y */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart /* 0x5A Z */, + CharFlags.None /* 0x5B */, + CharFlags.IdentifierStart /* 0x5C */, + CharFlags.None /* 0x5D */, + CharFlags.None /* 0x5E */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.Underscore/* 0x5F _ */, + CharFlags.None /* 0x60 */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate | CharFlags.Hex /* 0x61 a */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate | CharFlags.Hex /* 0x62 b */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate | CharFlags.Hex /* 0x63 c */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate | CharFlags.Hex /* 0x64 d */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate | CharFlags.Hex /* 0x65 e */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate | CharFlags.Hex /* 0x66 f */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x67 g */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x68 h */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x69 i */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x6A j */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x6B k */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x6C l */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x6D m */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x6E n */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x6F o */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x70 p */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x71 q */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x72 r */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x73 s */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x74 t */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x75 u */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x76 v */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x77 w */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x78 x */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x79 y */, + CharFlags.IdentifierStart | CharFlags.IdentifierPart | CharFlags.KeywordCandidate /* 0x7A z */, + CharFlags.JSXToken /* 0x7B */, + CharFlags.None /* 0x7C */, + CharFlags.None /* 0x7D */, + CharFlags.None /* 0x7E */, + CharFlags.None /* 0x7F */ +]; + +export const isIdStart = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0 +]; + +export const isIdPart = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0 +]; + + +export function isIdentifierStart(code: number): number { + /* + * ES2020 11.6 IdentifierStart + * $ (dollar sign) + * _ (underscore) + * or any character with the Unicode property «ID_Start». + * + * We use a lookup table for small and thus common characters for speed. + */ + return code <= 0x7F + ? isIdStart[code] + : (unicodeLookup[(code >>> 5) + 34816] >>> code) & 31 & 1; +} + +export function isIdentifierPart(code: number): any { + /* + * ES2020 11.6 IdentifierPart + * $ (dollar sign) + * _ (underscore) + * <ZWNJ> + * <ZWJ> + * or any character with the Unicode property «ID_Continue». + * + * We use a lookup table for small and thus common characters for speed. + */ + return code <= 0x7F + ? isIdPart[code] + : (unicodeLookup[(code >>> 5) + 0] >>> code) & 31 & 1 || (code === Chars.ZeroWidthJoiner || code === Chars.ZeroWidthNonJoiner); +} diff --git a/node_modules/meriyah/src/lexer/comments.ts b/node_modules/meriyah/src/lexer/comments.ts new file mode 100644 index 0000000..fc95da2 --- /dev/null +++ b/node_modules/meriyah/src/lexer/comments.ts @@ -0,0 +1,178 @@ +import { advanceChar, LexerState, scanNewLine, consumeLineFeed } from './common'; +import { CharTypes, CharFlags } from './charClassifier'; +import { Chars } from '../chars'; +import { Context, ParserState } from '../common'; +import { report, Errors } from '../errors'; + +export const enum CommentType { + Single, + Multi, + HTMLOpen, + HTMLClose, + HashBang +} + +export const CommentTypes = ['SingleLine', 'MultiLine', 'HTMLOpen', 'HTMLClose', 'HashbangComment']; + +/** + * Skips hasbang (stage 3) + * + * @param parser Parser object + */ +export function skipHashBang(parser: ParserState): void { + // HashbangComment :: + // #! SingleLineCommentChars_opt + const source = parser.source; + if (parser.currentChar === Chars.Hash && source.charCodeAt(parser.index + 1) === Chars.Exclamation) { + advanceChar(parser); + advanceChar(parser); + skipSingleLineComment( + parser, + source, + LexerState.None, + CommentType.HashBang, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + } +} + +export function skipSingleHTMLComment( + parser: ParserState, + source: string, + state: LexerState, + context: Context, + type: CommentType, + start: number, + line: number, + column: number +): LexerState { + if (context & Context.Module) report(parser, Errors.Unexpected); + return skipSingleLineComment(parser, source, state, type, start, line, column); +} + +/** + * Skips single line comment + * + * @param parser Parser object + * @param state Lexer state + */ +export function skipSingleLineComment( + parser: ParserState, + source: string, + state: LexerState, + type: CommentType, + start: number, + line: number, + column: number +): LexerState { + const { index } = parser; + parser.tokenPos = parser.index; + parser.linePos = parser.line; + parser.colPos = parser.column; + while (parser.index < parser.end) { + if (CharTypes[parser.currentChar] & CharFlags.LineTerminator) { + const isCR = parser.currentChar === Chars.CarriageReturn; + scanNewLine(parser); + if (isCR && parser.index < parser.end && parser.currentChar === Chars.LineFeed) + parser.currentChar = source.charCodeAt(++parser.index); + break; + } else if ((parser.currentChar ^ Chars.LineSeparator) <= 1) { + scanNewLine(parser); + break; + } + advanceChar(parser); + parser.tokenPos = parser.index; + parser.linePos = parser.line; + parser.colPos = parser.column; + } + if (parser.onComment) { + const loc = { + start: { + line, + column + }, + end: { + line: parser.linePos, + column: parser.colPos + } + }; + // For Single, start before "//", + // For HTMLOpen, start before "<!--", + // For HTMLClose, start before "\n-->" + parser.onComment(CommentTypes[type & 0xff], source.slice(index, parser.tokenPos), start, parser.tokenPos, loc); + } + return state | LexerState.NewLine; +} + +/** + * Skips multiline comment + * + * @param parser Parser object + * @param state Lexer state + */ +export function skipMultiLineComment(parser: ParserState, source: string, state: LexerState): LexerState | void { + const { index } = parser; + while (parser.index < parser.end) { + if (parser.currentChar < 0x2b) { + let skippedOneAsterisk = false; + while (parser.currentChar === Chars.Asterisk) { + if (!skippedOneAsterisk) { + state &= ~LexerState.LastIsCR; + skippedOneAsterisk = true; + } + if (advanceChar(parser) === Chars.Slash) { + advanceChar(parser); + if (parser.onComment) { + const loc = { + start: { + line: parser.linePos, + column: parser.colPos + }, + end: { + line: parser.line, + column: parser.column + } + }; + parser.onComment( + CommentTypes[CommentType.Multi & 0xff], + source.slice(index, parser.index - 2), + index - 2, // start before '/*' + parser.index, // end after '*/' + loc + ); + } + parser.tokenPos = parser.index; + parser.linePos = parser.line; + parser.colPos = parser.column; + return state; + } + } + + if (skippedOneAsterisk) { + continue; + } + + if (CharTypes[parser.currentChar] & CharFlags.LineTerminator) { + if (parser.currentChar === Chars.CarriageReturn) { + state |= LexerState.NewLine | LexerState.LastIsCR; + scanNewLine(parser); + } else { + consumeLineFeed(parser, state); + state = (state & ~LexerState.LastIsCR) | LexerState.NewLine; + } + } else { + advanceChar(parser); + } + } else if ((parser.currentChar ^ Chars.LineSeparator) <= 1) { + state = (state & ~LexerState.LastIsCR) | LexerState.NewLine; + scanNewLine(parser); + } else { + state &= ~LexerState.LastIsCR; + advanceChar(parser); + } + } + + report(parser, Errors.UnterminatedComment); +} diff --git a/node_modules/meriyah/src/lexer/common.ts b/node_modules/meriyah/src/lexer/common.ts new file mode 100644 index 0000000..de6f28d --- /dev/null +++ b/node_modules/meriyah/src/lexer/common.ts @@ -0,0 +1,140 @@ +import { Token } from '../token'; +import { Chars } from '../chars'; +import { ParserState, Flags } from '../common'; +import { unicodeLookup } from '../unicode'; +import { report, Errors } from '../errors'; + +export const enum LexerState { + None = 0, + NewLine = 1 << 0, + LastIsCR = 1 << 2 +} + +export const enum NumberKind { + ImplicitOctal = 1 << 0, + Binary = 1 << 1, + Octal = 1 << 2, + Hex = 1 << 3, + Decimal = 1 << 4, + NonOctalDecimal = 1 << 5, + Float = 1 << 6, + ValidBigIntKind = 1 << 7, + DecimalNumberKind = Decimal | NonOctalDecimal +} + +/** + * Advances this lexer's current index. + * + * @param parser The parser instance + */ +export function advanceChar(parser: ParserState): number { + parser.column++; + return (parser.currentChar = parser.source.charCodeAt(++parser.index)); +} + +/** + * Consumes multi unit code point + * + * @param parser The parser instance + * @param hi Code point to validate + */ +export function consumeMultiUnitCodePoint(parser: ParserState, hi: number): 0 | 1 { + // See: https://tc39.github.io/ecma262/#sec-ecmascript-language-types-string-type + if ((hi & 0xfc00) !== Chars.LeadSurrogateMin) return 0; + const lo = parser.source.charCodeAt(parser.index + 1); + if ((lo & 0xfc00) !== 0xdc00) return 0; + hi = parser.currentChar = Chars.NonBMPMin + ((hi & 0x3ff) << 10) + (lo & 0x3ff); + if (((unicodeLookup[(hi >>> 5) + 0] >>> hi) & 31 & 1) === 0) { + report(parser, Errors.IllegalCharacter, fromCodePoint(hi)); + } + parser.index++; + parser.column++; + return 1; +} + +/** + * Use to consume a line feed instead of `scanNewLine`. + */ +export function consumeLineFeed(parser: ParserState, state: LexerState): void { + parser.currentChar = parser.source.charCodeAt(++parser.index); + parser.flags |= Flags.NewLine; + if ((state & LexerState.LastIsCR) === 0) { + parser.column = 0; + parser.line++; + } +} + +export function scanNewLine(parser: ParserState): void { + parser.flags |= Flags.NewLine; + parser.currentChar = parser.source.charCodeAt(++parser.index); + parser.column = 0; + parser.line++; +} + +// ECMA-262 11.2 White Space +// gC=Zs, U+0009, U+000B, U+000C, U+FEFF +export function isExoticECMAScriptWhitespace(ch: number): boolean { + return ( + ch === Chars.NonBreakingSpace || + ch === Chars.ZeroWidthNoBreakSpace || + ch === Chars.NextLine || + ch === Chars.Ogham || + (ch >= Chars.EnQuad && ch <= Chars.ZeroWidthSpace) || + ch === Chars.NarrowNoBreakSpace || + ch === Chars.MathematicalSpace || + ch === Chars.IdeographicSpace || + ch === Chars.ThinSpace || + ch === Chars.ByteOrderMark + ); +} + +/** + * Optimized version of 'fromCodePoint' + * + * @param {number} code + * @returns {string} + */ +export function fromCodePoint(codePoint: number): string { + return codePoint <= 65535 + ? String.fromCharCode(codePoint) + : String.fromCharCode(codePoint >>> 10) + String.fromCharCode(codePoint & 0x3ff); +} + +/** + * Converts a value to a hex value + * + * @param code CodePoint + */ +export function toHex(code: number): number { + return code < Chars.UpperA ? code - Chars.Zero : (code - Chars.UpperA + 10) & 0xf; +} + +/** + * Converts a token to a string representation + * + * @param t Token + */ +export function convertTokenType(t: Token): string { + switch (t) { + case Token.NumericLiteral: + return 'NumericLiteral'; + case Token.StringLiteral: + return 'StringLiteral'; + case Token.FalseKeyword: + case Token.TrueKeyword: + return 'BooleanLiteral'; + case Token.NullKeyword: + return 'NullLiteral'; + case Token.RegularExpression: + return 'RegularExpression'; + case Token.TemplateContinuation: + case Token.TemplateSpan: + case Token.Template: + return 'TemplateLiteral'; + default: + if ((t & Token.IsIdentifier) === Token.IsIdentifier) return 'Identifier'; + if ((t & Token.Keyword) === Token.Keyword) return 'Keyword'; + + return 'Punctuator'; + } +} diff --git a/node_modules/meriyah/src/lexer/decodeHTML.ts b/node_modules/meriyah/src/lexer/decodeHTML.ts new file mode 100644 index 0000000..61cda52 --- /dev/null +++ b/node_modules/meriyah/src/lexer/decodeHTML.ts @@ -0,0 +1,2186 @@ +// https://html.spec.whatwg.org/entities.json +const entities: { [Identifier: string]: string } = { + AElig: '\u00C6', + AMP: '\u0026', + Aacute: '\u00C1', + Abreve: '\u0102', + Acirc: '\u00C2', + Acy: '\u0410', + Afr: '\uD835\uDD04', + Agrave: '\u00C0', + Alpha: '\u0391', + Amacr: '\u0100', + And: '\u2A53', + Aogon: '\u0104', + Aopf: '\uD835\uDD38', + ApplyFunction: '\u2061', + Aring: '\u00C5', + Ascr: '\uD835\uDC9C', + Assign: '\u2254', + Atilde: '\u00C3', + Auml: '\u00C4', + Backslash: '\u2216', + Barv: '\u2AE7', + Barwed: '\u2306', + Bcy: '\u0411', + Because: '\u2235', + Bernoullis: '\u212C', + Beta: '\u0392', + Bfr: '\uD835\uDD05', + Bopf: '\uD835\uDD39', + Breve: '\u02D8', + Bscr: '\u212C', + Bumpeq: '\u224E', + CHcy: '\u0427', + COPY: '\u00A9', + Cacute: '\u0106', + Cap: '\u22D2', + CapitalDifferentialD: '\u2145', + Cayleys: '\u212D', + Ccaron: '\u010C', + Ccedil: '\u00C7', + Ccirc: '\u0108', + Cconint: '\u2230', + Cdot: '\u010A', + Cedilla: '\u00B8', + CenterDot: '\u00B7', + Cfr: '\u212D', + Chi: '\u03A7', + CircleDot: '\u2299', + CircleMinus: '\u2296', + CirclePlus: '\u2295', + CircleTimes: '\u2297', + ClockwiseContourIntegral: '\u2232', + CloseCurlyDoubleQuote: '\u201D', + CloseCurlyQuote: '\u2019', + Colon: '\u2237', + Colone: '\u2A74', + Congruent: '\u2261', + Conint: '\u222F', + ContourIntegral: '\u222E', + Copf: '\u2102', + Coproduct: '\u2210', + CounterClockwiseContourIntegral: '\u2233', + Cross: '\u2A2F', + Cscr: '\uD835\uDC9E', + Cup: '\u22D3', + CupCap: '\u224D', + DD: '\u2145', + DDotrahd: '\u2911', + DJcy: '\u0402', + DScy: '\u0405', + DZcy: '\u040F', + Dagger: '\u2021', + Darr: '\u21A1', + Dashv: '\u2AE4', + Dcaron: '\u010E', + Dcy: '\u0414', + Del: '\u2207', + Delta: '\u0394', + Dfr: '\uD835\uDD07', + DiacriticalAcute: '\u00B4', + DiacriticalDot: '\u02D9', + DiacriticalDoubleAcute: '\u02DD', + DiacriticalGrave: '\u0060', + DiacriticalTilde: '\u02DC', + Diamond: '\u22C4', + DifferentialD: '\u2146', + Dopf: '\uD835\uDD3B', + Dot: '\u00A8', + DotDot: '\u20DC', + DotEqual: '\u2250', + DoubleContourIntegral: '\u222F', + DoubleDot: '\u00A8', + DoubleDownArrow: '\u21D3', + DoubleLeftArrow: '\u21D0', + DoubleLeftRightArrow: '\u21D4', + DoubleLeftTee: '\u2AE4', + DoubleLongLeftArrow: '\u27F8', + DoubleLongLeftRightArrow: '\u27FA', + DoubleLongRightArrow: '\u27F9', + DoubleRightArrow: '\u21D2', + DoubleRightTee: '\u22A8', + DoubleUpArrow: '\u21D1', + DoubleUpDownArrow: '\u21D5', + DoubleVerticalBar: '\u2225', + DownArrow: '\u2193', + DownArrowBar: '\u2913', + DownArrowUpArrow: '\u21F5', + DownBreve: '\u0311', + DownLeftRightVector: '\u2950', + DownLeftTeeVector: '\u295E', + DownLeftVector: '\u21BD', + DownLeftVectorBar: '\u2956', + DownRightTeeVector: '\u295F', + DownRightVector: '\u21C1', + DownRightVectorBar: '\u2957', + DownTee: '\u22A4', + DownTeeArrow: '\u21A7', + Downarrow: '\u21D3', + Dscr: '\uD835\uDC9F', + Dstrok: '\u0110', + ENG: '\u014A', + ETH: '\u00D0', + Eacute: '\u00C9', + Ecaron: '\u011A', + Ecirc: '\u00CA', + Ecy: '\u042D', + Edot: '\u0116', + Efr: '\uD835\uDD08', + Egrave: '\u00C8', + Element: '\u2208', + Emacr: '\u0112', + EmptySmallSquare: '\u25FB', + EmptyVerySmallSquare: '\u25AB', + Eogon: '\u0118', + Eopf: '\uD835\uDD3C', + Epsilon: '\u0395', + Equal: '\u2A75', + EqualTilde: '\u2242', + Equilibrium: '\u21CC', + Escr: '\u2130', + Esim: '\u2A73', + Eta: '\u0397', + Euml: '\u00CB', + Exists: '\u2203', + ExponentialE: '\u2147', + Fcy: '\u0424', + Ffr: '\uD835\uDD09', + FilledSmallSquare: '\u25FC', + FilledVerySmallSquare: '\u25AA', + Fopf: '\uD835\uDD3D', + ForAll: '\u2200', + Fouriertrf: '\u2131', + Fscr: '\u2131', + GJcy: '\u0403', + GT: '\u003E', + Gamma: '\u0393', + Gammad: '\u03DC', + Gbreve: '\u011E', + Gcedil: '\u0122', + Gcirc: '\u011C', + Gcy: '\u0413', + Gdot: '\u0120', + Gfr: '\uD835\uDD0A', + Gg: '\u22D9', + Gopf: '\uD835\uDD3E', + GreaterEqual: '\u2265', + GreaterEqualLess: '\u22DB', + GreaterFullEqual: '\u2267', + GreaterGreater: '\u2AA2', + GreaterLess: '\u2277', + GreaterSlantEqual: '\u2A7E', + GreaterTilde: '\u2273', + Gscr: '\uD835\uDCA2', + Gt: '\u226B', + HARDcy: '\u042A', + Hacek: '\u02C7', + Hat: '\u005E', + Hcirc: '\u0124', + Hfr: '\u210C', + HilbertSpace: '\u210B', + Hopf: '\u210D', + HorizontalLine: '\u2500', + Hscr: '\u210B', + Hstrok: '\u0126', + HumpDownHump: '\u224E', + HumpEqual: '\u224F', + IEcy: '\u0415', + IJlig: '\u0132', + IOcy: '\u0401', + Iacute: '\u00CD', + Icirc: '\u00CE', + Icy: '\u0418', + Idot: '\u0130', + Ifr: '\u2111', + Igrave: '\u00CC', + Im: '\u2111', + Imacr: '\u012A', + ImaginaryI: '\u2148', + Implies: '\u21D2', + Int: '\u222C', + Integral: '\u222B', + Intersection: '\u22C2', + InvisibleComma: '\u2063', + InvisibleTimes: '\u2062', + Iogon: '\u012E', + Iopf: '\uD835\uDD40', + Iota: '\u0399', + Iscr: '\u2110', + Itilde: '\u0128', + Iukcy: '\u0406', + Iuml: '\u00CF', + Jcirc: '\u0134', + Jcy: '\u0419', + Jfr: '\uD835\uDD0D', + Jopf: '\uD835\uDD41', + Jscr: '\uD835\uDCA5', + Jsercy: '\u0408', + Jukcy: '\u0404', + KHcy: '\u0425', + KJcy: '\u040C', + Kappa: '\u039A', + Kcedil: '\u0136', + Kcy: '\u041A', + Kfr: '\uD835\uDD0E', + Kopf: '\uD835\uDD42', + Kscr: '\uD835\uDCA6', + LJcy: '\u0409', + LT: '\u003C', + Lacute: '\u0139', + Lambda: '\u039B', + Lang: '\u27EA', + Laplacetrf: '\u2112', + Larr: '\u219E', + Lcaron: '\u013D', + Lcedil: '\u013B', + Lcy: '\u041B', + LeftAngleBracket: '\u27E8', + LeftArrow: '\u2190', + LeftArrowBar: '\u21E4', + LeftArrowRightArrow: '\u21C6', + LeftCeiling: '\u2308', + LeftDoubleBracket: '\u27E6', + LeftDownTeeVector: '\u2961', + LeftDownVector: '\u21C3', + LeftDownVectorBar: '\u2959', + LeftFloor: '\u230A', + LeftRightArrow: '\u2194', + LeftRightVector: '\u294E', + LeftTee: '\u22A3', + LeftTeeArrow: '\u21A4', + LeftTeeVector: '\u295A', + LeftTriangle: '\u22B2', + LeftTriangleBar: '\u29CF', + LeftTriangleEqual: '\u22B4', + LeftUpDownVector: '\u2951', + LeftUpTeeVector: '\u2960', + LeftUpVector: '\u21BF', + LeftUpVectorBar: '\u2958', + LeftVector: '\u21BC', + LeftVectorBar: '\u2952', + Leftarrow: '\u21D0', + Leftrightarrow: '\u21D4', + LessEqualGreater: '\u22DA', + LessFullEqual: '\u2266', + LessGreater: '\u2276', + LessLess: '\u2AA1', + LessSlantEqual: '\u2A7D', + LessTilde: '\u2272', + Lfr: '\uD835\uDD0F', + Ll: '\u22D8', + Lleftarrow: '\u21DA', + Lmidot: '\u013F', + LongLeftArrow: '\u27F5', + LongLeftRightArrow: '\u27F7', + LongRightArrow: '\u27F6', + Longleftarrow: '\u27F8', + Longleftrightarrow: '\u27FA', + Longrightarrow: '\u27F9', + Lopf: '\uD835\uDD43', + LowerLeftArrow: '\u2199', + LowerRightArrow: '\u2198', + Lscr: '\u2112', + Lsh: '\u21B0', + Lstrok: '\u0141', + Lt: '\u226A', + Map: '\u2905', + Mcy: '\u041C', + MediumSpace: '\u205F', + Mellintrf: '\u2133', + Mfr: '\uD835\uDD10', + MinusPlus: '\u2213', + Mopf: '\uD835\uDD44', + Mscr: '\u2133', + Mu: '\u039C', + NJcy: '\u040A', + Nacute: '\u0143', + Ncaron: '\u0147', + Ncedil: '\u0145', + Ncy: '\u041D', + NegativeMediumSpace: '\u200B', + NegativeThickSpace: '\u200B', + NegativeThinSpace: '\u200B', + NegativeVeryThinSpace: '\u200B', + NestedGreaterGreater: '\u226B', + NestedLessLess: '\u226A', + NewLine: '\u000A', + Nfr: '\uD835\uDD11', + NoBreak: '\u2060', + NonBreakingSpace: '\u00A0', + Nopf: '\u2115', + Not: '\u2AEC', + NotCongruent: '\u2262', + NotCupCap: '\u226D', + NotDoubleVerticalBar: '\u2226', + NotElement: '\u2209', + NotEqual: '\u2260', + NotEqualTilde: '\u2242\u0338', + NotExists: '\u2204', + NotGreater: '\u226F', + NotGreaterEqual: '\u2271', + NotGreaterFullEqual: '\u2267\u0338', + NotGreaterGreater: '\u226B\u0338', + NotGreaterLess: '\u2279', + NotGreaterSlantEqual: '\u2A7E\u0338', + NotGreaterTilde: '\u2275', + NotHumpDownHump: '\u224E\u0338', + NotHumpEqual: '\u224F\u0338', + NotLeftTriangle: '\u22EA', + NotLeftTriangleBar: '\u29CF\u0338', + NotLeftTriangleEqual: '\u22EC', + NotLess: '\u226E', + NotLessEqual: '\u2270', + NotLessGreater: '\u2278', + NotLessLess: '\u226A\u0338', + NotLessSlantEqual: '\u2A7D\u0338', + NotLessTilde: '\u2274', + NotNestedGreaterGreater: '\u2AA2\u0338', + NotNestedLessLess: '\u2AA1\u0338', + NotPrecedes: '\u2280', + NotPrecedesEqual: '\u2AAF\u0338', + NotPrecedesSlantEqual: '\u22E0', + NotReverseElement: '\u220C', + NotRightTriangle: '\u22EB', + NotRightTriangleBar: '\u29D0\u0338', + NotRightTriangleEqual: '\u22ED', + NotSquareSubset: '\u228F\u0338', + NotSquareSubsetEqual: '\u22E2', + NotSquareSuperset: '\u2290\u0338', + NotSquareSupersetEqual: '\u22E3', + NotSubset: '\u2282\u20D2', + NotSubsetEqual: '\u2288', + NotSucceeds: '\u2281', + NotSucceedsEqual: '\u2AB0\u0338', + NotSucceedsSlantEqual: '\u22E1', + NotSucceedsTilde: '\u227F\u0338', + NotSuperset: '\u2283\u20D2', + NotSupersetEqual: '\u2289', + NotTilde: '\u2241', + NotTildeEqual: '\u2244', + NotTildeFullEqual: '\u2247', + NotTildeTilde: '\u2249', + NotVerticalBar: '\u2224', + Nscr: '\uD835\uDCA9', + Ntilde: '\u00D1', + Nu: '\u039D', + OElig: '\u0152', + Oacute: '\u00D3', + Ocirc: '\u00D4', + Ocy: '\u041E', + Odblac: '\u0150', + Ofr: '\uD835\uDD12', + Ograve: '\u00D2', + Omacr: '\u014C', + Omega: '\u03A9', + Omicron: '\u039F', + Oopf: '\uD835\uDD46', + OpenCurlyDoubleQuote: '\u201C', + OpenCurlyQuote: '\u2018', + Or: '\u2A54', + Oscr: '\uD835\uDCAA', + Oslash: '\u00D8', + Otilde: '\u00D5', + Otimes: '\u2A37', + Ouml: '\u00D6', + OverBar: '\u203E', + OverBrace: '\u23DE', + OverBracket: '\u23B4', + OverParenthesis: '\u23DC', + PartialD: '\u2202', + Pcy: '\u041F', + Pfr: '\uD835\uDD13', + Phi: '\u03A6', + Pi: '\u03A0', + PlusMinus: '\u00B1', + Poincareplane: '\u210C', + Popf: '\u2119', + Pr: '\u2ABB', + Precedes: '\u227A', + PrecedesEqual: '\u2AAF', + PrecedesSlantEqual: '\u227C', + PrecedesTilde: '\u227E', + Prime: '\u2033', + Product: '\u220F', + Proportion: '\u2237', + Proportional: '\u221D', + Pscr: '\uD835\uDCAB', + Psi: '\u03A8', + QUOT: '\u0022', + Qfr: '\uD835\uDD14', + Qopf: '\u211A', + Qscr: '\uD835\uDCAC', + RBarr: '\u2910', + REG: '\u00AE', + Racute: '\u0154', + Rang: '\u27EB', + Rarr: '\u21A0', + Rarrtl: '\u2916', + Rcaron: '\u0158', + Rcedil: '\u0156', + Rcy: '\u0420', + Re: '\u211C', + ReverseElement: '\u220B', + ReverseEquilibrium: '\u21CB', + ReverseUpEquilibrium: '\u296F', + Rfr: '\u211C', + Rho: '\u03A1', + RightAngleBracket: '\u27E9', + RightArrow: '\u2192', + RightArrowBar: '\u21E5', + RightArrowLeftArrow: '\u21C4', + RightCeiling: '\u2309', + RightDoubleBracket: '\u27E7', + RightDownTeeVector: '\u295D', + RightDownVector: '\u21C2', + RightDownVectorBar: '\u2955', + RightFloor: '\u230B', + RightTee: '\u22A2', + RightTeeArrow: '\u21A6', + RightTeeVector: '\u295B', + RightTriangle: '\u22B3', + RightTriangleBar: '\u29D0', + RightTriangleEqual: '\u22B5', + RightUpDownVector: '\u294F', + RightUpTeeVector: '\u295C', + RightUpVector: '\u21BE', + RightUpVectorBar: '\u2954', + RightVector: '\u21C0', + RightVectorBar: '\u2953', + Rightarrow: '\u21D2', + Ropf: '\u211D', + RoundImplies: '\u2970', + Rrightarrow: '\u21DB', + Rscr: '\u211B', + Rsh: '\u21B1', + RuleDelayed: '\u29F4', + SHCHcy: '\u0429', + SHcy: '\u0428', + SOFTcy: '\u042C', + Sacute: '\u015A', + Sc: '\u2ABC', + Scaron: '\u0160', + Scedil: '\u015E', + Scirc: '\u015C', + Scy: '\u0421', + Sfr: '\uD835\uDD16', + ShortDownArrow: '\u2193', + ShortLeftArrow: '\u2190', + ShortRightArrow: '\u2192', + ShortUpArrow: '\u2191', + Sigma: '\u03A3', + SmallCircle: '\u2218', + Sopf: '\uD835\uDD4A', + Sqrt: '\u221A', + Square: '\u25A1', + SquareIntersection: '\u2293', + SquareSubset: '\u228F', + SquareSubsetEqual: '\u2291', + SquareSuperset: '\u2290', + SquareSupersetEqual: '\u2292', + SquareUnion: '\u2294', + Sscr: '\uD835\uDCAE', + Star: '\u22C6', + Sub: '\u22D0', + Subset: '\u22D0', + SubsetEqual: '\u2286', + Succeeds: '\u227B', + SucceedsEqual: '\u2AB0', + SucceedsSlantEqual: '\u227D', + SucceedsTilde: '\u227F', + SuchThat: '\u220B', + Sum: '\u2211', + Sup: '\u22D1', + Superset: '\u2283', + SupersetEqual: '\u2287', + Supset: '\u22D1', + THORN: '\u00DE', + TRADE: '\u2122', + TSHcy: '\u040B', + TScy: '\u0426', + Tab: '\u0009', + Tau: '\u03A4', + Tcaron: '\u0164', + Tcedil: '\u0162', + Tcy: '\u0422', + Tfr: '\uD835\uDD17', + Therefore: '\u2234', + Theta: '\u0398', + ThickSpace: '\u205F\u200A', + ThinSpace: '\u2009', + Tilde: '\u223C', + TildeEqual: '\u2243', + TildeFullEqual: '\u2245', + TildeTilde: '\u2248', + Topf: '\uD835\uDD4B', + TripleDot: '\u20DB', + Tscr: '\uD835\uDCAF', + Tstrok: '\u0166', + Uacute: '\u00DA', + Uarr: '\u219F', + Uarrocir: '\u2949', + Ubrcy: '\u040E', + Ubreve: '\u016C', + Ucirc: '\u00DB', + Ucy: '\u0423', + Udblac: '\u0170', + Ufr: '\uD835\uDD18', + Ugrave: '\u00D9', + Umacr: '\u016A', + UnderBar: '\u005F', + UnderBrace: '\u23DF', + UnderBracket: '\u23B5', + UnderParenthesis: '\u23DD', + Union: '\u22C3', + UnionPlus: '\u228E', + Uogon: '\u0172', + Uopf: '\uD835\uDD4C', + UpArrow: '\u2191', + UpArrowBar: '\u2912', + UpArrowDownArrow: '\u21C5', + UpDownArrow: '\u2195', + UpEquilibrium: '\u296E', + UpTee: '\u22A5', + UpTeeArrow: '\u21A5', + Uparrow: '\u21D1', + Updownarrow: '\u21D5', + UpperLeftArrow: '\u2196', + UpperRightArrow: '\u2197', + Upsi: '\u03D2', + Upsilon: '\u03A5', + Uring: '\u016E', + Uscr: '\uD835\uDCB0', + Utilde: '\u0168', + Uuml: '\u00DC', + VDash: '\u22AB', + Vbar: '\u2AEB', + Vcy: '\u0412', + Vdash: '\u22A9', + Vdashl: '\u2AE6', + Vee: '\u22C1', + Verbar: '\u2016', + Vert: '\u2016', + VerticalBar: '\u2223', + VerticalLine: '\u007C', + VerticalSeparator: '\u2758', + VerticalTilde: '\u2240', + VeryThinSpace: '\u200A', + Vfr: '\uD835\uDD19', + Vopf: '\uD835\uDD4D', + Vscr: '\uD835\uDCB1', + Vvdash: '\u22AA', + Wcirc: '\u0174', + Wedge: '\u22C0', + Wfr: '\uD835\uDD1A', + Wopf: '\uD835\uDD4E', + Wscr: '\uD835\uDCB2', + Xfr: '\uD835\uDD1B', + Xi: '\u039E', + Xopf: '\uD835\uDD4F', + Xscr: '\uD835\uDCB3', + YAcy: '\u042F', + YIcy: '\u0407', + YUcy: '\u042E', + Yacute: '\u00DD', + Ycirc: '\u0176', + Ycy: '\u042B', + Yfr: '\uD835\uDD1C', + Yopf: '\uD835\uDD50', + Yscr: '\uD835\uDCB4', + Yuml: '\u0178', + ZHcy: '\u0416', + Zacute: '\u0179', + Zcaron: '\u017D', + Zcy: '\u0417', + Zdot: '\u017B', + ZeroWidthSpace: '\u200B', + Zeta: '\u0396', + Zfr: '\u2128', + Zopf: '\u2124', + Zscr: '\uD835\uDCB5', + aacute: '\u00E1', + abreve: '\u0103', + ac: '\u223E', + acE: '\u223E\u0333', + acd: '\u223F', + acirc: '\u00E2', + acute: '\u00B4', + acy: '\u0430', + aelig: '\u00E6', + af: '\u2061', + afr: '\uD835\uDD1E', + agrave: '\u00E0', + alefsym: '\u2135', + aleph: '\u2135', + alpha: '\u03B1', + amacr: '\u0101', + amalg: '\u2A3F', + amp: '\u0026', + and: '\u2227', + andand: '\u2A55', + andd: '\u2A5C', + andslope: '\u2A58', + andv: '\u2A5A', + ang: '\u2220', + ange: '\u29A4', + angle: '\u2220', + angmsd: '\u2221', + angmsdaa: '\u29A8', + angmsdab: '\u29A9', + angmsdac: '\u29AA', + angmsdad: '\u29AB', + angmsdae: '\u29AC', + angmsdaf: '\u29AD', + angmsdag: '\u29AE', + angmsdah: '\u29AF', + angrt: '\u221F', + angrtvb: '\u22BE', + angrtvbd: '\u299D', + angsph: '\u2222', + angst: '\u00C5', + angzarr: '\u237C', + aogon: '\u0105', + aopf: '\uD835\uDD52', + ap: '\u2248', + apE: '\u2A70', + apacir: '\u2A6F', + ape: '\u224A', + apid: '\u224B', + apos: '\u0027', + approx: '\u2248', + approxeq: '\u224A', + aring: '\u00E5', + ascr: '\uD835\uDCB6', + ast: '\u002A', + asymp: '\u2248', + asympeq: '\u224D', + atilde: '\u00E3', + auml: '\u00E4', + awconint: '\u2233', + awint: '\u2A11', + bNot: '\u2AED', + backcong: '\u224C', + backepsilon: '\u03F6', + backprime: '\u2035', + backsim: '\u223D', + backsimeq: '\u22CD', + barvee: '\u22BD', + barwed: '\u2305', + barwedge: '\u2305', + bbrk: '\u23B5', + bbrktbrk: '\u23B6', + bcong: '\u224C', + bcy: '\u0431', + bdquo: '\u201E', + becaus: '\u2235', + because: '\u2235', + bemptyv: '\u29B0', + bepsi: '\u03F6', + bernou: '\u212C', + beta: '\u03B2', + beth: '\u2136', + between: '\u226C', + bfr: '\uD835\uDD1F', + bigcap: '\u22C2', + bigcirc: '\u25EF', + bigcup: '\u22C3', + bigodot: '\u2A00', + bigoplus: '\u2A01', + bigotimes: '\u2A02', + bigsqcup: '\u2A06', + bigstar: '\u2605', + bigtriangledown: '\u25BD', + bigtriangleup: '\u25B3', + biguplus: '\u2A04', + bigvee: '\u22C1', + bigwedge: '\u22C0', + bkarow: '\u290D', + blacklozenge: '\u29EB', + blacksquare: '\u25AA', + blacktriangle: '\u25B4', + blacktriangledown: '\u25BE', + blacktriangleleft: '\u25C2', + blacktriangleright: '\u25B8', + blank: '\u2423', + blk12: '\u2592', + blk14: '\u2591', + blk34: '\u2593', + block: '\u2588', + bne: '\u003D\u20E5', + bnequiv: '\u2261\u20E5', + bnot: '\u2310', + bopf: '\uD835\uDD53', + bot: '\u22A5', + bottom: '\u22A5', + bowtie: '\u22C8', + boxDL: '\u2557', + boxDR: '\u2554', + boxDl: '\u2556', + boxDr: '\u2553', + boxH: '\u2550', + boxHD: '\u2566', + boxHU: '\u2569', + boxHd: '\u2564', + boxHu: '\u2567', + boxUL: '\u255D', + boxUR: '\u255A', + boxUl: '\u255C', + boxUr: '\u2559', + boxV: '\u2551', + boxVH: '\u256C', + boxVL: '\u2563', + boxVR: '\u2560', + boxVh: '\u256B', + boxVl: '\u2562', + boxVr: '\u255F', + boxbox: '\u29C9', + boxdL: '\u2555', + boxdR: '\u2552', + boxdl: '\u2510', + boxdr: '\u250C', + boxh: '\u2500', + boxhD: '\u2565', + boxhU: '\u2568', + boxhd: '\u252C', + boxhu: '\u2534', + boxminus: '\u229F', + boxplus: '\u229E', + boxtimes: '\u22A0', + boxuL: '\u255B', + boxuR: '\u2558', + boxul: '\u2518', + boxur: '\u2514', + boxv: '\u2502', + boxvH: '\u256A', + boxvL: '\u2561', + boxvR: '\u255E', + boxvh: '\u253C', + boxvl: '\u2524', + boxvr: '\u251C', + bprime: '\u2035', + breve: '\u02D8', + brvbar: '\u00A6', + bscr: '\uD835\uDCB7', + bsemi: '\u204F', + bsim: '\u223D', + bsime: '\u22CD', + bsol: '\u005C', + bsolb: '\u29C5', + bsolhsub: '\u27C8', + bull: '\u2022', + bullet: '\u2022', + bump: '\u224E', + bumpE: '\u2AAE', + bumpe: '\u224F', + bumpeq: '\u224F', + cacute: '\u0107', + cap: '\u2229', + capand: '\u2A44', + capbrcup: '\u2A49', + capcap: '\u2A4B', + capcup: '\u2A47', + capdot: '\u2A40', + caps: '\u2229\uFE00', + caret: '\u2041', + caron: '\u02C7', + ccaps: '\u2A4D', + ccaron: '\u010D', + ccedil: '\u00E7', + ccirc: '\u0109', + ccups: '\u2A4C', + ccupssm: '\u2A50', + cdot: '\u010B', + cedil: '\u00B8', + cemptyv: '\u29B2', + cent: '\u00A2', + centerdot: '\u00B7', + cfr: '\uD835\uDD20', + chcy: '\u0447', + check: '\u2713', + checkmark: '\u2713', + chi: '\u03C7', + cir: '\u25CB', + cirE: '\u29C3', + circ: '\u02C6', + circeq: '\u2257', + circlearrowleft: '\u21BA', + circlearrowright: '\u21BB', + circledR: '\u00AE', + circledS: '\u24C8', + circledast: '\u229B', + circledcirc: '\u229A', + circleddash: '\u229D', + cire: '\u2257', + cirfnint: '\u2A10', + cirmid: '\u2AEF', + cirscir: '\u29C2', + clubs: '\u2663', + clubsuit: '\u2663', + colon: '\u003A', + colone: '\u2254', + coloneq: '\u2254', + comma: '\u002C', + commat: '\u0040', + comp: '\u2201', + compfn: '\u2218', + complement: '\u2201', + complexes: '\u2102', + cong: '\u2245', + congdot: '\u2A6D', + conint: '\u222E', + copf: '\uD835\uDD54', + coprod: '\u2210', + copy: '\u00A9', + copysr: '\u2117', + crarr: '\u21B5', + cross: '\u2717', + cscr: '\uD835\uDCB8', + csub: '\u2ACF', + csube: '\u2AD1', + csup: '\u2AD0', + csupe: '\u2AD2', + ctdot: '\u22EF', + cudarrl: '\u2938', + cudarrr: '\u2935', + cuepr: '\u22DE', + cuesc: '\u22DF', + cularr: '\u21B6', + cularrp: '\u293D', + cup: '\u222A', + cupbrcap: '\u2A48', + cupcap: '\u2A46', + cupcup: '\u2A4A', + cupdot: '\u228D', + cupor: '\u2A45', + cups: '\u222A\uFE00', + curarr: '\u21B7', + curarrm: '\u293C', + curlyeqprec: '\u22DE', + curlyeqsucc: '\u22DF', + curlyvee: '\u22CE', + curlywedge: '\u22CF', + curren: '\u00A4', + curvearrowleft: '\u21B6', + curvearrowright: '\u21B7', + cuvee: '\u22CE', + cuwed: '\u22CF', + cwconint: '\u2232', + cwint: '\u2231', + cylcty: '\u232D', + dArr: '\u21D3', + dHar: '\u2965', + dagger: '\u2020', + daleth: '\u2138', + darr: '\u2193', + dash: '\u2010', + dashv: '\u22A3', + dbkarow: '\u290F', + dblac: '\u02DD', + dcaron: '\u010F', + dcy: '\u0434', + dd: '\u2146', + ddagger: '\u2021', + ddarr: '\u21CA', + ddotseq: '\u2A77', + deg: '\u00B0', + delta: '\u03B4', + demptyv: '\u29B1', + dfisht: '\u297F', + dfr: '\uD835\uDD21', + dharl: '\u21C3', + dharr: '\u21C2', + diam: '\u22C4', + diamond: '\u22C4', + diamondsuit: '\u2666', + diams: '\u2666', + die: '\u00A8', + digamma: '\u03DD', + disin: '\u22F2', + div: '\u00F7', + divide: '\u00F7', + divideontimes: '\u22C7', + divonx: '\u22C7', + djcy: '\u0452', + dlcorn: '\u231E', + dlcrop: '\u230D', + dollar: '\u0024', + dopf: '\uD835\uDD55', + dot: '\u02D9', + doteq: '\u2250', + doteqdot: '\u2251', + dotminus: '\u2238', + dotplus: '\u2214', + dotsquare: '\u22A1', + doublebarwedge: '\u2306', + downarrow: '\u2193', + downdownarrows: '\u21CA', + downharpoonleft: '\u21C3', + downharpoonright: '\u21C2', + drbkarow: '\u2910', + drcorn: '\u231F', + drcrop: '\u230C', + dscr: '\uD835\uDCB9', + dscy: '\u0455', + dsol: '\u29F6', + dstrok: '\u0111', + dtdot: '\u22F1', + dtri: '\u25BF', + dtrif: '\u25BE', + duarr: '\u21F5', + duhar: '\u296F', + dwangle: '\u29A6', + dzcy: '\u045F', + dzigrarr: '\u27FF', + eDDot: '\u2A77', + eDot: '\u2251', + eacute: '\u00E9', + easter: '\u2A6E', + ecaron: '\u011B', + ecir: '\u2256', + ecirc: '\u00EA', + ecolon: '\u2255', + ecy: '\u044D', + edot: '\u0117', + ee: '\u2147', + efDot: '\u2252', + efr: '\uD835\uDD22', + eg: '\u2A9A', + egrave: '\u00E8', + egs: '\u2A96', + egsdot: '\u2A98', + el: '\u2A99', + elinters: '\u23E7', + ell: '\u2113', + els: '\u2A95', + elsdot: '\u2A97', + emacr: '\u0113', + empty: '\u2205', + emptyset: '\u2205', + emptyv: '\u2205', + emsp13: '\u2004', + emsp14: '\u2005', + emsp: '\u2003', + eng: '\u014B', + ensp: '\u2002', + eogon: '\u0119', + eopf: '\uD835\uDD56', + epar: '\u22D5', + eparsl: '\u29E3', + eplus: '\u2A71', + epsi: '\u03B5', + epsilon: '\u03B5', + epsiv: '\u03F5', + eqcirc: '\u2256', + eqcolon: '\u2255', + eqsim: '\u2242', + eqslantgtr: '\u2A96', + eqslantless: '\u2A95', + equals: '\u003D', + equest: '\u225F', + equiv: '\u2261', + equivDD: '\u2A78', + eqvparsl: '\u29E5', + erDot: '\u2253', + erarr: '\u2971', + escr: '\u212F', + esdot: '\u2250', + esim: '\u2242', + eta: '\u03B7', + eth: '\u00F0', + euml: '\u00EB', + euro: '\u20AC', + excl: '\u0021', + exist: '\u2203', + expectation: '\u2130', + exponentiale: '\u2147', + fallingdotseq: '\u2252', + fcy: '\u0444', + female: '\u2640', + ffilig: '\uFB03', + fflig: '\uFB00', + ffllig: '\uFB04', + ffr: '\uD835\uDD23', + filig: '\uFB01', + fjlig: '\u0066\u006A', + flat: '\u266D', + fllig: '\uFB02', + fltns: '\u25B1', + fnof: '\u0192', + fopf: '\uD835\uDD57', + forall: '\u2200', + fork: '\u22D4', + forkv: '\u2AD9', + fpartint: '\u2A0D', + frac12: '\u00BD', + frac13: '\u2153', + frac14: '\u00BC', + frac15: '\u2155', + frac16: '\u2159', + frac18: '\u215B', + frac23: '\u2154', + frac25: '\u2156', + frac34: '\u00BE', + frac35: '\u2157', + frac38: '\u215C', + frac45: '\u2158', + frac56: '\u215A', + frac58: '\u215D', + frac78: '\u215E', + frasl: '\u2044', + frown: '\u2322', + fscr: '\uD835\uDCBB', + gE: '\u2267', + gEl: '\u2A8C', + gacute: '\u01F5', + gamma: '\u03B3', + gammad: '\u03DD', + gap: '\u2A86', + gbreve: '\u011F', + gcirc: '\u011D', + gcy: '\u0433', + gdot: '\u0121', + ge: '\u2265', + gel: '\u22DB', + geq: '\u2265', + geqq: '\u2267', + geqslant: '\u2A7E', + ges: '\u2A7E', + gescc: '\u2AA9', + gesdot: '\u2A80', + gesdoto: '\u2A82', + gesdotol: '\u2A84', + gesl: '\u22DB\uFE00', + gesles: '\u2A94', + gfr: '\uD835\uDD24', + gg: '\u226B', + ggg: '\u22D9', + gimel: '\u2137', + gjcy: '\u0453', + gl: '\u2277', + glE: '\u2A92', + gla: '\u2AA5', + glj: '\u2AA4', + gnE: '\u2269', + gnap: '\u2A8A', + gnapprox: '\u2A8A', + gne: '\u2A88', + gneq: '\u2A88', + gneqq: '\u2269', + gnsim: '\u22E7', + gopf: '\uD835\uDD58', + grave: '\u0060', + gscr: '\u210A', + gsim: '\u2273', + gsime: '\u2A8E', + gsiml: '\u2A90', + gt: '\u003E', + gtcc: '\u2AA7', + gtcir: '\u2A7A', + gtdot: '\u22D7', + gtlPar: '\u2995', + gtquest: '\u2A7C', + gtrapprox: '\u2A86', + gtrarr: '\u2978', + gtrdot: '\u22D7', + gtreqless: '\u22DB', + gtreqqless: '\u2A8C', + gtrless: '\u2277', + gtrsim: '\u2273', + gvertneqq: '\u2269\uFE00', + gvnE: '\u2269\uFE00', + hArr: '\u21D4', + hairsp: '\u200A', + half: '\u00BD', + hamilt: '\u210B', + hardcy: '\u044A', + harr: '\u2194', + harrcir: '\u2948', + harrw: '\u21AD', + hbar: '\u210F', + hcirc: '\u0125', + hearts: '\u2665', + heartsuit: '\u2665', + hellip: '\u2026', + hercon: '\u22B9', + hfr: '\uD835\uDD25', + hksearow: '\u2925', + hkswarow: '\u2926', + hoarr: '\u21FF', + homtht: '\u223B', + hookleftarrow: '\u21A9', + hookrightarrow: '\u21AA', + hopf: '\uD835\uDD59', + horbar: '\u2015', + hscr: '\uD835\uDCBD', + hslash: '\u210F', + hstrok: '\u0127', + hybull: '\u2043', + hyphen: '\u2010', + iacute: '\u00ED', + ic: '\u2063', + icirc: '\u00EE', + icy: '\u0438', + iecy: '\u0435', + iexcl: '\u00A1', + iff: '\u21D4', + ifr: '\uD835\uDD26', + igrave: '\u00EC', + ii: '\u2148', + iiiint: '\u2A0C', + iiint: '\u222D', + iinfin: '\u29DC', + iiota: '\u2129', + ijlig: '\u0133', + imacr: '\u012B', + image: '\u2111', + imagline: '\u2110', + imagpart: '\u2111', + imath: '\u0131', + imof: '\u22B7', + imped: '\u01B5', + in: '\u2208', + incare: '\u2105', + infin: '\u221E', + infintie: '\u29DD', + inodot: '\u0131', + int: '\u222B', + intcal: '\u22BA', + integers: '\u2124', + intercal: '\u22BA', + intlarhk: '\u2A17', + intprod: '\u2A3C', + iocy: '\u0451', + iogon: '\u012F', + iopf: '\uD835\uDD5A', + iota: '\u03B9', + iprod: '\u2A3C', + iquest: '\u00BF', + iscr: '\uD835\uDCBE', + isin: '\u2208', + isinE: '\u22F9', + isindot: '\u22F5', + isins: '\u22F4', + isinsv: '\u22F3', + isinv: '\u2208', + it: '\u2062', + itilde: '\u0129', + iukcy: '\u0456', + iuml: '\u00EF', + jcirc: '\u0135', + jcy: '\u0439', + jfr: '\uD835\uDD27', + jmath: '\u0237', + jopf: '\uD835\uDD5B', + jscr: '\uD835\uDCBF', + jsercy: '\u0458', + jukcy: '\u0454', + kappa: '\u03BA', + kappav: '\u03F0', + kcedil: '\u0137', + kcy: '\u043A', + kfr: '\uD835\uDD28', + kgreen: '\u0138', + khcy: '\u0445', + kjcy: '\u045C', + kopf: '\uD835\uDD5C', + kscr: '\uD835\uDCC0', + lAarr: '\u21DA', + lArr: '\u21D0', + lAtail: '\u291B', + lBarr: '\u290E', + lE: '\u2266', + lEg: '\u2A8B', + lHar: '\u2962', + lacute: '\u013A', + laemptyv: '\u29B4', + lagran: '\u2112', + lambda: '\u03BB', + lang: '\u27E8', + langd: '\u2991', + langle: '\u27E8', + lap: '\u2A85', + laquo: '\u00AB', + larr: '\u2190', + larrb: '\u21E4', + larrbfs: '\u291F', + larrfs: '\u291D', + larrhk: '\u21A9', + larrlp: '\u21AB', + larrpl: '\u2939', + larrsim: '\u2973', + larrtl: '\u21A2', + lat: '\u2AAB', + latail: '\u2919', + late: '\u2AAD', + lates: '\u2AAD\uFE00', + lbarr: '\u290C', + lbbrk: '\u2772', + lbrace: '\u007B', + lbrack: '\u005B', + lbrke: '\u298B', + lbrksld: '\u298F', + lbrkslu: '\u298D', + lcaron: '\u013E', + lcedil: '\u013C', + lceil: '\u2308', + lcub: '\u007B', + lcy: '\u043B', + ldca: '\u2936', + ldquo: '\u201C', + ldquor: '\u201E', + ldrdhar: '\u2967', + ldrushar: '\u294B', + ldsh: '\u21B2', + le: '\u2264', + leftarrow: '\u2190', + leftarrowtail: '\u21A2', + leftharpoondown: '\u21BD', + leftharpoonup: '\u21BC', + leftleftarrows: '\u21C7', + leftrightarrow: '\u2194', + leftrightarrows: '\u21C6', + leftrightharpoons: '\u21CB', + leftrightsquigarrow: '\u21AD', + leftthreetimes: '\u22CB', + leg: '\u22DA', + leq: '\u2264', + leqq: '\u2266', + leqslant: '\u2A7D', + les: '\u2A7D', + lescc: '\u2AA8', + lesdot: '\u2A7F', + lesdoto: '\u2A81', + lesdotor: '\u2A83', + lesg: '\u22DA\uFE00', + lesges: '\u2A93', + lessapprox: '\u2A85', + lessdot: '\u22D6', + lesseqgtr: '\u22DA', + lesseqqgtr: '\u2A8B', + lessgtr: '\u2276', + lesssim: '\u2272', + lfisht: '\u297C', + lfloor: '\u230A', + lfr: '\uD835\uDD29', + lg: '\u2276', + lgE: '\u2A91', + lhard: '\u21BD', + lharu: '\u21BC', + lharul: '\u296A', + lhblk: '\u2584', + ljcy: '\u0459', + ll: '\u226A', + llarr: '\u21C7', + llcorner: '\u231E', + llhard: '\u296B', + lltri: '\u25FA', + lmidot: '\u0140', + lmoust: '\u23B0', + lmoustache: '\u23B0', + lnE: '\u2268', + lnap: '\u2A89', + lnapprox: '\u2A89', + lne: '\u2A87', + lneq: '\u2A87', + lneqq: '\u2268', + lnsim: '\u22E6', + loang: '\u27EC', + loarr: '\u21FD', + lobrk: '\u27E6', + longleftarrow: '\u27F5', + longleftrightarrow: '\u27F7', + longmapsto: '\u27FC', + longrightarrow: '\u27F6', + looparrowleft: '\u21AB', + looparrowright: '\u21AC', + lopar: '\u2985', + lopf: '\uD835\uDD5D', + loplus: '\u2A2D', + lotimes: '\u2A34', + lowast: '\u2217', + lowbar: '\u005F', + loz: '\u25CA', + lozenge: '\u25CA', + lozf: '\u29EB', + lpar: '\u0028', + lparlt: '\u2993', + lrarr: '\u21C6', + lrcorner: '\u231F', + lrhar: '\u21CB', + lrhard: '\u296D', + lrm: '\u200E', + lrtri: '\u22BF', + lsaquo: '\u2039', + lscr: '\uD835\uDCC1', + lsh: '\u21B0', + lsim: '\u2272', + lsime: '\u2A8D', + lsimg: '\u2A8F', + lsqb: '\u005B', + lsquo: '\u2018', + lsquor: '\u201A', + lstrok: '\u0142', + lt: '\u003C', + ltcc: '\u2AA6', + ltcir: '\u2A79', + ltdot: '\u22D6', + lthree: '\u22CB', + ltimes: '\u22C9', + ltlarr: '\u2976', + ltquest: '\u2A7B', + ltrPar: '\u2996', + ltri: '\u25C3', + ltrie: '\u22B4', + ltrif: '\u25C2', + lurdshar: '\u294A', + luruhar: '\u2966', + lvertneqq: '\u2268\uFE00', + lvnE: '\u2268\uFE00', + mDDot: '\u223A', + macr: '\u00AF', + male: '\u2642', + malt: '\u2720', + maltese: '\u2720', + map: '\u21A6', + mapsto: '\u21A6', + mapstodown: '\u21A7', + mapstoleft: '\u21A4', + mapstoup: '\u21A5', + marker: '\u25AE', + mcomma: '\u2A29', + mcy: '\u043C', + mdash: '\u2014', + measuredangle: '\u2221', + mfr: '\uD835\uDD2A', + mho: '\u2127', + micro: '\u00B5', + mid: '\u2223', + midast: '\u002A', + midcir: '\u2AF0', + middot: '\u00B7', + minus: '\u2212', + minusb: '\u229F', + minusd: '\u2238', + minusdu: '\u2A2A', + mlcp: '\u2ADB', + mldr: '\u2026', + mnplus: '\u2213', + models: '\u22A7', + mopf: '\uD835\uDD5E', + mp: '\u2213', + mscr: '\uD835\uDCC2', + mstpos: '\u223E', + mu: '\u03BC', + multimap: '\u22B8', + mumap: '\u22B8', + nGg: '\u22D9\u0338', + nGt: '\u226B\u20D2', + nGtv: '\u226B\u0338', + nLeftarrow: '\u21CD', + nLeftrightarrow: '\u21CE', + nLl: '\u22D8\u0338', + nLt: '\u226A\u20D2', + nLtv: '\u226A\u0338', + nRightarrow: '\u21CF', + nVDash: '\u22AF', + nVdash: '\u22AE', + nabla: '\u2207', + nacute: '\u0144', + nang: '\u2220\u20D2', + nap: '\u2249', + napE: '\u2A70\u0338', + napid: '\u224B\u0338', + napos: '\u0149', + napprox: '\u2249', + natur: '\u266E', + natural: '\u266E', + naturals: '\u2115', + nbsp: '\u00A0', + nbump: '\u224E\u0338', + nbumpe: '\u224F\u0338', + ncap: '\u2A43', + ncaron: '\u0148', + ncedil: '\u0146', + ncong: '\u2247', + ncongdot: '\u2A6D\u0338', + ncup: '\u2A42', + ncy: '\u043D', + ndash: '\u2013', + ne: '\u2260', + neArr: '\u21D7', + nearhk: '\u2924', + nearr: '\u2197', + nearrow: '\u2197', + nedot: '\u2250\u0338', + nequiv: '\u2262', + nesear: '\u2928', + nesim: '\u2242\u0338', + nexist: '\u2204', + nexists: '\u2204', + nfr: '\uD835\uDD2B', + ngE: '\u2267\u0338', + nge: '\u2271', + ngeq: '\u2271', + ngeqq: '\u2267\u0338', + ngeqslant: '\u2A7E\u0338', + nges: '\u2A7E\u0338', + ngsim: '\u2275', + ngt: '\u226F', + ngtr: '\u226F', + nhArr: '\u21CE', + nharr: '\u21AE', + nhpar: '\u2AF2', + ni: '\u220B', + nis: '\u22FC', + nisd: '\u22FA', + niv: '\u220B', + njcy: '\u045A', + nlArr: '\u21CD', + nlE: '\u2266\u0338', + nlarr: '\u219A', + nldr: '\u2025', + nle: '\u2270', + nleftarrow: '\u219A', + nleftrightarrow: '\u21AE', + nleq: '\u2270', + nleqq: '\u2266\u0338', + nleqslant: '\u2A7D\u0338', + nles: '\u2A7D\u0338', + nless: '\u226E', + nlsim: '\u2274', + nlt: '\u226E', + nltri: '\u22EA', + nltrie: '\u22EC', + nmid: '\u2224', + nopf: '\uD835\uDD5F', + not: '\u00AC', + notin: '\u2209', + notinE: '\u22F9\u0338', + notindot: '\u22F5\u0338', + notinva: '\u2209', + notinvb: '\u22F7', + notinvc: '\u22F6', + notni: '\u220C', + notniva: '\u220C', + notnivb: '\u22FE', + notnivc: '\u22FD', + npar: '\u2226', + nparallel: '\u2226', + nparsl: '\u2AFD\u20E5', + npart: '\u2202\u0338', + npolint: '\u2A14', + npr: '\u2280', + nprcue: '\u22E0', + npre: '\u2AAF\u0338', + nprec: '\u2280', + npreceq: '\u2AAF\u0338', + nrArr: '\u21CF', + nrarr: '\u219B', + nrarrc: '\u2933\u0338', + nrarrw: '\u219D\u0338', + nrightarrow: '\u219B', + nrtri: '\u22EB', + nrtrie: '\u22ED', + nsc: '\u2281', + nsccue: '\u22E1', + nsce: '\u2AB0\u0338', + nscr: '\uD835\uDCC3', + nshortmid: '\u2224', + nshortparallel: '\u2226', + nsim: '\u2241', + nsime: '\u2244', + nsimeq: '\u2244', + nsmid: '\u2224', + nspar: '\u2226', + nsqsube: '\u22E2', + nsqsupe: '\u22E3', + nsub: '\u2284', + nsubE: '\u2AC5\u0338', + nsube: '\u2288', + nsubset: '\u2282\u20D2', + nsubseteq: '\u2288', + nsubseteqq: '\u2AC5\u0338', + nsucc: '\u2281', + nsucceq: '\u2AB0\u0338', + nsup: '\u2285', + nsupE: '\u2AC6\u0338', + nsupe: '\u2289', + nsupset: '\u2283\u20D2', + nsupseteq: '\u2289', + nsupseteqq: '\u2AC6\u0338', + ntgl: '\u2279', + ntilde: '\u00F1', + ntlg: '\u2278', + ntriangleleft: '\u22EA', + ntrianglelefteq: '\u22EC', + ntriangleright: '\u22EB', + ntrianglerighteq: '\u22ED', + nu: '\u03BD', + num: '\u0023', + numero: '\u2116', + numsp: '\u2007', + nvDash: '\u22AD', + nvHarr: '\u2904', + nvap: '\u224D\u20D2', + nvdash: '\u22AC', + nvge: '\u2265\u20D2', + nvgt: '\u003E\u20D2', + nvinfin: '\u29DE', + nvlArr: '\u2902', + nvle: '\u2264\u20D2', + nvlt: '\u003C\u20D2', + nvltrie: '\u22B4\u20D2', + nvrArr: '\u2903', + nvrtrie: '\u22B5\u20D2', + nvsim: '\u223C\u20D2', + nwArr: '\u21D6', + nwarhk: '\u2923', + nwarr: '\u2196', + nwarrow: '\u2196', + nwnear: '\u2927', + oS: '\u24C8', + oacute: '\u00F3', + oast: '\u229B', + ocir: '\u229A', + ocirc: '\u00F4', + ocy: '\u043E', + odash: '\u229D', + odblac: '\u0151', + odiv: '\u2A38', + odot: '\u2299', + odsold: '\u29BC', + oelig: '\u0153', + ofcir: '\u29BF', + ofr: '\uD835\uDD2C', + ogon: '\u02DB', + ograve: '\u00F2', + ogt: '\u29C1', + ohbar: '\u29B5', + ohm: '\u03A9', + oint: '\u222E', + olarr: '\u21BA', + olcir: '\u29BE', + olcross: '\u29BB', + oline: '\u203E', + olt: '\u29C0', + omacr: '\u014D', + omega: '\u03C9', + omicron: '\u03BF', + omid: '\u29B6', + ominus: '\u2296', + oopf: '\uD835\uDD60', + opar: '\u29B7', + operp: '\u29B9', + oplus: '\u2295', + or: '\u2228', + orarr: '\u21BB', + ord: '\u2A5D', + order: '\u2134', + orderof: '\u2134', + ordf: '\u00AA', + ordm: '\u00BA', + origof: '\u22B6', + oror: '\u2A56', + orslope: '\u2A57', + orv: '\u2A5B', + oscr: '\u2134', + oslash: '\u00F8', + osol: '\u2298', + otilde: '\u00F5', + otimes: '\u2297', + otimesas: '\u2A36', + ouml: '\u00F6', + ovbar: '\u233D', + par: '\u2225', + para: '\u00B6', + parallel: '\u2225', + parsim: '\u2AF3', + parsl: '\u2AFD', + part: '\u2202', + pcy: '\u043F', + percnt: '\u0025', + period: '\u002E', + permil: '\u2030', + perp: '\u22A5', + pertenk: '\u2031', + pfr: '\uD835\uDD2D', + phi: '\u03C6', + phiv: '\u03D5', + phmmat: '\u2133', + phone: '\u260E', + pi: '\u03C0', + pitchfork: '\u22D4', + piv: '\u03D6', + planck: '\u210F', + planckh: '\u210E', + plankv: '\u210F', + plus: '\u002B', + plusacir: '\u2A23', + plusb: '\u229E', + pluscir: '\u2A22', + plusdo: '\u2214', + plusdu: '\u2A25', + pluse: '\u2A72', + plusmn: '\u00B1', + plussim: '\u2A26', + plustwo: '\u2A27', + pm: '\u00B1', + pointint: '\u2A15', + popf: '\uD835\uDD61', + pound: '\u00A3', + pr: '\u227A', + prE: '\u2AB3', + prap: '\u2AB7', + prcue: '\u227C', + pre: '\u2AAF', + prec: '\u227A', + precapprox: '\u2AB7', + preccurlyeq: '\u227C', + preceq: '\u2AAF', + precnapprox: '\u2AB9', + precneqq: '\u2AB5', + precnsim: '\u22E8', + precsim: '\u227E', + prime: '\u2032', + primes: '\u2119', + prnE: '\u2AB5', + prnap: '\u2AB9', + prnsim: '\u22E8', + prod: '\u220F', + profalar: '\u232E', + profline: '\u2312', + profsurf: '\u2313', + prop: '\u221D', + propto: '\u221D', + prsim: '\u227E', + prurel: '\u22B0', + pscr: '\uD835\uDCC5', + psi: '\u03C8', + puncsp: '\u2008', + qfr: '\uD835\uDD2E', + qint: '\u2A0C', + qopf: '\uD835\uDD62', + qprime: '\u2057', + qscr: '\uD835\uDCC6', + quaternions: '\u210D', + quatint: '\u2A16', + quest: '\u003F', + questeq: '\u225F', + quot: '\u0022', + rAarr: '\u21DB', + rArr: '\u21D2', + rAtail: '\u291C', + rBarr: '\u290F', + rHar: '\u2964', + race: '\u223D\u0331', + racute: '\u0155', + radic: '\u221A', + raemptyv: '\u29B3', + rang: '\u27E9', + rangd: '\u2992', + range: '\u29A5', + rangle: '\u27E9', + raquo: '\u00BB', + rarr: '\u2192', + rarrap: '\u2975', + rarrb: '\u21E5', + rarrbfs: '\u2920', + rarrc: '\u2933', + rarrfs: '\u291E', + rarrhk: '\u21AA', + rarrlp: '\u21AC', + rarrpl: '\u2945', + rarrsim: '\u2974', + rarrtl: '\u21A3', + rarrw: '\u219D', + ratail: '\u291A', + ratio: '\u2236', + rationals: '\u211A', + rbarr: '\u290D', + rbbrk: '\u2773', + rbrace: '\u007D', + rbrack: '\u005D', + rbrke: '\u298C', + rbrksld: '\u298E', + rbrkslu: '\u2990', + rcaron: '\u0159', + rcedil: '\u0157', + rceil: '\u2309', + rcub: '\u007D', + rcy: '\u0440', + rdca: '\u2937', + rdldhar: '\u2969', + rdquo: '\u201D', + rdquor: '\u201D', + rdsh: '\u21B3', + real: '\u211C', + realine: '\u211B', + realpart: '\u211C', + reals: '\u211D', + rect: '\u25AD', + reg: '\u00AE', + rfisht: '\u297D', + rfloor: '\u230B', + rfr: '\uD835\uDD2F', + rhard: '\u21C1', + rharu: '\u21C0', + rharul: '\u296C', + rho: '\u03C1', + rhov: '\u03F1', + rightarrow: '\u2192', + rightarrowtail: '\u21A3', + rightharpoondown: '\u21C1', + rightharpoonup: '\u21C0', + rightleftarrows: '\u21C4', + rightleftharpoons: '\u21CC', + rightrightarrows: '\u21C9', + rightsquigarrow: '\u219D', + rightthreetimes: '\u22CC', + ring: '\u02DA', + risingdotseq: '\u2253', + rlarr: '\u21C4', + rlhar: '\u21CC', + rlm: '\u200F', + rmoust: '\u23B1', + rmoustache: '\u23B1', + rnmid: '\u2AEE', + roang: '\u27ED', + roarr: '\u21FE', + robrk: '\u27E7', + ropar: '\u2986', + ropf: '\uD835\uDD63', + roplus: '\u2A2E', + rotimes: '\u2A35', + rpar: '\u0029', + rpargt: '\u2994', + rppolint: '\u2A12', + rrarr: '\u21C9', + rsaquo: '\u203A', + rscr: '\uD835\uDCC7', + rsh: '\u21B1', + rsqb: '\u005D', + rsquo: '\u2019', + rsquor: '\u2019', + rthree: '\u22CC', + rtimes: '\u22CA', + rtri: '\u25B9', + rtrie: '\u22B5', + rtrif: '\u25B8', + rtriltri: '\u29CE', + ruluhar: '\u2968', + rx: '\u211E', + sacute: '\u015B', + sbquo: '\u201A', + sc: '\u227B', + scE: '\u2AB4', + scap: '\u2AB8', + scaron: '\u0161', + sccue: '\u227D', + sce: '\u2AB0', + scedil: '\u015F', + scirc: '\u015D', + scnE: '\u2AB6', + scnap: '\u2ABA', + scnsim: '\u22E9', + scpolint: '\u2A13', + scsim: '\u227F', + scy: '\u0441', + sdot: '\u22C5', + sdotb: '\u22A1', + sdote: '\u2A66', + seArr: '\u21D8', + searhk: '\u2925', + searr: '\u2198', + searrow: '\u2198', + sect: '\u00A7', + semi: '\u003B', + seswar: '\u2929', + setminus: '\u2216', + setmn: '\u2216', + sext: '\u2736', + sfr: '\uD835\uDD30', + sfrown: '\u2322', + sharp: '\u266F', + shchcy: '\u0449', + shcy: '\u0448', + shortmid: '\u2223', + shortparallel: '\u2225', + shy: '\u00AD', + sigma: '\u03C3', + sigmaf: '\u03C2', + sigmav: '\u03C2', + sim: '\u223C', + simdot: '\u2A6A', + sime: '\u2243', + simeq: '\u2243', + simg: '\u2A9E', + simgE: '\u2AA0', + siml: '\u2A9D', + simlE: '\u2A9F', + simne: '\u2246', + simplus: '\u2A24', + simrarr: '\u2972', + slarr: '\u2190', + smallsetminus: '\u2216', + smashp: '\u2A33', + smeparsl: '\u29E4', + smid: '\u2223', + smile: '\u2323', + smt: '\u2AAA', + smte: '\u2AAC', + smtes: '\u2AAC\uFE00', + softcy: '\u044C', + sol: '\u002F', + solb: '\u29C4', + solbar: '\u233F', + sopf: '\uD835\uDD64', + spades: '\u2660', + spadesuit: '\u2660', + spar: '\u2225', + sqcap: '\u2293', + sqcaps: '\u2293\uFE00', + sqcup: '\u2294', + sqcups: '\u2294\uFE00', + sqsub: '\u228F', + sqsube: '\u2291', + sqsubset: '\u228F', + sqsubseteq: '\u2291', + sqsup: '\u2290', + sqsupe: '\u2292', + sqsupset: '\u2290', + sqsupseteq: '\u2292', + squ: '\u25A1', + square: '\u25A1', + squarf: '\u25AA', + squf: '\u25AA', + srarr: '\u2192', + sscr: '\uD835\uDCC8', + ssetmn: '\u2216', + ssmile: '\u2323', + sstarf: '\u22C6', + star: '\u2606', + starf: '\u2605', + straightepsilon: '\u03F5', + straightphi: '\u03D5', + strns: '\u00AF', + sub: '\u2282', + subE: '\u2AC5', + subdot: '\u2ABD', + sube: '\u2286', + subedot: '\u2AC3', + submult: '\u2AC1', + subnE: '\u2ACB', + subne: '\u228A', + subplus: '\u2ABF', + subrarr: '\u2979', + subset: '\u2282', + subseteq: '\u2286', + subseteqq: '\u2AC5', + subsetneq: '\u228A', + subsetneqq: '\u2ACB', + subsim: '\u2AC7', + subsub: '\u2AD5', + subsup: '\u2AD3', + succ: '\u227B', + succapprox: '\u2AB8', + succcurlyeq: '\u227D', + succeq: '\u2AB0', + succnapprox: '\u2ABA', + succneqq: '\u2AB6', + succnsim: '\u22E9', + succsim: '\u227F', + sum: '\u2211', + sung: '\u266A', + sup1: '\u00B9', + sup2: '\u00B2', + sup3: '\u00B3', + sup: '\u2283', + supE: '\u2AC6', + supdot: '\u2ABE', + supdsub: '\u2AD8', + supe: '\u2287', + supedot: '\u2AC4', + suphsol: '\u27C9', + suphsub: '\u2AD7', + suplarr: '\u297B', + supmult: '\u2AC2', + supnE: '\u2ACC', + supne: '\u228B', + supplus: '\u2AC0', + supset: '\u2283', + supseteq: '\u2287', + supseteqq: '\u2AC6', + supsetneq: '\u228B', + supsetneqq: '\u2ACC', + supsim: '\u2AC8', + supsub: '\u2AD4', + supsup: '\u2AD6', + swArr: '\u21D9', + swarhk: '\u2926', + swarr: '\u2199', + swarrow: '\u2199', + swnwar: '\u292A', + szlig: '\u00DF', + target: '\u2316', + tau: '\u03C4', + tbrk: '\u23B4', + tcaron: '\u0165', + tcedil: '\u0163', + tcy: '\u0442', + tdot: '\u20DB', + telrec: '\u2315', + tfr: '\uD835\uDD31', + there4: '\u2234', + therefore: '\u2234', + theta: '\u03B8', + thetasym: '\u03D1', + thetav: '\u03D1', + thickapprox: '\u2248', + thicksim: '\u223C', + thinsp: '\u2009', + thkap: '\u2248', + thksim: '\u223C', + thorn: '\u00FE', + tilde: '\u02DC', + times: '\u00D7', + timesb: '\u22A0', + timesbar: '\u2A31', + timesd: '\u2A30', + tint: '\u222D', + toea: '\u2928', + top: '\u22A4', + topbot: '\u2336', + topcir: '\u2AF1', + topf: '\uD835\uDD65', + topfork: '\u2ADA', + tosa: '\u2929', + tprime: '\u2034', + trade: '\u2122', + triangle: '\u25B5', + triangledown: '\u25BF', + triangleleft: '\u25C3', + trianglelefteq: '\u22B4', + triangleq: '\u225C', + triangleright: '\u25B9', + trianglerighteq: '\u22B5', + tridot: '\u25EC', + trie: '\u225C', + triminus: '\u2A3A', + triplus: '\u2A39', + trisb: '\u29CD', + tritime: '\u2A3B', + trpezium: '\u23E2', + tscr: '\uD835\uDCC9', + tscy: '\u0446', + tshcy: '\u045B', + tstrok: '\u0167', + twixt: '\u226C', + twoheadleftarrow: '\u219E', + twoheadrightarrow: '\u21A0', + uArr: '\u21D1', + uHar: '\u2963', + uacute: '\u00FA', + uarr: '\u2191', + ubrcy: '\u045E', + ubreve: '\u016D', + ucirc: '\u00FB', + ucy: '\u0443', + udarr: '\u21C5', + udblac: '\u0171', + udhar: '\u296E', + ufisht: '\u297E', + ufr: '\uD835\uDD32', + ugrave: '\u00F9', + uharl: '\u21BF', + uharr: '\u21BE', + uhblk: '\u2580', + ulcorn: '\u231C', + ulcorner: '\u231C', + ulcrop: '\u230F', + ultri: '\u25F8', + umacr: '\u016B', + uml: '\u00A8', + uogon: '\u0173', + uopf: '\uD835\uDD66', + uparrow: '\u2191', + updownarrow: '\u2195', + upharpoonleft: '\u21BF', + upharpoonright: '\u21BE', + uplus: '\u228E', + upsi: '\u03C5', + upsih: '\u03D2', + upsilon: '\u03C5', + upuparrows: '\u21C8', + urcorn: '\u231D', + urcorner: '\u231D', + urcrop: '\u230E', + uring: '\u016F', + urtri: '\u25F9', + uscr: '\uD835\uDCCA', + utdot: '\u22F0', + utilde: '\u0169', + utri: '\u25B5', + utrif: '\u25B4', + uuarr: '\u21C8', + uuml: '\u00FC', + uwangle: '\u29A7', + vArr: '\u21D5', + vBar: '\u2AE8', + vBarv: '\u2AE9', + vDash: '\u22A8', + vangrt: '\u299C', + varepsilon: '\u03F5', + varkappa: '\u03F0', + varnothing: '\u2205', + varphi: '\u03D5', + varpi: '\u03D6', + varpropto: '\u221D', + varr: '\u2195', + varrho: '\u03F1', + varsigma: '\u03C2', + varsubsetneq: '\u228A\uFE00', + varsubsetneqq: '\u2ACB\uFE00', + varsupsetneq: '\u228B\uFE00', + varsupsetneqq: '\u2ACC\uFE00', + vartheta: '\u03D1', + vartriangleleft: '\u22B2', + vartriangleright: '\u22B3', + vcy: '\u0432', + vdash: '\u22A2', + vee: '\u2228', + veebar: '\u22BB', + veeeq: '\u225A', + vellip: '\u22EE', + verbar: '\u007C', + vert: '\u007C', + vfr: '\uD835\uDD33', + vltri: '\u22B2', + vnsub: '\u2282\u20D2', + vnsup: '\u2283\u20D2', + vopf: '\uD835\uDD67', + vprop: '\u221D', + vrtri: '\u22B3', + vscr: '\uD835\uDCCB', + vsubnE: '\u2ACB\uFE00', + vsubne: '\u228A\uFE00', + vsupnE: '\u2ACC\uFE00', + vsupne: '\u228B\uFE00', + vzigzag: '\u299A', + wcirc: '\u0175', + wedbar: '\u2A5F', + wedge: '\u2227', + wedgeq: '\u2259', + weierp: '\u2118', + wfr: '\uD835\uDD34', + wopf: '\uD835\uDD68', + wp: '\u2118', + wr: '\u2240', + wreath: '\u2240', + wscr: '\uD835\uDCCC', + xcap: '\u22C2', + xcirc: '\u25EF', + xcup: '\u22C3', + xdtri: '\u25BD', + xfr: '\uD835\uDD35', + xhArr: '\u27FA', + xharr: '\u27F7', + xi: '\u03BE', + xlArr: '\u27F8', + xlarr: '\u27F5', + xmap: '\u27FC', + xnis: '\u22FB', + xodot: '\u2A00', + xopf: '\uD835\uDD69', + xoplus: '\u2A01', + xotime: '\u2A02', + xrArr: '\u27F9', + xrarr: '\u27F6', + xscr: '\uD835\uDCCD', + xsqcup: '\u2A06', + xuplus: '\u2A04', + xutri: '\u25B3', + xvee: '\u22C1', + xwedge: '\u22C0', + yacute: '\u00FD', + yacy: '\u044F', + ycirc: '\u0177', + ycy: '\u044B', + yen: '\u00A5', + yfr: '\uD835\uDD36', + yicy: '\u0457', + yopf: '\uD835\uDD6A', + yscr: '\uD835\uDCCE', + yucy: '\u044E', + yuml: '\u00FF', + zacute: '\u017A', + zcaron: '\u017E', + zcy: '\u0437', + zdot: '\u017C', + zeetrf: '\u2128', + zeta: '\u03B6', + zfr: '\uD835\uDD37', + zhcy: '\u0436', + zigrarr: '\u21DD', + zopf: '\uD835\uDD6B', + zscr: '\uD835\uDCCF', + zwj: '\u200D', + zwnj: '\u200C' +}; + +const decodeMap: { [Identifier: string]: number } = { + '0': 65533, + '128': 8364, + '130': 8218, + '131': 402, + '132': 8222, + '133': 8230, + '134': 8224, + '135': 8225, + '136': 710, + '137': 8240, + '138': 352, + '139': 8249, + '140': 338, + '142': 381, + '145': 8216, + '146': 8217, + '147': 8220, + '148': 8221, + '149': 8226, + '150': 8211, + '151': 8212, + '152': 732, + '153': 8482, + '154': 353, + '155': 8250, + '156': 339, + '158': 382, + '159': 376 +}; + +// Used code from https://github.com/fb55/entities (BSD license) +export function decodeHTMLStrict(text: string): string { + return text.replace(/&(?:[a-zA-Z]+|#[xX][\da-fA-F]+|#\d+);/g, (key) => { + if (key.charAt(1) === '#') { + const secondChar = key.charAt(2); + const codePoint = + secondChar === 'X' || secondChar === 'x' + ? parseInt(key.slice(3), 16) + : parseInt(key.slice(2), 10); + return decodeCodePoint(codePoint); + } + return entities[key.slice(1, -1)] || key; + }); +} + +function decodeCodePoint(codePoint: number): string { + if ((codePoint >= 0xd800 && codePoint <= 0xdfff) || codePoint > 0x10ffff) { + return '\uFFFD'; + } + + if (codePoint in decodeMap) { + codePoint = decodeMap[codePoint]; + } + + return String.fromCodePoint(codePoint); +} diff --git a/node_modules/meriyah/src/lexer/identifier.ts b/node_modules/meriyah/src/lexer/identifier.ts new file mode 100644 index 0000000..ec8a7e4 --- /dev/null +++ b/node_modules/meriyah/src/lexer/identifier.ts @@ -0,0 +1,177 @@ +import { ParserState, Context } from '../common'; +import { Token, descKeywordTable } from '../token'; +import { Chars } from '../chars'; +import { advanceChar, consumeMultiUnitCodePoint, fromCodePoint, toHex } from './common'; +import { CharTypes, CharFlags, isIdentifierPart, isIdentifierStart, isIdPart } from './charClassifier'; +import { report, reportScannerError, Errors } from '../errors'; + +/** + * Scans identifier + * + * @param parser Parser object + * @param context Context masks + */ +export function scanIdentifier(parser: ParserState, context: Context, isValidAsKeyword: 0 | 1): Token { + while (isIdPart[advanceChar(parser)]) {} + parser.tokenValue = parser.source.slice(parser.tokenPos, parser.index); + + return parser.currentChar !== Chars.Backslash && parser.currentChar < 0x7e + ? descKeywordTable[parser.tokenValue] || Token.Identifier + : scanIdentifierSlowCase(parser, context, 0, isValidAsKeyword); +} + +/** + * Scans unicode identifier + * + * @param parser Parser object + * @param context Context masks + */ +export function scanUnicodeIdentifier(parser: ParserState, context: Context): Token { + const cookedChar = scanIdentifierUnicodeEscape(parser); + if (!isIdentifierPart(cookedChar)) report(parser, Errors.InvalidUnicodeEscapeSequence); + parser.tokenValue = fromCodePoint(cookedChar); + return scanIdentifierSlowCase(parser, context, /* hasEscape */ 1, CharTypes[cookedChar] & CharFlags.KeywordCandidate); +} + +/** + * Scans identifier slow case + * + * @param parser Parser object + * @param context Context masks + * @param hasEscape True if contains a unicode sequence + * @param isValidAsKeyword + */ +export function scanIdentifierSlowCase( + parser: ParserState, + context: Context, + hasEscape: 0 | 1, + isValidAsKeyword: number +): Token { + let start = parser.index; + + while (parser.index < parser.end) { + if (parser.currentChar === Chars.Backslash) { + parser.tokenValue += parser.source.slice(start, parser.index); + hasEscape = 1; + const code = scanIdentifierUnicodeEscape(parser); + if (!isIdentifierPart(code)) report(parser, Errors.InvalidUnicodeEscapeSequence); + isValidAsKeyword = isValidAsKeyword && CharTypes[code] & CharFlags.KeywordCandidate; + parser.tokenValue += fromCodePoint(code); + start = parser.index; + } else if (isIdentifierPart(parser.currentChar) || consumeMultiUnitCodePoint(parser, parser.currentChar)) { + advanceChar(parser); + } else { + break; + } + } + + if (parser.index <= parser.end) { + parser.tokenValue += parser.source.slice(start, parser.index); + } + + const length = parser.tokenValue.length; + + if (isValidAsKeyword && length >= 2 && length <= 11) { + const token: Token | undefined = descKeywordTable[parser.tokenValue]; + if (token === void 0) return Token.Identifier; + if (!hasEscape) return token; + + if (context & Context.Strict) { + return token === Token.AwaitKeyword && (context & (Context.Module | Context.InAwaitContext)) === 0 + ? token + : token === Token.StaticKeyword + ? Token.EscapedFutureReserved + : (token & Token.FutureReserved) === Token.FutureReserved + ? Token.EscapedFutureReserved + : Token.EscapedReserved; + } + if ( + context & Context.AllowEscapedKeyword && + (context & Context.InGlobal) === 0 && + (token & Token.Reserved) === Token.Reserved + ) + return token; + if (token === Token.YieldKeyword) { + return context & Context.AllowEscapedKeyword + ? Token.AnyIdentifier + : context & Context.InYieldContext + ? Token.EscapedReserved + : token; + } + + return token === Token.AsyncKeyword && context & Context.AllowEscapedKeyword + ? Token.AnyIdentifier + : (token & Token.FutureReserved) === Token.FutureReserved + ? token + : token === Token.AwaitKeyword && (context & Context.InAwaitContext) === 0 + ? token + : Token.EscapedReserved; + } + return Token.Identifier; +} + +/** + * Scans private name + * + * @param parser Parser object + */ +export function scanPrivateIdentifier(parser: ParserState): Token { + if (!isIdentifierStart(advanceChar(parser))) report(parser, Errors.MissingPrivateIdentifier); + return Token.PrivateField; +} + +/** + * Scans unicode identifier + * + * @param parser Parser object + */ +export function scanIdentifierUnicodeEscape(parser: ParserState): number { + // Check for Unicode escape of the form '\uXXXX' + // and return code point value if valid Unicode escape is found. + if (parser.source.charCodeAt(parser.index + 1) !== Chars.LowerU) { + report(parser, Errors.InvalidUnicodeEscapeSequence); + } + parser.currentChar = parser.source.charCodeAt((parser.index += 2)); + return scanUnicodeEscape(parser); +} + +/** + * Scans unicode escape value + * + * @param parser Parser object + */ +export function scanUnicodeEscape(parser: ParserState): number { + // Accept both \uxxxx and \u{xxxxxx} + let codePoint = 0; + const char = parser.currentChar; + // First handle a delimited Unicode escape, e.g. \u{1F4A9} + if (char === Chars.LeftBrace) { + const begin = parser.index - 2; + while (CharTypes[advanceChar(parser)] & CharFlags.Hex) { + codePoint = (codePoint << 4) | toHex(parser.currentChar); + if (codePoint > Chars.NonBMPMax) reportScannerError(begin, parser.line, parser.index + 1, Errors.UnicodeOverflow); + } + + // At least 4 characters have to be read + if ((parser.currentChar as number) !== Chars.RightBrace) { + reportScannerError(begin, parser.line, parser.index - 1, Errors.InvalidHexEscapeSequence); + } + advanceChar(parser); // consumes '}' + return codePoint; + } + + if ((CharTypes[char] & CharFlags.Hex) === 0) report(parser, Errors.InvalidHexEscapeSequence); // first one is mandatory + + const char2 = parser.source.charCodeAt(parser.index + 1); + if ((CharTypes[char2] & CharFlags.Hex) === 0) report(parser, Errors.InvalidHexEscapeSequence); + const char3 = parser.source.charCodeAt(parser.index + 2); + if ((CharTypes[char3] & CharFlags.Hex) === 0) report(parser, Errors.InvalidHexEscapeSequence); + const char4 = parser.source.charCodeAt(parser.index + 3); + if ((CharTypes[char4] & CharFlags.Hex) === 0) report(parser, Errors.InvalidHexEscapeSequence); + + codePoint = (toHex(char) << 12) | (toHex(char2) << 8) | (toHex(char3) << 4) | toHex(char4); + + parser.currentChar = parser.source.charCodeAt((parser.index += 4)); + + return codePoint; +} diff --git a/node_modules/meriyah/src/lexer/index.ts b/node_modules/meriyah/src/lexer/index.ts new file mode 100644 index 0000000..d86aee6 --- /dev/null +++ b/node_modules/meriyah/src/lexer/index.ts @@ -0,0 +1,32 @@ +export { scanSingleToken, nextToken, TokenLookup } from './scan'; +export { + skipMultiLineComment, + skipSingleLineComment, + skipHashBang, + skipSingleHTMLComment, + CommentType +} from './comments'; +export { + advanceChar, + consumeMultiUnitCodePoint, + isExoticECMAScriptWhitespace, + fromCodePoint, + toHex, + consumeLineFeed, + scanNewLine, + LexerState, + NumberKind, + convertTokenType +} from './common'; +export { CharTypes, CharFlags, isIdentifierStart, isIdentifierPart } from './charClassifier'; +export { + scanIdentifier, + scanIdentifierSlowCase, + scanUnicodeIdentifier, + scanPrivateIdentifier, + scanUnicodeEscape +} from './identifier'; +export { scanString } from './string'; +export { scanNumber } from './numeric'; +export { scanTemplate, scanTemplateTail } from './template'; +export { scanRegularExpression } from './regexp'; diff --git a/node_modules/meriyah/src/lexer/jsx.ts b/node_modules/meriyah/src/lexer/jsx.ts new file mode 100644 index 0000000..7b80184 --- /dev/null +++ b/node_modules/meriyah/src/lexer/jsx.ts @@ -0,0 +1,126 @@ +import { CharFlags, CharTypes } from './charClassifier'; +import { Chars } from '../chars'; +import { Token } from '../token'; +import { ParserState, Context } from '../common'; +import { report, Errors } from '../errors'; +import { advanceChar, LexerState, TokenLookup, scanSingleToken, scanNewLine, consumeLineFeed } from './'; +import { decodeHTMLStrict } from './decodeHTML'; + +/** + * Scans JSX attribute value + * + * @param parser The parser instance + * @param context Context masks + */ +export function scanJSXAttributeValue(parser: ParserState, context: Context): Token { + parser.startPos = parser.tokenPos = parser.index; + parser.startColumn = parser.colPos = parser.column; + parser.startLine = parser.linePos = parser.line; + parser.token = + CharTypes[parser.currentChar] & CharFlags.StringLiteral + ? scanJSXString(parser, context) + : scanSingleToken(parser, context, LexerState.None); + return parser.token; +} + +/** + * Scans JSX string + * + * @param parser The parser object + */ +export function scanJSXString(parser: ParserState, context: Context): Token { + const quote = parser.currentChar; + let char = advanceChar(parser); + const start = parser.index; + while (char !== quote) { + if (parser.index >= parser.end) report(parser, Errors.UnterminatedString); + char = advanceChar(parser); + } + + // check for unterminated string + if (char !== quote) report(parser, Errors.UnterminatedString); + parser.tokenValue = parser.source.slice(start, parser.index); + advanceChar(parser); // skip the quote + if (context & Context.OptionsRaw) parser.tokenRaw = parser.source.slice(parser.tokenPos, parser.index); + return Token.StringLiteral; +} + +/** + * Scans JSX token + * + * @param parser The parser object + */ +export function scanJSXToken(parser: ParserState, context: Context): Token { + parser.startPos = parser.tokenPos = parser.index; + parser.startColumn = parser.colPos = parser.column; + parser.startLine = parser.linePos = parser.line; + + if (parser.index >= parser.end) return (parser.token = Token.EOF); + + const token = TokenLookup[parser.source.charCodeAt(parser.index)]; + + switch (token) { + // '<' + case Token.LessThan: { + advanceChar(parser); + if (parser.currentChar === Chars.Slash) { + advanceChar(parser); + parser.token = Token.JSXClose; + } else { + parser.token = Token.LessThan; + } + + break; + } + // '{' + case Token.LeftBrace: { + advanceChar(parser); + parser.token = Token.LeftBrace; + break; + } + default: { + let state = LexerState.None; + + while (parser.index < parser.end) { + const type = CharTypes[parser.source.charCodeAt(parser.index)]; + + if (type & CharFlags.CarriageReturn) { + state |= LexerState.NewLine | LexerState.LastIsCR; + scanNewLine(parser); + } else if (type & CharFlags.LineFeed) { + consumeLineFeed(parser, state); + state = (state & ~LexerState.LastIsCR) | LexerState.NewLine; + } else { + advanceChar(parser); + } + + if (CharTypes[parser.currentChar] & CharFlags.JSXToken) break; + } + + const raw = parser.source.slice(parser.tokenPos, parser.index); + if (context & Context.OptionsRaw) parser.tokenRaw = raw; + parser.tokenValue = decodeHTMLStrict(raw); + parser.token = Token.JSXText; + } + } + + return parser.token; +} + +/** + * Scans JSX identifier + * + * @param parser The parser instance + */ +export function scanJSXIdentifier(parser: ParserState): Token { + if ((parser.token & Token.IsIdentifier) === Token.IsIdentifier) { + const { index } = parser; + let char = parser.currentChar; + while (CharTypes[char] & (CharFlags.Hyphen | CharFlags.IdentifierPart)) { + char = advanceChar(parser); + } + parser.tokenValue += parser.source.slice(index, parser.index); + } + parser.token = Token.Identifier; + return parser.token; +} diff --git a/node_modules/meriyah/src/lexer/numeric.ts b/node_modules/meriyah/src/lexer/numeric.ts new file mode 100644 index 0000000..95725bb --- /dev/null +++ b/node_modules/meriyah/src/lexer/numeric.ts @@ -0,0 +1,259 @@ +import { ParserState, Context, Flags } from '../common'; +import { Token } from '../token'; +import { advanceChar, toHex, NumberKind } from './common'; +import { CharTypes, CharFlags, isIdentifierStart } from './charClassifier'; +import { Chars } from '../chars'; +import { report, Errors, reportScannerError } from '../errors'; + +/** + * Scans numeric literal + * + * @param parser Parser object + * @param context Context masks + * @param isFloat + */ +export function scanNumber(parser: ParserState, context: Context, kind: NumberKind): Token { + // DecimalLiteral :: + // DecimalIntegerLiteral . DecimalDigits_opt + // . DecimalDigits + let char = parser.currentChar; + let value: any = 0; + let digit = 9; + let atStart = kind & NumberKind.Float ? 0 : 1; + let digits = 0; + let allowSeparator: 0 | 1 = 0; + + if (kind & NumberKind.Float) { + value = '.' + scanDecimalDigitsOrSeparator(parser, char); + char = parser.currentChar; + // It is a Syntax Error if the MV is not an integer. (dot decimalDigits) + if (char === Chars.LowerN) report(parser, Errors.InvalidBigInt); + } else { + if (char === Chars.Zero) { + char = advanceChar(parser); + + // Hex + if ((char | 32) === Chars.LowerX) { + kind = NumberKind.Hex | NumberKind.ValidBigIntKind; + char = advanceChar(parser); // skips 'X', 'x' + while (CharTypes[char] & (CharFlags.Hex | CharFlags.Underscore)) { + if (char === Chars.Underscore) { + if (!allowSeparator) report(parser, Errors.ContinuousNumericSeparator); + allowSeparator = 0; + char = advanceChar(parser); + continue; + } + allowSeparator = 1; + value = value * 0x10 + toHex(char); + digits++; + char = advanceChar(parser); + } + + if (digits < 1 || !allowSeparator) { + report(parser, digits < 1 ? Errors.MissingHexDigits : Errors.TrailingNumericSeparator); + } + // Octal + } else if ((char | 32) === Chars.LowerO) { + kind = NumberKind.Octal | NumberKind.ValidBigIntKind; + char = advanceChar(parser); // skips 'X', 'x' + while (CharTypes[char] & (CharFlags.Octal | CharFlags.Underscore)) { + if (char === Chars.Underscore) { + if (!allowSeparator) { + report(parser, Errors.ContinuousNumericSeparator); + } + allowSeparator = 0; + char = advanceChar(parser); + continue; + } + allowSeparator = 1; + value = value * 8 + (char - Chars.Zero); + digits++; + char = advanceChar(parser); + } + if (digits < 1 || !allowSeparator) { + report(parser, digits < 1 ? Errors.Unexpected : Errors.TrailingNumericSeparator); + } + } else if ((char | 32) === Chars.LowerB) { + kind = NumberKind.Binary | NumberKind.ValidBigIntKind; + char = advanceChar(parser); // skips 'B', 'b' + while (CharTypes[char] & (CharFlags.Binary | CharFlags.Underscore)) { + if (char === Chars.Underscore) { + if (!allowSeparator) { + report(parser, Errors.ContinuousNumericSeparator); + } + allowSeparator = 0; + char = advanceChar(parser); + continue; + } + allowSeparator = 1; + value = value * 2 + (char - Chars.Zero); + digits++; + char = advanceChar(parser); + } + if (digits < 1 || !allowSeparator) { + report(parser, digits < 1 ? Errors.Unexpected : Errors.TrailingNumericSeparator); + } + } else if (CharTypes[char] & CharFlags.Octal) { + // Octal integer literals are not permitted in strict mode code + if (context & Context.Strict) report(parser, Errors.StrictOctalEscape); + kind = NumberKind.ImplicitOctal; + while (CharTypes[char] & CharFlags.Decimal) { + if (CharTypes[char] & CharFlags.ImplicitOctalDigits) { + kind = NumberKind.NonOctalDecimal; + atStart = 0; + break; + } + value = value * 8 + (char - Chars.Zero); + char = advanceChar(parser); + } + } else if (CharTypes[char] & CharFlags.ImplicitOctalDigits) { + if (context & Context.Strict) report(parser, Errors.StrictOctalEscape); + parser.flags |= Flags.Octals; + kind = NumberKind.NonOctalDecimal; + } else if (char === Chars.Underscore) { + report(parser, Errors.Unexpected); + } + } + + // Parse decimal digits and allow trailing fractional part + if (kind & NumberKind.DecimalNumberKind) { + if (atStart) { + while (digit >= 0 && CharTypes[char] & (CharFlags.Decimal | CharFlags.Underscore)) { + if (char === Chars.Underscore) { + char = advanceChar(parser); + if (char === Chars.Underscore || kind & NumberKind.NonOctalDecimal) { + reportScannerError( + parser.index, + parser.line, + parser.index + 1 /* skips `_` */, + Errors.ContinuousNumericSeparator + ); + } + allowSeparator = 1; + continue; + } + allowSeparator = 0; + value = 10 * value + (char - Chars.Zero); + char = advanceChar(parser); + --digit; + } + + if (allowSeparator) { + reportScannerError( + parser.index, + parser.line, + parser.index + 1 /* skips `_` */, + Errors.TrailingNumericSeparator + ); + } + + if (digit >= 0 && !isIdentifierStart(char) && char !== Chars.Period) { + // Most numbers are pure decimal integers without fractional component + // or exponential notation. Handle that with optimized code. + parser.tokenValue = value; + if (context & Context.OptionsRaw) parser.tokenRaw = parser.source.slice(parser.tokenPos, parser.index); + return Token.NumericLiteral; + } + } + + value += scanDecimalDigitsOrSeparator(parser, char); + + char = parser.currentChar; + + // Consume any decimal dot and fractional component. + if (char === Chars.Period) { + if (advanceChar(parser) === Chars.Underscore) report(parser, Errors.Unexpected); + kind = NumberKind.Float; + value += '.' + scanDecimalDigitsOrSeparator(parser, parser.currentChar); + char = parser.currentChar; + } + } + } + const end = parser.index; + + let isBigInt: 0 | 1 = 0; + + if (char === Chars.LowerN && kind & NumberKind.ValidBigIntKind) { + isBigInt = 1; + char = advanceChar(parser); + } else { + // Consume any exponential notation. + if ((char | 32) === Chars.LowerE) { + char = advanceChar(parser); + + // '-', '+' + if (CharTypes[char] & CharFlags.Exponent) char = advanceChar(parser); + + const { index } = parser; + + // Exponential notation must contain at least one digit + if ((CharTypes[char] & CharFlags.Decimal) < 1) report(parser, Errors.MissingExponent); + + // Consume exponential digits + value += parser.source.substring(end, index) + scanDecimalDigitsOrSeparator(parser, char); + + char = parser.currentChar; + } + } + + // The source character immediately following a numeric literal must + // not be an identifier start or a decimal digit + if ((parser.index < parser.end && CharTypes[char] & CharFlags.Decimal) || isIdentifierStart(char)) { + report(parser, Errors.IDStartAfterNumber); + } + + if (isBigInt) { + parser.tokenRaw = parser.source.slice(parser.tokenPos, parser.index); + parser.tokenValue = BigInt(value); + return Token.BigIntLiteral; + } + + parser.tokenValue = + kind & (NumberKind.ImplicitOctal | NumberKind.Binary | NumberKind.Hex | NumberKind.Octal) + ? value + : kind & NumberKind.NonOctalDecimal + ? parseFloat(parser.source.substring(parser.tokenPos, parser.index)) + : +value; + + if (context & Context.OptionsRaw) parser.tokenRaw = parser.source.slice(parser.tokenPos, parser.index); + + return Token.NumericLiteral; +} + +/** + * Scans numeric literal and skip underscore '_' if it exist + * + * @param parser Parser object + * @param char Code point + */ +export function scanDecimalDigitsOrSeparator(parser: ParserState, char: number): string { + let allowSeparator: 0 | 1 = 0; + let start = parser.index; + let ret = ''; + while (CharTypes[char] & (CharFlags.Decimal | CharFlags.Underscore)) { + if (char === Chars.Underscore) { + const { index } = parser; + char = advanceChar(parser); + if (char === Chars.Underscore) { + reportScannerError( + parser.index, + parser.line, + parser.index + 1 /* skips `_` */, + Errors.ContinuousNumericSeparator + ); + } + allowSeparator = 1; + ret += parser.source.substring(start, index); + start = parser.index; + continue; + } + allowSeparator = 0; + char = advanceChar(parser); + } + + if (allowSeparator) { + reportScannerError(parser.index, parser.line, parser.index + 1 /* skips `_` */, Errors.TrailingNumericSeparator); + } + + return ret + parser.source.substring(start, parser.index); +} diff --git a/node_modules/meriyah/src/lexer/regexp.ts b/node_modules/meriyah/src/lexer/regexp.ts new file mode 100644 index 0000000..4a48d50 --- /dev/null +++ b/node_modules/meriyah/src/lexer/regexp.ts @@ -0,0 +1,143 @@ +import { Chars } from '../chars'; +import { Context, ParserState } from '../common'; +import { Token } from '../token'; +import { advanceChar } from './common'; +import { isIdentifierPart } from './charClassifier'; +import { report, Errors } from '../errors'; + +/** + * Scans regular expression + * + * @param parser Parser object + * @param context Context masks + */ + +export function scanRegularExpression(parser: ParserState, context: Context): Token { + const enum RegexState { + Empty = 0, + Escape = 0x1, + Class = 0x2 + } + const bodyStart = parser.index; + // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags + let preparseState = RegexState.Empty; + + loop: while (true) { + const ch = parser.currentChar; + advanceChar(parser); + + if (preparseState & RegexState.Escape) { + preparseState &= ~RegexState.Escape; + } else { + switch (ch) { + case Chars.Slash: + if (!preparseState) break loop; + else break; + case Chars.Backslash: + preparseState |= RegexState.Escape; + break; + case Chars.LeftBracket: + preparseState |= RegexState.Class; + break; + case Chars.RightBracket: + preparseState &= RegexState.Escape; + break; + case Chars.CarriageReturn: + case Chars.LineFeed: + case Chars.LineSeparator: + case Chars.ParagraphSeparator: + report(parser, Errors.UnterminatedRegExp); + default: // ignore + } + } + + if (parser.index >= parser.source.length) { + return report(parser, Errors.UnterminatedRegExp); + } + } + + const bodyEnd = parser.index - 1; + + const enum RegexFlags { + Empty = 0b00000, + IgnoreCase = 0b00001, + Global = 0b00010, + Multiline = 0b00100, + Unicode = 0b10000, + Sticky = 0b01000, + DotAll = 0b1100 + } + + let mask = RegexFlags.Empty; + let char = parser.currentChar; + + const { index: flagStart } = parser; + + while (isIdentifierPart(char)) { + switch (char) { + case Chars.LowerG: + if (mask & RegexFlags.Global) report(parser, Errors.DuplicateRegExpFlag, 'g'); + mask |= RegexFlags.Global; + break; + + case Chars.LowerI: + if (mask & RegexFlags.IgnoreCase) report(parser, Errors.DuplicateRegExpFlag, 'i'); + mask |= RegexFlags.IgnoreCase; + break; + + case Chars.LowerM: + if (mask & RegexFlags.Multiline) report(parser, Errors.DuplicateRegExpFlag, 'm'); + mask |= RegexFlags.Multiline; + break; + + case Chars.LowerU: + if (mask & RegexFlags.Unicode) report(parser, Errors.DuplicateRegExpFlag, 'g'); + mask |= RegexFlags.Unicode; + break; + + case Chars.LowerY: + if (mask & RegexFlags.Sticky) report(parser, Errors.DuplicateRegExpFlag, 'y'); + mask |= RegexFlags.Sticky; + break; + + case Chars.LowerS: + if (mask & RegexFlags.DotAll) report(parser, Errors.DuplicateRegExpFlag, 's'); + mask |= RegexFlags.DotAll; + break; + + default: + report(parser, Errors.UnexpectedTokenRegExpFlag); + } + + char = advanceChar(parser); + } + + const flags = parser.source.slice(flagStart, parser.index); + + const pattern = parser.source.slice(bodyStart, bodyEnd); + + parser.tokenRegExp = { pattern, flags }; + + if (context & Context.OptionsRaw) parser.tokenRaw = parser.source.slice(parser.tokenPos, parser.index); + + parser.tokenValue = validate(parser, pattern, flags); + + return Token.RegularExpression; +} + +/** + * Validates regular expressions + * + * + * @param state Parser instance + * @param context Context masks + * @param pattern Regexp body + * @param flags Regexp flags + */ +function validate(parser: ParserState, pattern: string, flags: string): RegExp | null | Token { + try { + return new RegExp(pattern, flags); + } catch (e) { + report(parser, Errors.UnterminatedRegExp); + } +} diff --git a/node_modules/meriyah/src/lexer/scan.ts b/node_modules/meriyah/src/lexer/scan.ts new file mode 100644 index 0000000..25063e7 --- /dev/null +++ b/node_modules/meriyah/src/lexer/scan.ts @@ -0,0 +1,655 @@ +import { Chars } from '../chars'; +import { Token } from '../token'; +import { ParserState, Context, Flags } from '../common'; +import { report, Errors } from '../errors'; +import { unicodeLookup } from '../unicode'; +import { + advanceChar, + LexerState, + isExoticECMAScriptWhitespace, + NumberKind, + fromCodePoint, + consumeLineFeed, + scanNewLine, + convertTokenType +} from './common'; +import { skipSingleLineComment, skipMultiLineComment, skipSingleHTMLComment, CommentType } from './comments'; +import { scanRegularExpression } from './regexp'; +import { scanTemplate } from './template'; +import { scanNumber } from './numeric'; +import { scanString } from './string'; +import { scanIdentifier, scanUnicodeIdentifier, scanIdentifierSlowCase, scanPrivateIdentifier } from './identifier'; + +/* + * OneChar: 40, 41, 44, 58, 59, 63, 91, 93, 123, 125, 126: + * '(', ')', ',', ':', ';', '?', '[', ']', '{', '}', '~' + * PrivateField: 35: '#', + * Identifier: 36, 65..90, 92, 95, 97..122: '$', 'A'..'Z', '_', '\'', 'a'..'z' + * Period: 46: '.' + * StringLiteral: 34, 39: '"', `'` + * NumericLiteral: 48, 49..57: '0'..'9' + * WhiteSpace: 9, 11, 12, 32: '\t', '\v', '\f', ' ' + * LineFeed: 10: '\n' + * CarriageReturn: 13: '\r' + * Template: 96: '`' + */ + +export const TokenLookup = [ + /* 0 - Null */ Token.Illegal, + /* 1 - Start of Heading */ Token.Illegal, + /* 2 - Start of Text */ Token.Illegal, + /* 3 - End of Text */ Token.Illegal, + /* 4 - End of Transm. */ Token.Illegal, + /* 5 - Enquiry */ Token.Illegal, + /* 6 - Acknowledgment */ Token.Illegal, + /* 7 - Bell */ Token.Illegal, + /* 8 - Backspace */ Token.Illegal, + /* 9 - Horizontal Tab */ Token.WhiteSpace, + /* 10 - Line Feed */ Token.LineFeed, + /* 11 - Vertical Tab */ Token.WhiteSpace, + /* 12 - Form Feed */ Token.WhiteSpace, + /* 13 - Carriage Return */ Token.CarriageReturn, + /* 14 - Shift Out */ Token.Illegal, + /* 15 - Shift In */ Token.Illegal, + /* 16 - Data Line Escape */ Token.Illegal, + /* 17 - Device Control 1 */ Token.Illegal, + /* 18 - Device Control 2 */ Token.Illegal, + /* 19 - Device Control 3 */ Token.Illegal, + /* 20 - Device Control 4 */ Token.Illegal, + /* 21 - Negative Ack. */ Token.Illegal, + /* 22 - Synchronous Idle */ Token.Illegal, + /* 23 - End of Transmit */ Token.Illegal, + /* 24 - Cancel */ Token.Illegal, + /* 25 - End of Medium */ Token.Illegal, + /* 26 - Substitute */ Token.Illegal, + /* 27 - Escape */ Token.Illegal, + /* 28 - File Separator */ Token.Illegal, + /* 29 - Group Separator */ Token.Illegal, + /* 30 - Record Separator */ Token.Illegal, + /* 31 - Unit Separator */ Token.Illegal, + /* 32 - Space */ Token.WhiteSpace, + /* 33 - ! */ Token.Negate, + /* 34 - " */ Token.StringLiteral, + /* 35 - # */ Token.PrivateField, + /* 36 - $ */ Token.Identifier, + /* 37 - % */ Token.Modulo, + /* 38 - & */ Token.BitwiseAnd, + /* 39 - ' */ Token.StringLiteral, + /* 40 - ( */ Token.LeftParen, + /* 41 - ) */ Token.RightParen, + /* 42 - * */ Token.Multiply, + /* 43 - + */ Token.Add, + /* 44 - , */ Token.Comma, + /* 45 - - */ Token.Subtract, + /* 46 - . */ Token.Period, + /* 47 - / */ Token.Divide, + /* 48 - 0 */ Token.NumericLiteral, + /* 49 - 1 */ Token.NumericLiteral, + /* 50 - 2 */ Token.NumericLiteral, + /* 51 - 3 */ Token.NumericLiteral, + /* 52 - 4 */ Token.NumericLiteral, + /* 53 - 5 */ Token.NumericLiteral, + /* 54 - 6 */ Token.NumericLiteral, + /* 55 - 7 */ Token.NumericLiteral, + /* 56 - 8 */ Token.NumericLiteral, + /* 57 - 9 */ Token.NumericLiteral, + /* 58 - : */ Token.Colon, + /* 59 - ; */ Token.Semicolon, + /* 60 - < */ Token.LessThan, + /* 61 - = */ Token.Assign, + /* 62 - > */ Token.GreaterThan, + /* 63 - ? */ Token.QuestionMark, + /* 64 - @ */ Token.Decorator, + /* 65 - A */ Token.Identifier, + /* 66 - B */ Token.Identifier, + /* 67 - C */ Token.Identifier, + /* 68 - D */ Token.Identifier, + /* 69 - E */ Token.Identifier, + /* 70 - F */ Token.Identifier, + /* 71 - G */ Token.Identifier, + /* 72 - H */ Token.Identifier, + /* 73 - I */ Token.Identifier, + /* 74 - J */ Token.Identifier, + /* 75 - K */ Token.Identifier, + /* 76 - L */ Token.Identifier, + /* 77 - M */ Token.Identifier, + /* 78 - N */ Token.Identifier, + /* 79 - O */ Token.Identifier, + /* 80 - P */ Token.Identifier, + /* 81 - Q */ Token.Identifier, + /* 82 - R */ Token.Identifier, + /* 83 - S */ Token.Identifier, + /* 84 - T */ Token.Identifier, + /* 85 - U */ Token.Identifier, + /* 86 - V */ Token.Identifier, + /* 87 - W */ Token.Identifier, + /* 88 - X */ Token.Identifier, + /* 89 - Y */ Token.Identifier, + /* 90 - Z */ Token.Identifier, + /* 91 - [ */ Token.LeftBracket, + /* 92 - \ */ Token.EscapedIdentifier, + /* 93 - ] */ Token.RightBracket, + /* 94 - ^ */ Token.BitwiseXor, + /* 95 - _ */ Token.Identifier, + /* 96 - ` */ Token.Template, + /* 97 - a */ Token.Keyword, + /* 98 - b */ Token.Keyword, + /* 99 - c */ Token.Keyword, + /* 100 - d */ Token.Keyword, + /* 101 - e */ Token.Keyword, + /* 102 - f */ Token.Keyword, + /* 103 - g */ Token.Keyword, + /* 104 - h */ Token.Identifier, + /* 105 - i */ Token.Keyword, + /* 106 - j */ Token.Identifier, + /* 107 - k */ Token.Identifier, + /* 108 - l */ Token.Keyword, + /* 109 - m */ Token.Identifier, + /* 110 - n */ Token.Keyword, + /* 111 - o */ Token.Identifier, + /* 112 - p */ Token.Keyword, + /* 113 - q */ Token.Identifier, + /* 114 - r */ Token.Keyword, + /* 115 - s */ Token.Keyword, + /* 116 - t */ Token.Keyword, + /* 117 - u */ Token.Identifier, + /* 118 - v */ Token.Keyword, + /* 119 - w */ Token.Keyword, + /* 120 - x */ Token.Identifier, + /* 121 - y */ Token.Keyword, + /* 122 - z */ Token.Keyword, + /* 123 - { */ Token.LeftBrace, + /* 124 - | */ Token.BitwiseOr, + /* 125 - } */ Token.RightBrace, + /* 126 - ~ */ Token.Complement, + /* 127 - Delete */ Token.Illegal +]; + +/** + * Scans next token in the stream + * + * @param parser Parser object + * @param context Context masks + */ +export function nextToken(parser: ParserState, context: Context): void { + parser.flags = (parser.flags | Flags.NewLine) ^ Flags.NewLine; + parser.startPos = parser.index; + parser.startColumn = parser.column; + parser.startLine = parser.line; + parser.token = scanSingleToken(parser, context, LexerState.None); + if (parser.onToken && parser.token !== Token.EOF) { + const loc = { + start: { + line: parser.linePos, + column: parser.colPos + }, + end: { + line: parser.line, + column: parser.column + } + }; + parser.onToken(convertTokenType(parser.token), parser.tokenPos, parser.index, loc); + } +} + +export function scanSingleToken(parser: ParserState, context: Context, state: LexerState): Token { + const isStartOfLine = parser.index === 0; + + const source = parser.source; + + // These three are only for HTMLClose comment + let startPos = parser.index; + let startLine = parser.line; + let startColumn = parser.column; + + while (parser.index < parser.end) { + parser.tokenPos = parser.index; + parser.colPos = parser.column; + parser.linePos = parser.line; + + let char = parser.currentChar; + + if (char <= 0x7e) { + const token = TokenLookup[char]; + + switch (token) { + case Token.LeftParen: + case Token.RightParen: + case Token.LeftBrace: + case Token.RightBrace: + case Token.LeftBracket: + case Token.RightBracket: + case Token.Colon: + case Token.Semicolon: + case Token.Comma: + case Token.Complement: + case Token.Decorator: + case Token.Illegal: + advanceChar(parser); + return token; + + // Look for an identifier + case Token.Identifier: + return scanIdentifier(parser, context, /* isValidAsKeyword */ 0); + + // Look for identifier or keyword + case Token.Keyword: + return scanIdentifier(parser, context, /* isValidAsKeyword */ 1); + + // Look for a decimal number. + case Token.NumericLiteral: + return scanNumber(parser, context, NumberKind.Decimal | NumberKind.ValidBigIntKind); + + // Look for a string literal + case Token.StringLiteral: + return scanString(parser, context, char); + + // Look for a template string + case Token.Template: + return scanTemplate(parser, context); + + // Look for a escaped identifier + case Token.EscapedIdentifier: + return scanUnicodeIdentifier(parser, context); + + // `#` (private name) + case Token.PrivateField: + return scanPrivateIdentifier(parser); + + case Token.WhiteSpace: + advanceChar(parser); + break; + + case Token.CarriageReturn: + state |= LexerState.NewLine | LexerState.LastIsCR; + scanNewLine(parser); + break; + + case Token.LineFeed: + consumeLineFeed(parser, state); + state = (state & ~LexerState.LastIsCR) | LexerState.NewLine; + break; + + // `<`, `<=`, `<<`, `<<=`, `</`, `<!--` + case Token.LessThan: + let ch = advanceChar(parser); + if (parser.index < parser.end) { + if (ch === Chars.LessThan) { + if (parser.index < parser.end && advanceChar(parser) === Chars.EqualSign) { + advanceChar(parser); + return Token.ShiftLeftAssign; + } + return Token.ShiftLeft; + } else if (ch === Chars.EqualSign) { + advanceChar(parser); + return Token.LessThanOrEqual; + } + if (ch === Chars.Exclamation) { + // Treat HTML begin-comment as comment-till-end-of-line. + const index = parser.index + 1; + if ( + index + 1 < parser.end && + source.charCodeAt(index) === Chars.Hyphen && + source.charCodeAt(index + 1) == Chars.Hyphen + ) { + parser.column += 3; + parser.currentChar = source.charCodeAt((parser.index += 3)); + state = skipSingleHTMLComment( + parser, + source, + state, + context, + CommentType.HTMLOpen, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + startPos = parser.tokenPos; + startLine = parser.linePos; + startColumn = parser.colPos; + continue; + } + return Token.LessThan; + } + if (ch === Chars.Slash) { + if ((context & Context.OptionsJSX) < 1) return Token.LessThan; + const index = parser.index + 1; + + // Check that it's not a comment start. + if (index < parser.end) { + ch = source.charCodeAt(index); + if (ch === Chars.Asterisk || ch === Chars.Slash) break; + } + advanceChar(parser); + return Token.JSXClose; + } + } + return Token.LessThan; + + // `=`, `==`, `===`, `=>` + case Token.Assign: { + advanceChar(parser); + + const ch = parser.currentChar; + + if (ch === Chars.EqualSign) { + if (advanceChar(parser) === Chars.EqualSign) { + advanceChar(parser); + return Token.StrictEqual; + } + return Token.LooseEqual; + } + if (ch === Chars.GreaterThan) { + advanceChar(parser); + return Token.Arrow; + } + + return Token.Assign; + } + + // `!`, `!=`, `!==` + case Token.Negate: + if (advanceChar(parser) !== Chars.EqualSign) { + return Token.Negate; + } + if (advanceChar(parser) !== Chars.EqualSign) { + return Token.LooseNotEqual; + } + advanceChar(parser); + return Token.StrictNotEqual; + + // `%`, `%=` + case Token.Modulo: + if (advanceChar(parser) !== Chars.EqualSign) return Token.Modulo; + advanceChar(parser); + return Token.ModuloAssign; + + // `*`, `**`, `*=`, `**=` + case Token.Multiply: { + advanceChar(parser); + + if (parser.index >= parser.end) return Token.Multiply; + + const ch = parser.currentChar; + + if (ch === Chars.EqualSign) { + advanceChar(parser); + return Token.MultiplyAssign; + } + + if (ch !== Chars.Asterisk) return Token.Multiply; + + if (advanceChar(parser) !== Chars.EqualSign) return Token.Exponentiate; + + advanceChar(parser); + + return Token.ExponentiateAssign; + } + + // `^`, `^=` + case Token.BitwiseXor: + if (advanceChar(parser) !== Chars.EqualSign) return Token.BitwiseXor; + advanceChar(parser); + return Token.BitwiseXorAssign; + + // `+`, `++`, `+=` + case Token.Add: { + advanceChar(parser); + + const ch = parser.currentChar; + + if (ch === Chars.Plus) { + advanceChar(parser); + return Token.Increment; + } + + if (ch === Chars.EqualSign) { + advanceChar(parser); + return Token.AddAssign; + } + + return Token.Add; + } + + // `-`, `--`, `-=`, `-->` + case Token.Subtract: { + advanceChar(parser); + + const ch = parser.currentChar; + + if (ch === Chars.Hyphen) { + advanceChar(parser); + if ((state & LexerState.NewLine || isStartOfLine) && parser.currentChar === Chars.GreaterThan) { + if ((context & Context.OptionsWebCompat) === 0) report(parser, Errors.HtmlCommentInWebCompat); + advanceChar(parser); + state = skipSingleHTMLComment( + parser, + source, + state, + context, + CommentType.HTMLClose, + startPos, + startLine, + startColumn + ); + startPos = parser.tokenPos; + startLine = parser.linePos; + startColumn = parser.colPos; + continue; + } + + return Token.Decrement; + } + + if (ch === Chars.EqualSign) { + advanceChar(parser); + return Token.SubtractAssign; + } + + return Token.Subtract; + } + + // `/`, `/=`, `/>`, '/*..*/' + case Token.Divide: { + advanceChar(parser); + if (parser.index < parser.end) { + const ch = parser.currentChar; + if (ch === Chars.Slash) { + advanceChar(parser); + state = skipSingleLineComment( + parser, + source, + state, + CommentType.Single, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + startPos = parser.tokenPos; + startLine = parser.linePos; + startColumn = parser.colPos; + continue; + } + if (ch === Chars.Asterisk) { + advanceChar(parser); + state = skipMultiLineComment(parser, source, state) as LexerState; + startPos = parser.tokenPos; + startLine = parser.linePos; + startColumn = parser.colPos; + continue; + } + if (context & Context.AllowRegExp) { + return scanRegularExpression(parser, context); + } + if (ch === Chars.EqualSign) { + advanceChar(parser); + return Token.DivideAssign; + } + } + + return Token.Divide; + } + + // `.`, `...`, `.123` (numeric literal) + case Token.Period: + const next = advanceChar(parser); + if (next >= Chars.Zero && next <= Chars.Nine) + return scanNumber(parser, context, NumberKind.Float | NumberKind.Decimal); + if (next === Chars.Period) { + const index = parser.index + 1; + if (index < parser.end && source.charCodeAt(index) === Chars.Period) { + parser.column += 2; + parser.currentChar = source.charCodeAt((parser.index += 2)); + return Token.Ellipsis; + } + } + return Token.Period; + + // `|`, `||`, `|=`, `||=` + case Token.BitwiseOr: { + advanceChar(parser); + + const ch = parser.currentChar; + + if (ch === Chars.VerticalBar) { + advanceChar(parser); + + if (parser.currentChar === Chars.EqualSign) { + advanceChar(parser); + return Token.LogicalOrAssign; + } + + return Token.LogicalOr; + } + if (ch === Chars.EqualSign) { + advanceChar(parser); + return Token.BitwiseOrAssign; + } + + return Token.BitwiseOr; + } + + // `>`, `>=`, `>>`, `>>>`, `>>=`, `>>>=` + case Token.GreaterThan: { + advanceChar(parser); + + const ch = parser.currentChar; + + if (ch === Chars.EqualSign) { + advanceChar(parser); + return Token.GreaterThanOrEqual; + } + + if (ch !== Chars.GreaterThan) return Token.GreaterThan; + + advanceChar(parser); + + if (parser.index < parser.end) { + const ch = parser.currentChar; + + if (ch === Chars.GreaterThan) { + if (advanceChar(parser) === Chars.EqualSign) { + advanceChar(parser); + return Token.LogicalShiftRightAssign; + } + return Token.LogicalShiftRight; + } + if (ch === Chars.EqualSign) { + advanceChar(parser); + return Token.ShiftRightAssign; + } + } + + return Token.ShiftRight; + } + + // `&`, `&&`, `&=`, `&&=` + case Token.BitwiseAnd: { + advanceChar(parser); + + const ch = parser.currentChar; + + if (ch === Chars.Ampersand) { + advanceChar(parser); + + if (parser.currentChar === Chars.EqualSign) { + advanceChar(parser); + return Token.LogicalAndAssign; + } + + return Token.LogicalAnd; + } + + if (ch === Chars.EqualSign) { + advanceChar(parser); + return Token.BitwiseAndAssign; + } + + return Token.BitwiseAnd; + } + + // `?`, `??`, `?.`, `??=` + case Token.QuestionMark: { + let ch = advanceChar(parser); + if (ch === Chars.QuestionMark) { + advanceChar(parser); + + if (parser.currentChar === Chars.EqualSign) { + advanceChar(parser); + return Token.CoalesceAssign; + } + + return Token.Coalesce; + } + + if (ch === Chars.Period) { + const index = parser.index + 1; + // Check that it's not followed by any numbers + if (index < parser.end) { + ch = source.charCodeAt(index); + if (!(ch >= Chars.Zero && ch <= Chars.Nine)) { + advanceChar(parser); + return Token.QuestionMarkPeriod; + } + } + } + + return Token.QuestionMark; + } + + default: + // unreachable + } + } else { + if ((char ^ Chars.LineSeparator) <= 1) { + state = (state & ~LexerState.LastIsCR) | LexerState.NewLine; + scanNewLine(parser); + continue; + } + + if ((char & 0xfc00) === 0xd800 || ((unicodeLookup[(char >>> 5) + 34816] >>> char) & 31 & 1) !== 0) { + if ((char & 0xfc00) === 0xdc00) { + char = ((char & 0x3ff) << 10) | (char & 0x3ff) | 0x10000; + if (((unicodeLookup[(char >>> 5) + 0] >>> char) & 31 & 1) === 0) { + report(parser, Errors.IllegalCharacter, fromCodePoint(char)); + } + parser.index++; + parser.currentChar = char; + } + + parser.column++; + parser.tokenValue = ''; + return scanIdentifierSlowCase(parser, context, /* hasEscape */ 0, /* canBeKeyword */ 0); + } + + if (isExoticECMAScriptWhitespace(char)) { + advanceChar(parser); + continue; + } + + // Invalid ASCII code point/unit + report(parser, Errors.IllegalCharacter, fromCodePoint(char)); + } + } + return Token.EOF; +} diff --git a/node_modules/meriyah/src/lexer/string.ts b/node_modules/meriyah/src/lexer/string.ts new file mode 100644 index 0000000..2519c38 --- /dev/null +++ b/node_modules/meriyah/src/lexer/string.ts @@ -0,0 +1,242 @@ +import { ParserState, Context, Flags } from '../common'; +import { Token } from '../token'; +import { Chars } from '../chars'; +import { report, Errors } from '../errors'; +import { toHex, advanceChar, fromCodePoint } from './common'; +import { CharTypes, CharFlags } from './charClassifier'; +// Intentionally negative +export const enum Escape { + Empty = -1, + StrictOctal = -2, + EightOrNine = -3, + InvalidHex = -4, + OutOfRange = -5 +} + +/** + * Scan a string token. + */ +export function scanString(parser: ParserState, context: Context, quote: number): Token { + const { index: start } = parser; + + let ret: string | void = ''; + let char = advanceChar(parser); + let marker = parser.index; // Consumes the quote + + while ((CharTypes[char] & CharFlags.LineTerminator) === 0) { + if (char === quote) { + ret += parser.source.slice(marker, parser.index); + advanceChar(parser); // skip closing quote + if (context & Context.OptionsRaw) parser.tokenRaw = parser.source.slice(start, parser.index); + parser.tokenValue = ret; + return Token.StringLiteral; + } + + if ((char & 8) === 8 && char === Chars.Backslash) { + ret += parser.source.slice(marker, parser.index); + char = advanceChar(parser); + + if (char < 0x7f || char === Chars.LineSeparator || char === Chars.ParagraphSeparator) { + const code = parseEscape(parser, context, char); + if (code >= 0) ret += fromCodePoint(code); + else handleStringError(parser, code as Escape, /* isTemplate */ 0); + } else { + ret += fromCodePoint(char); + } + marker = parser.index + 1; + } + + if (parser.index >= parser.end) report(parser, Errors.UnterminatedString); + + char = advanceChar(parser); + } + + report(parser, Errors.UnterminatedString); +} + +// TODO! Use table lookup + +export function parseEscape(parser: ParserState, context: Context, first: number): number { + switch (first) { + // https://tc39.github.io/ecma262/#prod-SingleEscapeCharacter + // one of ' " \ b f n r t v + case Chars.LowerB: + return Chars.Backspace; + case Chars.LowerF: + return Chars.FormFeed; + case Chars.LowerR: + return Chars.CarriageReturn; + case Chars.LowerN: + return Chars.LineFeed; + case Chars.LowerT: + return Chars.Tab; + case Chars.LowerV: + return Chars.VerticalTab; + + // Line continuations + case Chars.CarriageReturn: { + if (parser.index < parser.end) { + const nextChar = parser.source.charCodeAt(parser.index + 1); + if (nextChar === Chars.LineFeed) { + parser.index = parser.index + 1; + parser.currentChar = nextChar; + } + } + } + // falls through + + case Chars.LineFeed: + case Chars.LineSeparator: + case Chars.ParagraphSeparator: + parser.column = -1; + parser.line++; + return Escape.Empty; + + // Null character, octals + case Chars.Zero: + case Chars.One: + case Chars.Two: + case Chars.Three: { + let code = first - Chars.Zero; + let index = parser.index + 1; + let column = parser.column + 1; + + if (index < parser.end) { + const next = parser.source.charCodeAt(index); + + if ((CharTypes[next] & CharFlags.Octal) === 0) { + // Verify that it's `\0` if we're in strict mode. + if ((code !== 0 || CharTypes[next] & CharFlags.ImplicitOctalDigits) && context & Context.Strict) + return Escape.StrictOctal; + } else if (context & Context.Strict) { + return Escape.StrictOctal; + } else { + parser.currentChar = next; + code = (code << 3) | (next - Chars.Zero); + index++; + column++; + if (index < parser.end) { + const next = parser.source.charCodeAt(index); + + if (CharTypes[next] & CharFlags.Octal) { + parser.currentChar = next; + code = (code << 3) | (next - Chars.Zero); + index++; + column++; + } + } + + parser.flags |= Flags.Octals; + + parser.index = index - 1; + parser.column = column - 1; + } + } + + return code; + } + + case Chars.Four: + case Chars.Five: + case Chars.Six: + case Chars.Seven: { + if (context & Context.Strict) return Escape.StrictOctal; + + let code = first - Chars.Zero; + const index = parser.index + 1; + const column = parser.column + 1; + + if (index < parser.end) { + const next = parser.source.charCodeAt(index); + + if (CharTypes[next] & CharFlags.Octal) { + code = (code << 3) | (next - Chars.Zero); + parser.currentChar = next; + parser.index = index; + parser.column = column; + } + } + + parser.flags |= Flags.Octals; + + return code; + } + + // HexEscapeSequence + // \x HexDigit HexDigit + case Chars.LowerX: { + const ch1 = advanceChar(parser); + if ((CharTypes[ch1] & CharFlags.Hex) === 0) return Escape.InvalidHex; + const hi = toHex(ch1); + const ch2 = advanceChar(parser); + if ((CharTypes[ch2] & CharFlags.Hex) === 0) return Escape.InvalidHex; + const lo = toHex(ch2); + + return (hi << 4) | lo; + } + + // UnicodeEscapeSequence + // \u HexDigit HexDigit HexDigit HexDigit + // \u { HexDigit HexDigit HexDigit ... } + case Chars.LowerU: { + const ch = advanceChar(parser); + + if (parser.currentChar === Chars.LeftBrace) { + let code = 0; + while ((CharTypes[advanceChar(parser)] & CharFlags.Hex) !== 0) { + code = (code << 4) | toHex(parser.currentChar); + if (code > Chars.NonBMPMax) return Escape.OutOfRange; + } + + if (parser.currentChar < 1 || (parser.currentChar as number) !== Chars.RightBrace) { + return Escape.InvalidHex; + } + return code; + } else { + if ((CharTypes[ch] & CharFlags.Hex) === 0) return Escape.InvalidHex; // first one is mandatory + const ch2 = parser.source.charCodeAt(parser.index + 1); + if ((CharTypes[ch2] & CharFlags.Hex) === 0) return Escape.InvalidHex; + const ch3 = parser.source.charCodeAt(parser.index + 2); + if ((CharTypes[ch3] & CharFlags.Hex) === 0) return Escape.InvalidHex; + const ch4 = parser.source.charCodeAt(parser.index + 3); + if ((CharTypes[ch4] & CharFlags.Hex) === 0) return Escape.InvalidHex; + + parser.index += 3; + parser.column += 3; + + parser.currentChar = parser.source.charCodeAt(parser.index); + + return (toHex(ch) << 12) | (toHex(ch2) << 8) | (toHex(ch3) << 4) | toHex(ch4); + } + } + + // `8`, `9` (invalid escapes) + case Chars.Eight: + case Chars.Nine: + if ((context & Context.OptionsWebCompat) === 0) return Escape.EightOrNine; + + default: + return first; + } +} + +export function handleStringError(state: ParserState, code: Escape, isTemplate: 0 | 1): void { + switch (code) { + case Escape.Empty: + return; + + case Escape.StrictOctal: + report(state, isTemplate ? Errors.TemplateOctalLiteral : Errors.StrictOctalEscape); + + case Escape.EightOrNine: + report(state, Errors.InvalidEightAndNine); + + case Escape.InvalidHex: + report(state, Errors.InvalidHexEscapeSequence); + + case Escape.OutOfRange: + report(state, Errors.UnicodeOverflow); + + default: + } +} diff --git a/node_modules/meriyah/src/lexer/template.ts b/node_modules/meriyah/src/lexer/template.ts new file mode 100644 index 0000000..0eeda59 --- /dev/null +++ b/node_modules/meriyah/src/lexer/template.ts @@ -0,0 +1,108 @@ +import { ParserState, Context } from '../common'; +import { Token } from '../token'; +import { Chars } from '../chars'; +import { advanceChar, fromCodePoint } from './common'; +import { parseEscape, Escape, handleStringError } from './string'; +import { report, Errors } from '../errors'; + +/** + * Scan a template section. It can start either from the quote or closing brace. + */ +export function scanTemplate(parser: ParserState, context: Context): Token { + const { index: start } = parser; + let token: Token = Token.TemplateSpan; + let ret: string | void = ''; + + let char = advanceChar(parser); + + while (char !== Chars.Backtick) { + if (char === Chars.Dollar && parser.source.charCodeAt(parser.index + 1) === Chars.LeftBrace) { + advanceChar(parser); // Skip: '}' + token = Token.TemplateContinuation; + break; + } else if ((char & 8) === 8 && char === Chars.Backslash) { + char = advanceChar(parser); + if (char > 0x7e) { + ret += fromCodePoint(char); + } else { + const code = parseEscape(parser, context | Context.Strict, char); + if (code >= 0) { + ret += fromCodePoint(code); + } else if (code !== Escape.Empty && context & Context.TaggedTemplate) { + ret = undefined; + char = scanBadTemplate(parser, char); + if (char < 0) token = Token.TemplateContinuation; + break; + } else { + handleStringError(parser, code as Escape, /* isTemplate */ 1); + } + } + } else { + if ( + parser.index < parser.end && + char === Chars.CarriageReturn && + parser.source.charCodeAt(parser.index) === Chars.LineFeed + ) { + ret += fromCodePoint(char); + parser.currentChar = parser.source.charCodeAt(++parser.index); + } + + if (((char & 83) < 3 && char === Chars.LineFeed) || (char ^ Chars.LineSeparator) <= 1) { + parser.column = -1; + parser.line++; + } + ret += fromCodePoint(char); + } + if (parser.index >= parser.end) report(parser, Errors.UnterminatedTemplate); + char = advanceChar(parser); + } + + advanceChar(parser); // Consume the quote or opening brace + parser.tokenValue = ret; + + parser.tokenRaw = parser.source.slice(start + 1, parser.index - (token === Token.TemplateSpan ? 1 : 2)); + + return token; +} + +/** + * Scans looser template segment + * + * @param parser Parser state + * @param ch Code point + */ +function scanBadTemplate(parser: ParserState, ch: number): number { + while (ch !== Chars.Backtick) { + switch (ch) { + case Chars.Dollar: { + const index = parser.index + 1; + if (index < parser.end && parser.source.charCodeAt(index) === Chars.LeftBrace) { + parser.index = index; + parser.column++; + return -ch; + } + break; + } + case Chars.LineFeed: + case Chars.LineSeparator: + case Chars.ParagraphSeparator: + parser.column = -1; + parser.line++; + // falls through + + default: + // do nothing + } + if (parser.index >= parser.end) report(parser, Errors.UnterminatedTemplate); + ch = advanceChar(parser); + } + + return ch; +} + +export function scanTemplateTail(parser: ParserState, context: Context): Token { + if (parser.index >= parser.end) report(parser, Errors.Unexpected); + parser.index--; + parser.column--; + return scanTemplate(parser, context); +} diff --git a/node_modules/meriyah/src/meriyah.ts b/node_modules/meriyah/src/meriyah.ts new file mode 100644 index 0000000..4f762ad --- /dev/null +++ b/node_modules/meriyah/src/meriyah.ts @@ -0,0 +1,29 @@ +import { Context } from './common'; +import { parseSource, Options } from './parser'; +import * as ESTree from './estree'; +// Current version +import * as meta from '../package.json'; +const version: string = meta.version; + +/** + * Parse a script, optionally with various options. + */ +export function parseScript(source: string, options?: Options): ESTree.Program { + return parseSource(source, options, Context.None); +} + +/** + * Parse a module, optionally with various options. + */ +export function parseModule(source: string, options?: Options): ESTree.Program { + return parseSource(source, options, Context.Strict | Context.Module); +} + +/** + * Parse a module or a script, optionally with various options. + */ +export function parse(source: string, options?: Options): ESTree.Program { + return parseSource(source, options, Context.None); +} + +export { Options, ESTree, version }; diff --git a/node_modules/meriyah/src/parser.ts b/node_modules/meriyah/src/parser.ts new file mode 100644 index 0000000..d5b4a51 --- /dev/null +++ b/node_modules/meriyah/src/parser.ts @@ -0,0 +1,9165 @@ +import { nextToken, skipHashBang } from './lexer'; +import { Token, KeywordDescTable } from './token'; +import * as ESTree from './estree'; +import { report, reportMessageAt, reportScopeError, Errors } from './errors'; +import { scanTemplateTail } from './lexer/template'; +import { scanJSXIdentifier, scanJSXToken, scanJSXAttributeValue } from './lexer/jsx'; +import { + Context, + ParserState, + PropertyKind, + Origin, + consumeOpt, + consume, + Flags, + OnComment, + OnToken, + pushComment, + pushToken, + reinterpretToPattern, + DestructuringKind, + AssignmentKind, + BindingKind, + validateBindingIdentifier, + validateFunctionName, + isStrictReservedWord, + optionalBit, + matchOrInsertSemicolon, + isPropertyWithPrivateFieldKey, + isValidLabel, + validateAndDeclareLabel, + finishNode, + HoistedClassFlags, + HoistedFunctionFlags, + createScope, + addChildScope, + ScopeKind, + ScopeState, + addVarName, + addBlockName, + addBindingToExports, + declareUnboundVariable, + isEqualTagName, + isValidStrictMode, + createArrowHeadParsingScope, + addVarOrBlock, + isValidIdentifier, + classifyIdentifier +} from './common'; + +/** + * Create a new parser instance + */ + +export function create( + source: string, + sourceFile: string | void, + onComment: OnComment | void, + onToken: OnToken | void +): ParserState { + return { + /** + * The source code to be parsed + */ + source, + + /** + * The mutable parser flags, in case any flags need passed by reference. + */ + flags: Flags.None, + + /** + * The current index + */ + index: 0, + + /** + * Beginning of current line + */ + line: 1, + + /** + * Beginning of current column + */ + column: 0, + + /** + * Start position of whitespace before current token + */ + startPos: 0, + + /** + * The end of the source code + */ + end: source.length, + + /** + * Start position of text of current token + */ + tokenPos: 0, + + /** + * Start position of the colum before newline + */ + startColumn: 0, + + /** + * Position in the input code of the first character after the last newline + */ + colPos: 0, + + /** + * The number of newlines + */ + linePos: 1, + + /** + * Start position of text of current token + */ + startLine: 1, + + /** + * Used together with source maps. File containing the code being parsed + */ + + sourceFile, + + /** + * Holds the scanned token value + */ + tokenValue: '', + + /** + * The current token in the stream to consume + */ + token: Token.EOF, + + /** + * Holds the raw text that have been scanned by the lexer + */ + tokenRaw: '', + + /** + * Holds the regExp info text that have been collected by the lexer + */ + tokenRegExp: void 0, + + /** + * The code point at the current index + */ + currentChar: source.charCodeAt(0), + + /** + * https://tc39.es/ecma262/#sec-module-semantics-static-semantics-exportednames + */ + exportedNames: [], + + /** + * https://tc39.es/ecma262/#sec-exports-static-semantics-exportedbindings + */ + + exportedBindings: [], + + /** + * Assignable state + */ + assignable: 1, + + /** + * Destructuring state + */ + destructible: 0, + + /** + * Holds either a function or array used on every comment + */ + onComment, + + /** + * Holds either a function or array used on every token + */ + onToken, + + /** + * Holds leading decorators before "export" or "class" keywords + */ + leadingDecorators: [] + }; +} + +/** + * The parser options. + */ +export interface Options { + // Allow module code + module?: boolean; + // Enable stage 3 support (ESNext) + next?: boolean; + // Enable start and end offsets to each node + ranges?: boolean; + // Enable web compatibility + webcompat?: boolean; + // Enable line/column location information to each node + loc?: boolean; + // Attach raw property to each literal and identifier node + raw?: boolean; + // Enabled directives + directives?: boolean; + // Allow return in the global scope + globalReturn?: boolean; + // Enable implied strict mode + impliedStrict?: boolean; + // Enable non-standard parenthesized expression node + preserveParens?: boolean; + // Enable lexical binding and scope tracking + lexical?: boolean; + // Adds a source attribute in every node’s loc object when the locations option is `true` + source?: string; + // Distinguish Identifier from IdentifierPattern + identifierPattern?: boolean; + // Enable React JSX parsing + jsx?: boolean; + // Allow edge cases that deviate from the spec + specDeviation?: boolean; + // Allows comment extraction. Accepts either a a callback function or an array + onComment?: OnComment; + // Allows token extraction. Accepts either a a callback function or an array + onToken?: OnToken; + // Creates unique key for in ObjectPattern when key value are same + uniqueKeyInPattern?: boolean; +} + +/** + * Consumes a sequence of tokens and produces an syntax tree + */ +export function parseSource(source: string, options: Options | void, context: Context): ESTree.Program { + let sourceFile = ''; + let onComment; + let onToken; + if (options != null) { + if (options.module) context |= Context.Module | Context.Strict; + if (options.next) context |= Context.OptionsNext; + if (options.loc) context |= Context.OptionsLoc; + if (options.ranges) context |= Context.OptionsRanges; + if (options.uniqueKeyInPattern) context |= Context.OptionsUniqueKeyInPattern; + if (options.lexical) context |= Context.OptionsLexical; + if (options.webcompat) context |= Context.OptionsWebCompat; + if (options.directives) context |= Context.OptionsDirectives | Context.OptionsRaw; + if (options.globalReturn) context |= Context.OptionsGlobalReturn; + if (options.raw) context |= Context.OptionsRaw; + if (options.preserveParens) context |= Context.OptionsPreserveParens; + if (options.impliedStrict) context |= Context.Strict; + if (options.jsx) context |= Context.OptionsJSX; + if (options.identifierPattern) context |= Context.OptionsIdentifierPattern; + if (options.specDeviation) context |= Context.OptionsSpecDeviation; + if (options.source) sourceFile = options.source; + // Accepts either a callback function to be invoked or an array to collect comments (as the node is constructed) + if (options.onComment != null) { + onComment = Array.isArray(options.onComment) ? pushComment(context, options.onComment) : options.onComment; + } + // Accepts either a callback function to be invoked or an array to collect tokens + if (options.onToken != null) { + onToken = Array.isArray(options.onToken) ? pushToken(context, options.onToken) : options.onToken; + } + } + + // Initialize parser state + const parser = create(source, sourceFile, onComment, onToken); + + // See: https://github.com/tc39/proposal-hashbang + if (context & Context.OptionsNext) skipHashBang(parser); + + const scope: ScopeState | undefined = context & Context.OptionsLexical ? createScope() : void 0; + + let body: (ESTree.Statement | ReturnType<typeof parseDirective | typeof parseModuleItem>)[] = []; + + // https://tc39.es/ecma262/#sec-scripts + // https://tc39.es/ecma262/#sec-modules + + let sourceType: 'module' | 'script' = 'script'; + + if (context & Context.Module) { + sourceType = 'module'; + body = parseModuleItemList(parser, context | Context.InGlobal, scope); + + if (scope) { + for (const key in parser.exportedBindings) { + if (key[0] === '#' && !(scope as any)[key]) report(parser, Errors.UndeclaredExportedBinding, key.slice(1)); + } + } + } else { + body = parseStatementList(parser, context | Context.InGlobal, scope); + } + + const node: ESTree.Program = { + type: 'Program', + sourceType, + body + }; + + if (context & Context.OptionsRanges) { + node.start = 0; + node.end = source.length; + node.range = [0, source.length]; + } + + if (context & Context.OptionsLoc) { + node.loc = { + start: { line: 1, column: 0 }, + end: { line: parser.line, column: parser.column } + }; + + if (parser.sourceFile) node.loc.source = sourceFile; + } + + return node; +} + +/** + * Parses statement list items + * + * @param parser Parser object + * @param context Context masks + */ +export function parseStatementList( + parser: ParserState, + context: Context, + scope: ScopeState | undefined +): ESTree.Statement[] { + // StatementList :: + // (StatementListItem)* <end_token> + + nextToken(parser, context | Context.AllowRegExp | Context.AllowEscapedKeyword); + + const statements: ESTree.Statement[] = []; + + while (parser.token === Token.StringLiteral) { + // "use strict" must be the exact literal without escape sequences or line continuation. + const { index, tokenPos, tokenValue, linePos, colPos, token } = parser; + const expr = parseLiteral(parser, context); + if (isValidStrictMode(parser, index, tokenPos, tokenValue)) context |= Context.Strict; + statements.push(parseDirective(parser, context, expr, token, tokenPos, linePos, colPos)); + } + + while (parser.token !== Token.EOF) { + statements.push(parseStatementListItem(parser, context, scope, Origin.TopLevel, {}) as ESTree.Statement); + } + return statements; +} + +/** + * Parse module item list + * + * @see [Link](https://tc39.github.io/ecma262/#prod-ModuleItemList) + * + * @param parser Parser object + * @param context Context masks + */ +export function parseModuleItemList( + parser: ParserState, + context: Context, + scope: ScopeState | undefined +): ReturnType<typeof parseDirective | typeof parseModuleItem>[] { + // ecma262/#prod-Module + // Module : + // ModuleBody? + // + // ecma262/#prod-ModuleItemList + // ModuleBody : + // ModuleItem* + + nextToken(parser, context | Context.AllowRegExp); + + const statements: ReturnType<typeof parseDirective | typeof parseModuleItem>[] = []; + + // Avoid this if we're not going to create any directive nodes. This is likely to be the case + // most of the time, considering the prevalence of strict mode and the fact modules + // are already in strict mode. + if (context & Context.OptionsDirectives) { + while (parser.token === Token.StringLiteral) { + const { tokenPos, linePos, colPos, token } = parser; + statements.push(parseDirective(parser, context, parseLiteral(parser, context), token, tokenPos, linePos, colPos)); + } + } + + while (parser.token !== Token.EOF) { + statements.push(parseModuleItem(parser, context, scope) as ESTree.Statement); + } + return statements; +} + +/** + * Parse module item + * + * @see [Link](https://tc39.github.io/ecma262/#prod-ModuleItem) + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope object + */ + +export function parseModuleItem(parser: ParserState, context: Context, scope: ScopeState | undefined): any { + // Support legacy decorators before export keyword. + parser.leadingDecorators = parseDecorators(parser, context); + + // ecma262/#prod-ModuleItem + // ModuleItem : + // ImportDeclaration + // ExportDeclaration + // StatementListItem + + let moduleItem; + switch (parser.token) { + case Token.ExportKeyword: + moduleItem = parseExportDeclaration(parser, context, scope); + break; + case Token.ImportKeyword: + moduleItem = parseImportDeclaration(parser, context, scope); + break; + default: + moduleItem = parseStatementListItem(parser, context, scope, Origin.TopLevel, {}); + } + + if (parser.leadingDecorators.length) { + report(parser, Errors.InvalidLeadingDecorator); + } + return moduleItem; +} + +/** + * Parse statement list + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope object + */ + +export function parseStatementListItem( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + origin: Origin, + labels: ESTree.Labels +): ESTree.Statement | ESTree.Decorator[] { + // ECMA 262 10th Edition + // StatementListItem[Yield, Return] : + // Statement[?Yield, ?Return] + // Declaration[?Yield] + // + // Declaration[Yield] : + // HoistableDeclaration[?Yield] + // ClassDeclaration[?Yield] + // LexicalDeclaration[In, ?Yield] + // + // HoistableDeclaration[Yield, Default] : + // FunctionDeclaration[?Yield, ?Default] + // GeneratorDeclaration[?Yield, ?Default] + // + // LexicalDeclaration[In, Yield] : + // LetOrConst BindingList[?In, ?Yield] ; + const start = parser.tokenPos; + const line = parser.linePos; + const column = parser.colPos; + + switch (parser.token) { + // HoistableDeclaration[?Yield, ~Default] + case Token.FunctionKeyword: + return parseFunctionDeclaration( + parser, + context, + scope, + origin, + 1, + HoistedFunctionFlags.None, + 0, + start, + line, + column + ); + // @decorator + case Token.Decorator: + // ClassDeclaration[?Yield, ~Default] + case Token.ClassKeyword: + return parseClassDeclaration(parser, context, scope, HoistedClassFlags.None, start, line, column); + // LexicalDeclaration[In, ?Yield] + // LetOrConst BindingList[?In, ?Yield] + case Token.ConstKeyword: + return parseLexicalDeclaration(parser, context, scope, BindingKind.Const, Origin.None, start, line, column); + case Token.LetKeyword: + return parseLetIdentOrVarDeclarationStatement(parser, context, scope, origin, start, line, column); + // ExportDeclaration + case Token.ExportKeyword: + report(parser, Errors.InvalidImportExportSloppy, 'export'); + // ImportDeclaration + case Token.ImportKeyword: + nextToken(parser, context); + switch (parser.token) { + case Token.LeftParen: + return parseImportCallDeclaration(parser, context, start, line, column); + case Token.Period: + return parseImportMetaDeclaration(parser, context, start, line, column); + default: + report(parser, Errors.InvalidImportExportSloppy, 'import'); + } + // async [no LineTerminator here] AsyncArrowBindingIdentifier ... + // async [no LineTerminator here] ArrowFormalParameters ... + case Token.AsyncKeyword: + return parseAsyncArrowOrAsyncFunctionDeclaration(parser, context, scope, origin, labels, 1, start, line, column); + default: + return parseStatement(parser, context, scope, origin, labels, 1, start, line, column); + } +} + +/** + * Parse statement + * + * @param parser Parser object + * @param context Context masks + * @param allowFuncDecl Allow / disallow func statement + */ + +export function parseStatement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + origin: Origin, + labels: ESTree.Labels, + allowFuncDecl: 0 | 1, + start: number, + line: number, + column: number +): ESTree.Statement { + // Statement :: + // Block + // VariableStatement + // EmptyStatement + // ExpressionStatement + // IfStatement + // IterationStatement + // ContinueStatement + // BreakStatement + // ReturnStatement + // WithStatement + // LabelledStatement + // SwitchStatement + // ThrowStatement + // TryStatement + // DebuggerStatement + + switch (parser.token) { + // VariableStatement[?Yield] + case Token.VarKeyword: + return parseVariableStatement(parser, context, scope, Origin.None, start, line, column); + // [+Return] ReturnStatement[?Yield] + case Token.ReturnKeyword: + return parseReturnStatement(parser, context, start, line, column); + case Token.IfKeyword: + return parseIfStatement(parser, context, scope, labels, start, line, column); + case Token.ForKeyword: + return parseForStatement(parser, context, scope, labels, start, line, column); + // BreakableStatement[Yield, Return]: + // IterationStatement[?Yield, ?Return] + // SwitchStatement[?Yield, ?Return] + case Token.DoKeyword: + return parseDoWhileStatement(parser, context, scope, labels, start, line, column); + case Token.WhileKeyword: + return parseWhileStatement(parser, context, scope, labels, start, line, column); + case Token.SwitchKeyword: + return parseSwitchStatement(parser, context, scope, labels, start, line, column); + case Token.Semicolon: + // EmptyStatement + return parseEmptyStatement(parser, context, start, line, column); + // BlockStatement[?Yield, ?Return] + case Token.LeftBrace: + return parseBlock( + parser, + context, + scope ? addChildScope(scope, ScopeKind.Block) : scope, + labels, + start, + line, + column + ) as ESTree.Statement; + + // ThrowStatement[?Yield] + case Token.ThrowKeyword: + return parseThrowStatement(parser, context, start, line, column); + case Token.BreakKeyword: + // BreakStatement[?Yield] + return parseBreakStatement(parser, context, labels, start, line, column); + // ContinueStatement[?Yield] + case Token.ContinueKeyword: + return parseContinueStatement(parser, context, labels, start, line, column); + // TryStatement[?Yield, ?Return] + case Token.TryKeyword: + return parseTryStatement(parser, context, scope, labels, start, line, column); + // WithStatement[?Yield, ?Return] + case Token.WithKeyword: + return parseWithStatement(parser, context, scope, labels, start, line, column); + case Token.DebuggerKeyword: + // DebuggerStatement + return parseDebuggerStatement(parser, context, start, line, column); + case Token.AsyncKeyword: + return parseAsyncArrowOrAsyncFunctionDeclaration(parser, context, scope, origin, labels, 0, start, line, column); + // Miscellaneous error cases arguably better caught here than elsewhere + case Token.CatchKeyword: + report(parser, Errors.CatchWithoutTry); + case Token.FinallyKeyword: + report(parser, Errors.FinallyWithoutTry); + case Token.FunctionKeyword: + // FunctionDeclaration & ClassDeclaration is forbidden by lookahead + // restriction in an arbitrary statement position. + report( + parser, + context & Context.Strict + ? Errors.StrictFunction + : (context & Context.OptionsWebCompat) < 1 + ? Errors.WebCompatFunction + : Errors.SloppyFunction + ); + case Token.ClassKeyword: + report(parser, Errors.ClassForbiddenAsStatement); + + default: + return parseExpressionOrLabelledStatement( + parser, + context, + scope, + origin, + labels, + allowFuncDecl, + start, + line, + column + ); + } +} + +/** + * Parses either expression or labeled statement + * + * @param parser Parser object + * @param context Context masks + * @param allowFuncDecl Allow / disallow func statement + */ + +export function parseExpressionOrLabelledStatement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + origin: Origin, + labels: ESTree.Labels, + allowFuncDecl: 0 | 1, + start: number, + line: number, + column: number +): ESTree.ExpressionStatement | ESTree.LabeledStatement { + // ExpressionStatement | LabelledStatement :: + // Expression ';' + // Identifier ':' Statement + // + // ExpressionStatement[Yield] : + // [lookahead notin {{, function, class, let [}] Expression[In, ?Yield] ; + + const { tokenValue, token } = parser; + + let expr: ESTree.Expression; + + switch (token) { + case Token.LetKeyword: + expr = parseIdentifier(parser, context, 0); + if (context & Context.Strict) report(parser, Errors.UnexpectedLetStrictReserved); + + // "let" followed by either "[", "{" or an identifier means a lexical + // declaration, which should not appear here. + // However, ASI may insert a line break before an identifier or a brace. + if (parser.token === Token.LeftBracket) report(parser, Errors.RestrictedLetProduction); + + break; + + default: + expr = parsePrimaryExpression( + parser, + context, + BindingKind.Empty, + 0, + 1, + 0, + 0, + 1, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + } + + /** LabelledStatement[Yield, Await, Return]: + * + * ExpressionStatement | LabelledStatement :: + * Expression ';' + * Identifier ':' Statement + * + * ExpressionStatement[Yield] : + * [lookahead notin {{, function, class, let [}] Expression[In, ?Yield] ; + */ + if (token & Token.IsIdentifier && parser.token === Token.Colon) { + return parseLabelledStatement( + parser, + context, + scope, + origin, + labels, + tokenValue, + expr, + token, + allowFuncDecl, + start, + line, + column + ); + } + /** MemberExpression : + * 1. PrimaryExpression + * 2. MemberExpression [ AssignmentExpression ] + * 3. MemberExpression . IdentifierName + * 4. MemberExpression TemplateLiteral + * + * CallExpression : + * 1. MemberExpression Arguments + * 2. CallExpression ImportCall + * 3. CallExpression Arguments + * 4. CallExpression [ AssignmentExpression ] + * 5. CallExpression . IdentifierName + * 6. CallExpression TemplateLiteral + * + * UpdateExpression :: + * ('++' | '--')? LeftHandSideExpression + * + */ + + expr = parseMemberOrUpdateExpression(parser, context, expr, 0, 0, start, line, column); + + /** AssignmentExpression : + * 1. ConditionalExpression + * 2. LeftHandSideExpression = AssignmentExpression + * + */ + + expr = parseAssignmentExpression(parser, context, 0, 0, start, line, column, expr as ESTree.ArgumentExpression); + + /** Sequence expression + * + * Note: The comma operator leads to a sequence expression which is not equivalent + * to the ES Expression, but it's part of the ESTree specs: + * + * https://github.com/estree/estree/blob/master/es5.md#sequenceexpression + * + */ + if (parser.token === Token.Comma) { + expr = parseSequenceExpression(parser, context, 0, start, line, column, expr); + } + + /** + * ExpressionStatement[Yield, Await]: + * [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }]Expression[+In, ?Yield, ?Await] + */ + + return parseExpressionStatement(parser, context, expr, start, line, column); +} + +/** + * Parses block statement + * + * @see [Link](https://tc39.github.io/ecma262/#prod-BlockStatement) + * @see [Link](https://tc39.github.io/ecma262/#prod-Block) + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope object + * @param labels Labels object + * @param start + * @param line + * @param column + * + */ +export function parseBlock( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + labels: ESTree.Labels, + start: number, + line: number, + column: number +): ESTree.BlockStatement { + // Block :: + // '{' StatementList '}' + const body: ESTree.Statement[] = []; + consume(parser, context | Context.AllowRegExp, Token.LeftBrace); + while (parser.token !== Token.RightBrace) { + body.push(parseStatementListItem(parser, context, scope, Origin.BlockStatement, { $: labels }) as any); + } + + consume(parser, context | Context.AllowRegExp, Token.RightBrace); + + return finishNode(parser, context, start, line, column, { + type: 'BlockStatement', + body + }); +} + +/** + * Parses return statement + * + * @see [Link](https://tc39.github.io/ecma262/#prod-ReturnStatement) + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param line + * @param column + */ +export function parseReturnStatement( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.ReturnStatement { + // ReturnStatement :: + // 'return' [no line terminator] Expression? ';' + if ((context & Context.OptionsGlobalReturn) < 1 && context & Context.InGlobal) report(parser, Errors.IllegalReturn); + + nextToken(parser, context | Context.AllowRegExp); + + const argument = + parser.flags & Flags.NewLine || parser.token & Token.IsAutoSemicolon + ? null + : parseExpressions(parser, context, 0, 1, parser.tokenPos, parser.line, parser.column); + + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + + return finishNode(parser, context, start, line, column, { + type: 'ReturnStatement', + argument + }); +} + +/** + * Parses an expression statement + * + * @see [Link](https://tc39.github.io/ecma262/#prod-ExpressionStatement) + * + * @param parser Parser object + * @param context Context masks + * @param expression AST node + * @param start + * @param line + * @param column + */ +export function parseExpressionStatement( + parser: ParserState, + context: Context, + expression: ESTree.Expression, + start: number, + line: number, + column: number +): ESTree.ExpressionStatement { + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + return finishNode(parser, context, start, line, column, { + type: 'ExpressionStatement', + expression + }); +} + +/** + * Parses either expression or labeled statement + * + * @param parser Parser object + * @param context Context masks + * @param expr ESTree AST node + * @param token Token to validate + * @param allowFuncDecl Allow / disallow func statement + * @param start + * @param line + * @param column + * + */ +export function parseLabelledStatement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + origin: Origin, + labels: ESTree.Labels, + value: string, + expr: ESTree.Identifier | ESTree.Expression, + token: Token, + allowFuncDecl: 0 | 1, + start: number, + line: number, + column: number +): ESTree.LabeledStatement { + // LabelledStatement :: + // Expression ';' + // Identifier ':' Statement + + validateBindingIdentifier(parser, context, BindingKind.None, token, 1); + validateAndDeclareLabel(parser, labels, value); + + nextToken(parser, context | Context.AllowRegExp); // skip: ':' + + const body = + allowFuncDecl && + (context & Context.Strict) < 1 && + context & Context.OptionsWebCompat && + // In sloppy mode, Annex B.3.2 allows labelled function declarations. + // Otherwise it's a parse error. + parser.token === Token.FunctionKeyword + ? parseFunctionDeclaration( + parser, + context, + addChildScope(scope, ScopeKind.Block), + origin, + 0, + HoistedFunctionFlags.None, + 0, + parser.tokenPos, + parser.linePos, + parser.colPos + ) + : parseStatement( + parser, + context, + scope, + origin, + labels, + allowFuncDecl, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + + return finishNode(parser, context, start, line, column, { + type: 'LabeledStatement', + label: expr as ESTree.Identifier, + body + }); +} + +/** + * Parses either async ident, async function or async arrow in + * statement position + * + * @param parser Parser object + * @param context Context masks + * @param labels + * @param allowFuncDecl Allow / disallow func statement + * @param start Start position of current AST node + * @param start + * @param line + * @param column + */ + +export function parseAsyncArrowOrAsyncFunctionDeclaration( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + origin: Origin, + labels: ESTree.Labels, + allowFuncDecl: 0 | 1, + start: number, + line: number, + column: number +): ESTree.ExpressionStatement | ESTree.LabeledStatement | ESTree.FunctionDeclaration { + // AsyncArrowFunction[In, Yield, Await]: + // async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In] + // CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In] + // + // AsyncArrowBindingIdentifier[Yield]: + // BindingIdentifier[?Yield, +Await] + // + // CoverCallExpressionAndAsyncArrowHead[Yield, Await]: + // MemberExpression[?Yield, ?Await]Arguments[?Yield, ?Await] + // + // AsyncFunctionDeclaration[Yield, Await, Default]: + // async[no LineTerminator here]functionBindingIdentifier[?Yield, ?Await](FormalParameters[~Yield, +Await]){AsyncFunctionBody} + // [+Default]async[no LineTerminator here]function(FormalParameters[~Yield, +Await]){AsyncFunctionBody} + // + // AsyncFunctionBody: + // FunctionBody[~Yield, +Await] + + const { token, tokenValue } = parser; + + let expr: ESTree.Expression = parseIdentifier(parser, context, 0); + + if (parser.token === Token.Colon) { + return parseLabelledStatement( + parser, + context, + scope, + origin, + labels, + tokenValue, + expr, + token, + 1, + start, + line, + column + ); + } + + const asyncNewLine = parser.flags & Flags.NewLine; + + if (!asyncNewLine) { + // async function ... + if (parser.token === Token.FunctionKeyword) { + if (!allowFuncDecl) report(parser, Errors.AsyncFunctionInSingleStatementContext); + + return parseFunctionDeclaration( + parser, + context, + scope, + origin, + 1, + HoistedFunctionFlags.None, + 1, + start, + line, + column + ); + } + + // async Identifier => ... + if ((parser.token & Token.IsIdentifier) === Token.IsIdentifier) { + /** ArrowFunction[In, Yield, Await]: + * ArrowParameters[?Yield, ?Await][no LineTerminator here]=>ConciseBody[?In] + */ + expr = parseAsyncArrowAfterIdent(parser, context, /* assignable */ 1, start, line, column); + if (parser.token === Token.Comma) expr = parseSequenceExpression(parser, context, 0, start, line, column, expr); + + /** + * ExpressionStatement[Yield, Await]: + * [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }]Expression[+In, ?Yield, ?Await] + */ + return parseExpressionStatement(parser, context, expr, start, line, column); + } + } + + /** ArrowFunction[In, Yield, Await]: + * ArrowParameters[?Yield, ?Await][no LineTerminator here]=>ConciseBody[?In] + */ + if (parser.token === Token.LeftParen) { + expr = parseAsyncArrowOrCallExpression( + parser, + context, + expr, + 1, + BindingKind.ArgumentList, + Origin.None, + asyncNewLine, + start, + line, + column + ); + } else { + if (parser.token === Token.Arrow) { + classifyIdentifier(parser, context, token, /* isArrow */ 1); + expr = parseArrowFromIdentifier(parser, context, parser.tokenValue, expr, 0, 1, 0, start, line, column); + } + + parser.assignable = AssignmentKind.Assignable; + } + + /** MemberExpression : + * 1. PrimaryExpression + * 2. MemberExpression [ AssignmentExpression ] + * 3. MemberExpression . IdentifierName + * 4. MemberExpression TemplateLiteral + * + * CallExpression : + * 1. MemberExpression Arguments + * 2. CallExpression ImportCall + * 3. CallExpression Arguments + * 4. CallExpression [ AssignmentExpression ] + * 5. CallExpression . IdentifierName + * 6. CallExpression TemplateLiteral + * + * UpdateExpression :: + * ('++' | '--')? LeftHandSideExpression + */ + + expr = parseMemberOrUpdateExpression(parser, context, expr, 0, 0, start, line, column); + /** Sequence expression + * + * Note: The comma operator leads to a sequence expression which is not equivalent + * to the ES Expression, but it's part of the ESTree specs: + * + * https://github.com/estree/estree/blob/master/es5.md#sequenceexpression + * + */ + if (parser.token === Token.Comma) expr = parseSequenceExpression(parser, context, 0, start, line, column, expr); + + /** AssignmentExpression : + * + * 1. ConditionalExpression + * 2. LeftHandSideExpression = AssignmentExpression + * + */ + expr = parseAssignmentExpression(parser, context, 0, 0, start, line, column, expr as ESTree.ArgumentExpression); + + parser.assignable = AssignmentKind.Assignable; + + /** + * ExpressionStatement[Yield, Await]: + * [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }]Expression[+In, ?Yield, ?Await] + */ + return parseExpressionStatement(parser, context, expr, start, line, column); +} + +/** + * Parse directive node + * + * @see [Link](https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive) + * + * @param parser Parser object + * @param context Context masks + * @param expression AST expression node + * @param token + * @param start Start pos of node + * @param line + * @param column + */ + +export function parseDirective( + parser: ParserState, + context: Context, + expression: ESTree.ArgumentExpression | ESTree.SequenceExpression | ESTree.Expression, + token: Token, + start: number, + line: number, + column: number +): ESTree.ExpressionStatement { + if (token !== Token.Semicolon) { + parser.assignable = AssignmentKind.CannotAssign; + + expression = parseMemberOrUpdateExpression(parser, context, expression, 0, 0, start, line, column); + + if (parser.token !== Token.Semicolon) { + expression = parseAssignmentExpression(parser, context, 0, 0, start, line, column, expression); + + if (parser.token === Token.Comma) { + expression = parseSequenceExpression(parser, context, 0, start, line, column, expression); + } + } + + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + } + + return context & Context.OptionsDirectives && expression.type === 'Literal' && typeof expression.value === 'string' + ? finishNode(parser, context, start, line, column, { + type: 'ExpressionStatement', + expression, + // OptionsRaw is implicitly turned on by OptionsDirectives. + directive: (expression.raw as string).slice(1, -1) + }) + : finishNode(parser, context, start, line, column, { + type: 'ExpressionStatement', + expression + }); +} + +/** + * Parses empty statement + * + * @param parser Parser object + * @param context Context masks + * @param start Start pos of node + * @param line + * @param column + */ + +export function parseEmptyStatement( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.EmptyStatement { + nextToken(parser, context | Context.AllowRegExp); + return finishNode(parser, context, start, line, column, { + type: 'EmptyStatement' + }); +} + +/** + * Parses throw statement + * + * @see [Link](https://tc39.github.io/ecma262/#prod-ThrowStatement) + * + * @param parser Parser object + * @param context Context masks + * @param start Start pos of node +* @param line +* @param column + + */ +export function parseThrowStatement( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.ThrowStatement { + // ThrowStatement :: + // 'throw' Expression ';' + nextToken(parser, context | Context.AllowRegExp); + if (parser.flags & Flags.NewLine) report(parser, Errors.NewlineAfterThrow); + const argument: ESTree.Expression = parseExpressions( + parser, + context, + 0, + 1, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + return finishNode(parser, context, start, line, column, { + type: 'ThrowStatement', + argument + }); +} + +/** + * Parses an if statement with an optional else block + * + * @see [Link](https://tc39.github.io/ecma262/#sec-if-statement) + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope instance + * @param start Start pos of node +* @param line +* @param column + + */ +export function parseIfStatement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + labels: ESTree.Labels, + start: number, + line: number, + column: number +): ESTree.IfStatement { + // IfStatement :: + // 'if' '(' Expression ')' Statement ('else' Statement)? + nextToken(parser, context); + consume(parser, context | Context.AllowRegExp, Token.LeftParen); + parser.assignable = AssignmentKind.Assignable; + const test = parseExpressions(parser, context, 0, 1, parser.tokenPos, parser.line, parser.colPos); + consume(parser, context | Context.AllowRegExp, Token.RightParen); + const consequent = parseConsequentOrAlternative( + parser, + context, + scope, + labels, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + let alternate: ESTree.Statement | null = null; + if (parser.token === Token.ElseKeyword) { + nextToken(parser, context | Context.AllowRegExp); + alternate = parseConsequentOrAlternative( + parser, + context, + scope, + labels, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + } + + return finishNode(parser, context, start, line, column, { + type: 'IfStatement', + test, + consequent, + alternate + }); +} + +/** + * Parse either consequent or alternate. + * + * @param parser Parser object + * @param context Context masks + * @param start Start pos of node + * @param line + * @param column + */ +export function parseConsequentOrAlternative( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + labels: ESTree.Labels, + start: number, + line: number, + column: number +): ESTree.Statement | ESTree.FunctionDeclaration { + return context & Context.Strict || + // Disallow if web compatibility is off + (context & Context.OptionsWebCompat) < 1 || + parser.token !== Token.FunctionKeyword + ? parseStatement( + parser, + context, + scope, + Origin.None, + { $: labels }, + 0, + parser.tokenPos, + parser.linePos, + parser.colPos + ) + : parseFunctionDeclaration( + parser, + context, + addChildScope(scope, ScopeKind.Block), + Origin.None, + 0, + HoistedFunctionFlags.None, + 0, + start, + line, + column + ); +} + +/** + * Parses switch statement + * + * @see [Link](https://tc39.github.io/ecma262/#prod-SwitchStatement) + * + * @param parser Parser object + * @param context Context masks + * @param start Start pos of node + * @param line + * @param column + */ +export function parseSwitchStatement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + labels: ESTree.Labels, + start: number, + line: number, + column: number +): ESTree.SwitchStatement { + // SwitchStatement :: + // 'switch' '(' Expression ')' '{' CaseClause* '}' + // CaseClause :: + // 'case' Expression ':' StatementList + // 'default' ':' StatementList + nextToken(parser, context); + consume(parser, context | Context.AllowRegExp, Token.LeftParen); + const discriminant = parseExpressions(parser, context, 0, 1, parser.tokenPos, parser.linePos, parser.colPos); + consume(parser, context, Token.RightParen); + consume(parser, context, Token.LeftBrace); + const cases: ESTree.SwitchCase[] = []; + let seenDefault: 0 | 1 = 0; + if (scope) scope = addChildScope(scope, ScopeKind.SwitchStatement); + while (parser.token !== Token.RightBrace) { + const { tokenPos, linePos, colPos } = parser; + let test: ESTree.Expression | null = null; + const consequent: ESTree.Statement[] = []; + if (consumeOpt(parser, context | Context.AllowRegExp, Token.CaseKeyword)) { + test = parseExpressions(parser, context, 0, 1, parser.tokenPos, parser.linePos, parser.colPos); + } else { + consume(parser, context | Context.AllowRegExp, Token.DefaultKeyword); + if (seenDefault) report(parser, Errors.MultipleDefaultsInSwitch); + seenDefault = 1; + } + consume(parser, context | Context.AllowRegExp, Token.Colon); + while ( + parser.token !== Token.CaseKeyword && + parser.token !== Token.RightBrace && + parser.token !== Token.DefaultKeyword + ) { + consequent.push( + parseStatementListItem(parser, context | Context.InSwitch, scope, Origin.BlockStatement, { + $: labels + }) as ESTree.Statement + ); + } + + cases.push( + finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'SwitchCase', + test, + consequent + }) + ); + } + + consume(parser, context | Context.AllowRegExp, Token.RightBrace); + return finishNode(parser, context, start, line, column, { + type: 'SwitchStatement', + discriminant, + cases + }); +} + +/** + * Parses while statement + * + * @see [Link](https://tc39.github.io/ecma262/#prod-grammar-notation-WhileStatement) + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param start Start pos of node + * @param line + * @param column + */ +export function parseWhileStatement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + labels: ESTree.Labels, + start: number, + line: number, + column: number +): ESTree.WhileStatement { + // WhileStatement :: + // 'while' '(' Expression ')' Statement + nextToken(parser, context); + consume(parser, context | Context.AllowRegExp, Token.LeftParen); + const test = parseExpressions(parser, context, 0, 1, parser.tokenPos, parser.linePos, parser.colPos); + consume(parser, context | Context.AllowRegExp, Token.RightParen); + const body = parseIterationStatementBody(parser, context, scope, labels); + return finishNode(parser, context, start, line, column, { + type: 'WhileStatement', + test, + body + }); +} + +/** + * Parses iteration statement body + * + * @see [Link](https://tc39.es/ecma262/#sec-iteration-statements) + * + * @param parser Parser object + * @param context Context masks + * @param start Start pos of node + * @param line + * @param column + */ +export function parseIterationStatementBody( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + labels: ESTree.Labels +): ESTree.Statement { + return parseStatement( + parser, + ((context | Context.DisallowIn) ^ Context.DisallowIn) | Context.InIteration, + scope, + Origin.None, + { loop: 1, $: labels }, + 0, + parser.tokenPos, + parser.linePos, + parser.colPos + ); +} + +/** + * Parses the continue statement production + * + * @see [Link](https://tc39.github.io/ecma262/#prod-ContinueStatement) + * + * @param parser Parser object + * @param context Context masks + */ +export function parseContinueStatement( + parser: ParserState, + context: Context, + labels: ESTree.Labels, + start: number, + line: number, + column: number +): ESTree.ContinueStatement { + // ContinueStatement :: + // 'continue' Identifier? ';' + if ((context & Context.InIteration) < 1) report(parser, Errors.IllegalContinue); + nextToken(parser, context); + let label: ESTree.Identifier | undefined | null = null; + if ((parser.flags & Flags.NewLine) < 1 && parser.token & Token.IsIdentifier) { + const { tokenValue } = parser; + label = parseIdentifier(parser, context | Context.AllowRegExp, 0); + if (!isValidLabel(parser, labels, tokenValue, /* requireIterationStatement */ 1)) + report(parser, Errors.UnknownLabel, tokenValue); + } + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + return finishNode(parser, context, start, line, column, { + type: 'ContinueStatement', + label + }); +} + +/** + * Parses the break statement production + * + * @see [Link](https://tc39.github.io/ecma262/#prod-BreakStatement) + * + * @param parser Parser object + * @param context Context masks + * @param start Start pos of node + * @param line + * @param column + */ +export function parseBreakStatement( + parser: ParserState, + context: Context, + labels: ESTree.Labels, + start: number, + line: number, + column: number +): ESTree.BreakStatement { + // BreakStatement :: + // 'break' Identifier? ';' + nextToken(parser, context | Context.AllowRegExp); + let label: ESTree.Identifier | undefined | null = null; + if ((parser.flags & Flags.NewLine) < 1 && parser.token & Token.IsIdentifier) { + const { tokenValue } = parser; + label = parseIdentifier(parser, context | Context.AllowRegExp, 0); + if (!isValidLabel(parser, labels, tokenValue, /* requireIterationStatement */ 0)) + report(parser, Errors.UnknownLabel, tokenValue); + } else if ((context & (Context.InSwitch | Context.InIteration)) < 1) { + report(parser, Errors.IllegalBreak); + } + + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + return finishNode(parser, context, start, line, column, { + type: 'BreakStatement', + label + }); +} + +/** + * Parses with statement + * + * @see [Link](https://tc39.github.io/ecma262/#prod-WithStatement) + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope instance + * @param start Start pos of node + * @param line + * @param column + */ +export function parseWithStatement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + labels: ESTree.Labels, + start: number, + line: number, + column: number +): ESTree.WithStatement { + // WithStatement :: + // 'with' '(' Expression ')' Statement + + nextToken(parser, context); + + if (context & Context.Strict) report(parser, Errors.StrictWith); + + consume(parser, context | Context.AllowRegExp, Token.LeftParen); + const object = parseExpressions(parser, context, 0, 1, parser.tokenPos, parser.linePos, parser.colPos); + consume(parser, context | Context.AllowRegExp, Token.RightParen); + const body = parseStatement( + parser, + context, + scope, + Origin.BlockStatement, + labels, + 0, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + return finishNode(parser, context, start, line, column, { + type: 'WithStatement', + object, + body + }); +} + +/** + * Parses the debugger statement production + * + * @see [Link](https://tc39.github.io/ecma262/#prod-DebuggerStatement) + * + * @param parser Parser object + * @param context Context masks + * @param start Start pos of node + * @param line + * @param column + */ +export function parseDebuggerStatement( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.DebuggerStatement { + // DebuggerStatement :: + // 'debugger' ';' + nextToken(parser, context | Context.AllowRegExp); + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + return finishNode(parser, context, start, line, column, { + type: 'DebuggerStatement' + }); +} + +/** + * Parses try statement + * + * @see [Link](https://tc39.github.io/ecma262/#prod-TryStatement) + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope instance + * @param start Start pos of node + * @param line + * @param column + */ +export function parseTryStatement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + labels: ESTree.Labels, + start: number, + line: number, + column: number +): ESTree.TryStatement { + // TryStatement :: + // 'try' Block Catch + // 'try' Block Finally + // 'try' Block Catch Finally + // + // Catch :: + // 'catch' '(' Identifier ')' Block + // + // Finally :: + // 'finally' Block + + nextToken(parser, context | Context.AllowRegExp); + + const firstScope = scope ? addChildScope(scope, ScopeKind.TryStatement) : void 0; + + const block = parseBlock(parser, context, firstScope, { $: labels }, parser.tokenPos, parser.linePos, parser.colPos); + const { tokenPos, linePos, colPos } = parser; + const handler = consumeOpt(parser, context | Context.AllowRegExp, Token.CatchKeyword) + ? parseCatchBlock(parser, context, scope, labels, tokenPos, linePos, colPos) + : null; + + let finalizer: ESTree.BlockStatement | null = null; + + if (parser.token === Token.FinallyKeyword) { + nextToken(parser, context | Context.AllowRegExp); + const finalizerScope = firstScope ? addChildScope(scope, ScopeKind.CatchStatement) : void 0; + finalizer = parseBlock( + parser, + context, + finalizerScope, + { $: labels }, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + } + + if (!handler && !finalizer) { + report(parser, Errors.NoCatchOrFinally); + } + + return finishNode(parser, context, start, line, column, { + type: 'TryStatement', + block, + handler, + finalizer + }); +} + +/** + * Parses catch block + * + * @see [Link](https://tc39.github.io/ecma262/#prod-Catch) + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope instance + * @param start Start pos of node + * @param line + * @param column + */ +export function parseCatchBlock( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + labels: ESTree.Labels, + start: number, + line: number, + column: number +): ESTree.CatchClause { + let param: ESTree.BindingPattern | ESTree.Identifier | null = null; + let additionalScope: ScopeState | undefined = scope; + + if (consumeOpt(parser, context, Token.LeftParen)) { + /* + * Create a lexical scope around the whole catch clause, + * including the head. + */ + if (scope) scope = addChildScope(scope, ScopeKind.CatchStatement); + + param = parseBindingPattern( + parser, + context, + scope, + (parser.token & Token.IsPatternStart) === Token.IsPatternStart + ? BindingKind.CatchPattern + : BindingKind.CatchIdentifier, + Origin.None, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + + if (parser.token === Token.Comma) { + report(parser, Errors.InvalidCatchParams); + } else if (parser.token === Token.Assign) { + report(parser, Errors.InvalidCatchParamDefault); + } + + consume(parser, context | Context.AllowRegExp, Token.RightParen); + // ES 13.15.7 CatchClauseEvaluation + // + // Step 8 means that the body of a catch block always has an additional + // lexical scope. + if (scope) additionalScope = addChildScope(scope, ScopeKind.CatchBlock); + } + + const body = parseBlock( + parser, + context, + additionalScope, + { $: labels }, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + + return finishNode(parser, context, start, line, column, { + type: 'CatchClause', + param, + body + }); +} + +/** + * Parses do while statement + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope instance + * @param start Start pos of node + * @param line + * @param column + */ +export function parseDoWhileStatement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + labels: ESTree.Labels, + start: number, + line: number, + column: number +): ESTree.DoWhileStatement { + // DoStatement :: + // 'do Statement while ( Expression ) ;' + + nextToken(parser, context | Context.AllowRegExp); + const body = parseIterationStatementBody(parser, context, scope, labels); + consume(parser, context, Token.WhileKeyword); + consume(parser, context | Context.AllowRegExp, Token.LeftParen); + const test = parseExpressions(parser, context, 0, 1, parser.tokenPos, parser.linePos, parser.colPos); + consume(parser, context | Context.AllowRegExp, Token.RightParen); + // ECMA-262, section 11.9 + // The previous token is ) and the inserted semicolon would then be parsed as the terminating semicolon of a do-while statement (13.7.2). + // This cannot be implemented in matchOrInsertSemicolon() because it doesn't know + // this RightRaren is the end of a do-while statement. + consumeOpt(parser, context, Token.Semicolon); + return finishNode(parser, context, start, line, column, { + type: 'DoWhileStatement', + body, + test + }); +} + +/** + * Because we are not doing any backtracking - this parses `let` as an identifier + * or a variable declaration statement. + * + * @see [Link](https://tc39.github.io/ecma262/#sec-declarations-and-the-variable-statement) + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope object + * @param origin Binding origin + * @param start Start pos of node + * @param start Start pos of node + * @param line + * @param column + */ +export function parseLetIdentOrVarDeclarationStatement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + origin: Origin, + start: number, + line: number, + column: number +): ESTree.VariableDeclaration | ESTree.LabeledStatement | ESTree.ExpressionStatement { + const { token, tokenValue } = parser; + let expr: ESTree.Identifier | ESTree.Expression = parseIdentifier(parser, context, 0); + + if (parser.token & (Token.IsIdentifier | Token.IsPatternStart)) { + /* VariableDeclarations :: + * ('let') (Identifier ('=' AssignmentExpression)?)+[','] + */ + + const declarations = parseVariableDeclarationList(parser, context, scope, BindingKind.Let, Origin.None); + + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + + return finishNode(parser, context, start, line, column, { + type: 'VariableDeclaration', + kind: 'let', + declarations + }); + } + // 'Let' as identifier + parser.assignable = AssignmentKind.Assignable; + + if (context & Context.Strict) report(parser, Errors.UnexpectedLetStrictReserved); + + /** LabelledStatement[Yield, Await, Return]: + * + * ExpressionStatement | LabelledStatement :: + * Expression ';' + * Identifier ':' Statement + * + * ExpressionStatement[Yield] : + * [lookahead notin {{, function, class, let [}] Expression[In, ?Yield] ; + */ + + if (parser.token === Token.Colon) { + return parseLabelledStatement(parser, context, scope, origin, {}, tokenValue, expr, token, 0, start, line, column); + } + + /** + * ArrowFunction : + * ArrowParameters => ConciseBody + * + * ConciseBody : + * [lookahead not {] AssignmentExpression + * { FunctionBody } + * + */ + if (parser.token === Token.Arrow) { + let scope: ScopeState | undefined = void 0; + + if (context & Context.OptionsLexical) scope = createArrowHeadParsingScope(parser, context, tokenValue); + + parser.flags = (parser.flags | Flags.SimpleParameterList) ^ Flags.SimpleParameterList; + + expr = parseArrowFunctionExpression(parser, context, scope, [expr], /* isAsync */ 0, start, line, column); + } else { + /** + * UpdateExpression :: + * ('++' | '--')? LeftHandSideExpression + * + * MemberExpression :: + * (PrimaryExpression | FunctionLiteral | ClassLiteral) + * ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)* + * + * CallExpression :: + * (SuperCall | ImportCall) + * ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)* + * + * LeftHandSideExpression :: + * (NewExpression | MemberExpression) ... + */ + + expr = parseMemberOrUpdateExpression(parser, context, expr, 0, 0, start, line, column); + + /** + * AssignmentExpression : + * 1. ConditionalExpression + * 2. LeftHandSideExpression = AssignmentExpression + * + */ + expr = parseAssignmentExpression(parser, context, 0, 0, start, line, column, expr as ESTree.ArgumentExpression); + } + + /** Sequence expression + */ + if (parser.token === Token.Comma) { + expr = parseSequenceExpression(parser, context, 0, start, line, column, expr); + } + + /** + * ExpressionStatement[Yield, Await]: + * [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }]Expression[+In, ?Yield, ?Await] + */ + return parseExpressionStatement(parser, context, expr, start, line, column); +} + +/** + * Parses a `const` or `let` lexical declaration statement + * + * @param parser Parser object + * @param context Context masks + * @param type Binding kind + * @param origin Binding origin + * @param type Binding kind + * @param start Start pos of node + * @param start Start pos of node + * @param line + * @param column + */ +function parseLexicalDeclaration( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + kind: BindingKind, + origin: Origin, + start: number, + line: number, + column: number +): ESTree.VariableDeclaration { + // BindingList :: + // LexicalBinding + // BindingIdentifier + // BindingPattern + nextToken(parser, context); + + const declarations = parseVariableDeclarationList(parser, context, scope, kind, origin); + + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + + return finishNode(parser, context, start, line, column, { + type: 'VariableDeclaration', + kind: kind & BindingKind.Let ? 'let' : 'const', + declarations + }); +} + +/** + * Parses a variable declaration statement + * + * @see [Link](https://tc39.github.io/ecma262/#prod-VariableStatement) + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope object + * @param origin Binding origin + * @param start Start pos of node + * @param start Start pos of node + * @param line + * @param column + */ +export function parseVariableStatement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + origin: Origin, + start: number, + line: number, + column: number +): ESTree.VariableDeclaration { + // VariableDeclarations :: + // ('var') (Identifier ('=' AssignmentExpression)?)+[','] + // + nextToken(parser, context); + const declarations = parseVariableDeclarationList(parser, context, scope, BindingKind.Variable, origin); + + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + return finishNode(parser, context, start, line, column, { + type: 'VariableDeclaration', + kind: 'var', + declarations + }); +} + +/** + * Parses variable declaration list + * + * @see [Link](https://tc39.github.io/ecma262/#prod-VariableDeclarationList) + * + * @param parser Parser object + * @param context Context masks + * @param type Binding kind + * @param origin Binding origin + */ +export function parseVariableDeclarationList( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + kind: BindingKind, + origin: Origin +): ESTree.VariableDeclarator[] { + let bindingCount = 1; + const list: ESTree.VariableDeclarator[] = [parseVariableDeclaration(parser, context, scope, kind, origin)]; + while (consumeOpt(parser, context, Token.Comma)) { + bindingCount++; + list.push(parseVariableDeclaration(parser, context, scope, kind, origin)); + } + + if (bindingCount > 1 && origin & Origin.ForStatement && parser.token & Token.IsInOrOf) { + report(parser, Errors.ForInOfLoopMultiBindings, KeywordDescTable[parser.token & Token.Type]); + } + return list; +} + +/** + * Parses variable declaration + * + * @see [Link](https://tc39.github.io/ecma262/#prod-VariableDeclaration) + * + * @param parser Parser object + * @param context Context masks + * @param start Start pos of node + * @param start Start pos of node + * @param line + * @param column + */ +function parseVariableDeclaration( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + kind: BindingKind, + origin: Origin +): ESTree.VariableDeclarator { + // VariableDeclaration : + // BindingIdentifier Initializeropt + // BindingPattern Initializer + // + // VariableDeclarationNoIn : + // BindingIdentifier InitializerNoInopt + // BindingPattern InitializerNoIn + + const { token, tokenPos, linePos, colPos } = parser; + + let init: ESTree.Expression | ESTree.BindingPattern | ESTree.Identifier | null = null; + + const id = parseBindingPattern(parser, context, scope, kind, origin, tokenPos, linePos, colPos); + + if (parser.token === Token.Assign) { + nextToken(parser, context | Context.AllowRegExp); + init = parseExpression(parser, context, 1, 0, 0, parser.tokenPos, parser.linePos, parser.colPos); + if (origin & Origin.ForStatement || (token & Token.IsPatternStart) < 1) { + // Lexical declarations in for-in / for-of loops can't be initialized + + if ( + parser.token === Token.OfKeyword || + (parser.token === Token.InKeyword && + (token & Token.IsPatternStart || (kind & BindingKind.Variable) < 1 || context & Context.Strict)) + ) { + reportMessageAt( + tokenPos, + parser.line, + parser.index - 3, + Errors.ForInOfLoopInitializer, + parser.token === Token.OfKeyword ? 'of' : 'in' + ); + } + } + // Normal const declarations, and const declarations in for(;;) heads, must be initialized. + } else if ( + (kind & BindingKind.Const || (token & Token.IsPatternStart) > 0) && + (parser.token & Token.IsInOrOf) !== Token.IsInOrOf + ) { + report(parser, Errors.DeclarationMissingInitializer, kind & BindingKind.Const ? 'const' : 'destructuring'); + } + + return finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'VariableDeclarator', + id, + init + }); +} + +/** + * Parses either For, ForIn or ForOf statement + * + * @see [Link](https://tc39.github.io/ecma262/#sec-for-statement) + * @see [Link](https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements) + * + * @param parser Parser object + * @param context Context masks + * @param start Start pos of node + * @param line + * @param column + + */ +export function parseForStatement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + labels: ESTree.Labels, + start: number, + line: number, + column: number +): ESTree.ForStatement | ESTree.ForInStatement | ESTree.ForOfStatement { + nextToken(parser, context); + + const forAwait = (context & Context.InAwaitContext) > 0 && consumeOpt(parser, context, Token.AwaitKeyword); + + consume(parser, context | Context.AllowRegExp, Token.LeftParen); + + if (scope) scope = addChildScope(scope, ScopeKind.ForStatement); + + let test: ESTree.Expression | null = null; + let update: ESTree.Expression | null = null; + let destructible: AssignmentKind | DestructuringKind = 0; + let init = null; + let isVarDecl = + parser.token === Token.VarKeyword || parser.token === Token.LetKeyword || parser.token === Token.ConstKeyword; + let right; + + const { token, tokenPos, linePos, colPos } = parser; + + if (isVarDecl) { + if (token === Token.LetKeyword) { + init = parseIdentifier(parser, context, 0); + if (parser.token & (Token.IsIdentifier | Token.IsPatternStart)) { + if (parser.token === Token.InKeyword) { + if (context & Context.Strict) report(parser, Errors.DisallowedLetInStrict); + } else { + init = finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'VariableDeclaration', + kind: 'let', + declarations: parseVariableDeclarationList( + parser, + context | Context.DisallowIn, + scope, + BindingKind.Let, + Origin.ForStatement + ) + }); + } + + parser.assignable = AssignmentKind.Assignable; + } else if (context & Context.Strict) { + report(parser, Errors.DisallowedLetInStrict); + } else { + isVarDecl = false; + parser.assignable = AssignmentKind.Assignable; + init = parseMemberOrUpdateExpression(parser, context, init, 0, 0, tokenPos, linePos, colPos); + + // `for of` only allows LeftHandSideExpressions which do not start with `let`, and no other production matches + if (parser.token === Token.OfKeyword) report(parser, Errors.ForOfLet); + } + } else { + nextToken(parser, context); + + init = finishNode( + parser, + context, + tokenPos, + linePos, + colPos, + token === Token.VarKeyword + ? { + type: 'VariableDeclaration', + kind: 'var', + declarations: parseVariableDeclarationList( + parser, + context | Context.DisallowIn, + scope, + BindingKind.Variable, + Origin.ForStatement + ) + } + : { + type: 'VariableDeclaration', + kind: 'const', + declarations: parseVariableDeclarationList( + parser, + context | Context.DisallowIn, + scope, + BindingKind.Const, + Origin.ForStatement + ) + } + ); + + parser.assignable = AssignmentKind.Assignable; + } + } else if (token === Token.Semicolon) { + if (forAwait) report(parser, Errors.InvalidForAwait); + } else if ((token & Token.IsPatternStart) === Token.IsPatternStart) { + init = + token === Token.LeftBrace + ? parseObjectLiteralOrPattern( + parser, + context, + void 0, + 1, + 0, + 0, + BindingKind.Empty, + Origin.ForStatement, + tokenPos, + linePos, + colPos + ) + : parseArrayExpressionOrPattern( + parser, + context, + void 0, + 1, + 0, + 0, + BindingKind.Empty, + Origin.ForStatement, + tokenPos, + linePos, + colPos + ); + + destructible = parser.destructible; + + if (context & Context.OptionsWebCompat && destructible & DestructuringKind.SeenProto) { + report(parser, Errors.DuplicateProto); + } + + parser.assignable = + destructible & DestructuringKind.CannotDestruct ? AssignmentKind.CannotAssign : AssignmentKind.Assignable; + + init = parseMemberOrUpdateExpression( + parser, + context | Context.DisallowIn, + init as ESTree.Expression, + 0, + 0, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + } else { + init = parseLeftHandSideExpression(parser, context | Context.DisallowIn, 1, 0, 1, tokenPos, linePos, colPos); + } + + if ((parser.token & Token.IsInOrOf) === Token.IsInOrOf) { + if (parser.token === Token.OfKeyword) { + if (parser.assignable & AssignmentKind.CannotAssign) + report(parser, Errors.CantAssignToInOfForLoop, forAwait ? 'await' : 'of'); + + reinterpretToPattern(parser, init); + nextToken(parser, context | Context.AllowRegExp); + + // IterationStatement: + // for(LeftHandSideExpression of AssignmentExpression) Statement + // forawait(LeftHandSideExpression of AssignmentExpression) Statement + right = parseExpression(parser, context, 1, 0, 0, parser.tokenPos, parser.linePos, parser.colPos); + + consume(parser, context | Context.AllowRegExp, Token.RightParen); + + const body = parseIterationStatementBody(parser, context, scope, labels); + + return finishNode(parser, context, start, line, column, { + type: 'ForOfStatement', + left: init, + right, + body, + await: forAwait + }); + } + + if (parser.assignable & AssignmentKind.CannotAssign) report(parser, Errors.CantAssignToInOfForLoop, 'in'); + + reinterpretToPattern(parser, init); + nextToken(parser, context | Context.AllowRegExp); + + // `for await` only accepts the `for-of` type + if (forAwait) report(parser, Errors.InvalidForAwait); + + // IterationStatement: + // for(LeftHandSideExpression in Expression) Statement + right = parseExpressions(parser, context, 0, 1, parser.tokenPos, parser.linePos, parser.colPos); + + consume(parser, context | Context.AllowRegExp, Token.RightParen); + const body = parseIterationStatementBody(parser, context, scope, labels); + + return finishNode(parser, context, start, line, column, { + type: 'ForInStatement', + body, + left: init, + right + }); + } + + if (forAwait) report(parser, Errors.InvalidForAwait); + + if (!isVarDecl) { + if (destructible & DestructuringKind.HasToDestruct && parser.token !== Token.Assign) { + report(parser, Errors.CantAssignToInOfForLoop, 'loop'); + } + + init = parseAssignmentExpression(parser, context | Context.DisallowIn, 0, 0, tokenPos, linePos, colPos, init); + } + + if (parser.token === Token.Comma) + init = parseSequenceExpression(parser, context, 0, parser.tokenPos, parser.linePos, parser.colPos, init); + + consume(parser, context | Context.AllowRegExp, Token.Semicolon); + + if (parser.token !== Token.Semicolon) + test = parseExpressions(parser, context, 0, 1, parser.tokenPos, parser.linePos, parser.colPos); + + consume(parser, context | Context.AllowRegExp, Token.Semicolon); + + if (parser.token !== Token.RightParen) + update = parseExpressions(parser, context, 0, 1, parser.tokenPos, parser.linePos, parser.colPos); + + consume(parser, context | Context.AllowRegExp, Token.RightParen); + + const body = parseIterationStatementBody(parser, context, scope, labels); + + return finishNode(parser, context, start, line, column, { + type: 'ForStatement', + init, + test, + update, + body + }); +} + +/** + * Parses restricted identifier in import & export declaration + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope object + */ + +export function parseRestrictedIdentifier( + parser: ParserState, + context: Context, + scope: ScopeState | undefined +): ESTree.Identifier { + if (!isValidIdentifier(context, parser.token)) report(parser, Errors.UnexpectedStrictReserved); + if ((parser.token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) report(parser, Errors.StrictEvalArguments); + if (scope) addBlockName(parser, context, scope, parser.tokenValue, BindingKind.Let, Origin.None); + return parseIdentifier(parser, context, 0); +} + +/** + * Parse import declaration + * + * @see [Link](https://tc39.github.io/ecma262/#prod-ImportDeclaration) + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope object + */ +function parseImportDeclaration( + parser: ParserState, + context: Context, + scope: ScopeState | undefined +): ESTree.ImportDeclaration | ESTree.ExpressionStatement { + // ImportDeclaration : + // 'import' ImportClause 'from' ModuleSpecifier ';' + // 'import' ModuleSpecifier ';' + // + // ImportClause : + // ImportedDefaultBinding + // NameSpaceImport + // NamedImports + // ImportedDefaultBinding ',' NameSpaceImport + // ImportedDefaultBinding ',' NamedImports + // + // NameSpaceImport : + // '*' 'as' ImportedBinding + const start = parser.tokenPos; + const line = parser.linePos; + const column = parser.colPos; + + nextToken(parser, context); + + let source: ESTree.Literal | null = null; + + const { tokenPos, linePos, colPos } = parser; + + let specifiers: (ESTree.ImportSpecifier | ESTree.ImportDefaultSpecifier | ESTree.ImportNamespaceSpecifier)[] = []; + + // 'import' ModuleSpecifier ';' + if (parser.token === Token.StringLiteral) { + source = parseLiteral(parser, context); + } else { + if (parser.token & Token.IsIdentifier) { + const local = parseRestrictedIdentifier(parser, context, scope); + specifiers = [ + finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'ImportDefaultSpecifier', + local + }) + ]; + + // NameSpaceImport + if (consumeOpt(parser, context, Token.Comma)) { + switch (parser.token) { + case Token.Multiply: + specifiers.push(parseImportNamespaceSpecifier(parser, context, scope)); + break; + + case Token.LeftBrace: + parseImportSpecifierOrNamedImports(parser, context, scope, specifiers); + break; + + default: + report(parser, Errors.InvalidDefaultImport); + } + } + } else { + // Parse NameSpaceImport or NamedImports if present + switch (parser.token) { + case Token.Multiply: + specifiers = [parseImportNamespaceSpecifier(parser, context, scope)]; + break; + case Token.LeftBrace: + parseImportSpecifierOrNamedImports(parser, context, scope, specifiers); + break; + case Token.LeftParen: + return parseImportCallDeclaration(parser, context, start, line, column); + case Token.Period: + return parseImportMetaDeclaration(parser, context, start, line, column); + default: + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + } + } + + source = parseModuleSpecifier(parser, context); + } + + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + + return finishNode(parser, context, start, line, column, { + type: 'ImportDeclaration', + specifiers, + source + }); +} + +/** + * Parse binding identifier + * + * @see [Link](https://tc39.github.io/ecma262/#prod-NameSpaceImport) + * + * @param parser Parser object + * @param context Context masks + * @param specifiers Array of import specifiers + */ +function parseImportNamespaceSpecifier( + parser: ParserState, + context: Context, + scope: ScopeState | undefined +): ESTree.ImportNamespaceSpecifier { + // NameSpaceImport: + // * as ImportedBinding + const { tokenPos, linePos, colPos } = parser; + nextToken(parser, context); + consume(parser, context, Token.AsKeyword); + + // 'import * as class from "foo":' + if ((parser.token & Token.IsStringOrNumber) === Token.IsStringOrNumber) { + reportMessageAt( + tokenPos, + parser.line, + parser.index, + Errors.UnexpectedToken, + KeywordDescTable[parser.token & Token.Type] + ); + } + + return finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'ImportNamespaceSpecifier', + local: parseRestrictedIdentifier(parser, context, scope) + }); +} + +/** + * Parse module specifier + * + * @see [Link](https://tc39.github.io/ecma262/#prod-ModuleSpecifier) + * + * @param parser Parser object + * @param context Context masks + */ +function parseModuleSpecifier(parser: ParserState, context: Context): ESTree.Literal { + // ModuleSpecifier : + // StringLiteral + consumeOpt(parser, context, Token.FromKeyword); + + if (parser.token !== Token.StringLiteral) report(parser, Errors.InvalidExportImportSource, 'Import'); + + return parseLiteral(parser, context); +} + +function parseImportSpecifierOrNamedImports( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + specifiers: (ESTree.ImportSpecifier | ESTree.ImportDefaultSpecifier | ESTree.ImportNamespaceSpecifier)[] +): (ESTree.ImportSpecifier | ESTree.ImportDefaultSpecifier | ESTree.ImportNamespaceSpecifier)[] { + // NamedImports : + // '{' '}' + // '{' ImportsList '}' + // '{' ImportsList ',' '}' + // + // ImportsList : + // ImportSpecifier + // ImportsList ',' ImportSpecifier + // + // ImportSpecifier : + // BindingIdentifier + // IdentifierName 'as' BindingIdentifier + + nextToken(parser, context); + + while (parser.token & Token.IsIdentifier) { + let { token, tokenValue, tokenPos, linePos, colPos } = parser; + const imported = parseIdentifier(parser, context, 0); + let local: ESTree.Identifier; + + if (consumeOpt(parser, context, Token.AsKeyword)) { + if ((parser.token & Token.IsStringOrNumber) === Token.IsStringOrNumber || parser.token === Token.Comma) { + report(parser, Errors.InvalidKeywordAsAlias); + } else { + validateBindingIdentifier(parser, context, BindingKind.Const, parser.token, 0); + } + tokenValue = parser.tokenValue; + local = parseIdentifier(parser, context, 0); + } else { + // Keywords cannot be bound to themselves, so an import name + // that is a keyword is a syntax error if it is not followed + // by the keyword 'as'. + // See the ImportSpecifier production in ES6 section 15.2.2. + validateBindingIdentifier(parser, context, BindingKind.Const, token, 0); + local = imported; + } + + if (scope) addBlockName(parser, context, scope, tokenValue, BindingKind.Let, Origin.None); + + specifiers.push( + finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'ImportSpecifier', + local, + imported + }) + ); + + if (parser.token !== Token.RightBrace) consume(parser, context, Token.Comma); + } + + consume(parser, context, Token.RightBrace); + + return specifiers; +} + +/** + * Parse import meta declaration + * + * @param parser Parser object + * @param context Context masks + * @param meta ESTree AST node + * @param start + * @param line + * @param column + */ +export function parseImportMetaDeclaration( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.ExpressionStatement { + let expr: ESTree.Expression = parseImportMetaExpression( + parser, + context, + finishNode(parser, context, start, line, column, { + type: 'Identifier', + name: 'import' + }), + start, + line, + column + ); + + /** MemberExpression : + * 1. PrimaryExpression + * 2. MemberExpression [ AssignmentExpression ] + * 3. MemberExpression . IdentifierName + * 4. MemberExpression TemplateLiteral + * + * CallExpression : + * 1. MemberExpression Arguments + * 2. CallExpression ImportCall + * 3. CallExpression Arguments + * 4. CallExpression [ AssignmentExpression ] + * 5. CallExpression . IdentifierName + * 6. CallExpression TemplateLiteral + * + * UpdateExpression :: + * ('++' | '--')? LeftHandSideExpression + * + */ + + expr = parseMemberOrUpdateExpression(parser, context, expr, 0, 0, start, line, column); + + /** AssignmentExpression : + * 1. ConditionalExpression + * 2. LeftHandSideExpression = AssignmentExpression + */ + + expr = parseAssignmentExpression(parser, context, 0, 0, start, line, column, expr as ESTree.Expression); + + /** + * ExpressionStatement[Yield, Await]: + * [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }]Expression[+In, ?Yield, ?Await] + */ + return parseExpressionStatement(parser, context, expr, start, line, column); +} + +/** + * Parse dynamic import declaration + * + * @see [Link](https://github.com/tc39/proposal-dynamic-import) + * + * @param parser Parser object + * @param context Context masks + * @param number + */ +function parseImportCallDeclaration( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.ExpressionStatement { + let expr = parseImportExpression(parser, context, /* inGroup */ 0, start, line, column); + + /** MemberExpression : + * 1. PrimaryExpression + * 2. MemberExpression [ AssignmentExpression ] + * 3. MemberExpression . IdentifierName + * 4. MemberExpression TemplateLiteral + * + * CallExpression : + * 1. MemberExpression Arguments + * 2. CallExpression ImportCall + * 3. CallExpression Arguments + * 4. CallExpression [ AssignmentExpression ] + * 5. CallExpression . IdentifierName + * 6. CallExpression TemplateLiteral + * + * UpdateExpression :: + * ('++' | '--')? LeftHandSideExpression + * + */ + + expr = parseMemberOrUpdateExpression(parser, context, expr, 0, 0, start, line, column); + + /** + * ExpressionStatement[Yield, Await]: + * [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }]Expression[+In, ?Yield, ?Await] + */ + return parseExpressionStatement(parser, context, expr, start, line, column); +} + +/** + * Parse export declaration + * + * @see [Link](https://tc39.github.io/ecma262/#prod-ExportDeclaration) + * + * @param parser Parser object + * @param context Context masks + */ +function parseExportDeclaration( + parser: ParserState, + context: Context, + scope: ScopeState | undefined +): ESTree.ExportAllDeclaration | ESTree.ExportNamedDeclaration | ESTree.ExportDefaultDeclaration { + // ExportDeclaration: + // 'export' '*' 'from' ModuleSpecifier ';' + // 'export' '*' 'as' IdentifierName 'from' ModuleSpecifier ';' + // 'export' ExportClause ('from' ModuleSpecifier)? ';' + // 'export' VariableStatement + // 'export' Declaration + // 'export' 'default' + const start = parser.tokenPos; + const line = parser.linePos; + const column = parser.colPos; + + // https://tc39.github.io/ecma262/#sec-exports + nextToken(parser, context | Context.AllowRegExp); + + const specifiers: ESTree.ExportSpecifier[] = []; + + let declaration: ESTree.ExportDeclaration | ESTree.Expression | null = null; + let source: ESTree.Literal | null = null; + let key: string; + + if (consumeOpt(parser, context | Context.AllowRegExp, Token.DefaultKeyword)) { + // export default HoistableDeclaration[Default] + // export default ClassDeclaration[Default] + // export default [lookahead not-in {function, class}] AssignmentExpression[In] ; + + switch (parser.token) { + // export default HoistableDeclaration[Default] + case Token.FunctionKeyword: { + declaration = parseFunctionDeclaration( + parser, + context, + scope, + Origin.TopLevel, + 1, + HoistedFunctionFlags.Hoisted, + 0, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + break; + } + // export default ClassDeclaration[Default] + // export default @decl ClassDeclaration[Default] + case Token.Decorator: + case Token.ClassKeyword: + declaration = parseClassDeclaration( + parser, + context, + scope, + HoistedClassFlags.Hoisted, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + break; + + // export default HoistableDeclaration[Default] + case Token.AsyncKeyword: + const { tokenPos, linePos, colPos } = parser; + + declaration = parseIdentifier(parser, context, 0); + + const { flags } = parser; + + if ((flags & Flags.NewLine) < 1) { + if (parser.token === Token.FunctionKeyword) { + declaration = parseFunctionDeclaration( + parser, + context, + scope, + Origin.TopLevel, + 1, + HoistedFunctionFlags.Hoisted, + 1, + tokenPos, + linePos, + colPos + ); + } else { + if (parser.token === Token.LeftParen) { + declaration = parseAsyncArrowOrCallExpression( + parser, + context, + declaration, + 1, + BindingKind.ArgumentList, + Origin.None, + flags, + tokenPos, + linePos, + colPos + ); + declaration = parseMemberOrUpdateExpression( + parser, + context, + declaration as any, + 0, + 0, + tokenPos, + linePos, + colPos + ); + declaration = parseAssignmentExpression( + parser, + context, + 0, + 0, + tokenPos, + linePos, + colPos, + declaration as any + ); + } else if (parser.token & Token.IsIdentifier) { + if (scope) scope = createArrowHeadParsingScope(parser, context, parser.tokenValue); + + declaration = parseIdentifier(parser, context, 0); + declaration = parseArrowFunctionExpression( + parser, + context, + scope, + [declaration], + 1, + tokenPos, + linePos, + colPos + ); + } + } + } + break; + + default: + // export default [lookahead ∉ {function, class}] AssignmentExpression[In] ; + declaration = parseExpression(parser, context, 1, 0, 0, parser.tokenPos, parser.linePos, parser.colPos); + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + } + + // See: https://www.ecma-international.org/ecma-262/9.0/index.html#sec-exports-static-semantics-exportednames + if (scope) declareUnboundVariable(parser, 'default'); + + return finishNode(parser, context, start, line, column, { + type: 'ExportDefaultDeclaration', + declaration + }); + } + + switch (parser.token) { + case Token.Multiply: { + // + // 'export' '*' 'as' IdentifierName 'from' ModuleSpecifier ';' + // + // See: https://github.com/tc39/ecma262/pull/1174 + nextToken(parser, context); // Skips: '*' + + let exported: ESTree.Identifier | null = null; + const isNamedDeclaration = consumeOpt(parser, context, Token.AsKeyword); + + if (isNamedDeclaration) { + if (scope) declareUnboundVariable(parser, parser.tokenValue); + exported = parseIdentifier(parser, context, 0); + } + + consume(parser, context, Token.FromKeyword); + + if (parser.token !== Token.StringLiteral) report(parser, Errors.InvalidExportImportSource, 'Export'); + + source = parseLiteral(parser, context); + + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + + return finishNode(parser, context, start, line, column, { + type: 'ExportAllDeclaration', + source, + exported + } as any); + } + case Token.LeftBrace: { + // ExportClause : + // '{' '}' + // '{' ExportsList '}' + // '{' ExportsList ',' '}' + // + // ExportsList : + // ExportSpecifier + // ExportsList ',' ExportSpecifier + // + // ExportSpecifier : + // IdentifierName + // IdentifierName 'as' IdentifierName + + nextToken(parser, context); // Skips: '{' + + const tmpExportedNames: string[] = []; + const tmpExportedBindings: string[] = []; + + while (parser.token & Token.IsIdentifier) { + const { tokenPos, tokenValue, linePos, colPos } = parser; + const local = parseIdentifier(parser, context, 0); + + let exported: ESTree.Identifier | null; + + if (parser.token === Token.AsKeyword) { + nextToken(parser, context); + if ((parser.token & Token.IsStringOrNumber) === Token.IsStringOrNumber) { + report(parser, Errors.InvalidKeywordAsAlias); + } + if (scope) { + tmpExportedNames.push(parser.tokenValue); + tmpExportedBindings.push(tokenValue); + } + exported = parseIdentifier(parser, context, 0); + } else { + if (scope) { + tmpExportedNames.push(parser.tokenValue); + tmpExportedBindings.push(parser.tokenValue); + } + exported = local; + } + + specifiers.push( + finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'ExportSpecifier', + local, + exported + }) + ); + + if (parser.token !== Token.RightBrace) consume(parser, context, Token.Comma); + } + + consume(parser, context, Token.RightBrace); + + if (consumeOpt(parser, context, Token.FromKeyword)) { + // The left hand side can't be a keyword where there is no + // 'from' keyword since it references a local binding. + if (parser.token !== Token.StringLiteral) report(parser, Errors.InvalidExportImportSource, 'Export'); + + source = parseLiteral(parser, context); + } else if (scope) { + let i = 0; + let iMax = tmpExportedNames.length; + for (; i < iMax; i++) { + declareUnboundVariable(parser, tmpExportedNames[i]); + } + i = 0; + iMax = tmpExportedBindings.length; + + for (; i < iMax; i++) { + addBindingToExports(parser, tmpExportedBindings[i]); + } + } + + matchOrInsertSemicolon(parser, context | Context.AllowRegExp); + + break; + } + + case Token.ClassKeyword: + declaration = parseClassDeclaration( + parser, + context, + scope, + HoistedClassFlags.Export, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + break; + case Token.FunctionKeyword: + declaration = parseFunctionDeclaration( + parser, + context, + scope, + Origin.TopLevel, + 1, + HoistedFunctionFlags.Export, + 0, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + break; + + case Token.LetKeyword: + declaration = parseLexicalDeclaration( + parser, + context, + scope, + BindingKind.Let, + Origin.Export, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + break; + case Token.ConstKeyword: + declaration = parseLexicalDeclaration( + parser, + context, + scope, + BindingKind.Const, + Origin.Export, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + break; + case Token.VarKeyword: + declaration = parseVariableStatement( + parser, + context, + scope, + Origin.Export, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + break; + case Token.AsyncKeyword: + const { tokenPos, linePos, colPos } = parser; + + nextToken(parser, context); + + if ((parser.flags & Flags.NewLine) < 1 && parser.token === Token.FunctionKeyword) { + declaration = parseFunctionDeclaration( + parser, + context, + scope, + Origin.TopLevel, + 1, + HoistedFunctionFlags.Export, + 1, + tokenPos, + linePos, + colPos + ); + if (scope) { + key = declaration.id ? declaration.id.name : ''; + declareUnboundVariable(parser, key); + } + break; + } + // falls through + default: + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + } + + return finishNode(parser, context, start, line, column, { + type: 'ExportNamedDeclaration', + declaration, + specifiers, + source + }); +} + +/** + * Parses an expression + * + * @param parser Parser object + * @param context Context masks + * @param assignable + */ +export function parseExpression( + parser: ParserState, + context: Context, + canAssign: 0 | 1, + isPattern: 0 | 1, + inGroup: 0 | 1, + start: number, + line: number, + column: number +): ESTree.Expression { + // Expression :: + // AssignmentExpression + // Expression ',' AssignmentExpression + + let expr = parsePrimaryExpression( + parser, + context, + BindingKind.Empty, + 0, + canAssign, + isPattern, + inGroup, + 1, + start, + line, + column + ); + + expr = parseMemberOrUpdateExpression(parser, context, expr, inGroup, 0, start, line, column); + + return parseAssignmentExpression(parser, context, inGroup, 0, start, line, column, expr); +} + +/** + * Parse sequence expression + * + * @param parser Parser object + * @param context Context masks + * @param expr ESTree AST node + */ +export function parseSequenceExpression( + parser: ParserState, + context: Context, + inGroup: 0 | 1, + start: number, + line: number, + column: number, + expr: ESTree.AssignmentExpression | ESTree.Expression +): ESTree.SequenceExpression { + // Expression :: + // AssignmentExpression + // Expression ',' AssignmentExpression + const expressions: ESTree.Expression[] = [expr]; + while (consumeOpt(parser, context | Context.AllowRegExp, Token.Comma)) { + expressions.push(parseExpression(parser, context, 1, 0, inGroup, parser.tokenPos, parser.linePos, parser.colPos)); + } + + return finishNode(parser, context, start, line, column, { + type: 'SequenceExpression', + expressions + }); +} + +/** + * Parse expression or sequence expression + * + * @param parser Parser object + * @param context Context masks + * @param canAssign + */ +export function parseExpressions( + parser: ParserState, + context: Context, + inGroup: 0 | 1, + canAssign: 0 | 1, + start: number, + line: number, + column: number +): ESTree.SequenceExpression | ESTree.Expression { + const expr = parseExpression(parser, context, canAssign, 0, inGroup, start, line, column); + return parser.token === Token.Comma + ? parseSequenceExpression(parser, context, inGroup, start, line, column, expr) + : expr; +} + +/** + * Parse assignment expression + * + * @param parser Parser object + * @param context Context masks + * @param inGroup + * @param isPattern + * @param start + * @param line + * @param column + * @param left + * + * * @param left ESTree AST node + */ +export function parseAssignmentExpression( + parser: ParserState, + context: Context, + inGroup: 0 | 1, + isPattern: 0 | 1, + start: number, + line: number, + column: number, + left: ESTree.ArgumentExpression | ESTree.Expression | null +): ESTree.ArgumentExpression | ESTree.Expression { + /** + * AssignmentExpression :: + * ConditionalExpression + * ArrowFunction + * AsyncArrowFunction + * YieldExpression + * LeftHandSideExpression AssignmentOperator AssignmentExpression + */ + + const { token } = parser; + + if ((token & Token.IsAssignOp) === Token.IsAssignOp) { + if (parser.assignable & AssignmentKind.CannotAssign) report(parser, Errors.CantAssignTo); + if ( + (!isPattern && token === Token.Assign && ((left as ESTree.Expression).type as string) === 'ArrayExpression') || + ((left as ESTree.Expression).type as string) === 'ObjectExpression' + ) { + reinterpretToPattern(parser, left); + } + + nextToken(parser, context | Context.AllowRegExp); + + const right = parseExpression(parser, context, 1, 1, inGroup, parser.tokenPos, parser.linePos, parser.colPos); + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode( + parser, + context, + start, + line, + column, + isPattern + ? { + type: 'AssignmentPattern', + left, + right + } + : ({ + type: 'AssignmentExpression', + left, + operator: KeywordDescTable[token & Token.Type], + right + } as any) + ); + } + + /** Binary expression + * + * https://tc39.github.io/ecma262/#sec-multiplicative-operators + * + */ + if ((token & Token.IsBinaryOp) === Token.IsBinaryOp) { + // We start using the binary expression parser for prec >= 4 only! + left = parseBinaryExpression(parser, context, inGroup, start, line, column, 4, token, left as ESTree.Expression); + } + + /** + * Conditional expression + * https://tc39.github.io/ecma262/#prod-ConditionalExpression + * + */ + if (consumeOpt(parser, context | Context.AllowRegExp, Token.QuestionMark)) { + left = parseConditionalExpression(parser, context, left as ESTree.Expression, start, line, column); + } + + return left as ESTree.Expression; +} + +/** + * Parse assignment expression or assignment pattern + * + * @param parser Parser object + * @param context Context masks + * @param inGroup + * @param isPattern + * @param start + * @param line + * @param column + * @param left + */ + +export function parseAssignmentExpressionOrPattern( + parser: ParserState, + context: Context, + inGroup: 0 | 1, + isPattern: 0 | 1, + start: number, + line: number, + column: number, + left: any +): any { + const { token } = parser; + + nextToken(parser, context | Context.AllowRegExp); + + const right = parseExpression(parser, context, 1, 1, inGroup, parser.tokenPos, parser.linePos, parser.colPos); + + left = finishNode( + parser, + context, + start, + line, + column, + isPattern + ? { + type: 'AssignmentPattern', + left, + right + } + : ({ + type: 'AssignmentExpression', + left, + operator: KeywordDescTable[token & Token.Type], + right + } as any) + ); + + parser.assignable = AssignmentKind.CannotAssign; + + return left as ESTree.Expression; +} + +/** + * Parse conditional expression + * + * @param parser Parser object + * @param context Context masks + * @param test ESTree AST node + */ +export function parseConditionalExpression( + parser: ParserState, + context: Context, + test: ESTree.Expression, + start: number, + line: number, + column: number +): ESTree.ConditionalExpression { + // ConditionalExpression :: + // LogicalOrExpression + // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression + const consequent = parseExpression( + parser, + (context | Context.DisallowIn) ^ Context.DisallowIn, + 1, + 0, + 0, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + consume(parser, context | Context.AllowRegExp, Token.Colon); + parser.assignable = AssignmentKind.Assignable; + // In parsing the first assignment expression in conditional + // expressions we always accept the 'in' keyword; see ECMA-262, + // section 11.12, page 58. + const alternate = parseExpression(parser, context, 1, 0, 0, parser.tokenPos, parser.linePos, parser.colPos); + parser.assignable = AssignmentKind.CannotAssign; + return finishNode(parser, context, start, line, column, { + type: 'ConditionalExpression', + test, + consequent, + alternate + }); +} + +/** + * Parses binary and unary expressions recursively + * based on the precedence of the operators encountered. + * + * @param parser Parser object + * @param context Context masks + * @param minPrec The precedence of the last binary expression parsed + * @param left ESTree AST node + */ +export function parseBinaryExpression( + parser: ParserState, + context: Context, + inGroup: 0 | 1, + start: number, + line: number, + column: number, + minPrec: number, + operator: Token, + left: ESTree.ArgumentExpression | ESTree.Expression +): ESTree.ArgumentExpression | ESTree.Expression { + const bit = -((context & Context.DisallowIn) > 0) & Token.InKeyword; + let t: Token; + let prec: number; + + parser.assignable = AssignmentKind.CannotAssign; + + while (parser.token & Token.IsBinaryOp) { + t = parser.token; + prec = t & Token.Precedence; + + if ((t & Token.IsLogical && operator & Token.IsCoalesc) || (operator & Token.IsLogical && t & Token.IsCoalesc)) { + report(parser, Errors.InvalidCoalescing); + } + + // 0 precedence will terminate binary expression parsing + + if (prec + (((t === Token.Exponentiate) as any) << 8) - (((bit === t) as any) << 12) <= minPrec) break; + nextToken(parser, context | Context.AllowRegExp); + + left = finishNode(parser, context, start, line, column, { + type: t & Token.IsLogical || t & Token.IsCoalesc ? 'LogicalExpression' : 'BinaryExpression', + left, + right: parseBinaryExpression( + parser, + context, + inGroup, + parser.tokenPos, + parser.linePos, + parser.colPos, + prec, + t, + parseLeftHandSideExpression(parser, context, 0, inGroup, 1, parser.tokenPos, parser.linePos, parser.colPos) + ), + operator: KeywordDescTable[t & Token.Type] + }); + } + + if (parser.token === Token.Assign) report(parser, Errors.CantAssignTo); + + return left; +} + +/** + * Parses unary expression + * + * @param parser Parser object + * @param context Context masks + */ +export function parseUnaryExpression( + parser: ParserState, + context: Context, + isLHS: 0 | 1, + start: number, + line: number, + column: number, + inGroup: 0 | 1 +): ESTree.UnaryExpression { + /** + * UnaryExpression :: + * 1) UpdateExpression + * 2) delete UnaryExpression + * 3) void UnaryExpression + * 4) typeof UnaryExpression + * 5) + UnaryExpression + * 6) - UnaryExpression + * 7) ~ UnaryExpression + * 8) ! UnaryExpression + * 9) AwaitExpression + */ + if (!isLHS) report(parser, Errors.Unexpected); + const unaryOperator = parser.token; + nextToken(parser, context | Context.AllowRegExp); + const arg = parseLeftHandSideExpression( + parser, + context, + 0, + inGroup, + 1, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + if (parser.token === Token.Exponentiate) report(parser, Errors.InvalidExponentiationLHS); + if (context & Context.Strict && unaryOperator === Token.DeleteKeyword) { + if (arg.type === 'Identifier') { + report(parser, Errors.StrictDelete); + // Prohibit delete of private class elements + } else if (isPropertyWithPrivateFieldKey(arg)) { + report(parser, Errors.DeletePrivateField); + } + } + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode(parser, context, start, line, column, { + type: 'UnaryExpression', + operator: KeywordDescTable[unaryOperator & Token.Type] as ESTree.UnaryOperator, + argument: arg, + prefix: true + }); +} + +/** + * Parse async expression + * + * @param parser Parser object + * @param context Context masks + */ +export function parseAsyncExpression( + parser: ParserState, + context: Context, + inGroup: 0 | 1, + isLHS: 0 | 1, + canAssign: 0 | 1, + isPattern: 0 | 1, + inNew: 0 | 1, + start: number, + line: number, + column: number +): ESTree.FunctionExpression | ESTree.ArrowFunctionExpression | ESTree.CallExpression | ESTree.Identifier { + const { token } = parser; + const expr = parseIdentifier(parser, context, isPattern); + const { flags } = parser; + + if ((flags & Flags.NewLine) < 1) { + // async function ... + if (parser.token === Token.FunctionKeyword) { + return parseFunctionExpression(parser, context, /* isAsync */ 1, inGroup, start, line, column); + } + + // async Identifier => ... + if ((parser.token & Token.IsIdentifier) === Token.IsIdentifier) { + if (!isLHS) report(parser, Errors.Unexpected); + return parseAsyncArrowAfterIdent(parser, context, canAssign, start, line, column); + } + } + + // async (...) => ... + if (!inNew && parser.token === Token.LeftParen) { + return parseAsyncArrowOrCallExpression( + parser, + context, + expr, + canAssign, + BindingKind.ArgumentList, + Origin.None, + flags, + start, + line, + column + ); + } + + if (parser.token === Token.Arrow) { + classifyIdentifier(parser, context, token, /* isArrow */ 1); + if (inNew) report(parser, Errors.InvalidAsyncArrow); + return parseArrowFromIdentifier(parser, context, parser.tokenValue, expr, inNew, canAssign, 0, start, line, column); + } + return expr; +} + +/** + * Parse yield expression + * + * @param parser Parser object + * @param context Context masks + */ +export function parseYieldExpression( + parser: ParserState, + context: Context, + inGroup: 0 | 1, + canAssign: 0 | 1, + start: number, + line: number, + column: number +): ESTree.YieldExpression | ESTree.Identifier | ESTree.ArrowFunctionExpression { + // YieldExpression[In] : + // yield + // yield [no LineTerminator here] AssignmentExpression[?In, Yield] + // yield [no LineTerminator here] * AssignmentExpression[?In, Yield] + + if (inGroup) parser.destructible |= DestructuringKind.Yield; + if (context & Context.InYieldContext) { + nextToken(parser, context | Context.AllowRegExp); + if (context & Context.InArgumentList) report(parser, Errors.YieldInParameter); + if (!canAssign) report(parser, Errors.CantAssignTo); + if (parser.token === Token.QuestionMark) report(parser, Errors.InvalidTernaryYield); + + let argument: ESTree.Expression | null = null; + let delegate = false; // yield* + + if ((parser.flags & Flags.NewLine) < 1) { + delegate = consumeOpt(parser, context | Context.AllowRegExp, Token.Multiply); + if (parser.token & (Token.Contextual | Token.IsExpressionStart) || delegate) { + argument = parseExpression(parser, context, 1, 0, 0, parser.tokenPos, parser.linePos, parser.colPos); + } + } + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode(parser, context, start, line, column, { + type: 'YieldExpression', + argument, + delegate + }); + } + + if (context & Context.Strict) report(parser, Errors.DisallowedInContext, 'yield'); + + return parseIdentifierOrArrow(parser, context, start, line, column); +} + +/** + * Parse await expression + * + * @param parser Parser object + * @param context Context masks + * @param inNew + */ +export function parseAwaitExpression( + parser: ParserState, + context: Context, + inNew: 0 | 1, + inGroup: 0 | 1, + start: number, + line: number, + column: number +): ESTree.IdentifierOrExpression | ESTree.AwaitExpression { + if (inGroup) parser.destructible |= DestructuringKind.Await; + if (context & Context.InAwaitContext || (context & Context.Module && context & Context.InGlobal)) { + if (inNew) report(parser, Errors.Unexpected); + + if (context & Context.InArgumentList) { + reportMessageAt(parser.index, parser.line, parser.index, Errors.AwaitInParameter); + } + + nextToken(parser, context | Context.AllowRegExp); + + const argument = parseLeftHandSideExpression( + parser, + context, + 0, + 0, + 1, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + + if (parser.token === Token.Exponentiate) report(parser, Errors.InvalidExponentiationLHS); + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode(parser, context, start, line, column, { + type: 'AwaitExpression', + argument + }); + } + + if (context & Context.Module) report(parser, Errors.AwaitOutsideAsync); + return parseIdentifierOrArrow(parser, context, start, line, column); +} + +/** + * Parses function body + * + * @param parser Parser object + * @param context Context masks + * @param scope Scope object | null + * @param origin Binding origin + * @param firstRestricted + * @param scopeError + */ +export function parseFunctionBody( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + origin: Origin, + firstRestricted: Token | undefined, + scopeError: any +): ESTree.BlockStatement { + const { tokenPos, linePos, colPos } = parser; + + consume(parser, context | Context.AllowRegExp, Token.LeftBrace); + + const body: ESTree.Statement[] = []; + const prevContext = context; + + if (parser.token !== Token.RightBrace) { + while (parser.token === Token.StringLiteral) { + const { index, tokenPos, tokenValue, token } = parser; + const expr = parseLiteral(parser, context); + if (isValidStrictMode(parser, index, tokenPos, tokenValue)) { + context |= Context.Strict; + // TC39 deemed "use strict" directives to be an error when occurring + // in the body of a function with non-simple parameter list, on + // 29/7/2015. https://goo.gl/ueA7Ln + if (parser.flags & Flags.SimpleParameterList) { + reportMessageAt(parser.index, parser.line, parser.tokenPos, Errors.IllegalUseStrict); + } + + if (parser.flags & Flags.Octals) { + reportMessageAt(parser.index, parser.line, parser.tokenPos, Errors.StrictOctalLiteral); + } + } + body.push(parseDirective(parser, context, expr, token, tokenPos, parser.linePos, parser.colPos)); + } + if (context & Context.Strict) { + if (firstRestricted) { + if ((firstRestricted & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) { + report(parser, Errors.StrictEvalArguments); + } + if ((firstRestricted & Token.FutureReserved) === Token.FutureReserved) { + report(parser, Errors.StrictFunctionName); + } + } + if (parser.flags & Flags.StrictEvalArguments) report(parser, Errors.StrictEvalArguments); + if (parser.flags & Flags.HasStrictReserved) report(parser, Errors.UnexpectedStrictReserved); + } + + if ( + context & Context.OptionsLexical && + scope && + scopeError !== void 0 && + (prevContext & Context.Strict) < 1 && + (context & Context.InGlobal) < 1 + ) { + reportScopeError(scopeError); + } + } + + parser.flags = + (parser.flags | Flags.StrictEvalArguments | Flags.HasStrictReserved | Flags.Octals) ^ + (Flags.StrictEvalArguments | Flags.HasStrictReserved | Flags.Octals); + + parser.destructible = (parser.destructible | DestructuringKind.Yield) ^ DestructuringKind.Yield; + + while (parser.token !== Token.RightBrace) { + body.push(parseStatementListItem(parser, context, scope, Origin.TopLevel, {}) as ESTree.Statement); + } + + consume( + parser, + origin & (Origin.Arrow | Origin.Declaration) ? context | Context.AllowRegExp : context, + Token.RightBrace + ); + + parser.flags &= ~(Flags.SimpleParameterList | Flags.Octals); + + if (parser.token === Token.Assign) report(parser, Errors.CantAssignTo); + + return finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'BlockStatement', + body + }); +} + +/** + * Parse super expression + * + * @param parser Parser object + * @param context Context masks + */ +export function parseSuperExpression( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.Super { + nextToken(parser, context); + + switch (parser.token) { + case Token.QuestionMarkPeriod: + report(parser, Errors.OptionalChainingNoSuper); + case Token.LeftParen: { + // The super property has to be within a class constructor + if ((context & Context.SuperCall) < 1) report(parser, Errors.SuperNoConstructor); + if (context & Context.InClass) report(parser, Errors.UnexpectedPrivateField); + parser.assignable = AssignmentKind.CannotAssign; + break; + } + case Token.LeftBracket: + case Token.Period: { + // new super() is never allowed. + // super() is only allowed in derived constructor + if ((context & Context.SuperProperty) < 1) report(parser, Errors.InvalidSuperProperty); + if (context & Context.InClass) report(parser, Errors.UnexpectedPrivateField); + parser.assignable = AssignmentKind.Assignable; + break; + } + default: + report(parser, Errors.UnexpectedToken, 'super'); + } + + return finishNode(parser, context, start, line, column, { type: 'Super' }); +} + +/** + * Parses left hand side + * + * @param parser Parser object + * @param context Context masks + * @param canAssign + * @param start + * @param line + * @param column + */ +export function parseLeftHandSideExpression( + parser: ParserState, + context: Context, + canAssign: 0 | 1, + inGroup: 0 | 1, + isLHS: 0 | 1, + start: number, + line: number, + column: number +): ESTree.Expression { + // LeftHandSideExpression :: + // (PrimaryExpression | MemberExpression) ... + + const expression = parsePrimaryExpression( + parser, + context, + BindingKind.Empty, + 0, + canAssign, + 0, + inGroup, + isLHS, + start, + line, + column + ); + + return parseMemberOrUpdateExpression(parser, context, expression, inGroup, 0, start, line, column); +} + +/** + * Parse update expression + * + * @param parser Parser object + * @param context Context masks + * @param inNew + * @param start + * @param line + * @param column + */ +function parseUpdateExpression( + parser: ParserState, + context: Context, + expr: ESTree.Expression, + start: number, + line: number, + column: number +) { + if (parser.assignable & AssignmentKind.CannotAssign) report(parser, Errors.InvalidIncDecTarget); + + const { token } = parser; + + nextToken(parser, context); + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode(parser, context, start, line, column, { + type: 'UpdateExpression', + argument: expr, + operator: KeywordDescTable[token & Token.Type] as ESTree.UpdateOperator, + prefix: false + }); +} +/** + * Parses member or update expression + * + * @param parser Parser object + * @param context Context masks + * @param expr ESTree AST node + * @param inGroup + * @param start + * @param line + * @param column + */ +export function parseMemberOrUpdateExpression( + parser: ParserState, + context: Context, + expr: ESTree.Expression, + inGroup: 0 | 1, + inChain: 0 | 1, + start: number, + line: number, + column: number +): any { + if ((parser.token & Token.IsUpdateOp) === Token.IsUpdateOp && (parser.flags & Flags.NewLine) < 1) { + expr = parseUpdateExpression(parser, context, expr, start, line, column); + } else if ((parser.token & Token.IsMemberOrCallExpression) === Token.IsMemberOrCallExpression) { + context = (context | Context.DisallowIn | Context.InGlobal) ^ (Context.DisallowIn | Context.InGlobal); + + switch (parser.token) { + /* Property */ + case Token.Period: { + nextToken(parser, context | Context.AllowEscapedKeyword); + + parser.assignable = AssignmentKind.Assignable; + + const property = parsePropertyOrPrivatePropertyName(parser, context); + + expr = finishNode(parser, context, start, line, column, { + type: 'MemberExpression', + object: expr, + computed: false, + property + }); + break; + } + + /* Property */ + case Token.LeftBracket: { + let restoreHasOptionalChaining = false; + if ((parser.flags & Flags.HasOptionalChaining) === Flags.HasOptionalChaining) { + restoreHasOptionalChaining = true; + parser.flags = (parser.flags | Flags.HasOptionalChaining) ^ Flags.HasOptionalChaining; + } + + nextToken(parser, context | Context.AllowRegExp); + + const { tokenPos, linePos, colPos } = parser; + const property = parseExpressions(parser, context, inGroup, 1, tokenPos, linePos, colPos); + + consume(parser, context, Token.RightBracket); + + parser.assignable = AssignmentKind.Assignable; + + expr = finishNode(parser, context, start, line, column, { + type: 'MemberExpression', + object: expr, + computed: true, + property + }); + + if (restoreHasOptionalChaining) { + parser.flags |= Flags.HasOptionalChaining; + } + break; + } + + /* Call */ + case Token.LeftParen: { + if ((parser.flags & Flags.DisallowCall) === Flags.DisallowCall) { + parser.flags = (parser.flags | Flags.DisallowCall) ^ Flags.DisallowCall; + return expr; + } + + let restoreHasOptionalChaining = false; + if ((parser.flags & Flags.HasOptionalChaining) === Flags.HasOptionalChaining) { + restoreHasOptionalChaining = true; + parser.flags = (parser.flags | Flags.HasOptionalChaining) ^ Flags.HasOptionalChaining; + } + + const args = parseArguments(parser, context, inGroup); + + parser.assignable = AssignmentKind.CannotAssign; + + expr = finishNode(parser, context, start, line, column, { + type: 'CallExpression', + callee: expr, + arguments: args + }); + + if (restoreHasOptionalChaining) { + parser.flags |= Flags.HasOptionalChaining; + } + break; + } + + /* Optional chaining */ + case Token.QuestionMarkPeriod: { + nextToken(parser, context); // skips: '?.' + parser.flags |= Flags.HasOptionalChaining; + parser.assignable = AssignmentKind.CannotAssign; + expr = parseOptionalChain(parser, context, expr, start, line, column); + break; + } + + default: + if ((parser.flags & Flags.HasOptionalChaining) === Flags.HasOptionalChaining) { + report(parser, Errors.OptionalChainingNoTemplate); + } + /* Tagged Template */ + parser.assignable = AssignmentKind.CannotAssign; + + expr = finishNode(parser, context, start, line, column, { + type: 'TaggedTemplateExpression', + tag: expr, + quasi: + parser.token === Token.TemplateContinuation + ? parseTemplate(parser, context | Context.TaggedTemplate) + : parseTemplateLiteral(parser, context, parser.tokenPos, parser.linePos, parser.colPos) + }); + } + + expr = parseMemberOrUpdateExpression(parser, context, expr, 0, 1, start, line, column); + } + + // Finalize ChainExpression + // FIXME: current implementation does not invalidate destructuring like `({ a: x?.obj['a'] } = {})` + if (inChain === 0 && (parser.flags & Flags.HasOptionalChaining) === Flags.HasOptionalChaining) { + parser.flags = (parser.flags | Flags.HasOptionalChaining) ^ Flags.HasOptionalChaining; + + expr = finishNode(parser, context, start, line, column, { + type: 'ChainExpression', + expression: expr as ESTree.CallExpression | ESTree.MemberExpression + }); + } + + return expr; +} + +/** + * Parses optional chain + * + * @param parser Parser object + * @param context Context masks + * @param expr ESTree AST node + */ +export function parseOptionalChain( + parser: ParserState, + context: Context, + expr: ESTree.Expression, + start: number, + line: number, + column: number +): ESTree.MemberExpression | ESTree.CallExpression { + let restoreHasOptionalChaining = false; + let node; + if (parser.token === Token.LeftBracket || parser.token === Token.LeftParen) { + if ((parser.flags & Flags.HasOptionalChaining) === Flags.HasOptionalChaining) { + restoreHasOptionalChaining = true; + parser.flags = (parser.flags | Flags.HasOptionalChaining) ^ Flags.HasOptionalChaining; + } + } + if (parser.token === Token.LeftBracket) { + nextToken(parser, context | Context.AllowRegExp); + const { tokenPos, linePos, colPos } = parser; + const property = parseExpressions(parser, context, 0, 1, tokenPos, linePos, colPos); + consume(parser, context, Token.RightBracket); + parser.assignable = AssignmentKind.CannotAssign; + node = finishNode(parser, context, start, line, column, { + type: 'MemberExpression', + object: expr, + computed: true, + optional: true, + property + }); + } else if (parser.token === Token.LeftParen) { + const args = parseArguments(parser, context, 0); + + parser.assignable = AssignmentKind.CannotAssign; + + node = finishNode(parser, context, start, line, column, { + type: 'CallExpression', + callee: expr, + arguments: args, + optional: true + }); + } else { + if ((parser.token & (Token.IsIdentifier | Token.Keyword)) < 1) report(parser, Errors.InvalidDotProperty); + const property = parseIdentifier(parser, context, 0); + parser.assignable = AssignmentKind.CannotAssign; + node = finishNode(parser, context, start, line, column, { + type: 'MemberExpression', + object: expr, + computed: false, + optional: true, + property + }); + } + + if (restoreHasOptionalChaining) { + parser.flags |= Flags.HasOptionalChaining; + } + return node; +} + +/** + * Parses property or private property name + * + * @param parser Parser object + * @param context Context masks + */ +export function parsePropertyOrPrivatePropertyName(parser: ParserState, context: Context): any { + if ((parser.token & (Token.IsIdentifier | Token.Keyword)) < 1 && parser.token !== Token.PrivateField) { + report(parser, Errors.InvalidDotProperty); + } + + return context & Context.OptionsNext && parser.token === Token.PrivateField + ? parsePrivateIdentifier(parser, context, parser.tokenPos, parser.linePos, parser.colPos) + : parseIdentifier(parser, context, 0); +} + +/** + * Parse update expression + * + * @param parser Parser object + * @param context Context masks + * @param inNew + * @param start + * @param line + * @param column + */ +export function parseUpdateExpressionPrefixed( + parser: ParserState, + context: Context, + inNew: 0 | 1, + isLHS: 0 | 1, + start: number, + line: number, + column: number +): ESTree.UpdateExpression { + // UpdateExpression :: + // LeftHandSideExpression ('++' | '--')? + + if (inNew) report(parser, Errors.InvalidIncDecNew); + if (!isLHS) report(parser, Errors.Unexpected); + + const { token } = parser; + + nextToken(parser, context | Context.AllowRegExp); + + const arg = parseLeftHandSideExpression(parser, context, 0, 0, 1, parser.tokenPos, parser.linePos, parser.colPos); + + if (parser.assignable & AssignmentKind.CannotAssign) { + report(parser, Errors.InvalidIncDecTarget); + } + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode(parser, context, start, line, column, { + type: 'UpdateExpression', + argument: arg, + operator: KeywordDescTable[token & Token.Type] as ESTree.UpdateOperator, + prefix: true + }); +} + +/** + * Parses expressions such as a literal expression + * and update expression. + * + * @param parser Parser object + * @param context Context masks + * @param kind Binding kind + * @param inNew + * @param canAssign + * @param isPattern + * @param inGroup + * @param start + * @param line + * @param column + */ + +export function parsePrimaryExpression( + parser: ParserState, + context: Context, + kind: BindingKind, + inNew: 0 | 1, + canAssign: 0 | 1, + isPattern: 0 | 1, + inGroup: 0 | 1, + isLHS: 0 | 1, + start: number, + line: number, + column: number +): any { + // PrimaryExpression :: + // 'this' + // 'null' + // 'true' + // 'false' + // Identifier + // Number + // String + // BigIntLiteral + // ArrayLiteral + // ObjectLiteral + // RegExpLiteral + // ClassLiteral + // ImportCall + // ImportMeta + // '(' Expression ')' + // TemplateLiteral + // AsyncFunctionLiteral + // YieldExpression + // AwaitExpression + // PrivateField + // Decorator + // Intrinsic + // JSX + + if ((parser.token & Token.IsIdentifier) === Token.IsIdentifier) { + switch (parser.token) { + case Token.AwaitKeyword: + return parseAwaitExpression(parser, context, inNew, inGroup, start, line, column); + case Token.YieldKeyword: + return parseYieldExpression(parser, context, inGroup, canAssign, start, line, column); + case Token.AsyncKeyword: + return parseAsyncExpression(parser, context, inGroup, isLHS, canAssign, isPattern, inNew, start, line, column); + default: // ignore + } + + const { token, tokenValue } = parser; + + const expr = parseIdentifier(parser, context | Context.TaggedTemplate, isPattern); + + if (parser.token === Token.Arrow) { + if (!isLHS) report(parser, Errors.Unexpected); + classifyIdentifier(parser, context, token, /* isArrow */ 1); + return parseArrowFromIdentifier(parser, context, tokenValue, expr, inNew, canAssign, 0, start, line, column); + } + + if (context & Context.InClass && token === Token.Arguments) report(parser, Errors.InvalidClassFieldArgEval); + + // Only a "simple validation" is done here to handle 'let' edge cases + + if (token === Token.LetKeyword) { + if (context & Context.Strict) report(parser, Errors.StrictInvalidLetInExprPos); + if (kind & (BindingKind.Let | BindingKind.Const)) report(parser, Errors.InvalidLetConstBinding); + } + + parser.assignable = + context & Context.Strict && (token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments + ? AssignmentKind.CannotAssign + : AssignmentKind.Assignable; + + return expr; + } + + if ((parser.token & Token.IsStringOrNumber) === Token.IsStringOrNumber) { + return parseLiteral(parser, context); + } + + // Update + Unary + Primary expression + switch (parser.token) { + case Token.Increment: + case Token.Decrement: + return parseUpdateExpressionPrefixed(parser, context, inNew, isLHS, start, line, column); + case Token.DeleteKeyword: + case Token.Negate: + case Token.Complement: + case Token.Add: + case Token.Subtract: + case Token.TypeofKeyword: + case Token.VoidKeyword: + return parseUnaryExpression(parser, context, isLHS, start, line, column, inGroup); + case Token.FunctionKeyword: + return parseFunctionExpression(parser, context, /* isAsync */ 0, inGroup, start, line, column); + case Token.LeftBrace: + return parseObjectLiteral(parser, context, canAssign ? 0 : 1, inGroup, start, line, column); + case Token.LeftBracket: + return parseArrayLiteral(parser, context, canAssign ? 0 : 1, inGroup, start, line, column); + case Token.LeftParen: + return parseParenthesizedExpression( + parser, + context, + canAssign, + BindingKind.ArgumentList, + Origin.None, + start, + line, + column + ); + case Token.FalseKeyword: + case Token.TrueKeyword: + case Token.NullKeyword: + return parseNullOrTrueOrFalseLiteral(parser, context, start, line, column); + case Token.ThisKeyword: + return parseThisExpression(parser, context); + case Token.RegularExpression: + return parseRegExpLiteral(parser, context, start, line, column); + case Token.Decorator: + case Token.ClassKeyword: + return parseClassExpression(parser, context, inGroup, start, line, column); + case Token.SuperKeyword: + return parseSuperExpression(parser, context, start, line, column); + case Token.TemplateSpan: + return parseTemplateLiteral(parser, context, start, line, column); + case Token.TemplateContinuation: + return parseTemplate(parser, context); + case Token.NewKeyword: + return parseNewExpression(parser, context, inGroup, start, line, column); + case Token.BigIntLiteral: + return parseBigIntLiteral(parser, context, start, line, column); + case Token.PrivateField: + return parsePrivateIdentifier(parser, context, start, line, column); + case Token.ImportKeyword: + return parseImportCallOrMetaExpression(parser, context, inNew, inGroup, start, line, column); + case Token.LessThan: + if (context & Context.OptionsJSX) + return parseJSXRootElementOrFragment(parser, context, /*inJSXChild*/ 1, start, line, column); + default: + if (isValidIdentifier(context, parser.token)) return parseIdentifierOrArrow(parser, context, start, line, column); + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + } +} + +/** + * Parses Import call expression + * + * @param parser Parser object + * @param context Context masks + * @param inGroup + * @param start + * @param line + * @param column + */ +function parseImportCallOrMetaExpression( + parser: ParserState, + context: Context, + inNew: 0 | 1, + inGroup: 0 | 1, + start: number, + line: number, + column: number +): ESTree.ImportExpression | ESTree.MetaProperty { + // ImportCall[Yield, Await]: + // import(AssignmentExpression[+In, ?Yield, ?Await]) + + let expr: ESTree.Identifier | ESTree.ImportExpression = parseIdentifier(parser, context, 0); + + if (parser.token === Token.Period) { + return parseImportMetaExpression(parser, context, expr, start, line, column); + } + + if (inNew) report(parser, Errors.InvalidImportNew); + + expr = parseImportExpression(parser, context, inGroup, start, line, column); + + parser.assignable = AssignmentKind.CannotAssign; + + return parseMemberOrUpdateExpression(parser, context, expr, inGroup, 0, start, line, column); +} + +/** + * Parses import meta expression + * + * @param parser Parser object + * @param context Context masks + * @param meta ESTree AST node + * @param start + * @param line + * @param column + */ + +export function parseImportMetaExpression( + parser: ParserState, + context: Context, + meta: ESTree.Identifier, + start: number, + line: number, + column: number +): ESTree.MetaProperty { + if ((context & Context.Module) === 0) report(parser, Errors.ImportMetaOutsideModule); + + nextToken(parser, context); // skips: '.' + + if (parser.token !== Token.Meta && parser.tokenValue !== 'meta') + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode(parser, context, start, line, column, { + type: 'MetaProperty', + meta, + property: parseIdentifier(parser, context, 0) + }); +} + +/** + * Parses import expression + * + * @param parser Parser object + * @param context Context masks + * @param inGroup + * @param start + * @param line + * @param column + */ + +export function parseImportExpression( + parser: ParserState, + context: Context, + inGroup: 0 | 1, + start: number, + line: number, + column: number +): ESTree.ImportExpression { + consume(parser, context | Context.AllowRegExp, Token.LeftParen); + + if (parser.token === Token.Ellipsis) report(parser, Errors.InvalidSpreadInImport); + + const source = parseExpression(parser, context, 1, 0, inGroup, parser.tokenPos, parser.linePos, parser.colPos); + + consume(parser, context, Token.RightParen); + + return finishNode(parser, context, start, line, column, { + type: 'ImportExpression', + source + }); +} + +/** + * Parses BigInt literal + * + * @param parser Parser object + * @param context Context masks + */ +export function parseBigIntLiteral( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.BigIntLiteral { + const { tokenRaw, tokenValue } = parser; + nextToken(parser, context); + parser.assignable = AssignmentKind.CannotAssign; + return finishNode( + parser, + context, + start, + line, + column, + context & Context.OptionsRaw + ? { + type: 'Literal', + value: tokenValue, + bigint: tokenRaw.slice(0, -1), // without the ending "n" + raw: tokenRaw + } + : { + type: 'Literal', + value: tokenValue, + bigint: tokenRaw.slice(0, -1) // without the ending "n" + } + ); +} + +/** + * Parses template literal + * + * @param parser Parser object + * @param context Context masks + */ +export function parseTemplateLiteral( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.TemplateLiteral { + /** + * Template Literals + * + * Template :: + * FullTemplate + * TemplateHead + * + * FullTemplate :: + * `TemplateCharactersopt` + * + * TemplateHead :: + * ` TemplateCharactersopt ${ + * + * TemplateSubstitutionTail :: + * TemplateMiddle + * TemplateTail + * + * TemplateMiddle :: + * } TemplateCharactersopt ${ + * + * TemplateTail :: + * } TemplateCharactersopt ` + * + * TemplateCharacters :: + * TemplateCharacter TemplateCharactersopt + * + * TemplateCharacter :: + * SourceCharacter but not one of ` or \ or $ + * $ [lookahead not { ] + * \ EscapeSequence + * LineContinuation + */ + + parser.assignable = AssignmentKind.CannotAssign; + const { tokenValue, tokenRaw, tokenPos, linePos, colPos } = parser; + consume(parser, context, Token.TemplateSpan); + const quasis = [parseTemplateElement(parser, context, tokenValue, tokenRaw, tokenPos, linePos, colPos, true)]; + + return finishNode(parser, context, start, line, column, { + type: 'TemplateLiteral', + expressions: [], + quasis + }); +} + +/** + * Parses template + * + * @param parser Parser object + * @param context Context masks + */ +export function parseTemplate(parser: ParserState, context: Context): ESTree.TemplateLiteral { + context = (context | Context.DisallowIn) ^ Context.DisallowIn; + + const { tokenValue, tokenRaw, tokenPos, linePos, colPos } = parser; + consume(parser, context | Context.AllowRegExp, Token.TemplateContinuation); + const quasis = [ + parseTemplateElement(parser, context, tokenValue, tokenRaw, tokenPos, linePos, colPos, /* tail */ false) + ]; + + const expressions = [parseExpressions(parser, context, 0, 1, parser.tokenPos, parser.linePos, parser.colPos)]; + + if (parser.token !== Token.RightBrace) report(parser, Errors.InvalidTemplateContinuation); + + while ((parser.token = scanTemplateTail(parser, context)) !== Token.TemplateSpan) { + const { tokenValue, tokenRaw, tokenPos, linePos, colPos } = parser; + consume(parser, context | Context.AllowRegExp, Token.TemplateContinuation); + quasis.push( + parseTemplateElement(parser, context, tokenValue, tokenRaw, tokenPos, linePos, colPos, /* tail */ false) + ); + + expressions.push(parseExpressions(parser, context, 0, 1, parser.tokenPos, parser.linePos, parser.colPos)); + if (parser.token !== Token.RightBrace) report(parser, Errors.InvalidTemplateContinuation); + } + + { + const { tokenValue, tokenRaw, tokenPos, linePos, colPos } = parser; + consume(parser, context, Token.TemplateSpan); + quasis.push( + parseTemplateElement(parser, context, tokenValue, tokenRaw, tokenPos, linePos, colPos, /* tail */ true) + ); + } + + return finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'TemplateLiteral', + expressions, + quasis + }); +} + +/** + * Parses template spans + * + * @param parser Parser object + * @param tail + */ +export function parseTemplateElement( + parser: ParserState, + context: Context, + cooked: string | null, + raw: string, + start: number, + line: number, + col: number, + tail: boolean +): ESTree.TemplateElement { + const node = finishNode(parser, context, start, line, col, { + type: 'TemplateElement', + value: { + cooked, + raw + }, + tail + }) as ESTree.TemplateElement; + + const tailSize = tail ? 1 : 2; + + // Patch range + if (context & Context.OptionsRanges) { + // skip the front "`" or "}" + (node.start as number) += 1; + (node.range as [number, number])[0] += 1; + // skip the tail "`" or "${" + (node.end as number) -= tailSize; + (node.range as [number, number])[1] -= tailSize; + } + + // Patch loc + if (context & Context.OptionsLoc) { + // skip the front "`" or "}" + (node.loc as ESTree.SourceLocation).start.column += 1; + // skip the tail "`" or "${" + (node.loc as ESTree.SourceLocation).end.column -= tailSize; + } + + return node; +} + +/** + * Parses spread element + * + * @param parser Parser object + * @param context Context masks + */ +function parseSpreadElement( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.SpreadElement { + context = (context | Context.DisallowIn) ^ Context.DisallowIn; + consume(parser, context | Context.AllowRegExp, Token.Ellipsis); + const argument = parseExpression(parser, context, 1, 0, 0, parser.tokenPos, parser.linePos, parser.colPos); + parser.assignable = AssignmentKind.Assignable; + return finishNode(parser, context, start, line, column, { + type: 'SpreadElement', + argument + }); +} + +/** + * Parses arguments + * + * @param parser Parser object + * @param context Context masks + */ +export function parseArguments( + parser: ParserState, + context: Context, + inGroup: 0 | 1 +): (ESTree.SpreadElement | ESTree.Expression)[] { + // Arguments :: + // '(' (AssignmentExpression)*[','] ')' + nextToken(parser, context | Context.AllowRegExp); + + const args: (ESTree.Expression | ESTree.SpreadElement)[] = []; + + if (parser.token === Token.RightParen) { + nextToken(parser, context); + return args; + } + + while (parser.token !== Token.RightParen) { + if (parser.token === Token.Ellipsis) { + args.push(parseSpreadElement(parser, context, parser.tokenPos, parser.linePos, parser.colPos)); + } else { + args.push(parseExpression(parser, context, 1, 0, inGroup, parser.tokenPos, parser.linePos, parser.colPos)); + } + + if (parser.token !== Token.Comma) break; + + nextToken(parser, context | Context.AllowRegExp); + + if (parser.token === Token.RightParen) break; + } + + consume(parser, context, Token.RightParen); + + return args; +} + +/** + * Parses an identifier expression + * + * @param parser Parser object + * @param context Context masks + */ +export function parseIdentifier(parser: ParserState, context: Context, isPattern: 0 | 1): ESTree.Identifier { + const { tokenValue, tokenPos, linePos, colPos } = parser; + nextToken(parser, context); + + return finishNode( + parser, + context, + tokenPos, + linePos, + colPos, + context & Context.OptionsIdentifierPattern + ? { + type: 'Identifier', + name: tokenValue, + pattern: isPattern === 1 + } + : { + type: 'Identifier', + name: tokenValue + } + ); +} + +/** + * Parses an literal expression such as string literal + * + * @param parser Parser object + * @param context Context masks + */ +export function parseLiteral(parser: ParserState, context: Context): ESTree.Literal { + const { tokenValue, tokenRaw, tokenPos, linePos, colPos } = parser; + if (parser.token === Token.BigIntLiteral) { + return parseBigIntLiteral(parser, context, tokenPos, linePos, colPos); + } + + nextToken(parser, context); + parser.assignable = AssignmentKind.CannotAssign; + return finishNode( + parser, + context, + tokenPos, + linePos, + colPos, + context & Context.OptionsRaw + ? { + type: 'Literal', + value: tokenValue, + raw: tokenRaw + } + : { + type: 'Literal', + value: tokenValue + } + ); +} + +/** + * Parses null and boolean expressions + * + * @param parser Parser object + * @param context Context masks + */ +export function parseNullOrTrueOrFalseLiteral( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.Literal { + const raw = KeywordDescTable[parser.token & Token.Type]; + const value = parser.token === Token.NullKeyword ? null : raw === 'true'; + + nextToken(parser, context); + parser.assignable = AssignmentKind.CannotAssign; + return finishNode( + parser, + context, + start, + line, + column, + context & Context.OptionsRaw + ? { + type: 'Literal', + value, + raw + } + : { + type: 'Literal', + value + } + ); +} + +/** + * Parses this expression + * + * @param parser Parser object + * @param context Context masks + */ +export function parseThisExpression(parser: ParserState, context: Context): ESTree.ThisExpression { + const { tokenPos, linePos, colPos } = parser; + nextToken(parser, context); + parser.assignable = AssignmentKind.CannotAssign; + return finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'ThisExpression' + }); +} + +/** + * Parse function declaration + * + * @param parser Parser object + * @param context Context masks + * @param scope + * @param allowGen + * @param ExportDefault + * @param isAsync + * @param start + */ +export function parseFunctionDeclaration( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + origin: Origin, + allowGen: 0 | 1, + flags: HoistedFunctionFlags, + isAsync: 0 | 1, + start: number, + line: number, + column: number +): ESTree.FunctionDeclaration { + // FunctionDeclaration :: + // function BindingIdentifier ( FormalParameters ) { FunctionBody } + // function ( FormalParameters ) { FunctionBody } + // + // GeneratorDeclaration :: + // function * BindingIdentifier ( FormalParameters ) { FunctionBody } + // function * ( FormalParameters ) { FunctionBody } + // + // AsyncFunctionDeclaration :: + // async function BindingIdentifier ( FormalParameters ) { FunctionBody } + // async function ( FormalParameters ) { FunctionBody } + // + // AsyncGeneratorDeclaration :: + // async function * BindingIdentifier ( FormalParameters ) { FunctionBody } + // async function * ( FormalParameters ) { FunctionBody } + + nextToken(parser, context | Context.AllowRegExp); + + const isGenerator = allowGen ? optionalBit(parser, context, Token.Multiply) : 0; + + let id: ESTree.Identifier | null = null; + let firstRestricted: Token | undefined; + + // Create a new function scope + let functionScope = scope ? createScope() : void 0; + + if (parser.token === Token.LeftParen) { + if ((flags & HoistedClassFlags.Hoisted) < 1) report(parser, Errors.DeclNoName, 'Function'); + } else { + // In ES6, a function behaves as a lexical binding, except in + // a script scope, or the initial scope of eval or another function. + const kind = + origin & Origin.TopLevel && ((context & Context.InGlobal) < 1 || (context & Context.Module) < 1) + ? BindingKind.Variable + : BindingKind.FunctionLexical; + + validateFunctionName(parser, context | ((context & 0b0000000000000000000_1100_00000000) << 11), parser.token); + + if (scope) { + if (kind & BindingKind.Variable) { + addVarName(parser, context, scope as ScopeState, parser.tokenValue, kind); + } else { + addBlockName(parser, context, scope, parser.tokenValue, kind, origin); + } + + functionScope = addChildScope(functionScope, ScopeKind.FunctionRoot); + + if (flags) { + if (flags & HoistedClassFlags.Export) { + declareUnboundVariable(parser, parser.tokenValue); + } + } + } + + firstRestricted = parser.token; + + if (parser.token & Token.IsIdentifier) { + id = parseIdentifier(parser, context, 0); + } else { + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + } + } + + context = + ((context | 0b0000001111011000000_0000_00000000) ^ 0b0000001111011000000_0000_00000000) | + Context.AllowNewTarget | + ((isAsync * 2 + isGenerator) << 21) | + (isGenerator ? 0 : Context.AllowEscapedKeyword); + + if (scope) functionScope = addChildScope(functionScope, ScopeKind.FunctionParams); + + const params = parseFormalParametersOrFormalList( + parser, + context | Context.InArgumentList, + functionScope, + 0, + BindingKind.ArgumentList + ); + + const body = parseFunctionBody( + parser, + (context | Context.InGlobal | Context.InSwitch | Context.InIteration) ^ + (Context.InGlobal | Context.InSwitch | Context.InIteration), + scope ? addChildScope(functionScope, ScopeKind.FunctionBody) : functionScope, + Origin.Declaration, + firstRestricted, + scope ? (functionScope as ScopeState).scopeError : void 0 + ); + + return finishNode(parser, context, start, line, column, { + type: 'FunctionDeclaration', + id, + params, + body, + async: isAsync === 1, + generator: isGenerator === 1 + }); +} + +/** + * Parse function expression + * + * @param parser Parser object + * @param context Context masks + * @param isAsync + */ +export function parseFunctionExpression( + parser: ParserState, + context: Context, + isAsync: 0 | 1, + inGroup: 0 | 1, + start: number, + line: number, + column: number +): ESTree.FunctionExpression { + // GeneratorExpression: + // function* BindingIdentifier [Yield][opt](FormalParameters[Yield]){ GeneratorBody } + // + // FunctionExpression: + // function BindingIdentifier[opt](FormalParameters){ FunctionBody } + + nextToken(parser, context | Context.AllowRegExp); + + const isGenerator = optionalBit(parser, context, Token.Multiply); + const generatorAndAsyncFlags = (isAsync * 2 + isGenerator) << 21; + + let id: ESTree.Identifier | null = null; + let firstRestricted: Token | undefined; + + // Create a new function scope + let scope = context & Context.OptionsLexical ? createScope() : void 0; + + if ((parser.token & (Token.IsIdentifier | Token.Keyword | Token.FutureReserved)) > 0) { + validateFunctionName(parser, ((context | 0x1ec0000) ^ 0x1ec0000) | generatorAndAsyncFlags, parser.token); + + if (scope) scope = addChildScope(scope, ScopeKind.FunctionRoot); + + firstRestricted = parser.token; + id = parseIdentifier(parser, context, /* isPattern */ 0); + } + + context = + ((context | 0b0000001111011000000_0000_00000000) ^ 0b0000001111011000000_0000_00000000) | + Context.AllowNewTarget | + generatorAndAsyncFlags | + (isGenerator ? 0 : Context.AllowEscapedKeyword); + + if (scope) scope = addChildScope(scope, ScopeKind.FunctionParams); + + const params = parseFormalParametersOrFormalList( + parser, + context | Context.InArgumentList, + scope, + inGroup, + BindingKind.ArgumentList + ); + + const body = parseFunctionBody( + parser, + context & ~(0x8001000 | Context.InGlobal | Context.InSwitch | Context.InIteration | Context.InClass), + scope ? addChildScope(scope, ScopeKind.FunctionBody) : scope, + 0, + firstRestricted, + void 0 + ); + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode(parser, context, start, line, column, { + type: 'FunctionExpression', + id, + params, + body, + async: isAsync === 1, + generator: isGenerator === 1 + }); +} + +/** + * Parses array literal expression + * + * @param parser Parser object + * @param context Context masks + * @param skipInitializer + */ +function parseArrayLiteral( + parser: ParserState, + context: Context, + skipInitializer: 0 | 1, + inGroup: 0 | 1, + start: number, + line: number, + column: number +): ESTree.ArrayExpression { + /* ArrayLiteral : + * [ Elisionopt ] + * [ ElementList ] + * [ ElementList , Elisionopt ] + * + * ElementList : + * Elisionopt AssignmentExpression + * Elisionopt ... AssignmentExpression + * ElementList , Elisionopt AssignmentExpression + * ElementList , Elisionopt SpreadElement + * + * Elision : + * , + * Elision , + * + * SpreadElement : + * ... AssignmentExpression + * + */ + const expr = parseArrayExpressionOrPattern( + parser, + context, + void 0, + skipInitializer, + inGroup, + 0, + BindingKind.Empty, + Origin.None, + start, + line, + column + ); + + if (context & Context.OptionsWebCompat && parser.destructible & DestructuringKind.SeenProto) { + report(parser, Errors.DuplicateProto); + } + + if (parser.destructible & DestructuringKind.HasToDestruct) { + report(parser, Errors.InvalidShorthandPropInit); + } + + return expr as ESTree.ArrayExpression; +} + +/** + * Parse array expression or pattern + * + * @param parser Parser object + * @param context Context masks + * @param skipInitializer + * @param BindingKind + */ + +export function parseArrayExpressionOrPattern( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + skipInitializer: 0 | 1, + inGroup: 0 | 1, + isPattern: 0 | 1, + kind: BindingKind, + origin: Origin, + start: number, + line: number, + column: number +): ESTree.ArrayExpression | ESTree.ArrayPattern | ESTree.AssignmentExpression { + /* ArrayLiteral : + * [ Elisionopt ] + * [ ElementList ] + * [ ElementList , Elisionopt ] + * + * ElementList : + * Elisionopt AssignmentExpression + * Elisionopt ... AssignmentExpression + * ElementList , Elisionopt AssignmentExpression + * ElementList , Elisionopt SpreadElement + * + * Elision : + * , + * Elision , + * + * SpreadElement : + * ... AssignmentExpression + * + * ArrayAssignmentPattern[Yield] : + * [ Elisionopt AssignmentRestElement[?Yield]opt ] + * [ AssignmentElementList[?Yield] ] + * [ AssignmentElementList[?Yield] , Elisionopt AssignmentRestElement[?Yield]opt ] + * + * AssignmentRestElement[Yield] : + * ... DestructuringAssignmentTarget[?Yield] + * + * AssignmentElementList[Yield] : + * AssignmentElisionElement[?Yield] + * AssignmentElementList[?Yield] , AssignmentElisionElement[?Yield] + * + * AssignmentElisionElement[Yield] : + * Elisionopt AssignmentElement[?Yield] + * + * AssignmentElement[Yield] : + * DestructuringAssignmentTarget[?Yield] Initializer[In,?Yield]opt + * + * DestructuringAssignmentTarget[Yield] : + * LeftHandSideExpression[?Yield] + */ + + nextToken(parser, context | Context.AllowRegExp); + + const elements: (ESTree.Identifier | ESTree.AssignmentExpression | null)[] = []; + let destructible: AssignmentKind | DestructuringKind = 0; + + context = (context | Context.DisallowIn) ^ Context.DisallowIn; + + while (parser.token !== Token.RightBracket) { + if (consumeOpt(parser, context | Context.AllowRegExp, Token.Comma)) { + elements.push(null); + } else { + let left: any; + + const { token, tokenPos, linePos, colPos, tokenValue } = parser; + + if (token & Token.IsIdentifier) { + left = parsePrimaryExpression(parser, context, kind, 0, 1, 0, inGroup, 1, tokenPos, linePos, colPos); + + if (parser.token === Token.Assign) { + if (parser.assignable & AssignmentKind.CannotAssign) report(parser, Errors.CantAssignTo); + + nextToken(parser, context | Context.AllowRegExp); + + if (scope) addVarOrBlock(parser, context, scope, tokenValue, kind, origin); + + const right = parseExpression(parser, context, 1, 1, inGroup, parser.tokenPos, parser.linePos, parser.colPos); + + left = finishNode( + parser, + context, + tokenPos, + linePos, + colPos, + isPattern + ? { + type: 'AssignmentPattern', + left, + right + } + : ({ + type: 'AssignmentExpression', + operator: '=', + left, + right + } as any) + ); + + destructible |= + parser.destructible & DestructuringKind.Yield + ? DestructuringKind.Yield + : 0 | (parser.destructible & DestructuringKind.Await) + ? DestructuringKind.Await + : 0; + } else if (parser.token === Token.Comma || parser.token === Token.RightBracket) { + if (parser.assignable & AssignmentKind.CannotAssign) { + destructible |= DestructuringKind.CannotDestruct; + } else if (scope) { + addVarOrBlock(parser, context, scope, tokenValue, kind, origin); + } + destructible |= + parser.destructible & DestructuringKind.Yield + ? DestructuringKind.Yield + : 0 | (parser.destructible & DestructuringKind.Await) + ? DestructuringKind.Await + : 0; + } else { + destructible |= + kind & BindingKind.ArgumentList + ? DestructuringKind.Assignable + : (kind & BindingKind.Empty) < 1 + ? DestructuringKind.CannotDestruct + : 0; + + left = parseMemberOrUpdateExpression(parser, context, left, inGroup, 0, tokenPos, linePos, colPos); + + if (parser.token !== Token.Comma && parser.token !== Token.RightBracket) { + if (parser.token !== Token.Assign) destructible |= DestructuringKind.CannotDestruct; + left = parseAssignmentExpression(parser, context, inGroup, isPattern, tokenPos, linePos, colPos, left); + } else if (parser.token !== Token.Assign) { + destructible |= + parser.assignable & AssignmentKind.CannotAssign + ? DestructuringKind.CannotDestruct + : DestructuringKind.Assignable; + } + } + } else if (token & Token.IsPatternStart) { + left = + parser.token === Token.LeftBrace + ? parseObjectLiteralOrPattern( + parser, + context, + scope, + 0, + inGroup, + isPattern, + kind, + origin, + tokenPos, + linePos, + colPos + ) + : parseArrayExpressionOrPattern( + parser, + context, + scope, + 0, + inGroup, + isPattern, + kind, + origin, + tokenPos, + linePos, + colPos + ); + + destructible |= parser.destructible; + + parser.assignable = + parser.destructible & DestructuringKind.CannotDestruct + ? AssignmentKind.CannotAssign + : AssignmentKind.Assignable; + + if (parser.token === Token.Comma || parser.token === Token.RightBracket) { + if (parser.assignable & AssignmentKind.CannotAssign) { + destructible |= DestructuringKind.CannotDestruct; + } + } else if (parser.destructible & DestructuringKind.HasToDestruct) { + report(parser, Errors.InvalidDestructuringTarget); + } else { + left = parseMemberOrUpdateExpression(parser, context, left, inGroup, 0, tokenPos, linePos, colPos); + destructible = parser.assignable & AssignmentKind.CannotAssign ? DestructuringKind.CannotDestruct : 0; + + if (parser.token !== Token.Comma && parser.token !== Token.RightBracket) { + left = parseAssignmentExpression(parser, context, inGroup, isPattern, tokenPos, linePos, colPos, left); + } else if (parser.token !== Token.Assign) { + destructible |= + parser.assignable & AssignmentKind.CannotAssign + ? DestructuringKind.CannotDestruct + : DestructuringKind.Assignable; + } + } + } else if (token === Token.Ellipsis) { + left = parseSpreadOrRestElement( + parser, + context, + scope, + Token.RightBracket, + kind, + origin, + 0, + inGroup, + isPattern, + tokenPos, + linePos, + colPos + ); + destructible |= parser.destructible; + if (parser.token !== Token.Comma && parser.token !== Token.RightBracket) + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + } else { + left = parseLeftHandSideExpression(parser, context, 1, 0, 1, tokenPos, linePos, colPos); + + if (parser.token !== Token.Comma && parser.token !== Token.RightBracket) { + left = parseAssignmentExpression(parser, context, inGroup, isPattern, tokenPos, linePos, colPos, left); + if ((kind & (BindingKind.Empty | BindingKind.ArgumentList)) < 1 && token === Token.LeftParen) + destructible |= DestructuringKind.CannotDestruct; + } else if (parser.assignable & AssignmentKind.CannotAssign) { + destructible |= DestructuringKind.CannotDestruct; + } else if (token === Token.LeftParen) { + destructible |= + parser.assignable & AssignmentKind.Assignable && kind & (BindingKind.Empty | BindingKind.ArgumentList) + ? DestructuringKind.Assignable + : DestructuringKind.CannotDestruct; + } + } + + elements.push(left); + + if (consumeOpt(parser, context | Context.AllowRegExp, Token.Comma)) { + if (parser.token === Token.RightBracket) break; + } else break; + } + } + + consume(parser, context, Token.RightBracket); + + const node = finishNode(parser, context, start, line, column, { + type: isPattern ? 'ArrayPattern' : 'ArrayExpression', + elements + } as any); + + if (!skipInitializer && parser.token & Token.IsAssignOp) { + return parseArrayOrObjectAssignmentPattern( + parser, + context, + destructible, + inGroup, + isPattern, + start, + line, + column, + node + ); + } + + parser.destructible = destructible; + + return node; +} + +/** + * Parses array or object assignment pattern + * + * @param parser Parser object + * @param context Context masks + * @param destructible + * @param inGroup + * @param start Start index + * @param line Start line + * @param column Start of column + * @param node ESTree AST node + */ + +function parseArrayOrObjectAssignmentPattern( + parser: ParserState, + context: Context, + destructible: AssignmentKind | DestructuringKind, + inGroup: 0 | 1, + isPattern: 0 | 1, + start: number, + line: number, + column: number, + node: ESTree.ArrayExpression | ESTree.ObjectExpression | ESTree.ObjectPattern +): ESTree.AssignmentExpression { + // 12.15.5 Destructuring Assignment + // + // AssignmentElement[Yield, Await]: + // DestructuringAssignmentTarget[?Yield, ?Await] + // DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] + // + + if (parser.token !== Token.Assign) report(parser, Errors.CantAssignTo); + + nextToken(parser, context | Context.AllowRegExp); + + if (destructible & DestructuringKind.CannotDestruct) report(parser, Errors.CantAssignTo); + + if (!isPattern) reinterpretToPattern(parser, node); + + const { tokenPos, linePos, colPos } = parser; + + const right = parseExpression(parser, context, 1, 1, inGroup, tokenPos, linePos, colPos); + + parser.destructible = + ((destructible | DestructuringKind.SeenProto | DestructuringKind.HasToDestruct) ^ + (DestructuringKind.HasToDestruct | DestructuringKind.SeenProto)) | + (parser.destructible & DestructuringKind.Await ? DestructuringKind.Await : 0) | + (parser.destructible & DestructuringKind.Yield ? DestructuringKind.Yield : 0); + + return finishNode( + parser, + context, + start, + line, + column, + isPattern + ? { + type: 'AssignmentPattern', + left: node, + right + } + : ({ + type: 'AssignmentExpression', + left: node, + operator: '=', + right + } as any) + ); +} + +/** + * Parses rest or spread element + * + * @param parser Parser object + * @param context Context masks + * @param closingToken + * @param type Binding kind + * @param origin Binding origin + * @param isAsync + * @param isGroup + * @param start Start index + * @param line Start line + * @param column Start of column + */ +function parseSpreadOrRestElement( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + closingToken: Token, + kind: BindingKind, + origin: Origin, + isAsync: 0 | 1, + inGroup: 0 | 1, + isPattern: 0 | 1, + start: number, + line: number, + column: number +): ESTree.SpreadElement | ESTree.RestElement { + nextToken(parser, context | Context.AllowRegExp); // skip '...' + + let argument: ESTree.Expression | null = null; + let destructible: AssignmentKind | DestructuringKind = DestructuringKind.None; + + let { token, tokenValue, tokenPos, linePos, colPos } = parser; + + if (token & (Token.Keyword | Token.IsIdentifier)) { + parser.assignable = AssignmentKind.Assignable; + + argument = parsePrimaryExpression(parser, context, kind, 0, 1, 0, inGroup, 1, tokenPos, linePos, colPos); + + token = parser.token; + + argument = parseMemberOrUpdateExpression( + parser, + context, + argument as ESTree.Expression, + inGroup, + 0, + tokenPos, + linePos, + colPos + ); + + if (parser.token !== Token.Comma && parser.token !== closingToken) { + if (parser.assignable & AssignmentKind.CannotAssign && parser.token === Token.Assign) + report(parser, Errors.InvalidDestructuringTarget); + + destructible |= DestructuringKind.CannotDestruct; + + argument = parseAssignmentExpression(parser, context, inGroup, isPattern, tokenPos, linePos, colPos, argument); + } + + if (parser.assignable & AssignmentKind.CannotAssign) { + destructible |= DestructuringKind.CannotDestruct; + } else if (token === closingToken || token === Token.Comma) { + if (scope) addVarOrBlock(parser, context, scope, tokenValue, kind, origin); + } else { + destructible |= DestructuringKind.Assignable; + } + + destructible |= parser.destructible & DestructuringKind.Await ? DestructuringKind.Await : 0; + } else if (token === closingToken) { + report(parser, Errors.RestMissingArg); + } else if (token & Token.IsPatternStart) { + argument = + parser.token === Token.LeftBrace + ? parseObjectLiteralOrPattern( + parser, + context, + scope, + 1, + inGroup, + isPattern, + kind, + origin, + tokenPos, + linePos, + colPos + ) + : parseArrayExpressionOrPattern( + parser, + context, + scope, + 1, + inGroup, + isPattern, + kind, + origin, + tokenPos, + linePos, + colPos + ); + + token = parser.token; + + if (token !== Token.Assign && token !== closingToken && token !== Token.Comma) { + if (parser.destructible & DestructuringKind.HasToDestruct) report(parser, Errors.InvalidDestructuringTarget); + + argument = parseMemberOrUpdateExpression(parser, context, argument, inGroup, 0, tokenPos, linePos, colPos); + + destructible |= parser.assignable & AssignmentKind.CannotAssign ? DestructuringKind.CannotDestruct : 0; + + if ((parser.token & Token.IsAssignOp) === Token.IsAssignOp) { + if (parser.token !== Token.Assign) destructible |= DestructuringKind.CannotDestruct; + argument = parseAssignmentExpression(parser, context, inGroup, isPattern, tokenPos, linePos, colPos, argument); + } else { + if ((parser.token & Token.IsBinaryOp) === Token.IsBinaryOp) { + argument = parseBinaryExpression(parser, context, 1, tokenPos, linePos, colPos, 4, token, argument as any); + } + if (consumeOpt(parser, context | Context.AllowRegExp, Token.QuestionMark)) { + argument = parseConditionalExpression(parser, context, argument as any, tokenPos, linePos, colPos); + } + destructible |= + parser.assignable & AssignmentKind.CannotAssign + ? DestructuringKind.CannotDestruct + : DestructuringKind.Assignable; + } + } else { + destructible |= + closingToken === Token.RightBrace && token !== Token.Assign + ? DestructuringKind.CannotDestruct + : parser.destructible; + } + } else { + destructible |= DestructuringKind.Assignable; + + argument = parseLeftHandSideExpression( + parser, + context, + 1, + inGroup, + 1, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + + const { token, tokenPos, linePos, colPos } = parser; + + if (token === Token.Assign && token !== closingToken && token !== Token.Comma) { + if (parser.assignable & AssignmentKind.CannotAssign) report(parser, Errors.CantAssignTo); + + argument = parseAssignmentExpression(parser, context, inGroup, isPattern, tokenPos, linePos, colPos, argument); + + destructible |= DestructuringKind.CannotDestruct; + } else { + if (token === Token.Comma) { + destructible |= DestructuringKind.CannotDestruct; + } else if (token !== closingToken) { + argument = parseAssignmentExpression(parser, context, inGroup, isPattern, tokenPos, linePos, colPos, argument); + } + + destructible |= + parser.assignable & AssignmentKind.Assignable ? DestructuringKind.Assignable : DestructuringKind.CannotDestruct; + } + + parser.destructible = destructible; + + if (parser.token !== closingToken && parser.token !== Token.Comma) report(parser, Errors.UnclosedSpreadElement); + + return finishNode(parser, context, start, line, column, { + type: isPattern ? 'RestElement' : 'SpreadElement', + argument: argument as ESTree.SpreadArgument + } as any); + } + + if (parser.token !== closingToken) { + if (kind & BindingKind.ArgumentList) + destructible |= isAsync ? DestructuringKind.CannotDestruct : DestructuringKind.Assignable; + + if (consumeOpt(parser, context | Context.AllowRegExp, Token.Assign)) { + if (destructible & DestructuringKind.CannotDestruct) report(parser, Errors.CantAssignTo); + + reinterpretToPattern(parser, argument); + + const right = parseExpression(parser, context, 1, 1, inGroup, parser.tokenPos, parser.linePos, parser.colPos); + + argument = finishNode( + parser, + context, + tokenPos, + linePos, + colPos, + isPattern + ? { + type: 'AssignmentPattern', + left: argument as ESTree.SpreadArgument, + right + } + : ({ + type: 'AssignmentExpression', + left: argument as ESTree.SpreadArgument, + operator: '=', + right + } as any) + ); + + destructible = DestructuringKind.CannotDestruct; + } else { + // Note the difference between '|=' and '=' above + destructible |= DestructuringKind.CannotDestruct; + } + } + + parser.destructible = destructible; + + return finishNode(parser, context, start, line, column, { + type: isPattern ? 'RestElement' : 'SpreadElement', + argument: argument as ESTree.SpreadArgument + } as any); +} + +/** + * Parses method definition + * + * @param parser Parser object + * @param context Context masks + * @param kind + * @param inGroup + * @param start Start index + * @param line Start line + * @param column Start of column + */ +export function parseMethodDefinition( + parser: ParserState, + context: Context, + kind: PropertyKind, + inGroup: 0 | 1, + start: number, + line: number, + column: number +): ESTree.FunctionExpression { + const modifierFlags = + (kind & PropertyKind.Constructor) < 1 ? 0b0000001111010000000_0000_00000000 : 0b0000000111000000000_0000_00000000; + + context = + ((context | modifierFlags) ^ modifierFlags) | + ((kind & 0b0000000000000000000_0000_01011000) << 18) | + 0b0000110000001000000_0000_00000000; + + let scope = context & Context.OptionsLexical ? addChildScope(createScope(), ScopeKind.FunctionParams) : void 0; + + const params = parseMethodFormals( + parser, + context | Context.InArgumentList, + scope, + kind, + BindingKind.ArgumentList, + inGroup + ); + + if (scope) scope = addChildScope(scope, ScopeKind.FunctionBody); + + const body = parseFunctionBody(parser, context & ~(0x8001000 | Context.InGlobal), scope, Origin.None, void 0, void 0); + + return finishNode(parser, context, start, line, column, { + type: 'FunctionExpression', + params, + body, + async: (kind & PropertyKind.Async) > 0, + generator: (kind & PropertyKind.Generator) > 0, + id: null + }); +} + +/** + * Parse object literal or object pattern + * + * @param parser Parser object + * @param context Context masks + * @param skipInitializer + * @param inGroup + * @param start Start index + * @param line Start line + * @param column Start of column + + */ +function parseObjectLiteral( + parser: ParserState, + context: Context, + skipInitializer: 0 | 1, + inGroup: 0 | 1, + start: number, + line: number, + column: number +): ESTree.ObjectExpression { + /** + * ObjectLiteral + * {} + * {PropertyDefinitionList } + * + * {PropertyDefinitionList } + * + * PropertyDefinitionList: + * PropertyDefinition + * PropertyDefinitionList, PropertyDefinition + * + * PropertyDefinition: + * { IdentifierReference } + * { CoverInitializedName } + * { PropertyName:AssignmentExpression } + * + * MethodDefinition: + * ...AssignmentExpression + * + * PropertyName: + * LiteralPropertyName + * ComputedPropertyName + * LiteralPropertyName: + * IdentifierName + * StringLiteral + * NumericLiteral + * + * ComputedPropertyName: AssignmentExpression + * + * CoverInitializedName: + * IdentifierReference , Initializer + * + * Initializer: + * =AssignmentExpression + */ + const expr = parseObjectLiteralOrPattern( + parser, + context, + void 0, + skipInitializer, + inGroup, + 0, + BindingKind.Empty, + Origin.None, + start, + line, + column + ); + + if (context & Context.OptionsWebCompat && parser.destructible & DestructuringKind.SeenProto) { + report(parser, Errors.DuplicateProto); + } + + if (parser.destructible & DestructuringKind.HasToDestruct) { + report(parser, Errors.InvalidShorthandPropInit); + } + + return expr as ESTree.ObjectExpression; +} + +/** + * Parse object literal or object pattern + * + * @param parser Parser object + * @param context Context masks + * @param skipInitializer Context masks + * @param inGroup + * @param kind Binding kind + * @param origin Binding origin + * @param start + * @param line + * @param column + */ +export function parseObjectLiteralOrPattern( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + skipInitializer: 0 | 1, + inGroup: 0 | 1, + isPattern: 0 | 1, + kind: BindingKind, + origin: Origin, + start: number, + line: number, + column: number +): ESTree.ObjectExpression | ESTree.ObjectPattern | ESTree.AssignmentExpression { + /** + * + * ObjectLiteral : + * { } + * { PropertyDefinitionList } + * + * PropertyDefinitionList : + * PropertyDefinition + * PropertyDefinitionList, PropertyDefinition + * + * PropertyDefinition : + * IdentifierName + * PropertyName : AssignmentExpression + * + * PropertyName : + * IdentifierName + * StringLiteral + * NumericLiteral + * + * + * ObjectBindingPattern : + * {} + * { BindingPropertyList } + * { BindingPropertyList , } + * + * BindingPropertyList : + * BindingProperty + * BindingPropertyList , BindingProperty + * + * BindingProperty : + * SingleNameBinding + * PropertyName : BindingElement + * + * SingleNameBinding : + * BindingIdentifier Initializeropt + * + * PropertyDefinition : + * IdentifierName + * CoverInitializedName + * PropertyName : AssignmentExpression + * MethodDefinition + */ + + nextToken(parser, context); + + const properties: (ESTree.Property | ESTree.SpreadElement | ESTree.RestElement)[] = []; + let destructible: DestructuringKind | AssignmentKind = 0; + let prototypeCount = 0; + + context = (context | Context.DisallowIn) ^ Context.DisallowIn; + + while (parser.token !== Token.RightBrace) { + const { token, tokenValue, linePos, colPos, tokenPos } = parser; + + if (token === Token.Ellipsis) { + properties.push( + parseSpreadOrRestElement( + parser, + context, + scope, + Token.RightBrace, + kind, + origin, + 0, + inGroup, + isPattern, + tokenPos, + linePos, + colPos + ) + ); + } else { + let state = PropertyKind.None; + let key: ESTree.Expression | null = null; + let value; + const t = parser.token; + if (parser.token & (Token.IsIdentifier | Token.Keyword) || parser.token === Token.EscapedReserved) { + key = parseIdentifier(parser, context, 0); + + if (parser.token === Token.Comma || parser.token === Token.RightBrace || parser.token === Token.Assign) { + state |= PropertyKind.Shorthand; + + if (context & Context.Strict && (token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) { + destructible |= DestructuringKind.CannotDestruct; + } else { + validateBindingIdentifier(parser, context, kind, token, 0); + } + + if (scope) addVarOrBlock(parser, context, scope, tokenValue, kind, origin); + + if (consumeOpt(parser, context | Context.AllowRegExp, Token.Assign)) { + destructible |= DestructuringKind.HasToDestruct; + + const right = parseExpression( + parser, + context, + 1, + 1, + inGroup, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + + destructible |= + parser.destructible & DestructuringKind.Yield + ? DestructuringKind.Yield + : 0 | (parser.destructible & DestructuringKind.Await) + ? DestructuringKind.Await + : 0; + + value = finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'AssignmentPattern', + left: context & Context.OptionsUniqueKeyInPattern ? Object.assign({}, key) : key, + right + }); + } else { + destructible |= + (token === Token.AwaitKeyword ? DestructuringKind.Await : 0) | + (token === Token.EscapedReserved ? DestructuringKind.CannotDestruct : 0); + value = context & Context.OptionsUniqueKeyInPattern ? Object.assign({}, key) : key; + } + } else if (consumeOpt(parser, context | Context.AllowRegExp, Token.Colon)) { + const { tokenPos, linePos, colPos } = parser; + + if (tokenValue === '__proto__') prototypeCount++; + + if (parser.token & Token.IsIdentifier) { + const tokenAfterColon = parser.token; + const valueAfterColon = parser.tokenValue; + // A reserved word is an IdentifierName that cannot be used as an Identifier + destructible |= t === Token.EscapedReserved ? DestructuringKind.CannotDestruct : 0; + + value = parsePrimaryExpression(parser, context, kind, 0, 1, 0, inGroup, 1, tokenPos, linePos, colPos); + + const { token } = parser; + + value = parseMemberOrUpdateExpression(parser, context, value, inGroup, 0, tokenPos, linePos, colPos); + + if (parser.token === Token.Comma || parser.token === Token.RightBrace) { + if (token === Token.Assign || token === Token.RightBrace || token === Token.Comma) { + destructible |= parser.destructible & DestructuringKind.Await ? DestructuringKind.Await : 0; + if (parser.assignable & AssignmentKind.CannotAssign) { + destructible |= DestructuringKind.CannotDestruct; + } else if (scope && (tokenAfterColon & Token.IsIdentifier) === Token.IsIdentifier) { + addVarOrBlock(parser, context, scope, valueAfterColon, kind, origin); + } + } else { + destructible |= + parser.assignable & AssignmentKind.Assignable + ? DestructuringKind.Assignable + : DestructuringKind.CannotDestruct; + } + } else if ((parser.token & Token.IsAssignOp) === Token.IsAssignOp) { + if (parser.assignable & AssignmentKind.CannotAssign) { + destructible |= DestructuringKind.CannotDestruct; + } else if (token !== Token.Assign) { + destructible |= DestructuringKind.Assignable; + } else if (scope) { + addVarOrBlock(parser, context, scope, valueAfterColon, kind, origin); + } + value = parseAssignmentExpression(parser, context, inGroup, isPattern, tokenPos, linePos, colPos, value); + } else { + destructible |= DestructuringKind.CannotDestruct; + if ((parser.token & Token.IsBinaryOp) === Token.IsBinaryOp) { + value = parseBinaryExpression(parser, context, 1, tokenPos, linePos, colPos, 4, token, value); + } + if (consumeOpt(parser, context | Context.AllowRegExp, Token.QuestionMark)) { + value = parseConditionalExpression(parser, context, value, tokenPos, linePos, colPos); + } + } + } else if ((parser.token & Token.IsPatternStart) === Token.IsPatternStart) { + value = + parser.token === Token.LeftBracket + ? parseArrayExpressionOrPattern( + parser, + context, + scope, + 0, + inGroup, + isPattern, + kind, + origin, + tokenPos, + linePos, + colPos + ) + : parseObjectLiteralOrPattern( + parser, + context, + scope, + 0, + inGroup, + isPattern, + kind, + origin, + tokenPos, + linePos, + colPos + ); + + destructible = parser.destructible; + + parser.assignable = + destructible & DestructuringKind.CannotDestruct ? AssignmentKind.CannotAssign : AssignmentKind.Assignable; + + if (parser.token === Token.Comma || parser.token === Token.RightBrace) { + if (parser.assignable & AssignmentKind.CannotAssign) destructible |= DestructuringKind.CannotDestruct; + } else if (parser.destructible & DestructuringKind.HasToDestruct) { + report(parser, Errors.InvalidDestructuringTarget); + } else { + value = parseMemberOrUpdateExpression(parser, context, value, inGroup, 0, tokenPos, linePos, colPos); + + destructible = parser.assignable & AssignmentKind.CannotAssign ? DestructuringKind.CannotDestruct : 0; + + if ((parser.token & Token.IsAssignOp) === Token.IsAssignOp) { + value = parseAssignmentExpressionOrPattern( + parser, + context, + inGroup, + isPattern, + tokenPos, + linePos, + colPos, + value + ); + } else { + if ((parser.token & Token.IsBinaryOp) === Token.IsBinaryOp) { + value = parseBinaryExpression(parser, context, 1, tokenPos, linePos, colPos, 4, token, value); + } + if (consumeOpt(parser, context | Context.AllowRegExp, Token.QuestionMark)) { + value = parseConditionalExpression(parser, context, value, tokenPos, linePos, colPos); + } + destructible |= + parser.assignable & AssignmentKind.CannotAssign + ? DestructuringKind.CannotDestruct + : DestructuringKind.Assignable; + } + } + } else { + value = parseLeftHandSideExpression(parser, context, 1, inGroup, 1, tokenPos, linePos, colPos); + + destructible |= + parser.assignable & AssignmentKind.Assignable + ? DestructuringKind.Assignable + : DestructuringKind.CannotDestruct; + + if (parser.token === Token.Comma || parser.token === Token.RightBrace) { + if (parser.assignable & AssignmentKind.CannotAssign) destructible |= DestructuringKind.CannotDestruct; + } else { + value = parseMemberOrUpdateExpression(parser, context, value, inGroup, 0, tokenPos, linePos, colPos); + + destructible = parser.assignable & AssignmentKind.CannotAssign ? DestructuringKind.CannotDestruct : 0; + + if (parser.token !== Token.Comma && token !== Token.RightBrace) { + if (parser.token !== Token.Assign) destructible |= DestructuringKind.CannotDestruct; + value = parseAssignmentExpression( + parser, + context, + inGroup, + isPattern, + tokenPos, + linePos, + colPos, + value + ); + } + } + } + } else if (parser.token === Token.LeftBracket) { + destructible |= DestructuringKind.CannotDestruct; + if (token === Token.AsyncKeyword) state |= PropertyKind.Async; + + state |= + (token === Token.GetKeyword + ? PropertyKind.Getter + : token === Token.SetKeyword + ? PropertyKind.Setter + : PropertyKind.Method) | PropertyKind.Computed; + + key = parseComputedPropertyName(parser, context, inGroup); + destructible |= parser.assignable; + + value = parseMethodDefinition( + parser, + context, + state, + inGroup, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + } else if (parser.token & (Token.IsIdentifier | Token.Keyword)) { + destructible |= DestructuringKind.CannotDestruct; + if (token === Token.EscapedReserved) report(parser, Errors.InvalidEscapedKeyword); + if (token === Token.AsyncKeyword) { + if (parser.flags & Flags.NewLine) report(parser, Errors.AsyncRestrictedProd); + state |= PropertyKind.Async; + } + key = parseIdentifier(parser, context, 0); + + state |= + token === Token.GetKeyword + ? PropertyKind.Getter + : token === Token.SetKeyword + ? PropertyKind.Setter + : PropertyKind.Method; + + value = parseMethodDefinition( + parser, + context, + state, + inGroup, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + } else if (parser.token === Token.LeftParen) { + destructible |= DestructuringKind.CannotDestruct; + state |= PropertyKind.Method; + value = parseMethodDefinition( + parser, + context, + state, + inGroup, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + } else if (parser.token === Token.Multiply) { + destructible |= DestructuringKind.CannotDestruct; + + if (token === Token.GetKeyword || token === Token.SetKeyword) { + report(parser, Errors.InvalidGeneratorGetter); + } else if (token === Token.AnyIdentifier) { + report(parser, Errors.InvalidEscapedKeyword); + } + + nextToken(parser, context); + + state |= + PropertyKind.Generator | PropertyKind.Method | (token === Token.AsyncKeyword ? PropertyKind.Async : 0); + + if (parser.token & Token.IsIdentifier) { + key = parseIdentifier(parser, context, 0); + } else if ((parser.token & Token.IsStringOrNumber) === Token.IsStringOrNumber) { + key = parseLiteral(parser, context); + } else if (parser.token === Token.LeftBracket) { + state |= PropertyKind.Computed; + key = parseComputedPropertyName(parser, context, inGroup); + destructible |= parser.assignable; + } else { + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + } + value = parseMethodDefinition( + parser, + context, + state, + inGroup, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + } else if ((parser.token & Token.IsStringOrNumber) === Token.IsStringOrNumber) { + if (token === Token.AsyncKeyword) state |= PropertyKind.Async; + + state |= + token === Token.GetKeyword + ? PropertyKind.Getter + : token === Token.SetKeyword + ? PropertyKind.Setter + : PropertyKind.Method; + + destructible |= DestructuringKind.CannotDestruct; + + key = parseLiteral(parser, context); + + value = parseMethodDefinition( + parser, + context, + state, + inGroup, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + } else { + report(parser, Errors.UnexpectedCharAfterObjLit); + } + } else if ((parser.token & Token.IsStringOrNumber) === Token.IsStringOrNumber) { + key = parseLiteral(parser, context); + + if (parser.token === Token.Colon) { + consume(parser, context | Context.AllowRegExp, Token.Colon); + + const { tokenPos, linePos, colPos } = parser; + + if (tokenValue === '__proto__') prototypeCount++; + + if (parser.token & Token.IsIdentifier) { + value = parsePrimaryExpression(parser, context, kind, 0, 1, 0, inGroup, 1, tokenPos, linePos, colPos); + + const { token, tokenValue: valueAfterColon } = parser; + + value = parseMemberOrUpdateExpression(parser, context, value, inGroup, 0, tokenPos, linePos, colPos); + + if (parser.token === Token.Comma || parser.token === Token.RightBrace) { + if (token === Token.Assign || token === Token.RightBrace || token === Token.Comma) { + if (parser.assignable & AssignmentKind.CannotAssign) { + destructible |= DestructuringKind.CannotDestruct; + } else if (scope) { + addVarOrBlock(parser, context, scope, valueAfterColon, kind, origin); + } + } else { + destructible |= + parser.assignable & AssignmentKind.Assignable + ? DestructuringKind.Assignable + : DestructuringKind.CannotDestruct; + } + } else if (parser.token === Token.Assign) { + if (parser.assignable & AssignmentKind.CannotAssign) destructible |= DestructuringKind.CannotDestruct; + value = parseAssignmentExpression(parser, context, inGroup, isPattern, tokenPos, linePos, colPos, value); + } else { + destructible |= DestructuringKind.CannotDestruct; + value = parseAssignmentExpression(parser, context, inGroup, isPattern, tokenPos, linePos, colPos, value); + } + } else if ((parser.token & Token.IsPatternStart) === Token.IsPatternStart) { + value = + parser.token === Token.LeftBracket + ? parseArrayExpressionOrPattern( + parser, + context, + scope, + 0, + inGroup, + isPattern, + kind, + origin, + tokenPos, + linePos, + colPos + ) + : parseObjectLiteralOrPattern( + parser, + context, + scope, + 0, + inGroup, + isPattern, + kind, + origin, + tokenPos, + linePos, + colPos + ); + + destructible = parser.destructible; + + parser.assignable = + destructible & DestructuringKind.CannotDestruct ? AssignmentKind.CannotAssign : AssignmentKind.Assignable; + + if (parser.token === Token.Comma || parser.token === Token.RightBrace) { + if (parser.assignable & AssignmentKind.CannotAssign) { + destructible |= DestructuringKind.CannotDestruct; + } + } else if ((parser.destructible & DestructuringKind.HasToDestruct) !== DestructuringKind.HasToDestruct) { + value = parseMemberOrUpdateExpression(parser, context, value, inGroup, 0, tokenPos, linePos, colPos); + destructible = parser.assignable & AssignmentKind.CannotAssign ? DestructuringKind.CannotDestruct : 0; + + if ((parser.token & Token.IsAssignOp) === Token.IsAssignOp) { + value = parseAssignmentExpressionOrPattern( + parser, + context, + inGroup, + isPattern, + tokenPos, + linePos, + colPos, + value + ); + } else { + if ((parser.token & Token.IsBinaryOp) === Token.IsBinaryOp) { + value = parseBinaryExpression(parser, context, 1, tokenPos, linePos, colPos, 4, token, value); + } + if (consumeOpt(parser, context | Context.AllowRegExp, Token.QuestionMark)) { + value = parseConditionalExpression(parser, context, value, tokenPos, linePos, colPos); + } + destructible |= + parser.assignable & AssignmentKind.CannotAssign + ? DestructuringKind.CannotDestruct + : DestructuringKind.Assignable; + } + } + } else { + value = parseLeftHandSideExpression(parser, context, 1, 0, 1, tokenPos, linePos, colPos); + + destructible |= + parser.assignable & AssignmentKind.Assignable + ? DestructuringKind.Assignable + : DestructuringKind.CannotDestruct; + + if (parser.token === Token.Comma || parser.token === Token.RightBrace) { + if (parser.assignable & AssignmentKind.CannotAssign) { + destructible |= DestructuringKind.CannotDestruct; + } + } else { + value = parseMemberOrUpdateExpression(parser, context, value, inGroup, 0, tokenPos, linePos, colPos); + + destructible = parser.assignable & AssignmentKind.Assignable ? 0 : DestructuringKind.CannotDestruct; + + if (parser.token !== Token.Comma && parser.token !== Token.RightBrace) { + if (parser.token !== Token.Assign) destructible |= DestructuringKind.CannotDestruct; + value = parseAssignmentExpression( + parser, + context, + inGroup, + isPattern, + tokenPos, + linePos, + colPos, + value + ); + } + } + } + } else if (parser.token === Token.LeftParen) { + state |= PropertyKind.Method; + value = parseMethodDefinition( + parser, + context, + state, + inGroup, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + destructible = parser.assignable | DestructuringKind.CannotDestruct; + } else { + report(parser, Errors.InvalidObjLitKey); + } + } else if (parser.token === Token.LeftBracket) { + key = parseComputedPropertyName(parser, context, inGroup); + + destructible |= parser.destructible & DestructuringKind.Yield ? DestructuringKind.Yield : 0; + + state |= PropertyKind.Computed; + + if (parser.token === Token.Colon) { + nextToken(parser, context | Context.AllowRegExp); // skip ':' + + const { tokenPos, linePos, colPos, tokenValue, token: tokenAfterColon } = parser; + + if (parser.token & Token.IsIdentifier) { + value = parsePrimaryExpression(parser, context, kind, 0, 1, 0, inGroup, 1, tokenPos, linePos, colPos); + + const { token } = parser; + + value = parseMemberOrUpdateExpression(parser, context, value, inGroup, 0, tokenPos, linePos, colPos); + + if ((parser.token & Token.IsAssignOp) === Token.IsAssignOp) { + destructible |= + parser.assignable & AssignmentKind.CannotAssign + ? DestructuringKind.CannotDestruct + : token === Token.Assign + ? 0 + : DestructuringKind.Assignable; + value = parseAssignmentExpressionOrPattern( + parser, + context, + inGroup, + isPattern, + tokenPos, + linePos, + colPos, + value + ); + } else if (parser.token === Token.Comma || parser.token === Token.RightBrace) { + if (token === Token.Assign || token === Token.RightBrace || token === Token.Comma) { + if (parser.assignable & AssignmentKind.CannotAssign) { + destructible |= DestructuringKind.CannotDestruct; + } else if (scope && (tokenAfterColon & Token.IsIdentifier) === Token.IsIdentifier) { + addVarOrBlock(parser, context, scope, tokenValue, kind, origin); + } + } else { + destructible |= + parser.assignable & AssignmentKind.Assignable + ? DestructuringKind.Assignable + : DestructuringKind.CannotDestruct; + } + } else { + destructible |= DestructuringKind.CannotDestruct; + value = parseAssignmentExpression(parser, context, inGroup, isPattern, tokenPos, linePos, colPos, value); + } + } else if ((parser.token & Token.IsPatternStart) === Token.IsPatternStart) { + value = + parser.token === Token.LeftBracket + ? parseArrayExpressionOrPattern( + parser, + context, + scope, + 0, + inGroup, + isPattern, + kind, + origin, + tokenPos, + linePos, + colPos + ) + : parseObjectLiteralOrPattern( + parser, + context, + scope, + 0, + inGroup, + isPattern, + kind, + origin, + tokenPos, + linePos, + colPos + ); + + destructible = parser.destructible; + + parser.assignable = + destructible & DestructuringKind.CannotDestruct ? AssignmentKind.CannotAssign : AssignmentKind.Assignable; + + if (parser.token === Token.Comma || parser.token === Token.RightBrace) { + if (parser.assignable & AssignmentKind.CannotAssign) destructible |= DestructuringKind.CannotDestruct; + } else if (destructible & DestructuringKind.HasToDestruct) { + report(parser, Errors.InvalidShorthandPropInit); + } else { + value = parseMemberOrUpdateExpression(parser, context, value, inGroup, 0, tokenPos, linePos, colPos); + + destructible = + parser.assignable & AssignmentKind.CannotAssign ? destructible | DestructuringKind.CannotDestruct : 0; + + if ((parser.token & Token.IsAssignOp) === Token.IsAssignOp) { + if (parser.token !== Token.Assign) destructible |= DestructuringKind.CannotDestruct; + value = parseAssignmentExpressionOrPattern( + parser, + context, + inGroup, + isPattern, + tokenPos, + linePos, + colPos, + value + ); + } else { + if ((parser.token & Token.IsBinaryOp) === Token.IsBinaryOp) { + value = parseBinaryExpression(parser, context, 1, tokenPos, linePos, colPos, 4, token, value); + } + if (consumeOpt(parser, context | Context.AllowRegExp, Token.QuestionMark)) { + value = parseConditionalExpression(parser, context, value, tokenPos, linePos, colPos); + } + destructible |= + parser.assignable & AssignmentKind.CannotAssign + ? DestructuringKind.CannotDestruct + : DestructuringKind.Assignable; + } + } + } else { + value = parseLeftHandSideExpression(parser, context, 1, 0, 1, tokenPos, linePos, colPos); + + destructible |= + parser.assignable & AssignmentKind.Assignable + ? DestructuringKind.Assignable + : DestructuringKind.CannotDestruct; + + if (parser.token === Token.Comma || parser.token === Token.RightBrace) { + if (parser.assignable & AssignmentKind.CannotAssign) destructible |= DestructuringKind.CannotDestruct; + } else { + value = parseMemberOrUpdateExpression(parser, context, value, inGroup, 0, tokenPos, linePos, colPos); + + destructible = parser.assignable & AssignmentKind.Assignable ? 0 : DestructuringKind.CannotDestruct; + + if (parser.token !== Token.Comma && parser.token !== Token.RightBrace) { + if (parser.token !== Token.Assign) destructible |= DestructuringKind.CannotDestruct; + value = parseAssignmentExpression( + parser, + context, + inGroup, + isPattern, + tokenPos, + linePos, + colPos, + value + ); + } + } + } + } else if (parser.token === Token.LeftParen) { + state |= PropertyKind.Method; + + value = parseMethodDefinition(parser, context, state, inGroup, parser.tokenPos, linePos, colPos); + + destructible = DestructuringKind.CannotDestruct; + } else { + report(parser, Errors.InvalidComputedPropName); + } + } else if (token === Token.Multiply) { + consume(parser, context | Context.AllowRegExp, Token.Multiply); + + state |= PropertyKind.Generator; + + if (parser.token & Token.IsIdentifier) { + const { token, line, index } = parser; + + key = parseIdentifier(parser, context, 0); + + state |= PropertyKind.Method; + + if (parser.token === Token.LeftParen) { + destructible |= DestructuringKind.CannotDestruct; + value = parseMethodDefinition( + parser, + context, + state, + inGroup, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + } else { + reportMessageAt( + index, + line, + index, + token === Token.AsyncKeyword + ? Errors.InvalidAsyncGetter + : token === Token.GetKeyword || parser.token === Token.SetKeyword + ? Errors.InvalidGetSetGenerator + : Errors.InvalidGenMethodShorthand, + KeywordDescTable[token & Token.Type] + ); + } + } else if ((parser.token & Token.IsStringOrNumber) === Token.IsStringOrNumber) { + destructible |= DestructuringKind.CannotDestruct; + key = parseLiteral(parser, context); + state |= PropertyKind.Method; + value = parseMethodDefinition(parser, context, state, inGroup, tokenPos, linePos, colPos); + } else if (parser.token === Token.LeftBracket) { + destructible |= DestructuringKind.CannotDestruct; + state |= PropertyKind.Computed | PropertyKind.Method; + key = parseComputedPropertyName(parser, context, inGroup); + value = parseMethodDefinition( + parser, + context, + state, + inGroup, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + } else { + report(parser, Errors.InvalidObjLitKeyStar); + } + } else { + report(parser, Errors.UnexpectedToken, KeywordDescTable[token & Token.Type]); + } + + destructible |= parser.destructible & DestructuringKind.Await ? DestructuringKind.Await : 0; + + parser.destructible = destructible; + + properties.push( + finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'Property', + key: key as ESTree.Expression, + value, + kind: !(state & PropertyKind.GetSet) ? 'init' : state & PropertyKind.Setter ? 'set' : 'get', + computed: (state & PropertyKind.Computed) > 0, + method: (state & PropertyKind.Method) > 0, + shorthand: (state & PropertyKind.Shorthand) > 0 + }) + ); + } + + destructible |= parser.destructible; + if (parser.token !== Token.Comma) break; + nextToken(parser, context); + } + + consume(parser, context, Token.RightBrace); + + if (prototypeCount > 1) destructible |= DestructuringKind.SeenProto; + + const node = finishNode(parser, context, start, line, column, { + type: isPattern ? 'ObjectPattern' : 'ObjectExpression', + properties + }); + + if (!skipInitializer && parser.token & Token.IsAssignOp) { + return parseArrayOrObjectAssignmentPattern( + parser, + context, + destructible, + inGroup, + isPattern, + start, + line, + column, + node + ); + } + + parser.destructible = destructible; + + return node; +} + +/** + * Parses method formals + * + * @param parser parser object + * @param context context masks + * @param kind + * @param type Binding kind + * @param inGroup + */ +export function parseMethodFormals( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + kind: PropertyKind, + type: BindingKind, + inGroup: 0 | 1 +): ESTree.Parameter[] { + // FormalParameter[Yield,GeneratorParameter] : + // BindingElement[?Yield, ?GeneratorParameter] + + consume(parser, context, Token.LeftParen); + + const params: (ESTree.AssignmentPattern | ESTree.Parameter)[] = []; + + parser.flags = (parser.flags | Flags.SimpleParameterList) ^ Flags.SimpleParameterList; + + if (parser.token === Token.RightParen) { + if (kind & PropertyKind.Setter) { + report(parser, Errors.AccessorWrongArgs, 'Setter', 'one', ''); + } + nextToken(parser, context); + return params; + } + + if (kind & PropertyKind.Getter) { + report(parser, Errors.AccessorWrongArgs, 'Getter', 'no', 's'); + } + if (kind & PropertyKind.Setter && parser.token === Token.Ellipsis) { + report(parser, Errors.BadSetterRestParameter); + } + + context = (context | Context.DisallowIn) ^ Context.DisallowIn; + + let setterArgs = 0; + let isSimpleParameterList: 0 | 1 = 0; + + while (parser.token !== Token.Comma) { + let left = null; + const { tokenPos, linePos, colPos } = parser; + + if (parser.token & Token.IsIdentifier) { + if ((context & Context.Strict) < 1) { + if ((parser.token & Token.FutureReserved) === Token.FutureReserved) { + parser.flags |= Flags.HasStrictReserved; + } + + if ((parser.token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) { + parser.flags |= Flags.StrictEvalArguments; + } + } + + left = parseAndClassifyIdentifier( + parser, + context, + scope, + kind | BindingKind.ArgumentList, + Origin.None, + tokenPos, + linePos, + colPos + ); + } else { + if (parser.token === Token.LeftBrace) { + left = parseObjectLiteralOrPattern( + parser, + context, + scope, + 1, + inGroup, + 1, + type, + Origin.None, + tokenPos, + linePos, + colPos + ); + } else if (parser.token === Token.LeftBracket) { + left = parseArrayExpressionOrPattern( + parser, + context, + scope, + 1, + inGroup, + 1, + type, + Origin.None, + tokenPos, + linePos, + colPos + ); + } else if (parser.token === Token.Ellipsis) { + left = parseSpreadOrRestElement( + parser, + context, + scope, + Token.RightParen, + type, + Origin.None, + 0, + inGroup, + 1, + tokenPos, + linePos, + colPos + ); + } + + isSimpleParameterList = 1; + + if (parser.destructible & (DestructuringKind.Assignable | DestructuringKind.CannotDestruct)) + report(parser, Errors.InvalidBindingDestruct); + } + + if (parser.token === Token.Assign) { + nextToken(parser, context | Context.AllowRegExp); + + isSimpleParameterList = 1; + + const right = parseExpression(parser, context, 1, 1, 0, parser.tokenPos, parser.linePos, parser.colPos); + + left = finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'AssignmentPattern', + left: left as ESTree.BindingPattern | ESTree.Identifier, + right + }); + } + + setterArgs++; + + params.push(left as any); + + if (!consumeOpt(parser, context, Token.Comma)) break; + if (parser.token === Token.RightParen) { + // allow the trailing comma + break; + } + } + + if (kind & PropertyKind.Setter && setterArgs !== 1) { + report(parser, Errors.AccessorWrongArgs, 'Setter', 'one', ''); + } + + if (scope && scope.scopeError !== void 0) reportScopeError(scope.scopeError); + + if (isSimpleParameterList) parser.flags |= Flags.SimpleParameterList; + + consume(parser, context, Token.RightParen); + + return params; +} + +/** + * Parse computed property name + * + * @param parser Parser object + * @param context Context masks + */ +export function parseComputedPropertyName(parser: ParserState, context: Context, inGroup: 0 | 1): ESTree.Expression { + // ComputedPropertyName : + // [ AssignmentExpression ] + nextToken(parser, context | Context.AllowRegExp); + const key = parseExpression( + parser, + (context | Context.DisallowIn) ^ Context.DisallowIn, + 1, + 0, + inGroup, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + consume(parser, context, Token.RightBracket); + return key; +} + +/** + * Parses an expression which has been parenthesised, or arrow head + * + * @param parser Parser object + * @param context Context masks + * @param assignable + * @param start Start index + * @param line Start line + * @param column Start of column + */ +export function parseParenthesizedExpression( + parser: ParserState, + context: Context, + canAssign: 0 | 1, + kind: BindingKind, + origin: Origin, + start: number, + line: number, + column: number +): any { + parser.flags = (parser.flags | Flags.SimpleParameterList) ^ Flags.SimpleParameterList; + + const { tokenPos: piStart, linePos: plStart, colPos: pcStart } = parser; + + nextToken(parser, context | Context.AllowRegExp | Context.AllowEscapedKeyword); + + const scope = context & Context.OptionsLexical ? addChildScope(createScope(), ScopeKind.ArrowParams) : void 0; + + context = (context | Context.DisallowIn) ^ Context.DisallowIn; + + if (consumeOpt(parser, context, Token.RightParen)) { + // Not valid expression syntax, but this is valid in an arrow function + // with no params: `() => body`. + return parseParenthesizedArrow(parser, context, scope, [], canAssign, 0, start, line, column); + } + + let destructible: AssignmentKind | DestructuringKind = 0; + + parser.destructible &= ~(DestructuringKind.Yield | DestructuringKind.Await); + + let expr; + let expressions: ESTree.Expression[] = []; + let isSequence: 0 | 1 = 0; + let isSimpleParameterList: 0 | 1 = 0; + + const { tokenPos: iStart, linePos: lStart, colPos: cStart } = parser; + + parser.assignable = AssignmentKind.Assignable; + + while (parser.token !== Token.RightParen) { + const { token, tokenPos, linePos, colPos } = parser; + + if (token & (Token.IsIdentifier | Token.Keyword)) { + if (scope) addBlockName(parser, context, scope, parser.tokenValue, BindingKind.ArgumentList, Origin.None); + + expr = parsePrimaryExpression(parser, context, kind, 0, 1, 0, 1, 1, tokenPos, linePos, colPos); + + if (parser.token === Token.RightParen || parser.token === Token.Comma) { + if (parser.assignable & AssignmentKind.CannotAssign) { + destructible |= DestructuringKind.CannotDestruct; + isSimpleParameterList = 1; + } else if ( + (token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments || + (token & Token.FutureReserved) === Token.FutureReserved + ) { + isSimpleParameterList = 1; + } + } else { + if (parser.token === Token.Assign) { + isSimpleParameterList = 1; + } else { + destructible |= DestructuringKind.CannotDestruct; + } + + expr = parseMemberOrUpdateExpression(parser, context, expr, /* inGroup */ 1, 0, tokenPos, linePos, colPos); + + if (parser.token !== Token.RightParen && parser.token !== Token.Comma) { + expr = parseAssignmentExpression(parser, context, 1, 0, tokenPos, linePos, colPos, expr); + } + } + } else if ((token & Token.IsPatternStart) === Token.IsPatternStart) { + expr = + token === Token.LeftBrace + ? parseObjectLiteralOrPattern( + parser, + context | Context.AllowEscapedKeyword, + scope, + 0, + 1, + 0, + kind, + origin, + tokenPos, + linePos, + colPos + ) + : parseArrayExpressionOrPattern( + parser, + context | Context.AllowEscapedKeyword, + scope, + 0, + 1, + 0, + kind, + origin, + tokenPos, + linePos, + colPos + ); + + destructible |= parser.destructible; + + isSimpleParameterList = 1; + + parser.assignable = AssignmentKind.CannotAssign; + + if (parser.token !== Token.RightParen && parser.token !== Token.Comma) { + if (destructible & DestructuringKind.HasToDestruct) report(parser, Errors.InvalidPatternTail); + + expr = parseMemberOrUpdateExpression(parser, context, expr, 0, 0, tokenPos, linePos, colPos); + + destructible |= DestructuringKind.CannotDestruct; + + if (parser.token !== Token.RightParen && parser.token !== Token.Comma) { + expr = parseAssignmentExpression(parser, context, 0, 0, tokenPos, linePos, colPos, expr); + } + } + } else if (token === Token.Ellipsis) { + expr = parseSpreadOrRestElement( + parser, + context, + scope, + Token.RightParen, + kind, + origin, + 0, + 1, + 0, + tokenPos, + linePos, + colPos + ); + + if (parser.destructible & DestructuringKind.CannotDestruct) report(parser, Errors.InvalidRestArg); + + isSimpleParameterList = 1; + + if (isSequence && (parser.token === Token.RightParen || parser.token === Token.Comma)) { + expressions.push(expr); + } + destructible |= DestructuringKind.HasToDestruct; + break; + } else { + destructible |= DestructuringKind.CannotDestruct; + + expr = parseExpression(parser, context, 1, 0, 1, tokenPos, linePos, colPos); + + if (isSequence && (parser.token === Token.RightParen || parser.token === Token.Comma)) { + expressions.push(expr); + } + + if (parser.token === Token.Comma) { + if (!isSequence) { + isSequence = 1; + expressions = [expr]; + } + } + + if (isSequence) { + while (consumeOpt(parser, context | Context.AllowRegExp, Token.Comma)) { + expressions.push(parseExpression(parser, context, 1, 0, 1, parser.tokenPos, parser.linePos, parser.colPos)); + } + + parser.assignable = AssignmentKind.CannotAssign; + + expr = finishNode(parser, context, iStart, lStart, cStart, { + type: 'SequenceExpression', + expressions + }); + } + + consume(parser, context, Token.RightParen); + + parser.destructible = destructible; + + return expr; + } + + if (isSequence && (parser.token === Token.RightParen || parser.token === Token.Comma)) { + expressions.push(expr); + } + + if (!consumeOpt(parser, context | Context.AllowRegExp, Token.Comma)) break; + + if (!isSequence) { + isSequence = 1; + expressions = [expr]; + } + + if (parser.token === Token.RightParen) { + destructible |= DestructuringKind.HasToDestruct; + break; + } + } + + if (isSequence) { + parser.assignable = AssignmentKind.CannotAssign; + + expr = finishNode(parser, context, iStart, lStart, cStart, { + type: 'SequenceExpression', + expressions + }); + } + + consume(parser, context, Token.RightParen); + + if (destructible & DestructuringKind.CannotDestruct && destructible & DestructuringKind.HasToDestruct) + report(parser, Errors.CantAssignToValidRHS); + + destructible |= + parser.destructible & DestructuringKind.Yield + ? DestructuringKind.Yield + : 0 | (parser.destructible & DestructuringKind.Await) + ? DestructuringKind.Await + : 0; + + if (parser.token === Token.Arrow) { + if (destructible & (DestructuringKind.Assignable | DestructuringKind.CannotDestruct)) + report(parser, Errors.InvalidArrowDestructLHS); + if (context & (Context.InAwaitContext | Context.Module) && destructible & DestructuringKind.Await) + report(parser, Errors.AwaitInParameter); + if (context & (Context.Strict | Context.InYieldContext) && destructible & DestructuringKind.Yield) { + report(parser, Errors.YieldInParameter); + } + if (isSimpleParameterList) parser.flags |= Flags.SimpleParameterList; + return parseParenthesizedArrow( + parser, + context, + scope, + isSequence ? expressions : [expr], + canAssign, + 0, + start, + line, + column + ); + } else if (destructible & DestructuringKind.HasToDestruct) { + report(parser, Errors.UncompleteArrow); + } + + parser.destructible = ((parser.destructible | DestructuringKind.Yield) ^ DestructuringKind.Yield) | destructible; + + return context & Context.OptionsPreserveParens + ? finishNode(parser, context, piStart, plStart, pcStart, { + type: 'ParenthesizedExpression', + expression: expr + }) + : expr; +} + +/** + * Parses either an identifier or an arrow function + * + * @param parser Parser object + * @param context Context masks + * @param start Start index + * @param line Start line + * @param column Start of column + + */ +export function parseIdentifierOrArrow( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.Identifier | ESTree.ArrowFunctionExpression { + const { tokenValue } = parser; + + const expr = parseIdentifier(parser, context, 0); + parser.assignable = AssignmentKind.Assignable; + if (parser.token === Token.Arrow) { + let scope: ScopeState | undefined = void 0; + + if (context & Context.OptionsLexical) scope = createArrowHeadParsingScope(parser, context, tokenValue); + + parser.flags = (parser.flags | Flags.SimpleParameterList) ^ Flags.SimpleParameterList; + + return parseArrowFunctionExpression(parser, context, scope, [expr], /* isAsync */ 0, start, line, column); + } + return expr; +} + +/** + * Parse arrow function expression + * + * @param parser Parser object + * @param context Context masks + * @param params + * @param isAsync + * @param start Start index + * @param line Start line + * @param column Start of column + */ +function parseArrowFromIdentifier( + parser: ParserState, + context: Context, + value: any, + expr: ESTree.Expression, + inNew: 0 | 1, + canAssign: 0 | 1, + isAsync: 0 | 1, + start: number, + line: number, + column: number +): ESTree.ArrowFunctionExpression { + if (!canAssign) report(parser, Errors.InvalidAssignmentTarget); + if (inNew) report(parser, Errors.InvalidAsyncArrow); + parser.flags &= ~Flags.SimpleParameterList; + const scope = context & Context.OptionsLexical ? createArrowHeadParsingScope(parser, context, value) : void 0; + + return parseArrowFunctionExpression(parser, context, scope, [expr], isAsync, start, line, column); +} + +/** + * Parse arrow function expression + * + * @param parser Parser object + * @param context Context masks + * @param params + * @param isAsync + * @param start Start index + * @param line Start line + * @param column Start of column + */ +function parseParenthesizedArrow( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + params: any, + canAssign: 0 | 1, + isAsync: 0 | 1, + start: number, + line: number, + column: number +): ESTree.ArrowFunctionExpression { + if (!canAssign) report(parser, Errors.InvalidAssignmentTarget); + + for (let i = 0; i < params.length; ++i) reinterpretToPattern(parser, params[i]); + + return parseArrowFunctionExpression(parser, context, scope, params, isAsync, start, line, column); +} + +/** + * Parse arrow function expression + * + * @param parser Parser object + * @param context Context masks + * @param params + * @param isAsync + * @param start Start index + * @param line Start line + * @param column Start of column + */ +export function parseArrowFunctionExpression( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + params: any, + isAsync: 0 | 1, + start: number, + line: number, + column: number +): ESTree.ArrowFunctionExpression { + /** + * ArrowFunction : + * ArrowParameters => ConciseBody + * + * ArrowParameters : + * BindingIdentifer + * CoverParenthesizedExpressionAndArrowParameterList + * + * CoverParenthesizedExpressionAndArrowParameterList : + * ( Expression ) + * ( ) + * ( ... BindingIdentifier ) + * ( Expression , ... BindingIdentifier ) + * + * ConciseBody : + * [lookahead not {] AssignmentExpression + * { FunctionBody } + * + */ + + if (parser.flags & Flags.NewLine) report(parser, Errors.InvalidLineBreak); + + consume(parser, context | Context.AllowRegExp, Token.Arrow); + + context = ((context | 0b0000000111100000000_0000_00000000) ^ 0b0000000111100000000_0000_00000000) | (isAsync << 22); + + const expression = parser.token !== Token.LeftBrace; + + let body: ESTree.BlockStatement | ESTree.Expression; + + if (scope && scope.scopeError !== void 0) { + reportScopeError(scope.scopeError); + } + + if (expression) { + // Single-expression body + body = parseExpression(parser, context, 1, 0, 0, parser.tokenPos, parser.linePos, parser.colPos); + } else { + if (scope) scope = addChildScope(scope, ScopeKind.FunctionBody); + + body = parseFunctionBody( + parser, + (context | 0b0001000000000000001_0000_00000000 | Context.InGlobal | Context.InClass) ^ + (0b0001000000000000001_0000_00000000 | Context.InGlobal | Context.InClass), + scope, + Origin.Arrow, + void 0, + void 0 + ); + + switch (parser.token) { + case Token.LeftBracket: + if ((parser.flags & Flags.NewLine) < 1) { + report(parser, Errors.InvalidInvokedBlockBodyArrow); + } + break; + case Token.Period: + case Token.TemplateSpan: + case Token.QuestionMark: + report(parser, Errors.InvalidAccessedBlockBodyArrow); + case Token.LeftParen: + if ((parser.flags & Flags.NewLine) < 1) { + report(parser, Errors.InvalidInvokedBlockBodyArrow); + } + parser.flags |= Flags.DisallowCall; + break; + default: // ignore + } + if ((parser.token & Token.IsBinaryOp) === Token.IsBinaryOp && (parser.flags & Flags.NewLine) < 1) + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + if ((parser.token & Token.IsUpdateOp) === Token.IsUpdateOp) report(parser, Errors.InvalidArrowPostfix); + } + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode(parser, context, start, line, column, { + type: 'ArrowFunctionExpression', + params, + body, + async: isAsync === 1, + expression + }); +} + +/** + * Parses formal parameters + * + * @param parser Parser object + * @param context Context masks + */ +export function parseFormalParametersOrFormalList( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + inGroup: 0 | 1, + kind: BindingKind +): ESTree.Parameter[] { + /** + * FormalParameter : + * BindingElement + * + * FormalParameterList : + * [empty] + * FunctionRestParameter + * FormalsList + * FormalsList , FunctionRestParameter + * + * FunctionRestParameter : + * ... BindingIdentifier + * + * FormalsList : + * FormalParameter + * FormalsList , FormalParameter + * + * FormalParameter : + * BindingElement + * + * BindingElement : + * SingleNameBinding + * BindingPattern Initializeropt + * + */ + consume(parser, context, Token.LeftParen); + + parser.flags = (parser.flags | Flags.SimpleParameterList) ^ Flags.SimpleParameterList; + + const params: ESTree.Parameter[] = []; + + if (consumeOpt(parser, context, Token.RightParen)) return params; + + context = (context | Context.DisallowIn) ^ Context.DisallowIn; + + let isSimpleParameterList: 0 | 1 = 0; + + while (parser.token !== Token.Comma) { + let left: any; + + const { tokenPos, linePos, colPos } = parser; + + if (parser.token & Token.IsIdentifier) { + if ((context & Context.Strict) < 1) { + if ((parser.token & Token.FutureReserved) === Token.FutureReserved) { + parser.flags |= Flags.HasStrictReserved; + } + if ((parser.token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) { + parser.flags |= Flags.StrictEvalArguments; + } + } + + left = parseAndClassifyIdentifier( + parser, + context, + scope, + kind | BindingKind.ArgumentList, + Origin.None, + tokenPos, + linePos, + colPos + ); + } else { + if (parser.token === Token.LeftBrace) { + left = parseObjectLiteralOrPattern( + parser, + context, + scope, + 1, + inGroup, + 1, + kind, + Origin.None, + tokenPos, + linePos, + colPos + ); + } else if (parser.token === Token.LeftBracket) { + left = parseArrayExpressionOrPattern( + parser, + context, + scope, + 1, + inGroup, + 1, + kind, + Origin.None, + tokenPos, + linePos, + colPos + ); + } else if (parser.token === Token.Ellipsis) { + left = parseSpreadOrRestElement( + parser, + context, + scope, + Token.RightParen, + kind, + Origin.None, + 0, + inGroup, + 1, + tokenPos, + linePos, + colPos + ); + } else { + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + } + + isSimpleParameterList = 1; + + if (parser.destructible & (DestructuringKind.Assignable | DestructuringKind.CannotDestruct)) { + report(parser, Errors.InvalidBindingDestruct); + } + } + + if (parser.token === Token.Assign) { + nextToken(parser, context | Context.AllowRegExp); + + isSimpleParameterList = 1; + + const right = parseExpression(parser, context, 1, 1, inGroup, parser.tokenPos, parser.linePos, parser.colPos); + + left = finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'AssignmentPattern', + left, + right + }); + } + + params.push(left); + + if (!consumeOpt(parser, context, Token.Comma)) break; + if (parser.token === Token.RightParen) { + // allow the trailing comma + break; + } + } + + if (isSimpleParameterList) parser.flags |= Flags.SimpleParameterList; + + if (scope && (isSimpleParameterList || context & Context.Strict) && scope.scopeError !== void 0) { + reportScopeError(scope.scopeError); + } + + consume(parser, context, Token.RightParen); + + return params; +} + +/** + * Parses member or update expression without call expression + * + * @param parser Parser object + * @param context Context masks + * @param expr ESTree AST node + * @param inGroup + * @param start + * @param line + * @param column + */ +export function parseMembeExpressionNoCall( + parser: ParserState, + context: Context, + expr: ESTree.Expression, + inGroup: 0 | 1, + start: number, + line: number, + column: number +): any { + const { token } = parser; + + if (token & Token.IsMemberOrCallExpression) { + /* Property */ + if (token === Token.Period) { + nextToken(parser, context | Context.AllowEscapedKeyword); + + parser.assignable = AssignmentKind.Assignable; + + const property = parsePropertyOrPrivatePropertyName(parser, context); + + return parseMembeExpressionNoCall( + parser, + context, + finishNode(parser, context, start, line, column, { + type: 'MemberExpression', + object: expr, + computed: false, + property + }), + 0, + start, + line, + column + ); + /* Property */ + } else if (token === Token.LeftBracket) { + nextToken(parser, context | Context.AllowRegExp); + + const { tokenPos, linePos, colPos } = parser; + + const property = parseExpressions(parser, context, inGroup, 1, tokenPos, linePos, colPos); + + consume(parser, context, Token.RightBracket); + + parser.assignable = AssignmentKind.Assignable; + + return parseMembeExpressionNoCall( + parser, + context, + finishNode(parser, context, start, line, column, { + type: 'MemberExpression', + object: expr, + computed: true, + property + }), + 0, + start, + line, + column + ); + /* Template */ + } else if (token === Token.TemplateContinuation || token === Token.TemplateSpan) { + parser.assignable = AssignmentKind.CannotAssign; + + return parseMembeExpressionNoCall( + parser, + context, + finishNode(parser, context, start, line, column, { + type: 'TaggedTemplateExpression', + tag: expr, + quasi: + parser.token === Token.TemplateContinuation + ? parseTemplate(parser, context | Context.TaggedTemplate) + : parseTemplateLiteral(parser, context, parser.tokenPos, parser.linePos, parser.colPos) + }), + 0, + start, + line, + column + ); + } + } + return expr; +} + +/** + * Parses new or new target expression + * + * @param parser Parser object + * @param context Context masks + * @returns {(ESTree.Expression | ESTree.MetaProperty)} + */ +export function parseNewExpression( + parser: ParserState, + context: Context, + inGroup: 0 | 1, + start: number, + line: number, + column: number +): ESTree.NewExpression | ESTree.Expression | ESTree.MetaProperty { + // NewExpression :: + // ('new')+ MemberExpression + // + // NewTarget :: + // 'new' '.' 'target' + // + // Examples of new expression: + // - new foo.bar().baz + // - new foo()() + // - new new foo()() + // - new new foo + // - new new foo() + // - new new foo().bar().baz + // - `new.target[await x]` + // - `new (foo);` + // - `new (foo)();` + // - `new foo()();` + // - `new (await foo);` + // - `new x(await foo);` + const id = parseIdentifier(parser, context | Context.AllowRegExp, 0); + const { tokenPos, linePos, colPos } = parser; + + if (consumeOpt(parser, context, Token.Period)) { + if (context & Context.AllowNewTarget && parser.token === Token.Target) { + parser.assignable = AssignmentKind.CannotAssign; + return parseMetaProperty(parser, context, id, start, line, column); + } + + report(parser, Errors.InvalidNewTarget); + } + + parser.assignable = AssignmentKind.CannotAssign; + + if ((parser.token & Token.IsUnaryOp) === Token.IsUnaryOp) { + report(parser, Errors.InvalidNewUnary, KeywordDescTable[parser.token & Token.Type]); + } + + const expr = parsePrimaryExpression( + parser, + context, + BindingKind.Empty, + 1, + 0, + 0, + inGroup, + 1, + tokenPos, + linePos, + colPos + ); + + context = (context | Context.DisallowIn) ^ Context.DisallowIn; + + if (parser.token === Token.QuestionMarkPeriod) report(parser, Errors.OptionalChainingNoNew); + + // NewExpression without arguments. + const callee = parseMembeExpressionNoCall(parser, context, expr, inGroup, tokenPos, linePos, colPos); + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode(parser, context, start, line, column, { + type: 'NewExpression', + callee, + arguments: parser.token === Token.LeftParen ? parseArguments(parser, context, inGroup) : [] + }); +} + +/** + * Parse meta property + * + * @see [Link](https://tc39.github.io/ecma262/#prod-StatementList) + * + * @param parser Parser object + * @param context Context masks + * @param meta ESTree AST node + */ +export function parseMetaProperty( + parser: ParserState, + context: Context, + meta: ESTree.Identifier, + start: number, + line: number, + column: number +): ESTree.MetaProperty { + const property = parseIdentifier(parser, context, 0); + return finishNode(parser, context, start, line, column, { + type: 'MetaProperty', + meta, + property + }); +} + +/** + * Parses async expression + * + * @param parser Parser object + * @param context Context masks + * @param inNew + * @param assignable + */ + +/** + * Parses async arrow after identifier + * + * @param parser Parser object + * @param context Context masks + * @param canAssign Either true or false + * @param start Start pos of node + * @param line Line pos of node + * @param column Column pos of node + */ +function parseAsyncArrowAfterIdent( + parser: ParserState, + context: Context, + canAssign: 0 | 1, + start: number, + line: number, + column: number +) { + if (parser.token === Token.AwaitKeyword) report(parser, Errors.AwaitInParameter); + + if (context & (Context.Strict | Context.InYieldContext) && parser.token === Token.YieldKeyword) { + report(parser, Errors.YieldInParameter); + } + + if ((parser.token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) { + parser.flags |= Flags.StrictEvalArguments; + } + + return parseArrowFromIdentifier( + parser, + context, + parser.tokenValue, + parseIdentifier(parser, context, 0), + 0, + canAssign, + 1, + start, + line, + column + ); +} + +/** + * Parses async arrow or call expressions + * + * @param parser Parser object + * @param context Context masks + * @param callee ESTree AST node + * @param assignable + * @param kind Binding kind + * @param origin Binding origin + * @param flags Mutual parser flags + * @param start Start pos of node + * @param line Line pos of node + * @param column Column pos of node + */ + +export function parseAsyncArrowOrCallExpression( + parser: ParserState, + context: Context, + callee: ESTree.Identifier | void, + canAssign: 0 | 1, + kind: BindingKind, + origin: Origin, + flags: Flags, + start: number, + line: number, + column: number +): ESTree.CallExpression | ESTree.ArrowFunctionExpression { + nextToken(parser, context | Context.AllowRegExp); + + const scope = context & Context.OptionsLexical ? addChildScope(createScope(), ScopeKind.ArrowParams) : void 0; + + context = (context | Context.DisallowIn) ^ Context.DisallowIn; + + if (consumeOpt(parser, context, Token.RightParen)) { + if (parser.token === Token.Arrow) { + if (flags & Flags.NewLine) report(parser, Errors.InvalidLineBreak); + return parseParenthesizedArrow(parser, context, scope, [], canAssign, 1, start, line, column); + } + + return finishNode(parser, context, start, line, column, { + type: 'CallExpression', + callee, + arguments: [] + }); + } + + let destructible: AssignmentKind | DestructuringKind = 0; + let expr: ESTree.Expression | null = null; + let isSimpleParameterList: 0 | 1 = 0; + + parser.destructible = + (parser.destructible | DestructuringKind.Yield | DestructuringKind.Await) ^ + (DestructuringKind.Yield | DestructuringKind.Await); + + const params: ESTree.Expression[] = []; + + while (parser.token !== Token.RightParen) { + const { token, tokenPos, linePos, colPos } = parser; + + if (token & (Token.IsIdentifier | Token.Keyword)) { + if (scope) addBlockName(parser, context, scope, parser.tokenValue, kind, Origin.None); + + expr = parsePrimaryExpression(parser, context, kind, 0, 1, 0, 1, 1, tokenPos, linePos, colPos); + + if (parser.token === Token.RightParen || parser.token === Token.Comma) { + if (parser.assignable & AssignmentKind.CannotAssign) { + destructible |= DestructuringKind.CannotDestruct; + isSimpleParameterList = 1; + } else if ((token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) { + parser.flags |= Flags.StrictEvalArguments; + } else if ((token & Token.FutureReserved) === Token.FutureReserved) { + parser.flags |= Flags.HasStrictReserved; + } + } else { + if (parser.token === Token.Assign) { + isSimpleParameterList = 1; + } else { + destructible |= DestructuringKind.CannotDestruct; + } + + expr = parseMemberOrUpdateExpression( + parser, + context, + expr as ESTree.Expression, + 1, + 0, + tokenPos, + linePos, + colPos + ); + + if (parser.token !== Token.RightParen && parser.token !== Token.Comma) { + expr = parseAssignmentExpression(parser, context, 1, 0, tokenPos, linePos, colPos, expr as ESTree.Expression); + } + } + } else if (token & Token.IsPatternStart) { + expr = + token === Token.LeftBrace + ? parseObjectLiteralOrPattern(parser, context, scope, 0, 1, 0, kind, origin, tokenPos, linePos, colPos) + : parseArrayExpressionOrPattern(parser, context, scope, 0, 1, 0, kind, origin, tokenPos, linePos, colPos); + + destructible |= parser.destructible; + + isSimpleParameterList = 1; + + if (parser.token !== Token.RightParen && parser.token !== Token.Comma) { + if (destructible & DestructuringKind.HasToDestruct) report(parser, Errors.InvalidPatternTail); + + expr = parseMemberOrUpdateExpression(parser, context, expr, 0, 0, tokenPos, linePos, colPos); + + destructible |= DestructuringKind.CannotDestruct; + + if ((parser.token & Token.IsBinaryOp) === Token.IsBinaryOp) { + expr = parseBinaryExpression(parser, context, 1, start, line, column, 4, token, expr as ESTree.Expression); + } + if (consumeOpt(parser, context | Context.AllowRegExp, Token.QuestionMark)) { + expr = parseConditionalExpression(parser, context, expr as ESTree.Expression, start, line, column); + } + } + } else if (token === Token.Ellipsis) { + expr = parseSpreadOrRestElement( + parser, + context, + scope, + Token.RightParen, + kind, + origin, + 1, + 1, + 0, + tokenPos, + linePos, + colPos + ); + + destructible |= (parser.token === Token.RightParen ? 0 : DestructuringKind.CannotDestruct) | parser.destructible; + + isSimpleParameterList = 1; + } else { + expr = parseExpression(parser, context, 1, 0, 0, tokenPos, linePos, colPos); + + destructible = parser.assignable; + + params.push(expr); + + while (consumeOpt(parser, context | Context.AllowRegExp, Token.Comma)) { + params.push(parseExpression(parser, context, 1, 0, 0, tokenPos, linePos, colPos)); + } + + destructible |= parser.assignable; + + consume(parser, context, Token.RightParen); + + parser.destructible = destructible | DestructuringKind.CannotDestruct; + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode(parser, context, start, line, column, { + type: 'CallExpression', + callee, + arguments: params + }); + } + + params.push(expr as ESTree.Expression); + + if (!consumeOpt(parser, context | Context.AllowRegExp, Token.Comma)) break; + } + + consume(parser, context, Token.RightParen); + + destructible |= + parser.destructible & DestructuringKind.Yield + ? DestructuringKind.Yield + : 0 | (parser.destructible & DestructuringKind.Await) + ? DestructuringKind.Await + : 0; + + if (parser.token === Token.Arrow) { + if (destructible & (DestructuringKind.Assignable | DestructuringKind.CannotDestruct)) + report(parser, Errors.InvalidLHSAsyncArrow); + if (parser.flags & Flags.NewLine || flags & Flags.NewLine) report(parser, Errors.InvalidLineBreak); + if (destructible & DestructuringKind.Await) report(parser, Errors.AwaitInParameter); + if (context & (Context.Strict | Context.InYieldContext) && destructible & DestructuringKind.Yield) + report(parser, Errors.YieldInParameter); + if (isSimpleParameterList) parser.flags |= Flags.SimpleParameterList; + + return parseParenthesizedArrow(parser, context, scope, params, canAssign, 1, start, line, column); + } else if (destructible & DestructuringKind.HasToDestruct) { + report(parser, Errors.InvalidShorthandPropInit); + } + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode(parser, context, start, line, column, { + type: 'CallExpression', + callee, + arguments: params + }); +} + +/** + * Parse regular expression literal + * + * @see [Link](https://tc39.github.io/ecma262/#sec-literals-regular-expression-literals) + * + * @param parser Parser object + * @param context Context masks + */ + +/** + * Parses reguar expression literal AST node + * + * @param parser Parser object + * @param context Context masks + */ +export function parseRegExpLiteral( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.RegExpLiteral { + const { tokenRaw, tokenRegExp, tokenValue } = parser; + nextToken(parser, context); + parser.assignable = AssignmentKind.CannotAssign; + return context & Context.OptionsRaw + ? finishNode(parser, context, start, line, column, { + type: 'Literal', + value: tokenValue, + regex: tokenRegExp as { pattern: string; flags: string }, + raw: tokenRaw + }) + : finishNode(parser, context, start, line, column, { + type: 'Literal', + value: tokenValue, + regex: tokenRegExp as { pattern: string; flags: string } + }); +} + +/** + * Parse class expression + * + * @param parser Parser object + * @param context Context masks + * @param ExportDefault + */ +export function parseClassDeclaration( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + flags: HoistedClassFlags, + start: number, + line: number, + column: number +): ESTree.ClassDeclaration { + // ClassDeclaration :: + // 'class' Identifier ('extends' LeftHandSideExpression)? '{' ClassBody '}' + // 'class' ('extends' LeftHandSideExpression)? '{' ClassBody '}' + // DecoratorList[?Yield, ?Await]optclassBindingIdentifier[?Yield, ?Await]ClassTail[?Yield, ?Await] + // DecoratorList[?Yield, ?Await]optclassClassTail[?Yield, ?Await] + // + context = (context | Context.InConstructor | Context.Strict) ^ Context.InConstructor; + + let decorators = parseDecorators(parser, context); + if (decorators.length) { + start = parser.tokenPos; + line = parser.linePos; + column = parser.colPos; + } + + if (parser.leadingDecorators.length) { + parser.leadingDecorators.push(...decorators); + decorators = parser.leadingDecorators; + parser.leadingDecorators = []; + } + + nextToken(parser, context); + let id: ESTree.Expression | null = null; + let superClass: ESTree.Expression | null = null; + + const { tokenValue } = parser; + + if (parser.token & Token.Keyword && parser.token !== Token.ExtendsKeyword) { + if (isStrictReservedWord(parser, context, parser.token)) { + report(parser, Errors.UnexpectedStrictReserved); + } + + if ((parser.token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) { + report(parser, Errors.StrictEvalArguments); + } + + if (scope) { + // A named class creates a new lexical scope with a const binding of the + // class name for the "inner name". + addBlockName(parser, context, scope, tokenValue, BindingKind.Class, Origin.None); + + if (flags) { + if (flags & HoistedClassFlags.Export) { + declareUnboundVariable(parser, tokenValue); + } + } + } + + id = parseIdentifier(parser, context, 0); + } else { + // Only under the "export default" context, class declaration does not require the class name. + // + // ExportDeclaration: + // ... + // export default ClassDeclaration[~Yield, +Default] + // ... + // + // ClassDeclaration[Yield, Default]: + // ... + // [+Default] class ClassTail[?Yield] + // + if ((flags & HoistedClassFlags.Hoisted) < 1) report(parser, Errors.DeclNoName, 'Class'); + } + let inheritedContext = context; + + if (consumeOpt(parser, context | Context.AllowRegExp, Token.ExtendsKeyword)) { + superClass = parseLeftHandSideExpression(parser, context, 0, 0, 0, parser.tokenPos, parser.linePos, parser.colPos); + inheritedContext |= Context.SuperCall; + } else { + inheritedContext = (inheritedContext | Context.SuperCall) ^ Context.SuperCall; + } + + const body = parseClassBody(parser, inheritedContext, context, scope, BindingKind.Empty, Origin.Declaration, 0); + + return finishNode( + parser, + context, + start, + line, + column, + context & Context.OptionsNext + ? { + type: 'ClassDeclaration', + id, + superClass, + decorators, + body + } + : { + type: 'ClassDeclaration', + id, + superClass, + body + } + ); +} + +/** + * Parse class expression + * + * @param parser Parser object + * @param context Context masks + */ +export function parseClassExpression( + parser: ParserState, + context: Context, + inGroup: 0 | 1, + start: number, + line: number, + column: number +): ESTree.ClassExpression { + // ClassExpression :: + // 'class' Identifier ('extends' LeftHandSideExpression)? '{' ClassBody '}' + // 'class' ('extends' LeftHandSideExpression)? '{' ClassBody '}' + // DecoratorList[?Yield, ?Await]optclassBindingIdentifier[?Yield, ?Await]ClassTail[?Yield, ?Await] + // + + let id: ESTree.Expression | null = null; + let superClass: ESTree.Expression | null = null; + + // All class code is always strict mode implicitly + context = (context | Context.Strict | Context.InConstructor) ^ Context.InConstructor; + + const decorators = parseDecorators(parser, context); + if (decorators.length) { + start = parser.tokenPos; + line = parser.linePos; + column = parser.colPos; + } + + nextToken(parser, context); + + if (parser.token & Token.Keyword && parser.token !== Token.ExtendsKeyword) { + if (isStrictReservedWord(parser, context, parser.token)) report(parser, Errors.UnexpectedStrictReserved); + if ((parser.token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) { + report(parser, Errors.StrictEvalArguments); + } + + id = parseIdentifier(parser, context, 0); + } + + // Second set of context masks to fix 'super' edge cases + let inheritedContext = context; + + if (consumeOpt(parser, context | Context.AllowRegExp, Token.ExtendsKeyword)) { + superClass = parseLeftHandSideExpression( + parser, + context, + 0, + inGroup, + 0, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + inheritedContext |= Context.SuperCall; + } else { + inheritedContext = (inheritedContext | Context.SuperCall) ^ Context.SuperCall; + } + + const body = parseClassBody(parser, inheritedContext, context, void 0, BindingKind.Empty, Origin.None, inGroup); + + parser.assignable = AssignmentKind.CannotAssign; + + return finishNode( + parser, + context, + start, + line, + column, + context & Context.OptionsNext + ? { + type: 'ClassExpression', + id, + superClass, + decorators, + body + } + : { + type: 'ClassExpression', + id, + superClass, + body + } + ); +} + +/** + * Parses a list of decorators + * + * @param parser Parser object + * @param context Context masks + */ +export function parseDecorators(parser: ParserState, context: Context): ESTree.Decorator[] { + const list: ESTree.Decorator[] = []; + + if (context & Context.OptionsNext) { + while (parser.token === Token.Decorator) { + list.push(parseDecoratorList(parser, context, parser.tokenPos, parser.linePos, parser.colPos)); + } + } + + return list; +} + +/** + * Parses a list of decorators + * + * @param parser Parser object + * @param context Context masks + * @param start + */ + +export function parseDecoratorList( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.Decorator { + nextToken(parser, context | Context.AllowRegExp); + + let expression = parsePrimaryExpression(parser, context, BindingKind.Empty, 0, 1, 0, 0, 1, start, line, column); + + expression = parseMemberOrUpdateExpression(parser, context, expression, 0, 0, start, line, column); + + return finishNode(parser, context, start, line, column, { + type: 'Decorator', + expression + }); +} +/** + * Parses class body + * + * @param parser Parser object + * @param context Context masks + * @param inheritedContext Second set of context masks + * @param type Binding kind + * @param origin Binding origin + * @param decorators + */ + +export function parseClassBody( + parser: ParserState, + context: Context, + inheritedContext: Context, + scope: ScopeState | undefined, + kind: BindingKind, + origin: Origin, + inGroup: 0 | 1 +): ESTree.ClassBody { + /** + * ClassElement : + * static MethodDefinition + * MethodDefinition + * DecoratorList + * DecoratorList static MethodDefinition + * DecoratorList PropertyDefinition + * DecoratorList static PropertyDefinition + * + * MethodDefinition : + * ClassElementName ( FormalParameterList ) { FunctionBody } + * get ClassElementName ( ) { FunctionBody } + * set ClassElementName ( PropertySetParameterList ) { FunctionBody } + * + * ClassElementName : + * PropertyName + * PrivateIdentifier + * + * PrivateIdentifier :: + * # IdentifierName + * + * IdentifierName :: + * IdentifierStart + * IdentifierName IdentifierPart + * + * IdentifierStart :: + * UnicodeIDStart + * $ + * _ + * \ UnicodeEscapeSequence + * IdentifierPart:: + * UnicodeIDContinue + * $ + * \ UnicodeEscapeSequence + * <ZWNJ> <ZWJ> + * + * UnicodeIDStart:: + * any Unicode code point with the Unicode property "ID_Start" + * + * UnicodeIDContinue:: + * any Unicode code point with the Unicode property "ID_Continue" + * + * GeneratorMethod : + * * ClassElementName ( UniqueFormalParameters ){GeneratorBody} + * + * AsyncMethod : + * async [no LineTerminator here] ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody } + * + * AsyncGeneratorMethod : + * async [no LineTerminator here]* ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody } + */ + + const { tokenPos, linePos, colPos } = parser; + + consume(parser, context | Context.AllowRegExp, Token.LeftBrace); + context = (context | Context.DisallowIn) ^ Context.DisallowIn; + parser.flags = (parser.flags | Flags.HasConstructor) ^ Flags.HasConstructor; + + const body: (ESTree.MethodDefinition | ESTree.PropertyDefinition)[] = []; + let decorators: ESTree.Decorator[]; + + while (parser.token !== Token.RightBrace) { + let length = 0; + + // See: https://github.com/tc39/proposal-decorators + + decorators = parseDecorators(parser, context); + + length = decorators.length; + + if (length > 0 && parser.tokenValue === 'constructor') { + report(parser, Errors.GeneratorConstructor); + } + + if (parser.token === Token.RightBrace) report(parser, Errors.TrailingDecorators); + + if (consumeOpt(parser, context, Token.Semicolon)) { + if (length > 0) report(parser, Errors.InvalidDecoratorSemicolon); + continue; + } + body.push( + parseClassElementList( + parser, + context, + scope, + inheritedContext, + kind, + decorators, + 0, + inGroup, + parser.tokenPos, + parser.linePos, + parser.colPos + ) + ); + } + consume(parser, origin & Origin.Declaration ? context | Context.AllowRegExp : context, Token.RightBrace); + + return finishNode(parser, context, tokenPos, linePos, colPos, { + type: 'ClassBody', + body + }); +} + +/** + * Parses class element list + * + * @param parser Parser object + * @param context Context masks + * @param inheritedContext Second set of context masks + * @param type Binding type + * @param decorators + * @param isStatic + */ +function parseClassElementList( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + inheritedContext: Context, + type: BindingKind, + decorators: ESTree.Decorator[], + isStatic: 0 | 1, + inGroup: 0 | 1, + start: number, + line: number, + column: number +): ESTree.MethodDefinition | ESTree.PropertyDefinition { + let kind: PropertyKind = isStatic ? PropertyKind.Static : PropertyKind.None; + let key: ESTree.Expression | ESTree.PrivateIdentifier | null = null; + + const { token, tokenPos, linePos, colPos } = parser; + + if (token & (Token.IsIdentifier | Token.FutureReserved)) { + key = parseIdentifier(parser, context, 0); + + switch (token) { + case Token.StaticKeyword: + if (!isStatic && parser.token !== Token.LeftParen) { + return parseClassElementList( + parser, + context, + scope, + inheritedContext, + type, + decorators, + 1, + inGroup, + start, + line, + column + ); + } + break; + + case Token.AsyncKeyword: + if (parser.token !== Token.LeftParen && (parser.flags & Flags.NewLine) < 1) { + if (context & Context.OptionsNext && (parser.token & Token.IsClassField) === Token.IsClassField) { + return parsePropertyDefinition(parser, context, key, kind, decorators, tokenPos, linePos, colPos); + } + + kind |= PropertyKind.Async | (optionalBit(parser, context, Token.Multiply) ? PropertyKind.Generator : 0); + } + break; + + case Token.GetKeyword: + if (parser.token !== Token.LeftParen) { + if (context & Context.OptionsNext && (parser.token & Token.IsClassField) === Token.IsClassField) { + return parsePropertyDefinition(parser, context, key, kind, decorators, tokenPos, linePos, colPos); + } + kind |= PropertyKind.Getter; + } + break; + + case Token.SetKeyword: + if (parser.token !== Token.LeftParen) { + if (context & Context.OptionsNext && (parser.token & Token.IsClassField) === Token.IsClassField) { + return parsePropertyDefinition(parser, context, key, kind, decorators, tokenPos, linePos, colPos); + } + kind |= PropertyKind.Setter; + } + break; + + default: // ignore + } + } else if (token === Token.LeftBracket) { + kind |= PropertyKind.Computed; + key = parseComputedPropertyName(parser, inheritedContext, inGroup); + } else if ((token & Token.IsStringOrNumber) === Token.IsStringOrNumber) { + key = parseLiteral(parser, context); + } else if (token === Token.Multiply) { + kind |= PropertyKind.Generator; + nextToken(parser, context); // skip: '*' + } else if (context & Context.OptionsNext && parser.token === Token.PrivateField) { + kind |= PropertyKind.PrivateField; + key = parsePrivateIdentifier(parser, context, tokenPos, linePos, colPos); + context = context | Context.InClass; + } else if (context & Context.OptionsNext && (parser.token & Token.IsClassField) === Token.IsClassField) { + kind |= PropertyKind.ClassField; + context = context | Context.InClass; + } else if (token === Token.EscapedFutureReserved) { + key = parseIdentifier(parser, context, 0); + if (parser.token !== Token.LeftParen) + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + } else { + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + } + + if (kind & (PropertyKind.Generator | PropertyKind.Async | PropertyKind.GetSet)) { + if (parser.token & Token.IsIdentifier) { + key = parseIdentifier(parser, context, 0); + } else if ((parser.token & Token.IsStringOrNumber) === Token.IsStringOrNumber) { + key = parseLiteral(parser, context); + } else if (parser.token === Token.LeftBracket) { + kind |= PropertyKind.Computed; + key = parseComputedPropertyName(parser, context, /* inGroup */ 0); + } else if (parser.token === Token.EscapedFutureReserved) { + key = parseIdentifier(parser, context, 0); + } else if (context & Context.OptionsNext && parser.token === Token.PrivateField) { + kind |= PropertyKind.PrivateField; + key = parsePrivateIdentifier(parser, context, tokenPos, linePos, colPos); + } else report(parser, Errors.InvalidKeyToken); + } + + if ((kind & PropertyKind.Computed) < 1) { + if (parser.tokenValue === 'constructor') { + if ((parser.token & Token.IsClassField) === Token.IsClassField) { + report(parser, Errors.InvalidClassFieldConstructor); + } else if ((kind & PropertyKind.Static) < 1 && parser.token === Token.LeftParen) { + if (kind & (PropertyKind.GetSet | PropertyKind.Async | PropertyKind.ClassField | PropertyKind.Generator)) { + report(parser, Errors.InvalidConstructor, 'accessor'); + } else if ((context & Context.SuperCall) < 1) { + if (parser.flags & Flags.HasConstructor) report(parser, Errors.DuplicateConstructor); + else parser.flags |= Flags.HasConstructor; + } + } + kind |= PropertyKind.Constructor; + } else if ( + // Static Async Generator Private Methods can be named "#prototype" (class declaration) + (kind & PropertyKind.PrivateField) < 1 && + kind & (PropertyKind.Static | PropertyKind.GetSet | PropertyKind.Generator | PropertyKind.Async) && + parser.tokenValue === 'prototype' + ) { + report(parser, Errors.StaticPrototype); + } + } + + if (context & Context.OptionsNext && parser.token !== Token.LeftParen) { + return parsePropertyDefinition(parser, context, key, kind, decorators, tokenPos, linePos, colPos); + } + + const value = parseMethodDefinition(parser, context, kind, inGroup, parser.tokenPos, parser.linePos, parser.colPos); + + return finishNode( + parser, + context, + start, + line, + column, + context & Context.OptionsNext + ? { + type: 'MethodDefinition', + kind: + (kind & PropertyKind.Static) < 1 && kind & PropertyKind.Constructor + ? 'constructor' + : kind & PropertyKind.Getter + ? 'get' + : kind & PropertyKind.Setter + ? 'set' + : 'method', + static: (kind & PropertyKind.Static) > 0, + computed: (kind & PropertyKind.Computed) > 0, + key, + decorators, + value + } + : { + type: 'MethodDefinition', + kind: + (kind & PropertyKind.Static) < 1 && kind & PropertyKind.Constructor + ? 'constructor' + : kind & PropertyKind.Getter + ? 'get' + : kind & PropertyKind.Setter + ? 'set' + : 'method', + static: (kind & PropertyKind.Static) > 0, + computed: (kind & PropertyKind.Computed) > 0, + key, + value + } + ); +} + +/** + * Parses private name + * + * @param parser Parser object + * @param context Context masks + */ +function parsePrivateIdentifier( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.PrivateIdentifier { + // PrivateIdentifier:: + // #IdentifierName + nextToken(parser, context); // skip: '#' + const { tokenValue } = parser; + if (tokenValue === 'constructor') report(parser, Errors.InvalidStaticClassFieldConstructor); + nextToken(parser, context); + + return finishNode(parser, context, start, line, column, { + type: 'PrivateIdentifier', + name: tokenValue + }); +} + +/** + * Parses field definition + * + * @param parser Parser object + * @param context Context masks + * @param key ESTree AST node + * @param state + * @param decorators + */ + +export function parsePropertyDefinition( + parser: ParserState, + context: Context, + key: ESTree.PrivateIdentifier | ESTree.Expression | null, + state: PropertyKind, + decorators: ESTree.Decorator[] | null, + start: number, + line: number, + column: number +): ESTree.PropertyDefinition { + // ClassElement : + // MethodDefinition + // static MethodDefinition + // PropertyDefinition ; + // ; + let value: ESTree.Expression | null = null; + + if (state & PropertyKind.Generator) report(parser, Errors.Unexpected); + + if (parser.token === Token.Assign) { + nextToken(parser, context | Context.AllowRegExp); + + const { tokenPos, linePos, colPos } = parser; + + if (parser.token === Token.Arguments) report(parser, Errors.StrictEvalArguments); + + value = parsePrimaryExpression( + parser, + context | Context.InClass, + BindingKind.Empty, + 0, + 1, + 0, + 0, + 1, + tokenPos, + linePos, + colPos + ); + + if ((parser.token & Token.IsClassField) !== Token.IsClassField) { + value = parseMemberOrUpdateExpression( + parser, + context | Context.InClass, + value as ESTree.Expression, + 0, + 0, + tokenPos, + linePos, + colPos + ); + + value = parseAssignmentExpression(parser, context | Context.InClass, 0, 0, tokenPos, linePos, colPos, value); + if (parser.token === Token.Comma) { + value = parseSequenceExpression(parser, context, 0, start, line, column, value as any); + } + } + } + + return finishNode(parser, context, start, line, column, { + type: 'PropertyDefinition', + key, + value, + static: (state & PropertyKind.Static) > 0, + computed: (state & PropertyKind.Computed) > 0, + decorators + } as any); +} + +/** + * Parses binding pattern + * + * @param parser Parser object + * @param context Context masks + * @param type Binding kind + */ +export function parseBindingPattern( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + type: BindingKind, + origin: Origin, + start: number, + line: number, + column: number +): ESTree.BindingPattern { + // Pattern :: + // Identifier + // ArrayLiteral + // ObjectLiteral + + if (parser.token & Token.IsIdentifier) + return parseAndClassifyIdentifier(parser, context, scope, type, origin, start, line, column); + + if ((parser.token & Token.IsPatternStart) !== Token.IsPatternStart) + report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]); + + const left: any = + parser.token === Token.LeftBracket + ? parseArrayExpressionOrPattern(parser, context, scope, 1, 0, 1, type, origin, start, line, column) + : parseObjectLiteralOrPattern(parser, context, scope, 1, 0, 1, type, origin, start, line, column); + + if (parser.destructible & DestructuringKind.CannotDestruct) report(parser, Errors.InvalidBindingDestruct); + + if (parser.destructible & DestructuringKind.Assignable) report(parser, Errors.InvalidBindingDestruct); + + return left; +} + +/** + * Classify and parse identifier if of valid type + * + * @param parser Parser object + * @param context Context masks + * @param type Binding kind + */ +function parseAndClassifyIdentifier( + parser: ParserState, + context: Context, + scope: ScopeState | undefined, + kind: BindingKind, + origin: Origin, + start: number, + line: number, + column: number +): ESTree.Identifier { + const { tokenValue, token } = parser; + + if (context & Context.Strict) { + if ((token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) { + report(parser, Errors.StrictEvalArguments); + } else if ((token & Token.FutureReserved) === Token.FutureReserved) { + report(parser, Errors.UnexpectedStrictReserved); + } + } + + if ((token & Token.Reserved) === Token.Reserved) { + report(parser, Errors.KeywordNotId); + } + + if (context & (Context.Module | Context.InYieldContext) && token === Token.YieldKeyword) { + report(parser, Errors.YieldInParameter); + } + if (token === Token.LetKeyword) { + if (kind & (BindingKind.Let | BindingKind.Const)) report(parser, Errors.InvalidLetConstBinding); + } + if (context & (Context.InAwaitContext | Context.Module) && token === Token.AwaitKeyword) { + report(parser, Errors.AwaitOutsideAsync); + } + + nextToken(parser, context); + + if (scope) addVarOrBlock(parser, context, scope, tokenValue, kind, origin); + + return finishNode(parser, context, start, line, column, { + type: 'Identifier', + name: tokenValue + }); +} + +/** + * Parses either a JSX element or JSX Fragment + * + * @param parser Parser object + * @param context Context masks + * @param inJSXChild + * @param start + * @param line + * @param column + */ + +function parseJSXRootElementOrFragment( + parser: ParserState, + context: Context, + inJSXChild: 0 | 1, + start: number, + line: number, + column: number +): ESTree.JSXElement | ESTree.JSXFragment { + nextToken(parser, context); + + // JSX fragments + if (parser.token === Token.GreaterThan) { + return finishNode(parser, context, start, line, column, { + type: 'JSXFragment', + openingFragment: parseOpeningFragment(parser, context, start, line, column), + children: parseJSXChildren(parser, context), + closingFragment: parseJSXClosingFragment( + parser, + context, + inJSXChild, + parser.tokenPos, + parser.linePos, + parser.colPos + ) + }); + } + + let closingElement: ESTree.JSXClosingElement | null = null; + let children: ESTree.JSXChild[] = []; + + const openingElement: ESTree.JSXOpeningElement = parseJSXOpeningFragmentOrSelfCloseElement( + parser, + context, + inJSXChild, + start, + line, + column + ); + + if (!openingElement.selfClosing) { + children = parseJSXChildren(parser, context); + closingElement = parseJSXClosingElement( + parser, + context, + inJSXChild, + parser.tokenPos, + parser.linePos, + parser.colPos + ); + const close = isEqualTagName(closingElement.name); + if (isEqualTagName(openingElement.name) !== close) report(parser, Errors.ExpectedJSXClosingTag, close); + } + + return finishNode(parser, context, start, line, column, { + type: 'JSXElement', + children, + openingElement, + closingElement + }); +} + +/** + * Parses JSX opening fragment + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param line + * @param column + */ +export function parseOpeningFragment( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.JSXOpeningFragment { + scanJSXToken(parser, context); + return finishNode(parser, context, start, line, column, { + type: 'JSXOpeningFragment' + }); +} + +/** + * Parses JSX Closing element + * + * @param parser Parser object + * @param context Context masks + * @param inJSXChild + * @param start + * @param line + * @param column + */ +function parseJSXClosingElement( + parser: ParserState, + context: Context, + inJSXChild: 0 | 1, + start: number, + line: number, + column: number +): ESTree.JSXClosingElement { + consume(parser, context, Token.JSXClose); + const name = parseJSXElementName(parser, context, parser.tokenPos, parser.linePos, parser.colPos); + if (inJSXChild) { + consume(parser, context, Token.GreaterThan); + } else { + parser.token = scanJSXToken(parser, context); + } + + return finishNode(parser, context, start, line, column, { + type: 'JSXClosingElement', + name + }); +} + +/** + * Parses JSX closing fragment + * + * @param parser Parser object + * @param context Context masks + * @param inJSXChild + * @param start + * @param line + * @param column + */ +export function parseJSXClosingFragment( + parser: ParserState, + context: Context, + inJSXChild: 0 | 1, + start: number, + line: number, + column: number +): ESTree.JSXClosingFragment { + consume(parser, context, Token.JSXClose); + + if (inJSXChild) { + consume(parser, context, Token.GreaterThan); + } else { + consume(parser, context, Token.GreaterThan); + } + + return finishNode(parser, context, start, line, column, { + type: 'JSXClosingFragment' + }); +} + +/** + * Parses JSX children + * + * @param parser Parser object + * @param context Context masks + */ +export function parseJSXChildren(parser: ParserState, context: Context): ESTree.JSXChild[] { + const children: ESTree.JSXChild[] = []; + while (parser.token !== Token.JSXClose) { + parser.index = parser.tokenPos = parser.startPos; + parser.column = parser.colPos = parser.startColumn; + parser.line = parser.linePos = parser.startLine; + scanJSXToken(parser, context); + children.push(parseJSXChild(parser, context, parser.tokenPos, parser.linePos, parser.colPos)); + } + return children; +} + +/** + * Parses a JSX child node + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param line + * @param column + */ +function parseJSXChild(parser: ParserState, context: Context, start: number, line: number, column: number): any { + if (parser.token === Token.JSXText) return parseJSXText(parser, context, start, line, column); + if (parser.token === Token.LeftBrace) + return parseJSXExpressionContainer(parser, context, /*inJSXChild*/ 0, /* isAttr */ 0, start, line, column); + if (parser.token === Token.LessThan) + return parseJSXRootElementOrFragment(parser, context, /*inJSXChild*/ 0, start, line, column); + report(parser, Errors.Unexpected); +} + +/** + * Parses JSX Text + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param line + * @param column + */ +export function parseJSXText( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.JSXText { + scanJSXToken(parser, context); + + const node = { + type: 'JSXText', + value: parser.tokenValue as string + } as ESTree.JSXText; + + if (context & Context.OptionsRaw) { + node.raw = parser.tokenRaw; + } + + return finishNode(parser, context, start, line, column, node); +} + +/** + * Parses either a JSX element, JSX Fragment or JSX self close element + * + * @param parser Parser object + * @param context Context masks + * @param inJSXChild + * @param start + * @param line + * @param column + */ +function parseJSXOpeningFragmentOrSelfCloseElement( + parser: ParserState, + context: Context, + inJSXChild: 0 | 1, + start: number, + line: number, + column: number +): ESTree.JSXOpeningElement { + if ((parser.token & Token.IsIdentifier) !== Token.IsIdentifier && (parser.token & Token.Keyword) !== Token.Keyword) + report(parser, Errors.Unexpected); + + const tagName = parseJSXElementName(parser, context, parser.tokenPos, parser.linePos, parser.colPos); + const attributes = parseJSXAttributes(parser, context); + const selfClosing = parser.token === Token.Divide; + + if (parser.token === Token.GreaterThan) { + scanJSXToken(parser, context); + } else { + consume(parser, context, Token.Divide); + if (inJSXChild) { + consume(parser, context, Token.GreaterThan); + } else { + scanJSXToken(parser, context); + } + } + + return finishNode(parser, context, start, line, column, { + type: 'JSXOpeningElement', + name: tagName, + attributes, + selfClosing + }); +} + +/** + * Parses JSX element name + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param line + * @param column + */ +function parseJSXElementName( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.JSXIdentifier | ESTree.JSXMemberExpression | ESTree.JSXNamespacedName { + scanJSXIdentifier(parser); + + let key: ESTree.JSXIdentifier | ESTree.JSXMemberExpression = parseJSXIdentifier(parser, context, start, line, column); + + // Namespace + if (parser.token === Token.Colon) return parseJSXNamespacedName(parser, context, key, start, line, column); + + // Member expression + while (consumeOpt(parser, context, Token.Period)) { + scanJSXIdentifier(parser); + key = parseJSXMemberExpression(parser, context, key, start, line, column); + } + return key; +} + +/** + * Parses JSX member expression + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param line + * @param column + */ +export function parseJSXMemberExpression( + parser: ParserState, + context: Context, + object: ESTree.JSXIdentifier | ESTree.JSXMemberExpression, + start: number, + line: number, + column: number +): ESTree.JSXMemberExpression { + const property = parseJSXIdentifier(parser, context, parser.tokenPos, parser.linePos, parser.colPos); + return finishNode(parser, context, start, line, column, { + type: 'JSXMemberExpression', + object, + property + }); +} + +/** + * Parses JSX attributes + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param line + * @param column + */ +export function parseJSXAttributes( + parser: ParserState, + context: Context +): (ESTree.JSXAttribute | ESTree.JSXSpreadAttribute)[] { + const attributes: (ESTree.JSXAttribute | ESTree.JSXSpreadAttribute)[] = []; + while (parser.token !== Token.Divide && parser.token !== Token.GreaterThan && parser.token !== Token.EOF) { + attributes.push(parseJsxAttribute(parser, context, parser.tokenPos, parser.linePos, parser.colPos)); + } + return attributes; +} + +/** + * Parses JSX Spread attribute + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param line + * @param column + */ +export function parseJSXSpreadAttribute( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.JSXSpreadAttribute { + nextToken(parser, context); // skips: '{' + consume(parser, context, Token.Ellipsis); + const expression = parseExpression(parser, context, 1, 0, 0, parser.tokenPos, parser.linePos, parser.colPos); + consume(parser, context, Token.RightBrace); + return finishNode(parser, context, start, line, column, { + type: 'JSXSpreadAttribute', + argument: expression + }); +} + +/** + * Parses JSX attribute + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param line + * @param column + */ +function parseJsxAttribute( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.JSXAttribute | ESTree.JSXSpreadAttribute { + if (parser.token === Token.LeftBrace) return parseJSXSpreadAttribute(parser, context, start, line, column); + scanJSXIdentifier(parser); + let value: ESTree.JSXAttributeValue | null = null; + let name: ESTree.JSXNamespacedName | ESTree.JSXIdentifier = parseJSXIdentifier(parser, context, start, line, column); + + if (parser.token === Token.Colon) { + name = parseJSXNamespacedName(parser, context, name, start, line, column); + } + + // HTML empty attribute + if (parser.token === Token.Assign) { + const token = scanJSXAttributeValue(parser, context); + const { tokenPos, linePos, colPos } = parser; + switch (token) { + case Token.StringLiteral: + value = parseLiteral(parser, context); + break; + case Token.LessThan: + value = parseJSXRootElementOrFragment(parser, context, /*inJSXChild*/ 1, tokenPos, linePos, colPos); + break; + case Token.LeftBrace: + value = parseJSXExpressionContainer(parser, context, 1, 1, tokenPos, linePos, colPos); + break; + default: + report(parser, Errors.InvalidJSXAttributeValue); + } + } + + return finishNode(parser, context, start, line, column, { + type: 'JSXAttribute', + value, + name + }); +} + +/** + * Parses JSX namespace name + * + * @param parser Parser object + * @param context Context masks + * @param namespace + * @param start + * @param line + * @param column + */ + +function parseJSXNamespacedName( + parser: ParserState, + context: Context, + namespace: ESTree.JSXIdentifier | ESTree.JSXMemberExpression, + start: number, + line: number, + column: number +): ESTree.JSXNamespacedName { + consume(parser, context, Token.Colon); + const name = parseJSXIdentifier(parser, context, parser.tokenPos, parser.linePos, parser.colPos); + return finishNode(parser, context, start, line, column, { + type: 'JSXNamespacedName', + namespace, + name + }); +} + +/** + * Parses JSX Expression container + * + * @param parser Parser object + * @param context Context masks + * @param inJSXChild + * @param start + * @param line + * @param column + */ +function parseJSXExpressionContainer( + parser: ParserState, + context: Context, + inJSXChild: 0 | 1, + isAttr: 0 | 1, + start: number, + line: number, + column: number +): ESTree.JSXExpressionContainer | ESTree.JSXSpreadChild { + nextToken(parser, context); + const { tokenPos, linePos, colPos } = parser; + if (parser.token === Token.Ellipsis) return parseJSXSpreadChild(parser, context, tokenPos, linePos, colPos); + + let expression: ESTree.Expression | ESTree.JSXEmptyExpression | null = null; + + if (parser.token === Token.RightBrace) { + // JSX attributes must only be assigned a non-empty 'expression' + if (isAttr) report(parser, Errors.InvalidNonEmptyJSXExpr); + expression = parseJSXEmptyExpression(parser, context, parser.startPos, parser.startLine, parser.startColumn); + } else { + expression = parseExpression(parser, context, 1, 0, 0, tokenPos, linePos, colPos); + } + if (inJSXChild) { + consume(parser, context, Token.RightBrace); + } else { + scanJSXToken(parser, context); + } + + return finishNode(parser, context, start, line, column, { + type: 'JSXExpressionContainer', + expression + }); +} + +/** + * Parses JSX spread child + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param line + * @param column + */ +function parseJSXSpreadChild( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.JSXSpreadChild { + consume(parser, context, Token.Ellipsis); + const expression = parseExpression(parser, context, 1, 0, 0, parser.tokenPos, parser.linePos, parser.colPos); + consume(parser, context, Token.RightBrace); + return finishNode(parser, context, start, line, column, { + type: 'JSXSpreadChild', + expression + }); +} + +/** + * Parses JSX empty expression + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param line + * @param column + */ +function parseJSXEmptyExpression( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.JSXEmptyExpression { + // Since " }" is treated as single token, we have to artificially break + // it into " " and "}". + // Move token start from beginning of whitespace(s) to beginning of "}", + // so JSXEmptyExpression can have correct end loc. + parser.startPos = parser.tokenPos; + parser.startLine = parser.linePos; + parser.startColumn = parser.colPos; + return finishNode(parser, context, start, line, column, { + type: 'JSXEmptyExpression' + }); +} + +/** + * Parses JSX Identifier + * + * @param parser Parser object + * @param context Context masks + * @param start + * @param line + * @param column + */ +export function parseJSXIdentifier( + parser: ParserState, + context: Context, + start: number, + line: number, + column: number +): ESTree.JSXIdentifier { + const { tokenValue } = parser; + nextToken(parser, context); + + return finishNode(parser, context, start, line, column, { + type: 'JSXIdentifier', + name: tokenValue + }); +} diff --git a/node_modules/meriyah/src/token.ts b/node_modules/meriyah/src/token.ts new file mode 100644 index 0000000..0527d81 --- /dev/null +++ b/node_modules/meriyah/src/token.ts @@ -0,0 +1,307 @@ +export const enum Token { + Type = 0xFF, + + /* Precedence for binary operators (always positive) */ + PrecStart = 8, + Precedence = 15 << PrecStart, // 8-11 + + /* Attribute names */ + Keyword = 1 << 12, + Contextual = 1 << 13 | Keyword, + Reserved = 1 << 14 | Keyword, + FutureReserved = 1 << 15 | Keyword, + + IsExpressionStart = 1 << 16, + IsIdentifier = 1 << 17 | Contextual, + IsInOrOf = 1 << 18, // 'in' or 'of' + IsLogical = 1 << 19, + IsAutoSemicolon = 1 << 20, + IsPatternStart = 1 << 21, // Start of pattern, '[' or '{' + IsAssignOp = 1 << 22, + IsBinaryOp = 1 << 23 | IsExpressionStart, + IsUnaryOp = 1 << 24 | IsExpressionStart, + IsUpdateOp = 1 << 25 | IsExpressionStart, + IsMemberOrCallExpression = 1 << 26, + IsStringOrNumber = 1 << 27, + IsCoalesc = 1 << 28, + IsEvalOrArguments = 1 << 29 | IsExpressionStart | IsIdentifier, + IsClassField = 1 << 30, + + // Note: 1 << 31... turns to negative + + /* Node types */ + EOF = 0 | IsAutoSemicolon, + + /* Constants/Bindings */ + Identifier = 1 | IsExpressionStart | IsIdentifier, + NumericLiteral = 2 | IsExpressionStart | IsStringOrNumber, + StringLiteral = 3 | IsExpressionStart | IsStringOrNumber, + RegularExpression = 4 | IsExpressionStart, + FalseKeyword = 5 | Reserved | IsExpressionStart, + TrueKeyword = 6 | Reserved | IsExpressionStart, + NullKeyword = 7 | Reserved | IsExpressionStart, + + /* Template nodes */ + TemplateContinuation = 8 | IsExpressionStart | IsMemberOrCallExpression, + TemplateSpan = 9 | IsExpressionStart | IsMemberOrCallExpression, + + /* Punctuators */ + Arrow = 10, // => + LeftParen = 11 | IsExpressionStart | IsMemberOrCallExpression, // ( + LeftBrace = 12 | IsExpressionStart | IsPatternStart, // { + Period = 13 | IsMemberOrCallExpression, // . + Ellipsis = 14, // ... + RightBrace = 15 | IsAutoSemicolon | IsClassField, // } + RightParen = 16, // ) + Semicolon = 17 | IsAutoSemicolon | IsClassField, // ; + Comma = 18, // , + LeftBracket = 19 | IsExpressionStart | IsPatternStart | IsMemberOrCallExpression, // [ + RightBracket = 20, // ] + Colon = 21, // : + QuestionMark = 22, // ? + SingleQuote = 23, // ' + DoubleQuote = 24, // " + JSXClose = 25, // </ + JSXAutoClose = 26, // /> + + /* Update operators */ + Increment = 27 | IsUpdateOp, // ++ + Decrement = 28 | IsUpdateOp, // -- + + /* Assign operators */ + Assign = 29 | IsAssignOp | IsClassField, // = + ShiftLeftAssign = 30 | IsAssignOp, // <<= + ShiftRightAssign = 31 | IsAssignOp, // >>= + LogicalShiftRightAssign = 32 | IsAssignOp, // >>>= + ExponentiateAssign = 33 | IsAssignOp, // **= + AddAssign = 34 | IsAssignOp, // += + SubtractAssign = 35 | IsAssignOp, // -= + MultiplyAssign = 36 | IsAssignOp, // *= + DivideAssign = 37 | IsAssignOp | IsExpressionStart, // /= + ModuloAssign = 38 | IsAssignOp, // %= + BitwiseXorAssign = 39 | IsAssignOp, // ^= + BitwiseOrAssign = 40 | IsAssignOp, // |= + BitwiseAndAssign = 41 | IsAssignOp, // &= + LogicalOrAssign = 42 | IsAssignOp, // ||= + LogicalAndAssign = 43 | IsAssignOp, // &&= + CoalesceAssign = 44 | IsAssignOp, // ??= + + /* Unary/binary operators */ + TypeofKeyword = 45 | IsUnaryOp | Reserved, + DeleteKeyword = 46 | IsUnaryOp | Reserved, + VoidKeyword = 47 | IsUnaryOp | Reserved, + Negate = 48 | IsUnaryOp, // ! + Complement = 49 | IsUnaryOp, // ~ + Add = 50 | IsUnaryOp | IsBinaryOp | 10 << PrecStart, // + + Subtract = 51 | IsUnaryOp | IsBinaryOp | 10 << PrecStart, // - + InKeyword = 52 | IsBinaryOp | 8 << PrecStart | Reserved | IsInOrOf, + InstanceofKeyword = 53 | IsBinaryOp | 8 << PrecStart | Reserved, + Multiply = 54 | IsBinaryOp | 11 << PrecStart, // * + Modulo = 55 | IsBinaryOp | 11 << PrecStart, // % + Divide = 56 | IsBinaryOp | IsExpressionStart | 11 << PrecStart, // / + Exponentiate = 57 | IsBinaryOp | 12 << PrecStart, // ** + LogicalAnd = 58 | IsBinaryOp | IsLogical | 3 << PrecStart, // && + LogicalOr = 59 | IsBinaryOp | IsLogical | 2 << PrecStart, // || + StrictEqual = 60 | IsBinaryOp | 7 << PrecStart, // === + StrictNotEqual = 61 | IsBinaryOp | 7 << PrecStart, // !== + LooseEqual = 62 | IsBinaryOp | 7 << PrecStart, // == + LooseNotEqual = 63 | IsBinaryOp | 7 << PrecStart, // != + LessThanOrEqual = 64 | IsBinaryOp | 7 << PrecStart, // <= + GreaterThanOrEqual = 65 | IsBinaryOp | 7 << PrecStart, // >= + LessThan = 66 | IsBinaryOp | IsExpressionStart | 8 << PrecStart, // < + GreaterThan = 67 | IsBinaryOp | 8 << PrecStart, // > + ShiftLeft = 68 | IsBinaryOp | 9 << PrecStart, // << + ShiftRight = 69 | IsBinaryOp | 9 << PrecStart, // >> + LogicalShiftRight = 70 | IsBinaryOp | 9 << PrecStart, // >>> + BitwiseAnd = 71 | IsBinaryOp | 6 << PrecStart, // & + BitwiseOr = 72 | IsBinaryOp | 4 << PrecStart, // | + BitwiseXor = 73 | IsBinaryOp | 5 << PrecStart, // ^ + + /* Variable declaration kinds */ + VarKeyword = 74 | IsExpressionStart | Reserved, + LetKeyword = 75 | IsExpressionStart | FutureReserved | IsIdentifier, + ConstKeyword = 76 | IsExpressionStart | Reserved, + + /* Other reserved words */ + BreakKeyword = 77 | Reserved, + CaseKeyword = 78 | Reserved, + CatchKeyword = 79 | Reserved, + ClassKeyword = 80 | IsExpressionStart | Reserved, + ContinueKeyword = 81 | Reserved, + DebuggerKeyword = 82 | Reserved, + DefaultKeyword = 83 | Reserved, + DoKeyword = 84 | Reserved, + ElseKeyword = 85 | Reserved, + ExportKeyword = 86 | Reserved, + ExtendsKeyword = 87 | Reserved, + FinallyKeyword = 88 | Reserved, + ForKeyword = 89 | Reserved, + FunctionKeyword = 90 | IsExpressionStart | Reserved, + IfKeyword = 91 | Reserved, + ImportKeyword = 92 | IsExpressionStart | Reserved, + NewKeyword = 93 | IsExpressionStart | Reserved, + ReturnKeyword = 94 | Reserved, + SuperKeyword = 95 | IsExpressionStart | Reserved, + SwitchKeyword = 96 | IsExpressionStart | Reserved, + ThisKeyword = 97 | IsExpressionStart | Reserved, + ThrowKeyword = 98 | IsExpressionStart | Reserved, + TryKeyword = 99 | Reserved, + WhileKeyword = 100 | Reserved, + WithKeyword = 101 | Reserved, + + /* Strict mode reserved words */ + ImplementsKeyword = 102 | FutureReserved, + InterfaceKeyword = 103 | FutureReserved, + PackageKeyword = 104 | FutureReserved, + PrivateKeyword = 105 | FutureReserved, + ProtectedKeyword = 106 | FutureReserved, + PublicKeyword = 107 | FutureReserved, + StaticKeyword = 108 | FutureReserved, + YieldKeyword = 109 | FutureReserved | IsExpressionStart | IsIdentifier, + + /* Contextual keywords */ + AsKeyword = 110 | Contextual | IsExpressionStart, + AsyncKeyword = 111 | Contextual | IsIdentifier | IsExpressionStart, + AwaitKeyword = 112 | Contextual | IsExpressionStart | IsIdentifier, + ConstructorKeyword = 113 | Contextual, + GetKeyword = 114 | Contextual, + SetKeyword = 115 | Contextual, + FromKeyword = 116 | Contextual, + OfKeyword = 117 | Contextual | IsInOrOf, + EnumKeyword = 118 | Reserved | IsExpressionStart, + + Eval = 119 | IsEvalOrArguments, + Arguments = 120 | IsEvalOrArguments, + + EscapedReserved = 121, + EscapedFutureReserved = 122, + AnyIdentifier = 123 | IsIdentifier, + + // Stage #3 proposals + PrivateIdentifier = 124, + BigIntLiteral = 125 | IsExpressionStart | IsStringOrNumber, + Coalesce = 126 | IsBinaryOp | IsCoalesc | 1 << PrecStart, // ?? + QuestionMarkPeriod = 127 | IsMemberOrCallExpression, // ?. + + // Others + WhiteSpace = 128, + Illegal = 129, + CarriageReturn = 130, + PrivateField = 131, + Template = 132, + Decorator = 133, + Target = 134 | IsIdentifier, + Meta = 135 | IsIdentifier, + LineFeed = 136, + EscapedIdentifier = 137, + + // JSX + JSXText = 138, +} + +export const KeywordDescTable = [ + 'end of source', + + /* Constants/Bindings */ + 'identifier', 'number', 'string', 'regular expression', + 'false', 'true', 'null', + + /* Template nodes */ + 'template continuation', 'template tail', + + /* Punctuators */ + '=>', '(', '{', '.', '...', '}', ')', ';', ',', '[', ']', ':', '?', '\'', '"', '</', '/>', + + /* Update operators */ + '++', '--', + + /* Assign operators */ + '=', '<<=', '>>=', '>>>=', '**=', '+=', '-=', '*=', '/=', '%=', '^=', '|=', + '&=', '||=', '&&=', '??=', + + /* Unary/binary operators */ + 'typeof', 'delete', 'void', '!', '~', '+', '-', 'in', 'instanceof', '*', '%', '/', '**', '&&', + '||', '===', '!==', '==', '!=', '<=', '>=', '<', '>', '<<', '>>', '>>>', '&', '|', '^', + + /* Variable declaration kinds */ + 'var', 'let', 'const', + + /* Other reserved words */ + 'break', 'case', 'catch', 'class', 'continue', 'debugger', 'default', 'do', 'else', 'export', + 'extends', 'finally', 'for', 'function', 'if', 'import', 'new', 'return', 'super', 'switch', + 'this', 'throw', 'try', 'while', 'with', + + /* Strict mode reserved words */ + 'implements', 'interface', 'package', 'private', 'protected', 'public', 'static', 'yield', + + /* Contextual keywords */ + 'as', 'async', 'await', 'constructor', 'get', 'set', 'from', 'of', + + /* Others */ + 'enum', 'eval', 'arguments', 'escaped keyword', 'escaped future reserved keyword', 'reserved if strict', '#', + + 'BigIntLiteral', '??', '?.', 'WhiteSpace', 'Illegal', 'LineTerminator', 'PrivateField', + + 'Template', '@', 'target', 'meta', 'LineFeed', 'Escaped', 'JSXText' +]; + +// Normal object is much faster than Object.create(null), even with typeof check to avoid Object.prototype interference +export const descKeywordTable: { [key: string]: Token } = Object.create(null, { + this: { value: Token.ThisKeyword }, + function: { value: Token.FunctionKeyword }, + if: { value: Token.IfKeyword }, + return: { value: Token.ReturnKeyword }, + var: { value: Token.VarKeyword }, + else: { value: Token.ElseKeyword }, + for: { value: Token.ForKeyword }, + new: { value: Token.NewKeyword }, + in: { value: Token.InKeyword }, + typeof: { value: Token.TypeofKeyword }, + while: { value: Token.WhileKeyword }, + case: { value: Token.CaseKeyword }, + break: { value: Token.BreakKeyword }, + try: { value: Token.TryKeyword }, + catch: { value: Token.CatchKeyword }, + delete: { value: Token.DeleteKeyword }, + throw: { value: Token.ThrowKeyword }, + switch: { value: Token.SwitchKeyword }, + continue: { value: Token.ContinueKeyword }, + default: { value: Token.DefaultKeyword }, + instanceof: { value: Token.InstanceofKeyword }, + do: { value: Token.DoKeyword }, + void: { value: Token.VoidKeyword }, + finally: { value: Token.FinallyKeyword }, + async: { value: Token.AsyncKeyword }, + await: { value: Token.AwaitKeyword }, + class: { value: Token.ClassKeyword }, + const: { value: Token.ConstKeyword }, + constructor: { value: Token.ConstructorKeyword }, + debugger: { value: Token.DebuggerKeyword }, + export: { value: Token.ExportKeyword }, + extends: { value: Token.ExtendsKeyword }, + false: { value: Token.FalseKeyword }, + from: { value: Token.FromKeyword }, + get: { value: Token.GetKeyword }, + implements: { value: Token.ImplementsKeyword }, + import: { value: Token.ImportKeyword }, + interface: { value: Token.InterfaceKeyword }, + let: { value: Token.LetKeyword }, + null: { value: Token.NullKeyword }, + of: { value: Token.OfKeyword }, + package: { value: Token.PackageKeyword }, + private: { value: Token.PrivateKeyword }, + protected: { value: Token.ProtectedKeyword }, + public: { value: Token.PublicKeyword }, + set: { value: Token.SetKeyword }, + static: { value: Token.StaticKeyword }, + super: { value: Token.SuperKeyword }, + true: { value: Token.TrueKeyword }, + with: { value: Token.WithKeyword }, + yield: { value: Token.YieldKeyword }, + enum: { value: Token.EnumKeyword }, + eval: { value: Token.Eval }, + as: { value: Token.AsKeyword }, + arguments: { value: Token.Arguments }, + target: { value: Token.Target }, + meta: { value: Token.Meta }, +}); diff --git a/node_modules/meriyah/src/unicode.ts b/node_modules/meriyah/src/unicode.ts new file mode 100644 index 0000000..0e9083a --- /dev/null +++ b/node_modules/meriyah/src/unicode.ts @@ -0,0 +1,36 @@ +// Unicode v. 13 support +/*eslint-disable*/ + +function isIDContinue(code:number) { + return (unicodeLookup[(code >>> 5) + 0] >>> code & 31 & 1) !== 0 +} +function isIDStart(code:number) { + return (unicodeLookup[(code >>> 5) + 34816] >>> code & 31 & 1) !== 0 +} +function mustEscape(code:number) { + return (unicodeLookup[(code >>> 5) + 69632] >>> code & 31 & 1) !== 0 +} +export const unicodeLookup = ((compressed, lookup) => { + const result = new Uint32Array(104448) + let index = 0; + let subIndex = 0 + while (index < 3540) { + const inst = compressed[index++] + if (inst < 0) { + subIndex -= inst + } else { + let code = compressed[index++] + if (inst & 2) code = lookup[code] + if (inst & 1) { + result.fill(code, subIndex, subIndex += compressed[index++]) + } else { + result[subIndex++] = code + } + } + } + return result +})( + [-1,2,24,2,25,2,5,-1,0,77595648,3,44,2,3,0,14,2,57,2,58,3,0,3,0,3168796671,0,4294956992,2,1,2,0,2,59,3,0,4,0,4294966523,3,0,4,2,16,2,60,2,0,0,4294836735,0,3221225471,0,4294901942,2,61,0,134152192,3,0,2,0,4294951935,3,0,2,0,2683305983,0,2684354047,2,17,2,0,0,4294961151,3,0,2,2,19,2,0,0,608174079,2,0,2,131,2,6,2,56,-1,2,37,0,4294443263,2,1,3,0,3,0,4294901711,2,39,0,4089839103,0,2961209759,0,1342439375,0,4294543342,0,3547201023,0,1577204103,0,4194240,0,4294688750,2,2,0,80831,0,4261478351,0,4294549486,2,2,0,2967484831,0,196559,0,3594373100,0,3288319768,0,8469959,2,194,2,3,0,3825204735,0,123747807,0,65487,0,4294828015,0,4092591615,0,1080049119,0,458703,2,3,2,0,0,2163244511,0,4227923919,0,4236247022,2,66,0,4284449919,0,851904,2,4,2,11,0,67076095,-1,2,67,0,1073741743,0,4093591391,-1,0,50331649,0,3265266687,2,32,0,4294844415,0,4278190047,2,18,2,129,-1,3,0,2,2,21,2,0,2,9,2,0,2,14,2,15,3,0,10,2,69,2,0,2,70,2,71,2,72,2,0,2,73,2,0,2,10,0,261632,2,23,3,0,2,2,12,2,4,3,0,18,2,74,2,5,3,0,2,2,75,0,2088959,2,27,2,8,0,909311,3,0,2,0,814743551,2,41,0,67057664,3,0,2,2,40,2,0,2,28,2,0,2,29,2,7,0,268374015,2,26,2,49,2,0,2,76,0,134153215,-1,2,6,2,0,2,7,0,2684354559,0,67044351,0,3221160064,0,1,-1,3,0,2,2,42,0,1046528,3,0,3,2,8,2,0,2,51,0,4294960127,2,9,2,38,2,10,0,4294377472,2,11,3,0,7,0,4227858431,3,0,8,2,12,2,0,2,78,2,9,2,0,2,79,2,80,2,81,-1,2,124,0,1048577,2,82,2,13,-1,2,13,0,131042,2,83,2,84,2,85,2,0,2,33,-83,2,0,2,53,2,7,3,0,4,0,1046559,2,0,2,14,2,0,0,2147516671,2,20,3,86,2,2,0,-16,2,87,0,524222462,2,4,2,0,0,4269801471,2,4,2,0,2,15,2,77,2,16,3,0,2,2,47,2,0,-1,2,17,-16,3,0,206,-2,3,0,655,2,18,3,0,36,2,68,-1,2,17,2,9,3,0,8,2,89,2,121,2,0,0,3220242431,3,0,3,2,19,2,90,2,91,3,0,2,2,92,2,0,2,93,2,94,2,0,0,4351,2,0,2,8,3,0,2,0,67043391,0,3909091327,2,0,2,22,2,8,2,18,3,0,2,0,67076097,2,7,2,0,2,20,0,67059711,0,4236247039,3,0,2,0,939524103,0,8191999,2,97,2,98,2,15,2,21,3,0,3,0,67057663,3,0,349,2,99,2,100,2,6,-264,3,0,11,2,22,3,0,2,2,31,-1,0,3774349439,2,101,2,102,3,0,2,2,19,2,103,3,0,10,2,9,2,17,2,0,2,45,2,0,2,30,2,104,2,23,0,1638399,2,172,2,105,3,0,3,2,18,2,24,2,25,2,5,2,26,2,0,2,7,2,106,-1,2,107,2,108,2,109,-1,3,0,3,2,11,-2,2,0,2,27,-3,2,150,-4,2,18,2,0,2,35,0,1,2,0,2,62,2,28,2,11,2,9,2,0,2,110,-1,3,0,4,2,9,2,21,2,111,2,6,2,0,2,112,2,0,2,48,-4,3,0,9,2,20,2,29,2,30,-4,2,113,2,114,2,29,2,20,2,7,-2,2,115,2,29,2,31,-2,2,0,2,116,-2,0,4277137519,0,2269118463,-1,3,18,2,-1,2,32,2,36,2,0,3,29,2,2,34,2,19,-3,3,0,2,2,33,-1,2,0,2,34,2,0,2,34,2,0,2,46,-10,2,0,0,203775,-2,2,18,2,43,2,35,-2,2,17,2,117,2,20,3,0,2,2,36,0,2147549120,2,0,2,11,2,17,2,135,2,0,2,37,2,52,0,5242879,3,0,2,0,402644511,-1,2,120,0,1090519039,-2,2,122,2,38,2,0,0,67045375,2,39,0,4226678271,0,3766565279,0,2039759,-4,3,0,2,0,3288270847,0,3,3,0,2,0,67043519,-5,2,0,0,4282384383,0,1056964609,-1,3,0,2,0,67043345,-1,2,0,2,40,2,41,-1,2,10,2,42,-6,2,0,2,11,-3,3,0,2,0,2147484671,2,125,0,4190109695,2,50,-2,2,126,0,4244635647,0,27,2,0,2,7,2,43,2,0,2,63,-1,2,0,2,40,-8,2,54,2,44,0,67043329,2,127,2,45,0,8388351,-2,2,128,0,3028287487,2,46,2,130,0,33259519,2,41,-9,2,20,-5,2,64,-2,3,0,28,2,31,-3,3,0,3,2,47,3,0,6,2,48,-85,3,0,33,2,47,-126,3,0,18,2,36,-269,3,0,17,2,40,2,7,2,41,-2,2,17,2,49,2,0,2,20,2,50,2,132,2,23,-21,3,0,2,-4,3,0,2,0,4294936575,2,0,0,4294934783,-2,0,196635,3,0,191,2,51,3,0,38,2,29,-1,2,33,-279,3,0,8,2,7,-1,2,133,2,52,3,0,11,2,6,-72,3,0,3,2,134,0,1677656575,-166,0,4161266656,0,4071,0,15360,-4,0,28,-13,3,0,2,2,37,2,0,2,136,2,137,2,55,2,0,2,138,2,139,2,140,3,0,10,2,141,2,142,2,15,3,37,2,3,53,2,3,54,2,0,4294954999,2,0,-16,2,0,2,88,2,0,0,2105343,0,4160749584,0,65534,-42,0,4194303871,0,2011,-6,2,0,0,1073684479,0,17407,-11,2,0,2,31,-40,3,0,6,0,8323103,-1,3,0,2,2,42,-37,2,55,2,144,2,145,2,146,2,147,2,148,-105,2,24,-32,3,0,1334,2,9,-1,3,0,129,2,27,3,0,6,2,9,3,0,180,2,149,3,0,233,0,1,-96,3,0,16,2,9,-47,3,0,154,2,56,-22381,3,0,7,2,23,-6130,3,5,2,-1,0,69207040,3,44,2,3,0,14,2,57,2,58,-3,0,3168731136,0,4294956864,2,1,2,0,2,59,3,0,4,0,4294966275,3,0,4,2,16,2,60,2,0,2,33,-1,2,17,2,61,-1,2,0,2,56,0,4294885376,3,0,2,0,3145727,0,2617294944,0,4294770688,2,23,2,62,3,0,2,0,131135,2,95,0,70256639,0,71303167,0,272,2,40,2,56,-1,2,37,2,30,-1,2,96,2,63,0,4278255616,0,4294836227,0,4294549473,0,600178175,0,2952806400,0,268632067,0,4294543328,0,57540095,0,1577058304,0,1835008,0,4294688736,2,65,2,64,0,33554435,2,123,2,65,2,151,0,131075,0,3594373096,0,67094296,2,64,-1,0,4294828000,0,603979263,2,160,0,3,0,4294828001,0,602930687,2,183,0,393219,0,4294828016,0,671088639,0,2154840064,0,4227858435,0,4236247008,2,66,2,36,-1,2,4,0,917503,2,36,-1,2,67,0,537788335,0,4026531935,-1,0,1,-1,2,32,2,68,0,7936,-3,2,0,0,2147485695,0,1010761728,0,4292984930,0,16387,2,0,2,14,2,15,3,0,10,2,69,2,0,2,70,2,71,2,72,2,0,2,73,2,0,2,11,-1,2,23,3,0,2,2,12,2,4,3,0,18,2,74,2,5,3,0,2,2,75,0,253951,3,19,2,0,122879,2,0,2,8,0,276824064,-2,3,0,2,2,40,2,0,0,4294903295,2,0,2,29,2,7,-1,2,17,2,49,2,0,2,76,2,41,-1,2,20,2,0,2,27,-2,0,128,-2,2,77,2,8,0,4064,-1,2,119,0,4227907585,2,0,2,118,2,0,2,48,2,173,2,9,2,38,2,10,-1,0,74440192,3,0,6,-2,3,0,8,2,12,2,0,2,78,2,9,2,0,2,79,2,80,2,81,-3,2,82,2,13,-3,2,83,2,84,2,85,2,0,2,33,-83,2,0,2,53,2,7,3,0,4,0,817183,2,0,2,14,2,0,0,33023,2,20,3,86,2,-17,2,87,0,524157950,2,4,2,0,2,88,2,4,2,0,2,15,2,77,2,16,3,0,2,2,47,2,0,-1,2,17,-16,3,0,206,-2,3,0,655,2,18,3,0,36,2,68,-1,2,17,2,9,3,0,8,2,89,0,3072,2,0,0,2147516415,2,9,3,0,2,2,23,2,90,2,91,3,0,2,2,92,2,0,2,93,2,94,0,4294965179,0,7,2,0,2,8,2,91,2,8,-1,0,1761345536,2,95,0,4294901823,2,36,2,18,2,96,2,34,2,166,0,2080440287,2,0,2,33,2,143,0,3296722943,2,0,0,1046675455,0,939524101,0,1837055,2,97,2,98,2,15,2,21,3,0,3,0,7,3,0,349,2,99,2,100,2,6,-264,3,0,11,2,22,3,0,2,2,31,-1,0,2700607615,2,101,2,102,3,0,2,2,19,2,103,3,0,10,2,9,2,17,2,0,2,45,2,0,2,30,2,104,-3,2,105,3,0,3,2,18,-1,3,5,2,2,26,2,0,2,7,2,106,-1,2,107,2,108,2,109,-1,3,0,3,2,11,-2,2,0,2,27,-8,2,18,2,0,2,35,-1,2,0,2,62,2,28,2,29,2,9,2,0,2,110,-1,3,0,4,2,9,2,17,2,111,2,6,2,0,2,112,2,0,2,48,-4,3,0,9,2,20,2,29,2,30,-4,2,113,2,114,2,29,2,20,2,7,-2,2,115,2,29,2,31,-2,2,0,2,116,-2,0,4277075969,2,29,-1,3,18,2,-1,2,32,2,117,2,0,3,29,2,2,34,2,19,-3,3,0,2,2,33,-1,2,0,2,34,2,0,2,34,2,0,2,48,-10,2,0,0,197631,-2,2,18,2,43,2,118,-2,2,17,2,117,2,20,2,119,2,51,-2,2,119,2,23,2,17,2,33,2,119,2,36,0,4294901904,0,4718591,2,119,2,34,0,335544350,-1,2,120,2,121,-2,2,122,2,38,2,7,-1,2,123,2,65,0,3758161920,0,3,-4,2,0,2,27,0,2147485568,0,3,2,0,2,23,0,176,-5,2,0,2,47,2,186,-1,2,0,2,23,2,197,-1,2,0,0,16779263,-2,2,11,-7,2,0,2,121,-3,3,0,2,2,124,2,125,0,2147549183,0,2,-2,2,126,2,35,0,10,0,4294965249,0,67633151,0,4026597376,2,0,0,536871935,-1,2,0,2,40,-8,2,54,2,47,0,1,2,127,2,23,-3,2,128,2,35,2,129,2,130,0,16778239,-10,2,34,-5,2,64,-2,3,0,28,2,31,-3,3,0,3,2,47,3,0,6,2,48,-85,3,0,33,2,47,-126,3,0,18,2,36,-269,3,0,17,2,40,2,7,-3,2,17,2,131,2,0,2,23,2,48,2,132,2,23,-21,3,0,2,-4,3,0,2,0,67583,-1,2,103,-2,0,11,3,0,191,2,51,3,0,38,2,29,-1,2,33,-279,3,0,8,2,7,-1,2,133,2,52,3,0,11,2,6,-72,3,0,3,2,134,2,135,-187,3,0,2,2,37,2,0,2,136,2,137,2,55,2,0,2,138,2,139,2,140,3,0,10,2,141,2,142,2,15,3,37,2,3,53,2,3,54,2,2,143,-73,2,0,0,1065361407,0,16384,-11,2,0,2,121,-40,3,0,6,2,117,-1,3,0,2,0,2063,-37,2,55,2,144,2,145,2,146,2,147,2,148,-138,3,0,1334,2,9,-1,3,0,129,2,27,3,0,6,2,9,3,0,180,2,149,3,0,233,0,1,-96,3,0,16,2,9,-47,3,0,154,2,56,-28517,2,0,0,1,-1,2,124,2,0,0,8193,-21,2,193,0,10255,0,4,-11,2,64,2,171,-1,0,71680,-1,2,161,0,4292900864,0,805306431,-5,2,150,-1,2,157,-1,0,6144,-2,2,127,-1,2,154,-1,0,2147532800,2,151,2,165,2,0,2,164,0,524032,0,4,-4,2,190,0,205128192,0,1333757536,0,2147483696,0,423953,0,747766272,0,2717763192,0,4286578751,0,278545,2,152,0,4294886464,0,33292336,0,417809,2,152,0,1327482464,0,4278190128,0,700594195,0,1006647527,0,4286497336,0,4160749631,2,153,0,469762560,0,4171219488,0,8323120,2,153,0,202375680,0,3214918176,0,4294508592,2,153,-1,0,983584,0,48,0,58720273,0,3489923072,0,10517376,0,4293066815,0,1,0,2013265920,2,177,2,0,0,2089,0,3221225552,0,201375904,2,0,-2,0,256,0,122880,0,16777216,2,150,0,4160757760,2,0,-6,2,167,-11,0,3263218176,-1,0,49664,0,2160197632,0,8388802,-1,0,12713984,-1,2,154,2,159,2,178,-2,2,162,-20,0,3758096385,-2,2,155,0,4292878336,2,90,2,169,0,4294057984,-2,2,163,2,156,2,175,-2,2,155,-1,2,182,-1,2,170,2,124,0,4026593280,0,14,0,4292919296,-1,2,158,0,939588608,-1,0,805306368,-1,2,124,0,1610612736,2,156,2,157,2,4,2,0,-2,2,158,2,159,-3,0,267386880,-1,2,160,0,7168,-1,0,65024,2,154,2,161,2,179,-7,2,168,-8,2,162,-1,0,1426112704,2,163,-1,2,164,0,271581216,0,2149777408,2,23,2,161,2,124,0,851967,2,180,-1,2,23,2,181,-4,2,158,-20,2,195,2,165,-56,0,3145728,2,185,-4,2,166,2,124,-4,0,32505856,-1,2,167,-1,0,2147385088,2,90,1,2155905152,2,-3,2,103,2,0,2,168,-2,2,169,-6,2,170,0,4026597375,0,1,-1,0,1,-1,2,171,-3,2,117,2,64,-2,2,166,-2,2,176,2,124,-878,2,159,-36,2,172,-1,2,201,-10,2,188,-5,2,174,-6,0,4294965251,2,27,-1,2,173,-1,2,174,-2,0,4227874752,-3,0,2146435072,2,159,-2,0,1006649344,2,124,-1,2,90,0,201375744,-3,0,134217720,2,90,0,4286677377,0,32896,-1,2,158,-3,2,175,-349,2,176,0,1920,2,177,3,0,264,-11,2,157,-2,2,178,2,0,0,520617856,0,2692743168,0,36,-3,0,524284,-11,2,23,-1,2,187,-1,2,184,0,3221291007,2,178,-1,2,202,0,2158720,-3,2,159,0,1,-4,2,124,0,3808625411,0,3489628288,2,200,0,1207959680,0,3221274624,2,0,-3,2,179,0,120,0,7340032,-2,2,180,2,4,2,23,2,163,3,0,4,2,159,-1,2,181,2,177,-1,0,8176,2,182,2,179,2,183,-1,0,4290773232,2,0,-4,2,163,2,189,0,15728640,2,177,-1,2,161,-1,0,4294934512,3,0,4,-9,2,90,2,170,2,184,3,0,4,0,704,0,1849688064,2,185,-1,2,124,0,4294901887,2,0,0,130547712,0,1879048192,2,199,3,0,2,-1,2,186,2,187,-1,0,17829776,0,2025848832,0,4261477888,-2,2,0,-1,0,4286580608,-1,0,29360128,2,192,0,16252928,0,3791388672,2,38,3,0,2,-2,2,196,2,0,-1,2,103,-1,0,66584576,-1,2,191,3,0,9,2,124,-1,0,4294755328,3,0,2,-1,2,161,2,178,3,0,2,2,23,2,188,2,90,-2,0,245760,0,2147418112,-1,2,150,2,203,0,4227923456,-1,2,164,2,161,2,90,-3,0,4292870145,0,262144,2,124,3,0,2,0,1073758848,2,189,-1,0,4227921920,2,190,0,68289024,0,528402016,0,4292927536,3,0,4,-2,0,268435456,2,91,-2,2,191,3,0,5,-1,2,192,2,163,2,0,-2,0,4227923936,2,62,-1,2,155,2,95,2,0,2,154,2,158,3,0,6,-1,2,177,3,0,3,-2,0,2146959360,0,9440640,0,104857600,0,4227923840,3,0,2,0,768,2,193,2,77,-2,2,161,-2,2,119,-1,2,155,3,0,8,0,512,0,8388608,2,194,2,172,2,187,0,4286578944,3,0,2,0,1152,0,1266679808,2,191,0,576,0,4261707776,2,95,3,0,9,2,155,3,0,5,2,16,-1,0,2147221504,-28,2,178,3,0,3,-3,0,4292902912,-6,2,96,3,0,85,-33,0,4294934528,3,0,126,-18,2,195,3,0,269,-17,2,155,2,124,2,198,3,0,2,2,23,0,4290822144,-2,0,67174336,0,520093700,2,17,3,0,21,-2,2,179,3,0,3,-2,0,30720,-1,0,32512,3,0,2,0,4294770656,-191,2,174,-38,2,170,2,0,2,196,3,0,279,-8,2,124,2,0,0,4294508543,0,65295,-11,2,177,3,0,72,-3,0,3758159872,0,201391616,3,0,155,-7,2,170,-1,0,384,-1,0,133693440,-3,2,196,-2,2,26,3,0,4,2,169,-2,2,90,2,155,3,0,4,-2,2,164,-1,2,150,0,335552923,2,197,-1,0,538974272,0,2214592512,0,132000,-10,0,192,-8,0,12288,-21,0,134213632,0,4294901761,3,0,42,0,100663424,0,4294965284,3,0,6,-1,0,3221282816,2,198,3,0,11,-1,2,199,3,0,40,-6,0,4286578784,2,0,-2,0,1006694400,3,0,24,2,35,-1,2,94,3,0,2,0,1,2,163,3,0,6,2,197,0,4110942569,0,1432950139,0,2701658217,0,4026532864,0,4026532881,2,0,2,45,3,0,8,-1,2,158,-2,2,169,0,98304,0,65537,2,170,-5,0,4294950912,2,0,2,118,0,65528,2,177,0,4294770176,2,26,3,0,4,-30,2,174,0,3758153728,-3,2,169,-2,2,155,2,188,2,158,-1,2,191,-1,2,161,0,4294754304,3,0,2,-3,0,33554432,-2,2,200,-3,2,169,0,4175478784,2,201,0,4286643712,0,4286644216,2,0,-4,2,202,-1,2,165,0,4227923967,3,0,32,-1334,2,163,2,0,-129,2,94,-6,2,163,-180,2,203,-233,2,4,3,0,96,-16,2,163,3,0,47,-154,2,165,3,0,22381,-7,2,17,3,0,6128], + [4294967295,4294967291,4092460543,4294828031,4294967294,134217726,268435455,2147483647,1048575,1073741823,3892314111,134217727,1061158911,536805376,4294910143,4160749567,4294901759,4294901760,536870911,262143,8388607,4294902783,4294918143,65535,67043328,2281701374,4294967232,2097151,4294903807,4194303,255,67108863,4294967039,511,524287,131071,127,4292870143,4294902271,4294549487,33554431,1023,67047423,4294901888,4286578687,4294770687,67043583,32767,15,2047999,67043343,16777215,4294902000,4294934527,4294966783,4294967279,2047,262083,20511,4290772991,41943039,493567,4294959104,603979775,65536,602799615,805044223,4294965206,8191,1031749119,4294917631,2134769663,4286578493,4282253311,4294942719,33540095,4294905855,4294967264,2868854591,1608515583,265232348,534519807,2147614720,1060109444,4093640016,17376,2139062143,224,4169138175,4294909951,4286578688,4294967292,4294965759,2044,4292870144,4294966272,4294967280,8289918,4294934399,4294901775,4294965375,1602223615,4294967259,4294443008,268369920,4292804608,486341884,4294963199,3087007615,1073692671,4128527,4279238655,4294902015,4294966591,2445279231,3670015,3238002687,31,63,4294967288,4294705151,4095,3221208447,4294549472,2147483648,4285526655,4294966527,4294705152,4294966143,64,4294966719,16383,3774873592,458752,536807423,67043839,3758096383,3959414372,3755993023,2080374783,4294835295,4294967103,4160749565,4087,184024726,2862017156,1593309078,268434431,268434414,4294901763,536870912,2952790016,202506752,139264,402653184,4261412864,4227922944,49152,61440,3758096384,117440512,65280,3233808384,3221225472,2097152,4294965248,32768,57152,67108864,4293918720,4290772992,25165824,57344,4227915776,4278190080,4227907584,65520,4026531840,4227858432,4160749568,3758129152,4294836224,63488,1073741824,4294967040,4194304,251658240,196608,4294963200,64512,417808,4227923712,12582912,50331648,65472,4294967168,4294966784,16,4294917120,2080374784,4096,65408,524288,65532] +) +export {isIDContinue,isIDStart,mustEscape}; |