aurelia-router-metadata
Version:
Adds decorator configuration with conventions and eager loading capabilities to aurelia-router
8,518 lines • 343 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var aureliaPal = require('aurelia-pal');
var aureliaDependencyInjection = require('aurelia-dependency-injection');
var aureliaRouter = require('aurelia-router');
var aureliaLogging = require('aurelia-logging');
var aureliaLoader = require('aurelia-loader');
// tslint:disable:max-classes-per-file
class $Application {
constructor() {
this._modules = [];
this._exports = [];
}
get $modules() {
return this._modules;
}
get $exports() {
return this._exports;
}
addModule($module) {
this.$modules.push($module);
this.$exports.push(...$module.$exports);
}
}
class $Module {
constructor(application, moduleId, raw) {
this._exports = [];
this._defaultExport = null;
this._application = application;
this._moduleId = moduleId;
this._raw = raw;
}
get $application() {
return this._application;
}
get moduleId() {
return this._moduleId;
}
get raw() {
return this._raw;
}
get $exports() {
return this._exports;
}
get $defaultExport() {
return this._defaultExport;
}
set $defaultExport(value) {
if (this._defaultExport !== null) {
throw new Error("defaultExport can only be set once");
}
this._defaultExport = value;
}
addExport($export) {
this.$exports.push($export);
}
}
class $Export {
constructor($module, name) {
this._constructor = null;
this._prototype = null;
this._module = $module;
this._name = name;
}
get $application() {
return this.$module.$application;
}
get moduleId() {
return this.$module.moduleId;
}
get exportPath() {
return `${this.$module.moduleId}::${this.name}`;
}
get $module() {
return this._module;
}
get name() {
return this._name;
}
get $constructor() {
return this._constructor;
}
set $constructor(value) {
if (this._constructor !== null) {
throw new Error("constructor can only be set once");
}
this._constructor = value;
}
get $prototype() {
return this._prototype;
}
set $prototype(value) {
if (this._prototype !== null) {
throw new Error("prototype can only be set once");
}
this._prototype = value;
}
get hasBase() {
return this.$constructor.hasBase;
}
get $base() {
return (this.$constructor.$base && this.$constructor.$base.$export) || null;
}
}
class $Constructor {
constructor($export, name, raw) {
this._properties = [];
this._base = null;
this._export = $export;
this._name = name;
this._raw = raw;
this._hasBase = Object.getPrototypeOf(raw) !== Function.prototype;
}
get $application() {
return this.$export.$application;
}
get moduleId() {
return this.$export.moduleId;
}
get exportPath() {
return this.$export.exportPath;
}
get $module() {
return this.$export.$module;
}
get $export() {
return this._export;
}
get name() {
return this._name;
}
get $properties() {
return this._properties;
}
get raw() {
return this._raw;
}
get hasBase() {
return this._hasBase;
}
get $base() {
return this._base;
}
set $base(value) {
if (this._base !== null) {
throw new Error("base can only be set once");
}
this._base = value;
}
addProperty($property) {
this.$properties.push($property);
}
}
class $Prototype {
constructor($export, name, raw) {
this._properties = [];
this._base = null;
this._export = $export;
this._name = name;
this._raw = raw;
this._hasBase = Object.getPrototypeOf(raw) !== Object.prototype;
}
get $application() {
return this.$export.$application;
}
get moduleId() {
return this.$export.moduleId;
}
get exportPath() {
return this.$export.exportPath;
}
get $module() {
return this.$export.$module;
}
get $export() {
return this._export;
}
get name() {
return this._name;
}
get $properties() {
return this._properties;
}
get raw() {
return this._raw;
}
get hasBase() {
return this._hasBase;
}
get $base() {
return this._base;
}
set $base(value) {
if (this._base !== null) {
throw new Error("base can only be set once");
}
this._base = value;
}
addProperty($property) {
this.$properties.push($property);
}
}
class $Property {
get $application() {
return this.$object.$application;
}
get moduleId() {
return this.$object.moduleId;
}
get $module() {
return this.$object.$module;
}
get $export() {
return this.$object.$export;
}
get $object() {
return this._object;
}
get descriptor() {
return this._descriptor;
}
get key() {
return this._key;
}
get isStatic() {
return this._isStatic;
}
constructor($object, key, descriptor) {
this._object = $object;
this._key = key;
this._isStatic = $object instanceof $Constructor;
this._descriptor = descriptor;
}
}
function allObjectKeys(obj) {
const names = Object.getOwnPropertyNames(obj);
const symbols = Object.getOwnPropertySymbols(obj);
return names.concat(symbols);
}
function ensureArray(value) {
if (value === null || value === undefined) {
return [];
}
return Array.isArray(value) ? value : [value];
}
function splitRouteConfig(configs) {
if (configs.length === 0) {
return configs;
}
const result = [];
for (const config of configs) {
if (Object.prototype.hasOwnProperty.call(config, "route")) {
if (/String/.test(Object.prototype.toString.call(config.route))) {
result.push([config]);
}
else if (Array.isArray(config.route)) {
if (config.route.length === 0) {
delete config.route;
result.push([config]);
}
else {
result.push(config.route.map(r => (Object.assign({}, config, { route: r }))));
}
}
else {
delete config.route;
result.push([config]);
}
}
else {
result.push([config]);
}
}
return result.reduce((prev, cur) => prev.concat(cur));
}
class Registry {
constructor() {
this.cache = Object.create(null);
this.moduleIds = new Set();
this.$application = new $Application();
}
getModule(normalizedId) {
let $module = this.cache[normalizedId];
if ($module === undefined) {
let moduleExport;
aureliaPal.PLATFORM.eachModule((moduleId, value) => {
if (moduleId === normalizedId) {
moduleExport = value;
return true;
}
else {
return false;
}
});
if (moduleExport !== undefined) {
$module = this.registerModule(moduleExport, normalizedId);
}
}
return $module;
}
registerModuleViaConstructor($constructor) {
let moduleInstance;
let moduleId;
aureliaPal.PLATFORM.eachModule((key, value) => {
if (typeof value === "object") {
for (const name of Object.keys(value)) {
if (value[name] === $constructor) {
moduleInstance = value;
moduleId = key;
return true;
}
}
}
if (value === $constructor) {
moduleInstance = value;
moduleId = key;
return true;
}
else {
return false;
}
});
if (!moduleInstance || !moduleId) {
throw new Error(`No module could be found for constructor ${$constructor}`);
}
return this.registerModule(moduleInstance, moduleId);
}
registerModule(moduleInstance, moduleId) {
this.moduleIds.add(moduleId);
const $module = (this.cache[moduleId] = new $Module(this.$application, moduleId, moduleInstance));
this.$application.addModule($module);
if (moduleInstance instanceof Function) {
this.registerModuleExport($module, "default", moduleInstance);
}
else {
for (const exportName of Object.keys(moduleInstance)) {
const exportValue = moduleInstance[exportName];
if (exportValue instanceof Function) {
this.registerModuleExport($module, exportName, exportValue);
}
}
}
return $module;
}
registerModuleExport($module, exportName, exportValue) {
if (!Object.prototype.hasOwnProperty.call(exportValue, "prototype")) {
return;
}
const $export = new $Export($module, exportName);
$export.$constructor = new $Constructor($export, exportName, exportValue);
$export.$prototype = new $Prototype($export, exportName, exportValue.prototype);
$module.addExport($export);
if ($module.$defaultExport === null) {
$module.$defaultExport = $export;
}
this.registerProperties($export.$constructor);
this.registerProperties($export.$prototype);
const ownNeedsBase = $export.hasBase && $export.$base === null;
const ownRaw = $export.$constructor.raw;
const ownBase = Object.getPrototypeOf(ownRaw);
for (const $other of this.$application.$exports) {
const otherNeedsBase = $other.hasBase && $other.$base === null;
const otherRaw = $other.$constructor.raw;
if (ownNeedsBase && ownBase === otherRaw) {
$export.$constructor.$base = $other.$constructor;
$export.$prototype.$base = $other.$prototype;
}
else if (otherNeedsBase) {
const otherBase = Object.getPrototypeOf(otherRaw);
if (otherBase === ownRaw) {
$other.$constructor.$base = $export.$constructor;
$other.$prototype.$base = $export.$prototype;
}
}
}
}
registerProperties($object) {
const obj = $object.raw;
for (const key of allObjectKeys(obj)) {
const descriptor = Object.getOwnPropertyDescriptor(obj, key);
const propertySymbol = new $Property($object, key, descriptor);
$object.addProperty(propertySymbol);
}
}
}
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
function __awaiter(thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
// Note: this *must* be kept in sync with the enum's order.
//
// It exploits the enum value ordering, and it's necessarily a complete and
// utter hack.
//
// All to lower it to a single monomorphic array access.
const keywordDescTable = [
'end of source',
/* Constants/Bindings */
'identifier', 'number', 'string', 'regular expression',
'false', 'true', 'null',
/* Template nodes */
'template continuation', 'template end',
/* 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',
'#',
'eval', 'arguments', 'enum', 'BigInt', '@', 'JSXText',
/** TS */
'KeyOf', 'ReadOnly', 'is', 'unique', 'declare', 'type', 'namespace', 'abstract', 'module'
];
/**
* The conversion function between token and its string description/representation.
*/
function tokenDesc(token) {
return keywordDescTable[token & 255 /* Type */];
}
// Used `Object.create(null)` to avoid potential `Object.prototype`
// interference.
const descKeywordTable = Object.create(null, {
this: { value: 33566815 /* ThisKeyword */ },
function: { value: 33566808 /* FunctionKeyword */ },
if: { value: 12377 /* IfKeyword */ },
return: { value: 12380 /* ReturnKeyword */ },
var: { value: 33566791 /* VarKeyword */ },
else: { value: 12370 /* ElseKeyword */ },
for: { value: 12374 /* ForKeyword */ },
new: { value: 33566811 /* NewKeyword */ },
in: { value: 168834865 /* InKeyword */ },
typeof: { value: 302002218 /* TypeofKeyword */ },
while: { value: 12402 /* WhileKeyword */ },
case: { value: 12363 /* CaseKeyword */ },
break: { value: 12362 /* BreakKeyword */ },
try: { value: 12385 /* TryKeyword */ },
catch: { value: 12364 /* CatchKeyword */ },
delete: { value: 302002219 /* DeleteKeyword */ },
throw: { value: 302002272 /* ThrowKeyword */ },
switch: { value: 33566814 /* SwitchKeyword */ },
continue: { value: 12366 /* ContinueKeyword */ },
default: { value: 12368 /* DefaultKeyword */ },
instanceof: { value: 167786290 /* InstanceofKeyword */ },
do: { value: 12369 /* DoKeyword */ },
void: { value: 302002220 /* VoidKeyword */ },
finally: { value: 12373 /* FinallyKeyword */ },
arguments: { value: 37814389 /* Arguments */ },
keyof: { value: 65658 /* KeyOfKeyword */ },
readonly: { value: 65659 /* ReadOnlyKeyword */ },
unique: { value: 65661 /* UniqueKeyword */ },
declare: { value: 65662 /* DeclareKeyword */ },
async: { value: 299116 /* AsyncKeyword */ },
await: { value: 33788013 /* AwaitKeyword */ },
class: { value: 33566797 /* ClassKeyword */ },
const: { value: 33566793 /* ConstKeyword */ },
constructor: { value: 36974 /* ConstructorKeyword */ },
debugger: { value: 12367 /* DebuggerKeyword */ },
enum: { value: 12406 /* EnumKeyword */ },
eval: { value: 37814388 /* Eval */ },
export: { value: 12371 /* ExportKeyword */ },
extends: { value: 12372 /* ExtendsKeyword */ },
false: { value: 33566725 /* FalseKeyword */ },
from: { value: 36977 /* FromKeyword */ },
get: { value: 36975 /* GetKeyword */ },
implements: { value: 20579 /* ImplementsKeyword */ },
import: { value: 33566810 /* ImportKeyword */ },
interface: { value: 20580 /* InterfaceKeyword */ },
let: { value: 33574984 /* LetKeyword */ },
null: { value: 33566727 /* NullKeyword */ },
of: { value: 1085554 /* OfKeyword */ },
package: { value: 20581 /* PackageKeyword */ },
private: { value: 20582 /* PrivateKeyword */ },
protected: { value: 20583 /* ProtectedKeyword */ },
public: { value: 20584 /* PublicKeyword */ },
set: { value: 36976 /* SetKeyword */ },
static: { value: 20585 /* StaticKeyword */ },
super: { value: 33566813 /* SuperKeyword */ },
true: { value: 33566726 /* TrueKeyword */ },
with: { value: 12387 /* WithKeyword */ },
yield: { value: 1107316842 /* YieldKeyword */ },
is: { value: 65660 /* IsKeyword */ },
type: { value: 65663 /* TypeKeyword */ },
namespace: { value: 65664 /* NameSpaceKeyword */ },
abstract: { value: 65665 /* AbstractKeyword */ },
as: { value: 36971 /* AsKeyword */ },
module: { value: 65666 /* ModuleKeyword */ },
});
function descKeyword(value) {
return (descKeywordTable[value] | 0);
}
/*@internal*/
const errorMessages = {
[0 /* Unexpected */]: 'Unexpected token',
[1 /* UnexpectedToken */]: 'Unexpected token \'%0\'',
[2 /* InvalidEscapedReservedWord */]: 'Keyword must not contain escaped characters',
[3 /* UnexpectedKeyword */]: 'Keyword \'%0\' is reserved',
[4 /* InvalidLHSInAssignment */]: 'Invalid left-hand side in assignment',
[5 /* UnterminatedString */]: 'Unterminated string literal',
[6 /* UnterminatedRegExp */]: 'Unterminated regular expression literal',
[7 /* UnterminatedComment */]: 'Unterminated MultiLineComment',
[8 /* UnterminatedTemplate */]: 'Unterminated template literal',
[9 /* UnexpectedChar */]: 'Invalid character \'%0\'',
[10 /* StrictOctalEscape */]: 'Octal escapes are not allowed in strict mode',
[11 /* InvalidEightAndNine */]: 'Escapes \\8 or \\9 are not syntactically valid escapes',
[12 /* UnicodeOutOfRange */]: 'Unicode escape code point out of range',
[13 /* DuplicateRegExpFlag */]: 'Duplicate regular expression flag \'%0\'',
[14 /* UnexpectedTokenRegExpFlag */]: 'Unexpected regular expression flag \'%0\'',
[15 /* StrictLHSAssignment */]: 'Eval or arguments can\'t be assigned to in strict mode code',
[16 /* IllegalReturn */]: 'Illegal return statement',
[17 /* StrictFunction */]: 'In strict mode code, functions can only be declared at top level or inside a block',
[18 /* 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',
[19 /* ForbiddenAsStatement */]: '%0 can\'t appear in single-statement context',
[20 /* GeneratorInSingleStatementContext */]: 'Generators can only be declared at the top level or inside a block',
[21 /* ForAwaitNotOf */]: '\'for await\' loop should be used with \'of\'',
[22 /* DeclarationMissingInitializer */]: 'Missing initializer in %0 declaration',
[23 /* ForInOfLoopInitializer */]: '\'for-%0\' loop variable declaration may not have an initializer',
[24 /* ForInOfLoopMultiBindings */]: 'Invalid left-hand side in for-%0 loop: Must have a single binding.',
[25 /* LetInLexicalBinding */]: 'let is disallowed as a lexically bound name',
[26 /* UnexpectedLexicalDeclaration */]: 'Lexical declaration cannot appear in a single-statement context',
[27 /* LabelRedeclaration */]: 'Label \'%0\' has already been declared',
[28 /* InvalidNestedStatement */]: '%0 statement must be nested within an iteration statement',
[29 /* IllegalContinue */]: 'Illegal continue statement: \'%0\' does not denote an iteration statement',
[30 /* UnknownLabel */]: 'Undefined label \'%0\'',
[31 /* MultipleDefaultsInSwitch */]: 'More than one default clause in switch statement',
[32 /* ImportExportDeclAtTopLevel */]: '%0 declarations may only appear at top level of a module',
[33 /* AsyncFunctionInSingleStatementContext */]: 'Async functions can only be declared at the top level or inside a block',
[34 /* InvalidLineBreak */]: 'No line break is allowed after \'%0\'',
[35 /* StrictModeWith */]: 'Strict mode code may not include a with statement',
[36 /* AwaitOutsideAsync */]: 'Await is only valid in async functions',
[37 /* UnNamedFunctionDecl */]: 'Function declaration must have a name in this context',
[38 /* DisallowedInContext */]: '\'%0\' may not be used as an identifier in this context',
[41 /* StrictDelete */]: 'Delete of an unqualified identifier in strict mode',
[42 /* DeletePrivateField */]: 'Private fields can not be deleted',
[39 /* PrivateFieldConstructor */]: 'Classes may not have a private field named \'#constructor\'',
[40 /* PublicFieldConstructor */]: 'Classes may not have a field named \'constructor\'',
[43 /* InvalidConstructor */]: 'Class constructor may not be a \'%0\'',
[44 /* UnexpectedReserved */]: 'Unexpected reserved word',
[45 /* StrictEvalArguments */]: 'Unexpected eval or arguments in strict mode',
[46 /* AwaitBindingIdentifier */]: '\'await\' is not a valid identifier inside an async function',
[47 /* YieldBindingIdentifier */]: '\'yield\' is not a valid identifier inside an generator function',
[48 /* UnexpectedStrictReserved */]: 'Unexpected strict mode reserved word',
[50 /* AwaitInParameter */]: 'Await expression not allowed in formal parameter',
[49 /* YieldInParameter */]: 'Yield expression not allowed in formal parameter',
[51 /* MetaNotInFunctionBody */]: 'new.target only allowed within functions',
[52 /* BadSuperCall */]: 'super() is not allowed in this context',
[53 /* UnexpectedSuper */]: 'Member access from super not allowed in this context',
[54 /* LoneSuper */]: 'Only "(" or "." or "[" are allowed after \'super\'',
[55 /* YieldReservedKeyword */]: '\'yield\' is a reserved keyword within generator function bodies',
[56 /* ContinuousNumericSeparator */]: 'Only one underscore is allowed as numeric separator',
[57 /* TrailingNumericSeparator */]: 'Numeric separators are not allowed at the end of numeric literals',
[58 /* ZeroDigitNumericSeparator */]: 'Numeric separator can not be used after leading 0.',
[59 /* StrictOctalLiteral */]: 'Legacy octal literals are not allowed in strict mode',
[60 /* InvalidLhsInAssignment */]: 'Invalid left-hand side in assignment',
[61 /* DuplicateProto */]: 'Property name __proto__ appears more than once in object literal',
[62 /* IllegalUseStrict */]: 'Illegal \'use strict\' directive in function with non-simple parameter list',
[63 /* StaticPrototype */]: 'Classes may not have a static property named \'prototype\'',
[64 /* AccessorWrongArgs */]: '%0 functions must have %1 argument%2',
[65 /* BadSetterRestParameter */]: 'Setter function argument must not be a rest parameter',
[66 /* StrictLHSPrefixPostFix */]: '%0 increment/decrement may not have eval or arguments operand in strict mode',
[67 /* InvalidElisonInObjPropList */]: 'Elision not allowed in object property list',
[68 /* ElementAfterRest */]: 'Rest element must be last element',
[70 /* ElementAfterSpread */]: 'Spread element must be last element',
[69 /* RestDefaultInitializer */]: 'Rest parameter may not have a default initializer',
[71 /* InvalidDestructuringTarget */]: 'Invalid destructuring assignment target',
[72 /* UnexpectedSurrogate */]: 'Unexpected surrogate pair',
[73 /* MalformedEscape */]: 'Malformed %0 character escape sequence',
[74 /* TemplateOctalLiteral */]: 'Template literals may not contain octal escape sequences',
[75 /* NotBindable */]: 'Invalid binding pattern',
[76 /* ParamAfterRest */]: 'Rest parameter must be last formal parameter',
[77 /* NoCatchOrFinally */]: 'Missing catch or finally after try',
[78 /* NewlineAfterThrow */]: 'Illegal newline after throw',
[79 /* ParamDupe */]: 'Duplicate parameter name not allowed in this context',
[80 /* AsAfterImportStart */]: 'Missing keyword \'as\' after import *',
[81 /* LabelNoColon */]: 'Labels must be followed by a \':\'',
[82 /* NonEmptyJSXExpression */]: 'JSX attributes must only be assigned a non-empty \'expression\'',
[83 /* ExpectedJSXClosingTag */]: 'Expected corresponding JSX closing tag for %0',
[84 /* AdjacentJSXElements */]: 'Adjacent JSX elements must be wrapped in an enclosing tag',
[85 /* InvalidJSXAttributeValue */]: 'Invalid JSX attribute value',
[86 /* RestWithComma */]: 'Rest element may not have a trailing comma',
[87 /* UndefinedUnicodeCodePoint */]: 'Undefined Unicode code-point',
[88 /* HtmlCommentInModule */]: 'HTML comments are not allowed in modules',
[89 /* InvalidCoverInitializedName */]: 'Invalid shorthand property initializer',
[90 /* TrailingDecorators */]: 'Trailing decorator may be followed by method',
[91 /* GeneratorConstructor */]: 'Decorators can\'t be used with a constructor',
[92 /* InvalidRestBindingPattern */]: '`...` must be followed by an identifier in declaration contexts',
};
/**
* Collect line, index, and colum from either the recorded error
* or directly from the parser and returns it
*
* @param parser Parser instance
* @param context Context masks
* @param index The 0-based end index of the error.
* @param line The 0-based line position of the error.
* @param column The 0-based column position of the error.
* @param parser The 0-based end index of the current node.
* @param description Error description
*/
function constructError(parser, context, index, line, column, description) {
const error = new SyntaxError(`Line ${line}, column ${column}: ${description}`);
error.index = index;
error.line = line;
error.column = column;
error.description = description;
if (context & 512 /* OptionsTolerant */) {
parser.errors.push(error);
}
else
throw error;
}
/**
* Collect line, index, and colum from either the recorded error
* or directly from the parser and returns it
*
* @param parser Parser instance
*/
function getErrorLocation(parser) {
let { index, startLine: line, startColumn: column } = parser;
const errorLoc = parser.errorLocation;
if (!!errorLoc) {
index = errorLoc.index;
line = errorLoc.line;
column = errorLoc.column;
}
return { index, line, column };
}
/**
* Throws an error
*
* @param parser Parser instance
* @param context Context masks
* @param type Error type
* @param params Error params
*/
function report(parser, type, ...params) {
const { index, line, column } = getErrorLocation(parser);
const errorMessage = errorMessages[type].replace(/%(\d+)/g, (_, i) => params[i]);
constructError(parser, 0 /* Empty */, index, line, column, errorMessage);
}
/**
* If in tolerant mode, all errors are pushed to a top-level error array containing
* otherwise throws
*
* @param parser Parser instance
* @param context Context masks
* @param type Error type
* @param params Error params
*/
function tolerant(parser, context, type, ...params) {
const { index, line, column } = getErrorLocation(parser);
const errorMessage = errorMessages[type].replace(/%(\d+)/g, (_, i) => params[i]);
constructError(parser, context, index, line, column, errorMessage);
}
/*@internal*/
const characterType = [
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
16 /* Space */,
48 /* Whitespace */,
16 /* Space */,
16 /* Space */,
48 /* Whitespace */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
16 /* Space */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
3 /* Letters */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
9 /* Decimals */,
9 /* Decimals */,
9 /* Decimals */,
9 /* Decimals */,
9 /* Decimals */,
9 /* Decimals */,
9 /* Decimals */,
9 /* Decimals */,
9 /* Decimals */,
9 /* Decimals */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
7 /* Hexadecimal */,
7 /* Hexadecimal */,
7 /* Hexadecimal */,
7 /* Hexadecimal */,
7 /* Hexadecimal */,
7 /* Hexadecimal */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
3 /* Letters */,
0 /* Unknown */,
7 /* Hexadecimal */,
7 /* Hexadecimal */,
7 /* Hexadecimal */,
7 /* Hexadecimal */,
7 /* Hexadecimal */,
7 /* Hexadecimal */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
3 /* Letters */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
0 /* Unknown */,
];
// Unicode v. 10 support
// tslint:disable
function isValidIdentifierPart(code) {
return (convert[(code >>> 5) + 0] >>> code & 31 & 1) !== 0;
}
function isValidIdentifierStart(code) {
return (convert[(code >>> 5) + 34816] >>> code & 31 & 1) !== 0;
}
function mustEscape(code) {
return (convert[(code >>> 5) + 69632] >>> code & 31 & 1) !== 0;
}
const convert = ((compressed, lookup) => {
const result = new Uint32Array(104448);
let index = 0;
let subIndex = 0;
while (index < 3293) {
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, 28, 2, 29, 2, 5, -1, 0, 77595648, 3, 41, 2, 3, 0, 14, 2, 52, 2, 53, 3, 0, 3, 0, 3168796671, 0, 4294956992, 2, 1, 2, 0, 2, 54, 3, 0, 4, 0, 4294966523, 3, 0, 4, 2, 55, 2, 56, 2, 4, 0, 4294836479, 0, 3221225471, 0, 4294901942, 2, 57, 0, 134152192, 3, 0, 2, 0, 4294951935, 3, 0, 2, 0, 2683305983, 0, 2684354047, 2, 17, 2, 0, 0, 4294961151, 3, 0, 2, 2, 20, 2, 0, 2, 59, 2, 0, 2, 125, 2, 6, 2, 19, -1, 2, 60, 2, 148, 2, 1, 3, 0, 3, 0, 4294901711, 2, 37, 0, 4089839103, 0, 2961209759, 0, 268697551, 0, 4294543342, 0, 3547201023, 0, 1577204103, 0, 4194240, 0, 4294688750, 2, 2, 0, 80831, 0, 4261478351, 0, 4294549486, 2, 2, 0, 2965387679, 0, 196559, 0, 3594373100, 0, 3288319768, 0, 8469959, 2, 167, 2, 3, 0, 3825204735, 0, 123747807, 0, 65487, 2, 3, 0, 4092591615, 0, 1080049119, 0, 458703, 2, 3, 2, 0, 0, 2163244511, 0, 4227923919, 0, 4236247020, 2, 64, 0, 4284449919, 0, 851904, 2, 4, 2, 16, 0, 67076095, -1, 2, 65, 0, 1006628014, 0, 4093591391, -1, 0, 50331649, 0, 3265266687, 2, 34, 0, 4294844415, 0, 4278190047, 2, 22, 2, 124, -1, 3, 0, 2, 2, 33, 2, 0, 2, 10, 2, 0, 2, 14, 2, 15, 3, 0, 10, 2, 66, 2, 0, 2, 67, 2, 68, 2, 69, 2, 0, 2, 70, 2, 0, 0, 3892314111, 0, 261632, 2, 27, 3, 0, 2, 2, 11, 2, 4, 3, 0, 18, 2, 71, 2, 5, 3, 0, 2, 2, 72, 0, 2088959, 2, 31, 2, 8, 0, 909311, 3, 0, 2, 0, 814743551, 2, 39, 0, 67057664, 3, 0, 2, 2, 9, 2, 0, 2, 32, 2, 0, 2, 18, 2, 7, 0, 268374015, 2, 30, 2, 46, 2, 0, 2, 73, 0, 134153215, -1, 2, 6, 2, 0, 2, 7, 0, 2684354559, 0, 67044351, 0, 1073676416, -2, 3, 0, 2, 2, 40, 0, 1046528, 3, 0, 3, 2, 8, 2, 0, 2, 9, 0, 4294960127, 2, 10, 2, 13, -1, 0, 4294377472, 2, 25, 3, 0, 7, 0, 4227858431, 3, 0, 8, 2, 11, 2, 0, 2, 75, 2, 10, 2, 0, 2, 76, 2, 77, 2, 78, -1, 2, 121, 0, 1048577, 2, 79, 2, 12, -1, 2, 12, 0, 131042, 2, 80, 2, 81, 2, 82, 2, 0, 2, 13, -83, 2, 0, 2, 49, 2, 7, 3, 0, 4, 0, 1046559, 2, 0, 2, 14, 2, 0, 0, 2147516671, 2, 23, 3, 83, 2, 2, 0, -16, 2, 84, 0, 524222462, 2, 4, 2, 0, 0, 4269801471, 2, 4, 2, 0, 2, 15, 2, 74, 2, 86, 3, 0, 2, 2, 43, 2, 16, -1, 2, 17, -16, 3, 0, 205, 2, 18, -2, 3, 0, 655, 2, 19, 3, 0, 36, 2, 47, -1, 2, 17, 2, 10, 3, 0, 8, 2, 87, 2, 117, 2, 0, 0, 3220242431, 3, 0, 3, 2, 20, 2, 21, 2, 88, 3, 0, 2, 2, 89, 2, 90, -1, 2, 21, 2, 0, 2, 26, 2, 0, 2, 8, 3, 0, 2, 0, 67043391, 0, 687865855, 2, 0, 2, 24, 2, 8, 2, 22, 3, 0, 2, 0, 67076097, 2, 7, 2, 0, 2, 23, 0, 67059711, 0, 4236247039, 3, 0, 2, 0, 939524103, 0, 8191999, 2, 94, 2, 95, 2, 15, 2, 92, 3, 0, 3, 0, 67057663, 3, 0, 349, 2, 96, 2, 97, 2, 6, -264, 3, 0, 11, 2, 24, 3, 0, 2, 2, 25, -1, 0, 3774349439, 2, 98, 2, 99, 3, 0, 2, 2, 20, 2, 100, 3, 0, 10, 2, 10, 2, 17, 2, 0, 2, 42, 2, 0, 2, 26, 2, 101, 2, 27, 0, 1638399, 2, 165, 2, 102, 3, 0, 3, 2, 22, 2, 28, 2, 29, 2, 5, 2, 30, 2, 0, 2, 7, 2, 103, -1, 2, 104, 2, 105, 2, 106, -1, 3, 0, 3, 2, 16, -2, 2, 0, 2, 31, -3, 2, 144, -4, 2, 22, 2, 0, 2, 107, 0, 1, 2, 0, 2, 58, 2, 32, 2, 16, 2, 10, 2, 0, 2, 108, -1, 3, 0, 4, 2, 10, 2, 33, 2, 109, 2, 6, 2, 0, 2, 110, 2, 0, 2, 44, -4, 3, 0, 9, 2, 23, 2, 18, 2, 26, -4, 2, 111, 2, 112, 2, 18, 2, 23, 2, 7, -2, 2, 113, 2, 18, 2, 25, -2, 2, 0, 2, 114, -2, 0, 4277137519, 0, 2265972735, -1, 3, 22, 2, -1, 2, 34, 2, 36, 2, 0, 3, 18, 2, 2, 35, 2, 20, -3, 3, 0, 2, 2, 13, -1, 2, 0, 2, 35, 2, 0, 2, 35, -24, 3, 0, 2, 2, 36, 0, 2147549120, 2, 0, 2, 16, 2, 17, 2, 128, 2, 0, 2, 48, 2, 17, 0, 5242879, 3, 0, 2, 0, 402594847, -1, 2, 116, 0, 1090519039, -2, 2, 118, 2, 119, 2, 0, 2, 38, 2, 37, 2, 2, 0, 3766565279, 0, 2039759, -4, 3, 0, 2, 2, 38, -1, 3, 0, 2, 0, 67043519, -5, 2, 0, 0, 4282384383, 0, 1056964609, -1, 3, 0, 2, 0, 67043345, -1, 2, 0, 2, 9, 2, 39, -1, 0, 3825205247, 2, 40, -11, 3, 0, 2, 0, 2147484671, -8, 2, 0, 2, 7, 0, 4294901888, 2, 0, 0, 67108815, -1, 2, 0, 2, 45, -8, 2, 50, 2, 41, 0, 67043329, 2, 122, 2, 42, 0, 8388351, -2, 2, 123, 0, 3028287487, 0, 67043583, -21, 3, 0, 28, 2, 25, -3, 3, 0, 3, 2, 43, 3, 0, 6, 2, 44, -85, 3, 0, 33, 2, 43, -126, 3, 0, 18, 2, 36, -269, 3, 0, 17, 2, 45, 2, 7, 2, 39, -2, 2, 17, 2, 46, 2, 0, 2, 23, 0, 67043343, 2, 126, 2, 27, -27, 3, 0, 2, 0, 4294901791, 2, 7, 2, 187, -2, 0, 3, 3, 0, 191, 2, 47, 3, 0, 23, 2, 35, -296, 3, 0, 8, 2, 7, -2, 2, 17, 3, 0, 11, 2, 6, -72, 3, 0, 3, 2, 127, 0, 1677656575, -166, 0, 4161266656, 0, 4071, 0, 15360, -4, 0, 28, -13, 3, 0, 2, 2, 48, 2, 0, 2, 129, 2, 130, 2, 51, 2, 0, 2, 131, 2, 132, 2, 133, 3, 0, 10, 2, 134, 2, 135, 2, 15, 3, 48, 2, 3, 49, 2, 3, 50, 2, 0, 4294954999, 2, 0, -16, 2, 0, 2, 85, 2, 0, 0, 2105343, 0, 4160749584, 2, 194, -42, 0, 4194303871, 0, 2011, -62, 3, 0, 6, 0, 8323103, -1, 3, 0, 2, 2, 38, -37, 2, 51, 2, 138, 2, 139, 2, 140, 2, 141, 2, 142, -138, 3, 0, 1334, 2, 23, -1, 3, 0, 129, 2, 31, 3, 0, 6, 2, 10, 3, 0, 180, 2, 143, 3, 0, 233, 0, 1, -96, 3, 0, 16, 2, 10, -22583, 3, 0, 7, 2, 27, -6130, 3, 5, 2, -1, 0, 69207040, 3, 41, 2, 3, 0, 14, 2, 52, 2, 53, -3, 0, 3168731136, 0, 4294956864, 2, 1, 2, 0, 2, 54, 3, 0, 4, 0, 4294966275, 3, 0, 4, 2, 55, 2, 56, 2, 4, 2, 26, -1, 2, 17, 2, 57, -1, 2, 0, 2, 19, 0, 4294885376, 3, 0, 2, 0, 3145727, 0, 2617294944, 0, 4294770688, 2, 27, 2, 58, 3, 0, 2, 0, 131135, 2, 91, 0, 70256639, 2, 59, 0, 272, 2, 45, 2, 19, -1, 2, 60, -2, 2, 93, 0, 603979775, 0, 4278255616, 0, 4294836227, 0, 4294549473, 0, 600178175, 0, 2952806400, 0, 268632067, 0, 4294543328, 0, 57540095, 0, 1577058304, 0, 1835008, 0, 4294688736, 2, 61, 2, 62, 0, 33554435, 2, 120, 2, 61, 2, 145, 0, 131075, 0, 3594373096, 0, 67094296, 2, 62, -1, 2, 63, 0, 603979263, 2, 153, 0, 3, 0, 4294828001, 0, 602930687, 2, 175, 0, 393219, 2, 63, 0, 671088639, 0, 2154840064, 0, 4227858435, 0, 4236247008, 2, 64, 2, 36, -1, 2, 4, 0, 917503, 2, 36, -1, 2, 65, 0, 537783470, 0, 4026531935, -1, 0, 1, -1, 2, 34, 2, 47, 0, 7936, -3, 2, 0, 0, 2147485695, 0, 1010761728, 0, 4292984930, 0, 16387, 2, 0, 2, 14, 2, 15, 3, 0, 10, 2, 66, 2, 0, 2, 67, 2, 68, 2, 69, 2, 0, 2, 70, 2, 0, 2, 16, -1, 2, 27, 3, 0, 2, 2, 11, 2, 4, 3, 0, 18, 2, 71, 2, 5, 3, 0, 2, 2, 72, 0, 253951, 3, 20, 2, 0, 122879, 2, 0, 2, 8, 0, 276824064, -2, 3, 0, 2, 2, 9, 2, 0, 0, 4294903295, 2, 0, 2, 18, 2, 7, -1, 2, 17, 2, 46, 2, 0, 2, 73, 2, 39, -1, 2, 23, 2, 0, 2, 31, -2, 0, 128, -2, 2, 74, 2, 8, 0, 4064, -1, 2, 115, 0, 4227907585, 2, 0, 2, 191, 2, 0, 2, 44, 0, 4227915776, 2, 10, 2, 13, -2, 0, 6544896, 3, 0, 6, -2, 3, 0, 8, 2, 11, 2, 0, 2, 75, 2, 10, 2, 0, 2, 76, 2, 77, 2, 78, -3, 2, 79, 2, 12, -3, 2, 80, 2, 81, 2, 82, 2, 0, 2, 13, -83, 2, 0, 2, 49, 2, 7, 3, 0, 4, 0, 817183, 2, 0, 2, 14, 2, 0, 0, 33023, 2, 23, 3, 83, 2, -17, 2, 84, 0, 524157950, 2, 4, 2, 0, 2, 85, 2, 4, 2, 0, 2, 15, 2, 74, 2, 86, 3, 0, 2, 2, 43, 2, 16, -1, 2, 17, -16, 3, 0, 205, 2, 18, -2, 3, 0, 655, 2, 19, 3, 0, 36, 2, 47, -1, 2, 17, 2, 10, 3, 0, 8, 2, 87, 0, 3072, 2, 0, 0, 2147516415, 2, 10, 3, 0, 2, 2, 27, 2, 21, 2, 88, 3, 0, 2, 2, 89, 2, 90, -1, 2, 21, 0, 4294965179, 0, 7, 2, 0, 2, 8, 2, 88, 2, 8, -1, 0, 687603712, 2, 91, 2, 92, 2, 36, 2, 22, 2, 93, 2, 35, 2, 159, 0, 2080440287, 2, 0, 2, 13, 2, 136, 0, 3296722943, 2, 0, 0, 1046675455, 0, 939524101, 0, 1837055, 2, 94, 2, 95, 2, 15, 2, 92, 3, 0, 3, 0, 7, 3, 0, 349, 2, 96, 2, 97, 2, 6, -264, 3, 0, 11, 2, 24, 3, 0, 2, 2, 25, -1, 0, 2700607615, 2, 98, 2, 99, 3, 0, 2, 2, 20, 2, 100, 3, 0, 10, 2, 10, 2, 17, 2, 0, 2, 42, 2, 0, 2, 26, 2, 101, -3, 2, 102, 3, 0, 3, 2, 22, -1, 3, 5, 2, 2, 30, 2, 0, 2, 7, 2, 103, -1, 2, 104, 2, 105, 2, 106, -1, 3, 0, 3, 2, 16, -2, 2, 0, 2, 31, -8, 2, 22, 2, 0, 2, 107, -1, 2, 0, 2, 58, 2, 32, 2, 18, 2, 10, 2, 0, 2, 108, -1, 3, 0, 4, 2, 10, 2, 17, 2, 109, 2, 6, 2, 0, 2, 110, 2, 0, 2, 44, -4, 3, 0, 9, 2, 23, 2, 18, 2, 26, -4, 2, 111, 2, 112, 2, 18, 2, 23, 2, 7, -2, 2, 113, 2, 18, 2, 25, -2, 2, 0, 2, 114, -2, 0, 4277075969, 2, 8, -1, 3, 22, 2, -1, 2, 34, 2, 137, 2, 0, 3, 18, 2, 2, 35, 2, 20, -3, 3, 0, 2, 2, 13, -1, 2, 0, 2, 35, 2, 0, 2, 35, -24, 2, 115, 2, 9, -2, 2, 115, 2, 27, 2, 17, 2, 13, 2, 115, 2, 36, 2, 17, 0, 4718591, 2, 115, 2, 35, 0, 335544350, -1, 2, 116, 2, 117, -2, 2, 118, 2, 119, 2, 7, -1, 2, 120, 2, 61, 0, 3758161920, 0, 3, -4, 2, 0, 2, 31, 2, 170, -1, 2, 0, 2, 27, 0, 176, -5, 2, 0, 2, 43, 2, 177, -1, 2, 0, 2, 27, 2, 189, -1, 2, 0, 2, 19, -2, 2, 25, -12, 3, 0, 2, 2, 121, -8, 0, 4294965249, 0, 67633151, 0, 4026597376, 2, 0, 0, 975, -1, 2, 0, 2, 45, -8, 2, 50, 2, 43, 0, 1, 2, 122, 2, 27, -3, 2, 123, 2, 107, 2, 124, -21, 3, 0, 28, 2, 25, -3, 3, 0, 3, 2, 43, 3, 0, 6, 2, 44, -85, 3, 0, 33, 2, 43, -126, 3, 0, 18, 2, 36, -269, 3, 0, 17, 2, 45, 2, 7, -3, 2, 17, 2, 125, 2, 0, 2, 27, 2, 44, 2, 126, 2, 27, -27, 3, 0, 2, 0, 65567, -1, 2, 100, -2, 0, 3, 3, 0, 191, 2, 47, 3, 0, 23, 2, 35, -296, 3, 0, 8, 2, 7, -2, 2, 17, 3, 0, 11, 2, 6, -72, 3, 0, 3, 2, 127, 2, 128, -187, 3, 0, 2, 2, 48, 2, 0, 2, 129, 2, 130, 2, 51, 2, 0, 2, 131, 2, 132, 2, 133, 3, 0, 10, 2, 134, 2, 135, 2, 15, 3, 48, 2, 3, 49, 2, 3, 50, 2, 2, 136, -129, 3, 0, 6, 2, 137, -1, 3, 0, 2, 2, 44, -37, 2, 51, 2, 138, 2, 139, 2, 140, 2, 141, 2, 142, -138, 3, 0, 1334, 2, 23, -1, 3, 0, 129, 2, 31, 3, 0, 6, 2, 10, 3, 0, 180, 2, 143, 3, 0, 233, 0, 1, -96, 3, 0, 16, 2, 10, -28719, 2, 0, 0, 1, -1, 2, 121, 2, 0, 0, 8193, -21, 0, 50331648, 0, 10255, 0, 4, -11, 2, 62, 2, 163, 0, 1, 0, 71936, -1, 2, 154, 0, 4292933632, 0, 805306431, -5, 2, 144, -1, 2, 172, -1, 0, 6144, -2, 2, 122, -1, 2, 164, -1, 2, 150, 2, 145, 2, 158, 2, 0, 0, 3223322624, 2, 8, 0, 4, -4, 2, 183, 0, 205128192, 0, 1333757536, 0, 3221225520, 0, 423953, 0, 747766272, 0, 2717763192, 0, 4290773055, 0, 278545, 2, 146, 0, 4294886464, 0, 33292336, 0, 417809, 2, 146, 0, 1329579616, 0, 4278190128, 0, 700594195, 0, 1006647527, 0, 4286497336, 0, 4160749631, 2, 147, 0, 469762560, 0, 4171219488, 0, 16711728, 2, 147, 0, 202375680, 0, 3214918176, 0, 4294508592, 2, 147, -1, 0, 983584, 0, 48, 0, 58720275, 0, 3489923072, 0, 10517376, 0, 4293066815, 0, 1, 0, 2013265920, 2, 171, 2, 0, 0, 17816169, 0, 3288339281, 0, 201375904, 2, 0, -2, 0, 256, 0, 122880, 0, 16777216, 2, 144, 0, 4160757760, 2, 0, -6, 2, 160, -11, 0, 3263218176, -1, 0, 49664, 0, 2160197632, 0, 8388802, -1, 0, 12713984, -1, 0, 402653184, 2, 152, 2, 155, -2, 2, 156, -20, 0, 3758096385, -2, 2, 185, 0, 4292878336, 2, 21, 2, 148, 0, 4294057984, -2, 2, 157, 2, 149, 2, 168, -2, 2, 166, -1, 2, 174, -1, 2, 162, 2, 121, 0, 4026593280, 0, 14, 0, 4292919296, -1, 2, 151, 0, 939588608, -1, 0, 805306368, -1, 2, 121, 0, 1610612736, 2, 149, 2, 150, 3, 0, 2, -2, 2, 151, 2, 152, -3, 0, 267386880, -1, 2, 153, 0, 7168, -1, 2, 180, 2, 0, 2, 154, 2, 155, -7, 2, 161, -8, 2, 156, -1, 0, 1426112704, 2, 157, -1, 2, 181, 0, 271581216, 0, 2149777408, 2, 27, 2, 154, 2, 121, 0, 851967, 0, 3758129152, -1, 2, 27, 2, 173, -4, 2, 151, -20, 2, 188, 2, 158, -56, 0, 3145728, 2, 179, 2, 184, 0, 4294443520, 2, 73, -1, 2, 159, 2, 121, -4, 0, 32505856, -1, 2, 160, -1, 0, 2147385088, 2, 21, 1, 2155905152, 2, -3, 2, 91, 2, 0, 2, 161, -2, 2, 148, -6, 2, 162, 0, 4026597375, 0, 1, -1, 0, 1, -1, 2, 163, -3, 2, 137, 2, 190, -2, 2, 159, 2, 164, -1, 2, 169, 2, 121, -6, 2, 121, -213, 2, 162, -657, 2, 158, -36, 2, 165, -1, 0, 65408, -10, 2, 193, -5, 2, 166, -5, 0, 4278222848, 2, 0, 2, 23, -1, 0, 4227919872, -1, 2, 166, -2, 0, 4227874752, 2, 157, -2, 0, 2146435072, 2, 152, -2, 0, 1006649344, 2, 121, -1, 2, 21, 0, 201375744, -3, 0, 134217720, 2, 21, 0, 4286677377, 0, 32896, -1, 2, 167, -3, 2, 168, -349, 2, 169, 2, 170, 2, 171, 3, 0, 264, -11, 2, 172, -2, 2, 155, 2, 0, 0, 520617856, 0, 2692743168, 0, 36, -3, 0, 524284, -11, 2, 27, -1, 2, 178, -1, 2, 176, 0, 3221291007, 2, 155, -1, 0, 524288, 0, 2158720, -3, 2, 152, 0, 1, -4, 2, 121, 0, 3808625411, 0, 3489628288, 0, 4096, 0, 1207959680, 0, 3221274624, 2, 0, -3, 2, 164, 0, 120, 0, 7340032, -2, 0, 4026564608, 2, 4, 2, 27, 2, 157, 3, 0, 4, 2, 152, -1, 2, 173, 2, 171, -1, 0, 8176, 2, 174, 2, 164, 2, 175, -1, 0, 4290773232, 2, 0, -4, 2, 157, 2, 182, 0, 15728640, 2, 171, -1, 2, 154, -1, 0, 4294934512, 3, 0, 4, -9, 2, 21, 2, 162, 2, 176, 3, 0, 4, 0, 704, 0, 1849688064, 0, 4194304, -1, 2, 121, 0, 4294901887, 2, 0, 0, 130547712, 0, 1879048192, 0, 2080374784, 3, 0, 2, -1, 2, 177, 2, 178, -1, 0, 17829776, 0, 2028994560, 0, 4261478144, -2, 2, 0, -1, 0, 4286580608, -1, 0, 29360128, 2, 179, 0, 16252928, 0, 3791388672, 2, 119, 3, 0, 2, -2, 2, 180, 2, 0, -1, 2, 100, -1, 0, 66584576, 3, 0, 11, 2, 121, 3, 0, 12, -2, 0, 245760, 0, 2147418112, -1, 2, 144, 2, 195, 0, 4227923456, -1, 2, 181, 2, 169, 2, 21, -2, 2, 172, 0, 4292870145, 0, 262144, 2, 121, 3, 0, 2, 0, 1073758848, 2, 182, -1, 0, 4227921920, 2, 183, 2, 146, 0, 528402016, 0, 4292927536, 3, 0, 4, -2, 0, 3556769792, 2, 0, -2, 2, 186, 3, 0, 5, -1, 2, 179, 2, 157, 2, 0, -2, 0, 4227923936, 2, 58, -1, 2, 166, 2, 91, 2, 0, 2, 184, 2, 151, 3, 0, 11, -2, 0, 2146959360, 3, 0, 8, -2, 2, 154, -1, 0, 536870960, 2, 115, -1, 2, 185, 3, 0, 8, 0, 512, 0, 8388608, 2, 167, 2, 165, 2, 178, 0, 4286578944, 3, 0, 2, 0, 1152, 0, 1266679808, 2, 186, 3, 0, 21, -28, 2, 155, 3, 0, 3, -3, 0, 4292902912, -6, 2, 93, 3, 0, 85, -33, 2, 187, 3, 0, 126, -18, 2, 188, 3, 0, 269, -17, 2, 185, 2, 121, 0, 4294917120, 3, 0, 2, 2, 27, 0, 4290822144, -2, 0, 67174336, 0, 520093700, 2, 17, 3, 0, 27, -2, 0, 65504, 2, 121, 2, 43, 3, 0, 2, 2, 88, -191, 2, 58, -23, 2, 100, 3, 0, 296, -8, 2, 121, 3, 0, 2, 2, 27, -11, 2, 171, 3, 0, 72, -3, 0, 3758159872, 0, 201391616, 3, 0, 155, -7, 2, 162, -1, 0, 384, -1, 0, 133693440, -3, 2, 180, -2, 2, 30, 3, 0, 5, -2, 2, 21, 2, 122, 3, 0, 4, -2, 2, 181, -1, 2, 144, 0, 335552923, 2, 189, -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, 62, -6, 0, 4286578784, 2, 0, -2, 0, 1006696448, 3, 0, 37, 2, 189, 0, 4110942569, 0, 1432950139, 0, 2701658217, 0, 4026532864, 0, 4026532881, 2, 0, 2, 42, 3, 0, 8, -1, 2, 151, -2, 2, 148, 2, 190, 0, 65537, 2, 162, 2, 165, 2, 159, -1, 2, 151, -1, 2, 58, 2, 0, 2, 191, 0, 65528, 2, 171, 0, 4294770176, 2, 30, 3, 0, 4, -30, 2, 192, 0, 4261470208, -3, 2, 148, -2, 2, 192, 2, 0, 2, 151, -1, 2, 186, -1, 2, 154, 0, 4294950912, 3, 0, 2, 2, 151, 2, 121, 2, 165, 2, 193, 2, 166, 2, 0, 2, 194, 2, 188, 3, 0, 48, -1334, 2, 21, 2, 0, -129, 2, 192, -6, 2, 157, -180, 2, 195, -233, 2, 4, 3, 0, 96, -16, 2, 157, 3, 0, 22583, -7, 2, 17, 3, 0, 6128], [4294967295, 4294967291, 4092460543, 4294828015, 4294967294, 134217726, 268435455, 2147483647, 1048575, 16777215, 1073741823, 1061158911, 536805376, 511, 4294910143, 4160749567, 134217727, 4294901760, 4194303, 2047, 262143, 4286578688, 536870911, 8388607, 4294918143, 67108863, 255, 65535, 67043328, 2281701374, 4294967232, 2097151, 4294903807, 4294902783, 4294967039, 524287, 127, 4294549487, 67045375, 1023, 67047423, 4286578687, 4294770687, 32767, 15, 33554431, 2047999, 8191, 4292870143, 4294934527, 4294966783, 4294967279, 262083, 20511, 4290772991, 4294901759, 41943039, 460799, 4294959104, 71303167, 1071644671, 602799615, 65536, 4294828000, 805044223, 4277151126, 1031749119, 4294917631, 2134769663, 4286578493, 4282253311, 4294942719, 33540095, 4294905855, 4294967264, 2868854591, 1608515583, 265232348, 534519807, 2147614720, 1060109444, 4093640016, 17376, 2139062143, 224, 4169138175, 4294868991, 4294909951, 4294967292, 4294965759, 16744447, 4294966272, 4294901823, 4294967280, 8289918, 4294934399, 4294901775, 4294965375, 1602223615, 4294967259, 4294443008, 268369920, 4292804608, 486341884, 4294963199, 3087007615, 1073692671, 131071, 4128527, 4279238655, 4294902015, 4294966591, 2445279231, 3670015, 3238002687, 4294967288, 4294705151, 4095, 3221208447, 4294902271, 4294549472, 2147483648, 4294705152, 4294966143, 64, 16383, 3774873592, 536807423, 67043839, 3758096383, 3959414372, 3755993023, 2080374783, 4294835295, 4294967103, 4160749565, 4087, 31, 184024726, 2862017156, 1593309078, 268434431, 268434414, 4294901763, 536870912, 2952790016, 202506752, 139280, 4293918720, 4227922944, 2147532800, 61440, 3758096384, 117440512, 65280, 4227858432, 3233808384, 3221225472, 4294965248, 32768, 57152, 67108864, 4290772992, 25165824, 4160749568, 57344, 4278190080, 65472, 4227907584, 65520, 1920, 4026531840, 49152, 4294836224, 63488, 1073741824, 4294967040, 251658240, 196608, 12582912, 4294966784, 2097152, 64512, 417808, 469762048, 4261412864, 4227923712, 4294934528, 4294967168, 16, 98304, 63, 4292870144, 4294963200, 65534, 65532]);
/**
* Return the next unicodechar in the stream
*
* @param parser Parser object
*/
function nextUnicodeChar(parser) {
const { index } = parser;
const hi = parser.source.charCodeAt(index);
if (hi < 55296 /* LeadSurrogateMin */ || hi > 56319 /* LeadSurrogateMax */)
return hi;
const lo = parser.source.charCodeAt(index + 1);
if (lo < 56320 /* TrailSurrogateMin */ || lo > 57343 /* TrailSurrogateMax */)
return hi;
return 65536 /* NonBMPMin */ + ((hi & 0x3FF) << 10) | lo & 0x3FF;
}
/**
* Returns true if this is a valid identifier part
*
* @param code Codepoint
*/
const isIdentifierPart = (code) => (characterType[code] & 1 /* IdentifierStart */) !== 0 || isValidIdentifierPart(code);
function escapeForPrinting(code) {
switch (code) {
case 0 /* Null */:
return '\\0';
case 8 /* Backspace */:
return '\\b';
case 9 /* Tab */:
return '\\t';
case 10 /* LineFeed */:
return '\\n';
case 11 /* VerticalTab */:
return '\\v';
case 12 /* FormFeed */:
return '\\f';
case 13 /* CarriageReturn */:
return '\\r';
default:
if (!mustEscape(code))
return fromCodePoint(code);
if (code < 0x10)
return `\\x0${code.toString(16)}`;
if (code < 0x100)
return `\\x${code.toString(16)}`;
if (code < 0x1000)
return `\\u0${code.toString(16)}`;
if (code < 0x10000)
return `\\u${code.toString(16)}`;
return `\\u{${code.toString(16)}}`;
}
}
/**
* Consume an token in the scanner on match. This is an equalent to
* 'consume' used in the parser code itself.
*
* @param parser Parser object
* @param context Context masks
*/
function consumeOpt(parser, code) {
if (parser.source.charCodeAt(parser.index) !== code)
return false;
parser.index++;
parser.column++;
return true;
}
/**
* Consumes line feed
*
* @param parser Parser object
* @param state Scanner state
*/
function consumeLineFeed(parser, state) {
parser.flags |= 1 /* NewLine */;
parser.index++;
if ((state & 2 /* LastIsCR */) === 0) {
parser.column = 0;
parser.line++;
}
}
/**
* Scans private name. Stage 3 proposal related
*
* @param parser Parser object
* @param context Context masks
*/
function scanPrivateName(parser, context) {
if (!(context & 32768 /* InClass */) || !isValidIdentifierStart(parser.source.charCodeAt(parser.index))) {
report(parser, 1 /* UnexpectedToken */, tokenDesc(parser.token));
}
return 115 /* Hash */;
}
/**
* Advance to new line
*
* @param parser Parser object
*/
function advanceNewline(parser) {
parser.flags |= 1 /* NewLine */;
parser.index++;
parser.column = 0;
parser.line++;
}
const fromCodePoint = (code) => {
return code <= 0xFFFF ?
String.fromCharCode(code) :
String.fromCharCode(((code - 65536 /* NonBMPMin */) >> 10) + 55296 /* LeadSurrogateMin */, ((code - 65536 /* NonBMPMin */) & (1024 - 1)) + 56320 /* TrailSurrogateMin */);
};
function readNext(parser) {
parser.index++;
parser.column++;
if (parser.index >= parser.source.length)
report(parser, 12 /* UnicodeOutOfRange */);
return nextUnicodeChar(parser);
}
function toHex(code) {
if (code < 48 /* Zero */)
return -1;
if (code <= 57 /* Nine */)
return code - 48 /* Zero */;
if (code < 65 /* UpperA */)
return -1;
if (code <= 70 /* UpperF */)
return code - 65 /* UpperA */ + 10;
if (code < 97 /* LowerA */)
return -1;
if (code <= 102 /* LowerF */)
return code - 97 /* LowerA */ + 10;
return -1;
}
function advanceOnMaybeAstral(parser, ch) {
parser.index++;
parser.column++;
if (ch > 0xFFFF)
parser.index++;
}
/**
* Scans regular expression
*
* @param parser Parser object
* @param context Context masks
*/
function scanRegularExpression(parser, context) {
const bodyStart = parser.index;
let preparseState = 0 /* Empty */;
loop: while (true) {
const ch = parser.source.charCodeAt(parser.index);
parser.index++;
parser.column++;
if (preparseState & 1 /* Escape */) {
preparseState &= ~1 /* Escape */;
}
else {
switch (ch) {
case 47 /* Slash */:
if (!preparseState)
break loop;
else
break;
case 92 /* Backslash */:
preparseState |= 1 /* Escape */;
break;
case 91 /* LeftBracket */:
preparseState |= 2 /* Class */;
break;
case 93 /* RightBracket */:
preparseState &= 1 /* Escape */;
break;
case 13 /* CarriageReturn */:
case 10 /* LineFeed */:
case 8232 /* LineSeparator */:
case 8233 /* ParagraphSeparator */:
report(parser, 6 /* UnterminatedRegExp */);
default: // ignore
}
}
if (parser.index >= parser.source.length) {
report(parser, 6 /* UnterminatedRegExp */);
}
}
const bodyEnd = parser.index - 1;
let mask = 0 /* Empty */;
const { index: flagStart } = parser;
loop: while (parser.index < parser.source.length) {
const code = parser.source.charCodeAt(parser.index);
switch (code) {
case 103 /* LowerG */:
if (mask & 2 /* Global */)
tolerant(parser, context, 13 /* DuplicateRegExpFlag */, 'g');
mask |= 2 /* Global */;
break;
case 105 /* LowerI */:
if (mask & 1 /* IgnoreCase */)
tolerant(parser, context, 13 /* DuplicateRegExpFlag */, 'i');
mask |= 1 /* IgnoreCase */;
break;
case 109 /* LowerM */:
if (mask & 4 /* Multiline */)
tolerant(parser, context, 13 /* DuplicateRegExpFlag */, 'm');
mask |= 4 /* Multiline */;
break;
case 117 /* LowerU */:
if (mask & 8 /* Unicode */)
tolerant(parser, context, 13 /* DuplicateRegExpFlag */, 'u');
mask |= 8 /* Unicode */;
break;
case 121 /* LowerY */:
if (mask & 16 /* Sticky */)
tolerant(parser, context, 13 /* DuplicateRegExpFlag */, 'y');
mask |= 16 /* Sticky */;
break;
case 115 /* LowerS */:
if (mask & 32 /* DotAll */)
tolerant(parser, context, 13 /* DuplicateRegExpFlag */, 's');
mask |= 32 /* DotAll */;
break;
default:
if (!isIdentifierPart(code))
break loop;
report(parser, 14 /* UnexpectedTokenRegExpFlag */, fromCodePoint(code));
}
parser.index++;
parser.column++;
}
const flags = parser.source.slice(flagStart, parser.index);
const pattern = parser.source.slice(bodyStart, bodyEnd);
parser.tokenRegExp = { pattern, flags };
if (context & 8 /* OptionsRaw */)
parser.tokenRaw = parser.source.slice(parser.startIndex, parser.index);
parser.tokenValue = validate(parser, context, pattern, flags);
return 33554436 /* RegularExpression */;
}
/**
* Validates regular expressions
*
*
* @param parser Parser instance
* @param context Context masks
* @param pattern Regexp body
* @param flags Regexp flags
*/
function validate(parser, context, pattern, flags) {
if (!(context & 1024 /* OptionsNode */)) {
try {
}
catch (e) {
report(parser, 6 /* UnterminatedRegExp */);
}
}
try {
return new RegExp(pattern, flags);
}
catch (e) {
return null;
}
}
/**
* Scan escape sequence
*
* @param parser Parser object
* @param context Context masks
*/
function scanEscapeSequence(parser, context, first) {
switch (first) {
case 98 /* LowerB */:
return 8 /* Backspace */;
case 102 /* LowerF */:
return 12 /* FormFeed */;
case 114 /* LowerR */:
return 13 /* CarriageReturn */;
case 110 /* LowerN */:
return 10 /* LineFeed */;
case 116 /* LowerT */:
return 9 /* Tab */;
case 118 /* LowerV */:
return 11 /* VerticalTab */;
case 13 /* CarriageReturn */:
case 10 /* LineFeed */:
case 8232 /* LineSeparator */:
case 8233 /* ParagraphSeparator */:
parser.column = -1;
parser.line++;
return -1 /* Empty */;
case 48 /* Zero */:
case 49 /* One */:
case 50 /* Two */:
case 51 /* Three */:
{
// 1 to 3 octal digits
let code = first - 48 /* Zero */;
let index = parser.index + 1;
let column = parser.column + 1;
let next = parser.source.charCodeAt(index);
if (next < 48 /* Zero */ || next > 55 /* Seven */) {
// Strict mode code allows only \0, then a non-digit.
if (code !== 0 || next === 56 /* Eight */ || next === 57 /* Nine */) {
if (context & 4096 /* Strict */)
return -2 /* StrictOctal */;
parser.flags |= 128 /* HasOctal */;
}
}
else if (context & 4096 /* Strict */) {
return -2 /* StrictOctal */;
}
else {
parser.flags |= 128 /* HasOctal */;
parser.lastValue = next;
code = code * 8 + (next - 48 /* Zero */);
index++;
column++;
next = parser.source.charCodeAt(index);
if (next >= 48 /* Zero */ && next <= 55 /* Seven */) {
parser.lastValue = next;
code = code * 8 + (next - 48 /* Zero */);
index++;
column++;
}
parser.index = index - 1;
parser.column = column - 1;
}
return code;
}
case 52 /* Four */:
case 53 /* Five */:
case 54 /* Six */:
case 55 /* Seven */:
{
// 1 to 2 octal digits
if (context & 4096 /* Strict */)
return -2 /* StrictOctal */;
let code = first - 48 /* Zero */;
const index = parser.index + 1;
const column = parser.column + 1;
const next = parser.source.charCodeAt(index);
if (next >= 48 /* Zero */ && next <= 55 /* Seven */) {
code = code * 8 + (next - 48 /* Zero */);
parser.lastValue = next;
parser.index = index;
parser.column = column;
}
return code;
}
// `8`, `9` (invalid escapes)
case 56 /* Eight */:
case 57 /* Nine */:
return -3 /* EightOrNine */;
// ASCII escapes
case 120 /* LowerX */:
{
const ch1 = parser.lastValue = readNext(parser);
const hi = toHex(ch1);
if (hi < 0)
return -4 /* InvalidHex */;
const ch2 = parser.lastValue = readNext(parser);
const lo = toHex(ch2);
if (lo < 0)
return -4 /* InvalidHex */;
return hi << 4 | lo;
}
// UCS-2/Unicode escapes
case 117 /* LowerU */:
{
let ch = parser.lastValue = readNext(parser);
if (ch === 123 /* LeftBrace */) {
ch = parser.lastValue = readNext(parser);
let code = toHex(ch);
if (code < 0)
return -4 /* InvalidHex */;
ch = parser.lastValue = readNext(parser);
while (ch !== 125 /* RightBrace */) {
const digit = toHex(ch);
if (digit < 0)
return -4 /* InvalidHex */;
code = code * 16 + digit;
// Code point out of bounds
if (code > 1114111 /* NonBMPMax */)
return -5 /* OutOfRange */;
ch = parser.lastValue = readNext(parser);
}
return code;
}
else {
// \uNNNN
let codePoint = toHex(ch);
if (codePoint < 0)
return -4 /* InvalidHex */;
for (let i = 0; i < 3; i++) {
ch = parser.lastValue = readNext(parser);
const digit = toHex(ch);
if (digit < 0)
return -4 /* InvalidHex */;
codePoint = codePoint * 16 + digit;
}
return codePoint;
}
}
default:
return parser.source.charCodeAt(parser.index);
}
}
/**
* Throws a string error for either string or template literal
*
* @param parser Parser object
* @param context Context masks
*/
function throwStringError(parser, context, code) {
switch (code) {
case -1 /* Empty */:
return;
case -2 /* StrictOctal */:
report(parser, context & 16384 /* TaggedTemplate */ ?
74 /* TemplateOctalLiteral */ :
10 /* StrictOctalEscape */);
case -3 /* EightOrNine */:
report(parser, 11 /* InvalidEightAndNine */);
case -4 /* InvalidHex */:
report(parser, 73 /* MalformedEscape */, 'hexadecimal');
case -5 /* OutOfRange */:
report(parser, 12 /* UnicodeOutOfRange */);
/* istanbul ignore next */
default:
// ignore
}
}
/**
* Scan a string literal
*
* @see [Link](https://tc39.github.io/ecma262/#sec-literals-string-literals)
*
* @param parser Parser object
* @param context Context masks
* @param quote codepoint
*/
function scanString(parser, context, quote) {
const { index: start, lastValue } = parser;
let ret = '';
parser.index++;
parser.column++; // consume quote
let ch = parser.source.charCodeAt(parser.index);
while (ch !== quote) {
switch (ch) {
case 8232 /* LineSeparator */:
case 8233 /* ParagraphSeparator */:
case 13 /* CarriageReturn */:
case 10 /* LineFeed */:
report(parser, 5 /* UnterminatedString */);
case 92 /* Backslash */:
ch = readNext(parser);
if (ch > 128 /* MaxAsciiCharacter */) {
ret += fromCodePoint(ch);
}
else {
parser.lastValue = ch;
const code = scanEscapeSequence(parser, context, ch);
if (code >= 0)
ret += fromCodePoint(code);
else
throwStringError(parser, context, code);
ch = parser.lastValue;
}
break;
default:
ret += fromCodePoint(ch);
}
ch = readNext(parser);
}
parser.index++;
parser.column++; // consume quote
parser.tokenRaw = parser.source.slice(start, parser.index);
parser.tokenValue = ret;
parser.lastValue = lastValue;
return 33554435 /* StringLiteral */;
}
/**
* Consumes template brace
*
* @param parser Parser object
* @param context Context masks
*/
function consumeTemplateBrace(parser, context) {
if (parser.index >= parser.length)
report(parser, 8 /* UnterminatedTemplate */);
// Upon reaching a '}', consume it and rewind the scanner state
parser.index--;
parser.column--;
return scanTemplate(parser, context);
}
/**
* Scan template
*
* @param parser Parser object
* @param context Context masks
* @param first Codepoint
*/
function scanTemplate(parser, context) {
const { index: start, lastValue } = parser;
let tail = true;
let ret = '';
let ch = readNext(parser);
loop: while (ch !== 96 /* Backtick */) {
switch (ch) {
// Break after a literal `${` (thus the dedicated code path).
case 36 /* Dollar */:
{
const index = parser.index + 1;
if (index < parser.length &&
parser.source.charCodeAt(index) === 123 /* LeftBrace */) {
parser.index = index;
parser.column++;
tail = false;
break loop;
}
ret += '$';
break;
}
case 92 /* Backslash */:
ch = readNext(parser);
if (ch >= 128) {
ret += fromCodePoint(ch);
}
else {
parser.lastValue = ch;
// Because octals are forbidden in escaped template sequences and the fact that
// both string and template scanning uses the same method - 'scanEscapeSequence',
// we set the strict context mask.
const code = scanEscapeSequence(parser, context | 4096 /* Strict */, ch);
if (code >= 0) {
ret += fromCodePoint(code);
}
else if (code !== -1 /* Empty */ && context & 16384 /* TaggedTemplate */) {
ret = undefined;
ch = scanLooserTemplateSegment(parser, parser.lastValue);
if (ch < 0) {
tail = false;
}
break loop;
}
else {
throwStringError(parser, context | 16384 /* TaggedTemplate */, code);
}
ch = parser.lastValue;
}
break;
case 13 /* CarriageReturn */:
case 10 /* LineFeed */:
case 8232 /* LineSeparator */:
case 8233 /* ParagraphSeparator */:
parser.column = -1;
parser.line++;
// falls through
default:
if (ret != null)
ret += fromCodePoint(ch);
}
ch = readNext(parser);
}
parser.index++;
parser.column++;
parser.tokenValue = ret;
parser.lastValue = lastValue;
if (tail) {
parser.tokenRaw = parser.source.slice(start + 1, parser.index - 1);
return 33554441 /* TemplateTail */;
}
else {
parser.tokenRaw = parser.source.slice(start + 1, parser.index - 2);
return 33554440 /* TemplateCont */;
}
}
/**
* Scan looser template segment
*
* @param parser Parser object
* @param ch codepoint
*/
function scanLooserTemplateSegment(parser, ch) {
while (ch !== 96 /* Backtick */) {
if (ch === 36 /* Dollar */ && parser.source.charCodeAt(parser.index + 1) === 123 /* LeftBrace */) {
parser.index++;
parser.column++;
return -ch;
}
// Skip '\' and continue to scan the template token to search
// for the end, without validating any escape sequences
ch = readNext(parser);
}
return ch;
}
// 11.8.3 Numeric Literals
/**
* Scans hex integer literal
*
* @see [Link](https://tc39.github.io/ecma262/#prod-HexIntegerLiteral)
*
* @param parser Parser object
* @param context Context masks
*/
function scanHexIntegerLiteral(parser, context) {
parser.index++;
parser.column++;
let state = 0 /* None */;
let value = toHex(parser.source.charCodeAt(parser.index));
if (value < 0)
report(parser, 0 /* Unexpected */);
parser.index++;
parser.column++;
while (parser.index < parser.length) {
const next = parser.source.charCodeAt(parser.index);
if (context & 1 /* OptionsNext */ && next === 95 /* Underscore */) {
state = scanNumericSeparator(parser, state);
continue;
}
state &= ~1 /* SeenSeparator */;
const digit = toHex(next);
if (digit < 0)
break;
value = value * 16 + digit;
parser.index++;
parser.column++;
}
if (state & 1 /* SeenSeparator */)
report(parser, 57 /* TrailingNumericSeparator */);
return assembleNumericLiteral(parser, context, value, consumeOpt(parser, 110 /* LowerN */));
}
/**
* Scans binary and octal integer literal
*
* @see [Link](https://tc39.github.io/ecma262/#prod-OctalIntegerLiteral)
* @see [Link](https://tc39.github.io/ecma262/#prod-BinaryIntegerLiteral)
*
* @param parser Parser object
* @param context Context masks
*/
function scanOctalOrBinary(parser, context, base) {
parser.index++;
parser.column++;
let digits = 0;
let ch;
let value = 0;
let state = 0 /* None */;
while (parser.index < parser.length) {
ch = parser.source.charCodeAt(parser.index);
if (context & 1 /* OptionsNext */ && ch === 95 /* Underscore */) {
state = scanNumericSeparator(parser, state);
continue;
}
state &= ~1 /* SeenSeparator */;
const converted = ch - 48 /* Zero */;
if (!(ch >= 48 /* Zero */ && ch <= 57 /* Nine */) || converted >= base)
break;
value = value * base + converted;
parser.index++;
parser.column++;
digits++;
}
if (digits === 0)
report(parser, 0 /* Unexpected */);
if (state & 1 /* SeenSeparator */)
report(parser, 57 /* TrailingNumericSeparator */);
return assembleNumericLiteral(parser, context, value, consumeOpt(parser, 110 /* LowerN */));
}
/**
* Scans implicit octal digits
*
* @see [Link](https://tc39.github.io/ecma262/#prod-OctalDigits)
*
* @param parser Parser object
* @param context Context masks
*/
function scanImplicitOctalDigits(parser, context) {
switch (parser.source.charCodeAt(parser.index)) {
case 48 /* Zero */:
case 49 /* One */:
case 50 /* Two */:
case 51 /* Three */:
case 52 /* Four */:
case 53 /* Five */:
case 54 /* Six */:
case 55 /* Seven */:
{
if (context & 4096 /* Strict */)
report(parser, 0 /* Unexpected */);
let index = parser.index;
let column = parser.column;
let code = 0;
parser.flags |= 128 /* HasOctal */;
// Implicit octal, unless there is a non-octal digit.
// (Annex B.1.1 on Numeric Literals)
while (index < parser.length) {
const next = parser.source.charCodeAt(index);
if (next === 95 /* Underscore */) {
report(parser, 58 /* ZeroDigitNumericSeparator */);
}
else if (next < 48 /* Zero */ || next > 55 /* Seven */) {
return scanNumericLiteral(parser, context);
}
else {
code = code * 8 + (next - 48 /* Zero */);
index++;
column++;
}
}
parser.index = index;
parser.column = column;
return assembleNumericLiteral(parser, context, code, consumeOpt(parser, 110 /* LowerN */));
}
case 56 /* Eight */:
case 57 /* Nine */:
parser.flags |= 128 /* HasOctal */;
default:
if (context & 1 /* OptionsNext */ && parser.source.charCodeAt(parser.index) === 95 /* Underscore */) {
report(parser, 58 /* ZeroDigitNumericSeparator */);
}
return scanNumericLiteral(parser, context);
}
}
/**
* Scans signed integer
*
* @see [Link](https://tc39.github.io/ecma262/#prod-SignedInteger)
*
* @param parser Parser object
* @param context Context masks
*/
function scanSignedInteger(parser, end) {
let next = parser.source.charCodeAt(parser.index);
if (next === 43 /* Plus */ || next === 45 /* Hyphen */) {
parser.index++;
parser.column++;
next = parser.source.charCodeAt(parser.index);
}
if (!(next >= 48 /* Zero */ && next <= 57 /* Nine */)) {
report(parser, 0 /* Unexpected */);
}
const preNumericPart = parser.index;
const finalFragment = scanDecimalDigitsOrSeparator(parser);
return parser.source.substring(end, preNumericPart) + finalFragment;
}
/**
* Scans numeric literal
*
* @see [Link](https://tc39.github.io/ecma262/#prod-NumericLiteral)
*
* @param parser Parser object
* @param context Context masks
*/
function scanNumericLiteral(parser, context, state = 0 /* None */) {
let value = state & 4 /* Float */ ?
0 :
scanDecimalAsSmi(parser, context);
const next = parser.source.charCodeAt(parser.index);
// I know I'm causing a bug here. The question is - will anyone figure this out?
if (next !== 46 /* Period */ && next !== 95 /* Underscore */ && !isValidIdentifierStart(next)) {
return assembleNumericLiteral(parser, context, value);
}
if (consumeOpt(parser, 46 /* Period */)) {
if (context & 1 /* OptionsNext */ && parser.source.charCodeAt(parser.index) === 95 /* Underscore */) {
report(parser, 58 /* ZeroDigitNumericSeparator */);
}
state |= 4 /* Float */;
value = `${value}.${scanDecimalDigitsOrSeparator(parser)}`;
}
const end = parser.index;
if (consumeOpt(parser, 110 /* LowerN */)) {
if (state & 4 /* Float */)
report(parser, 0 /* Unexpected */);
state |= 8 /* BigInt */;
}
if (consumeOpt(parser, 101 /* LowerE */) || consumeOpt(parser, 69 /* UpperE */)) {
state |= 4 /* Float */;
value += scanSignedInteger(parser, end);
}
if (isValidIdentifierStart(parser.source.charCodeAt(parser.index))) {
report(parser, 0 /* Unexpected */);
}
return assembleNumericLiteral(parser, context, state & 4 /* Float */ ? parseFloat(value) : parseInt(value, 10), !!(state & 8 /* BigInt */));
}
/**
* Internal helper function for scanning numeric separators.
*
* @param parser Parser object
* @param context Context masks
* @param state NumericState state
*/
function scanNumericSeparator(parser, state) {
parser.index++;
parser.column++;
if (state & 1 /* SeenSeparator */)
report(parser, 57 /* TrailingNumericSeparator */);
state |= 1 /* SeenSeparator */;
return state;
}
/**
* Internal helper function that scans numeric values
*
* @param parser Parser object
* @param context Context masks
*/
function scanDecimalDigitsOrSeparator(parser) {
let start = parser.index;
let state = 0 /* None */;
let ret = '';
loop: while (parser.index < parser.length) {
switch (parser.source.charCodeAt(parser.index)) {
case 95 /* Underscore */:
const preUnderscoreIndex = parser.index;
state = scanNumericSeparator(parser, state);
ret += parser.source.substring(start, preUnderscoreIndex);
start = parser.index;
continue;
case 48 /* Zero */:
case 49 /* One */:
case 50 /* Two */:
case 51 /* Three */:
case 52 /* Four */:
case 53 /* Five */:
case 54 /* Six */:
case 55 /* Seven */:
case 56 /* Eight */:
case 57 /* Nine */:
state = state & ~1 /* SeenSeparator */;
parser.index++;
parser.column++;
break;
default:
break loop;
}
}
if (state & 1 /* SeenSeparator */)
report(parser, 57 /* TrailingNumericSeparator */);
return ret + parser.source.substring(start, parser.index);
}
/**
* Internal helper function that scans numeric values
*
* @param parser Parser object
* @param context Context masks
*/
function scanDecimalAsSmi(parser, context) {
let state = 0 /* None */;
let value = 0;
let next = parser.source.charCodeAt(parser.index);
while (next >= 48 /* Zero */ && next <= 57 /* Nine */ || next === 95 /* Underscore */) {
if (context & 1 /* OptionsNext */ && next === 95 /* Underscore */) {
state = scanNumericSeparator(parser, state);
next = parser.source.charCodeAt(parser.index);
continue;
}
state &= ~1 /* SeenSeparator */;
value = value * 10 + (next - 48 /* Zero */);
parser.index++;
parser.column++;
next = parser.source.charCodeAt(parser.index);
}
if (state & 1 /* SeenSeparator */)
report(parser, 57 /* TrailingNumericSeparator */);
return value;
}
/**
* Internal helper function that assamble the number scanning parts and return
*
* @param parser Parser object
* @param context Context masks
* @param value The numeric value
*/
function assembleNumericLiteral(parser, context, value, isBigInt = false) {
parser.tokenValue = value;
if (context & 8 /* OptionsRaw */)
parser.tokenRaw = parser.source.slice(parser.startIndex, parser.index);
return isBigInt ? 33554551 /* BigIntLiteral */ : 33554434 /* NumericLiteral */;
}
/**
* Scan identifier
*
* @see [Link](https://tc39.github.io/ecma262/#sec-names-and-keywords)
* @see [Link](https://tc39.github.io/ecma262/#sec-literals-string-literals)
*
* @param Parser instance
* @param Context masks
*/
function scanIdentifier(parser, context, first) {
let start = parser.index;
let ret = '';
let isEscaped = false;
if (first)
advanceOnMaybeAstral(parser, first);
loop: while (parser.index < parser.length) {
const index = parser.index;
let ch = parser.source.charCodeAt(index);
switch (ch) {
case 92 /* Backslash */:
ret += parser.source.slice(start, index);
ret += scanUnicodeCodePointEscape(parser);
start = parser.index;
isEscaped = true;
break;
default:
if (ch >= 0xD800 && ch <= 0xDBFF) {
const lo = parser.source.charCodeAt(index + 1);
ch = (ch & 0x3FF) << 10 | lo & 0x3FF | 0x10000;
}
if (!isIdentifierPart(ch))
break loop;
advanceOnMaybeAstral(parser, ch);
}
}
if (start < parser.index)
ret += parser.source.slice(start, parser.index);
parser.tokenValue = ret;
const len = ret.length;
// Keywords are between 2 and 11 characters long and start with a lowercase letter
// https://tc39.github.io/ecma262/#sec-keywords
if (len >= 2 && len <= 11) {
const token = descKeyword(ret);
if (token > 0) {
if (isEscaped) {
if (context & 536870912 /* DisallowEscapedKeyword */) {
tolerant(parser, context, 2 /* InvalidEscapedReservedWord */);
}
// Here we fall back to a mutual parser flag if the escaped keyword isn't disallowed through
// context masks. This is similiar to how V8 does it - they are using an
// 'escaped_keyword' token.
// - J.K. Thomas
parser.flags |= 32768 /* EscapedKeyword */;
}
return token;
}
}
if (context & 256 /* OptionsRawidentifiers */)
parser.tokenRaw = parser.source.slice(start, parser.index);
return 33619969 /* Identifier */;
}
/**
* Scanning chars in the range 0...127, and treat them as an possible
* identifier. This allows subsequent checking to be faster.
*
* @param parser Parser instance
* @param context Context masks
* @param first Code point
*/
function scanMaybeIdentifier(parser, context, first) {
first = nextUnicodeChar(parser);
if (!isValidIdentifierStart(first)) {
report(parser, 9 /* UnexpectedChar */, escapeForPrinting(first));
}
return scanIdentifier(parser, context, first);
}
/**
* Scan unicode codepoint escape
*
* @param Parser instance
* @param Context masks
*/
function scanUnicodeCodePointEscape(parser) {
const { index } = parser;
if (index + 5 < parser.length) {
if (parser.source.charCodeAt(index + 1) !== 117 /* LowerU */) {
report(parser, 0 /* Unexpected */);
}
parser.index += 2;
parser.column += 2;
const code = scanIdentifierUnicodeEscape(parser);
if (code >= 55296 /* LeadSurrogateMin */ && code <= 56319 /* LeadSurrogateMax */) {
report(parser, 72 /* UnexpectedSurrogate */);
}
if (!isIdentifierPart(code)) {
report(parser, 73 /* MalformedEscape */, 'unicode');
}
return fromCodePoint(code);
}
report(parser, 0 /* Unexpected */);
}
/**
* Scan identifier unicode escape
*
* @param Parser instance
* @param Context masks
*/
function scanIdentifierUnicodeEscape(parser) {
// Accept both \uxxxx and \u{xxxxxx}. In the latter case, the number of
// hex digits between { } is arbitrary. \ and u have already been read.
let ch = parser.source.charCodeAt(parser.index);
let codePoint = 0;
// '\u{DDDDDDDD}'
if (ch === 123 /* LeftBrace */) { // {
ch = readNext(parser);
let digit = toHex(ch);
while (digit >= 0) {
codePoint = (codePoint << 4) | digit;
if (codePoint > 1114111 /* NonBMPMax */) {
report(parser, 87 /* UndefinedUnicodeCodePoint */);
}
parser.index++;
parser.column++;
digit = toHex(parser.source.charCodeAt(parser.index));
}
if (parser.source.charCodeAt(parser.index) !== 125 /* RightBrace */) {
report(parser, 73 /* MalformedEscape */, 'unicode');
}
consumeOpt(parser, 125 /* RightBrace */);
// '\uDDDD'
}
else {
for (let i = 0; i < 4; i++) {
ch = parser.source.charCodeAt(parser.index);
const digit = toHex(ch);
if (digit < 0)
report(parser, 73 /* MalformedEscape */, 'unicode');
codePoint = (codePoint << 4) | digit;
parser.index++;
parser.column++;
}
}
return codePoint;
}
// 11.4 Comments
/**
* Skips single HTML comments. Same behavior as in V8.
*
* @param parser Parser Object
* @param context Context masks.
* @param state Scanner state
* @param type Comment type
*/
function skipSingleHTMLComment(parser, context, state, type) {
if (context & 8192 /* Module */)
report(parser, 88 /* HtmlCommentInModule */);
return skipSingleLineComment(parser, context, state, type);
}
/**
* Skips SingleLineComment, SingleLineHTMLCloseComment and SingleLineHTMLOpenComment
*
* @see [Link](https://tc39.github.io/ecma262/#prod-SingleLineComment)
* @see [Link](https://tc39.github.io/ecma262/#prod-annexB-SingleLineHTMLOpenComment)
* @see [Link](https://tc39.github.io/ecma262/#prod-annexB-SingleLineHTMLCloseComment)
*
* @param parser Parser instance
* @param context Context masks
* @param state Scanner state
* @param type Comment type
*/
function skipSingleLineComment(parser, context, state, type) {
const start = parser.index;
const collectable = !!(context & 64 /* OptionsComments */);
while (parser.index < parser.length) {
switch (parser.source.charCodeAt(parser.index)) {
case 13 /* CarriageReturn */:
advanceNewline(parser);
if ((parser.index < parser.length) && parser.source.charCodeAt(parser.index) === 10 /* LineFeed */)
parser.index++;
return state | 1 /* NewLine */;
case 10 /* LineFeed */:
case 8232 /* LineSeparator */:
case 8233 /* ParagraphSeparator */:
advanceNewline(parser);
if (collectable)
addComment(parser, context, type, start);
return state | 1 /* NewLine */;
default:
parser.index++;
parser.column++;
}
}
if (collectable)
addComment(parser, context, type, start);
return state;
}
/**
* Skips multiline comment
*
* @see [Link](https://tc39.github.io/ecma262/#prod-annexB-MultiLineComment)
*
* @param parser Parser instance
* @param context Context masks
* @param state Scanner state
*/
function skipMultiLineComment(parser, context, state) {
const start = parser.index;
const collectable = !!(context & 64 /* OptionsComments */);
while (parser.index < parser.length) {
switch (parser.source.charCodeAt(parser.index)) {
case 42 /* Asterisk */:
parser.index++;
parser.column++;
state &= ~2 /* LastIsCR */;
if (consumeOpt(parser, 47 /* Slash */)) {
if (collectable)
addComment(parser, context, 'MultiLine', start);
return state;
}
break;
// Mark multiline comments containing linebreaks as new lines
// so we can perfectly handle edge cases like: '1/*\n*/--> a comment'
case 13 /* CarriageReturn */:
state |= 1 /* NewLine */ | 2 /* LastIsCR */;
advanceNewline(parser);
break;
case 10 /* LineFeed */:
consumeLineFeed(parser, state);
state = state & ~2 /* LastIsCR */ | 1 /* NewLine */;
break;
case 8232 /* LineSeparator */:
case 8233 /* ParagraphSeparator */:
state = state & ~2 /* LastIsCR */ | 1 /* NewLine */;
advanceNewline(parser);
break;
default:
state &= ~2 /* LastIsCR */;
parser.index++;
parser.column++;
}
}
// Unterminated multi-line comment.
tolerant(parser, context, 7 /* UnterminatedComment */);
}
function addComment(parser, context, type, start) {
const { index, startIndex, startLine, startColumn, lastLine, column } = parser;
const comment = {
type,
value: parser.source.slice(start, type === 'MultiLine' ? index - 2 : index),
start: startIndex,
end: index,
};
if (context & 16 /* OptionsLoc */) {
comment.loc = {
start: {
line: startLine,
column: startColumn,
},
end: {
line: lastLine,
column,
},
};
}
parser.comments.push(comment);
}
/**
* Scan
*
* @see [Link](https://tc39.github.io/ecma262/#sec-punctuatorss)
* @see [Link](https://tc39.github.io/ecma262/#sec-names-and-keywords)
*
* @param parser Parser object
* @param context Context masks
*/
function scan(parser, context) {
parser.flags &= ~1 /* NewLine */ | 32768 /* EscapedKeyword */;
const lineStart = parser.index === 0;
let state = 0 /* None */;
while (parser.index < parser.length) {
if (!lineStart) {
parser.startIndex = parser.index;
parser.startColumn = parser.column;
parser.startLine = parser.line;
}
const first = parser.source.charCodeAt(parser.index);
if (first > 128 /* MaxAsciiCharacter */) {
switch (first) {
case 8232 /* LineSeparator */:
case 8233 /* ParagraphSeparator */:
state = state & ~2 /* LastIsCR */ | 1 /* NewLine */;
advanceNewline(parser);
break;
case 65519 /* ByteOrderMark */:
case 160 /* NonBreakingSpace */:
case 5760 /* Ogham */:
case 8192 /* EnQuad */:
case 8193 /* EmQuad */:
case 8194 /* EnSpace */:
case 8195 /* EmSpace */:
case 8196 /* ThreePerEmSpace */:
case 8197 /* FourPerEmSpace */:
case 8198 /* SixPerEmSpace */:
case 8199 /* FigureSpace */:
case 8200 /* PunctuationSpace */:
case 8201 /* ThinSpace */:
case 8202 /* HairSpace */:
case 8239 /* NarrowNoBreakSpace */:
case 8287 /* MathematicalSpace */:
case 12288 /* IdeographicSpace */:
case 65279 /* Zwnbs */:
case 8205 /* Zwj */:
parser.index++;
parser.column++;
break;
default:
return scanMaybeIdentifier(parser, context, first);
}
}
else {
// Note: Here we first get rid of LT and WS, then we make sure that the lookup time
// for the single punctuator char is short as possible. A single punctuator
// char is a valid token that cannot also be a prefix of a combination
// of long tokens - e.g. '(', ')' and '=' is valid. '==' is not.
switch (first) {
case 13 /* CarriageReturn */:
state |= 1 /* NewLine */ | 2 /* LastIsCR */;
advanceNewline(parser);
break;
case 10 /* LineFeed */:
consumeLineFeed(parser, state);
state = state & ~2 /* LastIsCR */ | 1 /* NewLine */;
break;
case 9 /* Tab */:
case 11 /* VerticalTab */:
case 12 /* FormFeed */:
case 32 /* Space */:
parser.index++;
parser.column++;
break;
// `(`
case 40 /* LeftParen */:
parser.index++;
parser.column++;
return 50331659 /* LeftParen */;
// `)`
case 41 /* RightParen */:
parser.index++;
parser.column++;
return 16 /* RightParen */;
// `,`
case 44 /* Comma */:
parser.index++;
parser.column++;
return 16777234 /* Comma */;
// `:`
case 58 /* Colon */:
parser.index++;
parser.column++;
return 16777237 /* Colon */;
// `;`
case 59 /* Semicolon */:
parser.index++;
parser.column++;
return 17301521 /* Semicolon */;
// `?`
case 63 /* QuestionMark */:
parser.index++;
parser.column++;
return 22 /* QuestionMark */;
// `]`
case 93 /* RightBracket */:
parser.index++;
parser.column++;
return 20 /* RightBracket */;
// `{`
case 123 /* LeftBrace */:
parser.index++;
parser.column++;
return 41943052 /* LeftBrace */;
// `}`
case 125 /* RightBrace */:
parser.index++;
parser.column++;
return 17301519 /* RightBrace */;
// `~`
case 126 /* Tilde */:
parser.index++;
parser.column++;
return 301989934 /* Complement */;
// `[`
case 91 /* LeftBracket */:
parser.index++;
parser.column++;
return 41943059 /* LeftBracket */;
// `@`
case 64 /* At */:
parser.index++;
parser.column++;
return 120 /* At */;
// `/`, `/=`, `/>`
case 47 /* Slash */:
{
parser.index++;
parser.column++;
if (parser.index >= parser.length)
return 167774773 /* Divide */;
switch (parser.source.charCodeAt(parser.index)) {
case 47 /* Slash */:
{
parser.index++;
parser.column++;
state = skipSingleLineComment(parser, context, state, 'SingleLine');
continue;
}
case 42 /* Asterisk */:
{
parser.index++;
parser.column++;
state = skipMultiLineComment(parser, context, state);
continue;
}
case 61 /* EqualSign */:
{
parser.index++;
parser.column++;
return 100663333 /* DivideAssign */;
}
default:
return 167774773 /* Divide */;
}
}
// `-`, `--`, `-=`
case 45 /* Hyphen */:
{
parser.index++;
parser.column++; // skip `-`
const next = parser.source.charCodeAt(parser.index);
switch (next) {
case 45 /* Hyphen */:
{
parser.index++;
parser.column++;
if ((state & 1 /* NewLine */ || lineStart) &&
consumeOpt(parser, 62 /* GreaterThan */)) {
state = skipSingleHTMLComment(parser, context, state, 'HTMLClose');
continue;
}
return 570425372 /* Decrement */;
}
case 61 /* EqualSign */:
{
parser.index++;
parser.column++;
return 67108899 /* SubtractAssign */;
}
default:
return 436209968 /* Subtract */;
}
}
// `<`, `<=`, `<<`, `<<=`, `</`, <!--
case 60 /* LessThan */:
parser.index++;
parser.column++; // skip `<`
if (consumeOpt(parser, 33 /* Exclamation */) &&
consumeOpt(parser, 45 /* Hyphen */) &&
consumeOpt(parser, 45 /* Hyphen */)) {
state = skipSingleHTMLComment(parser, context, state, 'HTMLOpen');
continue;
}
switch (parser.source.charCodeAt(parser.index)) {
case 60 /* LessThan */:
parser.index++;
parser.column++;
return consumeOpt(parser, 61 /* EqualSign */) ?
67108894 /* ShiftLeftAssign */ :
167774273 /* ShiftLeft */;
case 61 /* EqualSign */:
parser.index++;
parser.column++;
return 167774013 /* LessThanOrEqual */;
case 47 /* Slash */:
{
if (!(context & 4 /* OptionsJSX */))
break;
const index = parser.index + 1;
// Check that it's not a comment start.
if (index < parser.length) {
const next = parser.source.charCodeAt(index);
if (next === 42 /* Asterisk */ || next === 47 /* Slash */)
break;
}
parser.index++;
parser.column++;
return 25 /* JSXClose */;
}
default: // ignore
return 167774015 /* LessThan */;
}
// `!`, `!=`, `!==`
case 33 /* Exclamation */:
parser.index++;
parser.column++;
if (!consumeOpt(parser, 61 /* EqualSign */))
return 301989933 /* Negate */;
if (!consumeOpt(parser, 61 /* EqualSign */))
return 167773756 /* LooseNotEqual */;
return 167773754 /* StrictNotEqual */;
// `'string'`, `"string"`
case 39 /* SingleQuote */:
case 34 /* DoubleQuote */:
return scanString(parser, context, first);
// `%`, `%=`
case 37 /* Percent */:
parser.index++;
parser.column++;
if (!consumeOpt(parser, 61 /* EqualSign */))
return 167774772 /* Modulo */;
return 67108902 /* ModuloAssign */;
// `&`, `&&`, `&=`
case 38 /* Ampersand */:
{
parser.index++;
parser.column++;
const next = parser.source.charCodeAt(parser.index);
if (next === 38 /* Ampersand */) {
parser.index++;
parser.column++;
return 169869879 /* LogicalAnd */;
}
if (next === 61 /* EqualSign */) {
parser.index++;
parser.column++;
return 67108905 /* BitwiseAndAssign */;
}
return 167773508 /* BitwiseAnd */;
}
// `*`, `**`, `*=`, `**=`
case 42 /* Asterisk */:
{
parser.index++;
parser.column++;
if (parser.index >= parser.length)
return 167774771 /* Multiply */;
const next = parser.source.charCodeAt(parser.index);
if (next === 61 /* EqualSign */) {
parser.index++;
parser.column++;
return 67108900 /* MultiplyAssign */;
}
if (next !== 42 /* Asterisk */)
return 167774771 /* Multiply */;
parser.index++;
parser.column++;
if (!consumeOpt(parser, 61 /* EqualSign */))
return 167775030 /* Exponentiate */;
return 67108897 /* ExponentiateAssign */;
}
// `+`, `++`, `+=`
case 43 /* Plus */:
{
parser.index++;
parser.column++;
if (parser.index >= parser.length)
return 436209967 /* Add */;
const next = parser.source.charCodeAt(parser.index);
if (next === 43 /* Plus */) {
parser.index++;
parser.column++;
return 570425371 /* Increment */;
}
if (next === 61 /* EqualSign */) {
parser.index++;
parser.column++;
return 67108898 /* AddAssign */;
}
return 436209967 /* Add */;
}
// `\\u{N}var`
case 92 /* Backslash */:
return scanIdentifier(parser, context);
// `=`, `==`, `===`, `=>`
case 61 /* EqualSign */:
{
parser.index++;
parser.column++;
const next = parser.source.charCodeAt(parser.index);
if (next === 61 /* EqualSign */) {
parser.index++;
parser.column++;
if (consumeOpt(parser, 61 /* EqualSign */)) {
return 167773753 /* StrictEqual */;
}
else {
return 167773755 /* LooseEqual */;
}
}
else if (next === 62 /* GreaterThan */) {
parser.index++;
parser.column++;
return 10 /* Arrow */;
}
return 83886109 /* Assign */;
}
// `>`, `>=`, `>>`, `>>>`, `>>=`, `>>>=`
case 62 /* GreaterThan */:
{
parser.index++;
parser.column++;
if (parser.index >= parser.length)
return 167774016 /* GreaterThan */;
if (context & 268435456 /* InJSXChild */)
return 167774016 /* GreaterThan */;
let next = parser.source.charCodeAt(parser.index);
if (next === 61 /* EqualSign */) {
parser.index++;
parser.column++;
return 167774014 /* GreaterThanOrEqual */;
}
if (next !== 62 /* GreaterThan */)
return 167774016 /* GreaterThan */;
parser.index++;
parser.column++;
next = parser.source.charCodeAt(parser.index);
if (next === 62 /* GreaterThan */) {
parser.index++;
parser.column++;
if (consumeOpt(parser, 61 /* EqualSign */)) {
return 67108896 /* LogicalShiftRightAssign */;
}
else {
return 167774275 /* LogicalShiftRight */;
}
}
else if (next === 61 /* EqualSign */) {
parser.index++;
parser.column++;
return 67108895 /* ShiftRightAssign */;
}
return 167774274 /* ShiftRight */;
}
// `^`, `^=`
case 94 /* Caret */:
parser.index++;
parser.column++;
if (!consumeOpt(parser, 61 /* EqualSign */))
return 167773254 /* BitwiseXor */;
return 67108903 /* BitwiseXorAssign */;
// ``string``
case 96 /* Backtick */:
return scanTemplate(parser, context);
// `|`, `||`, `|=`
case 124 /* VerticalBar */:
{
parser.index++;
parser.column++;
const next = parser.source.charCodeAt(parser.index);
if (next === 124 /* VerticalBar */) {
parser.index++;
parser.column++;
return 169869624 /* LogicalOr */;
}
else if (next === 61 /* EqualSign */) {
parser.index++;
parser.column++;
return 67108904 /* BitwiseOrAssign */;
}
return 167772997 /* BitwiseOr */;
}
// `.`, `...`, `.123` (numeric literal)
case 46 /* Period */:
{
let index = parser.index + 1;
const next = parser.source.charCodeAt(index);
if (next >= 48 /* Zero */ && next <= 57 /* Nine */) {
scanNumericLiteral(parser, context, 4 /* Float */);
return 33554434 /* NumericLiteral */;
}
else if (next === 46 /* Period */) {
index++;
if (index < parser.length &&
parser.source.charCodeAt(index) === 46 /* Period */) {
parser.index = index + 1;
parser.column += 3;
return 14 /* Ellipsis */;
}
}
parser.index++;
parser.column++;
return 16777229 /* Period */;
}
// `#`
case 35 /* Hash */:
{
parser.index++;
parser.column++;
const index = parser.index;
const next = parser.source.charCodeAt(index);
if (context & 128 /* OptionsShebang */ &&
lineStart &&
next === 33 /* Exclamation */) {
parser.index = index + 1;
skipSingleLineComment(parser, context, 0 /* None */, 'SheBang');
continue;
}
return scanPrivateName(parser, context);
}
// `0`...`9`
case 48 /* Zero */:
{
parser.index++;
parser.column++;
switch (parser.source.charCodeAt(parser.index)) {
// Hex number - '0x', '0X'
case 88 /* UpperX */:
case 120 /* LowerX */:
return scanHexIntegerLiteral(parser, context);
// Binary number - '0b', '0B'
case 66 /* UpperB */:
case 98 /* LowerB */:
return scanOctalOrBinary(parser, context, 2);
// Octal number - '0o', '0O'
case 79 /* UpperO */:
case 111 /* LowerO */:
return scanOctalOrBinary(parser, context, 8);
default:
// Implicit octal digits startign with '0'
return scanImplicitOctalDigits(parser, context);
}
}
case 49 /* One */:
case 50 /* Two */:
case 51 /* Three */:
case 52 /* Four */:
case 53 /* Five */:
case 54 /* Six */:
case 55 /* Seven */:
case 56 /* Eight */:
case 57 /* Nine */:
return scanNumericLiteral(parser, context);
// `a`...`z`, `A`...`Z`, `_var`, `$var`
case 65 /* UpperA */:
case 66 /* UpperB */:
case 67 /* UpperC */:
case 68 /* UpperD */:
case 69 /* UpperE */:
case 70 /* UpperF */:
case 71 /* UpperG */:
case 72 /* UpperH */:
case 73 /* UpperI */:
case 74 /* UpperJ */:
case 75 /* UpperK */:
case 76 /* UpperL */:
case 77 /* UpperM */:
case 78 /* UpperN */:
case 79 /* UpperO */:
case 80 /* UpperP */:
case 81 /* UpperQ */:
case 82 /* UpperR */:
case 83 /* UpperS */:
case 84 /* UpperT */:
case 85 /* UpperU */:
case 86 /* UpperV */:
case 87 /* UpperW */:
case 88 /* UpperX */:
case 89 /* UpperY */:
case 90 /* UpperZ */:
case 36 /* Dollar */:
case 95 /* Underscore */:
case 97 /* LowerA */:
case 98 /* LowerB */:
case 99 /* LowerC */:
case 100 /* LowerD */:
case 101 /* LowerE */:
case 102 /* LowerF */:
case 103 /* LowerG */:
case 104 /* LowerH */:
case 105 /* LowerI */:
case 106 /* LowerJ */:
case 107 /* LowerK */:
case 108 /* LowerL */:
case 109 /* LowerM */:
case 110 /* LowerN */:
case 111 /* LowerO */:
case 112 /* LowerP */:
case 113 /* LowerQ */:
case 114 /* LowerR */:
case 115 /* LowerS */:
case 116 /* LowerT */:
case 117 /* LowerU */:
case 118 /* LowerV */:
case 119 /* LowerW */:
case 120 /* LowerX */:
case 121 /* LowerY */:
case 122 /* LowerZ */:
default:
return scanIdentifier(parser, context, first);
}
}
}
return 524288 /* EndOfSource */;
}
/**
* Validate break and continue statement
*
* @param parser Parser object
* @param label label
* @param isContinue true if validation continue statement
*/
function validateBreakOrContinueLabel(parser, context, label, isContinue) {
const state = hasLabel(parser, label);
if (!state)
tolerant(parser, context, 30 /* UnknownLabel */, label);
if (isContinue && !(state & 2 /* Nested */))
tolerant(parser, context, 29 /* IllegalContinue */, label);
}
/**
* Add label to the stack
*
* @param parser Parser object
* @param label label
*/
function addLabel(parser, label) {
if (parser.labelSet === undefined)
parser.labelSet = {};
parser.labelSet[`$${label}`] = parser.token & 16 /* IsIterationStatement */ ? 2 /* Nested */ : 1 /* NotNested */;
}
/**
* Remove label from the stack
*
* @param parser Parser object
* @param label label
*/
function popLabel(parser, label) {
parser.labelSet[`$${label}`] = 0 /* None */;
}
/**
* Returns either true or false. Depends if the label exist.
*
* @param parser Parser object
* @param label Label
*/
function hasLabel(parser, label) {
return !parser.labelSet ? 0 /* None */ : parser.labelSet[`$${label}`];
}
/**
* Finish each the node for each parse. Set line / and column on the node if the
* options are set for it
*
* @param parser Parser object
* @param context Context masks
* @param meta Line / column
* @param node AST node
*/
function finishNode(context, parser, meta, node) {
const { lastIndex, lastLine, lastColumn, sourceFile, index } = parser;
if (context & 2 /* OptionsRanges */) {
node.start = meta.index;
node.end = lastIndex;
}
if (context & 16 /* OptionsLoc */) {
node.loc = {
start: {
line: meta.line,
column: meta.column
},
end: {
line: lastLine,
column: lastColumn
}
};
if (sourceFile)
node.loc.source = sourceFile;
}
return node;
}
/**
* Consumes the next token. If the consumed token is not of the expected type
* then report an error and return null. Otherwise return true.
*
* @param parser Parser object
* @param context Context masks
* @param t Token
* @param Err Optionally error message to be thrown
*/
function expect(parser, context, token, err = 1 /* UnexpectedToken */) {
if (parser.token !== token)
report(parser, err, tokenDesc(parser.token));
nextToken(parser, context);
return true;
}
/**
* If the next token matches the given token, this consumes the token
* and returns true. Otherwise return false.
*
* @param parser Parser object
* @param context Context masks
* @param t Token
*/
function consume(parser, context, token) {
if (parser.token !== token)
return false;
nextToken(parser, context);
return true;
}
/**
* Advance and return the next token in the stream
*
* @param parser Parser object
* @param context Context masks
*/
function nextToken(parser, context) {
parser.lastIndex = parser.index;
parser.lastLine = parser.line;
parser.lastColumn = parser.column;
return (parser.token = scan(parser, context));
}
const hasBit = (mask, flags) => (mask & flags) === flags;
/**
* Automatic Semicolon Insertion
*
* @see [Link](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion)
*
* @param parser Parser object
* @param context Context masks
*/
function consumeSemicolon(parser, context) {
return parser.token & 524288 /* ASI */ || parser.flags & 1 /* NewLine */
? consume(parser, context, 17301521 /* Semicolon */)
: report(parser, !(context & 131072 /* Async */) && parser.token & 131072 /* IsAwait */ ? 36 /* AwaitOutsideAsync */ : 1 /* UnexpectedToken */, tokenDesc(parser.token));
}
/**
* Bit fiddle current grammar state and keep track of the state during the parse and restore
* it back to original state after finish parsing or throw.
*
* Ideas for this is basicly from V8 and SM, but also the Esprima parser does this in a similar way.
*
* However this implementation is an major improvement over similiar implementations, and
* does not require additonal bitmasks to be set / unset during the parsing outside this function.
*
* @param parser Parser state
* @param context Context mask
* @param callback Callback function
* @param errMsg Optional error message
*/
function parseExpressionCoverGrammar(parser, context, callback) {
const { flags, pendingExpressionError } = parser;
parser.flags |= 2 /* AllowBinding */ | 4 /* AllowDestructuring */;
parser.pendingExpressionError = undefined;
const res = callback(parser, context);
// If there exist an pending expression error, we throw an error at
// the same location it was recorded
if (!!parser.pendingExpressionError) {
const { error, line, column, index } = parser.pendingExpressionError;
constructError(parser, context, index, line, column, error);
}
// Here we - just in case - disallow both binding and destructuring
// and only set the bitmaks if the previous flags (before the callback)
// is positive.
// Note that this bitmasks may have been turned off during parsing
// the callback
parser.flags &= ~(2 /* AllowBinding */ | 4 /* AllowDestructuring */);
if (flags & 2 /* AllowBinding */)
parser.flags |= 2 /* AllowBinding */;
if (flags & 4 /* AllowDestructuring */)
parser.flags |= 4 /* AllowDestructuring */;
parser.pendingExpressionError = pendingExpressionError;
return res;
}
/**
* Restor current grammar to previous state, or unset necessary bitmasks
*
* @param parser Parser state
* @param context Context mask
* @param callback Callback function
*/
function restoreExpressionCoverGrammar(parser, context, callback) {
const { flags, pendingExpressionError } = parser;
parser.flags |= 2 /* AllowBinding */ | 4 /* AllowDestructuring */;
// Clear pending expression error
parser.pendingExpressionError = undefined;
const res = callback(parser, context);
// Both the previous bitmasks and bitmasks set during parsing the callback
// has to be positive for us to allow further binding or destructuring.
// Note that we allow both before the callback, so this is the only thing
// we need to check for.
if (!(parser.flags & 2 /* AllowBinding */) || !(flags & 2 /* AllowBinding */)) {
parser.flags &= ~2 /* AllowBinding */;
}
if (!(parser.flags & 4 /* AllowDestructuring */) || !(flags & 4 /* AllowDestructuring */)) {
parser.flags &= ~4 /* AllowDestructuring */;
}
// Here we either
// 1) restore to previous pending expression error
// or
// 2) if a pending expression error have been set during the parse (*only in object literal*)
// we overwrite previous error, and keep the new one
parser.pendingExpressionError = pendingExpressionError || parser.pendingExpressionError;
return res;
}
/**
* Set / unset yield / await context masks based on the
* ModifierState masks before invoking the callback and
* returning it's content
*
* @param parser Parser object
* @param context Context masks
* @param state Modifier state
* @param callback Callback function to be invoked
* @param methodState Optional Objectstate.
*/
function swapContext(parser, context, state, callback, methodState = 0 /* None */) {
context &= ~(131072 /* Async */ | 262144 /* Yield */ | 524288 /* InParameter */);
if (state & 1 /* Generator */)
context |= 262144 /* Yield */;
if (state & 2 /* Await */)
context |= 131072 /* Async */;
return callback(parser, context, methodState);
}
/**
* Validates function params
*
* Note! In case anyone want to enable full scoping, replace 'paramSet' with an similiar
* object on the parser object itself. Then push / set the tokenValue to
* it an use an bitmask to mark it as an 'variable' not 'blockscope'. Then when
* implementing lexical scoping, you can use that for validation.
*
* @param parser Parser object
* @param context Context masks
* @param params Array of token values
*/
function validateParams(parser, context, params) {
const paramSet = new Map();
for (let i = 0; i < params.length; i++) {
const key = `@${params[i]}`;
if (paramSet.get(key)) {
tolerant(parser, context, 79 /* ParamDupe */);
}
else
paramSet.set(key, true);
}
}
/**
* Reinterpret various expressions as pattern
* This is only used for assignment and arrow parameter list
*
* @param parser Parser object
* @param context Context masks
* @param node AST node
*/
const reinterpret = (parser, context, node) => {
switch (node.type) {
case 'Identifier':
case 'ArrayPattern':
case 'AssignmentPattern':
case 'ObjectPattern':
case 'RestElement':
case 'MetaProperty':
return;
case 'ArrayExpression':
node.type = 'ArrayPattern';
for (let i = 0; i < node.elements.length; ++i) {
// skip holes in pattern
if (node.elements[i] !== null) {
reinterpret(parser, context, node.elements[i]);
}
}
return;
case 'ObjectExpression':
node.type = 'ObjectPattern';
for (let i = 0; i < node.properties.length; i++) {
reinterpret(parser, context, node.properties[i]);
}
return;
case 'Property':
reinterpret(parser, context, node.value);
return;
case 'SpreadElement':
node.type = 'RestElement';
if (node.argument.type !== 'ArrayExpression' &&
node.argument.type !== 'ObjectExpression' &&
!isValidSimpleAssignmentTarget(node.argument)) {
tolerant(parser, context, 69 /* RestDefaultInitializer */);
}
reinterpret(parser, context, node.argument);
break;
case 'AssignmentExpression':
node.type = 'AssignmentPattern';
delete node.operator; // operator is not relevant for assignment pattern
reinterpret(parser, context, node.left); // recursive descent
return;
case 'MemberExpression':
if (!(context & 524288 /* InParameter */))
return;
// Fall through
default:
tolerant(parser, context, context & 524288 /* InParameter */ ? 75 /* NotBindable */ : 71 /* InvalidDestructuringTarget */, node.type);
}
};
/**
* Does a lookahead.
*
* @param parser Parser object
* @param context Context masks
* @param callback Callback function to be invoked
*/
function lookahead(parser, context, callback) {
const { tokenValue, flags, line, column, startColumn, index, lastColumn, startLine, lastLine, lastIndex, startIndex, tokenRaw, token, lastValue, tokenRegExp } = parser;
const res = callback(parser, context);
parser.index = index;
parser.token = token;
parser.tokenValue = tokenValue;
parser.tokenValue = tokenValue;
parser.flags = flags;
parser.line = line;
parser.column = column;
parser.tokenRaw = tokenRaw;
parser.lastValue = lastValue;
parser.startColumn = startColumn;
parser.lastColumn = lastColumn;
parser.startLine = startLine;
parser.lastLine = lastLine;
parser.lastIndex = lastIndex;
parser.startIndex = startIndex;
parser.tokenRegExp = tokenRegExp;
return res;
}
/**
* Returns true if this an valid simple assignment target
*
* @param parser Parser object
* @param context Context masks
*/
function isValidSimpleAssignmentTarget(node) {
return node.type === 'Identifier' || node.type === 'MemberExpression' ? true : false;
}
/**
* Get current node location
*
* @param parser Parser object
* @param context Context masks
*/
function getLocation(parser) {
return {
line: parser.startLine,
column: parser.startColumn,
index: parser.startIndex
};
}
/**
* Returns true if this is an valid identifier
*
* @param context Context masks
* @param t Token
*/
function isValidIdentifier(context, t) {
if (context & 4096 /* Strict */) {
if (context & 8192 /* Module */ && t & 131072 /* IsAwait */)
return false;
if (t & 1073741824 /* IsYield */)
return false;
return (t & 65536 /* IsIdentifier */) === 65536 /* IsIdentifier */ || (t & 36864 /* Contextual */) === 36864 /* Contextual */;
}
return ((t & 65536 /* IsIdentifier */) === 65536 /* IsIdentifier */ ||
(t & 36864 /* Contextual */) === 36864 /* Contextual */ ||
(t & 20480 /* FutureReserved */) === 20480 /* FutureReserved */);
}
/**
* Returns true if this an valid lexical binding and not an identifier
*
* @param parser Parser object
* @param context Context masks
*/
function isLexical(parser, context) {
nextToken(parser, context);
const { token } = parser;
return !!(token & (65536 /* IsIdentifier */ | 8388608 /* IsBindingPattern */ | 1073741824 /* IsYield */ | 131072 /* IsAwait */) ||
token === 33574984 /* LetKeyword */ ||
(token & 36864 /* Contextual */) === 36864 /* Contextual */);
}
/**
* Returns true if this is end of case or default clauses
*
* @param parser Parser object
*/
function isEndOfCaseOrDefaultClauses(parser) {
return (parser.token === 12368 /* DefaultKeyword */ || parser.token === 17301519 /* RightBrace */ || parser.token === 12363 /* CaseKeyword */);
}
/**
* Validates if the next token in the stream is a left paren or a period
*
* @param parser Parser object
* @param context Context masks
*/
function nextTokenIsLeftParenOrPeriod(parser, context) {
nextToken(parser, context);
return parser.token === 50331659 /* LeftParen */ || parser.token === 16777229 /* Period */;
}
/**
* Validates if the next token in the stream is a identifier or left paren
*
* @param parser Parser object
* @param context Context masks
*/
function nextTokenisIdentifierOrParen(parser, context) {
nextToken(parser, context);
const { token } = parser;
return token & (65536 /* IsIdentifier */ | 1073741824 /* IsYield */) || token === 50331659 /* LeftParen */;
}
/**
* Validates if the next token in the stream is left parenthesis.
*
* @param parser Parser object
* @param context Context masks
*/
function nextTokenIsLeftParen(parser, context) {
nextToken(parser, context);
return parser.token === 50331659 /* LeftParen */;
}
/**
* Validates if the next token in the stream is a function keyword on the same line.
*
* @param parser Parser object
* @param context Context masks
*/
function nextTokenIsFuncKeywordOnSameLine(parser, context) {
nextToken(parser, context);
return !(parser.flags & 1 /* NewLine */) && parser.token === 33566808 /* FunctionKeyword */;
}
/**
* Checks if the property has any private field key
*
* @param parser Parser object
* @param context Context masks
*/
function isPropertyWithPrivateFieldKey(expr) {
return !expr.property ? false : expr.property.type === 'PrivateName';
}
/**
* Validates an identifier and either parse it or throw
*
* @param parser Parser object
* @param context Context masks
*/
function parseAndValidateIdentifier(parser, context) {
const { token } = parser;
if (context & 4096 /* Strict */) {
// Module code is also "strict mode code"
if (context & 8192 /* Module */ && token & 131072 /* IsAwait */) {
tolerant(parser, context, 38 /* DisallowedInContext */, tokenDesc(token));
}
if (token & 1073741824 /* IsYield */)
tolerant(parser, context, 38 /* DisallowedInContext */, tokenDesc(token));
if ((token & 65536 /* IsIdentifier */) === 65536 /* IsIdentifier */ || (token & 36864 /* Contextual */) === 36864 /* Contextual */) {
return parseIdentifier(parser, context);
}
report(parser, 1 /* UnexpectedToken */, tokenDesc(token));
}
if (context & 262144 /* Yield */ && token & 1073741824 /* IsYield */) {
tolerant(parser, context, 38 /* DisallowedInContext */, tokenDesc(token));
}
else if (context & 131072 /* Async */ && token & 131072 /* IsAwait */) {
tolerant(parser, context, 38 /* DisallowedInContext */, tokenDesc(token));
}
if ((token & 65536 /* IsIdentifier */) === 65536 /* IsIdentifier */ ||
(token & 36864 /* Contextual */) === 36864 /* Contextual */ ||
(token & 20480 /* FutureReserved */) === 20480 /* FutureReserved */) {
return parseIdentifier(parser, context);
}
report(parser, 1 /* UnexpectedToken */, tokenDesc(parser.token));
}
function nameIsArgumentsOrEval(value) {
return value === 'eval' || value === 'arguments';
}
/**
* Records an error from current position. If we report an error later, we'll do it from
* this position.
*
* @param parser Parser object
*/
function setPendingError(parser) {
parser.errorLocation = {
line: parser.startLine,
column: parser.startColumn,
index: parser.startIndex
};
}
/**
* Returns tagName for JSX element
*
* @param elementName JSX Element name
*/
function isEqualTagNames(elementName) {
// tslint:disable-next-line:switch-default | this switch is exhaustive
switch (elementName.type) {
case 'JSXIdentifier':
return elementName.name;
case 'JSXNamespacedName':
return `${isEqualTagNames(elementName.namespace)}:${isEqualTagNames(elementName.name)}`;
case 'JSXMemberExpression':
return `${isEqualTagNames(elementName.object)}.${isEqualTagNames(elementName.property)}`;
}
}
/**
* Returns true if this is an instance field ( stage 3 proposal)
*
* @param parser Parser object
*/
function isInstanceField(parser) {
const { token } = parser;
return token === 17301519 /* RightBrace */ || token === 17301521 /* Semicolon */ || token === 83886109 /* Assign */;
}
/**
*
* @param parser Parser object
* @param context Context masks
* @param expr AST expressions
* @param prefix prefix
*/
function validateUpdateExpression(parser, context, expr, prefix) {
if (context & 4096 /* Strict */ && nameIsArgumentsOrEval(expr.name)) {
tolerant(parser, context, 66 /* StrictLHSPrefixPostFix */, prefix);
}
if (!isValidSimpleAssignmentTarget(expr)) {
tolerant(parser, context, 4 /* InvalidLHSInAssignment */);
}
}
/**
* Record expression error
*
* @param parser Parser object
* @param error Error message
*/
function setPendingExpressionError(parser, type) {
parser.pendingExpressionError = {
error: errorMessages[type],
line: parser.line,
column: parser.column,
index: parser.index
};
}
/**
* Validate coer parenthesized expression
*
* @param parser Parser object
* @param state CoverParenthesizedState
*/
function validateCoverParenthesizedExpression(parser, state) {
const { token } = parser;
if (token & 8388608 /* IsBindingPattern */) {
parser.flags |= 8 /* SimpleParameterList */;
}
else {
if ((token & 4194304 /* IsEvalOrArguments */) === 4194304 /* IsEvalOrArguments */) {
setPendingError(parser);
state |= 2 /* HasEvalOrArguments */;
}
else if ((token & 20480 /* FutureReserved */) === 20480 /* FutureReserved */) {
setPendingError(parser);
state |= 4 /* HasReservedWords */;
}
else if ((token & 131072 /* IsAwait */) === 131072 /* IsAwait */) {
setPendingError(parser);
parser.flags |= 8192 /* HasAwait */;
}
}
return state;
}
/**
* Validate coer parenthesized expression
*
* @param parser Parser object
* @param state CoverParenthesizedState
*/
function validateAsyncArgumentList(parser, context, state) {
const { token } = parser;
if (!(parser.flags & 2 /* AllowBinding */)) {
tolerant(parser, context, 75 /* NotBindable */);
}
else if (token & 8388608 /* IsBindingPattern */) {
parser.flags |= 8 /* SimpleParameterList */;
}
else {
if ((token & 4194304 /* IsEvalOrArguments */) === 4194304 /* IsEvalOrArguments */) {
setPendingError(parser);
state |= 8 /* EvalOrArguments */;
}
else if ((token & 131072 /* IsAwait */) === 131072 /* IsAwait */) {
setPendingError(parser);
state |= 32 /* Await */;
}
else if ((token & 1073741824 /* IsYield */) === 1073741824 /* IsYield */) {
setPendingError(parser);
state |= 16 /* Yield */;
}
}
return state;
}
// JSX Specification
// https://facebook.github.io/jsx/
/**
* Parses JSX element or JSX fragment
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXRootElement(parser, context) {
const pos = getLocation(parser);
let children = [];
let closingElement = null;
let selfClosing = false;
let openingElement;
expect(parser, context, 167774015 /* LessThan */);
const isFragment = parser.token === 167774016 /* GreaterThan */;
if (isFragment) {
openingElement = parseJSXOpeningFragment(parser, context, pos);
}
else {
const name = parseJSXElementName(parser, context);
const attributes = parseJSXAttributes(parser, context);
selfClosing = consume(parser, context, 167774773 /* Divide */);
openingElement = parseJSXOpeningElement(parser, context, name, attributes, selfClosing, pos);
}
if (isFragment)
return parseJSXFragment(parser, context, openingElement, pos);
if (!selfClosing) {
children = parseJSXChildren(parser, context);
closingElement = parseJSXClosingElement(parser, context);
const open = isEqualTagNames(openingElement.name);
const close = isEqualTagNames(closingElement.name);
if (open !== close)
report(parser, 83 /* ExpectedJSXClosingTag */, close);
}
return finishNode(context, parser, pos, {
type: 'JSXElement',
children,
openingElement,
closingElement,
});
}
/**
* Parses JSX opening element
*
* @param parser Parser object
* @param context Context masks
* @param name Element name
* @param attributes Element attributes
* @param selfClosing True if this is a selfclosing JSX Element
* @param pos Line / Column tracking
*/
function parseJSXOpeningElement(parser, context, name, attributes, selfClosing, pos) {
if (context & 268435456 /* InJSXChild */ && selfClosing)
expect(parser, context, 167774016 /* GreaterThan */);
else
nextJSXToken(parser);
return finishNode(context, parser, pos, {
type: 'JSXOpeningElement',
name,
attributes,
selfClosing,
});
}
/**
* Parse JSX fragment
*
* @param parser Parser object
* @param context Context masks
* @param openingElement Opening fragment
* @param pos Line / Column location
*/
function parseJSXFragment(parser, context, openingElement, pos) {
const children = parseJSXChildren(parser, context);
const closingFragment = parseJSXClosingFragment(parser, context);
return finishNode(context, parser, pos, {
type: 'JSXFragment',
children,
openingElement,
closingFragment,
});
}
/**
* Parse JSX opening fragmentD
*
* @param parser Parser object
* @param context Context masks
* @param pos Line / Column location
*/
function parseJSXOpeningFragment(parser, context, pos) {
nextJSXToken(parser);
return finishNode(context, parser, pos, {
type: 'JSXOpeningFragment',
});
}
/**
* Prime the scanner and advance to the next JSX token in the stream
*
* @param parser Parser object
* @param context Context masks
*/
function nextJSXToken(parser) {
return parser.token = scanJSXToken(parser);
}
/**
* Mini scanner
*
* @param parser Parser object
* @param context Context masks
*/
function scanJSXToken(parser) {
if (parser.index >= parser.source.length)
return 524288 /* EndOfSource */;
parser.lastIndex = parser.startIndex = parser.index;
const char = parser.source.charCodeAt(parser.index);
if (char === 60 /* LessThan */) {
parser.index++;
parser.column++;
return consumeOpt(parser, 47 /* Slash */) ? 25 /* JSXClose */ : 167774015 /* LessThan */;
}
else if (char === 123 /* LeftBrace */) {
parser.index++;
parser.column++;
return 41943052 /* LeftBrace */;
}
while (parser.index < parser.source.length) {
parser.index++;
parser.column++;
const next = parser.source.charCodeAt(parser.index);
if (next === 123 /* LeftBrace */ || next === 60 /* LessThan */)
break;
}
return 121 /* JSXText */;
}
/**
* Parses JSX children
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXChildren(parser, context) {
const children = [];
while (parser.token !== 25 /* JSXClose */) {
children.push(parseJSXChild(parser, context));
}
return children;
}
/**
* Parses JSX Text
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXText(parser, context) {
const pos = getLocation(parser);
const value = parser.source.slice(parser.startIndex, parser.index);
parser.token = scanJSXToken(parser);
const node = finishNode(context, parser, pos, {
type: 'JSXText',
value,
});
if (context & 8 /* OptionsRaw */)
node.raw = value;
return node;
}
/**
* Parses JSX Child
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXChild(parser, context) {
switch (parser.token) {
case 33619969 /* Identifier */:
case 121 /* JSXText */:
return parseJSXText(parser, context);
case 41943052 /* LeftBrace */:
return parseJSXExpression(parser, context & ~268435456 /* InJSXChild */);
case 167774015 /* LessThan */:
return parseJSXRootElement(parser, context & ~268435456 /* InJSXChild */);
default:
report(parser, 0 /* Unexpected */);
}
return undefined; // note: get rid of this
}
/**
* Parses JSX attributes
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXAttributes(parser, context) {
const attributes = [];
while (parser.index < parser.source.length) {
if (parser.token === 167774773 /* Divide */ || parser.token === 167774016 /* GreaterThan */)
break;
attributes.push(parseJSXAttribute(parser, context));
}
return attributes;
}
/**
* Parses JSX spread attribute
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXSpreadAttribute(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 41943052 /* LeftBrace */);
expect(parser, context, 14 /* Ellipsis */);
const expression = parseExpressionCoverGrammar(parser, context & ~268435456 /* InJSXChild */, parseAssignmentExpression);
expect(parser, context, 17301519 /* RightBrace */);
return finishNode(context, parser, pos, {
type: 'JSXSpreadAttribute',
argument: expression,
});
}
/**
* Parses JSX namespace name
*
* @param parser Parser object
* @param context Context masks
* @param namespace Identifier
* @param pos Line / Column location
*/
function parseJSXNamespacedName(parser, context, namespace, pos) {
expect(parser, context, 16777237 /* Colon */);
const name = parseJSXIdentifier(parser, context);
return finishNode(context, parser, pos, {
type: 'JSXNamespacedName',
namespace,
name,
});
}
/**
* Parses JSX attribute name
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXAttributeName(parser, context) {
const pos = getLocation(parser);
const identifier = parseJSXIdentifier(parser, context);
return parser.token === 16777237 /* Colon */ ?
parseJSXNamespacedName(parser, context, identifier, pos) :
identifier;
}
/**
* Parses JSX Attribute value
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXAttributeValue(parser, context) {
switch (scanJSXAttributeValue(parser, context)) {
case 33554435 /* StringLiteral */:
return parseLiteral(parser, context);
case 41943052 /* LeftBrace */:
return parseJSXExpressionContainer(parser, context | 268435456 /* InJSXChild */);
case 167774015 /* LessThan */:
return parseJSXRootElement(parser, context | 268435456 /* InJSXChild */);
default:
tolerant(parser, context, 85 /* InvalidJSXAttributeValue */);
}
return undefined; // note: get rid of this
}
/**
* Parses JSX Attribute
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXAttribute(parser, context) {
const pos = getLocation(parser);
if (parser.token === 41943052 /* LeftBrace */)
return parseJSXSpreadAttribute(parser, context);
scanJSXIdentifier(parser);
const attrName = parseJSXAttributeName(parser, context);
const value = parser.token === 83886109 /* Assign */ ? parseJSXAttributeValue(parser, context) : null;
return finishNode(context, parser, pos, {
type: 'JSXAttribute',
value: value,
name: attrName,
});
}
/**
* Parses JSX Attribute value
*
* @param parser Parser object
* @param context Context masks
*/
function scanJSXAttributeValue(parser, context) {
parser.lastIndex = parser.index;
const ch = parser.source.charCodeAt(parser.index);
switch (ch) {
case 34 /* DoubleQuote */:
case 39 /* SingleQuote */:
return scanJSXString(parser, context, ch);
default:
return nextToken(parser, context);
}
}
/**
* Parses JSX String
*
* @param parser Parser object
* @param context Context masks
* @param quote Code point
*/
function scanJSXString(parser, context, quote) {
const rawStart = parser.index;
parser.index++;
parser.column++;
let ret = '';
let ch = parser.source.charCodeAt(parser.index);
while (ch !== quote) {
ret += fromCodePoint(ch);
parser.index++;
parser.column++;
ch = parser.source.charCodeAt(parser.index);
if (parser.index >= parser.source.length)
report(parser, 5 /* UnterminatedString */);
}
parser.index++;
parser.column++; // skip the quote
// raw
if (context & 8 /* OptionsRaw */)
parser.tokenRaw = parser.source.slice(rawStart, parser.index);
parser.tokenValue = ret;
return 33554435 /* StringLiteral */;
}
/**
* Parses JJSX Empty Expression
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXEmptyExpression(parser, context) {
const pos = getLocation(parser);
return finishNode(context, parser, pos, {
type: 'JSXEmptyExpression',
});
}
/**
* Parses JSX Spread child
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXSpreadChild(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 14 /* Ellipsis */);
const expression = parseExpression(parser, context);
expect(parser, context, 17301519 /* RightBrace */);
return finishNode(context, parser, pos, {
type: 'JSXSpreadChild',
expression,
});
}
/**
* Parses JSX Expression container
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXExpressionContainer(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 41943052 /* LeftBrace */);
// Note: JSX Expressions can't be empty
if (parser.token === 17301519 /* RightBrace */)
tolerant(parser, context, 82 /* NonEmptyJSXExpression */);
const expression = parseExpressionCoverGrammar(parser, context & ~268435456 /* InJSXChild */, parseAssignmentExpression);
expect(parser, context, 17301519 /* RightBrace */);
return finishNode(context, parser, pos, {
type: 'JSXExpressionContainer',
expression,
});
}
/**
* Parses JSX Expression
*
* @param parser Parser object
* @param context Context masks
* @param pos Line / Column location
*/
function parseJSXExpression(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 41943052 /* LeftBrace */);
if (parser.token === 14 /* Ellipsis */)
return parseJSXSpreadChild(parser, context);
const expression = parser.token === 17301519 /* RightBrace */ ?
parseJSXEmptyExpression(parser, context) :
parseExpressionCoverGrammar(parser, context, parseAssignmentExpression);
nextJSXToken(parser);
return finishNode(context, parser, pos, {
type: 'JSXExpressionContainer',
expression,
});
}
/**
* Parses JSX Closing fragment
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXClosingFragment(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 25 /* JSXClose */);
expect(parser, context, 167774016 /* GreaterThan */);
return finishNode(context, parser, pos, {
type: 'JSXClosingFragment',
});
}
/**
* Parses JSX Closing Element
*
* @param parser Parser object
* @param context Context masks
* @param pos Line / Column location
*/
function parseJSXClosingElement(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 25 /* JSXClose */);
const name = parseJSXElementName(parser, context);
if (context & 268435456 /* InJSXChild */)
expect(parser, context, 167774016 /* GreaterThan */);
else
nextJSXToken(parser);
return finishNode(context, parser, pos, {
type: 'JSXClosingElement',
name,
});
}
/**
* Parses JSX Identifier
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXIdentifier(parser, context) {
const { token, tokenValue: name, tokenRaw: raw } = parser;
if (!(token & (65536 /* IsIdentifier */ | 4096 /* Keyword */))) {
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(parser.token));
}
const pos = getLocation(parser);
nextToken(parser, context);
const node = finishNode(context, parser, pos, {
type: 'JSXIdentifier',
name,
});
if (context & 256 /* OptionsRawidentifiers */)
node.raw = raw;
return node;
}
/**
* Parses JSX Member expression
*
* @param parser Parser object
* @param context Context masks
* @param pos Line / Column location
*/
function parseJSXMemberExpression(parser, context, expr, pos) {
// Note: In order to be able to parse cases like ''<A.B.C.D.E.foo-bar />', where the dash is located at the
// end, we must rescan for the JSX Identifier now. This because JSX identifiers differ from normal identifiers
scanJSXIdentifier(parser);
return finishNode(context, parser, pos, {
type: 'JSXMemberExpression',
object: expr,
property: parseJSXIdentifier(parser, context),
});
}
/**
* Parses JSX Element name
*
* @param parser Parser object
* @param context Context masks
*/
function parseJSXElementName(parser, context) {
const pos = getLocation(parser);
scanJSXIdentifier(parser);
let elementName = parseJSXIdentifier(parser, context);
if (parser.token === 16777237 /* Colon */)
return parseJSXNamespacedName(parser, context, elementName, pos);
while (consume(parser, context, 16777229 /* Period */)) {
elementName = parseJSXMemberExpression(parser, context, elementName, pos);
}
return elementName;
}
/**
* Scans JSX Identifier
*
* @param parser Parser object
* @param context Context masks
*/
function scanJSXIdentifier(parser) {
const { token } = parser;
if (token & (65536 /* IsIdentifier */ | 4096 /* Keyword */)) {
const firstCharPosition = parser.index;
let ch = parser.source.charCodeAt(parser.index);
while ((parser.index < parser.source.length) && (ch === 45 /* Hyphen */ || (isValidIdentifierPart(ch)))) {
ch = readNext(parser);
}
parser.tokenValue += parser.source.substr(firstCharPosition, parser.index - firstCharPosition);
}
return parser.token;
}
/**
* Expression :
* AssignmentExpression
* Expression , AssignmentExpression
*
* ExpressionNoIn :
* AssignmentExpressionNoIn
* ExpressionNoIn , AssignmentExpressionNoIn
*
* @see [Link](https://tc39.github.io/ecma262/#prod-Expression)
*
* @param parser Parser object
* @param context Context masks
*/
function parseExpression(parser, context) {
const pos = getLocation(parser);
const saveDecoratorContext = parser.flags;
const expr = parseExpressionCoverGrammar(parser, context, parseAssignmentExpression);
return parser.token === 16777234 /* Comma */ ?
parseSequenceExpression(parser, context, expr, pos) :
expr;
}
/**
* Parse secuence expression
*
* @param parser Parser object
* @param context Context masks
*/
function parseSequenceExpression(parser, context, left, pos) {
const expressions = [left];
while (consume(parser, context, 16777234 /* Comma */)) {
expressions.push(parseExpressionCoverGrammar(parser, context, parseAssignmentExpression));
}
return finishNode(context, parser, pos, {
type: 'SequenceExpression',
expressions,
});
}
/**
* Parse yield expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-YieldExpression)
*
* @param parser Parser object
* @param context Context masks
*/
function parseYieldExpression(parser, context, pos) {
// YieldExpression[In] :
// yield
// yield [no LineTerminator here] AssignmentExpression[?In, Yield]
// yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
// https://tc39.github.io/ecma262/#sec-generator-function-definitions-static-semantics-early-errors
if (context & 524288 /* InParameter */)
tolerant(parser, context, 49 /* YieldInParameter */);
expect(parser, context, 1107316842 /* YieldKeyword */);
let argument = null;
let delegate = false;
if (!(parser.flags & 1 /* NewLine */)) {
delegate = consume(parser, context, 167774771 /* Multiply */);
// 'Token.IsExpressionStart' bitmask contains the complete set of
// tokens that can appear after an AssignmentExpression, and none of them
// can start an AssignmentExpression.
if (delegate || parser.token & 33554432 /* IsExpressionStart */) {
argument = parseAssignmentExpression(parser, context);
}
}
return finishNode(context, parser, pos, {
type: 'YieldExpression',
argument,
delegate,
});
}
/**
* AssignmentExpression :
* ConditionalExpression
* YieldExpression
* ArrowFunction
* AsyncArrowFunction
* LeftHandSideExpression = AssignmentExpression
* LeftHandSideExpression AssignmentOperator AssignmentExpression
*
* AssignmentExpressionNoIn :
* ConditionalExpressionNoIn
* YieldExpression
* ArrowFunction
* AsyncArrowFunction
* LeftHandSideExpression = AssignmentExpressionNoIn
* LeftHandSideExpression AssignmentOperator AssignmentExpressionNoIn
*
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AssignmentExpression)
*
* @param parser Parser object
* @param context Context masks
*/
function parseAssignmentExpression(parser, context) {
const pos = getLocation(parser);
let { token } = parser;
if (context & 262144 /* Yield */ && token & 1073741824 /* IsYield */)
return parseYieldExpression(parser, context, pos);
let expr = token & 262144 /* IsAsync */ && lookahead(parser, context, nextTokenisIdentifierOrParen)
? parserCoverCallExpressionAndAsyncArrowHead(parser, context)
: parseConditionalExpression(parser, context, pos);
if (parser.token === 10 /* Arrow */) {
if (token & (65536 /* IsIdentifier */ | 4096 /* Keyword */)) {
if (token & (20480 /* FutureReserved */ | 4194304 /* IsEvalOrArguments */)) {
// Invalid: ' yield => { 'use strict'; 0 };'
if (token & 20480 /* FutureReserved */) {
parser.flags |= 64 /* HasStrictReserved */;
}
if (token & 4194304 /* IsEvalOrArguments */) {
if (context & 4096 /* Strict */)
tolerant(parser, context, 45 /* StrictEvalArguments */);
parser.flags |= 2048 /* StrictEvalArguments */;
}
}
expr = [expr];
}
return parseArrowFunction(parser, context &= ~131072 /* Async */, pos, expr);
}
if (hasBit(parser.token, 67108864 /* IsAssignOp */)) {
token = parser.token;
if (context & 4096 /* Strict */ && nameIsArgumentsOrEval(expr.name)) {
tolerant(parser, context, 15 /* StrictLHSAssignment */);
}
else if (consume(parser, context, 83886109 /* Assign */)) {
if (!(parser.flags & 4 /* AllowDestructuring */)) {
tolerant(parser, context, 71 /* InvalidDestructuringTarget */);
}
// Only re-interpret if not inside a formal parameter list
if (!(context & 524288 /* InParameter */))
reinterpret(parser, context, expr);
if (context & 134217728 /* InParen */)
parser.flags |= 8 /* SimpleParameterList */;
if (parser.token & 131072 /* IsAwait */) {
setPendingError(parser);
parser.flags |= 8192 /* HasAwait */;
}
else if (context & 134217728 /* InParen */ &&
context & (4096 /* Strict */ | 262144 /* Yield */) &&
parser.token & 1073741824 /* IsYield */) {
setPendingError(parser);
parser.flags |= 16384 /* HasYield */;
}
}
else {
if (!isValidSimpleAssignmentTarget(expr)) {
tolerant(parser, context, 4 /* InvalidLHSInAssignment */);
}
parser.flags &= ~(4 /* AllowDestructuring */ | 2 /* AllowBinding */);
nextToken(parser, context);
}
const right = parseExpressionCoverGrammar(parser, context | 65536 /* AllowIn */, parseAssignmentExpression);
parser.pendingExpressionError = null;
return finishNode(context, parser, pos, {
type: 'AssignmentExpression',
left: expr,
operator: tokenDesc(token),
right,
});
}
return expr;
}
/**
* Parse conditional expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ConditionalExpression)
*
* @param parser Parser object
* @param context Context masks
*/
function parseConditionalExpression(parser, context, pos) {
const test = parseBinaryExpression(parser, context, 0, pos);
if (!consume(parser, context, 22 /* QuestionMark */))
return test;
const consequent = parseExpressionCoverGrammar(parser, context & ~1073741824 /* AllowDecorator */ | 65536 /* AllowIn */, parseAssignmentExpression);
expect(parser, context, 16777237 /* Colon */);
return finishNode(context, parser, pos, {
type: 'ConditionalExpression',
test,
consequent,
alternate: parseExpressionCoverGrammar(parser, context, parseAssignmentExpression),
});
}
/**
* Parse binary expression.
*
* @see [Link](https://tc39.github.io/ecma262/#sec-exp-operator)
* @see [Link](https://tc39.github.io/ecma262/#sec-binary-logical-operators)
* @see [Link](https://tc39.github.io/ecma262/#sec-additive-operators)
* @see [Link](https://tc39.github.io/ecma262/#sec-bitwise-shift-operators)
* @see [Link](https://tc39.github.io/ecma262/#sec-equality-operators)
* @see [Link](https://tc39.github.io/ecma262/#sec-binary-logical-operators)
* @see [Link](https://tc39.github.io/ecma262/#sec-relational-operators)
* @see [Link](https://tc39.github.io/ecma262/#sec-multiplicative-operators)
*
* @param parser Parser object
* @param context Context masks
* @param minPrec Minimum precedence value
* @param pos Line / Column info
* @param Left Left hand side of the binary expression
*/
function parseBinaryExpression(parser, context, minPrec, pos, left = parseUnaryExpression(parser, context)) {
// Shift-reduce parser for the binary operator part of the JS expression
// syntax.
const bit = context & 65536 /* AllowIn */ ^ 65536 /* AllowIn */;
while (hasBit(parser.token, 167772160 /* IsBinaryOp */)) {
const t = parser.token;
if (bit && t === 168834865 /* InKeyword */)
break;
const prec = t & 3840 /* Precedence */;
const delta = (t === 167775030 /* Exponentiate */) << 8 /* PrecStart */;
// When the next token is no longer a binary operator, it's potentially the
// start of an expression, so we break the loop
if (prec + delta <= minPrec)
break;
nextToken(parser, context);
left = finishNode(context, parser, pos, {
type: t & 2097152 /* IsLogical */ ? 'LogicalExpression' : 'BinaryExpression',
left,
right: parseBinaryExpression(parser, context & ~65536 /* AllowIn */, prec, getLocation(parser)),
operator: tokenDesc(t),
});
}
return left;
}
/**
* Parse await expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AwaitExpression)
*
* @param parser Parser object
* @param context Context masks
* @param pos Location info
*/
function parseAwaitExpression(parser, context, pos) {
if (context & 524288 /* InParameter */)
tolerant(parser, context, 50 /* AwaitInParameter */);
expect(parser, context, 33788013 /* AwaitKeyword */);
return finishNode(context, parser, pos, {
type: 'AwaitExpression',
argument: parseUnaryExpression(parser, context),
});
}
/**
* Parses unary expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-UnaryExpression)
*
* @param parser Parser object
* @param context Context masks
*/
function parseUnaryExpression(parser, context) {
const pos = getLocation(parser);
const { token } = parser;
if (hasBit(token, 301989888 /* IsUnaryOp */)) {
nextToken(parser, context);
if (parser.flags & 32768 /* EscapedKeyword */)
tolerant(parser, context, 2 /* InvalidEscapedReservedWord */);
const argument = parseExpressionCoverGrammar(parser, context, parseUnaryExpression);
if (parser.token === 167775030 /* Exponentiate */)
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(parser.token));
if (context & 4096 /* Strict */ && token === 302002219 /* DeleteKeyword */) {
if (argument.type === 'Identifier') {
tolerant(parser, context, 41 /* StrictDelete */);
}
else if (isPropertyWithPrivateFieldKey(argument)) {
tolerant(parser, context, 42 /* DeletePrivateField */);
}
}
return finishNode(context, parser, pos, {
type: 'UnaryExpression',
operator: tokenDesc(token),
argument,
prefix: true,
});
}
return context & 131072 /* Async */ && token & 131072 /* IsAwait */
? parseAwaitExpression(parser, context, pos)
: parseUpdateExpression(parser, context, pos);
}
/**
* Parses update expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-UpdateExpression)
*
* @param parser Parser object
* @param context Context masks
*/
function parseUpdateExpression(parser, context, pos) {
const { token } = parser;
if (hasBit(parser.token, 570425344 /* IsUpdateOp */)) {
nextToken(parser, context);
const expr = parseLeftHandSideExpression(parser, context, pos);
validateUpdateExpression(parser, context, expr, 'Prefix');
return finishNode(context, parser, pos, {
type: 'UpdateExpression',
argument: expr,
operator: tokenDesc(token),
prefix: true,
});
}
else if (context & 4 /* OptionsJSX */ && token === 167774015 /* LessThan */) {
return parseJSXRootElement(parser, context | 268435456 /* InJSXChild */);
}
const expression = parseLeftHandSideExpression(parser, context, pos);
if (hasBit(parser.token, 570425344 /* IsUpdateOp */) && !(parser.flags & 1 /* NewLine */)) {
validateUpdateExpression(parser, context, expression, 'Postfix');
const operator = parser.token;
nextToken(parser, context);
return finishNode(context, parser, pos, {
type: 'UpdateExpression',
argument: expression,
operator: tokenDesc(operator),
prefix: false,
});
}
return expression;
}
/**
* Parse assignment rest element
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AssignmentRestElement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseRestElement(parser, context, args = []) {
const pos = getLocation(parser);
expect(parser, context, 14 /* Ellipsis */);
if (context & 134217728 /* InParen */ && parser.token & 131072 /* IsAwait */)
parser.flags |= 8192 /* HasAwait */;
const argument = parseBindingIdentifierOrPattern(parser, context, args);
return finishNode(context, parser, pos, {
type: 'RestElement',
argument,
});
}
/**
* Parse spread element
*
* @see [Link](https://tc39.github.io/ecma262/#prod-SpreadElement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseSpreadElement(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 14 /* Ellipsis */);
const argument = restoreExpressionCoverGrammar(parser, context | 65536 /* AllowIn */, parseAssignmentExpression);
return finishNode(context, parser, pos, {
type: 'SpreadElement',
argument,
});
}
/**
* Parse left hand side expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-LeftHandSideExpression)
*
* @param Parser Parer instance
* @param Context Contextmasks
* @param pos Location info
*/
function parseLeftHandSideExpression(parser, context, pos) {
const expr = context & 1 /* OptionsNext */ && parser.token === 33566810 /* ImportKeyword */ ?
parseCallImportOrMetaProperty(parser, context | 65536 /* AllowIn */) :
parseMemberExpression(parser, context | 65536 /* AllowIn */, pos);
return parseCallExpression(parser, context | 65536 /* AllowIn */, pos, expr);
}
/**
* Parse member expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-MemberExpression)
*
* @param parser Parser object
* @param context Context masks
* @param pos Location info
* @param expr Expression
*/
function parseMemberExpression(parser, context, pos, expr = parsePrimaryExpression(parser, context)) {
while (true) {
switch (parser.token) {
case 16777229 /* Period */: {
consume(parser, context, 16777229 /* Period */);
parser.flags = parser.flags & ~2 /* AllowBinding */ | 4 /* AllowDestructuring */;
const property = parseIdentifierNameOrPrivateName(parser, context);
expr = finishNode(context, parser, pos, {
type: 'MemberExpression',
object: expr,
computed: false,
property,
});
continue;
}
case 41943059 /* LeftBracket */: {
consume(parser, context, 41943059 /* LeftBracket */);
parser.flags = parser.flags & ~2 /* AllowBinding */ | 4 /* AllowDestructuring */;
const property = parseExpression(parser, context);
expect(parser, context, 20 /* RightBracket */);
expr = finishNode(context, parser, pos, {
type: 'MemberExpression',
object: expr,
computed: true,
property,
});
continue;
}
case 33554441 /* TemplateTail */: {
expr = finishNode(context, parser, pos, {
type: 'TaggedTemplateExpression',
tag: expr,
quasi: parseTemplateLiteral(parser, context),
});
continue;
}
case 33554440 /* TemplateCont */: {
expr = finishNode(context, parser, pos, {
type: 'TaggedTemplateExpression',
tag: expr,
quasi: parseTemplate(parser, context | 16384 /* TaggedTemplate */),
});
continue;
}
default:
return expr;
}
}
}
/**
* Parse call expression
*
* @param parser Parer instance
* @param context Context masks
* @param pos Line / Colum info
* @param expr Expression
*/
function parseCallExpression(parser, context, pos, expr) {
while (true) {
expr = parseMemberExpression(parser, context, pos, expr);
if (parser.token !== 50331659 /* LeftParen */)
return expr;
const args = parseArgumentList(parser, context & ~1073741824 /* AllowDecorator */);
expr = finishNode(context, parser, pos, {
type: 'CallExpression',
callee: expr,
arguments: args,
});
}
}
/**
* Parse cover call expression and async arrow head
*
* @see [Link](https://tc39.github.io/ecma262/#prod-CoverCallExpressionAndAsyncArrowHead)
*
* @param parser Parser object
* @param context Context masks
*/
function parserCoverCallExpressionAndAsyncArrowHead(parser, context) {
const pos = getLocation(parser);
let expr = parseMemberExpression(parser, context | 65536 /* AllowIn */, pos);
// Here we jump right into it and parse a simple, faster sub-grammar for
// async arrow / async identifier + call expression. This could have been done different
// but ESTree sucks!
//
// - J.K. Thomas
if (parser.token & (65536 /* IsIdentifier */ | 4096 /* Keyword */)) {
if (parser.token & 131072 /* IsAwait */)
tolerant(parser, context, 38 /* DisallowedInContext */);
return parseAsyncArrowFunction(parser, context, 2 /* Await */, pos, [parseAndValidateIdentifier(parser, context)]);
}
if (parser.flags & 1 /* NewLine */)
tolerant(parser, context, 34 /* InvalidLineBreak */, 'async');
while (parser.token === 50331659 /* LeftParen */) {
expr = parseMemberExpression(parser, context, pos, expr);
const args = parseAsyncArgumentList(parser, context);
if (parser.token === 10 /* Arrow */) {
expr = parseAsyncArrowFunction(parser, context, 2 /* Await */, pos, args);
break;
}
expr = finishNode(context, parser, pos, {
type: 'CallExpression',
callee: expr,
arguments: args,
});
}
return expr;
}
/**
* Parse argument list
*
* @see [https://tc39.github.io/ecma262/#prod-ArgumentList)
*
* @param Parser Parser object
* @param Context Context masks
*/
function parseArgumentList(parser, context) {
// ArgumentList :
// AssignmentOrSpreadExpression
// ArgumentList , AssignmentOrSpreadExpression
//
// AssignmentOrSpreadExpression :
// ... AssignmentExpression
// AssignmentExpression
expect(parser, context, 50331659 /* LeftParen */);
const expressions = [];
while (parser.token !== 16 /* RightParen */) {
if (parser.token === 14 /* Ellipsis */) {
expressions.push(parseSpreadElement(parser, context));
}
else {
if (context & 262144 /* Yield */ && hasBit(parser.token, 1073741824 /* IsYield */)) {
parser.flags |= 16384 /* HasYield */;
setPendingError(parser);
}
expressions.push(parseExpressionCoverGrammar(parser, context | 65536 /* AllowIn */, parseAssignmentExpression));
}
if (parser.token !== 16 /* RightParen */)
expect(parser, context, 16777234 /* Comma */);
}
expect(parser, context, 16 /* RightParen */);
return expressions;
}
/**
* Parse argument list for async arrow / async call expression
*
* @see [https://tc39.github.io/ecma262/#prod-ArgumentList)
*
* @param Parser Parser object
* @param Context Context masks
*/
function parseAsyncArgumentList(parser, context) {
// Here we are parsing an "extended" argument list tweaked to handle async arrows. This is
// done here to avoid overhead and possible performance loss if we only
// parse out a simple call expression - E.g 'async(foo, bar)' or 'async(foo, bar)()';
//
// - J.K. Thomas
expect(parser, context, 50331659 /* LeftParen */);
const args = [];
let { token } = parser;
let state = 0 /* Empty */;
while (parser.token !== 16 /* RightParen */) {
if (parser.token === 14 /* Ellipsis */) {
parser.flags |= 8 /* SimpleParameterList */;
args.push(parseSpreadElement(parser, context));
state = 2 /* HasSpread */;
}
else {
token = parser.token;
state = validateAsyncArgumentList(parser, context, state);
args.push(restoreExpressionCoverGrammar(parser, context | 65536 /* AllowIn */, parseAssignmentExpression));
}
if (consume(parser, context, 16777234 /* Comma */)) {
parser.flags &= ~4 /* AllowDestructuring */;
if (state & 2 /* HasSpread */)
state = 1 /* SeenSpread */;
}
if (parser.token === 16 /* RightParen */)
break;
}
expect(parser, context, 16 /* RightParen */);
if (parser.token === 10 /* Arrow */) {
if (state & 1 /* SeenSpread */) {
tolerant(parser, context, 76 /* ParamAfterRest */);
}
else if (state & 8 /* EvalOrArguments */) {
if (context & 4096 /* Strict */)
tolerant(parser, context, 45 /* StrictEvalArguments */);
parser.flags |= 2048 /* StrictEvalArguments */;
}
else if (state & 16 /* Yield */) {
if (context & 4096 /* Strict */)
tolerant(parser, context, 49 /* YieldInParameter */);
parser.flags |= 64 /* HasStrictReserved */;
}
else if (parser.flags & 16384 /* HasYield */) {
tolerant(parser, context, 49 /* YieldInParameter */);
}
else if (state & 32 /* Await */ || parser.flags & 8192 /* HasAwait */) {
tolerant(parser, context, 50 /* AwaitInParameter */);
}
}
return args;
}
/**
* Parse primary expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-PrimaryExpression)
*
* @param Parser Parser object
* @param Context Context masks
*/
function parsePrimaryExpression(parser, context) {
switch (parser.token) {
case 33554434 /* NumericLiteral */:
case 33554435 /* StringLiteral */:
return parseLiteral(parser, context);
case 33554551 /* BigIntLiteral */:
return parseBigIntLiteral(parser, context);
case 33619969 /* Identifier */:
return parseIdentifier(parser, context);
case 33566727 /* NullKeyword */:
case 33566726 /* TrueKeyword */:
case 33566725 /* FalseKeyword */:
return parseNullOrTrueOrFalseLiteral(parser, context);
case 33566808 /* FunctionKeyword */:
return parseFunctionExpression(parser, context);
case 33566815 /* ThisKeyword */:
return parseThisExpression(parser, context);
case 299116 /* AsyncKeyword */:
return parseAsyncFunctionOrIdentifier(parser, context);
case 50331659 /* LeftParen */:
return parseCoverParenthesizedExpressionAndArrowParameterList(parser, context | 134217728 /* InParen */);
case 41943059 /* LeftBracket */:
return restoreExpressionCoverGrammar(parser, context, parseArrayLiteral);
case 41943052 /* LeftBrace */:
return restoreExpressionCoverGrammar(parser, context, parseObjectLiteral);
case 115 /* Hash */:
return parseIdentifierNameOrPrivateName(parser, context);
case 120 /* At */:
case 33566797 /* ClassKeyword */:
return parseClassExpression(parser, context);
case 33566811 /* NewKeyword */:
return parseNewExpressionOrMetaProperty(parser, context);
case 33566813 /* SuperKeyword */:
return parseSuperProperty(parser, context);
case 167774773 /* Divide */:
case 100663333 /* DivideAssign */:
scanRegularExpression(parser, context);
return parseRegularExpressionLiteral(parser, context);
case 33554441 /* TemplateTail */:
return parseTemplateLiteral(parser, context);
case 33554440 /* TemplateCont */:
return parseTemplate(parser, context);
case 33574984 /* LetKeyword */:
return parseLetAsIdentifier(parser, context);
default:
return parseAndValidateIdentifier(parser, context);
}
}
/**
* Parse 'let' as identifier in 'sloppy mode', and throws
* in 'strict mode' / 'module code'. We also avoid a lookahead on the
* ASI restictions while checking this after parsing out the 'let' keyword
*
* @param parser Parser object
* @param context context mask
*/
function parseLetAsIdentifier(parser, context) {
if (context & 4096 /* Strict */)
tolerant(parser, context, 48 /* UnexpectedStrictReserved */);
const pos = getLocation(parser);
const name = parser.tokenValue;
nextToken(parser, context);
if (parser.flags & 1 /* NewLine */) {
if (parser.token === 41943059 /* LeftBracket */)
tolerant(parser, context, 1 /* UnexpectedToken */, 'let');
}
return finishNode(context, parser, pos, {
type: 'Identifier',
name,
});
}
/**
* Parse either async function expression or identifier
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AsyncFunctionExpression)
* @see [Link](https://tc39.github.io/ecma262/#prod-Identifier)
*
* @param parser Parser object
* @param context context mask
*/
function parseAsyncFunctionOrIdentifier(parser, context) {
return lookahead(parser, context, nextTokenIsFuncKeywordOnSameLine) ?
parseAsyncFunctionOrAsyncGeneratorExpression(parser, context) :
parseIdentifier(parser, context);
}
/**
* Parses identifier
*
* @see [Link](https://tc39.github.io/ecma262/#prod-Identifier)
*
* @param parser Parser object
* @param context Context masks
*/
function parseIdentifier(parser, context) {
const pos = getLocation(parser);
const name = parser.tokenValue;
nextToken(parser, context | 16384 /* TaggedTemplate */);
const node = finishNode(context, parser, pos, {
type: 'Identifier',
name,
});
if (context & 256 /* OptionsRawidentifiers */)
node.raw = parser.tokenRaw;
return node;
}
/**
* Parse regular expression literal
*
* @see [Link](https://tc39.github.io/ecma262/#sec-literals-regular-expression-literals)
*
* @param parser Parser object
* @param context Context masks
*/
function parseRegularExpressionLiteral(parser, context) {
const pos = getLocation(parser);
const { tokenRegExp, tokenValue, tokenRaw } = parser;
nextToken(parser, context);
const node = finishNode(context, parser, pos, {
type: 'Literal',
value: tokenValue,
regex: tokenRegExp,
});
if (context & 8 /* OptionsRaw */)
node.raw = tokenRaw;
return node;
}
/**
* Parses string and number literal
*
* @see [Link](https://tc39.github.io/ecma262/#prod-NumericLiteral)
* @see [Link](https://tc39.github.io/ecma262/#prod-StringLiteral)
*
* @param parser Parser object
* @param context Context masks
*/
function parseLiteral(parser, context) {
const pos = getLocation(parser);
const value = parser.tokenValue;
if (context & 4096 /* Strict */ && parser.flags & 128 /* HasOctal */) {
tolerant(parser, context, 59 /* StrictOctalLiteral */);
}
nextToken(parser, context);
const node = finishNode(context, parser, pos, {
type: 'Literal',
value,
});
if (context & 8 /* OptionsRaw */)
node.raw = parser.tokenRaw;
return node;
}
/**
* Parses BigInt literal (stage 3 proposal)
*
* @see [Link](https://tc39.github.io/proposal-bigint/)
*
* @param parser Parser object
* @param context Context masks
*/
function parseBigIntLiteral(parser, context) {
const pos = getLocation(parser);
const { tokenValue, tokenRaw } = parser;
nextToken(parser, context);
const node = finishNode(context, parser, pos, {
type: 'Literal',
value: tokenValue,
bigint: tokenRaw,
});
if (context & 8 /* OptionsRaw */)
node.raw = parser.tokenRaw;
return node;
}
/**
* Parses either null or boolean literal
*
* @see [Link](https://tc39.github.io/ecma262/#prod-BooleanLiteral)
*
* @param parser Parser object
* @param context Context masks
*/
function parseNullOrTrueOrFalseLiteral(parser, context) {
const pos = getLocation(parser);
const { token } = parser;
const raw = tokenDesc(token);
if (parser.flags & 32768 /* EscapedKeyword */)
tolerant(parser, context, 2 /* InvalidEscapedReservedWord */);
nextToken(parser, context);
const node = finishNode(context, parser, pos, {
type: 'Literal',
value: token === 33566727 /* NullKeyword */ ? null : raw === 'true',
});
if (context & 8 /* OptionsRaw */)
node.raw = raw;
return node;
}
/**
* Parse this expression
*
* @param parser Parser object
* @param context Context masks
*/
function parseThisExpression(parser, context) {
if (parser.flags & 32768 /* EscapedKeyword */)
tolerant(parser, context, 2 /* InvalidEscapedReservedWord */);
const pos = getLocation(parser);
nextToken(parser, context | 536870912 /* DisallowEscapedKeyword */);
return finishNode(context, parser, pos, {
type: 'ThisExpression',
});
}
/**
* Parse identifier name
*
* @see [Link](https://tc39.github.io/ecma262/#prod-IdentifierName)
*
* @param parser Parser object
* @param context Context masks
* @param t token
*/
function parseIdentifierName(parser, context, t) {
if (!(t & (65536 /* IsIdentifier */ | 4096 /* Keyword */)))
tolerant(parser, context, 3 /* UnexpectedKeyword */, tokenDesc(t));
return parseIdentifier(parser, context);
}
/**
* Parse identifier name or private name (stage 3 proposal)
*
* @see [Link](https://tc39.github.io/ecma262/#prod-StatementList)
*
* @param parser Parser object
* @param context Context masks
*/
function parseIdentifierNameOrPrivateName(parser, context) {
if (!consume(parser, context, 115 /* Hash */))
return parseIdentifierName(parser, context, parser.token);
const { tokenValue } = parser;
const pos = getLocation(parser);
const name = tokenValue;
nextToken(parser, context);
return finishNode(context, parser, pos, {
type: 'PrivateName',
name,
});
}
/**
* Parse array literal
*
* ArrayLiteral :
* [ Elisionopt ]
* [ ElementList ]
* [ ElementList , Elisionopt ]
*
* ElementList :
* Elisionopt AssignmentExpression
* Elisionopt ... AssignmentExpression
* ElementList , Elisionopt AssignmentExpression
* ElementList , Elisionopt SpreadElement
*
* Elision :
* ,
* Elision ,
*
* SpreadElement :
* ... AssignmentExpression
*
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ArrayLiteral)
*
* @param parser Parser object
* @param context Context masks
*/
function parseArrayLiteral(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 41943059 /* LeftBracket */);
const elements = [];
while (parser.token !== 20 /* RightBracket */) {
if (consume(parser, context, 16777234 /* Comma */)) {
elements.push(null);
}
else if (parser.token === 14 /* Ellipsis */) {
elements.push(parseSpreadElement(parser, context));
if (parser.token !== 20 /* RightBracket */) {
parser.flags &= ~(4 /* AllowDestructuring */ | 2 /* AllowBinding */);
expect(parser, context, 16777234 /* Comma */);
}
}
else {
elements.push(restoreExpressionCoverGrammar(parser, context | 65536 /* AllowIn */, parseAssignmentExpression));
if (parser.token !== 20 /* RightBracket */)
expect(parser, context, 16777234 /* Comma */);
}
}
expect(parser, context, 20 /* RightBracket */);
return finishNode(context, parser, pos, {
type: 'ArrayExpression',
elements,
});
}
/**
* Parses cover parenthesized expression and arrow parameter list
*
* @see [Link](https://tc39.github.io/ecma262/#prod-parseCoverParenthesizedExpressionAndArrowParameterList)
*
* @param parser Parser object
* @param context Context masks
*/
function parseCoverParenthesizedExpressionAndArrowParameterList(parser, context) {
expect(parser, context, 50331659 /* LeftParen */);
switch (parser.token) {
// ')'
case 16 /* RightParen */:
{
expect(parser, context, 16 /* RightParen */);
parser.flags &= ~(4 /* AllowDestructuring */ | 2 /* AllowBinding */);
if (parser.token === 10 /* Arrow */)
return [];
}
// '...'
case 14 /* Ellipsis */:
{
const expr = parseRestElement(parser, context);
expect(parser, context, 16 /* RightParen */);
parser.flags = parser.flags & ~(4 /* AllowDestructuring */ | 2 /* AllowBinding */) | 8 /* SimpleParameterList */;
if (parser.token !== 10 /* Arrow */)
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(parser.token));
return [expr];
}
default:
{
let state = 0 /* None */;
// Record the sequence position
const sequencepos = getLocation(parser);
state = validateCoverParenthesizedExpression(parser, state);
if (parser.token & 8388608 /* IsBindingPattern */)
state |= 16 /* HasBinding */;
let expr = restoreExpressionCoverGrammar(parser, context | 65536 /* AllowIn */, parseAssignmentExpression);
// Sequence expression
if (parser.token === 16777234 /* Comma */) {
state |= 1 /* SequenceExpression */;
const expressions = [expr];
while (consume(parser, context | 536870912 /* DisallowEscapedKeyword */, 16777234 /* Comma */)) {
parser.flags &= ~4 /* AllowDestructuring */;
switch (parser.token) {
// '...'
case 14 /* Ellipsis */:
{
if (!(parser.flags & 2 /* AllowBinding */))
tolerant(parser, context, 75 /* NotBindable */);
parser.flags |= 8 /* SimpleParameterList */;
const restElement = parseRestElement(parser, context);
expect(parser, context, 16 /* RightParen */);
if (parser.token !== 10 /* Arrow */)
tolerant(parser, context, 76 /* ParamAfterRest */);
parser.flags &= ~2 /* AllowBinding */;
expressions.push(restElement);
return expressions;
}
// ')'
case 16 /* RightParen */:
{
expect(parser, context, 16 /* RightParen */);
if (parser.token !== 10 /* Arrow */)
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(parser.token));
return expressions;
}
default:
{
state = validateCoverParenthesizedExpression(parser, state);
expressions.push(restoreExpressionCoverGrammar(parser, context, parseAssignmentExpression));
}
}
}
expr = finishNode(context, parser, sequencepos, {
type: 'SequenceExpression',
expressions,
});
}
expect(parser, context, 16 /* RightParen */);
if (parser.token === 10 /* Arrow */) {
if (state & 2 /* HasEvalOrArguments */) {
if (context & 4096 /* Strict */)
tolerant(parser, context, 45 /* StrictEvalArguments */);
parser.flags |= 2048 /* StrictEvalArguments */;
}
else if (state & 4 /* HasReservedWords */) {
if (context & 4096 /* Strict */)
tolerant(parser, context, 48 /* UnexpectedStrictReserved */);
parser.flags |= 64 /* HasStrictReserved */;
}
else if (!(parser.flags & 2 /* AllowBinding */)) {
tolerant(parser, context, 75 /* NotBindable */);
}
else if (parser.flags & 16384 /* HasYield */) {
tolerant(parser, context, 49 /* YieldInParameter */);
}
else if (context & 131072 /* Async */ && parser.flags & 8192 /* HasAwait */) {
tolerant(parser, context, 50 /* AwaitInParameter */);
}
parser.flags &= ~(2 /* AllowBinding */ | 8192 /* HasAwait */ | 16384 /* HasYield */);
return (state & 1 /* SequenceExpression */ ? expr.expressions : [expr]);
}
parser.flags &= ~(8192 /* HasAwait */ | 16384 /* HasYield */ | 2 /* AllowBinding */);
if (!isValidSimpleAssignmentTarget(expr))
parser.flags &= ~4 /* AllowDestructuring */;
return expr;
}
}
}
/**
* Parses function expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-FunctionExpression)
*
* @param parser Parser object
* @param context Context masks
*/
function parseFunctionExpression(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 33566808 /* FunctionKeyword */);
const isGenerator = consume(parser, context, 167774771 /* Multiply */) ? 1 /* Generator */ : 0 /* None */;
let id = null;
const { token } = parser;
if (token & (65536 /* IsIdentifier */ | 4096 /* Keyword */)) {
if (token & 4194304 /* IsEvalOrArguments */) {
if (context & 4096 /* Strict */)
tolerant(parser, context, 45 /* StrictEvalArguments */);
parser.flags |= 2048 /* StrictEvalArguments */;
}
if (parser.token & 1073741824 /* IsYield */ && isGenerator & 1 /* Generator */) {
tolerant(parser, context, 47 /* YieldBindingIdentifier */);
}
id = parseBindingIdentifier(parser, context);
}
const { params, body } = swapContext(parser, context & ~(33554432 /* Method */ | 67108864 /* AllowSuperProperty */), isGenerator, parseFormalListAndBody);
return finishNode(context, parser, pos, {
type: 'FunctionExpression',
params,
body,
async: false,
generator: !!(isGenerator & 1 /* Generator */),
expression: false,
id,
});
}
/**
* Parses async function or async generator expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AsyncFunctionExpression)
*
* @param parser Parser object
* @param context Context masks
*/
function parseAsyncFunctionOrAsyncGeneratorExpression(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 299116 /* AsyncKeyword */);
expect(parser, context, 33566808 /* FunctionKeyword */);
const isGenerator = consume(parser, context, 167774771 /* Multiply */) ? 1 /* Generator */ : 0 /* None */;
const isAwait = 2 /* Await */;
let id = null;
const { token } = parser;
if (token & (65536 /* IsIdentifier */ | 4096 /* Keyword */)) {
if (token & 4194304 /* IsEvalOrArguments */) {
if (context & 4096 /* Strict */ || isAwait & 2 /* Await */)
tolerant(parser, context, 45 /* StrictEvalArguments */);
parser.flags |= 1024 /* StrictFunctionName */;
}
if (token & 131072 /* IsAwait */)
tolerant(parser, context, 46 /* AwaitBindingIdentifier */);
if (parser.token & 1073741824 /* IsYield */ && isGenerator & 1 /* Generator */)
tolerant(parser, context, 47 /* YieldBindingIdentifier */);
id = parseBindingIdentifier(parser, context);
}
const { params, body } = swapContext(parser, context & ~(33554432 /* Method */ | 67108864 /* AllowSuperProperty */), isGenerator | isAwait, parseFormalListAndBody);
return finishNode(context, parser, pos, {
type: 'FunctionExpression',
params,
body,
async: true,
generator: !!(isGenerator & 1 /* Generator */),
expression: false,
id,
});
}
/**
* Parse computed property names
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ComputedPropertyName)
*
* @param parser Parser object
* @param context Context masks
*/
function parseComputedPropertyName(parser, context) {
expect(parser, context, 41943059 /* LeftBracket */);
const key = parseAssignmentExpression(parser, context | 65536 /* AllowIn */);
expect(parser, context, 20 /* RightBracket */);
return key;
}
/**
* Parse property name
*
* @see [Link](https://tc39.github.io/ecma262/#prod-PropertyName)
*
* @param parser Parser object
* @param context Context masks
*/
function parsePropertyName(parser, context) {
switch (parser.token) {
case 33554434 /* NumericLiteral */:
case 33554435 /* StringLiteral */:
return parseLiteral(parser, context);
case 41943059 /* LeftBracket */:
return parseComputedPropertyName(parser, context);
default:
return parseIdentifier(parser, context);
}
}
/**
* Parse object spread properties
*
* @see [Link](https://tc39.github.io/proposal-object-rest-spread/#Spread)
*
* @param parser Parser object
* @param context Context masks
*/
function parseSpreadProperties(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 14 /* Ellipsis */);
if (parser.token & 8388608 /* IsBindingPattern */)
parser.flags &= ~4 /* AllowDestructuring */;
const argument = parseAssignmentExpression(parser, context | 65536 /* AllowIn */);
return finishNode(context, parser, pos, {
type: 'SpreadElement',
argument,
});
}
/**
* Parses object literal
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ObjectLiteral)
*
* @param parser Parser object
* @param context Context masks
*/
function parseObjectLiteral(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 41943052 /* LeftBrace */);
const properties = [];
while (parser.token !== 17301519 /* RightBrace */) {
properties.push(parser.token === 14 /* Ellipsis */ ?
parseSpreadProperties(parser, context) :
parsePropertyDefinition(parser, context));
if (parser.token !== 17301519 /* RightBrace */)
expect(parser, context, 16777234 /* Comma */);
}
expect(parser, context, 17301519 /* RightBrace */);
parser.flags &= ~512 /* HasProtoField */;
return finishNode(context, parser, pos, {
type: 'ObjectExpression',
properties,
});
}
/**
* Parse property definition
*
* @see [Link](https://tc39.github.io/ecma262/#prod-PropertyDefinition)
*
* @param parser Parser object
* @param context Context masks
*/
function parsePropertyDefinition(parser, context) {
const pos = getLocation(parser);
const flags = parser.flags;
let value;
let state = consume(parser, context, 167774771 /* Multiply */) ? 2 /* Generator */ | 32 /* Method */ : 32 /* Method */;
const t = parser.token;
let key = parsePropertyName(parser, context);
if (!(parser.token & 16777216 /* IsShorthandProperty */)) {
if (flags & 32768 /* EscapedKeyword */) {
tolerant(parser, context, 2 /* InvalidEscapedReservedWord */);
}
else if (!(state & 2 /* Generator */) && t & 262144 /* IsAsync */ && !(parser.flags & 1 /* NewLine */)) {
state |= consume(parser, context, 167774771 /* Multiply */) ? 2 /* Generator */ | 1 /* Async */ : 1 /* Async */;
key = parsePropertyName(parser, context);
}
else if (t === 36975 /* GetKeyword */) {
state = state & ~32 /* Method */ | 4 /* Getter */;
key = parsePropertyName(parser, context);
}
else if (t === 36976 /* SetKeyword */) {
state = state & ~32 /* Method */ | 8 /* Setter */;
key = parsePropertyName(parser, context);
}
if (state & (4 /* Getter */ | 8 /* Setter */)) {
if (state & 2 /* Generator */)
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(parser.token));
}
}
if (parser.token === 50331659 /* LeftParen */) {
value = parseMethodDeclaration(parser, context, state);
}
else {
state &= ~32 /* Method */;
if (parser.token === 16777237 /* Colon */) {
if ((state & (1 /* Async */ | 2 /* Generator */))) {
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(parser.token));
}
else if (t !== 41943059 /* LeftBracket */ && parser.tokenValue === '__proto__') {
if (parser.flags & 512 /* HasProtoField */) {
// Record the error and put it on hold until we've determined
// whether or not we're destructuring
setPendingExpressionError(parser, 61 /* DuplicateProto */);
}
else
parser.flags |= 512 /* HasProtoField */;
}
expect(parser, context, 16777237 /* Colon */);
// Invalid: 'async ({a: await}) => 1'
if (parser.token & 131072 /* IsAwait */)
parser.flags |= 8192 /* HasAwait */;
value = restoreExpressionCoverGrammar(parser, context, parseAssignmentExpression);
}
else {
if ((state & (2 /* Generator */ | 1 /* Async */)) || !isValidIdentifier(context, t)) {
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(t));
}
else if (context & (4096 /* Strict */ | 262144 /* Yield */) && t & 1073741824 /* IsYield */) {
setPendingError(parser);
parser.flags |= 16384 /* HasYield */;
}
state |= 64 /* Shorthand */;
if (parser.token === 83886109 /* Assign */) {
setPendingExpressionError(parser, 89 /* InvalidCoverInitializedName */);
expect(parser, context, 83886109 /* Assign */);
if (context & (4096 /* Strict */ | 262144 /* Yield */ | 131072 /* Async */) && parser.token & (1073741824 /* IsYield */ | 131072 /* IsAwait */)) {
setPendingError(parser);
parser.flags |= parser.token & 1073741824 /* IsYield */ ? 16384 /* HasYield */ : 8192 /* HasAwait */;
}
value = parseAssignmentPattern(parser, context, key, pos);
}
else {
if (t & 131072 /* IsAwait */) {
if (context & 131072 /* Async */)
tolerant(parser, context, 44 /* UnexpectedReserved */);
setPendingError(parser);
parser.flags |= 8192 /* HasAwait */;
}
value = key;
}
}
}
return finishNode(context, parser, pos, {
type: 'Property',
key,
value,
kind: !(state & 4 /* Getter */ | state & 8 /* Setter */) ? 'init' : (state & 8 /* Setter */) ? 'set' : 'get',
computed: t === 41943059 /* LeftBracket */,
method: !!(state & 32 /* Method */),
shorthand: !!(state & 64 /* Shorthand */),
});
}
/**
* Parse statement list
*
* @see [Link](https://tc39.github.io/ecma262/#prod-StatementList)
*
* @param parser Parser object
* @param context Context masks
*/
function parseMethodDeclaration(parser, context, state) {
const pos = getLocation(parser);
const isGenerator = state & 2 /* Generator */ ? 1 /* Generator */ : 0 /* None */;
const isAsync = state & 1 /* Async */ ? 2 /* Await */ : 0 /* None */;
const { params, body } = swapContext(parser, context | 33554432 /* Method */, isGenerator | isAsync, parseFormalListAndBody, state);
return finishNode(context, parser, pos, {
type: 'FunctionExpression',
params,
body,
async: !!(state & 1 /* Async */),
generator: !!(state & 2 /* Generator */),
expression: false,
id: null,
});
}
/**
* Parse arrow function
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ArrowFunction)
*
* @param parser Parser object
* @param context Context masks
*/
function parseArrowFunction(parser, context, pos, params) {
parser.flags &= ~(4 /* AllowDestructuring */ | 2 /* AllowBinding */);
if (parser.flags & 1 /* NewLine */)
tolerant(parser, context, 34 /* InvalidLineBreak */, '=>');
expect(parser, context, 10 /* Arrow */);
return parseArrowBody(parser, context & ~131072 /* Async */, params, pos, 0 /* None */);
}
/**
* Parse async arrow function
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AsyncArrowFunction)
*
* @param parser Parser object
* @param context Context masks
*/
function parseAsyncArrowFunction(parser, context, state, pos, params) {
parser.flags &= ~(4 /* AllowDestructuring */ | 2 /* AllowBinding */);
if (parser.flags & 1 /* NewLine */)
tolerant(parser, context, 34 /* InvalidLineBreak */, 'async');
expect(parser, context, 10 /* Arrow */);
return parseArrowBody(parser, context | 131072 /* Async */, params, pos, state);
}
/**
* Shared helper function for both async arrow and arrows
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ArrowFunction)
* @see [Link](https://tc39.github.io/ecma262/#prod-AsyncArrowFunction)
*
* @param parser Parser object
* @param context Context masks
*/
// https://tc39.github.io/ecma262/#prod-AsyncArrowFunction
function parseArrowBody(parser, context, params, pos, state) {
parser.pendingExpressionError = null;
for (const i in params)
reinterpret(parser, context | 524288 /* InParameter */, params[i]);
const expression = parser.token !== 41943052 /* LeftBrace */;
const body = expression ? parseExpressionCoverGrammar(parser, context & ~(262144 /* Yield */ | 524288 /* InParameter */), parseAssignmentExpression) :
swapContext(parser, context & ~(262144 /* Yield */ | 1073741824 /* AllowDecorator */) | 1048576 /* InFunctionBody */, state, parseFunctionBody);
return finishNode(context, parser, pos, {
type: 'ArrowFunctionExpression',
body,
params,
id: null,
async: !!(state & 2 /* Await */),
generator: false,
expression,
});
}
/**
* Parses formal parameters and function body.
*
* @see [Link](https://tc39.github.io/ecma262/#prod-FunctionBody)
* @see [Link](https://tc39.github.io/ecma262/#prod-FormalParameters)
*
* @param parser Parser object
* @param context Context masks
*/
function parseFormalListAndBody(parser, context, state) {
const paramList = parseFormalParameters(parser, context | 524288 /* InParameter */, state);
const args = paramList.args;
const params = paramList.params;
const body = parseFunctionBody(parser, context & ~1073741824 /* AllowDecorator */ | 1048576 /* InFunctionBody */, args);
return { params, body };
}
/**
* Parse funciton body
*
* @see [Link](https://tc39.github.io/ecma262/#prod-FunctionBody)
*
* @param parser Parser object
* @param context Context masks
*/
function parseFunctionBody(parser, context, params) {
// Note! The 'params' has an 'any' type now because it's really shouldn't be there. This should have been
// on the parser object instead. So for now the 'params' arg are only used within the
// 'parseFormalListAndBody' method, and not within the arrow function body.
const pos = getLocation(parser);
expect(parser, context | 536870912 /* DisallowEscapedKeyword */, 41943052 /* LeftBrace */);
const body = [];
while (parser.token === 33554435 /* StringLiteral */) {
const { tokenRaw, tokenValue } = parser;
body.push(parseDirective(parser, context));
if (tokenRaw.length === /* length of prologue*/ 12 && tokenValue === 'use strict') {
if (parser.flags & 8 /* SimpleParameterList */) {
tolerant(parser, context, 62 /* IllegalUseStrict */);
}
else if (parser.flags & (64 /* HasStrictReserved */ | 1024 /* StrictFunctionName */)) {
tolerant(parser, context, 48 /* UnexpectedStrictReserved */);
}
else if (parser.flags & 2048 /* StrictEvalArguments */) {
tolerant(parser, context, 45 /* StrictEvalArguments */);
}
context |= 4096 /* Strict */;
}
}
if (context & 4096 /* Strict */) {
validateParams(parser, context, params);
}
const { labelSet } = parser;
parser.labelSet = {};
const savedFlags = parser.flags;
parser.flags = parser.flags & ~(1024 /* StrictFunctionName */ | 2048 /* StrictEvalArguments */ | 16 /* InSwitchStatement */ | 32 /* InIterationStatement */) | 4 /* AllowDestructuring */;
while (parser.token !== 17301519 /* RightBrace */) {
body.push(parseStatementListItem(parser, context));
}
if (savedFlags & 32 /* InIterationStatement */)
parser.flags |= 32 /* InIterationStatement */;
if (savedFlags & 16 /* InSwitchStatement */)
parser.flags |= 16 /* InSwitchStatement */;
parser.labelSet = labelSet;
expect(parser, context, 17301519 /* RightBrace */);
return finishNode(context, parser, pos, {
type: 'BlockStatement',
body,
});
}
/**
* Parse formal parameters
*
* @see [Link](https://tc39.github.io/ecma262/#prod-FormalParameters)
*
* @param Parser object
* @param Context masks
* @param Optional objectstate. Default to none
*/
function parseFormalParameters(parser, context, state) {
// FormalParameterList :
// [empty]
// FunctionRestParameter
// FormalsList
// FormalsList , FunctionRestParameter
//
// FunctionRestParameter :
// ... BindingIdentifier
//
// FormalsList :
// FormalParameter
// FormalsList , FormalParameter
//
// FormalParameter :
// BindingElement
//
// BindingElement :
// SingleNameBinding
// BindingPattern Initializeropt
expect(parser, context, 50331659 /* LeftParen */);
parser.flags &= ~(8 /* SimpleParameterList */ | 64 /* HasStrictReserved */);
const args = [];
const params = [];
while (parser.token !== 16 /* RightParen */) {
if (parser.token === 14 /* Ellipsis */) {
if (state & 8 /* Setter */)
tolerant(parser, context, 65 /* BadSetterRestParameter */);
parser.flags |= 8 /* SimpleParameterList */;
params.push(parseRestElement(parser, context, args));
break;
}
params.push(parseFormalParameterList(parser, context, args));
if (!consume(parser, context, 16777234 /* Comma */))
break;
if (parser.token === 16 /* RightParen */)
break;
}
if (state & 8 /* Setter */ && params.length !== 1) {
tolerant(parser, context, 64 /* AccessorWrongArgs */, 'Setter', 'one', '');
}
if (state & 4 /* Getter */ && params.length > 0) {
tolerant(parser, context, 64 /* AccessorWrongArgs */, 'Getter', 'no', 's');
}
expect(parser, context, 16 /* RightParen */);
return { params, args };
}
/**
* Parse formal parameter list
*
* @see [Link](https://tc39.github.io/ecma262/#prod-FormalParameterList)
*
* @param parser Parser object
* @param context Context masks
*/
function parseFormalParameterList(parser, context, args) {
const pos = getLocation(parser);
if (parser.token & (65536 /* IsIdentifier */ | 4096 /* Keyword */)) {
if (hasBit(parser.token, 20480 /* FutureReserved */)) {
if (context & 4096 /* Strict */)
tolerant(parser, context, 48 /* UnexpectedStrictReserved */);
parser.flags |= 1024 /* StrictFunctionName */;
}
if (hasBit(parser.token, 4194304 /* IsEvalOrArguments */)) {
if (context & 4096 /* Strict */)
tolerant(parser, context, 45 /* StrictEvalArguments */);
parser.flags |= 2048 /* StrictEvalArguments */;
}
}
else {
parser.flags |= 8 /* SimpleParameterList */;
}
const left = parseBindingIdentifierOrPattern(parser, context, args);
if (!consume(parser, context, 83886109 /* Assign */))
return left;
if (parser.token & (1073741824 /* IsYield */ | 131072 /* IsAwait */) && context & (262144 /* Yield */ | 131072 /* Async */)) {
tolerant(parser, context, parser.token & 131072 /* IsAwait */ ? 50 /* AwaitInParameter */ : 49 /* YieldInParameter */);
}
parser.flags |= 8 /* SimpleParameterList */;
return finishNode(context, parser, pos, {
type: 'AssignmentPattern',
left,
right: parseExpressionCoverGrammar(parser, context, parseAssignmentExpression),
});
}
/**
* Parse class expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ClassExpression)
*
* @param parser Parser object
* @param context Context masks
*/
function parseClassExpression(parser, context) {
const pos = getLocation(parser);
let decorators = [];
if (context & 2048 /* OptionsExperimental */)
decorators = parseDecorators(parser, context);
expect(parser, context | 536870912 /* DisallowEscapedKeyword */, 33566797 /* ClassKeyword */);
const { token } = parser;
let state = 0 /* None */;
let id = null;
let superClass = null;
if ((token !== 41943052 /* LeftBrace */ && token !== 12372 /* ExtendsKeyword */)) {
if (context & 131072 /* Async */ && token & 131072 /* IsAwait */) {
tolerant(parser, context, 46 /* AwaitBindingIdentifier */);
}
id = parseBindingIdentifier(parser, context | 4096 /* Strict */);
}
if (consume(parser, context, 12372 /* ExtendsKeyword */)) {
superClass = parseLeftHandSideExpression(parser, context | 4096 /* Strict */, pos);
state |= 512 /* Heritage */;
}
const body = parseClassBodyAndElementList(parser, context | 4096 /* Strict */, state);
return finishNode(context, parser, pos, context & 2048 /* OptionsExperimental */ ? {
type: 'ClassExpression',
id,
superClass,
body,
decorators
} : {
type: 'ClassExpression',
id,
superClass,
body,
});
}
/**
* Parse class body and element list
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ClassBody)
* @see [Link](https://tc39.github.io/ecma262/#prod-ClassElementList)
*
*
* @param parser Parser object
* @param context Context masks
*/
function parseClassBodyAndElementList(parser, context, state) {
const pos = getLocation(parser);
expect(parser, context, 41943052 /* LeftBrace */);
const body = [];
let decorators = [];
while (parser.token !== 17301519 /* RightBrace */) {
if (!consume(parser, context, 17301521 /* Semicolon */)) {
if (context & 2048 /* OptionsExperimental */) {
decorators = parseDecorators(parser, context);
if (parser.token === 17301519 /* RightBrace */)
report(parser, 90 /* TrailingDecorators */);
if (decorators.length !== 0 && parser.tokenValue === 'constructor') {
report(parser, 91 /* GeneratorConstructor */);
}
}
body.push(context & 1 /* OptionsNext */ && parser.token === 115 /* Hash */
? parsePrivateFields(parser, context, decorators)
: parseClassElement(parser, context, state, decorators));
}
}
expect(parser, context, 17301519 /* RightBrace */);
return finishNode(context, parser, pos, {
type: 'ClassBody',
body,
});
}
/**
* Parse class element and class public instance fields & private instance fields
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ClassElement)
* @see [Link](https://tc39.github.io/proposal-class-public-fields/)
*
* @param parser Parser object
* @param context Context masks
*/
function parseClassElement(parser, context, state, decorators) {
const pos = getLocation(parser);
let { tokenValue, token } = parser;
const flags = parser.flags;
if (consume(parser, context, 167774771 /* Multiply */)) {
state |= 2 /* Generator */;
}
if (parser.token === 41943059 /* LeftBracket */)
state |= 16 /* Computed */;
if (parser.tokenValue === 'constructor') {
if (state & 2 /* Generator */)
tolerant(parser, context, 43 /* InvalidConstructor */, 'generator');
else if (state & 512 /* Heritage */)
context |= 67108864 /* AllowSuperProperty */;
state |= 256 /* Constructor */;
}
let key = parsePropertyName(parser, context);
let value;
if (!(parser.token & 16777216 /* IsShorthandProperty */)) {
if (flags & 32768 /* EscapedKeyword */)
tolerant(parser, context, 2 /* InvalidEscapedReservedWord */);
if (token === 20585 /* StaticKeyword */) {
token = parser.token;
if (consume(parser, context, 167774771 /* Multiply */))
state |= 2 /* Generator */;
tokenValue = parser.tokenValue;
if (parser.token === 41943059 /* LeftBracket */)
state |= 16 /* Computed */;
if (parser.tokenValue === 'prototype')
tolerant(parser, context, 63 /* StaticPrototype */);
state |= 128 /* Static */;
key = parsePropertyName(parser, context);
if (context & 1 /* OptionsNext */ && isInstanceField(parser)) {
if (tokenValue === 'constructor')
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(parser.token));
return parseFieldDefinition(parser, context, key, state, pos, decorators);
}
}
if (parser.token !== 50331659 /* LeftParen */) {
if (token & 262144 /* IsAsync */ && !(state & 2 /* Generator */) && !(parser.flags & 1 /* NewLine */)) {
token = parser.token;
tokenValue = parser.tokenValue;
state |= 1 /* Async */;
if (consume(parser, context, 167774771 /* Multiply */))
state |= 2 /* Generator */;
if (parser.token === 41943059 /* LeftBracket */)
state |= 16 /* Computed */;
key = parsePropertyName(parser, context);
}
else if ((token === 36975 /* GetKeyword */ || token === 36976 /* SetKeyword */)) {
state |= token === 36975 /* GetKeyword */ ? 4 /* Getter */ : 8 /* Setter */;
tokenValue = parser.tokenValue;
if (parser.token === 41943059 /* LeftBracket */)
state |= 16 /* Computed */;
key = parsePropertyName(parser, context);
}
if (tokenValue === 'prototype') {
tolerant(parser, context, 63 /* StaticPrototype */);
}
else if (!(state & 128 /* Static */) && tokenValue === 'constructor') {
tolerant(parser, context, 43 /* InvalidConstructor */, 'accessor');
}
}
}
if (parser.token === 50331659 /* LeftParen */) {
value = parseMethodDeclaration(parser, context, state);
}
else {
if (context & 1 /* OptionsNext */)
return parseFieldDefinition(parser, context, key, state, pos, decorators);
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(token));
}
const kind = (state & 256 /* Constructor */) ? 'constructor' : (state & 4 /* Getter */) ? 'get' :
(state & 8 /* Setter */) ? 'set' : 'method';
return finishNode(context, parser, pos, context & 2048 /* OptionsExperimental */ ? {
type: 'MethodDefinition',
kind,
static: !!(state & 128 /* Static */),
computed: !!(state & 16 /* Computed */),
key,
value,
decorators
} : {
type: 'MethodDefinition',
kind,
static: !!(state & 128 /* Static */),
computed: !!(state & 16 /* Computed */),
key,
value,
});
}
/**
* Parses field definition.
*
* @param parser Parser object
* @param context Context masks
*/
function parseFieldDefinition(parser, context, key, state, pos, decorators) {
if (state & 256 /* Constructor */)
tolerant(parser, context, 0 /* Unexpected */);
let value = null;
if (state & (1 /* Async */ | 2 /* Generator */))
tolerant(parser, context, 0 /* Unexpected */);
if (consume(parser, context, 83886109 /* Assign */)) {
if (parser.token & 4194304 /* IsEvalOrArguments */)
tolerant(parser, context, 45 /* StrictEvalArguments */);
value = parseAssignmentExpression(parser, context);
}
consume(parser, context, 16777234 /* Comma */);
return finishNode(context, parser, pos, context & 2048 /* OptionsExperimental */ ? {
type: 'FieldDefinition',
key,
value,
computed: !!(state & 16 /* Computed */),
static: !!(state & 128 /* Static */),
decorators
} : {
type: 'FieldDefinition',
key,
value,
computed: !!(state & 16 /* Computed */),
static: !!(state & 128 /* Static */),
});
}
/**
* Parse private name
*
* @param parser Parser object
* @param context Context masks
*/
function parsePrivateName(parser, context, pos) {
const name = parser.tokenValue;
nextToken(parser, context);
return finishNode(context, parser, pos, {
type: 'PrivateName',
name,
});
}
/**
* Parses private instance fields
*
* @see [Link](https://tc39.github.io/proposal-class-public-fields/)
*
* @param parser Parser object
* @param context Context masks
*/
function parsePrivateFields(parser, context, decorators) {
const pos = getLocation(parser);
expect(parser, context | 32768 /* InClass */, 115 /* Hash */);
if (parser.tokenValue === 'constructor')
tolerant(parser, context, 39 /* PrivateFieldConstructor */);
const key = parsePrivateName(parser, context, pos);
if (parser.token === 50331659 /* LeftParen */)
return parsePrivateMethod(parser, context, key, pos, decorators);
let value = null;
if (consume(parser, context, 83886109 /* Assign */)) {
if (parser.token & 4194304 /* IsEvalOrArguments */)
tolerant(parser, context, 45 /* StrictEvalArguments */);
value = parseAssignmentExpression(parser, context);
}
consume(parser, context, 16777234 /* Comma */);
return finishNode(context, parser, pos, context & 2048 /* OptionsExperimental */ ? {
type: 'FieldDefinition',
key,
value,
computed: false,
static: false,
decorators
} : {
type: 'FieldDefinition',
key,
value,
computed: false,
static: false,
});
}
function parsePrivateMethod(parser, context, key, pos, decorators) {
const value = parseMethodDeclaration(parser, context | 4096 /* Strict */, 0 /* None */);
parser.flags &= ~(4 /* AllowDestructuring */ | 2 /* AllowBinding */);
return finishNode(context, parser, pos, context & 2048 /* OptionsExperimental */ ? {
type: 'MethodDefinition',
kind: 'method',
static: false,
computed: false,
key,
value,
decorators
} : {
type: 'MethodDefinition',
kind: 'method',
static: false,
computed: false,
key,
value,
});
}
/**
* Parse either call expression or import expressions
*
* @param parser Parser object
* @param context Context masks
*/
function parseCallImportOrMetaProperty(parser, context) {
const pos = getLocation(parser);
const id = parseIdentifier(parser, context);
// Import.meta - Stage 3 proposal
if (consume(parser, context, 16777229 /* Period */)) {
if (context & 8192 /* Module */ && parser.tokenValue === 'meta')
return parseMetaProperty(parser, context, id, pos);
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(parser.token));
}
let expr = parseImportExpression(parser, context, pos);
expect(parser, context, 50331659 /* LeftParen */);
const args = parseExpressionCoverGrammar(parser, context | 65536 /* AllowIn */, parseAssignmentExpression);
expect(parser, context, 16 /* RightParen */);
expr = finishNode(context, parser, pos, {
type: 'CallExpression',
callee: expr,
arguments: [args],
});
return expr;
}
/**
* Parse Import() expression. (Stage 3 proposal)
*
* @param parser Parser object
* @param context Context masks
* @param pos Location
*/
function parseImportExpression(parser, context, pos) {
return finishNode(context, parser, pos, {
type: 'Import',
});
}
/**
* Parse meta property
*
* @see [Link](https://tc39.github.io/ecma262/#prod-StatementList)
*
* @param parser Parser object
* @param context Context masks
* @param meta Identifier
* @param pos Location
*/
function parseMetaProperty(parser, context, meta, pos) {
return finishNode(context, parser, pos, {
meta,
type: 'MetaProperty',
property: parseIdentifier(parser, context),
});
}
/**
* Parse new expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-NewExpression)
*
* @param parser Parser object
* @param context Context masks
*/
function parseNewExpressionOrMetaProperty(parser, context) {
const pos = getLocation(parser);
const id = parseIdentifier(parser, context);
if (consume(parser, context, 16777229 /* Period */)) {
if (parser.tokenValue !== 'target' ||
!(context & (524288 /* InParameter */ | 1048576 /* InFunctionBody */)))
tolerant(parser, context, 51 /* MetaNotInFunctionBody */);
return parseMetaProperty(parser, context, id, pos);
}
return finishNode(context, parser, pos, {
type: 'NewExpression',
callee: parseImportOrMemberExpression(parser, context, pos),
arguments: parser.token === 50331659 /* LeftParen */ ? parseArgumentList(parser, context) : [],
});
}
/**
* Parse either import or member expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-MemberExpression)
*
* @param parser Parser object
* @param context Context masks
*/
function parseImportOrMemberExpression(parser, context, pos) {
const { token } = parser;
if (context & 1 /* OptionsNext */ && token === 33566810 /* ImportKeyword */) {
// Invalid: '"new import(x)"'
if (lookahead(parser, context, nextTokenIsLeftParen))
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(token));
// Fixes cases like ''new import.meta','
return parseCallImportOrMetaProperty(parser, context);
}
return parseMemberExpression(parser, context, pos);
}
/**
* Parse super property
*
* @see [Link](https://tc39.github.io/ecma262/#prod-SuperProperty)
*
* @param parser Parser object
* @param context Context masks
*/
function parseSuperProperty(parser, context) {
// SuperProperty[Yield, Await]:
// super[Expression[+In, ?Yield, ?Await]]
// super.IdentifierName
const pos = getLocation(parser);
expect(parser, context, 33566813 /* SuperKeyword */);
switch (parser.token) {
case 50331659 /* LeftParen */:
// The super property has to be within a class constructor
if (!(context & 67108864 /* AllowSuperProperty */))
tolerant(parser, context, 52 /* BadSuperCall */);
break;
case 41943059 /* LeftBracket */:
case 16777229 /* Period */:
if (!(context & 33554432 /* Method */))
tolerant(parser, context, 53 /* UnexpectedSuper */);
break;
default:
tolerant(parser, context, 54 /* LoneSuper */);
}
return finishNode(context, parser, pos, {
type: 'Super',
});
}
/**
* Parse statement list
*
* @see [Link](https://tc39.github.io/ecma262/#prod-StatementList)
*
* @param parser Parser object
* @param context Context masks
*/
function parseTemplateLiteral(parser, context) {
const pos = getLocation(parser);
return finishNode(context, parser, pos, {
type: 'TemplateLiteral',
expressions: [],
quasis: [parseTemplateSpans(parser, context)],
});
}
/**
* Parse statement list
*
* @see [Link](https://tc39.github.io/ecma262/#prod-StatementList)
*
* @param parser Parser object
* @param context Context masks
*/
function parseTemplateHead(parser, context, cooked = null, raw, pos) {
parser.token = consumeTemplateBrace(parser, context);
return finishNode(context, parser, pos, {
type: 'TemplateElement',
value: {
cooked,
raw,
},
tail: false,
});
}
/**
* Parse statement list
*
* @see [Link](https://tc39.github.io/ecma262/#prod-StatementList)
*
* @param parser Parser object
* @param context Context masks
*/
function parseTemplate(parser, context, expressions = [], quasis = []) {
const pos = getLocation(parser);
const { tokenValue, tokenRaw } = parser;
expect(parser, context, 33554440 /* TemplateCont */);
expressions.push(parseExpression(parser, context));
const t = getLocation(parser);
quasis.push(parseTemplateHead(parser, context, tokenValue, tokenRaw, pos));
if (parser.token === 33554441 /* TemplateTail */) {
quasis.push(parseTemplateSpans(parser, context, t));
}
else {
parseTemplate(parser, context, expressions, quasis);
}
return finishNode(context, parser, pos, {
type: 'TemplateLiteral',
expressions,
quasis,
});
}
/**
* Parse statement list
*
* @see [Link](https://tc39.github.io/ecma262/#prod-StatementList)
*
* @param parser Parser object
* @param context Context masks
*/
function parseTemplateSpans(parser, context, pos = getLocation(parser)) {
const { tokenValue, tokenRaw } = parser;
expect(parser, context, 33554441 /* TemplateTail */);
return finishNode(context, parser, pos, {
type: 'TemplateElement',
value: {
cooked: tokenValue,
raw: tokenRaw,
},
tail: true,
});
}
/**
* Parses decorators
*
* @param parser Parser object
* @param context Context masks
*/
function parseDecoratorList(parser, context) {
const pos = getLocation(parser);
return finishNode(context, parser, pos, {
type: 'Decorator',
expression: parseLeftHandSideExpression(parser, context, pos)
});
}
/**
* Parses a list of decorators
*
* @param parser Parser object
* @param context Context masks
*/
function parseDecorators(parser, context) {
const decoratorList = [];
while (consume(parser, context, 120 /* At */)) {
decoratorList.push(parseDecoratorList(parser, context | 1073741824 /* AllowDecorator */));
}
return decoratorList;
}
// 12.15.5 Destructuring Assignment
/**
* Parses either a binding identifier or binding pattern
*
* @param parser Parser object
* @param context Context masks
*/
function parseBindingIdentifierOrPattern(parser, context, args = []) {
const { token } = parser;
if (token & 8388608 /* IsBindingPattern */) {
return token === 41943052 /* LeftBrace */ ?
parserObjectAssignmentPattern(parser, context) :
parseArrayAssignmentPattern(parser, context, args);
}
else if (token & (131072 /* IsAwait */ | 1073741824 /* IsYield */)) {
if (token & 131072 /* IsAwait */ && (context & (131072 /* Async */ | 8192 /* Module */))) {
tolerant(parser, context, 46 /* AwaitBindingIdentifier */);
}
else if (token & 1073741824 /* IsYield */ && (context & (262144 /* Yield */ | 4096 /* Strict */))) {
tolerant(parser, context, 47 /* YieldBindingIdentifier */);
}
}
args.push(parser.tokenValue);
return parseBindingIdentifier(parser, context);
}
/**
* Parse binding identifier
*
* @see [Link](https://tc39.github.io/ecma262/#prod-BindingIdentifier)
*
* @param parser Parser object
* @param context Context masks
*/
function parseBindingIdentifier(parser, context) {
const { token } = parser;
if (token & 4194304 /* IsEvalOrArguments */) {
if (context & 4096 /* Strict */)
tolerant(parser, context, 15 /* StrictLHSAssignment */);
parser.flags |= 2048 /* StrictEvalArguments */;
}
else if (context & 4194304 /* BlockScope */ && token === 33574984 /* LetKeyword */) {
// let is disallowed as a lexically bound name
tolerant(parser, context, 25 /* LetInLexicalBinding */);
}
else if (hasBit(token, 20480 /* FutureReserved */)) {
if (context & 4096 /* Strict */)
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(token));
parser.flags |= 1024 /* StrictFunctionName */;
}
else if (!isValidIdentifier(context, token)) {
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(token));
}
const pos = getLocation(parser);
const name = parser.tokenValue;
nextToken(parser, context);
return finishNode(context, parser, pos, {
type: 'Identifier',
name,
});
}
/**
* Parse assignment rest element
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AssignmentRestElement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseAssignmentRestElement(parser, context, args) {
const pos = getLocation(parser);
expect(parser, context, 14 /* Ellipsis */);
const argument = parseBindingIdentifierOrPattern(parser, context, args);
if (parser.token === 16777234 /* Comma */)
tolerant(parser, context, 86 /* RestWithComma */);
return finishNode(context, parser, pos, {
type: 'RestElement',
argument,
});
}
/**
* Parse rest property
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AssignmentRestProperty)
*
* @param parser Parser object
* @param context Context masks
*/
// tslint:disable-next-line:function-name
function AssignmentRestProperty(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 14 /* Ellipsis */);
const { token } = parser;
const argument = parseBindingIdentifierOrPattern(parser, context);
if (hasBit(token, 8388608 /* IsBindingPattern */))
tolerant(parser, context, 92 /* InvalidRestBindingPattern */);
if (parser.token === 16777234 /* Comma */)
tolerant(parser, context, 86 /* RestWithComma */);
return finishNode(context, parser, pos, {
type: 'RestElement',
argument,
});
}
/**
* 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]
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ArrayAssignmentPattern)
*
* @param Parser object
* @param Context masks
*/
function parseArrayAssignmentPattern(parser, context, args) {
const pos = getLocation(parser);
expect(parser, context, 41943059 /* LeftBracket */);
const elements = [];
while (parser.token !== 20 /* RightBracket */) {
if (consume(parser, context, 16777234 /* Comma */)) {
elements.push(null);
}
else {
if (parser.token === 14 /* Ellipsis */) {
elements.push(parseAssignmentRestElement(parser, context, args));
break;
}
else {
elements.push(parseExpressionCoverGrammar(parser, context | 65536 /* AllowIn */, parseBindingInitializer));
}
if (parser.token !== 20 /* RightBracket */)
expect(parser, context, 16777234 /* Comma */);
}
}
expect(parser, context, 20 /* RightBracket */);
// tslint:disable-next-line:no-object-literal-type-assertion
return finishNode(context, parser, pos, {
type: 'ArrayPattern',
elements,
});
}
/**
* Parse object assignment pattern
*
* @param Parser Parser object
* @param Context Context masks
*/
function parserObjectAssignmentPattern(parser, context) {
const pos = getLocation(parser);
const properties = [];
expect(parser, context, 41943052 /* LeftBrace */);
while (parser.token !== 17301519 /* RightBrace */) {
if (parser.token === 14 /* Ellipsis */) {
properties.push(AssignmentRestProperty(parser, context));
break;
}
properties.push(parseAssignmentProperty(parser, context));
if (parser.token !== 17301519 /* RightBrace */)
expect(parser, context, 16777234 /* Comma */);
}
expect(parser, context, 17301519 /* RightBrace */);
return finishNode(context, parser, pos, {
type: 'ObjectPattern',
properties,
});
}
/** Parse assignment pattern
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AssignmentPattern)
* @see [Link](https://tc39.github.io/ecma262/#prod-ArrayAssignmentPattern)
*
* @param parser Parser object
* @param context Context masks
* @param left LHS of assignment pattern
* @param pos Location
*/
function parseAssignmentPattern(parser, context, left, pos) {
return finishNode(context, parser, pos, {
type: 'AssignmentPattern',
left,
right: parseExpressionCoverGrammar(parser, context | 65536 /* AllowIn */, parseAssignmentExpression),
});
}
/**
* Parse binding initializer
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AssignmentPattern)
* @see [Link](https://tc39.github.io/ecma262/#prod-ArrayAssignmentPattern)
*
* @param parser Parser object
* @param context Context masks
*/
function parseBindingInitializer(parser, context) {
const pos = getLocation(parser);
const left = parseBindingIdentifierOrPattern(parser, context);
return !consume(parser, context, 83886109 /* Assign */) ?
left :
finishNode(context, parser, pos, {
type: 'AssignmentPattern',
left,
right: parseAssignmentExpression(parser, context | 65536 /* AllowIn */),
});
}
/**
* Parse assignment property
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AssignmentProperty)
*
* @param parser Parser object
* @param context Context masks
*/
function parseAssignmentProperty(parser, context) {
const pos = getLocation(parser);
const { token } = parser;
let key;
let value;
let computed = false;
let shorthand = false;
// single name binding
if (token & (65536 /* IsIdentifier */ | 4096 /* Keyword */)) {
key = parseIdentifier(parser, context);
shorthand = !consume(parser, context, 16777237 /* Colon */);
if (shorthand) {
const hasInitializer = consume(parser, context, 83886109 /* Assign */);
if (context & 262144 /* Yield */ && token & 1073741824 /* IsYield */)
tolerant(parser, context, 47 /* YieldBindingIdentifier */);
if (!isValidIdentifier(context, token))
tolerant(parser, context, 44 /* UnexpectedReserved */);
value = hasInitializer ? parseAssignmentPattern(parser, context, key, pos) : key;
}
else
value = parseBindingInitializer(parser, context);
}
else {
computed = token === 41943059 /* LeftBracket */;
key = parsePropertyName(parser, context);
expect(parser, context, 16777237 /* Colon */);
value = parseExpressionCoverGrammar(parser, context, parseBindingInitializer);
}
// Note! The specs specifically state that this is "assignment property", but
// nothing in ESTree specs explains the difference between this "property" and the "property" for object literals.
return finishNode(context, parser, pos, {
type: 'Property',
kind: 'init',
key,
computed,
value,
method: false,
shorthand,
});
}
// Declarations
/**
* Parses class declaration
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ClassDeclaration)
*
* @param parser Parser object
* @param context Context masks
*/
function parseClassDeclaration(parser, context) {
const pos = getLocation(parser);
let decorators = [];
if (context & 2048 /* OptionsExperimental */)
decorators = parseDecorators(parser, context);
expect(parser, context | 536870912 /* DisallowEscapedKeyword */, 33566797 /* ClassKeyword */);
const id = (context & 16777216 /* RequireIdentifier */ && (parser.token !== 33619969 /* Identifier */))
? null :
parseBindingIdentifier(parser, context | 4096 /* Strict */ | 536870912 /* DisallowEscapedKeyword */);
let state = 0 /* None */;
let superClass = null;
if (consume(parser, context, 12372 /* ExtendsKeyword */)) {
superClass = parseLeftHandSideExpression(parser, context | 4096 /* Strict */, pos);
state |= 512 /* Heritage */;
}
const body = parseClassBodyAndElementList(parser, context & ~16777216 /* RequireIdentifier */ | 4096 /* Strict */ | 32768 /* InClass */, state);
return finishNode(context, parser, pos, context & 2048 /* OptionsExperimental */ ? {
type: 'ClassDeclaration',
id,
superClass,
body,
decorators
} : {
type: 'ClassDeclaration',
id,
superClass,
body
});
}
/**
* Parses function declaration
*
* @see [Link](https://tc39.github.io/ecma262/#prod-FunctionDeclaration)
*
* @param parser Parser object
* @param context Context masks
*/
function parseFunctionDeclaration(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 33566808 /* FunctionKeyword */);
let isGenerator = 0 /* None */;
if (consume(parser, context, 167774771 /* Multiply */)) {
if (context & 2097152 /* AllowSingleStatement */ && !(context & 1048576 /* InFunctionBody */)) {
tolerant(parser, context, 20 /* GeneratorInSingleStatementContext */);
}
isGenerator = 1 /* Generator */;
}
return parseFunctionDeclarationBody(parser, context, isGenerator, pos);
}
/**
* Parses out a function declartion body
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AsyncFunctionDeclaration)
* @see [Link](https://tc39.github.io/ecma262/#prod-AsyncGeneratorDeclaration)
*
* @param parser Parser object
* @param context Context mask
* @param state Modifier state
* @param pos Current location
*/
function parseFunctionDeclarationBody(parser, context, state, pos) {
const id = parseFunctionDeclarationName(parser, context);
const { params, body } = swapContext(parser, context & ~(33554432 /* Method */ | 67108864 /* AllowSuperProperty */ | 16777216 /* RequireIdentifier */), state, parseFormalListAndBody);
return finishNode(context, parser, pos, {
type: 'FunctionDeclaration',
params,
body,
async: !!(state & 2 /* Await */),
generator: !!(state & 1 /* Generator */),
expression: false,
id,
});
}
/**
* Parses async function or async generator declaration
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AsyncFunctionDeclaration)
* @see [Link](https://tc39.github.io/ecma262/#prod-AsyncGeneratorDeclaration)
*
* @param parser Parser object
* @param context Context masks
*/
function parseAsyncFunctionOrAsyncGeneratorDeclaration(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 299116 /* AsyncKeyword */);
expect(parser, context, 33566808 /* FunctionKeyword */);
const isAwait = 2 /* Await */;
const isGenerator = consume(parser, context, 167774771 /* Multiply */) ? 1 /* Generator */ : 0 /* None */;
return parseFunctionDeclarationBody(parser, context, isGenerator | isAwait, pos);
}
/**
* Shared helper function for "parseFunctionDeclaration" and "parseAsyncFunctionOrAsyncGeneratorDeclaration"
* so we can re-use the same logic when parsing out the function name, or throw an
* error if the 'RequireIdentifier' mask is not set
*
* @param parser Parser object
* @param context Context masks
*/
function parseFunctionDeclarationName(parser, context) {
const { token } = parser;
let id = null;
if (context & 262144 /* Yield */ && token & 1073741824 /* IsYield */)
tolerant(parser, context, 47 /* YieldBindingIdentifier */);
if (context & 131072 /* Async */ && token & 131072 /* IsAwait */)
tolerant(parser, context, 46 /* AwaitBindingIdentifier */);
if (token !== 50331659 /* LeftParen */) {
id = parseBindingIdentifier(parser, context);
// Unnamed functions are forbidden in statement context.
}
else if (!(context & 16777216 /* RequireIdentifier */))
tolerant(parser, context, 37 /* UnNamedFunctionDecl */);
return id;
}
/**
* VariableDeclaration :
* BindingIdentifier Initializeropt
* BindingPattern Initializer
*
* VariableDeclarationNoIn :
* BindingIdentifier InitializerNoInopt
* BindingPattern InitializerNoIn
*
*
* @see [Link](https://tc39.github.io/ecma262/#prod-VariableDeclaration)
*
* @param parser Parser object
* @param context Context masks
*/
function parseVariableDeclaration(parser, context, isConst) {
const pos = getLocation(parser);
const isBindingPattern = (parser.token & 8388608 /* IsBindingPattern */) !== 0;
const id = parseBindingIdentifierOrPattern(parser, context);
let init = null;
if (consume(parser, context | 536870912 /* DisallowEscapedKeyword */, 83886109 /* Assign */)) {
init = parseExpressionCoverGrammar(parser, context & ~(4194304 /* BlockScope */ | 8388608 /* ForStatement */), parseAssignmentExpression);
if (parser.token & 1048576 /* IsInOrOf */ && (context & 8388608 /* ForStatement */ || isBindingPattern)) {
if (parser.token === 168834865 /* InKeyword */) {
// https://github.com/tc39/test262/blob/master/test/annexB/language/statements/for-in/strict-initializer.js
if (context & (4194304 /* BlockScope */ | 4096 /* Strict */ | 131072 /* Async */) || isBindingPattern) {
tolerant(parser, context, 23 /* ForInOfLoopInitializer */, tokenDesc(parser.token));
}
}
else
tolerant(parser, context, 23 /* ForInOfLoopInitializer */, tokenDesc(parser.token));
}
// Note: Initializers are required for 'const' and binding patterns
}
else if (!(parser.token & 1048576 /* IsInOrOf */) && (isConst || isBindingPattern)) {
tolerant(parser, context, 22 /* DeclarationMissingInitializer */, isConst ? 'const' : 'destructuring');
}
return finishNode(context, parser, pos, {
type: 'VariableDeclarator',
init,
id,
});
}
/**
* Parses variable declaration list
*
* @see [Link](https://tc39.github.io/ecma262/#prod-VariableDeclarationList)
*
* @param parser Parser object
* @param context Context masks
*/
function parseVariableDeclarationList(parser, context, isConst) {
const list = [parseVariableDeclaration(parser, context, isConst)];
while (consume(parser, context, 16777234 /* Comma */))
list.push(parseVariableDeclaration(parser, context, isConst));
if (context & 8388608 /* ForStatement */ && parser.token & 1048576 /* IsInOrOf */ && list.length !== 1) {
tolerant(parser, context, 24 /* ForInOfLoopMultiBindings */, tokenDesc(parser.token));
}
return list;
}
// Statements
/**
* Parses statement list items
*
* @see [Link](https://tc39.github.io/ecma262/#prod-StatementListItem)
*
* @param parser Parser object
* @param context Context masks
*/
function parseStatementListItem(parser, context) {
switch (parser.token) {
case 33566808 /* FunctionKeyword */:
return parseFunctionDeclaration(parser, context);
case 120 /* At */:
case 33566797 /* ClassKeyword */:
return parseClassDeclaration(parser, context);
case 33574984 /* LetKeyword */:
return parseLetOrExpressionStatement(parser, context | 65536 /* AllowIn */);
case 33566793 /* ConstKeyword */:
return parseVariableStatement(parser, context | 4194304 /* BlockScope */ | 65536 /* AllowIn */);
case 299116 /* AsyncKeyword */:
return parseAsyncFunctionDeclarationOrStatement(parser, context);
case 33566810 /* ImportKeyword */: {
if (context & 1 /* OptionsNext */ && lookahead(parser, context, nextTokenIsLeftParenOrPeriod)) {
return parseExpressionStatement(parser, context | 65536 /* AllowIn */);
}
}
case 12371 /* ExportKeyword */:
if (context & 8192 /* Module */) {
tolerant(parser, context, 32 /* ImportExportDeclAtTopLevel */, tokenDesc(parser.token));
}
default:
return parseStatement(parser, context | 2097152 /* AllowSingleStatement */);
}
}
/**
* Parses statements
*
* @see [Link](https://tc39.github.io/ecma262/#prod-Statement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseStatement(parser, context) {
switch (parser.token) {
case 33566791 /* VarKeyword */:
return parseVariableStatement(parser, context | 65536 /* AllowIn */);
case 17301521 /* Semicolon */:
return parseEmptyStatement(parser, context);
case 33566814 /* SwitchKeyword */:
return parseSwitchStatement(parser, context);
case 41943052 /* LeftBrace */:
return parseBlockStatement(parser, context);
case 12380 /* ReturnKeyword */:
return parseReturnStatement(parser, context);
case 12377 /* IfKeyword */:
return parseIfStatement(parser, context);
case 12369 /* DoKeyword */:
return parseDoWhileStatement(parser, context);
case 12402 /* WhileKeyword */:
return parseWhileStatement(parser, context);
case 12387 /* WithKeyword */:
return parseWithStatement(parser, context);
case 12362 /* BreakKeyword */:
return parseBreakStatement(parser, context);
case 12366 /* ContinueKeyword */:
return parseContinueStatement(parser, context);
case 12367 /* DebuggerKeyword */:
return parseDebuggerStatement(parser, context);
case 302002272 /* ThrowKeyword */:
return parseThrowStatement(parser, context);
case 12385 /* TryKeyword */:
return parseTryStatement(parser, context | 536870912 /* DisallowEscapedKeyword */);
case 12374 /* ForKeyword */:
return parseForStatement(parser, context | 8388608 /* ForStatement */);
case 299116 /* AsyncKeyword */:
if (lookahead(parser, context, nextTokenIsFuncKeywordOnSameLine)) {
tolerant(parser, context, 33 /* AsyncFunctionInSingleStatementContext */);
}
return parseExpressionOrLabelledStatement(parser, context | 2097152 /* AllowSingleStatement */);
case 33566808 /* FunctionKeyword */:
// V8
tolerant(parser, context, context & 4096 /* Strict */ ? 17 /* StrictFunction */ : 18 /* SloppyFunction */);
case 33566797 /* ClassKeyword */:
tolerant(parser, context, 19 /* ForbiddenAsStatement */, tokenDesc(parser.token));
default:
return parseExpressionOrLabelledStatement(parser, context);
}
}
/**
* Parses empty statement
*
* @see [Link](https://tc39.github.io/ecma262/#prod-EmptyStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseEmptyStatement(parser, context) {
const pos = getLocation(parser);
nextToken(parser, context);
return finishNode(context, parser, pos, {
type: 'EmptyStatement'
});
}
/**
* Parses the continue statement production
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ContinueStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseContinueStatement(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 12366 /* ContinueKeyword */);
// Appearing of continue without an IterationStatement leads to syntax error
if (!(parser.flags & 48 /* AllowBreakOrContinue */)) {
tolerant(parser, context, 28 /* InvalidNestedStatement */, tokenDesc(parser.token));
}
let label = null;
const { tokenValue } = parser;
if (!(parser.flags & 1 /* NewLine */) && parser.token & (65536 /* IsIdentifier */ | 4096 /* Keyword */)) {
label = parseIdentifier(parser, context);
validateBreakOrContinueLabel(parser, context, tokenValue, /* isContinue */ true);
}
consumeSemicolon(parser, context);
return finishNode(context, parser, pos, {
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
*/
function parseBreakStatement(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 12362 /* BreakKeyword */);
let label = null;
// Use 'tokenValue' to avoid accessing another object shape which in turn can lead to
// a "'deopt" when getting the identifier value (*if any*)
const { tokenValue } = parser;
if (!(parser.flags & 1 /* NewLine */) && parser.token & (65536 /* IsIdentifier */ | 4096 /* Keyword */)) {
label = parseIdentifier(parser, context);
validateBreakOrContinueLabel(parser, context, tokenValue, /* isContinue */ false);
}
else if (!(parser.flags & 48 /* AllowBreakOrContinue */)) {
tolerant(parser, context, 28 /* InvalidNestedStatement */, 'break');
}
consumeSemicolon(parser, context);
return finishNode(context, parser, pos, {
type: 'BreakStatement',
label
});
}
/**
* Parses the if statement production
*
* @see [Link](https://tc39.github.io/ecma262/#sec-if-statement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseIfStatement(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 12377 /* IfKeyword */);
expect(parser, context, 50331659 /* LeftParen */);
const test = parseExpression(parser, (context & ~1073741824 /* AllowDecorator */) | 65536 /* AllowIn */);
expect(parser, context, 16 /* RightParen */);
const consequent = parseConsequentOrAlternate(parser, context | 536870912 /* DisallowEscapedKeyword */);
const alternate = consume(parser, context, 12370 /* ElseKeyword */) ? parseConsequentOrAlternate(parser, context) : null;
return finishNode(context, parser, pos, {
type: 'IfStatement',
test,
consequent,
alternate
});
}
/**
* Parse either consequent or alternate. Supports AnnexB.
* @param parser Parser object
* @param context Context masks
*/
function parseConsequentOrAlternate(parser, context) {
return context & 4096 /* Strict */ || parser.token !== 33566808 /* FunctionKeyword */
? parseStatement(parser, context & ~2097152 /* AllowSingleStatement */)
: parseFunctionDeclaration(parser, context);
}
/**
* Parses the debugger statement production
*
* @see [Link](https://tc39.github.io/ecma262/#prod-DebuggerStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseDebuggerStatement(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 12367 /* DebuggerKeyword */);
consumeSemicolon(parser, context);
return finishNode(context, parser, pos, {
type: 'DebuggerStatement'
});
}
/**
* Parses try statement
*
* @see [Link](https://tc39.github.io/ecma262/#prod-TryStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseTryStatement(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 12385 /* TryKeyword */);
const block = parseBlockStatement(parser, context);
const handler = parser.token === 12364 /* CatchKeyword */ ? parseCatchBlock(parser, context) : null;
const finalizer = consume(parser, context, 12373 /* FinallyKeyword */) ? parseBlockStatement(parser, context) : null;
if (!handler && !finalizer)
tolerant(parser, context, 77 /* NoCatchOrFinally */);
return finishNode(context, parser, pos, {
type: 'TryStatement',
block,
handler,
finalizer
});
}
/**
* Parsescatch block
*
* @see [Link](https://tc39.github.io/ecma262/#prod-Catch)
*
* @param parser Parser object
* @param context Context masks
*/
function parseCatchBlock(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 12364 /* CatchKeyword */);
let param = null;
if (context & 1 /* OptionsNext */
? consume(parser, context, 50331659 /* LeftParen */)
: expect(parser, context, 50331659 /* LeftParen */)) {
const params = [];
param = parseBindingIdentifierOrPattern(parser, context, params);
validateParams(parser, context, params);
expect(parser, context, 16 /* RightParen */);
}
const body = parseBlockStatement(parser, context);
return finishNode(context, parser, pos, {
type: 'CatchClause',
param,
body
});
}
/**
* Parses throw statement
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ThrowStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseThrowStatement(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 302002272 /* ThrowKeyword */);
if (parser.flags & 1 /* NewLine */)
tolerant(parser, context, 78 /* NewlineAfterThrow */);
const argument = parseExpression(parser, (context & ~1073741824 /* AllowDecorator */) | 65536 /* AllowIn */);
consumeSemicolon(parser, context);
return finishNode(context, parser, pos, {
type: 'ThrowStatement',
argument
});
}
/**
* Parses expression statement
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ExpressionStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseExpressionStatement(parser, context) {
const pos = getLocation(parser);
const expr = parseExpression(parser, (context & ~1073741824 /* AllowDecorator */) | 65536 /* AllowIn */);
consumeSemicolon(parser, context);
return finishNode(context, parser, pos, {
type: 'ExpressionStatement',
expression: expr
});
}
/**
* 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
*/
function parseDirective(parser, context) {
const pos = getLocation(parser);
const directive = parser.tokenRaw.slice(1, -1);
const expr = parseExpression(parser, (context & ~1073741824 /* AllowDecorator */) | 65536 /* AllowIn */);
consumeSemicolon(parser, context);
return finishNode(context, parser, pos, {
type: 'ExpressionStatement',
expression: expr,
directive
});
}
/**
* Parses either expression or labelled statement
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ExpressionStatement)
* @see [Link](https://tc39.github.io/ecma262/#prod-LabelledStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseExpressionOrLabelledStatement(parser, context) {
const pos = getLocation(parser);
const { tokenValue, token } = parser;
const expr = parseExpression(parser, (context & ~(2097152 /* AllowSingleStatement */ | 1073741824 /* AllowDecorator */)) | 65536 /* AllowIn */);
if (token & (65536 /* IsIdentifier */ | 4096 /* Keyword */) && parser.token === 16777237 /* Colon */) {
// If within generator function bodies, we do it like this so we can throw an nice error message
if (context & 262144 /* Yield */ && token & 1073741824 /* IsYield */)
tolerant(parser, context, 55 /* YieldReservedKeyword */);
expect(parser, context, 16777237 /* Colon */, 81 /* LabelNoColon */);
if (hasLabel(parser, tokenValue))
tolerant(parser, context, 27 /* LabelRedeclaration */, tokenValue);
addLabel(parser, tokenValue);
let body;
if (!(context & 4096 /* Strict */) &&
context & 2097152 /* AllowSingleStatement */ &&
parser.token === 33566808 /* FunctionKeyword */) {
body = parseFunctionDeclaration(parser, context);
}
else {
body = parseStatement(parser, context);
}
popLabel(parser, tokenValue);
return finishNode(context, parser, pos, {
type: 'LabeledStatement',
label: expr,
body
});
}
consumeSemicolon(parser, context);
return finishNode(context, parser, pos, {
type: 'ExpressionStatement',
expression: expr
});
}
/**
* Parses either a binding identifier or bindign pattern
*
* @see [Link](https://tc39.github.io/ecma262/#prod-EmptyStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseDoWhileStatement(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 12369 /* DoKeyword */);
const body = parseIterationStatement(parser, context);
expect(parser, context, 12402 /* WhileKeyword */);
expect(parser, context, 50331659 /* LeftParen */);
const test = parseExpression(parser, (context & ~1073741824 /* AllowDecorator */) | 65536 /* AllowIn */);
expect(parser, context, 16 /* RightParen */);
consume(parser, context, 17301521 /* Semicolon */);
return finishNode(context, parser, pos, {
type: 'DoWhileStatement',
body,
test
});
}
/**
* Parses while statement
*
* @see [Link](https://tc39.github.io/ecma262/#prod-grammar-notation-WhileStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseWhileStatement(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 12402 /* WhileKeyword */);
expect(parser, context, 50331659 /* LeftParen */);
const test = parseExpression(parser, (context & ~1073741824 /* AllowDecorator */) | 65536 /* AllowIn */);
expect(parser, context, 16 /* RightParen */);
const body = parseIterationStatement(parser, context);
return finishNode(context, parser, pos, {
type: 'WhileStatement',
test,
body
});
}
/**
* 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
*/
function parseBlockStatement(parser, context) {
const pos = getLocation(parser);
const body = [];
expect(parser, context, 41943052 /* LeftBrace */);
while (parser.token !== 17301519 /* RightBrace */) {
body.push(parseStatementListItem(parser, context));
}
expect(parser, context, 17301519 /* RightBrace */);
return finishNode(context, parser, pos, {
type: 'BlockStatement',
body
});
}
/**
* Parses return statement
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ReturnStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseReturnStatement(parser, context) {
const pos = getLocation(parser);
if (!(context & (32 /* OptionsGlobalReturn */ | 1048576 /* InFunctionBody */))) {
tolerant(parser, context, 16 /* IllegalReturn */);
}
if (parser.flags & 32768 /* EscapedKeyword */)
tolerant(parser, context, 2 /* InvalidEscapedReservedWord */);
expect(parser, context, 12380 /* ReturnKeyword */);
const argument = !(parser.token & 524288 /* ASI */) && !(parser.flags & 1 /* NewLine */)
? parseExpression(parser, (context & ~(1048576 /* InFunctionBody */ | 1073741824 /* AllowDecorator */)) | 65536 /* AllowIn */)
: null;
consumeSemicolon(parser, context);
return finishNode(context, parser, pos, {
type: 'ReturnStatement',
argument
});
}
/**
* Sets the necessary mutable parser flags. The parser flags will
* be unset after done parsing out the statements.
*
* @see [Link](https://tc39.github.io/ecma262/#prod-grammar-notation-IterationStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseIterationStatement(parser, context) {
// Note: We are deviating from the original grammar here beauce the original grammar says that the
// 'iterationStatement' should return either'for', 'do' or 'while' statements. We are doing some
// bitfiddling before and after to modify the parser state before we let the 'parseStatement'
// return the mentioned statements (to match the original grammar).
const savedFlags = parser.flags;
parser.flags |= 32 /* InIterationStatement */ | 4 /* AllowDestructuring */;
const body = parseStatement(parser, (context & ~2097152 /* AllowSingleStatement */) | 536870912 /* DisallowEscapedKeyword */);
parser.flags = savedFlags;
return body;
}
/**
* Parses with statement
*
* @see [Link](https://tc39.github.io/ecma262/#prod-WithStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseWithStatement(parser, context) {
if (context & 4096 /* Strict */)
tolerant(parser, context, 35 /* StrictModeWith */);
const pos = getLocation(parser);
expect(parser, context, 12387 /* WithKeyword */);
expect(parser, context, 50331659 /* LeftParen */);
const object = parseExpression(parser, (context & ~1073741824 /* AllowDecorator */) | 65536 /* AllowIn */);
expect(parser, context, 16 /* RightParen */);
const body = parseStatement(parser, context & ~2097152 /* AllowSingleStatement */);
return finishNode(context, parser, pos, {
type: 'WithStatement',
object,
body
});
}
/**
* Parses switch statement
*
* @see [Link](https://tc39.github.io/ecma262/#prod-SwitchStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseSwitchStatement(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 33566814 /* SwitchKeyword */);
expect(parser, context, 50331659 /* LeftParen */);
const discriminant = parseExpression(parser, (context & ~1073741824 /* AllowDecorator */) | 65536 /* AllowIn */);
expect(parser, context, 16 /* RightParen */);
expect(parser, context | 536870912 /* DisallowEscapedKeyword */, 41943052 /* LeftBrace */);
const cases = [];
const savedFlags = parser.flags;
parser.flags |= 16 /* InSwitchStatement */;
let seenDefault = false;
while (parser.token !== 17301519 /* RightBrace */) {
const clause = parseCaseOrDefaultClauses(parser, context);
cases.push(clause);
if (clause.test === null) {
if (seenDefault)
tolerant(parser, context, 31 /* MultipleDefaultsInSwitch */);
seenDefault = true;
}
}
parser.flags = savedFlags;
expect(parser, context, 17301519 /* RightBrace */);
return finishNode(context, parser, pos, {
type: 'SwitchStatement',
discriminant,
cases
});
}
/**
* Parses either default clause or case clauses
*
* @see [Link](https://tc39.github.io/ecma262/#prod-CaseClauses)
* @see [Link](https://tc39.github.io/ecma262/#prod-DefaultClause)
*
* @param parser Parser object
* @param context Context masks
*/
function parseCaseOrDefaultClauses(parser, context) {
const pos = getLocation(parser);
let test = null;
if (consume(parser, context, 12363 /* CaseKeyword */)) {
test = parseExpression(parser, (context & ~1073741824 /* AllowDecorator */) | 65536 /* AllowIn */);
}
else {
expect(parser, context, 12368 /* DefaultKeyword */);
}
expect(parser, context, 16777237 /* Colon */);
const consequent = [];
while (!isEndOfCaseOrDefaultClauses(parser)) {
consequent.push(parseStatementListItem(parser, context | 65536 /* AllowIn */));
}
return finishNode(context, parser, pos, {
type: 'SwitchCase',
test,
consequent
});
}
/**
* Parses variable statement
*
* @see [Link](https://tc39.github.io/ecma262/#prod-VariableStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseVariableStatement(parser, context, shouldConsume = true) {
const pos = getLocation(parser);
const { token } = parser;
const isConst = token === 33566793 /* ConstKeyword */;
nextToken(parser, context);
const declarations = parseVariableDeclarationList(parser, context, isConst);
// Only consume semicolons if not inside the 'ForStatement' production
if (shouldConsume)
consumeSemicolon(parser, context);
return finishNode(context, parser, pos, {
type: 'VariableDeclaration',
kind: tokenDesc(token),
declarations
});
}
/**
* Parses either an lexical declaration (let) or an expression statement
*
* @see [Link](https://tc39.github.io/ecma262/#sec-let-and-const-declarations)
* @see [Link](https://tc39.github.io/ecma262/#prod-ExpressionStatement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseLetOrExpressionStatement(parser, context, shouldConsume = true) {
return lookahead(parser, context, isLexical)
? parseVariableStatement(parser, context | 4194304 /* BlockScope */, shouldConsume)
: parseExpressionOrLabelledStatement(parser, context);
}
/**
* Parses either async function declaration or statement
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AsyncFunctionDeclaration)
* @see [Link](https://tc39.github.io/ecma262/#prod-Statement)
*
* @param parser Parser object
* @param context Context masks
*/
function parseAsyncFunctionDeclarationOrStatement(parser, context) {
return lookahead(parser, context, nextTokenIsFuncKeywordOnSameLine)
? parseAsyncFunctionOrAsyncGeneratorDeclaration(parser, context)
: parseStatement(parser, context);
}
/**
* 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
*/
function parseForStatement(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 12374 /* ForKeyword */);
const awaitToken = !!(context & 131072 /* Async */ && consume(parser, context, 33788013 /* AwaitKeyword */));
expect(parser, context | 536870912 /* DisallowEscapedKeyword */, 50331659 /* LeftParen */);
const { token } = parser;
let init = null;
let sequencePos = null;
let variableStatement = null;
let type = 'ForStatement';
let test = null;
let update = null;
let right;
if (token === 33566793 /* ConstKeyword */ || (token === 33574984 /* LetKeyword */ && lookahead(parser, context, isLexical))) {
variableStatement = parseVariableStatement(parser, (context & ~65536 /* AllowIn */) | 4194304 /* BlockScope */, /* shouldConsume */ false);
}
else if (token === 33566791 /* VarKeyword */) {
variableStatement = parseVariableStatement(parser, context & ~65536 /* AllowIn */, /* shouldConsume */ false);
}
else if (token !== 17301521 /* Semicolon */) {
sequencePos = getLocation(parser);
init = restoreExpressionCoverGrammar(parser, (context & ~65536 /* AllowIn */) | 536870912 /* DisallowEscapedKeyword */, parseAssignmentExpression);
}
if (consume(parser, context, 1085554 /* OfKeyword */)) {
type = 'ForOfStatement';
if (init) {
if (!(parser.flags & 4 /* AllowDestructuring */) || init.type === 'AssignmentExpression') {
tolerant(parser, context, 71 /* InvalidDestructuringTarget */);
}
reinterpret(parser, context, init);
}
else
init = variableStatement;
right = parseAssignmentExpression(parser, context | 65536 /* AllowIn */);
}
else if (consume(parser, context, 168834865 /* InKeyword */)) {
if (init) {
if (!(parser.flags & 4 /* AllowDestructuring */))
tolerant(parser, context, 71 /* InvalidDestructuringTarget */);
reinterpret(parser, context, init);
}
else
init = variableStatement;
type = 'ForInStatement';
right = parseExpression(parser, (context & ~1073741824 /* AllowDecorator */) | 65536 /* AllowIn */);
}
else {
if (parser.token === 16777234 /* Comma */)
init = parseSequenceExpression(parser, context, init, sequencePos);
if (variableStatement)
init = variableStatement;
expect(parser, context, 17301521 /* Semicolon */);
test = parser.token !== 17301521 /* Semicolon */
? parseExpression(parser, (context & ~1073741824 /* AllowDecorator */) | 65536 /* AllowIn */)
: null;
expect(parser, context, 17301521 /* Semicolon */);
update = parser.token !== 16 /* RightParen */
? parseExpression(parser, (context & ~1073741824 /* AllowDecorator */) | 65536 /* AllowIn */)
: null;
}
expect(parser, context, 16 /* RightParen */);
const body = parseIterationStatement(parser, context);
return finishNode(context, parser, pos, type === 'ForOfStatement'
? {
type,
body,
left: init,
right,
await: awaitToken
}
: right
? {
type: type,
body,
left: init,
right
}
: {
type: type,
body,
init,
test,
update
});
}
// 15.2 Modules
/**
* Parse module item list
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ModuleItemList)
*
* @param parser Parser object
* @param context Context masks
*/
function parseModuleItemList(parser, context) {
// Prime the scanner
nextToken(parser, context);
const statements = [];
while (parser.token !== 524288 /* EndOfSource */) {
statements.push(parser.token === 33554435 /* StringLiteral */ ?
parseDirective(parser, context) :
parseModuleItem(parser, context | 65536 /* AllowIn */));
}
return statements;
}
/**
* Parse module item
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ModuleItem)
*
* @param parser Parser object
* @param context Context masks
*/
function parseModuleItem(parser, context) {
switch (parser.token) {
// @decorator
case 120 /* At */:
return parseDecorators(parser, context);
// ExportDeclaration
case 12371 /* ExportKeyword */:
return parseExportDeclaration(parser, context);
// ImportDeclaration
case 33566810 /* ImportKeyword */:
// 'Dynamic Import' or meta property disallowed here
if (!(context & 1 /* OptionsNext */ && lookahead(parser, context, nextTokenIsLeftParenOrPeriod))) {
return parseImportDeclaration(parser, context);
}
default:
return parseStatementListItem(parser, context);
}
}
/**
* Parse export declaration
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ExportDeclaration)
*
* @param parser Parser object
* @param context Context masks
*/
function parseExportDeclaration(parser, context) {
const pos = getLocation(parser);
const specifiers = [];
let source = null;
let declaration = null;
expect(parser, context | 536870912 /* DisallowEscapedKeyword */, 12371 /* ExportKeyword */);
switch (parser.token) {
// export * FromClause ;
case 167774771 /* Multiply */:
return parseExportAllDeclaration(parser, context, pos);
case 12368 /* DefaultKeyword */:
return parseExportDefault(parser, context, pos);
case 41943052 /* LeftBrace */:
{
// export ExportClause FromClause ;
// export ExportClause ;
expect(parser, context, 41943052 /* LeftBrace */);
let hasReservedWord = false;
while (parser.token !== 17301519 /* RightBrace */) {
if (parser.token & 12288 /* Reserved */) {
hasReservedWord = true;
setPendingError(parser);
}
specifiers.push(parseNamedExportDeclaration(parser, context));
if (parser.token !== 17301519 /* RightBrace */)
expect(parser, context, 16777234 /* Comma */);
}
expect(parser, context | 536870912 /* DisallowEscapedKeyword */, 17301519 /* RightBrace */);
if (parser.token === 36977 /* FromKeyword */) {
source = parseModuleSpecifier(parser, context);
// The left hand side can't be a keyword where there is no
// 'from' keyword since it references a local binding.
}
else if (hasReservedWord) {
tolerant(parser, context, 44 /* UnexpectedReserved */);
}
consumeSemicolon(parser, context);
break;
}
// export ClassDeclaration
case 33566797 /* ClassKeyword */:
declaration = (parseClassDeclaration(parser, context));
break;
// export LexicalDeclaration
case 33574984 /* LetKeyword */:
case 33566793 /* ConstKeyword */:
declaration = parseVariableStatement(parser, context | 4194304 /* BlockScope */);
break;
// export VariableDeclaration
case 33566791 /* VarKeyword */:
declaration = parseVariableStatement(parser, context);
break;
// export HoistableDeclaration
case 33566808 /* FunctionKeyword */:
declaration = parseFunctionDeclaration(parser, context);
break;
// export HoistableDeclaration
case 299116 /* AsyncKeyword */:
if (lookahead(parser, context, nextTokenIsFuncKeywordOnSameLine)) {
declaration = parseAsyncFunctionOrAsyncGeneratorDeclaration(parser, context);
break;
}
// Falls through
default:
report(parser, 1 /* UnexpectedToken */, tokenDesc(parser.token));
}
return finishNode(context, parser, pos, {
type: 'ExportNamedDeclaration',
source,
specifiers,
declaration,
});
}
/**
* Parse export all declaration
*
* @param parser Parser object
* @param context Context masks
*/
function parseExportAllDeclaration(parser, context, pos) {
expect(parser, context, 167774771 /* Multiply */);
const source = parseModuleSpecifier(parser, context);
consumeSemicolon(parser, context);
return finishNode(context, parser, pos, {
type: 'ExportAllDeclaration',
source,
});
}
/**
* Parse named export declaration
*
* @param parser Parser object
* @param context Context masks
*/
function parseNamedExportDeclaration(parser, context) {
const pos = getLocation(parser);
// ExportSpecifier :
// IdentifierName
// IdentifierName as IdentifierName
const local = parseIdentifierName(parser, context | 536870912 /* DisallowEscapedKeyword */, parser.token);
const exported = consume(parser, context, 36971 /* AsKeyword */)
? parseIdentifierName(parser, context, parser.token)
: local;
return finishNode(context, parser, pos, {
type: 'ExportSpecifier',
local,
exported,
});
}
/**
* Parse export default
*
* @see [Link](https://tc39.github.io/ecma262/#prod-HoistableDeclaration)
* @see [Link](https://tc39.github.io/ecma262/#prod-ClassDeclaration)
* @see [Link](https://tc39.github.io/ecma262/#prod-HoistableDeclaration)
*
* @param parser Parser object
* @param context Context masks
* @param pos Location
*/
function parseExportDefault(parser, context, pos) {
expect(parser, context | 536870912 /* DisallowEscapedKeyword */, 12368 /* DefaultKeyword */);
let declaration;
switch (parser.token) {
// export default HoistableDeclaration[Default]
case 33566808 /* FunctionKeyword */:
declaration = parseFunctionDeclaration(parser, context | 16777216 /* RequireIdentifier */);
break;
// export default ClassDeclaration[Default]
// export default @decl ClassDeclaration[Default]
case 120 /* At */:
case 33566797 /* ClassKeyword */:
declaration = parseClassDeclaration(parser, context & ~65536 /* AllowIn */ | 16777216 /* RequireIdentifier */);
break;
// export default HoistableDeclaration[Default]
case 299116 /* AsyncKeyword */:
declaration = parseAsyncFunctionOrAssignmentExpression(parser, context | 16777216 /* RequireIdentifier */);
break;
default:
{
// export default [lookahead ∉ {function, class}] AssignmentExpression[In] ;
declaration = parseAssignmentExpression(parser, context | 65536 /* AllowIn */);
consumeSemicolon(parser, context);
}
}
return finishNode(context, parser, pos, {
type: 'ExportDefaultDeclaration',
declaration,
});
}
/**
* Parse import declaration
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ImportDeclaration)
*
* @param parser Parser object
* @param context Context masks
*/
function parseImportDeclaration(parser, context) {
const pos = getLocation(parser);
expect(parser, context, 33566810 /* ImportKeyword */);
let source;
let specifiers = [];
// 'import' ModuleSpecifier ';'
if (parser.token === 33554435 /* StringLiteral */) {
source = parseLiteral(parser, context);
}
else {
specifiers = parseImportClause(parser, context | 536870912 /* DisallowEscapedKeyword */);
source = parseModuleSpecifier(parser, context);
}
consumeSemicolon(parser, context);
return finishNode(context, parser, pos, {
type: 'ImportDeclaration',
specifiers,
source,
});
}
/**
* Parse import clause
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ImportClause)
*
* @param parser Parser object
* @param context Context masks
*/
function parseImportClause(parser, context) {
const specifiers = [];
switch (parser.token) {
// 'import' ModuleSpecifier ';'
case 33619969 /* Identifier */:
{
specifiers.push(parseImportDefaultSpecifier(parser, context));
if (consume(parser, context, 16777234 /* Comma */)) {
switch (parser.token) {
// import a, * as foo
case 167774771 /* Multiply */:
parseImportNamespaceSpecifier(parser, context, specifiers);
break;
// import a, {bar}
case 41943052 /* LeftBrace */:
parseNamedImports(parser, context, specifiers);
break;
default:
tolerant(parser, context, 1 /* UnexpectedToken */, tokenDesc(parser.token));
}
}
break;
}
// import {bar}
case 41943052 /* LeftBrace */:
parseNamedImports(parser, context, specifiers);
break;
// import * as foo
case 167774771 /* Multiply */:
parseImportNamespaceSpecifier(parser, context, specifiers);
break;
default:
report(parser, 1 /* UnexpectedToken */, tokenDesc(parser.token));
}
return specifiers;
}
/**
* Parse named imports
*
* @see [Link](https://tc39.github.io/ecma262/#prod-NamedImports)
*
* @param parser Parser object
* @param context Context masks
*/
function parseNamedImports(parser, context, specifiers) {
expect(parser, context, 41943052 /* LeftBrace */);
while (parser.token !== 17301519 /* RightBrace */) {
specifiers.push(parseImportSpecifier(parser, context));
if (parser.token !== 17301519 /* RightBrace */) {
expect(parser, context, 16777234 /* Comma */);
}
}
expect(parser, context, 17301519 /* RightBrace */);
}
/**
* Parse import specifier
*
* @see [Link](https://tc39.github.io/ecma262/#prod-ImportSpecifier)
*
* @param parser Parser object
* @param context Context masks
*/
function parseImportSpecifier(parser, context) {
const pos = getLocation(parser);
const { token } = parser;
const imported = parseIdentifierName(parser, context | 536870912 /* DisallowEscapedKeyword */, token);
let local;
if (parser.token === 36971 /* AsKeyword */) {
expect(parser, context, 36971 /* AsKeyword */);
local = parseBindingIdentifier(parser, context);
}
else {
// An import name that is a keyword is a syntax error if it is not followed
// by the keyword 'as'.
if (hasBit(token, 12288 /* Reserved */))
tolerant(parser, context, 44 /* UnexpectedReserved */);
if (hasBit(token, 4194304 /* IsEvalOrArguments */))
tolerant(parser, context, 45 /* StrictEvalArguments */);
local = imported;
}
return finishNode(context, parser, pos, {
type: 'ImportSpecifier',
local,
imported,
});
}
/**
* Parse binding identifier
*
* @see [Link](https://tc39.github.io/ecma262/#prod-NameSpaceImport)
*
* @param parser Parser object
* @param context Context masks
*/
function parseImportNamespaceSpecifier(parser, context, specifiers) {
const pos = getLocation(parser);
expect(parser, context, 167774771 /* Multiply */);
expect(parser, context, 36971 /* AsKeyword */, 80 /* AsAfterImportStart */);
const local = parseBindingIdentifier(parser, context);
specifiers.push(finishNode(context, parser, pos, {
type: 'ImportNamespaceSpecifier',
local,
}));
}
/**
* Parse binding identifier
*
* @see [Link](https://tc39.github.io/ecma262/#prod-BindingIdentifier)
*
* @param parser Parser object
* @param context Context masks
*/
function parseModuleSpecifier(parser, context) {
// ModuleSpecifier :
// StringLiteral
expect(parser, context, 36977 /* FromKeyword */);
if (parser.token !== 33554435 /* StringLiteral */)
report(parser, 1 /* UnexpectedToken */, tokenDesc(parser.token));
return parseLiteral(parser, context);
}
/**
* Parse import default specifier
*
* @see [Link](https://tc39.github.io/ecma262/#prod-BindingIdentifier)
*
* @param parser Parser object
* @param context Context masks
*/
function parseImportDefaultSpecifier(parser, context) {
return finishNode(context, parser, getLocation(parser), {
type: 'ImportDefaultSpecifier',
local: parseIdentifier(parser, context),
});
}
/**
* Parses either async function or assignment expression
*
* @see [Link](https://tc39.github.io/ecma262/#prod-AssignmentExpression)
* @see [Link](https://tc39.github.io/ecma262/#prod-AsyncFunctionDeclaration)
* @see [Link](https://tc39.github.io/ecma262/#prod-AsyncGeneratorDeclaration)
*
* @param parser Parser object
* @param context Context masks
*/
function parseAsyncFunctionOrAssignmentExpression(parser, context) {
return lookahead(parser, context, nextTokenIsFuncKeywordOnSameLine) ?
parseAsyncFunctionOrAsyncGeneratorDeclaration(parser, context | 16777216 /* RequireIdentifier */) :
parseAssignmentExpression(parser, context | 65536 /* AllowIn */);
}
/**
* Creates the parser object
*
* @param source The source coode to parser
* @param sourceFile Optional source file info to be attached in every node
*/
function createParser(source, sourceFile) {
return {
// The source code to parse
source,
// Source length
length: source.length,
// Current position
index: 0,
// Current line
line: 1,
// Current column
column: 0,
// Start position before current token
startIndex: 0,
// Start position column before current token
startColumn: 0,
// Start position line before current token
startLine: 1,
// End position after parsing after current token
lastIndex: 0,
// End column position after current token
lastColumn: 0,
// End line position after current token
lastLine: 0,
// Pending cover grammar errors
pendingExpressionError: undefined,
// Mutable parser flags. Allows destructuring by default.
flags: 4 /* AllowDestructuring */,
// The tokens
token: 524288 /* EndOfSource */,
// Misc
tokenRaw: '',
lastValue: 0,
comments: [],
sourceFile,
tokenRegExp: undefined,
tokenValue: undefined,
labelSet: undefined,
errorLocation: undefined,
errors: [],
};
}
/**
* Parse either script code or module code
*
* @param source source code to parse
* @param options parser options
*/
function parse(source, options) {
return options && options.module
? parseSource(source, options, 4096 /* Strict */ | 8192 /* Module */)
: parseSource(source, options, 0 /* Empty */);
}
/**
* Creating the parser
*
* @param source The source coode to parser
* @param options The parser options
* @param context Context masks
*/
function parseSource(source, options, /*@internal*/ context) {
let sourceFile = '';
if (!!options) {
// The flag to enable module syntax support
if (options.module)
context |= 8192 /* Module */;
// The flag to enable stage 3 support (ESNext)
if (options.next)
context |= 1 /* OptionsNext */;
// The flag to enable React JSX parsing
if (options.jsx)
context |= 4 /* OptionsJSX */;
// The flag to enable start and end offsets to each node
if (options.ranges)
context |= 2 /* OptionsRanges */;
// The flag to enable line/column location information to each node
if (options.loc)
context |= 16 /* OptionsLoc */;
// The flag to attach raw property to each literal node
if (options.raw)
context |= 8 /* OptionsRaw */;
// Attach raw property to each identifier node
if (options.rawIdentifier)
context |= 256 /* OptionsRawidentifiers */;
// The flag to allow return in the global scope
if (options.globalReturn)
context |= 32 /* OptionsGlobalReturn */;
// The flag to allow to skip shebang - '#'
if (options.skipShebang)
context |= 128 /* OptionsShebang */;
// Enable tolerant mode
if (options.tolerant)
context |= 512 /* OptionsTolerant */;
// Set to true to record the source file in every node's loc object when the loc option is set.
if (!!options.source)
sourceFile = options.source;
// Create a top-level comments array containing all comments
if (!!options.comments)
context |= 64 /* OptionsComments */;
// The flag to enable implied strict mode
if (options.impliedStrict)
context |= 4096 /* Strict */;
// The flag to enable experimental features
if (options.experimental)
context |= 2048 /* OptionsExperimental */;
// The flag to set to bypass methods in Node
if (options.node)
context |= 1024 /* OptionsNode */;
// Accepts a callback function to be invoked for each syntax node (as the node is constructed)
}
const parser = createParser(source, sourceFile);
const body = context & 8192 /* Module */
? parseModuleItemList(parser, context)
: parseStatementList(parser, context);
const node = {
type: 'Program',
sourceType: context & 8192 /* Module */ ? 'module' : 'script',
body: body,
};
if (context & 2 /* OptionsRanges */) {
node.start = 0;
node.end = source.length;
}
if (context & 16 /* OptionsLoc */) {
node.loc = {
start: {
line: 1,
column: 0,
},
end: {
line: parser.line,
column: parser.column,
},
};
if (sourceFile)
node.loc.source = sourceFile;
}
if (context & 64 /* OptionsComments */)
node.comments = parser.comments;
if (context & 512 /* OptionsTolerant */)
node.errors = parser.errors;
return node;
}
/**
* Parse statement list
*
* @see [Link](https://tc39.github.io/ecma262/#prod-StatementList)
*
* @param Parser instance
* @param Context masks
*/
function parseStatementList(parser, context) {
const statements = [];
nextToken(parser, context | 536870912 /* DisallowEscapedKeyword */);
while (parser.token === 33554435 /* StringLiteral */) {
// We do a strict check here too speed up things in case someone is crazy eenough to
// write "use strict"; "use strict"; at Top-level. // J.K
if (!(context & 4096 /* Strict */) && parser.tokenRaw.length === /* length of prologue*/ 12 && parser.tokenValue === 'use strict') {
context |= 4096 /* Strict */;
}
statements.push(parseDirective(parser, context));
}
while (parser.token !== 524288 /* EndOfSource */) {
statements.push(parseStatementListItem(parser, context));
}
return statements;
}
/**
* Parse script code
*
* @see [Link](https://tc39.github.io/ecma262/#sec-scripts)
*
* @param source source code to parse
* @param options parser options
*/
function parseScript(source, options) {
return parseSource(source, options, 0 /* Empty */);
}
/**
* Parse module code
*
* @see [Link](https://tc39.github.io/ecma262/#sec-modules)
*
* @param source source code to parse
* @param options parser options
*/
function parseModule(source, options) {
return parseSource(source, options, 4096 /* Strict */ | 8192 /* Module */);
}
var estree = /*#__PURE__*/Object.freeze({
});
var index = /*#__PURE__*/Object.freeze({
scanIdentifier: scanIdentifier,
scanMaybeIdentifier: scanMaybeIdentifier,
scanHexIntegerLiteral: scanHexIntegerLiteral,
scanOctalOrBinary: scanOctalOrBinary,
scanImplicitOctalDigits: scanImplicitOctalDigits,
scanSignedInteger: scanSignedInteger,
scanNumericLiteral: scanNumericLiteral,
scanNumericSeparator: scanNumericSeparator,
scanDecimalDigitsOrSeparator: scanDecimalDigitsOrSeparator,
scanDecimalAsSmi: scanDecimalAsSmi,
scanRegularExpression: scanRegularExpression,
scan: scan,
scanEscapeSequence: scanEscapeSequence,
throwStringError: throwStringError,
scanString: scanString,
consumeTemplateBrace: consumeTemplateBrace,
scanTemplate: scanTemplate,
skipSingleHTMLComment: skipSingleHTMLComment,
skipSingleLineComment: skipSingleLineComment,
skipMultiLineComment: skipMultiLineComment,
addComment: addComment,
nextUnicodeChar: nextUnicodeChar,
isIdentifierPart: isIdentifierPart,
escapeForPrinting: escapeForPrinting,
consumeOpt: consumeOpt,
consumeLineFeed: consumeLineFeed,
scanPrivateName: scanPrivateName,
advanceNewline: advanceNewline,
fromCodePoint: fromCodePoint,
readNext: readNext,
toHex: toHex,
advanceOnMaybeAstral: advanceOnMaybeAstral
});
var parser = /*#__PURE__*/Object.freeze({
parseClassDeclaration: parseClassDeclaration,
parseFunctionDeclaration: parseFunctionDeclaration,
parseAsyncFunctionOrAsyncGeneratorDeclaration: parseAsyncFunctionOrAsyncGeneratorDeclaration,
parseVariableDeclarationList: parseVariableDeclarationList,
parseExpression: parseExpression,
parseSequenceExpression: parseSequenceExpression,
parseAssignmentExpression: parseAssignmentExpression,
parseRestElement: parseRestElement,
parseLeftHandSideExpression: parseLeftHandSideExpression,
parsePrimaryExpression: parsePrimaryExpression,
parseIdentifier: parseIdentifier,
parseLiteral: parseLiteral,
parseBigIntLiteral: parseBigIntLiteral,
parseIdentifierName: parseIdentifierName,
parseFunctionExpression: parseFunctionExpression,
parseAsyncFunctionOrAsyncGeneratorExpression: parseAsyncFunctionOrAsyncGeneratorExpression,
parsePropertyName: parsePropertyName,
parseObjectLiteral: parseObjectLiteral,
parseFormalListAndBody: parseFormalListAndBody,
parseFunctionBody: parseFunctionBody,
parseFormalParameters: parseFormalParameters,
parseFormalParameterList: parseFormalParameterList,
parseClassBodyAndElementList: parseClassBodyAndElementList,
parseClassElement: parseClassElement,
parseDecorators: parseDecorators,
parseModuleItemList: parseModuleItemList,
parseModuleItem: parseModuleItem,
parseExportDeclaration: parseExportDeclaration,
parseImportDeclaration: parseImportDeclaration,
createParser: createParser,
parse: parse,
parseSource: parseSource,
parseStatementList: parseStatementList,
parseScript: parseScript,
parseModule: parseModule,
parseBindingIdentifierOrPattern: parseBindingIdentifierOrPattern,
parseBindingIdentifier: parseBindingIdentifier,
parseAssignmentRestElement: parseAssignmentRestElement,
parseAssignmentPattern: parseAssignmentPattern,
parseBindingInitializer: parseBindingInitializer,
parseStatementListItem: parseStatementListItem,
parseStatement: parseStatement,
parseEmptyStatement: parseEmptyStatement,
parseContinueStatement: parseContinueStatement,
parseBreakStatement: parseBreakStatement,
parseIfStatement: parseIfStatement,
parseDebuggerStatement: parseDebuggerStatement,
parseTryStatement: parseTryStatement,
parseCatchBlock: parseCatchBlock,
parseThrowStatement: parseThrowStatement,
parseExpressionStatement: parseExpressionStatement,
parseDirective: parseDirective,
parseExpressionOrLabelledStatement: parseExpressionOrLabelledStatement,
parseDoWhileStatement: parseDoWhileStatement,
parseWhileStatement: parseWhileStatement,
parseBlockStatement: parseBlockStatement,
parseReturnStatement: parseReturnStatement,
parseIterationStatement: parseIterationStatement,
parseWithStatement: parseWithStatement,
parseSwitchStatement: parseSwitchStatement,
parseCaseOrDefaultClauses: parseCaseOrDefaultClauses,
parseVariableStatement: parseVariableStatement,
parseJSXRootElement: parseJSXRootElement,
parseJSXOpeningElement: parseJSXOpeningElement,
nextJSXToken: nextJSXToken,
scanJSXToken: scanJSXToken,
parseJSXText: parseJSXText,
parseJSXAttributes: parseJSXAttributes,
parseJSXSpreadAttribute: parseJSXSpreadAttribute,
parseJSXNamespacedName: parseJSXNamespacedName,
parseJSXAttributeName: parseJSXAttributeName,
parseJSXAttribute: parseJSXAttribute,
parseJSXEmptyExpression: parseJSXEmptyExpression,
parseJSXSpreadChild: parseJSXSpreadChild,
parseJSXExpressionContainer: parseJSXExpressionContainer,
parseJSXExpression: parseJSXExpression,
parseJSXClosingFragment: parseJSXClosingFragment,
parseJSXClosingElement: parseJSXClosingElement,
parseJSXIdentifier: parseJSXIdentifier,
parseJSXMemberExpression: parseJSXMemberExpression,
parseJSXElementName: parseJSXElementName,
scanJSXIdentifier: scanJSXIdentifier
});
// tslint:disable:max-classes-per-file
/**
* Class that creates RouteConfigs for the @routeConfig() decorator
*/
class RouteConfigFactory {
}
/**
* The default RouteConfig factory
*/
class DefaultRouteConfigFactory extends RouteConfigFactory {
/**
* Creates `RouteConfig` objects based an instruction for a class that can be navigated to
*
* @param instruction Instruction containing all information based on which the `RouteConfig` objects
* will be created
*/
createRouteConfigs(instruction) {
return __awaiter(this, void 0, void 0, function* () {
const resource = routerMetadata.getOrCreateOwn(instruction.target);
yield resource.load();
return buildRouteConfigCollection(instruction);
});
}
/**
* Creates `RouteConfig` objects based an instruction for a class that can navigate to others
*
* @param instruction Instruction containing all information based on which the `RouteConfig` objects
* will be created
*/
createChildRouteConfigs(instruction) {
return __awaiter(this, void 0, void 0, function* () {
const resource = routerMetadata.getOrCreateOwn(instruction.target);
yield resource.load();
return buildCompleteChildRouteConfigCollection(instruction);
});
}
}
const buildRouteConfigCollection = (instruction) => {
const result = [];
const defaults = getRouteConfigDefaults(instruction);
const overrides = buildRouteConfigOverrides(instruction);
const configs = ensureArray(instruction.routes).concat(ensureArray(instruction.target.routes));
// if there are no configs on any static properties, use the convention-based defaults for the target
if (configs.length === 0) {
configs.push(defaults);
}
let i = configs.length;
while (i--) {
const config = {};
mergeRouteConfig(config, defaults);
mergeRouteConfig(config, configs[i]);
if (Array.isArray(config.route)) {
let j = config.route.length;
while (j--) {
const multiConfig = {};
mergeRouteConfig(multiConfig, config);
multiConfig.route = config.route[j];
mergeRouteConfig(multiConfig, overrides);
result.push(multiConfig);
}
}
else {
mergeRouteConfig(config, overrides);
result.push(config);
}
}
const settings = getSettings(instruction);
return settings.transformRouteConfigs(result, instruction);
};
const getRouteConfigDefaults = (instruction) => {
const result = {};
const settings = getSettings(instruction);
mergeRouteConfig(result, settings.routeConfigDefaults);
const hyphenatedName = hyphenate(instruction.target.name);
result.route = hyphenatedName;
result.name = hyphenatedName;
result.title = toTitle(instruction.target.name);
mergeRouteConfig(result, instruction.target);
mergeRouteConfig(result, instruction.target.baseRoute);
return result;
};
const getContainer = (x) => {
if (x === aureliaDependencyInjection.Container) {
return aureliaDependencyInjection.Container.instance;
}
const routerResource = routerMetadata.getOrCreateOwn(x);
return (routerResource && routerResource.container) || aureliaDependencyInjection.Container.instance;
};
const getSettings = (x) => {
return x.settings ? x.settings : getContainer(x.target).get(RouterMetadataSettings);
};
const mergeRouteConfig = (target, source) => {
if (!source) {
return;
}
const keys = Object.keys(source);
let i = keys.length;
while (i--) {
const key = keys[i];
switch (key) {
case "route":
case "moduleId":
case "redirect":
case "navigationStrategy":
case "viewPorts":
case "nav":
case "href":
case "generationUsesHref":
case "title":
case "navModel":
case "caseSensitive":
case "activationStrategy":
case "layoutView":
case "layoutViewModel":
case "layoutModel":
case "name":
target[key] = source[key];
break;
case "routeName":
target.name = source.routeName;
break;
case "settings":
if (!target.settings) {
target.settings = {};
}
Object.assign(target.settings, source.settings);
break;
default: // no default
}
}
};
const buildRouteConfigOverrides = (instruction) => {
const result = {};
const settings = getSettings(instruction);
mergeRouteConfig(result, settings.routeConfigOverrides);
result.moduleId = instruction.moduleId;
if (!result.settings) {
result.settings = {};
}
return result;
};
function hyphenate(value) {
return (value.charAt(0).toLowerCase() + value.slice(1)).replace(/([A-Z])/g, (char) => `-${char.toLowerCase()}`);
}
function toTitle(value) {
return value.replace(/([A-Z])/g, (char) => ` ${char}`).trimLeft();
}
const buildCompleteChildRouteConfigCollection = (instruction, $module) => {
let $constructor = $module && $module.$defaultExport && $module.$defaultExport.$constructor;
if (!$constructor) {
$constructor = getRegisteredConstructor(instruction.target);
}
const collection = buildChildRouteConfigCollection($constructor);
return splitRouteConfig(collection);
};
const buildChildRouteConfigCollection = ($constructor) => {
const results = [];
const functionDeclaration = getConfigureRouterFunctionDeclaration($constructor);
if (functionDeclaration) {
let i = functionDeclaration.body.body.length;
while (i--) {
const statement = functionDeclaration.body.body[i];
if (statement.type === "ExpressionStatement" &&
statement.expression.type === "CallExpression" &&
statement.expression.callee.type === "MemberExpression" &&
statement.expression.callee.property.type === "Identifier" &&
statement.expression.callee.property.name === "map") {
const configCollection = getRouteConfigsFromMapCallExpression(statement.expression);
let j = configCollection.length;
while (j--) {
const config = configCollection[j];
if (Array.isArray(config.route)) {
let k = config.route.length;
while (k--) {
const multiConfig = {};
mergeRouteConfig(multiConfig, config);
multiConfig.route = config.route[k];
results.push(multiConfig);
}
}
else {
results.push(config);
}
}
}
}
}
return results;
};
const getRegisteredConstructor = (target) => {
const resource = routerMetadata.getOrCreateOwn(target);
if (!resource) {
throw new Error();
}
if (resource.$module && resource.$module.$defaultExport) {
return resource.$module.$defaultExport.$constructor;
}
else if (resource.moduleId) {
const registry = getContainer(target).get(Registry);
const $module = registry.getModule(resource.moduleId);
if ($module && $module.$defaultExport) {
return $module.$defaultExport.$constructor;
}
}
throw new Error();
};
const getRouteConfigsFromMapCallExpression = (callExpression) => {
const results = [];
let i = callExpression.arguments.length;
while (i--) {
const arg = callExpression.arguments[i];
switch (arg.type) {
case "ArrayExpression": {
for (const el of arg.elements) {
if (el && el.type === "ObjectExpression") {
results.push(analyzeObjectExpression(el));
}
}
break;
}
case "ObjectExpression": {
results.push(analyzeObjectExpression(arg));
break;
}
default:
}
}
return results;
};
const analyzeObjectExpression = (expression) => {
const objectResult = {};
let i = expression.properties.length;
while (i--) {
const prop = expression.properties[i];
if (prop.type === "Property" && prop.key.type === "Identifier" && prop.value !== null) {
switch (prop.value.type) {
case "Literal":
objectResult[prop.key.name] = prop.value.value;
break;
case "ArrayExpression":
objectResult[prop.key.name] = [];
let j = prop.value.elements.length;
while (j--) {
const el = prop.value.elements[j];
if (el && el.type === "Literal") {
objectResult[prop.key.name].push(el.value);
}
}
break;
case "ObjectExpression": {
objectResult[prop.key.name] = analyzeObjectExpression(prop.value);
}
default:
}
}
}
return objectResult;
};
const getConfigureRouterFunctionDeclaration = ($constructor) => {
let configureRouterMethod = $constructor.$export.$prototype.$properties.find(p => p.key === RouterResource.originalConfigureRouterSymbol);
if (!configureRouterMethod) {
configureRouterMethod = $constructor.$export.$prototype.$properties.find(p => p.key === "configureRouter");
}
if (configureRouterMethod) {
let body = configureRouterMethod.descriptor.value.toString();
// ensure we have a pattern "function functionName()" for the parser
if (/^function *\(/.test(body)) {
// regular named functions become "function()" when calling .toString() on the value
body = body.replace(/^function/, `function ${typeof configureRouterMethod.key !== "symbol" ? configureRouterMethod.key : "configureRouter"}`);
}
else if (!/^function/.test(body)) {
// symbol named functions become "functionName()" when calling .toString() on the value
body = `function ${body}`;
}
const program = parseScript(body);
let i = program.body.length;
while (i--) {
const statement = program.body[i];
if (statement.type === "FunctionDeclaration") {
return statement;
}
}
}
return null;
};
const noTransform = (configs) => configs;
const noFilter = () => true;
// tslint:disable-next-line:no-empty
const noAction = (..._) => { };
const defaults = {
nav: true
};
const overrides = {};
/**
* All available aurelia-router-metadata settings
*/
class RouterMetadataSettings {
constructor() {
this.routeConfigDefaults = defaults;
this.routeConfigOverrides = overrides;
this.transformRouteConfigs = noTransform;
this.filterChildRoutes = noFilter;
this.enableEagerLoading = true;
this.enableStaticAnalysis = true;
this.routerConfiguration = new aureliaRouter.RouterConfiguration();
this.onBeforeLoadChildRoutes = noAction;
this.onBeforeConfigMap = noAction;
this.assignRouterToViewModel = false;
this.onAfterMergeRouterConfiguration = noAction;
}
}
/**
* Class used to configure behavior of [[RouterResource]]
*/
class RouterMetadataConfiguration {
/**
* Gets the global configuration instance. This will be automatically resolved from
* [[Container.instance]] and assigned when first accessed.
*/
static get INSTANCE() {
if (this.instance === undefined) {
this.instance = aureliaDependencyInjection.Container.instance.get(RouterMetadataConfiguration);
}
return this.instance;
}
/**
* Sets the global configuration instance. Should be configured before setRoot()
* for changes to propagate.
*/
static set INSTANCE(instance) {
this.instance = instance;
}
/**
* @param container Optionally pass in a container to use for resolving the dependencies
* that this class resolves. Will default to Container.instance if null.
*/
constructor(container) {
this.container = container || aureliaDependencyInjection.Container.instance;
}
/**
* Makes this configuration instance globally reachable through RouterMetadataConfiguration.INSTANCE
*/
makeGlobal() {
RouterMetadataConfiguration.INSTANCE = this;
return this;
}
/**
* Gets the RouteConfigFactory that is registered with DI, or defaults to
* [[DefaultRouteConfigFactory]] if its not registered.
* @param container Optionally pass in a container to use for resolving this dependency.
* Can be a ChildContainer to scope certain overrides for certain viewModels.
*/
getConfigFactory(container) {
const c = container || this.container;
if (!c.hasResolver(RouteConfigFactory)) {
c.registerSingleton(RouteConfigFactory, DefaultRouteConfigFactory);
}
return c.get(RouteConfigFactory);
}
/**
* Gets the RouterMetadataSettings that is registered with DI, or creates
* a default one with noop functions if its not registered.
* @param container Optionally pass in a container to use for resolving this dependency.
* Can be a ChildContainer to scope certain overrides for certain viewModels.
*/
getSettings(container) {
const c = container || this.container;
return c.get(RouterMetadataSettings);
}
/**
* Gets the ResourceLoader that is registered with DI
* @param container Optionally pass in a container to use for resolving this dependency.
* Can be a ChildContainer to scope certain overrides for certain viewModels.
*/
getResourceLoader(container) {
const c = container || this.container;
return c.get(ResourceLoader);
}
getRegistry(container) {
const c = container || this.container;
return c.get(Registry);
}
}
const logger = aureliaLogging.getLogger("router-metadata");
/**
* Identifies a class as a resource that can be navigated to (has routes) and/or
* configures a router to navigate to other routes (maps routes)
*/
class RouterResource {
constructor(target, moduleId) {
this.$module = null;
this.target = target;
this.moduleId = moduleId;
this.isRouteConfig = false;
this.isConfigureRouter = false;
this.routeConfigModuleIds = [];
this.enableEagerLoading = false;
this.enableStaticAnalysis = false;
this.createRouteConfigInstruction = null;
this.ownRoutes = [];
this.childRoutes = [];
this.filterChildRoutes = null;
this.areChildRoutesLoaded = false;
this.areOwnRoutesLoaded = false;
this.isConfiguringRouter = false;
this.isRouterConfigured = false;
this.parents = new Set();
this.router = null;
}
/**
* The first (primary) parent of this route
*/
get parent() {
return this.parents.keys().next().value || null;
}
/**
* Only applicable when `isConfigureRouter`
*
* A convenience property which returns `router.container`, or `null` if the router is not set
*/
get container() {
return this.router ? this.router.container : null;
}
/**
* Only applicable when `isConfigureRouter`
*
* A convenience property which returns `router.container.viewModel`, or `null` if the router is not set
* This is an instance of the target class
*/
get instance() {
return this.container ? this.container.viewModel : null;
}
/**
* Creates a `@routeConfig` based on the provided instruction.
*
* This method is called by the `@routeConfig()` decorator, and can be used instead of the @routeConfig() decorator
* to achieve the same effect.
* @param instruction Instruction containing the parameters passed to the `@routeConfig` decorator
*/
static ROUTE_CONFIG(instruction) {
const resource = routerMetadata.getOrCreateOwn(instruction.target);
resource.initialize(instruction);
return resource;
}
/**
* Creates a `@configureRouter` based on the provided instruction.
*
* This method is called by the `@configureRouter()` decorator, and can be used instead of the @configureRouter() decorator
* to achieve the same effect.
* @param instruction Instruction containing the parameters passed to the `@configureRouter` decorator
*/
static CONFIGURE_ROUTER(instruction) {
const resource = routerMetadata.getOrCreateOwn(instruction.target);
resource.initialize(instruction);
return resource;
}
/**
* Initializes this resource based on the provided instruction.
*
* If there is a `routeConfigModuleIds` property present on the instruction,
* or the target has a `configureRouter()` method, it will be initialized as `configureRouter`, otherwise as `routeConfig`
* @param instruction Instruction containing the parameters passed to the `@configureRouter` decorator
*/
initialize(instruction) {
if (!instruction) {
if (this.isRouteConfig && this.isConfigureRouter) {
return; // already configured
}
// We're not being called from a decorator, so just apply defaults as if we're a @routeConfig
// tslint:disable-next-line:no-parameter-reassignment
instruction = this.ensureCreateRouteConfigInstruction();
}
const settings = this.getSettings(instruction);
const target = instruction.target;
if (isConfigureRouterInstruction(instruction)) {
if (this.isConfigureRouter) {
const moduleIds = instruction.routeConfigModuleIds;
if (moduleIds && moduleIds.length) {
for (const moduleId of moduleIds) {
if (this.routeConfigModuleIds.indexOf(moduleId) === -1) {
this.routeConfigModuleIds.push(moduleId);
}
}
}
return; // already configured
}
logger.debug(`initializing @configureRouter for ${target.name}`);
this.isConfigureRouter = true;
const configureInstruction = instruction;
this.routeConfigModuleIds = ensureArray$1(configureInstruction.routeConfigModuleIds);
this.filterChildRoutes = settings.filterChildRoutes;
this.enableEagerLoading = settings.enableEagerLoading;
this.enableStaticAnalysis = settings.enableStaticAnalysis;
assignOrProxyPrototypeProperty(target.prototype, "configureRouter", RouterResource.originalConfigureRouterSymbol, configureRouter);
}
else {
if (this.isRouteConfig) {
return; // already configured
}
logger.debug(`initializing @routeConfig for ${target.name}`);
this.isRouteConfig = true;
const configInstruction = instruction;
this.createRouteConfigInstruction = Object.assign({}, configInstruction, { settings });
}
}
/**
* Ensures that the module for this resources is loaded and registered so that its routing information can be queried.
*/
load() {
return __awaiter(this, void 0, void 0, function* () {
const registry = this.getRegistry();
const loader = this.getResourceLoader();
if (!this.moduleId) {
this.moduleId = registry.registerModuleViaConstructor(this.target).moduleId;
}
yield loader.loadRouterResource(this.moduleId);
});
}
loadOwnRoutes() {
return __awaiter(this, void 0, void 0, function* () {
if (this.areOwnRoutesLoaded) {
return this.ownRoutes;
}
// If we're in this method then it can never be the root, so it's always safe to apply @routeConfig initialization
if (!this.isRouteConfig) {
this.isRouteConfig = true;
this.initialize();
}
const instruction = this.ensureCreateRouteConfigInstruction();
const configs = yield this.getConfigFactory().createRouteConfigs(instruction);
for (const config of configs) {
config.settings.routerResource = this;
this.ownRoutes.push(config);
}
this.areOwnRoutesLoaded = true;
return this.ownRoutes;
});
}
/**
* Retrieves the `RouteConfig` objects which were generated by all referenced moduleIds
* and assigns them to `childRoutes`
*
* Will also call this method on child resources if `enableEagerLoading` is set to true.
*
* Will simply return the previously fetched `childRoutes` on subsequent calls.
*
* This method is called by `configureRouter()`.
*
* @param router (Optional) The router that was passed to the target instance's `configureRouter()`
*/
loadChildRoutes(router) {
return __awaiter(this, void 0, void 0, function* () {
this.router = router !== undefined ? router : null;
if (this.areChildRoutesLoaded) {
return this.childRoutes;
}
logger.debug(`loading childRoutes for ${this.target.name}`);
const loader = this.getResourceLoader();
let extractedChildRoutes;
if (this.enableStaticAnalysis) {
extractedChildRoutes = yield this.getConfigFactory().createChildRouteConfigs({ target: this.target });
for (const extracted of extractedChildRoutes) {
if (extracted.moduleId) {
if (this.routeConfigModuleIds.indexOf(extracted.moduleId) === -1) {
this.routeConfigModuleIds.push(extracted.moduleId);
}
yield loader.loadRouterResource(extracted.moduleId);
}
}
}
for (const moduleId of this.routeConfigModuleIds) {
const resource = yield loader.loadRouterResource(moduleId);
const childRoutes = yield resource.loadOwnRoutes();
resource.parents.add(this);
if (resource.isConfigureRouter && this.enableEagerLoading) {
yield resource.loadChildRoutes();
}
const childRoutesToProcess = [];
if (this.enableStaticAnalysis) {
const couples = alignRouteConfigs(childRoutes, extractedChildRoutes);
for (const couple of couples) {
if (couple.left) {
const childRoute = couple.left;
if (couple.right) {
Object.assign(childRoute, Object.assign({}, couple.right, { settings: Object.assign({}, childRoute.settings, couple.right.settings) }));
}
childRoutesToProcess.push(childRoute);
}
}
}
else {
childRoutesToProcess.push(...childRoutes);
}
for (const childRoute of childRoutesToProcess) {
if (!this.filterChildRoutes || (yield this.filterChildRoutes(childRoute, childRoutes, this))) {
if (this.ownRoutes.length > 0) {
childRoute.settings.parentRoute = this.ownRoutes[0];
}
this.childRoutes.push(childRoute);
}
}
}
if (this.isRouteConfig) {
const ownRoutes = yield this.loadOwnRoutes();
for (const ownRoute of ownRoutes) {
ownRoute.settings.childRoutes = this.childRoutes;
}
}
this.areChildRoutesLoaded = true;
return this.childRoutes;
});
}
/**
* Calls `loadChildRoutes()` to fetch the referenced modulesIds' `RouteConfig` objects, and maps them to the router.
*
* This method will be assigned to `target.prototype.configureRouter`, such that the routes will be configured
* even if there is no `configureRouter()` method present.
*
* If `target.prototype.configureRouter` already exists, a reference to that original method will be kept
* and called at the end of this `configureRouter()` method.
*/
configureRouter(config, router, ...args) {
return __awaiter(this, void 0, void 0, function* () {
yield this.load();
const viewModel = router.container.viewModel;
const settings = this.getSettings();
if (typeof settings.onBeforeLoadChildRoutes === "function") {
yield settings.onBeforeLoadChildRoutes(viewModel, config, router, this, ...args);
}
this.isConfiguringRouter = true;
const routes = yield this.loadChildRoutes();
assignPaths(routes);
if (typeof settings.onBeforeConfigMap === "function") {
yield settings.onBeforeConfigMap(viewModel, config, router, this, routes, ...args);
}
config.map(routes);
this.router = router;
if (router instanceof aureliaRouter.AppRouter || router.isRoot) {
const assign = settings.assignRouterToViewModel;
if (assign === true) {
viewModel.router = router;
}
else if (Object.prototype.toString.call(assign) === "[object String]") {
viewModel[assign] = router;
}
else if (typeof assign === "function") {
yield assign(viewModel, config, router, this, routes, ...args);
}
const settingsConfig = this.getSettings().routerConfiguration || {};
mergeRouterConfiguration(config, settingsConfig);
if (typeof settings.onAfterMergeRouterConfiguration === "function") {
yield settings.onAfterMergeRouterConfiguration(viewModel, config, router, this, routes, ...args);
}
}
this.isRouterConfigured = true;
this.isConfiguringRouter = false;
const originalConfigureRouter = this.target.prototype[RouterResource.originalConfigureRouterSymbol];
if (originalConfigureRouter !== undefined) {
if (this.enableStaticAnalysis) {
Object.defineProperty(config, RouterResource.routerResourceSymbol, {
enumerable: false,
configurable: true,
writable: true,
value: this
});
Object.defineProperty(config, RouterResource.originalMapSymbol, {
enumerable: false,
configurable: true,
writable: true,
value: config.map
});
Object.defineProperty(config, "map", {
enumerable: true,
configurable: true,
writable: true,
value: map.bind(config)
});
}
return originalConfigureRouter.call(viewModel, config, router);
}
});
}
ensureCreateRouteConfigInstruction() {
const instruction = this.createRouteConfigInstruction || (this.createRouteConfigInstruction = {});
instruction.target = instruction.target || this.target;
instruction.moduleId = instruction.moduleId || this.moduleId;
instruction.settings = instruction.settings || this.getSettings(instruction);
return instruction;
}
getSettings(instruction) {
const settings = RouterMetadataConfiguration.INSTANCE.getSettings(this.container);
if (instruction) {
Object.assign(settings, instruction.settings || {});
}
return settings;
}
getConfigFactory() {
return RouterMetadataConfiguration.INSTANCE.getConfigFactory(this.container);
}
getResourceLoader() {
return RouterMetadataConfiguration.INSTANCE.getResourceLoader(this.container);
}
getRegistry() {
return RouterMetadataConfiguration.INSTANCE.getRegistry(this.container);
}
}
RouterResource.originalConfigureRouterSymbol = Symbol("configureRouter");
RouterResource.originalMapSymbol = Symbol("map");
RouterResource.viewModelSymbol = Symbol("viewModel");
RouterResource.routerResourceSymbol = Symbol("routerResource");
function isConfigureRouterInstruction(instruction) {
return (!!instruction.routeConfigModuleIds ||
Object.prototype.hasOwnProperty.call(instruction.target.prototype, "configureRouter"));
}
function ensureArray$1(value) {
if (value === undefined) {
return [];
}
return Array.isArray(value) ? value : [value];
}
function assignPaths(routes) {
for (const route of routes.filter((r) => !r.settings.path)) {
const parentPath = route.settings.parentRoute ? route.settings.parentRoute.settings.path : "";
const pathProperty = route.settings.pathProperty || "route";
const path = route[pathProperty];
route.settings.path = `${parentPath}/${path}`.replace(/\/\//g, "/").replace(/^\//, "");
assignPaths(route.settings.childRoutes || []);
}
}
function assignOrProxyPrototypeProperty(proto, name, refSymbol, value) {
if (name in proto) {
let protoOrBase = proto;
while (!protoOrBase.hasOwnProperty(name)) {
protoOrBase = Object.getPrototypeOf(protoOrBase);
}
const original = protoOrBase[name];
Object.defineProperty(proto, refSymbol, { enumerable: false, configurable: true, writable: true, value: original });
}
proto[name] = value;
}
// tslint:disable:no-invalid-this
function configureRouter(config, router, ...args) {
return __awaiter(this, void 0, void 0, function* () {
const target = Object.getPrototypeOf(this).constructor;
const resource = routerMetadata.getOwn(target);
yield resource.configureRouter(config, router, ...args);
});
}
// tslint:enable:no-invalid-this
function map(originalConfigs) {
Object.defineProperty(this, "map", {
enumerable: false,
configurable: true,
writable: true,
value: this[RouterResource.originalMapSymbol].bind(this)
});
delete this[RouterResource.originalMapSymbol];
const resource = this[RouterResource.routerResourceSymbol];
delete this[RouterResource.routerResourceSymbol];
const splittedOriginalConfigs = splitRouteConfig(ensureArray$1(originalConfigs));
const couples = alignRouteConfigs(resource.childRoutes, splittedOriginalConfigs);
const remainingConfigs = [];
for (const couple of couples) {
if (couple.left && couple.right) {
Object.assign(couple.left, Object.assign({}, couple.right, { settings: Object.assign({}, couple.left.settings, couple.right.settings) }));
}
else if (couple.right) {
remainingConfigs.push(couple.right);
}
}
// tslint:disable-next-line:no-parameter-reassignment
originalConfigs = remainingConfigs;
if (originalConfigs.length > 0) {
this.map(originalConfigs);
}
return this;
}
function mergeRouterConfiguration(target, source) {
target.instructions = (target.instructions || []).concat(source.instructions || []);
target.options = Object.assign({}, (target.options || {}), (source.options || {}));
target.pipelineSteps = (target.pipelineSteps || []).concat(source.pipelineSteps || []);
target.title = source.title;
target.unknownRouteConfig = source.unknownRouteConfig;
target.viewPortDefaults = Object.assign({}, (target.viewPortDefaults || {}), (source.viewPortDefaults || {}));
return target;
}
function alignRouteConfigs(leftList, rightList) {
// we're essentially doing an OUTER JOIN here
const couples = leftList.map(left => {
const couple = {
left
};
let rightMatches = rightList.filter(r => r.moduleId === left.moduleId);
if (rightMatches.length > 1) {
rightMatches = rightMatches.filter(r => r.route === left.route);
if (rightMatches.length > 1) {
rightMatches = rightMatches.filter(r => r.name === left.name);
if (rightMatches.length > 1) {
rightMatches = rightMatches.filter(r => r.href === left.href);
}
}
}
if (rightMatches.length > 1) {
// really shouldn't be possible
throw new Error(`Probable duplicate routes found: ${JSON.stringify(rightMatches)}`);
}
if (rightMatches.length === 1) {
couple.right = rightMatches[0];
}
return couple;
});
for (const right of rightList) {
if (!couples.some(c => c.right === right)) {
couples.push({ right });
}
}
return couples;
}
const key = "__routerMetadata__";
const resourceKey = "resource";
const routerMetadata = {
getOwn(target) {
const metadata = getMetadataObject(target);
return metadata[resourceKey];
},
define(resource, target) {
const metadata = getMetadataObject(target);
Object.defineProperty(metadata, resourceKey, {
enumerable: false,
configurable: false,
writable: true,
value: resource
});
},
getOrCreateOwn(target, moduleId) {
const metadata = getMetadataObject(target);
let result = metadata[resourceKey];
if (result === undefined) {
result = metadata[resourceKey] = new RouterResource(target instanceof Function ? target : target.constructor, moduleId);
}
return result;
}
};
function getMetadataObject(target) {
const proto = target instanceof Function ? target.prototype : target;
if (!Object.prototype.hasOwnProperty.call(proto, key)) {
Object.defineProperty(proto, key, {
enumerable: false,
configurable: false,
writable: false,
value: Object.create(null)
});
}
return proto[key];
}
class ResourceLoader {
constructor(loader, registry) {
this.loader = loader;
this.registry = registry;
}
loadRouterResource(moduleId) {
return __awaiter(this, void 0, void 0, function* () {
const $module = yield this.loadModule(moduleId);
if (!$module.$defaultExport) {
throw new Error(`Unable to resolve RouterResource for ${$module.moduleId}.
Module appears to have no exported classes.`);
}
const resource = routerMetadata.getOrCreateOwn($module.$defaultExport.$constructor.raw, $module.moduleId);
// The decorators don't have access to their own module in aurelia-cli projects,
// so we set the moduleId now (only used by @routeConfig resources)
resource.moduleId = $module.moduleId;
resource.$module = $module;
return resource;
});
}
loadModule(normalizedId) {
return __awaiter(this, void 0, void 0, function* () {
let $module = this.registry.getModule(normalizedId);
if ($module === undefined) {
const moduleInstance = yield this.loader.loadModule(normalizedId);
$module = this.registry.registerModule(moduleInstance, normalizedId);
}
return $module;
});
}
}
/**
* Decorator: Indicates that the decorated class should define a `RouteConfig` for itself
* @param routesOrInstruction One or more RouteConfig objects whose properties will override the convention defaults,
* or an instruction object containing this decorators' parameters as properties
* @param overrideSettings A settings object to override the global RouterMetadataSettings for this resource
*/
function routeConfig(routesOrInstruction, overrideSettings) {
return (target) => {
let instruction;
if (Object.prototype.toString.call(routesOrInstruction) === "[object Object]" &&
routesOrInstruction.target) {
instruction = routesOrInstruction;
}
else {
instruction = {
target,
routes: routesOrInstruction,
settings: overrideSettings
};
}
RouterResource.ROUTE_CONFIG(instruction);
};
}
/**
* Decorator: Indicates that the decorated class should map RouteConfigs defined by the referenced moduleIds.
* @param routeConfigModuleIdsOrInstruction A single or array of `PLATFORM.moduleName("")`,
* or an instruction object containing this decorators' parameters as properties
* @param overrideSettings A settings object to override the global RouterMetadataSettings for this resource
*/
function configureRouter$1(routeConfigModuleIdsOrInstruction, overrideSettings) {
return (target) => {
let instruction;
if (Object.prototype.toString.call(routeConfigModuleIdsOrInstruction) === "[object Object]" &&
routeConfigModuleIdsOrInstruction.target) {
instruction = routeConfigModuleIdsOrInstruction;
}
else {
instruction = {
target,
routeConfigModuleIds: routeConfigModuleIdsOrInstruction,
settings: overrideSettings
};
}
RouterResource.CONFIGURE_ROUTER(instruction);
};
}
// tslint:disable:no-invalid-this
function configure(fxconfig, configureSettings) {
const settings = new RouterMetadataSettings();
if (typeof configureSettings === "function") {
configureSettings(settings);
}
const container = fxconfig.container;
const config = new RouterMetadataConfiguration(container).makeGlobal();
container.registerInstance(RouterMetadataSettings, settings);
container.registerInstance(RouterMetadataConfiguration, config);
const loader = container.get(aureliaLoader.Loader);
const registry = new Registry();
const resourceLoader = new ResourceLoader(loader, registry);
container.registerInstance(Registry, registry);
container.registerInstance(ResourceLoader, resourceLoader);
Object.defineProperty(aureliaDependencyInjection.Container.prototype, RouterResource.viewModelSymbol, {
enumerable: false,
configurable: true,
writable: true
});
Object.defineProperty(aureliaDependencyInjection.Container.prototype, "viewModel", {
enumerable: true,
configurable: true,
set: function (value) {
routerMetadata.getOrCreateOwn(value.constructor).initialize();
this[RouterResource.viewModelSymbol] = value;
},
get: function () {
return this[RouterResource.viewModelSymbol];
}
});
}
exports.configure = configure;
exports.routeConfig = routeConfig;
exports.configureRouter = configureRouter$1;
exports.$Application = $Application;
exports.$Module = $Module;
exports.$Export = $Export;
exports.$Constructor = $Constructor;
exports.$Prototype = $Prototype;
exports.$Property = $Property;
exports.Registry = Registry;
exports.ResourceLoader = ResourceLoader;
exports.RouteConfigFactory = RouteConfigFactory;
exports.DefaultRouteConfigFactory = DefaultRouteConfigFactory;
exports.RouterMetadataSettings = RouterMetadataSettings;
exports.RouterMetadataConfiguration = RouterMetadataConfiguration;
exports.routerMetadata = routerMetadata;
exports.RouterResource = RouterResource;