bin/r.js in requirejs-rails-0.9.8 vs bin/r.js in requirejs-rails-0.9.9

- old
+ new

@@ -1,7 +1,7 @@ /** - * @license r.js 2.1.17 Copyright (c) 2010-2015, The Dojo Foundation All Rights Reserved. + * @license r.js 2.1.19 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.17', + version = '2.1.19', jsSuffixRegExp = /\.js$/, commandOption = '', useLibLoaded = {}, //Used by jslib/rhino/args.js rhinoArgs = args, @@ -247,11 +247,11 @@ }; } } /** vim: et:ts=4:sw=4:sts=4 - * @license RequireJS 2.1.17 Copyright (c) 2010-2015, The Dojo Foundation All Rights Reserved. + * @license RequireJS 2.1.19 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. @@ -260,11 +260,11 @@ (function (global) { var req, s, head, baseElement, dataMain, src, interactiveScript, currentlyAddingScript, mainScript, subPath, - version = '2.1.17', + version = '2.1.19', commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, jsSuffixRegExp = /\.js$/, currDirRegExp = /^\.\//, op = Object.prototype, @@ -837,11 +837,11 @@ } else { return (mod.module = { id: mod.map.id, uri: mod.map.url, config: function () { - return getOwn(config.config, mod.map.id) || {}; + return getOwn(config.config, mod.map.id) || {}; }, exports: mod.exports || (mod.exports = {}) }); } } @@ -1365,10 +1365,13 @@ } this.depCount += 1; on(depMap, 'defined', bind(this, function (depExports) { + if (this.undefed) { + return; + } this.defineDep(i, depExports); this.check(); })); if (this.errback) { @@ -1481,11 +1484,12 @@ //Make sure any remaining defQueue items get properly processed. while (defQueue.length) { args = defQueue.shift(); if (args[0] === null) { - return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1])); + return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + + args[args.length - 1])); } else { //args are id, deps, factory. Should be normalized by the //define() function. callGetModule(args); } @@ -1568,11 +1572,11 @@ //Adjust packages if necessary. if (cfg.packages) { each(cfg.packages, function (pkgObj) { var location, name; - pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj; + pkgObj = typeof pkgObj === 'string' ? {name: pkgObj} : pkgObj; name = pkgObj.name; location = pkgObj.location; if (location) { config.paths[name] = pkgObj.location; @@ -1595,11 +1599,11 @@ eachProp(registry, function (mod, id) { //If module already has init called, since it is too //late to modify them, and ignore unnormalized ones //since they are transient. if (!mod.inited && !mod.map.unnormalized) { - mod.map = makeModuleMap(id); + mod.map = makeModuleMap(id, null, true); } }); //If a deps array or a config callback is specified, then call //require with those args. This is useful when require is defined as a @@ -1731,21 +1735,22 @@ takeGlobalQueue(); var map = makeModuleMap(id, relMap, true), mod = getOwn(registry, id); + mod.undefed = true; removeScript(id); delete defined[id]; delete urlFetched[map.url]; delete undefEvents[id]; //Clean queued defines too. Go backwards //in array so that the splices do not //mess up the iteration. eachReverse(defQueue, function(args, i) { - if(args[0] === id) { + if (args[0] === id) { defQueue.splice(i, 1); } }); if (mod) { @@ -2100,10 +2105,13 @@ var config = (context && context.config) || {}, node; if (isBrowser) { //In the browser so use a script tag node = req.createNode(config, moduleName, url); + if (config.onNodeCreated) { + config.onNodeCreated(node, config, moduleName, url); + } node.setAttribute('data-requirecontext', context.contextName); node.setAttribute('data-requiremodule', moduleName); //Set up load listener. Test attachEvent first because IE9 has @@ -2228,11 +2236,11 @@ //Strip off any trailing .js since mainScript is now //like a module name. mainScript = mainScript.replace(jsSuffixRegExp, ''); - //If mainScript is still a path, fall back to dataMain + //If mainScript is still a path, fall back to dataMain if (req.jsExtRegExp.test(mainScript)) { mainScript = dataMain; } //Put the data-main script in the files to load. @@ -2314,11 +2322,10 @@ define.amd = { jQuery: true }; - /** * Executes the text. Normally just uses eval, but can be modified * to use a better, environment-specific call. Only used for transpiling * loader plugins, not for plain JS modules. * @param {String} text the text to execute/evaluate. @@ -2927,11 +2934,12 @@ } function check(p) { if (hasProp(p, 'e') || hasProp(p, 'v')) { if (!prim.hideResolutionConflict) { - throw new Error('nope'); + throw new Error('Prim promise already resolved: ' + + JSON.stringify(p)); } return false; } return true; } @@ -4553,20 +4561,11 @@ //Just a blank file to use when building the optimizer with the optimizer, //so that the build does not attempt to inline some env modules, //like Node's fs and path. /* - Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com> - Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com> - Copyright (C) 2013 Mathias Bynens <mathias@qiwi.be> - Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com> - Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be> - Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl> - Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com> - Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com> - Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com> - Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com> + Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright @@ -4611,10 +4610,11 @@ PlaceHolders, Messages, Regex, source, strict, + sourceType, index, lineNumber, lineStart, hasLineTerminator, lastIndex, @@ -4625,22 +4625,26 @@ startLineStart, scanning, length, lookahead, state, - extra; + extra, + isBindingElement, + isAssignmentTarget, + firstCoverInitializedNameError; Token = { BooleanLiteral: 1, EOF: 2, Identifier: 3, Keyword: 4, NullLiteral: 5, NumericLiteral: 6, Punctuator: 7, StringLiteral: 8, - RegularExpression: 9 + RegularExpression: 9, + Template: 10 }; TokenName = {}; TokenName[Token.BooleanLiteral] = 'Boolean'; TokenName[Token.EOF] = '<end>'; @@ -4649,10 +4653,11 @@ TokenName[Token.NullLiteral] = 'Null'; TokenName[Token.NumericLiteral] = 'Numeric'; TokenName[Token.Punctuator] = 'Punctuator'; TokenName[Token.StringLiteral] = 'String'; TokenName[Token.RegularExpression] = 'RegularExpression'; + TokenName[Token.Template] = 'Template'; // A function following one of those tokens is an expression. FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new', 'return', 'case', 'delete', 'throw', 'void', // assignment operators @@ -4663,11 +4668,13 @@ '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=', '<=', '<', '>', '!=', '!==']; Syntax = { AssignmentExpression: 'AssignmentExpression', + AssignmentPattern: 'AssignmentPattern', ArrayExpression: 'ArrayExpression', + ArrayPattern: 'ArrayPattern', ArrowFunctionExpression: 'ArrowFunctionExpression', BlockStatement: 'BlockStatement', BinaryExpression: 'BinaryExpression', BreakStatement: 'BreakStatement', CallExpression: 'CallExpression', @@ -4678,40 +4685,56 @@ ConditionalExpression: 'ConditionalExpression', ContinueStatement: 'ContinueStatement', DoWhileStatement: 'DoWhileStatement', DebuggerStatement: 'DebuggerStatement', EmptyStatement: 'EmptyStatement', + ExportAllDeclaration: 'ExportAllDeclaration', + ExportDefaultDeclaration: 'ExportDefaultDeclaration', + ExportNamedDeclaration: 'ExportNamedDeclaration', + ExportSpecifier: 'ExportSpecifier', ExpressionStatement: 'ExpressionStatement', ForStatement: 'ForStatement', + ForOfStatement: 'ForOfStatement', ForInStatement: 'ForInStatement', FunctionDeclaration: 'FunctionDeclaration', FunctionExpression: 'FunctionExpression', Identifier: 'Identifier', IfStatement: 'IfStatement', + ImportDeclaration: 'ImportDeclaration', + ImportDefaultSpecifier: 'ImportDefaultSpecifier', + ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', + ImportSpecifier: 'ImportSpecifier', Literal: 'Literal', LabeledStatement: 'LabeledStatement', LogicalExpression: 'LogicalExpression', MemberExpression: 'MemberExpression', MethodDefinition: 'MethodDefinition', NewExpression: 'NewExpression', ObjectExpression: 'ObjectExpression', + ObjectPattern: 'ObjectPattern', Program: 'Program', Property: 'Property', RestElement: 'RestElement', ReturnStatement: 'ReturnStatement', SequenceExpression: 'SequenceExpression', - SwitchStatement: 'SwitchStatement', + SpreadElement: 'SpreadElement', + Super: 'Super', SwitchCase: 'SwitchCase', + SwitchStatement: 'SwitchStatement', + TaggedTemplateExpression: 'TaggedTemplateExpression', + TemplateElement: 'TemplateElement', + TemplateLiteral: 'TemplateLiteral', ThisExpression: 'ThisExpression', ThrowStatement: 'ThrowStatement', TryStatement: 'TryStatement', UnaryExpression: 'UnaryExpression', UpdateExpression: 'UpdateExpression', VariableDeclaration: 'VariableDeclaration', VariableDeclarator: 'VariableDeclarator', WhileStatement: 'WhileStatement', - WithStatement: 'WithStatement' + WithStatement: 'WithStatement', + YieldExpression: 'YieldExpression' }; PlaceHolders = { ArrowParameterPlaceHolder: 'ArrowParameterPlaceHolder' }; @@ -4721,23 +4744,26 @@ UnexpectedToken: 'Unexpected token %0', UnexpectedNumber: 'Unexpected number', UnexpectedString: 'Unexpected string', UnexpectedIdentifier: 'Unexpected identifier', UnexpectedReserved: 'Unexpected reserved word', + UnexpectedTemplate: 'Unexpected quasi %0', UnexpectedEOS: 'Unexpected end of input', NewlineAfterThrow: 'Illegal newline after throw', InvalidRegExp: 'Invalid regular expression', UnterminatedRegExp: 'Invalid regular expression: missing /', InvalidLHSInAssignment: 'Invalid left-hand side in assignment', InvalidLHSInForIn: 'Invalid left-hand side in for-in', + InvalidLHSInForLoop: 'Invalid left-hand side in for-loop', MultipleDefaultsInSwitch: 'More than one default clause in switch statement', NoCatchOrFinally: 'Missing catch or finally after try', UnknownLabel: 'Undefined label \'%0\'', Redeclaration: '%0 \'%1\' has already been declared', IllegalContinue: 'Illegal continue statement', IllegalBreak: 'Illegal break statement', IllegalReturn: 'Illegal return statement', + IllegalYield: 'Unexpected token yield', 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', @@ -4746,17 +4772,24 @@ 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', + TemplateOctalLiteral: 'Octal literals are not allowed in template strings.', 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' + StaticPrototype: 'Classes may not have static property named prototype', + MissingFromClause: 'Unexpected token', + NoAsAfterImportNamespace: 'Unexpected token', + InvalidModuleSpecifier: 'Unexpected token', + IllegalImportDeclaration: 'Unexpected token', + IllegalExportDeclaration: 'Unexpected token', + DuplicateBinding: 'Duplicate binding %0' }; // See also tools/generate-unicode-regex.py. Regex = { NonAsciiIdentifierStart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\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]'), @@ -4785,11 +4818,33 @@ function isOctalDigit(ch) { return '01234567'.indexOf(ch) >= 0; } + function octalToDecimal(ch) { + // \0 is not octal escape sequence + var octal = (ch !== '0'), code = '01234567'.indexOf(ch); + if (index < length && isOctalDigit(source[index])) { + octal = true; + code = code * 8 + '01234567'.indexOf(source[index++]); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ('0123'.indexOf(ch) >= 0 && + index < length && + isOctalDigit(source[index])) { + code = code * 8 + '01234567'.indexOf(source[index++]); + } + } + + return { + code: code, + octal: octal + }; + } + // 7.2 White Space function isWhiteSpace(ch) { return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) || (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0); @@ -4858,13 +4913,10 @@ } // 7.6.1.1 Keywords function isKeyword(id) { - if (strict && isStrictModeReservedWord(id)) { - return true; - } // 'const' is specialized as Keyword in V8. // 'yield' and 'let' are for compatibility with SpiderMonkey and ES.next. // Some others are from future reserved words. @@ -5006,24 +5058,20 @@ } else { ++index; } } - 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(); + // 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(); } function skipComment() { var ch, start; hasLineTerminator = false; @@ -5255,10 +5303,11 @@ case '{': if (extra.tokenize) { extra.openCurlyToken = extra.tokens.length; } + state.curlyStack.push('{'); ++index; break; case '.': ++index; @@ -5267,14 +5316,17 @@ index += 2; str = '...'; } break; + case '}': + ++index; + state.curlyStack.pop(); + break; case ')': case ';': case ',': - case '}': case '[': case ']': case ':': case '?': case '~': @@ -5529,11 +5581,11 @@ } // 7.8.4 String Literals function scanStringLiteral() { - var str = '', quote, start, ch, code, unescaped, restore, octal = false; + var str = '', quote, start, ch, unescaped, octToDec, octal = false; quote = source[index]; assert((quote === '\'' || quote === '"'), 'String literal must starts with a quote'); @@ -5554,18 +5606,15 @@ case 'x': if (source[index] === '{') { ++index; str += scanUnicodeCodePointEscape(); } else { - restore = index; unescaped = scanHexEscape(ch); - if (unescaped) { - str += unescaped; - } else { - index = restore; - str += ch; + if (!unescaped) { + throw throwUnexpectedToken(); } + str += unescaped; } break; case 'n': str += '\n'; break; @@ -5582,33 +5631,20 @@ str += '\f'; break; case 'v': str += '\x0B'; break; + case '8': + case '9': + throw throwUnexpectedToken(); default: if (isOctalDigit(ch)) { - code = '01234567'.indexOf(ch); + octToDec = octalToDecimal(ch); - // \0 is not octal escape sequence - if (code !== 0) { - octal = true; - } - - if (index < length && isOctalDigit(source[index])) { - octal = true; - code = code * 8 + '01234567'.indexOf(source[index++]); - - // 3 digits are only allowed when string starts - // with 0, 1, 2, 3 - if ('0123'.indexOf(ch) >= 0 && - index < length && - isOctalDigit(source[index])) { - code = code * 8 + '01234567'.indexOf(source[index++]); - } - } - str += String.fromCharCode(code); + octal = octToDec.octal || octal; + str += String.fromCharCode(octToDec.code); } else { str += ch; } break; } @@ -5639,30 +5675,165 @@ start: start, end: index }; } + function scanTemplate() { + var cooked = '', ch, start, rawOffset, terminated, head, tail, restore, unescaped; + + terminated = false; + tail = false; + start = index; + head = (source[index] === '`'); + rawOffset = 2; + + ++index; + + while (index < length) { + ch = source[index++]; + if (ch === '`') { + rawOffset = 1; + tail = true; + terminated = true; + break; + } else if (ch === '$') { + if (source[index] === '{') { + state.curlyStack.push('${'); + ++index; + terminated = true; + break; + } + cooked += ch; + } else if (ch === '\\') { + ch = source[index++]; + if (!isLineTerminator(ch.charCodeAt(0))) { + switch (ch) { + case 'n': + cooked += '\n'; + break; + case 'r': + cooked += '\r'; + break; + case 't': + cooked += '\t'; + break; + case 'u': + case 'x': + if (source[index] === '{') { + ++index; + cooked += scanUnicodeCodePointEscape(); + } else { + restore = index; + unescaped = scanHexEscape(ch); + if (unescaped) { + cooked += unescaped; + } else { + index = restore; + cooked += ch; + } + } + break; + case 'b': + cooked += '\b'; + break; + case 'f': + cooked += '\f'; + break; + case 'v': + cooked += '\v'; + break; + + default: + if (ch === '0') { + if (isDecimalDigit(source.charCodeAt(index))) { + // Illegal: \01 \02 and so on + throwError(Messages.TemplateOctalLiteral); + } + cooked += '\0'; + } else if (isOctalDigit(ch)) { + // Illegal: \1 \2 + throwError(Messages.TemplateOctalLiteral); + } else { + cooked += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + lineStart = index; + } + } else if (isLineTerminator(ch.charCodeAt(0))) { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + lineStart = index; + cooked += '\n'; + } else { + cooked += ch; + } + } + + if (!terminated) { + throwUnexpectedToken(); + } + + if (!head) { + state.curlyStack.pop(); + } + + return { + type: Token.Template, + value: { + cooked: cooked, + raw: source.slice(start + 1, index - rawOffset) + }, + head: head, + tail: tail, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + function testRegExp(pattern, flags) { - var tmp = pattern; + // The BMP character to use as a replacement for astral symbols when + // translating an ES6 "u"-flagged pattern to an ES5-compatible + // approximation. + // Note: replacing with '\uFFFF' enables false positives in unlikely + // scenarios. For example, `[\u{1044f}-\u{10440}]` is an invalid + // pattern that would not be detected by this substitution. + var astralSubstitute = '\uFFFF', + 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'; + // Replace every Unicode escape sequence with the equivalent + // BMP character or a constant ASCII code point in the case of + // astral symbols. (See the above note on `astralSubstitute` + // for more information.) + .replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g, function ($0, $1, $2) { + var codePoint = parseInt($1 || $2, 16); + if (codePoint > 0x10FFFF) { + throwUnexpectedToken(null, Messages.InvalidRegExp); } - throwUnexpectedToken(null, Messages.InvalidRegExp); + if (codePoint <= 0xFFFF) { + return String.fromCharCode(codePoint); + } + return astralSubstitute; }) - .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x'); + // Replace each paired surrogate with a single ASCII symbol to + // avoid throwing on regular expressions that are only valid in + // combination with the "u" flag. + .replace( + /[\uD800-\uDBFF][\uDC00-\uDFFF]/g, + astralSubstitute + ); } // First, detect invalid regular expressions. try { RegExp(tmp); @@ -5924,11 +6095,11 @@ } return scanPunctuator(); } function advance() { - var ch; + var ch, token; if (index >= length) { return { type: Token.EOF, lineNumber: lineNumber, @@ -5939,11 +6110,15 @@ } ch = source.charCodeAt(index); if (isIdentifierStart(ch)) { - return scanIdentifier(); + token = scanIdentifier(); + if (strict && isStrictModeReservedWord(token.value)) { + token.type = Token.Keyword; + } + return token; } // Very common: ( and ) and ; if (ch === 0x28 || ch === 0x29 || ch === 0x3B) { return scanPunctuator(); @@ -5952,11 +6127,10 @@ // String literal starts with single quote (U+0027) or double quote (U+0022). if (ch === 0x27 || ch === 0x22) { return scanStringLiteral(); } - // Dot (.) U+002E can also start a floating-point number, hence the need // to check the next character. if (ch === 0x2E) { if (isDecimalDigit(source.charCodeAt(index + 1))) { return scanNumericLiteral(); @@ -5971,10 +6145,16 @@ // Slash (/) U+002F can also start a regex. if (extra.tokenize && ch === 0x2F) { return advanceSlash(); } + // Template literals start with ` (U+0060) for template head + // or } (U+007D) for template middle or template tail. + if (ch === 0x60 || (ch === 0x7D && state.curlyStack[state.curlyStack.length - 1] === '${')) { + return scanTemplate(); + } + return scanPunctuator(); } function collectToken() { var loc, token, value, entry; @@ -6119,21 +6299,29 @@ delete last.trailingComments; } } // Eating the stack. - if (last) { - while (last && last.range[0] >= this.range[0]) { - lastChild = last; - last = bottomRight.pop(); - } + while (last && last.range[0] >= this.range[0]) { + lastChild = bottomRight.pop(); + last = bottomRight[bottomRight.length - 1]; } if (lastChild) { - if (lastChild.leadingComments && lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= this.range[0]) { - this.leadingComments = lastChild.leadingComments; - lastChild.leadingComments = undefined; + if (lastChild.leadingComments) { + leadingComments = []; + for (i = lastChild.leadingComments.length - 1; i >= 0; --i) { + comment = lastChild.leadingComments[i]; + if (comment.range[1] <= this.range[0]) { + leadingComments.unshift(comment); + lastChild.leadingComments.splice(i, 1); + } + } + + if (!lastChild.leadingComments.length) { + lastChild.leadingComments = undefined; + } } } else if (extra.leadingComments.length > 0) { leadingComments = []; for (i = extra.leadingComments.length - 1; i >= 0; --i) { comment = extra.leadingComments[i]; @@ -6179,10 +6367,17 @@ this.elements = elements; this.finish(); return this; }, + finishArrayPattern: function (elements) { + this.type = Syntax.ArrayPattern; + this.elements = elements; + this.finish(); + return this; + }, + finishArrowFunctionExpression: function (params, defaults, body, expression) { this.type = Syntax.ArrowFunctionExpression; this.id = null; this.params = params; this.defaults = defaults; @@ -6200,10 +6395,18 @@ this.right = right; this.finish(); return this; }, + finishAssignmentPattern: function (left, right) { + this.type = Syntax.AssignmentPattern; + this.left = left; + this.right = right; + this.finish(); + return this; + }, + finishBinaryExpression: function (operator, left, right) { this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression; this.operator = operator; this.left = left; this.right = right; @@ -6317,39 +6520,48 @@ this.body = body; this.finish(); return this; }, + finishForOfStatement: function (left, right, body) { + this.type = Syntax.ForOfStatement; + this.left = left; + this.right = right; + this.body = body; + this.finish(); + return this; + }, + 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; }, - finishFunctionDeclaration: function (id, params, defaults, body) { + finishFunctionDeclaration: function (id, params, defaults, body, generator) { this.type = Syntax.FunctionDeclaration; this.id = id; this.params = params; this.defaults = defaults; this.body = body; - this.generator = false; + this.generator = generator; this.expression = false; this.finish(); return this; }, - finishFunctionExpression: function (id, params, defaults, body) { + finishFunctionExpression: function (id, params, defaults, body, generator) { this.type = Syntax.FunctionExpression; this.id = id; this.params = params; this.defaults = defaults; this.body = body; - this.generator = false; + this.generator = generator; this.expression = false; this.finish(); return this; }, @@ -6410,10 +6622,17 @@ this.properties = properties; this.finish(); return this; }, + finishObjectPattern: function (properties) { + this.type = Syntax.ObjectPattern; + this.properties = properties; + this.finish(); + return this; + }, + finishPostfixExpression: function (operator, argument) { this.type = Syntax.UpdateExpression; this.operator = operator; this.argument = argument; this.prefix = false; @@ -6422,10 +6641,14 @@ }, finishProgram: function (body) { this.type = Syntax.Program; this.body = body; + if (sourceType === 'module') { + // very restrictive for now + this.sourceType = sourceType; + } this.finish(); return this; }, finishProperty: function (kind, key, computed, value, method, shorthand) { @@ -6459,26 +6682,63 @@ this.expressions = expressions; this.finish(); return this; }, + finishSpreadElement: function (argument) { + this.type = Syntax.SpreadElement; + this.argument = argument; + this.finish(); + return this; + }, + finishSwitchCase: function (test, consequent) { this.type = Syntax.SwitchCase; this.test = test; this.consequent = consequent; this.finish(); return this; }, + finishSuper: function () { + this.type = Syntax.Super; + this.finish(); + return this; + }, + finishSwitchStatement: function (discriminant, cases) { this.type = Syntax.SwitchStatement; this.discriminant = discriminant; this.cases = cases; this.finish(); return this; }, + finishTaggedTemplateExpression: function (tag, quasi) { + this.type = Syntax.TaggedTemplateExpression; + this.tag = tag; + this.quasi = quasi; + this.finish(); + return this; + }, + + finishTemplateElement: function (value, tail) { + this.type = Syntax.TemplateElement; + this.value = value; + this.tail = tail; + this.finish(); + return this; + }, + + finishTemplateLiteral: function (quasis, expressions) { + this.type = Syntax.TemplateLiteral; + this.quasis = quasis; + this.expressions = expressions; + this.finish(); + return this; + }, + finishThisExpression: function () { this.type = Syntax.ThisExpression; this.finish(); return this; }, @@ -6546,10 +6806,79 @@ this.type = Syntax.WithStatement; this.object = object; this.body = body; this.finish(); return this; + }, + + finishExportSpecifier: function (local, exported) { + this.type = Syntax.ExportSpecifier; + this.exported = exported || local; + this.local = local; + this.finish(); + return this; + }, + + finishImportDefaultSpecifier: function (local) { + this.type = Syntax.ImportDefaultSpecifier; + this.local = local; + this.finish(); + return this; + }, + + finishImportNamespaceSpecifier: function (local) { + this.type = Syntax.ImportNamespaceSpecifier; + this.local = local; + this.finish(); + return this; + }, + + finishExportNamedDeclaration: function (declaration, specifiers, src) { + this.type = Syntax.ExportNamedDeclaration; + this.declaration = declaration; + this.specifiers = specifiers; + this.source = src; + this.finish(); + return this; + }, + + finishExportDefaultDeclaration: function (declaration) { + this.type = Syntax.ExportDefaultDeclaration; + this.declaration = declaration; + this.finish(); + return this; + }, + + finishExportAllDeclaration: function (src) { + this.type = Syntax.ExportAllDeclaration; + this.source = src; + this.finish(); + return this; + }, + + finishImportSpecifier: function (local, imported) { + this.type = Syntax.ImportSpecifier; + this.local = local || imported; + this.imported = imported; + this.finish(); + return this; + }, + + finishImportDeclaration: function (specifiers, src) { + this.type = Syntax.ImportDeclaration; + this.specifiers = specifiers; + this.source = src; + this.finish(); + return this; + }, + + finishYieldExpression: function (argument, delegate) { + this.type = Syntax.YieldExpression; + this.argument = argument; + this.delegate = delegate; + this.finish(); + return this; } }; function recordError(error) { @@ -6613,29 +6942,36 @@ } // Throw an exception because of the token. function unexpectedTokenError(token, message) { - var msg = message || Messages.UnexpectedToken; + var value, msg = message || Messages.UnexpectedToken; - 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) { + if (!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 : + (token.type === Token.Template) ? Messages.UnexpectedTemplate : + Messages.UnexpectedToken; - 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.Keyword) { + if (isFutureReservedWord(token.value)) { + msg = Messages.UnexpectedReserved; + } else if (strict && isStrictModeReservedWord(token.value)) { + msg = Messages.StrictReservedWord; + } } } + + value = (token.type === Token.Template) ? token.value.raw : token.value; + } else { + value = 'ILLEGAL'; } - msg = msg.replace('%0', token ? token.value : 'ILLEGAL'); + msg = msg.replace('%0', value); return (token && typeof token.lineNumber === 'number') ? createError(token.lineNumber, token.start, msg) : createError(scanning ? lineNumber : lastLineNumber, scanning ? index : lastIndex, msg); } @@ -6707,10 +7043,17 @@ function matchKeyword(keyword) { return lookahead.type === Token.Keyword && lookahead.value === keyword; } + // Return true if the next token matches the specified contextual keyword + // (where an identifier is sometimes a keyword depending on the context) + + function matchContextualKeyword(keyword) { + return lookahead.type === Token.Identifier && lookahead.value === keyword; + } + // Return true if the next token is an assignment operator function matchAssign() { var op; @@ -6751,29 +7094,195 @@ if (lookahead.type !== Token.EOF && !match('}')) { throwUnexpectedToken(lookahead); } } - // Return true if provided expression is LeftHandSideExpression + // Cover grammar support. + // + // When an assignment expression position starts with an left parenthesis, the determination of the type + // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead) + // or the first comma. This situation also defers the determination of all the expressions nested in the pair. + // + // There are three productions that can be parsed in a parentheses pair that needs to be determined + // after the outermost pair is closed. They are: + // + // 1. AssignmentExpression + // 2. BindingElements + // 3. AssignmentTargets + // + // In order to avoid exponential backtracking, we use two flags to denote if the production can be + // binding element or assignment target. + // + // The three productions have the relationship: + // + // BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression + // + // with a single exception that CoverInitializedName when used directly in an Expression, generates + // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the + // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair. + // + // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not + // effect the current flags. This means the production the parser parses is only used as an expression. Therefore + // the CoverInitializedName check is conducted. + // + // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates + // the flags outside of the parser. This means the production the parser parses is used as a part of a potential + // pattern. The CoverInitializedName check is deferred. + function isolateCoverGrammar(parser) { + var oldIsBindingElement = isBindingElement, + oldIsAssignmentTarget = isAssignmentTarget, + oldFirstCoverInitializedNameError = firstCoverInitializedNameError, + result; + isBindingElement = true; + isAssignmentTarget = true; + firstCoverInitializedNameError = null; + result = parser(); + if (firstCoverInitializedNameError !== null) { + throwUnexpectedToken(firstCoverInitializedNameError); + } + isBindingElement = oldIsBindingElement; + isAssignmentTarget = oldIsAssignmentTarget; + firstCoverInitializedNameError = oldFirstCoverInitializedNameError; + return result; + } - function isLeftHandSide(expr) { - return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression; + function inheritCoverGrammar(parser) { + var oldIsBindingElement = isBindingElement, + oldIsAssignmentTarget = isAssignmentTarget, + oldFirstCoverInitializedNameError = firstCoverInitializedNameError, + result; + isBindingElement = true; + isAssignmentTarget = true; + firstCoverInitializedNameError = null; + result = parser(); + isBindingElement = isBindingElement && oldIsBindingElement; + isAssignmentTarget = isAssignmentTarget && oldIsAssignmentTarget; + firstCoverInitializedNameError = oldFirstCoverInitializedNameError || firstCoverInitializedNameError; + return result; } + function parseArrayPattern(params) { + var node = new Node(), elements = [], rest, restNode; + expect('['); + + while (!match(']')) { + if (match(',')) { + lex(); + elements.push(null); + } else { + if (match('...')) { + restNode = new Node(); + lex(); + params.push(lookahead); + rest = parseVariableIdentifier(params); + elements.push(restNode.finishRestElement(rest)); + break; + } else { + elements.push(parsePatternWithDefault(params)); + } + if (!match(']')) { + expect(','); + } + } + + } + + expect(']'); + + return node.finishArrayPattern(elements); + } + + function parsePropertyPattern(params) { + var node = new Node(), key, keyToken, computed = match('['), init; + if (lookahead.type === Token.Identifier) { + keyToken = lookahead; + key = parseVariableIdentifier(); + if (match('=')) { + params.push(keyToken); + lex(); + init = parseAssignmentExpression(); + + return node.finishProperty( + 'init', key, false, + new WrappingNode(keyToken).finishAssignmentPattern(key, init), false, false); + } else if (!match(':')) { + params.push(keyToken); + return node.finishProperty('init', key, false, key, false, true); + } + } else { + key = parseObjectPropertyKey(params); + } + expect(':'); + init = parsePatternWithDefault(params); + return node.finishProperty('init', key, computed, init, false, false); + } + + function parseObjectPattern(params) { + var node = new Node(), properties = []; + + expect('{'); + + while (!match('}')) { + properties.push(parsePropertyPattern(params)); + if (!match('}')) { + expect(','); + } + } + + lex(); + + return node.finishObjectPattern(properties); + } + + function parsePattern(params) { + var identifier; + if (lookahead.type === Token.Identifier) { + params.push(lookahead); + identifier = parseVariableIdentifier(); + return identifier; + } else if (match('[')) { + return parseArrayPattern(params); + } else if (match('{')) { + return parseObjectPattern(params); + } + throwUnexpectedToken(lookahead); + } + + function parsePatternWithDefault(params) { + var startToken = lookahead, pattern, right; + pattern = parsePattern(params); + if (match('=')) { + lex(); + right = isolateCoverGrammar(parseAssignmentExpression); + pattern = new WrappingNode(startToken).finishAssignmentPattern(pattern, right); + } + return pattern; + } + // 11.1.4 Array Initialiser function parseArrayInitialiser() { - var elements = [], node = new Node(); + var elements = [], node = new Node(), restSpread; expect('['); while (!match(']')) { if (match(',')) { lex(); elements.push(null); + } else if (match('...')) { + restSpread = new Node(); + lex(); + restSpread.finishSpreadElement(inheritCoverGrammar(parseAssignmentExpression)); + + if (!match(']')) { + isAssignmentTarget = isBindingElement = false; + expect(','); + } + elements.push(restSpread); } else { - elements.push(parseAssignmentExpression()); + elements.push(inheritCoverGrammar(parseAssignmentExpression)); if (!match(']')) { expect(','); } } @@ -6784,38 +7293,44 @@ return node.finishArrayExpression(elements); } // 11.1.5 Object Initialiser - function parsePropertyFunction(node, paramInfo) { + function parsePropertyFunction(node, paramInfo, isGenerator) { var previousStrict, body; + isAssignmentTarget = isBindingElement = false; + previousStrict = strict; - body = parseFunctionSourceElements(); + body = isolateCoverGrammar(parseFunctionSourceElements); if (strict && paramInfo.firstRestricted) { tolerateUnexpectedToken(paramInfo.firstRestricted, paramInfo.message); } if (strict && paramInfo.stricted) { tolerateUnexpectedToken(paramInfo.stricted, paramInfo.message); } strict = previousStrict; - return node.finishFunctionExpression(null, paramInfo.params, paramInfo.defaults, body); + return node.finishFunctionExpression(null, paramInfo.params, paramInfo.defaults, body, isGenerator); } function parsePropertyMethodFunction() { - var params, method, node = new Node(); + var params, method, node = new Node(), + previousAllowYield = state.allowYield; + state.allowYield = false; params = parseParams(); - method = parsePropertyFunction(node, params); + state.allowYield = previousAllowYield; + state.allowYield = false; + method = parsePropertyFunction(node, params, false); + state.allowYield = previousAllowYield; + 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, node = new Node(), expr; token = lex(); @@ -6834,11 +7349,11 @@ case Token.NullLiteral: case Token.Keyword: return node.finishIdentifier(token.value); case Token.Punctuator: if (token.value === '[') { - expr = parseAssignmentExpression(); + expr = isolateCoverGrammar(parseAssignmentExpression); expect(']'); return expr; } break; } @@ -6865,28 +7380,33 @@ // 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; + var value, options, methodNode, params, + previousAllowYield = state.allowYield; if (token.type === Token.Identifier) { // check for `get` and `set`; if (token.value === 'get' && lookaheadPropertyName()) { computed = match('['); key = parseObjectPropertyKey(); methodNode = new Node(); expect('('); expect(')'); + + state.allowYield = false; value = parsePropertyFunction(methodNode, { params: [], defaults: [], stricted: null, firstRestricted: null, message: null - }); + }, false); + state.allowYield = previousAllowYield; + return node.finishProperty('get', key, computed, value, false, false); } else if (token.value === 'set' && lookaheadPropertyName()) { computed = match('['); key = parseObjectPropertyKey(); methodNode = new Node(); @@ -6900,23 +7420,42 @@ paramSet: {} }; if (match(')')) { tolerateUnexpectedToken(lookahead); } else { + state.allowYield = false; parseParam(options); + state.allowYield = previousAllowYield; if (options.defaultCount === 0) { options.defaults = []; } } expect(')'); - value = parsePropertyFunction(methodNode, options); + state.allowYield = false; + value = parsePropertyFunction(methodNode, options, false); + state.allowYield = previousAllowYield; + return node.finishProperty('set', key, computed, value, false, false); } + } else if (token.type === Token.Punctuator && token.value === '*' && lookaheadPropertyName()) { + computed = match('['); + key = parseObjectPropertyKey(); + methodNode = new Node(); + + state.allowYield = false; + params = parseParams(); + state.allowYield = previousAllowYield; + + state.allowYield = true; + value = parsePropertyFunction(methodNode, params, true); + state.allowYield = previousAllowYield; + + return node.finishProperty('init', key, computed, value, true, false); } - if (match('(')) { + if (key && match('(')) { value = parsePropertyMethodFunction(); return node.finishProperty('init', key, computed, value, true, false); } // Not a MethodDefinition. @@ -6936,29 +7475,44 @@ function parseObjectProperty(hasProto) { var token = lookahead, node = new Node(), computed, key, maybeMethod, value; computed = match('['); - key = parseObjectPropertyKey(); + if (match('*')) { + lex(); + } else { + key = parseObjectPropertyKey(); + } maybeMethod = tryParseMethodDefinition(token, key, computed, node); if (maybeMethod) { checkProto(maybeMethod.key, maybeMethod.computed, hasProto); // finished return maybeMethod; } + if (!key) { + throwUnexpectedToken(lookahead); + } + // init property or short hand property. checkProto(key, computed, hasProto); if (match(':')) { lex(); - value = parseAssignmentExpression(); + value = inheritCoverGrammar(parseAssignmentExpression); return node.finishProperty('init', key, computed, value, false, false); } if (token.type === Token.Identifier) { + if (match('=')) { + firstCoverInitializedNameError = lookahead; + lex(); + value = isolateCoverGrammar(parseAssignmentExpression); + return node.finishProperty('init', key, computed, + new WrappingNode(token).finishAssignmentPattern(key, value), false, true); + } return node.finishProperty('init', key, computed, key, false, true); } throwUnexpectedToken(lookahead); } @@ -6979,118 +7533,202 @@ expect('}'); return node.finishObjectExpression(properties); } + function reinterpretExpressionAsPattern(expr) { + var i; + switch (expr.type) { + case Syntax.Identifier: + case Syntax.MemberExpression: + case Syntax.RestElement: + case Syntax.AssignmentPattern: + break; + case Syntax.SpreadElement: + expr.type = Syntax.RestElement; + reinterpretExpressionAsPattern(expr.argument); + break; + case Syntax.ArrayExpression: + expr.type = Syntax.ArrayPattern; + for (i = 0; i < expr.elements.length; i++) { + if (expr.elements[i] !== null) { + reinterpretExpressionAsPattern(expr.elements[i]); + } + } + break; + case Syntax.ObjectExpression: + expr.type = Syntax.ObjectPattern; + for (i = 0; i < expr.properties.length; i++) { + reinterpretExpressionAsPattern(expr.properties[i].value); + } + break; + case Syntax.AssignmentExpression: + expr.type = Syntax.AssignmentPattern; + reinterpretExpressionAsPattern(expr.left); + break; + default: + // Allow other node type for tolerant parsing. + break; + } + } + + function parseTemplateElement(option) { + var node, token; + + if (lookahead.type !== Token.Template || (option.head && !lookahead.head)) { + throwUnexpectedToken(); + } + + node = new Node(); + token = lex(); + + return node.finishTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail); + } + + function parseTemplateLiteral() { + var quasi, quasis, expressions, node = new Node(); + + quasi = parseTemplateElement({ head: true }); + quasis = [ quasi ]; + expressions = []; + + while (!quasi.tail) { + expressions.push(parseExpression()); + quasi = parseTemplateElement({ head: false }); + quasis.push(quasi); + } + + return node.finishTemplateLiteral(quasis, expressions); + } + // 11.1.6 The Grouping Operator function parseGroupExpression() { - var expr, expressions, startToken, isValidArrowParameter = true; + var expr, expressions, startToken, i, params = []; expect('('); if (match(')')) { lex(); if (!match('=>')) { expect('=>'); } return { type: PlaceHolders.ArrowParameterPlaceHolder, - params: [] + params: [], + rawParams: [] }; } startToken = lookahead; if (match('...')) { - expr = parseRestElement(); + expr = parseRestElement(params); expect(')'); if (!match('=>')) { expect('=>'); } return { type: PlaceHolders.ArrowParameterPlaceHolder, params: [expr] }; } - if (match('(')) { - isValidArrowParameter = false; - } + isBindingElement = true; + expr = inheritCoverGrammar(parseAssignmentExpression); - expr = parseAssignmentExpression(); - if (match(',')) { + isAssignmentTarget = false; expressions = [expr]; while (startIndex < length) { if (!match(',')) { break; } lex(); if (match('...')) { - if (!isValidArrowParameter) { + if (!isBindingElement) { throwUnexpectedToken(lookahead); } - expressions.push(parseRestElement()); + expressions.push(parseRestElement(params)); expect(')'); if (!match('=>')) { expect('=>'); } + isBindingElement = false; + for (i = 0; i < expressions.length; i++) { + reinterpretExpressionAsPattern(expressions[i]); + } return { type: PlaceHolders.ArrowParameterPlaceHolder, params: expressions }; - } else if (match('(')) { - isValidArrowParameter = false; } - expressions.push(parseAssignmentExpression()); + expressions.push(inheritCoverGrammar(parseAssignmentExpression)); } expr = new WrappingNode(startToken).finishSequenceExpression(expressions); } expect(')'); - if (match('=>') && !isValidArrowParameter) { - throwUnexpectedToken(lookahead); - } + if (match('=>')) { + if (!isBindingElement) { + throwUnexpectedToken(lookahead); + } + if (expr.type === Syntax.SequenceExpression) { + for (i = 0; i < expr.expressions.length; i++) { + reinterpretExpressionAsPattern(expr.expressions[i]); + } + } else { + reinterpretExpressionAsPattern(expr); + } + + expr = { + type: PlaceHolders.ArrowParameterPlaceHolder, + params: expr.type === Syntax.SequenceExpression ? expr.expressions : [expr] + }; + } + isBindingElement = false; return expr; } // 11.1 Primary Expressions function parsePrimaryExpression() { var type, token, expr, node; if (match('(')) { - return parseGroupExpression(); + isBindingElement = false; + return inheritCoverGrammar(parseGroupExpression); } if (match('[')) { - return parseArrayInitialiser(); + return inheritCoverGrammar(parseArrayInitialiser); } if (match('{')) { - return parseObjectInitialiser(); + return inheritCoverGrammar(parseObjectInitialiser); } type = lookahead.type; node = new Node(); if (type === Token.Identifier) { expr = node.finishIdentifier(lex().value); } else if (type === Token.StringLiteral || type === Token.NumericLiteral) { + isAssignmentTarget = isBindingElement = false; if (strict && lookahead.octal) { tolerateUnexpectedToken(lookahead, Messages.StrictOctalLiteral); } expr = node.finishLiteral(lex()); } else if (type === Token.Keyword) { + isAssignmentTarget = isBindingElement = false; if (matchKeyword('function')) { return parseFunctionExpression(); } if (matchKeyword('this')) { lex(); @@ -7099,44 +7737,56 @@ if (matchKeyword('class')) { return parseClassExpression(); } throwUnexpectedToken(lex()); } else if (type === Token.BooleanLiteral) { + isAssignmentTarget = isBindingElement = false; token = lex(); token.value = (token.value === 'true'); expr = node.finishLiteral(token); } else if (type === Token.NullLiteral) { + isAssignmentTarget = isBindingElement = false; token = lex(); token.value = null; expr = node.finishLiteral(token); } else if (match('/') || match('/=')) { + isAssignmentTarget = isBindingElement = false; index = startIndex; if (typeof extra.tokens !== 'undefined') { token = collectRegex(); } else { token = scanRegExp(); } lex(); expr = node.finishLiteral(token); + } else if (type === Token.Template) { + expr = parseTemplateLiteral(); } else { throwUnexpectedToken(lex()); } return expr; } // 11.2 Left-Hand-Side Expressions function parseArguments() { - var args = []; + var args = [], expr; expect('('); if (!match(')')) { while (startIndex < length) { - args.push(parseAssignmentExpression()); + if (match('...')) { + expr = new Node(); + lex(); + expr.finishSpreadElement(isolateCoverGrammar(parseAssignmentExpression)); + } else { + expr = isolateCoverGrammar(parseAssignmentExpression); + } + args.push(expr); if (match(')')) { break; } expectCommaSeparator(); } @@ -7168,68 +7818,105 @@ function parseComputedMember() { var expr; expect('['); - expr = parseExpression(); + expr = isolateCoverGrammar(parseExpression); expect(']'); return expr; } function parseNewExpression() { var callee, args, node = new Node(); expectKeyword('new'); - callee = parseLeftHandSideExpression(); + callee = isolateCoverGrammar(parseLeftHandSideExpression); args = match('(') ? parseArguments() : []; + isAssignmentTarget = isBindingElement = false; + return node.finishNewExpression(callee, args); } function parseLeftHandSideExpressionAllowCall() { - var expr, args, property, startToken, previousAllowIn = state.allowIn; + var quasi, expr, args, property, startToken, previousAllowIn = state.allowIn; startToken = lookahead; state.allowIn = true; - expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + if (matchKeyword('super') && state.inFunctionBody) { + expr = new Node(); + lex(); + expr = expr.finishSuper(); + if (!match('(') && !match('.') && !match('[')) { + throwUnexpectedToken(lookahead); + } + } else { + expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression); + } + for (;;) { if (match('.')) { + isBindingElement = false; + isAssignmentTarget = true; property = parseNonComputedMember(); expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property); } else if (match('(')) { + isBindingElement = false; + isAssignmentTarget = false; args = parseArguments(); expr = new WrappingNode(startToken).finishCallExpression(expr, args); } else if (match('[')) { + isBindingElement = false; + isAssignmentTarget = true; property = parseComputedMember(); expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property); + } else if (lookahead.type === Token.Template && lookahead.head) { + quasi = parseTemplateLiteral(); + expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi); } else { break; } } state.allowIn = previousAllowIn; return expr; } function parseLeftHandSideExpression() { - var expr, property, startToken; + var quasi, expr, property, startToken; assert(state.allowIn, 'callee of new expression always allow in keyword.'); startToken = lookahead; - expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + if (matchKeyword('super') && state.inFunctionBody) { + expr = new Node(); + lex(); + expr = expr.finishSuper(); + if (!match('[') && !match('.')) { + throwUnexpectedToken(lookahead); + } + } else { + expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression); + } for (;;) { if (match('[')) { + isBindingElement = false; + isAssignmentTarget = true; property = parseComputedMember(); expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property); } else if (match('.')) { + isBindingElement = false; + isAssignmentTarget = true; property = parseNonComputedMember(); expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property); + } else if (lookahead.type === Token.Template && lookahead.head) { + quasi = parseTemplateLiteral(); + expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi); } else { break; } } return expr; @@ -7238,23 +7925,25 @@ // 11.3 Postfix Expressions function parsePostfixExpression() { var expr, token, startToken = lookahead; - expr = parseLeftHandSideExpressionAllowCall(); + expr = inheritCoverGrammar(parseLeftHandSideExpressionAllowCall); if (!hasLineTerminator && lookahead.type === Token.Punctuator) { if (match('++') || match('--')) { // 11.3.1, 11.3.2 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { tolerateError(Messages.StrictLHSPostfix); } - if (!isLeftHandSide(expr)) { + if (!isAssignmentTarget) { tolerateError(Messages.InvalidLHSInAssignment); } + isAssignmentTarget = isBindingElement = false; + token = lex(); expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr); } } @@ -7269,34 +7958,36 @@ if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { expr = parsePostfixExpression(); } else if (match('++') || match('--')) { startToken = lookahead; token = lex(); - expr = parseUnaryExpression(); + expr = inheritCoverGrammar(parseUnaryExpression); // 11.4.4, 11.4.5 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { tolerateError(Messages.StrictLHSPrefix); } - if (!isLeftHandSide(expr)) { + if (!isAssignmentTarget) { tolerateError(Messages.InvalidLHSInAssignment); } - expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); + isAssignmentTarget = isBindingElement = false; } else if (match('+') || match('-') || match('~') || match('!')) { startToken = lookahead; token = lex(); - expr = parseUnaryExpression(); + expr = inheritCoverGrammar(parseUnaryExpression); expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); + isAssignmentTarget = isBindingElement = false; } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { startToken = lookahead; token = lex(); - expr = parseUnaryExpression(); + expr = inheritCoverGrammar(parseUnaryExpression); expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { tolerateError(Messages.StrictDelete); } + isAssignmentTarget = isBindingElement = false; } else { expr = parsePostfixExpression(); } return expr; @@ -7383,22 +8074,23 @@ function parseBinaryExpression() { var marker, markers, expr, token, prec, stack, right, operator, left, i; marker = lookahead; - left = parseUnaryExpression(); + left = inheritCoverGrammar(parseUnaryExpression); token = lookahead; prec = binaryPrecedence(token, state.allowIn); if (prec === 0) { return left; } + isAssignmentTarget = isBindingElement = false; token.prec = prec; lex(); markers = [marker, lookahead]; - right = parseUnaryExpression(); + right = isolateCoverGrammar(parseUnaryExpression); stack = [left, token, right]; while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) { @@ -7415,11 +8107,11 @@ // Shift. token = lex(); token.prec = prec; stack.push(token); markers.push(lookahead); - expr = parseUnaryExpression(); + expr = isolateCoverGrammar(parseUnaryExpression); stack.push(expr); } // Final reduce to clean-up the stack. i = stack.length - 1; @@ -7439,21 +8131,22 @@ function parseConditionalExpression() { var expr, previousAllowIn, consequent, alternate, startToken; startToken = lookahead; - expr = parseBinaryExpression(); + expr = inheritCoverGrammar(parseBinaryExpression); if (match('?')) { lex(); previousAllowIn = state.allowIn; state.allowIn = true; - consequent = parseAssignmentExpression(); + consequent = isolateCoverGrammar(parseAssignmentExpression); state.allowIn = previousAllowIn; expect(':'); - alternate = parseAssignmentExpression(); + alternate = isolateCoverGrammar(parseAssignmentExpression); expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate); + isAssignmentTarget = isBindingElement = false; } return expr; } @@ -7461,27 +8154,50 @@ function parseConciseBody() { if (match('{')) { return parseFunctionSourceElements(); } - return parseAssignmentExpression(); + return isolateCoverGrammar(parseAssignmentExpression); } + function checkPatternParam(options, param) { + var i; + switch (param.type) { + case Syntax.Identifier: + validateParam(options, param, param.name); + break; + case Syntax.RestElement: + checkPatternParam(options, param.argument); + break; + case Syntax.AssignmentPattern: + checkPatternParam(options, param.left); + break; + case Syntax.ArrayPattern: + for (i = 0; i < param.elements.length; i++) { + if (param.elements[i] !== null) { + checkPatternParam(options, param.elements[i]); + } + } + break; + default: + assert(param.type === Syntax.ObjectPattern, 'Invalid type'); + for (i = 0; i < param.properties.length; i++) { + checkPatternParam(options, param.properties[i].value); + } + break; + } + } 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; @@ -7491,25 +8207,22 @@ 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) { + switch (param.type) { + case Syntax.AssignmentPattern: params[i] = param.left; defaults.push(param.right); ++defaultCount; - validateParam(options, param.left, param.left.name); - } else { - return null; + checkPatternParam(options, param.left); + break; + default: + checkPatternParam(options, param); + params[i] = param; + defaults.push(null); + break; } } if (options.message === Messages.StrictParamDupe) { token = strict ? options.stricted : options.firstRestricted; @@ -7530,10 +8243,13 @@ } function parseArrowFunctionExpression(options, node) { var previousStrict, body; + if (hasLineTerminator) { + tolerateUnexpectedToken(lookahead); + } expect('=>'); previousStrict = strict; body = parseConciseBody(); @@ -7547,63 +8263,105 @@ strict = previousStrict; return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement); } + // [ES6] 14.4 Yield expression + + function parseYieldExpression() { + var argument, expr, delegate; + + expr = new Node(); + + if (!state.allowYield) { + tolerateUnexpectedToken(lookahead, Messages.IllegalYield); + } + + expectKeyword('yield'); + + if (!hasLineTerminator) { + delegate = match('*'); + if (delegate) { + lex(); + argument = parseExpression(); + } else { + if (!match(';') && !match('}') && lookahead.type !== Token.EOF) { + argument = parseExpression(); + } + } + } + + return expr.finishYieldExpression(argument, delegate); + } + // 11.13 Assignment Operators function parseAssignmentExpression() { var token, expr, right, list, startToken; startToken = lookahead; token = lookahead; + if (matchKeyword('yield')) { + return parseYieldExpression(); + } + expr = parseConditionalExpression(); if (expr.type === PlaceHolders.ArrowParameterPlaceHolder || match('=>')) { + isAssignmentTarget = isBindingElement = false; list = reinterpretAsCoverFormalsList(expr); if (list) { + firstCoverInitializedNameError = null; return parseArrowFunctionExpression(list, new WrappingNode(startToken)); } + + return expr; } if (matchAssign()) { - // LeftHandSideExpression - if (!isLeftHandSide(expr)) { + if (!isAssignmentTarget) { tolerateError(Messages.InvalidLHSInAssignment); } // 11.13.1 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { tolerateUnexpectedToken(token, Messages.StrictLHSAssignment); } + if (!match('=')) { + isAssignmentTarget = isBindingElement = false; + } else { + reinterpretExpressionAsPattern(expr); + } + token = lex(); - right = parseAssignmentExpression(); + right = isolateCoverGrammar(parseAssignmentExpression); expr = new WrappingNode(startToken).finishAssignmentExpression(token.value, expr, right); + firstCoverInitializedNameError = null; } return expr; } // 11.14 Comma Operator function parseExpression() { var expr, startToken = lookahead, expressions; - expr = parseAssignmentExpression(); + expr = isolateCoverGrammar(parseAssignmentExpression); if (match(',')) { expressions = [expr]; while (startIndex < length) { if (!match(',')) { break; } lex(); - expressions.push(parseAssignmentExpression()); + expressions.push(isolateCoverGrammar(parseAssignmentExpression)); } expr = new WrappingNode(startToken).finishSequenceExpression(expressions); } @@ -7613,13 +8371,23 @@ // 12.1 Block function parseStatementListItem() { if (lookahead.type === Token.Keyword) { switch (lookahead.value) { + case 'export': + if (sourceType !== 'module') { + tolerateUnexpectedToken(lookahead, Messages.IllegalExportDeclaration); + } + return parseExportDeclaration(); + case 'import': + if (sourceType !== 'module') { + tolerateUnexpectedToken(lookahead, Messages.IllegalImportDeclaration); + } + return parseImportDeclaration(); case 'const': case 'let': - return parseLexicalDeclaration(); + return parseLexicalDeclaration({inFor: false}); case 'function': return parseFunctionDeclaration(new Node()); case 'class': return parseClassDeclaration(); } @@ -7669,22 +8437,24 @@ return node.finishIdentifier(token.value); } function parseVariableDeclaration() { - var init = null, id, node = new Node(); + var init = null, id, node = new Node(), params = []; - id = parseVariableIdentifier(); + id = parsePattern(params); // 12.2.1 if (strict && isRestrictedWord(id.name)) { tolerateError(Messages.StrictVarName); } if (match('=')) { lex(); - init = parseAssignmentExpression(); + init = isolateCoverGrammar(parseAssignmentExpression); + } else if (id.type !== Syntax.Identifier) { + expect('='); } return node.finishVariableDeclarator(id, init); } @@ -7712,69 +8482,71 @@ consumeSemicolon(); return node.finishVariableDeclaration(declarations); } - function parseLexicalBinding(kind) { - var init = null, id, node = new Node(); + function parseLexicalBinding(kind, options) { + var init = null, id, node = new Node(), params = []; - id = parseVariableIdentifier(); + id = parsePattern(params); // 12.2.1 - if (strict && isRestrictedWord(id.name)) { + if (strict && id.type === Syntax.Identifier && isRestrictedWord(id.name)) { tolerateError(Messages.StrictVarName); } if (kind === 'const') { - if (!matchKeyword('in')) { + if (!matchKeyword('in') && !matchContextualKeyword('of')) { expect('='); - init = parseAssignmentExpression(); + init = isolateCoverGrammar(parseAssignmentExpression); } - } else if (match('=')) { - lex(); - init = parseAssignmentExpression(); + } else if ((!options.inFor && id.type !== Syntax.Identifier) || match('=')) { + expect('='); + init = isolateCoverGrammar(parseAssignmentExpression); } return node.finishVariableDeclarator(id, init); } - function parseBindingList(kind) { + function parseBindingList(kind, options) { var list = []; do { - list.push(parseLexicalBinding(kind)); + list.push(parseLexicalBinding(kind, options)); if (!match(',')) { break; } lex(); } while (startIndex < length); return list; } - function parseLexicalDeclaration() { + function parseLexicalDeclaration(options) { 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); + declarations = parseBindingList(kind, options); consumeSemicolon(); return node.finishLexicalDeclaration(declarations, kind); } - function parseRestElement() { + function parseRestElement(params) { var param, node = new Node(); lex(); if (match('{')) { throwError(Messages.ObjectPatternAsRestParameter); } + params.push(lookahead); + param = parseVariableIdentifier(); if (match('=')) { throwError(Messages.DefaultRestParameter); } @@ -7875,14 +8647,15 @@ return node.finishWhileStatement(test, body); } function parseForStatement(node) { - var init, test, update, left, right, kind, declarations, + var init, forIn, initSeq, initStartToken, test, update, left, right, kind, declarations, body, oldInIteration, previousAllowIn = state.allowIn; init = test = update = null; + forIn = true; expectKeyword('for'); expect('('); @@ -7900,47 +8673,80 @@ if (init.declarations.length === 1 && matchKeyword('in')) { lex(); left = init; right = parseExpression(); init = null; + } else if (init.declarations.length === 1 && init.declarations[0].init === null && matchContextualKeyword('of')) { + lex(); + left = init; + right = parseAssignmentExpression(); + init = null; + forIn = false; } else { expect(';'); } } else if (matchKeyword('const') || matchKeyword('let')) { init = new Node(); kind = lex().value; state.allowIn = false; - declarations = parseBindingList(kind); + declarations = parseBindingList(kind, {inFor: true}); 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 if (declarations.length === 1 && declarations[0].init === null && matchContextualKeyword('of')) { + init = init.finishLexicalDeclaration(declarations, kind); + lex(); + left = init; + right = parseAssignmentExpression(); + init = null; + forIn = false; } else { consumeSemicolon(); init = init.finishLexicalDeclaration(declarations, kind); } } else { + initStartToken = lookahead; state.allowIn = false; - init = parseExpression(); + init = inheritCoverGrammar(parseAssignmentExpression); state.allowIn = previousAllowIn; if (matchKeyword('in')) { - // LeftHandSideExpression - if (!isLeftHandSide(init)) { + if (!isAssignmentTarget) { tolerateError(Messages.InvalidLHSInForIn); } lex(); + reinterpretExpressionAsPattern(init); left = init; right = parseExpression(); init = null; + } else if (matchContextualKeyword('of')) { + if (!isAssignmentTarget) { + tolerateError(Messages.InvalidLHSInForLoop); + } + + lex(); + reinterpretExpressionAsPattern(init); + left = init; + right = parseAssignmentExpression(); + init = null; + forIn = false; } else { + if (match(',')) { + initSeq = [init]; + while (match(',')) { + lex(); + initSeq.push(isolateCoverGrammar(parseAssignmentExpression)); + } + init = new WrappingNode(initStartToken).finishSequenceExpression(initSeq); + } expect(';'); } } } @@ -7959,17 +8765,18 @@ expect(')'); oldInIteration = state.inIteration; state.inIteration = true; - body = parseStatement(); + body = isolateCoverGrammar(parseStatement); state.inIteration = oldInIteration; return (typeof left === 'undefined') ? node.finishForStatement(init, test, update, body) : - node.finishForInStatement(left, right, body); + forIn ? node.finishForInStatement(left, right, body) : + node.finishForOfStatement(left, right, body); } // 12.7 The continue statement function parseContinueStatement(node) { @@ -8205,20 +9012,28 @@ } // 12.14 The try statement function parseCatchClause() { - var param, body, node = new Node(); + var param, params = [], paramMap = {}, key, i, body, node = new Node(); expectKeyword('catch'); expect('('); if (match(')')) { throwUnexpectedToken(lookahead); } - param = parseVariableIdentifier(); + param = parsePattern(params); + for (i = 0; i < params.length; i++) { + key = '$' + params[i].value; + if (Object.prototype.hasOwnProperty.call(paramMap, key)) { + tolerateError(Messages.DuplicateBinding, params[i].value); + } + paramMap[key] = true; + } + // 12.14.1 if (strict && isRestrictedWord(param.name)) { tolerateError(Messages.StrictCatchVariable); } @@ -8274,11 +9089,11 @@ } if (type === Token.Punctuator && lookahead.value === '{') { return parseBlock(); } - + isAssignmentTarget = isBindingElement = true; node = new Node(); if (type === Token.Punctuator) { switch (lookahead.value) { case ';': @@ -8426,35 +9241,37 @@ 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.stricted = param; options.message = Messages.StrictParamDupe; } } options.paramSet[key] = true; } function parseParam(options) { - var token, param, def; + var token, param, params = [], i, def; token = lookahead; if (token.value === '...') { - param = parseRestElement(); + param = parseRestElement(params); validateParam(options, param.argument, param.argument.name); options.params.push(param); options.defaults.push(null); return false; } - param = parseVariableIdentifier(); - validateParam(options, token, token.value); + param = parsePatternWithDefault(params); + for (i = 0; i < params.length; i++) { + validateParam(options, params[i], params[i].value); + } - if (match('=')) { - lex(); - def = parseAssignmentExpression(); + if (param.type === Syntax.AssignmentPattern) { + def = param.right; + param = param.left; ++options.defaultCount; } options.params.push(param); options.defaults.push(def); @@ -8497,58 +9314,80 @@ firstRestricted: options.firstRestricted, message: options.message }; } - function parseFunctionDeclaration(node) { - var id, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict; + function parseFunctionDeclaration(node, identifierIsOptional) { + var id = null, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict, + isGenerator, previousAllowYield; expectKeyword('function'); - token = lookahead; - id = parseVariableIdentifier(); - if (strict) { - if (isRestrictedWord(token.value)) { - tolerateUnexpectedToken(token, Messages.StrictFunctionName); + + isGenerator = match('*'); + if (isGenerator) { + lex(); + } + + if (!identifierIsOptional || !match('(')) { + token = lookahead; + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + tolerateUnexpectedToken(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } } - } else { - if (isRestrictedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictFunctionName; - } else if (isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictReservedWord; - } } + previousAllowYield = state.allowYield; + state.allowYield = false; tmp = parseParams(firstRestricted); + state.allowYield = previousAllowYield; + params = tmp.params; defaults = tmp.defaults; stricted = tmp.stricted; firstRestricted = tmp.firstRestricted; if (tmp.message) { message = tmp.message; } + previousAllowYield = state.allowYield; previousStrict = strict; + state.allowYield = isGenerator; body = parseFunctionSourceElements(); if (strict && firstRestricted) { throwUnexpectedToken(firstRestricted, message); } if (strict && stricted) { tolerateUnexpectedToken(stricted, message); } strict = previousStrict; + state.allowYield = previousAllowYield; - return node.finishFunctionDeclaration(id, params, defaults, body); + return node.finishFunctionDeclaration(id, params, defaults, body, isGenerator); } function parseFunctionExpression() { var token, id = null, stricted, firstRestricted, message, tmp, - params = [], defaults = [], body, previousStrict, node = new Node(); + params = [], defaults = [], body, previousStrict, node = new Node(), + isGenerator, previousAllowYield; expectKeyword('function'); + isGenerator = match('*'); + if (isGenerator) { + lex(); + } + if (!match('(')) { token = lookahead; id = parseVariableIdentifier(); if (strict) { if (isRestrictedWord(token.value)) { @@ -8563,30 +9402,38 @@ message = Messages.StrictReservedWord; } } } + previousAllowYield = state.allowYield; + state.allowYield = false; tmp = parseParams(firstRestricted); + state.allowYield = previousAllowYield; + params = tmp.params; defaults = tmp.defaults; stricted = tmp.stricted; firstRestricted = tmp.firstRestricted; if (tmp.message) { message = tmp.message; } previousStrict = strict; + previousAllowYield = state.allowYield; + state.allowYield = isGenerator; body = parseFunctionSourceElements(); + if (strict && firstRestricted) { throwUnexpectedToken(firstRestricted, message); } if (strict && stricted) { tolerateUnexpectedToken(stricted, message); } strict = previousStrict; + state.allowYield = previousAllowYield; - return node.finishFunctionExpression(id, params, defaults, body); + return node.finishFunctionExpression(id, params, defaults, body, isGenerator); } function parseClassBody() { var classBody, token, isStatic, hasConstructor = false, body, method, computed, key; @@ -8601,20 +9448,28 @@ } else { method = new Node(); token = lookahead; isStatic = false; computed = match('['); - key = parseObjectPropertyKey(); - if (key.name === 'static' && lookaheadPropertyName()) { - token = lookahead; - isStatic = true; - computed = match('['); + if (match('*')) { + lex(); + } else { key = parseObjectPropertyKey(); + if (key.name === 'static' && (lookaheadPropertyName() || match('*'))) { + token = lookahead; + isStatic = true; + computed = match('['); + if (match('*')) { + lex(); + } else { + key = parseObjectPropertyKey(); + } + } } method = tryParseMethodDefinition(token, key, computed, method); if (method) { - method.static = isStatic; + method['static'] = isStatic; if (method.kind === 'init') { method.kind = 'method'; } if (!isStatic) { if (!method.computed && (method.key.name || method.key.value.toString()) === 'constructor') { @@ -8644,21 +9499,23 @@ } lex(); return classBody.finishClassBody(body); } - function parseClassDeclaration() { + function parseClassDeclaration(identifierIsOptional) { var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict; strict = true; expectKeyword('class'); - id = parseVariableIdentifier(); + if (!identifierIsOptional || lookahead.type === Token.Identifier) { + id = parseVariableIdentifier(); + } if (matchKeyword('extends')) { lex(); - superClass = parseLeftHandSideExpressionAllowCall(); + superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall); } classBody = parseClassBody(); strict = previousStrict; return classNode.finishClassDeclaration(id, superClass, classBody); @@ -8674,18 +9531,268 @@ id = parseVariableIdentifier(); } if (matchKeyword('extends')) { lex(); - superClass = parseLeftHandSideExpressionAllowCall(); + superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall); } classBody = parseClassBody(); strict = previousStrict; return classNode.finishClassExpression(id, superClass, classBody); } + // Modules grammar from: + // people.mozilla.org/~jorendorff/es6-draft.html + + function parseModuleSpecifier() { + var node = new Node(); + + if (lookahead.type !== Token.StringLiteral) { + throwError(Messages.InvalidModuleSpecifier); + } + return node.finishLiteral(lex()); + } + + function parseExportSpecifier() { + var exported, local, node = new Node(), def; + if (matchKeyword('default')) { + // export {default} from 'something'; + def = new Node(); + lex(); + local = def.finishIdentifier('default'); + } else { + local = parseVariableIdentifier(); + } + if (matchContextualKeyword('as')) { + lex(); + exported = parseNonComputedProperty(); + } + return node.finishExportSpecifier(local, exported); + } + + function parseExportNamedDeclaration(node) { + var declaration = null, + isExportFromIdentifier, + src = null, specifiers = []; + + // non-default export + if (lookahead.type === Token.Keyword) { + // covers: + // export var f = 1; + switch (lookahead.value) { + case 'let': + case 'const': + case 'var': + case 'class': + case 'function': + declaration = parseStatementListItem(); + return node.finishExportNamedDeclaration(declaration, specifiers, null); + } + } + + expect('{'); + if (!match('}')) { + do { + isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default'); + specifiers.push(parseExportSpecifier()); + } while (match(',') && lex()); + } + expect('}'); + + if (matchContextualKeyword('from')) { + // covering: + // export {default} from 'foo'; + // export {foo} from 'foo'; + lex(); + src = parseModuleSpecifier(); + consumeSemicolon(); + } else if (isExportFromIdentifier) { + // covering: + // export {default}; // missing fromClause + throwError(lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); + } else { + // cover + // export {foo}; + consumeSemicolon(); + } + return node.finishExportNamedDeclaration(declaration, specifiers, src); + } + + function parseExportDefaultDeclaration(node) { + var declaration = null, + expression = null; + + // covers: + // export default ... + expectKeyword('default'); + + if (matchKeyword('function')) { + // covers: + // export default function foo () {} + // export default function () {} + declaration = parseFunctionDeclaration(new Node(), true); + return node.finishExportDefaultDeclaration(declaration); + } + if (matchKeyword('class')) { + declaration = parseClassDeclaration(true); + return node.finishExportDefaultDeclaration(declaration); + } + + if (matchContextualKeyword('from')) { + throwError(Messages.UnexpectedToken, lookahead.value); + } + + // covers: + // export default {}; + // export default []; + // export default (1 + 2); + if (match('{')) { + expression = parseObjectInitialiser(); + } else if (match('[')) { + expression = parseArrayInitialiser(); + } else { + expression = parseAssignmentExpression(); + } + consumeSemicolon(); + return node.finishExportDefaultDeclaration(expression); + } + + function parseExportAllDeclaration(node) { + var src; + + // covers: + // export * from 'foo'; + expect('*'); + if (!matchContextualKeyword('from')) { + throwError(lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); + } + lex(); + src = parseModuleSpecifier(); + consumeSemicolon(); + + return node.finishExportAllDeclaration(src); + } + + function parseExportDeclaration() { + var node = new Node(); + if (state.inFunctionBody) { + throwError(Messages.IllegalExportDeclaration); + } + + expectKeyword('export'); + + if (matchKeyword('default')) { + return parseExportDefaultDeclaration(node); + } + if (match('*')) { + return parseExportAllDeclaration(node); + } + return parseExportNamedDeclaration(node); + } + + function parseImportSpecifier() { + // import {<foo as bar>} ...; + var local, imported, node = new Node(); + + imported = parseNonComputedProperty(); + if (matchContextualKeyword('as')) { + lex(); + local = parseVariableIdentifier(); + } + + return node.finishImportSpecifier(local, imported); + } + + function parseNamedImports() { + var specifiers = []; + // {foo, bar as bas} + expect('{'); + if (!match('}')) { + do { + specifiers.push(parseImportSpecifier()); + } while (match(',') && lex()); + } + expect('}'); + return specifiers; + } + + function parseImportDefaultSpecifier() { + // import <foo> ...; + var local, node = new Node(); + + local = parseNonComputedProperty(); + + return node.finishImportDefaultSpecifier(local); + } + + function parseImportNamespaceSpecifier() { + // import <* as foo> ...; + var local, node = new Node(); + + expect('*'); + if (!matchContextualKeyword('as')) { + throwError(Messages.NoAsAfterImportNamespace); + } + lex(); + local = parseNonComputedProperty(); + + return node.finishImportNamespaceSpecifier(local); + } + + function parseImportDeclaration() { + var specifiers, src, node = new Node(); + + if (state.inFunctionBody) { + throwError(Messages.IllegalImportDeclaration); + } + + expectKeyword('import'); + specifiers = []; + + if (lookahead.type === Token.StringLiteral) { + // covers: + // import 'foo'; + src = parseModuleSpecifier(); + consumeSemicolon(); + return node.finishImportDeclaration(specifiers, src); + } + + if (!matchKeyword('default') && isIdentifierName(lookahead)) { + // covers: + // import foo + // import foo, ... + specifiers.push(parseImportDefaultSpecifier()); + if (match(',')) { + lex(); + } + } + if (match('*')) { + // covers: + // import foo, * as foo + // import * as foo + specifiers.push(parseImportNamespaceSpecifier()); + } else if (match('{')) { + // covers: + // import foo, {bar} + // import {bar} + specifiers = specifiers.concat(parseNamedImports()); + } + + if (!matchContextualKeyword('from')) { + throwError(lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); + } + lex(); + src = parseModuleSpecifier(); + consumeSemicolon(); + + return node.finishImportDeclaration(specifiers, src); + } + // 14 Program function parseScriptBody() { var statement, body = [], token, directive, firstRestricted; @@ -8728,11 +9835,10 @@ function parseProgram() { var body, node; peek(); node = new Node(); - strict = false; body = parseScriptBody(); return node.finishProgram(body); } @@ -8781,15 +9887,17 @@ startLineStart = lineStart; length = source.length; lookahead = null; state = { allowIn: true, + allowYield: false, labelSet: {}, inFunctionBody: false, inIteration: false, inSwitch: false, - lastCommentStart: -1 + lastCommentStart: -1, + curlyStack: [] }; extra = {}; // Options matching. @@ -8868,16 +9976,20 @@ startLineStart = lineStart; length = source.length; lookahead = null; state = { allowIn: true, + allowYield: false, labelSet: {}, inFunctionBody: false, inIteration: false, inSwitch: false, - lastCommentStart: -1 + lastCommentStart: -1, + curlyStack: [] }; + sourceType = 'script'; + strict = false; extra = {}; if (typeof options !== 'undefined') { extra.range = (typeof options.range === 'boolean') && options.range; extra.loc = (typeof options.loc === 'boolean') && options.loc; @@ -8901,10 +10013,15 @@ extra.comments = []; extra.bottomRightStack = []; extra.trailingComments = []; extra.leadingComments = []; } + if (options.sourceType === 'module') { + // very restrictive condition for now + sourceType = options.sourceType; + strict = true; + } } try { program = parseProgram(); if (typeof extra.comments !== 'undefined') { @@ -8925,18 +10042,18 @@ return program; } // Sync with *.json manifests. - exports.version = '2.1.0'; + exports.version = '2.4.1'; exports.tokenize = tokenize; exports.parse = parse; // Deep copy. - /* istanbul ignore next */ + /* istanbul ignore next */ exports.Syntax = (function () { var name, types = {}; if (typeof Object.create === 'function') { types = Object.create(null); @@ -15838,14 +16955,16 @@ } return ret; }; function merge(obj, ext) { + var count = 0; for (var i in ext) if (ext.hasOwnProperty(i)) { obj[i] = ext[i]; + count++; } - return obj; + return count; }; function noop() {}; var MAP = (function(){ @@ -16030,12 +17149,18 @@ map: function(f) { var ret = []; for (var i in this._values) ret.push(f(this._values[i], i.substr(1))); return ret; - } + }, + toObject: function() { return this._values } }; +Dictionary.fromObject = function(obj) { + var dict = new Dictionary(); + dict._size = merge(dict._values, obj); + return dict; +}; /*********************************************************************** A JavaScript tokenizer / parser / beautifier / compressor. https://github.com/mishoo/UglifyJS2 @@ -16119,11 +17244,11 @@ this.prototype[name] = method; }; return ctor; }; -var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", { +var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file", { }, null); var AST_Node = DEFNODE("Node", "start end", { clone: function() { return new this.CTOR(this); @@ -16155,15 +17280,16 @@ var AST_Debugger = DEFNODE("Debugger", null, { $documentation: "Represents a debugger statement", }, AST_Statement); -var AST_Directive = DEFNODE("Directive", "value scope", { +var AST_Directive = DEFNODE("Directive", "value scope quote", { $documentation: "Represents a directive, like \"use strict\";", $propdoc: { value: "[string] The value of this directive as a plain string (it's not an AST_String!)", - scope: "[AST_Scope/S] The scope that this directive affects" + scope: "[AST_Scope/S] The scope that this directive affects", + quote: "[string] the original quote character" }, }, AST_Statement); var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", { $documentation: "A statement consisting of an expression, i.e. a = 1 + 2", @@ -16240,25 +17366,31 @@ var AST_DWLoop = DEFNODE("DWLoop", "condition", { $documentation: "Base class for do/while statements", $propdoc: { condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement" - }, - _walk: function(visitor) { - return visitor._visit(this, function(){ - this.condition._walk(visitor); - this.body._walk(visitor); - }); } }, AST_IterationStatement); var AST_Do = DEFNODE("Do", null, { $documentation: "A `do` statement", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + this.condition._walk(visitor); + }); + } }, AST_DWLoop); var AST_While = DEFNODE("While", null, { $documentation: "A `while` statement", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + }); + } }, AST_DWLoop); var AST_For = DEFNODE("For", "init condition step", { $documentation: "A `for` statement", $propdoc: { @@ -16795,12 +17927,15 @@ this.value._walk(visitor); }); } }); -var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, { +var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", { $documentation: "A key: value object property", + $propdoc: { + quote: "[string] the original quote character" + } }, AST_ObjectProperty); var AST_ObjectSetter = DEFNODE("ObjectSetter", null, { $documentation: "An object setter property", }, AST_ObjectProperty); @@ -16881,14 +18016,15 @@ getValue: function() { return this.value; } }); -var AST_String = DEFNODE("String", "value", { +var AST_String = DEFNODE("String", "value quote", { $documentation: "A string literal", $propdoc: { - value: "[string] the contents of this string" + value: "[string] the contents of this string", + quote: "[string] the original quote character" } }, AST_Constant); var AST_Number = DEFNODE("Number", "value", { $documentation: "A number literal", @@ -17128,11 +18264,11 @@ "&=", "&&", "||" ]); -var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000")); +var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\uFEFF")); var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:")); var PUNC_CHARS = makePredicate(characters("[]{}(),;:")); @@ -17140,11 +18276,12 @@ /* -----[ Tokenizer ]----- */ // regexps adapted from http://xregexp.com/plugins/#unicode var UNICODE = { - letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\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\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\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\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\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-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\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-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\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]"), + letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\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]"), + digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0DE6-\\u0DEF\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uA9F0-\\uA9F9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19]"), non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"), connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]") }; @@ -17153,17 +18290,21 @@ || (code >= 65 && code <= 90) || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code))); }; function is_digit(code) { - return code >= 48 && code <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9 + return code >= 48 && code <= 57; }; function is_alphanumeric_char(code) { return is_digit(code) || is_letter(code); }; +function is_unicode_digit(code) { + return UNICODE.digit.test(String.fromCharCode(code)); +} + function is_unicode_combining_mark(ch) { return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); }; function is_unicode_connector_punctuation(ch) { @@ -17184,10 +18325,11 @@ || is_digit(code) || code == 8204 // \u200c: zero-width non-joiner <ZWNJ> || code == 8205 // \u200d: zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c) || is_unicode_combining_mark(ch) || is_unicode_connector_punctuation(ch) + || is_unicode_digit(code) ; }; function is_identifier_string(str){ return /^[a-z_$][a-z0-9_$]*$/i.test(str); @@ -17201,12 +18343,13 @@ } else if (RE_DEC_NUMBER.test(num)) { return parseFloat(num); } }; -function JS_Parse_Error(message, line, col, pos) { +function JS_Parse_Error(message, filename, line, col, pos) { this.message = message; + this.filename = filename; this.line = line; this.col = col; this.pos = pos; this.stack = new Error().stack; }; @@ -17214,11 +18357,11 @@ JS_Parse_Error.prototype.toString = function() { return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; }; function js_error(message, filename, line, col, pos) { - throw new JS_Parse_Error(message, line, col, pos); + throw new JS_Parse_Error(message, filename, line, col, pos); }; function is_token(token, type, val) { return token.type == type && (val == null || token.value == val); }; @@ -17226,11 +18369,11 @@ var EX_EOF = {}; function tokenizer($TEXT, filename, html5_comments) { var S = { - text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/\uFEFF/g, ''), + text : $TEXT, filename : filename, pos : 0, tokpos : 0, line : 1, tokline : 0, @@ -17245,14 +18388,19 @@ function next(signal_eof, in_string) { var ch = S.text.charAt(S.pos++); if (signal_eof && !ch) throw EX_EOF; - if (ch == "\n") { + if ("\r\n\u2028\u2029".indexOf(ch) >= 0) { S.newline_before = S.newline_before || !in_string; ++S.line; S.col = 0; + if (!in_string && ch == "\r" && peek() == "\n") { + // treat a \r\n sequence as a single \n + ++S.pos; + ch = "\n"; + } } else { ++S.col; } return ch; }; @@ -17282,18 +18430,20 @@ S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX(value)) || (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) || (type == "punc" && PUNC_BEFORE_EXPRESSION(value))); prev_was_dot = (type == "punc" && value == "."); var ret = { - type : type, - value : value, - line : S.tokline, - col : S.tokcol, - pos : S.tokpos, - endpos : S.pos, - nlb : S.newline_before, - file : filename + type : type, + value : value, + line : S.tokline, + col : S.tokcol, + pos : S.tokpos, + endline : S.line, + endcol : S.col, + endpos : S.pos, + nlb : S.newline_before, + file : filename }; if (!is_comment) { ret.comments_before = S.comments_before; S.comments_before = []; // make note of any newlines in the comments that came before @@ -17304,11 +18454,12 @@ S.newline_before = false; return new AST_Token(ret); }; function skip_whitespace() { - while (WHITESPACE_CHARS(peek())) + var ch; + while (WHITESPACE_CHARS(ch = peek()) || ch == "\u2028" || ch == "\u2029") next(); }; function read_while(pred) { var ret = "", ch, i = 0; @@ -17359,12 +18510,17 @@ case 102 : return "\f"; case 48 : return "\0"; case 120 : return String.fromCharCode(hex_bytes(2)); // \x case 117 : return String.fromCharCode(hex_bytes(4)); // \u case 10 : return ""; // newline - default : return ch; + case 13 : // \r + if (peek() == "\n") { // DOS newline + next(true, in_string); + return ""; + } } + return ch; }; function hex_bytes(n) { var num = 0; for (; n > 0; --n) { @@ -17374,14 +18530,14 @@ num = (num << 4) | digit; } return num; }; - var read_string = with_eof_error("Unterminated string constant", function(){ + var read_string = with_eof_error("Unterminated string constant", function(quote_char){ var quote = next(), ret = ""; for (;;) { - var ch = next(true); + var ch = next(true, true); if (ch == "\\") { // read OctalEscapeSequence (XXX: deprecated if "strict mode") // https://github.com/mishoo/UglifyJS/issues/178 var octal_len = 0, first = null; ch = read_while(function(ch){ @@ -17399,11 +18555,13 @@ else ch = read_escaped_char(true); } else if (ch == quote) break; ret += ch; } - return token("string", ret); + var tok = token("string", ret); + tok.quote = quote_char; + return tok; }); function skip_line_comment(type) { var regex_allowed = S.regex_allowed; var i = find("\n"), ret; @@ -17412,10 +18570,11 @@ S.pos = S.text.length; } else { ret = S.text.substring(S.pos, i); S.pos = i; } + S.col = S.tokcol + (S.pos - S.tokpos); S.comments_before.push(token(type, ret, true)); S.regex_allowed = regex_allowed; return next_token(); }; @@ -17553,11 +18712,11 @@ } var ch = peek(); if (!ch) return token("eof"); var code = ch.charCodeAt(0); switch (code) { - case 34: case 39: return read_string(); + case 34: case 39: return read_string(ch); case 46: return handle_dot(); case 47: return handle_slash(); } if (is_digit(code)) return read_num(); if (PUNC_CHARS(ch)) return token("punc", next()); @@ -17743,12 +18902,18 @@ handle_regexp(); switch (S.token.type) { case "string": var dir = S.in_directives, stat = simple_statement(); // XXXv2: decide how to fix directives - if (dir && stat.body instanceof AST_String && !is("punc", ",")) - return new AST_Directive({ value: stat.body.value }); + if (dir && stat.body instanceof AST_String && !is("punc", ",")) { + return new AST_Directive({ + start : stat.body.start, + end : stat.body.end, + quote : stat.body.quote, + value : stat.body.value, + }); + } return stat; case "num": case "regexp": case "operator": case "atom": @@ -18130,11 +19295,16 @@ break; case "num": ret = new AST_Number({ start: tok, end: tok, value: tok.value }); break; case "string": - ret = new AST_String({ start: tok, end: tok, value: tok.value }); + ret = new AST_String({ + start : tok, + end : tok, + value : tok.value, + quote : tok.quote + }); break; case "regexp": ret = new AST_RegExp({ start: tok, end: tok, value: tok.value }); break; case "atom": @@ -18243,10 +19413,11 @@ } } expect(":"); a.push(new AST_ObjectKeyVal({ start : start, + quote : start.quote, key : name, value : expression(false), end : prev() })); } @@ -18748,27 +19919,40 @@ this.index = index; }; SymbolDef.prototype = { unmangleable: function(options) { - return (this.global && !(options && options.toplevel)) + if (!options) options = {}; + + return (this.global && !options.toplevel) || this.undeclared - || (!(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with)); + || (!options.eval && (this.scope.uses_eval || this.scope.uses_with)) + || (options.keep_fnames + && (this.orig[0] instanceof AST_SymbolLambda + || this.orig[0] instanceof AST_SymbolDefun)); }, mangle: function(options) { - if (!this.mangled_name && !this.unmangleable(options)) { + var cache = options.cache && options.cache.props; + if (this.global && cache && cache.has(this.name)) { + this.mangled_name = cache.get(this.name); + } + else if (!this.mangled_name && !this.unmangleable(options)) { var s = this.scope; if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda) s = s.parent_scope; this.mangled_name = s.next_mangled(options, this); + if (this.global && cache) { + cache.set(this.name, this.mangled_name); + } } } }; AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ options = defaults(options, { - screw_ie8: false + screw_ie8: false, + cache: null }); // pass 1: setup scope chaining and handle definitions var self = this; var scope = self.parent_scope = null; @@ -18869,10 +20053,14 @@ node.reference(); return true; } }); self.walk(tw); + + if (options.cache) { + this.cname = options.cache.cname; + } }); AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){ this.directives = []; // contains the directives defined in this scope, i.e. "use strict" this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) @@ -19013,15 +20201,16 @@ return this.definition().global; }); AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){ return defaults(options, { - except : [], - eval : false, - sort : false, - toplevel : false, - screw_ie8 : false + except : [], + eval : false, + sort : false, + toplevel : false, + screw_ie8 : false, + keep_fnames : false }); }); AST_Toplevel.DEFMETHOD("mangle_names", function(options){ options = this._default_mangler_options(options); @@ -19029,10 +20218,19 @@ // into the code generator will display the mangled name if it's // present (and for AST_SymbolRef-s it'll use the mangled name of // the AST_SymbolDeclaration that it points to). var lname = -1; var to_mangle = []; + + if (options.cache) { + this.globals.each(function(symbol){ + if (options.except.indexOf(symbol.name) < 0) { + to_mangle.push(symbol); + } + }); + } + var tw = new TreeWalker(function(node, descend){ if (node instanceof AST_LabeledStatement) { // lname is incremented when we get to the AST_Label var save_nesting = lname; descend(); @@ -19063,10 +20261,14 @@ return; } }); this.walk(tw); to_mangle.forEach(function(def){ def.mangle(options) }); + + if (options.cache) { + options.cache.cname = this.cname; + } }); AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){ options = this._default_mangler_options(options); var tw = new TreeWalker(function(node){ @@ -19162,11 +20364,13 @@ reset(); base54.get = function(){ return chars }; base54.freq = function(){ return frequency }; function base54(num) { var ret = "", base = 54; + num++; do { + num--; ret += String.fromCharCode(chars[num % base]); num = Math.floor(num / base); base = 64; } while (num > 0); return ret; @@ -19323,10 +20527,11 @@ semicolons : true, comments : false, preserve_line : false, screw_ie8 : false, preamble : null, + quote_style : 0 }, true); var indentation = 0; var current_col = 0; var current_line = 1; @@ -19344,13 +20549,13 @@ return "\\u" + code; } }); }; - function make_string(str) { + function make_string(str, quote) { var dq = 0, sq = 0; - str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){ + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0\ufeff]/g, function(s){ switch (s) { case "\\": return "\\\\"; case "\b": return "\\b"; case "\f": return "\\f"; case "\n": return "\\n"; @@ -19358,20 +20563,35 @@ case "\u2028": return "\\u2028"; case "\u2029": return "\\u2029"; case '"': ++dq; return '"'; case "'": ++sq; return "'"; case "\0": return "\\x00"; + case "\ufeff": return "\\ufeff"; } return s; }); + function quote_single() { + return "'" + str.replace(/\x27/g, "\\'") + "'"; + } + function quote_double() { + return '"' + str.replace(/\x22/g, '\\"') + '"'; + } if (options.ascii_only) str = to_ascii(str); - if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; - else return '"' + str.replace(/\x22/g, '\\"') + '"'; + switch (options.quote_style) { + case 1: + return quote_single(); + case 2: + return quote_double(); + case 3: + return quote == "'" ? quote_single() : quote_double(); + default: + return dq > sq ? quote_single() : quote_double(); + } }; - function encode_string(str) { - var ret = make_string(str); + function encode_string(str, quote) { + var ret = make_string(str, quote); if (options.inline_script) ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); return ret; }; @@ -19420,11 +20640,10 @@ } if (!options.beautify) might_need_space = false; } might_need_semicolon = false; - maybe_newline(); } if (!options.beautify && options.preserve_line && stack[stack.length - 1]) { var target_line = stack[stack.length - 1].start.line; while (current_line < target_line) { @@ -19481,11 +20700,11 @@ return ret; } : function(col, cont) { return cont() }; var newline = options.beautify ? function() { print("\n"); - } : noop; + } : maybe_newline; var semicolon = options.beautify ? function() { print(";"); } : function() { might_need_semicolon = true; @@ -19583,11 +20802,11 @@ last : function() { return last }, semicolon : semicolon, force_semicolon : force_semicolon, to_ascii : to_ascii, print_name : function(name) { print(make_name(name)) }, - print_string : function(str) { print(encode_string(str)) }, + print_string : function(str, quote) { print(encode_string(str, quote)) }, next_indent : next_indent, with_indent : with_indent, with_block : with_block, with_parens : with_parens, with_square : with_square, @@ -19672,10 +20891,19 @@ } else if (typeof c == "function") { comments = comments.filter(function(comment){ return c(self, comment); }); } + + // Keep single line comments after nlb, after nlb + if (!output.option("beautify") && comments.length > 0 && + /comment[134]/.test(comments[0].type) && + output.col() !== 0 && comments[0].nlb) + { + output.print("\n"); + } + comments.forEach(function(c){ if (/comment[134]/.test(c.type)) { output.print("//" + c.value + "\n"); output.indent(); } @@ -19809,16 +21037,10 @@ var p = output.parent(); if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this) return true; }); - PARENS(AST_NaN, function(output){ - var p = output.parent(); - if (p instanceof AST_PropAccess && p.expression === this) - return true; - }); - PARENS([ AST_Assign, AST_Conditional ], function (output){ var p = output.parent(); // !(a = false) → true if (p instanceof AST_Unary) return true; @@ -19837,11 +21059,11 @@ }); /* -----[ PRINTERS ]----- */ DEFPRINT(AST_Directive, function(self, output){ - output.print_string(self.value); + output.print_string(self.value, self.quote); output.semicolon(); }); DEFPRINT(AST_Debugger, function(self, output){ output.print("debugger"); output.semicolon(); @@ -20333,21 +21555,22 @@ }); else output.print("{}"); }); DEFPRINT(AST_ObjectKeyVal, function(self, output){ var key = self.key; + var quote = self.quote; if (output.option("quote_keys")) { output.print_string(key + ""); } else if ((typeof key == "number" || !output.option("beautify") && +key + "" == key) && parseFloat(key) >= 0) { output.print(make_num(key)); } else if (RESERVED_WORDS(key) ? output.option("screw_ie8") : is_identifier_string(key)) { output.print_name(key); } else { - output.print_string(key); + output.print_string(key, quote); } output.colon(); self.value.print(output); }); DEFPRINT(AST_ObjectSetter, function(self, output){ @@ -20369,23 +21592,23 @@ DEFPRINT(AST_Undefined, function(self, output){ output.print("void 0"); }); DEFPRINT(AST_Hole, noop); DEFPRINT(AST_Infinity, function(self, output){ - output.print("1/0"); + output.print("Infinity"); }); DEFPRINT(AST_NaN, function(self, output){ - output.print("0/0"); + output.print("NaN"); }); DEFPRINT(AST_This, function(self, output){ output.print("this"); }); DEFPRINT(AST_Constant, function(self, output){ output.print(self.getValue()); }); DEFPRINT(AST_String, function(self, output){ - output.print_string(self.getValue()); + output.print_string(self.getValue(), self.quote); }); DEFPRINT(AST_Number, function(self, output){ output.print(make_num(self.getValue())); }); @@ -20630,10 +21853,11 @@ booleans : !false_by_default, loops : !false_by_default, unused : !false_by_default, hoist_funs : !false_by_default, keep_fargs : false, + keep_fnames : false, hoist_vars : false, if_return : !false_by_default, join_vars : !false_by_default, cascade : !false_by_default, side_effects : !false_by_default, @@ -20730,14 +21954,14 @@ return make_node(val ? AST_True : AST_False, orig).optimize(compressor); case "undefined": return make_node(AST_Undefined, orig).optimize(compressor); default: if (val === null) { - return make_node(AST_Null, orig).optimize(compressor); + return make_node(AST_Null, orig, { value: null }).optimize(compressor); } if (val instanceof RegExp) { - return make_node(AST_RegExp, orig).optimize(compressor); + return make_node(AST_RegExp, orig, { value: val }).optimize(compressor); } throw new Error(string_template("Can't handle constant of type: {type}", { type: typeof val })); } @@ -20793,49 +22017,79 @@ } return statements; function process_for_angular(statements) { + function has_inject(comment) { + return /@ngInject/.test(comment.value); + } + function make_arguments_names_list(func) { + return func.argnames.map(function(sym){ + return make_node(AST_String, sym, { value: sym.name }); + }); + } + function make_array(orig, elements) { + return make_node(AST_Array, orig, { elements: elements }); + } function make_injector(func, name) { return make_node(AST_SimpleStatement, func, { body: make_node(AST_Assign, func, { operator: "=", left: make_node(AST_Dot, name, { expression: make_node(AST_SymbolRef, name, name), property: "$inject" }), - right: make_node(AST_Array, func, { - elements: func.argnames.map(function(sym){ - return make_node(AST_String, sym, { value: sym.name }); - }) - }) + right: make_array(func, make_arguments_names_list(func)) }) }); } + function check_expression(body) { + if (body && body.args) { + // if this is a function call check all of arguments passed + body.args.forEach(function(argument, index, array) { + var comments = argument.start.comments_before; + // if the argument is function preceded by @ngInject + if (argument instanceof AST_Lambda && comments.length && has_inject(comments[0])) { + // replace the function with an array of names of its parameters and function at the end + array[index] = make_array(argument, make_arguments_names_list(argument).concat(argument)); + } + }); + // if this is chained call check previous one recursively + if (body.expression && body.expression.expression) { + check_expression(body.expression.expression); + } + } + } return statements.reduce(function(a, stat){ a.push(stat); - var token = stat.start; - var comments = token.comments_before; - if (comments && comments.length > 0) { - var last = comments.pop(); - if (/@ngInject/.test(last.value)) { - // case 1: defun - if (stat instanceof AST_Defun) { - a.push(make_injector(stat, stat.name)); + + if (stat.body && stat.body.args) { + check_expression(stat.body); + } else { + var token = stat.start; + var comments = token.comments_before; + if (comments && comments.length > 0) { + var last = comments.pop(); + if (has_inject(last)) { + // case 1: defun + if (stat instanceof AST_Defun) { + a.push(make_injector(stat, stat.name)); + } + else if (stat instanceof AST_Definitions) { + stat.definitions.forEach(function(def) { + if (def.value && def.value instanceof AST_Lambda) { + a.push(make_injector(def.value, def.name)); + } + }); + } + else { + compressor.warn("Unknown statement marked with @ngInject [{file}:{line},{col}]", token); + } } - else if (stat instanceof AST_Definitions) { - stat.definitions.forEach(function(def){ - if (def.value && def.value instanceof AST_Lambda) { - a.push(make_injector(def.value, def.name)); - } - }); - } - else { - compressor.warn("Unknown statement marked with @ngInject [{file}:{line},{col}]", token); - } } } + return a; }, []); } function eliminate_spurious_blocks(statements) { @@ -21026,11 +22280,11 @@ body: seq })); seq = []; }; statements.forEach(function(stat){ - if (stat instanceof AST_SimpleStatement) seq.push(stat.body); + if (stat instanceof AST_SimpleStatement && seq.length < 2000) seq.push(stat.body); else push_seq(), ret.push(stat); }); push_seq(); ret = sequencesize_2(ret, compressor); CHANGED = ret.length != statements.length; @@ -21517,11 +22771,11 @@ return n > 0 && aborts(this.body[n - 1]); }; def(AST_BlockStatement, block_aborts); def(AST_SwitchBranch, block_aborts); def(AST_If, function(){ - return this.alternative && aborts(this.body) && aborts(this.alternative); + return this.alternative && aborts(this.body) && aborts(this.alternative) && this; }); })(function(node, func){ node.DEFMETHOD("aborts", func); }); @@ -21623,11 +22877,11 @@ } // pass 3: we should drop declarations not in_use var tt = new TreeTransformer( function before(node, descend, in_list) { if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) { - if (!compressor.option("keep_fargs")) { + if (compressor.option("unsafe") && !compressor.option("keep_fargs")) { for (var a = node.argnames, i = a.length; --i >= 0;) { var sym = a[i]; if (sym.unreferenced()) { a.pop(); compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", { @@ -21705,16 +22959,16 @@ } if (def.length == 0 && !side_effects) { return make_node(AST_EmptyStatement, node); } if (def.length == 0) { - return side_effects; + return in_list ? MAP.splice(side_effects.body) : side_effects; } node.definitions = def; if (side_effects) { side_effects.body.unshift(node); - node = side_effects; + return in_list ? MAP.splice(side_effects.body) : side_effects; } return node; } if (node instanceof AST_For) { descend(node, this); @@ -22234,11 +23488,11 @@ return self; }); OPT(AST_Function, function(self, compressor){ self = AST_Lambda.prototype.optimize.call(self, compressor); - if (compressor.option("unused")) { + if (compressor.option("unused") && !compressor.option("keep_fnames")) { if (self.name && self.name.unreferenced()) { self.name = null; } } return self; @@ -22290,10 +23544,15 @@ }), operator: "!" }).transform(compressor); break; case "Function": + // new Function() => function(){} + if (self.args.length == 0) return make_node(AST_Function, self, { + argnames: [], + body: [] + }); if (all(self.args, function(x){ return x instanceof AST_String })) { // quite a corner-case, but we can handle it: // https://github.com/mishoo/UglifyJS2/issues/203 // if the code argument is a constant, then we can minify it. try { @@ -22405,15 +23664,20 @@ && !AST_Block.prototype.has_side_effects.call(self.expression, compressor)) { return make_node(AST_Undefined, self).transform(compressor); } } if (compressor.option("drop_console")) { - if (self.expression instanceof AST_PropAccess && - self.expression.expression instanceof AST_SymbolRef && - self.expression.expression.name == "console" && - self.expression.expression.undeclared()) { - return make_node(AST_Undefined, self).transform(compressor); + if (self.expression instanceof AST_PropAccess) { + var name = self.expression.expression; + while (name.expression) { + name = name.expression; + } + if (name instanceof AST_SymbolRef + && name.name == "console" + && name.undeclared()) { + return make_node(AST_Undefined, self).transform(compressor); + } } } return self.evaluate(compressor)[0]; }); @@ -22469,11 +23733,11 @@ } } if (self.cdr instanceof AST_UnaryPrefix && self.cdr.operator == "void" && !self.cdr.expression.has_side_effects(compressor)) { - self.cdr.operator = self.car; + self.cdr.expression = self.car; return self.cdr; } if (self.cdr instanceof AST_Undefined) { return make_node(AST_UnaryPrefix, self, { operator : "void", @@ -22637,10 +23901,16 @@ case "&&": var ll = self.left.evaluate(compressor); var rr = self.right.evaluate(compressor); if ((ll.length > 1 && !ll[1]) || (rr.length > 1 && !rr[1])) { compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start); + if (self.left.has_side_effects(compressor)) { + return make_node(AST_Seq, self, { + car: self.left, + cdr: make_node(AST_False) + }).optimize(compressor); + } return make_node(AST_False, self); } if (ll.length > 1 && ll[1]) { return rr[0]; } @@ -22651,10 +23921,16 @@ case "||": var ll = self.left.evaluate(compressor); var rr = self.right.evaluate(compressor); if ((ll.length > 1 && ll[1]) || (rr.length > 1 && rr[1])) { compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start); + if (self.left.has_side_effects(compressor)) { + return make_node(AST_Seq, self, { + car: self.left, + cdr: make_node(AST_True) + }).optimize(compressor); + } return make_node(AST_True, self); } if (ll.length > 1 && !ll[1]) { return rr[0]; } @@ -22771,18 +24047,26 @@ } switch (self.name) { case "undefined": return make_node(AST_Undefined, self); case "NaN": - return make_node(AST_NaN, self); + return make_node(AST_NaN, self).transform(compressor); case "Infinity": - return make_node(AST_Infinity, self); + return make_node(AST_Infinity, self).transform(compressor); } } return self; }); + OPT(AST_Infinity, function (self, compressor) { + return make_node(AST_Binary, self, { + operator : '/', + left : make_node(AST_Number, self, {value: 1}), + right : make_node(AST_Number, self, {value: 0}) + }); + }); + OPT(AST_Undefined, function(self, compressor){ if (compressor.option("unsafe")) { var scope = compressor.find_parent(AST_Scope); var undef = scope.find_variable("undefined"); if (undef) { @@ -22842,10 +24126,11 @@ var alternative = self.alternative; if (consequent instanceof AST_Assign && alternative instanceof AST_Assign && consequent.operator == alternative.operator && consequent.left.equivalent_to(alternative.left) + && !consequent.left.has_side_effects(compressor) ) { /* * Stuff like this: * if (foo) exp = something; else exp = something_else; * ==> @@ -22862,10 +24147,11 @@ }); } if (consequent instanceof AST_Call && alternative.TYPE === consequent.TYPE && consequent.args.length == alternative.args.length + && !consequent.expression.has_side_effects(compressor) && consequent.expression.equivalent_to(alternative.expression)) { if (consequent.args.length == 0) { return make_node(AST_Seq, self, { car: self.condition, cdr: consequent @@ -22902,10 +24188,24 @@ } else { return make_node_from_constant(compressor, consequent.value, self); } } + // x=y?true:false --> x=!!y + if (consequent instanceof AST_True + && alternative instanceof AST_False) { + self.condition = self.condition.negate(compressor); + return make_node(AST_UnaryPrefix, self.condition, { + operator: "!", + expression: self.condition + }); + } + // x=y?false:true --> x=!y + if (consequent instanceof AST_False + && alternative instanceof AST_True) { + return self.condition.negate(compressor) + } return self; }); OPT(AST_Boolean, function(self, compressor){ if (compressor.option("booleans")) { @@ -22965,11 +24265,11 @@ } return self.evaluate(compressor)[0]; }); function literals_in_boolean_context(self, compressor) { - if (compressor.option("booleans") && compressor.in_boolean_context()) { + if (compressor.option("booleans") && compressor.in_boolean_context() && !self.has_side_effects(compressor)) { return make_node(AST_True, self); } return self; }; OPT(AST_Array, literals_in_boolean_context); @@ -23031,15 +24331,20 @@ orig : null, orig_line_diff : 0, dest_line_diff : 0, }); - var generator = new MOZ_SourceMap.SourceMapGenerator({ - file : options.file, - sourceRoot : options.root - }); var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig); + var generator; + if (orig_map) { + generator = MOZ_SourceMap.SourceMapGenerator.fromSourceMap(orig_map); + } else { + generator = new MOZ_SourceMap.SourceMapGenerator({ + file : options.file, + sourceRoot : options.root + }); + } function add(source, gen_line, gen_col, orig_line, orig_col, name) { if (orig_map) { var info = orig_map.originalPositionFor({ line: orig_line, column: orig_col @@ -23056,15 +24361,15 @@ generated : { line: gen_line + options.dest_line_diff, column: gen_col }, original : { line: orig_line + options.orig_line_diff, column: orig_col }, source : source, name : name }); - }; + } return { add : add, get : function() { return generator }, - toString : function() { return generator.toString() } + toString : function() { return JSON.stringify(generator.toJSON()); } }; }; /*********************************************************************** @@ -23436,30 +24741,34 @@ AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast); /* -----[ tools ]----- */ function my_start_token(moznode) { - var loc = moznode.loc; + var loc = moznode.loc, start = loc && loc.start; var range = moznode.range; return new AST_Token({ - 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 + file : loc && loc.source, + line : start && start.line, + col : start && start.column, + pos : range ? range[0] : moznode.start, + endline : start && start.line, + endcol : start && start.column, + endpos : range ? range[0] : moznode.start }); }; function my_end_token(moznode) { - var loc = moznode.loc; + var loc = moznode.loc, end = loc && loc.end; var range = moznode.range; return new AST_Token({ - 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 + file : loc && loc.source, + line : end && end.line, + col : end && end.column, + pos : range ? range[1] : moznode.end, + endline : end && end.line, + endcol : end && end.column, + endpos : range ? range[1] : moznode.end }); }; function map(moztype, mytype, propmap) { var moz_to_me = "function From_Moz_" + moztype + "(M){\n"; @@ -23531,27 +24840,20 @@ 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) { + function set_moz_loc(mynode, moznode, myparent) { var start = mynode.start; var end = mynode.end; - if (start.pos != null && end.pos != null) { - moznode.range = [start.pos, end.pos]; + if (start.pos != null && end.endpos != null) { + moznode.range = [start.pos, end.endpos]; } if (start.line) { moznode.loc = { - start: moz_sub_loc(start), - end: moz_sub_loc(end) + start: {line: start.line, column: start.col}, + end: end.endline ? {line: end.endline, column: end.endcol} : null }; if (start.file) { moznode.loc.source = start.file; } } @@ -23575,10 +24877,228 @@ }; }; })(); +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + <mihai.bazon@gmail.com> + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function find_builtins() { + var a = []; + [ Object, Array, Function, Number, + String, Boolean, Error, Math, + Date, RegExp + ].forEach(function(ctor){ + Object.getOwnPropertyNames(ctor).map(add); + if (ctor.prototype) { + Object.getOwnPropertyNames(ctor.prototype).map(add); + } + }); + function add(name) { + push_uniq(a, name); + } + return a; +} + +function mangle_properties(ast, options) { + options = defaults(options, { + reserved : null, + cache : null, + only_cache : false + }); + + var reserved = options.reserved; + if (reserved == null) + reserved = find_builtins(); + + var cache = options.cache; + if (cache == null) { + cache = { + cname: -1, + props: new Dictionary() + }; + } + + var names_to_mangle = []; + + // step 1: find candidates to mangle + ast.walk(new TreeWalker(function(node){ + if (node instanceof AST_ObjectKeyVal) { + add(node.key); + } + else if (node instanceof AST_ObjectProperty) { + // setter or getter, since KeyVal is handled above + add(node.key.name); + } + else if (node instanceof AST_Dot) { + if (this.parent() instanceof AST_Assign) { + add(node.property); + } + } + else if (node instanceof AST_Sub) { + if (this.parent() instanceof AST_Assign) { + addStrings(node.property); + } + } + })); + + // step 2: transform the tree, renaming properties + return ast.transform(new TreeTransformer(function(node){ + if (node instanceof AST_ObjectKeyVal) { + if (should_mangle(node.key)) { + node.key = mangle(node.key); + } + } + else if (node instanceof AST_ObjectProperty) { + // setter or getter + if (should_mangle(node.key.name)) { + node.key.name = mangle(node.key.name); + } + } + else if (node instanceof AST_Dot) { + if (should_mangle(node.property)) { + node.property = mangle(node.property); + } + } + else if (node instanceof AST_Sub) { + node.property = mangleStrings(node.property); + } + // else if (node instanceof AST_String) { + // if (should_mangle(node.value)) { + // AST_Node.warn( + // "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", { + // file : node.start.file, + // line : node.start.line, + // col : node.start.col, + // prop : node.value + // } + // ); + // } + // } + })); + + // only function declarations after this line + + function can_mangle(name) { + if (reserved.indexOf(name) >= 0) return false; + if (options.only_cache) { + return cache.props.has(name); + } + if (/^[0-9.]+$/.test(name)) return false; + return true; + } + + function should_mangle(name) { + if (reserved.indexOf(name) >= 0) return false; + return cache.props.has(name) + || names_to_mangle.indexOf(name) >= 0; + } + + function add(name) { + if (can_mangle(name)) + push_uniq(names_to_mangle, name); + } + + function mangle(name) { + var mangled = cache.props.get(name); + if (!mangled) { + do { + mangled = base54(++cache.cname); + } while (!can_mangle(mangled)); + cache.props.set(name, mangled); + } + return mangled; + } + + function addStrings(node) { + var out = {}; + try { + (function walk(node){ + node.walk(new TreeWalker(function(node){ + if (node instanceof AST_Seq) { + walk(node.cdr); + return true; + } + if (node instanceof AST_String) { + add(node.value); + return true; + } + if (node instanceof AST_Conditional) { + walk(node.consequent); + walk(node.alternative); + return true; + } + throw out; + })); + })(node); + } catch(ex) { + if (ex !== out) throw ex; + } + } + + function mangleStrings(node) { + return node.transform(new TreeTransformer(function(node){ + if (node instanceof AST_Seq) { + node.cdr = mangleStrings(node.cdr); + } + else if (node instanceof AST_String) { + if (should_mangle(node.value)) { + node.value = mangle(node.value); + } + } + else if (node instanceof AST_Conditional) { + node.consequent = mangleStrings(node.consequent); + node.alternative = mangleStrings(node.alternative); + } + return node; + })); + } + +} + AST_Node.warn_function = function(txt) { logger.error("uglifyjs2 WARN: " + txt); }; exports.minify = function(files, options, name) { options = defaults(options, { spidermonkey : false, outSourceMap : null, @@ -23622,12 +25142,12 @@ toplevel = toplevel.transform(sq); } // 3. mangle if (options.mangle) { - toplevel.figure_out_scope(); - toplevel.compute_char_frequency(); + toplevel.figure_out_scope(options.mangle); + toplevel.compute_char_frequency(options.mangle); toplevel.mangle_names(options.mangle); } // 4. output var inMap = options.inSourceMap; @@ -23658,13 +25178,18 @@ if(options.outSourceMap){ stream += "\n//# sourceMappingURL=" + options.outSourceMap; } + var source_map = output.source_map; + if (source_map) { + source_map = source_map + ""; + } + return { code : stream + "", - map : output.source_map + "" + map : source_map }; }; // exports.describe_ast = function() { // function doitem(ctor) { @@ -23713,11 +25238,10 @@ }; doitem(AST_Node); return out + ""; }; - }); /** * @license 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 @@ -24024,22 +25548,60 @@ * @param {String} fileName * @param {String} fileContents * @returns {Boolean} */ parse.definesRequire = function (fileName, fileContents) { - var found = false; + var foundDefine = false, + foundDefineAmd = false; traverse(esprima.parse(fileContents), function (node) { - if (parse.hasDefineAmd(node)) { - found = true; + // Look for a top level declaration of a define, like + // var requirejs, require, define, off Program body. + if (node.type === 'Program' && node.body && node.body.length) { + foundDefine = node.body.some(function(bodyNode) { + // var define + if (bodyNode.type === 'VariableDeclaration') { + var decls = bodyNode.declarations; + if (decls) { + var hasVarDefine = decls.some(function(declNode) { + return (declNode.type === 'VariableDeclarator' && + declNode.id && + declNode.id.type === 'Identifier' && + declNode.id.name === 'define'); + }); + if (hasVarDefine) { + return true; + } + } + } + // function define() {} + if (bodyNode.type === 'FunctionDeclaration' && + bodyNode.id && + bodyNode.id.type === 'Identifier' && + bodyNode.id.name === 'define') { + return true; + } + + + + + + + }); + } + + // Need define variable found first, before detecting define.amd. + if (foundDefine && parse.hasDefineAmd(node)) { + foundDefineAmd = true; + //Stop traversal return false; } }); - return found; + return foundDefine && foundDefineAmd; }; /** * Finds require("") calls inside a CommonJS anonymous module wrapped in a * define(function(require, exports, module){}) wrapper. These dependencies @@ -24540,13 +26102,21 @@ factory = deps; deps = null; } else if (deps.type === 'ObjectExpression') { //deps is object literal, null out deps = factory = null; - } else if (deps.type === 'Identifier' && args.length === 2) { - // define('id', factory) - deps = factory = null; + } else if (deps.type === 'Identifier') { + if (args.length === 2) { + //define('id', factory) + deps = factory = null; + } else if (args.length === 3 && isFnExpression(factory)) { + //define('id', depsIdentifier, factory) + //Since identifier, cannot know the deps, but do not + //error out, assume they are taken care of outside of + //static parsing. + deps = null; + } } } if (deps && deps.type === 'ArrayExpression') { deps = getValidDeps(deps); @@ -25194,11 +26764,11 @@ 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, + defineCheckRegExp: /typeof(\s+|\s*\(\s*)define(\s*\))?\s*===?\s*["']function["']\s*&&\s*define\s*\.\s*amd/g, defineStringCheckRegExp: /typeof\s+define\s*===?\s*["']function["']\s*&&\s*define\s*\[\s*["']amd["']\s*\]/g, defineTypeFirstCheckRegExp: /\s*["']function["']\s*==(=?)\s*typeof\s+define\s*&&\s*define\s*\.\s*amd/g, defineJQueryRegExp: /typeof\s+define\s*===?\s*["']function["']\s*&&\s*define\s*\.\s*amd\s*&&\s*define\s*\.\s*amd\s*\.\s*jQuery/g, 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/, @@ -25503,11 +27073,17 @@ JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.JSSourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]); } catch (e) { try { // Try for newer closure compiler that needs Java 7+ JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.SourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]); - } catch (e) {} + } catch (e) { + try { + // Try Nashorn style + var stringClass = Java.type("java.lang.String").class; + JSSourceFilefromCode = Java.type("com.google.javascript.jscomp.SourceFile").class.getMethod("fromCode", [stringClass, stringClass]); + } catch (e) {} + } } //Helper for closure compiler, because of weird Java-JavaScript interactions. function closurefromCode(filename, content) { return JSSourceFilefromCode.invoke(null, [filename, content]); @@ -26090,11 +27666,11 @@ lang.mixin(uconfig, config, true); uconfig.fromString = true; if (config.generateSourceMaps && (outFileName || config._buildSourceMap)) { - uconfig.outSourceMap = baseName; + uconfig.outSourceMap = baseName + '.map'; if (config._buildSourceMap) { existingMap = JSON.parse(config._buildSourceMap); uconfig.inSourceMap = existingMap; } else if (file.exists(existingMapPath)) { @@ -26108,26 +27684,20 @@ try { //var tempContents = fileContents.replace(/\/\/\# sourceMappingURL=.*$/, ''); result = uglify2.minify(fileContents, uconfig, baseName + '.src.js'); if (uconfig.outSourceMap && result.map) { resultMap = result.map; - if (existingMap) { - resultMap = JSON.parse(resultMap); - finalMap = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(resultMap)); - finalMap.applySourceMap(new SourceMapConsumer(existingMap)); - resultMap = finalMap.toString(); - } else if (!config._buildSourceMap) { + if (!existingMap && !config._buildSourceMap) { file.saveFile(outFileName + '.src.js', fileContents); } fileContents = result.code; if (config._buildSourceMap) { config._buildSourceMap = resultMap; } else { file.saveFile(outFileName + '.map', resultMap); - fileContents += "\n//# sourceMappingURL=" + baseName + ".map"; } } else { fileContents = result.code; } } catch (e) { @@ -27119,11 +28689,12 @@ //If buildPath and sourcePath are the same, throw since this //would result in modifying source. This condition can happen //with some more tricky paths: config and appDir/baseUrl //setting, which is a sign of incorrect config. - if (module._buildPath === module._sourcePath) { + if (module._buildPath === module._sourcePath && + !config.allowSourceOverwrites) { throw new Error('Module ID \'' + module.name + '\' has a source path that is same as output path: ' + module._sourcePath + '. Stopping, config is malformed.'); } @@ -28283,11 +29854,11 @@ //unresolved state since a setTimeout cannot be used to check for //timeout. var hasError = false; if (syncChecks[env.get()]) { try { - build.checkForErrors(context); + build.checkForErrors(context, layer); } catch (e) { hasError = true; deferred.reject(e); } } @@ -28303,26 +29874,26 @@ // If a sync env, then with the "two IDs to same anon module path" // issue, the require never completes, need to check for errors // here. if (syncChecks[env.get()]) { - build.checkForErrors(context); + build.checkForErrors(context, layer); } return deferred.promise.then(function () { //Reset config if (module.override && baseLoaderConfig) { require(lang.deeplikeCopy(baseLoaderConfig)); } - build.checkForErrors(context); + build.checkForErrors(context, layer); return layer; }); }; - build.checkForErrors = function (context) { + build.checkForErrors = function (context, layer) { //Check to see if it all loaded. If not, then throw, and give //a message on what is left. var id, prop, mod, idParts, pluginId, pluginResources, errMessage = '', failedPluginMap = {}, @@ -28370,12 +29941,13 @@ if (id.indexOf('_unnormalized') === -1 && mod && mod.enabled) { populateErrUrlMap(id, mod.map.url); } //Look for plugins that did not call load() - - if (idParts.length > 1) { + //But skip plugin IDs that were already inlined and called + //define() with a name. + if (!hasProp(layer.modulesWithNames, id) && idParts.length > 1) { if (falseProp(failedPluginMap, pluginId)) { failedPluginIds.push(pluginId); } pluginResources = failedPluginMap[pluginId]; if (!pluginResources) { @@ -28502,13 +30074,17 @@ } } if (config.generateSourceMaps) { sourceMapBase = config.dir || config.baseUrl; - fileForSourceMap = module._buildPath === 'FUNCTION' ? - (module.name || module.include[0] || 'FUNCTION') + '.build.js' : - module._buildPath.replace(sourceMapBase, ''); + if (module._buildPath === 'FUNCTION') { + fileForSourceMap = (module.name || module.include[0] || 'FUNCTION') + '.build.js'; + } else if (config.out) { + fileForSourceMap = module._buildPath.split('/').pop(); + } else { + fileForSourceMap = module._buildPath.replace(sourceMapBase, ''); + } sourceMapGenerator = new SourceMapGenerator.SourceMapGenerator({ file: fileForSourceMap }); } @@ -28619,11 +30195,11 @@ //concatenated with other content. singleContents += addSemiColon(currContents, config); }); } }).then(function () { - var refPath, pluginId, resourcePath, + var refPath, pluginId, resourcePath, shimDeps, sourceMapPath, sourceMapLineNumber, shortPath = path.replace(config.dir, ""); module.onCompleteData.included.push(shortPath); buildFileContents += shortPath + "\n"; @@ -28633,15 +30209,17 @@ //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) || (packageName && getOwn(config.shim, packageName))); if (shim) { + shimDeps = lang.isArray(shim) ? shim : shim.deps; if (config.wrapShim) { + singleContents = '(function(root) {\n' + namespaceWithDot + 'define("' + moduleName + '", ' + - (shim.deps && shim.deps.length ? - build.makeJsArrayString(shim.deps) + ', ' : '[], ') + + (shimDeps && shimDeps.length ? + build.makeJsArrayString(shimDeps) + ', ' : '[], ') + 'function() {\n' + ' return (function() {\n' + singleContents + // Start with a \n in case last line is a comment // in the singleContents, like a sourceURL comment. @@ -28650,12 +30228,12 @@ ' }).apply(root, arguments);\n' + '});\n' + '}(this));\n'; } else { singleContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", ' + - (shim.deps && shim.deps.length ? - build.makeJsArrayString(shim.deps) + ', ' : '') + + (shimDeps && shimDeps.length ? + build.makeJsArrayString(shimDeps) + ', ' : '') + (shim.exportsFn ? shim.exportsFn() : 'function(){}') + ');\n'; } } else { singleContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", function(){});\n'; @@ -28958,10 +30536,10 @@ } else if (commandOption === 'v') { console.log('r.js: ' + version + ', RequireJS: ' + this.requirejsVars.require.version + - ', UglifyJS2: 2.4.16, UglifyJS: 1.3.4'); + ', UglifyJS2: 2.4.23, UglifyJS: 1.3.4'); } else if (commandOption === 'convert') { loadLib(); this.requirejsVars.require(['env!env/args', 'commonJs', 'env!env/print'], function (args, commonJs, print) {