diff options
Diffstat (limited to 'tools')
49 files changed, 5212 insertions, 319 deletions
diff --git a/tools/eliminator/node_modules/uglify-js/lib/parse-js.js b/tools/eliminator/node_modules/uglify-js/lib/parse-js.js index a89163c6..c7c2025f 100644 --- a/tools/eliminator/node_modules/uglify-js/lib/parse-js.js +++ b/tools/eliminator/node_modules/uglify-js/lib/parse-js.js @@ -679,7 +679,28 @@ function NodeWithToken(str, start, end) { this.end = end; }; -NodeWithToken.prototype.toString = function() { return this.name; }; +NodeWithToken.prototype = { + get length() { + return this.name.length; + }, + set length(v) { + return this.name.length = v; + }, + replace: function() { return this.name.replace.apply(this.name, arguments); }, + concat: function() { return this.name.concat.apply(this.name, arguments); }, + indexOf: function() { return this.name.indexOf.apply(this.name, arguments); }, + lastIndexOf: function() { return this.name.lastIndexOf.apply(this.name, arguments); }, + lastIndexOf: function() { return this.name.lastIndexOf.apply(this.name, arguments); }, + match: function() { return this.name.match.apply(this.name, arguments); }, + search: function() { return this.name.search.apply(this.name, arguments); }, + slice: function() { return this.name.slice.apply(this.name, arguments); }, + split: function() { return this.name.split.apply(this.name, arguments); }, + substr: function() { return this.name.substr.apply(this.name, arguments); }, + substring: function() { return this.name.substring.apply(this.name, arguments); }, + toString: function() { return this.name; }, + toJSON: function() { return this.name; }, + valueOf: function() { return this.name; }, +}; function parse($TEXT, exigent_mode, embed_tokens) { @@ -765,15 +786,12 @@ function parse($TEXT, exigent_mode, embed_tokens) { return ex; }; - function add_tokens(str, start, end) { - return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end); - }; - function maybe_embed_tokens(parser) { if (embed_tokens) return function() { var start = S.token; var ast = parser.apply(this, arguments); - ast[0] = add_tokens(ast[0], start, prev()); + ast.start = start; + ast.end = prev; return ast; }; else return parser; @@ -1314,7 +1332,7 @@ function characters(str) { function member(name, array) { for (var i = array.length; --i >= 0;) - if (array[i] === name) + if (array[i] == name) return true; return false; }; diff --git a/tools/eliminator/node_modules/uglify-js/lib/process.js b/tools/eliminator/node_modules/uglify-js/lib/process.js index c3abb6f8..e1d692b2 100644 --- a/tools/eliminator/node_modules/uglify-js/lib/process.js +++ b/tools/eliminator/node_modules/uglify-js/lib/process.js @@ -64,6 +64,19 @@ var jsp = require("./parse-js"), PRECEDENCE = jsp.PRECEDENCE, OPERATORS = jsp.OPERATORS; +function NodeWithLine(str, line) { + this.str = str; + this.line = line; +} + +NodeWithLine.prototype = new String(); +NodeWithLine.prototype.toString = function() { return this.str; } +NodeWithLine.prototype.valueOf = function() { return this.str; } +NodeWithLine.prototype.lineComment = function() { return " //@line " + this.line; } + +// XXX ugly hack +String.prototype.lineComment = function() { return ""; } + /* -----[ helper for AST traversal ]----- */ function ast_walker() { @@ -1363,6 +1376,7 @@ var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for function gen_code(ast, options) { options = defaults(options, { + debug: false, indent_start : 0, indent_level : 4, quote_keys : false, @@ -1422,7 +1436,19 @@ function gen_code(ast, options) { }; function add_commas(a) { - return a.join("," + space); + var str = a.join("," + space); + if (options.debug) { + // if a line contains more than one comma-separated segment, assign it the + // original line number of the first NodeWithLine segment + for (var i = 0, l = a.length; i < l; i ++) { + var v = a[i]; + if (v instanceof NodeWithLine) { + v.str = str; + return v + } + } + } + return str; }; function parenthesize(expr) { @@ -1484,7 +1510,10 @@ function gen_code(ast, options) { a.push(m[2] + "e-" + (m[1].length + m[2].length), str.substr(str.indexOf("."))); } - return best_of(a); + var best = best_of(a); + if (options.debug && this.start) + return new NodeWithLine(best, this.start.line); + return best; }; var w = ast_walker(); @@ -1512,7 +1541,15 @@ function gen_code(ast, options) { }, "block": make_block, "var": function(defs) { - return "var " + add_commas(MAP(defs, make_1vardef)) + ";"; + var s = "var " + add_commas(MAP(defs, make_1vardef)) + ";"; + if (options.debug) { + // hack: we don't support mapping one optimized line to more than one + // generated line, so in case of multiple comma-separated var definitions, + // just take the first + if (defs[0][1] && defs[0][1].start) + return s + (new NodeWithLine(s, defs[0][1].start.line)).lineComment(); + } + return s; }, "const": function(defs) { return "const " + add_commas(MAP(defs, make_1vardef)) + ";"; @@ -1567,7 +1604,10 @@ function gen_code(ast, options) { "assign": function(op, lvalue, rvalue) { if (op && op !== true) op += "="; else op = "="; - return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]); + var s = add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]); + if (options.debug && this.start) + return new NodeWithLine(s, this.start.line); + return s; }, "dot": function(expr) { var out = make(expr), i = 1; @@ -1584,9 +1624,12 @@ function gen_code(ast, options) { var f = make(func); if (needs_parens(func)) f = "(" + f + ")"; - return f + "(" + add_commas(MAP(args, function(expr){ + var str = f + "(" + add_commas(MAP(args, function(expr){ return parenthesize(expr, "seq"); })) + ")"; + if (options.debug && this.start) + return new NodeWithLine(str, this.start.line) + return str; }, "function": make_function, "defun": make_function, @@ -1621,8 +1664,9 @@ function gen_code(ast, options) { }, "return": function(expr) { var out = [ "return" ]; - if (expr != null) out.push(make(expr)); - return add_spaces(out) + ";"; + var str = make(expr); + if (expr != null) out.push(str); + return add_spaces(out) + ";" + (str ? str.lineComment() : ''); }, "binary": function(operator, lvalue, rvalue) { var left = make(lvalue), right = make(rvalue); @@ -1642,7 +1686,16 @@ function gen_code(ast, options) { && rvalue[0] == "regexp" && /^script/i.test(rvalue[1])) { right = " " + right; } - return add_spaces([ left, operator, right ]); + var str = add_spaces([ left, operator, right ]); + if (options.debug) { + if (this.start) + return new NodeWithLine(str, this.start.line); + else if (lvalue.start) + return new NodeWithLine(str, lvalue.start.line); + else if (rvalue.start) + return new NodeWithLine(str, rvalue.start.line); + } + return str; }, "unary-prefix": function(operator, expr) { var val = make(expr); @@ -1698,7 +1751,8 @@ function gen_code(ast, options) { })), "]" ]); }, "stat": function(stmt) { - return make(stmt).replace(/;*\s*$/, ";"); + var str = make(stmt); + return str.replace(/;*\s*$/, ";") + str.lineComment(); }, "seq": function() { return add_commas(MAP(slice(arguments), make)); diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 7561abc8..3cd1b229 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -11,6 +11,7 @@ // *** Environment setup code *** var arguments_ = []; +var debug = false; var ENVIRONMENT_IS_NODE = typeof process === 'object'; var ENVIRONMENT_IS_WEB = typeof window === 'object'; @@ -102,7 +103,7 @@ function globalEval(x) { eval.call(null, x); } -if (typeof load == 'undefined' && typeof read != 'undefined') { +if (typeof load === 'undefined' && typeof read != 'undefined') { this['load'] = function(f) { globalEval(read(f)); }; @@ -146,11 +147,12 @@ var generatedFunctions = false; // whether we have received only generated funct var extraInfo = null; function srcToAst(src) { - return uglify.parser.parse(src); + return uglify.parser.parse(src, false, debug); } function astToSrc(ast, minifyWhitespace) { return uglify.uglify.gen_code(ast, { + debug: debug, ascii_only: true, beautify: !minifyWhitespace, indent_level: 1 @@ -162,10 +164,10 @@ function astToSrc(ast, minifyWhitespace) { function traverseChildren(node, traverse, pre, post, stack) { for (var i = 0; i < node.length; i++) { var subnode = node[i]; - if (typeof subnode == 'object' && subnode && subnode.length) { + if (Array.isArray(subnode)) { var subresult = traverse(subnode, pre, post, stack); - if (subresult == true) return true; - if (subresult !== null && typeof subresult == 'object') node[i] = subresult; + if (subresult === true) return true; + if (subresult !== null && typeof subresult === 'object') node[i] = subresult; } } } @@ -186,16 +188,16 @@ function traverseChildren(node, traverse, pre, post, stack) { // was stopped, true. Otherwise undefined. function traverse(node, pre, post, stack) { var type = node[0], result, len; - var relevant = typeof type == 'string'; + var relevant = typeof type === 'string'; if (relevant) { if (stack) len = stack.length; var result = pre(node, type, stack); - if (result == true) return true; - if (result !== null && typeof result == 'object') node = result; // Continue processing on this node - if (stack && len == stack.length) stack.push(0); + if (result === true) return true; + if (result && result !== null) node = result; // Continue processing on this node + if (stack && len === stack.length) stack.push(0); } if (result !== null) { - if (traverseChildren(node, traverse, pre, post, stack) == true) return true; + if (traverseChildren(node, traverse, pre, post, stack) === true) return true; } if (relevant) { if (post) { @@ -211,7 +213,7 @@ function traverse(node, pre, post, stack) { function traverseGenerated(ast, pre, post, stack) { assert(generatedFunctions); traverse(ast, function(node) { - if (node[0] == 'defun') { + if (node[0] === 'defun') { traverse(node, pre, post, stack); return null; } @@ -220,13 +222,13 @@ function traverseGenerated(ast, pre, post, stack) { function traverseGeneratedFunctions(ast, callback) { assert(generatedFunctions); - if (ast[0] == 'toplevel') { + if (ast[0] === 'toplevel') { var stats = ast[1]; for (var i = 0; i < stats.length; i++) { var curr = stats[i]; - if (curr[0] == 'defun') callback(curr); + if (curr[0] === 'defun') callback(curr); } - } else if (ast[0] == 'defun') { + } else if (ast[0] === 'defun') { callback(ast); } } @@ -236,7 +238,7 @@ function traverseWithVariables(ast, callback) { traverse(ast, function(node, type, stack) { if (type in FUNCTION) { stack.push({ type: 'function', vars: node[2] }); - } else if (type == 'var') { + } else if (type === 'var') { // Find our function, add our vars var func = stack[stack.length-1]; if (func) { @@ -244,12 +246,12 @@ function traverseWithVariables(ast, callback) { } } }, function(node, type, stack) { - if (type == 'toplevel' || type in FUNCTION) { + if (type === 'toplevel' || type in FUNCTION) { // We know all of the variables that are seen here, proceed to do relevant replacements var allVars = stack.map(function(item) { return item ? item.vars : [] }).reduce(concatenator, []); // FIXME dictionary for speed? traverse(node, function(node2, type2, stack2) { // Be careful not to look into our inner functions. They have already been processed. - if (sum(stack2) > 1 || (type == 'toplevel' && sum(stack2) == 1)) return; + if (sum(stack2) > 1 || (type === 'toplevel' && sum(stack2) === 1)) return; if (type2 in FUNCTION) stack2.push(1); return callback(node2, type2, allVars); }, null, []); @@ -262,7 +264,7 @@ function emptyNode() { // XXX do we need to create new nodes here? can't we reus } function isEmptyNode(node) { - return node.length == 2 && node[0] == 'toplevel' && node[1].length == 0; + return node.length === 2 && node[0] === 'toplevel' && node[1].length === 0; } // Passes @@ -284,7 +286,7 @@ function unGlobalize(ast) { throw 'this is deprecated!'; // and does not work with parallel compilation - assert(ast[0] == 'toplevel'); + assert(ast[0] === 'toplevel'); var values = {}; // Find global renamings of the relevant values ast[1].forEach(function(node, i) { @@ -305,7 +307,7 @@ function unGlobalize(ast) { ast[1][i][1][j] = emptyNode(); var assigned = false; traverseWithVariables(ast, function(node, type, allVars) { - if (type == 'assign' && node[2][0] == 'name' && node[2][1] == ident) assigned = true; + if (type === 'assign' && node[2][0] === 'name' && node[2][1] === ident) assigned = true; }); ast[1][i][1][j] = [ident, value]; if (!assigned) { @@ -315,12 +317,12 @@ function unGlobalize(ast) { return true; }); - if (node[1].length == 0) { + if (node[1].length === 0) { ast[1][i] = emptyNode(); } }); traverseWithVariables(ast, function(node, type, allVars) { - if (type == 'name') { + if (type === 'name') { var ident = node[1]; if (ident in values && allVars.indexOf(ident) < 0) { return copy(values[ident]); @@ -343,9 +345,9 @@ function unGlobalize(ast) { // is now explicit. function removeAssignsToUndefined(ast) { traverse(ast, function(node, type) { - if (type == 'assign' && jsonCompare(node[3], ['unary-prefix', 'void', ['num', 0]])) { + if (type === 'assign' && jsonCompare(node[3], ['unary-prefix', 'void', ['num', 0]])) { return emptyNode(); - } else if (type == 'var') { + } else if (type === 'var') { node[1] = node[1].map(function(varItem, j) { var ident = varItem[0]; var value = varItem[1]; @@ -359,10 +361,10 @@ function removeAssignsToUndefined(ast) { while (modified) { modified = false; traverse(ast, function(node, type) { - if (type == 'assign' && jsonCompare(node[3], emptyNode())) { + if (type === 'assign' && jsonCompare(node[3], emptyNode())) { modified = true; return emptyNode(); - } else if (type == 'var') { + } else if (type === 'var') { node[1] = node[1].map(function(varItem, j) { var ident = varItem[0]; var value = varItem[1]; @@ -380,19 +382,19 @@ function removeAssignsToUndefined(ast) { // are actually necessary. It's easy to clean those up now. function removeUnneededLabelSettings(ast) { traverse(ast, function(node, type) { - if (type == 'defun') { // all of our compiled code is in defun nodes + if (type === 'defun') { // all of our compiled code is in defun nodes // Find all checks var checked = {}; traverse(node, function(node, type) { - if (type == 'binary' && node[1] == '==' && node[2][0] == 'name' && node[2][1] == 'label') { - assert(node[3][0] == 'num'); + if (type === 'binary' && node[1] === '==' && node[2][0] === 'name' && node[2][1] === 'label') { + assert(node[3][0] === 'num'); checked[node[3][1]] = 1; } }); // Remove unneeded sets traverse(node, function(node, type) { - if (type == 'assign' && node[2][0] == 'name' && node[2][1] == 'label') { - assert(node[3][0] == 'num'); + if (type === 'assign' && node[2][0] === 'name' && node[2][1] === 'label') { + assert(node[3][0] === 'num'); if (!(node[3][1] in checked)) return emptyNode(); } }); @@ -408,13 +410,13 @@ function simplifyExpressionsPre(ast) { // Look for (x&A)<<B>>B and replace it with X&A if possible. function simplifySignExtends(ast) { traverse(ast, function(node, type) { - if (type == 'binary' && node[1] == '>>' && node[3][0] == 'num' && - node[2][0] == 'binary' && node[2][1] == '<<' && node[2][3][0] == 'num' && node[3][1] == node[2][3][1]) { + if (type === 'binary' && node[1] === '>>' && node[3][0] === 'num' && + node[2][0] === 'binary' && node[2][1] === '<<' && node[2][3][0] === 'num' && node[3][1] === node[2][3][1]) { var innerNode = node[2][2]; var shifts = node[3][1]; - if (innerNode[0] == 'binary' && innerNode[1] == '&' && innerNode[3][0] == 'num') { + if (innerNode[0] === 'binary' && innerNode[1] === '&' && innerNode[3][0] === 'num') { var mask = innerNode[3][1]; - if (mask << shifts >> shifts == mask) { + if (mask << shifts >> shifts === mask) { return innerNode; } } @@ -444,9 +446,10 @@ function simplifyExpressionsPre(ast) { while (rerun) { rerun = false; traverse(ast, function process(node, type, stack) { - if (type == 'binary' && node[1] == '|') { - if (node[2][0] == 'num' && node[3][0] == 'num') { - return ['num', node[2][1] | node[3][1]]; + if (type === 'binary' && node[1] === '|') { + if (node[2][0] === 'num' && node[3][0] === 'num') { + node[2][1] |= node[3][1]; + return node[2]; } var go = false; if (jsonCompare(node[2], ZERO)) { @@ -466,9 +469,9 @@ function simplifyExpressionsPre(ast) { for (var i = stack.length-1; i >= 0; i--) { if (stack[i] >= 1) { if (asm) { - if (stack[stack.length-1] < 2 && node[2][0] == 'call') break; // we can only remove multiple |0s on these + if (stack[stack.length-1] < 2 && node[2][0] === 'call') break; // we can only remove multiple |0s on these if (stack[stack.length-1] < 1 && (node[2][0] in COERCION_REQUIRING_OPS || - (node[2][0] == 'binary' && node[2][1] in COERCION_REQUIRING_BINARIES))) break; // we can remove |0 or >>2 + (node[2][0] === 'binary' && node[2][1] in COERCION_REQUIRING_BINARIES))) break; // we can remove |0 or >>2 } // we will replace ourselves with the non-zero side. Recursively process that node. var result = jsonCompare(node[2], ZERO) ? node[3] : node[2], other; @@ -479,15 +482,15 @@ function simplifyExpressionsPre(ast) { } rerun = true; return process(result, result[0], stack); - } else if (stack[i] == -1) { + } else if (stack[i] === -1) { break; // Too bad, we can't } } stack.push(2); // From here on up, no need for this kind of correction, it's done at the top // (Add this at the end, so it is only added if we did not remove it) - } else if (type == 'binary' && node[1] in USEFUL_BINARY_OPS) { + } else if (type === 'binary' && node[1] in USEFUL_BINARY_OPS) { stack.push(1); - } else if ((type == 'binary' && node[1] in SAFE_BINARY_OPS) || type == 'num' || type == 'name') { + } else if ((type === 'binary' && node[1] in SAFE_BINARY_OPS) || type === 'num' || type === 'name') { stack.push(0); // This node is safe in that it does not interfere with this optimization } else { stack.push(-1); // This node is dangerous! Give up if you see this before you see '1' @@ -503,7 +506,7 @@ function simplifyExpressionsPre(ast) { var heapBits, heapUnsigned; function parseHeap(name) { if (name.substr(0, 4) != 'HEAP') return false; - heapUnsigned = name[4] == 'U'; + heapUnsigned = name[4] === 'U'; heapBits = parseInt(name.substr(heapUnsigned ? 5 : 4)); return true; } @@ -511,21 +514,21 @@ function simplifyExpressionsPre(ast) { var hasTempDoublePtr = false, rerunOrZeroPass = false; traverse(ast, function(node, type) { - if (type == 'name') { - if (node[1] == 'tempDoublePtr') hasTempDoublePtr = true; - } else if (type == 'binary' && node[1] == '&' && node[3][0] == 'num') { - if (node[2][0] == 'num') return ['num', node[2][1] & node[3][1]]; + if (type === 'name') { + if (node[1] === 'tempDoublePtr') hasTempDoublePtr = true; + } else if (type === 'binary' && node[1] === '&' && node[3][0] === 'num') { + if (node[2][0] === 'num') return ['num', node[2][1] & node[3][1]]; var input = node[2]; var amount = node[3][1]; - if (input[0] == 'binary' && input[1] == '&' && input[3][0] == 'num') { + if (input[0] === 'binary' && input[1] === '&' && input[3][0] === 'num') { // Collapse X & 255 & 1 node[3][1] = amount & input[3][1]; node[2] = input[2]; - } else if (input[0] == 'sub' && input[1][0] == 'name') { + } else if (input[0] === 'sub' && input[1][0] === 'name') { // HEAP8[..] & 255 => HEAPU8[..] var name = input[1][1]; if (parseHeap(name)) { - if (amount == Math.pow(2, heapBits)-1) { + if (amount === Math.pow(2, heapBits)-1) { if (!heapUnsigned) { input[1][1] = 'HEAPU' + heapBits; // make unsigned } @@ -539,14 +542,14 @@ function simplifyExpressionsPre(ast) { } } } - } else if (type == 'binary' && node[1] == '>>' && node[3][0] == 'num' && - node[2][0] == 'binary' && node[2][1] == '<<' && node[2][3][0] == 'num' && - node[2][2][0] == 'sub' && node[2][ |