fix `reduce_vars` on catch variable (#1794)
authorAlex Lam S.L <alexlamsl@gmail.com>
Fri, 7 Apr 2017 04:32:56 +0000 (12:32 +0800)
committerGitHub <noreply@github.com>
Fri, 7 Apr 2017 04:32:56 +0000 (12:32 +0800)
Improved catch handling in `figure_out_scope()` means special case treatment of IE8 is no longer valid in `reset_opt_flags()`.

Also fixed recursive assignment in variable definition.

lib/compress.js
test/compress/reduce_vars.js

index de3b4db..8df6e58 100644 (file)
@@ -251,9 +251,7 @@ merge(Compressor.prototype, {
     AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan){
         var reduce_vars = rescan && compressor.option("reduce_vars");
         var toplevel = compressor.option("toplevel");
-        var ie8 = !compressor.option("screw_ie8");
-        var safe_ids = [];
-        push();
+        var safe_ids = Object.create(null);
         var suppressor = new TreeWalker(function(node) {
             if (node instanceof AST_Symbol) {
                 var d = node.definition();
@@ -277,7 +275,7 @@ merge(Compressor.prototype, {
                         d.fixed = false;
                     }
                 }
-                if (ie8 && node instanceof AST_SymbolCatch) {
+                if (node instanceof AST_SymbolCatch) {
                     node.definition().fixed = false;
                 }
                 if (node instanceof AST_VarDef) {
@@ -287,11 +285,12 @@ merge(Compressor.prototype, {
                             d.fixed = function() {
                                 return node.value;
                             };
+                            mark(d, false);
                             descend();
                         } else {
                             d.fixed = null;
                         }
-                        mark_as_safe(d);
+                        mark(d, true);
                         return true;
                     } else if (node.value) {
                         d.fixed = false;
@@ -303,11 +302,10 @@ merge(Compressor.prototype, {
                         d.fixed = false;
                     } else {
                         d.fixed = node;
-                        mark_as_safe(d);
+                        mark(d, true);
                     }
                     var save_ids = safe_ids;
-                    safe_ids = [];
-                    push();
+                    safe_ids = Object.create(null);
                     descend();
                     safe_ids = save_ids;
                     return true;
@@ -325,7 +323,7 @@ merge(Compressor.prototype, {
                         d.fixed = function() {
                             return iife.args[i] || make_node(AST_Undefined, iife);
                         };
-                        mark_as_safe(d);
+                        mark(d, true);
                     });
                 }
                 if (node instanceof AST_If || node instanceof AST_DWLoop) {
@@ -373,29 +371,27 @@ merge(Compressor.prototype, {
         });
         this.walk(tw);
 
-        function mark_as_safe(def) {
-            safe_ids[safe_ids.length - 1][def.id] = true;
+        function mark(def, safe) {
+            safe_ids[def.id] = safe;
         }
 
         function is_safe(def) {
-            for (var i = safe_ids.length, id = def.id; --i >= 0;) {
-                if (safe_ids[i][id]) {
-                    if (def.fixed == null) {
-                        var orig = def.orig[0];
-                        if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false;
-                        def.fixed = make_node(AST_Undefined, orig);
-                    }
-                    return true;
+            if (safe_ids[def.id]) {
+                if (def.fixed == null) {
+                    var orig = def.orig[0];
+                    if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false;
+                    def.fixed = make_node(AST_Undefined, orig);
                 }
+                return true;
             }
         }
 
         function push() {
-            safe_ids.push(Object.create(null));
+            safe_ids = Object.create(safe_ids);
         }
 
         function pop() {
-            safe_ids.pop();
+            safe_ids = Object.getPrototypeOf(safe_ids);
         }
 
         function reset_def(def) {
index fdfec99..842d8de 100644 (file)
@@ -1917,7 +1917,7 @@ side_effects_assign: {
     expect_stdout: "undefined"
 }
 
-pure_getters: {
+pure_getters_1: {
     options = {
         pure_getters: true,
         reduce_vars: true,
@@ -1938,3 +1938,45 @@ pure_getters: {
     }
     expect_stdout: "undefined"
 }
+
+pure_getters_2: {
+    options = {
+        pure_getters: true,
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var a;
+        var a = a && a.b;
+    }
+    expect: {
+        var a;
+        var a = a && a.b;
+    }
+}
+
+catch_var: {
+    options = {
+        booleans: true,
+        evaluate: true,
+        reduce_vars: true,
+    }
+    input: {
+        try {
+            throw {};
+        } catch (e) {
+            var e;
+            console.log(!!e);
+        }
+    }
+    expect: {
+        try {
+            throw {};
+        } catch (e) {
+            var e;
+            console.log(!!e);
+        }
+    }
+    expect_stdout: "true"
+}