fix corner case in `inline` (#3837)
authorAlex Lam S.L <alexlamsl@gmail.com>
Fri, 1 May 2020 09:20:23 +0000 (10:20 +0100)
committerGitHub <noreply@github.com>
Fri, 1 May 2020 09:20:23 +0000 (17:20 +0800)
fixes #3836

lib/compress.js
test/compress/functions.js

index 79f5278..d584bdf 100644 (file)
@@ -4003,16 +4003,30 @@ merge(Compressor.prototype, {
                     })) break;
                 }
                 if (fn.contains_this()) break;
-                var j = fn.argnames.length;
-                if (j > 0 && compressor.option("inline") < 2) break;
-                if (j > self.argnames.length) break;
-                if (j < self.argnames.length && !compressor.drop_fargs(fn, call)) break;
-                while (--j >= 0) {
+                var len = fn.argnames.length;
+                if (len > 0 && compressor.option("inline") < 2) break;
+                if (len > self.argnames.length) break;
+                for (var j = 0; j < len; j++) {
                     var arg = call.args[j];
                     if (!(arg instanceof AST_SymbolRef)) break;
                     if (arg.definition() !== self.argnames[j].definition()) break;
                 }
-                if (j >= 0) break;
+                if (j < len) break;
+                for (; j < call.args.length; j++) {
+                    if (call.args[j].has_side_effects(compressor)) break;
+                }
+                if (j < call.args.length) break;
+                if (len < self.argnames.length && !compressor.drop_fargs(self, compressor.parent())) {
+                    if (!compressor.drop_fargs(fn, call)) break;
+                    do {
+                        var argname = make_node(AST_SymbolFunarg, fn, {
+                            name: fn.make_var_name("argument_" + len),
+                            scope: fn
+                        });
+                        fn.argnames.push(argname);
+                        fn.enclosed.push(fn.def_variable(argname));
+                    } while (++len < self.argnames.length);
+                }
                 return call.expression;
             }
             break;
index f5ad08b..439c073 100644 (file)
@@ -4151,7 +4151,7 @@ issue_3821_2: {
     expect_stdout: "PASS"
 }
 
-substitude: {
+substitute: {
     options = {
         inline: true,
         reduce_vars: true,
@@ -4189,8 +4189,7 @@ substitude: {
                 };
             },
         ].forEach(function(g) {
-            console.log(g()(o));
-            console.log(g().call(o, o));
+            console.log(g()(o), g().call(o, o), g().length);
         });
     }
     expect: {
@@ -4218,25 +4217,56 @@ substitude: {
                 };
             },
         ].forEach(function(g) {
-            console.log(g()(o));
-            console.log(g().call(o, o));
+            console.log(g()(o), g().call(o, o), g().length);
         });
     }
     expect_stdout: [
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
+        "PASS PASS 1",
+        "PASS PASS 1",
+        "PASS PASS 1",
+        "PASS PASS 1",
+        "PASS PASS 2",
+    ]
+}
+
+substitute_add_farg: {
+    options = {
+        inline: true,
+        keep_fargs: "strict",
+    }
+    input: {
+        function f(g) {
+            console.log(g.length);
+            g(null, "FAIL");
+        }
+        f(function() {
+            return function(a, b) {
+                return function(c) {
+                    do {
+                        console.log("PASS");
+                    } while (c);
+                }(a, b);
+            };
+        }());
+    }
+    expect: {
+        function f(g) {
+            console.log(g.length);
+            g(null, "FAIL");
+        }
+        f(function(c, argument_1) {
+            do {
+                console.log("PASS");
+            } while (c);
+        });
+    }
+    expect_stdout: [
+        "2",
         "PASS",
     ]
 }
 
