diff options
-rw-r--r-- | README.md | 3 | ||||
-rwxr-xr-x | bin/uglifyjs | 2 | ||||
-rw-r--r-- | lib/compress.js | 42 | ||||
-rw-r--r-- | test/compress/issue-1034.js | 48 | ||||
-rw-r--r-- | test/mocha/minify.js | 11 | ||||
-rwxr-xr-x | test/run-tests.js | 2 | ||||
-rw-r--r-- | tools/node.js | 2 |
7 files changed, 66 insertions, 44 deletions
@@ -356,6 +356,9 @@ to set `true`; it's effectively a shortcut for `foo=true`). compressor from mangling/discarding function names. Useful for code relying on `Function.prototype.name`. +- `passes` -- default `1`. Number of times to run compress. Use an + integer argument larger than 1 to further reduce code size in some cases. + Note: raising the number of passes will increase uglify compress time. ### The `unsafe` option diff --git a/bin/uglifyjs b/bin/uglifyjs index 90197cc4..45c92b50 100755 --- a/bin/uglifyjs +++ b/bin/uglifyjs @@ -423,7 +423,7 @@ async.eachLimit(files, 1, function (file, cb) { if (COMPRESS) { time_it("squeeze", function(){ - TOPLEVEL = TOPLEVEL.transform(compressor); + TOPLEVEL = compressor.compress(TOPLEVEL); }); } diff --git a/lib/compress.js b/lib/compress.js index 3e33c1b4..53618ae1 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -75,18 +75,36 @@ function Compressor(options, false_by_default) { screw_ie8 : false, drop_console : false, angular : false, - warnings : true, - global_defs : {} + global_defs : {}, + passes : 1, }, true); + this.warnings_produced = {}; }; Compressor.prototype = new TreeTransformer; merge(Compressor.prototype, { option: function(key) { return this.options[key] }, - warn: function() { - if (this.options.warnings) - AST_Node.warn.apply(AST_Node, arguments); + compress: function(node) { + var passes = +this.options.passes || 1; + for (var pass = 0; pass < passes && pass < 3; ++pass) { + if (pass > 0) node.clear_opt_flags(); + node = node.transform(this); + } + return node; + }, + warn: function(text, props) { + if (this.options.warnings) { + // only emit unique warnings + var message = string_template(text, props); + if (!(message in this.warnings_produced)) { + this.warnings_produced[message] = true; + AST_Node.warn.apply(AST_Node, arguments); + } + } + }, + clear_warnings: function() { + this.warnings_produced = {}; }, before: function(node, descend, in_list) { if (node._squeezed) return node; @@ -129,6 +147,15 @@ merge(Compressor.prototype, { return this.print_to_string() == node.print_to_string(); }); + AST_Node.DEFMETHOD("clear_opt_flags", function(){ + this.walk(new TreeWalker(function(node){ + if (!(node instanceof AST_Directive || node instanceof AST_Constant)) { + node._squeezed = false; + node._optimized = false; + } + })); + }); + function make_node(ctor, orig, props) { if (!props) props = {}; if (orig) { @@ -392,10 +419,7 @@ merge(Compressor.prototype, { var_defs_removed = true; } // Further optimize statement after substitution. - stat.walk(new TreeWalker(function(node){ - delete node._squeezed; - delete node._optimized; - })); + stat.clear_opt_flags(); compressor.warn("Replacing " + (is_constant ? "constant" : "variable") + " " + var_name + " [{file}:{line},{col}]", node.start); diff --git a/test/compress/issue-1034.js b/test/compress/issue-1034.js index 039af2ed..b91eaced 100644 --- a/test/compress/issue-1034.js +++ b/test/compress/issue-1034.js @@ -39,7 +39,7 @@ non_hoisted_function_after_return_2a: { hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, if_return: true, join_vars: true, cascade: true, side_effects: true, - collapse_vars: false + collapse_vars: false, passes: 2 } input: { function foo(x) { @@ -57,20 +57,11 @@ non_hoisted_function_after_return_2a: { } } expect: { - // NOTE: Output is correct, but suboptimal. Not a regression. Can be improved in future. - // This output is run through non_hoisted_function_after_return_2b with same flags. function foo(x) { - if (x) { - return bar(1); - } else { - return bar(2); - var b; - } - var c = bar(3); + return bar(x ? 1 : 2); function bar(x) { return 7 - x; } - return b || c; } } expect_warnings: [ @@ -79,7 +70,12 @@ non_hoisted_function_after_return_2a: { "WARN: Dropping unreachable code [test/compress/issue-1034.js:51,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]", "WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]", - "WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]" + "WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]", + "WARN: Dropping unreachable code [test/compress/issue-1034.js:53,12]", + "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]", + "WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]", + "WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]", + "WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]" ] } @@ -91,7 +87,6 @@ non_hoisted_function_after_return_2b: { collapse_vars: false } input: { - // Note: output of test non_hoisted_function_after_return_2a run through compress again function foo(x) { if (x) { return bar(1); @@ -107,31 +102,20 @@ non_hoisted_function_after_return_2b: { } } expect: { - // the output we would have liked to see from non_hoisted_function_after_return_2a function foo(x) { return bar(x ? 1 : 2); function bar(x) { return 7 - x; } } } expect_warnings: [ - // Notice that some warnings are repeated by multiple compress passes. - // Not a regression. There is room for improvement here. - // Warnings should be cached and only output if unique. - "WARN: Dropping unreachable code [test/compress/issue-1034.js:100,16]", - "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:100,16]", - "WARN: Dropping unreachable code [test/compress/issue-1034.js:100,16]", - "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:100,16]", - "WARN: Dropping unreachable code [test/compress/issue-1034.js:100,16]", - "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:100,16]", - "WARN: Dropping unreachable code [test/compress/issue-1034.js:100,16]", - "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:100,16]", - "WARN: Dropping unreachable code [test/compress/issue-1034.js:102,12]", - "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:102,12]", - "WARN: Dropping unreachable code [test/compress/issue-1034.js:106,12]", - "WARN: Dropping unreachable code [test/compress/issue-1034.js:100,16]", - "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:100,16]", - "WARN: Dropping unused variable b [test/compress/issue-1034.js:100,20]", - "WARN: Dropping unused variable c [test/compress/issue-1034.js:102,16]" + // duplicate warnings no longer emitted + "WARN: Dropping unreachable code [test/compress/issue-1034.js:95,16]", + "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:95,16]", + "WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]", + "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,12]", + "WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]", + "WARN: Dropping unused variable b [test/compress/issue-1034.js:95,20]", + "WARN: Dropping unused variable c [test/compress/issue-1034.js:97,16]" ] } diff --git a/test/mocha/minify.js b/test/mocha/minify.js new file mode 100644 index 00000000..bbf188c4 --- /dev/null +++ b/test/mocha/minify.js @@ -0,0 +1,11 @@ +var Uglify = require('../../'); +var assert = require("assert"); + +describe("minify", function() { + it("Should test basic sanity of minify with default options", function() { + var js = 'function foo(bar) { if (bar) return 3; else return 7; var u = not_called(); }'; + var result = Uglify.minify(js, {fromString: true}); + assert.strictEqual(result.code, 'function foo(n){return n?3:7}'); + }); +}); + diff --git a/test/run-tests.js b/test/run-tests.js index e9ce3bb2..763575aa 100755 --- a/test/run-tests.js +++ b/test/run-tests.js @@ -110,7 +110,7 @@ function run_compress_tests() { if (test.mangle_props) { input = U.mangle_properties(input, test.mangle_props); } - var output = input.transform(cmp); + var output = cmp.compress(input); output.figure_out_scope(); if (test.mangle) { output.compute_char_frequency(test.mangle); diff --git a/tools/node.js b/tools/node.js index fa8c19dc..ecbf8d3e 100644 --- a/tools/node.js +++ b/tools/node.js @@ -78,7 +78,7 @@ exports.minify = function(files, options) { UglifyJS.merge(compress, options.compress); toplevel.figure_out_scope(); var sq = UglifyJS.Compressor(compress); - toplevel = toplevel.transform(sq); + toplevel = sq.compress(toplevel); } // 3. mangle properties |