| /*! jsonpath 1.0.2 */ |
| |
| (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.jsonpath = 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})({"./aesprim":[function(require,module,exports){ |
| /* |
| Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com> |
| Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com> |
| Copyright (C) 2013 Mathias Bynens <mathias@qiwi.be> |
| Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com> |
| Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be> |
| Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl> |
| Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com> |
| Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com> |
| Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com> |
| Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com> |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions are met: |
| |
| * Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| * Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY |
| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /*jslint bitwise:true plusplus:true */ |
| /*global esprima:true, define:true, exports:true, window: true, |
| throwErrorTolerant: true, |
| throwError: true, generateStatement: true, peek: true, |
| parseAssignmentExpression: true, parseBlock: true, parseExpression: true, |
| parseFunctionDeclaration: true, parseFunctionExpression: true, |
| parseFunctionSourceElements: true, parseVariableIdentifier: true, |
| parseLeftHandSideExpression: true, |
| parseUnaryExpression: true, |
| parseStatement: true, parseSourceElement: true */ |
| |
| (function (root, factory) { |
| 'use strict'; |
| |
| // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, |
| // Rhino, and plain browser loading. |
| |
| /* istanbul ignore next */ |
| if (typeof define === 'function' && define.amd) { |
| define(['exports'], factory); |
| } else if (typeof exports !== 'undefined') { |
| factory(exports); |
| } else { |
| factory((root.esprima = {})); |
| } |
| }(this, function (exports) { |
| 'use strict'; |
| |
| var Token, |
| TokenName, |
| FnExprTokens, |
| Syntax, |
| PropertyKind, |
| Messages, |
| Regex, |
| SyntaxTreeDelegate, |
| source, |
| strict, |
| index, |
| lineNumber, |
| lineStart, |
| length, |
| delegate, |
| lookahead, |
| state, |
| extra; |
| |
| Token = { |
| BooleanLiteral: 1, |
| EOF: 2, |
| Identifier: 3, |
| Keyword: 4, |
| NullLiteral: 5, |
| NumericLiteral: 6, |
| Punctuator: 7, |
| StringLiteral: 8, |
| RegularExpression: 9 |
| }; |
| |
| TokenName = {}; |
| TokenName[Token.BooleanLiteral] = 'Boolean'; |
| TokenName[Token.EOF] = '<end>'; |
| TokenName[Token.Identifier] = 'Identifier'; |
| TokenName[Token.Keyword] = 'Keyword'; |
| TokenName[Token.NullLiteral] = 'Null'; |
| TokenName[Token.NumericLiteral] = 'Numeric'; |
| TokenName[Token.Punctuator] = 'Punctuator'; |
| TokenName[Token.StringLiteral] = 'String'; |
| TokenName[Token.RegularExpression] = 'RegularExpression'; |
| |
| // A function following one of those tokens is an expression. |
| FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new', |
| 'return', 'case', 'delete', 'throw', 'void', |
| // assignment operators |
| '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=', |
| '&=', '|=', '^=', ',', |
| // binary/unary operators |
| '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&', |
| '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=', |
| '<=', '<', '>', '!=', '!==']; |
| |
| Syntax = { |
| AssignmentExpression: 'AssignmentExpression', |
| ArrayExpression: 'ArrayExpression', |
| BlockStatement: 'BlockStatement', |
| BinaryExpression: 'BinaryExpression', |
| BreakStatement: 'BreakStatement', |
| CallExpression: 'CallExpression', |
| CatchClause: 'CatchClause', |
| ConditionalExpression: 'ConditionalExpression', |
| ContinueStatement: 'ContinueStatement', |
| DoWhileStatement: 'DoWhileStatement', |
| DebuggerStatement: 'DebuggerStatement', |
| EmptyStatement: 'EmptyStatement', |
| ExpressionStatement: 'ExpressionStatement', |
| ForStatement: 'ForStatement', |
| ForInStatement: 'ForInStatement', |
| FunctionDeclaration: 'FunctionDeclaration', |
| FunctionExpression: 'FunctionExpression', |
| Identifier: 'Identifier', |
| IfStatement: 'IfStatement', |
| Literal: 'Literal', |
| LabeledStatement: 'LabeledStatement', |
| LogicalExpression: 'LogicalExpression', |
| MemberExpression: 'MemberExpression', |
| NewExpression: 'NewExpression', |
| ObjectExpression: 'ObjectExpression', |
| Program: 'Program', |
| Property: 'Property', |
| ReturnStatement: 'ReturnStatement', |
| SequenceExpression: 'SequenceExpression', |
| SwitchStatement: 'SwitchStatement', |
| SwitchCase: 'SwitchCase', |
| ThisExpression: 'ThisExpression', |
| ThrowStatement: 'ThrowStatement', |
| TryStatement: 'TryStatement', |
| UnaryExpression: 'UnaryExpression', |
| UpdateExpression: 'UpdateExpression', |
| VariableDeclaration: 'VariableDeclaration', |
| VariableDeclarator: 'VariableDeclarator', |
| WhileStatement: 'WhileStatement', |
| WithStatement: 'WithStatement' |
| }; |
| |
| PropertyKind = { |
| Data: 1, |
| Get: 2, |
| Set: 4 |
| }; |
| |
| // Error messages should be identical to V8. |
| Messages = { |
| UnexpectedToken: 'Unexpected token %0', |
| UnexpectedNumber: 'Unexpected number', |
| UnexpectedString: 'Unexpected string', |
| UnexpectedIdentifier: 'Unexpected identifier', |
| UnexpectedReserved: 'Unexpected reserved word', |
| UnexpectedEOS: 'Unexpected end of input', |
| NewlineAfterThrow: 'Illegal newline after throw', |
| InvalidRegExp: 'Invalid regular expression', |
| UnterminatedRegExp: 'Invalid regular expression: missing /', |
| InvalidLHSInAssignment: 'Invalid left-hand side in assignment', |
| InvalidLHSInForIn: 'Invalid left-hand side in for-in', |
| MultipleDefaultsInSwitch: 'More than one default clause in switch statement', |
| NoCatchOrFinally: 'Missing catch or finally after try', |
| UnknownLabel: 'Undefined label \'%0\'', |
| Redeclaration: '%0 \'%1\' has already been declared', |
| IllegalContinue: 'Illegal continue statement', |
| IllegalBreak: 'Illegal break statement', |
| IllegalReturn: 'Illegal return statement', |
| StrictModeWith: 'Strict mode code may not include a with statement', |
| StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', |
| StrictVarName: 'Variable name may not be eval or arguments in strict mode', |
| StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', |
| StrictParamDupe: 'Strict mode function may not have duplicate parameter names', |
| StrictFunctionName: 'Function name may not be eval or arguments in strict mode', |
| StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', |
| StrictDelete: 'Delete of an unqualified identifier in strict mode.', |
| StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', |
| AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', |
| AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', |
| StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', |
| StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', |
| StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', |
| StrictReservedWord: 'Use of future reserved word in strict mode' |
| }; |
| |
| // See also tools/generate-unicode-regex.py. |
| Regex = { |
| NonAsciiIdentifierStart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]'), |
| NonAsciiIdentifierPart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0\u08A2-\u08AC\u08E4-\u08FE\u0900-\u0963\u0966-\u096F\u0971-\u0977\u0979-\u097F\u0981-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C01-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C82\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D02\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191C\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1D00-\u1DE6\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA697\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7B\uAA80-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE26\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]') |
| }; |
| |
| // Ensure the condition is true, otherwise throw an error. |
| // This is only to have a better contract semantic, i.e. another safety net |
| // to catch a logic error. The condition shall be fulfilled in normal case. |
| // Do NOT use this to enforce a certain condition on any user input. |
| |
| function assert(condition, message) { |
| /* istanbul ignore if */ |
| if (!condition) { |
| throw new Error('ASSERT: ' + message); |
| } |
| } |
| |
| function isDecimalDigit(ch) { |
| return (ch >= 48 && ch <= 57); // 0..9 |
| } |
| |
| function isHexDigit(ch) { |
| return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; |
| } |
| |
| function isOctalDigit(ch) { |
| return '01234567'.indexOf(ch) >= 0; |
| } |
| |
| |
| // 7.2 White Space |
| |
| function isWhiteSpace(ch) { |
| return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) || |
| (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0); |
| } |
| |
| // 7.3 Line Terminators |
| |
| function isLineTerminator(ch) { |
| return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029); |
| } |
| |
| // 7.6 Identifier Names and Identifiers |
| |
| function isIdentifierStart(ch) { |
| return (ch == 0x40) || (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore) |
| (ch >= 0x41 && ch <= 0x5A) || // A..Z |
| (ch >= 0x61 && ch <= 0x7A) || // a..z |
| (ch === 0x5C) || // \ (backslash) |
| ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch))); |
| } |
| |
| function isIdentifierPart(ch) { |
| return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore) |
| (ch >= 0x41 && ch <= 0x5A) || // A..Z |
| (ch >= 0x61 && ch <= 0x7A) || // a..z |
| (ch >= 0x30 && ch <= 0x39) || // 0..9 |
| (ch === 0x5C) || // \ (backslash) |
| ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch))); |
| } |
| |
| // 7.6.1.2 Future Reserved Words |
| |
| function isFutureReservedWord(id) { |
| switch (id) { |
| case 'class': |
| case 'enum': |
| case 'export': |
| case 'extends': |
| case 'import': |
| case 'super': |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| function isStrictModeReservedWord(id) { |
| switch (id) { |
| case 'implements': |
| case 'interface': |
| case 'package': |
| case 'private': |
| case 'protected': |
| case 'public': |
| case 'static': |
| case 'yield': |
| case 'let': |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| function isRestrictedWord(id) { |
| return id === 'eval' || id === 'arguments'; |
| } |
| |
| // 7.6.1.1 Keywords |
| |
| function isKeyword(id) { |
| if (strict && isStrictModeReservedWord(id)) { |
| return true; |
| } |
| |
| // 'const' is specialized as Keyword in V8. |
| // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next. |
| // Some others are from future reserved words. |
| |
| switch (id.length) { |
| case 2: |
| return (id === 'if') || (id === 'in') || (id === 'do'); |
| case 3: |
| return (id === 'var') || (id === 'for') || (id === 'new') || |
| (id === 'try') || (id === 'let'); |
| case 4: |
| return (id === 'this') || (id === 'else') || (id === 'case') || |
| (id === 'void') || (id === 'with') || (id === 'enum'); |
| case 5: |
| return (id === 'while') || (id === 'break') || (id === 'catch') || |
| (id === 'throw') || (id === 'const') || (id === 'yield') || |
| (id === 'class') || (id === 'super'); |
| case 6: |
| return (id === 'return') || (id === 'typeof') || (id === 'delete') || |
| (id === 'switch') || (id === 'export') || (id === 'import'); |
| case 7: |
| return (id === 'default') || (id === 'finally') || (id === 'extends'); |
| case 8: |
| return (id === 'function') || (id === 'continue') || (id === 'debugger'); |
| case 10: |
| return (id === 'instanceof'); |
| default: |
| return false; |
| } |
| } |
| |
| // 7.4 Comments |
| |
| function addComment(type, value, start, end, loc) { |
| var comment, attacher; |
| |
| assert(typeof start === 'number', 'Comment must have valid position'); |
| |
| // Because the way the actual token is scanned, often the comments |
| // (if any) are skipped twice during the lexical analysis. |
| // Thus, we need to skip adding a comment if the comment array already |
| // handled it. |
| if (state.lastCommentStart >= start) { |
| return; |
| } |
| state.lastCommentStart = start; |
| |
| comment = { |
| type: type, |
| value: value |
| }; |
| if (extra.range) { |
| comment.range = [start, end]; |
| } |
| if (extra.loc) { |
| comment.loc = loc; |
| } |
| extra.comments.push(comment); |
| if (extra.attachComment) { |
| extra.leadingComments.push(comment); |
| extra.trailingComments.push(comment); |
| } |
| } |
| |
| function skipSingleLineComment(offset) { |
| var start, loc, ch, comment; |
| |
| start = index - offset; |
| loc = { |
| start: { |
| line: lineNumber, |
| column: index - lineStart - offset |
| } |
| }; |
| |
| while (index < length) { |
| ch = source.charCodeAt(index); |
| ++index; |
| if (isLineTerminator(ch)) { |
| if (extra.comments) { |
| comment = source.slice(start + offset, index - 1); |
| loc.end = { |
| line: lineNumber, |
| column: index - lineStart - 1 |
| }; |
| addComment('Line', comment, start, index - 1, loc); |
| } |
| if (ch === 13 && source.charCodeAt(index) === 10) { |
| ++index; |
| } |
| ++lineNumber; |
| lineStart = index; |
| return; |
| } |
| } |
| |
| if (extra.comments) { |
| comment = source.slice(start + offset, index); |
| loc.end = { |
| line: lineNumber, |
| column: index - lineStart |
| }; |
| addComment('Line', comment, start, index, loc); |
| } |
| } |
| |
| function skipMultiLineComment() { |
| var start, loc, ch, comment; |
| |
| if (extra.comments) { |
| start = index - 2; |
| loc = { |
| start: { |
| line: lineNumber, |
| column: index - lineStart - 2 |
| } |
| }; |
| } |
| |
| while (index < length) { |
| ch = source.charCodeAt(index); |
| if (isLineTerminator(ch)) { |
| if (ch === 0x0D && source.charCodeAt(index + 1) === 0x0A) { |
| ++index; |
| } |
| ++lineNumber; |
| ++index; |
| lineStart = index; |
| if (index >= length) { |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| } else if (ch === 0x2A) { |
| // Block comment ends with '*/'. |
| if (source.charCodeAt(index + 1) === 0x2F) { |
| ++index; |
| ++index; |
| if (extra.comments) { |
| comment = source.slice(start + 2, index - 2); |
| loc.end = { |
| line: lineNumber, |
| column: index - lineStart |
| }; |
| addComment('Block', comment, start, index, loc); |
| } |
| return; |
| } |
| ++index; |
| } else { |
| ++index; |
| } |
| } |
| |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| |
| function skipComment() { |
| var ch, start; |
| |
| start = (index === 0); |
| while (index < length) { |
| ch = source.charCodeAt(index); |
| |
| if (isWhiteSpace(ch)) { |
| ++index; |
| } else if (isLineTerminator(ch)) { |
| ++index; |
| if (ch === 0x0D && source.charCodeAt(index) === 0x0A) { |
| ++index; |
| } |
| ++lineNumber; |
| lineStart = index; |
| start = true; |
| } else if (ch === 0x2F) { // U+002F is '/' |
| ch = source.charCodeAt(index + 1); |
| if (ch === 0x2F) { |
| ++index; |
| ++index; |
| skipSingleLineComment(2); |
| start = true; |
| } else if (ch === 0x2A) { // U+002A is '*' |
| ++index; |
| ++index; |
| skipMultiLineComment(); |
| } else { |
| break; |
| } |
| } else if (start && ch === 0x2D) { // U+002D is '-' |
| // U+003E is '>' |
| if ((source.charCodeAt(index + 1) === 0x2D) && (source.charCodeAt(index + 2) === 0x3E)) { |
| // '-->' is a single-line comment |
| index += 3; |
| skipSingleLineComment(3); |
| } else { |
| break; |
| } |
| } else if (ch === 0x3C) { // U+003C is '<' |
| if (source.slice(index + 1, index + 4) === '!--') { |
| ++index; // `<` |
| ++index; // `!` |
| ++index; // `-` |
| ++index; // `-` |
| skipSingleLineComment(4); |
| } else { |
| break; |
| } |
| } else { |
| break; |
| } |
| } |
| } |
| |
| function scanHexEscape(prefix) { |
| var i, len, ch, code = 0; |
| |
| len = (prefix === 'u') ? 4 : 2; |
| for (i = 0; i < len; ++i) { |
| if (index < length && isHexDigit(source[index])) { |
| ch = source[index++]; |
| code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); |
| } else { |
| return ''; |
| } |
| } |
| return String.fromCharCode(code); |
| } |
| |
| function getEscapedIdentifier() { |
| var ch, id; |
| |
| ch = source.charCodeAt(index++); |
| id = String.fromCharCode(ch); |
| |
| // '\u' (U+005C, U+0075) denotes an escaped character. |
| if (ch === 0x5C) { |
| if (source.charCodeAt(index) !== 0x75) { |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| ++index; |
| ch = scanHexEscape('u'); |
| if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) { |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| id = ch; |
| } |
| |
| while (index < length) { |
| ch = source.charCodeAt(index); |
| if (!isIdentifierPart(ch)) { |
| break; |
| } |
| ++index; |
| id += String.fromCharCode(ch); |
| |
| // '\u' (U+005C, U+0075) denotes an escaped character. |
| if (ch === 0x5C) { |
| id = id.substr(0, id.length - 1); |
| if (source.charCodeAt(index) !== 0x75) { |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| ++index; |
| ch = scanHexEscape('u'); |
| if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) { |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| id += ch; |
| } |
| } |
| |
| return id; |
| } |
| |
| function getIdentifier() { |
| var start, ch; |
| |
| start = index++; |
| while (index < length) { |
| ch = source.charCodeAt(index); |
| if (ch === 0x5C) { |
| // Blackslash (U+005C) marks Unicode escape sequence. |
| index = start; |
| return getEscapedIdentifier(); |
| } |
| if (isIdentifierPart(ch)) { |
| ++index; |
| } else { |
| break; |
| } |
| } |
| |
| return source.slice(start, index); |
| } |
| |
| function scanIdentifier() { |
| var start, id, type; |
| |
| start = index; |
| |
| // Backslash (U+005C) starts an escaped character. |
| id = (source.charCodeAt(index) === 0x5C) ? getEscapedIdentifier() : getIdentifier(); |
| |
| // There is no keyword or literal with only one character. |
| // Thus, it must be an identifier. |
| if (id.length === 1) { |
| type = Token.Identifier; |
| } else if (isKeyword(id)) { |
| type = Token.Keyword; |
| } else if (id === 'null') { |
| type = Token.NullLiteral; |
| } else if (id === 'true' || id === 'false') { |
| type = Token.BooleanLiteral; |
| } else { |
| type = Token.Identifier; |
| } |
| |
| return { |
| type: type, |
| value: id, |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| } |
| |
| |
| // 7.7 Punctuators |
| |
| function scanPunctuator() { |
| var start = index, |
| code = source.charCodeAt(index), |
| code2, |
| ch1 = source[index], |
| ch2, |
| ch3, |
| ch4; |
| |
| switch (code) { |
| |
| // Check for most common single-character punctuators. |
| case 0x2E: // . dot |
| case 0x28: // ( open bracket |
| case 0x29: // ) close bracket |
| case 0x3B: // ; semicolon |
| case 0x2C: // , comma |
| case 0x7B: // { open curly brace |
| case 0x7D: // } close curly brace |
| case 0x5B: // [ |
| case 0x5D: // ] |
| case 0x3A: // : |
| case 0x3F: // ? |
| case 0x7E: // ~ |
| ++index; |
| if (extra.tokenize) { |
| if (code === 0x28) { |
| extra.openParenToken = extra.tokens.length; |
| } else if (code === 0x7B) { |
| extra.openCurlyToken = extra.tokens.length; |
| } |
| } |
| return { |
| type: Token.Punctuator, |
| value: String.fromCharCode(code), |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| |
| default: |
| code2 = source.charCodeAt(index + 1); |
| |
| // '=' (U+003D) marks an assignment or comparison operator. |
| if (code2 === 0x3D) { |
| switch (code) { |
| case 0x2B: // + |
| case 0x2D: // - |
| case 0x2F: // / |
| case 0x3C: // < |
| case 0x3E: // > |
| case 0x5E: // ^ |
| case 0x7C: // | |
| case 0x25: // % |
| case 0x26: // & |
| case 0x2A: // * |
| index += 2; |
| return { |
| type: Token.Punctuator, |
| value: String.fromCharCode(code) + String.fromCharCode(code2), |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| |
| case 0x21: // ! |
| case 0x3D: // = |
| index += 2; |
| |
| // !== and === |
| if (source.charCodeAt(index) === 0x3D) { |
| ++index; |
| } |
| return { |
| type: Token.Punctuator, |
| value: source.slice(start, index), |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| } |
| } |
| } |
| |
| // 4-character punctuator: >>>= |
| |
| ch4 = source.substr(index, 4); |
| |
| if (ch4 === '>>>=') { |
| index += 4; |
| return { |
| type: Token.Punctuator, |
| value: ch4, |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| } |
| |
| // 3-character punctuators: === !== >>> <<= >>= |
| |
| ch3 = ch4.substr(0, 3); |
| |
| if (ch3 === '>>>' || ch3 === '<<=' || ch3 === '>>=') { |
| index += 3; |
| return { |
| type: Token.Punctuator, |
| value: ch3, |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| } |
| |
| // Other 2-character punctuators: ++ -- << >> && || |
| ch2 = ch3.substr(0, 2); |
| |
| if ((ch1 === ch2[1] && ('+-<>&|'.indexOf(ch1) >= 0)) || ch2 === '=>') { |
| index += 2; |
| return { |
| type: Token.Punctuator, |
| value: ch2, |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| } |
| |
| // 1-character punctuators: < > = ! + - * % & | ^ / |
| if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { |
| ++index; |
| return { |
| type: Token.Punctuator, |
| value: ch1, |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| } |
| |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| |
| // 7.8.3 Numeric Literals |
| |
| function scanHexLiteral(start) { |
| var number = ''; |
| |
| while (index < length) { |
| if (!isHexDigit(source[index])) { |
| break; |
| } |
| number += source[index++]; |
| } |
| |
| if (number.length === 0) { |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| |
| if (isIdentifierStart(source.charCodeAt(index))) { |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| |
| return { |
| type: Token.NumericLiteral, |
| value: parseInt('0x' + number, 16), |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| } |
| |
| function scanOctalLiteral(start) { |
| var number = '0' + source[index++]; |
| while (index < length) { |
| if (!isOctalDigit(source[index])) { |
| break; |
| } |
| number += source[index++]; |
| } |
| |
| if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) { |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| |
| return { |
| type: Token.NumericLiteral, |
| value: parseInt(number, 8), |
| octal: true, |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| } |
| |
| function scanNumericLiteral() { |
| var number, start, ch; |
| |
| ch = source[index]; |
| assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), |
| 'Numeric literal must start with a decimal digit or a decimal point'); |
| |
| start = index; |
| number = ''; |
| if (ch !== '.') { |
| number = source[index++]; |
| ch = source[index]; |
| |
| // Hex number starts with '0x'. |
| // Octal number starts with '0'. |
| if (number === '0') { |
| if (ch === 'x' || ch === 'X') { |
| ++index; |
| return scanHexLiteral(start); |
| } |
| if (isOctalDigit(ch)) { |
| return scanOctalLiteral(start); |
| } |
| |
| // decimal number starts with '0' such as '09' is illegal. |
| if (ch && isDecimalDigit(ch.charCodeAt(0))) { |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| } |
| |
| while (isDecimalDigit(source.charCodeAt(index))) { |
| number += source[index++]; |
| } |
| ch = source[index]; |
| } |
| |
| if (ch === '.') { |
| number += source[index++]; |
| while (isDecimalDigit(source.charCodeAt(index))) { |
| number += source[index++]; |
| } |
| ch = source[index]; |
| } |
| |
| if (ch === 'e' || ch === 'E') { |
| number += source[index++]; |
| |
| ch = source[index]; |
| if (ch === '+' || ch === '-') { |
| number += source[index++]; |
| } |
| if (isDecimalDigit(source.charCodeAt(index))) { |
| while (isDecimalDigit(source.charCodeAt(index))) { |
| number += source[index++]; |
| } |
| } else { |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| } |
| |
| if (isIdentifierStart(source.charCodeAt(index))) { |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| |
| return { |
| type: Token.NumericLiteral, |
| value: parseFloat(number), |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| } |
| |
| // 7.8.4 String Literals |
| |
| function scanStringLiteral() { |
| var str = '', quote, start, ch, code, unescaped, restore, octal = false, startLineNumber, startLineStart; |
| startLineNumber = lineNumber; |
| startLineStart = lineStart; |
| |
| quote = source[index]; |
| assert((quote === '\'' || quote === '"'), |
| 'String literal must starts with a quote'); |
| |
| start = index; |
| ++index; |
| |
| while (index < length) { |
| ch = source[index++]; |
| |
| if (ch === quote) { |
| quote = ''; |
| break; |
| } else if (ch === '\\') { |
| ch = source[index++]; |
| if (!ch || !isLineTerminator(ch.charCodeAt(0))) { |
| switch (ch) { |
| case 'u': |
| case 'x': |
| restore = index; |
| unescaped = scanHexEscape(ch); |
| if (unescaped) { |
| str += unescaped; |
| } else { |
| index = restore; |
| str += ch; |
| } |
| break; |
| case 'n': |
| str += '\n'; |
| break; |
| case 'r': |
| str += '\r'; |
| break; |
| case 't': |
| str += '\t'; |
| break; |
| case 'b': |
| str += '\b'; |
| break; |
| case 'f': |
| str += '\f'; |
| break; |
| case 'v': |
| str += '\x0B'; |
| break; |
| |
| default: |
| if (isOctalDigit(ch)) { |
| code = '01234567'.indexOf(ch); |
| |
| // \0 is not octal escape sequence |
| if (code !== 0) { |
| octal = true; |
| } |
| |
| if (index < length && isOctalDigit(source[index])) { |
| octal = true; |
| code = code * 8 + '01234567'.indexOf(source[index++]); |
| |
| // 3 digits are only allowed when string starts |
| // with 0, 1, 2, 3 |
| if ('0123'.indexOf(ch) >= 0 && |
| index < length && |
| isOctalDigit(source[index])) { |
| code = code * 8 + '01234567'.indexOf(source[index++]); |
| } |
| } |
| str += String.fromCharCode(code); |
| } else { |
| str += ch; |
| } |
| break; |
| } |
| } else { |
| ++lineNumber; |
| if (ch === '\r' && source[index] === '\n') { |
| ++index; |
| } |
| lineStart = index; |
| } |
| } else if (isLineTerminator(ch.charCodeAt(0))) { |
| break; |
| } else { |
| str += ch; |
| } |
| } |
| |
| if (quote !== '') { |
| throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| |
| return { |
| type: Token.StringLiteral, |
| value: str, |
| octal: octal, |
| startLineNumber: startLineNumber, |
| startLineStart: startLineStart, |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| } |
| |
| function testRegExp(pattern, flags) { |
| var value; |
| try { |
| value = new RegExp(pattern, flags); |
| } catch (e) { |
| throwError({}, Messages.InvalidRegExp); |
| } |
| return value; |
| } |
| |
| function scanRegExpBody() { |
| var ch, str, classMarker, terminated, body; |
| |
| ch = source[index]; |
| assert(ch === '/', 'Regular expression literal must start with a slash'); |
| str = source[index++]; |
| |
| classMarker = false; |
| terminated = false; |
| while (index < length) { |
| ch = source[index++]; |
| str += ch; |
| if (ch === '\\') { |
| ch = source[index++]; |
| // ECMA-262 7.8.5 |
| if (isLineTerminator(ch.charCodeAt(0))) { |
| throwError({}, Messages.UnterminatedRegExp); |
| } |
| str += ch; |
| } else if (isLineTerminator(ch.charCodeAt(0))) { |
| throwError({}, Messages.UnterminatedRegExp); |
| } else if (classMarker) { |
| if (ch === ']') { |
| classMarker = false; |
| } |
| } else { |
| if (ch === '/') { |
| terminated = true; |
| break; |
| } else if (ch === '[') { |
| classMarker = true; |
| } |
| } |
| } |
| |
| if (!terminated) { |
| throwError({}, Messages.UnterminatedRegExp); |
| } |
| |
| // Exclude leading and trailing slash. |
| body = str.substr(1, str.length - 2); |
| return { |
| value: body, |
| literal: str |
| }; |
| } |
| |
| function scanRegExpFlags() { |
| var ch, str, flags, restore; |
| |
| str = ''; |
| flags = ''; |
| while (index < length) { |
| ch = source[index]; |
| if (!isIdentifierPart(ch.charCodeAt(0))) { |
| break; |
| } |
| |
| ++index; |
| if (ch === '\\' && index < length) { |
| ch = source[index]; |
| if (ch === 'u') { |
| ++index; |
| restore = index; |
| ch = scanHexEscape('u'); |
| if (ch) { |
| flags += ch; |
| for (str += '\\u'; restore < index; ++restore) { |
| str += source[restore]; |
| } |
| } else { |
| index = restore; |
| flags += 'u'; |
| str += '\\u'; |
| } |
| throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } else { |
| str += '\\'; |
| throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL'); |
| } |
| } else { |
| flags += ch; |
| str += ch; |
| } |
| } |
| |
| return { |
| value: flags, |
| literal: str |
| }; |
| } |
| |
| function scanRegExp() { |
| var start, body, flags, pattern, value; |
| |
| lookahead = null; |
| skipComment(); |
| start = index; |
| |
| body = scanRegExpBody(); |
| flags = scanRegExpFlags(); |
| value = testRegExp(body.value, flags.value); |
| |
| if (extra.tokenize) { |
| return { |
| type: Token.RegularExpression, |
| value: value, |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: start, |
| end: index |
| }; |
| } |
| |
| return { |
| literal: body.literal + flags.literal, |
| value: value, |
| start: start, |
| end: index |
| }; |
| } |
| |
| function collectRegex() { |
| var pos, loc, regex, token; |
| |
| skipComment(); |
| |
| pos = index; |
| loc = { |
| start: { |
| line: lineNumber, |
| column: index - lineStart |
| } |
| }; |
| |
| regex = scanRegExp(); |
| loc.end = { |
| line: lineNumber, |
| column: index - lineStart |
| }; |
| |
| /* istanbul ignore next */ |
| if (!extra.tokenize) { |
| // Pop the previous token, which is likely '/' or '/=' |
| if (extra.tokens.length > 0) { |
| token = extra.tokens[extra.tokens.length - 1]; |
| if (token.range[0] === pos && token.type === 'Punctuator') { |
| if (token.value === '/' || token.value === '/=') { |
| extra.tokens.pop(); |
| } |
| } |
| } |
| |
| extra.tokens.push({ |
| type: 'RegularExpression', |
| value: regex.literal, |
| range: [pos, index], |
| loc: loc |
| }); |
| } |
| |
| return regex; |
| } |
| |
| function isIdentifierName(token) { |
| return token.type === Token.Identifier || |
| token.type === Token.Keyword || |
| token.type === Token.BooleanLiteral || |
| token.type === Token.NullLiteral; |
| } |
| |
| function advanceSlash() { |
| var prevToken, |
| checkToken; |
| // Using the following algorithm: |
| // https://github.com/mozilla/sweet.js/wiki/design |
| prevToken = extra.tokens[extra.tokens.length - 1]; |
| if (!prevToken) { |
| // Nothing before that: it cannot be a division. |
| return collectRegex(); |
| } |
| if (prevToken.type === 'Punctuator') { |
| if (prevToken.value === ']') { |
| return scanPunctuator(); |
| } |
| if (prevToken.value === ')') { |
| checkToken = extra.tokens[extra.openParenToken - 1]; |
| if (checkToken && |
| checkToken.type === 'Keyword' && |
| (checkToken.value === 'if' || |
| checkToken.value === 'while' || |
| checkToken.value === 'for' || |
| checkToken.value === 'with')) { |
| return collectRegex(); |
| } |
| return scanPunctuator(); |
| } |
| if (prevToken.value === '}') { |
| // Dividing a function by anything makes little sense, |
| // but we have to check for that. |
| if (extra.tokens[extra.openCurlyToken - 3] && |
| extra.tokens[extra.openCurlyToken - 3].type === 'Keyword') { |
| // Anonymous function. |
| checkToken = extra.tokens[extra.openCurlyToken - 4]; |
| if (!checkToken) { |
| return scanPunctuator(); |
| } |
| } else if (extra.tokens[extra.openCurlyToken - 4] && |
| extra.tokens[extra.openCurlyToken - 4].type === 'Keyword') { |
| // Named function. |
| checkToken = extra.tokens[extra.openCurlyToken - 5]; |
| if (!checkToken) { |
| return collectRegex(); |
| } |
| } else { |
| return scanPunctuator(); |
| } |
| // checkToken determines whether the function is |
| // a declaration or an expression. |
| if (FnExprTokens.indexOf(checkToken.value) >= 0) { |
| // It is an expression. |
| return scanPunctuator(); |
| } |
| // It is a declaration. |
| return collectRegex(); |
| } |
| return collectRegex(); |
| } |
| if (prevToken.type === 'Keyword') { |
| return collectRegex(); |
| } |
| return scanPunctuator(); |
| } |
| |
| function advance() { |
| var ch; |
| |
| skipComment(); |
| |
| if (index >= length) { |
| return { |
| type: Token.EOF, |
| lineNumber: lineNumber, |
| lineStart: lineStart, |
| start: index, |
| end: index |
| }; |
| } |
| |
| ch = source.charCodeAt(index); |
| |
| if (isIdentifierStart(ch)) { |
| return scanIdentifier(); |
| } |
| |
| // Very common: ( and ) and ; |
| if (ch === 0x28 || ch === 0x29 || ch === 0x3B) { |
| return scanPunctuator(); |
| } |
| |
| // String literal starts with single quote (U+0027) or double quote (U+0022). |
| if (ch === 0x27 || ch === 0x22) { |
| return scanStringLiteral(); |
| } |
| |
| |
| // Dot (.) U+002E can also start a floating-point number, hence the need |
| // to check the next character. |
| if (ch === 0x2E) { |
| if (isDecimalDigit(source.charCodeAt(index + 1))) { |
| return scanNumericLiteral(); |
| } |
| return scanPunctuator(); |
| } |
| |
| if (isDecimalDigit(ch)) { |
| return scanNumericLiteral(); |
| } |
| |
| // Slash (/) U+002F can also start a regex. |
| if (extra.tokenize && ch === 0x2F) { |
| return advanceSlash(); |
| } |
| |
| return scanPunctuator(); |
| } |
| |
| function collectToken() { |
| var loc, token, range, value; |
| |
| skipComment(); |
| loc = { |
| start: { |
| line: lineNumber, |
| column: index - lineStart |
| } |
| }; |
| |
| token = advance(); |
| loc.end = { |
| line: lineNumber, |
| column: index - lineStart |
| }; |
| |
| if (token.type !== Token.EOF) { |
| value = source.slice(token.start, token.end); |
| extra.tokens.push({ |
| type: TokenName[token.type], |
| value: value, |
| range: [token.start, token.end], |
| loc: loc |
| }); |
| } |
| |
| return token; |
| } |
| |
| function lex() { |
| var token; |
| |
| token = lookahead; |
| index = token.end; |
| lineNumber = token.lineNumber; |
| lineStart = token.lineStart; |
| |
| lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance(); |
| |
| index = token.end; |
| lineNumber = token.lineNumber; |
| lineStart = token.lineStart; |
| |
| return token; |
| } |
| |
| function peek() { |
| var pos, line, start; |
| |
| pos = index; |
| line = lineNumber; |
| start = lineStart; |
| lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance(); |
| index = pos; |
| lineNumber = line; |
| lineStart = start; |
| } |
| |
| function Position(line, column) { |
| this.line = line; |
| this.column = column; |
| } |
| |
| function SourceLocation(startLine, startColumn, line, column) { |
| this.start = new Position(startLine, startColumn); |
| this.end = new Position(line, column); |
| } |
| |
| SyntaxTreeDelegate = { |
| |
| name: 'SyntaxTree', |
| |
| processComment: function (node) { |
| var lastChild, trailingComments; |
| |
| if (node.type === Syntax.Program) { |
| if (node.body.length > 0) { |
| return; |
| } |
| } |
| |
| if (extra.trailingComments.length > 0) { |
| if (extra.trailingComments[0].range[0] >= node.range[1]) { |
| trailingComments = extra.trailingComments; |
| extra.trailingComments = []; |
| } else { |
| extra.trailingComments.length = 0; |
| } |
| } else { |
| if (extra.bottomRightStack.length > 0 && |
| extra.bottomRightStack[extra.bottomRightStack.length - 1].trailingComments && |
| extra.bottomRightStack[extra.bottomRightStack.length - 1].trailingComments[0].range[0] >= node.range[1]) { |
| trailingComments = extra.bottomRightStack[extra.bottomRightStack.length - 1].trailingComments; |
| delete extra.bottomRightStack[extra.bottomRightStack.length - 1].trailingComments; |
| } |
| } |
| |
| // Eating the stack. |
| while (extra.bottomRightStack.length > 0 && extra.bottomRightStack[extra.bottomRightStack.length - 1].range[0] >= node.range[0]) { |
| lastChild = extra.bottomRightStack.pop(); |
| } |
| |
| if (lastChild) { |
| if (lastChild.leadingComments && lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= node.range[0]) { |
| node.leadingComments = lastChild.leadingComments; |
| delete lastChild.leadingComments; |
| } |
| } else if (extra.leadingComments.length > 0 && extra.leadingComments[extra.leadingComments.length - 1].range[1] <= node.range[0]) { |
| node.leadingComments = extra.leadingComments; |
| extra.leadingComments = []; |
| } |
| |
| |
| if (trailingComments) { |
| node.trailingComments = trailingComments; |
| } |
| |
| extra.bottomRightStack.push(node); |
| }, |
| |
| markEnd: function (node, startToken) { |
| if (extra.range) { |
| node.range = [startToken.start, index]; |
| } |
| if (extra.loc) { |
| node.loc = new SourceLocation( |
| startToken.startLineNumber === undefined ? startToken.lineNumber : startToken.startLineNumber, |
| startToken.start - (startToken.startLineStart === undefined ? startToken.lineStart : startToken.startLineStart), |
| lineNumber, |
| index - lineStart |
| ); |
| this.postProcess(node); |
| } |
| |
| if (extra.attachComment) { |
| this.processComment(node); |
| } |
| return node; |
| }, |
| |
| postProcess: function (node) { |
| if (extra.source) { |
| node.loc.source = extra.source; |
| } |
| return node; |
| }, |
| |
| createArrayExpression: function (elements) { |
| return { |
| type: Syntax.ArrayExpression, |
| elements: elements |
| }; |
| }, |
| |
| createAssignmentExpression: function (operator, left, right) { |
| return { |
| type: Syntax.AssignmentExpression, |
| operator: operator, |
| left: left, |
| right: right |
| }; |
| }, |
| |
| createBinaryExpression: function (operator, left, right) { |
| var type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : |
| Syntax.BinaryExpression; |
| return { |
| type: type, |
| operator: operator, |
| left: left, |
| right: right |
| }; |
| }, |
| |
| createBlockStatement: function (body) { |
| return { |
| type: Syntax.BlockStatement, |
| body: body |
| }; |
| }, |
| |
| createBreakStatement: function (label) { |
| return { |
| type: Syntax.BreakStatement, |
| label: label |
| }; |
| }, |
| |
| createCallExpression: function (callee, args) { |
| return { |
| type: Syntax.CallExpression, |
| callee: callee, |
| 'arguments': args |
| }; |
| }, |
| |
| createCatchClause: function (param, body) { |
| return { |
| type: Syntax.CatchClause, |
| param: param, |
| body: body |
| }; |
| }, |
| |
| createConditionalExpression: function (test, consequent, alternate) { |
| return { |
| type: Syntax.ConditionalExpression, |
| test: test, |
| consequent: consequent, |
| alternate: alternate |
| }; |
| }, |
| |
| createContinueStatement: function (label) { |
| return { |
| type: Syntax.ContinueStatement, |
| label: label |
| }; |
| }, |
| |
| createDebuggerStatement: function () { |
| return { |
| type: Syntax.DebuggerStatement |
| }; |
| }, |
| |
| createDoWhileStatement: function (body, test) { |
| return { |
| type: Syntax.DoWhileStatement, |
| body: body, |
| test: test |
| }; |
| }, |
| |
| createEmptyStatement: function () { |
| return { |
| type: Syntax.EmptyStatement |
| }; |
| }, |
| |
| createExpressionStatement: function (expression) { |
| return { |
| type: Syntax.ExpressionStatement, |
| expression: expression |
| }; |
| }, |
| |
| createForStatement: function (init, test, update, body) { |
| return { |
| type: Syntax.ForStatement, |
| init: init, |
| test: test, |
| update: update, |
| body: body |
| }; |
| }, |
| |
| createForInStatement: function (left, right, body) { |
| return { |
| type: Syntax.ForInStatement, |
| left: left, |
| right: right, |
| body: body, |
| each: false |
| }; |
| }, |
| |
| createFunctionDeclaration: function (id, params, defaults, body) { |
| return { |
| type: Syntax.FunctionDeclaration, |
| id: id, |
| params: params, |
| defaults: defaults, |
| body: body, |
| rest: null, |
| generator: false, |
| expression: false |
| }; |
| }, |
| |
| createFunctionExpression: function (id, params, defaults, body) { |
| return { |
| type: Syntax.FunctionExpression, |
| id: id, |
| params: params, |
| defaults: defaults, |
| body: body, |
| rest: null, |
| generator: false, |
| expression: false |
| }; |
| }, |
| |
| createIdentifier: function (name) { |
| return { |
| type: Syntax.Identifier, |
| name: name |
| }; |
| }, |
| |
| createIfStatement: function (test, consequent, alternate) { |
| return { |
| type: Syntax.IfStatement, |
| test: test, |
| consequent: consequent, |
| alternate: alternate |
| }; |
| }, |
| |
| createLabeledStatement: function (label, body) { |
| return { |
| type: Syntax.LabeledStatement, |
| label: label, |
| body: body |
| }; |
| }, |
| |
| createLiteral: function (token) { |
| return { |
| type: Syntax.Literal, |
| value: token.value, |
| raw: source.slice(token.start, token.end) |
| }; |
| }, |
| |
| createMemberExpression: function (accessor, object, property) { |
| return { |
| type: Syntax.MemberExpression, |
| computed: accessor === '[', |
| object: object, |
| property: property |
| }; |
| }, |
| |
| createNewExpression: function (callee, args) { |
| return { |
| type: Syntax.NewExpression, |
| callee: callee, |
| 'arguments': args |
| }; |
| }, |
| |
| createObjectExpression: function (properties) { |
| return { |
| type: Syntax.ObjectExpression, |
| properties: properties |
| }; |
| }, |
| |
| createPostfixExpression: function (operator, argument) { |
| return { |
| type: Syntax.UpdateExpression, |
| operator: operator, |
| argument: argument, |
| prefix: false |
| }; |
| }, |
| |
| createProgram: function (body) { |
| return { |
| type: Syntax.Program, |
| body: body |
| }; |
| }, |
| |
| createProperty: function (kind, key, value) { |
| return { |
| type: Syntax.Property, |
| key: key, |
| value: value, |
| kind: kind |
| }; |
| }, |
| |
| createReturnStatement: function (argument) { |
| return { |
| type: Syntax.ReturnStatement, |
| argument: argument |
| }; |
| }, |
| |
| createSequenceExpression: function (expressions) { |
| return { |
| type: Syntax.SequenceExpression, |
| expressions: expressions |
| }; |
| }, |
| |
| createSwitchCase: function (test, consequent) { |
| return { |
| type: Syntax.SwitchCase, |
| test: test, |
| consequent: consequent |
| }; |
| }, |
| |
| createSwitchStatement: function (discriminant, cases) { |
| return { |
| type: Syntax.SwitchStatement, |
| discriminant: discriminant, |
| cases: cases |
| }; |
| }, |
| |
| createThisExpression: function () { |
| return { |
| type: Syntax.ThisExpression |
| }; |
| }, |
| |
| createThrowStatement: function (argument) { |
| return { |
| type: Syntax.ThrowStatement, |
| argument: argument |
| }; |
| }, |
| |
| createTryStatement: function (block, guardedHandlers, handlers, finalizer) { |
| return { |
| type: Syntax.TryStatement, |
| block: block, |
| guardedHandlers: guardedHandlers, |
| handlers: handlers, |
| finalizer: finalizer |
| }; |
| }, |
| |
| createUnaryExpression: function (operator, argument) { |
| if (operator === '++' || operator === '--') { |
| return { |
| type: Syntax.UpdateExpression, |
| operator: operator, |
| argument: argument, |
| prefix: true |
| }; |
| } |
| return { |
| type: Syntax.UnaryExpression, |
| operator: operator, |
| argument: argument, |
| prefix: true |
| }; |
| }, |
| |
| createVariableDeclaration: function (declarations, kind) { |
| return { |
| type: Syntax.VariableDeclaration, |
| declarations: declarations, |
| kind: kind |
| }; |
| }, |
| |
| createVariableDeclarator: function (id, init) { |
| return { |
| type: Syntax.VariableDeclarator, |
| id: id, |
| init: init |
| }; |
| }, |
| |
| createWhileStatement: function (test, body) { |
| return { |
| type: Syntax.WhileStatement, |
| test: test, |
| body: body |
| }; |
| }, |
| |
| createWithStatement: function (object, body) { |
| return { |
| type: Syntax.WithStatement, |
| object: object, |
| body: body |
| }; |
| } |
| }; |
| |
| // Return true if there is a line terminator before the next token. |
| |
| function peekLineTerminator() { |
| var pos, line, start, found; |
| |
| pos = index; |
| line = lineNumber; |
| start = lineStart; |
| skipComment(); |
| found = lineNumber !== line; |
| index = pos; |
| lineNumber = line; |
| lineStart = start; |
| |
| return found; |
| } |
| |
| // Throw an exception |
| |
| function throwError(token, messageFormat) { |
| var error, |
| args = Array.prototype.slice.call(arguments, 2), |
| msg = messageFormat.replace( |
| /%(\d)/g, |
| function (whole, index) { |
| assert(index < args.length, 'Message reference must be in range'); |
| return args[index]; |
| } |
| ); |
| |
| if (typeof token.lineNumber === 'number') { |
| error = new Error('Line ' + token.lineNumber + ': ' + msg); |
| error.index = token.start; |
| error.lineNumber = token.lineNumber; |
| error.column = token.start - lineStart + 1; |
| } else { |
| error = new Error('Line ' + lineNumber + ': ' + msg); |
| error.index = index; |
| error.lineNumber = lineNumber; |
| error.column = index - lineStart + 1; |
| } |
| |
| error.description = msg; |
| throw error; |
| } |
| |
| function throwErrorTolerant() { |
| try { |
| throwError.apply(null, arguments); |
| } catch (e) { |
| if (extra.errors) { |
| extra.errors.push(e); |
| } else { |
| throw e; |
| } |
| } |
| } |
| |
| |
| // Throw an exception because of the token. |
| |
| function throwUnexpected(token) { |
| if (token.type === Token.EOF) { |
| throwError(token, Messages.UnexpectedEOS); |
| } |
| |
| if (token.type === Token.NumericLiteral) { |
| throwError(token, Messages.UnexpectedNumber); |
| } |
| |
| if (token.type === Token.StringLiteral) { |
| throwError(token, Messages.UnexpectedString); |
| } |
| |
| if (token.type === Token.Identifier) { |
| throwError(token, Messages.UnexpectedIdentifier); |
| } |
| |
| if (token.type === Token.Keyword) { |
| if (isFutureReservedWord(token.value)) { |
| throwError(token, Messages.UnexpectedReserved); |
| } else if (strict && isStrictModeReservedWord(token.value)) { |
| throwErrorTolerant(token, Messages.StrictReservedWord); |
| return; |
| } |
| throwError(token, Messages.UnexpectedToken, token.value); |
| } |
| |
| // BooleanLiteral, NullLiteral, or Punctuator. |
| throwError(token, Messages.UnexpectedToken, token.value); |
| } |
| |
| // Expect the next token to match the specified punctuator. |
| // If not, an exception will be thrown. |
| |
| function expect(value) { |
| var token = lex(); |
| if (token.type !== Token.Punctuator || token.value !== value) { |
| throwUnexpected(token); |
| } |
| } |
| |
| // Expect the next token to match the specified keyword. |
| // If not, an exception will be thrown. |
| |
| function expectKeyword(keyword) { |
| var token = lex(); |
| if (token.type !== Token.Keyword || token.value !== keyword) { |
| throwUnexpected(token); |
| } |
| } |
| |
| // Return true if the next token matches the specified punctuator. |
| |
| function match(value) { |
| return lookahead.type === Token.Punctuator && lookahead.value === value; |
| } |
| |
| // Return true if the next token matches the specified keyword |
| |
| function matchKeyword(keyword) { |
| return lookahead.type === Token.Keyword && lookahead.value === keyword; |
| } |
| |
| // Return true if the next token is an assignment operator |
| |
| function matchAssign() { |
| var op; |
| |
| if (lookahead.type !== Token.Punctuator) { |
| return false; |
| } |
| op = lookahead.value; |
| return op === '=' || |
| op === '*=' || |
| op === '/=' || |
| op === '%=' || |
| op === '+=' || |
| op === '-=' || |
| op === '<<=' || |
| op === '>>=' || |
| op === '>>>=' || |
| op === '&=' || |
| op === '^=' || |
| op === '|='; |
| } |
| |
| function consumeSemicolon() { |
| var line; |
| |
| // Catch the very common case first: immediately a semicolon (U+003B). |
| if (source.charCodeAt(index) === 0x3B || match(';')) { |
| lex(); |
| return; |
| } |
| |
| line = lineNumber; |
| skipComment(); |
| if (lineNumber !== line) { |
| return; |
| } |
| |
| if (lookahead.type !== Token.EOF && !match('}')) { |
| throwUnexpected(lookahead); |
| } |
| } |
| |
| // Return true if provided expression is LeftHandSideExpression |
| |
| function isLeftHandSide(expr) { |
| return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression; |
| } |
| |
| // 11.1.4 Array Initialiser |
| |
| function parseArrayInitialiser() { |
| var elements = [], startToken; |
| |
| startToken = lookahead; |
| expect('['); |
| |
| while (!match(']')) { |
| if (match(',')) { |
| lex(); |
| elements.push(null); |
| } else { |
| elements.push(parseAssignmentExpression()); |
| |
| if (!match(']')) { |
| expect(','); |
| } |
| } |
| } |
| |
| lex(); |
| |
| return delegate.markEnd(delegate.createArrayExpression(elements), startToken); |
| } |
| |
| // 11.1.5 Object Initialiser |
| |
| function parsePropertyFunction(param, first) { |
| var previousStrict, body, startToken; |
| |
| previousStrict = strict; |
| startToken = lookahead; |
| body = parseFunctionSourceElements(); |
| if (first && strict && isRestrictedWord(param[0].name)) { |
| throwErrorTolerant(first, Messages.StrictParamName); |
| } |
| strict = previousStrict; |
| return delegate.markEnd(delegate.createFunctionExpression(null, param, [], body), startToken); |
| } |
| |
| function parseObjectPropertyKey() { |
| var token, startToken; |
| |
| startToken = lookahead; |
| token = lex(); |
| |
| // Note: This function is called only from parseObjectProperty(), where |
| // EOF and Punctuator tokens are already filtered out. |
| |
| if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) { |
| if (strict && token.octal) { |
| throwErrorTolerant(token, Messages.StrictOctalLiteral); |
| } |
| return delegate.markEnd(delegate.createLiteral(token), startToken); |
| } |
| |
| return delegate.markEnd(delegate.createIdentifier(token.value), startToken); |
| } |
| |
| function parseObjectProperty() { |
| var token, key, id, value, param, startToken; |
| |
| token = lookahead; |
| startToken = lookahead; |
| |
| if (token.type === Token.Identifier) { |
| |
| id = parseObjectPropertyKey(); |
| |
| // Property Assignment: Getter and Setter. |
| |
| if (token.value === 'get' && !match(':')) { |
| key = parseObjectPropertyKey(); |
| expect('('); |
| expect(')'); |
| value = parsePropertyFunction([]); |
| return delegate.markEnd(delegate.createProperty('get', key, value), startToken); |
| } |
| if (token.value === 'set' && !match(':')) { |
| key = parseObjectPropertyKey(); |
| expect('('); |
| token = lookahead; |
| if (token.type !== Token.Identifier) { |
| expect(')'); |
| throwErrorTolerant(token, Messages.UnexpectedToken, token.value); |
| value = parsePropertyFunction([]); |
| } else { |
| param = [ parseVariableIdentifier() ]; |
| expect(')'); |
| value = parsePropertyFunction(param, token); |
| } |
| return delegate.markEnd(delegate.createProperty('set', key, value), startToken); |
| } |
| expect(':'); |
| value = parseAssignmentExpression(); |
| return delegate.markEnd(delegate.createProperty('init', id, value), startToken); |
| } |
| if (token.type === Token.EOF || token.type === Token.Punctuator) { |
| throwUnexpected(token); |
| } else { |
| key = parseObjectPropertyKey(); |
| expect(':'); |
| value = parseAssignmentExpression(); |
| return delegate.markEnd(delegate.createProperty('init', key, value), startToken); |
| } |
| } |
| |
| function parseObjectInitialiser() { |
| var properties = [], property, name, key, kind, map = {}, toString = String, startToken; |
| |
| startToken = lookahead; |
| |
| expect('{'); |
| |
| while (!match('}')) { |
| property = parseObjectProperty(); |
| |
| if (property.key.type === Syntax.Identifier) { |
| name = property.key.name; |
| } else { |
| name = toString(property.key.value); |
| } |
| kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; |
| |
| key = '$' + name; |
| if (Object.prototype.hasOwnProperty.call(map, key)) { |
| if (map[key] === PropertyKind.Data) { |
| if (strict && kind === PropertyKind.Data) { |
| throwErrorTolerant({}, Messages.StrictDuplicateProperty); |
| } else if (kind !== PropertyKind.Data) { |
| throwErrorTolerant({}, Messages.AccessorDataProperty); |
| } |
| } else { |
| if (kind === PropertyKind.Data) { |
| throwErrorTolerant({}, Messages.AccessorDataProperty); |
| } else if (map[key] & kind) { |
| throwErrorTolerant({}, Messages.AccessorGetSet); |
| } |
| } |
| map[key] |= kind; |
| } else { |
| map[key] = kind; |
| } |
| |
| properties.push(property); |
| |
| if (!match('}')) { |
| expect(','); |
| } |
| } |
| |
| expect('}'); |
| |
| return delegate.markEnd(delegate.createObjectExpression(properties), startToken); |
| } |
| |
| // 11.1.6 The Grouping Operator |
| |
| function parseGroupExpression() { |
| var expr; |
| |
| expect('('); |
| |
| expr = parseExpression(); |
| |
| expect(')'); |
| |
| return expr; |
| } |
| |
| |
| // 11.1 Primary Expressions |
| |
| function parsePrimaryExpression() { |
| var type, token, expr, startToken; |
| |
| if (match('(')) { |
| return parseGroupExpression(); |
| } |
| |
| if (match('[')) { |
| return parseArrayInitialiser(); |
| } |
| |
| if (match('{')) { |
| return parseObjectInitialiser(); |
| } |
| |
| type = lookahead.type; |
| startToken = lookahead; |
| |
| if (type === Token.Identifier) { |
| expr = delegate.createIdentifier(lex().value); |
| } else if (type === Token.StringLiteral || type === Token.NumericLiteral) { |
| if (strict && lookahead.octal) { |
| throwErrorTolerant(lookahead, Messages.StrictOctalLiteral); |
| } |
| expr = delegate.createLiteral(lex()); |
| } else if (type === Token.Keyword) { |
| if (matchKeyword('function')) { |
| return parseFunctionExpression(); |
| } |
| if (matchKeyword('this')) { |
| lex(); |
| expr = delegate.createThisExpression(); |
| } else { |
| throwUnexpected(lex()); |
| } |
| } else if (type === Token.BooleanLiteral) { |
| token = lex(); |
| token.value = (token.value === 'true'); |
| expr = delegate.createLiteral(token); |
| } else if (type === Token.NullLiteral) { |
| token = lex(); |
| token.value = null; |
| expr = delegate.createLiteral(token); |
| } else if (match('/') || match('/=')) { |
| if (typeof extra.tokens !== 'undefined') { |
| expr = delegate.createLiteral(collectRegex()); |
| } else { |
| expr = delegate.createLiteral(scanRegExp()); |
| } |
| peek(); |
| } else { |
| throwUnexpected(lex()); |
| } |
| |
| return delegate.markEnd(expr, startToken); |
| } |
| |
| // 11.2 Left-Hand-Side Expressions |
| |
| function parseArguments() { |
| var args = []; |
| |
| expect('('); |
| |
| if (!match(')')) { |
| while (index < length) { |
| args.push(parseAssignmentExpression()); |
| if (match(')')) { |
| break; |
| } |
| expect(','); |
| } |
| } |
| |
| expect(')'); |
| |
| return args; |
| } |
| |
| function parseNonComputedProperty() { |
| var token, startToken; |
| |
| startToken = lookahead; |
| token = lex(); |
| |
| if (!isIdentifierName(token)) { |
| throwUnexpected(token); |
| } |
| |
| return delegate.markEnd(delegate.createIdentifier(token.value), startToken); |
| } |
| |
| function parseNonComputedMember() { |
| expect('.'); |
| |
| return parseNonComputedProperty(); |
| } |
| |
| function parseComputedMember() { |
| var expr; |
| |
| expect('['); |
| |
| expr = parseExpression(); |
| |
| expect(']'); |
| |
| return expr; |
| } |
| |
| function parseNewExpression() { |
| var callee, args, startToken; |
| |
| startToken = lookahead; |
| expectKeyword('new'); |
| callee = parseLeftHandSideExpression(); |
| args = match('(') ? parseArguments() : []; |
| |
| return delegate.markEnd(delegate.createNewExpression(callee, args), startToken); |
| } |
| |
| function parseLeftHandSideExpressionAllowCall() { |
| var previousAllowIn, expr, args, property, startToken; |
| |
| startToken = lookahead; |
| |
| previousAllowIn = state.allowIn; |
| state.allowIn = true; |
| expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); |
| state.allowIn = previousAllowIn; |
| |
| for (;;) { |
| if (match('.')) { |
| property = parseNonComputedMember(); |
| expr = delegate.createMemberExpression('.', expr, property); |
| } else if (match('(')) { |
| args = parseArguments(); |
| expr = delegate.createCallExpression(expr, args); |
| } else if (match('[')) { |
| property = parseComputedMember(); |
| expr = delegate.createMemberExpression('[', expr, property); |
| } else { |
| break; |
| } |
| delegate.markEnd(expr, startToken); |
| } |
| |
| return expr; |
| } |
| |
| function parseLeftHandSideExpression() { |
| var previousAllowIn, expr, property, startToken; |
| |
| startToken = lookahead; |
| |
| previousAllowIn = state.allowIn; |
| expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); |
| state.allowIn = previousAllowIn; |
| |
| while (match('.') || match('[')) { |
| if (match('[')) { |
| property = parseComputedMember(); |
| expr = delegate.createMemberExpression('[', expr, property); |
| } else { |
| property = parseNonComputedMember(); |
| expr = delegate.createMemberExpression('.', expr, property); |
| } |
| delegate.markEnd(expr, startToken); |
| } |
| |
| return expr; |
| } |
| |
| // 11.3 Postfix Expressions |
| |
| function parsePostfixExpression() { |
| var expr, token, startToken = lookahead; |
| |
| expr = parseLeftHandSideExpressionAllowCall(); |
| |
| if (lookahead.type === Token.Punctuator) { |
| if ((match('++') || match('--')) && !peekLineTerminator()) { |
| // 11.3.1, 11.3.2 |
| if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { |
| throwErrorTolerant({}, Messages.StrictLHSPostfix); |
| } |
| |
| if (!isLeftHandSide(expr)) { |
| throwErrorTolerant({}, Messages.InvalidLHSInAssignment); |
| } |
| |
| token = lex(); |
| expr = delegate.markEnd(delegate.createPostfixExpression(token.value, expr), startToken); |
| } |
| } |
| |
| return expr; |
| } |
| |
| // 11.4 Unary Operators |
| |
| function parseUnaryExpression() { |
| var token, expr, startToken; |
| |
| if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { |
| expr = parsePostfixExpression(); |
| } else if (match('++') || match('--')) { |
| startToken = lookahead; |
| token = lex(); |
| expr = parseUnaryExpression(); |
| // 11.4.4, 11.4.5 |
| if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { |
| throwErrorTolerant({}, Messages.StrictLHSPrefix); |
| } |
| |
| if (!isLeftHandSide(expr)) { |
| throwErrorTolerant({}, Messages.InvalidLHSInAssignment); |
| } |
| |
| expr = delegate.createUnaryExpression(token.value, expr); |
| expr = delegate.markEnd(expr, startToken); |
| } else if (match('+') || match('-') || match('~') || match('!')) { |
| startToken = lookahead; |
| token = lex(); |
| expr = parseUnaryExpression(); |
| expr = delegate.createUnaryExpression(token.value, expr); |
| expr = delegate.markEnd(expr, startToken); |
| } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { |
| startToken = lookahead; |
| token = lex(); |
| expr = parseUnaryExpression(); |
| expr = delegate.createUnaryExpression(token.value, expr); |
| expr = delegate.markEnd(expr, startToken); |
| if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { |
| throwErrorTolerant({}, Messages.StrictDelete); |
| } |
| } else { |
| expr = parsePostfixExpression(); |
| } |
| |
| return expr; |
| } |
| |
| function binaryPrecedence(token, allowIn) { |
| var prec = 0; |
| |
| if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { |
| return 0; |
| } |
| |
| switch (token.value) { |
| case '||': |
| prec = 1; |
| break; |
| |
| case '&&': |
| prec = 2; |
| break; |
| |
| case '|': |
| prec = 3; |
| break; |
| |
| case '^': |
| prec = 4; |
| break; |
| |
| case '&': |
| prec = 5; |
| break; |
| |
| case '==': |
| case '!=': |
| case '===': |
| case '!==': |
| prec = 6; |
| break; |
| |
| case '<': |
| case '>': |
| case '<=': |
| case '>=': |
| case 'instanceof': |
| prec = 7; |
| break; |
| |
| case 'in': |
| prec = allowIn ? 7 : 0; |
| break; |
| |
| case '<<': |
| case '>>': |
| case '>>>': |
| prec = 8; |
| break; |
| |
| case '+': |
| case '-': |
| prec = 9; |
| break; |
| |
| case '*': |
| case '/': |
| case '%': |
| prec = 11; |
| break; |
| |
| default: |
| break; |
| } |
| |
| return prec; |
| } |
| |
| // 11.5 Multiplicative Operators |
| // 11.6 Additive Operators |
| // 11.7 Bitwise Shift Operators |
| // 11.8 Relational Operators |
| // 11.9 Equality Operators |
| // 11.10 Binary Bitwise Operators |
| // 11.11 Binary Logical Operators |
| |
| function parseBinaryExpression() { |
| var marker, markers, expr, token, prec, stack, right, operator, left, i; |
| |
| marker = lookahead; |
| left = parseUnaryExpression(); |
| |
| token = lookahead; |
| prec = binaryPrecedence(token, state.allowIn); |
| if (prec === 0) { |
| return left; |
| } |
| token.prec = prec; |
| lex(); |
| |
| markers = [marker, lookahead]; |
| right = parseUnaryExpression(); |
| |
| stack = [left, token, right]; |
| |
| while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) { |
| |
| // Reduce: make a binary expression from the three topmost entries. |
| while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { |
| right = stack.pop(); |
| operator = stack.pop().value; |
| left = stack.pop(); |
| expr = delegate.createBinaryExpression(operator, left, right); |
| markers.pop(); |
| marker = markers[markers.length - 1]; |
| delegate.markEnd(expr, marker); |
| stack.push(expr); |
| } |
| |
| // Shift. |
| token = lex(); |
| token.prec = prec; |
| stack.push(token); |
| markers.push(lookahead); |
| expr = parseUnaryExpression(); |
| stack.push(expr); |
| } |
| |
| // Final reduce to clean-up the stack. |
| i = stack.length - 1; |
| expr = stack[i]; |
| markers.pop(); |
| while (i > 1) { |
| expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr); |
| i -= 2; |
| marker = markers.pop(); |
| delegate.markEnd(expr, marker); |
| } |
| |
| return expr; |
| } |
| |
| |
| // 11.12 Conditional Operator |
| |
| function parseConditionalExpression() { |
| var expr, previousAllowIn, consequent, alternate, startToken; |
| |
| startToken = lookahead; |
| |
| expr = parseBinaryExpression(); |
| |
| if (match('?')) { |
| lex(); |
| previousAllowIn = state.allowIn; |
| state.allowIn = true; |
| consequent = parseAssignmentExpression(); |
| state.allowIn = previousAllowIn; |
| expect(':'); |
| alternate = parseAssignmentExpression(); |
| |
| expr = delegate.createConditionalExpression(expr, consequent, alternate); |
| delegate.markEnd(expr, startToken); |
| } |
| |
| return expr; |
| } |
| |
| // 11.13 Assignment Operators |
| |
| function parseAssignmentExpression() { |
| var token, left, right, node, startToken; |
| |
| token = lookahead; |
| startToken = lookahead; |
| |
| node = left = parseConditionalExpression(); |
| |
| if (matchAssign()) { |
| // LeftHandSideExpression |
| if (!isLeftHandSide(left)) { |
| throwErrorTolerant({}, Messages.InvalidLHSInAssignment); |
| } |
| |
| // 11.13.1 |
| if (strict && left.type === Syntax.Identifier && isRestrictedWord(left.name)) { |
| throwErrorTolerant(token, Messages.StrictLHSAssignment); |
| } |
| |
| token = lex(); |
| right = parseAssignmentExpression(); |
| node = delegate.markEnd(delegate.createAssignmentExpression(token.value, left, right), startToken); |
| } |
| |
| return node; |
| } |
| |
| // 11.14 Comma Operator |
| |
| function parseExpression() { |
| var expr, startToken = lookahead; |
| |
| expr = parseAssignmentExpression(); |
| |
| if (match(',')) { |
| expr = delegate.createSequenceExpression([ expr ]); |
| |
| while (index < length) { |
| if (!match(',')) { |
| break; |
| } |
| lex(); |
| expr.expressions.push(parseAssignmentExpression()); |
| } |
| |
| delegate.markEnd(expr, startToken); |
| } |
| |
| return expr; |
| } |
| |
| // 12.1 Block |
| |
| function parseStatementList() { |
| var list = [], |
| statement; |
| |
| while (index < length) { |
| if (match('}')) { |
| break; |
| } |
| statement = parseSourceElement(); |
| if (typeof statement === 'undefined') { |
| break; |
| } |
| list.push(statement); |
| } |
| |
| return list; |
| } |
| |
| function parseBlock() { |
| var block, startToken; |
| |
| startToken = lookahead; |
| expect('{'); |
| |
| block = parseStatementList(); |
| |
| expect('}'); |
| |
| return delegate.markEnd(delegate.createBlockStatement(block), startToken); |
| } |
| |
| // 12.2 Variable Statement |
| |
| function parseVariableIdentifier() { |
| var token, startToken; |
| |
| startToken = lookahead; |
| token = lex(); |
| |
| if (token.type !== Token.Identifier) { |
| throwUnexpected(token); |
| } |
| |
| return delegate.markEnd(delegate.createIdentifier(token.value), startToken); |
| } |
| |
| function parseVariableDeclaration(kind) { |
| var init = null, id, startToken; |
| |
| startToken = lookahead; |
| id = parseVariableIdentifier(); |
| |
| // 12.2.1 |
| if (strict && isRestrictedWord(id.name)) { |
| throwErrorTolerant({}, Messages.StrictVarName); |
| } |
| |
| if (kind === 'const') { |
| expect('='); |
| init = parseAssignmentExpression(); |
| } else if (match('=')) { |
| lex(); |
| init = parseAssignmentExpression(); |
| } |
| |
| return delegate.markEnd(delegate.createVariableDeclarator(id, init), startToken); |
| } |
| |
| function parseVariableDeclarationList(kind) { |
| var list = []; |
| |
| do { |
| list.push(parseVariableDeclaration(kind)); |
| if (!match(',')) { |
| break; |
| } |
| lex(); |
| } while (index < length); |
| |
| return list; |
| } |
| |
| function parseVariableStatement() { |
| var declarations; |
| |
| expectKeyword('var'); |
| |
| declarations = parseVariableDeclarationList(); |
| |
| consumeSemicolon(); |
| |
| return delegate.createVariableDeclaration(declarations, 'var'); |
| } |
| |
| // kind may be `const` or `let` |
| // Both are experimental and not in the specification yet. |
| // see http://wiki.ecmascript.org/doku.php?id=harmony:const |
| // and http://wiki.ecmascript.org/doku.php?id=harmony:let |
| function parseConstLetDeclaration(kind) { |
| var declarations, startToken; |
| |
| startToken = lookahead; |
| |
| expectKeyword(kind); |
| |
| declarations = parseVariableDeclarationList(kind); |
| |
| consumeSemicolon(); |
| |
| return delegate.markEnd(delegate.createVariableDeclaration(declarations, kind), startToken); |
| } |
| |
| // 12.3 Empty Statement |
| |
| function parseEmptyStatement() { |
| expect(';'); |
| return delegate.createEmptyStatement(); |
| } |
| |
| // 12.4 Expression Statement |
| |
| function parseExpressionStatement() { |
| var expr = parseExpression(); |
| consumeSemicolon(); |
| return delegate.createExpressionStatement(expr); |
| } |
| |
| // 12.5 If statement |
| |
| function parseIfStatement() { |
| var test, consequent, alternate; |
| |
| expectKeyword('if'); |
| |
| expect('('); |
| |
| test = parseExpression(); |
| |
| expect(')'); |
| |
| consequent = parseStatement(); |
| |
| if (matchKeyword('else')) { |
| lex(); |
| alternate = parseStatement(); |
| } else { |
| alternate = null; |
| } |
| |
| return delegate.createIfStatement(test, consequent, alternate); |
| } |
| |
| // 12.6 Iteration Statements |
| |
| function parseDoWhileStatement() { |
| var body, test, oldInIteration; |
| |
| expectKeyword('do'); |
| |
| oldInIteration = state.inIteration; |
| state.inIteration = true; |
| |
| body = parseStatement(); |
| |
| state.inIteration = oldInIteration; |
| |
| expectKeyword('while'); |
| |
| expect('('); |
| |
| test = parseExpression(); |
| |
| expect(')'); |
| |
| if (match(';')) { |
| lex(); |
| } |
| |
| return delegate.createDoWhileStatement(body, test); |
| } |
| |
| function parseWhileStatement() { |
| var test, body, oldInIteration; |
| |
| expectKeyword('while'); |
| |
| expect('('); |
| |
| test = parseExpression(); |
| |
| expect(')'); |
| |
| oldInIteration = state.inIteration; |
| state.inIteration = true; |
| |
| body = parseStatement(); |
| |
| state.inIteration = oldInIteration; |
| |
| return delegate.createWhileStatement(test, body); |
| } |
| |
| function parseForVariableDeclaration() { |
| var token, declarations, startToken; |
| |
| startToken = lookahead; |
| token = lex(); |
| declarations = parseVariableDeclarationList(); |
| |
| return delegate.markEnd(delegate.createVariableDeclaration(declarations, token.value), startToken); |
| } |
| |
| function parseForStatement() { |
| var init, test, update, left, right, body, oldInIteration; |
| |
| init = test = update = null; |
| |
| expectKeyword('for'); |
| |
| expect('('); |
| |
| if (match(';')) { |
| lex(); |
| } else { |
| if (matchKeyword('var') || matchKeyword('let')) { |
| state.allowIn = false; |
| init = parseForVariableDeclaration(); |
| state.allowIn = true; |
| |
| if (init.declarations.length === 1 && matchKeyword('in')) { |
| lex(); |
| left = init; |
| right = parseExpression(); |
| init = null; |
| } |
| } else { |
| state.allowIn = false; |
| init = parseExpression(); |
| state.allowIn = true; |
| |
| if (matchKeyword('in')) { |
| // LeftHandSideExpression |
| if (!isLeftHandSide(init)) { |
| throwErrorTolerant({}, Messages.InvalidLHSInForIn); |
| } |
| |
| lex(); |
| left = init; |
| right = parseExpression(); |
| init = null; |
| } |
| } |
| |
| if (typeof left === 'undefined') { |
| expect(';'); |
| } |
| } |
| |
| if (typeof left === 'undefined') { |
| |
| if (!match(';')) { |
| test = parseExpression(); |
| } |
| expect(';'); |
| |
| if (!match(')')) { |
| update = parseExpression(); |
| } |
| } |
| |
| expect(')'); |
| |
| oldInIteration = state.inIteration; |
| state.inIteration = true; |
| |
| body = parseStatement(); |
| |
| state.inIteration = oldInIteration; |
| |
| return (typeof left === 'undefined') ? |
| delegate.createForStatement(init, test, update, body) : |
| delegate.createForInStatement(left, right, body); |
| } |
| |
| // 12.7 The continue statement |
| |
| function parseContinueStatement() { |
| var label = null, key; |
| |
| expectKeyword('continue'); |
| |
| // Optimize the most common form: 'continue;'. |
| if (source.charCodeAt(index) === 0x3B) { |
| lex(); |
| |
| if (!state.inIteration) { |
| throwError({}, Messages.IllegalContinue); |
| } |
| |
| return delegate.createContinueStatement(null); |
| } |
| |
| if (peekLineTerminator()) { |
| if (!state.inIteration) { |
| throwError({}, Messages.IllegalContinue); |
| } |
| |
| return delegate.createContinueStatement(null); |
| } |
| |
| if (lookahead.type === Token.Identifier) { |
| label = parseVariableIdentifier(); |
| |
| key = '$' + label.name; |
| if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { |
| throwError({}, Messages.UnknownLabel, label.name); |
| } |
| } |
| |
| consumeSemicolon(); |
| |
| if (label === null && !state.inIteration) { |
| throwError({}, Messages.IllegalContinue); |
| } |
| |
| return delegate.createContinueStatement(label); |
| } |
| |
| // 12.8 The break statement |
| |
| function parseBreakStatement() { |
| var label = null, key; |
| |
| expectKeyword('break'); |
| |
| // Catch the very common case first: immediately a semicolon (U+003B). |
| if (source.charCodeAt(index) === 0x3B) { |
| lex(); |
| |
| if (!(state.inIteration || state.inSwitch)) { |
| throwError({}, Messages.IllegalBreak); |
| } |
| |
| return delegate.createBreakStatement(null); |
| } |
| |
| if (peekLineTerminator()) { |
| if (!(state.inIteration || state.inSwitch)) { |
| throwError({}, Messages.IllegalBreak); |
| } |
| |
| return delegate.createBreakStatement(null); |
| } |
| |
| if (lookahead.type === Token.Identifier) { |
| label = parseVariableIdentifier(); |
| |
| key = '$' + label.name; |
| if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { |
| throwError({}, Messages.UnknownLabel, label.name); |
| } |
| } |
| |
| consumeSemicolon(); |
| |
| if (label === null && !(state.inIteration || state.inSwitch)) { |
| throwError({}, Messages.IllegalBreak); |
| } |
| |
| return delegate.createBreakStatement(label); |
| } |
| |
| // 12.9 The return statement |
| |
| function parseReturnStatement() { |
| var argument = null; |
| |
| expectKeyword('return'); |
| |
| if (!state.inFunctionBody) { |
| throwErrorTolerant({}, Messages.IllegalReturn); |
| } |
| |
| // 'return' followed by a space and an identifier is very common. |
| if (source.charCodeAt(index) === 0x20) { |
| if (isIdentifierStart(source.charCodeAt(index + 1))) { |
| argument = parseExpression(); |
| consumeSemicolon(); |
| return delegate.createReturnStatement(argument); |
| } |
| } |
| |
| if (peekLineTerminator()) { |
| return delegate.createReturnStatement(null); |
| } |
| |
| if (!match(';')) { |
| if (!match('}') && lookahead.type !== Token.EOF) { |
| argument = parseExpression(); |
| } |
| } |
| |
| consumeSemicolon(); |
| |
| return delegate.createReturnStatement(argument); |
| } |
| |
| // 12.10 The with statement |
| |
| function parseWithStatement() { |
| var object, body; |
| |
| if (strict) { |
| // TODO(ikarienator): Should we update the test cases instead? |
| skipComment(); |
| throwErrorTolerant({}, Messages.StrictModeWith); |
| } |
| |
| expectKeyword('with'); |
| |
| expect('('); |
| |
| object = parseExpression(); |
| |
| expect(')'); |
| |
| body = parseStatement(); |
| |
| return delegate.createWithStatement(object, body); |
| } |
| |
| // 12.10 The swith statement |
| |
| function parseSwitchCase() { |
| var test, consequent = [], statement, startToken; |
| |
| startToken = lookahead; |
| if (matchKeyword('default')) { |
| lex(); |
| test = null; |
| } else { |
| expectKeyword('case'); |
| test = parseExpression(); |
| } |
| expect(':'); |
| |
| while (index < length) { |
| if (match('}') || matchKeyword('default') || matchKeyword('case')) { |
| break; |
| } |
| statement = parseStatement(); |
| consequent.push(statement); |
| } |
| |
| return delegate.markEnd(delegate.createSwitchCase(test, consequent), startToken); |
| } |
| |
| function parseSwitchStatement() { |
| var discriminant, cases, clause, oldInSwitch, defaultFound; |
| |
| expectKeyword('switch'); |
| |
| expect('('); |
| |
| discriminant = parseExpression(); |
| |
| expect(')'); |
| |
| expect('{'); |
| |
| cases = []; |
| |
| if (match('}')) { |
| lex(); |
| return delegate.createSwitchStatement(discriminant, cases); |
| } |
| |
| oldInSwitch = state.inSwitch; |
| state.inSwitch = true; |
| defaultFound = false; |
| |
| while (index < length) { |
| if (match('}')) { |
| break; |
| } |
| clause = parseSwitchCase(); |
| if (clause.test === null) { |
| if (defaultFound) { |
| throwError({}, Messages.MultipleDefaultsInSwitch); |
| } |
| defaultFound = true; |
| } |
| cases.push(clause); |
| } |
| |
| state.inSwitch = oldInSwitch; |
| |
| expect('}'); |
| |
| return delegate.createSwitchStatement(discriminant, cases); |
| } |
| |
| // 12.13 The throw statement |
| |
| function parseThrowStatement() { |
| var argument; |
| |
| expectKeyword('throw'); |
| |
| if (peekLineTerminator()) { |
| throwError({}, Messages.NewlineAfterThrow); |
| } |
| |
| argument = parseExpression(); |
| |
| consumeSemicolon(); |
| |
| return delegate.createThrowStatement(argument); |
| } |
| |
| // 12.14 The try statement |
| |
| function parseCatchClause() { |
| var param, body, startToken; |
| |
| startToken = lookahead; |
| expectKeyword('catch'); |
| |
| expect('('); |
| if (match(')')) { |
| throwUnexpected(lookahead); |
| } |
| |
| param = parseVariableIdentifier(); |
| // 12.14.1 |
| if (strict && isRestrictedWord(param.name)) { |
| throwErrorTolerant({}, Messages.StrictCatchVariable); |
| } |
| |
| expect(')'); |
| body = parseBlock(); |
| return delegate.markEnd(delegate.createCatchClause(param, body), startToken); |
| } |
| |
| function parseTryStatement() { |
| var block, handlers = [], finalizer = null; |
| |
| expectKeyword('try'); |
| |
| block = parseBlock(); |
| |
| if (matchKeyword('catch')) { |
| handlers.push(parseCatchClause()); |
| } |
| |
| if (matchKeyword('finally')) { |
| lex(); |
| finalizer = parseBlock(); |
| } |
| |
| if (handlers.length === 0 && !finalizer) { |
| throwError({}, Messages.NoCatchOrFinally); |
| } |
| |
| return delegate.createTryStatement(block, [], handlers, finalizer); |
| } |
| |
| // 12.15 The debugger statement |
| |
| function parseDebuggerStatement() { |
| expectKeyword('debugger'); |
| |
| consumeSemicolon(); |
| |
| return delegate.createDebuggerStatement(); |
| } |
| |
| // 12 Statements |
| |
| function parseStatement() { |
| var type = lookahead.type, |
| expr, |
| labeledBody, |
| key, |
| startToken; |
| |
| if (type === Token.EOF) { |
| throwUnexpected(lookahead); |
| } |
| |
| if (type === Token.Punctuator && lookahead.value === '{') { |
| return parseBlock(); |
| } |
| |
| startToken = lookahead; |
| |
| if (type === Token.Punctuator) { |
| switch (lookahead.value) { |
| case ';': |
| return delegate.markEnd(parseEmptyStatement(), startToken); |
| case '(': |
| return delegate.markEnd(parseExpressionStatement(), startToken); |
| default: |
| break; |
| } |
| } |
| |
| if (type === Token.Keyword) { |
| switch (lookahead.value) { |
| case 'break': |
| return delegate.markEnd(parseBreakStatement(), startToken); |
| case 'continue': |
| return delegate.markEnd(parseContinueStatement(), startToken); |
| case 'debugger': |
| return delegate.markEnd(parseDebuggerStatement(), startToken); |
| case 'do': |
| return delegate.markEnd(parseDoWhileStatement(), startToken); |
| case 'for': |
| return delegate.markEnd(parseForStatement(), startToken); |
| case 'function': |
| return delegate.markEnd(parseFunctionDeclaration(), startToken); |
| case 'if': |
| return delegate.markEnd(parseIfStatement(), startToken); |
| case 'return': |
| return delegate.markEnd(parseReturnStatement(), startToken); |
| case 'switch': |
| return delegate.markEnd(parseSwitchStatement(), startToken); |
| case 'throw': |
| return delegate.markEnd(parseThrowStatement(), startToken); |
| case 'try': |
| return delegate.markEnd(parseTryStatement(), startToken); |
| case 'var': |
| return delegate.markEnd(parseVariableStatement(), startToken); |
| case 'while': |
| return delegate.markEnd(parseWhileStatement(), startToken); |
| case 'with': |
| return delegate.markEnd(parseWithStatement(), startToken); |
| default: |
| break; |
| } |
| } |
| |
| expr = parseExpression(); |
| |
| // 12.12 Labelled Statements |
| if ((expr.type === Syntax.Identifier) && match(':')) { |
| lex(); |
| |
| key = '$' + expr.name; |
| if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) { |
| throwError({}, Messages.Redeclaration, 'Label', expr.name); |
| } |
| |
| state.labelSet[key] = true; |
| labeledBody = parseStatement(); |
| delete state.labelSet[key]; |
| return delegate.markEnd(delegate.createLabeledStatement(expr, labeledBody), startToken); |
| } |
| |
| consumeSemicolon(); |
| |
| return delegate.markEnd(delegate.createExpressionStatement(expr), startToken); |
| } |
| |
| // 13 Function Definition |
| |
| function parseFunctionSourceElements() { |
| var sourceElement, sourceElements = [], token, directive, firstRestricted, |
| oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, startToken; |
| |
| startToken = lookahead; |
| expect('{'); |
| |
| while (index < length) { |
| if (lookahead.type !== Token.StringLiteral) { |
| break; |
| } |
| token = lookahead; |
| |
| sourceElement = parseSourceElement(); |
| sourceElements.push(sourceElement); |
| if (sourceElement.expression.type !== Syntax.Literal) { |
| // this is not directive |
| break; |
| } |
| directive = source.slice(token.start + 1, token.end - 1); |
| if (directive === 'use strict') { |
| strict = true; |
| if (firstRestricted) { |
| throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); |
| } |
| } else { |
| if (!firstRestricted && token.octal) { |
| firstRestricted = token; |
| } |
| } |
| } |
| |
| oldLabelSet = state.labelSet; |
| oldInIteration = state.inIteration; |
| oldInSwitch = state.inSwitch; |
| oldInFunctionBody = state.inFunctionBody; |
| |
| state.labelSet = {}; |
| state.inIteration = false; |
| state.inSwitch = false; |
| state.inFunctionBody = true; |
| |
| while (index < length) { |
| if (match('}')) { |
| break; |
| } |
| sourceElement = parseSourceElement(); |
| if (typeof sourceElement === 'undefined') { |
| break; |
| } |
| sourceElements.push(sourceElement); |
| } |
| |
| expect('}'); |
| |
| state.labelSet = oldLabelSet; |
| state.inIteration = oldInIteration; |
| state.inSwitch = oldInSwitch; |
| state.inFunctionBody = oldInFunctionBody; |
| |
| return delegate.markEnd(delegate.createBlockStatement(sourceElements), startToken); |
| } |
| |
| function parseParams(firstRestricted) { |
| var param, params = [], token, stricted, paramSet, key, message; |
| expect('('); |
| |
| if (!match(')')) { |
| paramSet = {}; |
| while (index < length) { |
| token = lookahead; |
| param = parseVariableIdentifier(); |
| key = '$' + token.value; |
| if (strict) { |
| if (isRestrictedWord(token.value)) { |
| stricted = token; |
| message = Messages.StrictParamName; |
| } |
| if (Object.prototype.hasOwnProperty.call(paramSet, key)) { |
| stricted = token; |
| message = Messages.StrictParamDupe; |
| } |
| } else if (!firstRestricted) { |
| if (isRestrictedWord(token.value)) { |
| firstRestricted = token; |
| message = Messages.StrictParamName; |
| } else if (isStrictModeReservedWord(token.value)) { |
| firstRestricted = token; |
| message = Messages.StrictReservedWord; |
| } else if (Object.prototype.hasOwnProperty.call(paramSet, key)) { |
| firstRestricted = token; |
| message = Messages.StrictParamDupe; |
| } |
| } |
| params.push(param); |
| paramSet[key] = true; |
| if (match(')')) { |
| break; |
| } |
| expect(','); |
| } |
| } |
| |
| expect(')'); |
| |
| return { |
| params: params, |
| stricted: stricted, |
| firstRestricted: firstRestricted, |
| message: message |
| }; |
| } |
| |
| function parseFunctionDeclaration() { |
| var id, params = [], body, token, stricted, tmp, firstRestricted, message, previousStrict, startToken; |
| |
| startToken = lookahead; |
| |
| expectKeyword('function'); |
| token = lookahead; |
| id = parseVariableIdentifier(); |
| if (strict) { |
| if (isRestrictedWord(token.value)) { |
| throwErrorTolerant(token, Messages.StrictFunctionName); |
| } |
| } else { |
| if (isRestrictedWord(token.value)) { |
| firstRestricted = token; |
| message = Messages.StrictFunctionName; |
| } else if (isStrictModeReservedWord(token.value)) { |
| firstRestricted = token; |
| message = Messages.StrictReservedWord; |
| } |
| } |
| |
| tmp = parseParams(firstRestricted); |
| params = tmp.params; |
| stricted = tmp.stricted; |
| firstRestricted = tmp.firstRestricted; |
| if (tmp.message) { |
| message = tmp.message; |
| } |
| |
| previousStrict = strict; |
| body = parseFunctionSourceElements(); |
| if (strict && firstRestricted) { |
| throwError(firstRestricted, message); |
| } |
| if (strict && stricted) { |
| throwErrorTolerant(stricted, message); |
| } |
| strict = previousStrict; |
| |
| return delegate.markEnd(delegate.createFunctionDeclaration(id, params, [], body), startToken); |
| } |
| |
| function parseFunctionExpression() { |
| var token, id = null, stricted, firstRestricted, message, tmp, params = [], body, previousStrict, startToken; |
| |
| startToken = lookahead; |
| expectKeyword('function'); |
| |
| if (!match('(')) { |
| token = lookahead; |
| id = parseVariableIdentifier(); |
| if (strict) { |
| if (isRestrictedWord(token.value)) { |
| throwErrorTolerant(token, Messages.StrictFunctionName); |
| } |
| } else { |
| if (isRestrictedWord(token.value)) { |
| firstRestricted = token; |
| message = Messages.StrictFunctionName; |
| } else if (isStrictModeReservedWord(token.value)) { |
| firstRestricted = token; |
| message = Messages.StrictReservedWord; |
| } |
| } |
| } |
| |
| tmp = parseParams(firstRestricted); |
| params = tmp.params; |
| stricted = tmp.stricted; |
| firstRestricted = tmp.firstRestricted; |
| if (tmp.message) { |
| message = tmp.message; |
| } |
| |
| previousStrict = strict; |
| body = parseFunctionSourceElements(); |
| if (strict && firstRestricted) { |
| throwError(firstRestricted, message); |
| } |
| if (strict && stricted) { |
| throwErrorTolerant(stricted, message); |
| } |
| strict = previousStrict; |
| |
| return delegate.markEnd(delegate.createFunctionExpression(id, params, [], body), startToken); |
| } |
| |
| // 14 Program |
| |
| function parseSourceElement() { |
| if (lookahead.type === Token.Keyword) { |
| switch (lookahead.value) { |
| case 'const': |
| case 'let': |
| return parseConstLetDeclaration(lookahead.value); |
| case 'function': |
| return parseFunctionDeclaration(); |
| default: |
| return parseStatement(); |
| } |
| } |
| |
| if (lookahead.type !== Token.EOF) { |
| return parseStatement(); |
| } |
| } |
| |
| function parseSourceElements() { |
| var sourceElement, sourceElements = [], token, directive, firstRestricted; |
| |
| while (index < length) { |
| token = lookahead; |
| if (token.type !== Token.StringLiteral) { |
| break; |
| } |
| |
| sourceElement = parseSourceElement(); |
| sourceElements.push(sourceElement); |
| if (sourceElement.expression.type !== Syntax.Literal) { |
| // this is not directive |
| break; |
| } |
| directive = source.slice(token.start + 1, token.end - 1); |
| if (directive === 'use strict') { |
| strict = true; |
| if (firstRestricted) { |
| throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); |
| } |
| } else { |
| if (!firstRestricted && token.octal) { |
| firstRestricted = token; |
| } |
| } |
| } |
| |
| while (index < length) { |
| sourceElement = parseSourceElement(); |
| /* istanbul ignore if */ |
| if (typeof sourceElement === 'undefined') { |
| break; |
| } |
| sourceElements.push(sourceElement); |
| } |
| return sourceElements; |
| } |
| |
| function parseProgram() { |
| var body, startToken; |
| |
| skipComment(); |
| peek(); |
| startToken = lookahead; |
| strict = false; |
| |
| body = parseSourceElements(); |
| return delegate.markEnd(delegate.createProgram(body), startToken); |
| } |
| |
| function filterTokenLocation() { |
| var i, entry, token, tokens = []; |
| |
| for (i = 0; i < extra.tokens.length; ++i) { |
| entry = extra.tokens[i]; |
| token = { |
| type: entry.type, |
| value: entry.value |
| }; |
| if (extra.range) { |
| token.range = entry.range; |
| } |
| if (extra.loc) { |
| token.loc = entry.loc; |
| } |
| tokens.push(token); |
| } |
| |
| extra.tokens = tokens; |
| } |
| |
| function tokenize(code, options) { |
| var toString, |
| token, |
| tokens; |
| |
| toString = String; |
| if (typeof code !== 'string' && !(code instanceof String)) { |
| code = toString(code); |
| } |
| |
| delegate = SyntaxTreeDelegate; |
| source = code; |
| index = 0; |
| lineNumber = (source.length > 0) ? 1 : 0; |
| lineStart = 0; |
| length = source.length; |
| lookahead = null; |
| state = { |
| allowIn: true, |
| labelSet: {}, |
| inFunctionBody: false, |
| inIteration: false, |
| inSwitch: false, |
| lastCommentStart: -1 |
| }; |
| |
| extra = {}; |
| |
| // Options matching. |
| options = options || {}; |
| |
| // Of course we collect tokens here. |
| options.tokens = true; |
| extra.tokens = []; |
| extra.tokenize = true; |
| // The following two fields are necessary to compute the Regex tokens. |
| extra.openParenToken = -1; |
| extra.openCurlyToken = -1; |
| |
| extra.range = (typeof options.range === 'boolean') && options.range; |
| extra.loc = (typeof options.loc === 'boolean') && options.loc; |
| |
| if (typeof options.comment === 'boolean' && options.comment) { |
| extra.comments = []; |
| } |
| if (typeof options.tolerant === 'boolean' && options.tolerant) { |
| extra.errors = []; |
| } |
| |
| try { |
| peek(); |
| if (lookahead.type === Token.EOF) { |
| return extra.tokens; |
| } |
| |
| token = lex(); |
| while (lookahead.type !== Token.EOF) { |
| try { |
| token = lex(); |
| } catch (lexError) { |
| token = lookahead; |
| if (extra.errors) { |
| extra.errors.push(lexError); |
| // We have to break on the first error |
| // to avoid infinite loops. |
| break; |
| } else { |
| throw lexError; |
| } |
| } |
| } |
| |
| filterTokenLocation(); |
| tokens = extra.tokens; |
| if (typeof extra.comments !== 'undefined') { |
| tokens.comments = extra.comments; |
| } |
| if (typeof extra.errors !== 'undefined') { |
| tokens.errors = extra.errors; |
| } |
| } catch (e) { |
| throw e; |
| } finally { |
| extra = {}; |
| } |
| return tokens; |
| } |
| |
| function parse(code, options) { |
| var program, toString; |
| |
| toString = String; |
| if (typeof code !== 'string' && !(code instanceof String)) { |
| code = toString(code); |
| } |
| |
| delegate = SyntaxTreeDelegate; |
| source = code; |
| index = 0; |
| lineNumber = (source.length > 0) ? 1 : 0; |
| lineStart = 0; |
| length = source.length; |
| lookahead = null; |
| state = { |
| allowIn: true, |
| labelSet: {}, |
| inFunctionBody: false, |
| inIteration: false, |
| inSwitch: false, |
| lastCommentStart: -1 |
| }; |
| |
| extra = {}; |
| if (typeof options !== 'undefined') { |
| extra.range = (typeof options.range === 'boolean') && options.range; |
| extra.loc = (typeof options.loc === 'boolean') && options.loc; |
| extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment; |
| |
| if (extra.loc && options.source !== null && options.source !== undefined) { |
| extra.source = toString(options.source); |
| } |
| |
| if (typeof options.tokens === 'boolean' && options.tokens) { |
| extra.tokens = []; |
| } |
| if (typeof options.comment === 'boolean' && options.comment) { |
| extra.comments = []; |
| } |
| if (typeof options.tolerant === 'boolean' && options.tolerant) { |
| extra.errors = []; |
| } |
| if (extra.attachComment) { |
| extra.range = true; |
| extra.comments = []; |
| extra.bottomRightStack = []; |
| extra.trailingComments = []; |
| extra.leadingComments = []; |
| } |
| } |
| |
| try { |
| program = parseProgram(); |
| if (typeof extra.comments !== 'undefined') { |
| program.comments = extra.comments; |
| } |
| if (typeof extra.tokens !== 'undefined') { |
| filterTokenLocation(); |
| program.tokens = extra.tokens; |
| } |
| if (typeof extra.errors !== 'undefined') { |
| program.errors = extra.errors; |
| } |
| } catch (e) { |
| throw e; |
| } finally { |
| extra = {}; |
| } |
| |
| return program; |
| } |
| |
| // Sync with *.json manifests. |
| exports.version = '1.2.2'; |
| |
| exports.tokenize = tokenize; |
| |
| exports.parse = parse; |
| |
| // Deep copy. |
| /* istanbul ignore next */ |
| exports.Syntax = (function () { |
| var name, types = {}; |
| |
| if (typeof Object.create === 'function') { |
| types = Object.create(null); |
| } |
| |
| for (name in Syntax) { |
| if (Syntax.hasOwnProperty(name)) { |
| types[name] = Syntax[name]; |
| } |
| } |
| |
| if (typeof Object.freeze === 'function') { |
| Object.freeze(types); |
| } |
| |
| return types; |
| }()); |
| |
| })); |
| /* vim: set sw=4 ts=4 et tw=80 : */ |
| |
| },{}],1:[function(require,module,exports){ |
| (function (process){ |
| /* parser generated by jison 0.4.13 */ |
| /* |
| Returns a Parser object of the following structure: |
| |
| Parser: { |
| yy: {} |
| } |
| |
| Parser.prototype: { |
| yy: {}, |
| trace: function(), |
| symbols_: {associative list: name ==> number}, |
| terminals_: {associative list: number ==> name}, |
| productions_: [...], |
| performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$), |
| table: [...], |
| defaultActions: {...}, |
| parseError: function(str, hash), |
| parse: function(input), |
| |
| lexer: { |
| EOF: 1, |
| parseError: function(str, hash), |
| setInput: function(input), |
| input: function(), |
| unput: function(str), |
| more: function(), |
| less: function(n), |
| pastInput: function(), |
| upcomingInput: function(), |
| showPosition: function(), |
| test_match: function(regex_match_array, rule_index), |
| next: function(), |
| lex: function(), |
| begin: function(condition), |
| popState: function(), |
| _currentRules: function(), |
| topState: function(), |
| pushState: function(condition), |
| |
| options: { |
| ranges: boolean (optional: true ==> token location info will include a .range[] member) |
| flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match) |
| backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code) |
| }, |
| |
| performAction: function(yy, yy_, $avoiding_name_collisions, YY_START), |
| rules: [...], |
| conditions: {associative list: name ==> set}, |
| } |
| } |
| |
| |
| token location info (@$, _$, etc.): { |
| first_line: n, |
| last_line: n, |
| first_column: n, |
| last_column: n, |
| range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based) |
| } |
| |
| |
| the parseError function receives a 'hash' object with these members for lexer and parser errors: { |
| text: (matched text) |
| token: (the produced terminal token, if any) |
| line: (yylineno) |
| } |
| while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: { |
| loc: (yylloc) |
| expected: (string describing the set of expected tokens) |
| recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error) |
| } |
| */ |
| var parser = (function(){ |
| var parser = {trace: function trace() { }, |
| yy: {}, |
| symbols_: {"error":2,"JSON_PATH":3,"DOLLAR":4,"PATH_COMPONENTS":5,"LEADING_CHILD_MEMBER_EXPRESSION":6,"PATH_COMPONENT":7,"MEMBER_COMPONENT":8,"SUBSCRIPT_COMPONENT":9,"CHILD_MEMBER_COMPONENT":10,"DESCENDANT_MEMBER_COMPONENT":11,"DOT":12,"MEMBER_EXPRESSION":13,"DOT_DOT":14,"STAR":15,"IDENTIFIER":16,"SCRIPT_EXPRESSION":17,"INTEGER":18,"END":19,"CHILD_SUBSCRIPT_COMPONENT":20,"DESCENDANT_SUBSCRIPT_COMPONENT":21,"[":22,"SUBSCRIPT":23,"]":24,"SUBSCRIPT_EXPRESSION":25,"SUBSCRIPT_EXPRESSION_LIST":26,"SUBSCRIPT_EXPRESSION_LISTABLE":27,",":28,"STRING_LITERAL":29,"ARRAY_SLICE":30,"FILTER_EXPRESSION":31,"QQ_STRING":32,"Q_STRING":33,"$accept":0,"$end":1}, |
| terminals_: {2:"error",4:"DOLLAR",12:"DOT",14:"DOT_DOT",15:"STAR",16:"IDENTIFIER",17:"SCRIPT_EXPRESSION",18:"INTEGER",19:"END",22:"[",24:"]",28:",",30:"ARRAY_SLICE",31:"FILTER_EXPRESSION",32:"QQ_STRING",33:"Q_STRING"}, |
| productions_: [0,[3,1],[3,2],[3,1],[3,2],[5,1],[5,2],[7,1],[7,1],[8,1],[8,1],[10,2],[6,1],[11,2],[13,1],[13,1],[13,1],[13,1],[13,1],[9,1],[9,1],[20,3],[21,4],[23,1],[23,1],[26,1],[26,3],[27,1],[27,1],[27,1],[25,1],[25,1],[25,1],[29,1],[29,1]], |
| performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */ |
| /**/) { |
| /* this == yyval */ |
| if (!yy.ast) { |
| yy.ast = _ast; |
| _ast.initialize(); |
| } |
| |
| var $0 = $$.length - 1; |
| switch (yystate) { |
| case 1:yy.ast.set({ expression: { type: "root", value: $$[$0] } }); yy.ast.unshift(); return yy.ast.yield() |
| break; |
| case 2:yy.ast.set({ expression: { type: "root", value: $$[$0-1] } }); yy.ast.unshift(); return yy.ast.yield() |
| break; |
| case 3:yy.ast.unshift(); return yy.ast.yield() |
| break; |
| case 4:yy.ast.set({ operation: "member", scope: "child", expression: { type: "identifier", value: $$[$0-1] }}); yy.ast.unshift(); return yy.ast.yield() |
| break; |
| case 5: |
| break; |
| case 6: |
| break; |
| case 7:yy.ast.set({ operation: "member" }); yy.ast.push() |
| break; |
| case 8:yy.ast.set({ operation: "subscript" }); yy.ast.push() |
| break; |
| case 9:yy.ast.set({ scope: "child" }) |
| break; |
| case 10:yy.ast.set({ scope: "descendant" }) |
| break; |
| case 11: |
| break; |
| case 12:yy.ast.set({ scope: "child", operation: "member" }) |
| break; |
| case 13: |
| break; |
| case 14:yy.ast.set({ expression: { type: "wildcard", value: $$[$0] } }) |
| break; |
| case 15:yy.ast.set({ expression: { type: "identifier", value: $$[$0] } }) |
| break; |
| case 16:yy.ast.set({ expression: { type: "script_expression", value: $$[$0] } }) |
| break; |
| case 17:yy.ast.set({ expression: { type: "numeric_literal", value: parseInt($$[$0]) } }) |
| break; |
| case 18: |
| break; |
| case 19:yy.ast.set({ scope: "child" }) |
| break; |
| case 20:yy.ast.set({ scope: "descendant" }) |
| break; |
| case 21: |
| break; |
| case 22: |
| break; |
| case 23: |
| break; |
| case 24:$$[$0].length > 1? yy.ast.set({ expression: { type: "union", value: $$[$0] } }) : this.$ = $$[$0] |
| break; |
| case 25:this.$ = [$$[$0]] |
| break; |
| case 26:this.$ = $$[$0-2].concat($$[$0]) |
| break; |
| case 27:this.$ = { expression: { type: "numeric_literal", value: parseInt($$[$0]) } }; yy.ast.set(this.$) |
| break; |
| case 28:this.$ = { expression: { type: "string_literal", value: $$[$0] } }; yy.ast.set(this.$) |
| break; |
| case 29:this.$ = { expression: { type: "slice", value: $$[$0] } }; yy.ast.set(this.$) |
| break; |
| case 30:this.$ = { expression: { type: "wildcard", value: $$[$0] } }; yy.ast.set(this.$) |
| break; |
| case 31:this.$ = { expression: { type: "script_expression", value: $$[$0] } }; yy.ast.set(this.$) |
| break; |
| case 32:this.$ = { expression: { type: "filter_expression", value: $$[$0] } }; yy.ast.set(this.$) |
| break; |
| case 33:this.$ = $$[$0] |
| break; |
| case 34:this.$ = $$[$0] |
| break; |
| } |
| }, |
| table: [{3:1,4:[1,2],6:3,13:4,15:[1,5],16:[1,6],17:[1,7],18:[1,8],19:[1,9]},{1:[3]},{1:[2,1],5:10,7:11,8:12,9:13,10:14,11:15,12:[1,18],14:[1,19],20:16,21:17,22:[1,20]},{1:[2,3],5:21,7:11,8:12,9:13,10:14,11:15,12:[1,18],14:[1,19],20:16,21:17,22:[1,20]},{1:[2,12],12:[2,12],14:[2,12],22:[2,12]},{1:[2,14],12:[2,14],14:[2,14],22:[2,14]},{1:[2,15],12:[2,15],14:[2,15],22:[2,15]},{1:[2,16],12:[2,16],14:[2,16],22:[2,16]},{1:[2,17],12:[2,17],14:[2,17],22:[2,17]},{1:[2,18],12:[2,18],14:[2,18],22:[2,18]},{1:[2,2],7:22,8:12,9:13,10:14,11:15,12:[1,18],14:[1,19],20:16,21:17,22:[1,20]},{1:[2,5],12:[2,5],14:[2,5],22:[2,5]},{1:[2,7],12:[2,7],14:[2,7],22:[2,7]},{1:[2,8],12:[2,8],14:[2,8],22:[2,8]},{1:[2,9],12:[2,9],14:[2,9],22:[2,9]},{1:[2,10],12:[2,10],14:[2,10],22:[2,10]},{1:[2,19],12:[2,19],14:[2,19],22:[2,19]},{1:[2,20],12:[2,20],14:[2,20],22:[2,20]},{13:23,15:[1,5],16:[1,6],17:[1,7],18:[1,8],19:[1,9]},{13:24,15:[1,5],16:[1,6],17:[1,7],18:[1,8],19:[1,9],22:[1,25]},{15:[1,29],17:[1,30],18:[1,33],23:26,25:27,26:28,27:32,29:34,30:[1,35],31:[1,31],32:[1,36],33:[1,37]},{1:[2,4],7:22,8:12,9:13,10:14,11:15,12:[1,18],14:[1,19],20:16,21:17,22:[1,20]},{1:[2,6],12:[2,6],14:[2,6],22:[2,6]},{1:[2,11],12:[2,11],14:[2,11],22:[2,11]},{1:[2,13],12:[2,13],14:[2,13],22:[2,13]},{15:[1,29],17:[1,30],18:[1,33],23:38,25:27,26:28,27:32,29:34,30:[1,35],31:[1,31],32:[1,36],33:[1,37]},{24:[1,39]},{24:[2,23]},{24:[2,24],28:[1,40]},{24:[2,30]},{24:[2,31]},{24:[2,32]},{24:[2,25],28:[2,25]},{24:[2,27],28:[2,27]},{24:[2,28],28:[2,28]},{24:[2,29],28:[2,29]},{24:[2,33],28:[2,33]},{24:[2,34],28:[2,34]},{24:[1,41]},{1:[2,21],12:[2,21],14:[2,21],22:[2,21]},{18:[1,33],27:42,29:34,30:[1,35],32:[1,36],33:[1,37]},{1:[2,22],12:[2,22],14:[2,22],22:[2,22]},{24:[2,26],28:[2,26]}], |
| defaultActions: {27:[2,23],29:[2,30],30:[2,31],31:[2,32]}, |
| parseError: function parseError(str, hash) { |
| if (hash.recoverable) { |
| this.trace(str); |
| } else { |
| throw new Error(str); |
| } |
| }, |
| parse: function parse(input) { |
| var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; |
| var args = lstack.slice.call(arguments, 1); |
| this.lexer.setInput(input); |
| this.lexer.yy = this.yy; |
| this.yy.lexer = this.lexer; |
| this.yy.parser = this; |
| if (typeof this.lexer.yylloc == 'undefined') { |
| this.lexer.yylloc = {}; |
| } |
| var yyloc = this.lexer.yylloc; |
| lstack.push(yyloc); |
| var ranges = this.lexer.options && this.lexer.options.ranges; |
| if (typeof this.yy.parseError === 'function') { |
| this.parseError = this.yy.parseError; |
| } else { |
| this.parseError = Object.getPrototypeOf(this).parseError; |
| } |
| function popStack(n) { |
| stack.length = stack.length - 2 * n; |
| vstack.length = vstack.length - n; |
| lstack.length = lstack.length - n; |
| } |
| function lex() { |
| var token; |
| token = self.lexer.lex() || EOF; |
| if (typeof token !== 'number') { |
| token = self.symbols_[token] || token; |
| } |
| return token; |
| } |
| var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; |
| while (true) { |
| state = stack[stack.length - 1]; |
| if (this.defaultActions[state]) { |
| action = this.defaultActions[state]; |
| } else { |
| if (symbol === null || typeof symbol == 'undefined') { |
| symbol = lex(); |
| } |
| action = table[state] && table[state][symbol]; |
| } |
| if (typeof action === 'undefined' || !action.length || !action[0]) { |
| var errStr = ''; |
| expected = []; |
| for (p in table[state]) { |
| if (this.terminals_[p] && p > TERROR) { |
| expected.push('\'' + this.terminals_[p] + '\''); |
| } |
| } |
| if (this.lexer.showPosition) { |
| errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + this.lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''; |
| } else { |
| errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\''); |
| } |
| this.parseError(errStr, { |
| text: this.lexer.match, |
| token: this.terminals_[symbol] || symbol, |
| line: this.lexer.yylineno, |
| loc: yyloc, |
| expected: expected |
| }); |
| } |
| if (action[0] instanceof Array && action.length > 1) { |
| throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol); |
| } |
| switch (action[0]) { |
| case 1: |
| stack.push(symbol); |
| vstack.push(this.lexer.yytext); |
| lstack.push(this.lexer.yylloc); |
| stack.push(action[1]); |
| symbol = null; |
| if (!preErrorSymbol) { |
| yyleng = this.lexer.yyleng; |
| yytext = this.lexer.yytext; |
| yylineno = this.lexer.yylineno; |
| yyloc = this.lexer.yylloc; |
| if (recovering > 0) { |
| recovering--; |
| } |
| } else { |
| symbol = preErrorSymbol; |
| preErrorSymbol = null; |
| } |
| break; |
| case 2: |
| len = this.productions_[action[1]][1]; |
| yyval.$ = vstack[vstack.length - len]; |
| yyval._$ = { |
| first_line: lstack[lstack.length - (len || 1)].first_line, |
| last_line: lstack[lstack.length - 1].last_line, |
| first_column: lstack[lstack.length - (len || 1)].first_column, |
| last_column: lstack[lstack.length - 1].last_column |
| }; |
| if (ranges) { |
| yyval._$.range = [ |
| lstack[lstack.length - (len || 1)].range[0], |
| lstack[lstack.length - 1].range[1] |
| ]; |
| } |
| r = this.performAction.apply(yyval, [ |
| yytext, |
| yyleng, |
| yylineno, |
| this.yy, |
| action[1], |
| vstack, |
| lstack |
| ].concat(args)); |
| if (typeof r !== 'undefined') { |
| return r; |
| } |
| if (len) { |
| stack = stack.slice(0, -1 * len * 2); |
| vstack = vstack.slice(0, -1 * len); |
| lstack = lstack.slice(0, -1 * len); |
| } |
| stack.push(this.productions_[action[1]][0]); |
| vstack.push(yyval.$); |
| lstack.push(yyval._$); |
| newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; |
| stack.push(newState); |
| break; |
| case 3: |
| return true; |
| } |
| } |
| return true; |
| }}; |
| var _ast = { |
| |
| initialize: function() { |
| this._nodes = []; |
| this._node = {}; |
| this._stash = []; |
| }, |
| |
| set: function(props) { |
| for (var k in props) this._node[k] = props[k]; |
| return this._node; |
| }, |
| |
| node: function(obj) { |
| if (arguments.length) this._node = obj; |
| return this._node; |
| }, |
| |
| push: function() { |
| this._nodes.push(this._node); |
| this._node = {}; |
| }, |
| |
| unshift: function() { |
| this._nodes.unshift(this._node); |
| this._node = {}; |
| }, |
| |
| yield: function() { |
| var _nodes = this._nodes; |
| this.initialize(); |
| return _nodes; |
| } |
| }; |
| /* generated by jison-lex 0.2.1 */ |
| var lexer = (function(){ |
| var lexer = { |
| |
| EOF:1, |
| |
| parseError:function parseError(str, hash) { |
| if (this.yy.parser) { |
| this.yy.parser.parseError(str, hash); |
| } else { |
| throw new Error(str); |
| } |
| }, |
| |
| // resets the lexer, sets new input |
| setInput:function (input) { |
| this._input = input; |
| this._more = this._backtrack = this.done = false; |
| this.yylineno = this.yyleng = 0; |
| this.yytext = this.matched = this.match = ''; |
| this.conditionStack = ['INITIAL']; |
| this.yylloc = { |
| first_line: 1, |
| first_column: 0, |
| last_line: 1, |
| last_column: 0 |
| }; |
| if (this.options.ranges) { |
| this.yylloc.range = [0,0]; |
| } |
| this.offset = 0; |
| return this; |
| }, |
| |
| // consumes and returns one char from the input |
| input:function () { |
| var ch = this._input[0]; |
| this.yytext += ch; |
| this.yyleng++; |
| this.offset++; |
| this.match += ch; |
| this.matched += ch; |
| var lines = ch.match(/(?:\r\n?|\n).*/g); |
| if (lines) { |
| this.yylineno++; |
| this.yylloc.last_line++; |
| } else { |
| this.yylloc.last_column++; |
| } |
| if (this.options.ranges) { |
| this.yylloc.range[1]++; |
| } |
| |
| this._input = this._input.slice(1); |
| return ch; |
| }, |
| |
| // unshifts one char (or a string) into the input |
| unput:function (ch) { |
| var len = ch.length; |
| var lines = ch.split(/(?:\r\n?|\n)/g); |
| |
| this._input = ch + this._input; |
| this.yytext = this.yytext.substr(0, this.yytext.length - len - 1); |
| //this.yyleng -= len; |
| this.offset -= len; |
| var oldLines = this.match.split(/(?:\r\n?|\n)/g); |
| this.match = this.match.substr(0, this.match.length - 1); |
| this.matched = this.matched.substr(0, this.matched.length - 1); |
| |
| if (lines.length - 1) { |
| this.yylineno -= lines.length - 1; |
| } |
| var r = this.yylloc.range; |
| |
| this.yylloc = { |
| first_line: this.yylloc.first_line, |
| last_line: this.yylineno + 1, |
| first_column: this.yylloc.first_column, |
| last_column: lines ? |
| (lines.length === oldLines.length ? this.yylloc.first_column : 0) |
| + oldLines[oldLines.length - lines.length].length - lines[0].length : |
| this.yylloc.first_column - len |
| }; |
| |
| if (this.options.ranges) { |
| this.yylloc.range = [r[0], r[0] + this.yyleng - len]; |
| } |
| this.yyleng = this.yytext.length; |
| return this; |
| }, |
| |
| // When called from action, caches matched text and appends it on next action |
| more:function () { |
| this._more = true; |
| return this; |
| }, |
| |
| // When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead. |
| reject:function () { |
| if (this.options.backtrack_lexer) { |
| this._backtrack = true; |
| } else { |
| return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), { |
| text: "", |
| token: null, |
| line: this.yylineno |
| }); |
| |
| } |
| return this; |
| }, |
| |
| // retain first n characters of the match |
| less:function (n) { |
| this.unput(this.match.slice(n)); |
| }, |
| |
| // displays already matched input, i.e. for error messages |
| pastInput:function () { |
| var past = this.matched.substr(0, this.matched.length - this.match.length); |
| return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); |
| }, |
| |
| // displays upcoming input, i.e. for error messages |
| upcomingInput:function () { |
| var next = this.match; |
| if (next.length < 20) { |
| next += this._input.substr(0, 20-next.length); |
| } |
| return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); |
| }, |
| |
| // displays the character position where the lexing error occurred, i.e. for error messages |
| showPosition:function () { |
| var pre = this.pastInput(); |
| var c = new Array(pre.length + 1).join("-"); |
| return pre + this.upcomingInput() + "\n" + c + "^"; |
| }, |
| |
| // test the lexed token: return FALSE when not a match, otherwise return token |
| test_match:function (match, indexed_rule) { |
| var token, |
| lines, |
| backup; |
| |
| if (this.options.backtrack_lexer) { |
| // save context |
| backup = { |
| yylineno: this.yylineno, |
| yylloc: { |
| first_line: this.yylloc.first_line, |
| last_line: this.last_line, |
| first_column: this.yylloc.first_column, |
| last_column: this.yylloc.last_column |
| }, |
| yytext: this.yytext, |
| match: this.match, |
| matches: this.matches, |
| matched: this.matched, |
| yyleng: this.yyleng, |
| offset: this.offset, |
| _more: this._more, |
| _input: this._input, |
| yy: this.yy, |
| conditionStack: this.conditionStack.slice(0), |
| done: this.done |
| }; |
| if (this.options.ranges) { |
| backup.yylloc.range = this.yylloc.range.slice(0); |
| } |
| } |
| |
| lines = match[0].match(/(?:\r\n?|\n).*/g); |
| if (lines) { |
| this.yylineno += lines.length; |
| } |
| this.yylloc = { |
| first_line: this.yylloc.last_line, |
| last_line: this.yylineno + 1, |
| first_column: this.yylloc.last_column, |
| last_column: lines ? |
| lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : |
| this.yylloc.last_column + match[0].length |
| }; |
| this.yytext += match[0]; |
| this.match += match[0]; |
| this.matches = match; |
| this.yyleng = this.yytext.length; |
| if (this.options.ranges) { |
| this.yylloc.range = [this.offset, this.offset += this.yyleng]; |
| } |
| this._more = false; |
| this._backtrack = false; |
| this._input = this._input.slice(match[0].length); |
| this.matched += match[0]; |
| token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]); |
| if (this.done && this._input) { |
| this.done = false; |
| } |
| if (token) { |
| return token; |
| } else if (this._backtrack) { |
| // recover context |
| for (var k in backup) { |
| this[k] = backup[k]; |
| } |
| return false; // rule action called reject() implying the next rule should be tested instead. |
| } |
| return false; |
| }, |
| |
| // return next match in input |
| next:function () { |
| if (this.done) { |
| return this.EOF; |
| } |
| if (!this._input) { |
| this.done = true; |
| } |
| |
| var token, |
| match, |
| tempMatch, |
| index; |
| if (!this._more) { |
| this.yytext = ''; |
| this.match = ''; |
| } |
| var rules = this._currentRules(); |
| for (var i = 0; i < rules.length; i++) { |
| tempMatch = this._input.match(this.rules[rules[i]]); |
| if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { |
| match = tempMatch; |
| index = i; |
| if (this.options.backtrack_lexer) { |
| token = this.test_match(tempMatch, rules[i]); |
| if (token !== false) { |
| return token; |
| } else if (this._backtrack) { |
| match = false; |
| continue; // rule action called reject() implying a rule MISmatch. |
| } else { |
| // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) |
| return false; |
| } |
| } else if (!this.options.flex) { |
| break; |
| } |
| } |
| } |
| if (match) { |
| token = this.test_match(match, rules[index]); |
| if (token !== false) { |
| return token; |
| } |
| // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) |
| return false; |
| } |
| if (this._input === "") { |
| return this.EOF; |
| } else { |
| return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { |
| text: "", |
| token: null, |
| line: this.yylineno |
| }); |
| } |
| }, |
| |
| // return next match that has a token |
| lex:function lex() { |
| var r = this.next(); |
| if (r) { |
| return r; |
| } else { |
| return this.lex(); |
| } |
| }, |
| |
| // activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) |
| begin:function begin(condition) { |
| this.conditionStack.push(condition); |
| }, |
| |
| // pop the previously active lexer condition state off the condition stack |
| popState:function popState() { |
| var n = this.conditionStack.length - 1; |
| if (n > 0) { |
| return this.conditionStack.pop(); |
| } else { |
| return this.conditionStack[0]; |
| } |
| }, |
| |
| // produce the lexer rule set which is active for the currently active lexer condition state |
| _currentRules:function _currentRules() { |
| if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) { |
| return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; |
| } else { |
| return this.conditions["INITIAL"].rules; |
| } |
| }, |
| |
| // return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available |
| topState:function topState(n) { |
| n = this.conditionStack.length - 1 - Math.abs(n || 0); |
| if (n >= 0) { |
| return this.conditionStack[n]; |
| } else { |
| return "INITIAL"; |
| } |
| }, |
| |
| // alias for begin(condition) |
| pushState:function pushState(condition) { |
| this.begin(condition); |
| }, |
| |
| // return the number of states currently on the stack |
| stateStackSize:function stateStackSize() { |
| return this.conditionStack.length; |
| }, |
| options: {}, |
| performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START |
| /**/) { |
| |
| var YYSTATE=YY_START; |
| switch($avoiding_name_collisions) { |
| case 0:return 4 |
| break; |
| case 1:return 14 |
| break; |
| case 2:return 12 |
| break; |
| case 3:return 15 |
| break; |
| case 4:return 16 |
| break; |
| case 5:return 22 |
| break; |
| case 6:return 24 |
| break; |
| case 7:return 28 |
| break; |
| case 8:return 30 |
| break; |
| case 9:return 18 |
| break; |
| case 10:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 32; |
| break; |
| case 11:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 33; |
| break; |
| case 12:return 17 |
| break; |
| case 13:return 31 |
| break; |
| } |
| }, |
| rules: [/^(?:\$)/,/^(?:\.\.)/,/^(?:\.)/,/^(?:\*)/,/^(?:[a-zA-Z_]+[a-zA-Z0-9_]*)/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?:((-?(?:0|[1-9][0-9]*)))?\:((-?(?:0|[1-9][0-9]*)))?(\:((-?(?:0|[1-9][0-9]*)))?)?)/,/^(?:(-?(?:0|[1-9][0-9]*)))/,/^(?:"(?:\\["bfnrt/\\]|\\u[a-fA-F0-9]{4}|[^"\\])*")/,/^(?:'(?:\\['bfnrt/\\]|\\u[a-fA-F0-9]{4}|[^'\\])*')/,/^(?:\(.+?\)(?=\]))/,/^(?:\?\(.+?\)(?=\]))/], |
| conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}} |
| }; |
| return lexer; |
| })(); |
| parser.lexer = lexer; |
| function Parser () { |
| this.yy = {}; |
| } |
| Parser.prototype = parser;parser.Parser = Parser; |
| return new Parser; |
| })(); |
| |
| |
| if (typeof require !== 'undefined' && typeof exports !== 'undefined') { |
| exports.parser = parser; |
| exports.Parser = parser.Parser; |
| exports.parse = function () { return parser.parse.apply(parser, arguments); }; |
| exports.main = function commonjsMain(args) { |
| if (!args[1]) { |
| console.log('Usage: '+args[0]+' FILE'); |
| process.exit(1); |
| } |
| var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8"); |
| return exports.parser.parse(source); |
| }; |
| if (typeof module !== 'undefined' && require.main === module) { |
| exports.main(process.argv.slice(1)); |
| } |
| } |
| |
| }).call(this,require('_process')) |
| },{"_process":14,"fs":12,"path":13}],2:[function(require,module,exports){ |
| module.exports = { |
| identifier: "[a-zA-Z_]+[a-zA-Z0-9_]*", |
| integer: "-?(?:0|[1-9][0-9]*)", |
| qq_string: "\"(?:\\\\[\"bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\"\\\\])*\"", |
| q_string: "'(?:\\\\[\'bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\'\\\\])*'" |
| }; |
| |
| },{}],3:[function(require,module,exports){ |
| var dict = require('./dict'); |
| var fs = require('fs'); |
| var grammar = { |
| |
| lex: { |
| |
| macros: { |
| esc: "\\\\", |
| int: dict.integer |
| }, |
| |
| rules: [ |
| ["\\$", "return 'DOLLAR'"], |
| ["\\.\\.", "return 'DOT_DOT'"], |
| ["\\.", "return 'DOT'"], |
| ["\\*", "return 'STAR'"], |
| [dict.identifier, "return 'IDENTIFIER'"], |
| ["\\[", "return '['"], |
| ["\\]", "return ']'"], |
| [",", "return ','"], |
| ["({int})?\\:({int})?(\\:({int})?)?", "return 'ARRAY_SLICE'"], |
| ["{int}", "return 'INTEGER'"], |
| [dict.qq_string, "yytext = yytext.substr(1,yyleng-2); return 'QQ_STRING';"], |
| [dict.q_string, "yytext = yytext.substr(1,yyleng-2); return 'Q_STRING';"], |
| ["\\(.+?\\)(?=\\])", "return 'SCRIPT_EXPRESSION'"], |
| ["\\?\\(.+?\\)(?=\\])", "return 'FILTER_EXPRESSION'"] |
| ] |
| }, |
| |
| start: "JSON_PATH", |
| |
| bnf: { |
| |
| JSON_PATH: [ |
| [ 'DOLLAR', 'yy.ast.set({ expression: { type: "root", value: $1 } }); yy.ast.unshift(); return yy.ast.yield()' ], |
| [ 'DOLLAR PATH_COMPONENTS', 'yy.ast.set({ expression: { type: "root", value: $1 } }); yy.ast.unshift(); return yy.ast.yield()' ], |
| [ 'LEADING_CHILD_MEMBER_EXPRESSION', 'yy.ast.unshift(); return yy.ast.yield()' ], |
| [ 'LEADING_CHILD_MEMBER_EXPRESSION PATH_COMPONENTS', 'yy.ast.set({ operation: "member", scope: "child", expression: { type: "identifier", value: $1 }}); yy.ast.unshift(); return yy.ast.yield()' ] ], |
| |
| PATH_COMPONENTS: [ |
| [ 'PATH_COMPONENT', '' ], |
| [ 'PATH_COMPONENTS PATH_COMPONENT', '' ] ], |
| |
| PATH_COMPONENT: [ |
| [ 'MEMBER_COMPONENT', 'yy.ast.set({ operation: "member" }); yy.ast.push()' ], |
| [ 'SUBSCRIPT_COMPONENT', 'yy.ast.set({ operation: "subscript" }); yy.ast.push() ' ] ], |
| |
| MEMBER_COMPONENT: [ |
| [ 'CHILD_MEMBER_COMPONENT', 'yy.ast.set({ scope: "child" })' ], |
| [ 'DESCENDANT_MEMBER_COMPONENT', 'yy.ast.set({ scope: "descendant" })' ] ], |
| |
| CHILD_MEMBER_COMPONENT: [ |
| [ 'DOT MEMBER_EXPRESSION', '' ] ], |
| |
| LEADING_CHILD_MEMBER_EXPRESSION: [ |
| [ 'MEMBER_EXPRESSION', 'yy.ast.set({ scope: "child", operation: "member" })' ] ], |
| |
| DESCENDANT_MEMBER_COMPONENT: [ |
| [ 'DOT_DOT MEMBER_EXPRESSION', '' ] ], |
| |
| MEMBER_EXPRESSION: [ |
| [ 'STAR', 'yy.ast.set({ expression: { type: "wildcard", value: $1 } })' ], |
| [ 'IDENTIFIER', 'yy.ast.set({ expression: { type: "identifier", value: $1 } })' ], |
| [ 'SCRIPT_EXPRESSION', 'yy.ast.set({ expression: { type: "script_expression", value: $1 } })' ], |
| [ 'INTEGER', 'yy.ast.set({ expression: { type: "numeric_literal", value: parseInt($1) } })' ], |
| [ 'END', '' ] ], |
| |
| SUBSCRIPT_COMPONENT: [ |
| [ 'CHILD_SUBSCRIPT_COMPONENT', 'yy.ast.set({ scope: "child" })' ], |
| [ 'DESCENDANT_SUBSCRIPT_COMPONENT', 'yy.ast.set({ scope: "descendant" })' ] ], |
| |
| CHILD_SUBSCRIPT_COMPONENT: [ |
| [ '[ SUBSCRIPT ]', '' ] ], |
| |
| DESCENDANT_SUBSCRIPT_COMPONENT: [ |
| [ 'DOT_DOT [ SUBSCRIPT ]', '' ] ], |
| |
| SUBSCRIPT: [ |
| [ 'SUBSCRIPT_EXPRESSION', '' ], |
| [ 'SUBSCRIPT_EXPRESSION_LIST', '$1.length > 1? yy.ast.set({ expression: { type: "union", value: $1 } }) : $$ = $1' ] ], |
| |
| SUBSCRIPT_EXPRESSION_LIST: [ |
| [ 'SUBSCRIPT_EXPRESSION_LISTABLE', '$$ = [$1]'], |
| [ 'SUBSCRIPT_EXPRESSION_LIST , SUBSCRIPT_EXPRESSION_LISTABLE', '$$ = $1.concat($3)' ] ], |
| |
| SUBSCRIPT_EXPRESSION_LISTABLE: [ |
| [ 'INTEGER', '$$ = { expression: { type: "numeric_literal", value: parseInt($1) } }; yy.ast.set($$)' ], |
| [ 'STRING_LITERAL', '$$ = { expression: { type: "string_literal", value: $1 } }; yy.ast.set($$)' ], |
| [ 'ARRAY_SLICE', '$$ = { expression: { type: "slice", value: $1 } }; yy.ast.set($$)' ] ], |
| |
| SUBSCRIPT_EXPRESSION: [ |
| [ 'STAR', '$$ = { expression: { type: "wildcard", value: $1 } }; yy.ast.set($$)' ], |
| [ 'SCRIPT_EXPRESSION', '$$ = { expression: { type: "script_expression", value: $1 } }; yy.ast.set($$)' ], |
| [ 'FILTER_EXPRESSION', '$$ = { expression: { type: "filter_expression", value: $1 } }; yy.ast.set($$)' ] ], |
| |
| STRING_LITERAL: [ |
| [ 'QQ_STRING', "$$ = $1" ], |
| [ 'Q_STRING', "$$ = $1" ] ] |
| } |
| }; |
| if (fs.readFileSync) { |
| grammar.moduleInclude = fs.readFileSync(require.resolve("../include/module.js")); |
| grammar.actionInclude = fs.readFileSync(require.resolve("../include/action.js")); |
| } |
| |
| module.exports = grammar; |
| |
| },{"./dict":2,"fs":12}],4:[function(require,module,exports){ |
| var aesprim = require('./aesprim'); |
| var slice = require('./slice'); |
| var _evaluate = require('static-eval'); |
| var _uniq = require('underscore').uniq; |
| |
| var Handlers = function() { |
| return this.initialize.apply(this, arguments); |
| } |
| |
| Handlers.prototype.initialize = function() { |
| this.traverse = traverser(true); |
| this.descend = traverser(); |
| } |
| |
| Handlers.prototype.keys = Object.keys; |
| |
| Handlers.prototype.resolve = function(component) { |
| |
| var key = [ component.operation, component.scope, component.expression.type ].join('-'); |
| var method = this._fns[key]; |
| |
| if (!method) throw new Error("couldn't resolve key: " + key); |
| return method.bind(this); |
| }; |
| |
| Handlers.prototype.register = function(key, handler) { |
| |
| if (!handler instanceof Function) { |
| throw new Error("handler must be a function"); |
| } |
| |
| this._fns[key] = handler; |
| }; |
| |
| Handlers.prototype._fns = { |
| |
| 'member-child-identifier': function(component, partial) { |
| var key = component.expression.value; |
| var value = partial.value; |
| if (value instanceof Object && key in value) { |
| return [ { value: value[key], path: partial.path.concat(key) } ] |
| } |
| }, |
| |
| 'member-descendant-identifier': |
| _traverse(function(key, value, ref) { return key == ref }), |
| |
| 'subscript-child-numeric_literal': |
| _descend(function(key, value, ref) { return key === ref }), |
| |
| 'member-child-numeric_literal': |
| _descend(function(key, value, ref) { return String(key) === String(ref) }), |
| |
| 'subscript-descendant-numeric_literal': |
| _traverse(function(key, value, ref) { return key === ref }), |
| |
| 'member-child-wildcard': |
| _descend(function() { return true }), |
| |
| 'member-descendant-wildcard': |
| _traverse(function() { return true }), |
| |
| 'subscript-descendant-wildcard': |
| _traverse(function() { return true }), |
| |
| 'subscript-child-wildcard': |
| _descend(function() { return true }), |
| |
| 'subscript-child-slice': function(component, partial) { |
| if (is_array(partial.value)) { |
| var args = component.expression.value.split(':').map(_parse_nullable_int); |
| var values = partial.value.map(function(v, i) { return { value: v, path: partial.path.concat(i) } }); |
| return slice.apply(null, [values].concat(args)); |
| } |
| }, |
| |
| 'subscript-child-union': function(component, partial) { |
| var results = []; |
| component.expression.value.forEach(function(component) { |
| var _component = { operation: 'subscript', scope: 'child', expression: component.expression }; |
| var handler = this.resolve(_component); |
| var _results = handler(_component, partial); |
| if (_results) { |
| results = results.concat(_results); |
| } |
| }, this); |
| |
| return unique(results); |
| }, |
| |
| 'subscript-descendant-union': function(component, partial, count) { |
| |
| var jp = require('..'); |
| var self = this; |
| |
| var results = []; |
| var nodes = jp.nodes(partial, '$..*').slice(1); |
| |
| nodes.forEach(function(node) { |
| if (results.length >= count) return; |
| component.expression.value.forEach(function(component) { |
| var _component = { operation: 'subscript', scope: 'child', expression: component.expression }; |
| var handler = self.resolve(_component); |
| var _results = handler(_component, node); |
| results = results.concat(_results); |
| }); |
| }); |
| |
| return unique(results); |
| }, |
| |
| 'subscript-child-filter_expression': function(component, partial, count) { |
| |
| // slice out the expression from ?(expression) |
| var src = component.expression.value.slice(2, -1); |
| var ast = aesprim.parse(src).body[0].expression; |
| |
| var passable = function(key, value) { |
| return evaluate(ast, { '@': value }); |
| } |
| |
| return this.descend(partial, null, passable, count); |
| |
| }, |
| |
| 'subscript-descendant-filter_expression': function(component, partial, count) { |
| |
| // slice out the expression from ?(expression) |
| var src = component.expression.value.slice(2, -1); |
| var ast = aesprim.parse(src).body[0].expression; |
| |
| var passable = function(key, value) { |
| return evaluate(ast, { '@': value }); |
| } |
| |
| return this.traverse(partial, null, passable, count); |
| }, |
| |
| 'subscript-child-script_expression': function(component, partial) { |
| var exp = component.expression.value.slice(1, -1); |
| return eval_recurse(partial, exp, '$[{{value}}]'); |
| }, |
| |
| 'member-child-script_expression': function(component, partial) { |
| var exp = component.expression.value.slice(1, -1); |
| return eval_recurse(partial, exp, '$.{{value}}'); |
| }, |
| |
| 'member-descendant-script_expression': function(component, partial) { |
| var exp = component.expression.value.slice(1, -1); |
| return eval_recurse(partial, exp, '$..value'); |
| } |
| }; |
| |
| Handlers.prototype._fns['subscript-child-string_literal'] = |
| Handlers.prototype._fns['member-child-identifier']; |
| |
| Handlers.prototype._fns['member-descendant-numeric_literal'] = |
| Handlers.prototype._fns['subscript-descendant-string_literal'] = |
| Handlers.prototype._fns['member-descendant-identifier']; |
| |
| function eval_recurse(partial, src, template) { |
| |
| var jp = require('./index'); |
| var ast = aesprim.parse(src).body[0].expression; |
| var value = evaluate(ast, { '@': partial.value }); |
| var path = template.replace(/\{\{\s*value\s*\}\}/g, value); |
| |
| var results = jp.nodes(partial.value, path); |
| results.forEach(function(r) { |
| r.path = partial.path.concat(r.path.slice(1)); |
| }); |
| |
| return results; |
| } |
| |
| function is_array(val) { |
| return Array.isArray(val); |
| } |
| |
| function is_object(val) { |
| // is this a non-array, non-null object? |
| return val && !(val instanceof Array) && val instanceof Object; |
| } |
| |
| function traverser(recurse) { |
| |
| return function(partial, ref, passable, count) { |
| |
| var value = partial.value; |
| var path = partial.path; |
| |
| var results = []; |
| |
| var descend = function(value, path) { |
| |
| if (is_array(value)) { |
| value.forEach(function(element, index) { |
| if (results.length >= count) { return } |
| if (passable(index, element, ref)) { |
| results.push({ path: path.concat(index), value: element }); |
| } |
| }); |
| value.forEach(function(element, index) { |
| if (results.length >= count) { return } |
| if (recurse) { |
| descend(element, path.concat(index)); |
| } |
| }); |
| } else if (is_object(value)) { |
| this.keys(value).forEach(function(k) { |
| if (results.length >= count) { return } |
| if (passable(k, value[k], ref)) { |
| results.push({ path: path.concat(k), value: value[k] }); |
| } |
| }) |
| this.keys(value).forEach(function(k) { |
| if (results.length >= count) { return } |
| if (recurse) { |
| descend(value[k], path.concat(k)); |
| } |
| }); |
| } |
| }.bind(this); |
| descend(value, path); |
| return results; |
| } |
| } |
| |
| function _descend(passable) { |
| return function(component, partial, count) { |
| return this.descend(partial, component.expression.value, passable, count); |
| } |
| } |
| |
| function _traverse(passable) { |
| return function(component, partial, count) { |
| return this.traverse(partial, component.expression.value, passable, count); |
| } |
| } |
| |
| function evaluate() { |
| try { return _evaluate.apply(this, arguments) } |
| catch (e) { } |
| } |
| |
| function unique(results) { |
| results = results.filter(function(d) { return d }) |
| return _uniq( |
| results, |
| function(r) { return r.path.map(function(c) { return String(c).replace('-', '--') }).join('-') } |
| ); |
| } |
| |
| function _parse_nullable_int(val) { |
| var sval = String(val); |
| return sval.match(/^-?[0-9]+$/) ? parseInt(sval) : null; |
| } |
| |
| module.exports = Handlers; |
| |
| },{"..":"jsonpath","./aesprim":"./aesprim","./index":5,"./slice":7,"static-eval":15,"underscore":12}],5:[function(require,module,exports){ |
| var assert = require('assert'); |
| var dict = require('./dict'); |
| var Parser = require('./parser'); |
| var Handlers = require('./handlers'); |
| |
| var JSONPath = function() { |
| this.initialize.apply(this, arguments); |
| }; |
| |
| JSONPath.prototype.initialize = function() { |
| this.parser = new Parser(); |
| this.handlers = new Handlers(); |
| }; |
| |
| JSONPath.prototype.parse = function(string) { |
| assert.ok(_is_string(string), "we need a path"); |
| return this.parser.parse(string); |
| }; |
| |
| JSONPath.prototype.parent = function(obj, string) { |
| |
| assert.ok(obj instanceof Object, "obj needs to be an object"); |
| assert.ok(string, "we need a path"); |
| |
| var node = this.nodes(obj, string)[0]; |
| var key = node.path.pop(); /* jshint unused:false */ |
| return this.value(obj, node.path); |
| } |
| |
| JSONPath.prototype.apply = function(obj, string, fn) { |
| |
| assert.ok(obj instanceof Object, "obj needs to be an object"); |
| assert.ok(string, "we need a path"); |
| assert.equal(typeof fn, "function", "fn needs to be function") |
| |
| var nodes = this.nodes(obj, string).sort(function(a, b) { |
| // sort nodes so we apply from the bottom up |
| return b.path.length - a.path.length; |
| }); |
| |
| nodes.forEach(function(node) { |
| var key = node.path.pop(); |
| var parent = this.value(obj, this.stringify(node.path)); |
| var val = node.value = fn.call(obj, parent[key]); |
| parent[key] = val; |
| }, this); |
| |
| return nodes; |
| } |
| |
| JSONPath.prototype.value = function(obj, path, value) { |
| |
| assert.ok(obj instanceof Object, "obj needs to be an object"); |
| assert.ok(path, "we need a path"); |
| |
| if (arguments.length >= 3) { |
| var node = this.nodes(obj, path).shift(); |
| if (!node) return this._vivify(obj, path, value); |
| var key = node.path.slice(-1).shift(); |
| var parent = this.parent(obj, this.stringify(node.path)); |
| parent[key] = value; |
| } |
| return this.query(obj, this.stringify(path), 1).shift(); |
| } |
| |
| JSONPath.prototype._vivify = function(obj, string, value) { |
| |
| var self = this; |
| |
| assert.ok(obj instanceof Object, "obj needs to be an object"); |
| assert.ok(string, "we need a path"); |
| |
| var path = this.parser.parse(string) |
| .map(function(component) { return component.expression.value }); |
| |
| var setValue = function(path, value) { |
| var key = path.pop(); |
| var node = self.value(obj, path); |
| if (!node) { |
| setValue(path.concat(), typeof key === 'string' ? {} : []); |
| node = self.value(obj, path); |
| } |
| node[key] = value; |
| } |
| setValue(path, value); |
| return this.query(obj, string)[0]; |
| } |
| |
| JSONPath.prototype.query = function(obj, string, count) { |
| |
| assert.ok(obj instanceof Object, "obj needs to be an object"); |
| assert.ok(_is_string(string), "we need a path"); |
| |
| var results = this.nodes(obj, string, count) |
| .map(function(r) { return r.value }); |
| |
| return results; |
| }; |
| |
| JSONPath.prototype.paths = function(obj, string, count) { |
| |
| assert.ok(obj instanceof Object, "obj needs to be an object"); |
| assert.ok(string, "we need a path"); |
| |
| var results = this.nodes(obj, string, count) |
| .map(function(r) { return r.path }); |
| |
| return results; |
| }; |
| |
| JSONPath.prototype.nodes = function(obj, string, count) { |
| |
| assert.ok(obj instanceof Object, "obj needs to be an object"); |
| assert.ok(string, "we need a path"); |
| |
| if (count === 0) return []; |
| |
| var path = this.parser.parse(string); |
| var handlers = this.handlers; |
| |
| var partials = [ { path: ['$'], value: obj } ]; |
| var matches = []; |
| |
| if (path.length && path[0].expression.type == 'root') path.shift(); |
| |
| if (!path.length) return partials; |
| |
| path.forEach(function(component, index) { |
| |
| if (matches.length >= count) return; |
| var handler = handlers.resolve(component); |
| var _partials = []; |
| |
| partials.forEach(function(p) { |
| |
| if (matches.length >= count) return; |
| var results = handler(component, p, count); |
| |
| if (index == path.length - 1) { |
| // if we're through the components we're done |
| matches = matches.concat(results || []); |
| } else { |
| // otherwise accumulate and carry on through |
| _partials = _partials.concat(results || []); |
| } |
| }); |
| |
| partials = _partials; |
| |
| }); |
| |
| return count ? matches.slice(0, count) : matches; |
| }; |
| |
| JSONPath.prototype.stringify = function(path) { |
| |
| assert.ok(path, "we need a path"); |
| |
| var string = '$'; |
| |
| var templates = { |
| 'descendant-member': '..{{value}}', |
| 'child-member': '.{{value}}', |
| 'descendant-subscript': '..[{{value}}]', |
| 'child-subscript': '[{{value}}]' |
| }; |
| |
| path = this._normalize(path); |
| |
| path.forEach(function(component) { |
| |
| if (component.expression.type == 'root') return; |
| |
| var key = [component.scope, component.operation].join('-'); |
| var template = templates[key]; |
| var value; |
| |
| if (component.expression.type == 'string_literal') { |
| value = JSON.stringify(component.expression.value) |
| } else { |
| value = component.expression.value; |
| } |
| |
| if (!template) throw new Error("couldn't find template " + key); |
| |
| string += template.replace(/{{value}}/, value); |
| }); |
| |
| return string; |
| } |
| |
| JSONPath.prototype._normalize = function(path) { |
| |
| assert.ok(path, "we need a path"); |
| |
| if (typeof path == "string") { |
| |
| return this.parser.parse(path); |
| |
| } else if (Array.isArray(path) && typeof path[0] == "string") { |
| |
| var _path = [ { expression: { type: "root", value: "$" } } ]; |
| |
| path.forEach(function(component, index) { |
| |
| if (component == '$' && index === 0) return; |
| |
| if (typeof component == "string" && component.match("^" + dict.identifier + "$")) { |
| |
| _path.push({ |
| operation: 'member', |
| scope: 'child', |
| expression: { value: component, type: 'identifier' } |
| }); |
| |
| } else { |
| |
| var type = typeof component == "number" ? |
| 'numeric_literal' : 'string_literal'; |
| |
| _path.push({ |
| operation: 'subscript', |
| scope: 'child', |
| expression: { value: component, type: type } |
| }); |
| } |
| }); |
| |
| return _path; |
| |
| } else if (Array.isArray(path) && typeof path[0] == "object") { |
| |
| return path |
| } |
| |
| throw new Error("couldn't understand path " + path); |
| } |
| |
| function _is_string(obj) { |
| return Object.prototype.toString.call(obj) == '[object String]'; |
| } |
| |
| JSONPath.Handlers = Handlers; |
| JSONPath.Parser = Parser; |
| |
| var instance = new JSONPath; |
| instance.JSONPath = JSONPath; |
| |
| module.exports = instance; |
| |
| },{"./dict":2,"./handlers":4,"./parser":6,"assert":8}],6:[function(require,module,exports){ |
| var grammar = require('./grammar'); |
| var gparser = require('../generated/parser'); |
| |
| var Parser = function() { |
| |
| var parser = new gparser.Parser(); |
| |
| var _parseError = parser.parseError; |
| parser.yy.parseError = function() { |
| if (parser.yy.ast) { |
| parser.yy.ast.initialize(); |
| } |
| _parseError.apply(parser, arguments); |
| } |
| |
| return parser; |
| |
| }; |
| |
| Parser.grammar = grammar; |
| module.exports = Parser; |
| |
| },{"../generated/parser":1,"./grammar":3}],7:[function(require,module,exports){ |
| module.exports = function(arr, start, end, step) { |
| |
| if (typeof start == 'string') throw new Error("start cannot be a string"); |
| if (typeof end == 'string') throw new Error("end cannot be a string"); |
| if (typeof step == 'string') throw new Error("step cannot be a string"); |
| |
| var len = arr.length; |
| |
| if (step === 0) throw new Error("step cannot be zero"); |
| step = step ? integer(step) : 1; |
| |
| // normalize negative values |
| start = start < 0 ? len + start : start; |
| end = end < 0 ? len + end : end; |
| |
| // default extents to extents |
| start = integer(start === 0 ? 0 : !start ? (step > 0 ? 0 : len - 1) : start); |
| end = integer(end === 0 ? 0 : !end ? (step > 0 ? len : -1) : end); |
| |
| // clamp extents |
| start = step > 0 ? Math.max(0, start) : Math.min(len, start); |
| end = step > 0 ? Math.min(end, len) : Math.max(-1, end); |
| |
| // return empty if extents are backwards |
| if (step > 0 && end <= start) return []; |
| if (step < 0 && start <= end) return []; |
| |
| var result = []; |
| |
| for (var i = start; i != end; i += step) { |
| if ((step < 0 && i <= end) || (step > 0 && i >= end)) break; |
| result.push(arr[i]); |
| } |
| |
| return result; |
| } |
| |
| function integer(val) { |
| return String(val).match(/^[0-9]+$/) ? parseInt(val) : |
| Number.isFinite(val) ? parseInt(val, 10) : 0; |
| } |
| |
| },{}],8:[function(require,module,exports){ |
| // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 |
| // |
| // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! |
| // |
| // Originally from narwhal.js (http://narwhaljs.org) |
| // Copyright (c) 2009 Thomas Robinson <280north.com> |
| // |
| // Permission is hereby granted, free of charge, to any person obtaining a copy |
| // of this software and associated documentation files (the 'Software'), to |
| // deal in the Software without restriction, including without limitation the |
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
| // sell copies of the Software, and to permit persons to whom the Software is |
| // furnished to do so, subject to the following conditions: |
| // |
| // The above copyright notice and this permission notice shall be included in |
| // all copies or substantial portions of the Software. |
| // |
| // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| |
| // when used in node, this will actually load the util module we depend on |
| // versus loading the builtin util module as happens otherwise |
| // this is a bug in node module loading as far as I am concerned |
| var util = require('util/'); |
| |
| var pSlice = Array.prototype.slice; |
| var hasOwn = Object.prototype.hasOwnProperty; |
| |
| // 1. The assert module provides functions that throw |
| // AssertionError's when particular conditions are not met. The |
| // assert module must conform to the following interface. |
| |
| var assert = module.exports = ok; |
| |
| // 2. The AssertionError is defined in assert. |
| // new assert.AssertionError({ message: message, |
| // actual: actual, |
| // expected: expected }) |
| |
| assert.AssertionError = function AssertionError(options) { |
| this.name = 'AssertionError'; |
| this.actual = options.actual; |
| this.expected = options.expected; |
| this.operator = options.operator; |
| if (options.message) { |
| this.message = options.message; |
| this.generatedMessage = false; |
| } else { |
| this.message = getMessage(this); |
| this.generatedMessage = true; |
| } |
| var stackStartFunction = options.stackStartFunction || fail; |
| |
| if (Error.captureStackTrace) { |
| Error.captureStackTrace(this, stackStartFunction); |
| } |
| else { |
| // non v8 browsers so we can have a stacktrace |
| var err = new Error(); |
| if (err.stack) { |
| var out = err.stack; |
| |
| // try to strip useless frames |
| var fn_name = stackStartFunction.name; |
| var idx = out.indexOf('\n' + fn_name); |
| if (idx >= 0) { |
| // once we have located the function frame |
| // we need to strip out everything before it (and its line) |
| var next_line = out.indexOf('\n', idx + 1); |
| out = out.substring(next_line + 1); |
| } |
| |
| this.stack = out; |
| } |
| } |
| }; |
| |
| // assert.AssertionError instanceof Error |
| util.inherits(assert.AssertionError, Error); |
| |
| function replacer(key, value) { |
| if (util.isUndefined(value)) { |
| return '' + value; |
| } |
| if (util.isNumber(value) && !isFinite(value)) { |
| return value.toString(); |
| } |
| if (util.isFunction(value) || util.isRegExp(value)) { |
| return value.toString(); |
| } |
| return value; |
| } |
| |
| function truncate(s, n) { |
| if (util.isString(s)) { |
| return s.length < n ? s : s.slice(0, n); |
| } else { |
| return s; |
| } |
| } |
| |
| function getMessage(self) { |
| return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + |
| self.operator + ' ' + |
| truncate(JSON.stringify(self.expected, replacer), 128); |
| } |
| |
| // At present only the three keys mentioned above are used and |
| // understood by the spec. Implementations or sub modules can pass |
| // other keys to the AssertionError's constructor - they will be |
| // ignored. |
| |
| // 3. All of the following functions must throw an AssertionError |
| // when a corresponding condition is not met, with a message that |
| // may be undefined if not provided. All assertion methods provide |
| // both the actual and expected values to the assertion error for |
| // display purposes. |
| |
| function fail(actual, expected, message, operator, stackStartFunction) { |
| throw new assert.AssertionError({ |
| message: message, |
| actual: actual, |
| expected: expected, |
| operator: operator, |
| stackStartFunction: stackStartFunction |
| }); |
| } |
| |
| // EXTENSION! allows for well behaved errors defined elsewhere. |
| assert.fail = fail; |
| |
| // 4. Pure assertion tests whether a value is truthy, as determined |
| // by !!guard. |
| // assert.ok(guard, message_opt); |
| // This statement is equivalent to assert.equal(true, !!guard, |
| // message_opt);. To test strictly for the value true, use |
| // assert.strictEqual(true, guard, message_opt);. |
| |
| function ok(value, message) { |
| if (!value) fail(value, true, message, '==', assert.ok); |
| } |
| assert.ok = ok; |
| |
| // 5. The equality assertion tests shallow, coercive equality with |
| // ==. |
| // assert.equal(actual, expected, message_opt); |
| |
| assert.equal = function equal(actual, expected, message) { |
| if (actual != expected) fail(actual, expected, message, '==', assert.equal); |
| }; |
| |
| // 6. The non-equality assertion tests for whether two objects are not equal |
| // with != assert.notEqual(actual, expected, message_opt); |
| |
| assert.notEqual = function notEqual(actual, expected, message) { |
| if (actual == expected) { |
| fail(actual, expected, message, '!=', assert.notEqual); |
| } |
| }; |
| |
| // 7. The equivalence assertion tests a deep equality relation. |
| // assert.deepEqual(actual, expected, message_opt); |
| |
| assert.deepEqual = function deepEqual(actual, expected, message) { |
| if (!_deepEqual(actual, expected)) { |
| fail(actual, expected, message, 'deepEqual', assert.deepEqual); |
| } |
| }; |
| |
| function _deepEqual(actual, expected) { |
| // 7.1. All identical values are equivalent, as determined by ===. |
| if (actual === expected) { |
| return true; |
| |
| } else if (util.isBuffer(actual) && util.isBuffer(expected)) { |
| if (actual.length != expected.length) return false; |
| |
| for (var i = 0; i < actual.length; i++) { |
| if (actual[i] !== expected[i]) return false; |
| } |
| |
| return true; |
| |
| // 7.2. If the expected value is a Date object, the actual value is |
| // equivalent if it is also a Date object that refers to the same time. |
| } else if (util.isDate(actual) && util.isDate(expected)) { |
| return actual.getTime() === expected.getTime(); |
| |
| // 7.3 If the expected value is a RegExp object, the actual value is |
| // equivalent if it is also a RegExp object with the same source and |
| // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). |
| } else if (util.isRegExp(actual) && util.isRegExp(expected)) { |
| return actual.source === expected.source && |
| actual.global === expected.global && |
| actual.multiline === expected.multiline && |
| actual.lastIndex === expected.lastIndex && |
| actual.ignoreCase === expected.ignoreCase; |
| |
| // 7.4. Other pairs that do not both pass typeof value == 'object', |
| // equivalence is determined by ==. |
| } else if (!util.isObject(actual) && !util.isObject(expected)) { |
| return actual == expected; |
| |
| // 7.5 For all other Object pairs, including Array objects, equivalence is |
| // determined by having the same number of owned properties (as verified |
| // with Object.prototype.hasOwnProperty.call), the same set of keys |
| // (although not necessarily the same order), equivalent values for every |
| // corresponding key, and an identical 'prototype' property. Note: this |
| // accounts for both named and indexed properties on Arrays. |
| } else { |
| return objEquiv(actual, expected); |
| } |
| } |
| |
| function isArguments(object) { |
| return Object.prototype.toString.call(object) == '[object Arguments]'; |
| } |
| |
| function objEquiv(a, b) { |
| if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b)) |
| return false; |
| // an identical 'prototype' property. |
| if (a.prototype !== b.prototype) return false; |
| // if one is a primitive, the other must be same |
| if (util.isPrimitive(a) || util.isPrimitive(b)) { |
| return a === b; |
| } |
| var aIsArgs = isArguments(a), |
| bIsArgs = isArguments(b); |
| if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) |
| return false; |
| if (aIsArgs) { |
| a = pSlice.call(a); |
| b = pSlice.call(b); |
| return _deepEqual(a, b); |
| } |
| var ka = objectKeys(a), |
| kb = objectKeys(b), |
| key, i; |
| // having the same number of owned properties (keys incorporates |
| // hasOwnProperty) |
| if (ka.length != kb.length) |
| return false; |
| //the same set of keys (although not necessarily the same order), |
| ka.sort(); |
| kb.sort(); |
| //~~~cheap key test |
| for (i = ka.length - 1; i >= 0; i--) { |
| if (ka[i] != kb[i]) |
| return false; |
| } |
| //equivalent values for every corresponding key, and |
| //~~~possibly expensive deep test |
| for (i = ka.length - 1; i >= 0; i--) { |
| key = ka[i]; |
| if (!_deepEqual(a[key], b[key])) return false; |
| } |
| return true; |
| } |
| |
| // 8. The non-equivalence assertion tests for any deep inequality. |
| // assert.notDeepEqual(actual, expected, message_opt); |
| |
| assert.notDeepEqual = function notDeepEqual(actual, expected, message) { |
| if (_deepEqual(actual, expected)) { |
| fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); |
| } |
| }; |
| |
| // 9. The strict equality assertion tests strict equality, as determined by ===. |
| // assert.strictEqual(actual, expected, message_opt); |
| |
| assert.strictEqual = function strictEqual(actual, expected, message) { |
| if (actual !== expected) { |
| fail(actual, expected, message, '===', assert.strictEqual); |
| } |
| }; |
| |
| // 10. The strict non-equality assertion tests for strict inequality, as |
| // determined by !==. assert.notStrictEqual(actual, expected, message_opt); |
| |
| assert.notStrictEqual = function notStrictEqual(actual, expected, message) { |
| if (actual === expected) { |
| fail(actual, expected, message, '!==', assert.notStrictEqual); |
| } |
| }; |
| |
| function expectedException(actual, expected) { |
| if (!actual || !expected) { |
| return false; |
| } |
| |
| if (Object.prototype.toString.call(expected) == '[object RegExp]') { |
| return expected.test(actual); |
| } else if (actual instanceof expected) { |
| return true; |
| } else if (expected.call({}, actual) === true) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| function _throws(shouldThrow, block, expected, message) { |
| var actual; |
| |
| if (util.isString(expected)) { |
| message = expected; |
| expected = null; |
| } |
| |
| try { |
| block(); |
| } catch (e) { |
| actual = e; |
| } |
| |
| message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + |
| (message ? ' ' + message : '.'); |
| |
| if (shouldThrow && !actual) { |
| fail(actual, expected, 'Missing expected exception' + message); |
| } |
| |
| if (!shouldThrow && expectedException(actual, expected)) { |
| fail(actual, expected, 'Got unwanted exception' + message); |
| } |
| |
| if ((shouldThrow && actual && expected && |
| !expectedException(actual, expected)) || (!shouldThrow && actual)) { |
| throw actual; |
| } |
| } |
| |
| // 11. Expected to throw an error: |
| // assert.throws(block, Error_opt, message_opt); |
| |
| assert.throws = function(block, /*optional*/error, /*optional*/message) { |
| _throws.apply(this, [true].concat(pSlice.call(arguments))); |
| }; |
| |
| // EXTENSION! This is annoying to write outside this module. |
| assert.doesNotThrow = function(block, /*optional*/message) { |
| _throws.apply(this, [false].concat(pSlice.call(arguments))); |
| }; |
| |
| assert.ifError = function(err) { if (err) {throw err;}}; |
| |
| var objectKeys = Object.keys || function (obj) { |
| var keys = []; |
| for (var key in obj) { |
| if (hasOwn.call(obj, key)) keys.push(key); |
| } |
| return keys; |
| }; |
| |
| },{"util/":11}],9:[function(require,module,exports){ |
| if (typeof Object.create === 'function') { |
| // implementation from standard node.js 'util' module |
| module.exports = function inherits(ctor, superCtor) { |
| ctor.super_ = superCtor |
| ctor.prototype = Object.create(superCtor.prototype, { |
| constructor: { |
| value: ctor, |
| enumerable: false, |
| writable: true, |
| configurable: true |
| } |
| }); |
| }; |
| } else { |
| // old school shim for old browsers |
| module.exports = function inherits(ctor, superCtor) { |
| ctor.super_ = superCtor |
| var TempCtor = function () {} |
| TempCtor.prototype = superCtor.prototype |
| ctor.prototype = new TempCtor() |
| ctor.prototype.constructor = ctor |
| } |
| } |
| |
| },{}],10:[function(require,module,exports){ |
| module.exports = function isBuffer(arg) { |
| return arg && typeof arg === 'object' |
| && typeof arg.copy === 'function' |
| && typeof arg.fill === 'function' |
| && typeof arg.readUInt8 === 'function'; |
| } |
| },{}],11:[function(require,module,exports){ |
| (function (process,global){ |
| // Copyright Joyent, Inc. and other Node contributors. |
| // |
| // Permission is hereby granted, free of charge, to any person obtaining a |
| // copy of this software and associated documentation files (the |
| // "Software"), to deal in the Software without restriction, including |
| // without limitation the rights to use, copy, modify, merge, publish, |
| // distribute, sublicense, and/or sell copies of the Software, and to permit |
| // persons to whom the Software is furnished to do so, subject to the |
| // following conditions: |
| // |
| // The above copyright notice and this permission notice shall be included |
| // in all copies or substantial portions of the Software. |
| // |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN |
| // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
| // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
| // USE OR OTHER DEALINGS IN THE SOFTWARE. |
| |
| var formatRegExp = /%[sdj%]/g; |
| exports.format = function(f) { |
| if (!isString(f)) { |
| var objects = []; |
| for (var i = 0; i < arguments.length; i++) { |
| objects.push(inspect(arguments[i])); |
| } |
| return objects.join(' '); |
| } |
| |
| var i = 1; |
| var args = arguments; |
| var len = args.length; |
| var str = String(f).replace(formatRegExp, function(x) { |
| if (x === '%%') return '%'; |
| if (i >= len) return x; |
| switch (x) { |
| case '%s': return String(args[i++]); |
| case '%d': return Number(args[i++]); |
| case '%j': |
| try { |
| return JSON.stringify(args[i++]); |
| } catch (_) { |
| return '[Circular]'; |
| } |
| default: |
| return x; |
| } |
| }); |
| for (var x = args[i]; i < len; x = args[++i]) { |
| if (isNull(x) || !isObject(x)) { |
| str += ' ' + x; |
| } else { |
| str += ' ' + inspect(x); |
| } |
| } |
| return str; |
| }; |
| |
| |
| // Mark that a method should not be used. |
| // Returns a modified function which warns once by default. |
| // If --no-deprecation is set, then it is a no-op. |
| exports.deprecate = function(fn, msg) { |
| // Allow for deprecating things in the process of starting up. |
| if (isUndefined(global.process)) { |
| return function() { |
| return exports.deprecate(fn, msg).apply(this, arguments); |
| }; |
| } |
| |
| if (process.noDeprecation === true) { |
| return fn; |
| } |
| |
| var warned = false; |
| function deprecated() { |
| if (!warned) { |
| if (process.throwDeprecation) { |
| throw new Error(msg); |
| } else if (process.traceDeprecation) { |
| console.trace(msg); |
| } else { |
| console.error(msg); |
| } |
| warned = true; |
| } |
| return fn.apply(this, arguments); |
| } |
| |
| return deprecated; |
| }; |
| |
| |
| var debugs = {}; |
| var debugEnviron; |
| exports.debuglog = function(set) { |
| if (isUndefined(debugEnviron)) |
| debugEnviron = process.env.NODE_DEBUG || ''; |
| set = set.toUpperCase(); |
| if (!debugs[set]) { |
| if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { |
| var pid = process.pid; |
| debugs[set] = function() { |
| var msg = exports.format.apply(exports, arguments); |
| console.error('%s %d: %s', set, pid, msg); |
| }; |
| } else { |
| debugs[set] = function() {}; |
| } |
| } |
| return debugs[set]; |
| }; |
| |
| |
| /** |
| * Echos the value of a value. Trys to print the value out |
| * in the best way possible given the different types. |
| * |
| * @param {Object} obj The object to print out. |
| * @param {Object} opts Optional options object that alters the output. |
| */ |
| /* legacy: obj, showHidden, depth, colors*/ |
| function inspect(obj, opts) { |
| // default options |
| var ctx = { |
| seen: [], |
| stylize: stylizeNoColor |
| }; |
| // legacy... |
| if (arguments.length >= 3) ctx.depth = arguments[2]; |
| if (arguments.length >= 4) ctx.colors = arguments[3]; |
| if (isBoolean(opts)) { |
| // legacy... |
| ctx.showHidden = opts; |
| } else if (opts) { |
| // got an "options" object |
| exports._extend(ctx, opts); |
| } |
| // set default options |
| if (isUndefined(ctx.showHidden)) ctx.showHidden = false; |
| if (isUndefined(ctx.depth)) ctx.depth = 2; |
| if (isUndefined(ctx.colors)) ctx.colors = false; |
| if (isUndefined(ctx.customInspect)) ctx.customInspect = true; |
| if (ctx.colors) ctx.stylize = stylizeWithColor; |
| return formatValue(ctx, obj, ctx.depth); |
| } |
| exports.inspect = inspect; |
| |
| |
| // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics |
| inspect.colors = { |
| 'bold' : [1, 22], |
| 'italic' : [3, 23], |
| 'underline' : [4, 24], |
| 'inverse' : [7, 27], |
| 'white' : [37, 39], |
| 'grey' : [90, 39], |
| 'black' : [30, 39], |
| 'blue' : [34, 39], |
| 'cyan' : [36, 39], |
| 'green' : [32, 39], |
| 'magenta' : [35, 39], |
| 'red' : [31, 39], |
| 'yellow' : [33, 39] |
| }; |
| |
| // Don't use 'blue' not visible on cmd.exe |
| inspect.styles = { |
| 'special': 'cyan', |
| 'number': 'yellow', |
| 'boolean': 'yellow', |
| 'undefined': 'grey', |
| 'null': 'bold', |
| 'string': 'green', |
| 'date': 'magenta', |
| // "name": intentionally not styling |
| 'regexp': 'red' |
| }; |
| |
| |
| function stylizeWithColor(str, styleType) { |
| var style = inspect.styles[styleType]; |
| |
| if (style) { |
| return '\u001b[' + inspect.colors[style][0] + 'm' + str + |
| '\u001b[' + inspect.colors[style][1] + 'm'; |
| } else { |
| return str; |
| } |
| } |
| |
| |
| function stylizeNoColor(str, styleType) { |
| return str; |
| } |
| |
| |
| function arrayToHash(array) { |
| var hash = {}; |
| |
| array.forEach(function(val, idx) { |
| hash[val] = true; |
| }); |
| |
| return hash; |
| } |
| |
| |
| function formatValue(ctx, value, recurseTimes) { |
| // Provide a hook for user-specified inspect functions. |
| // Check that value is an object with an inspect function on it |
| if (ctx.customInspect && |
| value && |
| isFunction(value.inspect) && |
| // Filter out the util module, it's inspect function is special |
| value.inspect !== exports.inspect && |
| // Also filter out any prototype objects using the circular check. |
| !(value.constructor && value.constructor.prototype === value)) { |
| var ret = value.inspect(recurseTimes, ctx); |
| if (!isString(ret)) { |
| ret = formatValue(ctx, ret, recurseTimes); |
| } |
| return ret; |
| } |
| |
| // Primitive types cannot have properties |
| var primitive = formatPrimitive(ctx, value); |
| if (primitive) { |
| return primitive; |
| } |
| |
| // Look up the keys of the object. |
| var keys = Object.keys(value); |
| var visibleKeys = arrayToHash(keys); |
| |
| if (ctx.showHidden) { |
| keys = Object.getOwnPropertyNames(value); |
| } |
| |
| // IE doesn't make error fields non-enumerable |
| // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx |
| if (isError(value) |
| && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { |
| return formatError(value); |
| } |
| |
| // Some type of object without properties can be shortcutted. |
| if (keys.length === 0) { |
| if (isFunction(value)) { |
| var name = value.name ? ': ' + value.name : ''; |
| return ctx.stylize('[Function' + name + ']', 'special'); |
| } |
| if (isRegExp(value)) { |
| return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); |
| } |
| if (isDate(value)) { |
| return ctx.stylize(Date.prototype.toString.call(value), 'date'); |
| } |
| if (isError(value)) { |
| return formatError(value); |
| } |
| } |
| |
| var base = '', array = false, braces = ['{', '}']; |
| |
| // Make Array say that they are Array |
| if (isArray(value)) { |
| array = true; |
| braces = ['[', ']']; |
| } |
| |
| // Make functions say that they are functions |
| if (isFunction(value)) { |
| var n = value.name ? ': ' + value.name : ''; |
| base = ' [Function' + n + ']'; |
| } |
| |
| // Make RegExps say that they are RegExps |
| if (isRegExp(value)) { |
| base = ' ' + RegExp.prototype.toString.call(value); |
| } |
| |
| // Make dates with properties first say the date |
| if (isDate(value)) { |
| base = ' ' + Date.prototype.toUTCString.call(value); |
| } |
| |
| // Make error with message first say the error |
| if (isError(value)) { |
| base = ' ' + formatError(value); |
| } |
| |
| if (keys.length === 0 && (!array || value.length == 0)) { |
| return braces[0] + base + braces[1]; |
| } |
| |
| if (recurseTimes < 0) { |
| if (isRegExp(value)) { |
| return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); |
| } else { |
| return ctx.stylize('[Object]', 'special'); |
| } |
| } |
| |
| ctx.seen.push(value); |
| |
| var output; |
| if (array) { |
| output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); |
| } else { |
| output = keys.map(function(key) { |
| return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); |
| }); |
| } |
| |
| ctx.seen.pop(); |
| |
| return reduceToSingleString(output, base, braces); |
| } |
| |
| |
| function formatPrimitive(ctx, value) { |
| if (isUndefined(value)) |
| return ctx.stylize('undefined', 'undefined'); |
| if (isString(value)) { |
| var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') |
| .replace(/'/g, "\\'") |
| .replace(/\\"/g, '"') + '\''; |
| return ctx.stylize(simple, 'string'); |
| } |
| if (isNumber(value)) |
| return ctx.stylize('' + value, 'number'); |
| if (isBoolean(value)) |
| return ctx.stylize('' + value, 'boolean'); |
| // For some reason typeof null is "object", so special case here. |
| if (isNull(value)) |
| return ctx.stylize('null', 'null'); |
| } |
| |
| |
| function formatError(value) { |
| return '[' + Error.prototype.toString.call(value) + ']'; |
| } |
| |
| |
| function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { |
| var output = []; |
| for (var i = 0, l = value.length; i < l; ++i) { |
| if (hasOwnProperty(value, String(i))) { |
| output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, |
| String(i), true)); |
| } else { |
| output.push(''); |
| } |
| } |
| keys.forEach(function(key) { |
| if (!key.match(/^\d+$/)) { |
| output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, |
| key, true)); |
| } |
| }); |
| return output; |
| } |
| |
| |
| function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { |
| var name, str, desc; |
| desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; |
| if (desc.get) { |
| if (desc.set) { |
| str = ctx.stylize('[Getter/Setter]', 'special'); |
| } else { |
| str = ctx.stylize('[Getter]', 'special'); |
| } |
| } else { |
| if (desc.set) { |
| str = ctx.stylize('[Setter]', 'special'); |
| } |
| } |
| if (!hasOwnProperty(visibleKeys, key)) { |
| name = '[' + key + ']'; |
| } |
| if (!str) { |
| if (ctx.seen.indexOf(desc.value) < 0) { |
| if (isNull(recurseTimes)) { |
| str = formatValue(ctx, desc.value, null); |
| } else { |
| str = formatValue(ctx, desc.value, recurseTimes - 1); |
| } |
| if (str.indexOf('\n') > -1) { |
| if (array) { |
| str = str.split('\n').map(function(line) { |
| return ' ' + line; |
| }).join('\n').substr(2); |
| } else { |
| str = '\n' + str.split('\n').map(function(line) { |
| return ' ' + line; |
| }).join('\n'); |
| } |
| } |
| } else { |
| str = ctx.stylize('[Circular]', 'special'); |
| } |
| } |
| if (isUndefined(name)) { |
| if (array && key.match(/^\d+$/)) { |
| return str; |
| } |
| name = JSON.stringify('' + key); |
| if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { |
| name = name.substr(1, name.length - 2); |
| name = ctx.stylize(name, 'name'); |
| } else { |
| name = name.replace(/'/g, "\\'") |
| .replace(/\\"/g, '"') |
| .replace(/(^"|"$)/g, "'"); |
| name = ctx.stylize(name, 'string'); |
| } |
| } |
| |
| return name + ': ' + str; |
| } |
| |
| |
| function reduceToSingleString(output, base, braces) { |
| var numLinesEst = 0; |
| var length = output.reduce(function(prev, cur) { |
| numLinesEst++; |
| if (cur.indexOf('\n') >= 0) numLinesEst++; |
| return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; |
| }, 0); |
| |
| if (length > 60) { |
| return braces[0] + |
| (base === '' ? '' : base + '\n ') + |
| ' ' + |
| output.join(',\n ') + |
| ' ' + |
| braces[1]; |
| } |
| |
| return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; |
| } |
| |
| |
| // NOTE: These type checking functions intentionally don't use `instanceof` |
| // because it is fragile and can be easily faked with `Object.create()`. |
| function isArray(ar) { |
| return Array.isArray(ar); |
| } |
| exports.isArray = isArray; |
| |
| function isBoolean(arg) { |
| return typeof arg === 'boolean'; |
| } |
| exports.isBoolean = isBoolean; |
| |
| function isNull(arg) { |
| return arg === null; |
| } |
| exports.isNull = isNull; |
| |
| function isNullOrUndefined(arg) { |
| return arg == null; |
| } |
| exports.isNullOrUndefined = isNullOrUndefined; |
| |
| function isNumber(arg) { |
| return typeof arg === 'number'; |
| } |
| exports.isNumber = isNumber; |
| |
| function isString(arg) { |
| return typeof arg === 'string'; |
| } |
| exports.isString = isString; |
| |
| function isSymbol(arg) { |
| return typeof arg === 'symbol'; |
| } |
| exports.isSymbol = isSymbol; |
| |
| function isUndefined(arg) { |
| return arg === void 0; |
| } |
| exports.isUndefined = isUndefined; |
| |
| function isRegExp(re) { |
| return isObject(re) && objectToString(re) === '[object RegExp]'; |
| } |
| exports.isRegExp = isRegExp; |
| |
| function isObject(arg) { |
| return typeof arg === 'object' && arg !== null; |
| } |
| exports.isObject = isObject; |
| |
| function isDate(d) { |
| return isObject(d) && objectToString(d) === '[object Date]'; |
| } |
| exports.isDate = isDate; |
| |
| function isError(e) { |
| return isObject(e) && |
| (objectToString(e) === '[object Error]' || e instanceof Error); |
| } |
| exports.isError = isError; |
| |
| function isFunction(arg) { |
| return typeof arg === 'function'; |
| } |
| exports.isFunction = isFunction; |
| |
| function isPrimitive(arg) { |
| return arg === null || |
| typeof arg === 'boolean' || |
| typeof arg === 'number' || |
| typeof arg === 'string' || |
| typeof arg === 'symbol' || // ES6 symbol |
| typeof arg === 'undefined'; |
| } |
| exports.isPrimitive = isPrimitive; |
| |
| exports.isBuffer = require('./support/isBuffer'); |
| |
| function objectToString(o) { |
| return Object.prototype.toString.call(o); |
| } |
| |
| |
| function pad(n) { |
| return n < 10 ? '0' + n.toString(10) : n.toString(10); |
| } |
| |
| |
| var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', |
| 'Oct', 'Nov', 'Dec']; |
| |
| // 26 Feb 16:19:34 |
| function timestamp() { |
| var d = new Date(); |
| var time = [pad(d.getHours()), |
| pad(d.getMinutes()), |
| pad(d.getSeconds())].join(':'); |
| return [d.getDate(), months[d.getMonth()], time].join(' '); |
| } |
| |
| |
| // log is just a thin wrapper to console.log that prepends a timestamp |
| exports.log = function() { |
| console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); |
| }; |
| |
| |
| /** |
| * Inherit the prototype methods from one constructor into another. |
| * |
| * The Function.prototype.inherits from lang.js rewritten as a standalone |
| * function (not on Function.prototype). NOTE: If this file is to be loaded |
| * during bootstrapping this function needs to be rewritten using some native |
| * functions as prototype setup using normal JavaScript does not work as |
| * expected during bootstrapping (see mirror.js in r114903). |
| * |
| * @param {function} ctor Constructor function which needs to inherit the |
| * prototype. |
| * @param {function} superCtor Constructor function to inherit prototype from. |
| */ |
| exports.inherits = require('inherits'); |
| |
| exports._extend = function(origin, add) { |
| // Don't do anything if add isn't an object |
| if (!add || !isObject(add)) return origin; |
| |
| var keys = Object.keys(add); |
| var i = keys.length; |
| while (i--) { |
| origin[keys[i]] = add[keys[i]]; |
| } |
| return origin; |
| }; |
| |
| function hasOwnProperty(obj, prop) { |
| return Object.prototype.hasOwnProperty.call(obj, prop); |
| } |
| |
| }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) |
| },{"./support/isBuffer":10,"_process":14,"inherits":9}],12:[function(require,module,exports){ |
| |
| },{}],13:[function(require,module,exports){ |
| (function (process){ |
| // .dirname, .basename, and .extname methods are extracted from Node.js v8.11.1, |
| // backported and transplited with Babel, with backwards-compat fixes |
| |
| // Copyright Joyent, Inc. and other Node contributors. |
| // |
| // Permission is hereby granted, free of charge, to any person obtaining a |
| // copy of this software and associated documentation files (the |
| // "Software"), to deal in the Software without restriction, including |
| // without limitation the rights to use, copy, modify, merge, publish, |
| // distribute, sublicense, and/or sell copies of the Software, and to permit |
| // persons to whom the Software is furnished to do so, subject to the |
| // following conditions: |
| // |
| // The above copyright notice and this permission notice shall be included |
| // in all copies or substantial portions of the Software. |
| // |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN |
| // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
| // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
| // USE OR OTHER DEALINGS IN THE SOFTWARE. |
| |
| // resolves . and .. elements in a path array with directory names there |
| // must be no slashes, empty elements, or device names (c:\) in the array |
| // (so also no leading and trailing slashes - it does not distinguish |
| // relative and absolute paths) |
| function normalizeArray(parts, allowAboveRoot) { |
| // if the path tries to go above the root, `up` ends up > 0 |
| var up = 0; |
| for (var i = parts.length - 1; i >= 0; i--) { |
| var last = parts[i]; |
| if (last === '.') { |
| parts.splice(i, 1); |
| } else if (last === '..') { |
| parts.splice(i, 1); |
| up++; |
| } else if (up) { |
| parts.splice(i, 1); |
| up--; |
| } |
| } |
| |
| // if the path is allowed to go above the root, restore leading ..s |
| if (allowAboveRoot) { |
| for (; up--; up) { |
| parts.unshift('..'); |
| } |
| } |
| |
| return parts; |
| } |
| |
| // path.resolve([from ...], to) |
| // posix version |
| exports.resolve = function() { |
| var resolvedPath = '', |
| resolvedAbsolute = false; |
| |
| for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { |
| var path = (i >= 0) ? arguments[i] : process.cwd(); |
| |
| // Skip empty and invalid entries |
| if (typeof path !== 'string') { |
| throw new TypeError('Arguments to path.resolve must be strings'); |
| } else if (!path) { |
| continue; |
| } |
| |
| resolvedPath = path + '/' + resolvedPath; |
| resolvedAbsolute = path.charAt(0) === '/'; |
| } |
| |
| // At this point the path should be resolved to a full absolute path, but |
| // handle relative paths to be safe (might happen when process.cwd() fails) |
| |
| // Normalize the path |
| resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { |
| return !!p; |
| }), !resolvedAbsolute).join('/'); |
| |
| return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; |
| }; |
| |
| // path.normalize(path) |
| // posix version |
| exports.normalize = function(path) { |
| var isAbsolute = exports.isAbsolute(path), |
| trailingSlash = substr(path, -1) === '/'; |
| |
| // Normalize the path |
| path = normalizeArray(filter(path.split('/'), function(p) { |
| return !!p; |
| }), !isAbsolute).join('/'); |
| |
| if (!path && !isAbsolute) { |
| path = '.'; |
| } |
| if (path && trailingSlash) { |
| path += '/'; |
| } |
| |
| return (isAbsolute ? '/' : '') + path; |
| }; |
| |
| // posix version |
| exports.isAbsolute = function(path) { |
| return path.charAt(0) === '/'; |
| }; |
| |
| // posix version |
| exports.join = function() { |
| var paths = Array.prototype.slice.call(arguments, 0); |
| return exports.normalize(filter(paths, function(p, index) { |
| if (typeof p !== 'string') { |
| throw new TypeError('Arguments to path.join must be strings'); |
| } |
| return p; |
| }).join('/')); |
| }; |
| |
| |
| // path.relative(from, to) |
| // posix version |
| exports.relative = function(from, to) { |
| from = exports.resolve(from).substr(1); |
| to = exports.resolve(to).substr(1); |
| |
| function trim(arr) { |
| var start = 0; |
| for (; start < arr.length; start++) { |
| if (arr[start] !== '') break; |
| } |
| |
| var end = arr.length - 1; |
| for (; end >= 0; end--) { |
| if (arr[end] !== '') break; |
| } |
| |
| if (start > end) return []; |
| return arr.slice(start, end - start + 1); |
| } |
| |
| var fromParts = trim(from.split('/')); |
| var toParts = trim(to.split('/')); |
| |
| var length = Math.min(fromParts.length, toParts.length); |
| var samePartsLength = length; |
| for (var i = 0; i < length; i++) { |
| if (fromParts[i] !== toParts[i]) { |
| samePartsLength = i; |
| break; |
| } |
| } |
| |
| var outputParts = []; |
| for (var i = samePartsLength; i < fromParts.length; i++) { |
| outputParts.push('..'); |
| } |
| |
| outputParts = outputParts.concat(toParts.slice(samePartsLength)); |
| |
| return outputParts.join('/'); |
| }; |
| |
| exports.sep = '/'; |
| exports.delimiter = ':'; |
| |
| exports.dirname = function (path) { |
| if (typeof path !== 'string') path = path + ''; |
| if (path.length === 0) return '.'; |
| var code = path.charCodeAt(0); |
| var hasRoot = code === 47 /*/*/; |
| var end = -1; |
| var matchedSlash = true; |
| for (var i = path.length - 1; i >= 1; --i) { |
| code = path.charCodeAt(i); |
| if (code === 47 /*/*/) { |
| if (!matchedSlash) { |
| end = i; |
| break; |
| } |
| } else { |
| // We saw the first non-path separator |
| matchedSlash = false; |
| } |
| } |
| |
| if (end === -1) return hasRoot ? '/' : '.'; |
| if (hasRoot && end === 1) { |
| // return '//'; |
| // Backwards-compat fix: |
| return '/'; |
| } |
| return path.slice(0, end); |
| }; |
| |
| function basename(path) { |
| if (typeof path !== 'string') path = path + ''; |
| |
| var start = 0; |
| var end = -1; |
| var matchedSlash = true; |
| var i; |
| |
| for (i = path.length - 1; i >= 0; --i) { |
| if (path.charCodeAt(i) === 47 /*/*/) { |
| // If we reached a path separator that was not part of a set of path |
| // separators at the end of the string, stop now |
| if (!matchedSlash) { |
| start = i + 1; |
| break; |
| } |
| } else if (end === -1) { |
| // We saw the first non-path separator, mark this as the end of our |
| // path component |
| matchedSlash = false; |
| end = i + 1; |
| } |
| } |
| |
| if (end === -1) return ''; |
| return path.slice(start, end); |
| } |
| |
| // Uses a mixed approach for backwards-compatibility, as ext behavior changed |
| // in new Node.js versions, so only basename() above is backported here |
| exports.basename = function (path, ext) { |
| var f = basename(path); |
| if (ext && f.substr(-1 * ext.length) === ext) { |
| f = f.substr(0, f.length - ext.length); |
| } |
| return f; |
| }; |
| |
| exports.extname = function (path) { |
| if (typeof path !== 'string') path = path + ''; |
| var startDot = -1; |
| var startPart = 0; |
| var end = -1; |
| var matchedSlash = true; |
| // Track the state of characters (if any) we see before our first dot and |
| // after any path separator we find |
| var preDotState = 0; |
| for (var i = path.length - 1; i >= 0; --i) { |
| var code = path.charCodeAt(i); |
| if (code === 47 /*/*/) { |
| // If we reached a path separator that was not part of a set of path |
| // separators at the end of the string, stop now |
| if (!matchedSlash) { |
| startPart = i + 1; |
| break; |
| } |
| continue; |
| } |
| if (end === -1) { |
| // We saw the first non-path separator, mark this as the end of our |
| // extension |
| matchedSlash = false; |
| end = i + 1; |
| } |
| if (code === 46 /*.*/) { |
| // If this is our first dot, mark it as the start of our extension |
| if (startDot === -1) |
| startDot = i; |
| else if (preDotState !== 1) |
| preDotState = 1; |
| } else if (startDot !== -1) { |
| // We saw a non-dot and non-path separator before our dot, so we should |
| // have a good chance at having a non-empty extension |
| preDotState = -1; |
| } |
| } |
| |
| if (startDot === -1 || end === -1 || |
| // We saw a non-dot character immediately before the dot |
| preDotState === 0 || |
| // The (right-most) trimmed path component is exactly '..' |
| preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) { |
| return ''; |
| } |
| return path.slice(startDot, end); |
| }; |
| |
| function filter (xs, f) { |
| if (xs.filter) return xs.filter(f); |
| var res = []; |
| for (var i = 0; i < xs.length; i++) { |
| if (f(xs[i], i, xs)) res.push(xs[i]); |
| } |
| return res; |
| } |
| |
| // String.prototype.substr - negative index don't work in IE8 |
| var substr = 'ab'.substr(-1) === 'b' |
| ? function (str, start, len) { return str.substr(start, len) } |
| : function (str, start, len) { |
| if (start < 0) start = str.length + start; |
| return str.substr(start, len); |
| } |
| ; |
| |
| }).call(this,require('_process')) |
| },{"_process":14}],14:[function(require,module,exports){ |
| // shim for using process in browser |
| var process = module.exports = {}; |
| |
| // cached from whatever global is present so that test runners that stub it |
| // don't break things. But we need to wrap it in a try catch in case it is |
| // wrapped in strict mode code which doesn't define any globals. It's inside a |
| // function because try/catches deoptimize in certain engines. |
| |
| var cachedSetTimeout; |
| var cachedClearTimeout; |
| |
| function defaultSetTimout() { |
| throw new Error('setTimeout has not been defined'); |
| } |
| function defaultClearTimeout () { |
| throw new Error('clearTimeout has not been defined'); |
| } |
| (function () { |
| try { |
| if (typeof setTimeout === 'function') { |
| cachedSetTimeout = setTimeout; |
| } else { |
| cachedSetTimeout = defaultSetTimout; |
| } |
| } catch (e) { |
| cachedSetTimeout = defaultSetTimout; |
| } |
| try { |
| if (typeof clearTimeout === 'function') { |
| cachedClearTimeout = clearTimeout; |
| } else { |
| cachedClearTimeout = defaultClearTimeout; |
| } |
| } catch (e) { |
| cachedClearTimeout = defaultClearTimeout; |
| } |
| } ()) |
| function runTimeout(fun) { |
| if (cachedSetTimeout === setTimeout) { |
| //normal enviroments in sane situations |
| return setTimeout(fun, 0); |
| } |
| // if setTimeout wasn't available but was latter defined |
| if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { |
| cachedSetTimeout = setTimeout; |
| return setTimeout(fun, 0); |
| } |
| try { |
| // when when somebody has screwed with setTimeout but no I.E. maddness |
| return cachedSetTimeout(fun, 0); |
| } catch(e){ |
| try { |
| // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally |
| return cachedSetTimeout.call(null, fun, 0); |
| } catch(e){ |
| // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error |
| return cachedSetTimeout.call(this, fun, 0); |
| } |
| } |
| |
| |
| } |
| function runClearTimeout(marker) { |
| if (cachedClearTimeout === clearTimeout) { |
| //normal enviroments in sane situations |
| return clearTimeout(marker); |
| } |
| // if clearTimeout wasn't available but was latter defined |
| if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { |
| cachedClearTimeout = clearTimeout; |
| return clearTimeout(marker); |
| } |
| try { |
| // when when somebody has screwed with setTimeout but no I.E. maddness |
| return cachedClearTimeout(marker); |
| } catch (e){ |
| try { |
| // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally |
| return cachedClearTimeout.call(null, marker); |
| } catch (e){ |
| // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. |
| // Some versions of I.E. have different rules for clearTimeout vs setTimeout |
| return cachedClearTimeout.call(this, marker); |
| } |
| } |
| |
| |
| |
| } |
| var queue = []; |
| var draining = false; |
| var currentQueue; |
| var queueIndex = -1; |
| |
| function cleanUpNextTick() { |
| if (!draining || !currentQueue) { |
| return; |
| } |
| draining = false; |
| if (currentQueue.length) { |
| queue = currentQueue.concat(queue); |
| } else { |
| queueIndex = -1; |
| } |
| if (queue.length) { |
| drainQueue(); |
| } |
| } |
| |
| function drainQueue() { |
| if (draining) { |
| return; |
| } |
| var timeout = runTimeout(cleanUpNextTick); |
| draining = true; |
| |
| var len = queue.length; |
| while(len) { |
| currentQueue = queue; |
| queue = []; |
| while (++queueIndex < len) { |
| if (currentQueue) { |
| currentQueue[queueIndex].run(); |
| } |
| } |
| queueIndex = -1; |
| len = queue.length; |
| } |
| currentQueue = null; |
| draining = false; |
| runClearTimeout(timeout); |
| } |
| |
| process.nextTick = function (fun) { |
| var args = new Array(arguments.length - 1); |
| if (arguments.length > 1) { |
| for (var i = 1; i < arguments.length; i++) { |
| args[i - 1] = arguments[i]; |
| } |
| } |
| queue.push(new Item(fun, args)); |
| if (queue.length === 1 && !draining) { |
| runTimeout(drainQueue); |
| } |
| }; |
| |
| // v8 likes predictible objects |
| function Item(fun, array) { |
| this.fun = fun; |
| this.array = array; |
| } |
| Item.prototype.run = function () { |
| this.fun.apply(null, this.array); |
| }; |
| process.title = 'browser'; |
| process.browser = true; |
| process.env = {}; |
| process.argv = []; |
| process.version = ''; // empty string to avoid regexp issues |
| process.versions = {}; |
| |
| function noop() {} |
| |
| process.on = noop; |
| process.addListener = noop; |
| process.once = noop; |
| process.off = noop; |
| process.removeListener = noop; |
| process.removeAllListeners = noop; |
| process.emit = noop; |
| process.prependListener = noop; |
| process.prependOnceListener = noop; |
| |
| process.listeners = function (name) { return [] } |
| |
| process.binding = function (name) { |
| throw new Error('process.binding is not supported'); |
| }; |
| |
| process.cwd = function () { return '/' }; |
| process.chdir = function (dir) { |
| throw new Error('process.chdir is not supported'); |
| }; |
| process.umask = function() { return 0; }; |
| |
| },{}],15:[function(require,module,exports){ |
| var unparse = require('escodegen').generate; |
| |
| module.exports = function (ast, vars) { |
| if (!vars) vars = {}; |
| var FAIL = {}; |
| |
| var result = (function walk (node, scopeVars) { |
| if (node.type === 'Literal') { |
| return node.value; |
| } |
| else if (node.type === 'UnaryExpression'){ |
| var val = walk(node.argument) |
| if (node.operator === '+') return +val |
| if (node.operator === '-') return -val |
| if (node.operator === '~') return ~val |
| if (node.operator === '!') return !val |
| return FAIL |
| } |
| else if (node.type === 'ArrayExpression') { |
| var xs = []; |
| for (var i = 0, l = node.elements.length; i < l; i++) { |
| var x = walk(node.elements[i]); |
| if (x === FAIL) return FAIL; |
| xs.push(x); |
| } |
| return xs; |
| } |
| else if (node.type === 'ObjectExpression') { |
| var obj = {}; |
| for (var i = 0; i < node.properties.length; i++) { |
| var prop = node.properties[i]; |
| var value = prop.value === null |
| ? prop.value |
| : walk(prop.value) |
| ; |
| if (value === FAIL) return FAIL; |
| obj[prop.key.value || prop.key.name] = value; |
| } |
| return obj; |
| } |
| else if (node.type === 'BinaryExpression' || |
| node.type === 'LogicalExpression') { |
| var l = walk(node.left); |
| if (l === FAIL) return FAIL; |
| var r = walk(node.right); |
| if (r === FAIL) return FAIL; |
| |
| var op = node.operator; |
| if (op === '==') return l == r; |
| if (op === '===') return l === r; |
| if (op === '!=') return l != r; |
| if (op === '!==') return l !== r; |
| if (op === '+') return l + r; |
| if (op === '-') return l - r; |
| if (op === '*') return l * r; |
| if (op === '/') return l / r; |
| if (op === '%') return l % r; |
| if (op === '<') return l < r; |
| if (op === '<=') return l <= r; |
| if (op === '>') return l > r; |
| if (op === '>=') return l >= r; |
| if (op === '|') return l | r; |
| if (op === '&') return l & r; |
| if (op === '^') return l ^ r; |
| if (op === '&&') return l && r; |
| if (op === '||') return l || r; |
| |
| return FAIL; |
| } |
| else if (node.type === 'Identifier') { |
| if ({}.hasOwnProperty.call(vars, node.name)) { |
| return vars[node.name]; |
| } |
| else return FAIL; |
| } |
| else if (node.type === 'ThisExpression') { |
| if ({}.hasOwnProperty.call(vars, 'this')) { |
| return vars['this']; |
| } |
| else return FAIL; |
| } |
| else if (node.type === 'CallExpression') { |
| var callee = walk(node.callee); |
| if (callee === FAIL) return FAIL; |
| if (typeof callee !== 'function') return FAIL; |
| |
| var ctx = node.callee.object ? walk(node.callee.object) : FAIL; |
| if (ctx === FAIL) ctx = null; |
| |
| var args = []; |
| for (var i = 0, l = node.arguments.length; i < l; i++) { |
| var x = walk(node.arguments[i]); |
| if (x === FAIL) return FAIL; |
| args.push(x); |
| } |
| return callee.apply(ctx, args); |
| } |
| else if (node.type === 'MemberExpression') { |
| var obj = walk(node.object); |
| // do not allow access to methods on Function |
| if((obj === FAIL) || (typeof obj == 'function')){ |
| return FAIL; |
| } |
| if (node.property.type === 'Identifier') { |
| return obj[node.property.name]; |
| } |
| var prop = walk(node.property); |
| if (prop === FAIL) return FAIL; |
| return obj[prop]; |
| } |
| else if (node.type === 'ConditionalExpression') { |
| var val = walk(node.test) |
| if (val === FAIL) return FAIL; |
| return val ? walk(node.consequent) : walk(node.alternate) |
| } |
| else if (node.type === 'ExpressionStatement') { |
| var val = walk(node.expression) |
| if (val === FAIL) return FAIL; |
| return val; |
| } |
| else if (node.type === 'ReturnStatement') { |
| return walk(node.argument) |
| } |
| else if (node.type === 'FunctionExpression') { |
| |
| var bodies = node.body.body; |
| |
| // Create a "scope" for our arguments |
| var oldVars = {}; |
| Object.keys(vars).forEach(function(element){ |
| oldVars[element] = vars[element]; |
| }) |
| |
| for(var i=0; i<node.params.length; i++){ |
| var key = node.params[i]; |
| if(key.type == 'Identifier'){ |
| vars[key.name] = null; |
| } |
| else return FAIL; |
| } |
| for(var i in bodies){ |
| if(walk(bodies[i]) === FAIL){ |
| return FAIL; |
| } |
| } |
| // restore the vars and scope after we walk |
| vars = oldVars; |
| |
| var keys = Object.keys(vars); |
| var vals = keys.map(function(key) { |
| return vars[key]; |
| }); |
| return Function(keys.join(', '), 'return ' + unparse(node)).apply(null, vals); |
| } |
| else if (node.type === 'TemplateLiteral') { |
| var str = ''; |
| for (var i = 0; i < node.expressions.length; i++) { |
| str += walk(node.quasis[i]); |
| str += walk(node.expressions[i]); |
| } |
| str += walk(node.quasis[i]); |
| return str; |
| } |
| else if (node.type === 'TaggedTemplateExpression') { |
| var tag = walk(node.tag); |
| var quasi = node.quasi; |
| var strings = quasi.quasis.map(walk); |
| var values = quasi.expressions.map(walk); |
| return tag.apply(null, [strings].concat(values)); |
| } |
| else if (node.type === 'TemplateElement') { |
| return node.value.cooked; |
| } |
| else return FAIL; |
| })(ast); |
| |
| return result === FAIL ? undefined : result; |
| }; |
| |
| },{"escodegen":12}],"jsonpath":[function(require,module,exports){ |
| module.exports = require('./lib/index'); |
| |
| },{"./lib/index":5}]},{},["jsonpath"])("jsonpath") |
| }); |