fix corner cases with `arguments` (#4481)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 29 Dec 2020 16:22:03 +0000 (16:22 +0000)
committerGitHub <noreply@github.com>
Tue, 29 Dec 2020 16:22:03 +0000 (00:22 +0800)
fixes #4480

lib/compress.js
lib/scope.js
test/compress/arguments.js
test/compress/evaluate.js
test/compress/keep_fargs.js

index 591ad4d..3ac9e74 100644 (file)
@@ -357,10 +357,7 @@ merge(Compressor.prototype, {
     }
 
     function is_arguments(def) {
-        if (def.name != "arguments") return false;
-        if (!def.scope.uses_arguments) return false;
-        var orig = def.orig;
-        return orig.length == 1 && orig[0] instanceof AST_SymbolFunarg;
+        return def.name == "arguments" && def.scope.uses_arguments;
     }
 
     function is_funarg(def) {
index 0c35b0d..4660c78 100644 (file)
@@ -265,10 +265,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
             }
             if (!sym) {
                 sym = self.def_global(node);
-            } else if (name == "arguments"
-                && sym.orig[0] instanceof AST_SymbolFunarg
-                && !(sym.orig[1] instanceof AST_SymbolFunarg)
-                && !(sym.scope instanceof AST_Arrow)) {
+            } else if (name == "arguments" && is_arguments(sym)) {
                 var parent = tw.parent();
                 if (parent instanceof AST_Assign && parent.left === node
                     || parent instanceof AST_Unary && unary_side_effects[parent.operator]) {
@@ -297,6 +294,13 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
             node.reference(options);
             return true;
         }
+        if (node instanceof AST_VarDef) {
+            if (node.value && node.name.name == "arguments") {
+                var sym = node.name.scope.resolve().find_variable("arguments");
+                if (sym && is_arguments(sym)) sym.scope.uses_arguments = 3;
+            }
+            return;
+        }
     });
     self.walk(tw);
 
@@ -322,6 +326,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
         }
     }));
 
+    function is_arguments(sym) {
+        return sym.orig[0] instanceof AST_SymbolFunarg
+            && !(sym.orig[1] instanceof AST_SymbolFunarg || sym.orig[2] instanceof AST_SymbolFunarg)
+            && !(sym.scope instanceof AST_Arrow);
+    }
+
     function redefine(node, scope) {
         var name = node.name;
         var old_def = node.thedef;
index 3ca244a..655d75a 100644 (file)
@@ -101,6 +101,13 @@ replace_index_drop_fargs_1: {
             var arguments;
             console.log(arguments[1], arguments["1"], arguments["foo"]);
         })("bar", 42);
+        (function() {
+            var arguments = {
+                1: "foo",
+                foo: "bar",
+            };
+            console.log(arguments[1], arguments["1"], arguments["foo"]);
+        })("bar", 42);
     }
     expect: {
         var arguments = [];
@@ -114,8 +121,15 @@ replace_index_drop_fargs_1: {
         (function(arguments) {
             console.log(arguments[1], arguments[1], arguments.foo);
         })("bar", 42);
-        (function() {
+        (function(argument_0, argument_1) {
             var arguments;
+            console.log(argument_1, argument_1, arguments.foo);
+        })("bar", 42);
+        (function() {
+            var arguments = {
+                1: "foo",
+                foo: "bar",
+            };
             console.log(arguments[1], arguments[1], arguments.foo);
         })("bar", 42);
     }
@@ -125,6 +139,7 @@ replace_index_drop_fargs_1: {
         "42 42 undefined",
         "a a undefined",
         "42 42 undefined",
+        "foo foo bar",
     ]
 }
 
index 7466d63..73c982f 100644 (file)
@@ -3117,3 +3117,28 @@ issue_4422: {
     }
     expect_stdout: "PASS"
 }
+
+issue_4480: {
+    options = {
+        evaluate: true,
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        var a = function f(b) {
+            b = "FAIL";
+            arguments[0] = "PASS";
+            var arguments = 0;
+            console.log(b);
+        }(a);
+    }
+    expect: {
+        var a = function(b) {
+            b = "FAIL";
+            arguments[0] = "PASS";
+            var arguments = 0;
+            console.log(b);
+        }(a);
+    }
+    expect_stdout: "PASS"
+}
index 049684a..d5d7ef9 100644 (file)
@@ -80,56 +80,6 @@ keep_fargs_true: {
     ]
 }
 
-replace_index: {
-    options = {
-        arguments: true,
-        evaluate: true,
-        keep_fargs: false,
-        properties: true,
-    }
-    input: {
-        var arguments = [];
-        console.log(arguments[0]);
-        (function() {
-            console.log(arguments[1], arguments["1"], arguments["foo"]);
-        })("bar", 42);
-        (function(a, b) {
-            console.log(arguments[1], arguments["1"], arguments["foo"]);
-        })("bar", 42);
-        (function(arguments) {
-            console.log(arguments[1], arguments["1"], arguments["foo"]);
-        })("bar", 42);
-        (function() {
-            var arguments;
-            console.log(arguments[1], arguments["1"], arguments["foo"]);
-        })("bar", 42);
-    }
-    expect: {
-        var arguments = [];
-        console.log(arguments[0]);
-        (function(argument_0, argument_1) {
-            console.log(argument_1, argument_1, arguments.foo);
-        })("bar", 42);
-        (function(a, b) {
-            console.log(b, b, arguments.foo);
-        })("bar", 42);
-        (function(arguments) {
-            console.log(arguments[1], arguments[1], arguments.foo);
-        })("bar", 42);
-        (function() {
-            var arguments;
-            console.log(arguments[1], arguments[1], arguments.foo);
-        })("bar", 42);
-    }
-    expect_stdout: [
-        "undefined",
-        "42 42 undefined",
-        "42 42 undefined",
-        "a a undefined",
-        "42 42 undefined",
-    ]
-}
-
 replace_index_strict: {
     options = {
         arguments: true,