UNPKG

power-assert-formatter

Version:
1,229 lines (1,116 loc) 373 kB
/** * Modules in this bundle * @license * * power-assert-formatter: * license: MIT (http://opensource.org/licenses/MIT) * author: Takuto Wada <takuto.wada@gmail.com> * contributors: James Talmage * homepage: https://github.com/power-assert-js/power-assert-formatter * version: 1.4.1 * * acorn: * license: MIT (http://opensource.org/licenses/MIT) * maintainers: marijn <marijnh@gmail.com>, rreverser <me@rreverser.com> * contributors: -e List of Acorn contributors. Updated before every release., Adrian Rakovsky, Alistair Braidwood, Andres Suarez, Angelo, Aparajita Fishman, Arian Stolwijk, Artem Govorov, Brandon Mills, Charles Hughes, Conrad Irwin, David Bonnet, Domenico Matteo, ForbesLindesay, Forbes Lindesay, Gilad Peleg, impinball, Ingvar Stepanyan, Jackson Ray Hamilton, Jesse McCarthy, Jiaxing Wang, Joel Kemp, Johannes Herr, Jordan Klassen, Jürg Lehni, keeyipchan, Keheliya Gallaba, Kevin Kwok, krator, Marijn Haverbeke, Martin Carlberg, Mathias Bynens, Mathieu 'p01' Henri, Matthew Bastien, Max Schaefer, Max Zerzouri, Mihai Bazon, Mike Rennie, Nicholas C. Zakas, Nick Fitzgerald, Olivier Thomann, Oskar Schöldström, Paul Harper, Peter Rust, PlNG, Prayag Verma, ReadmeCritic, r-e-d, Richard Gibson, Rich Harris, Sebastian McKenzie, Timothy Gu, Toru Nagashima, zsjforcn * homepage: https://github.com/ternjs/acorn * version: 3.2.0 * * acorn-es7-plugin: * license: MIT (http://opensource.org/licenses/MIT) * author: matatbread * maintainers: matatbread <npm@mailed.me.uk> * homepage: https://github.com/MatAtBread/acorn-es7-plugin#readme * version: 1.0.15 * * core-js: * license: MIT (http://opensource.org/licenses/MIT) * maintainers: zloirock <zloirock@zloirock.ru> * homepage: https://github.com/zloirock/core-js#readme * version: 2.4.0 * * diff-match-patch: * license: http://www.apache.org/licenses/LICENSE-2.0 * maintainers: forbeslindesay <forbes@lindeay.co.uk> * homepage: https://github.com/ForbesLindesay/diff-match-patch#readme * version: 1.0.0 * * eastasianwidth: * license: MIT (http://opensource.org/licenses/MIT) * author: Masaki Komagata * maintainers: komagata <komagata@gmail.com> * homepage: https://github.com/komagata/eastasianwidth#readme * version: 0.1.1 * * espurify: * license: MIT (http://opensource.org/licenses/MIT) * author: Takuto Wada <takuto.wada@gmail.com> * maintainers: twada <takuto.wada@gmail.com> * homepage: https://github.com/estools/espurify * version: 1.6.0 * * estraverse: * license: BSD-2-Clause (http://opensource.org/licenses/BSD-2-Clause) * maintainers: constellation <utatane.tea@gmail.com>, michaelficarra <npm@michael.ficarra.me>, nzakas <nicholas@nczconsulting.com> * homepage: https://github.com/estools/estraverse * version: 4.2.0 * * events: * license: MIT (http://opensource.org/licenses/MIT) * author: Irakli Gozalishvili <rfobic@gmail.com> * maintainers: gozala <rfobic@gmail.com>, defunctzombie <shtylman@gmail.com> * homepage: https://github.com/Gozala/events#readme * version: 1.1.1 * * inherits: * license: ISC (http://opensource.org/licenses/ISC) * maintainers: isaacs <i@izs.me> * homepage: https://github.com/isaacs/inherits#readme * version: 2.0.1 * * power-assert-context-formatter: * license: MIT (http://opensource.org/licenses/MIT) * author: Takuto Wada <takuto.wada@gmail.com> * maintainers: twada <takuto.wada@gmail.com> * homepage: https://github.com/twada/power-assert-runtime * version: 1.0.7 * * power-assert-context-reducer-ast: * license: MIT (http://opensource.org/licenses/MIT) * author: Takuto Wada <takuto.wada@gmail.com> * maintainers: twada <takuto.wada@gmail.com> * homepage: https://github.com/twada/power-assert-runtime * version: 1.0.7 * * power-assert-context-traversal: * license: MIT (http://opensource.org/licenses/MIT) * author: Takuto Wada <takuto.wada@gmail.com> * maintainers: twada <takuto.wada@gmail.com> * homepage: https://github.com/twada/power-assert-runtime * version: 1.0.7 * * power-assert-renderer-assertion: * license: MIT (http://opensource.org/licenses/MIT) * author: Takuto Wada <takuto.wada@gmail.com> * maintainers: twada <takuto.wada@gmail.com> * homepage: https://github.com/twada/power-assert-runtime * version: 1.0.7 * * power-assert-renderer-base: * license: MIT (http://opensource.org/licenses/MIT) * author: Takuto Wada <takuto.wada@gmail.com> * maintainers: twada <takuto.wada@gmail.com> * homepage: https://github.com/twada/power-assert-runtime * version: 1.0.7 * * power-assert-renderer-comparison: * license: MIT (http://opensource.org/licenses/MIT) * author: Takuto Wada <takuto.wada@gmail.com> * maintainers: twada <takuto.wada@gmail.com> * homepage: https://github.com/twada/power-assert-runtime * version: 1.0.7 * * power-assert-renderer-diagram: * license: MIT (http://opensource.org/licenses/MIT) * author: Takuto Wada <takuto.wada@gmail.com> * maintainers: twada <takuto.wada@gmail.com> * homepage: https://github.com/twada/power-assert-runtime * version: 1.0.7 * * power-assert-renderer-file: * license: MIT (http://opensource.org/licenses/MIT) * author: Takuto Wada <takuto.wada@gmail.com> * maintainers: twada <takuto.wada@gmail.com> * homepage: https://github.com/twada/power-assert-runtime * version: 1.0.7 * * process: * license: MIT (http://opensource.org/licenses/MIT) * author: Roman Shtylman <shtylman@gmail.com> * maintainers: coolaj86 <coolaj86@gmail.com>, cwmma <calvin.metcalf@gmail.com>, defunctzombie <shtylman@gmail.com> * homepage: https://github.com/shtylman/node-process#readme * version: 0.11.5 * * stringifier: * license: MIT (http://opensource.org/licenses/MIT) * author: Takuto Wada <takuto.wada@gmail.com> * maintainers: twada <takuto.wada@gmail.com> * homepage: https://github.com/twada/stringifier * version: 1.3.0 * * traverse: * license: MIT (http://opensource.org/licenses/MIT) * author: James Halliday <mail@substack.net> * maintainers: substack <mail@substack.net> * homepage: https://github.com/substack/js-traverse * version: 0.6.6 * * type-name: * license: MIT (http://opensource.org/licenses/MIT) * author: Takuto Wada <takuto.wada@gmail.com> * maintainers: twada <takuto.wada@gmail.com> * contributors: azu, Yosuke Furukawa * homepage: https://github.com/twada/type-name * version: 2.0.1 * * util: * license: MIT (http://opensource.org/licenses/MIT) * author: Joyent * maintainers: shtylman <shtylman@gmail.com> * homepage: https://github.com/defunctzombie/node-util * version: 0.10.3 * * This header is generated by licensify (https://github.com/twada/licensify) */ (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.powerAssertFormatter = 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<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ /** * power-assert-formatter.js - Power Assert output formatter * * https://github.com/power-assert-js/power-assert-formatter * * Copyright (c) 2013-2016 Takuto Wada * Licensed under the MIT license. * https://github.com/power-assert-js/power-assert-formatter/blob/master/MIT-LICENSE.txt */ 'use strict'; module.exports = _dereq_('./lib/create'); },{"./lib/create":2}],2:[function(_dereq_,module,exports){ 'use strict'; var createFormatter = _dereq_('power-assert-context-formatter'); var appendAst = _dereq_('power-assert-context-reducer-ast'); var FileRenderer = _dereq_('power-assert-renderer-file'); var AssertionRenderer = _dereq_('power-assert-renderer-assertion'); var DiagramRenderer = _dereq_('power-assert-renderer-diagram'); var ComparisonRenderer = _dereq_('power-assert-renderer-comparison'); var defaultOptions = _dereq_('./default-options'); var assign = _dereq_('core-js/library/fn/object/assign'); var map = _dereq_('core-js/library/fn/array/map'); // "Browserify can only analyze static requires. It is not in the scope of browserify to handle dynamic requires." // https://github.com/substack/node-browserify/issues/377 var defaultRendererClasses = { './built-in/file': FileRenderer, './built-in/assertion': AssertionRenderer, './built-in/diagram': DiagramRenderer, './built-in/binary-expression': ComparisonRenderer }; function toRendererClass (rendererName) { var RendererClass; if (typeof rendererName === 'function') { RendererClass = rendererName; } else if (typeof rendererName === 'string') { if (defaultRendererClasses[rendererName]) { RendererClass = defaultRendererClasses[rendererName]; } else { RendererClass = _dereq_(rendererName); } } return RendererClass; } function create (options) { var config = assign(defaultOptions(), options); var rendererClasses = map(config.renderers, toRendererClass); var renderers = map(rendererClasses, function (clazz) { return { ctor: clazz, options: config }; }); return createFormatter(assign({}, config, { reducers: [ appendAst ], renderers: renderers, legacy: true })); } create.renderers = { AssertionRenderer: AssertionRenderer, FileRenderer: FileRenderer, DiagramRenderer: DiagramRenderer, BinaryExpressionRenderer: ComparisonRenderer }; create.defaultOptions = defaultOptions; module.exports = create; },{"./default-options":3,"core-js/library/fn/array/map":10,"core-js/library/fn/object/assign":13,"power-assert-context-formatter":76,"power-assert-context-reducer-ast":81,"power-assert-renderer-assertion":85,"power-assert-renderer-comparison":87,"power-assert-renderer-diagram":90,"power-assert-renderer-file":93}],3:[function(_dereq_,module,exports){ 'use strict'; module.exports = function defaultOptions () { return { lineDiffThreshold: 5, maxDepth: 1, outputOffset: 2, anonymous: 'Object', circular: '#@Circular#', lineSeparator: '\n', ambiguousEastAsianCharWidth: 2, renderers: [ './built-in/file', './built-in/assertion', './built-in/diagram', './built-in/binary-expression' ] }; }; },{}],4:[function(_dereq_,module,exports){ var NotAsync = {} ; var asyncExit = /^async[\t ]+(return|throw)/ ; var asyncFunction = /^async[\t ]+function/ ; var atomOrPropertyOrLabel = /^\s*[):;]/ ; var removeComments = /([^\n])\/\*(\*(?!\/)|[^\n*])*\*\/([^\n])/g ; function hasLineTerminatorBeforeNext(st, since) { return st.lineStart >= since; } function test(regex,st,noComment) { var src = st.input.slice(st.start) ; if (noComment) { src = src.replace(removeComments,"$1 $3") ; } return regex.test(src); } /* Return the object holding the parser's 'State'. This is different between acorn ('this') * and babylon ('this.state') */ function state(p) { if (('state' in p) && p.state.constructor && p.state.constructor.name==='State') return p.state ; // Probably babylon return p ; // Probably acorn } /* Create a new parser derived from the specified parser, so that in the * event of an error we can back out and try again */ function subParse(parser, pos, extensions) { // NB: The Babylon constructor does NOT expect 'pos' as an argument, and so // the input needs truncation at the start position, however at present // this doesn't work nicely as all the node location/start/end values // are therefore offset. Consequently, this plug-in is NOT currently working // with the (undocumented) Babylon plug-in interface. var p = new parser.constructor(parser.options, parser.input, pos); if (extensions) for (var k in extensions) p[k] = extensions[k] ; var src = state(parser) ; var dest = state(p) ; ['inFunction','inAsyncFunction','inAsync','inGenerator','inModule'].forEach(function(k){ if (k in src) dest[k] = src[k] ; }) ; p.nextToken(); return p; } function asyncAwaitPlugin (parser,options){ var es7check = function(){} ; parser.extend("initialContext",function(base){ return function(){ if (this.options.ecmaVersion < 7) { es7check = function(node) { parser.raise(node.start,"async/await keywords only available when ecmaVersion>=7") ; } ; } this.reservedWords = new RegExp(this.reservedWords.toString().replace(/await|async/g,"").replace("|/","/").replace("/|","/").replace("||","|")) ; this.reservedWordsStrict = new RegExp(this.reservedWordsStrict.toString().replace(/await|async/g,"").replace("|/","/").replace("/|","/").replace("||","|")) ; this.reservedWordsStrictBind = new RegExp(this.reservedWordsStrictBind.toString().replace(/await|async/g,"").replace("|/","/").replace("/|","/").replace("||","|")) ; this.inAsyncFunction = options.inAsyncFunction ; if (options.awaitAnywhere && options.inAsyncFunction) parser.raise(node.start,"The options awaitAnywhere and inAsyncFunction are mutually exclusive") ; return base.apply(this,arguments); } }) ; parser.extend("shouldParseExportStatement",function(base){ return function(){ if (this.type.label==='name' && this.value==='async' && test(asyncFunction,state(this))) { return true ; } return base.apply(this,arguments) ; } }) ; parser.extend("parseStatement",function(base){ return function (declaration, topLevel) { var st = state(this) ; var start = st.start; var startLoc = st.startLoc; if (st.type.label==='name') { if (test(asyncFunction,st,true)) { var wasAsync = st.inAsyncFunction ; try { st.inAsyncFunction = true ; this.next() ; var r = this.parseStatement(declaration, topLevel) ; r.async = true ; r.start = start; r.loc && (r.loc.start = startLoc); return r ; } finally { st.inAsyncFunction = wasAsync ; } } else if ((typeof options==="object" && options.asyncExits) && test(asyncExit,st)) { // NON-STANDARD EXTENSION iff. options.asyncExits is set, the // extensions 'async return <expr>?' and 'async throw <expr>?' // are enabled. In each case they are the standard ESTree nodes // with the flag 'async:true' this.next() ; var r = this.parseStatement(declaration, topLevel) ; r.async = true ; r.start = start; r.loc && (r.loc.start = startLoc); return r ; } } return base.apply(this,arguments); } }) ; parser.extend("parseIdent",function(base){ return function(liberal){ var id = base.apply(this,arguments); var st = state(this) ; if (st.inAsyncFunction && id.name==='await') { if (arguments.length===0) { this.raise(id.start,"'await' is reserved within async functions") ; } } return id ; } }) ; parser.extend("parseExprAtom",function(base){ return function(refShorthandDefaultPos){ var st = state(this) ; var start = st.start ; var startLoc = st.startLoc; var rhs,r = base.apply(this,arguments); if (r.type==='Identifier') { if (r.name==='async' && !hasLineTerminatorBeforeNext(st, r.end)) { // Is this really an async function? var isAsync = st.inAsyncFunction ; try { st.inAsyncFunction = true ; var pp = this ; var inBody = false ; var parseHooks = { parseFunctionBody:function(node,isArrowFunction){ try { var wasInBody = inBody ; inBody = true ; return pp.parseFunctionBody.apply(this,arguments) ; } finally { inBody = wasInBody ; } }, raise:function(){ try { return pp.raise.apply(this,arguments) ; } catch(ex) { throw inBody?ex:NotAsync ; } } } ; rhs = subParse(this,st.start,parseHooks).parseExpression() ; if (rhs.type==='SequenceExpression') rhs = rhs.expressions[0] ; if (rhs.type==='FunctionExpression' || rhs.type==='FunctionDeclaration' || rhs.type==='ArrowFunctionExpression') { rhs.async = true ; rhs.start = start; rhs.loc && (rhs.loc.start = startLoc); st.pos = rhs.end; this.next(); es7check(rhs) ; return rhs ; } } catch (ex) { if (ex!==NotAsync) throw ex ; } finally { st.inAsyncFunction = isAsync ; } } else if (r.name==='await') { var n = this.startNodeAt(r.start, r.loc && r.loc.start); if (st.inAsyncFunction) { rhs = this.parseExprSubscripts() ; n.operator = 'await' ; n.argument = rhs ; n = this.finishNodeAt(n,'AwaitExpression', rhs.end, rhs.loc && rhs.loc.end) ; es7check(n) ; return n ; } else // NON-STANDARD EXTENSION iff. options.awaitAnywhere is true, // an 'AwaitExpression' is allowed anywhere the token 'await' // could not be an identifier with the name 'await'. // Look-ahead to see if this is really a property or label called async or await if (st.input.slice(r.end).match(atomOrPropertyOrLabel)) return r ; // This is a valid property name or label if (typeof options==="object" && options.awaitAnywhere) { start = st.start ; rhs = subParse(this,start-4).parseExprSubscripts() ; if (rhs.end<=start) { rhs = subParse(this,start).parseExprSubscripts() ; n.operator = 'await' ; n.argument = rhs ; n = this.finishNodeAt(n,'AwaitExpression', rhs.end, rhs.loc && rhs.loc.end) ; st.pos = rhs.end; this.next(); es7check(n) ; return n ; } } } } return r ; } }) ; parser.extend('finishNodeAt',function(base){ return function(node,type,pos,loc) { if (node.__asyncValue) { delete node.__asyncValue ; node.value.async = true ; } return base.apply(this,arguments) ; } }) ; parser.extend('finishNode',function(base){ return function(node,type) { if (node.__asyncValue) { delete node.__asyncValue ; node.value.async = true ; } return base.apply(this,arguments) ; } }) ; parser.extend("parsePropertyName",function(base){ return function (prop) { var st = state(this) ; var key = base.apply(this,arguments) ; if (key.type === "Identifier" && key.name === "async" && !hasLineTerminatorBeforeNext(st, key.end)) { // Look-ahead to see if this is really a property or label called async or await if (!st.input.slice(key.end).match(atomOrPropertyOrLabel)){ es7check(prop) ; key = base.apply(this,arguments) ; if (key.type==='Identifier') { if (key.name==='constructor') this.raise(key.start,"'constructor()' cannot be be async") ; else if (key.name==='set') this.raise(key.start,"'set <member>(value)' cannot be be async") ; } prop.__asyncValue = true ; } } return key; }; }) ; parser.extend("parseClassMethod",function(base){ return function (classBody, method, isGenerator) { var st, wasAsync ; if (method.__asyncValue) { st = state(this) ; wasAsync = st.inAsyncFunction ; st.inAsyncFunction = true ; } var r = base.apply(this,arguments) ; if (st) { st.inAsyncFunction = wasAsync ; } return r ; } }) ; parser.extend("parsePropertyValue",function(base){ return function (prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors) { var st, wasAsync ; if (prop.__asyncValue) { st = state(this) ; wasAsync = st.inAsyncFunction ; st.inAsyncFunction = true ; } var r = base.apply(this,arguments) ; if (st) { st.inAsyncFunction = wasAsync ; } return r ; } }) ; } module.exports = function(acorn) { acorn.plugins.asyncawait = asyncAwaitPlugin ; return acorn } },{}],5:[function(_dereq_,module,exports){ (function (global){ (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.acorn = 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 _dereq_=="function"&&_dereq_;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 _dereq_=="function"&&_dereq_;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ // 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 _tokentype = _dereq_("./tokentype"); var _state = _dereq_("./state"); var _parseutil = _dereq_("./parseutil"); var pp = _state.Parser.prototype; // Check if property name clashes with already added. // Object/class getters and setters are not allowed to clash — // either with each other or with an init property — and in // strict mode, init properties are also not allowed to be repeated. pp.checkPropClash = function (prop, propHash) { if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) return; var key = prop.key;var name = undefined; switch (key.type) { case "Identifier": name = key.name;break; case "Literal": name = String(key.value);break; default: return; } var kind = prop.kind; if (this.options.ecmaVersion >= 6) { if (name === "__proto__" && kind === "init") { if (propHash.proto) this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); propHash.proto = true; } return; } name = "$" + name; var other = propHash[name]; if (other) { var isGetSet = kind !== "init"; if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) this.raiseRecoverable(key.start, "Redefinition of property"); } else { other = propHash[name] = { init: false, get: false, set: false }; } other[kind] = 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, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); if (this.type === _tokentype.types.comma) { var node = this.startNodeAt(startPos, startLoc); node.expressions = [expr]; while (this.eat(_tokentype.types.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)); return this.finishNode(node, "SequenceExpression"); } return expr; }; // Parse an assignment expression. This includes applications of // operators like `+=`. pp.parseMaybeAssign = function (noIn, refDestructuringErrors, afterLeftParse) { if (this.inGenerator && this.isContextual("yield")) return this.parseYield(); var ownDestructuringErrors = false; if (!refDestructuringErrors) { refDestructuringErrors = new _parseutil.DestructuringErrors(); ownDestructuringErrors = true; } var startPos = this.start, startLoc = this.startLoc; if (this.type == _tokentype.types.parenL || this.type == _tokentype.types.name) this.potentialArrowAt = this.start; var left = this.parseMaybeConditional(noIn, refDestructuringErrors); if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc); if (this.type.isAssign) { this.checkPatternErrors(refDestructuringErrors, true); if (!ownDestructuringErrors) _parseutil.DestructuringErrors.call(refDestructuringErrors); var node = this.startNodeAt(startPos, startLoc); node.operator = this.value; node.left = this.type === _tokentype.types.eq ? this.toAssignable(left) : left; refDestructuringErrors.shorthandAssign = 0; // reset because shorthand default was used correctly this.checkLVal(left); this.next(); node.right = this.parseMaybeAssign(noIn); return this.finishNode(node, "AssignmentExpression"); } else { if (ownDestructuringErrors) this.checkExpressionErrors(refDestructuringErrors, true); } return left; }; // Parse a ternary conditional (`?:`) operator. pp.parseMaybeConditional = function (noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseExprOps(noIn, refDestructuringErrors); if (this.checkExpressionErrors(refDestructuringErrors)) return expr; if (this.eat(_tokentype.types.question)) { var node = this.startNodeAt(startPos, startLoc); node.test = expr; node.consequent = this.parseMaybeAssign(); this.expect(_tokentype.types.colon); node.alternate = this.parseMaybeAssign(noIn); return this.finishNode(node, "ConditionalExpression"); } return expr; }; // Start the precedence parser. pp.parseExprOps = function (noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseMaybeUnary(refDestructuringErrors, false); if (this.checkExpressionErrors(refDestructuringErrors)) return expr; 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.type.binop; if (prec != null && (!noIn || this.type !== _tokentype.types._in)) { if (prec > minPrec) { var logical = this.type === _tokentype.types.logicalOR || this.type === _tokentype.types.logicalAND; var op = this.value; this.next(); var startPos = this.start, startLoc = this.startLoc; var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn); var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical); return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn); } } return left; }; pp.buildBinary = function (startPos, startLoc, left, right, op, logical) { var node = this.startNodeAt(startPos, startLoc); node.left = left; node.operator = op; node.right = right; return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression"); }; // Parse unary operators, both prefix and postfix. pp.parseMaybeUnary = function (refDestructuringErrors, sawUnary) { var startPos = this.start, startLoc = this.startLoc, expr = undefined; if (this.type.prefix) { var node = this.startNode(), update = this.type === _tokentype.types.incDec; node.operator = this.value; node.prefix = true; this.next(); node.argument = this.parseMaybeUnary(null, true); this.checkExpressionErrors(refDestructuringErrors, true); if (update) this.checkLVal(node.argument);else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") this.raiseRecoverable(node.start, "Deleting local variable in strict mode");else sawUnary = true; expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); } else { expr = this.parseExprSubscripts(refDestructuringErrors); if (this.checkExpressionErrors(refDestructuringErrors)) return expr; while (this.type.postfix && !this.canInsertSemicolon()) { var node = this.startNodeAt(startPos, startLoc); node.operator = this.value; node.prefix = false; node.argument = expr; this.checkLVal(expr); this.next(); expr = this.finishNode(node, "UpdateExpression"); } } if (!sawUnary && this.eat(_tokentype.types.starstar)) return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false);else return expr; }; // Parse call, dot, and `[]`-subscript expressions. pp.parseExprSubscripts = function (refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseExprAtom(refDestructuringErrors); var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr; return this.parseSubscripts(expr, startPos, startLoc); }; pp.parseSubscripts = function (base, startPos, startLoc, noCalls) { for (;;) { if (this.eat(_tokentype.types.dot)) { var node = this.startNodeAt(startPos, startLoc); node.object = base; node.property = this.parseIdent(true); node.computed = false; base = this.finishNode(node, "MemberExpression"); } else if (this.eat(_tokentype.types.bracketL)) { var node = this.startNodeAt(startPos, startLoc); node.object = base; node.property = this.parseExpression(); node.computed = true; this.expect(_tokentype.types.bracketR); base = this.finishNode(node, "MemberExpression"); } else if (!noCalls && this.eat(_tokentype.types.parenL)) { var node = this.startNodeAt(startPos, startLoc); node.callee = base; node.arguments = this.parseExprList(_tokentype.types.parenR, false); base = this.finishNode(node, "CallExpression"); } else if (this.type === _tokentype.types.backQuote) { var node = this.startNodeAt(startPos, startLoc); node.tag = base; node.quasi = this.parseTemplate(); base = this.finishNode(node, "TaggedTemplateExpression"); } else { return base; } } }; // 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 (refDestructuringErrors) { var node = undefined, canBeArrow = this.potentialArrowAt == this.start; switch (this.type) { case _tokentype.types._super: if (!this.inFunction) this.raise(this.start, "'super' outside of function or class"); case _tokentype.types._this: var type = this.type === _tokentype.types._this ? "ThisExpression" : "Super"; node = this.startNode(); this.next(); return this.finishNode(node, type); case _tokentype.types.name: var startPos = this.start, startLoc = this.startLoc; var id = this.parseIdent(this.type !== _tokentype.types.name); if (canBeArrow && !this.canInsertSemicolon() && this.eat(_tokentype.types.arrow)) return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id]); return id; case _tokentype.types.regexp: var value = this.value; node = this.parseLiteral(value.value); node.regex = { pattern: value.pattern, flags: value.flags }; return node; case _tokentype.types.num:case _tokentype.types.string: return this.parseLiteral(this.value); case _tokentype.types._null:case _tokentype.types._true:case _tokentype.types._false: node = this.startNode(); node.value = this.type === _tokentype.types._null ? null : this.type === _tokentype.types._true; node.raw = this.type.keyword; this.next(); return this.finishNode(node, "Literal"); case _tokentype.types.parenL: return this.parseParenAndDistinguishExpression(canBeArrow); case _tokentype.types.bracketL: node = this.startNode(); this.next(); node.elements = this.parseExprList(_tokentype.types.bracketR, true, true, refDestructuringErrors); return this.finishNode(node, "ArrayExpression"); case _tokentype.types.braceL: return this.parseObj(false, refDestructuringErrors); case _tokentype.types._function: node = this.startNode(); this.next(); return this.parseFunction(node, false); case _tokentype.types._class: return this.parseClass(this.startNode(), false); case _tokentype.types._new: return this.parseNew(); case _tokentype.types.backQuote: return this.parseTemplate(); default: this.unexpected(); } }; pp.parseLiteral = function (value) { var node = this.startNode(); node.value = value; node.raw = this.input.slice(this.start, this.end); this.next(); return this.finishNode(node, "Literal"); }; pp.parseParenExpression = function () { this.expect(_tokentype.types.parenL); var val = this.parseExpression(); this.expect(_tokentype.types.parenR); return val; }; pp.parseParenAndDistinguishExpression = function (canBeArrow) { var startPos = this.start, startLoc = this.startLoc, val = undefined; if (this.options.ecmaVersion >= 6) { this.next(); var innerStartPos = this.start, innerStartLoc = this.startLoc; var exprList = [], first = true; var refDestructuringErrors = new _parseutil.DestructuringErrors(), spreadStart = undefined, innerParenStart = undefined; while (this.type !== _tokentype.types.parenR) { first ? first = false : this.expect(_tokentype.types.comma); if (this.type === _tokentype.types.ellipsis) { spreadStart = this.start; exprList.push(this.parseParenItem(this.parseRest())); break; } else { if (this.type === _tokentype.types.parenL && !innerParenStart) { innerParenStart = this.start; } exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); } } var innerEndPos = this.start, innerEndLoc = this.startLoc; this.expect(_tokentype.types.parenR); if (canBeArrow && !this.canInsertSemicolon() && this.eat(_tokentype.types.arrow)) { this.checkPatternErrors(refDestructuringErrors, true); if (innerParenStart) this.unexpected(innerParenStart); return this.parseParenArrowList(startPos, startLoc, exprList); } if (!exprList.length) this.unexpected(this.lastTokStart); if (spreadStart) this.unexpected(spreadStart); this.checkExpressionErrors(refDestructuringErrors, true); if (exprList.length > 1) { val = this.startNodeAt(innerStartPos, innerStartLoc); val.expressions = exprList; this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); } else { val = exprList[0]; } } else { val = this.parseParenExpression(); } if (this.options.preserveParens) { var par = this.startNodeAt(startPos, startLoc); par.expression = val; return this.finishNode(par, "ParenthesizedExpression"); } else { return val; } }; pp.parseParenItem = function (item) { return item; }; pp.parseParenArrowList = function (startPos, startLoc, exprList) { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList); }; // 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 noCalls // argument to parseSubscripts to prevent it from consuming the // argument list. var empty = []; pp.parseNew = function () { var node = this.startNode(); var meta = this.parseIdent(true); if (this.options.ecmaVersion >= 6 && this.eat(_tokentype.types.dot)) { node.meta = meta; node.property = this.parseIdent(true); if (node.property.name !== "target") this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); if (!this.inFunction) this.raiseRecoverable(node.start, "new.target can only be used in functions"); return this.finishNode(node, "MetaProperty"); } var startPos = this.start, startLoc = this.startLoc; node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); if (this.eat(_tokentype.types.parenL)) node.arguments = this.parseExprList(_tokentype.types.parenR, false);else node.arguments = empty; return this.finishNode(node, "NewExpression"); }; // Parse template expression. pp.parseTemplateElement = function () { var elem = this.startNode(); elem.value = { raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, '\n'), cooked: this.value }; this.next(); elem.tail = this.type === _tokentype.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(_tokentype.types.dollarBraceL); node.expressions.push(this.parseExpression()); this.expect(_tokentype.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, refDestructuringErrors) { var node = this.startNode(), first = true, propHash = {}; node.properties = []; this.next(); while (!this.eat(_tokentype.types.braceR)) { if (!first) { this.expect(_tokentype.types.comma); if (this.afterTrailingComma(_tokentype.types.braceR)) break; } else first = false; var prop = this.startNode(), isGenerator = undefined, startPos = undefined, startLoc = undefined; if (this.options.ecmaVersion >= 6) { prop.method = false; prop.shorthand = false; if (isPattern || refDestructuringErrors) { startPos = this.start; startLoc = this.startLoc; } if (!isPattern) isGenerator = this.eat(_tokentype.types.star); } this.parsePropertyName(prop); this.parsePropertyValue(prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors); this.checkPropClash(prop, propHash); node.properties.push(this.finishNode(prop, "Property")); } return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression"); }; pp.parsePropertyValue = function (prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors) { if (this.eat(_tokentype.types.colon)) { prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); prop.kind = "init"; } else if (this.options.ecmaVersion >= 6 && this.type === _tokentype.types.parenL) { if (isPattern) this.unexpected(); prop.kind = "init"; prop.method = true; prop.value = this.parseMethod(isGenerator); } else if (this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && this.type != _tokentype.types.comma && this.type != _tokentype.types.braceR) { if (isGenerator || isPattern) this.unexpected(); prop.kind = prop.key.name; this.parsePropertyName(prop); prop.value = this.parseMethod(false); var paramCount = prop.kind === "get" ? 0 : 1; if (prop.value.params.length !== paramCount) { var start = prop.value.start; if (prop.kind === "get") this.raiseRecoverable(start, "getter should have no params");else this.raiseRecoverable(start, "setter should have exactly one param"); } if (prop.kind === "set" && prop.value.params[0].type === "RestElement") this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { if (this.keywords.test(prop.key.name) || (this.strict ? this.reservedWordsStrictBind : this.reservedWords).test(prop.key.name) || this.inGenerator && prop.key.name == "yield") this.raiseRecoverable(prop.key.start, "'" + prop.key.name + "' can not be used as shorthand property"); prop.kind = "init"; if (isPattern) { prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); } else if (this.type === _tokentype.types.eq && refDestructuringErrors) { if (!refDestructuringErrors.shorthandAssign) refDestructuringErrors.shorthandAssign = this.start; prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); } else { prop.value = prop.key; } prop.shorthand = true; } else this.unexpected(); }; pp.parsePropertyName = function (prop) { if (this.options.ecmaVersion >= 6) { if (this.eat(_tokentype.types.bracketL)) { prop.computed = true; prop.key = this.parseMaybeAssign(); this.expect(_tokentype.types.bracketR); return prop.key; } else { prop.computed = false; } } return prop.key = this.type === _tokentype.types.num || this.type === _tokentype.types.string ? this.parseExprAtom() : this.parseIdent(true); }; // Initialize empty function node. pp.initFunction = function (node) { node.id = null; if (this.options.ecmaVersion >= 6) { node.generator = false; node.expression = false; } }; // Parse object or class method. pp.parseMethod = function (isGenerator) { var node = this.startNode(), oldInGen = this.inGenerator; this.inGenerator = isGenerator; this.initFunction(node); this.expect(_tokentype.types.parenL); node.params = this.parseBindingList(_tokentype.types.parenR, false, false); if (this.options.ecmaVersion >= 6) node.generator = isGenerator; this.parseFunctionBody(node, false); this.inGenerator = oldInGen; return this.finishNode(node, "FunctionExpression"); }; // Parse arrow function expression with given parameters. pp.parseArrowExpression = function (node, params) { var oldInGen = this.inGenerator; this.inGenerator = false; this.initFunction(node); node.params = this.toAssignableList(params, true); this.parseFunctionBody(node, true); this.inGenerator = oldInGen; return this.finishNode(node, "ArrowFunctionExpression"); }; // Parse function body and check parameters. pp.parseFunctionBody = function (node, isArrowFunction) { var isExpression = isArrowFunction && this.type !== _tokentype.types.braceL; 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.inFunction, oldLabels = this.labels; this.inFunction = true;this.labels = []; node.body = this.parseBlock(true); node.expression = false; this.inFunction = oldInFunc;this.labels = oldLabels; } // 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`. if (this.strict || !isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) { var oldStrict = this.strict; this.strict = true; if (node.id) this.checkLVal(node.id, true); this.checkParams(node); this.strict = oldStrict; } else if (isArrowFunction) { this.checkParams(node); } }; // Checks function params for various disallowed patterns such as using "eval" // or "arguments" and duplicate parameters. pp.checkParams = function (node) { var nameHash = {}; for (var i = 0; i < node.params.length; i++) { this.checkLVal(node.params[i], true, nameHash); } }; // 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, refDestructuringErrors) { var elts = [], first = true; while (!this.eat(close)) { if (!first) { this.expect(_tokentype.types.comma); if (allowTrailingComma && this.afterTrailingComma(close)) break; } else first = false; var elt = undefined; if (allowEmpty && this.type === _tokentype.types.comma) elt = null;else if (this.type === _tokentype.types.ellipsis) { elt = this.parseSpread(refDestructuringErrors); if (this.type === _tokentype.types.comma && refDestructuringErrors && !refDestructuringErrors.trailingComma) { refDestructuringErrors.trailingComma = this.lastTokStart; } } else elt = this.parseMaybeAssign(false, refDestructuringErrors); elts.push(elt); } return elts; }; // Parse the next token as an identifier. If `liberal` is true (used // when parsing properties), it will