are recognized by the keyword they // start with. Many are trivial to parse, some require a bit of // complexity. switch (starttype) { case types._break:case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword); case types._debugger: return this.parseDebuggerStatement(node); case types._do: return this.parseDoStatement(node); case types._for: return this.parseForStatement(node); case types._function: if (!declaration) this.unexpected(); return this.parseFunctionStatement(node); case types._class: if (!declaration) this.unexpected(); return this.parseClass(node, true); case types._if: return this.parseIfStatement(node); case types._return: return this.parseReturnStatement(node); case types._switch: return this.parseSwitchStatement(node); case types._throw: return this.parseThrowStatement(node); case types._try: return this.parseTryStatement(node); case types._let: case types._const: if (!declaration) this.unexpected(); // NOTE: falls through to _var case types._var: return this.parseVarStatement(node, starttype); case types._while: return this.parseWhileStatement(node); case types._with: return this.parseWithStatement(node); case types.braceL: return this.parseBlock(); case types.semi: return this.parseEmptyStatement(node); case types._export: case types._import: if (this.hasPlugin("dynamicImport") && this.lookahead().type === types.parenL) break; if (!this.options.allowImportExportEverywhere) { if (!topLevel) { this.raise(this.state.start, "'import' and 'export' may only appear at the top level"); } if (!this.inModule) { this.raise(this.state.start, "'import' and 'export' may appear only with 'sourceType: \"module\"'"); } } return starttype === types._import ? this.parseImport(node) : this.parseExport(node); case types.name: if (this.state.value === "async") { // peek ahead and see if next token is a function var state = this.state.clone(); this.next(); if (this.match(types._function) && !this.canInsertSemicolon()) { this.expect(types._function); return this.parseFunction(node, true, false, true); } else { this.state = state; } } } // If the statement does not start with a statement keyword or a // brace, it's an ExpressionStatement or LabeledStatement. We // simply start parsing an expression, and afterwards, if the // next token is a colon and the expression was a simple // Identifier node, we switch to interpreting it as a label. var maybeName = this.state.value; var expr = this.parseExpression(); if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)) { return this.parseLabeledStatement(node, maybeName, expr); } else { return this.parseExpressionStatement(node, expr); } }; pp$1.takeDecorators = function (node) { if (this.state.decorators.length) { node.decorators = this.state.decorators; this.state.decorators = []; } }; pp$1.parseDecorators = function (allowExport) { while (this.match(types.at)) { var decorator = this.parseDecorator(); this.state.decorators.push(decorator); } if (allowExport && this.match(types._export)) { return; } if (!this.match(types._class)) { this.raise(this.state.start, "Leading decorators must be attached to a class declaration"); } }; pp$1.parseDecorator = function () { if (!this.hasPlugin("decorators")) { this.unexpected(); } var node = this.startNode(); this.next(); node.expression = this.parseMaybeAssign(); return this.finishNode(node, "Decorator"); }; pp$1.parseBreakContinueStatement = function (node, keyword) { var isBreak = keyword === "break"; this.next(); if (this.isLineTerminator()) { node.label = null; } else if (!this.match(types.name)) { this.unexpected(); } else { node.label = this.parseIdentifier(); this.semicolon(); } // Verify that there is an actual destination to break or // continue to. var i = void 0; for (i = 0; i < this.state.labels.length; ++i) { var lab = this.state.labels[i]; if (node.label == null || lab.name === node.label.name) { if (lab.kind != null && (isBreak || lab.kind === "loop")) break; if (node.label && isBreak) break; } } if (i === this.state.labels.length) this.raise(node.start, "Unsyntactic " + keyword); return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement"); }; pp$1.parseDebuggerStatement = function (node) { this.next(); this.semicolon(); return this.finishNode(node, "DebuggerStatement"); }; pp$1.parseDoStatement = function (node) { this.next(); this.state.labels.push(loopLabel); node.body = this.parseStatement(false); this.state.labels.pop(); this.expect(types._while); node.test = this.parseParenExpression(); this.eat(types.semi); return this.finishNode(node, "DoWhileStatement"); }; // Disambiguating between a `for` and a `for`/`in` or `for`/`of` // loop is non-trivial. Basically, we have to parse the init `var` // statement or expression, disallowing the `in` operator (see // the second parameter to `parseExpression`), and then check // whether the next token is `in` or `of`. When there is no init // part (semicolon immediately after the opening parenthesis), it // is a regular `for` loop. pp$1.parseForStatement = function (node) { this.next(); this.state.labels.push(loopLabel); var forAwait = false; if (this.hasPlugin("asyncGenerators") && this.state.inAsync && this.isContextual("await")) { forAwait = true; this.next(); } this.expect(types.parenL); if (this.match(types.semi)) { if (forAwait) { this.unexpected(); } return this.parseFor(node, null); } if (this.match(types._var) || this.match(types._let) || this.match(types._const)) { var _init = this.startNode(); var varKind = this.state.type; this.next(); this.parseVar(_init, true, varKind); this.finishNode(_init, "VariableDeclaration"); if (this.match(types._in) || this.isContextual("of")) { if (_init.declarations.length === 1 && !_init.declarations[0].init) { return this.parseForIn(node, _init, forAwait); } } if (forAwait) { this.unexpected(); } return this.parseFor(node, _init); } var refShorthandDefaultPos = { start: 0 }; var init = this.parseExpression(true, refShorthandDefaultPos); if (this.match(types._in) || this.isContextual("of")) { var description = this.isContextual("of") ? "for-of statement" : "for-in statement"; this.toAssignable(init, undefined, description); this.checkLVal(init, undefined, undefined, description); return this.parseForIn(node, init, forAwait); } else if (refShorthandDefaultPos.start) { this.unexpected(refShorthandDefaultPos.start); } if (forAwait) { this.unexpected(); } return this.parseFor(node, init); }; pp$1.parseFunctionStatement = function (node) { this.next(); return this.parseFunction(node, true); }; pp$1.parseIfStatement = function (node) { this.next(); node.test = this.parseParenExpression(); node.consequent = this.parseStatement(false); node.alternate = this.eat(types._else) ? this.parseStatement(false) : null; return this.finishNode(node, "IfStatement"); }; pp$1.parseReturnStatement = function (node) { if (!this.state.inFunction && !this.options.allowReturnOutsideFunction) { this.raise(this.state.start, "'return' outside of function"); } this.next(); // In `return` (and `break`/`continue`), the keywords with // optional arguments, we eagerly look for a semicolon or the // possibility to insert one. if (this.isLineTerminator()) { node.argument = null; } else { node.argument = this.parseExpression(); this.semicolon(); } return this.finishNode(node, "ReturnStatement"); }; pp$1.parseSwitchStatement = function (node) { this.next(); node.discriminant = this.parseParenExpression(); node.cases = []; this.expect(types.braceL); this.state.labels.push(switchLabel); // Statements under must be grouped (by label) in SwitchCase // nodes. `cur` is used to keep the node that we are currently // adding statements to. var cur = void 0; for (var sawDefault; !this.match(types.braceR);) { if (this.match(types._case) || this.match(types._default)) { var isCase = this.match(types._case); if (cur) this.finishNode(cur, "SwitchCase"); node.cases.push(cur = this.startNode()); cur.consequent = []; this.next(); if (isCase) { cur.test = this.parseExpression(); } else { if (sawDefault) this.raise(this.state.lastTokStart, "Multiple default clauses"); sawDefault = true; cur.test = null; } this.expect(types.colon); } else { if (cur) { cur.consequent.push(this.parseStatement(true)); } else { this.unexpected(); } } } if (cur) this.finishNode(cur, "SwitchCase"); this.next(); // Closing brace this.state.labels.pop(); return this.finishNode(node, "SwitchStatement"); }; pp$1.parseThrowStatement = function (node) { this.next(); if (lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.start))) this.raise(this.state.lastTokEnd, "Illegal newline after throw"); node.argument = this.parseExpression(); this.semicolon(); return this.finishNode(node, "ThrowStatement"); }; // Reused empty array added for node fields that are always empty. var empty = []; pp$1.parseTryStatement = function (node) { this.next(); node.block = this.parseBlock(); node.handler = null; if (this.match(types._catch)) { var clause = this.startNode(); this.next(); this.expect(types.parenL); clause.param = this.parseBindingAtom(); this.checkLVal(clause.param, true, Object.create(null), "catch clause"); this.expect(types.parenR); clause.body = this.parseBlock(); node.handler = this.finishNode(clause, "CatchClause"); } node.guardedHandlers = empty; node.finalizer = this.eat(types._finally) ? this.parseBlock() : null; if (!node.handler && !node.finalizer) { this.raise(node.start, "Missing catch or finally clause"); } return this.finishNode(node, "TryStatement"); }; pp$1.parseVarStatement = function (node, kind) { this.next(); this.parseVar(node, false, kind); this.semicolon(); return this.finishNode(node, "VariableDeclaration"); }; pp$1.parseWhileStatement = function (node) { this.next(); node.test = this.parseParenExpression(); this.state.labels.push(loopLabel); node.body = this.parseStatement(false); this.state.labels.pop(); return this.finishNode(node, "WhileStatement"); }; pp$1.parseWithStatement = function (node) { if (this.state.strict) this.raise(this.state.start, "'with' in strict mode"); this.next(); node.object = this.parseParenExpression(); node.body = this.parseStatement(false); return this.finishNode(node, "WithStatement"); }; pp$1.parseEmptyStatement = function (node) { this.next(); return this.finishNode(node, "EmptyStatement"); }; pp$1.parseLabeledStatement = function (node, maybeName, expr) { for (var _iterator = this.state.labels, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { var _ref; if (_isArray) { if (_i >= _iterator.length) break; _ref = _iterator[_i++]; } else { _i = _iterator.next(); if (_i.done) break; _ref = _i.value; } var _label = _ref; if (_label.name === maybeName) { this.raise(expr.start, "Label '" + maybeName + "' is already declared"); } } var kind = this.state.type.isLoop ? "loop" : this.match(types._switch) ? "switch" : null; for (var i = this.state.labels.length - 1; i >= 0; i--) { var label = this.state.labels[i]; if (label.statementStart === node.start) { label.statementStart = this.state.start; label.kind = kind; } else { break; } } this.state.labels.push({ name: maybeName, kind: kind, statementStart: this.state.start }); node.body = this.parseStatement(true); this.state.labels.pop(); node.label = expr; return this.finishNode(node, "LabeledStatement"); }; pp$1.parseExpressionStatement = function (node, expr) { node.expression = expr; this.semicolon(); return this.finishNode(node, "ExpressionStatement"); }; // Parse a semicolon-enclosed block of statements, handling `"use // strict"` declarations when `allowStrict` is true (used for // function bodies). pp$1.parseBlock = function (allowDirectives) { var node = this.startNode(); this.expect(types.braceL); this.parseBlockBody(node, allowDirectives, false, types.braceR); return this.finishNode(node, "BlockStatement"); }; pp$1.isValidDirective = function (stmt) { return stmt.type === "ExpressionStatement" && stmt.expression.type === "StringLiteral" && !stmt.expression.extra.parenthesized; }; pp$1.parseBlockBody = function (node, allowDirectives, topLevel, end) { node.body = []; node.directives = []; var parsedNonDirective = false; var oldStrict = void 0; var octalPosition = void 0; while (!this.eat(end)) { if (!parsedNonDirective && this.state.containsOctal && !octalPosition) { octalPosition = this.state.octalPosition; } var stmt = this.parseStatement(true, topLevel); if (allowDirectives && !parsedNonDirective && this.isValidDirective(stmt)) { var directive = this.stmtToDirective(stmt); node.directives.push(directive); if (oldStrict === undefined && directive.value.value === "use strict") { oldStrict = this.state.strict; this.setStrict(true); if (octalPosition) { this.raise(octalPosition, "Octal literal in strict mode"); } } continue; } parsedNonDirective = true; node.body.push(stmt); } if (oldStrict === false) { this.setStrict(false); } }; // Parse a regular `for` loop. The disambiguation code in // `parseStatement` will already have parsed the init statement or // expression. pp$1.parseFor = function (node, init) { node.init = init; this.expect(types.semi); node.test = this.match(types.semi) ? null : this.parseExpression(); this.expect(types.semi); node.update = this.match(types.parenR) ? null : this.parseExpression(); this.expect(types.parenR); node.body = this.parseStatement(false); this.state.labels.pop(); return this.finishNode(node, "ForStatement"); }; // Parse a `for`/`in` and `for`/`of` loop, which are almost // same from parser's perspective. pp$1.parseForIn = function (node, init, forAwait) { var type = void 0; if (forAwait) { this.eatContextual("of"); type = "ForAwaitStatement"; } else { type = this.match(types._in) ? "ForInStatement" : "ForOfStatement"; this.next(); } node.left = init; node.right = this.parseExpression(); this.expect(types.parenR); node.body = this.parseStatement(false); this.state.labels.pop(); return this.finishNode(node, type); }; // Parse a list of variable declarations. pp$1.parseVar = function (node, isFor, kind) { node.declarations = []; node.kind = kind.keyword; for (;;) { var decl = this.startNode(); this.parseVarHead(decl); if (this.eat(types.eq)) { decl.init = this.parseMaybeAssign(isFor); } else if (kind === types._const && !(this.match(types._in) || this.isContextual("of"))) { this.unexpected(); } else if (decl.id.type !== "Identifier" && !(isFor && (this.match(types._in) || this.isContextual("of")))) { this.raise(this.state.lastTokEnd, "Complex binding patterns require an initialization value"); } else { decl.init = null; } node.declarations.push(this.finishNode(decl, "VariableDeclarator")); if (!this.eat(types.comma)) break; } return node; }; pp$1.parseVarHead = function (decl) { decl.id = this.parseBindingAtom(); this.checkLVal(decl.id, true, undefined, "variable declaration"); }; // Parse a function declaration or literal (depending on the // `isStatement` parameter). pp$1.parseFunction = function (node, isStatement, allowExpressionBody, isAsync, optionalId) { var oldInMethod = this.state.inMethod; this.state.inMethod = false; this.initFunction(node, isAsync); if (this.match(types.star)) { if (node.async && !this.hasPlugin("asyncGenerators")) { this.unexpected(); } else { node.generator = true; this.next(); } } if (isStatement && !optionalId && !this.match(types.name) && !this.match(types._yield)) { this.unexpected(); } if (this.match(types.name) || this.match(types._yield)) { node.id = this.parseBindingIdentifier(); } this.parseFunctionParams(node); this.parseFunctionBody(node, allowExpressionBody); this.state.inMethod = oldInMethod; return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression"); }; pp$1.parseFunctionParams = function (node) { this.expect(types.parenL); node.params = this.parseBindingList(types.parenR); }; // Parse a class declaration or literal (depending on the // `isStatement` parameter). pp$1.parseClass = function (node, isStatement, optionalId) { this.next(); this.takeDecorators(node); this.parseClassId(node, isStatement, optionalId); this.parseClassSuper(node); this.parseClassBody(node); return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression"); }; pp$1.isClassProperty = function () { return this.match(types.eq) || this.match(types.semi) || this.match(types.braceR); }; pp$1.isClassMethod = function () { return this.match(types.parenL); }; pp$1.isNonstaticConstructor = function (method) { return !method.computed && !method.static && (method.key.name === "constructor" || // Identifier method.key.value === "constructor" // Literal ); }; pp$1.parseClassBody = function (node) { // class bodies are implicitly strict var oldStrict = this.state.strict; this.state.strict = true; var hadConstructorCall = false; var hadConstructor = false; var decorators = []; var classBody = this.startNode(); classBody.body = []; this.expect(types.braceL); while (!this.eat(types.braceR)) { if (this.eat(types.semi)) { if (decorators.length > 0) { this.raise(this.state.lastTokEnd, "Decorators must not be followed by a semicolon"); } continue; } if (this.match(types.at)) { decorators.push(this.parseDecorator()); continue; } var method = this.startNode(); // steal the decorators if there are any if (decorators.length) { method.decorators = decorators; decorators = []; } method.static = false; if (this.match(types.name) && this.state.value === "static") { var key = this.parseIdentifier(true); // eats 'static' if (this.isClassMethod()) { // a method named 'static' method.kind = "method"; method.computed = false; method.key = key; this.parseClassMethod(classBody, method, false, false); continue; } else if (this.isClassProperty()) { // a property named 'static' method.computed = false; method.key = key; classBody.body.push(this.parseClassProperty(method)); continue; } // otherwise something static method.static = true; } if (this.eat(types.star)) { // a generator method.kind = "method"; this.parsePropertyName(method); if (this.isNonstaticConstructor(method)) { this.raise(method.key.start, "Constructor can't be a generator"); } if (!method.computed && method.static && (method.key.name === "prototype" || method.key.value === "prototype")) { this.raise(method.key.start, "Classes may not have static property named prototype"); } this.parseClassMethod(classBody, method, true, false); } else { var isSimple = this.match(types.name); var _key = this.parsePropertyName(method); if (!method.computed && method.static && (method.key.name === "prototype" || method.key.value === "prototype")) { this.raise(method.key.start, "Classes may not have static property named prototype"); } if (this.isClassMethod()) { // a normal method if (this.isNonstaticConstructor(method)) { if (hadConstructor) { this.raise(_key.start, "Duplicate constructor in the same class"); } else if (method.decorators) { this.raise(method.start, "You can't attach decorators to a class constructor"); } hadConstructor = true; method.kind = "constructor"; } else { method.kind = "method"; } this.parseClassMethod(classBody, method, false, false); } else if (this.isClassProperty()) { // a normal property if (this.isNonstaticConstructor(method)) { this.raise(method.key.start, "Classes may not have a non-static field named 'constructor'"); } classBody.body.push(this.parseClassProperty(method)); } else if (isSimple && _key.name === "async" && !this.isLineTerminator()) { // an async method var isGenerator = this.hasPlugin("asyncGenerators") && this.eat(types.star); method.kind = "method"; this.parsePropertyName(method); if (this.isNonstaticConstructor(method)) { this.raise(method.key.start, "Constructor can't be an async function"); } this.parseClassMethod(classBody, method, isGenerator, true); } else if (isSimple && (_key.name === "get" || _key.name === "set") && !(this.isLineTerminator() && this.match(types.star))) { // `get\n*` is an uninitialized property named 'get' followed by a generator. // a getter or setter method.kind = _key.name; this.parsePropertyName(method); if (this.isNonstaticConstructor(method)) { this.raise(method.key.start, "Constructor can't have get/set modifier"); } this.parseClassMethod(classBody, method, false, false); this.checkGetterSetterParamCount(method); } else if (this.hasPlugin("classConstructorCall") && isSimple && _key.name === "call" && this.match(types.name) && this.state.value === "constructor") { // a (deprecated) call constructor if (hadConstructorCall) { this.raise(method.start, "Duplicate constructor call in the same class"); } else if (method.decorators) { this.raise(method.start, "You can't attach decorators to a class constructor"); } hadConstructorCall = true; method.kind = "constructorCall"; this.parsePropertyName(method); // consume "constructor" and make it the method's name this.parseClassMethod(classBody, method, false, false); } else if (this.isLineTerminator()) { // an uninitialized class property (due to ASI, since we don't otherwise recognize the next token) if (this.isNonstaticConstructor(method)) { this.raise(method.key.start, "Classes may not have a non-static field named 'constructor'"); } classBody.body.push(this.parseClassProperty(method)); } else { this.unexpected(); } } } if (decorators.length) { this.raise(this.state.start, "You have trailing decorators with no method"); } node.body = this.finishNode(classBody, "ClassBody"); this.state.strict = oldStrict; }; pp$1.parseClassProperty = function (node) { this.state.inClassProperty = true; if (this.match(types.eq)) { if (!this.hasPlugin("classProperties")) this.unexpected(); this.next(); node.value = this.parseMaybeAssign(); } else { node.value = null; } this.semicolon(); this.state.inClassProperty = false; return this.finishNode(node, "ClassProperty"); }; pp$1.parseClassMethod = function (classBody, method, isGenerator, isAsync) { this.parseMethod(method, isGenerator, isAsync); classBody.body.push(this.finishNode(method, "ClassMethod")); }; pp$1.parseClassId = function (node, isStatement, optionalId) { if (this.match(types.name)) { node.id = this.parseIdentifier(); } else { if (optionalId || !isStatement) { node.id = null; } else { this.unexpected(); } } }; pp$1.parseClassSuper = function (node) { node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null; }; // Parses module export declaration. pp$1.parseExport = function (node) { this.next(); // export * from '...' if (this.match(types.star)) { var specifier = this.startNode(); this.next(); if (this.hasPlugin("exportExtensions") && this.eatContextual("as")) { specifier.exported = this.parseIdentifier(); node.specifiers = [this.finishNode(specifier, "ExportNamespaceSpecifier")]; this.parseExportSpecifiersMaybe(node); this.parseExportFrom(node, true); } else { this.parseExportFrom(node, true); return this.finishNode(node, "ExportAllDeclaration"); } } else if (this.hasPlugin("exportExtensions") && this.isExportDefaultSpecifier()) { var _specifier = this.startNode(); _specifier.exported = this.parseIdentifier(true); node.specifiers = [this.finishNode(_specifier, "ExportDefaultSpecifier")]; if (this.match(types.comma) && this.lookahead().type === types.star) { this.expect(types.comma); var _specifier2 = this.startNode(); this.expect(types.star); this.expectContextual("as"); _specifier2.exported = this.parseIdentifier(); node.specifiers.push(this.finishNode(_specifier2, "ExportNamespaceSpecifier")); } else { this.parseExportSpecifiersMaybe(node); } this.parseExportFrom(node, true); } else if (this.eat(types._default)) { // export default ... var expr = this.startNode(); var needsSemi = false; if (this.eat(types._function)) { expr = this.parseFunction(expr, true, false, false, true); } else if (this.match(types._class)) { expr = this.parseClass(expr, true, true); } else { needsSemi = true; expr = this.parseMaybeAssign(); } node.declaration = expr; if (needsSemi) this.semicolon(); this.checkExport(node, true, true); return this.finishNode(node, "ExportDefaultDeclaration"); } else if (this.shouldParseExportDeclaration()) { node.specifiers = []; node.source = null; node.declaration = this.parseExportDeclaration(node); } else { // export { x, y as z } [from '...'] node.declaration = null; node.specifiers = this.parseExportSpecifiers(); this.parseExportFrom(node); } this.checkExport(node, true); return this.finishNode(node, "ExportNamedDeclaration"); }; pp$1.parseExportDeclaration = function () { return this.parseStatement(true); }; pp$1.isExportDefaultSpecifier = function () { if (this.match(types.name)) { return this.state.value !== "async"; } if (!this.match(types._default)) { return false; } var lookahead = this.lookahead(); return lookahead.type === types.comma || lookahead.type === types.name && lookahead.value === "from"; }; pp$1.parseExportSpecifiersMaybe = function (node) { if (this.eat(types.comma)) { node.specifiers = node.specifiers.concat(this.parseExportSpecifiers()); } }; pp$1.parseExportFrom = function (node, expect) { if (this.eatContextual("from")) { node.source = this.match(types.string) ? this.parseExprAtom() : this.unexpected(); this.checkExport(node); } else { if (expect) { this.unexpected(); } else { node.source = null; } } this.semicolon(); }; pp$1.shouldParseExportDeclaration = function () { return this.state.type.keyword === "var" || this.state.type.keyword === "const" || this.state.type.keyword === "let" || this.state.type.keyword === "function" || this.state.type.keyword === "class" || this.isContextual("async"); }; pp$1.checkExport = function (node, checkNames, isDefault) { if (checkNames) { // Check for duplicate exports if (isDefault) { // Default exports this.checkDuplicateExports(node, "default"); } else if (node.specifiers && node.specifiers.length) { // Named exports for (var _iterator2 = node.specifiers, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { var _ref2; if (_isArray2) { if (_i2 >= _iterator2.length) break; _ref2 = _iterator2[_i2++]; } else { _i2 = _iterator2.next(); if (_i2.done) break; _ref2 = _i2.value; } var specifier = _ref2; this.checkDuplicateExports(specifier, specifier.exported.name); } } else if (node.declaration) { // Exported declarations if (node.declaration.type === "FunctionDeclaration" || node.declaration.type === "ClassDeclaration") { this.checkDuplicateExports(node, node.declaration.id.name); } else if (node.declaration.type === "VariableDeclaration") { for (var _iterator3 = node.declaration.declarations, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { var _ref3; if (_isArray3) { if (_i3 >= _iterator3.length) break; _ref3 = _iterator3[_i3++]; } else { _i3 = _iterator3.next(); if (_i3.done) break; _ref3 = _i3.value; } var declaration = _ref3; this.checkDeclaration(declaration.id); } } } } if (this.state.decorators.length) { var isClass = node.declaration && (node.declaration.type === "ClassDeclaration" || node.declaration.type === "ClassExpression"); if (!node.declaration || !isClass) { this.raise(node.start, "You can only use decorators on an export when exporting a class"); } this.takeDecorators(node.declaration); } }; pp$1.checkDeclaration = function (node) { if (node.type === "ObjectPattern") { for (var _iterator4 = node.properties, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { var _ref4; if (_isArray4) { if (_i4 >= _iterator4.length) break; _ref4 = _iterator4[_i4++]; } else { _i4 = _iterator4.next(); if (_i4.done) break; _ref4 = _i4.value; } var prop = _ref4; this.checkDeclaration(prop); } } else if (node.type === "ArrayPattern") { for (var _iterator5 = node.elements, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { var _ref5; if (_isArray5) { if (_i5 >= _iterator5.length) break; _ref5 = _iterator5[_i5++]; } else { _i5 = _iterator5.next(); if (_i5.done) break; _ref5 = _i5.value; } var elem = _ref5; if (elem) { this.checkDeclaration(elem); } } } else if (node.type === "ObjectProperty") { this.checkDeclaration(node.value); } else if (node.type === "RestElement" || node.type === "RestProperty") { this.checkDeclaration(node.argument); } else if (node.type === "Identifier") { this.checkDuplicateExports(node, node.name); } }; pp$1.checkDuplicateExports = function (node, name) { if (this.state.exportedIdentifiers.indexOf(name) > -1) { this.raiseDuplicateExportError(node, name); } this.state.exportedIdentifiers.push(name); }; pp$1.raiseDuplicateExportError = function (node, name) { this.raise(node.start, name === "default" ? "Only one default export allowed per module." : "`" + name + "` has already been exported. Exported identifiers must be unique."); }; // Parses a comma-separated list of module exports. pp$1.parseExportSpecifiers = function () { var nodes = []; var first = true; var needsFrom = void 0; // export { x, y as z } [from '...'] this.expect(types.braceL); while (!this.eat(types.braceR)) { if (first) { first = false; } else { this.expect(types.comma); if (this.eat(types.braceR)) break; } var isDefault = this.match(types._default); if (isDefault && !needsFrom) needsFrom = true; var node = this.startNode(); node.local = this.parseIdentifier(isDefault); node.exported = this.eatContextual("as") ? this.parseIdentifier(true) : node.local.__clone(); nodes.push(this.finishNode(node, "ExportSpecifier")); } // https://github.com/ember-cli/ember-cli/pull/3739 if (needsFrom && !this.isContextual("from")) { this.unexpected(); } return nodes; }; // Parses import declaration. pp$1.parseImport = function (node) { this.eat(types._import); // import '...' if (this.match(types.string)) { node.specifiers = []; node.source = this.parseExprAtom(); } else { node.specifiers = []; this.parseImportSpecifiers(node); this.expectContextual("from"); node.source = this.match(types.string) ? this.parseExprAtom() : this.unexpected(); } this.semicolon(); return this.finishNode(node, "ImportDeclaration"); }; // Parses a comma-separated list of module imports. pp$1.parseImportSpecifiers = function (node) { var first = true; if (this.match(types.name)) { // import defaultObj, { x, y as z } from '...' var startPos = this.state.start; var startLoc = this.state.startLoc; node.specifiers.push(this.parseImportSpecifierDefault(this.parseIdentifier(), startPos, startLoc)); if (!this.eat(types.comma)) return; } if (this.match(types.star)) { var specifier = this.startNode(); this.next(); this.expectContextual("as"); specifier.local = this.parseIdentifier(); this.checkLVal(specifier.local, true, undefined, "import namespace specifier"); node.specifiers.push(this.finishNode(specifier, "ImportNamespaceSpecifier")); return; } this.expect(types.braceL); while (!this.eat(types.braceR)) { if (first) { first = false; } else { // Detect an attempt to deep destructure if (this.eat(types.colon)) { this.unexpected(null, "ES2015 named imports do not destructure. Use another statement for destructuring after the import."); } this.expect(types.comma); if (this.eat(types.braceR)) break; } this.parseImportSpecifier(node); } }; pp$1.parseImportSpecifier = function (node) { var specifier = this.startNode(); specifier.imported = this.parseIdentifier(true); if (this.eatContextual("as")) { specifier.local = this.parseIdentifier(); } else { this.checkReservedWord(specifier.imported.name, specifier.start, true, true); specifier.local = specifier.imported.__clone(); } this.checkLVal(specifier.local, true, undefined, "import specifier"); node.specifiers.push(this.finishNode(specifier, "ImportSpecifier")); }; pp$1.parseImportSpecifierDefault = function (id, startPos, startLoc) { var node = this.startNodeAt(startPos, startLoc); node.local = id; this.checkLVal(node.local, true, undefined, "default import specifier"); return this.finishNode(node, "ImportDefaultSpecifier"); }; var pp$2 = Parser.prototype; // Convert existing expression atom to assignable pattern // if possible. pp$2.toAssignable = function (node, isBinding, contextDescription) { if (node) { switch (node.type) { case "Identifier": case "ObjectPattern": case "ArrayPattern": case "AssignmentPattern": break; case "ObjectExpression": node.type = "ObjectPattern"; for (var _iterator = node.properties, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { var _ref; if (_isArray) { if (_i >= _iterator.length) break; _ref = _iterator[_i++]; } else { _i = _iterator.next(); if (_i.done) break; _ref = _i.value; } var prop = _ref; if (prop.type === "ObjectMethod") { if (prop.kind === "get" || prop.kind === "set") { this.raise(prop.key.start, "Object pattern can't contain getter or setter"); } else { this.raise(prop.key.start, "Object pattern can't contain methods"); } } else { this.toAssignable(prop, isBinding, "object destructuring pattern"); } } break; case "ObjectProperty": this.toAssignable(node.value, isBinding, contextDescription); break; case "SpreadProperty": node.type = "RestProperty"; var arg = node.argument; this.toAssignable(arg, isBinding, contextDescription); break; case "ArrayExpression": node.type = "ArrayPattern"; this.toAssignableList(node.elements, isBinding, contextDescription); break; case "AssignmentExpression": if (node.operator === "=") { node.type = "AssignmentPattern"; delete node.operator; } else { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } break; case "MemberExpression": if (!isBinding) break; default: { var message = "Invalid left-hand side" + (contextDescription ? " in " + contextDescription : /* istanbul ignore next */"expression"); this.raise(node.start, message); } } } return node; }; // Convert list of expression atoms to binding list. pp$2.toAssignableList = function (exprList, isBinding, contextDescription) { var end = exprList.length; if (end) { var last = exprList[end - 1]; if (last && last.type === "RestElement") { --end; } else if (last && last.type === "SpreadElement") { last.type = "RestElement"; var arg = last.argument; this.toAssignable(arg, isBinding, contextDescription); if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern") { this.unexpected(arg.start); } --end; } } for (var i = 0; i < end; i++) { var elt = exprList[i]; if (elt) this.toAssignable(elt, isBinding, contextDescription); } return exprList; }; // Convert list of expression atoms to a list of pp$2.toReferencedList = function (exprList) { return exprList; }; // Parses spread element. pp$2.parseSpread = function (refShorthandDefaultPos) { var node = this.startNode(); this.next(); node.argument = this.parseMaybeAssign(false, refShorthandDefaultPos); return this.finishNode(node, "SpreadElement"); }; pp$2.parseRest = function () { var node = this.startNode(); this.next(); node.argument = this.parseBindingIdentifier(); return this.finishNode(node, "RestElement"); }; pp$2.shouldAllowYieldIdentifier = function () { return this.match(types._yield) && !this.state.strict && !this.state.inGenerator; }; pp$2.parseBindingIdentifier = function () { return this.parseIdentifier(this.shouldAllowYieldIdentifier()); }; // Parses lvalue (assignable) atom. pp$2.parseBindingAtom = function () { switch (this.state.type) { case types._yield: if (this.state.strict || this.state.inGenerator) this.unexpected(); // fall-through case types.name: return this.parseIdentifier(true); case types.bracketL: var node = this.startNode(); this.next(); node.elements = this.parseBindingList(types.bracketR, true); return this.finishNode(node, "ArrayPattern"); case types.braceL: return this.parseObj(true); default: this.unexpected(); } }; pp$2.parseBindingList = function (close, allowEmpty) { var elts = []; var first = true; while (!this.eat(close)) { if (first) { first = false; } else { this.expect(types.comma); } if (allowEmpty && this.match(types.comma)) { elts.push(null); } else if (this.eat(close)) { break; } else if (this.match(types.ellipsis)) { elts.push(this.parseAssignableListItemTypes(this.parseRest())); this.expect(close); break; } else { var decorators = []; while (this.match(types.at)) { decorators.push(this.parseDecorator()); } var left = this.parseMaybeDefault(); if (decorators.length) { left.decorators = decorators; } this.parseAssignableListItemTypes(left); elts.push(this.parseMaybeDefault(left.start, left.loc.start, left)); } } return elts; }; pp$2.parseAssignableListItemTypes = function (param) { return param; }; // Parses assignment pattern around given atom if possible. pp$2.parseMaybeDefault = function (startPos, startLoc, left) { startLoc = startLoc || this.state.startLoc; startPos = startPos || this.state.start; left = left || this.parseBindingAtom(); if (!this.eat(types.eq)) return left; var node = this.startNodeAt(startPos, startLoc); node.left = left; node.right = this.parseMaybeAssign(); return this.finishNode(node, "AssignmentPattern"); }; // Verify that a node is an lval — something that can be assigned // to. pp$2.checkLVal = function (expr, isBinding, checkClashes, contextDescription) { switch (expr.type) { case "Identifier": this.checkReservedWord(expr.name, expr.start, false, true); if (checkClashes) { // we need to prefix this with an underscore for the cases where we have a key of // `__proto__`. there's a bug in old V8 where the following wouldn't work: // // > var obj = Object.create(null); // undefined // > obj.__proto__ // null // > obj.__proto__ = true; // true // > obj.__proto__ // null var key = "_" + expr.name; if (checkClashes[key]) { this.raise(expr.start, "Argument name clash in strict mode"); } else { checkClashes[key] = true; } } break; case "MemberExpression": if (isBinding) this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression"); break; case "ObjectPattern": for (var _iterator2 = expr.properties, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { var _ref2; if (_isArray2) { if (_i2 >= _iterator2.length) break; _ref2 = _iterator2[_i2++]; } else { _i2 = _iterator2.next(); if (_i2.done) break; _ref2 = _i2.value; } var prop = _ref2; if (prop.type === "ObjectProperty") prop = prop.value; this.checkLVal(prop, isBinding, checkClashes, "object destructuring pattern"); } break; case "ArrayPattern": for (var _iterator3 = expr.elements, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { var _ref3; if (_isArray3) { if (_i3 >= _iterator3.length) break; _ref3 = _iterator3[_i3++]; } else { _i3 = _iterator3.next(); if (_i3.done) break; _ref3 = _i3.value; } var elem = _ref3; if (elem) this.checkLVal(elem, isBinding, checkClashes, "array destructuring pattern"); } break; case "AssignmentPattern": this.checkLVal(expr.left, isBinding, checkClashes, "assignment pattern"); break; case "RestProperty": this.checkLVal(expr.argument, isBinding, checkClashes, "rest property"); break; case "RestElement": this.checkLVal(expr.argument, isBinding, checkClashes, "rest element"); break; default: { var message = (isBinding ? /* istanbul ignore next */"Binding invalid" : "Invalid") + " left-hand side" + (contextDescription ? " in " + contextDescription : /* istanbul ignore next */"expression"); this.raise(expr.start, message); } } }; /* eslint max-len: 0 */ // A recursive descent parser operates by defining functions for all // syntactic elements, and recursively calling those, each function // advancing the input stream and returning an AST node. Precedence // of constructs (for example, the fact that `!x[1]` means `!(x[1])` // instead of `(!x)[1]` is handled by the fact that the parser // function that parses unary prefix operators is called first, and // in turn calls the function that parses `[]` subscripts — that // way, it'll receive the node for `x[1]` already parsed, and wraps // *that* in the unary operator node. // // Acorn uses an [operator precedence parser][opp] to handle binary // operator precedence, because it is much more compact than using // the technique outlined above, which uses different, nesting // functions to specify precedence, for all of the ten binary // precedence levels that JavaScript defines. // // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser var pp$3 = Parser.prototype; // Check if property name clashes with already added. // Object/class getters and setters are not allowed to clash — // either with each other or with an init property — and in // strict mode, init properties are also not allowed to be repeated. pp$3.checkPropClash = function (prop, propHash) { if (prop.computed || prop.kind) return; var key = prop.key; // It is either an Identifier or a String/NumericLiteral var name = key.type === "Identifier" ? key.name : String(key.value); if (name === "__proto__") { if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property"); propHash.proto = true; } }; // Convenience method to parse an Expression only pp$3.getExpression = function () { this.nextToken(); var expr = this.parseExpression(); if (!this.match(types.eof)) { this.unexpected(); } return expr; }; // ### Expression parsing // These nest, from the most general expression type at the top to // 'atomic', nondivisible expression types at the bottom. Most of // the functions will simply let the function (s) below them parse, // and, *if* the syntactic construct they handle is present, wrap // the AST node that the inner parser gave them in another node. // Parse a full expression. The optional arguments are used to // forbid the `in` operator (in for loops initialization expressions) // and provide reference for storing '=' operator inside shorthand // property assignment in contexts where both object expression // and object pattern might appear (so it's possible to raise // delayed syntax error at correct position). pp$3.parseExpression = function (noIn, refShorthandDefaultPos) { var startPos = this.state.start; var startLoc = this.state.startLoc; var expr = this.parseMaybeAssign(noIn, refShorthandDefaultPos); if (this.match(types.comma)) { var node = this.startNodeAt(startPos, startLoc); node.expressions = [expr]; while (this.eat(types.comma)) { node.expressions.push(this.parseMaybeAssign(noIn, refShorthandDefaultPos)); } this.toReferencedList(node.expressions); return this.finishNode(node, "SequenceExpression"); } return expr; }; // Parse an assignment expression. This includes applications of // operators like `+=`. pp$3.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse, refNeedsArrowPos) { var startPos = this.state.start; var startLoc = this.state.startLoc; if (this.match(types._yield) && this.state.inGenerator) { var _left = this.parseYield(); if (afterLeftParse) _left = afterLeftParse.call(this, _left, startPos, startLoc); return _left; } var failOnShorthandAssign = void 0; if (refShorthandDefaultPos) { failOnShorthandAssign = false; } else { refShorthandDefaultPos = { start: 0 }; failOnShorthandAssign = true; } if (this.match(types.parenL) || this.match(types.name)) { this.state.potentialArrowAt = this.state.start; } var left = this.parseMaybeConditional(noIn, refShorthandDefaultPos, refNeedsArrowPos); if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc); if (this.state.type.isAssign) { var node = this.startNodeAt(startPos, startLoc); node.operator = this.state.value; node.left = this.match(types.eq) ? this.toAssignable(left, undefined, "assignment expression") : left; refShorthandDefaultPos.start = 0; // reset because shorthand default was used correctly this.checkLVal(left, undefined, undefined, "assignment expression"); if (left.extra && left.extra.parenthesized) { var errorMsg = void 0; if (left.type === "ObjectPattern") { errorMsg = "`({a}) = 0` use `({a} = 0)`"; } else if (left.type === "ArrayPattern") { errorMsg = "`([a]) = 0` use `([a] = 0)`"; } if (errorMsg) { this.raise(left.start, "You're trying to assign to a parenthesized expression, eg. instead of " + errorMsg); } } this.next(); node.right = this.parseMaybeAssign(noIn); return this.finishNode(node, "AssignmentExpression"); } else if (failOnShorthandAssign && refShorthandDefaultPos.start) { this.unexpected(refShorthandDefaultPos.start); } return left; }; // Parse a ternary conditional (`?:`) operator. pp$3.parseMaybeConditional = function (noIn, refShorthandDefaultPos, refNeedsArrowPos) { var startPos = this.state.start; var startLoc = this.state.startLoc; var expr = this.parseExprOps(noIn, refShorthandDefaultPos); if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr; return this.parseConditional(expr, noIn, startPos, startLoc, refNeedsArrowPos); }; pp$3.parseConditional = function (expr, noIn, startPos, startLoc) { if (this.eat(types.question)) { var node = this.startNodeAt(startPos, startLoc); node.test = expr; node.consequent = this.parseMaybeAssign(); this.expect(types.colon); node.alternate = this.parseMaybeAssign(noIn); return this.finishNode(node, "ConditionalExpression"); } return expr; }; // Start the precedence parser. pp$3.parseExprOps = function (noIn, refShorthandDefaultPos) { var startPos = this.state.start; var startLoc = this.state.startLoc; var expr = this.parseMaybeUnary(refShorthandDefaultPos); if (refShorthandDefaultPos && refShorthandDefaultPos.start) { return expr; } else { return this.parseExprOp(expr, startPos, startLoc, -1, noIn); } }; // Parse binary operators with the operator precedence parsing // algorithm. `left` is the left-hand side of the operator. // `minPrec` provides context that allows the function to stop and // defer further parser to one of its callers when it encounters an // operator that has a lower precedence than the set it is parsing. pp$3.parseExprOp = function (left, leftStartPos, leftStartLoc, minPrec, noIn) { var prec = this.state.type.binop; if (prec != null && (!noIn || !this.match(types._in))) { if (prec > minPrec) { var node = this.startNodeAt(leftStartPos, leftStartLoc); node.left = left; node.operator = this.state.value; if (node.operator === "**" && left.type === "UnaryExpression" && left.extra && !left.extra.parenthesizedArgument && !left.extra.parenthesized) { this.raise(left.argument.start, "Illegal expression. Wrap left hand side or entire exponentiation in parentheses."); } var op = this.state.type; this.next(); var startPos = this.state.start; var startLoc = this.state.startLoc; node.right = this.parseExprOp(this.parseMaybeUnary(), startPos, startLoc, op.rightAssociative ? prec - 1 : prec, noIn); this.finishNode(node, op === types.logicalOR || op === types.logicalAND ? "LogicalExpression" : "BinaryExpression"); return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn); } } return left; }; // Parse unary operators, both prefix and postfix. pp$3.parseMaybeUnary = function (refShorthandDefaultPos) { if (this.state.type.prefix) { var node = this.startNode(); var update = this.match(types.incDec); node.operator = this.state.value; node.prefix = true; this.next(); var argType = this.state.type; node.argument = this.parseMaybeUnary(); this.addExtra(node, "parenthesizedArgument", argType === types.parenL && (!node.argument.extra || !node.argument.extra.parenthesized)); if (refShorthandDefaultPos && refShorthandDefaultPos.start) { this.unexpected(refShorthandDefaultPos.start); } if (update) { this.checkLVal(node.argument, undefined, undefined, "prefix operation"); } else if (this.state.strict && node.operator === "delete" && node.argument.type === "Identifier") { this.raise(node.start, "Deleting local variable in strict mode"); } return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); } var startPos = this.state.start; var startLoc = this.state.startLoc; var expr = this.parseExprSubscripts(refShorthandDefaultPos); if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr; while (this.state.type.postfix && !this.canInsertSemicolon()) { var _node = this.startNodeAt(startPos, startLoc); _node.operator = this.state.value; _node.prefix = false; _node.argument = expr; this.checkLVal(expr, undefined, undefined, "postfix operation"); this.next(); expr = this.finishNode(_node, "UpdateExpression"); } return expr; }; // Parse call, dot, and `[]`-subscript expressions. pp$3.parseExprSubscripts = function (refShorthandDefaultPos) { var startPos = this.state.start; var startLoc = this.state.startLoc; var potentialArrowAt = this.state.potentialArrowAt; var expr = this.parseExprAtom(refShorthandDefaultPos); if (expr.type === "ArrowFunctionExpression" && expr.start === potentialArrowAt) { return expr; } if (refShorthandDefaultPos && refShorthandDefaultPos.start) { return expr; } return this.parseSubscripts(expr, startPos, startLoc); }; pp$3.parseSubscripts = function (base, startPos, startLoc, noCalls) { for (;;) { if (!noCalls && this.eat(types.doubleColon)) { var node = this.startNodeAt(startPos, startLoc); node.object = base; node.callee = this.parseNoCallExpr(); return this.parseSubscripts(this.finishNode(node, "BindExpression"), startPos, startLoc, noCalls); } else if (this.eat(types.dot)) { var _node2 = this.startNodeAt(startPos, startLoc); _node2.object = base; _node2.property = this.parseIdentifier(true); _node2.computed = false; base = this.finishNode(_node2, "MemberExpression"); } else if (this.eat(types.bracketL)) { var _node3 = this.startNodeAt(startPos, startLoc); _node3.object = base; _node3.property = this.parseExpression(); _node3.computed = true; this.expect(types.bracketR); base = this.finishNode(_node3, "MemberExpression"); } else if (!noCalls && this.match(types.parenL)) { var possibleAsync = this.state.potentialArrowAt === base.start && base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon(); this.next(); var _node4 = this.startNodeAt(startPos, startLoc); _node4.callee = base; _node4.arguments = this.parseCallExpressionArguments(types.parenR, possibleAsync); if (_node4.callee.type === "Import" && _node4.arguments.length !== 1) { this.raise(_node4.start, "import() requires exactly one argument"); } base = this.finishNode(_node4, "CallExpression"); if (possibleAsync && this.shouldParseAsyncArrow()) { return this.parseAsyncArrowFromCallExpression(this.startNodeAt(startPos, startLoc), _node4); } else { this.toReferencedList(_node4.arguments); } } else if (this.match(types.backQuote)) { var _node5 = this.startNodeAt(startPos, startLoc); _node5.tag = base; _node5.quasi = this.parseTemplate(true); base = this.finishNode(_node5, "TaggedTemplateExpression"); } else { return base; } } }; pp$3.parseCallExpressionArguments = function (close, possibleAsyncArrow) { var elts = []; var innerParenStart = void 0; var first = true; while (!this.eat(close)) { if (first) { first = false; } else { this.expect(types.comma); if (this.eat(close)) break; } // we need to make sure that if this is an async arrow functions, that we don't allow inner parens inside the params if (this.match(types.parenL) && !innerParenStart) { innerParenStart = this.state.start; } elts.push(this.parseExprListItem(false, possibleAsyncArrow ? { start: 0 } : undefined, possibleAsyncArrow ? { start: 0 } : undefined)); } // we found an async arrow function so let's not allow any inner parens if (possibleAsyncArrow && innerParenStart && this.shouldParseAsyncArrow()) { this.unexpected(); } return elts; }; pp$3.shouldParseAsyncArrow = function () { return this.match(types.arrow); }; pp$3.parseAsyncArrowFromCallExpression = function (node, call) { this.expect(types.arrow); return this.parseArrowExpression(node, call.arguments, true); }; // Parse a no-call expression (like argument of `new` or `::` operators). pp$3.parseNoCallExpr = function () { var startPos = this.state.start; var startLoc = this.state.startLoc; return this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); }; // Parse an atomic expression — either a single token that is an // expression, an expression started by a keyword like `function` or // `new`, or an expression wrapped in punctuation like `()`, `[]`, // or `{}`. pp$3.parseExprAtom = function (refShorthandDefaultPos) { var canBeArrow = this.state.potentialArrowAt === this.state.start; var node = void 0; switch (this.state.type) { case types._super: if (!this.state.inMethod && !this.state.inClassProperty && !this.options.allowSuperOutsideMethod) { this.raise(this.state.start, "'super' outside of function or class"); } node = this.startNode(); this.next(); if (!this.match(types.parenL) && !this.match(types.bracketL) && !this.match(types.dot)) { this.unexpected(); } if (this.match(types.parenL) && this.state.inMethod !== "constructor" && !this.options.allowSuperOutsideMethod) { this.raise(node.start, "super() outside of class constructor"); } return this.finishNode(node, "Super"); case types._import: if (!this.hasPlugin("dynamicImport")) this.unexpected(); node = this.startNode(); this.next(); if (!this.match(types.parenL)) { this.unexpected(null, types.parenL); } return this.finishNode(node, "Import"); case types._this: node = this.startNode(); this.next(); return this.finishNode(node, "ThisExpression"); case types._yield: if (this.state.inGenerator) this.unexpected(); case types.name: node = this.startNode(); var allowAwait = this.state.value === "await" && this.state.inAsync; var allowYield = this.shouldAllowYieldIdentifier(); var id = this.parseIdentifier(allowAwait || allowYield); if (id.name === "await") { if (this.state.inAsync || this.inModule) { return this.parseAwait(node); } } else if (id.name === "async" && this.match(types._function) && !this.canInsertSemicolon()) { this.next(); return this.parseFunction(node, false, false, true); } else if (canBeArrow && id.name === "async" && this.match(types.name)) { var params = [this.parseIdentifier()]; this.expect(types.arrow); // let foo = bar => {}; return this.parseArrowExpression(node, params, true); } if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) { return this.parseArrowExpression(node, [id]); } return id; case types._do: if (this.hasPlugin("doExpressions")) { var _node6 = this.startNode(); this.next(); var oldInFunction = this.state.inFunction; var oldLabels = this.state.labels; this.state.labels = []; this.state.inFunction = false; _node6.body = this.parseBlock(false, true); this.state.inFunction = oldInFunction; this.state.labels = oldLabels; return this.finishNode(_node6, "DoExpression"); } case types.regexp: var value = this.state.value; node = this.parseLiteral(value.value, "RegExpLiteral"); node.pattern = value.pattern; node.flags = value.flags; return node; case types.num: return this.parseLiteral(this.state.value, "NumericLiteral"); case types.string: return this.parseLiteral(this.state.value, "StringLiteral"); case types._null: node = this.startNode(); this.next(); return this.finishNode(node, "NullLiteral"); case types._true:case types._false: node = this.startNode(); node.value = this.match(types._true); this.next(); return this.finishNode(node, "BooleanLiteral"); case types.parenL: return this.parseParenAndDistinguishExpression(null, null, canBeArrow); case types.bracketL: node = this.startNode(); this.next(); node.elements = this.parseExprList(types.bracketR, true, refShorthandDefaultPos); this.toReferencedList(node.elements); return this.finishNode(node, "ArrayExpression"); case types.braceL: return this.parseObj(false, refShorthandDefaultPos); case types._function: return this.parseFunctionExpression(); case types.at: this.parseDecorators(); case types._class: node = this.startNode(); this.takeDecorators(node); return this.parseClass(node, false); case types._new: return this.parseNew(); case types.backQuote: return this.parseTemplate(false); case types.doubleColon: node = this.startNode(); this.next(); node.object = null; var callee = node.callee = this.parseNoCallExpr(); if (callee.type === "MemberExpression") { return this.finishNode(node, "BindExpression"); } else { this.raise(callee.start, "Binding should be performed on object property."); } default: this.unexpected(); } }; pp$3.parseFunctionExpression = function () { var node = this.startNode(); var meta = this.parseIdentifier(true); if (this.state.inGenerator && this.eat(types.dot) && this.hasPlugin("functionSent")) { return this.parseMetaProperty(node, meta, "sent"); } else { return this.parseFunction(node, false); } }; pp$3.parseMetaProperty = function (node, meta, propertyName) { node.meta = meta; node.property = this.parseIdentifier(true); if (node.property.name !== propertyName) { this.raise(node.property.start, "The only valid meta property for new is " + meta.name + "." + propertyName); } return this.finishNode(node, "MetaProperty"); }; pp$3.parseLiteral = function (value, type, startPos, startLoc) { startPos = startPos || this.state.start; startLoc = startLoc || this.state.startLoc; var node = this.startNodeAt(startPos, startLoc); this.addExtra(node, "rawValue", value); this.addExtra(node, "raw", this.input.slice(startPos, this.state.end)); node.value = value; this.next(); return this.finishNode(node, type); }; pp$3.parseParenExpression = function () { this.expect(types.parenL); var val = this.parseExpression(); this.expect(types.parenR); return val; }; pp$3.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow) { startPos = startPos || this.state.start; startLoc = startLoc || this.state.startLoc; var val = void 0; this.expect(types.parenL); var innerStartPos = this.state.start; var innerStartLoc = this.state.startLoc; var exprList = []; var refShorthandDefaultPos = { start: 0 }; var refNeedsArrowPos = { start: 0 }; var first = true; var spreadStart = void 0; var optionalCommaStart = void 0; while (!this.match(types.parenR)) { if (first) { first = false; } else { this.expect(types.comma, refNeedsArrowPos.start || null); if (this.match(types.parenR)) { optionalCommaStart = this.state.start; break; } } if (this.match(types.ellipsis)) { var spreadNodeStartPos = this.state.start; var spreadNodeStartLoc = this.state.startLoc; spreadStart = this.state.start; exprList.push(this.parseParenItem(this.parseRest(), spreadNodeStartPos, spreadNodeStartLoc)); break; } else { exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem, refNeedsArrowPos)); } } var innerEndPos = this.state.start; var innerEndLoc = this.state.startLoc; this.expect(types.parenR); var arrowNode = this.startNodeAt(startPos, startLoc); if (canBeArrow && this.shouldParseArrow() && (arrowNode = this.parseArrow(arrowNode))) { for (var _iterator = exprList, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { var _ref; if (_isArray) { if (_i >= _iterator.length) break; _ref = _iterator[_i++]; } else { _i = _iterator.next(); if (_i.done) break; _ref = _i.value; } var param = _ref; if (param.extra && param.extra.parenthesized) this.unexpected(param.extra.parenStart); } return this.parseArrowExpression(arrowNode, exprList); } if (!exprList.length) { this.unexpected(this.state.lastTokStart); } if (optionalCommaStart) this.unexpected(optionalCommaStart); if (spreadStart) this.unexpected(spreadStart); if (refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start); if (refNeedsArrowPos.start) this.unexpected(refNeedsArrowPos.start); if (exprList.length > 1) { val = this.startNodeAt(innerStartPos, innerStartLoc); val.expressions = exprList; this.toReferencedList(val.expressions); this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); } else { val = exprList[0]; } this.addExtra(val, "parenthesized", true); this.addExtra(val, "parenStart", startPos); return val; }; pp$3.shouldParseArrow = function () { return !this.canInsertSemicolon(); }; pp$3.parseArrow = function (node) { if (this.eat(types.arrow)) { return node; } }; pp$3.parseParenItem = function (node) { return node; }; // New's precedence is slightly tricky. It must allow its argument // to be a `[]` or dot subscript expression, but not a call — at // least, not without wrapping it in parentheses. Thus, it uses the pp$3.parseNew = function () { var node = this.startNode(); var meta = this.parseIdentifier(true); if (this.eat(types.dot)) { var metaProp = this.parseMetaProperty(node, meta, "target"); if (!this.state.inFunction) { this.raise(metaProp.property.start, "new.target can only be used in functions"); } return metaProp; } node.callee = this.parseNoCallExpr(); if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR); this.toReferencedList(node.arguments); } else { node.arguments = []; } return this.finishNode(node, "NewExpression"); }; // Parse template expression. pp$3.parseTemplateElement = function (isTagged) { var elem = this.startNode(); if (this.state.value === null) { if (!isTagged || !this.hasPlugin("templateInvalidEscapes")) { this.raise(this.state.invalidTemplateEscapePosition, "Invalid escape sequence in template"); } else { this.state.invalidTemplateEscapePosition = null; } } elem.value = { raw: this.input.slice(this.state.start, this.state.end).replace(/\r\n?/g, "\n"), cooked: this.state.value }; this.next(); elem.tail = this.match(types.backQuote); return this.finishNode(elem, "TemplateElement"); }; pp$3.parseTemplate = function (isTagged) { var node = this.startNode(); this.next(); node.expressions = []; var curElt = this.parseTemplateElement(isTagged); node.quasis = [curElt]; while (!curElt.tail) { this.expect(types.dollarBraceL); node.expressions.push(this.parseExpression()); this.expect(types.braceR); node.quasis.push(curElt = this.parseTemplateElement(isTagged)); } this.next(); return this.finishNode(node, "TemplateLiteral"); }; // Parse an object literal or binding pattern. pp$3.parseObj = function (isPattern, refShorthandDefaultPos) { var decorators = []; var propHash = Object.create(null); var first = true; var node = this.startNode(); node.properties = []; this.next(); var firstRestLocation = null; while (!this.eat(types.braceR)) { if (first) { first = false; } else { this.expect(types.comma); if (this.eat(types.braceR)) break; } while (this.match(types.at)) { decorators.push(this.parseDecorator()); } var prop = this.startNode(), isGenerator = false, isAsync = false, startPos = void 0, startLoc = void 0; if (decorators.length) { prop.decorators = decorators; decorators = []; } if (this.hasPlugin("objectRestSpread") && this.match(types.ellipsis)) { prop = this.parseSpread(isPattern ? { start: 0 } : undefined); prop.type = isPattern ? "RestProperty" : "SpreadProperty"; if (isPattern) this.toAssignable(prop.argument, true, "object pattern"); node.properties.push(prop); if (isPattern) { var position = this.state.start; if (firstRestLocation !== null) { this.unexpected(firstRestLocation, "Cannot have multiple rest elements when destructuring"); } else if (this.eat(types.braceR)) { break; } else if (this.match(types.comma) && this.lookahead().type === types.braceR) { // TODO: temporary rollback // this.unexpected(position, "A trailing comma is not permitted after the rest element"); continue; } else { firstRestLocation = position; continue; } } else { continue; } } prop.method = false; prop.shorthand = false; if (isPattern || refShorthandDefaultPos) { startPos = this.state.start; startLoc = this.state.startLoc; } if (!isPattern) { isGenerator = this.eat(types.star); } if (!isPattern && this.isContextual("async")) { if (isGenerator) this.unexpected(); var asyncId = this.parseIdentifier(); if (this.match(types.colon) || this.match(types.parenL) || this.match(types.braceR) || this.match(types.eq) || this.match(types.comma)) { prop.key = asyncId; prop.computed = false; } else { isAsync = true; if (this.hasPlugin("asyncGenerators")) isGenerator = this.eat(types.star); this.parsePropertyName(prop); } } else { this.parsePropertyName(prop); } this.parseObjPropValue(prop, startPos, startLoc, isGenerator, isAsync, isPattern, refShorthandDefaultPos); this.checkPropClash(prop, propHash); if (prop.shorthand) { this.addExtra(prop, "shorthand", true); } node.properties.push(prop); } if (firstRestLocation !== null) { this.unexpected(firstRestLocation, "The rest element has to be the last element when destructuring"); } if (decorators.length) { this.raise(this.state.start, "You have trailing decorators with no property"); } return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression"); }; pp$3.isGetterOrSetterMethod = function (prop, isPattern) { return !isPattern && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && (this.match(types.string) || // get "string"() {} this.match(types.num) || // get 1() {} this.match(types.bracketL) || // get ["string"]() {} this.match(types.name) || // get foo() {} this.state.type.keyword // get debugger() {} ); }; // get methods aren't allowed to have any parameters // set methods must have exactly 1 parameter pp$3.checkGetterSetterParamCount = function (method) { var paramCount = method.kind === "get" ? 0 : 1; if (method.params.length !== paramCount) { var start = method.start; if (method.kind === "get") { this.raise(start, "getter should have no params"); } else { this.raise(start, "setter should have exactly one param"); } } }; pp$3.parseObjectMethod = function (prop, isGenerator, isAsync, isPattern) { if (isAsync || isGenerator || this.match(types.parenL)) { if (isPattern) this.unexpected(); prop.kind = "method"; prop.method = true; this.parseMethod(prop, isGenerator, isAsync); return this.finishNode(prop, "ObjectMethod"); } if (this.isGetterOrSetterMethod(prop, isPattern)) { if (isGenerator || isAsync) this.unexpected(); prop.kind = prop.key.name; this.parsePropertyName(prop); this.parseMethod(prop); this.checkGetterSetterParamCount(prop); return this.finishNode(prop, "ObjectMethod"); } }; pp$3.parseObjectProperty = function (prop, startPos, startLoc, isPattern, refShorthandDefaultPos) { if (this.eat(types.colon)) { prop.value = isPattern ? this.parseMaybeDefault(this.state.start, this.state.startLoc) : this.parseMaybeAssign(false, refShorthandDefaultPos); return this.finishNode(prop, "ObjectProperty"); } if (!prop.computed && prop.key.type === "Identifier") { this.checkReservedWord(prop.key.name, prop.key.start, true, true); if (isPattern) { prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone()); } else if (this.match(types.eq) && refShorthandDefaultPos) { if (!refShorthandDefaultPos.start) { refShorthandDefaultPos.start = this.state.start; } prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone()); } else { prop.value = prop.key.__clone(); } prop.shorthand = true; return this.finishNode(prop, "ObjectProperty"); } }; pp$3.parseObjPropValue = function (prop, startPos, startLoc, isGenerator, isAsync, isPattern, refShorthandDefaultPos) { var node = this.parseObjectMethod(prop, isGenerator, isAsync, isPattern) || this.parseObjectProperty(prop, startPos, startLoc, isPattern, refShorthandDefaultPos); if (!node) this.unexpected(); return node; }; pp$3.parsePropertyName = function (prop) { if (this.eat(types.bracketL)) { prop.computed = true; prop.key = this.parseMaybeAssign(); this.expect(types.bracketR); } else { prop.computed = false; var oldInPropertyName = this.state.inPropertyName; this.state.inPropertyName = true; prop.key = this.match(types.num) || this.match(types.string) ? this.parseExprAtom() : this.parseIdentifier(true); this.state.inPropertyName = oldInPropertyName; } return prop.key; }; // Initialize empty function node. pp$3.initFunction = function (node, isAsync) { node.id = null; node.generator = false; node.expression = false; node.async = !!isAsync; }; // Parse object or class method. pp$3.parseMethod = function (node, isGenerator, isAsync) { var oldInMethod = this.state.inMethod; this.state.inMethod = node.kind || true; this.initFunction(node, isAsync); this.expect(types.parenL); node.params = this.parseBindingList(types.parenR); node.generator = !!isGenerator; this.parseFunctionBody(node); this.state.inMethod = oldInMethod; return node; }; // Parse arrow function expression with given parameters. pp$3.parseArrowExpression = function (node, params, isAsync) { this.initFunction(node, isAsync); node.params = this.toAssignableList(params, true, "arrow function parameters"); this.parseFunctionBody(node, true); return this.finishNode(node, "ArrowFunctionExpression"); }; pp$3.isStrictBody = function (node, isExpression) { if (!isExpression && node.body.directives.length) { for (var _iterator2 = node.body.directives, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { var _ref2; if (_isArray2) { if (_i2 >= _iterator2.length) break; _ref2 = _iterator2[_i2++]; } else { _i2 = _iterator2.next(); if (_i2.done) break; _ref2 = _i2.value; } var directive = _ref2; if (directive.value.value === "use strict") { return true; } } } return false; }; // Parse function body and check parameters. pp$3.parseFunctionBody = function (node, allowExpression) { var isExpression = allowExpression && !this.match(types.braceL); var oldInAsync = this.state.inAsync; this.state.inAsync = node.async; if (isExpression) { node.body = this.parseMaybeAssign(); node.expression = true; } else { // Start a new scope with regard to labels and the `inFunction` // flag (restore them to their old value afterwards). var oldInFunc = this.state.inFunction; var oldInGen = this.state.inGenerator; var oldLabels = this.state.labels; this.state.inFunction = true;this.state.inGenerator = node.generator;this.state.labels = []; node.body = this.parseBlock(true); node.expression = false; this.state.inFunction = oldInFunc;this.state.inGenerator = oldInGen;this.state.labels = oldLabels; } this.state.inAsync = oldInAsync; // If this is a strict mode function, verify that argument names // are not repeated, and it does not try to bind the words `eval` // or `arguments`. var isStrict = this.isStrictBody(node, isExpression); // Also check when allowExpression === true for arrow functions var checkLVal = this.state.strict || allowExpression || isStrict; if (isStrict && node.id && node.id.type === "Identifier" && node.id.name === "yield") { this.raise(node.id.start, "Binding yield in strict mode"); } if (checkLVal) { var nameHash = Object.create(null); var oldStrict = this.state.strict; if (isStrict) this.state.strict = true; if (node.id) { this.checkLVal(node.id, true, undefined, "function name"); } for (var _iterator3 = node.params, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { var _ref3; if (_isArray3) { if (_i3 >= _iterator3.length) break; _ref3 = _iterator3[_i3++]; } else { _i3 = _iterator3.next(); if (_i3.done) break; _ref3 = _i3.value; } var param = _ref3; if (isStrict && param.type !== "Identifier") { this.raise(param.start, "Non-simple parameter in strict mode"); } this.checkLVal(param, true, nameHash, "function parameter list"); } this.state.strict = oldStrict; } }; // Parses a comma-separated list of expressions, and returns them as // an array. `close` is the token type that ends the list, and // `allowEmpty` can be turned on to allow subsequent commas with // nothing in between them to be parsed as `null` (which is needed // for array literals). pp$3.parseExprList = function (close, allowEmpty, refShorthandDefaultPos) { var elts = []; var first = true; while (!this.eat(close)) { if (first) { first = false; } else { this.expect(types.comma); if (this.eat(close)) break; } elts.push(this.parseExprListItem(allowEmpty, refShorthandDefaultPos)); } return elts; }; pp$3.parseExprListItem = function (allowEmpty, refShorthandDefaultPos, refNeedsArrowPos) { var elt = void 0; if (allowEmpty && this.match(types.comma)) { elt = null; } else if (this.match(types.ellipsis)) { elt = this.parseSpread(refShorthandDefaultPos); } else { elt = this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem, refNeedsArrowPos); } return elt; }; // Parse the next token as an identifier. If `liberal` is true (used // when parsing properties), it will also convert keywords into // identifiers. pp$3.parseIdentifier = function (liberal) { var node = this.startNode(); if (!liberal) { this.checkReservedWord(this.state.value, this.state.start, !!this.state.type.keyword, false); } if (this.match(types.name)) { node.name = this.state.value; } else if (this.state.type.keyword) { node.name = this.state.type.keyword; } else { this.unexpected(); } if (!liberal && node.name === "await" && this.state.inAsync) { this.raise(node.start, "invalid use of await inside of an async function"); } node.loc.identifierName = node.name; this.next(); return this.finishNode(node, "Identifier"); }; pp$3.checkReservedWord = function (word, startLoc, checkKeywords, isBinding) { if (this.isReservedWord(word) || checkKeywords && this.isKeyword(word)) { this.raise(startLoc, word + " is a reserved word"); } if (this.state.strict && (reservedWords.strict(word) || isBinding && reservedWords.strictBind(word))) { this.raise(startLoc, word + " is a reserved word in strict mode"); } }; // Parses await expression inside async function. pp$3.parseAwait = function (node) { // istanbul ignore next: this condition is checked at the call site so won't be hit here if (!this.state.inAsync) { this.unexpected(); } if (this.match(types.star)) { this.raise(node.start, "await* has been removed from the async functions proposal. Use Promise.all() instead."); } node.argument = this.parseMaybeUnary(); return this.finishNode(node, "AwaitExpression"); }; // Parses yield expression inside generator. pp$3.parseYield = function () { var node = this.startNode(); this.next(); if (this.match(types.semi) || this.canInsertSemicolon() || !this.match(types.star) && !this.state.type.startsExpr) { node.delegate = false; node.argument = null; } else { node.delegate = this.eat(types.star); node.argument = this.parseMaybeAssign(); } return this.finishNode(node, "YieldExpression"); }; // Start an AST node, attaching a start offset. var pp$4 = Parser.prototype; var commentKeys = ["leadingComments", "trailingComments", "innerComments"]; var Node = function () { function Node(pos, loc, filename) { classCallCheck(this, Node); this.type = ""; this.start = pos; this.end = 0; this.loc = new SourceLocation(loc); if (filename) this.loc.filename = filename; } Node.prototype.__clone = function __clone() { var node2 = new Node(); for (var key in this) { // Do not clone comments that are already attached to the node if (commentKeys.indexOf(key) < 0) { node2[key] = this[key]; } } return node2; }; return Node; }(); pp$4.startNode = function () { return new Node(this.state.start, this.state.startLoc, this.filename); }; pp$4.startNodeAt = function (pos, loc) { return new Node(pos, loc, this.filename); }; function finishNodeAt(node, type, pos, loc) { node.type = type; node.end = pos; node.loc.end = loc; this.processComment(node); return node; } // Finish an AST node, adding `type` and `end` properties. pp$4.finishNode = function (node, type) { return finishNodeAt.call(this, node, type, this.state.lastTokEnd, this.state.lastTokEndLoc); }; // Finish node at given position pp$4.finishNodeAt = function (node, type, pos, loc) { return finishNodeAt.call(this, node, type, pos, loc); }; var pp$5 = Parser.prototype; // This function is used to raise exceptions on parse errors. It // takes an offset integer (into the current `input`) to indicate // the location of the error, attaches the position to the end // of the error message, and then raises a `SyntaxError` with that // message. pp$5.raise = function (pos, message) { var loc = getLineInfo(this.input, pos); message += " (" + loc.line + ":" + loc.column + ")"; var err = new SyntaxError(message); err.pos = pos; err.loc = loc; throw err; }; /* eslint max-len: 0 */ /** * Based on the comment attachment algorithm used in espree and estraverse. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ function last(stack) { return stack[stack.length - 1]; } var pp$6 = Parser.prototype; pp$6.addComment = function (comment) { if (this.filename) comment.loc.filename = this.filename; this.state.trailingComments.push(comment); this.state.leadingComments.push(comment); }; pp$6.processComment = function (node) { if (node.type === "Program" && node.body.length > 0) return; var stack = this.state.commentStack; var firstChild = void 0, lastChild = void 0, trailingComments = void 0, i = void 0, j = void 0; if (this.state.trailingComments.length > 0) { // If the first comment in trailingComments comes after the // current node, then we're good - all comments in the array will // come after the node and so it's safe to add them as official // trailingComments. if (this.state.trailingComments[0].start >= node.end) { trailingComments = this.state.trailingComments; this.state.trailingComments = []; } else { // Otherwise, if the first comment doesn't come after the // current node, that means we have a mix of leading and trailing // comments in the array and that leadingComments contains the // same items as trailingComments. Reset trailingComments to // zero items and we'll handle this by evaluating leadingComments // later. this.state.trailingComments.length = 0; } } else { var lastInStack = last(stack); if (stack.length > 0 && lastInStack.trailingComments && lastInStack.trailingComments[0].start >= node.end) { trailingComments = lastInStack.trailingComments; lastInStack.trailingComments = null; } } // Eating the stack. if (stack.length > 0 && last(stack).start >= node.start) { firstChild = stack.pop(); } while (stack.length > 0 && last(stack).start >= node.start) { lastChild = stack.pop(); } if (!lastChild && firstChild) lastChild = firstChild; // Attach comments that follow a trailing comma on the last // property in an object literal or a trailing comma in function arguments // as trailing comments if (firstChild && this.state.leadingComments.length > 0) { var lastComment = last(this.state.leadingComments); if (firstChild.type === "ObjectProperty") { if (lastComment.start >= node.start) { if (this.state.commentPreviousNode) { for (j = 0; j < this.state.leadingComments.length; j++) { if (this.state.leadingComments[j].end < this.state.commentPreviousNode.end) { this.state.leadingComments.splice(j, 1); j--; } } if (this.state.leadingComments.length > 0) { firstChild.trailingComments = this.state.leadingComments; this.state.leadingComments = []; } } } } else if (node.type === "CallExpression" && node.arguments && node.arguments.length) { var lastArg = last(node.arguments); if (lastArg && lastComment.start >= lastArg.start && lastComment.end <= node.end) { if (this.state.commentPreviousNode) { if (this.state.leadingComments.length > 0) { lastArg.trailingComments = this.state.leadingComments; this.state.leadingComments = []; } } } } } if (lastChild) { if (lastChild.leadingComments) { if (lastChild !== node && last(lastChild.leadingComments).end <= node.start) { node.leadingComments = lastChild.leadingComments; lastChild.leadingComments = null; } else { // A leading comment for an anonymous class had been stolen by its first ClassMethod, // so this takes back the leading comment. // See also: https://github.com/eslint/espree/issues/158 for (i = lastChild.leadingComments.length - 2; i >= 0; --i) { if (lastChild.leadingComments[i].end <= node.start) { node.leadingComments = lastChild.leadingComments.splice(0, i + 1); break; } } } } } else if (this.state.leadingComments.length > 0) { if (last(this.state.leadingComments).end <= node.start) { if (this.state.commentPreviousNode) { for (j = 0; j < this.state.leadingComments.length; j++) { if (this.state.leadingComments[j].end < this.state.commentPreviousNode.end) { this.state.leadingComments.splice(j, 1); j--; } } } if (this.state.leadingComments.length > 0) { node.leadingComments = this.state.leadingComments; this.state.leadingComments = []; } } else { // https://github.com/eslint/espree/issues/2 // // In special cases, such as return (without a value) and // debugger, all comments will end up as leadingComments and // will otherwise be eliminated. This step runs when the // commentStack is empty and there are comments left // in leadingComments. // // This loop figures out the stopping point between the actual // leading and trailing comments by finding the location of the // first comment that comes after the given node. for (i = 0; i < this.state.leadingComments.length; i++) { if (this.state.leadingComments[i].end > node.start) { break; } } // Split the array based on the location of the first comment // that comes after the node. Keep in mind that this could // result in an empty array, and if so, the array must be // deleted. node.leadingComments = this.state.leadingComments.slice(0, i); if (node.leadingComments.length === 0) { node.leadingComments = null; } // Similarly, trailing comments are attached later. The variable // must be reset to null if there are no trailing comments. trailingComments = this.state.leadingComments.slice(i); if (trailingComments.length === 0) { trailingComments = null; } } } this.state.commentPreviousNode = node; if (trailingComments) { if (trailingComments.length && trailingComments[0].start >= node.start && last(trailingComments).end <= node.end) { node.innerComments = trailingComments; } else { node.trailingComments = trailingComments; } } stack.push(node); }; var pp$7 = Parser.prototype; pp$7.estreeParseRegExpLiteral = function (_ref) { var pattern = _ref.pattern, flags = _ref.flags; var regex = null; try { regex = new RegExp(pattern, flags); } catch (e) { // In environments that don't support these flags value will // be null as the regex can't be represented natively. } var node = this.estreeParseLiteral(regex); node.regex = { pattern: pattern, flags: flags }; return node; }; pp$7.estreeParseLiteral = function (value) { return this.parseLiteral(value, "Literal"); }; pp$7.directiveToStmt = function (directive) { var directiveLiteral = directive.value; var stmt = this.startNodeAt(directive.start, directive.loc.start); var expression = this.startNodeAt(directiveLiteral.start, directiveLiteral.loc.start); expression.value = directiveLiteral.value; expression.raw = directiveLiteral.extra.raw; stmt.expression = this.finishNodeAt(expression, "Literal", directiveLiteral.end, directiveLiteral.loc.end); stmt.directive = directiveLiteral.extra.raw.slice(1, -1); return this.finishNodeAt(stmt, "ExpressionStatement", directive.end, directive.loc.end); }; function isSimpleProperty(node) { return node && node.type === "Property" && node.kind === "init" && node.method === false; } var estreePlugin = function (instance) { instance.extend("checkDeclaration", function (inner) { return function (node) { if (isSimpleProperty(node)) { this.checkDeclaration(node.value); } else { inner.call(this, node); } }; }); instance.extend("checkGetterSetterParamCount", function () { return function (prop) { var paramCount = prop.kind === "get" ? 0 : 1; if (prop.value.params.length !== paramCount) { var start = prop.start; if (prop.kind === "get") { this.raise(start, "getter should have no params"); } else { this.raise(start, "setter should have exactly one param"); } } }; }); instance.extend("checkLVal", function (inner) { return function (expr, isBinding, checkClashes) { var _this = this; switch (expr.type) { case "ObjectPattern": expr.properties.forEach(function (prop) { _this.checkLVal(prop.type === "Property" ? prop.value : prop, isBinding, checkClashes, "object destructuring pattern"); }); break; default: for (var _len = arguments.length, args = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) { args[_key - 3] = arguments[_key]; } inner.call.apply(inner, [this, expr, isBinding, checkClashes].concat(args)); } }; }); instance.extend("checkPropClash", function () { return function (prop, propHash) { if (prop.computed || !isSimpleProperty(prop)) return; var key = prop.key; // It is either an Identifier or a String/NumericLiteral var name = key.type === "Identifier" ? key.name : String(key.value); if (name === "__proto__") { if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property"); propHash.proto = true; } }; }); instance.extend("isStrictBody", function () { return function (node, isExpression) { if (!isExpression && node.body.body.length > 0) { for (var _iterator = node.body.body, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { var _ref2; if (_isArray) { if (_i >= _iterator.length) break; _ref2 = _iterator[_i++]; } else { _i = _iterator.next(); if (_i.done) break; _ref2 = _i.value; } var directive = _ref2; if (directive.type === "ExpressionStatement" && directive.expression.type === "Literal") { if (directive.expression.value === "use strict") return true; } else { // Break for the first non literal expression break; } } } return false; }; }); instance.extend("isValidDirective", function () { return function (stmt) { return stmt.type === "ExpressionStatement" && stmt.expression.type === "Literal" && typeof stmt.expression.value === "string" && (!stmt.expression.extra || !stmt.expression.extra.parenthesized); }; }); instance.extend("stmtToDirective", function (inner) { return function (stmt) { var directive = inner.call(this, stmt); var value = stmt.expression.value; // Reset value to the actual value as in estree mode we want // the stmt to have the real value and not the raw value directive.value.value = value; return directive; }; }); instance.extend("parseBlockBody", function (inner) { return function (node) { var _this2 = this; for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } inner.call.apply(inner, [this, node].concat(args)); node.directives.reverse().forEach(function (directive) { node.body.unshift(_this2.directiveToStmt(directive)); }); delete node.directives; }; }); instance.extend("parseClassMethod", function () { return function (classBody, method, isGenerator, isAsync) { this.parseMethod(method, isGenerator, isAsync); if (method.typeParameters) { method.value.typeParameters = method.typeParameters; delete method.typeParameters; } classBody.body.push(this.finishNode(method, "MethodDefinition")); }; }); instance.extend("parseExprAtom", function (inner) { return function () { switch (this.state.type) { case types.regexp: return this.estreeParseRegExpLiteral(this.state.value); case types.num: case types.string: return this.estreeParseLiteral(this.state.value); case types._null: return this.estreeParseLiteral(null); case types._true: return this.estreeParseLiteral(true); case types._false: return this.estreeParseLiteral(false); default: for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } return inner.call.apply(inner, [this].concat(args)); } }; }); instance.extend("parseLiteral", function (inner) { return function () { for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } var node = inner.call.apply(inner, [this].concat(args)); node.raw = node.extra.raw; delete node.extra; return node; }; }); instance.extend("parseMethod", function (inner) { return function (node) { var funcNode = this.startNode(); funcNode.kind = node.kind; // provide kind, so inner method correctly sets state for (var _len5 = arguments.length, args = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) { args[_key5 - 1] = arguments[_key5]; } funcNode = inner.call.apply(inner, [this, funcNode].concat(args)); delete funcNode.kind; node.value = this.finishNode(funcNode, "FunctionExpression"); return node; }; }); instance.extend("parseObjectMethod", function (inner) { return function () { for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) { args[_key6] = arguments[_key6]; } var node = inner.call.apply(inner, [this].concat(args)); if (node) { if (node.kind === "method") node.kind = "init"; node.type = "Property"; } return node; }; }); instance.extend("parseObjectProperty", function (inner) { return function () { for (var _len7 = arguments.length, args = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) { args[_key7] = arguments[_key7]; } var node = inner.call.apply(inner, [this].concat(args)); if (node) { node.kind = "init"; node.type = "Property"; } return node; }; }); instance.extend("toAssignable", function (inner) { return function (node, isBinding) { for (var _len8 = arguments.length, args = Array(_len8 > 2 ? _len8 - 2 : 0), _key8 = 2; _key8 < _len8; _key8++) { args[_key8 - 2] = arguments[_key8]; } if (isSimpleProperty(node)) { this.toAssignable.apply(this, [node.value, isBinding].concat(args)); return node; } else if (node.type === "ObjectExpression") { node.type = "ObjectPattern"; for (var _iterator2 = node.properties, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { var _ref3; if (_isArray2) { if (_i2 >= _iterator2.length) break; _ref3 = _iterator2[_i2++]; } else { _i2 = _iterator2.next(); if (_i2.done) break; _ref3 = _i2.value; } var prop = _ref3; if (prop.kind === "get" || prop.kind === "set") { this.raise(prop.key.start, "Object pattern can't contain getter or setter"); } else if (prop.method) { this.raise(prop.key.start, "Object pattern can't contain methods"); } else { this.toAssignable(prop, isBinding, "object destructuring pattern"); } } return node; } return inner.call.apply(inner, [this, node, isBinding].concat(args)); }; }); }; /* eslint max-len: 0 */ var primitiveTypes = ["any", "mixed", "empty", "bool", "boolean", "number", "string", "void", "null"]; var pp$8 = Parser.prototype; pp$8.flowParseTypeInitialiser = function (tok) { var oldInType = this.state.inType; this.state.inType = true; this.expect(tok || types.colon); var type = this.flowParseType(); this.state.inType = oldInType; return type; }; pp$8.flowParsePredicate = function () { var node = this.startNode(); var moduloLoc = this.state.startLoc; var moduloPos = this.state.start; this.expect(types.modulo); var checksLoc = this.state.startLoc; this.expectContextual("checks"); // Force '%' and 'checks' to be adjacent if (moduloLoc.line !== checksLoc.line || moduloLoc.column !== checksLoc.column - 1) { this.raise(moduloPos, "Spaces between ´%´ and ´checks´ are not allowed here."); } if (this.eat(types.parenL)) { node.expression = this.parseExpression(); this.expect(types.parenR); return this.finishNode(node, "DeclaredPredicate"); } else { return this.finishNode(node, "InferredPredicate"); } }; pp$8.flowParseTypeAndPredicateInitialiser = function () { var oldInType = this.state.inType; this.state.inType = true; this.expect(types.colon); var type = null; var predicate = null; if (this.match(types.modulo)) { this.state.inType = oldInType; predicate = this.flowParsePredicate(); } else { type = this.flowParseType(); this.state.inType = oldInType; if (this.match(types.modulo)) { predicate = this.flowParsePredicate(); } } return [type, predicate]; }; pp$8.flowParseDeclareClass = function (node) { this.next(); this.flowParseInterfaceish(node, true); return this.finishNode(node, "DeclareClass"); }; pp$8.flowParseDeclareFunction = function (node) { this.next(); var id = node.id = this.parseIdentifier(); var typeNode = this.startNode(); var typeContainer = this.startNode(); if (this.isRelational("<")) { typeNode.typeParameters = this.flowParseTypeParameterDeclaration(); } else { typeNode.typeParameters = null; } this.expect(types.parenL); var tmp = this.flowParseFunctionTypeParams(); typeNode.params = tmp.params; typeNode.rest = tmp.rest; this.expect(types.parenR); var predicate = null; var _flowParseTypeAndPred = this.flowParseTypeAndPredicateInitialiser(); typeNode.returnType = _flowParseTypeAndPred[0]; predicate = _flowParseTypeAndPred[1]; typeContainer.typeAnnotation = this.finishNode(typeNode, "FunctionTypeAnnotation"); typeContainer.predicate = predicate; id.typeAnnotation = this.finishNode(typeContainer, "TypeAnnotation"); this.finishNode(id, id.type); this.semicolon(); return this.finishNode(node, "DeclareFunction"); }; pp$8.flowParseDeclare = function (node) { if (this.match(types._class)) { return this.flowParseDeclareClass(node); } else if (this.match(types._function)) { return this.flowParseDeclareFunction(node); } else if (this.match(types._var)) { return this.flowParseDeclareVariable(node); } else if (this.isContextual("module")) { if (this.lookahead().type === types.dot) { return this.flowParseDeclareModuleExports(node); } else { return this.flowParseDeclareModule(node); } } else if (this.isContextual("type")) { return this.flowParseDeclareTypeAlias(node); } else if (this.isContextual("opaque")) { return this.flowParseDeclareOpaqueType(node); } else if (this.isContextual("interface")) { return this.flowParseDeclareInterface(node); } else if (this.match(types._export)) { return this.flowParseDeclareExportDeclaration(node); } else { this.unexpected(); } }; pp$8.flowParseDeclareExportDeclaration = function (node) { this.expect(types._export); if (this.isContextual("opaque") // declare export opaque ... ) { node.declaration = this.flowParseDeclare(this.startNode()); node.default = false; return this.finishNode(node, "DeclareExportDeclaration"); } throw this.unexpected(); }; pp$8.flowParseDeclareVariable = function (node) { this.next(); node.id = this.flowParseTypeAnnotatableIdentifier(); this.semicolon(); return this.finishNode(node, "DeclareVariable"); }; pp$8.flowParseDeclareModule = function (node) { this.next(); if (this.match(types.string)) { node.id = this.parseExprAtom(); } else { node.id = this.parseIdentifier(); } var bodyNode = node.body = this.startNode(); var body = bodyNode.body = []; this.expect(types.braceL); while (!this.match(types.braceR)) { var _bodyNode = this.startNode(); if (this.match(types._import)) { var lookahead = this.lookahead(); if (lookahead.value !== "type" && lookahead.value !== "typeof") { this.unexpected(null, "Imports within a `declare module` body must always be `import type` or `import typeof`"); } this.parseImport(_bodyNode); } else { this.expectContextual("declare", "Only declares and type imports are allowed inside declare module"); _bodyNode = this.flowParseDeclare(_bodyNode, true); } body.push(_bodyNode); } this.expect(types.braceR); this.finishNode(bodyNode, "BlockStatement"); return this.finishNode(node, "DeclareModule"); }; pp$8.flowParseDeclareModuleExports = function (node) { this.expectContextual("module"); this.expect(types.dot); this.expectContextual("exports"); node.typeAnnotation = this.flowParseTypeAnnotation(); this.semicolon(); return this.finishNode(node, "DeclareModuleExports"); }; pp$8.flowParseDeclareTypeAlias = function (node) { this.next(); this.flowParseTypeAlias(node); return this.finishNode(node, "DeclareTypeAlias"); }; pp$8.flowParseDeclareOpaqueType = function (node) { this.next(); this.flowParseOpaqueType(node, true); return this.finishNode(node, "DeclareOpaqueType"); }; pp$8.flowParseDeclareInterface = function (node) { this.next(); this.flowParseInterfaceish(node); return this.finishNode(node, "DeclareInterface"); }; // Interfaces pp$8.flowParseInterfaceish = function (node) { node.id = this.parseIdentifier(); if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterDeclaration(); } else { node.typeParameters = null; } node.extends = []; node.mixins = []; if (this.eat(types._extends)) { do { node.extends.push(this.flowParseInterfaceExtends()); } while (this.eat(types.comma)); } if (this.isContextual("mixins")) { this.next(); do { node.mixins.push(this.flowParseInterfaceExtends()); } while (this.eat(types.comma)); } node.body = this.flowParseObjectType(true, false, false); }; pp$8.flowParseInterfaceExtends = function () { var node = this.startNode(); node.id = this.flowParseQualifiedTypeIdentifier(); if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterInstantiation(); } else { node.typeParameters = null; } return this.finishNode(node, "InterfaceExtends"); }; pp$8.flowParseInterface = function (node) { this.flowParseInterfaceish(node, false); return this.finishNode(node, "InterfaceDeclaration"); }; pp$8.flowParseRestrictedIdentifier = function (liberal) { if (primitiveTypes.indexOf(this.state.value) > -1) { this.raise(this.state.start, "Cannot overwrite primitive type " + this.state.value); } return this.parseIdentifier(liberal); }; // Type aliases pp$8.flowParseTypeAlias = function (node) { node.id = this.flowParseRestrictedIdentifier(); if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterDeclaration(); } else { node.typeParameters = null; } node.right = this.flowParseTypeInitialiser(types.eq); this.semicolon(); return this.finishNode(node, "TypeAlias"); }; // Opaque type aliases pp$8.flowParseOpaqueType = function (node, declare) { this.expectContextual("type"); node.id = this.flowParseRestrictedIdentifier(); if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterDeclaration(); } else { node.typeParameters = null; } // Parse the supertype node.supertype = null; if (this.match(types.colon)) { node.supertype = this.flowParseTypeInitialiser(types.colon); } node.impltype = null; if (!declare) { node.impltype = this.flowParseTypeInitialiser(types.eq); } this.semicolon(); return this.finishNode(node, "OpaqueType"); }; // Type annotations pp$8.flowParseTypeParameter = function () { var node = this.startNode(); var variance = this.flowParseVariance(); var ident = this.flowParseTypeAnnotatableIdentifier(); node.name = ident.name; node.variance = variance; node.bound = ident.typeAnnotation; if (this.match(types.eq)) { this.eat(types.eq); node.default = this.flowParseType(); } return this.finishNode(node, "TypeParameter"); }; pp$8.flowParseTypeParameterDeclaration = function () { var oldInType = this.state.inType; var node = this.startNode(); node.params = []; this.state.inType = true; // istanbul ignore else: this condition is already checked at all call sites if (this.isRelational("<") || this.match(types.jsxTagStart)) { this.next(); } else { this.unexpected(); } do { node.params.push(this.flowParseTypeParameter()); if (!this.isRelational(">")) { this.expect(types.comma); } } while (!this.isRelational(">")); this.expectRelational(">"); this.state.inType = oldInType; return this.finishNode(node, "TypeParameterDeclaration"); }; pp$8.flowParseTypeParameterInstantiation = function () { var node = this.startNode(); var oldInType = this.state.inType; node.params = []; this.state.inType = true; this.expectRelational("<"); while (!this.isRelational(">")) { node.params.push(this.flowParseType()); if (!this.isRelational(">")) { this.expect(types.comma); } } this.expectRelational(">"); this.state.inType = oldInType; return this.finishNode(node, "TypeParameterInstantiation"); }; pp$8.flowParseObjectPropertyKey = function () { return this.match(types.num) || this.match(types.string) ? this.parseExprAtom() : this.parseIdentifier(true); }; pp$8.flowParseObjectTypeIndexer = function (node, isStatic, variance) { node.static = isStatic; this.expect(types.bracketL); if (this.lookahead().type === types.colon) { node.id = this.flowParseObjectPropertyKey(); node.key = this.flowParseTypeInitialiser(); } else { node.id = null; node.key = this.flowParseType(); } this.expect(types.bracketR); node.value = this.flowParseTypeInitialiser(); node.variance = variance; this.flowObjectTypeSemicolon(); return this.finishNode(node, "ObjectTypeIndexer"); }; pp$8.flowParseObjectTypeMethodish = function (node) { node.params = []; node.rest = null; node.typeParameters = null; if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterDeclaration(); } this.expect(types.parenL); while (!this.match(types.parenR) && !this.match(types.ellipsis)) { node.params.push(this.flowParseFunctionTypeParam()); if (!this.match(types.parenR)) { this.expect(types.comma); } } if (this.eat(types.ellipsis)) { node.rest = this.flowParseFunctionTypeParam(); } this.expect(types.parenR); node.returnType = this.flowParseTypeInitialiser(); return this.finishNode(node, "FunctionTypeAnnotation"); }; pp$8.flowParseObjectTypeMethod = function (startPos, startLoc, isStatic, key) { var node = this.startNodeAt(startPos, startLoc); node.value = this.flowParseObjectTypeMethodish(this.startNodeAt(startPos, startLoc)); node.static = isStatic; node.key = key; node.optional = false; this.flowObjectTypeSemicolon(); return this.finishNode(node, "ObjectTypeProperty"); }; pp$8.flowParseObjectTypeCallProperty = function (node, isStatic) { var valueNode = this.startNode(); node.static = isStatic; node.value = this.flowParseObjectTypeMethodish(valueNode); this.flowObjectTypeSemicolon(); return this.finishNode(node, "ObjectTypeCallProperty"); }; pp$8.flowParseObjectType = function (allowStatic, allowExact, allowSpread) { var oldInType = this.state.inType; this.state.inType = true; var nodeStart = this.startNode(); var node = void 0; var propertyKey = void 0; var isStatic = false; nodeStart.callProperties = []; nodeStart.properties = []; nodeStart.indexers = []; var endDelim = void 0; var exact = void 0; if (allowExact && this.match(types.braceBarL)) { this.expect(types.braceBarL); endDelim = types.braceBarR; exact = true; } else { this.expect(types.braceL); endDelim = types.braceR; exact = false; } nodeStart.exact = exact; while (!this.match(endDelim)) { var optional = false; var startPos = this.state.start; var startLoc = this.state.startLoc; node = this.startNode(); if (allowStatic && this.isContextual("static") && this.lookahead().type !== types.colon) { this.next(); isStatic = true; } var variancePos = this.state.start; var variance = this.flowParseVariance(); if (this.match(types.bracketL)) { nodeStart.indexers.push(this.flowParseObjectTypeIndexer(node, isStatic, variance)); } else if (this.match(types.parenL) || this.isRelational("<")) { if (variance) { this.unexpected(variancePos); } nodeStart.callProperties.push(this.flowParseObjectTypeCallProperty(node, isStatic)); } else { if (this.match(types.ellipsis)) { if (!allowSpread) { this.unexpected(null, "Spread operator cannot appear in class or interface definitions"); } if (variance) { this.unexpected(variance.start, "Spread properties cannot have variance"); } this.expect(types.ellipsis); node.argument = this.flowParseType(); this.flowObjectTypeSemicolon(); nodeStart.properties.push(this.finishNode(node, "ObjectTypeSpreadProperty")); } else { propertyKey = this.flowParseObjectPropertyKey(); if (this.isRelational("<") || this.match(types.parenL)) { // This is a method property if (variance) { this.unexpected(variance.start); } nodeStart.properties.push(this.flowParseObjectTypeMethod(startPos, startLoc, isStatic, propertyKey)); } else { if (this.eat(types.question)) { optional = true; } node.key = propertyKey; node.value = this.flowParseTypeInitialiser(); node.optional = optional; node.static = isStatic; node.variance = variance; this.flowObjectTypeSemicolon(); nodeStart.properties.push(this.finishNode(node, "ObjectTypeProperty")); } } } isStatic = false; } this.expect(endDelim); var out = this.finishNode(nodeStart, "ObjectTypeAnnotation"); this.state.inType = oldInType; return out; }; pp$8.flowObjectTypeSemicolon = function () { if (!this.eat(types.semi) && !this.eat(types.comma) && !this.match(types.braceR) && !this.match(types.braceBarR)) { this.unexpected(); } }; pp$8.flowParseQualifiedTypeIdentifier = function (startPos, startLoc, id) { startPos = startPos || this.state.start; startLoc = startLoc || this.state.startLoc; var node = id || this.parseIdentifier(); while (this.eat(types.dot)) { var node2 = this.startNodeAt(startPos, startLoc); node2.qualification = node; node2.id = this.parseIdentifier(); node = this.finishNode(node2, "QualifiedTypeIdentifier"); } return node; }; pp$8.flowParseGenericType = function (startPos, startLoc, id) { var node = this.startNodeAt(startPos, startLoc); node.typeParameters = null; node.id = this.flowParseQualifiedTypeIdentifier(startPos, startLoc, id); if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterInstantiation(); } return this.finishNode(node, "GenericTypeAnnotation"); }; pp$8.flowParseTypeofType = function () { var node = this.startNode(); this.expect(types._typeof); node.argument = this.flowParsePrimaryType(); return this.finishNode(node, "TypeofTypeAnnotation"); }; pp$8.flowParseTupleType = function () { var node = this.startNode(); node.types = []; this.expect(types.bracketL); // We allow trailing commas while (this.state.pos < this.input.length && !this.match(types.bracketR)) { node.types.push(this.flowParseType()); if (this.match(types.bracketR)) break; this.expect(types.comma); } this.expect(types.bracketR); return this.finishNode(node, "TupleTypeAnnotation"); }; pp$8.flowParseFunctionTypeParam = function () { var name = null; var optional = false; var typeAnnotation = null; var node = this.startNode(); var lh = this.lookahead(); if (lh.type === types.colon || lh.type === types.question) { name = this.parseIdentifier(); if (this.eat(types.question)) { optional = true; } typeAnnotation = this.flowParseTypeInitialiser(); } else { typeAnnotation = this.flowParseType(); } node.name = name; node.optional = optional; node.typeAnnotation = typeAnnotation; return this.finishNode(node, "FunctionTypeParam"); }; pp$8.reinterpretTypeAsFunctionTypeParam = function (type) { var node = this.startNodeAt(type.start, type.loc.start); node.name = null; node.optional = false; node.typeAnnotation = type; return this.finishNode(node, "FunctionTypeParam"); }; pp$8.flowParseFunctionTypeParams = function () { var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var ret = { params: params, rest: null }; while (!this.match(types.parenR) && !this.match(types.ellipsis)) { ret.params.push(this.flowParseFunctionTypeParam()); if (!this.match(types.parenR)) { this.expect(types.comma); } } if (this.eat(types.ellipsis)) { ret.rest = this.flowParseFunctionTypeParam(); } return ret; }; pp$8.flowIdentToTypeAnnotation = function (startPos, startLoc, node, id) { switch (id.name) { case "any": return this.finishNode(node, "AnyTypeAnnotation"); case "void": return this.finishNode(node, "VoidTypeAnnotation"); case "bool": case "boolean": return this.finishNode(node, "BooleanTypeAnnotation"); case "mixed": return this.finishNode(node, "MixedTypeAnnotation"); case "empty": return this.finishNode(node, "EmptyTypeAnnotation"); case "number": return this.finishNode(node, "NumberTypeAnnotation"); case "string": return this.finishNode(node, "StringTypeAnnotation"); default: return this.flowParseGenericType(startPos, startLoc, id); } }; // The parsing of types roughly parallels the parsing of expressions, and // primary types are kind of like primary expressions...they're the // primitives with which other types are constructed. pp$8.flowParsePrimaryType = function () { var startPos = this.state.start; var startLoc = this.state.startLoc; var node = this.startNode(); var tmp = void 0; var type = void 0; var isGroupedType = false; var oldNoAnonFunctionType = this.state.noAnonFunctionType; switch (this.state.type) { case types.name: return this.flowIdentToTypeAnnotation(startPos, startLoc, node, this.parseIdentifier()); case types.braceL: return this.flowParseObjectType(false, false, true); case types.braceBarL: return this.flowParseObjectType(false, true, true); case types.bracketL: return this.flowParseTupleType(); case types.relational: if (this.state.value === "<") { node.typeParameters = this.flowParseTypeParameterDeclaration(); this.expect(types.parenL); tmp = this.flowParseFunctionTypeParams(); node.params = tmp.params; node.rest = tmp.rest; this.expect(types.parenR); this.expect(types.arrow); node.returnType = this.flowParseType(); return this.finishNode(node, "FunctionTypeAnnotation"); } break; case types.parenL: this.next(); // Check to see if this is actually a grouped type if (!this.match(types.parenR) && !this.match(types.ellipsis)) { if (this.match(types.name)) { var token = this.lookahead().type; isGroupedType = token !== types.question && token !== types.colon; } else { isGroupedType = true; } } if (isGroupedType) { this.state.noAnonFunctionType = false; type = this.flowParseType(); this.state.noAnonFunctionType = oldNoAnonFunctionType; // A `,` or a `) =>` means this is an anonymous function type if (this.state.noAnonFunctionType || !(this.match(types.comma) || this.match(types.parenR) && this.lookahead().type === types.arrow)) { this.expect(types.parenR); return type; } else { // Eat a comma if there is one this.eat(types.comma); } } if (type) { tmp = this.flowParseFunctionTypeParams([this.reinterpretTypeAsFunctionTypeParam(type)]); } else { tmp = this.flowParseFunctionTypeParams(); } node.params = tmp.params; node.rest = tmp.rest; this.expect(types.parenR); this.expect(types.arrow); node.returnType = this.flowParseType(); node.typeParameters = null; return this.finishNode(node, "FunctionTypeAnnotation"); case types.string: return this.parseLiteral(this.state.value, "StringLiteralTypeAnnotation"); case types._true:case types._false: node.value = this.match(types._true); this.next(); return this.finishNode(node, "BooleanLiteralTypeAnnotation"); case types.plusMin: if (this.state.value === "-") { this.next(); if (!this.match(types.num)) this.unexpected(null, "Unexpected token, expected number"); return this.parseLiteral(-this.state.value, "NumericLiteralTypeAnnotation", node.start, node.loc.start); } this.unexpected(); case types.num: return this.parseLiteral(this.state.value, "NumericLiteralTypeAnnotation"); case types._null: node.value = this.match(types._null); this.next(); return this.finishNode(node, "NullLiteralTypeAnnotation"); case types._this: node.value = this.match(types._this); this.next(); return this.finishNode(node, "ThisTypeAnnotation"); case types.star: this.next(); return this.finishNode(node, "ExistentialTypeParam"); default: if (this.state.type.keyword === "typeof") { return this.flowParseTypeofType(); } } this.unexpected(); }; pp$8.flowParsePostfixType = function () { var startPos = this.state.start, startLoc = this.state.startLoc; var type = this.flowParsePrimaryType(); while (!this.canInsertSemicolon() && this.match(types.bracketL)) { var node = this.startNodeAt(startPos, startLoc); node.elementType = type; this.expect(types.bracketL); this.expect(types.bracketR); type = this.finishNode(node, "ArrayTypeAnnotation"); } return type; }; pp$8.flowParsePrefixType = function () { var node = this.startNode(); if (this.eat(types.question)) { node.typeAnnotation = this.flowParsePrefixType(); return this.finishNode(node, "NullableTypeAnnotation"); } else { return this.flowParsePostfixType(); } }; pp$8.flowParseAnonFunctionWithoutParens = function () { var param = this.flowParsePrefixType(); if (!this.state.noAnonFunctionType && this.eat(types.arrow)) { var node = this.startNodeAt(param.start, param.loc.start); node.params = [this.reinterpretTypeAsFunctionTypeParam(param)]; node.rest = null; node.returnType = this.flowParseType(); node.typeParameters = null; return this.finishNode(node, "FunctionTypeAnnotation"); } return param; }; pp$8.flowParseIntersectionType = function () { var node = this.startNode(); this.eat(types.bitwiseAND); var type = this.flowParseAnonFunctionWithoutParens(); node.types = [type]; while (this.eat(types.bitwiseAND)) { node.types.push(this.flowParseAnonFunctionWithoutParens()); } return node.types.length === 1 ? type : this.finishNode(node, "IntersectionTypeAnnotation"); }; pp$8.flowParseUnionType = function () { var node = this.startNode(); this.eat(types.bitwiseOR); var type = this.flowParseIntersectionType(); node.types = [type]; while (this.eat(types.bitwiseOR)) { node.types.push(this.flowParseIntersectionType()); } return node.types.length === 1 ? type : this.finishNode(node, "UnionTypeAnnotation"); }; pp$8.flowParseType = function () { var oldInType = this.state.inType; this.state.inType = true; var type = this.flowParseUnionType(); this.state.inType = oldInType; return type; }; pp$8.flowParseTypeAnnotation = function () { var node = this.startNode(); node.typeAnnotation = this.flowParseTypeInitialiser(); return this.finishNode(node, "TypeAnnotation"); }; pp$8.flowParseTypeAndPredicateAnnotation = function () { var node = this.startNode(); var _flowParseTypeAndPred2 = this.flowParseTypeAndPredicateInitialiser(); node.typeAnnotation = _flowParseTypeAndPred2[0]; node.predicate = _flowParseTypeAndPred2[1]; return this.finishNode(node, "TypeAnnotation"); }; pp$8.flowParseTypeAnnotatableIdentifier = function () { var ident = this.flowParseRestrictedIdentifier(); if (this.match(types.colon)) { ident.typeAnnotation = this.flowParseTypeAnnotation(); this.finishNode(ident, ident.type); } return ident; }; pp$8.typeCastToParameter = function (node) { node.expression.typeAnnotation = node.typeAnnotation; return this.finishNodeAt(node.expression, node.expression.type, node.typeAnnotation.end, node.typeAnnotation.loc.end); }; pp$8.flowParseVariance = function () { var variance = null; if (this.match(types.plusMin)) { if (this.state.value === "+") { variance = "plus"; } else if (this.state.value === "-") { variance = "minus"; } this.next(); } return variance; }; var flowPlugin = function (instance) { // plain function return types: function name(): string {} instance.extend("parseFunctionBody", function (inner) { return function (node, allowExpression) { if (this.match(types.colon) && !allowExpression) { // if allowExpression is true then we're parsing an arrow function and if // there's a return type then it's been handled elsewhere node.returnType = this.flowParseTypeAndPredicateAnnotation(); } return inner.call(this, node, allowExpression); }; }); // interfaces instance.extend("parseStatement", function (inner) { return function (declaration, topLevel) { // strict mode handling of `interface` since it's a reserved word if (this.state.strict && this.match(types.name) && this.state.value === "interface") { var node = this.startNode(); this.next(); return this.flowParseInterface(node); } else { return inner.call(this, declaration, topLevel); } }; }); // declares, interfaces and type aliases instance.extend("parseExpressionStatement", function (inner) { return function (node, expr) { if (expr.type === "Identifier") { if (expr.name === "declare") { if (this.match(types._class) || this.match(types.name) || this.match(types._function) || this.match(types._var) || this.match(types._export)) { return this.flowParseDeclare(node); } } else if (this.match(types.name)) { if (expr.name === "interface") { return this.flowParseInterface(node); } else if (expr.name === "type") { return this.flowParseTypeAlias(node); } else if (expr.name === "opaque") { return this.flowParseOpaqueType(node, false); } } } return inner.call(this, node, expr); }; }); // export type instance.extend("shouldParseExportDeclaration", function (inner) { return function () { return this.isContextual("type") || this.isContextual("interface") || this.isContextual("opaque") || inner.call(this); }; }); instance.extend("isExportDefaultSpecifier", function (inner) { return function () { if (this.match(types.name) && (this.state.value === "type" || this.state.value === "interface" || this.state.value === "opaque")) { return false; } return inner.call(this); }; }); instance.extend("parseConditional", function (inner) { return function (expr, noIn, startPos, startLoc, refNeedsArrowPos) { // only do the expensive clone if there is a question mark // and if we come from inside parens if (refNeedsArrowPos && this.match(types.question)) { var state = this.state.clone(); try { return inner.call(this, expr, noIn, startPos, startLoc); } catch (err) { if (err instanceof SyntaxError) { this.state = state; refNeedsArrowPos.start = err.pos || this.state.start; return expr; } else { // istanbul ignore next: no such error is expected throw err; } } } return inner.call(this, expr, noIn, startPos, startLoc); }; }); instance.extend("parseParenItem", function (inner) { return function (node, startPos, startLoc) { node = inner.call(this, node, startPos, startLoc); if (this.eat(types.question)) { node.optional = true; } if (this.match(types.colon)) { var typeCastNode = this.startNodeAt(startPos, startLoc); typeCastNode.expression = node; typeCastNode.typeAnnotation = this.flowParseTypeAnnotation(); return this.finishNode(typeCastNode, "TypeCastExpression"); } return node; }; }); instance.extend("parseExport", function (inner) { return function (node) { node = inner.call(this, node); if (node.type === "ExportNamedDeclaration") { node.exportKind = node.exportKind || "value"; } return node; }; }); instance.extend("parseExportDeclaration", function (inner) { return function (node) { if (this.isContextual("type")) { node.exportKind = "type"; var declarationNode = this.startNode(); this.next(); if (this.match(types.braceL)) { // export type { foo, bar }; node.specifiers = this.parseExportSpecifiers(); this.parseExportFrom(node); return null; } else { // export type Foo = Bar; return this.flowParseTypeAlias(declarationNode); } } else if (this.isContextual("opaque")) { node.exportKind = "type"; var _declarationNode = this.startNode(); this.next(); // export opaque type Foo = Bar; return this.flowParseOpaqueType(_declarationNode, false); } else if (this.isContextual("interface")) { node.exportKind = "type"; var _declarationNode2 = this.startNode(); this.next(); return this.flowParseInterface(_declarationNode2); } else { return inner.call(this, node); } }; }); instance.extend("parseClassId", function (inner) { return function (node) { inner.apply(this, arguments); if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterDeclaration(); } }; }); // don't consider `void` to be a keyword as then it'll use the void token type // and set startExpr instance.extend("isKeyword", function (inner) { return function (name) { if (this.state.inType && name === "void") { return false; } else { return inner.call(this, name); } }; }); // ensure that inside flow types, we bypass the jsx parser plugin instance.extend("readToken", function (inner) { return function (code) { if (this.state.inType && (code === 62 || code === 60)) { return this.finishOp(types.relational, 1); } else { return inner.call(this, code); } }; }); // don't lex any token as a jsx one inside a flow type instance.extend("jsx_readToken", function (inner) { return function () { if (!this.state.inType) return inner.call(this); }; }); instance.extend("toAssignable", function (inner) { return function (node, isBinding, contextDescription) { if (node.type === "TypeCastExpression") { return inner.call(this, this.typeCastToParameter(node), isBinding, contextDescription); } else { return inner.call(this, node, isBinding, contextDescription); } }; }); // turn type casts that we found in function parameter head into type annotated params instance.extend("toAssignableList", function (inner) { return function (exprList, isBinding, contextDescription) { for (var i = 0; i < exprList.length; i++) { var expr = exprList[i]; if (expr && expr.type === "TypeCastExpression") { exprList[i] = this.typeCastToParameter(expr); } } return inner.call(this, exprList, isBinding, contextDescription); }; }); // this is a list of nodes, from something like a call expression, we need to filter the // type casts that we've found that are illegal in this context instance.extend("toReferencedList", function () { return function (exprList) { for (var i = 0; i < exprList.length; i++) { var expr = exprList[i]; if (expr && expr._exprListItem && expr.type === "TypeCastExpression") { this.raise(expr.start, "Unexpected type cast"); } } return exprList; }; }); // parse an item inside a expression list eg. `(NODE, NODE)` where NODE represents // the position where this function is called instance.extend("parseExprListItem", function (inner) { return function () { var container = this.startNode(); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } var node = inner.call.apply(inner, [this].concat(args)); if (this.match(types.colon)) { container._exprListItem = true; container.expression = node; container.typeAnnotation = this.flowParseTypeAnnotation(); return this.finishNode(container, "TypeCastExpression"); } else { return node; } }; }); instance.extend("checkLVal", function (inner) { return function (node) { if (node.type !== "TypeCastExpression") { return inner.apply(this, arguments); } }; }); // parse class property type annotations instance.extend("parseClassProperty", function (inner) { return function (node) { delete node.variancePos; if (this.match(types.colon)) { node.typeAnnotation = this.flowParseTypeAnnotation(); } return inner.call(this, node); }; }); // determine whether or not we're currently in the position where a class method would appear instance.extend("isClassMethod", function (inner) { return function () { return this.isRelational("<") || inner.call(this); }; }); // determine whether or not we're currently in the position where a class property would appear instance.extend("isClassProperty", function (inner) { return function () { return this.match(types.colon) || inner.call(this); }; }); instance.extend("isNonstaticConstructor", function (inner) { return function (method) { return !this.match(types.colon) && inner.call(this, method); }; }); // parse type parameters for class methods instance.extend("parseClassMethod", function (inner) { return function (classBody, method) { if (method.variance) { this.unexpected(method.variancePos); } delete method.variance; delete method.variancePos; if (this.isRelational("<")) { method.typeParameters = this.flowParseTypeParameterDeclaration(); } for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { args[_key2 - 2] = arguments[_key2]; } inner.call.apply(inner, [this, classBody, method].concat(args)); }; }); // parse a the super class type parameters and implements instance.extend("parseClassSuper", function (inner) { return function (node, isStatement) { inner.call(this, node, isStatement); if (node.superClass && this.isRelational("<")) { node.superTypeParameters = this.flowParseTypeParameterInstantiation(); } if (this.isContextual("implements")) { this.next(); var implemented = node.implements = []; do { var _node = this.startNode(); _node.id = this.parseIdentifier(); if (this.isRelational("<")) { _node.typeParameters = this.flowParseTypeParameterInstantiation(); } else { _node.typeParameters = null; } implemented.push(this.finishNode(_node, "ClassImplements")); } while (this.eat(types.comma)); } }; }); instance.extend("parsePropertyName", function (inner) { return function (node) { var variancePos = this.state.start; var variance = this.flowParseVariance(); var key = inner.call(this, node); node.variance = variance; node.variancePos = variancePos; return key; }; }); // parse type parameters for object method shorthand instance.extend("parseObjPropValue", function (inner) { return function (prop) { if (prop.variance) { this.unexpected(prop.variancePos); } delete prop.variance; delete prop.variancePos; var typeParameters = void 0; // method shorthand if (this.isRelational("<")) { typeParameters = this.flowParseTypeParameterDeclaration(); if (!this.match(types.parenL)) this.unexpected(); } inner.apply(this, arguments); // add typeParameters if we found them if (typeParameters) { (prop.value || prop).typeParameters = typeParameters; } }; }); instance.extend("parseAssignableListItemTypes", function () { return function (param) { if (this.eat(types.question)) { param.optional = true; } if (this.match(types.colon)) { param.typeAnnotation = this.flowParseTypeAnnotation(); } this.finishNode(param, param.type); return param; }; }); instance.extend("parseMaybeDefault", function (inner) { return function () { for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } var node = inner.apply(this, args); if (node.type === "AssignmentPattern" && node.typeAnnotation && node.right.start < node.typeAnnotation.start) { this.raise(node.typeAnnotation.start, "Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`"); } return node; }; }); // parse typeof and type imports instance.extend("parseImportSpecifiers", function (inner) { return function (node) { node.importKind = "value"; var kind = null; if (this.match(types._typeof)) { kind = "typeof"; } else if (this.isContextual("type")) { kind = "type"; } if (kind) { var lh = this.lookahead(); if (lh.type === types.name && lh.value !== "from" || lh.type === types.braceL || lh.type === types.star) { this.next(); node.importKind = kind; } } inner.call(this, node); }; }); // parse import-type/typeof shorthand instance.extend("parseImportSpecifier", function () { return function (node) { var specifier = this.startNode(); var firstIdentLoc = this.state.start; var firstIdent = this.parseIdentifier(true); var specifierTypeKind = null; if (firstIdent.name === "type") { specifierTypeKind = "type"; } else if (firstIdent.name === "typeof") { specifierTypeKind = "typeof"; } var isBinding = false; if (this.isContextual("as")) { var as_ident = this.parseIdentifier(true); if (specifierTypeKind !== null && !this.match(types.name) && !this.state.type.keyword) { // `import {type as ,` or `import {type as }` specifier.imported = as_ident; specifier.importKind = specifierTypeKind; specifier.local = as_ident.__clone(); } else { // `import {type as foo` specifier.imported = firstIdent; specifier.importKind = null; specifier.local = this.parseIdentifier(); } } else if (specifierTypeKind !== null && (this.match(types.name) || this.state.type.keyword)) { // `import {type foo` specifier.imported = this.parseIdentifier(true); specifier.importKind = specifierTypeKind; if (this.eatContextual("as")) { specifier.local = this.parseIdentifier(); } else { isBinding = true; specifier.local = specifier.imported.__clone(); } } else { isBinding = true; specifier.imported = firstIdent; specifier.importKind = null; specifier.local = specifier.imported.__clone(); } if ((node.importKind === "type" || node.importKind === "typeof") && (specifier.importKind === "type" || specifier.importKind === "typeof")) { this.raise(firstIdentLoc, "`The `type` and `typeof` keywords on named imports can only be used on regular `import` statements. It cannot be used with `import type` or `import typeof` statements`"); } if (isBinding) this.checkReservedWord(specifier.local.name, specifier.start, true, true); this.checkLVal(specifier.local, true, undefined, "import specifier"); node.specifiers.push(this.finishNode(specifier, "ImportSpecifier")); }; }); // parse function type parameters - function foo<T>() {} instance.extend("parseFunctionParams", function (inner) { return function (node) { if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterDeclaration(); } inner.call(this, node); }; }); // parse flow type annotations on variable declarator heads - let foo: string = bar instance.extend("parseVarHead", function (inner) { return function (decl) { inner.call(this, decl); if (this.match(types.colon)) { decl.id.typeAnnotation = this.flowParseTypeAnnotation(); this.finishNode(decl.id, decl.id.type); } }; }); // parse the return type of an async arrow function - let foo = (async (): number => {}); instance.extend("parseAsyncArrowFromCallExpression", function (inner) { return function (node, call) { if (this.match(types.colon)) { var oldNoAnonFunctionType = this.state.noAnonFunctionType; this.state.noAnonFunctionType = true; node.returnType = this.flowParseTypeAnnotation(); this.state.noAnonFunctionType = oldNoAnonFunctionType; } return inner.call(this, node, call); }; }); // todo description instance.extend("shouldParseAsyncArrow", function (inner) { return function () { return this.match(types.colon) || inner.call(this); }; }); // We need to support type parameter declarations for arrow functions. This // is tricky. There are three situations we need to handle // // 1. This is either JSX or an arrow function. We'll try JSX first. If that // fails, we'll try an arrow function. If that fails, we'll throw the JSX // error. // 2. This is an arrow function. We'll parse the type parameter declaration, // parse the rest, make sure the rest is an arrow function, and go from // there // 3. This is neither. Just call the inner function instance.extend("parseMaybeAssign", function (inner) { return function () { var jsxError = null; for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } if (types.jsxTagStart && this.match(types.jsxTagStart)) { var state = this.state.clone(); try { return inner.apply(this, args); } catch (err) { if (err instanceof SyntaxError) { this.state = state; // Remove `tc.j_expr` and `tc.j_oTag` from context added // by parsing `jsxTagStart` to stop the JSX plugin from // messing with the tokens this.state.context.length -= 2; jsxError = err; } else { // istanbul ignore next: no such error is expected throw err; } } } if (jsxError != null || this.isRelational("<")) { var arrowExpression = void 0; var typeParameters = void 0; try { typeParameters = this.flowParseTypeParameterDeclaration(); arrowExpression = inner.apply(this, args); arrowExpression.typeParameters = typeParameters; arrowExpression.start = typeParameters.start; arrowExpression.loc.start = typeParameters.loc.start; } catch (err) { throw jsxError || err; } if (arrowExpression.type === "ArrowFunctionExpression") { return arrowExpression; } else if (jsxError != null) { throw jsxError; } else { this.raise(typeParameters.start, "Expected an arrow function after this type parameter declaration"); } } return inner.apply(this, args); }; }); // handle return types for arrow functions instance.extend("parseArrow", function (inner) { return function (node) { if (this.match(types.colon)) { var state = this.state.clone(); try { var oldNoAnonFunctionType = this.state.noAnonFunctionType; this.state.noAnonFunctionType = true; var returnType = this.flowParseTypeAndPredicateAnnotation(); this.state.noAnonFunctionType = oldNoAnonFunctionType; if (this.canInsertSemicolon()) this.unexpected(); if (!this.match(types.arrow)) this.unexpected(); // assign after it is clear it is an arrow node.returnType = returnType; } catch (err) { if (err instanceof SyntaxError) { this.state = state; } else { // istanbul ignore next: no such error is expected throw err; } } } return inner.call(this, node); }; }); instance.extend("shouldParseArrow", function (inner) { return function () { return this.match(types.colon) || inner.call(this); }; }); }; // Adapted from String.fromcodepoint to export the function without modifying String /*! https://mths.be/fromcodepoint v0.2.1 by @mathias */ // The MIT License (MIT) // Copyright (c) Mathias Bynens // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and // associated documentation files (the "Software"), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, publish, distribute, // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var fromCodePoint = String.fromCodePoint; if (!fromCodePoint) { var stringFromCharCode = String.fromCharCode; var floor = Math.floor; fromCodePoint = function fromCodePoint() { var MAX_SIZE = 0x4000; var codeUnits = []; var highSurrogate = void 0; var lowSurrogate = void 0; var index = -1; var length = arguments.length; if (!length) { return ""; } var result = ""; while (++index < length) { var codePoint = Number(arguments[index]); if (!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity` codePoint < 0 || // not a valid Unicode code point codePoint > 0x10FFFF || // not a valid Unicode code point floor(codePoint) != codePoint // not an integer ) { throw RangeError("Invalid code point: " + codePoint); } if (codePoint <= 0xFFFF) { // BMP code point codeUnits.push(codePoint); } else { // Astral code point; split in surrogate halves // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae codePoint -= 0x10000; highSurrogate = (codePoint >> 10) + 0xD800; lowSurrogate = codePoint % 0x400 + 0xDC00; codeUnits.push(highSurrogate, lowSurrogate); } if (index + 1 == length || codeUnits.length > MAX_SIZE) { result += stringFromCharCode.apply(null, codeUnits); codeUnits.length = 0; } } return result; }; } var fromCodePoint$1 = fromCodePoint; var XHTMLEntities = { quot: "\"", amp: "&", apos: "'", lt: "<", gt: ">", nbsp: "\xA0", iexcl: "\xA1", cent: "\xA2", pound: "\xA3", curren: "\xA4", yen: "\xA5", brvbar: "\xA6", sect: "\xA7", uml: "\xA8", copy: "\xA9", ordf: "\xAA", laquo: "\xAB", not: "\xAC", shy: "\xAD", reg: "\xAE", macr: "\xAF", deg: "\xB0", plusmn: "\xB1", sup2: "\xB2", sup3: "\xB3", acute: "\xB4", micro: "\xB5", para: "\xB6", middot: "\xB7", cedil: "\xB8", sup1: "\xB9", ordm: "\xBA", raquo: "\xBB", frac14: "\xBC", frac12: "\xBD", frac34: "\xBE", iquest: "\xBF", Agrave: "\xC0", Aacute: "\xC1", Acirc: "\xC2", Atilde: "\xC3", Auml: "\xC4", Aring: "\xC5", AElig: "\xC6", Ccedil: "\xC7", Egrave: "\xC8", Eacute: "\xC9", Ecirc: "\xCA", Euml: "\xCB", Igrave: "\xCC", Iacute: "\xCD", Icirc: "\xCE", Iuml: "\xCF", ETH: "\xD0", Ntilde: "\xD1", Ograve: "\xD2", Oacute: "\xD3", Ocirc: "\xD4", Otilde: "\xD5", Ouml: "\xD6", times: "\xD7", Oslash: "\xD8", Ugrave: "\xD9", Uacute: "\xDA", Ucirc: "\xDB", Uuml: "\xDC", Yacute: "\xDD", THORN: "\xDE", szlig: "\xDF", agrave: "\xE0", aacute: "\xE1", acirc: "\xE2", atilde: "\xE3", auml: "\xE4", aring: "\xE5", aelig: "\xE6", ccedil: "\xE7", egrave: "\xE8", eacute: "\xE9", ecirc: "\xEA", euml: "\xEB", igrave: "\xEC", iacute: "\xED", icirc: "\xEE", iuml: "\xEF", eth: "\xF0", ntilde: "\xF1", ograve: "\xF2", oacute: "\xF3", ocirc: "\xF4", otilde: "\xF5", ouml: "\xF6", divide: "\xF7", oslash: "\xF8", ugrave: "\xF9", uacute: "\xFA", ucirc: "\xFB", uuml: "\xFC", yacute: "\xFD", thorn: "\xFE", yuml: "\xFF", OElig: "\u0152", oelig: "\u0153", Scaron: "\u0160", scaron: "\u0161", Yuml: "\u0178", fnof: "\u0192", circ: "\u02C6", tilde: "\u02DC", Alpha: "\u0391", Beta: "\u0392", Gamma: "\u0393", Delta: "\u0394", Epsilon: "\u0395", Zeta: "\u0396", Eta: "\u0397", Theta: "\u0398", Iota: "\u0399", Kappa: "\u039A", Lambda: "\u039B", Mu: "\u039C", Nu: "\u039D", Xi: "\u039E", Omicron: "\u039F", Pi: "\u03A0", Rho: "\u03A1", Sigma: "\u03A3", Tau: "\u03A4", Upsilon: "\u03A5", Phi: "\u03A6", Chi: "\u03A7", Psi: "\u03A8", Omega: "\u03A9", alpha: "\u03B1", beta: "\u03B2", gamma: "\u03B3", delta: "\u03B4", epsilon: "\u03B5", zeta: "\u03B6", eta: "\u03B7", theta: "\u03B8", iota: "\u03B9", kappa: "\u03BA", lambda: "\u03BB", mu: "\u03BC", nu: "\u03BD", xi: "\u03BE", omicron: "\u03BF", pi: "\u03C0", rho: "\u03C1", sigmaf: "\u03C2", sigma: "\u03C3", tau: "\u03C4", upsilon: "\u03C5", phi: "\u03C6", chi: "\u03C7", psi: "\u03C8", omega: "\u03C9", thetasym: "\u03D1", upsih: "\u03D2", piv: "\u03D6", ensp: "\u2002", emsp: "\u2003", thinsp: "\u2009", zwnj: "\u200C", zwj: "\u200D", lrm: "\u200E", rlm: "\u200F", ndash: "\u2013", mdash: "\u2014", lsquo: "\u2018", rsquo: "\u2019", sbquo: "\u201A", ldquo: "\u201C", rdquo: "\u201D", bdquo: "\u201E", dagger: "\u2020", Dagger: "\u2021", bull: "\u2022", hellip: "\u2026", permil: "\u2030", prime: "\u2032", Prime: "\u2033", lsaquo: "\u2039", rsaquo: "\u203A", oline: "\u203E", frasl: "\u2044", euro: "\u20AC", image: "\u2111", weierp: "\u2118", real: "\u211C", trade: "\u2122", alefsym: "\u2135", larr: "\u2190", uarr: "\u2191", rarr: "\u2192", darr: "\u2193", harr: "\u2194", crarr: "\u21B5", lArr: "\u21D0", uArr: "\u21D1", rArr: "\u21D2", dArr: "\u21D3", hArr: "\u21D4", forall: "\u2200", part: "\u2202", exist: "\u2203", empty: "\u2205", nabla: "\u2207", isin: "\u2208", notin: "\u2209", ni: "\u220B", prod: "\u220F", sum: "\u2211", minus: "\u2212", lowast: "\u2217", radic: "\u221A", prop: "\u221D", infin: "\u221E", ang: "\u2220", and: "\u2227", or: "\u2228", cap: "\u2229", cup: "\u222A", "int": "\u222B", there4: "\u2234", sim: "\u223C", cong: "\u2245", asymp: "\u2248", ne: "\u2260", equiv: "\u2261", le: "\u2264", ge: "\u2265", sub: "\u2282", sup: "\u2283", nsub: "\u2284", sube: "\u2286", supe: "\u2287", oplus: "\u2295", otimes: "\u2297", perp: "\u22A5", sdot: "\u22C5", lceil: "\u2308", rceil: "\u2309", lfloor: "\u230A", rfloor: "\u230B", lang: "\u2329", rang: "\u232A", loz: "\u25CA", spades: "\u2660", clubs: "\u2663", hearts: "\u2665", diams: "\u2666" }; var HEX_NUMBER = /^[\da-fA-F]+$/; var DECIMAL_NUMBER = /^\d+$/; types$1.j_oTag = new TokContext("<tag", false); types$1.j_cTag = new TokContext("</tag", false); types$1.j_expr = new TokContext("<tag>...</tag>", true, true); types.jsxName = new TokenType("jsxName"); types.jsxText = new TokenType("jsxText", { beforeExpr: true }); types.jsxTagStart = new TokenType("jsxTagStart", { startsExpr: true }); types.jsxTagEnd = new TokenType("jsxTagEnd"); types.jsxTagStart.updateContext = function () { this.state.context.push(types$1.j_expr); // treat as beginning of JSX expression this.state.context.push(types$1.j_oTag); // start opening tag context this.state.exprAllowed = false; }; types.jsxTagEnd.updateContext = function (prevType) { var out = this.state.context.pop(); if (out === types$1.j_oTag && prevType === types.slash || out === types$1.j_cTag) { this.state.context.pop(); this.state.exprAllowed = this.curContext() === types$1.j_expr; } else { this.state.exprAllowed = true; } }; var pp$9 = Parser.prototype; // Reads inline JSX contents token. pp$9.jsxReadToken = function () { var out = ""; var chunkStart = this.state.pos; for (;;) { if (this.state.pos >= this.input.length) { this.raise(this.state.start, "Unterminated JSX contents"); } var ch = this.input.charCodeAt(this.state.pos); switch (ch) { case 60: // "<" case 123: // "{" if (this.state.pos === this.state.start) { if (ch === 60 && this.state.exprAllowed) { ++this.state.pos; return this.finishToken(types.jsxTagStart); } return this.getTokenFromCode(ch); } out += this.input.slice(chunkStart, this.state.pos); return this.finishToken(types.jsxText, out); case 38: // "&" out += this.input.slice(chunkStart, this.state.pos); out += this.jsxReadEntity(); chunkStart = this.state.pos; break; default: if (isNewLine(ch)) { out += this.input.slice(chunkStart, this.state.pos); out += this.jsxReadNewLine(true); chunkStart = this.state.pos; } else { ++this.state.pos; } } } }; pp$9.jsxReadNewLine = function (normalizeCRLF) { var ch = this.input.charCodeAt(this.state.pos); var out = void 0; ++this.state.pos; if (ch === 13 && this.input.charCodeAt(this.state.pos) === 10) { ++this.state.pos; out = normalizeCRLF ? "\n" : "\r\n"; } else { out = String.fromCharCode(ch); } ++this.state.curLine; this.state.lineStart = this.state.pos; return out; }; pp$9.jsxReadString = function (quote) { var out = ""; var chunkStart = ++this.state.pos; for (;;) { if (this.state.pos >= this.input.length) { this.raise(this.state.start, "Unterminated string constant"); } var ch = this.input.charCodeAt(this.state.pos); if (ch === quote) break; if (ch === 38) { // "&" out += this.input.slice(chunkStart, this.state.pos); out += this.jsxReadEntity(); chunkStart = this.state.pos; } else if (isNewLine(ch)) { out += this.input.slice(chunkStart, this.state.pos); out += this.jsxReadNewLine(false); chunkStart = this.state.pos; } else { ++this.state.pos; } } out += this.input.slice(chunkStart, this.state.pos++); return this.finishToken(types.string, out); }; pp$9.jsxReadEntity = function () { var str = ""; var count = 0; var entity = void 0; var ch = this.input[this.state.pos]; var startPos = ++this.state.pos; while (this.state.pos < this.input.length && count++ < 10) { ch = this.input[this.state.pos++]; if (ch === ";") { if (str[0] === "#") { if (str[1] === "x") { str = str.substr(2); if (HEX_NUMBER.test(str)) entity = fromCodePoint$1(parseInt(str, 16)); } else { str = str.substr(1); if (DECIMAL_NUMBER.test(str)) entity = fromCodePoint$1(parseInt(str, 10)); } } else { entity = XHTMLEntities[str]; } break; } str += ch; } if (!entity) { this.state.pos = startPos; return "&"; } return entity; }; // Read a JSX identifier (valid tag or attribute name). // // Optimized version since JSX identifiers can"t contain // escape characters and so can be read as single slice. // Also assumes that first character was already checked // by isIdentifierStart in readToken. pp$9.jsxReadWord = function () { var ch = void 0; var start = this.state.pos; do { ch = this.input.charCodeAt(++this.state.pos); } while (isIdentifierChar(ch) || ch === 45); // "-" return this.finishToken(types.jsxName, this.input.slice(start, this.state.pos)); }; // Transforms JSX element name to string. function getQualifiedJSXName(object) { if (object.type === "JSXIdentifier") { return object.name; } if (object.type === "JSXNamespacedName") { return object.namespace.name + ":" + object.name.name; } if (object.type === "JSXMemberExpression") { return getQualifiedJSXName(object.object) + "." + getQualifiedJSXName(object.property); } } // Parse next token as JSX identifier pp$9.jsxParseIdentifier = function () { var node = this.startNode(); if (this.match(types.jsxName)) { node.name = this.state.value; } else if (this.state.type.keyword) { node.name = this.state.type.keyword; } else { this.unexpected(); } this.next(); return this.finishNode(node, "JSXIdentifier"); }; // Parse namespaced identifier. pp$9.jsxParseNamespacedName = function () { var startPos = this.state.start; var startLoc = this.state.startLoc; var name = this.jsxParseIdentifier(); if (!this.eat(types.colon)) return name; var node = this.startNodeAt(startPos, startLoc); node.namespace = name; node.name = this.jsxParseIdentifier(); return this.finishNode(node, "JSXNamespacedName"); }; // Parses element name in any form - namespaced, member // or single identifier. pp$9.jsxParseElementName = function () { var startPos = this.state.start; var startLoc = this.state.startLoc; var node = this.jsxParseNamespacedName(); while (this.eat(types.dot)) { var newNode = this.startNodeAt(startPos, startLoc); newNode.object = node; newNode.property = this.jsxParseIdentifier(); node = this.finishNode(newNode, "JSXMemberExpression"); } return node; }; // Parses any type of JSX attribute value. pp$9.jsxParseAttributeValue = function () { var node = void 0; switch (this.state.type) { case types.braceL: node = this.jsxParseExpressionContainer(); if (node.expression.type === "JSXEmptyExpression") { this.raise(node.start, "JSX attributes must only be assigned a non-empty expression"); } else { return node; } case types.jsxTagStart: case types.string: node = this.parseExprAtom(); node.extra = null; return node; default: this.raise(this.state.start, "JSX value should be either an expression or a quoted JSX text"); } }; // JSXEmptyExpression is unique type since it doesn't actually parse anything, // and so it should start at the end of last read token (left brace) and finish // at the beginning of the next one (right brace). pp$9.jsxParseEmptyExpression = function () { var node = this.startNodeAt(this.state.lastTokEnd, this.state.lastTokEndLoc); return this.finishNodeAt(node, "JSXEmptyExpression", this.state.start, this.state.startLoc); }; // Parse JSX spread child pp$9.jsxParseSpreadChild = function () { var node = this.startNode(); this.expect(types.braceL); this.expect(types.ellipsis); node.expression = this.parseExpression(); this.expect(types.braceR); return this.finishNode(node, "JSXSpreadChild"); }; // Parses JSX expression enclosed into curly brackets. pp$9.jsxParseExpressionContainer = function () { var node = this.startNode(); this.next(); if (this.match(types.braceR)) { node.expression = this.jsxParseEmptyExpression(); } else { node.expression = this.parseExpression(); } this.expect(types.braceR); return this.finishNode(node, "JSXExpressionContainer"); }; // Parses following JSX attribute name-value pair. pp$9.jsxParseAttribute = function () { var node = this.startNode(); if (this.eat(types.braceL)) { this.expect(types.ellipsis); node.argument = this.parseMaybeAssign(); this.expect(types.braceR); return this.finishNode(node, "JSXSpreadAttribute"); } node.name = this.jsxParseNamespacedName(); node.value = this.eat(types.eq) ? this.jsxParseAttributeValue() : null; return this.finishNode(node, "JSXAttribute"); }; // Parses JSX opening tag starting after "<". pp$9.jsxParseOpeningElementAt = function (startPos, startLoc) { var node = this.startNodeAt(startPos, startLoc); node.attributes = []; node.name = this.jsxParseElementName(); while (!this.match(types.slash) && !this.match(types.jsxTagEnd)) { node.attributes.push(this.jsxParseAttribute()); } node.selfClosing = this.eat(types.slash); this.expect(types.jsxTagEnd); return this.finishNode(node, "JSXOpeningElement"); }; // Parses JSX closing tag starting after "</". pp$9.jsxParseClosingElementAt = function (startPos, startLoc) { var node = this.startNodeAt(startPos, startLoc); node.name = this.jsxParseElementName(); this.expect(types.jsxTagEnd); return this.finishNode(node, "JSXClosingElement"); }; // Parses entire JSX element, including it"s opening tag // (starting after "<"), attributes, contents and closing tag. pp$9.jsxParseElementAt = function (startPos, startLoc) { var node = this.startNodeAt(startPos, startLoc); var children = []; var openingElement = this.jsxParseOpeningElementAt(startPos, startLoc); var closingElement = null; if (!openingElement.selfClosing) { contents: for (;;) { switch (this.state.type) { case types.jsxTagStart: startPos = this.state.start;startLoc = this.state.startLoc; this.next(); if (this.eat(types.slash)) { closingElement = this.jsxParseClosingElementAt(startPos, startLoc); break contents; } children.push(this.jsxParseElementAt(startPos, startLoc)); break; case types.jsxText: children.push(this.parseExprAtom()); break; case types.braceL: if (this.lookahead().type === types.ellipsis) { children.push(this.jsxParseSpreadChild()); } else { children.push(this.jsxParseExpressionContainer()); } break; // istanbul ignore next - should never happen default: this.unexpected(); } } if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) { this.raise(closingElement.start, "Expected corresponding JSX closing tag for <" + getQualifiedJSXName(openingElement.name) + ">"); } } node.openingElement = openingElement; node.closingElement = closingElement; node.children = children; if (this.match(types.relational) && this.state.value === "<") { this.raise(this.state.start, "Adjacent JSX elements must be wrapped in an enclosing tag"); } return this.finishNode(node, "JSXElement"); }; // Parses entire JSX element from current position. pp$9.jsxParseElement = function () { var startPos = this.state.start; var startLoc = this.state.startLoc; this.next(); return this.jsxParseElementAt(startPos, startLoc); }; var jsxPlugin = function (instance) { instance.extend("parseExprAtom", function (inner) { return function (refShortHandDefaultPos) { if (this.match(types.jsxText)) { var node = this.parseLiteral(this.state.value, "JSXText"); // https://github.com/babel/babel/issues/2078 node.extra = null; return node; } else if (this.match(types.jsxTagStart)) { return this.jsxParseElement(); } else { return inner.call(this, refShortHandDefaultPos); } }; }); instance.extend("readToken", function (inner) { return function (code) { if (this.state.inPropertyName) return inner.call(this, code); var context = this.curContext(); if (context === types$1.j_expr) { return this.jsxReadToken(); } if (context === types$1.j_oTag || context === types$1.j_cTag) { if (isIdentifierStart(code)) { return this.jsxReadWord(); } if (code === 62) { ++this.state.pos; return this.finishToken(types.jsxTagEnd); } if ((code === 34 || code === 39) && context === types$1.j_oTag) { return this.jsxReadString(code); } } if (code === 60 && this.state.exprAllowed) { ++this.state.pos; return this.finishToken(types.jsxTagStart); } return inner.call(this, code); }; }); instance.extend("updateContext", function (inner) { return function (prevType) { if (this.match(types.braceL)) { var curContext = this.curContext(); if (curContext === types$1.j_oTag) { this.state.context.push(types$1.braceExpression); } else if (curContext === types$1.j_expr) { this.state.context.push(types$1.templateQuasi); } else { inner.call(this, prevType); } this.state.exprAllowed = true; } else if (this.match(types.slash) && prevType === types.jsxTagStart) { this.state.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore this.state.context.push(types$1.j_cTag); // reconsider as closing tag context this.state.exprAllowed = false; } else { return inner.call(this, prevType); } }; }); }; plugins.estree = estreePlugin; plugins.flow = flowPlugin; plugins.jsx = jsxPlugin; function parse(input, options) { return new Parser(options, input).parse(); } function parseExpression(input, options) { var parser = new Parser(options, input); if (parser.options.strictMode) { parser.state.strict = true; } return parser.getExpression(); } exports.parse = parse; exports.parseExpression = parseExpression; exports.tokTypes = types; tonglan/adminSystem - Gogs: Go Git Service

1 次代码提交 (11e3a9652a62b867d722e5aebdba895bb86f9ed3)

作者 SHA1 备注 提交日期
  FFIB 11e3a9652a first 7 年之前