From 55ebb27878211799f62786fce0548b6949607f0e Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Tue, 19 May 2020 04:34:50 +0100 Subject: [PATCH] fix corner case in `collapse_vars` (#3909) fixes #3908 --- lib/compress.js | 29 +++++++++++++++-------------- test/compress/collapse_vars.js | 24 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index f91d213e..006b635a 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -741,11 +741,6 @@ merge(Compressor.prototype, { if (j < 0) return value; return iife.args[j] || make_node(AST_Undefined, iife); }; - d.fixed.reduce_arg = function() { - var j = fn.argnames.indexOf(arg); - if (j < 0 || j >= iife.args.length) return; - iife.args[j] = make_node(AST_Number, iife.args[j], { value: 0 }); - }; tw.loop_ids[d.id] = tw.in_loop; mark(tw, d, true); } else { @@ -1307,7 +1302,7 @@ merge(Compressor.prototype, { value_def.replaced++; return List.skip; } - return get_rvalue(candidate); + return rvalue; case 1: if (!assign_used && node.body === candidate) { hit = true; @@ -1326,7 +1321,7 @@ merge(Compressor.prototype, { if (is_lhs(node, multi_replacer.parent())) return node; def.replaced++; value_def.replaced--; - return get_rvalue(candidate).clone(); + return rvalue.clone(); } // Skip (non-executed) functions and (leading) default case in switch statements if (node instanceof AST_Default || node instanceof AST_Scope) return node; @@ -1356,7 +1351,8 @@ merge(Compressor.prototype, { // Locate symbols which may execute code outside of scanning range var lvalues = get_lvalues(candidate); var lhs_local = is_lhs_local(lhs); - if (!side_effects) side_effects = value_has_side_effects(candidate); + var rvalue = get_rvalue(candidate); + if (!side_effects) side_effects = value_has_side_effects(); var replace_all = replace_all_symbols(candidate); var may_throw = candidate.may_throw(compressor) ? in_try ? function(node) { return node.has_side_effects(compressor); @@ -1427,6 +1423,7 @@ merge(Compressor.prototype, { } function should_stop(node, parent) { + if (node === rvalue) return true; if (parent instanceof AST_For) return node !== parent.init; if (node instanceof AST_Assign) { return node.operator != "=" && lhs.equivalent_to(node.left); @@ -1434,8 +1431,7 @@ merge(Compressor.prototype, { if (node instanceof AST_Call) { if (!(lhs instanceof AST_PropAccess)) return false; if (!lhs.equivalent_to(node.expression)) return false; - var rhs = get_rvalue(candidate); - return !(rhs instanceof AST_Function && !rhs.contains_this()); + return !(rvalue instanceof AST_Function && !rvalue.contains_this()); } if (node instanceof AST_Debugger) return true; if (node instanceof AST_Defun) return funarg && lhs.name === node.name.name; @@ -1974,9 +1970,9 @@ merge(Compressor.prototype, { || candidate instanceof AST_Assign && candidate.operator != "=")); } - function value_has_side_effects(expr) { - if (expr instanceof AST_Unary) return false; - return get_rvalue(expr).has_side_effects(compressor); + function value_has_side_effects() { + if (candidate instanceof AST_Unary) return false; + return rvalue.has_side_effects(compressor); } function replace_all_symbols(expr) { @@ -7577,7 +7573,12 @@ merge(Compressor.prototype, { })); } else { value = fixed.optimize(compressor); - if (def.fixed.reduce_arg) def.fixed.reduce_arg(); + if (value === fixed) value = value.transform(new TreeTransformer(function(node, descend) { + if (node instanceof AST_Scope) return node; + node = node.clone(); + descend(node, this); + return node; + })); } def.replaced++; return value; diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index 97975b1c..446377a1 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -8084,3 +8084,27 @@ issue_3897: { "2", ] } + +issue_3908: { + options = { + collapse_vars: true, + conditionals: true, + reduce_vars: true, + side_effects: true, + toplevel: true, + unused: true, + } + input: { + if (console) { + var o = { + p: !1 + }, a = o; + } + console.log("PASS"); + } + expect: { + console && 0; + console.log("PASS"); + } + expect_stdout: "PASS" +} -- 2.34.1