fix corner case in `collapse_vars` (#4061)
authorAlex Lam S.L <alexlamsl@gmail.com>
Fri, 21 Aug 2020 02:35:34 +0000 (03:35 +0100)
committerGitHub <noreply@github.com>
Fri, 21 Aug 2020 02:35:34 +0000 (10:35 +0800)
lib/compress.js
test/compress/collapse_vars.js

index f15776c..595e503 100644 (file)
@@ -1952,6 +1952,7 @@ merge(Compressor.prototype, {
             function get_lvalues(expr) {
                 var lvalues = new Dictionary();
                 if (expr instanceof AST_VarDef) lvalues.add(expr.name.name, lhs);
+                var find_arguments = scope.uses_arguments && !compressor.has_directive("use strict");
                 var scan_toplevel = scope instanceof AST_Toplevel;
                 var tw = new TreeWalker(function(node) {
                     var value;
@@ -1960,21 +1961,27 @@ merge(Compressor.prototype, {
                     } else if (node instanceof AST_This) {
                         value = node;
                     }
-                    if (value) {
-                        lvalues.add(node.name, is_modified(compressor, tw, node, value, 0));
-                    } else if (scan_toplevel) {
-                        if (node.TYPE == "Call") {
-                            if (modify_toplevel) return;
-                            var exp = node.expression;
-                            if (exp instanceof AST_PropAccess) return;
-                            if (exp instanceof AST_Function && !exp.contains_this()) return;
-                            modify_toplevel = true;
-                        } else if (node instanceof AST_PropAccess && may_be_global(node.expression)) {
-                            if (node === lhs && !(expr instanceof AST_Unary)) {
-                                modify_toplevel = true;
-                            } else {
-                                read_toplevel = true;
+                    if (value) lvalues.add(node.name, is_modified(compressor, tw, node, value, 0));
+                    if (find_arguments && node instanceof AST_Sub) {
+                        scope.argnames.forEach(function(argname) {
+                            if (!compressor.option("reduce_vars") || argname.definition().assignments) {
+                                lvalues.add(argname.name, true);
                             }
+                        });
+                        find_arguments = false;
+                    }
+                    if (!scan_toplevel) return;
+                    if (node.TYPE == "Call") {
+                        if (modify_toplevel) return;
+                        var exp = node.expression;
+                        if (exp instanceof AST_PropAccess) return;
+                        if (exp instanceof AST_Function && !exp.contains_this()) return;
+                        modify_toplevel = true;
+                    } else if (node instanceof AST_PropAccess && may_be_global(node.expression)) {
+                        if (node === lhs && !(expr instanceof AST_Unary)) {
+                            modify_toplevel = true;
+                        } else {
+                            read_toplevel = true;
                         }
                     }
                 });
index aa8b89c..c042f96 100644 (file)
@@ -1599,7 +1599,7 @@ collapse_vars_constants: {
     }
 }
 
-collapse_vars_arguments: {
+collapse_vars_arguments_1: {
     options = {
         booleans: true,
         collapse_vars: true,
@@ -1636,6 +1636,78 @@ collapse_vars_arguments: {
     expect_stdout: true
 }
 
+collapse_vars_arguments_2: {
+    options = {
+        collapse_vars: true,
+    }
+    input: {
+        function log(a, b) {
+            console.log(b);
+        }
+        function f(c) {
+            var d = arguments[0];
+            c = "FAIL";
+            log(c, d);
+        }
+        f();
+        f("PASS");
+    }
+    expect: {
+        function log(a, b) {
+            console.log(b);
+        }
+        function f(c) {
+            var d = arguments[0];
+            log(c = "FAIL", d);
+        }
+        f();
+        f("PASS");
+    }
+    expect_stdout: [
+        "undefined",
+        "PASS",
+    ]
+}
+
+collapse_vars_arguments_3: {
+    options = {
+        collapse_vars: true,
+    }
+    input: {
+        function log(a, b) {
+            console.log(b);
+        }
+        function f(c) {
+            var args = arguments;
+            console.log(c);
+            var d = args[0];
+            c = "FAIL";
+            log(c, d);
+        }
+        f();
+        f("PASS");
+    }
+    expect: {
+        function log(a, b) {
+            console.log(b);
+        }
+        function f(c) {
+            var args = arguments;
+            console.log(c);
+            var d = args[0];
+            log(c = "FAIL", d);
+        }
+        f();
+        f("PASS");
+    }
+    expect_stdout: [
+        "undefined",
+        "undefined",
+        "PASS",
+        "PASS",
+    ]
+}
+
 collapse_vars_short_circuit: {
     options = {
         booleans: true,