fix corner case in `inline` (#3595)
authorAlex Lam S.L <alexlamsl@gmail.com>
Mon, 18 Nov 2019 07:04:55 +0000 (15:04 +0800)
committerGitHub <noreply@github.com>
Mon, 18 Nov 2019 07:04:55 +0000 (15:04 +0800)
lib/compress.js
test/compress/functions.js

index b7a7343..a878ef2 100644 (file)
@@ -862,13 +862,9 @@ merge(Compressor.prototype, {
 
     AST_Toplevel.DEFMETHOD("reset_opt_flags", function(compressor) {
         var tw = new TreeWalker(compressor.option("reduce_vars") ? function(node, descend) {
-            node._squeezed = false;
-            node._optimized = false;
+            reset_flags(node);
             return node.reduce_vars(tw, descend, compressor);
-        } : function(node) {
-            node._squeezed = false;
-            node._optimized = false;
-        });
+        } : reset_flags);
         // Flow control for visiting `AST_Defun`s
         tw.defun_ids = Object.create(null);
         tw.defun_visited = Object.create(null);
@@ -881,6 +877,12 @@ merge(Compressor.prototype, {
         // - backup & restore via `save_ids` when visiting out-of-order sections
         tw.safe_ids = Object.create(null);
         this.walk(tw);
+
+        function reset_flags(node) {
+            node._squeezed = false;
+            node._optimized = false;
+            if (node instanceof AST_Scope) delete node._var_names;
+        }
     });
 
     AST_Symbol.DEFMETHOD("fixed_value", function(final) {
@@ -5582,6 +5584,11 @@ merge(Compressor.prototype, {
                 definitions: decls
             }));
             [].splice.apply(scope.body, args);
+            fn.enclosed.forEach(function(def) {
+                if (scope.var_names()[def.name]) return;
+                scope.enclosed.push(def);
+                scope.var_names()[def.name] = true;
+            });
             return expressions;
         }
     });
index 297dac7..2af14a6 100644 (file)
@@ -3487,3 +3487,84 @@ hoisted_single_use: {
         "bar",
     ]
 }
+
+pr_3592_1: {
+    options = {
+        inline: true,
+        reduce_funcs: false,
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        function problem(w) {
+            return g.indexOf(w);
+        }
+        function unused(x) {
+            return problem(x);
+        }
+        function B(problem) {
+            return g[problem];
+        }
+        function A(y) {
+            return problem(y);
+        }
+        function main(z) {
+            return B(A(z));
+        }
+        var g = [ "PASS" ];
+        console.log(main("PASS"));
+    }
+    expect: {
+        function problem(w) {
+            return g.indexOf(w);
+        }
+        function B(problem) {
+            return g[problem];
+        }
+        var g = [ "PASS" ];
+        console.log((z = "PASS", B((y = z, problem(y)))));
+        var z, y;
+    }
+    expect_stdout: "PASS"
+}
+
+pr_3592_2: {
+    options = {
+        inline: true,
+        reduce_funcs: true,
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        function problem(w) {
+            return g.indexOf(w);
+        }
+        function unused(x) {
+            return problem(x);
+        }
+        function B(problem) {
+            return g[problem];
+        }
+        function A(y) {
+            return problem(y);
+        }
+        function main(z) {
+            return B(A(z));
+        }
+        var g = [ "PASS" ];
+        console.log(main("PASS"));
+    }
+    expect: {
+        function problem(w) {
+            return g.indexOf(w);
+        }
+        var g = [ "PASS" ];
+        console.log((z = "PASS", function(problem) {
+            return g[problem];
+        }((y = z, problem(y)))));
+        var z, y;
+    }
+    expect_stdout: "PASS"
+}