From 9d34f8428bc4a5fb7d26ac953f585b2622d63171 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sun, 29 Nov 2020 02:05:48 +0000 Subject: [PATCH] fix corner case in `side_effects` (#4326) fixes #4325 --- lib/compress.js | 33 +++++++++++++++++++------------ test/compress/functions.js | 4 +--- test/compress/keep_fargs.js | 2 +- test/compress/loops.js | 1 + test/compress/side_effects.js | 37 +++++++++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+), 17 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 708b9df3..7434a20d 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -5592,20 +5592,10 @@ merge(Compressor.prototype, { } else if (node instanceof AST_ForIn) { if (!drop_vars || !compressor.option("loops")) return; if (!is_empty(node.body)) return; - var sym = node.init; - if (sym instanceof AST_Definitions) { - sym = sym.definitions[0].name; - } else while (sym instanceof AST_PropAccess) { - sym = sym.expression.tail_node(); - } - if (sym instanceof AST_Destructured) return; + var sym = get_init_symbol(node); + if (!sym) return; var def = sym.definition(); - if (!def) return; if (def.id in in_use_ids) return; - if (def.scope !== self) { - var d = self.find_variable(sym); - if ((d && d.redefined() || d) === def) return; - } log(sym, "Dropping unused loop variable {name}"); if (for_ins[def.id] === node) delete for_ins[def.id]; var body = []; @@ -5705,6 +5695,16 @@ merge(Compressor.prototype, { return rhs.right; } + function get_init_symbol(for_in) { + var init = for_in.init; + if (init instanceof AST_Definitions) { + init = init.definitions[0].name; + return init instanceof AST_SymbolDeclaration && init; + } + while (init instanceof AST_PropAccess) init = init.expression.tail_node(); + if (init instanceof AST_SymbolRef) return init; + } + function scan_ref_scoped(node, descend, init) { if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) { var def = node.left.definition(); @@ -5748,8 +5748,14 @@ merge(Compressor.prototype, { } if (!drop_vars || !compressor.option("loops")) return; if (!is_empty(node.body)) return; - if (node.init instanceof AST_Destructured) return; if (node.init.has_side_effects(compressor)) return; + var sym = get_init_symbol(node); + if (!sym) return; + var def = sym.definition(); + if (def.scope !== self) { + var d = self.find_variable(sym); + if ((d && d.redefined() || d) === def) return; + } node.object.walk(tw); return true; } @@ -6259,6 +6265,7 @@ merge(Compressor.prototype, { }); // always shallow clone to ensure stripping of negated IIFEs self = self.clone(); + self.expression = exp.clone(); } if (self instanceof AST_New) { var fn = exp; diff --git a/test/compress/functions.js b/test/compress/functions.js index e06596b8..49bbfac9 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -3322,9 +3322,7 @@ issue_3506_1: { } expect: { var a = "FAIL"; - !function(b) { - b && (a = "PASS"); - }(a); + a && (a = "PASS"); console.log(a); } expect_stdout: "PASS" diff --git a/test/compress/keep_fargs.js b/test/compress/keep_fargs.js index e1737081..7141a410 100644 --- a/test/compress/keep_fargs.js +++ b/test/compress/keep_fargs.js @@ -525,7 +525,7 @@ issue_2506: { function f0(bar) { (function() { (function() { - if (false <= 0/0 & this >> 1 >= 0) + if (false <= NaN & this >> 1 >= 0) c++; })(c++); })(); diff --git a/test/compress/loops.js b/test/compress/loops.js index 69150820..c16fa5bd 100644 --- a/test/compress/loops.js +++ b/test/compress/loops.js @@ -1052,6 +1052,7 @@ issue_4084: { options = { keep_fargs: "strict", loops: true, + passes: 2, reduce_vars: true, unused: true, } diff --git a/test/compress/side_effects.js b/test/compress/side_effects.js index 3c53dd25..0654a4ce 100644 --- a/test/compress/side_effects.js +++ b/test/compress/side_effects.js @@ -433,3 +433,40 @@ trim_new: { } expect_stdout: "PASS" } + +issue_4325: { + options = { + keep_fargs: "strict", + passes: 2, + pure_getters: "strict", + reduce_vars: true, + side_effects: true, + unused: true, + } + input: { + (function f() { + (function(b, c) { + try { + c.p = 0; + } catch (e) { + console.log("PASS"); + return b; + } + c; + })(f++); + })(); + } + expect: { + (function() { + (function() { + try { + (void 0).p = 0; + } catch (e) { + console.log("PASS"); + return; + } + })(); + })(); + } + expect_stdout: "PASS" +} -- 2.34.1