fix corner case in `collapse_vars` (#3909)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 19 May 2020 03:34:50 +0000 (04:34 +0100)
committerGitHub <noreply@github.com>
Tue, 19 May 2020 03:34:50 +0000 (11:34 +0800)
fixes #3908

lib/compress.js
test/compress/collapse_vars.js

index f91d213..006b635 100644 (file)
@@ -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;
index 97975b1..446377a 100644 (file)
@@ -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"
+}