fix corner cases in `inline` (#3773)
authorAlex Lam S.L <alexlamsl@gmail.com>
Fri, 10 Apr 2020 16:34:45 +0000 (17:34 +0100)
committerGitHub <noreply@github.com>
Fri, 10 Apr 2020 16:34:45 +0000 (00:34 +0800)
fixes #3770
fixes #3771
fixes #3772

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

index 7961486..94b7667 100644 (file)
@@ -5828,14 +5828,17 @@ merge(Compressor.prototype, {
                 && !(fn.name && fn instanceof AST_Function)
                 && (value = can_flatten_body(stat))
                 && (exp === fn
-                    || !recursive_ref(compressor, def = exp.definition) && fn.is_constant_expression(exp.scope))
+                    || !recursive_ref(compressor, def = exp.definition()) && fn.is_constant_expression(exp.scope))
                 && !fn.contains_this()) {
                 if (can_substitute_directly()) {
                     var args = self.args.slice();
                     args.push(value.clone(true).transform(new TreeTransformer(function(node) {
                         if (node instanceof AST_SymbolRef) {
                             var def = node.definition();
-                            if (fn.variables.get(node.name) !== def) return node;
+                            if (fn.variables.get(node.name) !== def) {
+                                if (exp !== fn) def.references.push(node);
+                                return node;
+                            }
                             var index = resolve_index(def);
                             var arg = args[index];
                             if (!arg) return make_node(AST_Undefined, self);
@@ -5931,10 +5934,14 @@ merge(Compressor.prototype, {
 
         function can_substitute_directly() {
             if (compressor.option("inline") <= 1 && fn.argnames.length) return;
-            if (fn.variables.size() > fn.argnames.length + 1) return;
+            var var_count = fn.variables.size() - 1;
+            if (var_count > fn.argnames.length) return;
+            var var_names = [];
             if (!all(fn.argnames, function(argname) {
+                push_uniq(var_names, argname.name);
                 return argname.definition().references.length < 2;
             })) return;
+            if (var_count > var_names.length) return;
             var abort = false;
             var begin;
             var in_order = [];
index 4a192d5..c1522e2 100644 (file)
@@ -3928,3 +3928,89 @@ preserve_binding_2: {
     }
     expect_stdout: "PASS"
 }
+
+issue_3770: {
+    options = {
+        inline: true,
+        reduce_vars: true,
+        side_effects: true,
+        unused: true,
+    }
+    input: {
+        (function() {
+            function f(a, a) {
+                var b = function() {
+                    return a || "PASS";
+                }();
+                console.log(b);
+            }
+            f("FAIL");
+        })();
+    }
+    expect: {
+        (function() {
+            b = a || "PASS",
+            console.log(b);
+            var a, b;
+        })();
+    }
+    expect_stdout: "PASS"
+}
+
+issue_3771: {
+    options = {
+        inline: true,
+        reduce_vars: true,
+        side_effects: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        try {
+            function f(a) {
+                var a = f(1234);
+            }
+            f();
+        } catch (e) {
+            console.log("PASS");
+        }
+    }
+    expect: {
+        try {
+            (function f(a) {
+                f();
+            })();
+        } catch (e) {
+            console.log("PASS");
+        }
+    }
+    expect_stdout: "PASS"
+}
+
+issue_3772: {
+    options = {
+        collapse_vars: true,
+        dead_code: true,
+        inline: true,
+        reduce_vars: true,
+        side_effects: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var a = "PASS";
+        function f() {
+            return a;
+        }
+        var b = f();
+        function g() {
+            console.log(f());
+        }
+        g();
+    }
+    expect: {
+        var a = "PASS";
+        console.log(a);
+    }
+    expect_stdout: "PASS"
+}