From 9a6faf365bdd481be733bafb8c580bc76f4b353e Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Mon, 2 Dec 2019 06:43:54 +0800 Subject: [PATCH] fix corner cases in `keep_fargs` & `unused` (#3618) --- lib/compress.js | 16 +- test/compress/collapse_vars.js | 43 +++--- test/compress/drop-unused.js | 12 +- test/compress/evaluate.js | 4 +- test/compress/functions.js | 2 +- test/compress/keep_fargs.js | 270 +++++++++++++++++++++++++++++++++ test/compress/reduce_vars.js | 12 +- 7 files changed, 320 insertions(+), 39 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 09019a7419..284b79adfc 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -5173,12 +5173,14 @@ merge(Compressor.prototype, { && !fn.uses_arguments && !fn.pinned()) { var pos = 0, last = 0; + var drop_fargs = exp === fn && compressor.drop_fargs(fn, self) + && (!fn.name || !fn.name.definition().recursive_refs); var side_effects = []; for (var i = 0; i < self.args.length; i++) { var trim = i >= fn.argnames.length; if (trim || fn.argnames[i].__unused) { var node = self.args[i].drop_side_effect_free(compressor); - if (exp === fn) { + if (drop_fargs) { fn.argnames.splice(i, 1); self.args.splice(i, 1); if (node) side_effects.push(node); @@ -5207,8 +5209,17 @@ merge(Compressor.prototype, { } last = pos; } + if (drop_fargs) for (; i < fn.argnames.length; i++) { + if (fn.argnames[i].__unused) fn.argnames.splice(i--, 1); + } self.args.length = last; - if (side_effects.length) self.args.push(make_sequence(self, side_effects)); + if (side_effects.length) { + var arg = make_sequence(self, side_effects); + self.args.push(self.args.length < fn.argnames.length ? make_node(AST_UnaryPrefix, self, { + operator: "void", + expression: arg + }) : arg); + } } if (compressor.option("unsafe")) { if (is_undeclared_ref(exp)) switch (exp.name) { @@ -6568,6 +6579,7 @@ merge(Compressor.prototype, { name.scope = value; value.name = name; lambda_def = value.def_function(name); + lambda_def.recursive_refs = def.recursive_refs; } value.walk(new TreeWalker(function(node) { if (!(node instanceof AST_SymbolRef)) return; diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index eef6377991..58325be1db 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -1051,7 +1051,6 @@ collapse_vars_repeated: { var a = "GOOD" + x, e = "BAD", k = "!", e = a; console.log(e + k); })("!"), - (function(x) { var a = "GOOD" + x, e = "BAD" + x, k = "!", e = a; console.log(e + k); @@ -1064,10 +1063,10 @@ collapse_vars_repeated: { function f2(x) { return x; } - (function() { + (function(x) { console.log("GOOD!!"); })(), - (function() { + (function(x) { console.log("GOOD!!"); })(); } @@ -2425,7 +2424,7 @@ issue_1858: { }(1)); } expect: { - console.log(function() { + console.log(function(x) { var a = {}, b = a.b = 1; return a.b + b; }()); @@ -2569,12 +2568,12 @@ chained_3: { }(1, 2)); } expect: { - console.log(function(b) { + console.log(function(a, b) { var c = 1; c = b; b++; return c; - }(2)); + }(0, 2)); } expect_stdout: "2" } @@ -2845,7 +2844,7 @@ issue_2187_2: { } expect: { var b = 1; - console.log(function() { + console.log(function(a) { return b-- && ++b; }()); } @@ -2924,7 +2923,7 @@ issue_2203_2: { console.log({ a: "FAIL", b: function() { - return function() { + return function(c) { return (String, (Object, function() { return this; }())).a; @@ -3081,7 +3080,7 @@ issue_2319_1: { }())); } expect: { - console.log(function() { + console.log(function(a) { return !function() { return this; }(); @@ -3129,7 +3128,7 @@ issue_2319_3: { } expect: { "use strict"; - console.log(function() { + console.log(function(a) { return !function() { return this; }(); @@ -3594,7 +3593,7 @@ issue_2425_2: { } expect: { var a = 8; - (function(b) { + (function(b, c) { b.toString(); })(--a, a |= 10); console.log(a); @@ -3616,7 +3615,7 @@ issue_2425_3: { } expect: { var a = 8; - (function() { + (function(b, b) { (a |= 10).toString(); })(--a); console.log(a); @@ -4160,7 +4159,7 @@ issue_2436_13: { var a = "PASS"; (function() { (function(b) { - (function() { + (function(b) { a && (a.null = "FAIL"); })(); })(); @@ -4264,11 +4263,11 @@ issue_2506: { expect: { var c = 0; function f0(bar) { - (function() { - (function() { + (function(Infinity_2) { + (function(NaN) { if (false <= 0/0 & this >> 1 >= 0) c++; - })(c++); + })(0, c++); })(); } f0(false); @@ -4566,20 +4565,20 @@ replace_all_var_scope: { var a = 100, b = 10; (function(r, a) { switch (~a) { - case (b += a): - case a++: + case (b += a): + case a++: } })(--b, a); console.log(a, b); } expect: { var a = 100, b = 10; - (function(c) { + (function(c, o) { switch (~a) { - case (b += a): - case c++: + case (b += a): + case o++: } - })((--b, a)); + })(--b, a); console.log(a, b); } expect_stdout: "100 109" diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js index bc18db9add..15420d8ab6 100644 --- a/test/compress/drop-unused.js +++ b/test/compress/drop-unused.js @@ -815,9 +815,9 @@ issue_1583: { } expect: { function m(t) { - (function() { + (function(e) { (function() { - return (function() { + return (function(a) { return function(a) {}; })(); })(); @@ -1329,7 +1329,7 @@ issue_2226_2: { }(1, 2)); } expect: { - console.log(function(a) { + console.log(function(a, b) { return a += 2; }(1)); } @@ -1349,7 +1349,7 @@ issue_2226_3: { }(1, 2)); } expect: { - console.log(function(a) { + console.log(function(a, b) { return a += 2; }(1)); } @@ -1702,11 +1702,11 @@ chained_3: { }(1, 2)); } expect: { - console.log(function(b) { + console.log(function(a, b) { var c = b; b++; return c; - }(2)); + }(0, 2)); } expect_stdout: "2" } diff --git a/test/compress/evaluate.js b/test/compress/evaluate.js index fadf717e04..09fdfb2ad3 100644 --- a/test/compress/evaluate.js +++ b/test/compress/evaluate.js @@ -1674,7 +1674,7 @@ if_increment: { }(0)); } expect: { - console.log(function() { + console.log(function(a) { if (console) return 1; }()); @@ -1696,7 +1696,7 @@ try_increment: { }(0)); } expect: { - console.log(function() { + console.log(function(a) { try { return 1; } catch (e) {} diff --git a/test/compress/functions.js b/test/compress/functions.js index 1473f74c45..4fea42dc45 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -1279,7 +1279,7 @@ issue_2630_3: { expect: { var x = 2, a = 1; (function() { - (function f1() { + (function f1(a) { f2(); --x >= 0 && f1({}); })(a++); diff --git a/test/compress/keep_fargs.js b/test/compress/keep_fargs.js index 440abbd919..29308ff3b6 100644 --- a/test/compress/keep_fargs.js +++ b/test/compress/keep_fargs.js @@ -1155,3 +1155,273 @@ issue_3423_2: { } expect_stdout: "1" } + +collapse_vars_repeated: { + options = { + booleans: true, + collapse_vars: true, + comparisons: true, + conditionals: true, + dead_code: true, + evaluate: true, + hoist_funs: true, + if_return: true, + join_vars: true, + keep_fargs: "strict", + loops: true, + properties: true, + reduce_funcs: true, + reduce_vars: true, + sequences: true, + side_effects: true, + unused: true, + } + input: { + function f1() { + var dummy = 3, a = 5, unused = 2, a = 1, a = 3; + return -a; + } + function f2(x) { + var a = 3, a = x; + return a; + } + (function(x) { + var a = "GOOD" + x, e = "BAD", k = "!", e = a; + console.log(e + k); + })("!"), + (function(x) { + var a = "GOOD" + x, e = "BAD" + x, k = "!", e = a; + console.log(e + k); + })("!"); + } + expect: { + function f1() { + return -3; + } + function f2(x) { + return x; + } + (function() { + console.log("GOOD!!"); + })(), + (function() { + console.log("GOOD!!"); + })(); + } + expect_stdout: true +} + +chained_3: { + options = { + collapse_vars: true, + keep_fargs: "strict", + unused: true, + } + input: { + console.log(function(a, b) { + var c = a, c = b; + b++; + return c; + }(1, 2)); + } + expect: { + console.log(function(b) { + var c = 1; + c = b; + b++; + return c; + }(2)); + } + expect_stdout: "2" +} + +replace_all_var_scope: { + rename = true + options = { + collapse_vars: true, + keep_fargs: "strict", + unused: true, + } + mangle = {} + input: { + var a = 100, b = 10; + (function(r, a) { + switch (~a) { + case (b += a): + case a++: + } + })(--b, a); + console.log(a, b); + } + expect: { + var a = 100, b = 10; + (function(c) { + switch (~a) { + case (b += a): + case c++: + } + })((--b, a)); + console.log(a, b); + } + expect_stdout: "100 109" +} + +issue_1583: { + options = { + keep_fargs: "strict", + passes: 2, + reduce_funcs: true, + reduce_vars: true, + unused: true, + } + input: { + function m(t) { + (function(e) { + t = e(); + })(function() { + return (function(a) { + return a; + })(function(a) {}); + }); + } + } + expect: { + function m(t) { + (function() { + (function() { + return (function() { + return function(a) {}; + })(); + })(); + })(); + } + } +} + +issues_3267_1: { + options = { + collapse_vars: true, + conditionals: true, + dead_code: true, + evaluate: true, + inline: true, + keep_fargs: "strict", + reduce_vars: true, + sequences: true, + side_effects: true, + unused: true, + } + input: { + (function(x) { + x(); + })(function() { + (function(i) { + if (i) + return console.log("PASS"); + throw "FAIL"; + })(Object()); + }); + } + expect: { + !function() { + if (Object()) + return console.log("PASS"); + throw "FAIL"; + }(); + } + expect_stdout: "PASS" +} + +trailing_argument_side_effects: { + options = { + keep_fargs: "strict", + unused: true, + } + input: { + function f() { + return "FAIL"; + } + console.log(function(a, b) { + return b || "PASS"; + }(f())); + } + expect: { + function f() { + return "FAIL"; + } + console.log(function(b) { + return b || "PASS"; + }(void f())); + } + expect_stdout: "PASS" +} + +recursive_iife_1: { + options = { + keep_fargs: "strict", + reduce_vars: true, + unused: true, + } + input: { + console.log(function f(a, b) { + return b || f("FAIL", "PASS"); + }()); + } + expect: { + console.log(function f(a, b) { + return b || f("FAIL", "PASS"); + }()); + } + expect_stdout: "PASS" +} + +recursive_iife_2: { + options = { + keep_fargs: "strict", + reduce_vars: true, + unused: true, + } + input: { + console.log(function f(a, b) { + return b || f("FAIL", "PASS"); + }(null, 0)); + } + expect: { + console.log(function f(a, b) { + return b || f("FAIL", "PASS"); + }(0, 0)); + } + expect_stdout: "PASS" +} + +recursive_iife_3: { + options = { + keep_fargs: false, + reduce_vars: true, + unused: true, + } + input: { + var a = 1, c = "PASS"; + (function() { + function f(b, d, e) { + a-- && f(null, 42, 0); + e && (c = "FAIL"); + d && d.p; + } + var a_1 = f(); + })(); + console.log(c); + } + expect: { + var a = 1, c = "PASS"; + (function() { + (function f(b, d, e) { + a-- && f(null, 42, 0); + e && (c = "FAIL"); + d && d.p; + })(); + })(); + console.log(c); + } + expect_stdout: "PASS" +} diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 9dcf96aaf5..a3421c001e 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -1599,7 +1599,7 @@ defun_label: { } expect: { !function() { - console.log(function() { + console.log(function(a) { L: { if (2) break L; return 1; @@ -1763,13 +1763,13 @@ iife_func_side_effects: { function z() { console.log("z"); } - (function(b) { + (function(a, b, c) { return function() { console.log("FAIL"); } + b(); - })((x(), function() { + })(x(), function() { return y(); - }), z()); + }, z()); } expect_stdout: [ "x", @@ -1830,7 +1830,7 @@ issue_1595_3: { })(2); } expect: { - (function() { + (function(a) { return g(3); })(); } @@ -6602,7 +6602,7 @@ issues_3267_1: { }); } expect: { - !function() { + !function(i) { if (Object()) return console.log("PASS"); throw "FAIL";