aboutsummaryrefslogtreecommitdiff
path: root/node_modules/babylon/lib/parser/statement.js
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2016-11-03 01:33:53 +0100
committerFlorian Dold <florian.dold@gmail.com>2016-11-03 01:33:53 +0100
commitd1291f67551c58168af43698a359cb5ddfd266b0 (patch)
tree55a13ed29fe1915e3f42f1b1b7038dafa2e975a7 /node_modules/babylon/lib/parser/statement.js
parentd0a0695fb5d34996850723f7d4b1b59c3df909c2 (diff)
node_modules
Diffstat (limited to 'node_modules/babylon/lib/parser/statement.js')
-rw-r--r--node_modules/babylon/lib/parser/statement.js1107
1 files changed, 0 insertions, 1107 deletions
diff --git a/node_modules/babylon/lib/parser/statement.js b/node_modules/babylon/lib/parser/statement.js
deleted file mode 100644
index 3aa2f7882..000000000
--- a/node_modules/babylon/lib/parser/statement.js
+++ /dev/null
@@ -1,1107 +0,0 @@
-"use strict";
-
-var _types = require("../tokenizer/types");
-
-var _index = require("./index");
-
-var _index2 = _interopRequireDefault(_index);
-
-var _whitespace = require("../util/whitespace");
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-var pp = _index2.default.prototype;
-
-// ### Statement parsing
-
-// Parse a program. Initializes the parser, reads any number of
-// statements, and wraps them in a Program node. Optionally takes a
-// `program` argument. If present, the statements will be appended
-// to its body instead of creating a new node.
-
-/* eslint indent: 0 */
-/* eslint max-len: 0 */
-
-pp.parseTopLevel = function (file, program) {
- program.sourceType = this.options.sourceType;
-
- this.parseBlockBody(program, true, true, _types.types.eof);
-
- file.program = this.finishNode(program, "Program");
- file.comments = this.state.comments;
- file.tokens = this.state.tokens;
-
- return this.finishNode(file, "File");
-};
-
-var loopLabel = { kind: "loop" },
- switchLabel = { kind: "switch" };
-
-// TODO
-
-pp.stmtToDirective = function (stmt) {
- var expr = stmt.expression;
-
- var directiveLiteral = this.startNodeAt(expr.start, expr.loc.start);
- var directive = this.startNodeAt(stmt.start, stmt.loc.start);
-
- var raw = this.input.slice(expr.start, expr.end);
- var val = directiveLiteral.value = raw.slice(1, -1); // remove quotes
-
- this.addExtra(directiveLiteral, "raw", raw);
- this.addExtra(directiveLiteral, "rawValue", val);
-
- directive.value = this.finishNodeAt(directiveLiteral, "DirectiveLiteral", expr.end, expr.loc.end);
-
- return this.finishNodeAt(directive, "Directive", stmt.end, stmt.loc.end);
-};
-
-// Parse a single statement.
-//
-// If expecting a statement and finding a slash operator, parse a
-// regular expression literal. This is to handle cases like
-// `if (foo) /blah/.exec(foo)`, where looking at the previous token
-// does not help.
-
-pp.parseStatement = function (declaration, topLevel) {
- if (this.match(_types.types.at)) {
- this.parseDecorators(true);
- }
-
- var starttype = this.state.type,
- node = this.startNode();
-
- // Most types of statements are recognized by the keyword they
- // start with. Many are trivial to parse, some require a bit of
- // complexity.
-
- switch (starttype) {
- case _types.types._break:case _types.types._continue:
- return this.parseBreakContinueStatement(node, starttype.keyword);
- case _types.types._debugger:
- return this.parseDebuggerStatement(node);
- case _types.types._do:
- return this.parseDoStatement(node);
- case _types.types._for:
- return this.parseForStatement(node);
- case _types.types._function:
- if (!declaration) this.unexpected();
- return this.parseFunctionStatement(node);
-
- case _types.types._class:
- if (!declaration) this.unexpected();
- this.takeDecorators(node);
- return this.parseClass(node, true);
-
- case _types.types._if:
- return this.parseIfStatement(node);
- case _types.types._return:
- return this.parseReturnStatement(node);
- case _types.types._switch:
- return this.parseSwitchStatement(node);
- case _types.types._throw:
- return this.parseThrowStatement(node);
- case _types.types._try:
- return this.parseTryStatement(node);
-
- case _types.types._let:
- case _types.types._const:
- if (!declaration) this.unexpected(); // NOTE: falls through to _var
-
- case _types.types._var:
- return this.parseVarStatement(node, starttype);
-
- case _types.types._while:
- return this.parseWhileStatement(node);
- case _types.types._with:
- return this.parseWithStatement(node);
- case _types.types.braceL:
- return this.parseBlock();
- case _types.types.semi:
- return this.parseEmptyStatement(node);
- case _types.types._export:
- case _types.types._import:
- 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.types._import ? this.parseImport(node) : this.parseExport(node);
-
- case _types.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.types._function) && !this.canInsertSemicolon()) {
- this.expect(_types.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.types.name && expr.type === "Identifier" && this.eat(_types.types.colon)) {
- return this.parseLabeledStatement(node, maybeName, expr);
- } else {
- return this.parseExpressionStatement(node, expr);
- }
-};
-
-pp.takeDecorators = function (node) {
- if (this.state.decorators.length) {
- node.decorators = this.state.decorators;
- this.state.decorators = [];
- }
-};
-
-pp.parseDecorators = function (allowExport) {
- while (this.match(_types.types.at)) {
- this.state.decorators.push(this.parseDecorator());
- }
-
- if (allowExport && this.match(_types.types._export)) {
- return;
- }
-
- if (!this.match(_types.types._class)) {
- this.raise(this.state.start, "Leading decorators must be attached to a class declaration");
- }
-};
-
-pp.parseDecorator = function () {
- if (!this.hasPlugin("decorators")) {
- this.unexpected();
- }
- var node = this.startNode();
- this.next();
- node.expression = this.parseMaybeAssign();
- return this.finishNode(node, "Decorator");
-};
-
-pp.parseBreakContinueStatement = function (node, keyword) {
- var isBreak = keyword === "break";
- this.next();
-
- if (this.isLineTerminator()) {
- node.label = null;
- } else if (!this.match(_types.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.parseDebuggerStatement = function (node) {
- this.next();
- this.semicolon();
- return this.finishNode(node, "DebuggerStatement");
-};
-
-pp.parseDoStatement = function (node) {
- this.next();
- this.state.labels.push(loopLabel);
- node.body = this.parseStatement(false);
- this.state.labels.pop();
- this.expect(_types.types._while);
- node.test = this.parseParenExpression();
- this.eat(_types.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.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.types.parenL);
-
- if (this.match(_types.types.semi)) {
- if (forAwait) {
- this.unexpected();
- }
- return this.parseFor(node, null);
- }
-
- if (this.match(_types.types._var) || this.match(_types.types._let) || this.match(_types.types._const)) {
- var _init = this.startNode(),
- varKind = this.state.type;
- this.next();
- this.parseVar(_init, true, varKind);
- this.finishNode(_init, "VariableDeclaration");
-
- if (this.match(_types.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.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.parseFunctionStatement = function (node) {
- this.next();
- return this.parseFunction(node, true);
-};
-
-pp.parseIfStatement = function (node) {
- this.next();
- node.test = this.parseParenExpression();
- node.consequent = this.parseStatement(false);
- node.alternate = this.eat(_types.types._else) ? this.parseStatement(false) : null;
- return this.finishNode(node, "IfStatement");
-};
-
-pp.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.parseSwitchStatement = function (node) {
- this.next();
- node.discriminant = this.parseParenExpression();
- node.cases = [];
- this.expect(_types.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.types.braceR);) {
- if (this.match(_types.types._case) || this.match(_types.types._default)) {
- var isCase = this.match(_types.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.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.parseThrowStatement = function (node) {
- this.next();
- if (_whitespace.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.parseTryStatement = function (node) {
- this.next();
-
- node.block = this.parseBlock();
- node.handler = null;
-
- if (this.match(_types.types._catch)) {
- var clause = this.startNode();
- this.next();
-
- this.expect(_types.types.parenL);
- clause.param = this.parseBindingAtom();
- this.checkLVal(clause.param, true, Object.create(null), "catch clause");
- this.expect(_types.types.parenR);
-
- clause.body = this.parseBlock();
- node.handler = this.finishNode(clause, "CatchClause");
- }
-
- node.guardedHandlers = empty;
- node.finalizer = this.eat(_types.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.parseVarStatement = function (node, kind) {
- this.next();
- this.parseVar(node, false, kind);
- this.semicolon();
- return this.finishNode(node, "VariableDeclaration");
-};
-
-pp.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.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.parseEmptyStatement = function (node) {
- this.next();
- return this.finishNode(node, "EmptyStatement");
-};
-
-pp.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.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.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.parseBlock = function (allowDirectives) {
- var node = this.startNode();
- this.expect(_types.types.braceL);
- this.parseBlockBody(node, allowDirectives, false, _types.types.braceR);
- return this.finishNode(node, "BlockStatement");
-};
-
-// TODO
-
-pp.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 && stmt.type === "ExpressionStatement" && stmt.expression.type === "StringLiteral" && !stmt.expression.extra.parenthesized) {
- 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.parseFor = function (node, init) {
- node.init = init;
- this.expect(_types.types.semi);
- node.test = this.match(_types.types.semi) ? null : this.parseExpression();
- this.expect(_types.types.semi);
- node.update = this.match(_types.types.parenR) ? null : this.parseExpression();
- this.expect(_types.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.parseForIn = function (node, init, forAwait) {
- var type = void 0;
- if (forAwait) {
- this.eatContextual("of");
- type = "ForAwaitStatement";
- } else {
- type = this.match(_types.types._in) ? "ForInStatement" : "ForOfStatement";
- this.next();
- }
- node.left = init;
- node.right = this.parseExpression();
- this.expect(_types.types.parenR);
- node.body = this.parseStatement(false);
- this.state.labels.pop();
- return this.finishNode(node, type);
-};
-
-// Parse a list of variable declarations.
-
-pp.parseVar = function (node, isFor, kind) {
- node.declarations = [];
- node.kind = kind.keyword;
- for (;;) {
- var decl = this.startNode();
- this.parseVarHead(decl);
- if (this.eat(_types.types.eq)) {
- decl.init = this.parseMaybeAssign(isFor);
- } else if (kind === _types.types._const && !(this.match(_types.types._in) || this.isContextual("of"))) {
- this.unexpected();
- } else if (decl.id.type !== "Identifier" && !(isFor && (this.match(_types.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.types.comma)) break;
- }
- return node;
-};
-
-pp.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.parseFunction = function (node, isStatement, allowExpressionBody, isAsync, optionalId) {
- var oldInMethod = this.state.inMethod;
- this.state.inMethod = false;
-
- this.initFunction(node, isAsync);
-
- if (this.match(_types.types.star)) {
- if (node.async && !this.hasPlugin("asyncGenerators")) {
- this.unexpected();
- } else {
- node.generator = true;
- this.next();
- }
- }
-
- if (isStatement && !optionalId && !this.match(_types.types.name) && !this.match(_types.types._yield)) {
- this.unexpected();
- }
-
- if (this.match(_types.types.name) || this.match(_types.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.parseFunctionParams = function (node) {
- this.expect(_types.types.parenL);
- node.params = this.parseBindingList(_types.types.parenR);
-};
-
-// Parse a class declaration or literal (depending on the
-// `isStatement` parameter).
-
-pp.parseClass = function (node, isStatement, optionalId) {
- this.next();
- this.parseClassId(node, isStatement, optionalId);
- this.parseClassSuper(node);
- this.parseClassBody(node);
- return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
-};
-
-pp.isClassProperty = function () {
- return this.match(_types.types.eq) || this.isLineTerminator();
-};
-
-pp.isClassMutatorStarter = function () {
- return false;
-};
-
-pp.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.types.braceL);
-
- while (!this.eat(_types.types.braceR)) {
- if (this.eat(_types.types.semi)) {
- continue;
- }
-
- if (this.match(_types.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 = [];
- }
-
- var isConstructorCall = false;
- var isMaybeStatic = this.match(_types.types.name) && this.state.value === "static";
- var isGenerator = this.eat(_types.types.star);
- var isGetSet = false;
- var isAsync = false;
-
- this.parsePropertyName(method);
-
- method.static = isMaybeStatic && !this.match(_types.types.parenL);
- if (method.static) {
- if (isGenerator) this.unexpected();
- isGenerator = this.eat(_types.types.star);
- this.parsePropertyName(method);
- }
-
- if (!isGenerator) {
- if (this.isClassProperty()) {
- classBody.body.push(this.parseClassProperty(method));
- continue;
- }
-
- if (method.key.type === "Identifier" && !method.computed && this.hasPlugin("classConstructorCall") && method.key.name === "call" && this.match(_types.types.name) && this.state.value === "constructor") {
- isConstructorCall = true;
- this.parsePropertyName(method);
- }
- }
-
- var isAsyncMethod = !this.match(_types.types.parenL) && !method.computed && method.key.type === "Identifier" && method.key.name === "async";
- if (isAsyncMethod) {
- if (this.hasPlugin("asyncGenerators") && this.eat(_types.types.star)) isGenerator = true;
- isAsync = true;
- this.parsePropertyName(method);
- }
-
- method.kind = "method";
-
- if (!method.computed) {
- var key = method.key;
-
- // handle get/set methods
- // eg. class Foo { get bar() {} set bar() {} }
-
- if (!isAsync && !isGenerator && !this.isClassMutatorStarter() && key.type === "Identifier" && !this.match(_types.types.parenL) && (key.name === "get" || key.name === "set")) {
- isGetSet = true;
- method.kind = key.name;
- key = this.parsePropertyName(method);
- }
-
- // disallow invalid constructors
- var isConstructor = !isConstructorCall && !method.static && (key.type === "Identifier" && key.name === "constructor" || key.type === "StringLiteral" && key.value === "constructor");
- if (isConstructor) {
- if (hadConstructor) this.raise(key.start, "Duplicate constructor in the same class");
- if (isGetSet) this.raise(key.start, "Constructor can't have get/set modifier");
- if (isGenerator) this.raise(key.start, "Constructor can't be a generator");
- if (isAsync) this.raise(key.start, "Constructor can't be an async function");
- method.kind = "constructor";
- hadConstructor = true;
- }
-
- // disallow static prototype method
- var isStaticPrototype = method.static && (key.type === "Identifier" && key.name === "prototype" || key.type === "StringLiteral" && key.value === "prototype");
- if (isStaticPrototype) {
- this.raise(key.start, "Classes may not have static property named prototype");
- }
- }
-
- // convert constructor to a constructor call
- if (isConstructorCall) {
- if (hadConstructorCall) this.raise(method.start, "Duplicate constructor call in the same class");
- method.kind = "constructorCall";
- hadConstructorCall = true;
- }
-
- // disallow decorators on class constructors
- if ((method.kind === "constructor" || method.kind === "constructorCall") && method.decorators) {
- this.raise(method.start, "You can't attach decorators to a class constructor");
- }
-
- this.parseClassMethod(classBody, method, isGenerator, isAsync);
-
- // get methods aren't allowed to have any parameters
- // set methods must have exactly 1 parameter
- if (isGetSet) {
- 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");
- }
- }
- }
- }
-
- 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.parseClassProperty = function (node) {
- if (this.match(_types.types.eq)) {
- if (!this.hasPlugin("classProperties")) this.unexpected();
- this.next();
- node.value = this.parseMaybeAssign();
- } else {
- node.value = null;
- }
- this.semicolon();
- return this.finishNode(node, "ClassProperty");
-};
-
-pp.parseClassMethod = function (classBody, method, isGenerator, isAsync) {
- this.parseMethod(method, isGenerator, isAsync);
- classBody.body.push(this.finishNode(method, "ClassMethod"));
-};
-
-pp.parseClassId = function (node, isStatement, optionalId) {
- if (this.match(_types.types.name)) {
- node.id = this.parseIdentifier();
- } else {
- if (optionalId || !isStatement) {
- node.id = null;
- } else {
- this.unexpected();
- }
- }
-};
-
-pp.parseClassSuper = function (node) {
- node.superClass = this.eat(_types.types._extends) ? this.parseExprSubscripts() : null;
-};
-
-// Parses module export declaration.
-
-pp.parseExport = function (node) {
- this.next();
- // export * from '...'
- if (this.match(_types.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.types.comma) && this.lookahead().type === _types.types.star) {
- this.expect(_types.types.comma);
- var _specifier2 = this.startNode();
- this.expect(_types.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.types._default)) {
- // export default ...
- var expr = this.startNode();
- var needsSemi = false;
- if (this.eat(_types.types._function)) {
- expr = this.parseFunction(expr, true, false, false, true);
- } else if (this.match(_types.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.state.type.keyword || 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.parseExportDeclaration = function () {
- return this.parseStatement(true);
-};
-
-pp.isExportDefaultSpecifier = function () {
- if (this.match(_types.types.name)) {
- return this.state.value !== "type" && this.state.value !== "async" && this.state.value !== "interface";
- }
-
- if (!this.match(_types.types._default)) {
- return false;
- }
-
- var lookahead = this.lookahead();
- return lookahead.type === _types.types.comma || lookahead.type === _types.types.name && lookahead.value === "from";
-};
-
-pp.parseExportSpecifiersMaybe = function (node) {
- if (this.eat(_types.types.comma)) {
- node.specifiers = node.specifiers.concat(this.parseExportSpecifiers());
- }
-};
-
-pp.parseExportFrom = function (node, expect) {
- if (this.eatContextual("from")) {
- node.source = this.match(_types.types.string) ? this.parseExprAtom() : this.unexpected();
- this.checkExport(node);
- } else {
- if (expect) {
- this.unexpected();
- } else {
- node.source = null;
- }
- }
-
- this.semicolon();
-};
-
-pp.shouldParseExportDeclaration = function () {
- return this.isContextual("async");
-};
-
-pp.checkExport = function (node, checkNames, isDefault) {
- if (checkNames) {
- // Check for duplicate exports
- if (isDefault) {
- // Default exports
- this.checkDuplicateExports(node, "default", isDefault);
- } 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;
-
- var name = specifier.exported.name;
- if (name === "default") isDefault = true;
- this.checkDuplicateExports(specifier, name, isDefault);
- }
- } else if (node.declaration) {
- // Exported declarations
- if (node.declaration.type === "FunctionDeclaration" || node.declaration.type === "ClassDeclaration") {
- this.checkDuplicateExports(node, node.declaration.id.name, isDefault);
- } 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;
-
- if (declaration.id.name) {
- this.checkDuplicateExports(declaration, declaration.id.name, isDefault);
- }
- }
- }
- }
- }
-
- 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.checkDuplicateExports = function (node, name, isDefault) {
- if (this.state.exportedIdentifiers.indexOf(name) > -1) {
- this.raiseDuplicateExportError(node, name, isDefault);
- }
- this.state.exportedIdentifiers.push(name);
-};
-
-pp.raiseDuplicateExportError = function (node, name, isDefault) {
- this.raise(node.start, isDefault ? "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.parseExportSpecifiers = function () {
- var nodes = [];
- var first = true;
- var needsFrom = void 0;
-
- // export { x, y as z } [from '...']
- this.expect(_types.types.braceL);
-
- while (!this.eat(_types.types.braceR)) {
- if (first) {
- first = false;
- } else {
- this.expect(_types.types.comma);
- if (this.eat(_types.types.braceR)) break;
- }
-
- var isDefault = this.match(_types.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.parseImport = function (node) {
- this.next();
-
- // import '...'
- if (this.match(_types.types.string)) {
- node.specifiers = [];
- node.source = this.parseExprAtom();
- } else {
- node.specifiers = [];
- this.parseImportSpecifiers(node);
- this.expectContextual("from");
- node.source = this.match(_types.types.string) ? this.parseExprAtom() : this.unexpected();
- }
- this.semicolon();
- return this.finishNode(node, "ImportDeclaration");
-};
-
-// Parses a comma-separated list of module imports.
-
-pp.parseImportSpecifiers = function (node) {
- var first = true;
- if (this.match(_types.types.name)) {
- // import defaultObj, { x, y as z } from '...'
- var startPos = this.state.start,
- startLoc = this.state.startLoc;
- node.specifiers.push(this.parseImportSpecifierDefault(this.parseIdentifier(), startPos, startLoc));
- if (!this.eat(_types.types.comma)) return;
- }
-
- if (this.match(_types.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.types.braceL);
- while (!this.eat(_types.types.braceR)) {
- if (first) {
- first = false;
- } else {
- this.expect(_types.types.comma);
- if (this.eat(_types.types.braceR)) break;
- }
-
- var _specifier3 = this.startNode();
- _specifier3.imported = this.parseIdentifier(true);
- _specifier3.local = this.eatContextual("as") ? this.parseIdentifier() : _specifier3.imported.__clone();
- this.checkLVal(_specifier3.local, true, undefined, "import specifier");
- node.specifiers.push(this.finishNode(_specifier3, "ImportSpecifier"));
- }
-};
-
-pp.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");
-}; \ No newline at end of file