aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkzc <zaxxon2011@gmail.com>2016-04-12 09:19:38 -0400
committerRichard van Velzen <rvanvelzen@experty.com>2016-04-19 20:05:33 +0200
commitc55dd5ed74888d533cf8402c6ba3612916ba2885 (patch)
treedf2d89aae0733406252dc2778ac54378882e5484
parente4fa4b109a0db5691d91b3dfba0eac41ac21c0ef (diff)
downloadtracifyjs-c55dd5ed74888d533cf8402c6ba3612916ba2885.tar.gz
tracifyjs-c55dd5ed74888d533cf8402c6ba3612916ba2885.zip
Add `passes` compress option. Fix duplicate compress warnings.
-rw-r--r--README.md3
-rwxr-xr-xbin/uglifyjs2
-rw-r--r--lib/compress.js42
-rw-r--r--test/compress/issue-1034.js48
-rw-r--r--test/mocha/minify.js11
-rwxr-xr-xtest/run-tests.js2
-rw-r--r--tools/node.js2
7 files changed, 66 insertions, 44 deletions
diff --git a/README.md b/README.md
index 9118d663..041a0709 100644
--- a/README.md
+++ b/README.md
@@ -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