bin/r.js in requirejs-rails-0.9.5 vs bin/r.js in requirejs-rails-0.9.6
- old
+ new
@@ -1,7 +1,7 @@
/**
- * @license r.js 2.1.15 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
+ * @license r.js 2.1.17 Copyright (c) 2010-2015, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
/*
@@ -18,11 +18,11 @@
var requirejs, require, define, xpcUtil;
(function (console, args, readFileFunc) {
var fileName, env, fs, vm, path, exec, rhinoContext, dir, nodeRequire,
nodeDefine, exists, reqMain, loadedOptimizedLib, existsForNode, Cc, Ci,
- version = '2.1.15',
+ version = '2.1.17',
jsSuffixRegExp = /\.js$/,
commandOption = '',
useLibLoaded = {},
//Used by jslib/rhino/args.js
rhinoArgs = args,
@@ -99,16 +99,27 @@
if (fileName && fileName.indexOf('-') === 0) {
commandOption = fileName.substring(1);
fileName = args[1];
}
- //Set up execution context.
- rhinoContext = Packages.org.mozilla.javascript.ContextFactory.getGlobal().enterContext();
+ //Exec/readFile differs between Rhino and Nashorn. Rhino has an
+ //importPackage where Nashorn does not, so branch on that. This is a
+ //coarser check -- detecting readFile existence might also be enough for
+ //this spot. However, sticking with importPackage to keep it the same
+ //as other Rhino/Nashorn detection branches.
+ if (typeof importPackage !== 'undefined') {
+ rhinoContext = Packages.org.mozilla.javascript.ContextFactory.getGlobal().enterContext();
- exec = function (string, name) {
- return rhinoContext.evaluateString(this, string, name, 0, null);
- };
+ exec = function (string, name) {
+ return rhinoContext.evaluateString(this, string, name, 0, null);
+ };
+ } else {
+ exec = function (string, name) {
+ load({ script: string, name: name});
+ };
+ readFile = readFully;
+ }
exists = function (fileName) {
return (new java.io.File(fileName)).exists();
};
@@ -236,11 +247,11 @@
};
}
}
/** vim: et:ts=4:sw=4:sts=4
- * @license RequireJS 2.1.15 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
+ * @license RequireJS 2.1.17 Copyright (c) 2010-2015, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
//Not using strict: uneven strict support in browsers, #392, and causes
//problems with requirejs.exec()/transpiler plugins that may not be strict.
@@ -249,11 +260,11 @@
(function (global) {
var req, s, head, baseElement, dataMain, src,
interactiveScript, currentlyAddingScript, mainScript, subPath,
- version = '2.1.15',
+ version = '2.1.17',
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
jsSuffixRegExp = /\.js$/,
currDirRegExp = /^\.\//,
op = Object.prototype,
@@ -481,11 +492,11 @@
// If at the start, or previous value is still ..,
// keep them so that when converted to a path it may
// still work when converted to a path, even though
// as an ID it is less than ideal. In larger point
// releases, may be better to just kick out an error.
- if (i === 0 || (i == 1 && ary[2] === '..') || ary[i - 1] === '..') {
+ if (i === 0 || (i === 1 && ary[2] === '..') || ary[i - 1] === '..') {
continue;
} else if (i > 0) {
ary.splice(i - 1, 2);
i -= 2;
}
@@ -1360,10 +1371,17 @@
this.check();
}));
if (this.errback) {
on(depMap, 'error', bind(this, this.errback));
+ } else if (this.events.error) {
+ // No direct errback on this module, but something
+ // else is listening for errors, so be sure to
+ // propagate the error correctly.
+ on(depMap, 'error', bind(this, function(err) {
+ this.emit('error', err);
+ }));
}
}
id = depMap.id;
mod = registry[id];
@@ -2333,19 +2351,24 @@
//text is not strict-compliant.
/*jslint sloppy: true, evil: true */
/*global require, XMLHttpRequest */
(function () {
+ // Separate function to avoid eval pollution, same with arguments use.
+ function exec() {
+ eval(arguments[0]);
+ }
+
require.load = function (context, moduleName, url) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
- eval(xhr.responseText);
+ exec(xhr.responseText);
//Support anonymous modules.
context.completeLoad(moduleName);
}
};
@@ -2380,23 +2403,24 @@
* @license RequireJS node Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
-/*jslint regexp: false */
+//Explicity not strict since this file contains an eval call, and do not want
+//to enforce strict on code evaluated that way. See
+//https://github.com/jrburke/r.js/issues/774
+/*jslint regexp: false, sloppy: true*/
/*global require: false, define: false, requirejsVars: false, process: false */
/**
* This adapter assumes that x.js has loaded it and set up
* some variables. This adapter just allows limited RequireJS
* usage from within the requirejs directory. The general
* node adapater is r.js.
*/
(function () {
- 'use strict';
-
var nodeReq = requirejsVars.nodeRequire,
req = requirejsVars.require,
def = requirejsVars.define,
fs = nodeReq('fs'),
path = nodeReq('path'),
@@ -2665,11 +2689,13 @@
isJavaObj = function () {
return false;
};
- if (typeof java !== 'undefined' && java.lang && java.lang.Object) {
+ //Rhino, but not Nashorn (detected by importPackage not existing)
+ //Can have some strange foreign objects.
+ if (typeof java !== 'undefined' && java.lang && java.lang.Object && typeof importPackage !== 'undefined') {
isJavaObj = function (obj) {
return obj instanceof java.lang.Object;
};
}
@@ -4012,11 +4038,17 @@
outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile));
}
os = new java.io.BufferedWriter(outWriter);
try {
- os.write(fileContents);
+ //If in Nashorn, need to coerce the JS string to a Java string so that
+ //writer.write method dispatch correctly detects the type.
+ if (typeof importPackage !== 'undefined') {
+ os.write(fileContents);
+ } else {
+ os.write(new java.lang.String(fileContents));
+ }
} finally {
os.close();
}
},
@@ -4553,21 +4585,10 @@
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/*jslint bitwise:true plusplus:true */
-/*global esprima:true, define:true, exports:true, window: true,
-throwErrorTolerant: true,
-throwError: true, generateStatement: true, peek: true,
-parseAssignmentExpression: true, parseBlock: true, parseExpression: true,
-parseFunctionDeclaration: true, parseFunctionExpression: true,
-parseFunctionSourceElements: true, parseVariableIdentifier: true,
-parseLeftHandSideExpression: true,
-parseUnaryExpression: true,
-parseStatement: true, parseSourceElement: true */
-
(function (root, factory) {
'use strict';
// Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
// Rhino, and plain browser loading.
@@ -4585,21 +4606,27 @@
var Token,
TokenName,
FnExprTokens,
Syntax,
- PropertyKind,
+ PlaceHolders,
Messages,
Regex,
- SyntaxTreeDelegate,
source,
strict,
index,
lineNumber,
lineStart,
+ hasLineTerminator,
+ lastIndex,
+ lastLineNumber,
+ lastLineStart,
+ startIndex,
+ startLineNumber,
+ startLineStart,
+ scanning,
length,
- delegate,
lookahead,
state,
extra;
Token = {
@@ -4637,15 +4664,19 @@
'<=', '<', '>', '!=', '!=='];
Syntax = {
AssignmentExpression: 'AssignmentExpression',
ArrayExpression: 'ArrayExpression',
+ ArrowFunctionExpression: 'ArrowFunctionExpression',
BlockStatement: 'BlockStatement',
BinaryExpression: 'BinaryExpression',
BreakStatement: 'BreakStatement',
CallExpression: 'CallExpression',
CatchClause: 'CatchClause',
+ ClassBody: 'ClassBody',
+ ClassDeclaration: 'ClassDeclaration',
+ ClassExpression: 'ClassExpression',
ConditionalExpression: 'ConditionalExpression',
ContinueStatement: 'ContinueStatement',
DoWhileStatement: 'DoWhileStatement',
DebuggerStatement: 'DebuggerStatement',
EmptyStatement: 'EmptyStatement',
@@ -4658,14 +4689,16 @@
IfStatement: 'IfStatement',
Literal: 'Literal',
LabeledStatement: 'LabeledStatement',
LogicalExpression: 'LogicalExpression',
MemberExpression: 'MemberExpression',
+ MethodDefinition: 'MethodDefinition',
NewExpression: 'NewExpression',
ObjectExpression: 'ObjectExpression',
Program: 'Program',
Property: 'Property',
+ RestElement: 'RestElement',
ReturnStatement: 'ReturnStatement',
SequenceExpression: 'SequenceExpression',
SwitchStatement: 'SwitchStatement',
SwitchCase: 'SwitchCase',
ThisExpression: 'ThisExpression',
@@ -4677,57 +4710,59 @@
VariableDeclarator: 'VariableDeclarator',
WhileStatement: 'WhileStatement',
WithStatement: 'WithStatement'
};
- PropertyKind = {
- Data: 1,
- Get: 2,
- Set: 4
+ PlaceHolders = {
+ ArrowParameterPlaceHolder: 'ArrowParameterPlaceHolder'
};
// Error messages should be identical to V8.
Messages = {
- UnexpectedToken: 'Unexpected token %0',
- UnexpectedNumber: 'Unexpected number',
- UnexpectedString: 'Unexpected string',
- UnexpectedIdentifier: 'Unexpected identifier',
- UnexpectedReserved: 'Unexpected reserved word',
- UnexpectedEOS: 'Unexpected end of input',
- NewlineAfterThrow: 'Illegal newline after throw',
+ UnexpectedToken: 'Unexpected token %0',
+ UnexpectedNumber: 'Unexpected number',
+ UnexpectedString: 'Unexpected string',
+ UnexpectedIdentifier: 'Unexpected identifier',
+ UnexpectedReserved: 'Unexpected reserved word',
+ UnexpectedEOS: 'Unexpected end of input',
+ NewlineAfterThrow: 'Illegal newline after throw',
InvalidRegExp: 'Invalid regular expression',
- UnterminatedRegExp: 'Invalid regular expression: missing /',
- InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
- InvalidLHSInForIn: 'Invalid left-hand side in for-in',
+ UnterminatedRegExp: 'Invalid regular expression: missing /',
+ InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
+ InvalidLHSInForIn: 'Invalid left-hand side in for-in',
MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
- NoCatchOrFinally: 'Missing catch or finally after try',
+ NoCatchOrFinally: 'Missing catch or finally after try',
UnknownLabel: 'Undefined label \'%0\'',
Redeclaration: '%0 \'%1\' has already been declared',
IllegalContinue: 'Illegal continue statement',
IllegalBreak: 'Illegal break statement',
IllegalReturn: 'Illegal return statement',
- StrictModeWith: 'Strict mode code may not include a with statement',
- StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
- StrictVarName: 'Variable name may not be eval or arguments in strict mode',
- StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
+ StrictModeWith: 'Strict mode code may not include a with statement',
+ StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
+ StrictVarName: 'Variable name may not be eval or arguments in strict mode',
+ StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
- StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
- StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
- StrictDelete: 'Delete of an unqualified identifier in strict mode.',
- StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
- AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
- AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
- StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
- StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
- StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
- StrictReservedWord: 'Use of future reserved word in strict mode'
+ 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.',
+ 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',
+ ParameterAfterRestParameter: 'Rest parameter must be last formal parameter',
+ DefaultRestParameter: 'Unexpected token =',
+ ObjectPatternAsRestParameter: 'Unexpected token {',
+ DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals',
+ ConstructorSpecialMethod: 'Class constructor may not be an accessor',
+ DuplicateConstructor: 'A class may only have one constructor',
+ StaticPrototype: 'Classes may not have static property named prototype'
};
// 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]')
+ NonAsciiIdentifierStart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\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-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\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-\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-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\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-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\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\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\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-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\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\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\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\u0D01-\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\u0DE6-\u0DEF\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-\u16F8\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-\u191E\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\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\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-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\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-\uFE2D\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.
@@ -4739,11 +4774,11 @@
throw new Error('ASSERT: ' + message);
}
}
function isDecimalDigit(ch) {
- return (ch >= 48 && ch <= 57); // 0..9
+ return (ch >= 0x30 && ch <= 0x39); // 0..9
}
function isHexDigit(ch) {
return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
}
@@ -4787,22 +4822,22 @@
// 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;
}
}
+ // 11.6.2.2 Future Reserved Words
+
function isStrictModeReservedWord(id) {
switch (id) {
case 'implements':
case 'interface':
case 'package':
@@ -4828,11 +4863,11 @@
if (strict && isStrictModeReservedWord(id)) {
return true;
}
// 'const' is specialized as Keyword in V8.
- // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next.
+ // 'yield' and 'let' are for compatibility with SpiderMonkey and ES.next.
// Some others are from future reserved words.
switch (id.length) {
case 2:
return (id === 'if') || (id === 'in') || (id === 'do');
@@ -4861,21 +4896,14 @@
}
// 7.4 Comments
function addComment(type, value, start, end, loc) {
- var comment, attacher;
+ var comment;
assert(typeof start === 'number', 'Comment must have valid position');
- // Because the way the actual token is scanned, often the comments
- // (if any) are skipped twice during the lexical analysis.
- // Thus, we need to skip adding a comment if the comment array already
- // handled it.
- if (state.lastCommentStart >= start) {
- return;
- }
state.lastCommentStart = start;
comment = {
type: type,
value: value
@@ -4906,10 +4934,11 @@
while (index < length) {
ch = source.charCodeAt(index);
++index;
if (isLineTerminator(ch)) {
+ hasLineTerminator = true;
if (extra.comments) {
comment = source.slice(start + offset, index - 1);
loc.end = {
line: lineNumber,
column: index - lineStart - 1
@@ -4952,16 +4981,14 @@
ch = source.charCodeAt(index);
if (isLineTerminator(ch)) {
if (ch === 0x0D && source.charCodeAt(index + 1) === 0x0A) {
++index;
}
+ hasLineTerminator = true;
++lineNumber;
++index;
lineStart = index;
- if (index >= length) {
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
- }
} else if (ch === 0x2A) {
// Block comment ends with '*/'.
if (source.charCodeAt(index + 1) === 0x2F) {
++index;
++index;
@@ -4979,23 +5006,38 @@
} else {
++index;
}
}
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ if (extra.errors && index >= length) {
+ //ran off the end of the file - the whole thing is a comment
+ if (extra.comments) {
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart
+ };
+ comment = source.slice(start + 2, index);
+ addComment('Block', comment, start, index, loc);
+ }
+ tolerateUnexpectedToken();
+ } else {
+ throwUnexpectedToken();
+ }
}
function skipComment() {
var ch, start;
+ hasLineTerminator = false;
start = (index === 0);
while (index < length) {
ch = source.charCodeAt(index);
if (isWhiteSpace(ch)) {
++index;
} else if (isLineTerminator(ch)) {
+ hasLineTerminator = true;
++index;
if (ch === 0x0D && source.charCodeAt(index) === 0x0A) {
++index;
}
++lineNumber;
@@ -5053,25 +5095,57 @@
}
}
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 === '}') {
+ throwUnexpectedToken();
+ }
+
+ while (index < length) {
+ ch = source[index++];
+ if (!isHexDigit(ch)) {
+ break;
+ }
+ code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
+ }
+
+ if (code > 0x10FFFF || ch !== '}') {
+ throwUnexpectedToken();
+ }
+
+ // 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' (U+005C, U+0075) denotes an escaped character.
if (ch === 0x5C) {
if (source.charCodeAt(index) !== 0x75) {
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ throwUnexpectedToken();
}
++index;
ch = scanHexEscape('u');
if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) {
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ throwUnexpectedToken();
}
id = ch;
}
while (index < length) {
@@ -5084,16 +5158,16 @@
// '\u' (U+005C, U+0075) denotes an escaped character.
if (ch === 0x5C) {
id = id.substr(0, id.length - 1);
if (source.charCodeAt(index) !== 0x75) {
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ throwUnexpectedToken();
}
++index;
ch = scanHexEscape('u');
if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) {
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ throwUnexpectedToken();
}
id += ch;
}
}
@@ -5155,213 +5229,226 @@
// 7.7 Punctuators
function scanPunctuator() {
- var start = index,
- code = source.charCodeAt(index),
- code2,
- ch1 = source[index],
- ch2,
- ch3,
- ch4;
+ var token, str;
- switch (code) {
+ token = {
+ type: Token.Punctuator,
+ value: '',
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: index,
+ end: index
+ };
// Check for most common single-character punctuators.
- case 0x2E: // . dot
- case 0x28: // ( open bracket
- case 0x29: // ) close bracket
- case 0x3B: // ; semicolon
- case 0x2C: // , comma
- case 0x7B: // { open curly brace
- case 0x7D: // } close curly brace
- case 0x5B: // [
- case 0x5D: // ]
- case 0x3A: // :
- case 0x3F: // ?
- case 0x7E: // ~
+ str = source[index];
+ switch (str) {
+
+ case '(':
+ if (extra.tokenize) {
+ extra.openParenToken = extra.tokens.length;
+ }
++index;
+ break;
+
+ case '{':
if (extra.tokenize) {
- if (code === 0x28) {
- extra.openParenToken = extra.tokens.length;
- } else if (code === 0x7B) {
- extra.openCurlyToken = extra.tokens.length;
- }
+ extra.openCurlyToken = extra.tokens.length;
}
- return {
- type: Token.Punctuator,
- value: String.fromCharCode(code),
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
+ ++index;
+ break;
+ case '.':
+ ++index;
+ if (source[index] === '.' && source[index + 1] === '.') {
+ // Spread operator: ...
+ index += 2;
+ str = '...';
+ }
+ break;
+
+ case ')':
+ case ';':
+ case ',':
+ case '}':
+ case '[':
+ case ']':
+ case ':':
+ case '?':
+ case '~':
+ ++index;
+ break;
+
default:
- code2 = source.charCodeAt(index + 1);
+ // 4-character punctuator.
+ str = source.substr(index, 4);
+ if (str === '>>>=') {
+ index += 4;
+ } else {
- // '=' (U+003D) marks an assignment or comparison operator.
- if (code2 === 0x3D) {
- switch (code) {
- case 0x2B: // +
- case 0x2D: // -
- case 0x2F: // /
- case 0x3C: // <
- case 0x3E: // >
- case 0x5E: // ^
- case 0x7C: // |
- case 0x25: // %
- case 0x26: // &
- case 0x2A: // *
- index += 2;
- return {
- type: Token.Punctuator,
- value: String.fromCharCode(code) + String.fromCharCode(code2),
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
+ // 3-character punctuators.
+ str = str.substr(0, 3);
+ if (str === '===' || str === '!==' || str === '>>>' ||
+ str === '<<=' || str === '>>=') {
+ index += 3;
+ } else {
- case 0x21: // !
- case 0x3D: // =
- index += 2;
+ // 2-character punctuators.
+ str = str.substr(0, 2);
+ if (str === '&&' || str === '||' || str === '==' || str === '!=' ||
+ str === '+=' || str === '-=' || str === '*=' || str === '/=' ||
+ str === '++' || str === '--' || str === '<<' || str === '>>' ||
+ str === '&=' || str === '|=' || str === '^=' || str === '%=' ||
+ str === '<=' || str === '>=' || str === '=>') {
+ index += 2;
+ } else {
- // !== and ===
- if (source.charCodeAt(index) === 0x3D) {
- ++index;
+ // 1-character punctuators.
+ str = source[index];
+ if ('<>=!+-*%&|^/'.indexOf(str) >= 0) {
+ ++index;
+ }
}
- return {
- type: Token.Punctuator,
- value: source.slice(start, index),
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
}
}
}
- // 4-character punctuator: >>>=
-
- ch4 = source.substr(index, 4);
-
- if (ch4 === '>>>=') {
- index += 4;
- return {
- type: Token.Punctuator,
- value: ch4,
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
+ if (index === token.start) {
+ throwUnexpectedToken();
}
- // 3-character punctuators: === !== >>> <<= >>=
+ token.end = index;
+ token.value = str;
+ return token;
+ }
- ch3 = ch4.substr(0, 3);
+ // 7.8.3 Numeric Literals
- if (ch3 === '>>>' || ch3 === '<<=' || ch3 === '>>=') {
- index += 3;
- return {
- type: Token.Punctuator,
- value: ch3,
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
+ function scanHexLiteral(start) {
+ var number = '';
+
+ while (index < length) {
+ if (!isHexDigit(source[index])) {
+ break;
+ }
+ number += source[index++];
}
- // Other 2-character punctuators: ++ -- << >> && ||
- ch2 = ch3.substr(0, 2);
-
- if ((ch1 === ch2[1] && ('+-<>&|'.indexOf(ch1) >= 0)) || ch2 === '=>') {
- index += 2;
- return {
- type: Token.Punctuator,
- value: ch2,
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
+ if (number.length === 0) {
+ throwUnexpectedToken();
}
- // 1-character punctuators: < > = ! + - * % & | ^ /
- if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
- ++index;
- return {
- type: Token.Punctuator,
- value: ch1,
- lineNumber: lineNumber,
- lineStart: lineStart,
- start: start,
- end: index
- };
+ if (isIdentifierStart(source.charCodeAt(index))) {
+ throwUnexpectedToken();
}
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ return {
+ type: Token.NumericLiteral,
+ value: parseInt('0x' + number, 16),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
}
- // 7.8.3 Numeric Literals
+ function scanBinaryLiteral(start) {
+ var ch, number;
- function scanHexLiteral(start) {
- var number = '';
+ number = '';
while (index < length) {
- if (!isHexDigit(source[index])) {
+ ch = source[index];
+ if (ch !== '0' && ch !== '1') {
break;
}
number += source[index++];
}
if (number.length === 0) {
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ // only 0b or 0B
+ throwUnexpectedToken();
}
- if (isIdentifierStart(source.charCodeAt(index))) {
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ if (index < length) {
+ ch = source.charCodeAt(index);
+ /* istanbul ignore else */
+ if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
+ throwUnexpectedToken();
+ }
}
return {
type: Token.NumericLiteral,
- value: parseInt('0x' + number, 16),
+ value: parseInt(number, 2),
lineNumber: lineNumber,
lineStart: lineStart,
start: start,
end: index
};
}
- function scanOctalLiteral(start) {
- var number = '0' + source[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
+ throwUnexpectedToken();
+ }
+
if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ throwUnexpectedToken();
}
return {
type: Token.NumericLiteral,
value: parseInt(number, 8),
- octal: true,
+ octal: octal,
lineNumber: lineNumber,
lineStart: lineStart,
start: start,
end: index
};
}
+ function isImplicitOctalLiteral() {
+ var i, ch;
+
+ // Implicit octal, unless there is a non-octal digit.
+ // (Annex B.1.1 on Numeric Literals)
+ for (i = index + 1; i < length; ++i) {
+ ch = source[i];
+ if (ch === '8' || ch === '9') {
+ return false;
+ }
+ if (!isOctalDigit(ch)) {
+ return true;
+ }
+ }
+
+ return true;
+ }
+
function scanNumericLiteral() {
var number, start, ch;
ch = source[index];
assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
@@ -5373,22 +5460,29 @@
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 (isOctalDigit(ch)) {
- return scanOctalLiteral(start);
+ if (ch === 'b' || ch === 'B') {
+ ++index;
+ return scanBinaryLiteral(start);
}
+ if (ch === 'o' || ch === 'O') {
+ return scanOctalLiteral(ch, start);
+ }
- // decimal number starts with '0' such as '09' is illegal.
- if (ch && isDecimalDigit(ch.charCodeAt(0))) {
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ if (isOctalDigit(ch)) {
+ if (isImplicitOctalLiteral()) {
+ return scanOctalLiteral(ch, start);
+ }
}
}
while (isDecimalDigit(source.charCodeAt(index))) {
number += source[index++];
@@ -5414,16 +5508,16 @@
if (isDecimalDigit(source.charCodeAt(index))) {
while (isDecimalDigit(source.charCodeAt(index))) {
number += source[index++];
}
} else {
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ throwUnexpectedToken();
}
}
if (isIdentifierStart(source.charCodeAt(index))) {
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ throwUnexpectedToken();
}
return {
type: Token.NumericLiteral,
value: parseFloat(number),
@@ -5435,13 +5529,11 @@
}
// 7.8.4 String Literals
function scanStringLiteral() {
- var str = '', quote, start, ch, code, unescaped, restore, octal = false, startLineNumber, startLineStart;
- startLineNumber = lineNumber;
- startLineStart = lineStart;
+ var str = '', quote, start, ch, code, unescaped, restore, octal = false;
quote = source[index];
assert((quote === '\'' || quote === '"'),
'String literal must starts with a quote');
@@ -5458,17 +5550,22 @@
ch = source[index++];
if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
switch (ch) {
case 'u':
case 'x':
- restore = index;
- unescaped = scanHexEscape(ch);
- if (unescaped) {
- str += unescaped;
+ if (source[index] === '{') {
+ ++index;
+ str += scanUnicodeCodePointEscape();
} else {
- index = restore;
- str += ch;
+ restore = index;
+ unescaped = scanHexEscape(ch);
+ if (unescaped) {
+ str += unescaped;
+ } else {
+ index = restore;
+ str += ch;
+ }
}
break;
case 'n':
str += '\n';
break;
@@ -5515,11 +5612,11 @@
}
break;
}
} else {
++lineNumber;
- if (ch === '\r' && source[index] === '\n') {
+ if (ch === '\r' && source[index] === '\n') {
++index;
}
lineStart = index;
}
} else if (isLineTerminator(ch.charCodeAt(0))) {
@@ -5528,34 +5625,61 @@
str += ch;
}
}
if (quote !== '') {
- throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ throwUnexpectedToken();
}
return {
type: Token.StringLiteral,
value: str,
octal: octal,
- startLineNumber: startLineNumber,
- startLineStart: startLineStart,
- lineNumber: lineNumber,
- lineStart: lineStart,
+ lineNumber: startLineNumber,
+ lineStart: startLineStart,
start: start,
end: index
};
}
function testRegExp(pattern, flags) {
- var value;
+ var tmp = pattern;
+
+ if (flags.indexOf('u') >= 0) {
+ // Replace each astral symbol and every Unicode code point
+ // escape sequence with a single ASCII symbol to avoid throwing on
+ // regular expressions that are only valid in combination with the
+ // `/u` flag.
+ // Note: replacing with the ASCII symbol `x` might cause false
+ // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
+ // perfectly valid pattern that is equivalent to `[a-b]`, but it
+ // would be replaced by `[x-b]` which throws an error.
+ tmp = tmp
+ .replace(/\\u\{([0-9a-fA-F]+)\}/g, function ($0, $1) {
+ if (parseInt($1, 16) <= 0x10FFFF) {
+ return 'x';
+ }
+ throwUnexpectedToken(null, Messages.InvalidRegExp);
+ })
+ .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x');
+ }
+
+ // First, detect invalid regular expressions.
try {
- value = new RegExp(pattern, flags);
+ RegExp(tmp);
} catch (e) {
- throwError({}, Messages.InvalidRegExp);
+ throwUnexpectedToken(null, Messages.InvalidRegExp);
}
- return value;
+
+ // Return a regular expression object for this pattern-flag pair, or
+ // `null` in case the current environment doesn't support the flags it
+ // uses.
+ try {
+ return new RegExp(pattern, flags);
+ } catch (exception) {
+ return null;
+ }
}
function scanRegExpBody() {
var ch, str, classMarker, terminated, body;
@@ -5570,15 +5694,15 @@
str += ch;
if (ch === '\\') {
ch = source[index++];
// ECMA-262 7.8.5
if (isLineTerminator(ch.charCodeAt(0))) {
- throwError({}, Messages.UnterminatedRegExp);
+ throwUnexpectedToken(null, Messages.UnterminatedRegExp);
}
str += ch;
} else if (isLineTerminator(ch.charCodeAt(0))) {
- throwError({}, Messages.UnterminatedRegExp);
+ throwUnexpectedToken(null, Messages.UnterminatedRegExp);
} else if (classMarker) {
if (ch === ']') {
classMarker = false;
}
} else {
@@ -5590,11 +5714,11 @@
}
}
}
if (!terminated) {
- throwError({}, Messages.UnterminatedRegExp);
+ throwUnexpectedToken(null, Messages.UnterminatedRegExp);
}
// Exclude leading and trailing slash.
body = str.substr(1, str.length - 2);
return {
@@ -5629,14 +5753,14 @@
} else {
index = restore;
flags += 'u';
str += '\\u';
}
- throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
+ tolerateUnexpectedToken();
} else {
str += '\\';
- throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
+ tolerateUnexpectedToken();
}
} else {
flags += ch;
str += ch;
}
@@ -5647,34 +5771,43 @@
literal: str
};
}
function scanRegExp() {
- var start, body, flags, pattern, value;
+ scanning = true;
+ var start, body, flags, value;
lookahead = null;
skipComment();
start = index;
body = scanRegExpBody();
flags = scanRegExpFlags();
value = testRegExp(body.value, flags.value);
-
+ scanning = false;
if (extra.tokenize) {
return {
type: Token.RegularExpression,
value: value,
+ regex: {
+ pattern: body.value,
+ flags: flags.value
+ },
lineNumber: lineNumber,
lineStart: lineStart,
start: start,
end: index
};
}
return {
literal: body.literal + flags.literal,
value: value,
+ regex: {
+ pattern: body.value,
+ flags: flags.value
+ },
start: start,
end: index
};
}
@@ -5690,10 +5823,11 @@
column: index - lineStart
}
};
regex = scanRegExp();
+
loc.end = {
line: lineNumber,
column: index - lineStart
};
@@ -5710,10 +5844,11 @@
}
extra.tokens.push({
type: 'RegularExpression',
value: regex.literal,
+ regex: regex.regex,
range: [pos, index],
loc: loc
});
}
@@ -5782,21 +5917,19 @@
// It is a declaration.
return collectRegex();
}
return collectRegex();
}
- if (prevToken.type === 'Keyword') {
+ if (prevToken.type === 'Keyword' && prevToken.value !== 'this') {
return collectRegex();
}
return scanPunctuator();
}
function advance() {
var ch;
- skipComment();
-
if (index >= length) {
return {
type: Token.EOF,
lineNumber: lineNumber,
lineStart: lineStart,
@@ -5842,13 +5975,12 @@
return scanPunctuator();
}
function collectToken() {
- var loc, token, range, value;
+ var loc, token, value, entry;
- skipComment();
loc = {
start: {
line: lineNumber,
column: index - lineStart
}
@@ -5860,578 +5992,710 @@
column: index - lineStart
};
if (token.type !== Token.EOF) {
value = source.slice(token.start, token.end);
- extra.tokens.push({
+ entry = {
type: TokenName[token.type],
value: value,
range: [token.start, token.end],
loc: loc
- });
+ };
+ if (token.regex) {
+ entry.regex = {
+ pattern: token.regex.pattern,
+ flags: token.regex.flags
+ };
+ }
+ extra.tokens.push(entry);
}
return token;
}
function lex() {
var token;
+ scanning = true;
- token = lookahead;
- index = token.end;
- lineNumber = token.lineNumber;
- lineStart = token.lineStart;
+ lastIndex = index;
+ lastLineNumber = lineNumber;
+ lastLineStart = lineStart;
- lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
+ skipComment();
- index = token.end;
- lineNumber = token.lineNumber;
- lineStart = token.lineStart;
+ token = lookahead;
+ startIndex = index;
+ startLineNumber = lineNumber;
+ startLineStart = lineStart;
+
+ lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
+ scanning = false;
return token;
}
function peek() {
- var pos, line, start;
+ scanning = true;
- pos = index;
- line = lineNumber;
- start = lineStart;
+ skipComment();
+
+ lastIndex = index;
+ lastLineNumber = lineNumber;
+ lastLineStart = lineStart;
+
+ startIndex = index;
+ startLineNumber = lineNumber;
+ startLineStart = lineStart;
+
lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
- index = pos;
- lineNumber = line;
- lineStart = start;
+ scanning = false;
}
- function Position(line, column) {
- this.line = line;
- this.column = column;
+ function Position() {
+ this.line = startLineNumber;
+ this.column = startIndex - startLineStart;
}
- function SourceLocation(startLine, startColumn, line, column) {
- this.start = new Position(startLine, startColumn);
- this.end = new Position(line, column);
+ function SourceLocation() {
+ this.start = new Position();
+ this.end = null;
}
- SyntaxTreeDelegate = {
+ function WrappingSourceLocation(startToken) {
+ this.start = {
+ line: startToken.lineNumber,
+ column: startToken.start - startToken.lineStart
+ };
+ this.end = null;
+ }
- name: 'SyntaxTree',
+ function Node() {
+ if (extra.range) {
+ this.range = [startIndex, 0];
+ }
+ if (extra.loc) {
+ this.loc = new SourceLocation();
+ }
+ }
- processComment: function (node) {
- var lastChild, trailingComments;
+ function WrappingNode(startToken) {
+ if (extra.range) {
+ this.range = [startToken.start, 0];
+ }
+ if (extra.loc) {
+ this.loc = new WrappingSourceLocation(startToken);
+ }
+ }
- if (node.type === Syntax.Program) {
- if (node.body.length > 0) {
+ WrappingNode.prototype = Node.prototype = {
+
+ processComment: function () {
+ var lastChild,
+ leadingComments,
+ trailingComments,
+ bottomRight = extra.bottomRightStack,
+ i,
+ comment,
+ last = bottomRight[bottomRight.length - 1];
+
+ if (this.type === Syntax.Program) {
+ if (this.body.length > 0) {
return;
}
}
if (extra.trailingComments.length > 0) {
- if (extra.trailingComments[0].range[0] >= node.range[1]) {
- trailingComments = extra.trailingComments;
- extra.trailingComments = [];
- } else {
- extra.trailingComments.length = 0;
+ trailingComments = [];
+ for (i = extra.trailingComments.length - 1; i >= 0; --i) {
+ comment = extra.trailingComments[i];
+ if (comment.range[0] >= this.range[1]) {
+ trailingComments.unshift(comment);
+ extra.trailingComments.splice(i, 1);
+ }
}
+ extra.trailingComments = [];
} else {
- if (extra.bottomRightStack.length > 0 &&
- extra.bottomRightStack[extra.bottomRightStack.length - 1].trailingComments &&
- extra.bottomRightStack[extra.bottomRightStack.length - 1].trailingComments[0].range[0] >= node.range[1]) {
- trailingComments = extra.bottomRightStack[extra.bottomRightStack.length - 1].trailingComments;
- delete extra.bottomRightStack[extra.bottomRightStack.length - 1].trailingComments;
+ if (last && last.trailingComments && last.trailingComments[0].range[0] >= this.range[1]) {
+ trailingComments = last.trailingComments;
+ delete last.trailingComments;
}
}
// Eating the stack.
- while (extra.bottomRightStack.length > 0 && extra.bottomRightStack[extra.bottomRightStack.length - 1].range[0] >= node.range[0]) {
- lastChild = extra.bottomRightStack.pop();
+ if (last) {
+ while (last && last.range[0] >= this.range[0]) {
+ lastChild = last;
+ last = bottomRight.pop();
+ }
}
if (lastChild) {
- if (lastChild.leadingComments && lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= node.range[0]) {
- node.leadingComments = lastChild.leadingComments;
- delete lastChild.leadingComments;
+ if (lastChild.leadingComments && lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= this.range[0]) {
+ this.leadingComments = lastChild.leadingComments;
+ lastChild.leadingComments = undefined;
}
- } else if (extra.leadingComments.length > 0 && extra.leadingComments[extra.leadingComments.length - 1].range[1] <= node.range[0]) {
- node.leadingComments = extra.leadingComments;
- extra.leadingComments = [];
+ } else if (extra.leadingComments.length > 0) {
+ leadingComments = [];
+ for (i = extra.leadingComments.length - 1; i >= 0; --i) {
+ comment = extra.leadingComments[i];
+ if (comment.range[1] <= this.range[0]) {
+ leadingComments.unshift(comment);
+ extra.leadingComments.splice(i, 1);
+ }
+ }
}
- if (trailingComments) {
- node.trailingComments = trailingComments;
+ if (leadingComments && leadingComments.length > 0) {
+ this.leadingComments = leadingComments;
}
+ if (trailingComments && trailingComments.length > 0) {
+ this.trailingComments = trailingComments;
+ }
- extra.bottomRightStack.push(node);
+ bottomRight.push(this);
},
- markEnd: function (node, startToken) {
+ finish: function () {
if (extra.range) {
- node.range = [startToken.start, index];
+ this.range[1] = lastIndex;
}
if (extra.loc) {
- node.loc = new SourceLocation(
- startToken.startLineNumber === undefined ? startToken.lineNumber : startToken.startLineNumber,
- startToken.start - (startToken.startLineStart === undefined ? startToken.lineStart : startToken.startLineStart),
- lineNumber,
- index - lineStart
- );
- this.postProcess(node);
+ this.loc.end = {
+ line: lastLineNumber,
+ column: lastIndex - lastLineStart
+ };
+ if (extra.source) {
+ this.loc.source = extra.source;
+ }
}
if (extra.attachComment) {
- this.processComment(node);
+ this.processComment();
}
- return node;
},
- postProcess: function (node) {
- if (extra.source) {
- node.loc.source = extra.source;
- }
- return node;
+ finishArrayExpression: function (elements) {
+ this.type = Syntax.ArrayExpression;
+ this.elements = elements;
+ this.finish();
+ return this;
},
- createArrayExpression: function (elements) {
- return {
- type: Syntax.ArrayExpression,
- elements: elements
- };
+ finishArrowFunctionExpression: function (params, defaults, body, expression) {
+ this.type = Syntax.ArrowFunctionExpression;
+ this.id = null;
+ this.params = params;
+ this.defaults = defaults;
+ this.body = body;
+ this.generator = false;
+ this.expression = expression;
+ this.finish();
+ return this;
},
- createAssignmentExpression: function (operator, left, right) {
- return {
- type: Syntax.AssignmentExpression,
- operator: operator,
- left: left,
- right: right
- };
+ finishAssignmentExpression: function (operator, left, right) {
+ this.type = Syntax.AssignmentExpression;
+ this.operator = operator;
+ this.left = left;
+ this.right = right;
+ this.finish();
+ return this;
},
- createBinaryExpression: function (operator, left, right) {
- var type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression :
- Syntax.BinaryExpression;
- return {
- type: type,
- operator: operator,
- left: left,
- right: right
- };
+ finishBinaryExpression: function (operator, left, right) {
+ this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression;
+ this.operator = operator;
+ this.left = left;
+ this.right = right;
+ this.finish();
+ return this;
},
- createBlockStatement: function (body) {
- return {
- type: Syntax.BlockStatement,
- body: body
- };
+ finishBlockStatement: function (body) {
+ this.type = Syntax.BlockStatement;
+ this.body = body;
+ this.finish();
+ return this;
},
- createBreakStatement: function (label) {
- return {
- type: Syntax.BreakStatement,
- label: label
- };
+ finishBreakStatement: function (label) {
+ this.type = Syntax.BreakStatement;
+ this.label = label;
+ this.finish();
+ return this;
},
- createCallExpression: function (callee, args) {
- return {
- type: Syntax.CallExpression,
- callee: callee,
- 'arguments': args
- };
+ finishCallExpression: function (callee, args) {
+ this.type = Syntax.CallExpression;
+ this.callee = callee;
+ this.arguments = args;
+ this.finish();
+ return this;
},
- createCatchClause: function (param, body) {
- return {
- type: Syntax.CatchClause,
- param: param,
- body: body
- };
+ finishCatchClause: function (param, body) {
+ this.type = Syntax.CatchClause;
+ this.param = param;
+ this.body = body;
+ this.finish();
+ return this;
},
- createConditionalExpression: function (test, consequent, alternate) {
- return {
- type: Syntax.ConditionalExpression,
- test: test,
- consequent: consequent,
- alternate: alternate
- };
+ finishClassBody: function (body) {
+ this.type = Syntax.ClassBody;
+ this.body = body;
+ this.finish();
+ return this;
},
- createContinueStatement: function (label) {
- return {
- type: Syntax.ContinueStatement,
- label: label
- };
+ finishClassDeclaration: function (id, superClass, body) {
+ this.type = Syntax.ClassDeclaration;
+ this.id = id;
+ this.superClass = superClass;
+ this.body = body;
+ this.finish();
+ return this;
},
- createDebuggerStatement: function () {
- return {
- type: Syntax.DebuggerStatement
- };
+ finishClassExpression: function (id, superClass, body) {
+ this.type = Syntax.ClassExpression;
+ this.id = id;
+ this.superClass = superClass;
+ this.body = body;
+ this.finish();
+ return this;
},
- createDoWhileStatement: function (body, test) {
- return {
- type: Syntax.DoWhileStatement,
- body: body,
- test: test
- };
+ finishConditionalExpression: function (test, consequent, alternate) {
+ this.type = Syntax.ConditionalExpression;
+ this.test = test;
+ this.consequent = consequent;
+ this.alternate = alternate;
+ this.finish();
+ return this;
},
- createEmptyStatement: function () {
- return {
- type: Syntax.EmptyStatement
- };
+ finishContinueStatement: function (label) {
+ this.type = Syntax.ContinueStatement;
+ this.label = label;
+ this.finish();
+ return this;
},
- createExpressionStatement: function (expression) {
- return {
- type: Syntax.ExpressionStatement,
- expression: expression
- };
+ finishDebuggerStatement: function () {
+ this.type = Syntax.DebuggerStatement;
+ this.finish();
+ return this;
},
- createForStatement: function (init, test, update, body) {
- return {
- type: Syntax.ForStatement,
- init: init,
- test: test,
- update: update,
- body: body
- };
+ finishDoWhileStatement: function (body, test) {
+ this.type = Syntax.DoWhileStatement;
+ this.body = body;
+ this.test = test;
+ this.finish();
+ return this;
},
- createForInStatement: function (left, right, body) {
- return {
- type: Syntax.ForInStatement,
- left: left,
- right: right,
- body: body,
- each: false
- };
+ finishEmptyStatement: function () {
+ this.type = Syntax.EmptyStatement;
+ this.finish();
+ return this;
},
- createFunctionDeclaration: function (id, params, defaults, body) {
- return {
- type: Syntax.FunctionDeclaration,
- id: id,
- params: params,
- defaults: defaults,
- body: body,
- rest: null,
- generator: false,
- expression: false
- };
+ finishExpressionStatement: function (expression) {
+ this.type = Syntax.ExpressionStatement;
+ this.expression = expression;
+ this.finish();
+ return this;
},
- createFunctionExpression: function (id, params, defaults, body) {
- return {
- type: Syntax.FunctionExpression,
- id: id,
- params: params,
- defaults: defaults,
- body: body,
- rest: null,
- generator: false,
- expression: false
- };
+ finishForStatement: function (init, test, update, body) {
+ this.type = Syntax.ForStatement;
+ this.init = init;
+ this.test = test;
+ this.update = update;
+ this.body = body;
+ this.finish();
+ return this;
},
- createIdentifier: function (name) {
- return {
- type: Syntax.Identifier,
- name: name
- };
+ finishForInStatement: function (left, right, body) {
+ this.type = Syntax.ForInStatement;
+ this.left = left;
+ this.right = right;
+ this.body = body;
+ this.each = false;
+ this.finish();
+ return this;
},
- createIfStatement: function (test, consequent, alternate) {
- return {
- type: Syntax.IfStatement,
- test: test,
- consequent: consequent,
- alternate: alternate
- };
+ finishFunctionDeclaration: function (id, params, defaults, body) {
+ this.type = Syntax.FunctionDeclaration;
+ this.id = id;
+ this.params = params;
+ this.defaults = defaults;
+ this.body = body;
+ this.generator = false;
+ this.expression = false;
+ this.finish();
+ return this;
},
- createLabeledStatement: function (label, body) {
- return {
- type: Syntax.LabeledStatement,
- label: label,
- body: body
- };
+ finishFunctionExpression: function (id, params, defaults, body) {
+ this.type = Syntax.FunctionExpression;
+ this.id = id;
+ this.params = params;
+ this.defaults = defaults;
+ this.body = body;
+ this.generator = false;
+ this.expression = false;
+ this.finish();
+ return this;
},
- createLiteral: function (token) {
- return {
- type: Syntax.Literal,
- value: token.value,
- raw: source.slice(token.start, token.end)
- };
+ finishIdentifier: function (name) {
+ this.type = Syntax.Identifier;
+ this.name = name;
+ this.finish();
+ return this;
},
- createMemberExpression: function (accessor, object, property) {
- return {
- type: Syntax.MemberExpression,
- computed: accessor === '[',
- object: object,
- property: property
- };
+ finishIfStatement: function (test, consequent, alternate) {
+ this.type = Syntax.IfStatement;
+ this.test = test;
+ this.consequent = consequent;
+ this.alternate = alternate;
+ this.finish();
+ return this;
},
- createNewExpression: function (callee, args) {
- return {
- type: Syntax.NewExpression,
- callee: callee,
- 'arguments': args
- };
+ finishLabeledStatement: function (label, body) {
+ this.type = Syntax.LabeledStatement;
+ this.label = label;
+ this.body = body;
+ this.finish();
+ return this;
},
- createObjectExpression: function (properties) {
- return {
- type: Syntax.ObjectExpression,
- properties: properties
- };
+ finishLiteral: function (token) {
+ this.type = Syntax.Literal;
+ this.value = token.value;
+ this.raw = source.slice(token.start, token.end);
+ if (token.regex) {
+ this.regex = token.regex;
+ }
+ this.finish();
+ return this;
},
- createPostfixExpression: function (operator, argument) {
- return {
- type: Syntax.UpdateExpression,
- operator: operator,
- argument: argument,
- prefix: false
- };
+ finishMemberExpression: function (accessor, object, property) {
+ this.type = Syntax.MemberExpression;
+ this.computed = accessor === '[';
+ this.object = object;
+ this.property = property;
+ this.finish();
+ return this;
},
- createProgram: function (body) {
- return {
- type: Syntax.Program,
- body: body
- };
+ finishNewExpression: function (callee, args) {
+ this.type = Syntax.NewExpression;
+ this.callee = callee;
+ this.arguments = args;
+ this.finish();
+ return this;
},
- createProperty: function (kind, key, value) {
- return {
- type: Syntax.Property,
- key: key,
- value: value,
- kind: kind
- };
+ finishObjectExpression: function (properties) {
+ this.type = Syntax.ObjectExpression;
+ this.properties = properties;
+ this.finish();
+ return this;
},
- createReturnStatement: function (argument) {
- return {
- type: Syntax.ReturnStatement,
- argument: argument
- };
+ finishPostfixExpression: function (operator, argument) {
+ this.type = Syntax.UpdateExpression;
+ this.operator = operator;
+ this.argument = argument;
+ this.prefix = false;
+ this.finish();
+ return this;
},
- createSequenceExpression: function (expressions) {
- return {
- type: Syntax.SequenceExpression,
- expressions: expressions
- };
+ finishProgram: function (body) {
+ this.type = Syntax.Program;
+ this.body = body;
+ this.finish();
+ return this;
},
- createSwitchCase: function (test, consequent) {
- return {
- type: Syntax.SwitchCase,
- test: test,
- consequent: consequent
- };
+ finishProperty: function (kind, key, computed, value, method, shorthand) {
+ this.type = Syntax.Property;
+ this.key = key;
+ this.computed = computed;
+ this.value = value;
+ this.kind = kind;
+ this.method = method;
+ this.shorthand = shorthand;
+ this.finish();
+ return this;
},
- createSwitchStatement: function (discriminant, cases) {
- return {
- type: Syntax.SwitchStatement,
- discriminant: discriminant,
- cases: cases
- };
+ finishRestElement: function (argument) {
+ this.type = Syntax.RestElement;
+ this.argument = argument;
+ this.finish();
+ return this;
},
- createThisExpression: function () {
- return {
- type: Syntax.ThisExpression
- };
+ finishReturnStatement: function (argument) {
+ this.type = Syntax.ReturnStatement;
+ this.argument = argument;
+ this.finish();
+ return this;
},
- createThrowStatement: function (argument) {
- return {
- type: Syntax.ThrowStatement,
- argument: argument
- };
+ finishSequenceExpression: function (expressions) {
+ this.type = Syntax.SequenceExpression;
+ this.expressions = expressions;
+ this.finish();
+ return this;
},
- createTryStatement: function (block, guardedHandlers, handlers, finalizer) {
- return {
- type: Syntax.TryStatement,
- block: block,
- guardedHandlers: guardedHandlers,
- handlers: handlers,
- finalizer: finalizer
- };
+ finishSwitchCase: function (test, consequent) {
+ this.type = Syntax.SwitchCase;
+ this.test = test;
+ this.consequent = consequent;
+ this.finish();
+ return this;
},
- createUnaryExpression: function (operator, argument) {
- if (operator === '++' || operator === '--') {
- return {
- type: Syntax.UpdateExpression,
- operator: operator,
- argument: argument,
- prefix: true
- };
- }
- return {
- type: Syntax.UnaryExpression,
- operator: operator,
- argument: argument,
- prefix: true
- };
+ finishSwitchStatement: function (discriminant, cases) {
+ this.type = Syntax.SwitchStatement;
+ this.discriminant = discriminant;
+ this.cases = cases;
+ this.finish();
+ return this;
},
- createVariableDeclaration: function (declarations, kind) {
- return {
- type: Syntax.VariableDeclaration,
- declarations: declarations,
- kind: kind
- };
+ finishThisExpression: function () {
+ this.type = Syntax.ThisExpression;
+ this.finish();
+ return this;
},
- createVariableDeclarator: function (id, init) {
- return {
- type: Syntax.VariableDeclarator,
- id: id,
- init: init
- };
+ finishThrowStatement: function (argument) {
+ this.type = Syntax.ThrowStatement;
+ this.argument = argument;
+ this.finish();
+ return this;
},
- createWhileStatement: function (test, body) {
- return {
- type: Syntax.WhileStatement,
- test: test,
- body: body
- };
+ finishTryStatement: function (block, handler, finalizer) {
+ this.type = Syntax.TryStatement;
+ this.block = block;
+ this.guardedHandlers = [];
+ this.handlers = handler ? [ handler ] : [];
+ this.handler = handler;
+ this.finalizer = finalizer;
+ this.finish();
+ return this;
},
- createWithStatement: function (object, body) {
- return {
- type: Syntax.WithStatement,
- object: object,
- body: body
- };
+ finishUnaryExpression: function (operator, argument) {
+ this.type = (operator === '++' || operator === '--') ? Syntax.UpdateExpression : Syntax.UnaryExpression;
+ this.operator = operator;
+ this.argument = argument;
+ this.prefix = true;
+ this.finish();
+ return this;
+ },
+
+ finishVariableDeclaration: function (declarations) {
+ this.type = Syntax.VariableDeclaration;
+ this.declarations = declarations;
+ this.kind = 'var';
+ this.finish();
+ return this;
+ },
+
+ finishLexicalDeclaration: function (declarations, kind) {
+ this.type = Syntax.VariableDeclaration;
+ this.declarations = declarations;
+ this.kind = kind;
+ this.finish();
+ return this;
+ },
+
+ finishVariableDeclarator: function (id, init) {
+ this.type = Syntax.VariableDeclarator;
+ this.id = id;
+ this.init = init;
+ this.finish();
+ return this;
+ },
+
+ finishWhileStatement: function (test, body) {
+ this.type = Syntax.WhileStatement;
+ this.test = test;
+ this.body = body;
+ this.finish();
+ return this;
+ },
+
+ finishWithStatement: function (object, body) {
+ this.type = Syntax.WithStatement;
+ this.object = object;
+ this.body = body;
+ this.finish();
+ return this;
}
};
- // Return true if there is a line terminator before the next token.
- function peekLineTerminator() {
- var pos, line, start, found;
+ function recordError(error) {
+ var e, existing;
- pos = index;
- line = lineNumber;
- start = lineStart;
- skipComment();
- found = lineNumber !== line;
- index = pos;
- lineNumber = line;
- lineStart = start;
+ for (e = 0; e < extra.errors.length; e++) {
+ existing = extra.errors[e];
+ // Prevent duplicated error.
+ /* istanbul ignore next */
+ if (existing.index === error.index && existing.message === error.message) {
+ return;
+ }
+ }
- return found;
+ extra.errors.push(error);
}
+ function createError(line, pos, description) {
+ var error = new Error('Line ' + line + ': ' + description);
+ error.index = pos;
+ error.lineNumber = line;
+ error.column = pos - (scanning ? lineStart : lastLineStart) + 1;
+ error.description = description;
+ return error;
+ }
+
// 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];
- }
- );
+ function throwError(messageFormat) {
+ var args, msg;
- if (typeof token.lineNumber === 'number') {
- error = new Error('Line ' + token.lineNumber + ': ' + msg);
- error.index = token.start;
- error.lineNumber = token.lineNumber;
- error.column = token.start - lineStart + 1;
- } else {
- error = new Error('Line ' + lineNumber + ': ' + msg);
- error.index = index;
- error.lineNumber = lineNumber;
- error.column = index - lineStart + 1;
- }
+ args = Array.prototype.slice.call(arguments, 1);
+ msg = messageFormat.replace(/%(\d)/g,
+ function (whole, idx) {
+ assert(idx < args.length, 'Message reference must be in range');
+ return args[idx];
+ }
+ );
- error.description = msg;
- throw error;
+ throw createError(lastLineNumber, lastIndex, msg);
}
- function throwErrorTolerant() {
- try {
- throwError.apply(null, arguments);
- } catch (e) {
- if (extra.errors) {
- extra.errors.push(e);
- } else {
- throw e;
+ function tolerateError(messageFormat) {
+ var args, msg, error;
+
+ args = Array.prototype.slice.call(arguments, 1);
+ /* istanbul ignore next */
+ msg = messageFormat.replace(/%(\d)/g,
+ function (whole, idx) {
+ assert(idx < args.length, 'Message reference must be in range');
+ return args[idx];
}
+ );
+
+ error = createError(lineNumber, lastIndex, msg);
+ if (extra.errors) {
+ recordError(error);
+ } else {
+ throw error;
}
}
-
// Throw an exception because of the token.
- function throwUnexpected(token) {
- if (token.type === Token.EOF) {
- throwError(token, Messages.UnexpectedEOS);
- }
+ function unexpectedTokenError(token, message) {
+ var msg = message || Messages.UnexpectedToken;
- if (token.type === Token.NumericLiteral) {
- throwError(token, Messages.UnexpectedNumber);
- }
+ if (token && !message) {
+ msg = (token.type === Token.EOF) ? Messages.UnexpectedEOS :
+ (token.type === Token.Identifier) ? Messages.UnexpectedIdentifier :
+ (token.type === Token.NumericLiteral) ? Messages.UnexpectedNumber :
+ (token.type === Token.StringLiteral) ? Messages.UnexpectedString :
+ Messages.UnexpectedToken;
- if (token.type === Token.StringLiteral) {
- throwError(token, Messages.UnexpectedString);
+ if (token.type === Token.Keyword) {
+ if (isFutureReservedWord(token.value)) {
+ msg = Messages.UnexpectedReserved;
+ } else if (strict && isStrictModeReservedWord(token.value)) {
+ msg = Messages.StrictReservedWord;
+ }
+ }
}
- if (token.type === Token.Identifier) {
- throwError(token, Messages.UnexpectedIdentifier);
- }
+ msg = msg.replace('%0', token ? token.value : 'ILLEGAL');
- 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);
- }
+ return (token && typeof token.lineNumber === 'number') ?
+ createError(token.lineNumber, token.start, msg) :
+ createError(scanning ? lineNumber : lastLineNumber, scanning ? index : lastIndex, msg);
+ }
- // BooleanLiteral, NullLiteral, or Punctuator.
- throwError(token, Messages.UnexpectedToken, token.value);
+ function throwUnexpectedToken(token, message) {
+ throw unexpectedTokenError(token, message);
}
+ function tolerateUnexpectedToken(token, message) {
+ var error = unexpectedTokenError(token, message);
+ if (extra.errors) {
+ recordError(error);
+ } else {
+ throw error;
+ }
+ }
+
// 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);
+ throwUnexpectedToken(token);
}
}
+ /**
+ * @name expectCommaSeparator
+ * @description Quietly expect a comma when in tolerant mode, otherwise delegates
+ * to <code>expect(value)</code>
+ * @since 2.0
+ */
+ function expectCommaSeparator() {
+ var token;
+
+ if (extra.errors) {
+ token = lookahead;
+ if (token.type === Token.Punctuator && token.value === ',') {
+ lex();
+ } else if (token.type === Token.Punctuator && token.value === ';') {
+ lex();
+ tolerateUnexpectedToken(token);
+ } else {
+ tolerateUnexpectedToken(token, Messages.UnexpectedToken);
+ }
+ } else {
+ expect(',');
+ }
+ }
+
// 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);
+ throwUnexpectedToken(token);
}
}
// Return true if the next token matches the specified punctuator.
@@ -6467,26 +6731,27 @@
op === '^=' ||
op === '|=';
}
function consumeSemicolon() {
- var line;
-
// Catch the very common case first: immediately a semicolon (U+003B).
- if (source.charCodeAt(index) === 0x3B || match(';')) {
+ if (source.charCodeAt(startIndex) === 0x3B || match(';')) {
lex();
return;
}
- line = lineNumber;
- skipComment();
- if (lineNumber !== line) {
+ if (hasLineTerminator) {
return;
}
+ // FIXME(ikarienator): this is seemingly an issue in the previous location info convention.
+ lastIndex = startIndex;
+ lastLineNumber = startLineNumber;
+ lastLineStart = startLineStart;
+
if (lookahead.type !== Token.EOF && !match('}')) {
- throwUnexpected(lookahead);
+ throwUnexpectedToken(lookahead);
}
}
// Return true if provided expression is LeftHandSideExpression
@@ -6495,13 +6760,12 @@
}
// 11.1.4 Array Initialiser
function parseArrayInitialiser() {
- var elements = [], startToken;
+ var elements = [], node = new Node();
- startToken = lookahead;
expect('[');
while (!match(']')) {
if (match(',')) {
lex();
@@ -6515,163 +6779,294 @@
}
}
lex();
- return delegate.markEnd(delegate.createArrayExpression(elements), startToken);
+ return node.finishArrayExpression(elements);
}
// 11.1.5 Object Initialiser
- function parsePropertyFunction(param, first) {
- var previousStrict, body, startToken;
+ function parsePropertyFunction(node, paramInfo) {
+ var previousStrict, body;
previousStrict = strict;
- startToken = lookahead;
body = parseFunctionSourceElements();
- if (first && strict && isRestrictedWord(param[0].name)) {
- throwErrorTolerant(first, Messages.StrictParamName);
+
+ if (strict && paramInfo.firstRestricted) {
+ tolerateUnexpectedToken(paramInfo.firstRestricted, paramInfo.message);
}
+ if (strict && paramInfo.stricted) {
+ tolerateUnexpectedToken(paramInfo.stricted, paramInfo.message);
+ }
+
strict = previousStrict;
- return delegate.markEnd(delegate.createFunctionExpression(null, param, [], body), startToken);
+ return node.finishFunctionExpression(null, paramInfo.params, paramInfo.defaults, body);
}
+ function parsePropertyMethodFunction() {
+ var params, method, node = new Node();
+
+ params = parseParams();
+ method = parsePropertyFunction(node, params);
+
+ return method;
+ }
+
+ // This function returns a tuple `[PropertyName, boolean]` where the PropertyName is the key being consumed and the second
+ // element indicate whether its a computed PropertyName or a static PropertyName.
function parseObjectPropertyKey() {
- var token, startToken;
+ var token, node = new Node(), expr;
- startToken = lookahead;
token = lex();
// Note: This function is called only from parseObjectProperty(), where
// EOF and Punctuator tokens are already filtered out.
- if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
+ switch (token.type) {
+ case Token.StringLiteral:
+ case Token.NumericLiteral:
if (strict && token.octal) {
- throwErrorTolerant(token, Messages.StrictOctalLiteral);
+ tolerateUnexpectedToken(token, Messages.StrictOctalLiteral);
}
- return delegate.markEnd(delegate.createLiteral(token), startToken);
+ return node.finishLiteral(token);
+ case Token.Identifier:
+ case Token.BooleanLiteral:
+ case Token.NullLiteral:
+ case Token.Keyword:
+ return node.finishIdentifier(token.value);
+ case Token.Punctuator:
+ if (token.value === '[') {
+ expr = parseAssignmentExpression();
+ expect(']');
+ return expr;
+ }
+ break;
}
+ throwUnexpectedToken(token);
+ }
- return delegate.markEnd(delegate.createIdentifier(token.value), startToken);
+ function lookaheadPropertyName() {
+ switch (lookahead.type) {
+ case Token.Identifier:
+ case Token.StringLiteral:
+ case Token.BooleanLiteral:
+ case Token.NullLiteral:
+ case Token.NumericLiteral:
+ case Token.Keyword:
+ return true;
+ case Token.Punctuator:
+ return lookahead.value === '[';
+ }
+ return false;
}
- function parseObjectProperty() {
- var token, key, id, value, param, startToken;
+ // This function is to try to parse a MethodDefinition as defined in 14.3. But in the case of object literals,
+ // it might be called at a position where there is in fact a short hand identifier pattern or a data property.
+ // This can only be determined after we consumed up to the left parentheses.
+ //
+ // In order to avoid back tracking, it returns `null` if the position is not a MethodDefinition and the caller
+ // is responsible to visit other options.
+ function tryParseMethodDefinition(token, key, computed, node) {
+ var value, options, methodNode;
- token = lookahead;
- startToken = lookahead;
-
if (token.type === Token.Identifier) {
+ // check for `get` and `set`;
- id = parseObjectPropertyKey();
-
- // Property Assignment: Getter and Setter.
-
- if (token.value === 'get' && !match(':')) {
+ if (token.value === 'get' && lookaheadPropertyName()) {
+ computed = match('[');
key = parseObjectPropertyKey();
+ methodNode = new Node();
expect('(');
expect(')');
- value = parsePropertyFunction([]);
- return delegate.markEnd(delegate.createProperty('get', key, value), startToken);
- }
- if (token.value === 'set' && !match(':')) {
+ value = parsePropertyFunction(methodNode, {
+ params: [],
+ defaults: [],
+ stricted: null,
+ firstRestricted: null,
+ message: null
+ });
+ return node.finishProperty('get', key, computed, value, false, false);
+ } else if (token.value === 'set' && lookaheadPropertyName()) {
+ computed = match('[');
key = parseObjectPropertyKey();
+ methodNode = new Node();
expect('(');
- token = lookahead;
- if (token.type !== Token.Identifier) {
- expect(')');
- throwErrorTolerant(token, Messages.UnexpectedToken, token.value);
- value = parsePropertyFunction([]);
+
+ options = {
+ params: [],
+ defaultCount: 0,
+ defaults: [],
+ firstRestricted: null,
+ paramSet: {}
+ };
+ if (match(')')) {
+ tolerateUnexpectedToken(lookahead);
} else {
- param = [ parseVariableIdentifier() ];
- expect(')');
- value = parsePropertyFunction(param, token);
+ parseParam(options);
+ if (options.defaultCount === 0) {
+ options.defaults = [];
+ }
}
- return delegate.markEnd(delegate.createProperty('set', key, value), startToken);
+ expect(')');
+
+ value = parsePropertyFunction(methodNode, options);
+ return node.finishProperty('set', key, computed, value, false, false);
}
- expect(':');
- value = parseAssignmentExpression();
- return delegate.markEnd(delegate.createProperty('init', id, value), startToken);
}
- if (token.type === Token.EOF || token.type === Token.Punctuator) {
- throwUnexpected(token);
- } else {
- key = parseObjectPropertyKey();
- expect(':');
- value = parseAssignmentExpression();
- return delegate.markEnd(delegate.createProperty('init', key, value), startToken);
+
+ if (match('(')) {
+ value = parsePropertyMethodFunction();
+ return node.finishProperty('init', key, computed, value, true, false);
}
+
+ // Not a MethodDefinition.
+ return null;
}
- function parseObjectInitialiser() {
- var properties = [], property, name, key, kind, map = {}, toString = String, startToken;
+ function checkProto(key, computed, hasProto) {
+ if (computed === false && (key.type === Syntax.Identifier && key.name === '__proto__' ||
+ key.type === Syntax.Literal && key.value === '__proto__')) {
+ if (hasProto.value) {
+ tolerateError(Messages.DuplicateProtoProperty);
+ } else {
+ hasProto.value = true;
+ }
+ }
+ }
- startToken = lookahead;
+ function parseObjectProperty(hasProto) {
+ var token = lookahead, node = new Node(), computed, key, maybeMethod, value;
- expect('{');
+ computed = match('[');
+ key = parseObjectPropertyKey();
+ maybeMethod = tryParseMethodDefinition(token, key, computed, node);
- while (!match('}')) {
- property = parseObjectProperty();
+ if (maybeMethod) {
+ checkProto(maybeMethod.key, maybeMethod.computed, hasProto);
+ // finished
+ return maybeMethod;
+ }
- 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;
+ // init property or short hand property.
+ checkProto(key, computed, hasProto);
- 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;
- }
+ if (match(':')) {
+ lex();
+ value = parseAssignmentExpression();
+ return node.finishProperty('init', key, computed, value, false, false);
+ }
- properties.push(property);
+ if (token.type === Token.Identifier) {
+ return node.finishProperty('init', key, computed, key, false, true);
+ }
+ throwUnexpectedToken(lookahead);
+ }
+
+ function parseObjectInitialiser() {
+ var properties = [], hasProto = {value: false}, node = new Node();
+
+ expect('{');
+
+ while (!match('}')) {
+ properties.push(parseObjectProperty(hasProto));
+
if (!match('}')) {
- expect(',');
+ expectCommaSeparator();
}
}
expect('}');
- return delegate.markEnd(delegate.createObjectExpression(properties), startToken);
+ return node.finishObjectExpression(properties);
}
// 11.1.6 The Grouping Operator
function parseGroupExpression() {
- var expr;
+ var expr, expressions, startToken, isValidArrowParameter = true;
expect('(');
- expr = parseExpression();
+ if (match(')')) {
+ lex();
+ if (!match('=>')) {
+ expect('=>');
+ }
+ return {
+ type: PlaceHolders.ArrowParameterPlaceHolder,
+ params: []
+ };
+ }
+ startToken = lookahead;
+ if (match('...')) {
+ expr = parseRestElement();
+ expect(')');
+ if (!match('=>')) {
+ expect('=>');
+ }
+ return {
+ type: PlaceHolders.ArrowParameterPlaceHolder,
+ params: [expr]
+ };
+ }
+
+ if (match('(')) {
+ isValidArrowParameter = false;
+ }
+
+ expr = parseAssignmentExpression();
+
+ if (match(',')) {
+ expressions = [expr];
+
+ while (startIndex < length) {
+ if (!match(',')) {
+ break;
+ }
+ lex();
+
+ if (match('...')) {
+ if (!isValidArrowParameter) {
+ throwUnexpectedToken(lookahead);
+ }
+ expressions.push(parseRestElement());
+ expect(')');
+ if (!match('=>')) {
+ expect('=>');
+ }
+ return {
+ type: PlaceHolders.ArrowParameterPlaceHolder,
+ params: expressions
+ };
+ } else if (match('(')) {
+ isValidArrowParameter = false;
+ }
+
+ expressions.push(parseAssignmentExpression());
+ }
+
+ expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
+ }
+
+
expect(')');
+ if (match('=>') && !isValidArrowParameter) {
+ throwUnexpectedToken(lookahead);
+ }
+
return expr;
}
// 11.1 Primary Expressions
function parsePrimaryExpression() {
- var type, token, expr, startToken;
+ var type, token, expr, node;
if (match('(')) {
return parseGroupExpression();
}
@@ -6682,84 +7077,88 @@
if (match('{')) {
return parseObjectInitialiser();
}
type = lookahead.type;
- startToken = lookahead;
+ node = new Node();
if (type === Token.Identifier) {
- expr = delegate.createIdentifier(lex().value);
+ expr = node.finishIdentifier(lex().value);
} else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
if (strict && lookahead.octal) {
- throwErrorTolerant(lookahead, Messages.StrictOctalLiteral);
+ tolerateUnexpectedToken(lookahead, Messages.StrictOctalLiteral);
}
- expr = delegate.createLiteral(lex());
+ expr = node.finishLiteral(lex());
} else if (type === Token.Keyword) {
if (matchKeyword('function')) {
return parseFunctionExpression();
}
if (matchKeyword('this')) {
lex();
- expr = delegate.createThisExpression();
- } else {
- throwUnexpected(lex());
+ return node.finishThisExpression();
}
+ if (matchKeyword('class')) {
+ return parseClassExpression();
+ }
+ throwUnexpectedToken(lex());
} else if (type === Token.BooleanLiteral) {
token = lex();
token.value = (token.value === 'true');
- expr = delegate.createLiteral(token);
+ expr = node.finishLiteral(token);
} else if (type === Token.NullLiteral) {
token = lex();
token.value = null;
- expr = delegate.createLiteral(token);
+ expr = node.finishLiteral(token);
} else if (match('/') || match('/=')) {
+ index = startIndex;
+
if (typeof extra.tokens !== 'undefined') {
- expr = delegate.createLiteral(collectRegex());
+ token = collectRegex();
} else {
- expr = delegate.createLiteral(scanRegExp());
+ token = scanRegExp();
}
- peek();
+ lex();
+ expr = node.finishLiteral(token);
} else {
- throwUnexpected(lex());
+ throwUnexpectedToken(lex());
}
- return delegate.markEnd(expr, startToken);
+ return expr;
}
// 11.2 Left-Hand-Side Expressions
function parseArguments() {
var args = [];
expect('(');
if (!match(')')) {
- while (index < length) {
+ while (startIndex < length) {
args.push(parseAssignmentExpression());
if (match(')')) {
break;
}
- expect(',');
+ expectCommaSeparator();
}
}
expect(')');
return args;
}
function parseNonComputedProperty() {
- var token, startToken;
+ var token, node = new Node();
- startToken = lookahead;
token = lex();
if (!isIdentifierName(token)) {
- throwUnexpected(token);
+ throwUnexpectedToken(token);
}
- return delegate.markEnd(delegate.createIdentifier(token.value), startToken);
+ return node.finishIdentifier(token.value);
}
function parseNonComputedMember() {
expect('.');
@@ -6777,92 +7176,87 @@
return expr;
}
function parseNewExpression() {
- var callee, args, startToken;
+ var callee, args, node = new Node();
- startToken = lookahead;
expectKeyword('new');
callee = parseLeftHandSideExpression();
args = match('(') ? parseArguments() : [];
- return delegate.markEnd(delegate.createNewExpression(callee, args), startToken);
+ return node.finishNewExpression(callee, args);
}
function parseLeftHandSideExpressionAllowCall() {
- var previousAllowIn, expr, args, property, startToken;
+ var expr, args, property, startToken, previousAllowIn = state.allowIn;
startToken = lookahead;
-
- previousAllowIn = state.allowIn;
state.allowIn = true;
expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
- state.allowIn = previousAllowIn;
for (;;) {
if (match('.')) {
property = parseNonComputedMember();
- expr = delegate.createMemberExpression('.', expr, property);
+ expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
} else if (match('(')) {
args = parseArguments();
- expr = delegate.createCallExpression(expr, args);
+ expr = new WrappingNode(startToken).finishCallExpression(expr, args);
} else if (match('[')) {
property = parseComputedMember();
- expr = delegate.createMemberExpression('[', expr, property);
+ expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
} else {
break;
}
- delegate.markEnd(expr, startToken);
}
+ state.allowIn = previousAllowIn;
return expr;
}
function parseLeftHandSideExpression() {
- var previousAllowIn, expr, property, startToken;
+ var expr, property, startToken;
+ assert(state.allowIn, 'callee of new expression always allow in keyword.');
startToken = lookahead;
- previousAllowIn = state.allowIn;
expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
- state.allowIn = previousAllowIn;
- while (match('.') || match('[')) {
+ for (;;) {
if (match('[')) {
property = parseComputedMember();
- expr = delegate.createMemberExpression('[', expr, property);
- } else {
+ expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
+ } else if (match('.')) {
property = parseNonComputedMember();
- expr = delegate.createMemberExpression('.', expr, property);
+ expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
+ } else {
+ break;
}
- delegate.markEnd(expr, startToken);
}
-
return expr;
}
// 11.3 Postfix Expressions
function parsePostfixExpression() {
var expr, token, startToken = lookahead;
expr = parseLeftHandSideExpressionAllowCall();
- if (lookahead.type === Token.Punctuator) {
- if ((match('++') || match('--')) && !peekLineTerminator()) {
+ if (!hasLineTerminator && lookahead.type === Token.Punctuator) {
+ if (match('++') || match('--')) {
// 11.3.1, 11.3.2
if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
- throwErrorTolerant({}, Messages.StrictLHSPostfix);
+ tolerateError(Messages.StrictLHSPostfix);
}
if (!isLeftHandSide(expr)) {
- throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
+ tolerateError(Messages.InvalidLHSInAssignment);
}
token = lex();
- expr = delegate.markEnd(delegate.createPostfixExpression(token.value, expr), startToken);
+ expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr);
}
}
return expr;
}
@@ -6878,33 +7272,30 @@
startToken = lookahead;
token = lex();
expr = parseUnaryExpression();
// 11.4.4, 11.4.5
if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
- throwErrorTolerant({}, Messages.StrictLHSPrefix);
+ tolerateError(Messages.StrictLHSPrefix);
}
if (!isLeftHandSide(expr)) {
- throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
+ tolerateError(Messages.InvalidLHSInAssignment);
}
- expr = delegate.createUnaryExpression(token.value, expr);
- expr = delegate.markEnd(expr, startToken);
+ expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
} else if (match('+') || match('-') || match('~') || match('!')) {
startToken = lookahead;
token = lex();
expr = parseUnaryExpression();
- expr = delegate.createUnaryExpression(token.value, expr);
- expr = delegate.markEnd(expr, startToken);
+ expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
} else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
startToken = lookahead;
token = lex();
expr = parseUnaryExpression();
- expr = delegate.createUnaryExpression(token.value, expr);
- expr = delegate.markEnd(expr, startToken);
+ expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
- throwErrorTolerant({}, Messages.StrictDelete);
+ tolerateError(Messages.StrictDelete);
}
} else {
expr = parsePostfixExpression();
}
@@ -7014,14 +7405,12 @@
// Reduce: make a binary expression from the three topmost entries.
while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
right = stack.pop();
operator = stack.pop().value;
left = stack.pop();
- expr = delegate.createBinaryExpression(operator, left, right);
markers.pop();
- marker = markers[markers.length - 1];
- delegate.markEnd(expr, marker);
+ expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right);
stack.push(expr);
}
// Shift.
token = lex();
@@ -7035,14 +7424,12 @@
// Final reduce to clean-up the stack.
i = stack.length - 1;
expr = stack[i];
markers.pop();
while (i > 1) {
- expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
+ expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
i -= 2;
- marker = markers.pop();
- delegate.markEnd(expr, marker);
}
return expr;
}
@@ -7053,212 +7440,372 @@
var expr, previousAllowIn, consequent, alternate, startToken;
startToken = lookahead;
expr = parseBinaryExpression();
-
if (match('?')) {
lex();
previousAllowIn = state.allowIn;
state.allowIn = true;
consequent = parseAssignmentExpression();
state.allowIn = previousAllowIn;
expect(':');
alternate = parseAssignmentExpression();
- expr = delegate.createConditionalExpression(expr, consequent, alternate);
- delegate.markEnd(expr, startToken);
+ expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
}
return expr;
}
+ // [ES6] 14.2 Arrow Function
+
+ function parseConciseBody() {
+ if (match('{')) {
+ return parseFunctionSourceElements();
+ }
+ return parseAssignmentExpression();
+ }
+
+ function reinterpretAsCoverFormalsList(expr) {
+ var i, len, param, params, defaults, defaultCount, options, token;
+
+ defaults = [];
+ defaultCount = 0;
+ params = [expr];
+
+ switch (expr.type) {
+ case Syntax.Identifier:
+ case Syntax.AssignmentExpression:
+ break;
+ case Syntax.SequenceExpression:
+ params = expr.expressions;
+ break;
+ case PlaceHolders.ArrowParameterPlaceHolder:
+ params = expr.params;
+ break;
+ default:
+ return null;
+ }
+
+ options = {
+ paramSet: {}
+ };
+
+ for (i = 0, len = params.length; i < len; i += 1) {
+ param = params[i];
+ if (param.type === Syntax.Identifier) {
+ params[i] = param;
+ defaults.push(null);
+ validateParam(options, param, param.name);
+ } else if (param.type === Syntax.RestElement) {
+ params[i] = param;
+ defaults.push(null);
+ validateParam(options, param.argument, param.argument.name);
+ } else if (param.type === Syntax.AssignmentExpression) {
+ params[i] = param.left;
+ defaults.push(param.right);
+ ++defaultCount;
+ validateParam(options, param.left, param.left.name);
+ } else {
+ return null;
+ }
+ }
+
+ if (options.message === Messages.StrictParamDupe) {
+ token = strict ? options.stricted : options.firstRestricted;
+ throwUnexpectedToken(token, options.message);
+ }
+
+ if (defaultCount === 0) {
+ defaults = [];
+ }
+
+ return {
+ params: params,
+ defaults: defaults,
+ stricted: options.stricted,
+ firstRestricted: options.firstRestricted,
+ message: options.message
+ };
+ }
+
+ function parseArrowFunctionExpression(options, node) {
+ var previousStrict, body;
+
+ expect('=>');
+ previousStrict = strict;
+
+ body = parseConciseBody();
+
+ if (strict && options.firstRestricted) {
+ throwUnexpectedToken(options.firstRestricted, options.message);
+ }
+ if (strict && options.stricted) {
+ tolerateUnexpectedToken(options.stricted, options.message);
+ }
+
+ strict = previousStrict;
+
+ return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement);
+ }
+
// 11.13 Assignment Operators
function parseAssignmentExpression() {
- var token, left, right, node, startToken;
+ var token, expr, right, list, startToken;
- token = lookahead;
startToken = lookahead;
+ token = lookahead;
- node = left = parseConditionalExpression();
+ expr = parseConditionalExpression();
+ if (expr.type === PlaceHolders.ArrowParameterPlaceHolder || match('=>')) {
+ list = reinterpretAsCoverFormalsList(expr);
+
+ if (list) {
+ return parseArrowFunctionExpression(list, new WrappingNode(startToken));
+ }
+ }
+
if (matchAssign()) {
// LeftHandSideExpression
- if (!isLeftHandSide(left)) {
- throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
+ if (!isLeftHandSide(expr)) {
+ tolerateError(Messages.InvalidLHSInAssignment);
}
// 11.13.1
- if (strict && left.type === Syntax.Identifier && isRestrictedWord(left.name)) {
- throwErrorTolerant(token, Messages.StrictLHSAssignment);
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
+ tolerateUnexpectedToken(token, Messages.StrictLHSAssignment);
}
token = lex();
right = parseAssignmentExpression();
- node = delegate.markEnd(delegate.createAssignmentExpression(token.value, left, right), startToken);
+ expr = new WrappingNode(startToken).finishAssignmentExpression(token.value, expr, right);
}
- return node;
+ return expr;
}
// 11.14 Comma Operator
function parseExpression() {
- var expr, startToken = lookahead;
+ var expr, startToken = lookahead, expressions;
expr = parseAssignmentExpression();
if (match(',')) {
- expr = delegate.createSequenceExpression([ expr ]);
+ expressions = [expr];
- while (index < length) {
+ while (startIndex < length) {
if (!match(',')) {
break;
}
lex();
- expr.expressions.push(parseAssignmentExpression());
+ expressions.push(parseAssignmentExpression());
}
- delegate.markEnd(expr, startToken);
+ expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
}
return expr;
}
// 12.1 Block
- function parseStatementList() {
- var list = [],
- statement;
+ function parseStatementListItem() {
+ if (lookahead.type === Token.Keyword) {
+ switch (lookahead.value) {
+ case 'const':
+ case 'let':
+ return parseLexicalDeclaration();
+ case 'function':
+ return parseFunctionDeclaration(new Node());
+ case 'class':
+ return parseClassDeclaration();
+ }
+ }
- while (index < length) {
+ return parseStatement();
+ }
+
+ function parseStatementList() {
+ var list = [];
+ while (startIndex < length) {
if (match('}')) {
break;
}
- statement = parseSourceElement();
- if (typeof statement === 'undefined') {
- break;
- }
- list.push(statement);
+ list.push(parseStatementListItem());
}
return list;
}
function parseBlock() {
- var block, startToken;
+ var block, node = new Node();
- startToken = lookahead;
expect('{');
block = parseStatementList();
expect('}');
- return delegate.markEnd(delegate.createBlockStatement(block), startToken);
+ return node.finishBlockStatement(block);
}
// 12.2 Variable Statement
function parseVariableIdentifier() {
- var token, startToken;
+ var token, node = new Node();
- startToken = lookahead;
token = lex();
if (token.type !== Token.Identifier) {
- throwUnexpected(token);
+ if (strict && token.type === Token.Keyword && isStrictModeReservedWord(token.value)) {
+ tolerateUnexpectedToken(token, Messages.StrictReservedWord);
+ } else {
+ throwUnexpectedToken(token);
+ }
}
- return delegate.markEnd(delegate.createIdentifier(token.value), startToken);
+ return node.finishIdentifier(token.value);
}
- function parseVariableDeclaration(kind) {
- var init = null, id, startToken;
+ function parseVariableDeclaration() {
+ var init = null, id, node = new Node();
- startToken = lookahead;
id = parseVariableIdentifier();
// 12.2.1
if (strict && isRestrictedWord(id.name)) {
- throwErrorTolerant({}, Messages.StrictVarName);
+ tolerateError(Messages.StrictVarName);
}
- if (kind === 'const') {
- expect('=');
- init = parseAssignmentExpression();
- } else if (match('=')) {
+ if (match('=')) {
lex();
init = parseAssignmentExpression();
}
- return delegate.markEnd(delegate.createVariableDeclarator(id, init), startToken);
+ return node.finishVariableDeclarator(id, init);
}
- function parseVariableDeclarationList(kind) {
+ function parseVariableDeclarationList() {
var list = [];
do {
- list.push(parseVariableDeclaration(kind));
+ list.push(parseVariableDeclaration());
if (!match(',')) {
break;
}
lex();
- } while (index < length);
+ } while (startIndex < length);
return list;
}
- function parseVariableStatement() {
+ function parseVariableStatement(node) {
var declarations;
expectKeyword('var');
declarations = parseVariableDeclarationList();
consumeSemicolon();
- return delegate.createVariableDeclaration(declarations, 'var');
+ return node.finishVariableDeclaration(declarations);
}
- // kind may be `const` or `let`
- // Both are experimental and not in the specification yet.
- // see http://wiki.ecmascript.org/doku.php?id=harmony:const
- // and http://wiki.ecmascript.org/doku.php?id=harmony:let
- function parseConstLetDeclaration(kind) {
- var declarations, startToken;
+ function parseLexicalBinding(kind) {
+ var init = null, id, node = new Node();
- startToken = lookahead;
+ id = parseVariableIdentifier();
- expectKeyword(kind);
+ // 12.2.1
+ if (strict && isRestrictedWord(id.name)) {
+ tolerateError(Messages.StrictVarName);
+ }
- declarations = parseVariableDeclarationList(kind);
+ if (kind === 'const') {
+ if (!matchKeyword('in')) {
+ expect('=');
+ init = parseAssignmentExpression();
+ }
+ } else if (match('=')) {
+ lex();
+ init = parseAssignmentExpression();
+ }
+ return node.finishVariableDeclarator(id, init);
+ }
+
+ function parseBindingList(kind) {
+ var list = [];
+
+ do {
+ list.push(parseLexicalBinding(kind));
+ if (!match(',')) {
+ break;
+ }
+ lex();
+ } while (startIndex < length);
+
+ return list;
+ }
+
+ function parseLexicalDeclaration() {
+ var kind, declarations, node = new Node();
+
+ kind = lex().value;
+ assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const');
+
+ declarations = parseBindingList(kind);
+
consumeSemicolon();
- return delegate.markEnd(delegate.createVariableDeclaration(declarations, kind), startToken);
+ return node.finishLexicalDeclaration(declarations, kind);
}
+ function parseRestElement() {
+ var param, node = new Node();
+
+ lex();
+
+ if (match('{')) {
+ throwError(Messages.ObjectPatternAsRestParameter);
+ }
+
+ param = parseVariableIdentifier();
+
+ if (match('=')) {
+ throwError(Messages.DefaultRestParameter);
+ }
+
+ if (!match(')')) {
+ throwError(Messages.ParameterAfterRestParameter);
+ }
+
+ return node.finishRestElement(param);
+ }
+
// 12.3 Empty Statement
- function parseEmptyStatement() {
+ function parseEmptyStatement(node) {
expect(';');
- return delegate.createEmptyStatement();
+ return node.finishEmptyStatement();
}
// 12.4 Expression Statement
- function parseExpressionStatement() {
+ function parseExpressionStatement(node) {
var expr = parseExpression();
consumeSemicolon();
- return delegate.createExpressionStatement(expr);
+ return node.finishExpressionStatement(expr);
}
// 12.5 If statement
- function parseIfStatement() {
+ function parseIfStatement(node) {
var test, consequent, alternate;
expectKeyword('if');
expect('(');
@@ -7274,16 +7821,16 @@
alternate = parseStatement();
} else {
alternate = null;
}
- return delegate.createIfStatement(test, consequent, alternate);
+ return node.finishIfStatement(test, consequent, alternate);
}
// 12.6 Iteration Statements
- function parseDoWhileStatement() {
+ function parseDoWhileStatement(node) {
var body, test, oldInIteration;
expectKeyword('do');
oldInIteration = state.inIteration;
@@ -7303,14 +7850,14 @@
if (match(';')) {
lex();
}
- return delegate.createDoWhileStatement(body, test);
+ return node.finishDoWhileStatement(body, test);
}
- function parseWhileStatement() {
+ function parseWhileStatement(node) {
var test, body, oldInIteration;
expectKeyword('while');
expect('(');
@@ -7324,67 +7871,79 @@
body = parseStatement();
state.inIteration = oldInIteration;
- return delegate.createWhileStatement(test, body);
+ return node.finishWhileStatement(test, body);
}
- function parseForVariableDeclaration() {
- var token, declarations, startToken;
+ function parseForStatement(node) {
+ var init, test, update, left, right, kind, declarations,
+ body, oldInIteration, previousAllowIn = state.allowIn;
- startToken = lookahead;
- token = lex();
- declarations = parseVariableDeclarationList();
-
- return delegate.markEnd(delegate.createVariableDeclaration(declarations, token.value), startToken);
- }
-
- function parseForStatement() {
- var init, test, update, left, right, body, oldInIteration;
-
init = test = update = null;
expectKeyword('for');
expect('(');
if (match(';')) {
lex();
} else {
- if (matchKeyword('var') || matchKeyword('let')) {
+ if (matchKeyword('var')) {
+ init = new Node();
+ lex();
+
state.allowIn = false;
- init = parseForVariableDeclaration();
- state.allowIn = true;
+ init = init.finishVariableDeclaration(parseVariableDeclarationList());
+ state.allowIn = previousAllowIn;
if (init.declarations.length === 1 && matchKeyword('in')) {
lex();
left = init;
right = parseExpression();
init = null;
+ } else {
+ expect(';');
}
+ } else if (matchKeyword('const') || matchKeyword('let')) {
+ init = new Node();
+ kind = lex().value;
+
+ state.allowIn = false;
+ declarations = parseBindingList(kind);
+ state.allowIn = previousAllowIn;
+
+ if (declarations.length === 1 && declarations[0].init === null && matchKeyword('in')) {
+ init = init.finishLexicalDeclaration(declarations, kind);
+ lex();
+ left = init;
+ right = parseExpression();
+ init = null;
+ } else {
+ consumeSemicolon();
+ init = init.finishLexicalDeclaration(declarations, kind);
+ }
} else {
state.allowIn = false;
init = parseExpression();
- state.allowIn = true;
+ state.allowIn = previousAllowIn;
if (matchKeyword('in')) {
// LeftHandSideExpression
if (!isLeftHandSide(init)) {
- throwErrorTolerant({}, Messages.InvalidLHSInForIn);
+ tolerateError(Messages.InvalidLHSInForIn);
}
lex();
left = init;
right = parseExpression();
init = null;
+ } else {
+ expect(';');
}
}
-
- if (typeof left === 'undefined') {
- expect(';');
- }
}
if (typeof left === 'undefined') {
if (!match(';')) {
@@ -7405,146 +7964,145 @@
body = parseStatement();
state.inIteration = oldInIteration;
return (typeof left === 'undefined') ?
- delegate.createForStatement(init, test, update, body) :
- delegate.createForInStatement(left, right, body);
+ node.finishForStatement(init, test, update, body) :
+ node.finishForInStatement(left, right, body);
}
// 12.7 The continue statement
- function parseContinueStatement() {
+ function parseContinueStatement(node) {
var label = null, key;
expectKeyword('continue');
// Optimize the most common form: 'continue;'.
- if (source.charCodeAt(index) === 0x3B) {
+ if (source.charCodeAt(startIndex) === 0x3B) {
lex();
if (!state.inIteration) {
- throwError({}, Messages.IllegalContinue);
+ throwError(Messages.IllegalContinue);
}
- return delegate.createContinueStatement(null);
+ return node.finishContinueStatement(null);
}
- if (peekLineTerminator()) {
+ if (hasLineTerminator) {
if (!state.inIteration) {
- throwError({}, Messages.IllegalContinue);
+ throwError(Messages.IllegalContinue);
}
- return delegate.createContinueStatement(null);
+ return node.finishContinueStatement(null);
}
if (lookahead.type === Token.Identifier) {
label = parseVariableIdentifier();
key = '$' + label.name;
if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
- throwError({}, Messages.UnknownLabel, label.name);
+ throwError(Messages.UnknownLabel, label.name);
}
}
consumeSemicolon();
if (label === null && !state.inIteration) {
- throwError({}, Messages.IllegalContinue);
+ throwError(Messages.IllegalContinue);
}
- return delegate.createContinueStatement(label);
+ return node.finishContinueStatement(label);
}
// 12.8 The break statement
- function parseBreakStatement() {
+ function parseBreakStatement(node) {
var label = null, key;
expectKeyword('break');
// Catch the very common case first: immediately a semicolon (U+003B).
- if (source.charCodeAt(index) === 0x3B) {
+ if (source.charCodeAt(lastIndex) === 0x3B) {
lex();
if (!(state.inIteration || state.inSwitch)) {
- throwError({}, Messages.IllegalBreak);
+ throwError(Messages.IllegalBreak);
}
- return delegate.createBreakStatement(null);
+ return node.finishBreakStatement(null);
}
- if (peekLineTerminator()) {
+ if (hasLineTerminator) {
if (!(state.inIteration || state.inSwitch)) {
- throwError({}, Messages.IllegalBreak);
+ throwError(Messages.IllegalBreak);
}
- return delegate.createBreakStatement(null);
+ return node.finishBreakStatement(null);
}
if (lookahead.type === Token.Identifier) {
label = parseVariableIdentifier();
key = '$' + label.name;
if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
- throwError({}, Messages.UnknownLabel, label.name);
+ throwError(Messages.UnknownLabel, label.name);
}
}
consumeSemicolon();
if (label === null && !(state.inIteration || state.inSwitch)) {
- throwError({}, Messages.IllegalBreak);
+ throwError(Messages.IllegalBreak);
}
- return delegate.createBreakStatement(label);
+ return node.finishBreakStatement(label);
}
// 12.9 The return statement
- function parseReturnStatement() {
+ function parseReturnStatement(node) {
var argument = null;
expectKeyword('return');
if (!state.inFunctionBody) {
- throwErrorTolerant({}, Messages.IllegalReturn);
+ tolerateError(Messages.IllegalReturn);
}
// 'return' followed by a space and an identifier is very common.
- if (source.charCodeAt(index) === 0x20) {
- if (isIdentifierStart(source.charCodeAt(index + 1))) {
+ if (source.charCodeAt(lastIndex) === 0x20) {
+ if (isIdentifierStart(source.charCodeAt(lastIndex + 1))) {
argument = parseExpression();
consumeSemicolon();
- return delegate.createReturnStatement(argument);
+ return node.finishReturnStatement(argument);
}
}
- if (peekLineTerminator()) {
- return delegate.createReturnStatement(null);
+ if (hasLineTerminator) {
+ // HACK
+ return node.finishReturnStatement(null);
}
if (!match(';')) {
if (!match('}') && lookahead.type !== Token.EOF) {
argument = parseExpression();
}
}
consumeSemicolon();
- return delegate.createReturnStatement(argument);
+ return node.finishReturnStatement(argument);
}
// 12.10 The with statement
- function parseWithStatement() {
+ function parseWithStatement(node) {
var object, body;
if (strict) {
- // TODO(ikarienator): Should we update the test cases instead?
- skipComment();
- throwErrorTolerant({}, Messages.StrictModeWith);
+ tolerateError(Messages.StrictModeWith);
}
expectKeyword('with');
expect('(');
@@ -7553,40 +8111,39 @@
expect(')');
body = parseStatement();
- return delegate.createWithStatement(object, body);
+ return node.finishWithStatement(object, body);
}
// 12.10 The swith statement
function parseSwitchCase() {
- var test, consequent = [], statement, startToken;
+ var test, consequent = [], statement, node = new Node();
- startToken = lookahead;
if (matchKeyword('default')) {
lex();
test = null;
} else {
expectKeyword('case');
test = parseExpression();
}
expect(':');
- while (index < length) {
+ while (startIndex < length) {
if (match('}') || matchKeyword('default') || matchKeyword('case')) {
break;
}
- statement = parseStatement();
+ statement = parseStatementListItem();
consequent.push(statement);
}
- return delegate.markEnd(delegate.createSwitchCase(test, consequent), startToken);
+ return node.finishSwitchCase(test, consequent);
}
- function parseSwitchStatement() {
+ function parseSwitchStatement(node) {
var discriminant, cases, clause, oldInSwitch, defaultFound;
expectKeyword('switch');
expect('(');
@@ -7599,173 +8156,170 @@
cases = [];
if (match('}')) {
lex();
- return delegate.createSwitchStatement(discriminant, cases);
+ return node.finishSwitchStatement(discriminant, cases);
}
oldInSwitch = state.inSwitch;
state.inSwitch = true;
defaultFound = false;
- while (index < length) {
+ while (startIndex < length) {
if (match('}')) {
break;
}
clause = parseSwitchCase();
if (clause.test === null) {
if (defaultFound) {
- throwError({}, Messages.MultipleDefaultsInSwitch);
+ throwError(Messages.MultipleDefaultsInSwitch);
}
defaultFound = true;
}
cases.push(clause);
}
state.inSwitch = oldInSwitch;
expect('}');
- return delegate.createSwitchStatement(discriminant, cases);
+ return node.finishSwitchStatement(discriminant, cases);
}
// 12.13 The throw statement
- function parseThrowStatement() {
+ function parseThrowStatement(node) {
var argument;
expectKeyword('throw');
- if (peekLineTerminator()) {
- throwError({}, Messages.NewlineAfterThrow);
+ if (hasLineTerminator) {
+ throwError(Messages.NewlineAfterThrow);
}
argument = parseExpression();
consumeSemicolon();
- return delegate.createThrowStatement(argument);
+ return node.finishThrowStatement(argument);
}
// 12.14 The try statement
function parseCatchClause() {
- var param, body, startToken;
+ var param, body, node = new Node();
- startToken = lookahead;
expectKeyword('catch');
expect('(');
if (match(')')) {
- throwUnexpected(lookahead);
+ throwUnexpectedToken(lookahead);
}
param = parseVariableIdentifier();
// 12.14.1
if (strict && isRestrictedWord(param.name)) {
- throwErrorTolerant({}, Messages.StrictCatchVariable);
+ tolerateError(Messages.StrictCatchVariable);
}
expect(')');
body = parseBlock();
- return delegate.markEnd(delegate.createCatchClause(param, body), startToken);
+ return node.finishCatchClause(param, body);
}
- function parseTryStatement() {
- var block, handlers = [], finalizer = null;
+ function parseTryStatement(node) {
+ var block, handler = null, finalizer = null;
expectKeyword('try');
block = parseBlock();
if (matchKeyword('catch')) {
- handlers.push(parseCatchClause());
+ handler = parseCatchClause();
}
if (matchKeyword('finally')) {
lex();
finalizer = parseBlock();
}
- if (handlers.length === 0 && !finalizer) {
- throwError({}, Messages.NoCatchOrFinally);
+ if (!handler && !finalizer) {
+ throwError(Messages.NoCatchOrFinally);
}
- return delegate.createTryStatement(block, [], handlers, finalizer);
+ return node.finishTryStatement(block, handler, finalizer);
}
// 12.15 The debugger statement
- function parseDebuggerStatement() {
+ function parseDebuggerStatement(node) {
expectKeyword('debugger');
consumeSemicolon();
- return delegate.createDebuggerStatement();
+ return node.finishDebuggerStatement();
}
// 12 Statements
function parseStatement() {
var type = lookahead.type,
expr,
labeledBody,
key,
- startToken;
+ node;
if (type === Token.EOF) {
- throwUnexpected(lookahead);
+ throwUnexpectedToken(lookahead);
}
if (type === Token.Punctuator && lookahead.value === '{') {
return parseBlock();
}
- startToken = lookahead;
+ node = new Node();
if (type === Token.Punctuator) {
switch (lookahead.value) {
case ';':
- return delegate.markEnd(parseEmptyStatement(), startToken);
+ return parseEmptyStatement(node);
case '(':
- return delegate.markEnd(parseExpressionStatement(), startToken);
+ return parseExpressionStatement(node);
default:
break;
}
- }
-
- if (type === Token.Keyword) {
+ } else if (type === Token.Keyword) {
switch (lookahead.value) {
case 'break':
- return delegate.markEnd(parseBreakStatement(), startToken);
+ return parseBreakStatement(node);
case 'continue':
- return delegate.markEnd(parseContinueStatement(), startToken);
+ return parseContinueStatement(node);
case 'debugger':
- return delegate.markEnd(parseDebuggerStatement(), startToken);
+ return parseDebuggerStatement(node);
case 'do':
- return delegate.markEnd(parseDoWhileStatement(), startToken);
+ return parseDoWhileStatement(node);
case 'for':
- return delegate.markEnd(parseForStatement(), startToken);
+ return parseForStatement(node);
case 'function':
- return delegate.markEnd(parseFunctionDeclaration(), startToken);
+ return parseFunctionDeclaration(node);
case 'if':
- return delegate.markEnd(parseIfStatement(), startToken);
+ return parseIfStatement(node);
case 'return':
- return delegate.markEnd(parseReturnStatement(), startToken);
+ return parseReturnStatement(node);
case 'switch':
- return delegate.markEnd(parseSwitchStatement(), startToken);
+ return parseSwitchStatement(node);
case 'throw':
- return delegate.markEnd(parseThrowStatement(), startToken);
+ return parseThrowStatement(node);
case 'try':
- return delegate.markEnd(parseTryStatement(), startToken);
+ return parseTryStatement(node);
case 'var':
- return delegate.markEnd(parseVariableStatement(), startToken);
+ return parseVariableStatement(node);
case 'while':
- return delegate.markEnd(parseWhileStatement(), startToken);
+ return parseWhileStatement(node);
case 'with':
- return delegate.markEnd(parseWithStatement(), startToken);
+ return parseWithStatement(node);
default:
break;
}
}
@@ -7775,50 +8329,50 @@
if ((expr.type === Syntax.Identifier) && match(':')) {
lex();
key = '$' + expr.name;
if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
- throwError({}, Messages.Redeclaration, 'Label', expr.name);
+ throwError(Messages.Redeclaration, 'Label', expr.name);
}
state.labelSet[key] = true;
labeledBody = parseStatement();
delete state.labelSet[key];
- return delegate.markEnd(delegate.createLabeledStatement(expr, labeledBody), startToken);
+ return node.finishLabeledStatement(expr, labeledBody);
}
consumeSemicolon();
- return delegate.markEnd(delegate.createExpressionStatement(expr), startToken);
+ return node.finishExpressionStatement(expr);
}
// 13 Function Definition
function parseFunctionSourceElements() {
- var sourceElement, sourceElements = [], token, directive, firstRestricted,
- oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, startToken;
+ var statement, body = [], token, directive, firstRestricted,
+ oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesisCount,
+ node = new Node();
- startToken = lookahead;
expect('{');
- while (index < length) {
+ while (startIndex < length) {
if (lookahead.type !== Token.StringLiteral) {
break;
}
token = lookahead;
- sourceElement = parseSourceElement();
- sourceElements.push(sourceElement);
- if (sourceElement.expression.type !== Syntax.Literal) {
+ statement = parseStatementListItem();
+ body.push(statement);
+ if (statement.expression.type !== Syntax.Literal) {
// this is not directive
break;
}
directive = source.slice(token.start + 1, token.end - 1);
if (directive === 'use strict') {
strict = true;
if (firstRestricted) {
- throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
+ tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
}
} else {
if (!firstRestricted && token.octal) {
firstRestricted = token;
}
@@ -7827,98 +8381,135 @@
oldLabelSet = state.labelSet;
oldInIteration = state.inIteration;
oldInSwitch = state.inSwitch;
oldInFunctionBody = state.inFunctionBody;
+ oldParenthesisCount = state.parenthesizedCount;
state.labelSet = {};
state.inIteration = false;
state.inSwitch = false;
state.inFunctionBody = true;
+ state.parenthesizedCount = 0;
- while (index < length) {
+ while (startIndex < length) {
if (match('}')) {
break;
}
- sourceElement = parseSourceElement();
- if (typeof sourceElement === 'undefined') {
- break;
- }
- sourceElements.push(sourceElement);
+ body.push(parseStatementListItem());
}
expect('}');
state.labelSet = oldLabelSet;
state.inIteration = oldInIteration;
state.inSwitch = oldInSwitch;
state.inFunctionBody = oldInFunctionBody;
+ state.parenthesizedCount = oldParenthesisCount;
- return delegate.markEnd(delegate.createBlockStatement(sourceElements), startToken);
+ return node.finishBlockStatement(body);
}
+ 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, param, def;
+
+ token = lookahead;
+ if (token.value === '...') {
+ param = parseRestElement();
+ validateParam(options, param.argument, param.argument.name);
+ options.params.push(param);
+ options.defaults.push(null);
+ return false;
+ }
+
+ param = parseVariableIdentifier();
+ validateParam(options, token, token.value);
+
+ if (match('=')) {
+ lex();
+ def = parseAssignmentExpression();
+ ++options.defaultCount;
+ }
+
+ options.params.push(param);
+ options.defaults.push(def);
+
+ return !match(')');
+ }
+
function parseParams(firstRestricted) {
- var param, params = [], token, stricted, paramSet, key, message;
+ var options;
+
+ options = {
+ params: [],
+ defaultCount: 0,
+ defaults: [],
+ firstRestricted: firstRestricted
+ };
+
expect('(');
if (!match(')')) {
- paramSet = {};
- while (index < length) {
- token = lookahead;
- param = parseVariableIdentifier();
- key = '$' + token.value;
- if (strict) {
- if (isRestrictedWord(token.value)) {
- stricted = token;
- message = Messages.StrictParamName;
- }
- if (Object.prototype.hasOwnProperty.call(paramSet, key)) {
- stricted = token;
- message = Messages.StrictParamDupe;
- }
- } else if (!firstRestricted) {
- if (isRestrictedWord(token.value)) {
- firstRestricted = token;
- message = Messages.StrictParamName;
- } else if (isStrictModeReservedWord(token.value)) {
- firstRestricted = token;
- message = Messages.StrictReservedWord;
- } else if (Object.prototype.hasOwnProperty.call(paramSet, key)) {
- firstRestricted = token;
- message = Messages.StrictParamDupe;
- }
- }
- params.push(param);
- paramSet[key] = true;
- if (match(')')) {
+ options.paramSet = {};
+ while (startIndex < length) {
+ if (!parseParam(options)) {
break;
}
expect(',');
}
}
expect(')');
+ if (options.defaultCount === 0) {
+ options.defaults = [];
+ }
+
return {
- params: params,
- stricted: stricted,
- firstRestricted: firstRestricted,
- message: message
+ params: options.params,
+ defaults: options.defaults,
+ stricted: options.stricted,
+ firstRestricted: options.firstRestricted,
+ message: options.message
};
}
- function parseFunctionDeclaration() {
- var id, params = [], body, token, stricted, tmp, firstRestricted, message, previousStrict, startToken;
+ function parseFunctionDeclaration(node) {
+ var id, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict;
- startToken = lookahead;
-
expectKeyword('function');
token = lookahead;
id = parseVariableIdentifier();
if (strict) {
if (isRestrictedWord(token.value)) {
- throwErrorTolerant(token, Messages.StrictFunctionName);
+ tolerateUnexpectedToken(token, Messages.StrictFunctionName);
}
} else {
if (isRestrictedWord(token.value)) {
firstRestricted = token;
message = Messages.StrictFunctionName;
@@ -7928,41 +8519,42 @@
}
}
tmp = parseParams(firstRestricted);
params = tmp.params;
+ defaults = tmp.defaults;
stricted = tmp.stricted;
firstRestricted = tmp.firstRestricted;
if (tmp.message) {
message = tmp.message;
}
previousStrict = strict;
body = parseFunctionSourceElements();
if (strict && firstRestricted) {
- throwError(firstRestricted, message);
+ throwUnexpectedToken(firstRestricted, message);
}
if (strict && stricted) {
- throwErrorTolerant(stricted, message);
+ tolerateUnexpectedToken(stricted, message);
}
strict = previousStrict;
- return delegate.markEnd(delegate.createFunctionDeclaration(id, params, [], body), startToken);
+ return node.finishFunctionDeclaration(id, params, defaults, body);
}
function parseFunctionExpression() {
- var token, id = null, stricted, firstRestricted, message, tmp, params = [], body, previousStrict, startToken;
+ var token, id = null, stricted, firstRestricted, message, tmp,
+ params = [], defaults = [], body, previousStrict, node = new Node();
- startToken = lookahead;
expectKeyword('function');
if (!match('(')) {
token = lookahead;
id = parseVariableIdentifier();
if (strict) {
if (isRestrictedWord(token.value)) {
- throwErrorTolerant(token, Messages.StrictFunctionName);
+ tolerateUnexpectedToken(token, Messages.StrictFunctionName);
}
} else {
if (isRestrictedWord(token.value)) {
firstRestricted = token;
message = Messages.StrictFunctionName;
@@ -7973,98 +8565,177 @@
}
}
tmp = parseParams(firstRestricted);
params = tmp.params;
+ defaults = tmp.defaults;
stricted = tmp.stricted;
firstRestricted = tmp.firstRestricted;
if (tmp.message) {
message = tmp.message;
}
previousStrict = strict;
body = parseFunctionSourceElements();
if (strict && firstRestricted) {
- throwError(firstRestricted, message);
+ throwUnexpectedToken(firstRestricted, message);
}
if (strict && stricted) {
- throwErrorTolerant(stricted, message);
+ tolerateUnexpectedToken(stricted, message);
}
strict = previousStrict;
- return delegate.markEnd(delegate.createFunctionExpression(id, params, [], body), startToken);
+ return node.finishFunctionExpression(id, params, defaults, body);
}
- // 14 Program
- function parseSourceElement() {
- if (lookahead.type === Token.Keyword) {
- switch (lookahead.value) {
- case 'const':
- case 'let':
- return parseConstLetDeclaration(lookahead.value);
- case 'function':
- return parseFunctionDeclaration();
- default:
- return parseStatement();
+ function parseClassBody() {
+ var classBody, token, isStatic, hasConstructor = false, body, method, computed, key;
+
+ classBody = new Node();
+
+ expect('{');
+ body = [];
+ while (!match('}')) {
+ if (match(';')) {
+ lex();
+ } else {
+ method = new Node();
+ token = lookahead;
+ isStatic = false;
+ computed = match('[');
+ key = parseObjectPropertyKey();
+ if (key.name === 'static' && lookaheadPropertyName()) {
+ token = lookahead;
+ isStatic = true;
+ computed = match('[');
+ key = parseObjectPropertyKey();
+ }
+ method = tryParseMethodDefinition(token, key, computed, method);
+ if (method) {
+ method.static = isStatic;
+ if (method.kind === 'init') {
+ method.kind = 'method';
+ }
+ if (!isStatic) {
+ if (!method.computed && (method.key.name || method.key.value.toString()) === 'constructor') {
+ if (method.kind !== 'method' || !method.method || method.value.generator) {
+ throwUnexpectedToken(token, Messages.ConstructorSpecialMethod);
+ }
+ if (hasConstructor) {
+ throwUnexpectedToken(token, Messages.DuplicateConstructor);
+ } else {
+ hasConstructor = true;
+ }
+ method.kind = 'constructor';
+ }
+ } else {
+ if (!method.computed && (method.key.name || method.key.value.toString()) === 'prototype') {
+ throwUnexpectedToken(token, Messages.StaticPrototype);
+ }
+ }
+ method.type = Syntax.MethodDefinition;
+ delete method.method;
+ delete method.shorthand;
+ body.push(method);
+ } else {
+ throwUnexpectedToken(lookahead);
+ }
}
}
+ lex();
+ return classBody.finishClassBody(body);
+ }
- if (lookahead.type !== Token.EOF) {
- return parseStatement();
+ function parseClassDeclaration() {
+ var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict;
+ strict = true;
+
+ expectKeyword('class');
+
+ id = parseVariableIdentifier();
+
+ if (matchKeyword('extends')) {
+ lex();
+ superClass = parseLeftHandSideExpressionAllowCall();
}
+ classBody = parseClassBody();
+ strict = previousStrict;
+
+ return classNode.finishClassDeclaration(id, superClass, classBody);
}
- function parseSourceElements() {
- var sourceElement, sourceElements = [], token, directive, firstRestricted;
+ function parseClassExpression() {
+ var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict;
+ strict = true;
- while (index < length) {
+ expectKeyword('class');
+
+ if (lookahead.type === Token.Identifier) {
+ id = parseVariableIdentifier();
+ }
+
+ if (matchKeyword('extends')) {
+ lex();
+ superClass = parseLeftHandSideExpressionAllowCall();
+ }
+ classBody = parseClassBody();
+ strict = previousStrict;
+
+ return classNode.finishClassExpression(id, superClass, classBody);
+ }
+
+ // 14 Program
+
+ function parseScriptBody() {
+ var statement, body = [], token, directive, firstRestricted;
+
+ while (startIndex < length) {
token = lookahead;
if (token.type !== Token.StringLiteral) {
break;
}
- sourceElement = parseSourceElement();
- sourceElements.push(sourceElement);
- if (sourceElement.expression.type !== Syntax.Literal) {
+ statement = parseStatementListItem();
+ body.push(statement);
+ if (statement.expression.type !== Syntax.Literal) {
// this is not directive
break;
}
directive = source.slice(token.start + 1, token.end - 1);
if (directive === 'use strict') {
strict = true;
if (firstRestricted) {
- throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
+ tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
}
} else {
if (!firstRestricted && token.octal) {
firstRestricted = token;
}
}
}
- while (index < length) {
- sourceElement = parseSourceElement();
+ while (startIndex < length) {
+ statement = parseStatementListItem();
/* istanbul ignore if */
- if (typeof sourceElement === 'undefined') {
+ if (typeof statement === 'undefined') {
break;
}
- sourceElements.push(sourceElement);
+ body.push(statement);
}
- return sourceElements;
+ return body;
}
function parseProgram() {
- var body, startToken;
+ var body, node;
- skipComment();
peek();
- startToken = lookahead;
+ node = new Node();
strict = false;
- body = parseSourceElements();
- return delegate.markEnd(delegate.createProgram(body), startToken);
+ body = parseScriptBody();
+ return node.finishProgram(body);
}
function filterTokenLocation() {
var i, entry, token, tokens = [];
@@ -8072,10 +8743,16 @@
entry = extra.tokens[i];
token = {
type: entry.type,
value: entry.value
};
+ if (entry.regex) {
+ token.regex = {
+ pattern: entry.regex.pattern,
+ flags: entry.regex.flags
+ };
+ }
if (extra.range) {
token.range = entry.range;
}
if (extra.loc) {
token.loc = entry.loc;
@@ -8086,23 +8763,24 @@
extra.tokens = tokens;
}
function tokenize(code, options) {
var toString,
- token,
tokens;
toString = String;
if (typeof code !== 'string' && !(code instanceof String)) {
code = toString(code);
}
- delegate = SyntaxTreeDelegate;
source = code;
index = 0;
lineNumber = (source.length > 0) ? 1 : 0;
lineStart = 0;
+ startIndex = index;
+ startLineNumber = lineNumber;
+ startLineStart = lineStart;
length = source.length;
lookahead = null;
state = {
allowIn: true,
labelSet: {},
@@ -8139,18 +8817,17 @@
peek();
if (lookahead.type === Token.EOF) {
return extra.tokens;
}
- token = lex();
+ lex();
while (lookahead.type !== Token.EOF) {
try {
- token = lex();
+ lex();
} catch (lexError) {
- token = lookahead;
if (extra.errors) {
- extra.errors.push(lexError);
+ recordError(lexError);
// We have to break on the first error
// to avoid infinite loops.
break;
} else {
throw lexError;
@@ -8180,15 +8857,17 @@
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;
+ startIndex = index;
+ startLineNumber = lineNumber;
+ startLineStart = lineStart;
length = source.length;
lookahead = null;
state = {
allowIn: true,
labelSet: {},
@@ -8246,11 +8925,11 @@
return program;
}
// Sync with *.json manifests.
- exports.version = '1.2.2';
+ exports.version = '2.1.0';
exports.tokenize = tokenize;
exports.parse = parse;
@@ -14167,10 +14846,13 @@
// Copy sourcesContents of applied map.
aSourceMapConsumer.sources.forEach(function (sourceFile) {
var content = aSourceMapConsumer.sourceContentFor(sourceFile);
if (content) {
+ if (aSourceMapPath) {
+ sourceFile = util.join(aSourceMapPath, sourceFile);
+ }
if (sourceRoot) {
sourceFile = util.relative(sourceRoot, sourceFile);
}
this.setSourceContent(sourceFile, content);
}
@@ -14345,10 +15027,17 @@
define('source-map/source-node', function (require, exports, module) {
var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator;
var util = require('./util');
+ // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
+ // operating systems these days (capturing the result).
+ var REGEX_NEWLINE = /(\r?\n)/g;
+
+ // Matches a Windows-style newline, or any character.
+ var REGEX_CHARACTER = /\r\n|[\s\S]/g;
+
/**
* SourceNodes provide a way to abstract over interpolating/concatenating
* snippets of generated JavaScript source code while maintaining the line and
* column information associated with the original source code.
*
@@ -14379,13 +15068,21 @@
function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) {
// The SourceNode we want to fill with the generated code
// and the SourceMap
var node = new SourceNode();
- // The generated code
- // Processed fragments are removed from this array.
- var remainingLines = aGeneratedCode.split('\n');
+ // All even indices of this array are one line of the generated code,
+ // while all odd indices are the newlines between two adjacent lines
+ // (since `REGEX_NEWLINE` captures its match).
+ // Processed fragments are removed from this array, by calling `shiftNextLine`.
+ var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);
+ var shiftNextLine = function() {
+ var lineContents = remainingLines.shift();
+ // The last line of a file might not have a newline.
+ var newLine = remainingLines.shift() || "";
+ return lineContents + newLine;
+ };
// We need to remember the position of "remainingLines"
var lastGeneratedLine = 1, lastGeneratedColumn = 0;
// The generate SourceNodes we need a code range.
@@ -14398,11 +15095,11 @@
// We add the code from "lastMapping" to "mapping":
// First check if there is a new line in between.
if (lastGeneratedLine < mapping.generatedLine) {
var code = "";
// Associate first line with "lastMapping"
- addMappingWithCode(lastMapping, remainingLines.shift() + "\n");
+ addMappingWithCode(lastMapping, shiftNextLine());
lastGeneratedLine++;
lastGeneratedColumn = 0;
// The remaining code is added without mapping
} else {
// There is no new line in between.
@@ -14422,11 +15119,11 @@
}
// We add the generated code until the first mapping
// to the SourceNode without any mapping.
// Each line is added as separate string.
while (lastGeneratedLine < mapping.generatedLine) {
- node.add(remainingLines.shift() + "\n");
+ node.add(shiftNextLine());
lastGeneratedLine++;
}
if (lastGeneratedColumn < mapping.generatedColumn) {
var nextLine = remainingLines[0];
node.add(nextLine.substr(0, mapping.generatedColumn));
@@ -14437,16 +15134,14 @@
}, this);
// We have processed all mappings.
if (remainingLines.length > 0) {
if (lastMapping) {
// Associate the remaining code in the current line with "lastMapping"
- var lastLine = remainingLines.shift();
- if (remainingLines.length > 0) lastLine += "\n";
- addMappingWithCode(lastMapping, lastLine);
+ addMappingWithCode(lastMapping, shiftNextLine());
}
// and add the remaining lines without any mapping
- node.add(remainingLines.join("\n"));
+ node.add(remainingLines.join(""));
}
// Copy sourcesContent into SourceNode
aSourceMapConsumer.sources.forEach(function (sourceFile) {
var content = aSourceMapConsumer.sourceContentFor(sourceFile);
@@ -14681,12 +15376,12 @@
}
});
lastOriginalSource = null;
sourceMappingActive = false;
}
- chunk.split('').forEach(function (ch, idx, array) {
- if (ch === '\n') {
+ chunk.match(REGEX_CHARACTER).forEach(function (ch, idx, array) {
+ if (REGEX_NEWLINE.test(ch)) {
generated.line++;
generated.column = 0;
// Mappings end at eol
if (idx + 1 === array.length) {
lastOriginalSource = null;
@@ -14704,11 +15399,11 @@
},
name: original.name
});
}
} else {
- generated.column++;
+ generated.column += ch.length;
}
});
});
this.walkSourceContents(function (sourceFile, sourceContent) {
map.setSourceContent(sourceFile, sourceContent);
@@ -15635,14 +16330,14 @@
var self = this;
var args = [];
var parameters = [];
arg_parameter_pairs.forEach(function(pair) {
- var split = pair.split(":");
+ var splitAt = pair.lastIndexOf(":");
- args.push(split[0]);
- parameters.push(split[1]);
+ args.push(pair.substr(0, splitAt));
+ parameters.push(pair.substr(splitAt + 1));
});
var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";
wrapped_tl = parse(wrapped_tl);
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
@@ -16493,18 +17188,11 @@
|| is_unicode_connector_punctuation(ch)
;
};
function is_identifier_string(str){
- var i = str.length;
- if (i == 0) return false;
- if (!is_identifier_start(str.charCodeAt(0))) return false;
- while (--i >= 0) {
- if (!is_identifier_char(str.charAt(i)))
- return false;
- }
- return true;
+ return /^[a-z_$][a-z0-9_$]*$/i.test(str);
};
function parse_js_number(num) {
if (RE_HEX_NUMBER.test(num)) {
return parseInt(num.substr(2), 16);
@@ -16941,10 +17629,11 @@
strict : false,
filename : null,
toplevel : null,
expression : false,
html5_comments : true,
+ bare_returns : false,
});
var S = {
input : (typeof $TEXT == "string"
? tokenizer($TEXT, options.filename,
@@ -17120,11 +17809,11 @@
case "if":
return if_();
case "return":
- if (S.in_function == 0)
+ if (S.in_function == 0 && !options.bare_returns)
croak("'return' outside of function");
return new AST_Return({
value: ( is("punc", ";")
? (next(), null)
: can_insert_semicolon()
@@ -18534,10 +19223,11 @@
&& node.name == "eval") {
AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
}
if (options.unreferenced
&& (node instanceof AST_SymbolDeclaration || node instanceof AST_Label)
+ && !(node instanceof AST_SymbolCatch)
&& node.unreferenced()) {
AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
type: node instanceof AST_Label ? "Label" : "Symbol",
name: node.name,
file: node.start.file,
@@ -19004,11 +19694,17 @@
});
/* -----[ PARENTHESES ]----- */
function PARENS(nodetype, func) {
- nodetype.DEFMETHOD("needs_parens", func);
+ if (Array.isArray(nodetype)) {
+ nodetype.forEach(function(nodetype){
+ PARENS(nodetype, func);
+ });
+ } else {
+ nodetype.DEFMETHOD("needs_parens", func);
+ }
};
PARENS(AST_Node, function(){
return false;
});
@@ -19023,11 +19719,11 @@
// interpreted as a block of code.
PARENS(AST_Object, function(output){
return first_in_statement(output);
});
- PARENS(AST_Unary, function(output){
+ PARENS([ AST_Unary, AST_Undefined ], function(output){
var p = output.parent();
return p instanceof AST_PropAccess && p.expression === this;
});
PARENS(AST_Seq, function(output){
@@ -19119,11 +19815,11 @@
var p = output.parent();
if (p instanceof AST_PropAccess && p.expression === this)
return true;
});
- function assign_and_conditional_paren_rules(output) {
+ PARENS([ AST_Assign, AST_Conditional ], function (output){
var p = output.parent();
// !(a = false) → true
if (p instanceof AST_Unary)
return true;
// 1 + (a = 2) + 3 → 6, side effect setting a = 2
@@ -19136,15 +19832,12 @@
if (p instanceof AST_Conditional && p.condition === this)
return true;
// (a = foo)["prop"] —or— (a = foo).prop
if (p instanceof AST_PropAccess && p.expression === this)
return true;
- };
+ });
- PARENS(AST_Assign, assign_and_conditional_paren_rules);
- PARENS(AST_Conditional, assign_and_conditional_paren_rules);
-
/* -----[ PRINTERS ]----- */
DEFPRINT(AST_Directive, function(self, output){
output.print_string(self.value);
output.semicolon();
@@ -19226,11 +19919,11 @@
});
DEFPRINT(AST_For, function(self, output){
output.print("for");
output.space();
output.with_parens(function(){
- if (self.init) {
+ if (self.init && !(self.init instanceof AST_EmptyStatement)) {
if (self.init instanceof AST_Definitions) {
self.init.print(output);
} else {
parenthesize_for_noin(self.init, output, true);
}
@@ -19566,12 +20259,16 @@
output.print("]");
});
DEFPRINT(AST_UnaryPrefix, function(self, output){
var op = self.operator;
output.print(op);
- if (/^[a-z]/i.test(op))
+ if (/^[a-z]/i.test(op)
+ || (/[+-]$/.test(op)
+ && self.expression instanceof AST_UnaryPrefix
+ && /^[+-]/.test(self.expression.operator))) {
output.space();
+ }
self.expression.print(output);
});
DEFPRINT(AST_UnaryPostfix, function(self, output){
self.expression.print(output);
output.print(self.operator);
@@ -20646,10 +21343,18 @@
def(AST_SymbolRef, function(compressor){
var d = this.definition();
if (d && d.constant && d.init) return ev(d.init, compressor);
throw def;
});
+ def(AST_Dot, function(compressor){
+ if (compressor.option("unsafe") && this.property == "length") {
+ var str = ev(this.expression, compressor);
+ if (typeof str == "string")
+ return str.length;
+ }
+ throw def;
+ });
})(function(node, func){
node.DEFMETHOD("_eval", func);
});
// method to negate an expression
@@ -20760,11 +21465,13 @@
return this.operator == "delete"
|| this.operator == "++"
|| this.operator == "--"
|| this.expression.has_side_effects(compressor);
});
- def(AST_SymbolRef, function(compressor){ return false });
+ def(AST_SymbolRef, function(compressor){
+ return this.global() && this.undeclared();
+ });
def(AST_Object, function(compressor){
for (var i = this.properties.length; --i >= 0;)
if (this.properties[i].has_side_effects(compressor))
return true;
return false;
@@ -21608,10 +22315,11 @@
}
}));
} catch(ex) {
if (ex !== ast) throw ex;
};
+ if (!fun) return self;
var args = fun.argnames.map(function(arg, i){
return make_node(AST_String, self.args[i], {
value: arg.print_to_string()
});
});
@@ -22183,10 +22891,21 @@
}),
consequent: consequent.consequent,
alternative: alternative
});
}
+ // x=y?1:1 --> x=1
+ if (consequent instanceof AST_Constant
+ && alternative instanceof AST_Constant
+ && consequent.equivalent_to(alternative)) {
+ if (self.condition.has_side_effects(compressor)) {
+ return AST_Seq.from_array([self.condition, make_node_from_constant(compressor, consequent.value, self)]);
+ } else {
+ return make_node_from_constant(compressor, consequent.value, self);
+
+ }
+ }
return self;
});
OPT(AST_Boolean, function(self, compressor){
if (compressor.option("booleans")) {
@@ -22220,11 +22939,11 @@
prop = prop.getValue();
if (RESERVED_WORDS(prop) ? compressor.option("screw_ie8") : is_identifier_string(prop)) {
return make_node(AST_Dot, self, {
expression : self.expression,
property : prop
- });
+ }).optimize(compressor);
}
var v = parseFloat(prop);
if (!isNaN(v) && v.toString() == prop) {
self.property = make_node(AST_Number, self.property, {
value: v
@@ -22232,10 +22951,23 @@
}
}
return self;
});
+ OPT(AST_Dot, function(self, compressor){
+ var prop = self.property;
+ if (RESERVED_WORDS(prop) && !compressor.option("screw_ie8")) {
+ return make_node(AST_Sub, self, {
+ expression : self.expression,
+ property : make_node(AST_String, self, {
+ value: prop
+ })
+ }).optimize(compressor);
+ }
+ return self.evaluate(compressor)[0];
+ });
+
function literals_in_boolean_context(self, compressor) {
if (compressor.option("booleans") && compressor.in_boolean_context()) {
return make_node(AST_True, self);
}
return self;
@@ -22316,11 +23048,11 @@
return;
}
source = info.source;
orig_line = info.line;
orig_col = info.column;
- name = info.name;
+ name = info.name || name;
}
generator.addMapping({
generated : { line: gen_line + options.dest_line_diff, column: gen_col },
original : { line: orig_line + options.orig_line_diff, column: orig_col },
source : source,
@@ -22380,73 +23112,95 @@
"use strict";
(function(){
var MOZ_TO_ME = {
- TryStatement : function(M) {
+ ExpressionStatement: function(M) {
+ var expr = M.expression;
+ if (expr.type === "Literal" && typeof expr.value === "string") {
+ return new AST_Directive({
+ start: my_start_token(M),
+ end: my_end_token(M),
+ value: expr.value
+ });
+ }
+ return new AST_SimpleStatement({
+ start: my_start_token(M),
+ end: my_end_token(M),
+ body: from_moz(expr)
+ });
+ },
+ TryStatement: function(M) {
+ var handlers = M.handlers || [M.handler];
+ if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) {
+ throw new Error("Multiple catch clauses are not supported.");
+ }
return new AST_Try({
start : my_start_token(M),
end : my_end_token(M),
body : from_moz(M.block).body,
- bcatch : from_moz(M.handlers[0]),
+ bcatch : from_moz(handlers[0]),
bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
});
},
- CatchClause : function(M) {
- return new AST_Catch({
- start : my_start_token(M),
- end : my_end_token(M),
- argname : from_moz(M.param),
- body : from_moz(M.body).body
- });
+ Property: function(M) {
+ var key = M.key;
+ var name = key.type == "Identifier" ? key.name : key.value;
+ var args = {
+ start : my_start_token(key),
+ end : my_end_token(M.value),
+ key : name,
+ value : from_moz(M.value)
+ };
+ switch (M.kind) {
+ case "init":
+ return new AST_ObjectKeyVal(args);
+ case "set":
+ args.value.name = from_moz(key);
+ return new AST_ObjectSetter(args);
+ case "get":
+ args.value.name = from_moz(key);
+ return new AST_ObjectGetter(args);
+ }
},
- ObjectExpression : function(M) {
+ ObjectExpression: function(M) {
return new AST_Object({
start : my_start_token(M),
end : my_end_token(M),
properties : M.properties.map(function(prop){
- var key = prop.key;
- var name = key.type == "Identifier" ? key.name : key.value;
- var args = {
- start : my_start_token(key),
- end : my_end_token(prop.value),
- key : name,
- value : from_moz(prop.value)
- };
- switch (prop.kind) {
- case "init":
- return new AST_ObjectKeyVal(args);
- case "set":
- args.value.name = from_moz(key);
- return new AST_ObjectSetter(args);
- case "get":
- args.value.name = from_moz(key);
- return new AST_ObjectGetter(args);
- }
+ prop.type = "Property";
+ return from_moz(prop)
})
});
},
- SequenceExpression : function(M) {
+ SequenceExpression: function(M) {
return AST_Seq.from_array(M.expressions.map(from_moz));
},
- MemberExpression : function(M) {
+ MemberExpression: function(M) {
return new (M.computed ? AST_Sub : AST_Dot)({
start : my_start_token(M),
end : my_end_token(M),
property : M.computed ? from_moz(M.property) : M.property.name,
expression : from_moz(M.object)
});
},
- SwitchCase : function(M) {
+ SwitchCase: function(M) {
return new (M.test ? AST_Case : AST_Default)({
start : my_start_token(M),
end : my_end_token(M),
expression : from_moz(M.test),
body : M.consequent.map(from_moz)
});
},
- Literal : function(M) {
+ VariableDeclaration: function(M) {
+ return new (M.kind === "const" ? AST_Const : AST_Var)({
+ start : my_start_token(M),
+ end : my_end_token(M),
+ definitions : M.declarations.map(from_moz)
+ });
+ },
+ Literal: function(M) {
var val = M.value, args = {
start : my_start_token(M),
end : my_end_token(M)
};
if (val === null) return new AST_Null(args);
@@ -22462,16 +23216,13 @@
default:
args.value = val;
return new AST_RegExp(args);
}
},
- UnaryExpression: From_Moz_Unary,
- UpdateExpression: From_Moz_Unary,
Identifier: function(M) {
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
- return new (M.name == "this" ? AST_This
- : p.type == "LabeledStatement" ? AST_Label
+ return new ( p.type == "LabeledStatement" ? AST_Label
: p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
: p.type == "CatchClause" ? AST_SymbolCatch
: p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef
@@ -22481,29 +23232,25 @@
name : M.name
});
}
};
- function From_Moz_Unary(M) {
+ MOZ_TO_ME.UpdateExpression =
+ MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {
var prefix = "prefix" in M ? M.prefix
: M.type == "UnaryExpression" ? true : false;
return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
start : my_start_token(M),
end : my_end_token(M),
operator : M.operator,
expression : from_moz(M.argument)
});
};
- var ME_TO_MOZ = {};
-
- map("Node", AST_Node);
map("Program", AST_Toplevel, "body@body");
- map("Function", AST_Function, "id>name, params@argnames, body%body");
map("EmptyStatement", AST_EmptyStatement);
map("BlockStatement", AST_BlockStatement, "body@body");
- map("ExpressionStatement", AST_SimpleStatement, "expression>body");
map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
map("LabeledStatement", AST_LabeledStatement, "label>label, body>body");
map("BreakStatement", AST_Break, "label>label");
map("ContinueStatement", AST_Continue, "label>label");
map("WithStatement", AST_With, "object>expression, body>body");
@@ -22514,75 +23261,261 @@
map("DoWhileStatement", AST_Do, "test>condition, body>body");
map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
map("DebuggerStatement", AST_Debugger);
map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body");
- map("VariableDeclaration", AST_Var, "declarations@definitions");
map("VariableDeclarator", AST_VarDef, "id>name, init>value");
+ map("CatchClause", AST_Catch, "param>argname, body%body");
map("ThisExpression", AST_This);
map("ArrayExpression", AST_Array, "elements@elements");
map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body");
map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
- map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
+ map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
map("NewExpression", AST_New, "callee>expression, arguments@args");
map("CallExpression", AST_Call, "callee>expression, arguments@args");
+ def_to_moz(AST_Directive, function To_Moz_Directive(M) {
+ return {
+ type: "ExpressionStatement",
+ expression: {
+ type: "Literal",
+ value: M.value
+ }
+ };
+ });
+
+ def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) {
+ return {
+ type: "ExpressionStatement",
+ expression: to_moz(M.body)
+ };
+ });
+
+ def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) {
+ return {
+ type: "SwitchCase",
+ test: to_moz(M.expression),
+ consequent: M.body.map(to_moz)
+ };
+ });
+
+ def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
+ return {
+ type: "TryStatement",
+ block: to_moz_block(M),
+ handler: to_moz(M.bcatch),
+ guardedHandlers: [],
+ finalizer: to_moz(M.bfinally)
+ };
+ });
+
+ def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {
+ return {
+ type: "CatchClause",
+ param: to_moz(M.argname),
+ guard: null,
+ body: to_moz_block(M)
+ };
+ });
+
+ def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
+ return {
+ type: "VariableDeclaration",
+ kind: M instanceof AST_Const ? "const" : "var",
+ declarations: M.definitions.map(to_moz)
+ };
+ });
+
+ def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) {
+ return {
+ type: "SequenceExpression",
+ expressions: M.to_array().map(to_moz)
+ };
+ });
+
+ def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {
+ var isComputed = M instanceof AST_Sub;
+ return {
+ type: "MemberExpression",
+ object: to_moz(M.expression),
+ computed: isComputed,
+ property: isComputed ? to_moz(M.property) : {type: "Identifier", name: M.property}
+ };
+ });
+
+ def_to_moz(AST_Unary, function To_Moz_Unary(M) {
+ return {
+ type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression",
+ operator: M.operator,
+ prefix: M instanceof AST_UnaryPrefix,
+ argument: to_moz(M.expression)
+ };
+ });
+
+ def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
+ return {
+ type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression",
+ left: to_moz(M.left),
+ operator: M.operator,
+ right: to_moz(M.right)
+ };
+ });
+
+ def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) {
+ return {
+ type: "ObjectExpression",
+ properties: M.properties.map(to_moz)
+ };
+ });
+
+ def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
+ var key = (
+ is_identifier(M.key)
+ ? {type: "Identifier", name: M.key}
+ : {type: "Literal", value: M.key}
+ );
+ var kind;
+ if (M instanceof AST_ObjectKeyVal) {
+ kind = "init";
+ } else
+ if (M instanceof AST_ObjectGetter) {
+ kind = "get";
+ } else
+ if (M instanceof AST_ObjectSetter) {
+ kind = "set";
+ }
+ return {
+ type: "Property",
+ kind: kind,
+ key: key,
+ value: to_moz(M.value)
+ };
+ });
+
+ def_to_moz(AST_Symbol, function To_Moz_Identifier(M) {
+ var def = M.definition();
+ return {
+ type: "Identifier",
+ name: def ? def.mangled_name || def.name : M.name
+ };
+ });
+
+ def_to_moz(AST_Constant, function To_Moz_Literal(M) {
+ var value = M.value;
+ if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) {
+ return {
+ type: "UnaryExpression",
+ operator: "-",
+ prefix: true,
+ argument: {
+ type: "Literal",
+ value: -value
+ }
+ };
+ }
+ return {
+ type: "Literal",
+ value: value
+ };
+ });
+
+ def_to_moz(AST_Atom, function To_Moz_Atom(M) {
+ return {
+ type: "Identifier",
+ name: String(M.value)
+ };
+ });
+
+ AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
+ AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
+ AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null });
+
+ AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast);
+ AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast);
+
/* -----[ tools ]----- */
function my_start_token(moznode) {
+ var loc = moznode.loc;
+ var range = moznode.range;
return new AST_Token({
- file : moznode.loc && moznode.loc.source,
- line : moznode.loc && moznode.loc.start.line,
- col : moznode.loc && moznode.loc.start.column,
- pos : moznode.start,
- endpos : moznode.start
+ file : loc && loc.source,
+ line : loc && loc.start.line,
+ col : loc && loc.start.column,
+ pos : range ? range[0] : moznode.start,
+ endpos : range ? range[0] : moznode.start
});
};
function my_end_token(moznode) {
+ var loc = moznode.loc;
+ var range = moznode.range;
return new AST_Token({
- file : moznode.loc && moznode.loc.source,
- line : moznode.loc && moznode.loc.end.line,
- col : moznode.loc && moznode.loc.end.column,
- pos : moznode.end,
- endpos : moznode.end
+ file : loc && loc.source,
+ line : loc && loc.end.line,
+ col : loc && loc.end.column,
+ pos : range ? range[1] : moznode.end,
+ endpos : range ? range[1] : moznode.end
});
};
function map(moztype, mytype, propmap) {
var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
- moz_to_me += "return new mytype({\n" +
+ moz_to_me += "return new " + mytype.name + "({\n" +
"start: my_start_token(M),\n" +
"end: my_end_token(M)";
+ var me_to_moz = "function To_Moz_" + moztype + "(M){\n";
+ me_to_moz += "return {\n" +
+ "type: " + JSON.stringify(moztype);
+
if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){
var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
if (!m) throw new Error("Can't understand property map: " + prop);
- var moz = "M." + m[1], how = m[2], my = m[3];
+ var moz = m[1], how = m[2], my = m[3];
moz_to_me += ",\n" + my + ": ";
- if (how == "@") {
- moz_to_me += moz + ".map(from_moz)";
- } else if (how == ">") {
- moz_to_me += "from_moz(" + moz + ")";
- } else if (how == "=") {
- moz_to_me += moz;
- } else if (how == "%") {
- moz_to_me += "from_moz(" + moz + ").body";
- } else throw new Error("Can't understand operator in propmap: " + prop);
+ me_to_moz += ",\n" + moz + ": ";
+ switch (how) {
+ case "@":
+ moz_to_me += "M." + moz + ".map(from_moz)";
+ me_to_moz += "M." + my + ".map(to_moz)";
+ break;
+ case ">":
+ moz_to_me += "from_moz(M." + moz + ")";
+ me_to_moz += "to_moz(M." + my + ")";
+ break;
+ case "=":
+ moz_to_me += "M." + moz;
+ me_to_moz += "M." + my;
+ break;
+ case "%":
+ moz_to_me += "from_moz(M." + moz + ").body";
+ me_to_moz += "to_moz_block(M)";
+ break;
+ default:
+ throw new Error("Can't understand operator in propmap: " + prop);
+ }
});
- moz_to_me += "\n})}";
- // moz_to_me = parse(moz_to_me).print_to_string({ beautify: true });
- // console.log(moz_to_me);
+ moz_to_me += "\n})\n}";
+ me_to_moz += "\n}\n}";
- moz_to_me = new Function("mytype", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
- mytype, my_start_token, my_end_token, from_moz
+ //moz_to_me = parse(moz_to_me).print_to_string({ beautify: true });
+ //me_to_moz = parse(me_to_moz).print_to_string({ beautify: true });
+ //console.log(moz_to_me);
+
+ moz_to_me = new Function("my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
+ my_start_token, my_end_token, from_moz
);
- return MOZ_TO_ME[moztype] = moz_to_me;
+ me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
+ to_moz, to_moz_block
+ );
+ MOZ_TO_ME[moztype] = moz_to_me;
+ def_to_moz(mytype, me_to_moz);
};
var FROM_MOZ_STACK = null;
function from_moz(node) {
@@ -22598,10 +23531,52 @@
var ast = from_moz(node);
FROM_MOZ_STACK = save_stack;
return ast;
};
+ function moz_sub_loc(token) {
+ return token.line ? {
+ line: token.line,
+ column: token.col
+ } : null;
+ };
+
+ function set_moz_loc(mynode, moznode) {
+ var start = mynode.start;
+ var end = mynode.end;
+ if (start.pos != null && end.pos != null) {
+ moznode.range = [start.pos, end.pos];
+ }
+ if (start.line) {
+ moznode.loc = {
+ start: moz_sub_loc(start),
+ end: moz_sub_loc(end)
+ };
+ if (start.file) {
+ moznode.loc.source = start.file;
+ }
+ }
+ return moznode;
+ };
+
+ function def_to_moz(mytype, handler) {
+ mytype.DEFMETHOD("to_mozilla_ast", function() {
+ return set_moz_loc(this, handler(this));
+ });
+ };
+
+ function to_moz(node) {
+ return node != null ? node.to_mozilla_ast() : null;
+ };
+
+ function to_moz_block(node) {
+ return {
+ type: "BlockStatement",
+ body: node.body.map(to_moz)
+ };
+ };
+
})();
AST_Node.warn_function = function(txt) { logger.error("uglifyjs2 WARN: " + txt); };
exports.minify = function(files, options, name) {
options = defaults(options, {
@@ -22667,21 +23642,26 @@
root: options.sourceRoot
});
if (options.sourceMapIncludeSources) {
for (var file in sourcesContent) {
if (sourcesContent.hasOwnProperty(file)) {
- options.source_map.get().setSourceContent(file, sourcesContent[file]);
+ output.source_map.get().setSourceContent(file, sourcesContent[file]);
}
}
}
}
if (options.output) {
merge(output, options.output);
}
var stream = OutputStream(output);
toplevel.print(stream);
+
+ if(options.outSourceMap){
+ stream += "\n//# sourceMappingURL=" + options.outSourceMap;
+ }
+
return {
code : stream + "",
map : output.source_map + ""
};
};
@@ -22840,10 +23820,17 @@
});
return deps.length ? deps : undefined;
}
+ // Detects regular or arrow function expressions as the desired expression
+ // type.
+ function isFnExpression(node) {
+ return (node && (node.type === 'FunctionExpression' ||
+ node.type === 'ArrowFunctionExpression'));
+ }
+
/**
* Main parse function. Returns a string of any valid require or
* define/require.def calls as part of one JavaScript source string.
* @param {String} moduleName the module name that represents this file.
* It is used to create a default define if there is not one already for the
@@ -22933,10 +23920,11 @@
return result || null;
}
parse.traverse = traverse;
parse.traverseBroad = traverseBroad;
+ parse.isFnExpression = isFnExpression;
/**
* Handles parsing a file recursively for require calls.
* @param {Array} parentNode the AST node to start with.
* @param {Function} onMatch function to call on a parse match.
@@ -22978,23 +23966,29 @@
}
//Build up a "scope" object that informs nested recurse calls if
//the define call references an identifier that is likely a UMD
//wrapped function expression argument.
+ //Catch (function(a) {... wrappers
if (object.type === 'ExpressionStatement' && object.expression &&
object.expression.type === 'CallExpression' && object.expression.callee &&
- object.expression.callee.type === 'FunctionExpression') {
+ isFnExpression(object.expression.callee)) {
tempObject = object.expression.callee;
-
- if (tempObject.params && tempObject.params.length) {
- params = tempObject.params;
- fnExpScope = mixin({}, fnExpScope, true);
- for (i = 0; i < params.length; i++) {
- param = params[i];
- if (param.type === 'Identifier') {
- fnExpScope[param.name] = true;
- }
+ }
+ // Catch !function(a) {... wrappers
+ if (object.type === 'UnaryExpression' && object.argument &&
+ object.argument.type === 'CallExpression' && object.argument.callee &&
+ isFnExpression(object.argument.callee)) {
+ tempObject = object.argument.callee;
+ }
+ if (tempObject && tempObject.params && tempObject.params.length) {
+ params = tempObject.params;
+ fnExpScope = mixin({}, fnExpScope, true);
+ for (i = 0; i < params.length; i++) {
+ param = params[i];
+ if (param.type === 'Identifier') {
+ fnExpScope[param.name] = true;
}
}
}
for (key in object) {
@@ -23110,19 +24104,18 @@
if (parse.isDefineNodeWithArgs(node)) {
//Just the factory function passed to define
arg0 = node[argPropName][0];
- if (arg0 && arg0.type === 'FunctionExpression') {
+ if (isFnExpression(arg0)) {
match = arg0;
return false;
}
//A string literal module ID followed by the factory function.
arg1 = node[argPropName][1];
- if (arg0.type === 'Literal' &&
- arg1 && arg1.type === 'FunctionExpression') {
+ if (arg0.type === 'Literal' && isFnExpression(arg1)) {
match = arg1;
return false;
}
}
});
@@ -23507,11 +24500,11 @@
callName = parse.hasRequire(node);
if (callName === 'require' || callName === 'requirejs') {
//A plain require/requirejs call
arg = node[argPropName] && node[argPropName][0];
- if (arg.type !== 'ArrayExpression') {
+ if (arg && arg.type !== 'ArrayExpression') {
if (arg.type === 'ObjectExpression') {
//A config call, try the second arg.
arg = node[argPropName][1];
}
}
@@ -23530,21 +24523,21 @@
if (name.type === 'ArrayExpression') {
//No name, adjust args
factory = deps;
deps = name;
name = null;
- } else if (name.type === 'FunctionExpression') {
+ } else if (isFnExpression(name)) {
//Just the factory, no name or deps
factory = name;
name = deps = null;
} else if (name.type !== 'Literal') {
//An object literal, just null out
name = deps = factory = null;
}
if (name && name.type === 'Literal' && deps) {
- if (deps.type === 'FunctionExpression') {
+ if (isFnExpression(deps)) {
//deps is the factory
factory = deps;
deps = null;
} else if (deps.type === 'ObjectExpression') {
//deps is object literal, null out
@@ -23555,11 +24548,11 @@
}
}
if (deps && deps.type === 'ArrayExpression') {
deps = getValidDeps(deps);
- } else if (factory && factory.type === 'FunctionExpression') {
+ } else if (isFnExpression(factory)) {
//If no deps and a factory function, could be a commonjs sugar
//wrapper, scan the function for dependencies.
cjsDeps = parse.getAnonDepsFromNode(factory);
if (cjsDeps.length) {
deps = cjsDeps;
@@ -23576,11 +24569,11 @@
return onMatch("define", null, name, deps, node,
(factory && factory.type === 'Identifier' ? factory.name : undefined),
fnExpScope);
} else if (node.type === 'CallExpression' && node.callee &&
- node.callee.type === 'FunctionExpression' &&
+ isFnExpression(node.callee) &&
node.callee.body && node.callee.body.body &&
node.callee.body.body.length === 1 &&
node.callee.body.body[0].type === 'IfStatement') {
bodyNode = node.callee.body.body[0];
//Look for a define(Identifier) case, but only if inside an
@@ -23828,11 +24821,11 @@
//The define(factory) case, but
//only allow it if one Identifier arg,
//to limit impact of false positives.
needsId = true;
depAction = 'empty';
- } else if (firstArg.type === 'FunctionExpression') {
+ } else if (parse.isFnExpression(firstArg)) {
//define(function(){})
factoryNode = firstArg;
needsId = true;
depAction = 'scan';
} else if (firstArg.type === 'ObjectExpression') {
@@ -23868,11 +24861,11 @@
typeof firstArg.value === 'string') {
//define('string', ....)
//Already has an ID.
needsId = false;
if (args.length === 2 &&
- args[1].type === 'FunctionExpression') {
+ parse.isFnExpression(args[1])) {
//Needs dependency scanning.
factoryNode = args[1];
depAction = 'scan';
} else {
depAction = 'skip';
@@ -24196,11 +25189,11 @@
return temp; // Object
}
var pragma = {
conditionalRegExp: /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/,
- useStrictRegExp: /['"]use strict['"];/g,
+ useStrictRegExp: /(^|[^{]\r?\n)['"]use strict['"];/g,
hasRegExp: /has\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
configRegExp: /(^|[^\.])(requirejs|require)(\.config)\s*\(/g,
nsWrapRegExp: /\/\*requirejs namespace: true \*\//,
apiDefRegExp: /var requirejs,\s*require,\s*define;/,
defineCheckRegExp: /typeof\s+define\s*===?\s*["']function["']\s*&&\s*define\s*\.\s*amd/g,
@@ -24210,11 +25203,11 @@
defineHasRegExp: /typeof\s+define\s*==(=)?\s*['"]function['"]\s*&&\s*typeof\s+define\.amd\s*==(=)?\s*['"]object['"]\s*&&\s*define\.amd/g,
defineTernaryRegExp: /typeof\s+define\s*===?\s*['"]function["']\s*&&\s*define\s*\.\s*amd\s*\?\s*define/,
amdefineRegExp: /if\s*\(\s*typeof define\s*\!==\s*'function'\s*\)\s*\{\s*[^\{\}]+amdefine[^\{\}]+\}/g,
removeStrict: function (contents, config) {
- return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, '');
+ return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, '$1');
},
namespace: function (fileContents, ns, onLifecycleName) {
if (ns) {
//Namespace require/define calls
@@ -25175,11 +26168,15 @@
) {
var allowRun = true,
hasProp = lang.hasProp,
falseProp = lang.falseProp,
- getOwn = lang.getOwn;
+ getOwn = lang.getOwn,
+ // Used to strip out use strict from toString()'d functions for the
+ // shim config since they will explicitly want to not be bound by strict,
+ // but some envs, explicitly xpcshell, adds a use strict.
+ useStrictRegExp = /['"]use strict['"];/g;
//Turn off throwing on resolution conflict, that was just an older prim
//idea about finding errors early, but does not comply with how promises
//should operate.
prim.hideResolutionConflict = true;
@@ -25287,11 +26284,12 @@
if (value.exports && value.exports.indexOf('.') === -1) {
str += 'root.' + value.exports + ' = ';
}
if (value.init) {
- str += '(' + value.init.toString() + '.apply(this, arguments))';
+ str += '(' + value.init.toString()
+ .replace(useStrictRegExp, '') + '.apply(this, arguments))';
}
if (value.init && value.exports) {
str += ' || ';
}
if (value.exports) {
@@ -25304,11 +26302,12 @@
fn = function () {
return '(function (global) {\n' +
' return function () {\n' +
' var ret, fn;\n' +
(value.init ?
- (' fn = ' + value.init.toString() + ';\n' +
+ (' fn = ' + value.init.toString()
+ .replace(useStrictRegExp, '') + ';\n' +
' ret = fn.apply(global, arguments);\n') : '') +
(value.exports ?
' return ret || global.' + value.exports + ';\n' :
' return ret;\n') +
' };\n' +
@@ -26031,11 +27030,11 @@
//Set up build path for each path prefix, but only do so
//if the path falls out of the current baseUrl
if (paths[prop].indexOf(config.baseUrl) === 0) {
buildPaths[prop] = paths[prop].replace(config.baseUrl, config.dirBaseUrl);
} else {
- buildPaths[prop] = paths[prop] === 'empty:' ? 'empty:' : prop.replace(/\./g, "/");
+ buildPaths[prop] = paths[prop] === 'empty:' ? 'empty:' : prop;
//Make sure source path is fully formed with baseUrl,
//if it is a relative URL.
srcPath = paths[prop];
if (srcPath.indexOf('/') !== 0 && srcPath.indexOf(':') === -1) {
@@ -26834,10 +27833,18 @@
absFilePath = config.baseUrl = file.absPath(file.parent(buildFile));
//Load build file options.
buildFileContents = file.readFile(buildFile);
try {
+ //Be a bit lenient in the file ending in a ; or ending with
+ //a //# sourceMappingUrl comment, mostly for compiled languages
+ //that create a config, like typescript.
+ buildFileContents = buildFileContents
+ .replace(/\/\/\#[^\n\r]+[\n\r]*$/, '')
+ .trim()
+ .replace(/;$/, '');
+
buildFileConfig = eval("(" + buildFileContents + ")");
build.makeAbsConfig(buildFileConfig, absFilePath);
//Mix in the config now so that items in mainConfigFile can
//be resolved relative to them if necessary, like if appDir
@@ -27455,16 +28462,17 @@
sourceMapBase,
buildFileContents = '';
return prim().start(function () {
var reqIndex, currContents, fileForSourceMap,
- moduleName, shim, packageMain, packageName,
+ moduleName, shim, packageName,
parts, builder, writeApi,
namespace, namespaceWithDot, stubModulesByName,
context = layer.context,
onLayerEnds = [],
- onLayerEndAdded = {};
+ onLayerEndAdded = {},
+ pkgsMainMap = {};
//Use override settings, particularly for pragmas
//Do this before the var readings since it reads config values.
if (module.override) {
config = build.createOverrideConfig(config, module.override);
@@ -27502,28 +28510,29 @@
sourceMapGenerator = new SourceMapGenerator.SourceMapGenerator({
file: fileForSourceMap
});
}
+ //Create a reverse lookup for packages main module IDs to their package
+ //names, useful for knowing when to write out define() package main ID
+ //adapters.
+ lang.eachProp(layer.context.config.pkgs, function(value, prop) {
+ pkgsMainMap[value] = prop;
+ });
+
//Write the built module to disk, and build up the build output.
- fileContents = "";
+ fileContents = config.wrap ? config.wrap.start : "";
return prim.serial(layer.buildFilePaths.map(function (path) {
return function () {
var lineCount,
singleContents = '';
moduleName = layer.buildFileToModule[path];
- packageName = moduleName.split('/').shift();
- //If the moduleName is for a package main, then update it to the
- //real main value.
- packageMain = layer.context.config.pkgs &&
- getOwn(layer.context.config.pkgs, packageName);
- if (packageMain !== moduleName) {
- // Not a match, clear packageMain
- packageMain = undefined;
- }
+ //If the moduleName is a package main, then hold on to the
+ //packageName in case an adapter needs to be written.
+ packageName = getOwn(pkgsMainMap, moduleName);
return prim().start(function () {
//Figure out if the module is a result of a build plugin, and if so,
//then delegate to that plugin.
parts = context.makeModuleMap(moduleName);
@@ -27581,11 +28590,11 @@
if (config.onBuildRead) {
currContents = config.onBuildRead(moduleName, path, currContents);
}
- if (packageMain) {
+ if (packageName) {
hasPackageName = (packageName === parse.getNamedDefine(currContents));
}
if (namespace) {
currContents = pragma.namespace(currContents, namespace);
@@ -27593,11 +28602,11 @@
currContents = build.toTransport(namespace, moduleName, path, currContents, layer, {
useSourceUrl: config.useSourceUrl
});
- if (packageMain && !hasPackageName) {
+ if (packageName && !hasPackageName) {
currContents = addSemiColon(currContents, config) + '\n';
currContents += namespaceWithDot + "define('" +
packageName + "', ['" + moduleName +
"'], function (main) { return main; });\n";
}
@@ -27622,11 +28631,11 @@
//Some files may not have declared a require module, and if so,
//put in a placeholder call so the require does not try to load them
//after the module is processed.
//If we have a name, but no defined module, then add in the placeholder.
if (moduleName && falseProp(layer.modulesWithNames, moduleName) && !config.skipModuleInsertion) {
- shim = config.shim && (getOwn(config.shim, moduleName) || (packageMain && getOwn(config.shim, moduleName) || getOwn(config.shim, packageName)));
+ shim = config.shim && (getOwn(config.shim, moduleName) || (packageName && getOwn(config.shim, packageName)));
if (shim) {
if (config.wrapShim) {
singleContents = '(function(root) {\n' +
namespaceWithDot + 'define("' + moduleName + '", ' +
(shim.deps && shim.deps.length ?
@@ -27742,11 +28751,11 @@
}
});
}).then(function () {
return {
text: config.wrap ?
- config.wrap.start + fileContents + config.wrap.end :
+ fileContents + config.wrap.end :
fileContents,
buildText: buildFileContents,
sourceMap: sourceMapGenerator ?
JSON.stringify(sourceMapGenerator.toJSON(), null, ' ') :
undefined
@@ -27949,10 +28958,10 @@
} else if (commandOption === 'v') {
console.log('r.js: ' + version +
', RequireJS: ' + this.requirejsVars.require.version +
- ', UglifyJS2: 2.4.13, UglifyJS: 1.3.4');
+ ', UglifyJS2: 2.4.16, UglifyJS: 1.3.4');
} else if (commandOption === 'convert') {
loadLib();
this.requirejsVars.require(['env!env/args', 'commonJs', 'env!env/print'],
function (args, commonJs, print) {