improve fix for #2954 (#2958)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sun, 25 Feb 2018 19:14:22 +0000 (03:14 +0800)
committerGitHub <noreply@github.com>
Sun, 25 Feb 2018 19:14:22 +0000 (03:14 +0800)
lib/compress.js
test/compress/collapse_vars.js

index 2d0a03a..c402e3b 100644 (file)
@@ -913,8 +913,8 @@ merge(Compressor.prototype, {
     }
 
     function tighten_body(statements, compressor) {
-        var scope = compressor.find_parent(AST_Scope);
-        var in_loop = is_in_node(AST_IterationStatement);
+        var in_loop, in_try, scope;
+        find_loop_scope_try();
         var CHANGED, max_iter = 10;
         do {
             CHANGED = false;
@@ -937,13 +937,20 @@ merge(Compressor.prototype, {
             }
         } while (CHANGED && max_iter-- > 0);
 
-        function is_in_node(type) {
-            if (compressor.self() instanceof type) return true;
-            for (var node, level = 0; node = compressor.parent(level); level++) {
-                if (node instanceof type) return true;
-                if (node instanceof AST_Scope) break;
-            }
-            return false;
+        function find_loop_scope_try() {
+            var node = compressor.self(), level = 0;
+            do {
+                if (node instanceof AST_Catch || node instanceof AST_Finally) {
+                    level++;
+                } else if (node instanceof AST_IterationStatement) {
+                    in_loop = true;
+                } else if (node instanceof AST_Scope) {
+                    scope = node;
+                    break;
+                } else if (node instanceof AST_Try) {
+                    in_try = true;
+                }
+            } while (node = compressor.parent(level++));
         }
 
         // Search from right to left for assignment-like expressions:
@@ -958,7 +965,6 @@ merge(Compressor.prototype, {
             if (scope.uses_eval || scope.uses_with) return statements;
             var args;
             var candidates = [];
-            var in_try = is_in_node(AST_Try);
             var stat_index = statements.length;
             var scanner = new TreeTransformer(function(node, descend) {
                 if (abort) return node;
@@ -1433,7 +1439,10 @@ merge(Compressor.prototype, {
                 if (def.orig.length == 1 && def.orig[0] instanceof AST_SymbolDefun) return false;
                 if (def.scope !== scope) return true;
                 return !all(def.references, function(ref) {
-                    return ref.scope === scope;
+                    var s = ref.scope;
+                    // "block" scope within AST_Catch
+                    if (s.TYPE == "Scope") s = s.parent_scope;
+                    return s === scope;
                 });
             }
 
index ecf6424..6050550 100644 (file)
@@ -2219,8 +2219,8 @@ unused_orig: {
         console.log(function(b) {
             var c = b;
             for (var d in c) {
-                var a = c[0];
-                return --b + a;
+                var a;
+                return --b + c[0];
             }
             a && a.NaN;
         }([2]), a);
@@ -4666,7 +4666,7 @@ issue_2931: {
     expect_stdout: "undefined"
 }
 
-issue_2954: {
+issue_2954_1: {
     options = {
         collapse_vars: true,
     }
@@ -4700,3 +4700,73 @@ issue_2954: {
     }
     expect_stdout: "PASS"
 }
+
+issue_2954_2: {
+    options = {
+        collapse_vars: true,
+    }
+    input: {
+        var a = "FAIL_1", b;
+        try {
+            throw 0;
+        } catch (e) {
+            do {
+                b = function() {
+                    throw new Error("PASS");
+                }();
+                a = "FAIL_2";
+                b && b.c;
+            } while (0);
+        }
+        console.log(a);
+    }
+    expect: {
+        var a = "FAIL_1", b;
+        try {
+            throw 0;
+        } catch (e) {
+            do {
+                a = "FAIL_2";
+                (b = function() {
+                    throw new Error("PASS");
+                }()) && b.c;
+            } while (0);
+        }
+        console.log(a);
+    }
+    expect_stdout: Error("PASS")
+}
+
+issue_2954_3: {
+    options = {
+        collapse_vars: true,
+    }
+    input: {
+        var a = "FAIL_1", b;
+        try {
+        } finally {
+            do {
+                b = function() {
+                    throw new Error("PASS");
+                }();
+                a = "FAIL_2";
+                b && b.c;
+            } while (0);
+        }
+        console.log(a);
+    }
+    expect: {
+        var a = "FAIL_1", b;
+        try {
+        } finally {
+            do {
+                a = "FAIL_2";
+                (b = function() {
+                    throw new Error("PASS");
+                }()) && b.c;
+            } while (0);
+        }
+        console.log(a);
+    }
+    expect_stdout: Error("PASS")
+}