-substitude_arguments: {
+substitute_arguments: {
     options = {
         inline: true,
         reduce_vars: true,
@@ -4244,7 +4274,7 @@ substitude_arguments: {
     }
     input: {
         var o = {};
-        function f() {
+        function f(a) {
             return arguments[0] === o ? "PASS" : "FAIL";
         }
         [
@@ -4274,13 +4304,12 @@ substitude_arguments: {
                 };
             },
         ].forEach(function(g) {
-            console.log(g()(o));
-            console.log(g().call(o, o));
+            console.log(g()(o), g().call(o, o), g().length);
         });
     }
     expect: {
         var o = {};
-        function f() {
+        function f(a) {
             return arguments[0] === o ? "PASS" : "FAIL";
         }
         [
@@ -4310,25 +4339,19 @@ substitude_arguments: {
                 };
             },
         ].forEach(function(g) {
-            console.log(g()(o));
-            console.log(g().call(o, o));
+            console.log(g()(o), g().call(o, o), g().length);
         });
     }
     expect_stdout: [
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
+        "PASS PASS 1",
+        "PASS PASS 1",
+        "PASS PASS 1",
+        "PASS PASS 1",
+        "PASS PASS 2",
     ]
 }
 
-substitude_drop_fargs: {
+substitute_drop_farg: {
     options = {
         inline: true,
         keep_fargs: false,
@@ -4367,8 +4390,7 @@ substitude_drop_fargs: {
                 };
             },
         ].forEach(function(g) {
-            console.log(g()(o));
-            console.log(g().call(o, o));
+            console.log(g()(o), g().call(o, o));
         });
     }
     expect: {
@@ -4394,25 +4416,19 @@ substitude_drop_fargs: {
                 return f;
             },
         ].forEach(function(g) {
-            console.log(g()(o));
-            console.log(g().call(o, o));
+            console.log(g()(o), g().call(o, o));
         });
     }
     expect_stdout: [
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
+        "PASS PASS",
+        "PASS PASS",
+        "PASS PASS",
+        "PASS PASS",
+        "PASS PASS",
     ]
 }
 
-substitude_this: {
+substitute_this: {
     options = {
         inline: true,
         reduce_vars: true,
@@ -4450,8 +4466,7 @@ substitude_this: {
                 };
             },
         ].forEach(function(g) {
-            console.log(g()(o));
-            console.log(g().call(o, o));
+            console.log(g()(o), g().call(o, o), g().length);
         });
     }
     expect: {
@@ -4486,25 +4501,19 @@ substitude_this: {
                 };
             },
         ].forEach(function(g) {
-            console.log(g()(o));
-            console.log(g().call(o, o));
+            console.log(g()(o), g().call(o, o), g().length);
         });
     }
     expect_stdout: [
-        "false",
-        "true",
-        "false",
-        "false",
-        "false",
-        "false",
-        "false",
-        "false",
-        "false",
-        "false",
+        "false true 1",
+        "false false 1",
+        "false false 1",
+        "false false 1",
+        "false false 2",
     ]
 }
 
-substitude_use_strict: {
+substitute_use_strict: {
     options = {
         inline: true,
         reduce_vars: true,
@@ -4543,8 +4552,7 @@ substitude_use_strict: {
                 };
             },
         ].forEach(function(g) {
-            console.log(g()(o));
-            console.log(g().call(o, o));
+            console.log(g()(o), g().call(o, o), g().length);
         });
     }
     expect: {
@@ -4573,21 +4581,15 @@ substitude_use_strict: {
                 };
             },
         ].forEach(function(g) {
-            console.log(g()(o));
-            console.log(g().call(o, o));
+            console.log(g()(o), g().call(o, o), g().length);
         });
     }
     expect_stdout: [
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
-        "PASS",
+        "PASS PASS 1",
+        "PASS PASS 1",
+        "PASS PASS 1",
+        "PASS PASS 1",
+        "PASS PASS 2",
     ]
 }
 
@@ -4637,3 +4639,24 @@ issue_3835: {
     }
     expect_stdout: true
 }
+
+issue_3836: {
+    options = {
+        inline: true,
+    }
+    input: {
+        (function() {
+            return function() {
+                for (var a in 0)
+                    console.log(k);
+            }(console.log("PASS"));
+        })();
+    }
+    expect: {
+        (function() {
+            for (var a in 0)
+                console.log(k);
+        })(console.log("PASS"));
+    }
+    expect_stdout: "PASS"
+}