fix corner case in `arguments` (#4810)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sun, 21 Mar 2021 02:40:32 +0000 (02:40 +0000)
committerGitHub <noreply@github.com>
Sun, 21 Mar 2021 02:40:32 +0000 (10:40 +0800)
fixes #4809

lib/compress.js
test/compress/arguments.js
test/compress/arrows.js

index 63c1164..ce12da2 100644 (file)
@@ -463,6 +463,7 @@ merge(Compressor.prototype, {
             })) {
                 tw.defun_ids[def.id] = false;
             }
+            def.reassigned = 0;
             def.recursive_refs = 0;
             def.references = [];
             def.should_replace = undefined;
@@ -662,7 +663,7 @@ merge(Compressor.prototype, {
             var key = node.property;
             if (key.is_constant()) key = key.value;
             if (!(key instanceof AST_Node) && !RE_POSITIVE_INTEGER.test(key)) return;
-            def.reassigned = true;
+            def.reassigned++;
             (key instanceof AST_Node ? def.scope.argnames : [ def.scope.argnames[key] ]).forEach(function(argname) {
                 if (argname instanceof AST_SymbolFunarg) argname.definition().fixed = false;
             });
@@ -11235,14 +11236,12 @@ merge(Compressor.prototype, {
                     || !all(fn.argnames, function(argname) {
                         return argname instanceof AST_SymbolFunarg;
                     })) {
-                    if (!compressor.option("reduce_vars")
-                        || def.reassigned
-                        || arg_def.assignments
-                        || arg_def.orig.length > 1) {
-                        argname = null;
-                    }
+                    if (has_reassigned() || arg_def.assignments || arg_def.orig.length > 1) argname = null;
                 }
-            } else if (index < fn.argnames.length + 5 && compressor.drop_fargs(fn, fn_parent) && !fn.rest) {
+            } else if ((assigned || !has_reassigned())
+                && index < fn.argnames.length + 5
+                && compressor.drop_fargs(fn, fn_parent)
+                && !fn.rest) {
                 while (index >= fn.argnames.length) {
                     argname = fn.make_var(AST_SymbolFunarg, fn, "argument_" + fn.argnames.length);
                     fn.argnames.push(argname);
@@ -11251,7 +11250,7 @@ merge(Compressor.prototype, {
             if (argname && find_if(function(node) {
                 return node.name === argname.name;
             }, fn.argnames) === argname) {
-                def.reassigned = false;
+                if (assigned) def.reassigned--;
                 var sym = make_node(AST_SymbolRef, self, argname);
                 sym.reference();
                 delete argname.__unused;
@@ -11330,6 +11329,10 @@ merge(Compressor.prototype, {
                 }
             }
         }
+
+        function has_reassigned() {
+            return !compressor.option("reduce_vars") || def.reassigned;
+        }
     });
 
     AST_Arrow.DEFMETHOD("contains_super", return_false);
index 4c602a6..5d77317 100644 (file)
@@ -84,6 +84,7 @@ replace_index_drop_fargs_1: {
         evaluate: true,
         keep_fargs: false,
         properties: true,
+        reduce_vars: true,
     }
     input: {
         var arguments = [];
@@ -119,7 +120,7 @@ replace_index_drop_fargs_1: {
             console.log(b, b, arguments.foo);
         })("bar", 42);
         (function(arguments) {
-            console.log(arguments[1], arguments[1], arguments.foo);
+            console.log("bar"[1], "bar"[1], "bar".foo);
         })("bar", 42);
         (function(argument_0, argument_1) {
             var arguments;
@@ -649,6 +650,7 @@ issue_3420_1: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         console.log(function() {
@@ -671,6 +673,7 @@ issue_3420_2: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         var foo = function() {
@@ -691,6 +694,7 @@ issue_3420_3: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         "use strict";
@@ -713,6 +717,7 @@ issue_3420_4: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         !function() {
@@ -738,6 +743,7 @@ issue_3420_5: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         "use strict";
@@ -765,6 +771,7 @@ issue_3420_6: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         console.log(function() {
@@ -783,6 +790,7 @@ issue_3420_7: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         "use strict";
@@ -827,6 +835,7 @@ issue_4291_1: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         console.log(function() {
@@ -847,6 +856,7 @@ issue_4291_2: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         var a = function() {
@@ -857,8 +867,8 @@ issue_4291_2: {
         console.log(a[1], a[0], a.length);
     }
     expect: {
-        var a = function(argument_0) {
-            if (argument_0)
+        var a = function() {
+            if (arguments[0])
                 arguments[1] = "PASS";
             return arguments;
         }(42);
@@ -871,6 +881,7 @@ issue_4397: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         console.log(typeof function() {
@@ -999,3 +1010,26 @@ issue_4696: {
     }
     expect_stdout: "PASS"
 }
+
+issue_4809: {
+    options = {
+        arguments: true,
+        keep_fargs: false,
+        reduce_vars: true,
+    }
+    input: {
+        A = 0;
+        (function() {
+            arguments[A] = "PASS";
+            console.log(arguments[0]);
+        })();
+    }
+    expect: {
+        A = 0;
+        (function() {
+            arguments[A] = "PASS";
+            console.log(arguments[0]);
+        })();
+    }
+    expect_stdout: "PASS"
+}
index c906aa4..56355ed 100644 (file)
@@ -276,6 +276,7 @@ drop_arguments: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         console.log(function() {