(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.babylon = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 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. */ "use strict"; var _interopRequireDefault = _dereq_(25)["default"]; var _index = _dereq_(5); var _index2 = _interopRequireDefault(_index); function last(stack) { return stack[stack.length - 1]; } var pp = _index2["default"].prototype; pp.addComment = function (comment) { this.state.trailingComments.push(comment); this.state.leadingComments.push(comment); }; pp.processComment = function (node) { if (node.type === "Program" && node.body.length > 0) return; var stack = this.state.commentStack; var lastChild = undefined, trailingComments = undefined, i = undefined; 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. while (stack.length > 0 && last(stack).start >= node.start) { lastChild = stack.pop(); } 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) { 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; } } } 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); }; },{"25":25,"5":5}],4:[function(_dereq_,module,exports){ /* eslint indent: 0 */ /* 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 "use strict"; var _Object$create = _dereq_(21)["default"]; var _interopRequireDefault = _dereq_(25)["default"]; var _tokenizerTypes = _dereq_(17); var _index = _dereq_(5); var _index2 = _interopRequireDefault(_index); var _utilIdentifier = _dereq_(18); var pp = _index2["default"].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.checkPropClash = function (prop, propHash) { if (prop.computed) return; var key = prop.key; var name = undefined; switch (key.type) { case "Identifier": name = key.name; break; case "StringLiteral": case "NumericLiteral": name = String(key.value); break; default: return; } if (name === "__proto__" && prop.kind === "init") { if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property"); propHash.proto = true; } }; // ### 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 initalization 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.parseExpression = function (noIn, refShorthandDefaultPos) { var startPos = this.state.start, startLoc = this.state.startLoc; var expr = this.parseMaybeAssign(noIn, refShorthandDefaultPos); if (this.match(_tokenizerTypes.types.comma)) { var node = this.startNodeAt(startPos, startLoc); node.expressions = [expr]; while (this.eat(_tokenizerTypes.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.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse) { if (this.match(_tokenizerTypes.types._yield) && this.state.inGenerator) { return this.parseYield(); } var failOnShorthandAssign = undefined; if (refShorthandDefaultPos) { failOnShorthandAssign = false; } else { refShorthandDefaultPos = { start: 0 }; failOnShorthandAssign = true; } var startPos = this.state.start; var startLoc = this.state.startLoc; if (this.match(_tokenizerTypes.types.parenL) || this.match(_tokenizerTypes.types.name)) { this.state.potentialArrowAt = this.state.start; } var left = this.parseMaybeConditional(noIn, refShorthandDefaultPos); 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(_tokenizerTypes.types.eq) ? this.toAssignable(left) : left; refShorthandDefaultPos.start = 0; // reset because shorthand default was used correctly this.checkLVal(left); if (left.extra && left.extra.parenthesized) { var errorMsg = undefined; 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.parseMaybeConditional = function (noIn, refShorthandDefaultPos) { var startPos = this.state.start, startLoc = this.state.startLoc; var expr = this.parseExprOps(noIn, refShorthandDefaultPos); if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr; if (this.eat(_tokenizerTypes.types.question)) { var node = this.startNodeAt(startPos, startLoc); node.test = expr; node.consequent = this.parseMaybeAssign(); this.expect(_tokenizerTypes.types.colon); node.alternate = this.parseMaybeAssign(noIn); return this.finishNode(node, "ConditionalExpression"); } return expr; }; // Start the precedence parser. pp.parseExprOps = function (noIn, refShorthandDefaultPos) { var startPos = this.state.start, 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.parseExprOp = function (left, leftStartPos, leftStartLoc, minPrec, noIn) { var prec = this.state.type.binop; if (prec != null && (!noIn || !this.match(_tokenizerTypes.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) { 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 === _tokenizerTypes.types.logicalOR || op === _tokenizerTypes.types.logicalAND ? "LogicalExpression" : "BinaryExpression"); return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn); } } return left; }; // Parse unary operators, both prefix and postfix. pp.parseMaybeUnary = function (refShorthandDefaultPos) { if (this.state.type.prefix) { var node = this.startNode(); var update = this.match(_tokenizerTypes.types.incDec); node.operator = this.state.value; node.prefix = true; this.next(); var argType = this.state.type; this.addExtra(node, "parenthesizedArgument", argType === _tokenizerTypes.types.parenL); node.argument = this.parseMaybeUnary(); if (refShorthandDefaultPos && refShorthandDefaultPos.start) { this.unexpected(refShorthandDefaultPos.start); } if (update) { this.checkLVal(node.argument); } 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, 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); this.next(); expr = this.finishNode(node, "UpdateExpression"); } return expr; }; // Parse call, dot, and `[]`-subscript expressions. pp.parseExprSubscripts = function (refShorthandDefaultPos) { var startPos = this.state.start, 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.parseSubscripts = function (base, startPos, startLoc, noCalls) { for (;;) { if (!noCalls && this.eat(_tokenizerTypes.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(_tokenizerTypes.types.dot)) { var node = this.startNodeAt(startPos, startLoc); node.object = base; node.property = this.parseIdentifier(true); node.computed = false; base = this.finishNode(node, "MemberExpression"); } else if (this.eat(_tokenizerTypes.types.bracketL)) { var node = this.startNodeAt(startPos, startLoc); node.object = base; node.property = this.parseExpression(); node.computed = true; this.expect(_tokenizerTypes.types.bracketR); base = this.finishNode(node, "MemberExpression"); } else if (!noCalls && this.match(_tokenizerTypes.types.parenL)) { var possibleAsync = this.state.potentialArrowAt === base.start && base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon(); this.next(); var node = this.startNodeAt(startPos, startLoc); node.callee = base; node.arguments = this.parseCallExpressionArguments(_tokenizerTypes.types.parenR, this.hasPlugin("trailingFunctionCommas"), possibleAsync); base = this.finishNode(node, "CallExpression"); if (possibleAsync && this.shouldParseAsyncArrow()) { return this.parseAsyncArrowFromCallExpression(this.startNodeAt(startPos, startLoc), node); } else { this.toReferencedList(node.arguments); } } else if (this.match(_tokenizerTypes.types.backQuote)) { var node = this.startNodeAt(startPos, startLoc); node.tag = base; node.quasi = this.parseTemplate(); base = this.finishNode(node, "TaggedTemplateExpression"); } else { return base; } } }; pp.parseCallExpressionArguments = function (close, allowTrailingComma, possibleAsyncArrow) { var innerParenStart = undefined; var elts = [], first = true; while (!this.eat(close)) { if (first) { first = false; } else { this.expect(_tokenizerTypes.types.comma); if (allowTrailingComma && 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(_tokenizerTypes.types.parenL) && !innerParenStart) { innerParenStart = this.state.start; } elts.push(this.parseExprListItem()); } // we found an async arrow function so let's not allow any inner parens if (possibleAsyncArrow && innerParenStart && this.shouldParseAsyncArrow()) { this.unexpected(); } return elts; }; pp.shouldParseAsyncArrow = function () { return this.match(_tokenizerTypes.types.arrow); }; pp.parseAsyncArrowFromCallExpression = function (node, call) { if (!this.hasPlugin("asyncFunctions")) this.unexpected(); this.expect(_tokenizerTypes.types.arrow); return this.parseArrowExpression(node, call.arguments, true); }; // Parse a no-call expression (like argument of `new` or `::` operators). pp.parseNoCallExpr = function () { var startPos = this.state.start, 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.parseExprAtom = function (refShorthandDefaultPos) { var node = undefined, canBeArrow = this.state.potentialArrowAt === this.state.start; switch (this.state.type) { case _tokenizerTypes.types._super: if (!this.state.inMethod && !this.options.allowSuperOutsideMethod) { this.raise(this.state.start, "'super' outside of function or class"); } node = this.startNode(); this.next(); if (!this.match(_tokenizerTypes.types.parenL) && !this.match(_tokenizerTypes.types.bracketL) && !this.match(_tokenizerTypes.types.dot)) { this.unexpected(); } if (this.match(_tokenizerTypes.types.parenL) && this.state.inMethod !== "constructor" && !this.options.allowSuperOutsideMethod) { this.raise(node.start, "super() outside of class constructor"); } return this.finishNode(node, "Super"); case _tokenizerTypes.types._this: node = this.startNode(); this.next(); return this.finishNode(node, "ThisExpression"); case _tokenizerTypes.types._yield: if (this.state.inGenerator) this.unexpected(); case _tokenizerTypes.types.name: node = this.startNode(); var allowAwait = this.hasPlugin("asyncFunctions") && this.state.value === "await" && this.state.inAsync; var allowYield = this.shouldAllowYieldIdentifier(); var id = this.parseIdentifier(allowAwait || allowYield); if (this.hasPlugin("asyncFunctions")) { if (id.name === "await") { if (this.state.inAsync || this.inModule) { return this.parseAwait(node); } } else if (id.name === "async" && this.match(_tokenizerTypes.types._function) && !this.canInsertSemicolon()) { this.next(); return this.parseFunction(node, false, false, true); } else if (canBeArrow && id.name === "async" && this.match(_tokenizerTypes.types.name)) { var params = [this.parseIdentifier()]; this.expect(_tokenizerTypes.types.arrow); // let foo = bar => {}; return this.parseArrowExpression(node, params, true); } } if (canBeArrow && !this.canInsertSemicolon() && this.eat(_tokenizerTypes.types.arrow)) { return this.parseArrowExpression(node, [id]); } return id; case _tokenizerTypes.types._do: if (this.hasPlugin("doExpressions")) { var _node = this.startNode(); this.next(); var oldInFunction = this.state.inFunction; var oldLabels = this.state.labels; this.state.labels = []; this.state.inFunction = false; _node.body = this.parseBlock(false, true); this.state.inFunction = oldInFunction; this.state.labels = oldLabels; return this.finishNode(_node, "DoExpression"); } case _tokenizerTypes.types.regexp: var value = this.state.value; node = this.parseLiteral(value.value, "RegExpLiteral"); node.pattern = value.pattern; node.flags = value.flags; return node; case _tokenizerTypes.types.num: return this.parseLiteral(this.state.value, "NumericLiteral"); case _tokenizerTypes.types.string: return this.parseLiteral(this.state.value, "StringLiteral"); case _tokenizerTypes.types._null: node = this.startNode(); this.next(); return this.finishNode(node, "NullLiteral"); case _tokenizerTypes.types._true:case _tokenizerTypes.types._false: node = this.startNode(); node.value = this.match(_tokenizerTypes.types._true); this.next(); return this.finishNode(node, "BooleanLiteral"); case _tokenizerTypes.types.parenL: return this.parseParenAndDistinguishExpression(null, null, canBeArrow); case _tokenizerTypes.types.bracketL: node = this.startNode(); this.next(); node.elements = this.parseExprList(_tokenizerTypes.types.bracketR, true, true, refShorthandDefaultPos); this.toReferencedList(node.elements); return this.finishNode(node, "ArrayExpression"); case _tokenizerTypes.types.braceL: return this.parseObj(false, refShorthandDefaultPos); case _tokenizerTypes.types._function: return this.parseFunctionExpression(); case _tokenizerTypes.types.at: this.parseDecorators(); case _tokenizerTypes.types._class: node = this.startNode(); this.takeDecorators(node); return this.parseClass(node, false); case _tokenizerTypes.types._new: return this.parseNew(); case _tokenizerTypes.types.backQuote: return this.parseTemplate(); case _tokenizerTypes.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.parseFunctionExpression = function () { var node = this.startNode(); var meta = this.parseIdentifier(true); if (this.state.inGenerator && this.eat(_tokenizerTypes.types.dot) && this.hasPlugin("functionSent")) { return this.parseMetaProperty(node, meta, "sent"); } else { return this.parseFunction(node, false); } }; pp.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.parseLiteral = function (value, type) { var node = this.startNode(); this.addExtra(node, "rawValue", value); this.addExtra(node, "raw", this.input.slice(this.state.start, this.state.end)); node.value = value; this.next(); return this.finishNode(node, type); }; pp.parseParenExpression = function () { this.expect(_tokenizerTypes.types.parenL); var val = this.parseExpression(); this.expect(_tokenizerTypes.types.parenR); return val; }; pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow, isAsync, allowOptionalCommaStart) { startPos = startPos || this.state.start; startLoc = startLoc || this.state.startLoc; var val = undefined; this.next(); var innerStartPos = this.state.start, innerStartLoc = this.state.startLoc; var exprList = [], first = true; var refShorthandDefaultPos = { start: 0 }, spreadStart = undefined, optionalCommaStart = undefined; while (!this.match(_tokenizerTypes.types.parenR)) { if (first) { first = false; } else { this.expect(_tokenizerTypes.types.comma); if (this.match(_tokenizerTypes.types.parenR) && this.hasPlugin("trailingFunctionCommas")) { optionalCommaStart = this.state.start; break; } } if (this.match(_tokenizerTypes.types.ellipsis)) { var spreadNodeStartPos = this.state.start, spreadNodeStartLoc = this.state.startLoc; spreadStart = this.state.start; exprList.push(this.parseParenItem(this.parseRest(), spreadNodeStartLoc, spreadNodeStartPos)); break; } else { exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem)); } } var innerEndPos = this.state.start; var innerEndLoc = this.state.startLoc; this.expect(_tokenizerTypes.types.parenR); if (canBeArrow && !this.canInsertSemicolon() && this.eat(_tokenizerTypes.types.arrow)) { for (var _i = 0; _i < exprList.length; _i++) { var param = exprList[_i]; if (param.extra && param.extra.parenthesized) this.unexpected(param.extra.parenStart); } return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, isAsync); } if (!exprList.length) { if (isAsync) { return; } else { this.unexpected(this.state.lastTokStart); } } if (optionalCommaStart && !allowOptionalCommaStart) this.unexpected(optionalCommaStart); if (spreadStart) this.unexpected(spreadStart); if (refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.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.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.parseNew = function () { var node = this.startNode(); var meta = this.parseIdentifier(true); if (this.eat(_tokenizerTypes.types.dot)) { return this.parseMetaProperty(node, meta, "target"); } node.callee = this.parseNoCallExpr(); if (this.eat(_tokenizerTypes.types.parenL)) { node.arguments = this.parseExprList(_tokenizerTypes.types.parenR, this.hasPlugin("trailingFunctionCommas")); this.toReferencedList(node.arguments); } else { node.arguments = []; } return this.finishNode(node, "NewExpression"); }; // Parse template expression. pp.parseTemplateElement = function () { var elem = this.startNode(); 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(_tokenizerTypes.types.backQuote); return this.finishNode(elem, "TemplateElement"); }; pp.parseTemplate = function () { var node = this.startNode(); this.next(); node.expressions = []; var curElt = this.parseTemplateElement(); node.quasis = [curElt]; while (!curElt.tail) { this.expect(_tokenizerTypes.types.dollarBraceL); node.expressions.push(this.parseExpression()); this.expect(_tokenizerTypes.types.braceR); node.quasis.push(curElt = this.parseTemplateElement()); } this.next(); return this.finishNode(node, "TemplateLiteral"); }; // Parse an object literal or binding pattern. pp.parseObj = function (isPattern, refShorthandDefaultPos) { var decorators = []; var propHash = _Object$create(null); var first = true; var node = this.startNode(); node.properties = []; this.next(); while (!this.eat(_tokenizerTypes.types.braceR)) { if (first) { first = false; } else { this.expect(_tokenizerTypes.types.comma); if (this.eat(_tokenizerTypes.types.braceR)) break; } while (this.match(_tokenizerTypes.types.at)) { decorators.push(this.parseDecorator()); } var prop = this.startNode(), isGenerator = false, isAsync = false, startPos = undefined, startLoc = undefined; if (decorators.length) { prop.decorators = decorators; decorators = []; } if (this.hasPlugin("objectRestSpread") && this.match(_tokenizerTypes.types.ellipsis)) { prop = this.parseSpread(); prop.type = isPattern ? "RestProperty" : "SpreadProperty"; node.properties.push(prop); continue; } prop.method = false; prop.shorthand = false; if (isPattern || refShorthandDefaultPos) { startPos = this.state.start; startLoc = this.state.startLoc; } if (!isPattern) { isGenerator = this.eat(_tokenizerTypes.types.star); } if (!isPattern && this.hasPlugin("asyncFunctions") && this.isContextual("async")) { if (isGenerator) this.unexpected(); var asyncId = this.parseIdentifier(); if (this.match(_tokenizerTypes.types.colon) || this.match(_tokenizerTypes.types.parenL) || this.match(_tokenizerTypes.types.braceR)) { prop.key = asyncId; } else { isAsync = true; if (this.hasPlugin("asyncGenerators")) isGenerator = this.eat(_tokenizerTypes.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 (decorators.length) { this.raise(this.state.start, "You have trailing decorators with no property"); } return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression"); }; pp.parseObjPropValue = function (prop, startPos, startLoc, isGenerator, isAsync, isPattern, refShorthandDefaultPos) { if (isAsync || isGenerator || this.match(_tokenizerTypes.types.parenL)) { if (isPattern) this.unexpected(); prop.kind = "method"; prop.method = true; this.parseMethod(prop, isGenerator, isAsync); return this.finishNode(prop, "ObjectMethod"); } if (this.eat(_tokenizerTypes.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" && (prop.key.name === "get" || prop.key.name === "set") && !this.match(_tokenizerTypes.types.comma) && !this.match(_tokenizerTypes.types.braceR)) { if (isGenerator || isAsync || isPattern) this.unexpected(); prop.kind = prop.key.name; this.parsePropertyName(prop); this.parseMethod(prop, false); var paramCount = prop.kind === "get" ? 0 : 1; if (prop.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"); } } return this.finishNode(prop, "ObjectMethod"); } if (!prop.computed && prop.key.type === "Identifier") { if (isPattern) { var illegalBinding = this.isKeyword(prop.key.name); if (!illegalBinding && this.state.strict) { illegalBinding = _utilIdentifier.reservedWords.strictBind(prop.key.name) || _utilIdentifier.reservedWords.strict(prop.key.name); } if (illegalBinding) { this.raise(prop.key.start, "Binding " + prop.key.name); } prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone()); } else if (this.match(_tokenizerTypes.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"); } this.unexpected(); }; pp.parsePropertyName = function (prop) { if (this.eat(_tokenizerTypes.types.bracketL)) { prop.computed = true; prop.key = this.parseMaybeAssign(); this.expect(_tokenizerTypes.types.bracketR); return prop.key; } else { prop.computed = false; return prop.key = this.match(_tokenizerTypes.types.num) || this.match(_tokenizerTypes.types.string) ? this.parseExprAtom() : this.parseIdentifier(true); } }; // Initialize empty function node. pp.initFunction = function (node, isAsync) { node.id = null; node.generator = false; node.expression = false; if (this.hasPlugin("asyncFunctions")) { node.async = !!isAsync; } }; // Parse object or class method. pp.parseMethod = function (node, isGenerator, isAsync) { var oldInMethod = this.state.inMethod; this.state.inMethod = node.kind || true; this.initFunction(node, isAsync); this.expect(_tokenizerTypes.types.parenL); node.params = this.parseBindingList(_tokenizerTypes.types.parenR, false, this.hasPlugin("trailingFunctionCommas")); node.generator = isGenerator; this.parseFunctionBody(node); this.state.inMethod = oldInMethod; return node; }; // Parse arrow function expression with given parameters. pp.parseArrowExpression = function (node, params, isAsync) { this.initFunction(node, isAsync); node.params = this.toAssignableList(params, true); this.parseFunctionBody(node, true); return this.finishNode(node, "ArrowFunctionExpression"); }; // Parse function body and check parameters. pp.parseFunctionBody = function (node, allowExpression) { var isExpression = allowExpression && !this.match(_tokenizerTypes.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, oldInGen = this.state.inGenerator, 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 checkLVal = this.state.strict; var checkLValStrict = false; var isStrict = false; // arrow function if (allowExpression) checkLVal = true; // normal function if (!isExpression && node.body.directives.length) { var _arr = node.body.directives; for (var _i2 = 0; _i2 < _arr.length; _i2++) { var directive = _arr[_i2]; if (directive.value.value === "use strict") { isStrict = true; checkLVal = true; checkLValStrict = true; break; } } } // 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 (checkLValStrict) this.state.strict = true; if (node.id) { this.checkLVal(node.id, true); } var _arr2 = node.params; for (var _i3 = 0; _i3 < _arr2.length; _i3++) { var param = _arr2[_i3]; this.checkLVal(param, true, nameHash); } 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.parseExprList = function (close, allowTrailingComma, allowEmpty, refShorthandDefaultPos) { var elts = [], first = true; while (!this.eat(close)) { if (first) { first = false; } else { this.expect(_tokenizerTypes.types.comma); if (allowTrailingComma && this.eat(close)) break; } elts.push(this.parseExprListItem(allowEmpty, refShorthandDefaultPos)); } return elts; }; pp.parseExprListItem = function (allowEmpty, refShorthandDefaultPos) { var elt = undefined; if (allowEmpty && this.match(_tokenizerTypes.types.comma)) { elt = null; } else if (this.match(_tokenizerTypes.types.ellipsis)) { elt = this.parseSpread(refShorthandDefaultPos); } else { elt = this.parseMaybeAssign(false, refShorthandDefaultPos); } 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.parseIdentifier = function (liberal) { var node = this.startNode(); if (this.match(_tokenizerTypes.types.name)) { if (!liberal && this.state.strict && _utilIdentifier.reservedWords.strict(this.state.value)) { this.raise(this.state.start, "The keyword '" + this.state.value + "' is reserved"); } node.name = this.state.value; } else if (liberal && 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"); } this.next(); return this.finishNode(node, "Identifier"); }; // Parses await expression inside async function. pp.parseAwait = function (node) { if (!this.state.inAsync) { this.unexpected(); } if (this.isLineTerminator()) { this.unexpected(); } if (this.match(_tokenizerTypes.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.parseYield = function () { var node = this.startNode(); this.next(); if (this.match(_tokenizerTypes.types.semi) || this.canInsertSemicolon() || !this.match(_tokenizerTypes.types.star) && !this.state.type.startsExpr) { node.delegate = false; node.argument = null; } else { node.delegate = this.eat(_tokenizerTypes.types.star); node.argument = this.parseMaybeAssign(); } return this.finishNode(node, "YieldExpression"); }; },{"17":17,"18":18,"21":21,"25":25,"5":5}],5:[function(_dereq_,module,exports){ "use strict"; var _inherits = _dereq_(24)["default"]; var _classCallCheck = _dereq_(23)["default"]; var _interopRequireDefault = _dereq_(25)["default"]; exports.__esModule = true; var _utilIdentifier = _dereq_(18); var _options = _dereq_(2); var _tokenizer = _dereq_(15); var _tokenizer2 = _interopRequireDefault(_tokenizer); var plugins = {}; exports.plugins = plugins; var Parser = (function (_Tokenizer) { _inherits(Parser, _Tokenizer); function Parser(options, input) { _classCallCheck(this, Parser); options = _options.getOptions(options); _Tokenizer.call(this, options, input); this.options = options; this.inModule = this.options.sourceType === "module"; this.isReservedWord = _utilIdentifier.reservedWords[6]; this.input = input; this.plugins = this.loadPlugins(this.options.plugins); this.filename = options.sourceFilename; // If enabled, skip leading hashbang line. if (this.state.pos === 0 && this.input[0] === "#" && this.input[1] === "!") { this.skipLineComment(2); } } Parser.prototype.hasPlugin = function hasPlugin(name) { return !!(this.plugins["*"] || this.plugins[name]); }; Parser.prototype.extend = function extend(name, f) { this[name] = f(this[name]); }; Parser.prototype.loadPlugins = function loadPlugins(plugins) { var pluginMap = {}; if (plugins.indexOf("flow") >= 0) { // ensure flow plugin loads last plugins = plugins.filter(function (plugin) { return plugin !== "flow"; }); plugins.push("flow"); } for (var _i = 0; _i < plugins.length; _i++) { var _name = plugins[_i]; if (!pluginMap[_name]) { pluginMap[_name] = true; var plugin = exports.plugins[_name]; if (plugin) plugin(this); } } return pluginMap; }; Parser.prototype.parse = function parse() { var file = this.startNode(); var program = this.startNode(); this.nextToken(); return this.parseTopLevel(file, program); }; return Parser; })(_tokenizer2["default"]); exports["default"] = Parser; },{"15":15,"18":18,"2":2,"23":23,"24":24,"25":25}],6:[function(_dereq_,module,exports){ "use strict"; var _interopRequireDefault = _dereq_(25)["default"]; var _utilLocation = _dereq_(19); var _index = _dereq_(5); var _index2 = _interopRequireDefault(_index); var pp = _index2["default"].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.raise = function (pos, message) { var loc = _utilLocation.getLineInfo(this.input, pos); message += " (" + loc.line + ":" + loc.column + ")"; var err = new SyntaxError(message); err.pos = pos; err.loc = loc; throw err; }; },{"19":19,"25":25,"5":5}],7:[function(_dereq_,module,exports){ /* eslint indent: 0 */ "use strict"; var _interopRequireDefault = _dereq_(25)["default"]; var _tokenizerTypes = _dereq_(17); var _index = _dereq_(5); var _index2 = _interopRequireDefault(_index); var _utilIdentifier = _dereq_(18); var pp = _index2["default"].prototype; // Convert existing expression atom to assignable pattern // if possible. pp.toAssignable = function (node, isBinding) { if (node) { switch (node.type) { case "Identifier": case "ObjectPattern": case "ArrayPattern": case "AssignmentPattern": break; case "ObjectExpression": node.type = "ObjectPattern"; var _arr = node.properties; for (var _i = 0; _i < _arr.length; _i++) { var prop = _arr[_i]; 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); } } break; case "ObjectProperty": this.toAssignable(node.value, isBinding); break; case "SpreadProperty": node.type = "RestProperty"; break; case "ArrayExpression": node.type = "ArrayPattern"; this.toAssignableList(node.elements, isBinding); 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: this.raise(node.start, "Assigning to rvalue"); } } return node; }; // Convert list of expression atoms to binding list. pp.toAssignableList = function (exprList, isBinding) { 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); 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); } return exprList; }; // Convert list of expression atoms to a list of pp.toReferencedList = function (exprList) { return exprList; }; // Parses spread element. pp.parseSpread = function (refShorthandDefaultPos) { var node = this.startNode(); this.next(); node.argument = this.parseMaybeAssign(refShorthandDefaultPos); return this.finishNode(node, "SpreadElement"); }; pp.parseRest = function () { var node = this.startNode(); this.next(); node.argument = this.parseBindingIdentifier(); return this.finishNode(node, "RestElement"); }; pp.shouldAllowYieldIdentifier = function () { return this.match(_tokenizerTypes.types._yield) && !this.state.strict && !this.state.inGenerator; }; pp.parseBindingIdentifier = function () { return this.parseIdentifier(this.shouldAllowYieldIdentifier()); }; // Parses lvalue (assignable) atom. pp.parseBindingAtom = function () { switch (this.state.type) { case _tokenizerTypes.types._yield: if (this.state.strict || this.state.inGenerator) this.unexpected(); case _tokenizerTypes.types.name: return this.parseIdentifier(true); case _tokenizerTypes.types.bracketL: var node = this.startNode(); this.next(); node.elements = this.parseBindingList(_tokenizerTypes.types.bracketR, true, true); return this.finishNode(node, "ArrayPattern"); case _tokenizerTypes.types.braceL: return this.parseObj(true); default: this.unexpected(); } }; pp.parseBindingList = function (close, allowEmpty, allowTrailingComma) { var elts = []; var first = true; while (!this.eat(close)) { if (first) { first = false; } else { this.expect(_tokenizerTypes.types.comma); } if (allowEmpty && this.match(_tokenizerTypes.types.comma)) { elts.push(null); } else if (allowTrailingComma && this.eat(close)) { break; } else if (this.match(_tokenizerTypes.types.ellipsis)) { elts.push(this.parseAssignableListItemTypes(this.parseRest())); this.expect(close); break; } else { var left = this.parseMaybeDefault(); this.parseAssignableListItemTypes(left); elts.push(this.parseMaybeDefault(null, null, left)); } } return elts; }; pp.parseAssignableListItemTypes = function (param) { return param; }; // Parses assignment pattern around given atom if possible. pp.parseMaybeDefault = function (startPos, startLoc, left) { startLoc = startLoc || this.state.startLoc; startPos = startPos || this.state.start; left = left || this.parseBindingAtom(); if (!this.eat(_tokenizerTypes.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.checkLVal = function (expr, isBinding, checkClashes) { switch (expr.type) { case "Identifier": if (this.state.strict && (_utilIdentifier.reservedWords.strictBind(expr.name) || _utilIdentifier.reservedWords.strict(expr.name))) { this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } 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": var _arr2 = expr.properties; for (var _i2 = 0; _i2 < _arr2.length; _i2++) { var prop = _arr2[_i2]; if (prop.type === "ObjectProperty") prop = prop.value; this.checkLVal(prop, isBinding, checkClashes); } break; case "ArrayPattern": var _arr3 = expr.elements; for (var _i3 = 0; _i3 < _arr3.length; _i3++) { var elem = _arr3[_i3]; if (elem) this.checkLVal(elem, isBinding, checkClashes); } break; case "AssignmentPattern": this.checkLVal(expr.left, isBinding, checkClashes); break; case "RestProperty": case "RestElement": this.checkLVal(expr.argument, isBinding, checkClashes); break; default: this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue"); } }; },{"17":17,"18":18,"25":25,"5":5}],8:[function(_dereq_,module,exports){ "use strict"; var _classCallCheck = _dereq_(23)["default"]; var _interopRequireDefault = _dereq_(25)["default"]; var _index = _dereq_(5); var _index2 = _interopRequireDefault(_index); var _utilLocation = _dereq_(19); // Start an AST node, attaching a start offset. var pp = _index2["default"].prototype; var Node = (function () { function Node(pos, loc, filename) { _classCallCheck(this, Node); this.type = ""; this.start = pos; this.end = 0; this.loc = new _utilLocation.SourceLocation(loc); if (filename) this.loc.filename = filename; } Node.prototype.__clone = function __clone() { var node2 = new Node(); for (var key in this) { node2[key] = this[key]; }return node2; }; return Node; })(); pp.startNode = function () { return new Node(this.state.start, this.state.startLoc, this.filename); }; pp.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.finishNode = function (node, type) { return finishNodeAt.call(this, node, type, this.state.lastTokEnd, this.state.lastTokEndLoc); }; // Finish node at given position pp.finishNodeAt = function (node, type, pos, loc) { return finishNodeAt.call(this, node, type, pos, loc); }; },{"19":19,"23":23,"25":25,"5":5}],9:[function(_dereq_,module,exports){ /* eslint indent: 0 */ /* eslint max-len: 0 */ "use strict"; var _Object$create = _dereq_(21)["default"]; var _interopRequireDefault = _dereq_(25)["default"]; var _tokenizerTypes = _dereq_(17); var _index = _dereq_(5); var _index2 = _interopRequireDefault(_index); var _utilWhitespace = _dereq_(20); 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. pp.parseTopLevel = function (file, program) { program.sourceType = this.options.sourceType; this.parseBlockBody(program, true, true, _tokenizerTypes.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(_tokenizerTypes.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 _tokenizerTypes.types._break:case _tokenizerTypes.types._continue: return this.parseBreakContinueStatement(node, starttype.keyword); case _tokenizerTypes.types._debugger: return this.parseDebuggerStatement(node); case _tokenizerTypes.types._do: return this.parseDoStatement(node); case _tokenizerTypes.types._for: return this.parseForStatement(node); case _tokenizerTypes.types._function: if (!declaration) this.unexpected(); return this.parseFunctionStatement(node); case _tokenizerTypes.types._class: if (!declaration) this.unexpected(); this.takeDecorators(node); return this.parseClass(node, true); case _tokenizerTypes.types._if: return this.parseIfStatement(node); case _tokenizerTypes.types._return: return this.parseReturnStatement(node); case _tokenizerTypes.types._switch: return this.parseSwitchStatement(node); case _tokenizerTypes.types._throw: return this.parseThrowStatement(node); case _tokenizerTypes.types._try: return this.parseTryStatement(node); case _tokenizerTypes.types._let: case _tokenizerTypes.types._const: if (!declaration) this.unexpected(); // NOTE: falls through to _var case _tokenizerTypes.types._var: return this.parseVarStatement(node, starttype); case _tokenizerTypes.types._while: return this.parseWhileStatement(node); case _tokenizerTypes.types._with: return this.parseWithStatement(node); case _tokenizerTypes.types.braceL: return this.parseBlock(); case _tokenizerTypes.types.semi: return this.parseEmptyStatement(node); case _tokenizerTypes.types._export: case _tokenizerTypes.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 === _tokenizerTypes.types._import ? this.parseImport(node) : this.parseExport(node); case _tokenizerTypes.types.name: if (this.hasPlugin("asyncFunctions") && this.state.value === "async") { // peek ahead and see if next token is a function var state = this.state.clone(); this.next(); if (this.match(_tokenizerTypes.types._function) && !this.canInsertSemicolon()) { this.expect(_tokenizerTypes.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 === _tokenizerTypes.types.name && expr.type === "Identifier" && this.eat(_tokenizerTypes.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(_tokenizerTypes.types.at)) { this.state.decorators.push(this.parseDecorator()); } if (allowExport && this.match(_tokenizerTypes.types._export)) { return; } if (!this.match(_tokenizerTypes.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(_tokenizerTypes.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 = undefined; 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(_tokenizerTypes.types._while); node.test = this.parseParenExpression(); this.eat(_tokenizerTypes.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); this.expect(_tokenizerTypes.types.parenL); if (this.match(_tokenizerTypes.types.semi)) { return this.parseFor(node, null); } if (this.match(_tokenizerTypes.types._var) || this.match(_tokenizerTypes.types._let) || this.match(_tokenizerTypes.types._const)) { var _init = this.startNode(), varKind = this.state.type; this.next(); this.parseVar(_init, true, varKind); this.finishNode(_init, "VariableDeclaration"); if (this.match(_tokenizerTypes.types._in) || this.isContextual("of")) { if (_init.declarations.length === 1 && !_init.declarations[0].init) { return this.parseForIn(node, _init); } } return this.parseFor(node, _init); } var refShorthandDefaultPos = { start: 0 }; var init = this.parseExpression(true, refShorthandDefaultPos); if (this.match(_tokenizerTypes.types._in) || this.isContextual("of")) { this.toAssignable(init); this.checkLVal(init); return this.parseForIn(node, init); } else if (refShorthandDefaultPos.start) { this.unexpected(refShorthandDefaultPos.start); } 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(_tokenizerTypes.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(_tokenizerTypes.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 = undefined; for (var sawDefault = undefined; !this.match(_tokenizerTypes.types.braceR);) { if (this.match(_tokenizerTypes.types._case) || this.match(_tokenizerTypes.types._default)) { var isCase = this.match(_tokenizerTypes.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(_tokenizerTypes.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 (_utilWhitespace.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(_tokenizerTypes.types._catch)) { var clause = this.startNode(); this.next(); this.expect(_tokenizerTypes.types.parenL); clause.param = this.parseBindingAtom(); this.checkLVal(clause.param, true, _Object$create(null)); this.expect(_tokenizerTypes.types.parenR); clause.body = this.parseBlock(); node.handler = this.finishNode(clause, "CatchClause"); } node.guardedHandlers = empty; node.finalizer = this.eat(_tokenizerTypes.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) { var _arr = this.state.labels; for (var _i = 0; _i < _arr.length; _i++) { var label = _arr[_i]; if (label.name === maybeName) { this.raise(expr.start, "Label '" + maybeName + "' is already declared"); } } var kind = this.state.type.isLoop ? "loop" : this.match(_tokenizerTypes.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(_tokenizerTypes.types.braceL); this.parseBlockBody(node, allowDirectives, false, _tokenizerTypes.types.braceR); return this.finishNode(node, "BlockStatement"); }; // TODO pp.parseBlockBody = function (node, allowDirectives, topLevel, end) { node.body = []; node.directives = []; var parsedNonDirective = false; var oldStrict = undefined; var octalPosition = undefined; 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(_tokenizerTypes.types.semi); node.test = this.match(_tokenizerTypes.types.semi) ? null : this.parseExpression(); this.expect(_tokenizerTypes.types.semi); node.update = this.match(_tokenizerTypes.types.parenR) ? null : this.parseExpression(); this.expect(_tokenizerTypes.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) { var type = this.match(_tokenizerTypes.types._in) ? "ForInStatement" : "ForOfStatement"; this.next(); node.left = init; node.right = this.parseExpression(); this.expect(_tokenizerTypes.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(_tokenizerTypes.types.eq)) { decl.init = this.parseMaybeAssign(isFor); } else if (kind === _tokenizerTypes.types._const && !(this.match(_tokenizerTypes.types._in) || this.isContextual("of"))) { this.unexpected(); } else if (decl.id.type !== "Identifier" && !(isFor && (this.match(_tokenizerTypes.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(_tokenizerTypes.types.comma)) break; } return node; }; pp.parseVarHead = function (decl) { decl.id = this.parseBindingAtom(); this.checkLVal(decl.id, true); }; // 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(_tokenizerTypes.types.star)) { if (node.async && !this.hasPlugin("asyncGenerators")) { this.unexpected(); } else { node.generator = true; this.next(); } } if (isStatement && !optionalId && !this.match(_tokenizerTypes.types.name) && !this.match(_tokenizerTypes.types._yield)) { this.unexpected(); } if (this.match(_tokenizerTypes.types.name) || this.match(_tokenizerTypes.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(_tokenizerTypes.types.parenL); node.params = this.parseBindingList(_tokenizerTypes.types.parenR, false, this.hasPlugin("trailingFunctionCommas")); }; // 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(_tokenizerTypes.types.eq) || this.isLineTerminator(); }; 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(_tokenizerTypes.types.braceL); while (!this.eat(_tokenizerTypes.types.braceR)) { if (this.eat(_tokenizerTypes.types.semi)) { continue; } if (this.match(_tokenizerTypes.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(_tokenizerTypes.types.name) && this.state.value === "static"; var isGenerator = this.eat(_tokenizerTypes.types.star); var isGetSet = false; var isAsync = false; this.parsePropertyName(method); method["static"] = isMaybeStatic && !this.match(_tokenizerTypes.types.parenL); if (method["static"]) { if (isGenerator) this.unexpected(); isGenerator = this.eat(_tokenizerTypes.types.star); this.parsePropertyName(method); } if (!isGenerator && method.key.type === "Identifier" && !method.computed) { if (this.isClassProperty()) { classBody.body.push(this.parseClassProperty(method)); continue; } if (this.hasPlugin("classConstructorCall") && method.key.name === "call" && this.match(_tokenizerTypes.types.name) && this.state.value === "constructor") { isConstructorCall = true; this.parsePropertyName(method); } } var isAsyncMethod = this.hasPlugin("asyncFunctions") && !this.match(_tokenizerTypes.types.parenL) && !method.computed && method.key.type === "Identifier" && method.key.name === "async"; if (isAsyncMethod) { if (this.hasPlugin("asyncGenerators") && this.eat(_tokenizerTypes.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 && key.type === "Identifier" && !this.match(_tokenizerTypes.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(_tokenizerTypes.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(_tokenizerTypes.types.name)) { node.id = this.parseIdentifier(); } else { if (optionalId || !isStatement) { node.id = null; } else { this.unexpected(); } } }; pp.parseClassSuper = function (node) { node.superClass = this.eat(_tokenizerTypes.types._extends) ? this.parseExprSubscripts() : null; }; // Parses module export declaration. pp.parseExport = function (node) { this.next(); // export * from '...' if (this.match(_tokenizerTypes.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(_tokenizerTypes.types.comma) && this.lookahead().type === _tokenizerTypes.types.star) { this.expect(_tokenizerTypes.types.comma); var _specifier = this.startNode(); this.expect(_tokenizerTypes.types.star); this.expectContextual("as"); _specifier.exported = this.parseIdentifier(); node.specifiers.push(this.finishNode(_specifier, "ExportNamespaceSpecifier")); } else { this.parseExportSpecifiersMaybe(node); } this.parseExportFrom(node, true); } else if (this.eat(_tokenizerTypes.types._default)) { // export default ... var expr = this.startNode(); var needsSemi = false; if (this.eat(_tokenizerTypes.types._function)) { expr = this.parseFunction(expr, true, false, false, true); } else if (this.match(_tokenizerTypes.types._class)) { expr = this.parseClass(expr, true, true); } else { needsSemi = true; expr = this.parseMaybeAssign(); } node.declaration = expr; if (needsSemi) this.semicolon(); this.checkExport(node); 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); return this.finishNode(node, "ExportNamedDeclaration"); }; pp.parseExportDeclaration = function () { return this.parseStatement(true); }; pp.isExportDefaultSpecifier = function () { if (this.match(_tokenizerTypes.types.name)) { return this.state.value !== "type" && this.state.value !== "async" && this.state.value !== "interface"; } if (!this.match(_tokenizerTypes.types._default)) { return false; } var lookahead = this.lookahead(); return lookahead.type === _tokenizerTypes.types.comma || lookahead.type === _tokenizerTypes.types.name && lookahead.value === "from"; }; pp.parseExportSpecifiersMaybe = function (node) { if (this.eat(_tokenizerTypes.types.comma)) { node.specifiers = node.specifiers.concat(this.parseExportSpecifiers()); } }; pp.parseExportFrom = function (node, expect) { if (this.eatContextual("from")) { node.source = this.match(_tokenizerTypes.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.hasPlugin("asyncFunctions") && this.isContextual("async"); }; pp.checkExport = function (node) { 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); } }; // Parses a comma-separated list of module exports. pp.parseExportSpecifiers = function () { var nodes = []; var first = true; var needsFrom = undefined; // export { x, y as z } [from '...'] this.expect(_tokenizerTypes.types.braceL); while (!this.eat(_tokenizerTypes.types.braceR)) { if (first) { first = false; } else { this.expect(_tokenizerTypes.types.comma); if (this.eat(_tokenizerTypes.types.braceR)) break; } var isDefault = this.match(_tokenizerTypes.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(_tokenizerTypes.types.string)) { node.specifiers = []; node.source = this.parseExprAtom(); } else { node.specifiers = []; this.parseImportSpecifiers(node); this.expectContextual("from"); node.source = this.match(_tokenizerTypes.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(_tokenizerTypes.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(_tokenizerTypes.types.comma)) return; } if (this.match(_tokenizerTypes.types.star)) { var specifier = this.startNode(); this.next(); this.expectContextual("as"); specifier.local = this.parseIdentifier(); this.checkLVal(specifier.local, true); node.specifiers.push(this.finishNode(specifier, "ImportNamespaceSpecifier")); return; } this.expect(_tokenizerTypes.types.braceL); while (!this.eat(_tokenizerTypes.types.braceR)) { if (first) { first = false; } else { this.expect(_tokenizerTypes.types.comma); if (this.eat(_tokenizerTypes.types.braceR)) break; } var specifier = this.startNode(); specifier.imported = this.parseIdentifier(true); specifier.local = this.eatContextual("as") ? this.parseIdentifier() : specifier.imported.__clone(); this.checkLVal(specifier.local, true); node.specifiers.push(this.finishNode(specifier, "ImportSpecifier")); } }; pp.parseImportSpecifierDefault = function (id, startPos, startLoc) { var node = this.startNodeAt(startPos, startLoc); node.local = id; this.checkLVal(node.local, true); return this.finishNode(node, "ImportDefaultSpecifier"); }; },{"17":17,"20":20,"21":21,"25":25,"5":5}],10:[function(_dereq_,module,exports){ "use strict"; var _interopRequireDefault = _dereq_(25)["default"]; var _tokenizerTypes = _dereq_(17); var _index = _dereq_(5); var _index2 = _interopRequireDefault(_index); var _utilWhitespace = _dereq_(20); var pp = _index2["default"].prototype; // ## Parser utilities // TODO pp.addExtra = function (node, key, val) { if (!node) return; var extra = node.extra = node.extra || {}; extra[key] = val; }; // TODO pp.isRelational = function (op) { return this.match(_tokenizerTypes.types.relational) && this.state.value === op; }; // TODO pp.expectRelational = function (op) { if (this.isRelational(op)) { this.next(); } else { this.unexpected(); } }; // Tests whether parsed token is a contextual keyword. pp.isContextual = function (name) { return this.match(_tokenizerTypes.types.name) && this.state.value === name; }; // Consumes contextual keyword if possible. pp.eatContextual = function (name) { return this.state.value === name && this.eat(_tokenizerTypes.types.name); }; // Asserts that following token is given contextual keyword. pp.expectContextual = function (name) { if (!this.eatContextual(name)) this.unexpected(); }; // Test whether a semicolon can be inserted at the current position. pp.canInsertSemicolon = function () { return this.match(_tokenizerTypes.types.eof) || this.match(_tokenizerTypes.types.braceR) || _utilWhitespace.lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.start)); }; // TODO pp.isLineTerminator = function () { return this.eat(_tokenizerTypes.types.semi) || this.canInsertSemicolon(); }; // Consume a semicolon, or, failing that, see if we are allowed to // pretend that there is a semicolon at this position. pp.semicolon = function () { if (!this.isLineTerminator()) this.unexpected(); }; // Expect a token of a given type. If found, consume it, otherwise, // raise an unexpected token error. pp.expect = function (type) { return this.eat(type) || this.unexpected(); }; // Raise an unexpected token error. pp.unexpected = function (pos) { this.raise(pos != null ? pos : this.state.start, "Unexpected token"); }; },{"17":17,"20":20,"25":25,"5":5}],11:[function(_dereq_,module,exports){ /* eslint indent: 0 */ /* eslint max-len: 0 */ "use strict"; var _interopRequireDefault = _dereq_(25)["default"]; exports.__esModule = true; var _tokenizerTypes = _dereq_(17); var _parser = _dereq_(5); var _parser2 = _interopRequireDefault(_parser); var pp = _parser2["default"].prototype; pp.flowParseTypeInitialiser = function (tok, allowLeadingPipeOrAnd) { var oldInType = this.state.inType; this.state.inType = true; this.expect(tok || _tokenizerTypes.types.colon); if (allowLeadingPipeOrAnd) { if (this.match(_tokenizerTypes.types.bitwiseAND) || this.match(_tokenizerTypes.types.bitwiseOR)) { this.next(); } } var type = this.flowParseType(); this.state.inType = oldInType; return type; }; pp.flowParseDeclareClass = function (node) { this.next(); this.flowParseInterfaceish(node, true); return this.finishNode(node, "DeclareClass"); }; pp.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(_tokenizerTypes.types.parenL); var tmp = this.flowParseFunctionTypeParams(); typeNode.params = tmp.params; typeNode.rest = tmp.rest; this.expect(_tokenizerTypes.types.parenR); typeNode.returnType = this.flowParseTypeInitialiser(); typeContainer.typeAnnotation = this.finishNode(typeNode, "FunctionTypeAnnotation"); id.typeAnnotation = this.finishNode(typeContainer, "TypeAnnotation"); this.finishNode(id, id.type); this.semicolon(); return this.finishNode(node, "DeclareFunction"); }; pp.flowParseDeclare = function (node) { if (this.match(_tokenizerTypes.types._class)) { return this.flowParseDeclareClass(node); } else if (this.match(_tokenizerTypes.types._function)) { return this.flowParseDeclareFunction(node); } else if (this.match(_tokenizerTypes.types._var)) { return this.flowParseDeclareVariable(node); } else if (this.isContextual("module")) { return this.flowParseDeclareModule(node); } else if (this.isContextual("type")) { return this.flowParseDeclareTypeAlias(node); } else if (this.isContextual("interface")) { return this.flowParseDeclareInterface(node); } else { this.unexpected(); } }; pp.flowParseDeclareVariable = function (node) { this.next(); node.id = this.flowParseTypeAnnotatableIdentifier(); this.semicolon(); return this.finishNode(node, "DeclareVariable"); }; pp.flowParseDeclareModule = function (node) { this.next(); if (this.match(_tokenizerTypes.types.string)) { node.id = this.parseExprAtom(); } else { node.id = this.parseIdentifier(); } var bodyNode = node.body = this.startNode(); var body = bodyNode.body = []; this.expect(_tokenizerTypes.types.braceL); while (!this.match(_tokenizerTypes.types.braceR)) { var node2 = this.startNode(); // todo: declare check this.next(); body.push(this.flowParseDeclare(node2)); } this.expect(_tokenizerTypes.types.braceR); this.finishNode(bodyNode, "BlockStatement"); return this.finishNode(node, "DeclareModule"); }; pp.flowParseDeclareTypeAlias = function (node) { this.next(); this.flowParseTypeAlias(node); return this.finishNode(node, "DeclareTypeAlias"); }; pp.flowParseDeclareInterface = function (node) { this.next(); this.flowParseInterfaceish(node); return this.finishNode(node, "DeclareInterface"); }; // Interfaces pp.flowParseInterfaceish = function (node, allowStatic) { node.id = this.parseIdentifier(); if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterDeclaration(); } else { node.typeParameters = null; } node["extends"] = []; node.mixins = []; if (this.eat(_tokenizerTypes.types._extends)) { do { node["extends"].push(this.flowParseInterfaceExtends()); } while (this.eat(_tokenizerTypes.types.comma)); } if (this.isContextual("mixins")) { this.next(); do { node.mixins.push(this.flowParseInterfaceExtends()); } while (this.eat(_tokenizerTypes.types.comma)); } node.body = this.flowParseObjectType(allowStatic); }; pp.flowParseInterfaceExtends = function () { var node = this.startNode(); node.id = this.parseIdentifier(); if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterInstantiation(); } else { node.typeParameters = null; } return this.finishNode(node, "InterfaceExtends"); }; pp.flowParseInterface = function (node) { this.flowParseInterfaceish(node, false); return this.finishNode(node, "InterfaceDeclaration"); }; // Type aliases pp.flowParseTypeAlias = function (node) { node.id = this.parseIdentifier(); if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterDeclaration(); } else { node.typeParameters = null; } node.right = this.flowParseTypeInitialiser(_tokenizerTypes.types.eq, /*allowLeadingPipeOrAnd*/true); this.semicolon(); return this.finishNode(node, "TypeAlias"); }; // Type annotations pp.flowParseTypeParameterDeclaration = function () { var node = this.startNode(); node.params = []; this.expectRelational("<"); while (!this.isRelational(">")) { node.params.push(this.flowParseExistentialTypeParam() || this.flowParseTypeAnnotatableIdentifier()); if (!this.isRelational(">")) { this.expect(_tokenizerTypes.types.comma); } } this.expectRelational(">"); return this.finishNode(node, "TypeParameterDeclaration"); }; pp.flowParseExistentialTypeParam = function () { if (this.match(_tokenizerTypes.types.star)) { var node = this.startNode(); this.next(); return this.finishNode(node, "ExistentialTypeParam"); } }; pp.flowParseTypeParameterInstantiation = function () { var node = this.startNode(), oldInType = this.state.inType; node.params = []; this.state.inType = true; this.expectRelational("<"); while (!this.isRelational(">")) { node.params.push(this.flowParseExistentialTypeParam() || this.flowParseType()); if (!this.isRelational(">")) { this.expect(_tokenizerTypes.types.comma); } } this.expectRelational(">"); this.state.inType = oldInType; return this.finishNode(node, "TypeParameterInstantiation"); }; pp.flowParseObjectPropertyKey = function () { return this.match(_tokenizerTypes.types.num) || this.match(_tokenizerTypes.types.string) ? this.parseExprAtom() : this.parseIdentifier(true); }; pp.flowParseObjectTypeIndexer = function (node, isStatic) { node["static"] = isStatic; this.expect(_tokenizerTypes.types.bracketL); node.id = this.flowParseObjectPropertyKey(); node.key = this.flowParseTypeInitialiser(); this.expect(_tokenizerTypes.types.bracketR); node.value = this.flowParseTypeInitialiser(); this.flowObjectTypeSemicolon(); return this.finishNode(node, "ObjectTypeIndexer"); }; pp.flowParseObjectTypeMethodish = function (node) { node.params = []; node.rest = null; node.typeParameters = null; if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterDeclaration(); } this.expect(_tokenizerTypes.types.parenL); while (this.match(_tokenizerTypes.types.name)) { node.params.push(this.flowParseFunctionTypeParam()); if (!this.match(_tokenizerTypes.types.parenR)) { this.expect(_tokenizerTypes.types.comma); } } if (this.eat(_tokenizerTypes.types.ellipsis)) { node.rest = this.flowParseFunctionTypeParam(); } this.expect(_tokenizerTypes.types.parenR); node.returnType = this.flowParseTypeInitialiser(); return this.finishNode(node, "FunctionTypeAnnotation"); }; pp.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.flowParseObjectTypeCallProperty = function (node, isStatic) { var valueNode = this.startNode(); node["static"] = isStatic; node.value = this.flowParseObjectTypeMethodish(valueNode); this.flowObjectTypeSemicolon(); return this.finishNode(node, "ObjectTypeCallProperty"); }; pp.flowParseObjectType = function (allowStatic) { var nodeStart = this.startNode(); var node = undefined; var propertyKey = undefined; var isStatic = undefined; nodeStart.callProperties = []; nodeStart.properties = []; nodeStart.indexers = []; this.expect(_tokenizerTypes.types.braceL); while (!this.match(_tokenizerTypes.types.braceR)) { var optional = false; var startPos = this.state.start, startLoc = this.state.startLoc; node = this.startNode(); if (allowStatic && this.isContextual("static")) { this.next(); isStatic = true; } if (this.match(_tokenizerTypes.types.bracketL)) { nodeStart.indexers.push(this.flowParseObjectTypeIndexer(node, isStatic)); } else if (this.match(_tokenizerTypes.types.parenL) || this.isRelational("<")) { nodeStart.callProperties.push(this.flowParseObjectTypeCallProperty(node, allowStatic)); } else { if (isStatic && this.match(_tokenizerTypes.types.colon)) { propertyKey = this.parseIdentifier(); } else { propertyKey = this.flowParseObjectPropertyKey(); } if (this.isRelational("<") || this.match(_tokenizerTypes.types.parenL)) { // This is a method property nodeStart.properties.push(this.flowParseObjectTypeMethod(startPos, startLoc, isStatic, propertyKey)); } else { if (this.eat(_tokenizerTypes.types.question)) { optional = true; } node.key = propertyKey; node.value = this.flowParseTypeInitialiser(); node.optional = optional; node["static"] = isStatic; this.flowObjectTypeSemicolon(); nodeStart.properties.push(this.finishNode(node, "ObjectTypeProperty")); } } } this.expect(_tokenizerTypes.types.braceR); return this.finishNode(nodeStart, "ObjectTypeAnnotation"); }; pp.flowObjectTypeSemicolon = function () { if (!this.eat(_tokenizerTypes.types.semi) && !this.eat(_tokenizerTypes.types.comma) && !this.match(_tokenizerTypes.types.braceR)) { this.unexpected(); } }; pp.flowParseGenericType = function (startPos, startLoc, id) { var node = this.startNodeAt(startPos, startLoc); node.typeParameters = null; node.id = id; while (this.eat(_tokenizerTypes.types.dot)) { var node2 = this.startNodeAt(startPos, startLoc); node2.qualification = node.id; node2.id = this.parseIdentifier(); node.id = this.finishNode(node2, "QualifiedTypeIdentifier"); } if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterInstantiation(); } return this.finishNode(node, "GenericTypeAnnotation"); }; pp.flowParseTypeofType = function () { var node = this.startNode(); this.expect(_tokenizerTypes.types._typeof); node.argument = this.flowParsePrimaryType(); return this.finishNode(node, "TypeofTypeAnnotation"); }; pp.flowParseTupleType = function () { var node = this.startNode(); node.types = []; this.expect(_tokenizerTypes.types.bracketL); // We allow trailing commas while (this.state.pos < this.input.length && !this.match(_tokenizerTypes.types.bracketR)) { node.types.push(this.flowParseType()); if (this.match(_tokenizerTypes.types.bracketR)) break; this.expect(_tokenizerTypes.types.comma); } this.expect(_tokenizerTypes.types.bracketR); return this.finishNode(node, "TupleTypeAnnotation"); }; pp.flowParseFunctionTypeParam = function () { var optional = false; var node = this.startNode(); node.name = this.parseIdentifier(); if (this.eat(_tokenizerTypes.types.question)) { optional = true; } node.optional = optional; node.typeAnnotation = this.flowParseTypeInitialiser(); return this.finishNode(node, "FunctionTypeParam"); }; pp.flowParseFunctionTypeParams = function () { var ret = { params: [], rest: null }; while (this.match(_tokenizerTypes.types.name)) { ret.params.push(this.flowParseFunctionTypeParam()); if (!this.match(_tokenizerTypes.types.parenR)) { this.expect(_tokenizerTypes.types.comma); } } if (this.eat(_tokenizerTypes.types.ellipsis)) { ret.rest = this.flowParseFunctionTypeParam(); } return ret; }; pp.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 "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.flowParsePrimaryType = function () { var startPos = this.state.start, startLoc = this.state.startLoc; var node = this.startNode(); var tmp = undefined; var type = undefined; var isGroupedType = false; switch (this.state.type) { case _tokenizerTypes.types.name: return this.flowIdentToTypeAnnotation(startPos, startLoc, node, this.parseIdentifier()); case _tokenizerTypes.types.braceL: return this.flowParseObjectType(); case _tokenizerTypes.types.bracketL: return this.flowParseTupleType(); case _tokenizerTypes.types.relational: if (this.state.value === "<") { node.typeParameters = this.flowParseTypeParameterDeclaration(); this.expect(_tokenizerTypes.types.parenL); tmp = this.flowParseFunctionTypeParams(); node.params = tmp.params; node.rest = tmp.rest; this.expect(_tokenizerTypes.types.parenR); this.expect(_tokenizerTypes.types.arrow); node.returnType = this.flowParseType(); return this.finishNode(node, "FunctionTypeAnnotation"); } case _tokenizerTypes.types.parenL: this.next(); // Check to see if this is actually a grouped type if (!this.match(_tokenizerTypes.types.parenR) && !this.match(_tokenizerTypes.types.ellipsis)) { if (this.match(_tokenizerTypes.types.name)) { var token = this.lookahead().type; isGroupedType = token !== _tokenizerTypes.types.question && token !== _tokenizerTypes.types.colon; } else { isGroupedType = true; } } if (isGroupedType) { type = this.flowParseType(); this.expect(_tokenizerTypes.types.parenR); // If we see a => next then someone was probably confused about // function types, so we can provide a better error message if (this.eat(_tokenizerTypes.types.arrow)) { this.raise(node, "Unexpected token =>. It looks like " + "you are trying to write a function type, but you ended up " + "writing a grouped type followed by an =>, which is a syntax " + "error. Remember, function type parameters are named so function " + "types look like (name1: type1, name2: type2) => returnType. You " + "probably wrote (type1) => returnType"); } return type; } tmp = this.flowParseFunctionTypeParams(); node.params = tmp.params; node.rest = tmp.rest; this.expect(_tokenizerTypes.types.parenR); this.expect(_tokenizerTypes.types.arrow); node.returnType = this.flowParseType(); node.typeParameters = null; return this.finishNode(node, "FunctionTypeAnnotation"); case _tokenizerTypes.types.string: node.value = this.state.value; this.addExtra(node, "rawValue", node.value); this.addExtra(node, "raw", this.input.slice(this.state.start, this.state.end)); this.next(); return this.finishNode(node, "StringLiteralTypeAnnotation"); case _tokenizerTypes.types._true:case _tokenizerTypes.types._false: node.value = this.match(_tokenizerTypes.types._true); this.next(); return this.finishNode(node, "BooleanLiteralTypeAnnotation"); case _tokenizerTypes.types.num: node.value = this.state.value; this.addExtra(node, "rawValue", node.value); this.addExtra(node, "raw", this.input.slice(this.state.start, this.state.end)); this.next(); return this.finishNode(node, "NumericLiteralTypeAnnotation"); case _tokenizerTypes.types._null: node.value = this.match(_tokenizerTypes.types._null); this.next(); return this.finishNode(node, "NullLiteralTypeAnnotation"); case _tokenizerTypes.types._this: node.value = this.match(_tokenizerTypes.types._this); this.next(); return this.finishNode(node, "ThisTypeAnnotation"); default: if (this.state.type.keyword === "typeof") { return this.flowParseTypeofType(); } } this.unexpected(); }; pp.flowParsePostfixType = function () { var node = this.startNode(); var type = node.elementType = this.flowParsePrimaryType(); if (this.match(_tokenizerTypes.types.bracketL)) { this.expect(_tokenizerTypes.types.bracketL); this.expect(_tokenizerTypes.types.bracketR); return this.finishNode(node, "ArrayTypeAnnotation"); } else { return type; } }; pp.flowParsePrefixType = function () { var node = this.startNode(); if (this.eat(_tokenizerTypes.types.question)) { node.typeAnnotation = this.flowParsePrefixType(); return this.finishNode(node, "NullableTypeAnnotation"); } else { return this.flowParsePostfixType(); } }; pp.flowParseIntersectionType = function () { var node = this.startNode(); var type = this.flowParsePrefixType(); node.types = [type]; while (this.eat(_tokenizerTypes.types.bitwiseAND)) { node.types.push(this.flowParsePrefixType()); } return node.types.length === 1 ? type : this.finishNode(node, "IntersectionTypeAnnotation"); }; pp.flowParseUnionType = function () { var node = this.startNode(); var type = this.flowParseIntersectionType(); node.types = [type]; while (this.eat(_tokenizerTypes.types.bitwiseOR)) { node.types.push(this.flowParseIntersectionType()); } return node.types.length === 1 ? type : this.finishNode(node, "UnionTypeAnnotation"); }; pp.flowParseType = function () { var oldInType = this.state.inType; this.state.inType = true; var type = this.flowParseUnionType(); this.state.inType = oldInType; return type; }; pp.flowParseTypeAnnotation = function () { var node = this.startNode(); node.typeAnnotation = this.flowParseTypeInitialiser(); return this.finishNode(node, "TypeAnnotation"); }; pp.flowParseTypeAnnotatableIdentifier = function (requireTypeAnnotation, canBeOptionalParam) { var variance = undefined; if (this.match(_tokenizerTypes.types.plusMin)) { if (this.state.value === "+") { variance = "plus"; } else if (this.state.value === "-") { variance = "minus"; } this.eat(_tokenizerTypes.types.plusMin); } var ident = this.parseIdentifier(); var isOptionalParam = false; if (variance) { ident.variance = variance; } if (canBeOptionalParam && this.eat(_tokenizerTypes.types.question)) { this.expect(_tokenizerTypes.types.question); isOptionalParam = true; } if (requireTypeAnnotation || this.match(_tokenizerTypes.types.colon)) { ident.typeAnnotation = this.flowParseTypeAnnotation(); this.finishNode(ident, ident.type); } if (isOptionalParam) { ident.optional = true; this.finishNode(ident, ident.type); } return ident; }; exports["default"] = function (instance) { // plain function return types: function name(): string {} instance.extend("parseFunctionBody", function (inner) { return function (node, allowExpression) { if (this.match(_tokenizerTypes.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.flowParseTypeAnnotation(); } 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(_tokenizerTypes.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(_tokenizerTypes.types._class) || this.match(_tokenizerTypes.types.name) || this.match(_tokenizerTypes.types._function) || this.match(_tokenizerTypes.types._var)) { return this.flowParseDeclare(node); } } else if (this.match(_tokenizerTypes.types.name)) { if (expr.name === "interface") { return this.flowParseInterface(node); } else if (expr.name === "type") { return this.flowParseTypeAlias(node); } } } return inner.call(this, node, expr); }; }); // export type instance.extend("shouldParseExportDeclaration", function (inner) { return function () { return this.isContextual("type") || this.isContextual("interface") || inner.call(this); }; }); instance.extend("parseParenItem", function () { return function (node, startLoc, startPos, forceArrow) { var canBeArrow = this.state.potentialArrowAt = startPos; if (this.match(_tokenizerTypes.types.colon)) { var typeCastNode = this.startNodeAt(startLoc, startPos); typeCastNode.expression = node; typeCastNode.typeAnnotation = this.flowParseTypeAnnotation(); if (forceArrow && !this.match(_tokenizerTypes.types.arrow)) { this.unexpected(); } if (canBeArrow && this.eat(_tokenizerTypes.types.arrow)) { // ((lol): number => {}); var params = node.type === "SequenceExpression" ? node.expressions : [node]; var func = this.parseArrowExpression(this.startNodeAt(startLoc, startPos), params); func.returnType = typeCastNode.typeAnnotation; return func; } else { return this.finishNode(typeCastNode, "TypeCastExpression"); } } else { 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(_tokenizerTypes.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("interface")) { node.exportKind = "type"; var declarationNode = this.startNode(); this.next(); return this.flowParseInterface(declarationNode); } 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(_tokenizerTypes.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); }; }); function typeCastToParameter(node) { node.expression.typeAnnotation = node.typeAnnotation; return node.expression; } instance.extend("toAssignable", function (inner) { return function (node) { if (node.type === "TypeCastExpression") { return typeCastToParameter(node); } else { return inner.apply(this, arguments); } }; }); // turn type casts that we found in function parameter head into type annotated params instance.extend("toAssignableList", function (inner) { return function (exprList, isBinding) { for (var i = 0; i < exprList.length; i++) { var expr = exprList[i]; if (expr && expr.type === "TypeCastExpression") { exprList[i] = typeCastToParameter(expr); } } return inner.call(this, exprList, isBinding); }; }); // 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 cal;ed instance.extend("parseExprListItem", function (inner) { return function (allowEmpty, refShorthandDefaultPos) { var container = this.startNode(); var node = inner.call(this, allowEmpty, refShorthandDefaultPos); if (this.match(_tokenizerTypes.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) { if (this.match(_tokenizerTypes.types.colon)) { node.typeAnnotation = this.flowParseTypeAnnotation(); } return inner.call(this, node); }; }); // 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(_tokenizerTypes.types.colon) || inner.call(this); }; }); // parse type parameters for class methods instance.extend("parseClassMethod", function () { return function (classBody, method, isGenerator, isAsync) { if (this.isRelational("<")) { method.typeParameters = this.flowParseTypeParameterDeclaration(); } this.parseMethod(method, isGenerator, isAsync); classBody.body.push(this.finishNode(method, "ClassMethod")); }; }); // 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(_tokenizerTypes.types.comma)); } }; }); // parse type parameters for object method shorthand instance.extend("parseObjPropValue", function (inner) { return function (prop) { var typeParameters = undefined; // method shorthand if (this.isRelational("<")) { typeParameters = this.flowParseTypeParameterDeclaration(); if (!this.match(_tokenizerTypes.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(_tokenizerTypes.types.question)) { param.optional = true; } if (this.match(_tokenizerTypes.types.colon)) { param.typeAnnotation = this.flowParseTypeAnnotation(); } this.finishNode(param, param.type); return param; }; }); // parse typeof and type imports instance.extend("parseImportSpecifiers", function (inner) { return function (node) { node.importKind = "value"; var kind = null; if (this.match(_tokenizerTypes.types._typeof)) { kind = "typeof"; } else if (this.isContextual("type")) { kind = "type"; } if (kind) { var lh = this.lookahead(); if (lh.type === _tokenizerTypes.types.name && lh.value !== "from" || lh.type === _tokenizerTypes.types.braceL || lh.type === _tokenizerTypes.types.star) { this.next(); node.importKind = kind; } } inner.call(this, node); }; }); // parse function type parameters - function foo() {} 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(_tokenizerTypes.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(_tokenizerTypes.types.colon)) { node.returnType = this.flowParseTypeAnnotation(); } return inner.call(this, node, call); }; }); // todo description instance.extend("shouldParseAsyncArrow", function (inner) { return function () { return this.match(_tokenizerTypes.types.colon) || inner.call(this); }; }); // handle return types for arrow functions instance.extend("parseParenAndDistinguishExpression", function (inner) { return function (startPos, startLoc, canBeArrow, isAsync) { startPos = startPos || this.state.start; startLoc = startLoc || this.state.startLoc; if (canBeArrow && this.lookahead().type === _tokenizerTypes.types.parenR) { // let foo = (): number => {}; this.expect(_tokenizerTypes.types.parenL); this.expect(_tokenizerTypes.types.parenR); var node = this.startNodeAt(startPos, startLoc); if (this.match(_tokenizerTypes.types.colon)) node.returnType = this.flowParseTypeAnnotation(); this.expect(_tokenizerTypes.types.arrow); return this.parseArrowExpression(node, [], isAsync); } else { // let foo = (foo): number => {}; var node = inner.call(this, startPos, startLoc, canBeArrow, isAsync, this.hasPlugin("trailingFunctionCommas")); if (this.match(_tokenizerTypes.types.colon)) { var state = this.state.clone(); try { return this.parseParenItem(node, startPos, startLoc, true); } catch (err) { if (err instanceof SyntaxError) { this.state = state; return node; } else { throw err; } } } else { return node; } } }; }); }; module.exports = exports["default"]; },{"17":17,"25":25,"5":5}],12:[function(_dereq_,module,exports){ /* eslint indent: 0 */ "use strict"; var _interopRequireDefault = _dereq_(25)["default"]; exports.__esModule = true; var _xhtml = _dereq_(13); var _xhtml2 = _interopRequireDefault(_xhtml); var _tokenizerTypes = _dereq_(17); var _tokenizerContext = _dereq_(14); var _parser = _dereq_(5); var _parser2 = _interopRequireDefault(_parser); var _utilIdentifier = _dereq_(18); var _utilWhitespace = _dereq_(20); var HEX_NUMBER = /^[\da-fA-F]+$/; var DECIMAL_NUMBER = /^\d+$/; _tokenizerContext.types.j_oTag = new _tokenizerContext.TokContext("...", true, true); _tokenizerTypes.types.jsxName = new _tokenizerTypes.TokenType("jsxName"); _tokenizerTypes.types.jsxText = new _tokenizerTypes.TokenType("jsxText", { beforeExpr: true }); _tokenizerTypes.types.jsxTagStart = new _tokenizerTypes.TokenType("jsxTagStart"); _tokenizerTypes.types.jsxTagEnd = new _tokenizerTypes.TokenType("jsxTagEnd"); _tokenizerTypes.types.jsxTagStart.updateContext = function () { this.state.context.push(_tokenizerContext.types.j_expr); // treat as beginning of JSX expression this.state.context.push(_tokenizerContext.types.j_oTag); // start opening tag context this.state.exprAllowed = false; }; _tokenizerTypes.types.jsxTagEnd.updateContext = function (prevType) { var out = this.state.context.pop(); if (out === _tokenizerContext.types.j_oTag && prevType === _tokenizerTypes.types.slash || out === _tokenizerContext.types.j_cTag) { this.state.context.pop(); this.state.exprAllowed = this.curContext() === _tokenizerContext.types.j_expr; } else { this.state.exprAllowed = true; } }; var pp = _parser2["default"].prototype; // Reads inline JSX contents token. pp.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(_tokenizerTypes.types.jsxTagStart); } return this.getTokenFromCode(ch); } out += this.input.slice(chunkStart, this.state.pos); return this.finishToken(_tokenizerTypes.types.jsxText, out); case 38: // "&" out += this.input.slice(chunkStart, this.state.pos); out += this.jsxReadEntity(); chunkStart = this.state.pos; break; default: if (_utilWhitespace.isNewLine(ch)) { out += this.input.slice(chunkStart, this.state.pos); out += this.jsxReadNewLine(true); chunkStart = this.state.pos; } else { ++this.state.pos; } } } }; pp.jsxReadNewLine = function (normalizeCRLF) { var ch = this.input.charCodeAt(this.state.pos); var out = undefined; ++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.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 (_utilWhitespace.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(_tokenizerTypes.types.string, out); }; pp.jsxReadEntity = function () { var str = ""; var count = 0; var entity = undefined; 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 = String.fromCharCode(parseInt(str, 16)); } else { str = str.substr(1); if (DECIMAL_NUMBER.test(str)) entity = String.fromCharCode(parseInt(str, 10)); } } else { entity = _xhtml2["default"][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.jsxReadWord = function () { var ch = undefined; var start = this.state.pos; do { ch = this.input.charCodeAt(++this.state.pos); } while (_utilIdentifier.isIdentifierChar(ch) || ch === 45); // "-" return this.finishToken(_tokenizerTypes.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.jsxParseIdentifier = function () { var node = this.startNode(); if (this.match(_tokenizerTypes.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.jsxParseNamespacedName = function () { var startPos = this.state.start, startLoc = this.state.startLoc; var name = this.jsxParseIdentifier(); if (!this.eat(_tokenizerTypes.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.jsxParseElementName = function () { var startPos = this.state.start, startLoc = this.state.startLoc; var node = this.jsxParseNamespacedName(); while (this.eat(_tokenizerTypes.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.jsxParseAttributeValue = function () { var node = undefined; switch (this.state.type) { case _tokenizerTypes.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 _tokenizerTypes.types.jsxTagStart: case _tokenizerTypes.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.jsxParseEmptyExpression = function () { var node = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc); return this.finishNodeAt(node, "JSXEmptyExpression", this.start, this.startLoc); }; // Parses JSX expression enclosed into curly brackets. pp.jsxParseExpressionContainer = function () { var node = this.startNode(); this.next(); if (this.match(_tokenizerTypes.types.braceR)) { node.expression = this.jsxParseEmptyExpression(); } else { node.expression = this.parseExpression(); } this.expect(_tokenizerTypes.types.braceR); return this.finishNode(node, "JSXExpressionContainer"); }; // Parses following JSX attribute name-value pair. pp.jsxParseAttribute = function () { var node = this.startNode(); if (this.eat(_tokenizerTypes.types.braceL)) { this.expect(_tokenizerTypes.types.ellipsis); node.argument = this.parseMaybeAssign(); this.expect(_tokenizerTypes.types.braceR); return this.finishNode(node, "JSXSpreadAttribute"); } node.name = this.jsxParseNamespacedName(); node.value = this.eat(_tokenizerTypes.types.eq) ? this.jsxParseAttributeValue() : null; return this.finishNode(node, "JSXAttribute"); }; // Parses JSX opening tag starting after "<". pp.jsxParseOpeningElementAt = function (startPos, startLoc) { var node = this.startNodeAt(startPos, startLoc); node.attributes = []; node.name = this.jsxParseElementName(); while (!this.match(_tokenizerTypes.types.slash) && !this.match(_tokenizerTypes.types.jsxTagEnd)) { node.attributes.push(this.jsxParseAttribute()); } node.selfClosing = this.eat(_tokenizerTypes.types.slash); this.expect(_tokenizerTypes.types.jsxTagEnd); return this.finishNode(node, "JSXOpeningElement"); }; // Parses JSX closing tag starting after ""); } } node.openingElement = openingElement; node.closingElement = closingElement; node.children = children; if (this.match(_tokenizerTypes.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.jsxParseElement = function () { var startPos = this.state.start, startLoc = this.state.startLoc; this.next(); return this.jsxParseElementAt(startPos, startLoc); }; exports["default"] = function (instance) { instance.extend("parseExprAtom", function (inner) { return function (refShortHandDefaultPos) { if (this.match(_tokenizerTypes.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(_tokenizerTypes.types.jsxTagStart)) { return this.jsxParseElement(); } else { return inner.call(this, refShortHandDefaultPos); } }; }); instance.extend("readToken", function (inner) { return function (code) { var context = this.curContext(); if (context === _tokenizerContext.types.j_expr) { return this.jsxReadToken(); } if (context === _tokenizerContext.types.j_oTag || context === _tokenizerContext.types.j_cTag) { if (_utilIdentifier.isIdentifierStart(code)) { return this.jsxReadWord(); } if (code === 62) { ++this.state.pos; return this.finishToken(_tokenizerTypes.types.jsxTagEnd); } if ((code === 34 || code === 39) && context === _tokenizerContext.types.j_oTag) { return this.jsxReadString(code); } } if (code === 60 && this.state.exprAllowed) { ++this.state.pos; return this.finishToken(_tokenizerTypes.types.jsxTagStart); } return inner.call(this, code); }; }); instance.extend("updateContext", function (inner) { return function (prevType) { if (this.match(_tokenizerTypes.types.braceL)) { var curContext = this.curContext(); if (curContext === _tokenizerContext.types.j_oTag) { this.state.context.push(_tokenizerContext.types.b_expr); } else if (curContext === _tokenizerContext.types.j_expr) { this.state.context.push(_tokenizerContext.types.b_tmpl); } else { inner.call(this, prevType); } this.state.exprAllowed = true; } else if (this.match(_tokenizerTypes.types.slash) && prevType === _tokenizerTypes.types.jsxTagStart) { this.state.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore this.state.context.push(_tokenizerContext.types.j_cTag); // reconsider as closing tag context this.state.exprAllowed = false; } else { return inner.call(this, prevType); } }; }); }; module.exports = exports["default"]; },{"13":13,"14":14,"17":17,"18":18,"20":20,"25":25,"5":5}],13:[function(_dereq_,module,exports){ "use strict"; exports.__esModule = true; exports["default"] = { quot: "\"", amp: "&", apos: "'", lt: "<", gt: ">", nbsp: " ", iexcl: "¡", cent: "¢", pound: "£", curren: "¤", yen: "¥", brvbar: "¦", sect: "§", uml: "¨", copy: "©", ordf: "ª", laquo: "«", not: "¬", shy: "­", reg: "®", macr: "¯", deg: "°", plusmn: "±", sup2: "²", sup3: "³", acute: "´", micro: "µ", para: "¶", middot: "·", cedil: "¸", sup1: "¹", ordm: "º", raquo: "»", frac14: "¼", frac12: "½", frac34: "¾", iquest: "¿", Agrave: "À", Aacute: "Á", Acirc: "Â", Atilde: "Ã", Auml: "Ä", Aring: "Å", AElig: "Æ", Ccedil: "Ç", Egrave: "È", Eacute: "É", Ecirc: "Ê", Euml: "Ë", Igrave: "Ì", Iacute: "Í", Icirc: "Î", Iuml: "Ï", ETH: "Ð", Ntilde: "Ñ", Ograve: "Ò", Oacute: "Ó", Ocirc: "Ô", Otilde: "Õ", Ouml: "Ö", times: "×", Oslash: "Ø", Ugrave: "Ù", Uacute: "Ú", Ucirc: "Û", Uuml: "Ü", Yacute: "Ý", THORN: "Þ", szlig: "ß", agrave: "à", aacute: "á", acirc: "â", atilde: "ã", auml: "ä", aring: "å", aelig: "æ", ccedil: "ç", egrave: "è", eacute: "é", ecirc: "ê", euml: "ë", igrave: "ì", iacute: "í", icirc: "î", iuml: "ï", eth: "ð", ntilde: "ñ", ograve: "ò", oacute: "ó", ocirc: "ô", otilde: "õ", ouml: "ö", divide: "÷", oslash: "ø", ugrave: "ù", uacute: "ú", ucirc: "û", uuml: "ü", yacute: "ý", thorn: "þ", yuml: "ÿ", OElig: "Œ", oelig: "œ", Scaron: "Š", scaron: "š", Yuml: "Ÿ", fnof: "ƒ", circ: "ˆ", tilde: "˜", Alpha: "Α", Beta: "Β", Gamma: "Γ", Delta: "Δ", Epsilon: "Ε", Zeta: "Ζ", Eta: "Η", Theta: "Θ", Iota: "Ι", Kappa: "Κ", Lambda: "Λ", Mu: "Μ", Nu: "Ν", Xi: "Ξ", Omicron: "Ο", Pi: "Π", Rho: "Ρ", Sigma: "Σ", Tau: "Τ", Upsilon: "Υ", Phi: "Φ", Chi: "Χ", Psi: "Ψ", Omega: "Ω", alpha: "α", beta: "β", gamma: "γ", delta: "δ", epsilon: "ε", zeta: "ζ", eta: "η", theta: "θ", iota: "ι", kappa: "κ", lambda: "λ", mu: "μ", nu: "ν", xi: "ξ", omicron: "ο", pi: "π", rho: "ρ", sigmaf: "ς", sigma: "σ", tau: "τ", upsilon: "υ", phi: "φ", chi: "χ", psi: "ψ", omega: "ω", thetasym: "ϑ", upsih: "ϒ", piv: "ϖ", ensp: " ", emsp: " ", thinsp: " ", zwnj: "‌", zwj: "‍", lrm: "‎", rlm: "‏", ndash: "–", mdash: "—", lsquo: "‘", rsquo: "’", sbquo: "‚", ldquo: "“", rdquo: "”", bdquo: "„", dagger: "†", Dagger: "‡", bull: "•", hellip: "…", permil: "‰", prime: "′", Prime: "″", lsaquo: "‹", rsaquo: "›", oline: "‾", frasl: "⁄", euro: "€", image: "ℑ", weierp: "℘", real: "ℜ", trade: "™", alefsym: "ℵ", larr: "←", uarr: "↑", rarr: "→", darr: "↓", harr: "↔", crarr: "↵", lArr: "⇐", uArr: "⇑", rArr: "⇒", dArr: "⇓", hArr: "⇔", forall: "∀", part: "∂", exist: "∃", empty: "∅", nabla: "∇", isin: "∈", notin: "∉", ni: "∋", prod: "∏", sum: "∑", minus: "−", lowast: "∗", radic: "√", prop: "∝", infin: "∞", ang: "∠", and: "∧", or: "∨", cap: "∩", cup: "∪", "int": "∫", there4: "∴", sim: "∼", cong: "≅", asymp: "≈", ne: "≠", equiv: "≡", le: "≤", ge: "≥", sub: "⊂", sup: "⊃", nsub: "⊄", sube: "⊆", supe: "⊇", oplus: "⊕", otimes: "⊗", perp: "⊥", sdot: "⋅", lceil: "⌈", rceil: "⌉", lfloor: "⌊", rfloor: "⌋", lang: "〈", rang: "〉", loz: "◊", spades: "♠", clubs: "♣", hearts: "♥", diams: "♦" }; module.exports = exports["default"]; },{}],14:[function(_dereq_,module,exports){ // The algorithm used to determine whether a regexp can appear at a // given point in the program is loosely based on sweet.js' approach. // See https://github.com/mozilla/sweet.js/wiki/design "use strict"; var _classCallCheck = _dereq_(23)["default"]; exports.__esModule = true; var _types = _dereq_(17); var _utilWhitespace = _dereq_(20); var TokContext = function TokContext(token, isExpr, preserveSpace, override) { _classCallCheck(this, TokContext); this.token = token; this.isExpr = !!isExpr; this.preserveSpace = !!preserveSpace; this.override = override; }; exports.TokContext = TokContext; var types = { b_stat: new TokContext("{", false), b_expr: new TokContext("{", true), b_tmpl: new TokContext("${", true), p_stat: new TokContext("(", false), p_expr: new TokContext("(", true), q_tmpl: new TokContext("`", true, true, function (p) { return p.readTmplToken(); }), f_expr: new TokContext("function", true) }; exports.types = types; // Token-specific context update code _types.types.parenR.updateContext = _types.types.braceR.updateContext = function () { if (this.state.context.length === 1) { this.state.exprAllowed = true; return; } var out = this.state.context.pop(); if (out === types.b_stat && this.curContext() === types.f_expr) { this.state.context.pop(); this.state.exprAllowed = false; } else if (out === types.b_tmpl) { this.state.exprAllowed = true; } else { this.state.exprAllowed = !out.isExpr; } }; _types.types.name.updateContext = function (prevType) { this.state.exprAllowed = false; if (prevType === _types.types._let || prevType === _types.types._const || prevType === _types.types._var) { if (_utilWhitespace.lineBreak.test(this.input.slice(this.state.end))) { this.state.exprAllowed = true; } } }; _types.types.braceL.updateContext = function (prevType) { this.state.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr); this.state.exprAllowed = true; }; _types.types.dollarBraceL.updateContext = function () { this.state.context.push(types.b_tmpl); this.state.exprAllowed = true; }; _types.types.parenL.updateContext = function (prevType) { var statementParens = prevType === _types.types._if || prevType === _types.types._for || prevType === _types.types._with || prevType === _types.types._while; this.state.context.push(statementParens ? types.p_stat : types.p_expr); this.state.exprAllowed = true; }; _types.types.incDec.updateContext = function () { // tokExprAllowed stays unchanged }; _types.types._function.updateContext = function () { if (this.curContext() !== types.b_stat) { this.state.context.push(types.f_expr); } this.state.exprAllowed = false; }; _types.types.backQuote.updateContext = function () { if (this.curContext() === types.q_tmpl) { this.state.context.pop(); } else { this.state.context.push(types.q_tmpl); } this.state.exprAllowed = false; }; },{"17":17,"20":20,"23":23}],15:[function(_dereq_,module,exports){ /* eslint max-len: 0 */ /* eslint indent: 0 */ "use strict"; var _classCallCheck = _dereq_(23)["default"]; var _interopRequireDefault = _dereq_(25)["default"]; exports.__esModule = true; var _utilIdentifier = _dereq_(18); var _types = _dereq_(17); var _context = _dereq_(14); var _utilLocation = _dereq_(19); var _utilWhitespace = _dereq_(20); var _state = _dereq_(16); var _state2 = _interopRequireDefault(_state); // Object type used to represent tokens. Note that normally, tokens // simply exist as properties on the parser object. This is only // used for the onToken callback and the external tokenizer. var Token = function Token(state) { _classCallCheck(this, Token); this.type = state.type; this.value = state.value; this.start = state.start; this.end = state.end; this.loc = new _utilLocation.SourceLocation(state.startLoc, state.endLoc); } // ## Tokenizer ; exports.Token = Token; function codePointToString(code) { // UTF-16 Decoding if (code <= 0xFFFF) { return String.fromCharCode(code); } else { return String.fromCharCode((code - 0x10000 >> 10) + 0xD800, (code - 0x10000 & 1023) + 0xDC00); } } var Tokenizer = (function () { function Tokenizer(options, input) { _classCallCheck(this, Tokenizer); this.state = new _state2["default"](); this.state.init(options, input); } // Move to the next token Tokenizer.prototype.next = function next() { if (!this.isLookahead) { this.state.tokens.push(new Token(this.state)); } this.state.lastTokEnd = this.state.end; this.state.lastTokStart = this.state.start; this.state.lastTokEndLoc = this.state.endLoc; this.state.lastTokStartLoc = this.state.startLoc; this.nextToken(); }; // TODO Tokenizer.prototype.eat = function eat(type) { if (this.match(type)) { this.next(); return true; } else { return false; } }; // TODO Tokenizer.prototype.match = function match(type) { return this.state.type === type; }; // TODO Tokenizer.prototype.isKeyword = function isKeyword(word) { return _utilIdentifier.isKeyword(word); }; // TODO Tokenizer.prototype.lookahead = function lookahead() { var old = this.state; this.state = old.clone(true); this.isLookahead = true; this.next(); this.isLookahead = false; var curr = this.state.clone(true); this.state = old; return curr; }; // Toggle strict mode. Re-reads the next number or string to please // pedantic tests (`"use strict"; 010;` should fail). Tokenizer.prototype.setStrict = function setStrict(strict) { this.state.strict = strict; if (!this.match(_types.types.num) && !this.match(_types.types.string)) return; this.state.pos = this.state.start; while (this.state.pos < this.state.lineStart) { this.state.lineStart = this.input.lastIndexOf("\n", this.state.lineStart - 2) + 1; --this.state.curLine; } this.nextToken(); }; Tokenizer.prototype.curContext = function curContext() { return this.state.context[this.state.context.length - 1]; }; // Read a single token, updating the parser object's token-related // properties. Tokenizer.prototype.nextToken = function nextToken() { var curContext = this.curContext(); if (!curContext || !curContext.preserveSpace) this.skipSpace(); this.state.containsOctal = false; this.state.octalPosition = null; this.state.start = this.state.pos; this.state.startLoc = this.state.curPosition(); if (this.state.pos >= this.input.length) return this.finishToken(_types.types.eof); if (curContext.override) { return curContext.override(this); } else { return this.readToken(this.fullCharCodeAtPos()); } }; Tokenizer.prototype.readToken = function readToken(code) { // Identifier or keyword. '\uXXXX' sequences are allowed in // identifiers, so '\' also dispatches to that. if (_utilIdentifier.isIdentifierStart(code) || code === 92 /* '\' */) { return this.readWord(); } else { return this.getTokenFromCode(code); } }; Tokenizer.prototype.fullCharCodeAtPos = function fullCharCodeAtPos() { var code = this.input.charCodeAt(this.state.pos); if (code <= 0xd7ff || code >= 0xe000) return code; var next = this.input.charCodeAt(this.state.pos + 1); return (code << 10) + next - 0x35fdc00; }; Tokenizer.prototype.pushComment = function pushComment(block, text, start, end, startLoc, endLoc) { var comment = { type: block ? "CommentBlock" : "CommentLine", value: text, start: start, end: end, loc: new _utilLocation.SourceLocation(startLoc, endLoc) }; if (!this.isLookahead) { this.state.tokens.push(comment); this.state.comments.push(comment); } this.addComment(comment); }; Tokenizer.prototype.skipBlockComment = function skipBlockComment() { var startLoc = this.state.curPosition(); var start = this.state.pos, end = this.input.indexOf("*/", this.state.pos += 2); if (end === -1) this.raise(this.state.pos - 2, "Unterminated comment"); this.state.pos = end + 2; _utilWhitespace.lineBreakG.lastIndex = start; var match = undefined; while ((match = _utilWhitespace.lineBreakG.exec(this.input)) && match.index < this.state.pos) { ++this.state.curLine; this.state.lineStart = match.index + match[0].length; } this.pushComment(true, this.input.slice(start + 2, end), start, this.state.pos, startLoc, this.state.curPosition()); }; Tokenizer.prototype.skipLineComment = function skipLineComment(startSkip) { var start = this.state.pos; var startLoc = this.state.curPosition(); var ch = this.input.charCodeAt(this.state.pos += startSkip); while (this.state.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { ++this.state.pos; ch = this.input.charCodeAt(this.state.pos); } this.pushComment(false, this.input.slice(start + startSkip, this.state.pos), start, this.state.pos, startLoc, this.state.curPosition()); }; // Called at the start of the parse and after every token. Skips // whitespace and comments, and. Tokenizer.prototype.skipSpace = function skipSpace() { loop: while (this.state.pos < this.input.length) { var ch = this.input.charCodeAt(this.state.pos); switch (ch) { case 32:case 160: // ' ' ++this.state.pos; break; case 13: if (this.input.charCodeAt(this.state.pos + 1) === 10) { ++this.state.pos; } case 10:case 8232:case 8233: ++this.state.pos; ++this.state.curLine; this.state.lineStart = this.state.pos; break; case 47: // '/' switch (this.input.charCodeAt(this.state.pos + 1)) { case 42: // '*' this.skipBlockComment(); break; case 47: this.skipLineComment(2); break; default: break loop; } break; default: if (ch > 8 && ch < 14 || ch >= 5760 && _utilWhitespace.nonASCIIwhitespace.test(String.fromCharCode(ch))) { ++this.state.pos; } else { break loop; } } } }; // Called at the end of every token. Sets `end`, `val`, and // maintains `context` and `exprAllowed`, and skips the space after // the token, so that the next one's `start` will point at the // right position. Tokenizer.prototype.finishToken = function finishToken(type, val) { this.state.end = this.state.pos; this.state.endLoc = this.state.curPosition(); var prevType = this.state.type; this.state.type = type; this.state.value = val; this.updateContext(prevType); }; // ### Token reading // This is the function that is called to fetch the next token. It // is somewhat obscure, because it works in character codes rather // than characters, and because operator parsing has been inlined // into it. // // All in the name of speed. // Tokenizer.prototype.readToken_dot = function readToken_dot() { var next = this.input.charCodeAt(this.state.pos + 1); if (next >= 48 && next <= 57) { return this.readNumber(true); } var next2 = this.input.charCodeAt(this.state.pos + 2); if (next === 46 && next2 === 46) { // 46 = dot '.' this.state.pos += 3; return this.finishToken(_types.types.ellipsis); } else { ++this.state.pos; return this.finishToken(_types.types.dot); } }; Tokenizer.prototype.readToken_slash = function readToken_slash() { // '/' if (this.state.exprAllowed) { ++this.state.pos; return this.readRegexp(); } var next = this.input.charCodeAt(this.state.pos + 1); if (next === 61) { return this.finishOp(_types.types.assign, 2); } else { return this.finishOp(_types.types.slash, 1); } }; Tokenizer.prototype.readToken_mult_modulo = function readToken_mult_modulo(code) { // '%*' var type = code === 42 ? _types.types.star : _types.types.modulo; var width = 1; var next = this.input.charCodeAt(this.state.pos + 1); if (next === 42 && this.hasPlugin("exponentiationOperator")) { // '*' width++; next = this.input.charCodeAt(this.state.pos + 2); type = _types.types.exponent; } if (next === 61) { width++; type = _types.types.assign; } return this.finishOp(type, width); }; Tokenizer.prototype.readToken_pipe_amp = function readToken_pipe_amp(code) { // '|&' var next = this.input.charCodeAt(this.state.pos + 1); if (next === code) return this.finishOp(code === 124 ? _types.types.logicalOR : _types.types.logicalAND, 2); if (next === 61) return this.finishOp(_types.types.assign, 2); return this.finishOp(code === 124 ? _types.types.bitwiseOR : _types.types.bitwiseAND, 1); }; Tokenizer.prototype.readToken_caret = function readToken_caret() { // '^' var next = this.input.charCodeAt(this.state.pos + 1); if (next === 61) { return this.finishOp(_types.types.assign, 2); } else { return this.finishOp(_types.types.bitwiseXOR, 1); } }; Tokenizer.prototype.readToken_plus_min = function readToken_plus_min(code) { // '+-' var next = this.input.charCodeAt(this.state.pos + 1); if (next === code) { if (next === 45 && this.input.charCodeAt(this.state.pos + 2) === 62 && _utilWhitespace.lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.pos))) { // A `-->` line comment this.skipLineComment(3); this.skipSpace(); return this.nextToken(); } return this.finishOp(_types.types.incDec, 2); } if (next === 61) { return this.finishOp(_types.types.assign, 2); } else { return this.finishOp(_types.types.plusMin, 1); } }; Tokenizer.prototype.readToken_lt_gt = function readToken_lt_gt(code) { // '<>' var next = this.input.charCodeAt(this.state.pos + 1); var size = 1; if (next === code) { size = code === 62 && this.input.charCodeAt(this.state.pos + 2) === 62 ? 3 : 2; if (this.input.charCodeAt(this.state.pos + size) === 61) return this.finishOp(_types.types.assign, size + 1); return this.finishOp(_types.types.bitShift, size); } if (next === 33 && code === 60 && this.input.charCodeAt(this.state.pos + 2) === 45 && this.input.charCodeAt(this.state.pos + 3) === 45) { if (this.inModule) this.unexpected(); // `