--- /dev/null
+/**
+ * JSXTransformer v0.4.0
+ */
+(function(e){if("function"==typeof bootstrap)bootstrap("jsxtransformer",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeJSXTransformer=e}else"undefined"!=typeof window?window.JSXTransformer=e():global.JSXTransformer=e()})(function(){var define,ses,bootstrap,module,exports;
+return (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
+var Base62 = (function (my) {
+ my.chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
+
+ my.encode = function(i){
+ if (i === 0) {return '0'}
+ var s = ''
+ while (i > 0) {
+ s = this.chars[i % 62] + s
+ i = Math.floor(i/62)
+ }
+ return s
+ };
+ my.decode = function(a,b,c,d){
+ for (
+ b = c = (
+ a === (/\W|_|^$/.test(a += "") || a)
+ ) - 1;
+ d = a.charCodeAt(c++);
+ )
+ b = b * 62 + d - [, 48, 29, 87][d >> 5];
+ return b
+ };
+
+ return my;
+}({}));
+
+module.exports = Base62
+},{}],2:[function(require,module,exports){
+(function(process){function filter (xs, fn) {
+ var res = [];
+ for (var i = 0; i < xs.length; i++) {
+ if (fn(xs[i], i, xs)) res.push(xs[i]);
+ }
+ return res;
+}
+
+// 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; 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;
+}
+
+// Regex to split a filename into [*, dir, basename, ext]
+// posix version
+var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;
+
+// path.resolve([from ...], to)
+// posix version
+exports.resolve = function() {
+var resolvedPath = '',
+ resolvedAbsolute = false;
+
+for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
+ var path = (i >= 0)
+ ? arguments[i]
+ : process.cwd();
+
+ // Skip empty and invalid entries
+ if (typeof path !== 'string' || !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 = path.charAt(0) === '/',
+ trailingSlash = path.slice(-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.join = function() {
+ var paths = Array.prototype.slice.call(arguments, 0);
+ return exports.normalize(filter(paths, function(p, index) {
+ return p && typeof p === 'string';
+ }).join('/'));
+};
+
+
+exports.dirname = function(path) {
+ var dir = splitPathRe.exec(path)[1] || '';
+ var isWindows = false;
+ if (!dir) {
+ // No dirname
+ return '.';
+ } else if (dir.length === 1 ||
+ (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
+ // It is just a slash or a drive letter with a slash
+ return dir;
+ } else {
+ // It is a full dirname, strip trailing slash
+ return dir.substring(0, dir.length - 1);
+ }
+};
+
+
+exports.basename = function(path, ext) {
+ var f = splitPathRe.exec(path)[2] || '';
+ // TODO: make this comparison case-insensitive on windows?
+ if (ext && f.substr(-1 * ext.length) === ext) {
+ f = f.substr(0, f.length - ext.length);
+ }
+ return f;
+};
+
+
+exports.extname = function(path) {
+ return splitPathRe.exec(path)[3] || '';
+};
+
+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('/');
+};
+
+})(require("__browserify_process"))
+},{"__browserify_process":3}],3:[function(require,module,exports){
+// shim for using process in browser
+
+var process = module.exports = {};
+
+process.nextTick = (function () {
+ var canSetImmediate = typeof window !== 'undefined'
+ && window.setImmediate;
+ var canPost = typeof window !== 'undefined'
+ && window.postMessage && window.addEventListener
+ ;
+
+ if (canSetImmediate) {
+ return function (f) { return window.setImmediate(f) };
+ }
+
+ if (canPost) {
+ var queue = [];
+ window.addEventListener('message', function (ev) {
+ if (ev.source === window && ev.data === 'process-tick') {
+ ev.stopPropagation();
+ if (queue.length > 0) {
+ var fn = queue.shift();
+ fn();
+ }
+ }
+ }, true);
+
+ return function nextTick(fn) {
+ queue.push(fn);
+ window.postMessage('process-tick', '*');
+ };
+ }
+
+ return function nextTick(fn) {
+ setTimeout(fn, 0);
+ };
+})();
+
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+}
+
+// TODO(shtylman)
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+
+},{}],4:[function(require,module,exports){
+(function(){/*
+ Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
+ 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,
+throwError: true, generateStatement: true, peek: true,
+parseAssignmentExpression: true, parseBlock: true,
+parseClassExpression: true, parseClassDeclaration: true, parseExpression: true,
+parseForStatement: true,
+parseFunctionDeclaration: true, parseFunctionExpression: true,
+parseFunctionSourceElements: true, parseVariableIdentifier: true,
+parseImportSpecifier: true,
+parseLeftHandSideExpression: true, parseParams: true, validateParam: true,
+parseSpreadOrAssignmentExpression: true,
+parseStatement: true, parseSourceElement: true, parseModuleBlock: true, parseConciseBody: true,
+advanceXJSChild: true, isXJSIdentifierStart: true, isXJSIdentifierPart: true,
+scanXJSStringLiteral: true, scanXJSIdentifier: true,
+parseXJSAttributeValue: true, parseXJSChild: true, parseXJSElement: true, parseXJSExpressionContainer: true, parseXJSEmptyExpression: true,
+parseYieldExpression: true
+*/
+
+(function (root, factory) {
+ 'use strict';
+
+ // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
+ // Rhino, and plain browser loading.
+ 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,
+ XHTMLEntities,
+ ClassPropertyType,
+ 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,
+ Template: 10,
+ XJSIdentifier: 11,
+ XJSText: 12
+ };
+
+ 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.XJSIdentifier] = 'XJSIdentifier';
+ TokenName[Token.XJSText] = 'XJSText';
+ 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 = {
+ ArrayExpression: 'ArrayExpression',
+ ArrayPattern: 'ArrayPattern',
+ ArrowFunctionExpression: 'ArrowFunctionExpression',
+ AssignmentExpression: 'AssignmentExpression',
+ BinaryExpression: 'BinaryExpression',
+ BlockStatement: 'BlockStatement',
+ BreakStatement: 'BreakStatement',
+ CallExpression: 'CallExpression',
+ CatchClause: 'CatchClause',
+ ClassBody: 'ClassBody',
+ ClassDeclaration: 'ClassDeclaration',
+ ClassExpression: 'ClassExpression',
+ ClassHeritage: 'ClassHeritage',
+ ComprehensionBlock: 'ComprehensionBlock',
+ ComprehensionExpression: 'ComprehensionExpression',
+ ConditionalExpression: 'ConditionalExpression',
+ ContinueStatement: 'ContinueStatement',
+ DebuggerStatement: 'DebuggerStatement',
+ DoWhileStatement: 'DoWhileStatement',
+ EmptyStatement: 'EmptyStatement',
+ ExportDeclaration: 'ExportDeclaration',
+ ExportSpecifier: 'ExportSpecifier',
+ ExportSpecifierSet: 'ExportSpecifierSet',
+ ExpressionStatement: 'ExpressionStatement',
+ ForInStatement: 'ForInStatement',
+ ForOfStatement: 'ForOfStatement',
+ ForStatement: 'ForStatement',
+ FunctionDeclaration: 'FunctionDeclaration',
+ FunctionExpression: 'FunctionExpression',
+ Glob: 'Glob',
+ Identifier: 'Identifier',
+ IfStatement: 'IfStatement',
+ ImportDeclaration: 'ImportDeclaration',
+ ImportSpecifier: 'ImportSpecifier',
+ LabeledStatement: 'LabeledStatement',
+ Literal: 'Literal',
+ LogicalExpression: 'LogicalExpression',
+ MemberExpression: 'MemberExpression',
+ MethodDefinition: 'MethodDefinition',
+ ModuleDeclaration: 'ModuleDeclaration',
+ NewExpression: 'NewExpression',
+ ObjectExpression: 'ObjectExpression',
+ ObjectPattern: 'ObjectPattern',
+ Path: 'Path',
+ Program: 'Program',
+ Property: 'Property',
+ ReturnStatement: 'ReturnStatement',
+ SequenceExpression: 'SequenceExpression',
+ SpreadElement: 'SpreadElement',
+ SwitchCase: 'SwitchCase',
+ SwitchStatement: 'SwitchStatement',
+ TaggedTemplateExpression: 'TaggedTemplateExpression',
+ TemplateElement: 'TemplateElement',
+ TemplateLiteral: 'TemplateLiteral',
+ ThisExpression: 'ThisExpression',
+ ThrowStatement: 'ThrowStatement',
+ TryStatement: 'TryStatement',
+ UnaryExpression: 'UnaryExpression',
+ UpdateExpression: 'UpdateExpression',
+ VariableDeclaration: 'VariableDeclaration',
+ VariableDeclarator: 'VariableDeclarator',
+ WhileStatement: 'WhileStatement',
+ WithStatement: 'WithStatement',
+ XJSIdentifier: 'XJSIdentifier',
+ XJSEmptyExpression: 'XJSEmptyExpression',
+ XJSExpressionContainer: 'XJSExpressionContainer',
+ XJSElement: 'XJSElement',
+ XJSClosingElement: 'XJSClosingElement',
+ XJSOpeningElement: 'XJSOpeningElement',
+ XJSAttribute: 'XJSAttribute',
+ XJSText: 'XJSText',
+ YieldExpression: 'YieldExpression'
+ };
+
+ PropertyKind = {
+ Data: 1,
+ Get: 2,
+ Set: 4
+ };
+
+ ClassPropertyType = {
+ static: 'static',
+ prototype: 'prototype'
+ };
+
+ // 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',
+ UnexpectedTemplate: 'Unexpected quasi %0',
+ 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',
+ InvalidLHSInFormalsList: 'Invalid left-hand side in formals list',
+ 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',
+ IllegalDuplicateClassProperty: 'Illegal duplicate property in class definition',
+ IllegalReturn: 'Illegal return statement',
+ IllegalYield: 'Illegal yield expression',
+ IllegalSpread: 'Illegal spread element',
+ 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',
+ ParameterAfterRestParameter: 'Rest parameter must be final parameter of an argument list',
+ ElementAfterSpreadElement: 'Spread must be the final element of an element list',
+ ObjectPatternAsRestParameter: 'Invalid rest parameter',
+ ObjectPatternAsSpread: 'Invalid spread argument',
+ 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',
+ NoFromAfterImport: 'Missing from after import',
+ NoYieldInGenerator: 'Missing yield in generator',
+ NoUnintializedConst: 'Const must be initialized',
+ ComprehensionRequiresBlock: 'Comprehension must have at least one block',
+ ComprehensionError: 'Comprehension Error',
+ EachNotAllowed: 'Each is not supported',
+ InvalidXJSTagName: 'XJS tag name can not be empty',
+ InvalidXJSAttributeValue: 'XJS value should be either an expression or a quoted XJS text',
+ ExpectedXJSClosingTag: 'Expected corresponding XJS closing tag for %0'
+ };
+
+ // 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) {
+ 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 === 32) || // space
+ (ch === 9) || // tab
+ (ch === 0xB) ||
+ (ch === 0xC) ||
+ (ch === 0xA0) ||
+ (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) > 0);
+ }
+
+ // 7.3 Line Terminators
+
+ function isLineTerminator(ch) {
+ return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029);
+ }
+
+ // 7.6 Identifier Names and Identifiers
+
+ function isIdentifierStart(ch) {
+ return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore)
+ (ch >= 65 && ch <= 90) || // A..Z
+ (ch >= 97 && ch <= 122) || // a..z
+ (ch === 92) || // \ (backslash)
+ ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch)));
+ }
+
+ function isIdentifierPart(ch) {
+ return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore)
+ (ch >= 65 && ch <= 90) || // A..Z
+ (ch >= 97 && ch <= 122) || // a..z
+ (ch >= 48 && ch <= 57) || // 0..9
+ (ch === 92) || // \ (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 skipComment() {
+ var ch, blockComment, lineComment;
+
+ blockComment = false;
+ lineComment = false;
+
+ while (index < length) {
+ ch = source.charCodeAt(index);
+
+ if (lineComment) {
+ ++index;
+ if (isLineTerminator(ch)) {
+ lineComment = false;
+ if (ch === 13 && source.charCodeAt(index) === 10) {
+ ++index;
+ }
+ ++lineNumber;
+ lineStart = index;
+ }
+ } else if (blockComment) {
+ if (isLineTerminator(ch)) {
+ if (ch === 13 && source.charCodeAt(index + 1) === 10) {
+ ++index;
+ }
+ ++lineNumber;
+ ++index;
+ lineStart = index;
+ if (index >= length) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ } else {
+ ch = source.charCodeAt(index++);
+ if (index >= length) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ // Block comment ends with '*/' (char #42, char #47).
+ if (ch === 42) {
+ ch = source.charCodeAt(index);
+ if (ch === 47) {
+ ++index;
+ blockComment = false;
+ }
+ }
+ }
+ } else if (ch === 47) {
+ ch = source.charCodeAt(index + 1);
+ // Line comment starts with '//' (char #47, char #47).
+ if (ch === 47) {
+ index += 2;
+ lineComment = true;
+ } else if (ch === 42) {
+ // Block comment starts with '/*' (char #47, char #42).
+ index += 2;
+ blockComment = true;
+ if (index >= length) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ } else {
+ break;
+ }
+ } else if (isWhiteSpace(ch)) {
+ ++index;
+ } else if (isLineTerminator(ch)) {
+ ++index;
+ if (ch === 13 && source.charCodeAt(index) === 10) {
+ ++index;
+ }
+ ++lineNumber;
+ lineStart = index;
+ } 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 scanUnicodeCodePointEscape() {
+ var ch, code, cu1, cu2;
+
+ ch = source[index];
+ code = 0;
+
+ // At least, one hex digit is required.
+ if (ch === '}') {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ while (index < length) {
+ ch = source[index++];
+ if (!isHexDigit(ch)) {
+ break;
+ }
+ code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
+ }
+
+ if (code > 0x10FFFF || ch !== '}') {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ // UTF-16 Encoding
+ if (code <= 0xFFFF) {
+ return String.fromCharCode(code);
+ }
+ cu1 = ((code - 0x10000) >> 10) + 0xD800;
+ cu2 = ((code - 0x10000) & 1023) + 0xDC00;
+ return String.fromCharCode(cu1, cu2);
+ }
+
+ function getEscapedIdentifier() {
+ var ch, id;
+
+ ch = source.charCodeAt(index++);
+ id = String.fromCharCode(ch);
+
+ // '\u' (char #92, char #117) denotes an escaped character.
+ if (ch === 92) {
+ if (source.charCodeAt(index) !== 117) {
+ 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' (char #92, char #117) denotes an escaped character.
+ if (ch === 92) {
+ id = id.substr(0, id.length - 1);
+ if (source.charCodeAt(index) !== 117) {
+ 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 === 92) {
+ // Blackslash (char #92) 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 (char #92) starts an escaped character.
+ id = (source.charCodeAt(index) === 92) ? 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,
+ range: [start, 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 40: // ( open bracket
+ case 41: // ) close bracket
+ case 59: // ; semicolon
+ case 44: // , comma
+ case 123: // { open curly brace
+ case 125: // } close curly brace
+ case 91: // [
+ case 93: // ]
+ case 58: // :
+ case 63: // ?
+ case 126: // ~
+ ++index;
+ if (extra.tokenize) {
+ if (code === 40) {
+ extra.openParenToken = extra.tokens.length;
+ } else if (code === 123) {
+ extra.openCurlyToken = extra.tokens.length;
+ }
+ }
+ return {
+ type: Token.Punctuator,
+ value: String.fromCharCode(code),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+
+ default:
+ code2 = source.charCodeAt(index + 1);
+
+ // '=' (char #61) marks an assignment or comparison operator.
+ if (code2 === 61) {
+ switch (code) {
+ case 37: // %
+ case 38: // &
+ case 42: // *:
+ case 43: // +
+ case 45: // -
+ case 47: // /
+ case 60: // <
+ case 62: // >
+ case 94: // ^
+ case 124: // |
+ index += 2;
+ return {
+ type: Token.Punctuator,
+ value: String.fromCharCode(code) + String.fromCharCode(code2),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+
+ case 33: // !
+ case 61: // =
+ index += 2;
+
+ // !== and ===
+ if (source.charCodeAt(index) === 61) {
+ ++index;
+ }
+ return {
+ type: Token.Punctuator,
+ value: source.slice(start, index),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ default:
+ break;
+ }
+ }
+ break;
+ }
+
+ // Peek more characters.
+
+ ch2 = source[index + 1];
+ ch3 = source[index + 2];
+ ch4 = source[index + 3];
+
+ // 4-character punctuator: >>>=
+
+ if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
+ if (ch4 === '=') {
+ index += 4;
+ return {
+ type: Token.Punctuator,
+ value: '>>>=',
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+ }
+
+ // 3-character punctuators: === !== >>> <<= >>=
+
+ if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
+ index += 3;
+ return {
+ type: Token.Punctuator,
+ value: '>>>',
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+
+ if (ch1 === '<' && ch2 === '<' && ch3 === '=') {
+ index += 3;
+ return {
+ type: Token.Punctuator,
+ value: '<<=',
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+
+ if (ch1 === '>' && ch2 === '>' && ch3 === '=') {
+ index += 3;
+ return {
+ type: Token.Punctuator,
+ value: '>>=',
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+
+ if (ch1 === '.' && ch2 === '.' && ch3 === '.') {
+ index += 3;
+ return {
+ type: Token.Punctuator,
+ value: '...',
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+
+ // Other 2-character punctuators: ++ -- << >> && ||
+
+ if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) {
+ index += 2;
+ return {
+ type: Token.Punctuator,
+ value: ch1 + ch2,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+
+ if (ch1 === '=' && ch2 === '>') {
+ index += 2;
+ return {
+ type: Token.Punctuator,
+ value: '=>',
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+
+ if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
+ ++index;
+ return {
+ type: Token.Punctuator,
+ value: ch1,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+
+ if (ch1 === '.') {
+ ++index;
+ return {
+ type: Token.Punctuator,
+ value: ch1,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, 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,
+ range: [start, index]
+ };
+ }
+
+ function scanOctalLiteral(prefix, start) {
+ var number, octal;
+
+ if (isOctalDigit(prefix)) {
+ octal = true;
+ number = '0' + source[index++];
+ } else {
+ octal = false;
+ ++index;
+ number = '';
+ }
+
+ while (index < length) {
+ if (!isOctalDigit(source[index])) {
+ break;
+ }
+ number += source[index++];
+ }
+
+ if (!octal && number.length === 0) {
+ // only 0o or 0O
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: parseInt(number, 8),
+ octal: octal,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+
+ function scanNumericLiteral() {
+ var number, start, ch, octal;
+
+ 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'.
+ // Octal number in ES6 starts with '0o'.
+ // Binary number in ES6 starts with '0b'.
+ if (number === '0') {
+ if (ch === 'x' || ch === 'X') {
+ ++index;
+ return scanHexLiteral(start);
+ }
+ if (ch === 'b' || ch === 'B') {
+ ++index;
+ number = '';
+
+ while (index < length) {
+ ch = source[index];
+ if (ch !== '0' && ch !== '1') {
+ break;
+ }
+ number += source[index++];
+ }
+
+ if (number.length === 0) {
+ // only 0b or 0B
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ if (index < length) {
+ ch = source.charCodeAt(index);
+ if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ }
+ return {
+ type: Token.NumericLiteral,
+ value: parseInt(number, 2),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+ if (ch === 'o' || ch === 'O' || isOctalDigit(ch)) {
+ return scanOctalLiteral(ch, 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,
+ range: [start, index]
+ };
+ }
+
+ // 7.8.4 String Literals
+
+ function scanStringLiteral() {
+ var str = '', quote, start, ch, code, unescaped, restore, octal = false;
+
+ 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 'n':
+ str += '\n';
+ break;
+ case 'r':
+ str += '\r';
+ break;
+ case 't':
+ str += '\t';
+ break;
+ case 'u':
+ case 'x':
+ if (source[index] === '{') {
+ ++index;
+ str += scanUnicodeCodePointEscape();
+ } else {
+ restore = index;
+ unescaped = scanHexEscape(ch);
+ if (unescaped) {
+ str += unescaped;
+ } else {
+ index = restore;
+ str += ch;
+ }
+ }
+ 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;
+ }
+ }
+ } else if (isLineTerminator(ch.charCodeAt(0))) {
+ break;
+ } else {
+ str += ch;
+ }
+ }
+
+ if (quote !== '') {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ return {
+ type: Token.StringLiteral,
+ value: str,
+ octal: octal,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+
+ function scanTemplate() {
+ var cooked = '', ch, start, terminated, tail, restore, unescaped, code, octal;
+
+ terminated = false;
+ tail = false;
+ start = index;
+
+ ++index;
+
+ while (index < length) {
+ ch = source[index++];
+ if (ch === '`') {
+ tail = true;
+ terminated = true;
+ break;
+ } else if (ch === '$') {
+ if (source[index] === '{') {
+ ++index;
+ terminated = true;
+ break;
+ }
+ cooked += ch;
+ } else if (ch === '\\') {
+ ch = source[index++];
+ if (!isLineTerminator(ch.charCodeAt(0))) {
+ switch (ch) {
+ case 'n':
+ cooked += '\n';
+ break;
+ case 'r':
+ cooked += '\r';
+ break;
+ case 't':
+ cooked += '\t';
+ break;
+ case 'u':
+ case 'x':
+ if (source[index] === '{') {
+ ++index;
+ cooked += scanUnicodeCodePointEscape();
+ } else {
+ restore = index;
+ unescaped = scanHexEscape(ch);
+ if (unescaped) {
+ cooked += unescaped;
+ } else {
+ index = restore;
+ cooked += ch;
+ }
+ }
+ break;
+ case 'b':
+ cooked += '\b';
+ break;
+ case 'f':
+ cooked += '\f';
+ break;
+ case 'v':
+ cooked += '\v';
+ 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++]);
+ }
+ }
+ cooked += String.fromCharCode(code);
+ } else {
+ cooked += ch;
+ }
+ break;
+ }
+ } else {
+ ++lineNumber;
+ if (ch === '\r' && source[index] === '\n') {
+ ++index;
+ }
+ }
+ } else if (isLineTerminator(ch.charCodeAt(0))) {
+ ++lineNumber;
+ if (ch === '\r' && source[index] === '\n') {
+ ++index;
+ }
+ } else {
+ cooked += ch;
+ }
+ }
+
+ if (!terminated) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ return {
+ type: Token.Template,
+ value: {
+ cooked: cooked,
+ raw: source.slice(start + 1, index - ((tail) ? 1 : 2))
+ },
+ tail: tail,
+ octal: octal,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+
+ function scanTemplateElement(option) {
+ var startsWith, template;
+
+ lookahead = null;
+ skipComment();
+
+ startsWith = (option.head) ? '`' : '}';
+
+ if (source[index] !== startsWith) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ template = scanTemplate();
+
+ peek();
+
+ return template;
+ }
+
+ function scanRegExp() {
+ var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false;
+
+ lookahead = null;
+ skipComment();
+
+ start = index;
+ ch = source[index];
+ assert(ch === '/', 'Regular expression literal must start with a slash');
+ str = source[index++];
+
+ while (index < length) {
+ ch = source[index++];
+ str += ch;
+ if (classMarker) {
+ if (ch === ']') {
+ classMarker = false;
+ }
+ } else {
+ if (ch === '\\') {
+ ch = source[index++];
+ // ECMA-262 7.8.5
+ if (isLineTerminator(ch.charCodeAt(0))) {
+ throwError({}, Messages.UnterminatedRegExp);
+ }
+ str += ch;
+ } else if (ch === '/') {
+ terminated = true;
+ break;
+ } else if (ch === '[') {
+ classMarker = true;
+ } else if (isLineTerminator(ch.charCodeAt(0))) {
+ throwError({}, Messages.UnterminatedRegExp);
+ }
+ }
+ }
+
+ if (!terminated) {
+ throwError({}, Messages.UnterminatedRegExp);
+ }
+
+ // Exclude leading and trailing slash.
+ pattern = str.substr(1, str.length - 2);
+
+ 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';
+ }
+ } else {
+ str += '\\';
+ }
+ } else {
+ flags += ch;
+ str += ch;
+ }
+ }
+
+ try {
+ value = new RegExp(pattern, flags);
+ } catch (e) {
+ throwError({}, Messages.InvalidRegExp);
+ }
+
+ peek();
+
+
+ if (extra.tokenize) {
+ return {
+ type: Token.RegularExpression,
+ value: value,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+ return {
+ literal: str,
+ value: value,
+ range: [start, index]
+ };
+ }
+
+ 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 scanRegExp();
+ }
+ if (prevToken.type === "Punctuator") {
+ 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 scanRegExp();
+ }
+ 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 scanRegExp();
+ }
+ } 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 scanRegExp();
+ }
+ return scanRegExp();
+ }
+ if (prevToken.type === "Keyword") {
+ return scanRegExp();
+ }
+ return scanPunctuator();
+ }
+
+ function advance() {
+ var ch;
+
+ if (state.inXJSChild) {
+ return advanceXJSChild();
+ }
+
+ skipComment();
+
+ if (index >= length) {
+ return {
+ type: Token.EOF,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [index, index]
+ };
+ }
+
+ ch = source.charCodeAt(index);
+
+ // Very common: ( and ) and ;
+ if (ch === 40 || ch === 41 || ch === 58) {
+ return scanPunctuator();
+ }
+
+ // String literal starts with single quote (#39) or double quote (#34).
+ if (ch === 39 || ch === 34) {
+ if (state.inXJSTag) {
+ return scanXJSStringLiteral();
+ }
+ return scanStringLiteral();
+ }
+
+ if (state.inXJSTag && isXJSIdentifierStart(ch)) {
+ return scanXJSIdentifier();
+ }
+
+ if (ch === 96) {
+ return scanTemplate();
+ }
+ if (isIdentifierStart(ch)) {
+ return scanIdentifier();
+ }
+
+ // Dot (.) char #46 can also start a floating-point number, hence the need
+ // to check the next character.
+ if (ch === 46) {
+ if (isDecimalDigit(source.charCodeAt(index + 1))) {
+ return scanNumericLiteral();
+ }
+ return scanPunctuator();
+ }
+
+ if (isDecimalDigit(ch)) {
+ return scanNumericLiteral();
+ }
+
+ // Slash (/) char #47 can also start a regex.
+ if (extra.tokenize && ch === 47) {
+ return advanceSlash();
+ }
+
+ return scanPunctuator();
+ }
+
+ function lex() {
+ var token;
+
+ token = lookahead;
+ index = token.range[1];
+ lineNumber = token.lineNumber;
+ lineStart = token.lineStart;
+
+ lookahead = advance();
+
+ index = token.range[1];
+ lineNumber = token.lineNumber;
+ lineStart = token.lineStart;
+
+ return token;
+ }
+
+ function peek() {
+ var pos, line, start;
+
+ pos = index;
+ line = lineNumber;
+ start = lineStart;
+ lookahead = advance();
+ index = pos;
+ lineNumber = line;
+ lineStart = start;
+ }
+
+ function lookahead2() {
+ var adv, pos, line, start, result;
+
+ // If we are collecting the tokens, don't grab the next one yet.
+ adv = (typeof extra.advance === 'function') ? extra.advance : advance;
+
+ pos = index;
+ line = lineNumber;
+ start = lineStart;
+
+ // Scan for the next immediate token.
+ if (lookahead === null) {
+ lookahead = adv();
+ }
+ index = lookahead.range[1];
+ lineNumber = lookahead.lineNumber;
+ lineStart = lookahead.lineStart;
+
+ // Grab the token right after.
+ result = adv();
+ index = pos;
+ lineNumber = line;
+ lineStart = start;
+
+ return result;
+ }
+
+ SyntaxTreeDelegate = {
+
+ name: 'SyntaxTree',
+
+ postProcess: function (node) {
+ 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
+ };
+ },
+
+ createForOfStatement: function (left, right, body) {
+ return {
+ type: Syntax.ForOfStatement,
+ left: left,
+ right: right,
+ body: body,
+ };
+ },
+
+ createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression) {
+ return {
+ type: Syntax.FunctionDeclaration,
+ id: id,
+ params: params,
+ defaults: defaults,
+ body: body,
+ rest: rest,
+ generator: generator,
+ expression: expression
+ };
+ },
+
+ createFunctionExpression: function (id, params, defaults, body, rest, generator, expression) {
+ return {
+ type: Syntax.FunctionExpression,
+ id: id,
+ params: params,
+ defaults: defaults,
+ body: body,
+ rest: rest,
+ generator: generator,
+ expression: expression
+ };
+ },
+
+ createIdentifier: function (name) {
+ return {
+ type: Syntax.Identifier,
+ name: name
+ };
+ },
+
+ createXJSAttribute: function (name, value) {
+ return {
+ type: Syntax.XJSAttribute,
+ name: name,
+ value: value
+ };
+ },
+
+ createXJSIdentifier: function (name, namespace) {
+ return {
+ type: Syntax.XJSIdentifier,
+ name: name,
+ namespace: namespace
+ };
+ },
+
+ createXJSElement: function (openingElement, closingElement, children) {
+ return {
+ type: Syntax.XJSElement,
+ name: openingElement.name,
+ selfClosing: openingElement.selfClosing,
+ openingElement: openingElement,
+ closingElement: closingElement,
+ attributes: openingElement.attributes,
+ children: children
+ };
+ },
+
+ createXJSEmptyExpression: function () {
+ return {
+ type: Syntax.XJSEmptyExpression
+ };
+ },
+
+ createXJSExpressionContainer: function (expression) {
+ return {
+ type: Syntax.XJSExpressionContainer,
+ expression: expression
+ };
+ },
+
+ createXJSOpeningElement: function (name, attributes, selfClosing) {
+ return {
+ type: Syntax.XJSOpeningElement,
+ name: name,
+ selfClosing: selfClosing,
+ attributes: attributes
+ };
+ },
+
+ createXJSClosingElement: function (name) {
+ return {
+ type: Syntax.XJSClosingElement,
+ 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.range[0], token.range[1])
+ };
+ },
+
+ 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, method, shorthand) {
+ return {
+ type: Syntax.Property,
+ key: key,
+ value: value,
+ kind: kind,
+ method: method,
+ shorthand: shorthand
+ };
+ },
+
+ 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
+ };
+ },
+
+ 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
+ };
+ },
+
+ createTemplateElement: function (value, tail) {
+ return {
+ type: Syntax.TemplateElement,
+ value: value,
+ tail: tail
+ };
+ },
+
+ createTemplateLiteral: function (quasis, expressions) {
+ return {
+ type: Syntax.TemplateLiteral,
+ quasis: quasis,
+ expressions: expressions
+ };
+ },
+
+ createSpreadElement: function (argument) {
+ return {
+ type: Syntax.SpreadElement,
+ argument: argument
+ };
+ },
+
+ createTaggedTemplateExpression: function (tag, quasi) {
+ return {
+ type: Syntax.TaggedTemplateExpression,
+ tag: tag,
+ quasi: quasi
+ };
+ },
+
+ createArrowFunctionExpression: function (params, defaults, body, rest, expression) {
+ return {
+ type: Syntax.ArrowFunctionExpression,
+ id: null,
+ params: params,
+ defaults: defaults,
+ body: body,
+ rest: rest,
+ generator: false,
+ expression: expression
+ };
+ },
+
+ createMethodDefinition: function (propertyType, kind, key, value) {
+ return {
+ type: Syntax.MethodDefinition,
+ key: key,
+ value: value,
+ kind: kind,
+ 'static': propertyType === ClassPropertyType.static
+ };
+ },
+
+ createClassBody: function (body) {
+ return {
+ type: Syntax.ClassBody,
+ body: body
+ };
+ },
+
+ createClassExpression: function (id, superClass, body) {
+ return {
+ type: Syntax.ClassExpression,
+ id: id,
+ superClass: superClass,
+ body: body
+ };
+ },
+
+ createClassDeclaration: function (id, superClass, body) {
+ return {
+ type: Syntax.ClassDeclaration,
+ id: id,
+ superClass: superClass,
+ body: body
+ };
+ },
+
+ createPath: function (body) {
+ return {
+ type: Syntax.Path,
+ body: body
+ };
+ },
+
+ createGlob: function () {
+ return {
+ type: Syntax.Glob
+ };
+ },
+
+ createExportSpecifier: function (id, from) {
+ return {
+ type: Syntax.ExportSpecifier,
+ id: id,
+ from: from
+ };
+ },
+
+ createExportSpecifierSet: function (specifiers) {
+ return {
+ type: Syntax.ExportSpecifierSet,
+ specifiers: specifiers
+ };
+ },
+
+ createExportDeclaration: function (declaration, specifiers) {
+ return {
+ type: Syntax.ExportDeclaration,
+ declaration: declaration,
+ specifiers: specifiers
+ };
+ },
+
+ createImportSpecifier: function (id, from) {
+ return {
+ type: Syntax.ImportSpecifier,
+ id: id,
+ from: from
+ };
+ },
+
+ createImportDeclaration: function (specifiers, from) {
+ return {
+ type: Syntax.ImportDeclaration,
+ specifiers: specifiers,
+ from: from
+ };
+ },
+
+ createYieldExpression: function (argument, delegate) {
+ return {
+ type: Syntax.YieldExpression,
+ argument: argument,
+ delegate: delegate
+ };
+ },
+
+ createModuleDeclaration: function (id, from, body) {
+ return {
+ type: Syntax.ModuleDeclaration,
+ id: id,
+ from: from,
+ 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.range[0];
+ error.lineNumber = token.lineNumber;
+ error.column = token.range[0] - 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);
+ }
+
+ if (token.type === Token.Template) {
+ throwError(token, Messages.UnexpectedTemplate, token.value.raw);
+ }
+
+ // 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 matches the specified contextual keyword
+
+ function matchContextualKeyword(keyword) {
+ return lookahead.type === Token.Identifier && 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 (char #59).
+ if (source.charCodeAt(index) === 59) {
+ lex();
+ return;
+ }
+
+ line = lineNumber;
+ skipComment();
+ if (lineNumber !== line) {
+ return;
+ }
+
+ if (match(';')) {
+ lex();
+ 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;
+ }
+
+ function isAssignableLeftHandSide(expr) {
+ return isLeftHandSide(expr) || expr.type === Syntax.ObjectPattern || expr.type === Syntax.ArrayPattern;
+ }
+
+ // 11.1.4 Array Initialiser
+
+ function parseArrayInitialiser() {
+ var elements = [], blocks = [], filter = null, tmp, possiblecomprehension = true, body;
+
+ expect('[');
+ while (!match(']')) {
+ if (lookahead.value === 'for' &&
+ lookahead.type === Token.Keyword) {
+ if (!possiblecomprehension) {
+ throwError({}, Messages.ComprehensionError);
+ }
+ matchKeyword('for');
+ tmp = parseForStatement({ignore_body: true});
+ tmp.of = tmp.type === Syntax.ForOfStatement;
+ tmp.type = Syntax.ComprehensionBlock;
+ if (tmp.left.kind) { // can't be let or const
+ throwError({}, Messages.ComprehensionError);
+ }
+ blocks.push(tmp);
+ } else if (lookahead.value === 'if' &&
+ lookahead.type === Token.Keyword) {
+ if (!possiblecomprehension) {
+ throwError({}, Messages.ComprehensionError);
+ }
+ expectKeyword('if');
+ expect('(');
+ filter = parseExpression();
+ expect(')');
+ } else if (lookahead.value === ',' &&
+ lookahead.type === Token.Punctuator) {
+ possiblecomprehension = false; // no longer allowed.
+ lex();
+ elements.push(null);
+ } else {
+ tmp = parseSpreadOrAssignmentExpression();
+ elements.push(tmp);
+ if (tmp && tmp.type === Syntax.SpreadElement) {
+ if (!match(']')) {
+ throwError({}, Messages.ElementAfterSpreadElement);
+ }
+ } else if (!(match(']') || matchKeyword('for') || matchKeyword('if'))) {
+ expect(','); // this lexes.
+ possiblecomprehension = false;
+ }
+ }
+ }
+
+ expect(']');
+
+ if (filter && !blocks.length) {
+ throwError({}, Messages.ComprehensionRequiresBlock);
+ }
+
+ if (blocks.length) {
+ if (elements.length !== 1) {
+ throwError({}, Messages.ComprehensionError);
+ }
+ return {
+ type: Syntax.ComprehensionExpression,
+ filter: filter,
+ blocks: blocks,
+ body: elements[0]
+ };
+ }
+ return delegate.createArrayExpression(elements);
+ }
+
+ // 11.1.5 Object Initialiser
+
+ function parsePropertyFunction(options) {
+ var previousStrict, previousYieldAllowed, params, body;
+
+ previousStrict = strict;
+ previousYieldAllowed = state.yieldAllowed;
+ state.yieldAllowed = options.generator;
+ params = options.params || [];
+
+ body = parseConciseBody();
+ if (options.name && strict && isRestrictedWord(params[0].name)) {
+ throwErrorTolerant(options.name, Messages.StrictParamName);
+ }
+ if (state.yieldAllowed && !state.yieldFound) {
+ throwError({}, Messages.NoYieldInGenerator);
+ }
+ strict = previousStrict;
+ state.yieldAllowed = previousYieldAllowed;
+
+ return delegate.createFunctionExpression(null, params, [], body, options.rest || null, options.generator, body.type !== Syntax.BlockStatement);
+ }
+
+
+ function parsePropertyMethodFunction(options) {
+ var previousStrict, tmp, method;
+
+ previousStrict = strict;
+ strict = true;
+
+ tmp = parseParams();
+
+ if (tmp.stricted) {
+ throwErrorTolerant(tmp.stricted, tmp.message);
+ }
+
+
+ method = parsePropertyFunction({
+ params: tmp.params,
+ rest: tmp.rest,
+ generator: options.generator
+ });
+
+ strict = previousStrict;
+
+ return method;
+ }
+
+
+ function parseObjectPropertyKey() {
+ var 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.createLiteral(token);
+ }
+
+ return delegate.createIdentifier(token.value);
+ }
+
+ function parseObjectProperty() {
+ var token, key, id, value, param;
+
+ token = lookahead;
+
+ if (token.type === Token.Identifier) {
+
+ id = parseObjectPropertyKey();
+
+ // Property Assignment: Getter and Setter.
+
+ if (token.value === 'get' && !(match(':') || match('('))) {
+ key = parseObjectPropertyKey();
+ expect('(');
+ expect(')');
+ return delegate.createProperty('get', key, parsePropertyFunction({ generator: false }), false, false);
+ }
+ if (token.value === 'set' && !(match(':') || match('('))) {
+ key = parseObjectPropertyKey();
+ expect('(');
+ token = lookahead;
+ param = [ parseVariableIdentifier() ];
+ expect(')');
+ return delegate.createProperty('set', key, parsePropertyFunction({ params: param, generator: false, name: token }), false, false);
+ }
+ if (match(':')) {
+ lex();
+ return delegate.createProperty('init', id, parseAssignmentExpression(), false, false);
+ }
+ if (match('(')) {
+ return delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: false }), true, false);
+ }
+ return delegate.createProperty('init', id, id, false, true);
+ }
+ if (token.type === Token.EOF || token.type === Token.Punctuator) {
+ if (!match('*')) {
+ throwUnexpected(token);
+ }
+ lex();
+
+ id = parseObjectPropertyKey();
+
+ if (!match('(')) {
+ throwUnexpected(lex());
+ }
+
+ return delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: true }), true, false);
+ }
+ key = parseObjectPropertyKey();
+ if (match(':')) {
+ lex();
+ return delegate.createProperty('init', key, parseAssignmentExpression(), false, false);
+ }
+ if (match('(')) {
+ return delegate.createProperty('init', key, parsePropertyMethodFunction({ generator: false }), true, false);
+ }
+ throwUnexpected(lex());
+ }
+
+ function parseObjectInitialiser() {
+ var properties = [], property, name, key, kind, map = {}, toString = String;
+
+ 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.createObjectExpression(properties);
+ }
+
+ function parseTemplateElement(option) {
+ var token = scanTemplateElement(option);
+ if (strict && token.octal) {
+ throwError(token, Messages.StrictOctalLiteral);
+ }
+ return delegate.createTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail);
+ }
+
+ function parseTemplateLiteral() {
+ var quasi, quasis, expressions;
+
+ quasi = parseTemplateElement({ head: true });
+ quasis = [ quasi ];
+ expressions = [];
+
+ while (!quasi.tail) {
+ expressions.push(parseExpression());
+ quasi = parseTemplateElement({ head: false });
+ quasis.push(quasi);
+ }
+
+ return delegate.createTemplateLiteral(quasis, expressions);
+ }
+
+ // 11.1.6 The Grouping Operator
+
+ function parseGroupExpression() {
+ var expr;
+
+ expect('(');
+
+ ++state.parenthesizedCount;
+
+ state.allowArrowFunction = !state.allowArrowFunction;
+ expr = parseExpression();
+ state.allowArrowFunction = false;
+
+ if (expr.type !== Syntax.ArrowFunctionExpression) {
+ expect(')');
+ }
+
+ return expr;
+ }
+
+
+ // 11.1 Primary Expressions
+
+ function parsePrimaryExpression() {
+ var type, token;
+
+ token = lookahead;
+ type = lookahead.type;
+
+ if (type === Token.Identifier) {
+ lex();
+ return delegate.createIdentifier(token.value);
+ }
+
+ if (type === Token.StringLiteral || type === Token.NumericLiteral) {
+ if (strict && lookahead.octal) {
+ throwErrorTolerant(lookahead, Messages.StrictOctalLiteral);
+ }
+ return delegate.createLiteral(lex());
+ }
+
+ if (type === Token.Keyword) {
+ if (matchKeyword('this')) {
+ lex();
+ return delegate.createThisExpression();
+ }
+
+ if (matchKeyword('function')) {
+ return parseFunctionExpression();
+ }
+
+ if (matchKeyword('class')) {
+ return parseClassExpression();
+ }
+
+ if (matchKeyword('super')) {
+ lex();
+ return delegate.createIdentifier('super');
+ }
+ }
+
+ if (type === Token.BooleanLiteral) {
+ token = lex();
+ token.value = (token.value === 'true');
+ return delegate.createLiteral(token);
+ }
+
+ if (type === Token.NullLiteral) {
+ token = lex();
+ token.value = null;
+ return delegate.createLiteral(token);
+ }
+
+ if (match('[')) {
+ return parseArrayInitialiser();
+ }
+
+ if (match('{')) {
+ return parseObjectInitialiser();
+ }
+
+ if (match('(')) {
+ return parseGroupExpression();
+ }
+
+ if (match('/') || match('/=')) {
+ return delegate.createLiteral(scanRegExp());
+ }
+
+ if (type === Token.Template) {
+ return parseTemplateLiteral();
+ }
+
+ if (match('<')) {
+ return parseXJSElement();
+ }
+
+ return throwUnexpected(lex());
+ }
+
+ // 11.2 Left-Hand-Side Expressions
+
+ function parseArguments() {
+ var args = [], arg;
+
+ expect('(');
+
+ if (!match(')')) {
+ while (index < length) {
+ arg = parseSpreadOrAssignmentExpression();
+ args.push(arg);
+
+ if (match(')')) {
+ break;
+ } else if (arg.type === Syntax.SpreadElement) {
+ throwError({}, Messages.ElementAfterSpreadElement);
+ }
+
+ expect(',');
+ }
+ }
+
+ expect(')');
+
+ return args;
+ }
+
+ function parseSpreadOrAssignmentExpression() {
+ if (match('...')) {
+ lex();
+ return delegate.createSpreadElement(parseAssignmentExpression());
+ }
+ return parseAssignmentExpression();
+ }
+
+ function parseNonComputedProperty() {
+ var token = lex();
+
+ if (!isIdentifierName(token)) {
+ throwUnexpected(token);
+ }
+
+ return delegate.createIdentifier(token.value);
+ }
+
+ function parseNonComputedMember() {
+ expect('.');
+
+ return parseNonComputedProperty();
+ }
+
+ function parseComputedMember() {
+ var expr;
+
+ expect('[');
+
+ expr = parseExpression();
+
+ expect(']');
+
+ return expr;
+ }
+
+ function parseNewExpression() {
+ var callee, args;
+
+ expectKeyword('new');
+ callee = parseLeftHandSideExpression();
+ args = match('(') ? parseArguments() : [];
+
+ return delegate.createNewExpression(callee, args);
+ }
+
+ function parseLeftHandSideExpressionAllowCall() {
+ var expr, args, property;
+
+ expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
+
+ while (match('.') || match('[') || match('(') || lookahead.type === Token.Template) {
+ if (match('(')) {
+ args = parseArguments();
+ expr = delegate.createCallExpression(expr, args);
+ } else if (match('[')) {
+ expr = delegate.createMemberExpression('[', expr, parseComputedMember());
+ } else if (match('.')) {
+ expr = delegate.createMemberExpression('.', expr, parseNonComputedMember());
+ } else {
+ expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral());
+ }
+ }
+
+ return expr;
+ }
+
+
+ function parseLeftHandSideExpression() {
+ var expr, property;
+
+ expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
+
+ while (match('.') || match('[') || lookahead.type === Token.Template) {
+ if (match('[')) {
+ expr = delegate.createMemberExpression('[', expr, parseComputedMember());
+ } else if (match('.')) {
+ expr = delegate.createMemberExpression('.', expr, parseNonComputedMember());
+ } else {
+ expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral());
+ }
+ }
+
+ return expr;
+ }
+
+ // 11.3 Postfix Expressions
+
+ function parsePostfixExpression() {
+ var expr = parseLeftHandSideExpressionAllowCall(),
+ token = lookahead;
+
+ if (lookahead.type !== Token.Punctuator) {
+ return expr;
+ }
+
+ 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)) {
+ throwError({}, Messages.InvalidLHSInAssignment);
+ }
+
+ token = lex();
+ expr = delegate.createPostfixExpression(token.value, expr);
+ }
+
+ return expr;
+ }
+
+ // 11.4 Unary Operators
+
+ function parseUnaryExpression() {
+ var token, expr;
+
+ if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
+ return parsePostfixExpression();
+ }
+
+ if (match('++') || match('--')) {
+ 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)) {
+ throwError({}, Messages.InvalidLHSInAssignment);
+ }
+
+ return delegate.createUnaryExpression(token.value, expr);
+ }
+
+ if (match('+') || match('-') || match('~') || match('!')) {
+ token = lex();
+ expr = parseUnaryExpression();
+ return delegate.createUnaryExpression(token.value, expr);
+ }
+
+ if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
+ token = lex();
+ expr = parseUnaryExpression();
+ expr = delegate.createUnaryExpression(token.value, expr);
+ if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
+ throwErrorTolerant({}, Messages.StrictDelete);
+ }
+ return expr;
+ }
+
+ return parsePostfixExpression();
+ }
+
+ 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 expr, token, prec, previousAllowIn, stack, right, operator, left, i;
+
+ previousAllowIn = state.allowIn;
+ state.allowIn = true;
+
+ expr = parseUnaryExpression();
+
+ token = lookahead;
+ prec = binaryPrecedence(token, previousAllowIn);
+ if (prec === 0) {
+ return expr;
+ }
+ token.prec = prec;
+ lex();
+
+ stack = [expr, token, parseUnaryExpression()];
+
+ while ((prec = binaryPrecedence(lookahead, previousAllowIn)) > 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();
+ stack.push(delegate.createBinaryExpression(operator, left, right));
+ }
+
+ // Shift.
+ token = lex();
+ token.prec = prec;
+ stack.push(token);
+ stack.push(parseUnaryExpression());
+ }
+
+ state.allowIn = previousAllowIn;
+
+ // Final reduce to clean-up the stack.
+ i = stack.length - 1;
+ expr = stack[i];
+ while (i > 1) {
+ expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
+ i -= 2;
+ }
+ return expr;
+ }
+
+
+ // 11.12 Conditional Operator
+
+ function parseConditionalExpression() {
+ var expr, previousAllowIn, consequent, alternate;
+
+ 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);
+ }
+
+ return expr;
+ }
+
+ // 11.13 Assignment Operators
+
+ function reinterpretAsAssignmentBindingPattern(expr) {
+ var i, len, property, element;
+
+ if (expr.type === Syntax.ObjectExpression) {
+ expr.type = Syntax.ObjectPattern;
+ for (i = 0, len = expr.properties.length; i < len; i += 1) {
+ property = expr.properties[i];
+ if (property.kind !== 'init') {
+ throwError({}, Messages.InvalidLHSInAssignment);
+ }
+ reinterpretAsAssignmentBindingPattern(property.value);
+ }
+ } else if (expr.type === Syntax.ArrayExpression) {
+ expr.type = Syntax.ArrayPattern;
+ for (i = 0, len = expr.elements.length; i < len; i += 1) {
+ element = expr.elements[i];
+ if (element) {
+ reinterpretAsAssignmentBindingPattern(element);
+ }
+ }
+ } else if (expr.type === Syntax.Identifier) {
+ if (isRestrictedWord(expr.name)) {
+ throwError({}, Messages.InvalidLHSInAssignment);
+ }
+ } else if (expr.type === Syntax.SpreadElement) {
+ reinterpretAsAssignmentBindingPattern(expr.argument);
+ if (expr.argument.type === Syntax.ObjectPattern) {
+ throwError({}, Messages.ObjectPatternAsSpread);
+ }
+ } else {
+ if (expr.type !== Syntax.MemberExpression && expr.type !== Syntax.CallExpression && expr.type !== Syntax.NewExpression) {
+ throwError({}, Messages.InvalidLHSInAssignment);
+ }
+ }
+ }
+
+
+ function reinterpretAsDestructuredParameter(options, expr) {
+ var i, len, property, element;
+
+ if (expr.type === Syntax.ObjectExpression) {
+ expr.type = Syntax.ObjectPattern;
+ for (i = 0, len = expr.properties.length; i < len; i += 1) {
+ property = expr.properties[i];
+ if (property.kind !== 'init') {
+ throwError({}, Messages.InvalidLHSInFormalsList);
+ }
+ reinterpretAsDestructuredParameter(options, property.value);
+ }
+ } else if (expr.type === Syntax.ArrayExpression) {
+ expr.type = Syntax.ArrayPattern;
+ for (i = 0, len = expr.elements.length; i < len; i += 1) {
+ element = expr.elements[i];
+ if (element) {
+ reinterpretAsDestructuredParameter(options, element);
+ }
+ }
+ } else if (expr.type === Syntax.Identifier) {
+ validateParam(options, expr, expr.name);
+ } else {
+ if (expr.type !== Syntax.MemberExpression) {
+ throwError({}, Messages.InvalidLHSInFormalsList);
+ }
+ }
+ }
+
+ function reinterpretAsCoverFormalsList(expressions) {
+ var i, len, param, params, options, rest;
+
+ params = [];
+ rest = null;
+ options = {
+ paramSet: {}
+ };
+
+ for (i = 0, len = expressions.length; i < len; i += 1) {
+ param = expressions[i];
+ if (param.type === Syntax.Identifier) {
+ params.push(param);
+ validateParam(options, param, param.name);
+ } else if (param.type === Syntax.ObjectExpression || param.type === Syntax.ArrayExpression) {
+ reinterpretAsDestructuredParameter(options, param);
+ params.push(param);
+ } else if (param.type === Syntax.SpreadElement) {
+ assert(i === len - 1, "It is guaranteed that SpreadElement is last element by parseExpression");
+ reinterpretAsDestructuredParameter(options, param.argument);
+ rest = param.argument;
+ } else {
+ return null;
+ }
+ }
+
+ if (options.firstRestricted) {
+ throwError(options.firstRestricted, options.message);
+ }
+ if (options.stricted) {
+ throwErrorTolerant(options.stricted, options.message);
+ }
+
+ return { params: params, rest: rest };
+ }
+
+ function parseArrowFunctionExpression(options) {
+ var previousStrict, previousYieldAllowed, body;
+
+ expect('=>');
+
+ previousStrict = strict;
+ previousYieldAllowed = state.yieldAllowed;
+ strict = true;
+ state.yieldAllowed = false;
+ body = parseConciseBody();
+ strict = previousStrict;
+ state.yieldAllowed = previousYieldAllowed;
+
+ return delegate.createArrowFunctionExpression(options.params, [], body, options.rest, body.type !== Syntax.BlockStatement);
+ }
+
+ function parseAssignmentExpression() {
+ var expr, token, params, oldParenthesizedCount;
+
+ if (matchKeyword('yield')) {
+ return parseYieldExpression();
+ }
+
+ oldParenthesizedCount = state.parenthesizedCount;
+
+ if (match('(')) {
+ token = lookahead2();
+ if ((token.type === Token.Punctuator && token.value === ')') || token.value === '...') {
+ params = parseParams();
+ if (!match('=>')) {
+ throwUnexpected(lex());
+ }
+ return parseArrowFunctionExpression(params);
+ }
+ }
+
+ token = lookahead;
+ expr = parseConditionalExpression();
+
+ if (match('=>') && expr.type === Syntax.Identifier) {
+ if (state.parenthesizedCount === oldParenthesizedCount || state.parenthesizedCount === (oldParenthesizedCount + 1)) {
+ if (isRestrictedWord(expr.name)) {
+ throwError({}, Messages.StrictParamName);
+ }
+ return parseArrowFunctionExpression({ params: [ expr ], rest: null });
+ }
+ }
+
+ if (matchAssign()) {
+ // 11.13.1
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
+ throwErrorTolerant(token, Messages.StrictLHSAssignment);
+ }
+
+ // ES.next draf 11.13 Runtime Semantics step 1
+ if (match('=') && (expr.type === Syntax.ObjectExpression || expr.type === Syntax.ArrayExpression)) {
+ reinterpretAsAssignmentBindingPattern(expr);
+ } else if (!isLeftHandSide(expr)) {
+ throwError({}, Messages.InvalidLHSInAssignment);
+ }
+
+ expr = delegate.createAssignmentExpression(lex().value, expr, parseAssignmentExpression());
+ }
+
+ return expr;
+ }
+
+ // 11.14 Comma Operator
+
+ function parseExpression() {
+ var expr, expressions, sequence, coverFormalsList, spreadFound, token;
+
+ expr = parseAssignmentExpression();
+ expressions = [ expr ];
+
+ if (match(',')) {
+ while (index < length) {
+ if (!match(',')) {
+ break;
+ }
+
+ lex();
+ expr = parseSpreadOrAssignmentExpression();
+ expressions.push(expr);
+
+ if (expr.type === Syntax.SpreadElement) {
+ spreadFound = true;
+ if (!match(')')) {
+ throwError({}, Messages.ElementAfterSpreadElement);
+ }
+ break;
+ }
+ }
+
+ sequence = delegate.createSequenceExpression(expressions);
+ }
+
+ if (state.allowArrowFunction && match(')')) {
+ token = lookahead2();
+ if (token.value === '=>') {
+ lex();
+
+ state.allowArrowFunction = false;
+ expr = expressions;
+ coverFormalsList = reinterpretAsCoverFormalsList(expr);
+ if (coverFormalsList) {
+ return parseArrowFunctionExpression(coverFormalsList);
+ }
+
+ throwUnexpected(token);
+ }
+ }
+
+ if (spreadFound) {
+ throwError({}, Messages.IllegalSpread);
+ }
+
+ return sequence || 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;
+
+ expect('{');
+
+ block = parseStatementList();
+
+ expect('}');
+
+ return delegate.createBlockStatement(block);
+ }
+
+ // 12.2 Variable Statement
+
+ function parseVariableIdentifier() {
+ var token = lex();
+
+ if (token.type !== Token.Identifier) {
+ throwUnexpected(token);
+ }
+
+ return delegate.createIdentifier(token.value);
+ }
+
+ function parseVariableDeclaration(kind) {
+ var id,
+ init = null;
+ if (match('{')) {
+ id = parseObjectInitialiser();
+ reinterpretAsAssignmentBindingPattern(id);
+ } else if (match('[')) {
+ id = parseArrayInitialiser();
+ reinterpretAsAssignmentBindingPattern(id);
+ } else {
+ id = parseVariableIdentifier();
+ // 12.2.1
+ if (strict && isRestrictedWord(id.name)) {
+ throwErrorTolerant({}, Messages.StrictVarName);
+ }
+ }
+
+ if (kind === 'const') {
+ if (!match('=')) {
+ throwError({}, Messages.NoUnintializedConst);
+ }
+ expect('=');
+ init = parseAssignmentExpression();
+ } else if (match('=')) {
+ lex();
+ init = parseAssignmentExpression();
+ }
+
+ return delegate.createVariableDeclarator(id, init);
+ }
+
+ 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;
+
+ expectKeyword(kind);
+
+ declarations = parseVariableDeclarationList(kind);
+
+ consumeSemicolon();
+
+ return delegate.createVariableDeclaration(declarations, kind);
+ }
+
+ // http://wiki.ecmascript.org/doku.php?id=harmony:modules
+
+ function parsePath() {
+ var body = [];
+
+ while (true) {
+ body.push(parseVariableIdentifier());
+ if (!match('.')) {
+ break;
+ }
+ lex();
+ }
+
+ return delegate.createPath(body);
+ }
+
+ function parseGlob() {
+ expect('*');
+ return delegate.createGlob();
+ }
+
+ function parseModuleDeclaration() {
+ var id, token, from = null;
+
+ lex();
+
+ id = parseVariableIdentifier();
+
+ if (match('{')) {
+ return delegate.createModuleDeclaration(id, from, parseModuleBlock());
+ }
+
+ expect('=');
+
+ token = lookahead;
+ if (token.type === Token.StringLiteral) {
+ from = parsePrimaryExpression();
+ } else {
+ from = parsePath();
+ }
+
+ consumeSemicolon();
+
+ return delegate.createModuleDeclaration(id, from, null);
+ }
+
+ function parseExportSpecifierSetProperty() {
+ var id, from = null;
+
+ id = parseVariableIdentifier();
+
+ if (match(':')) {
+ lex();
+ from = parsePath();
+ }
+
+ return delegate.createExportSpecifier(id, from);
+ }
+
+ function parseExportSpecifier() {
+ var specifiers, id, from;
+
+ if (match('{')) {
+ lex();
+ specifiers = [];
+
+ do {
+ specifiers.push(parseExportSpecifierSetProperty());
+ } while (match(',') && lex());
+
+ expect('}');
+
+ return delegate.createExportSpecifierSet(specifiers);
+ }
+
+ from = null;
+
+ if (match('*')) {
+ id = parseGlob();
+ if (matchContextualKeyword('from')) {
+ lex();
+ from = parsePath();
+ }
+ } else {
+ id = parseVariableIdentifier();
+ }
+ return delegate.createExportSpecifier(id, from);
+ }
+
+ function parseExportDeclaration() {
+ var token, specifiers;
+
+ expectKeyword('export');
+
+ token = lookahead;
+
+ if (token.type === Token.Keyword || (token.type === Token.Identifier && token.value === 'module')) {
+ switch (token.value) {
+ case 'function':
+ return delegate.createExportDeclaration(parseFunctionDeclaration(), null);
+ case 'module':
+ return delegate.createExportDeclaration(parseModuleDeclaration(), null);
+ case 'let':
+ case 'const':
+ return delegate.createExportDeclaration(parseConstLetDeclaration(token.value), null);
+ case 'var':
+ return delegate.createExportDeclaration(parseStatement(), null);
+ case 'class':
+ return delegate.createExportDeclaration(parseClassDeclaration(), null);
+ }
+ throwUnexpected(lex());
+ }
+
+ specifiers = [ parseExportSpecifier() ];
+ if (match(',')) {
+ while (index < length) {
+ if (!match(',')) {
+ break;
+ }
+ lex();
+ specifiers.push(parseExportSpecifier());
+ }
+ }
+
+ consumeSemicolon();
+
+ return delegate.createExportDeclaration(null, specifiers);
+ }
+
+ function parseImportDeclaration() {
+ var specifiers, from;
+
+ expectKeyword('import');
+
+ if (match('*')) {
+ specifiers = [parseGlob()];
+ } else if (match('{')) {
+ lex();
+ specifiers = [];
+
+ do {
+ specifiers.push(parseImportSpecifier());
+ } while (match(',') && lex());
+
+ expect('}');
+ } else {
+ specifiers = [parseVariableIdentifier()];
+ }
+
+ if (!matchContextualKeyword('from')) {
+ throwError({}, Messages.NoFromAfterImport);
+ }
+
+ lex();
+
+ if (lookahead.type === Token.StringLiteral) {
+ from = parsePrimaryExpression();
+ } else {
+ from = parsePath();
+ }
+
+ consumeSemicolon();
+
+ return delegate.createImportDeclaration(specifiers, from);
+ }
+
+ function parseImportSpecifier() {
+ var id, from;
+
+ id = parseVariableIdentifier();
+ from = null;
+
+ if (match(':')) {
+ lex();
+ from = parsePath();
+ }
+
+ return delegate.createImportSpecifier(id, from);
+ }
+
+ // 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 = lex(),
+ declarations = parseVariableDeclarationList();
+
+ return delegate.createVariableDeclaration(declarations, token.value);
+ }
+
+ function parseForStatement(opts) {
+ var init, test, update, left, right, body, operator, oldInIteration;
+ init = test = update = null;
+ expectKeyword('for');
+
+ // http://wiki.ecmascript.org/doku.php?id=proposals:iterators_and_generators&s=each
+ if (matchContextualKeyword("each")) {
+ throwError({}, Messages.EachNotAllowed);
+ }
+
+ expect('(');
+
+ if (match(';')) {
+ lex();
+ } else {
+ if (matchKeyword('var') || matchKeyword('let') || matchKeyword('const')) {
+ state.allowIn = false;
+ init = parseForVariableDeclaration();
+ state.allowIn = true;
+
+ if (init.declarations.length === 1) {
+ if (matchKeyword('in') || matchContextualKeyword('of')) {
+ operator = lookahead;
+ if (!((operator.value === 'in' || init.kind !== 'var') && init.declarations[0].init)) {
+ lex();
+ left = init;
+ right = parseExpression();
+ init = null;
+ }
+ }
+ }
+ } else {
+ state.allowIn = false;
+ init = parseExpression();
+ state.allowIn = true;
+
+ if (matchContextualKeyword('of')) {
+ operator = lex();
+ left = init;
+ right = parseExpression();
+ init = null;
+ } else if (matchKeyword('in')) {
+ // LeftHandSideExpression
+ if (!isAssignableLeftHandSide(init)) {
+ throwError({}, Messages.InvalidLHSInForIn);
+ }
+ operator = 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;
+
+ if (!(opts !== undefined && opts.ignore_body)) {
+ body = parseStatement();
+ }
+
+ state.inIteration = oldInIteration;
+
+ if (typeof left === 'undefined') {
+ return delegate.createForStatement(init, test, update, body);
+ }
+
+ if (operator.value === 'in') {
+ return delegate.createForInStatement(left, right, body);
+ }
+ return delegate.createForOfStatement(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) === 59) {
+ 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 (char #59).
+ if (source.charCodeAt(index) === 59) {
+ 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) === 32) {
+ 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) {
+ 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 = [],
+ sourceElement;
+
+ if (matchKeyword('default')) {
+ lex();
+ test = null;
+ } else {
+ expectKeyword('case');
+ test = parseExpression();
+ }
+ expect(':');
+
+ while (index < length) {
+ if (match('}') || matchKeyword('default') || matchKeyword('case')) {
+ break;
+ }
+ sourceElement = parseSourceElement();
+ if (typeof sourceElement === 'undefined') {
+ break;
+ }
+ consequent.push(sourceElement);
+ }
+
+ return delegate.createSwitchCase(test, consequent);
+ }
+
+ function parseSwitchStatement() {
+ var discriminant, cases, clause, oldInSwitch, defaultFound;
+
+ expectKeyword('switch');
+
+ expect('(');
+
+ discriminant = parseExpression();
+
+ expect(')');
+
+ expect('{');
+
+ 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;
+
+ expectKeyword('catch');
+
+ expect('(');
+ if (match(')')) {
+ throwUnexpected(lookahead);
+ }
+
+ param = parseExpression();
+ // 12.14.1
+ if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) {
+ throwErrorTolerant({}, Messages.StrictCatchVariable);
+ }
+
+ expect(')');
+ body = parseBlock();
+ return delegate.createCatchClause(param, body);
+ }
+
+ 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;
+
+ if (type === Token.EOF) {
+ throwUnexpected(lookahead);
+ }
+
+ if (type === Token.Punctuator) {
+ switch (lookahead.value) {
+ case ';':
+ return parseEmptyStatement();
+ case '{':
+ return parseBlock();
+ case '(':
+ return parseExpressionStatement();
+ default:
+ break;
+ }
+ }
+
+ if (type === Token.Keyword) {
+ switch (lookahead.value) {
+ case 'break':
+ return parseBreakStatement();
+ case 'continue':
+ return parseContinueStatement();
+ case 'debugger':
+ return parseDebuggerStatement();
+ case 'do':
+ return parseDoWhileStatement();
+ case 'for':
+ return parseForStatement();
+ case 'function':
+ return parseFunctionDeclaration();
+ case 'class':
+ return parseClassDeclaration();
+ case 'if':
+ return parseIfStatement();
+ case 'return':
+ return parseReturnStatement();
+ case 'switch':
+ return parseSwitchStatement();
+ case 'throw':
+ return parseThrowStatement();
+ case 'try':
+ return parseTryStatement();
+ case 'var':
+ return parseVariableStatement();
+ case 'while':
+ return parseWhileStatement();
+ case 'with':
+ return parseWithStatement();
+ 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.createLabeledStatement(expr, labeledBody);
+ }
+
+ consumeSemicolon();
+
+ return delegate.createExpressionStatement(expr);
+ }
+
+ // 13 Function Definition
+
+ function parseConciseBody() {
+ if (match('{')) {
+ return parseFunctionSourceElements();
+ }
+ return parseAssignmentExpression();
+ }
+
+ function parseFunctionSourceElements() {
+ var sourceElement, sourceElements = [], token, directive, firstRestricted,
+ oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesizedCount;
+
+ 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.range[0] + 1, token.range[1] - 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;
+ oldParenthesizedCount = state.parenthesizedCount;
+
+ state.labelSet = {};
+ state.inIteration = false;
+ state.inSwitch = false;
+ state.inFunctionBody = true;
+ state.parenthesizedCount = 0;
+
+ 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;
+ state.parenthesizedCount = oldParenthesizedCount;
+
+ return delegate.createBlockStatement(sourceElements);
+ }
+
+ function validateParam(options, param, name) {
+ var key = '$' + name;
+ if (strict) {
+ if (isRestrictedWord(name)) {
+ options.stricted = param;
+ options.message = Messages.StrictParamName;
+ }
+ if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
+ options.stricted = param;
+ options.message = Messages.StrictParamDupe;
+ }
+ } else if (!options.firstRestricted) {
+ if (isRestrictedWord(name)) {
+ options.firstRestricted = param;
+ options.message = Messages.StrictParamName;
+ } else if (isStrictModeReservedWord(name)) {
+ options.firstRestricted = param;
+ options.message = Messages.StrictReservedWord;
+ } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
+ options.firstRestricted = param;
+ options.message = Messages.StrictParamDupe;
+ }
+ }
+ options.paramSet[key] = true;
+ }
+
+ function parseParam(options) {
+ var token, rest, param;
+
+ token = lookahead;
+ if (token.value === '...') {
+ token = lex();
+ rest = true;
+ }
+
+ if (match('[')) {
+ param = parseArrayInitialiser();
+ reinterpretAsDestructuredParameter(options, param);
+ } else if (match('{')) {
+ if (rest) {
+ throwError({}, Messages.ObjectPatternAsRestParameter);
+ }
+ param = parseObjectInitialiser();
+ reinterpretAsDestructuredParameter(options, param);
+ } else {
+ param = parseVariableIdentifier();
+ validateParam(options, token, token.value);
+ }
+
+ if (rest) {
+ if (!match(')')) {
+ throwError({}, Messages.ParameterAfterRestParameter);
+ }
+ options.rest = param;
+ return false;
+ }
+
+ options.params.push(param);
+ return !match(')');
+ }
+
+ function parseParams(firstRestricted) {
+ var options;
+
+ options = {
+ params: [],
+ rest: null,
+ firstRestricted: firstRestricted
+ };
+
+ expect('(');
+
+ if (!match(')')) {
+ options.paramSet = {};
+ while (index < length) {
+ if (!parseParam(options)) {
+ break;
+ }
+ expect(',');
+ }
+ }
+
+ expect(')');
+
+ return options;
+ }
+
+ function parseFunctionDeclaration() {
+ var id, body, token, tmp, firstRestricted, message, previousStrict, previousYieldAllowed, generator, expression;
+
+ expectKeyword('function');
+
+ generator = false;
+ if (match('*')) {
+ lex();
+ generator = true;
+ }
+
+ 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);
+ firstRestricted = tmp.firstRestricted;
+ if (tmp.message) {
+ message = tmp.message;
+ }
+
+ previousStrict = strict;
+ previousYieldAllowed = state.yieldAllowed;
+ state.yieldAllowed = generator;
+
+ // here we redo some work in order to set 'expression'
+ expression = !match('{');
+ body = parseConciseBody();
+
+ if (strict && firstRestricted) {
+ throwError(firstRestricted, message);
+ }
+ if (strict && tmp.stricted) {
+ throwErrorTolerant(tmp.stricted, message);
+ }
+ if (state.yieldAllowed && !state.yieldFound) {
+ throwError({}, Messages.NoYieldInGenerator);
+ }
+ strict = previousStrict;
+ state.yieldAllowed = previousYieldAllowed;
+
+ return delegate.createFunctionDeclaration(id, tmp.params, [], body, tmp.rest, generator, expression);
+ }
+
+ function parseFunctionExpression() {
+ var token, id = null, firstRestricted, message, tmp, body, previousStrict, previousYieldAllowed, generator, expression;
+
+ expectKeyword('function');
+
+ generator = false;
+
+ if (match('*')) {
+ lex();
+ generator = true;
+ }
+
+ 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);
+ firstRestricted = tmp.firstRestricted;
+ if (tmp.message) {
+ message = tmp.message;
+ }
+
+ previousStrict = strict;
+ previousYieldAllowed = state.yieldAllowed;
+ state.yieldAllowed = generator;
+
+ // here we redo some work in order to set 'expression'
+ expression = !match('{');
+ body = parseConciseBody();
+
+ if (strict && firstRestricted) {
+ throwError(firstRestricted, message);
+ }
+ if (strict && tmp.stricted) {
+ throwErrorTolerant(tmp.stricted, message);
+ }
+ if (state.yieldAllowed && !state.yieldFound) {
+ throwError({}, Messages.NoYieldInGenerator);
+ }
+ strict = previousStrict;
+ state.yieldAllowed = previousYieldAllowed;
+
+ return delegate.createFunctionExpression(id, tmp.params, [], body, tmp.rest, generator, expression);
+ }
+
+ function parseYieldExpression() {
+ var delegateFlag, expr, previousYieldAllowed;
+
+ expectKeyword('yield');
+
+ if (!state.yieldAllowed) {
+ throwErrorTolerant({}, Messages.IllegalYield);
+ }
+
+ delegateFlag = false;
+ if (match('*')) {
+ lex();
+ delegateFlag = true;
+ }
+
+ // It is a Syntax Error if any AssignmentExpression Contains YieldExpression.
+ previousYieldAllowed = state.yieldAllowed;
+ state.yieldAllowed = false;
+ expr = parseAssignmentExpression();
+ state.yieldAllowed = previousYieldAllowed;
+ state.yieldFound = true;
+
+ return delegate.createYieldExpression(expr, delegateFlag);
+ }
+
+ // 14 Classes
+
+ function parseMethodDefinition(existingPropNames) {
+ var token, key, param, propType, isValidDuplicateProp = false;
+
+ if (lookahead.value === 'static') {
+ propType = ClassPropertyType.static;
+ lex();
+ } else {
+ propType = ClassPropertyType.prototype;
+ }
+
+ if (match('*')) {
+ lex();
+ return delegate.createMethodDefinition(
+ propType,
+ '',
+ parseObjectPropertyKey(),
+ parsePropertyMethodFunction({ generator: true })
+ );
+ }
+
+ token = lookahead;
+ key = parseObjectPropertyKey();
+
+ if (token.value === 'get' && !match('(')) {
+ key = parseObjectPropertyKey();
+
+ // It is a syntax error if any other properties have a name
+ // duplicating this one unless they are a setter
+ if (existingPropNames[propType].hasOwnProperty(key.name)) {
+ isValidDuplicateProp =
+ // There isn't already a getter for this prop
+ existingPropNames[propType][key.name].get === undefined
+ // There isn't already a data prop by this name
+ && existingPropNames[propType][key.name].data === undefined
+ // The only existing prop by this name is a setter
+ && existingPropNames[propType][key.name].set !== undefined;
+ if (!isValidDuplicateProp) {
+ throwError(key, Messages.IllegalDuplicateClassProperty);
+ }
+ } else {
+ existingPropNames[propType][key.name] = {};
+ }
+ existingPropNames[propType][key.name].get = true;
+
+ expect('(');
+ expect(')');
+ return delegate.createMethodDefinition(
+ propType,
+ 'get',
+ key,
+ parsePropertyFunction({ generator: false })
+ );
+ }
+ if (token.value === 'set' && !match('(')) {
+ key = parseObjectPropertyKey();
+
+ // It is a syntax error if any other properties have a name
+ // duplicating this one unless they are a getter
+ if (existingPropNames[propType].hasOwnProperty(key.name)) {
+ isValidDuplicateProp =
+ // There isn't already a setter for this prop
+ existingPropNames[propType][key.name].set === undefined
+ // There isn't already a data prop by this name
+ && existingPropNames[propType][key.name].data === undefined
+ // The only existing prop by this name is a getter
+ && existingPropNames[propType][key.name].get !== undefined;
+ if (!isValidDuplicateProp) {
+ throwError(key, Messages.IllegalDuplicateClassProperty);
+ }
+ } else {
+ existingPropNames[propType][key.name] = {};
+ }
+ existingPropNames[propType][key.name].set = true;
+
+ expect('(');
+ token = lookahead;
+ param = [ parseVariableIdentifier() ];
+ expect(')');
+ return delegate.createMethodDefinition(
+ propType,
+ 'set',
+ key,
+ parsePropertyFunction({ params: param, generator: false, name: token })
+ );
+ }
+
+ // It is a syntax error if any other properties have the same name as a
+ // non-getter, non-setter method
+ if (existingPropNames[propType].hasOwnProperty(key.name)) {
+ throwError(key, Messages.IllegalDuplicateClassProperty);
+ } else {
+ existingPropNames[propType][key.name] = {};
+ }
+ existingPropNames[propType][key.name].data = true;
+
+ return delegate.createMethodDefinition(
+ propType,
+ '',
+ key,
+ parsePropertyMethodFunction({ generator: false })
+ );
+ }
+
+ function parseClassElement(existingProps) {
+ if (match(';')) {
+ lex();
+ return;
+ }
+ return parseMethodDefinition(existingProps);
+ }
+
+ function parseClassBody() {
+ var classElement, classElements = [], existingProps = {};
+
+ existingProps[ClassPropertyType.static] = {};
+ existingProps[ClassPropertyType.prototype] = {};
+
+ expect('{');
+
+ while (index < length) {
+ if (match('}')) {
+ break;
+ }
+ classElement = parseClassElement(existingProps);
+
+ if (typeof classElement !== 'undefined') {
+ classElements.push(classElement);
+ }
+ }
+
+ expect('}');
+
+ return delegate.createClassBody(classElements);
+ }
+
+ function parseClassExpression() {
+ var id, previousYieldAllowed, superClass = null;
+
+ expectKeyword('class');
+
+ if (!matchKeyword('extends') && !match('{')) {
+ id = parseVariableIdentifier();
+ }
+
+ if (matchKeyword('extends')) {
+ expectKeyword('extends');
+ previousYieldAllowed = state.yieldAllowed;
+ state.yieldAllowed = false;
+ superClass = parseAssignmentExpression();
+ state.yieldAllowed = previousYieldAllowed;
+ }
+
+ return delegate.createClassExpression(id, superClass, parseClassBody());
+ }
+
+ function parseClassDeclaration() {
+ var token, id, previousYieldAllowed, superClass = null;
+
+ expectKeyword('class');
+
+ token = lookahead;
+ id = parseVariableIdentifier();
+
+ if (matchKeyword('extends')) {
+ expectKeyword('extends');
+ previousYieldAllowed = state.yieldAllowed;
+ state.yieldAllowed = false;
+ superClass = parseAssignmentExpression();
+ state.yieldAllowed = previousYieldAllowed;
+ }
+
+ return delegate.createClassDeclaration(id, superClass, parseClassBody());
+ }
+
+ // 15 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 parseProgramElement() {
+ var lineNumber, token;
+
+ if (lookahead.type === Token.Keyword) {
+ switch (lookahead.value) {
+ case 'export':
+ return parseExportDeclaration();
+ case 'import':
+ return parseImportDeclaration();
+ }
+ }
+
+ if (lookahead.value === 'module' && lookahead.type === Token.Identifier) {
+ lineNumber = lookahead.lineNumber;
+ token = lookahead2();
+ if (token.type === Token.Identifier && token.lineNumber === lineNumber) {
+ return parseModuleDeclaration();
+ }
+ }
+
+ return parseSourceElement();
+ }
+
+ function parseProgramElements() {
+ var sourceElement, sourceElements = [], token, directive, firstRestricted;
+
+ while (index < length) {
+ token = lookahead;
+ if (token.type !== Token.StringLiteral) {
+ break;
+ }
+
+ sourceElement = parseProgramElement();
+ sourceElements.push(sourceElement);
+ if (sourceElement.expression.type !== Syntax.Literal) {
+ // this is not directive
+ break;
+ }
+ directive = source.slice(token.range[0] + 1, token.range[1] - 1);
+ if (directive === 'use strict') {
+ strict = true;
+ if (firstRestricted) {
+ throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
+ }
+ } else {
+ if (!firstRestricted && token.octal) {
+ firstRestricted = token;
+ }
+ }
+ }
+
+ while (index < length) {
+ sourceElement = parseProgramElement();
+ if (typeof sourceElement === 'undefined') {
+ break;
+ }
+ sourceElements.push(sourceElement);
+ }
+ return sourceElements;
+ }
+
+ function parseModuleElement() {
+ return parseProgramElement();
+ }
+
+ function parseModuleElements() {
+ var list = [],
+ statement;
+
+ while (index < length) {
+ if (match('}')) {
+ break;
+ }
+ statement = parseModuleElement();
+ if (typeof statement === 'undefined') {
+ break;
+ }
+ list.push(statement);
+ }
+
+ return list;
+ }
+
+ function parseModuleBlock() {
+ var block;
+
+ expect('{');
+
+ block = parseModuleElements();
+
+ expect('}');
+
+ return delegate.createBlockStatement(block);
+ }
+
+ function parseProgram() {
+ var body;
+ strict = false;
+ peek();
+ body = parseProgramElements();
+ return delegate.createProgram(body);
+ }
+
+ // The following functions are needed only when the option to preserve
+ // the comments is active.
+
+ function addComment(type, value, start, end, loc) {
+ 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 (extra.comments.length > 0) {
+ if (extra.comments[extra.comments.length - 1].range[1] > start) {
+ return;
+ }
+ }
+
+ extra.comments.push({
+ type: type,
+ value: value,
+ range: [start, end],
+ loc: loc
+ });
+ }
+
+ function scanComment() {
+ var comment, ch, loc, start, blockComment, lineComment;
+
+ comment = '';
+ blockComment = false;
+ lineComment = false;
+
+ while (index < length) {
+ ch = source[index];
+
+ if (lineComment) {
+ ch = source[index++];
+ if (isLineTerminator(ch.charCodeAt(0))) {
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart - 1
+ };
+ lineComment = false;
+ addComment('Line', comment, start, index - 1, loc);
+ if (ch === '\r' && source[index] === '\n') {
+ ++index;
+ }
+ ++lineNumber;
+ lineStart = index;
+ comment = '';
+ } else if (index >= length) {
+ lineComment = false;
+ comment += ch;
+ loc.end = {
+ line: lineNumber,
+ column: length - lineStart
+ };
+ addComment('Line', comment, start, length, loc);
+ } else {
+ comment += ch;
+ }
+ } else if (blockComment) {
+ if (isLineTerminator(ch.charCodeAt(0))) {
+ if (ch === '\r' && source[index + 1] === '\n') {
+ ++index;
+ comment += '\r\n';
+ } else {
+ comment += ch;
+ }
+ ++lineNumber;
+ ++index;
+ lineStart = index;
+ if (index >= length) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ } else {
+ ch = source[index++];
+ if (index >= length) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ comment += ch;
+ if (ch === '*') {
+ ch = source[index];
+ if (ch === '/') {
+ comment = comment.substr(0, comment.length - 1);
+ blockComment = false;
+ ++index;
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart
+ };
+ addComment('Block', comment, start, index, loc);
+ comment = '';
+ }
+ }
+ }
+ } else if (ch === '/') {
+ ch = source[index + 1];
+ if (ch === '/') {
+ loc = {
+ start: {
+ line: lineNumber,
+ column: index - lineStart
+ }
+ };
+ start = index;
+ index += 2;
+ lineComment = true;
+ if (index >= length) {
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart
+ };
+ lineComment = false;
+ addComment('Line', comment, start, index, loc);
+ }
+ } else if (ch === '*') {
+ start = index;
+ index += 2;
+ blockComment = true;
+ loc = {
+ start: {
+ line: lineNumber,
+ column: index - lineStart - 2
+ }
+ };
+ if (index >= length) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ } else {
+ break;
+ }
+ } else if (isWhiteSpace(ch.charCodeAt(0))) {
+ ++index;
+ } else if (isLineTerminator(ch.charCodeAt(0))) {
+ ++index;
+ if (ch === '\r' && source[index] === '\n') {
+ ++index;
+ }
+ ++lineNumber;
+ lineStart = index;
+ } else {
+ break;
+ }
+ }
+ }
+
+ function filterCommentLocation() {
+ var i, entry, comment, comments = [];
+
+ for (i = 0; i < extra.comments.length; ++i) {
+ entry = extra.comments[i];
+ comment = {
+ type: entry.type,
+ value: entry.value
+ };
+ if (extra.range) {
+ comment.range = entry.range;
+ }
+ if (extra.loc) {
+ comment.loc = entry.loc;
+ }
+ comments.push(comment);
+ }
+
+ extra.comments = comments;
+ }
+
+ // 16 XJS
+
+ XHTMLEntities = {
+ quot: '\u0022',
+ amp: '&',
+ apos: "\u0027",
+ lt: "<",
+ gt: ">",
+ nbsp: "\u00A0",
+ iexcl: "\u00A1",
+ cent: "\u00A2",
+ pound: "\u00A3",
+ curren: "\u00A4",
+ yen: "\u00A5",
+ brvbar: "\u00A6",
+ sect: "\u00A7",
+ uml: "\u00A8",
+ copy: "\u00A9",
+ ordf: "\u00AA",
+ laquo: "\u00AB",
+ not: "\u00AC",
+ shy: "\u00AD",
+ reg: "\u00AE",
+ macr: "\u00AF",
+ deg: "\u00B0",
+ plusmn: "\u00B1",
+ sup2: "\u00B2",
+ sup3: "\u00B3",
+ acute: "\u00B4",
+ micro: "\u00B5",
+ para: "\u00B6",
+ middot: "\u00B7",
+ cedil: "\u00B8",
+ sup1: "\u00B9",
+ ordm: "\u00BA",
+ raquo: "\u00BB",
+ frac14: "\u00BC",
+ frac12: "\u00BD",
+ frac34: "\u00BE",
+ iquest: "\u00BF",
+ Agrave: "\u00C0",
+ Aacute: "\u00C1",
+ Acirc: "\u00C2",
+ Atilde: "\u00C3",
+ Auml: "\u00C4",
+ Aring: "\u00C5",
+ AElig: "\u00C6",
+ Ccedil: "\u00C7",
+ Egrave: "\u00C8",
+ Eacute: "\u00C9",
+ Ecirc: "\u00CA",
+ Euml: "\u00CB",
+ Igrave: "\u00CC",
+ Iacute: "\u00CD",
+ Icirc: "\u00CE",
+ Iuml: "\u00CF",
+ ETH: "\u00D0",
+ Ntilde: "\u00D1",
+ Ograve: "\u00D2",
+ Oacute: "\u00D3",
+ Ocirc: "\u00D4",
+ Otilde: "\u00D5",
+ Ouml: "\u00D6",
+ times: "\u00D7",
+ Oslash: "\u00D8",
+ Ugrave: "\u00D9",
+ Uacute: "\u00DA",
+ Ucirc: "\u00DB",
+ Uuml: "\u00DC",
+ Yacute: "\u00DD",
+ THORN: "\u00DE",
+ szlig: "\u00DF",
+ agrave: "\u00E0",
+ aacute: "\u00E1",
+ acirc: "\u00E2",
+ atilde: "\u00E3",
+ auml: "\u00E4",
+ aring: "\u00E5",
+ aelig: "\u00E6",
+ ccedil: "\u00E7",
+ egrave: "\u00E8",
+ eacute: "\u00E9",
+ ecirc: "\u00EA",
+ euml: "\u00EB",
+ igrave: "\u00EC",
+ iacute: "\u00ED",
+ icirc: "\u00EE",
+ iuml: "\u00EF",
+ eth: "\u00F0",
+ ntilde: "\u00F1",
+ ograve: "\u00F2",
+ oacute: "\u00F3",
+ ocirc: "\u00F4",
+ otilde: "\u00F5",
+ ouml: "\u00F6",
+ divide: "\u00F7",
+ oslash: "\u00F8",
+ ugrave: "\u00F9",
+ uacute: "\u00FA",
+ ucirc: "\u00FB",
+ uuml: "\u00FC",
+ yacute: "\u00FD",
+ thorn: "\u00FE",
+ yuml: "\u00FF",
+ OElig: "\u0152",
+ oelig: "\u0153",
+ Scaron: "\u0160",
+ scaron: "\u0161",
+ Yuml: "\u0178",
+ fnof: "\u0192",
+ circ: "\u02C6",
+ tilde: "\u02DC",
+ Alpha: "\u0391",
+ Beta: "\u0392",
+ Gamma: "\u0393",
+ Delta: "\u0394",
+ Epsilon: "\u0395",
+ Zeta: "\u0396",
+ Eta: "\u0397",
+ Theta: "\u0398",
+ Iota: "\u0399",
+ Kappa: "\u039A",
+ Lambda: "\u039B",
+ Mu: "\u039C",
+ Nu: "\u039D",
+ Xi: "\u039E",
+ Omicron: "\u039F",
+ Pi: "\u03A0",
+ Rho: "\u03A1",
+ Sigma: "\u03A3",
+ Tau: "\u03A4",
+ Upsilon: "\u03A5",
+ Phi: "\u03A6",
+ Chi: "\u03A7",
+ Psi: "\u03A8",
+ Omega: "\u03A9",
+ alpha: "\u03B1",
+ beta: "\u03B2",
+ gamma: "\u03B3",
+ delta: "\u03B4",
+ epsilon: "\u03B5",
+ zeta: "\u03B6",
+ eta: "\u03B7",
+ theta: "\u03B8",
+ iota: "\u03B9",
+ kappa: "\u03BA",
+ lambda: "\u03BB",
+ mu: "\u03BC",
+ nu: "\u03BD",
+ xi: "\u03BE",
+ omicron: "\u03BF",
+ pi: "\u03C0",
+ rho: "\u03C1",
+ sigmaf: "\u03C2",
+ sigma: "\u03C3",
+ tau: "\u03C4",
+ upsilon: "\u03C5",
+ phi: "\u03C6",
+ chi: "\u03C7",
+ psi: "\u03C8",
+ omega: "\u03C9",
+ thetasym: "\u03D1",
+ upsih: "\u03D2",
+ piv: "\u03D6",
+ ensp: "\u2002",
+ emsp: "\u2003",
+ thinsp: "\u2009",
+ zwnj: "\u200C",
+ zwj: "\u200D",
+ lrm: "\u200E",
+ rlm: "\u200F",
+ ndash: "\u2013",
+ mdash: "\u2014",
+ lsquo: "\u2018",
+ rsquo: "\u2019",
+ sbquo: "\u201A",
+ ldquo: "\u201C",
+ rdquo: "\u201D",
+ bdquo: "\u201E",
+ dagger: "\u2020",
+ Dagger: "\u2021",
+ bull: "\u2022",
+ hellip: "\u2026",
+ permil: "\u2030",
+ prime: "\u2032",
+ Prime: "\u2033",
+ lsaquo: "\u2039",
+ rsaquo: "\u203A",
+ oline: "\u203E",
+ frasl: "\u2044",
+ euro: "\u20AC",
+ image: "\u2111",
+ weierp: "\u2118",
+ real: "\u211C",
+ trade: "\u2122",
+ alefsym: "\u2135",
+ larr: "\u2190",
+ uarr: "\u2191",
+ rarr: "\u2192",
+ darr: "\u2193",
+ harr: "\u2194",
+ crarr: "\u21B5",
+ lArr: "\u21D0",
+ uArr: "\u21D1",
+ rArr: "\u21D2",
+ dArr: "\u21D3",
+ hArr: "\u21D4",
+ forall: "\u2200",
+ part: "\u2202",
+ exist: "\u2203",
+ empty: "\u2205",
+ nabla: "\u2207",
+ isin: "\u2208",
+ notin: "\u2209",
+ ni: "\u220B",
+ prod: "\u220F",
+ sum: "\u2211",
+ minus: "\u2212",
+ lowast: "\u2217",
+ radic: "\u221A",
+ prop: "\u221D",
+ infin: "\u221E",
+ ang: "\u2220",
+ and: "\u2227",
+ or: "\u2228",
+ cap: "\u2229",
+ cup: "\u222A",
+ "int": "\u222B",
+ there4: "\u2234",
+ sim: "\u223C",
+ cong: "\u2245",
+ asymp: "\u2248",
+ ne: "\u2260",
+ equiv: "\u2261",
+ le: "\u2264",
+ ge: "\u2265",
+ sub: "\u2282",
+ sup: "\u2283",
+ nsub: "\u2284",
+ sube: "\u2286",
+ supe: "\u2287",
+ oplus: "\u2295",
+ otimes: "\u2297",
+ perp: "\u22A5",
+ sdot: "\u22C5",
+ lceil: "\u2308",
+ rceil: "\u2309",
+ lfloor: "\u230A",
+ rfloor: "\u230B",
+ lang: "\u2329",
+ rang: "\u232A",
+ loz: "\u25CA",
+ spades: "\u2660",
+ clubs: "\u2663",
+ hearts: "\u2665",
+ diams: "\u2666"
+ };
+
+ function isXJSIdentifierStart(ch) {
+ // exclude backslash (\)
+ return (ch !== 92) && isIdentifierStart(ch);
+ }
+
+ function isXJSIdentifierPart(ch) {
+ // exclude backslash (\) and add hyphen (-)
+ return (ch !== 92) && (ch === 45 || isIdentifierPart(ch));
+ }
+
+ function scanXJSIdentifier() {
+ var ch, start, id = '', namespace;
+
+ start = index;
+ while (index < length) {
+ ch = source.charCodeAt(index);
+ if (!isXJSIdentifierPart(ch)) {
+ break;
+ }
+ id += source[index++];
+ }
+
+ if (ch === 58) { // :
+ ++index;
+ namespace = id;
+ id = '';
+
+ while (index < length) {
+ ch = source.charCodeAt(index);
+ if (!isXJSIdentifierPart(ch)) {
+ break;
+ }
+ id += source[index++];
+ }
+ }
+
+ if (!id) {
+ throwError({}, Messages.InvalidXJSTagName);
+ }
+
+ return {
+ type: Token.XJSIdentifier,
+ value: id,
+ namespace: namespace,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+
+ function scanXJSEntity() {
+ var ch, str = '', count = 0, entity;
+ ch = source[index];
+ assert(ch === '&', 'Entity must start with an ampersand');
+ index++;
+ while (index < length && count++ < 10) {
+ ch = source[index++];
+ if (ch === ';') {
+ break;
+ }
+ str += ch;
+ }
+
+ if (str[0] === '#' && str[1] === 'x') {
+ entity = String.fromCharCode(parseInt(str.substr(2), 16));
+ } else if (str[0] === '#') {
+ entity = String.fromCharCode(parseInt(str.substr(1), 10));
+ } else {
+ entity = XHTMLEntities[str];
+ }
+ return entity;
+ }
+
+ function scanXJSText(stopChars) {
+ var ch, str = '', start;
+ start = index;
+ while (index < length) {
+ ch = source[index];
+ if (stopChars.indexOf(ch) !== -1) {
+ break;
+ }
+ if (ch === '&') {
+ str += scanXJSEntity();
+ } else {
+ ch = source[index++];
+ if (isLineTerminator(ch.charCodeAt(0))) {
+ ++lineNumber;
+ lineStart = index;
+ }
+ str += ch;
+ }
+ }
+ return {
+ type: Token.XJSText,
+ value: str,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ range: [start, index]
+ };
+ }
+
+ function scanXJSStringLiteral() {
+ var innerToken, quote, start;
+
+ quote = source[index];
+ assert((quote === '\'' || quote === '"'),
+ 'String literal must starts with a quote');
+
+ start = index;
+ ++index;
+
+ innerToken = scanXJSText([quote]);
+
+ if (quote !== source[index]) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ ++index;
+
+ innerToken.range = [start, index];
+
+ return innerToken;
+ }
+
+ /**
+ * Between XJS opening and closing tags (e.g. <foo>HERE</foo>), anything that
+ * is not another XJS tag and is not an expression wrapped by {} is text.
+ */
+ function advanceXJSChild() {
+ var ch = source.charCodeAt(index);
+
+ // { (123) and < (60)
+ if (ch !== 123 && ch !== 60) {
+ return scanXJSText(['<', '{']);
+ }
+
+ return scanPunctuator();
+ }
+
+ function parseXJSIdentifier() {
+ var token;
+
+ if (lookahead.type !== Token.XJSIdentifier) {
+ throwError({}, Messages.InvalidXJSTagName);
+ }
+
+ token = lex();
+ return delegate.createXJSIdentifier(token.value, token.namespace);
+ }
+
+ function parseXJSAttributeValue() {
+ var value;
+ if (match('{')) {
+ value = parseXJSExpressionContainer();
+ if (value.expression.type === Syntax.XJSEmptyExpression) {
+ throwError(
+ value,
+ 'XJS attributes must only be assigned a non-empty ' +
+ 'expression'
+ );
+ }
+ } else if (lookahead.type === Token.XJSText) {
+ value = delegate.createLiteral(lex());
+ } else {
+ throwError({}, Messages.InvalidXJSAttributeValue);
+ }
+ return value;
+ }
+
+ function parseXJSEmptyExpression() {
+ while (source.charAt(index) !== '}') {
+ index++;
+ }
+ return delegate.createXJSEmptyExpression();
+ }
+
+ function parseXJSExpressionContainer() {
+ var expression, origInXJSChild, origInXJSTag;
+
+ origInXJSChild = state.inXJSChild;
+ origInXJSTag = state.inXJSTag;
+ state.inXJSChild = false;
+ state.inXJSTag = false;
+
+ expect('{');
+
+ if (match('}')) {
+ expression = parseXJSEmptyExpression();
+ } else {
+ expression = parseExpression();
+ }
+
+ state.inXJSChild = origInXJSChild;
+ state.inXJSTag = origInXJSTag;
+
+ expect('}');
+
+ return delegate.createXJSExpressionContainer(expression);
+ }
+
+ function parseXJSAttribute() {
+ var token, name, value;
+
+ name = parseXJSIdentifier();
+
+ // HTML empty attribute
+ if (match('=')) {
+ lex();
+ return delegate.createXJSAttribute(name, parseXJSAttributeValue());
+ }
+
+ return delegate.createXJSAttribute(name);
+ }
+
+ function parseXJSChild() {
+ var token;
+ if (match('{')) {
+ token = parseXJSExpressionContainer();
+ } else if (lookahead.type === Token.XJSText) {
+ token = delegate.createLiteral(lex());
+ } else {
+ state.inXJSChild = false;
+ token = parseXJSElement();
+ state.inXJSChild = true;
+ }
+ return token;
+ }
+
+ function parseXJSClosingElement() {
+ var name, origInXJSTag;
+ origInXJSTag = state.inXJSTag;
+ state.inXJSTag = true;
+ state.inXJSChild = false;
+ expect('<');
+ expect('/');
+ name = parseXJSIdentifier();
+ state.inXJSTag = origInXJSTag;
+ expect('>');
+ return delegate.createXJSClosingElement(name);
+ }
+
+ function parseXJSOpeningElement() {
+ var name, attribute, attributes = [], selfClosing = false, origInXJSTag;
+
+ origInXJSTag = state.inXJSTag;
+ state.inXJSTag = true;
+
+ expect('<');
+
+ name = parseXJSIdentifier();
+
+ while (index < length &&
+ lookahead.value !== '/' &&
+ lookahead.value !== '>') {
+ attributes.push(parseXJSAttribute());
+ }
+
+ state.inXJSTag = origInXJSTag;
+
+ if (lookahead.value === '/') {
+ expect('/');
+ expect('>');
+ selfClosing = true;
+ } else {
+ state.inXJSChild = true;
+ expect('>');
+ }
+ return delegate.createXJSOpeningElement(name, attributes, selfClosing);
+ }
+
+ function parseXJSElement() {
+ var openingElement, closingElement, children = [], origInXJSChild;
+
+ openingElement = parseXJSOpeningElement();
+
+ if (!openingElement.selfClosing) {
+ origInXJSChild = state.inXJSChild;
+ while (index < length) {
+ state.inXJSChild = false; // </ should not be considered in the child
+ if (lookahead.value === '<' && lookahead2().value === '/') {
+ break;
+ }
+ state.inXJSChild = true;
+ peek(); // reset lookahead token
+ children.push(parseXJSChild());
+ }
+ state.inXJSChild = origInXJSChild;
+ closingElement = parseXJSClosingElement();
+ if (closingElement.name.namespace !== openingElement.name.namespace || closingElement.name.name !== openingElement.name.name) {
+ throwError({}, Messages.ExpectedXJSClosingTag, openingElement.name.namespace ? openingElement.name.namespace + ':' + openingElement.name.name : openingElement.name.name);
+ }
+ }
+
+ return delegate.createXJSElement(openingElement, closingElement, children);
+ }
+
+ function collectToken() {
+ var start, loc, token, range, value;
+
+ skipComment();
+ start = index;
+ loc = {
+ start: {
+ line: lineNumber,
+ column: index - lineStart
+ }
+ };
+
+ token = extra.advance();
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart
+ };
+
+ if (token.type !== Token.EOF) {
+ range = [token.range[0], token.range[1]];
+ value = source.slice(token.range[0], token.range[1]);
+ extra.tokens.push({
+ type: TokenName[token.type],
+ value: value,
+ range: range,
+ loc: loc
+ });
+ }
+
+ return token;
+ }
+
+ function collectRegex() {
+ var pos, loc, regex, token;
+
+ skipComment();
+
+ pos = index;
+ loc = {
+ start: {
+ line: lineNumber,
+ column: index - lineStart
+ }
+ };
+
+ regex = extra.scanRegExp();
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart
+ };
+
+ 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 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 createLocationMarker() {
+ var marker = {};
+
+ marker.range = [index, index];
+ marker.loc = {
+ start: {
+ line: lineNumber,
+ column: index - lineStart
+ },
+ end: {
+ line: lineNumber,
+ column: index - lineStart
+ }
+ };
+
+ marker.end = function () {
+ this.range[1] = index;
+ this.loc.end.line = lineNumber;
+ this.loc.end.column = index - lineStart;
+ };
+
+ marker.applyGroup = function (node) {
+ if (extra.range) {
+ node.groupRange = [this.range[0], this.range[1]];
+ }
+ if (extra.loc) {
+ node.groupLoc = {
+ start: {
+ line: this.loc.start.line,
+ column: this.loc.start.column
+ },
+ end: {
+ line: this.loc.end.line,
+ column: this.loc.end.column
+ }
+ };
+ node = delegate.postProcess(node);
+ }
+ };
+
+ marker.apply = function (node) {
+ var nodeType = typeof node;
+ assert(nodeType === "object",
+ "Applying location marker to an unexpected node type: " +
+ nodeType);
+
+ if (extra.range) {
+ node.range = [this.range[0], this.range[1]];
+ }
+ if (extra.loc) {
+ node.loc = {
+ start: {
+ line: this.loc.start.line,
+ column: this.loc.start.column
+ },
+ end: {
+ line: this.loc.end.line,
+ column: this.loc.end.column
+ }
+ };
+ node = delegate.postProcess(node);
+ }
+ };
+
+ return marker;
+ }
+
+ function trackGroupExpression() {
+ var marker, expr;
+
+ skipComment();
+ marker = createLocationMarker();
+ expect('(');
+
+ ++state.parenthesizedCount;
+
+ state.allowArrowFunction = !state.allowArrowFunction;
+ expr = parseExpression();
+ state.allowArrowFunction = false;
+
+ if (expr.type === 'ArrowFunctionExpression') {
+ marker.end();
+ marker.apply(expr);
+ } else {
+ expect(')');
+ marker.end();
+ marker.applyGroup(expr);
+ }
+
+ return expr;
+ }
+
+ function trackLeftHandSideExpression() {
+ var marker, expr;
+
+ skipComment();
+ marker = createLocationMarker();
+
+ expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
+
+ while (match('.') || match('[') || lookahead.type === Token.Template) {
+ if (match('[')) {
+ expr = delegate.createMemberExpression('[', expr, parseComputedMember());
+ marker.end();
+ marker.apply(expr);
+ } else if (match('.')) {
+ expr = delegate.createMemberExpression('.', expr, parseNonComputedMember());
+ marker.end();
+ marker.apply(expr);
+ } else {
+ expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral());
+ marker.end();
+ marker.apply(expr);
+ }
+ }
+
+ return expr;
+ }
+
+ function trackLeftHandSideExpressionAllowCall() {
+ var marker, expr, args;
+
+ skipComment();
+ marker = createLocationMarker();
+
+ expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
+
+ while (match('.') || match('[') || match('(') || lookahead.type === Token.Template) {
+ if (match('(')) {
+ args = parseArguments();
+ expr = delegate.createCallExpression(expr, args);
+ marker.end();
+ marker.apply(expr);
+ } else if (match('[')) {
+ expr = delegate.createMemberExpression('[', expr, parseComputedMember());
+ marker.end();
+ marker.apply(expr);
+ } else if (match('.')) {
+ expr = delegate.createMemberExpression('.', expr, parseNonComputedMember());
+ marker.end();
+ marker.apply(expr);
+ } else {
+ expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral());
+ marker.end();
+ marker.apply(expr);
+ }
+ }
+
+ return expr;
+ }
+
+ function filterGroup(node) {
+ var n, i, entry;
+
+ n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {};
+ for (i in node) {
+ if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') {
+ entry = node[i];
+ if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) {
+ n[i] = entry;
+ } else {
+ n[i] = filterGroup(entry);
+ }
+ }
+ }
+ return n;
+ }
+
+ function wrapTrackingFunction(range, loc, preserveWhitespace) {
+
+ return function (parseFunction) {
+
+ function isBinary(node) {
+ return node.type === Syntax.LogicalExpression ||
+ node.type === Syntax.BinaryExpression;
+ }
+
+ function visit(node) {
+ var start, end;
+
+ if (isBinary(node.left)) {
+ visit(node.left);
+ }
+ if (isBinary(node.right)) {
+ visit(node.right);
+ }
+
+ if (range) {
+ if (node.left.groupRange || node.right.groupRange) {
+ start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0];
+ end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1];
+ node.range = [start, end];
+ } else if (typeof node.range === 'undefined') {
+ start = node.left.range[0];
+ end = node.right.range[1];
+ node.range = [start, end];
+ }
+ }
+ if (loc) {
+ if (node.left.groupLoc || node.right.groupLoc) {
+ start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start;
+ end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end;
+ node.loc = {
+ start: start,
+ end: end
+ };
+ node = delegate.postProcess(node);
+ } else if (typeof node.loc === 'undefined') {
+ node.loc = {
+ start: node.left.loc.start,
+ end: node.right.loc.end
+ };
+ node = delegate.postProcess(node);
+ }
+ }
+ }
+
+ return function () {
+ var marker, node;
+
+ if (!preserveWhitespace) {
+ skipComment();
+ }
+
+ marker = createLocationMarker();
+ node = parseFunction.apply(null, arguments);
+ marker.end();
+
+ if (range && typeof node.range === 'undefined') {
+ marker.apply(node);
+ }
+
+ if (loc && typeof node.loc === 'undefined') {
+ marker.apply(node);
+ }
+
+ if (isBinary(node)) {
+ visit(node);
+ }
+
+ return node;
+ };
+ };
+ }
+
+ function patch() {
+
+ var wrapTracking, wrapTrackingPreserveWhitespace;
+
+ if (extra.comments) {
+ extra.skipComment = skipComment;
+ skipComment = scanComment;
+ }
+
+ if (extra.range || extra.loc) {
+
+ extra.parseGroupExpression = parseGroupExpression;
+ extra.parseLeftHandSideExpression = parseLeftHandSideExpression;
+ extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall;
+ parseGroupExpression = trackGroupExpression;
+ parseLeftHandSideExpression = trackLeftHandSideExpression;
+ parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall;
+
+ wrapTracking = wrapTrackingFunction(extra.range, extra.loc);
+ wrapTrackingPreserveWhitespace =
+ wrapTrackingFunction(extra.range, extra.loc, true);
+
+ extra.parseAssignmentExpression = parseAssignmentExpression;
+ extra.parseBinaryExpression = parseBinaryExpression;
+ extra.parseBlock = parseBlock;
+ extra.parseFunctionSourceElements = parseFunctionSourceElements;
+ extra.parseCatchClause = parseCatchClause;
+ extra.parseComputedMember = parseComputedMember;
+ extra.parseConditionalExpression = parseConditionalExpression;
+ extra.parseConstLetDeclaration = parseConstLetDeclaration;
+ extra.parseExportDeclaration = parseExportDeclaration;
+ extra.parseExportSpecifier = parseExportSpecifier;
+ extra.parseExportSpecifierSetProperty = parseExportSpecifierSetProperty;
+ extra.parseExpression = parseExpression;
+ extra.parseForVariableDeclaration = parseForVariableDeclaration;
+ extra.parseFunctionDeclaration = parseFunctionDeclaration;
+ extra.parseFunctionExpression = parseFunctionExpression;
+ extra.parseParams = parseParams;
+ extra.parseGlob = parseGlob;
+ extra.parseImportDeclaration = parseImportDeclaration;
+ extra.parseImportSpecifier = parseImportSpecifier;
+ extra.parseModuleDeclaration = parseModuleDeclaration;
+ extra.parseModuleBlock = parseModuleBlock;
+ extra.parseNewExpression = parseNewExpression;
+ extra.parseNonComputedProperty = parseNonComputedProperty;
+ extra.parseObjectProperty = parseObjectProperty;
+ extra.parseObjectPropertyKey = parseObjectPropertyKey;
+ extra.parsePath = parsePath;
+ extra.parsePostfixExpression = parsePostfixExpression;
+ extra.parsePrimaryExpression = parsePrimaryExpression;
+ extra.parseProgram = parseProgram;
+ extra.parsePropertyFunction = parsePropertyFunction;
+ extra.parseSpreadOrAssignmentExpression = parseSpreadOrAssignmentExpression;
+ extra.parseTemplateElement = parseTemplateElement;
+ extra.parseTemplateLiteral = parseTemplateLiteral;
+ extra.parseStatement = parseStatement;
+ extra.parseSwitchCase = parseSwitchCase;
+ extra.parseUnaryExpression = parseUnaryExpression;
+ extra.parseVariableDeclaration = parseVariableDeclaration;
+ extra.parseVariableIdentifier = parseVariableIdentifier;
+ extra.parseMethodDefinition = parseMethodDefinition;
+ extra.parseClassDeclaration = parseClassDeclaration;
+ extra.parseClassExpression = parseClassExpression;
+ extra.parseClassBody = parseClassBody;
+ extra.parseXJSIdentifier = parseXJSIdentifier;
+ extra.parseXJSChild = parseXJSChild;
+ extra.parseXJSAttribute = parseXJSAttribute;
+ extra.parseXJSAttributeValue = parseXJSAttributeValue;
+ extra.parseXJSExpressionContainer = parseXJSExpressionContainer;
+ extra.parseXJSEmptyExpression = parseXJSEmptyExpression;
+ extra.parseXJSElement = parseXJSElement;
+ extra.parseXJSClosingElement = parseXJSClosingElement;
+ extra.parseXJSOpeningElement = parseXJSOpeningElement;
+
+ parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression);
+ parseBinaryExpression = wrapTracking(extra.parseBinaryExpression);
+ parseBlock = wrapTracking(extra.parseBlock);
+ parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements);
+ parseCatchClause = wrapTracking(extra.parseCatchClause);
+ parseComputedMember = wrapTracking(extra.parseComputedMember);
+ parseConditionalExpression = wrapTracking(extra.parseConditionalExpression);
+ parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration);
+ parseExportDeclaration = wrapTracking(parseExportDeclaration);
+ parseExportSpecifier = wrapTracking(parseExportSpecifier);
+ parseExportSpecifierSetProperty = wrapTracking(parseExportSpecifierSetProperty);
+ parseExpression = wrapTracking(extra.parseExpression);
+ parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration);
+ parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration);
+ parseFunctionExpression = wrapTracking(extra.parseFunctionExpression);
+ parseParams = wrapTracking(extra.parseParams);
+ parseGlob = wrapTracking(extra.parseGlob);
+ parseImportDeclaration = wrapTracking(extra.parseImportDeclaration);
+ parseImportSpecifier = wrapTracking(extra.parseImportSpecifier);
+ parseModuleDeclaration = wrapTracking(extra.parseModuleDeclaration);
+ parseModuleBlock = wrapTracking(extra.parseModuleBlock);
+ parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression);
+ parseNewExpression = wrapTracking(extra.parseNewExpression);
+ parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty);
+ parseObjectProperty = wrapTracking(extra.parseObjectProperty);
+ parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey);
+ parsePath = wrapTracking(extra.parsePath);
+ parsePostfixExpression = wrapTracking(extra.parsePostfixExpression);
+ parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression);
+ parseProgram = wrapTracking(extra.parseProgram);
+ parsePropertyFunction = wrapTracking(extra.parsePropertyFunction);
+ parseTemplateElement = wrapTracking(extra.parseTemplateElement);
+ parseTemplateLiteral = wrapTracking(extra.parseTemplateLiteral);
+ parseSpreadOrAssignmentExpression = wrapTracking(extra.parseSpreadOrAssignmentExpression);
+ parseStatement = wrapTracking(extra.parseStatement);
+ parseSwitchCase = wrapTracking(extra.parseSwitchCase);
+ parseUnaryExpression = wrapTracking(extra.parseUnaryExpression);
+ parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration);
+ parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier);
+ parseMethodDefinition = wrapTracking(extra.parseMethodDefinition);
+ parseClassDeclaration = wrapTracking(extra.parseClassDeclaration);
+ parseClassExpression = wrapTracking(extra.parseClassExpression);
+ parseClassBody = wrapTracking(extra.parseClassBody);
+ parseXJSIdentifier = wrapTracking(extra.parseXJSIdentifier);
+ parseXJSChild = wrapTrackingPreserveWhitespace(extra.parseXJSChild);
+ parseXJSAttribute = wrapTracking(extra.parseXJSAttribute);
+ parseXJSAttributeValue = wrapTracking(extra.parseXJSAttributeValue);
+ parseXJSExpressionContainer = wrapTracking(extra.parseXJSExpressionContainer);
+ parseXJSEmptyExpression = wrapTrackingPreserveWhitespace(extra.parseXJSEmptyExpression);
+ parseXJSElement = wrapTracking(extra.parseXJSElement);
+ parseXJSClosingElement = wrapTracking(extra.parseXJSClosingElement);
+ parseXJSOpeningElement = wrapTracking(extra.parseXJSOpeningElement);
+ }
+
+ if (typeof extra.tokens !== 'undefined') {
+ extra.advance = advance;
+ extra.scanRegExp = scanRegExp;
+
+ advance = collectToken;
+ scanRegExp = collectRegex;
+ }
+ }
+
+ function unpatch() {
+ if (typeof extra.skipComment === 'function') {
+ skipComment = extra.skipComment;
+ }
+
+ if (extra.range || extra.loc) {
+ parseAssignmentExpression = extra.parseAssignmentExpression;
+ parseBinaryExpression = extra.parseBinaryExpression;
+ parseBlock = extra.parseBlock;
+ parseFunctionSourceElements = extra.parseFunctionSourceElements;
+ parseCatchClause = extra.parseCatchClause;
+ parseComputedMember = extra.parseComputedMember;
+ parseConditionalExpression = extra.parseConditionalExpression;
+ parseConstLetDeclaration = extra.parseConstLetDeclaration;
+ parseExportDeclaration = extra.parseExportDeclaration;
+ parseExportSpecifier = extra.parseExportSpecifier;
+ parseExportSpecifierSetProperty = extra.parseExportSpecifierSetProperty;
+ parseExpression = extra.parseExpression;
+ parseForVariableDeclaration = extra.parseForVariableDeclaration;
+ parseFunctionDeclaration = extra.parseFunctionDeclaration;
+ parseFunctionExpression = extra.parseFunctionExpression;
+ parseGlob = extra.parseGlob;
+ parseImportDeclaration = extra.parseImportDeclaration;
+ parseImportSpecifier = extra.parseImportSpecifier;
+ parseGroupExpression = extra.parseGroupExpression;
+ parseLeftHandSideExpression = extra.parseLeftHandSideExpression;
+ parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall;
+ parseModuleDeclaration = extra.parseModuleDeclaration;
+ parseModuleBlock = extra.parseModuleBlock;
+ parseNewExpression = extra.parseNewExpression;
+ parseNonComputedProperty = extra.parseNonComputedProperty;
+ parseObjectProperty = extra.parseObjectProperty;
+ parseObjectPropertyKey = extra.parseObjectPropertyKey;
+ parsePath = extra.parsePath;
+ parsePostfixExpression = extra.parsePostfixExpression;
+ parsePrimaryExpression = extra.parsePrimaryExpression;
+ parseProgram = extra.parseProgram;
+ parsePropertyFunction = extra.parsePropertyFunction;
+ parseTemplateElement = extra.parseTemplateElement;
+ parseTemplateLiteral = extra.parseTemplateLiteral;
+ parseSpreadOrAssignmentExpression = extra.parseSpreadOrAssignmentExpression;
+ parseStatement = extra.parseStatement;
+ parseSwitchCase = extra.parseSwitchCase;
+ parseUnaryExpression = extra.parseUnaryExpression;
+ parseVariableDeclaration = extra.parseVariableDeclaration;
+ parseVariableIdentifier = extra.parseVariableIdentifier;
+ parseMethodDefinition = extra.parseMethodDefinition;
+ parseClassDeclaration = extra.parseClassDeclaration;
+ parseClassExpression = extra.parseClassExpression;
+ parseClassBody = extra.parseClassBody;
+ parseXJSIdentifier = extra.parseXJSIdentifier;
+ parseXJSChild = extra.parseXJSChild;
+ parseXJSAttribute = extra.parseXJSAttribute;
+ parseXJSAttributeValue = extra.parseXJSAttributeValue;
+ parseXJSExpressionContainer = extra.parseXJSExpressionContainer;
+ parseXJSEmptyExpression = extra.parseXJSEmptyExpression;
+ parseXJSElement = extra.parseXJSElement;
+ parseXJSClosingElement = extra.parseXJSClosingElement;
+ parseXJSOpeningElement = extra.parseXJSOpeningElement;
+ }
+
+ if (typeof extra.scanRegExp === 'function') {
+ advance = extra.advance;
+ scanRegExp = extra.scanRegExp;
+ }
+ }
+
+ // This is used to modify the delegate.
+
+ function extend(object, properties) {
+ var entry, result = {};
+
+ for (entry in object) {
+ if (object.hasOwnProperty(entry)) {
+ result[entry] = object[entry];
+ }
+ }
+
+ for (entry in properties) {
+ if (properties.hasOwnProperty(entry)) {
+ result[entry] = properties[entry];
+ }
+ }
+
+ return result;
+ }
+
+ 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
+ };
+
+ 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 = [];
+ }
+
+ if (length > 0) {
+ if (typeof source[0] === 'undefined') {
+ // Try first to convert to a string. This is good as fast path
+ // for old IE which understands string indexing for string
+ // literals only and not for string object.
+ if (code instanceof String) {
+ source = code.valueOf();
+ }
+ }
+ }
+
+ patch();
+
+ 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') {
+ filterCommentLocation();
+ tokens.comments = extra.comments;
+ }
+ if (typeof extra.errors !== 'undefined') {
+ tokens.errors = extra.errors;
+ }
+ } catch (e) {
+ throw e;
+ } finally {
+ unpatch();
+ 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: {},
+ parenthesizedCount: 0,
+ inFunctionBody: false,
+ inIteration: false,
+ inSwitch: false,
+ yieldAllowed: false,
+ yieldFound: false
+ };
+
+ extra = {};
+ if (typeof options !== 'undefined') {
+ extra.range = (typeof options.range === 'boolean') && options.range;
+ extra.loc = (typeof options.loc === 'boolean') && options.loc;
+
+ if (extra.loc && options.source !== null && options.source !== undefined) {
+ delegate = extend(delegate, {
+ 'postProcess': function (node) {
+ node.loc.source = toString(options.source);
+ return node;
+ }
+ });
+ }
+
+ 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 (length > 0) {
+ if (typeof source[0] === 'undefined') {
+ // Try first to convert to a string. This is good as fast path
+ // for old IE which understands string indexing for string
+ // literals only and not for string object.
+ if (code instanceof String) {
+ source = code.valueOf();
+ }
+ }
+ }
+
+ patch();
+ try {
+ program = parseProgram();
+ if (typeof extra.comments !== 'undefined') {
+ filterCommentLocation();
+ program.comments = extra.comments;
+ }
+ if (typeof extra.tokens !== 'undefined') {
+ filterTokenLocation();
+ program.tokens = extra.tokens;
+ }
+ if (typeof extra.errors !== 'undefined') {
+ program.errors = extra.errors;
+ }
+ if (extra.range || extra.loc) {
+ program.body = filterGroup(program.body);
+ }
+ } catch (e) {
+ throw e;
+ } finally {
+ unpatch();
+ extra = {};
+ }
+
+ return program;
+ }
+
+ // Sync with package.json and component.json.
+ exports.version = '1.1.0-dev-harmony';
+
+ exports.tokenize = tokenize;
+
+ exports.parse = parse;
+
+ // Deep copy.
+ 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 : */
+
+})()
+},{}],5:[function(require,module,exports){
+/*
+ * Copyright 2009-2011 Mozilla Foundation and contributors
+ * Licensed under the New BSD license. See LICENSE.txt or:
+ * http://opensource.org/licenses/BSD-3-Clause
+ */
+exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator;
+exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer;
+exports.SourceNode = require('./source-map/source-node').SourceNode;
+
+},{"./source-map/source-map-consumer":10,"./source-map/source-map-generator":11,"./source-map/source-node":12}],6:[function(require,module,exports){
+/* -*- Mode: js; js-indent-level: 2; -*- */
+/*
+ * Copyright 2011 Mozilla Foundation and contributors
+ * Licensed under the New BSD license. See LICENSE or:
+ * http://opensource.org/licenses/BSD-3-Clause
+ */
+if (typeof define !== 'function') {
+ var define = require('amdefine')(module, require);
+}
+define(function (require, exports, module) {
+
+ var util = require('./util');
+
+ /**
+ * A data structure which is a combination of an array and a set. Adding a new
+ * member is O(1), testing for membership is O(1), and finding the index of an
+ * element is O(1). Removing elements from the set is not supported. Only
+ * strings are supported for membership.
+ */
+ function ArraySet() {
+ this._array = [];
+ this._set = {};
+ }
+
+ /**
+ * Static method for creating ArraySet instances from an existing array.
+ */
+ ArraySet.fromArray = function ArraySet_fromArray(aArray) {
+ var set = new ArraySet();
+ for (var i = 0, len = aArray.length; i < len; i++) {
+ set.add(aArray[i]);
+ }
+ return set;
+ };
+
+ /**
+ * Add the given string to this set.
+ *
+ * @param String aStr
+ */
+ ArraySet.prototype.add = function ArraySet_add(aStr) {
+ if (this.has(aStr)) {
+ // Already a member; nothing to do.
+ return;
+ }
+ var idx = this._array.length;
+ this._array.push(aStr);
+ this._set[util.toSetString(aStr)] = idx;
+ };
+
+ /**
+ * Is the given string a member of this set?
+ *
+ * @param String aStr
+ */
+ ArraySet.prototype.has = function ArraySet_has(aStr) {
+ return Object.prototype.hasOwnProperty.call(this._set,
+ util.toSetString(aStr));
+ };
+
+ /**
+ * What is the index of the given string in the array?
+ *
+ * @param String aStr
+ */
+ ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
+ if (this.has(aStr)) {
+ return this._set[util.toSetString(aStr)];
+ }
+ throw new Error('"' + aStr + '" is not in the set.');
+ };
+
+ /**
+ * What is the element at the given index?
+ *
+ * @param Number aIdx
+ */
+ ArraySet.prototype.at = function ArraySet_at(aIdx) {
+ if (aIdx >= 0 && aIdx < this._array.length) {
+ return this._array[aIdx];
+ }
+ throw new Error('No element indexed by ' + aIdx);
+ };
+
+ /**
+ * Returns the array representation of this set (which has the proper indices
+ * indicated by indexOf). Note that this is a copy of the internal array used
+ * for storing the members so that no one can mess with internal state.
+ */
+ ArraySet.prototype.toArray = function ArraySet_toArray() {
+ return this._array.slice();
+ };
+
+ exports.ArraySet = ArraySet;
+
+});
+
+},{"./util":13,"amdefine":14}],7:[function(require,module,exports){
+/* -*- Mode: js; js-indent-level: 2; -*- */
+/*
+ * Copyright 2011 Mozilla Foundation and contributors
+ * Licensed under the New BSD license. See LICENSE or:
+ * http://opensource.org/licenses/BSD-3-Clause
+ *
+ * Based on the Base 64 VLQ implementation in Closure Compiler:
+ * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
+ *
+ * Copyright 2011 The Closure Compiler Authors. All rights reserved.
+ * 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.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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 THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ */
+if (typeof define !== 'function') {
+ var define = require('amdefine')(module, require);
+}
+define(function (require, exports, module) {
+
+ var base64 = require('./base64');
+
+ // A single base 64 digit can contain 6 bits of data. For the base 64 variable
+ // length quantities we use in the source map spec, the first bit is the sign,
+ // the next four bits are the actual value, and the 6th bit is the
+ // continuation bit. The continuation bit tells us whether there are more
+ // digits in this value following this digit.
+ //
+ // Continuation
+ // | Sign
+ // | |
+ // V V
+ // 101011
+
+ var VLQ_BASE_SHIFT = 5;
+
+ // binary: 100000
+ var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
+
+ // binary: 011111
+ var VLQ_BASE_MASK = VLQ_BASE - 1;
+
+ // binary: 100000
+ var VLQ_CONTINUATION_BIT = VLQ_BASE;
+
+ /**
+ * Converts from a two-complement value to a value where the sign bit is
+ * is placed in the least significant bit. For example, as decimals:
+ * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
+ * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
+ */
+ function toVLQSigned(aValue) {
+ return aValue < 0
+ ? ((-aValue) << 1) + 1
+ : (aValue << 1) + 0;
+ }
+
+ /**
+ * Converts to a two-complement value from a value where the sign bit is
+ * is placed in the least significant bit. For example, as decimals:
+ * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
+ * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
+ */
+ function fromVLQSigned(aValue) {
+ var isNegative = (aValue & 1) === 1;
+ var shifted = aValue >> 1;
+ return isNegative
+ ? -shifted
+ : shifted;
+ }
+
+ /**
+ * Returns the base 64 VLQ encoded value.
+ */
+ exports.encode = function base64VLQ_encode(aValue) {
+ var encoded = "";
+ var digit;
+
+ var vlq = toVLQSigned(aValue);
+
+ do {
+ digit = vlq & VLQ_BASE_MASK;
+ vlq >>>= VLQ_BASE_SHIFT;
+ if (vlq > 0) {
+ // There are still more digits in this value, so we must make sure the
+ // continuation bit is marked.
+ digit |= VLQ_CONTINUATION_BIT;
+ }
+ encoded += base64.encode(digit);
+ } while (vlq > 0);
+
+ return encoded;
+ };
+
+ /**
+ * Decodes the next base 64 VLQ value from the given string and returns the
+ * value and the rest of the string.
+ */
+ exports.decode = function base64VLQ_decode(aStr) {
+ var i = 0;
+ var strLen = aStr.length;
+ var result = 0;
+ var shift = 0;
+ var continuation, digit;
+
+ do {
+ if (i >= strLen) {
+ throw new Error("Expected more digits in base 64 VLQ value.");
+ }
+ digit = base64.decode(aStr.charAt(i++));
+ continuation = !!(digit & VLQ_CONTINUATION_BIT);
+ digit &= VLQ_BASE_MASK;
+ result = result + (digit << shift);
+ shift += VLQ_BASE_SHIFT;
+ } while (continuation);
+
+ return {
+ value: fromVLQSigned(result),
+ rest: aStr.slice(i)
+ };
+ };
+
+});
+
+},{"./base64":8,"amdefine":14}],8:[function(require,module,exports){
+/* -*- Mode: js; js-indent-level: 2; -*- */
+/*
+ * Copyright 2011 Mozilla Foundation and contributors
+ * Licensed under the New BSD license. See LICENSE or:
+ * http://opensource.org/licenses/BSD-3-Clause
+ */
+if (typeof define !== 'function') {
+ var define = require('amdefine')(module, require);
+}
+define(function (require, exports, module) {
+
+ var charToIntMap = {};
+ var intToCharMap = {};
+
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
+ .split('')
+ .forEach(function (ch, index) {
+ charToIntMap[ch] = index;
+ intToCharMap[index] = ch;
+ });
+
+ /**
+ * Encode an integer in the range of 0 to 63 to a single base 64 digit.
+ */
+ exports.encode = function base64_encode(aNumber) {
+ if (aNumber in intToCharMap) {
+ return intToCharMap[aNumber];
+ }
+ throw new TypeError("Must be between 0 and 63: " + aNumber);
+ };
+
+ /**
+ * Decode a single base 64 digit to an integer.
+ */
+ exports.decode = function base64_decode(aChar) {
+ if (aChar in charToIntMap) {
+ return charToIntMap[aChar];
+ }
+ throw new TypeError("Not a valid base 64 digit: " + aChar);
+ };
+
+});
+
+},{"amdefine":14}],9:[function(require,module,exports){
+/* -*- Mode: js; js-indent-level: 2; -*- */
+/*
+ * Copyright 2011 Mozilla Foundation and contributors
+ * Licensed under the New BSD license. See LICENSE or:
+ * http://opensource.org/licenses/BSD-3-Clause
+ */
+if (typeof define !== 'function') {
+ var define = require('amdefine')(module, require);
+}
+define(function (require, exports, module) {
+
+ /**
+ * Recursive implementation of binary search.
+ *
+ * @param aLow Indices here and lower do not contain the needle.
+ * @param aHigh Indices here and higher do not contain the needle.
+ * @param aNeedle The element being searched for.
+ * @param aHaystack The non-empty array being searched.
+ * @param aCompare Function which takes two elements and returns -1, 0, or 1.
+ */
+ function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) {
+ // This function terminates when one of the following is true:
+ //
+ // 1. We find the exact element we are looking for.
+ //
+ // 2. We did not find the exact element, but we can return the next
+ // closest element that is less than that element.
+ //
+ // 3. We did not find the exact element, and there is no next-closest
+ // element which is less than the one we are searching for, so we
+ // return null.
+ var mid = Math.floor((aHigh - aLow) / 2) + aLow;
+ var cmp = aCompare(aNeedle, aHaystack[mid]);
+ if (cmp === 0) {
+ // Found the element we are looking for.
+ return aHaystack[mid];
+ }
+ else if (cmp > 0) {
+ // aHaystack[mid] is greater than our needle.
+ if (aHigh - mid > 1) {
+ // The element is in the upper half.
+ return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare);
+ }
+ // We did not find an exact match, return the next closest one
+ // (termination case 2).
+ return aHaystack[mid];
+ }
+ else {
+ // aHaystack[mid] is less than our needle.
+ if (mid - aLow > 1) {
+ // The element is in the lower half.
+ return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare);
+ }
+ // The exact needle element was not found in this haystack. Determine if
+ // we are in termination case (2) or (3) and return the appropriate thing.
+ return aLow < 0
+ ? null
+ : aHaystack[aLow];
+ }
+ }
+
+ /**
+ * This is an implementation of binary search which will always try and return
+ * the next lowest value checked if there is no exact hit. This is because
+ * mappings between original and generated line/col pairs are single points,
+ * and there is an implicit region between each of them, so a miss just means
+ * that you aren't on the very start of a region.
+ *
+ * @param aNeedle The element you are looking for.
+ * @param aHaystack The array that is being searched.
+ * @param aCompare A function which takes the needle and an element in the
+ * array and returns -1, 0, or 1 depending on whether the needle is less
+ * than, equal to, or greater than the element, respectively.
+ */
+ exports.search = function search(aNeedle, aHaystack, aCompare) {
+ return aHaystack.length > 0
+ ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare)
+ : null;
+ };
+
+});
+
+},{"amdefine":14}],10:[function(require,module,exports){
+/* -*- Mode: js; js-indent-level: 2; -*- */
+/*
+ * Copyright 2011 Mozilla Foundation and contributors
+ * Licensed under the New BSD license. See LICENSE or:
+ * http://opensource.org/licenses/BSD-3-Clause
+ */
+if (typeof define !== 'function') {
+ var define = require('amdefine')(module, require);
+}
+define(function (require, exports, module) {
+
+ var util = require('./util');
+ var binarySearch = require('./binary-search');
+ var ArraySet = require('./array-set').ArraySet;
+ var base64VLQ = require('./base64-vlq');
+
+ /**
+ * A SourceMapConsumer instance represents a parsed source map which we can
+ * query for information about the original file positions by giving it a file
+ * position in the generated source.
+ *
+ * The only parameter is the raw source map (either as a JSON string, or
+ * already parsed to an object). According to the spec, source maps have the
+ * following attributes:
+ *
+ * - version: Which version of the source map spec this map is following.
+ * - sources: An array of URLs to the original source files.
+ * - names: An array of identifiers which can be referrenced by individual mappings.
+ * - sourceRoot: Optional. The URL root from which all sources are relative.
+ * - sourcesContent: Optional. An array of contents of the original source files.
+ * - mappings: A string of base64 VLQs which contain the actual mappings.
+ * - file: The generated file this source map is associated with.
+ *
+ * Here is an example source map, taken from the source map spec[0]:
+ *
+ * {
+ * version : 3,
+ * file: "out.js",
+ * sourceRoot : "",
+ * sources: ["foo.js", "bar.js"],
+ * names: ["src", "maps", "are", "fun"],
+ * mappings: "AA,AB;;ABCDE;"
+ * }
+ *
+ * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
+ */
+ function SourceMapConsumer(aSourceMap) {
+ var sourceMap = aSourceMap;
+ if (typeof aSourceMap === 'string') {
+ sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
+ }
+
+ var version = util.getArg(sourceMap, 'version');
+ var sources = util.getArg(sourceMap, 'sources');
+ var names = util.getArg(sourceMap, 'names');
+ var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
+ var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
+ var mappings = util.getArg(sourceMap, 'mappings');
+ var file = util.getArg(sourceMap, 'file');
+
+ if (version !== this._version) {
+ throw new Error('Unsupported version: ' + version);
+ }
+
+ this._names = ArraySet.fromArray(names);
+ this._sources = ArraySet.fromArray(sources);
+ this.sourceRoot = sourceRoot;
+ this.sourcesContent = sourcesContent;
+ this.file = file;
+
+ // `this._generatedMappings` and `this._originalMappings` hold the parsed
+ // mapping coordinates from the source map's "mappings" attribute. Each
+ // object in the array is of the form
+ //
+ // {
+ // generatedLine: The line number in the generated code,
+ // generatedColumn: The column number in the generated code,
+ // source: The path to the original source file that generated this
+ // chunk of code,
+ // originalLine: The line number in the original source that
+ // corresponds to this chunk of generated code,
+ // originalColumn: The column number in the original source that
+ // corresponds to this chunk of generated code,
+ // name: The name of the original symbol which generated this chunk of
+ // code.
+ // }
+ //
+ // All properties except for `generatedLine` and `generatedColumn` can be
+ // `null`.
+ //
+ // `this._generatedMappings` is ordered by the generated positions.
+ //
+ // `this._originalMappings` is ordered by the original positions.
+ this._generatedMappings = [];
+ this._originalMappings = [];
+ this._parseMappings(mappings, sourceRoot);
+ }
+
+ /**
+ * The version of the source mapping spec that we are consuming.
+ */
+ SourceMapConsumer.prototype._version = 3;
+
+ /**
+ * The list of original sources.
+ */
+ Object.defineProperty(SourceMapConsumer.prototype, 'sources', {
+ get: function () {
+ return this._sources.toArray().map(function (s) {
+ return this.sourceRoot ? util.join(this.sourceRoot, s) : s;
+ }, this);
+ }
+ });
+
+ /**
+ * Parse the mappings in a string in to a data structure which we can easily
+ * query (an ordered list in this._generatedMappings).
+ */
+ SourceMapConsumer.prototype._parseMappings =
+ function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
+ var generatedLine = 1;
+ var previousGeneratedColumn = 0;
+ var previousOriginalLine = 0;
+ var previousOriginalColumn = 0;
+ var previousSource = 0;
+ var previousName = 0;
+ var mappingSeparator = /^[,;]/;
+ var str = aStr;
+ var mapping;
+ var temp;
+
+ while (str.length > 0) {
+ if (str.charAt(0) === ';') {
+ generatedLine++;
+ str = str.slice(1);
+ previousGeneratedColumn = 0;
+ }
+ else if (str.charAt(0) === ',') {
+ str = str.slice(1);
+ }
+ else {
+ mapping = {};
+ mapping.generatedLine = generatedLine;
+
+ // Generated column.
+ temp = base64VLQ.decode(str);
+ mapping.generatedColumn = previousGeneratedColumn + temp.value;
+ previousGeneratedColumn = mapping.generatedColumn;
+ str = temp.rest;
+
+ if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {
+ // Original source.
+ temp = base64VLQ.decode(str);
+ mapping.source = this._sources.at(previousSource + temp.value);
+ previousSource += temp.value;
+ str = temp.rest;
+ if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {
+ throw new Error('Found a source, but no line and column');
+ }
+
+ // Original line.
+ temp = base64VLQ.decode(str);
+ mapping.originalLine = previousOriginalLine + temp.value;
+ previousOriginalLine = mapping.originalLine;
+ // Lines are stored 0-based
+ mapping.originalLine += 1;
+ str = temp.rest;
+ if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {
+ throw new Error('Found a source and line, but no column');
+ }
+
+ // Original column.
+ temp = base64VLQ.decode(str);
+ mapping.originalColumn = previousOriginalColumn + temp.value;
+ previousOriginalColumn = mapping.originalColumn;
+ str = temp.rest;
+
+ if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {
+ // Original name.
+ temp = base64VLQ.decode(str);
+ mapping.name = this._names.at(previousName + temp.value);
+ previousName += temp.value;
+ str = temp.rest;
+ }
+ }
+
+ this._generatedMappings.push(mapping);
+ if (typeof mapping.originalLine === 'number') {
+ this._originalMappings.push(mapping);
+ }
+ }
+ }
+
+ this._originalMappings.sort(this._compareOriginalPositions);
+ };
+
+ /**
+ * Comparator between two mappings where the original positions are compared.
+ */
+ SourceMapConsumer.prototype._compareOriginalPositions =
+ function SourceMapConsumer_compareOriginalPositions(mappingA, mappingB) {
+ if (mappingA.source > mappingB.source) {
+ return 1;
+ }
+ else if (mappingA.source < mappingB.source) {
+ return -1;
+ }
+ else {
+ var cmp = mappingA.originalLine - mappingB.originalLine;
+ return cmp === 0
+ ? mappingA.originalColumn - mappingB.originalColumn
+ : cmp;
+ }
+ };
+
+ /**
+ * Comparator between two mappings where the generated positions are compared.
+ */
+ SourceMapConsumer.prototype._compareGeneratedPositions =
+ function SourceMapConsumer_compareGeneratedPositions(mappingA, mappingB) {
+ var cmp = mappingA.generatedLine - mappingB.generatedLine;
+ return cmp === 0
+ ? mappingA.generatedColumn - mappingB.generatedColumn
+ : cmp;
+ };
+
+ /**
+ * Find the mapping that best matches the hypothetical "needle" mapping that
+ * we are searching for in the given "haystack" of mappings.
+ */
+ SourceMapConsumer.prototype._findMapping =
+ function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,
+ aColumnName, aComparator) {
+ // To return the position we are searching for, we must first find the
+ // mapping for the given position and then return the opposite position it
+ // points to. Because the mappings are sorted, we can use binary search to
+ // find the best mapping.
+
+ if (aNeedle[aLineName] <= 0) {
+ throw new TypeError('Line must be greater than or equal to 1, got '
+ + aNeedle[aLineName]);
+ }
+ if (aNeedle[aColumnName] < 0) {
+ throw new TypeError('Column must be greater than or equal to 0, got '
+ + aNeedle[aColumnName]);
+ }
+
+ return binarySearch.search(aNeedle, aMappings, aComparator);
+ };
+
+ /**
+ * Returns the original source, line, and column information for the generated
+ * source's line and column positions provided. The only argument is an object
+ * with the following properties:
+ *
+ * - line: The line number in the generated source.
+ * - column: The column number in the generated source.
+ *
+ * and an object is returned with the following properties:
+ *
+ * - source: The original source file, or null.
+ * - line: The line number in the original source, or null.
+ * - column: The column number in the original source, or null.
+ * - name: The original identifier, or null.
+ */
+ SourceMapConsumer.prototype.originalPositionFor =
+ function SourceMapConsumer_originalPositionFor(aArgs) {
+ var needle = {
+ generatedLine: util.getArg(aArgs, 'line'),
+ generatedColumn: util.getArg(aArgs, 'column')
+ };
+
+ var mapping = this._findMapping(needle,
+ this._generatedMappings,
+ "generatedLine",
+ "generatedColumn",
+ this._compareGeneratedPositions);
+
+ if (mapping) {
+ var source = util.getArg(mapping, 'source', null);
+ if (source && this.sourceRoot) {
+ source = util.join(this.sourceRoot, source);
+ }
+ return {
+ source: source,
+ line: util.getArg(mapping, 'originalLine', null),
+ column: util.getArg(mapping, 'originalColumn', null),
+ name: util.getArg(mapping, 'name', null)
+ };
+ }
+
+ return {
+ source: null,
+ line: null,
+ column: null,
+ name: null
+ };
+ };
+
+ /**
+ * Returns the original source content. The only argument is the url of the
+ * original source file. Returns null if no original source content is
+ * availible.
+ */
+ SourceMapConsumer.prototype.sourceContentFor =
+ function SourceMapConsumer_sourceContentFor(aSource) {
+ if (!this.sourcesContent) {
+ return null;
+ }
+
+ if (this.sourceRoot) {
+ aSource = util.relative(this.sourceRoot, aSource);
+ }
+
+ if (this._sources.has(aSource)) {
+ return this.sourcesContent[this._sources.indexOf(aSource)];
+ }
+
+ var url;
+ if (this.sourceRoot
+ && (url = util.urlParse(this.sourceRoot))) {
+ // XXX: file:// URIs and absolute paths lead to unexpected behavior for
+ // many users. We can help them out when they expect file:// URIs to
+ // behave like it would if they were running a local HTTP server. See
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.
+ var fileUriAbsPath = aSource.replace(/^file:\/\//, "");
+ if (url.scheme == "file"
+ && this._sources.has(fileUriAbsPath)) {
+ return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]
+ }
+
+ if ((!url.path || url.path == "/")
+ && this._sources.has("/" + aSource)) {
+ return this.sourcesContent[this._sources.indexOf("/" + aSource)];
+ }
+ }
+
+ throw new Error('"' + aSource + '" is not in the SourceMap.');
+ };
+
+ /**
+ * Returns the generated line and column information for the original source,
+ * line, and column positions provided. The only argument is an object with
+ * the following properties:
+ *
+ * - source: The filename of the original source.
+ * - line: The line number in the original source.
+ * - column: The column number in the original source.
+ *
+ * and an object is returned with the following properties:
+ *
+ * - line: The line number in the generated source, or null.
+ * - column: The column number in the generated source, or null.
+ */
+ SourceMapConsumer.prototype.generatedPositionFor =
+ function SourceMapConsumer_generatedPositionFor(aArgs) {
+ var needle = {
+ source: util.getArg(aArgs, 'source'),
+ originalLine: util.getArg(aArgs, 'line'),
+ originalColumn: util.getArg(aArgs, 'column')
+ };
+
+ if (this.sourceRoot) {
+ needle.source = util.relative(this.sourceRoot, needle.source);
+ }
+
+ var mapping = this._findMapping(needle,
+ this._originalMappings,
+ "originalLine",
+ "originalColumn",
+ this._compareOriginalPositions);
+
+ if (mapping) {
+ return {
+ line: util.getArg(mapping, 'generatedLine', null),
+ column: util.getArg(mapping, 'generatedColumn', null)
+ };
+ }
+
+ return {
+ line: null,
+ column: null
+ };
+ };
+
+ SourceMapConsumer.GENERATED_ORDER = 1;
+ SourceMapConsumer.ORIGINAL_ORDER = 2;
+
+ /**
+ * Iterate over each mapping between an original source/line/column and a
+ * generated line/column in this source map.
+ *
+ * @param Function aCallback
+ * The function that is called with each mapping.
+ * @param Object aContext
+ * Optional. If specified, this object will be the value of `this` every
+ * time that `aCallback` is called.
+ * @param aOrder
+ * Either `SourceMapConsumer.GENERATED_ORDER` or
+ * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to
+ * iterate over