eliminate invalid state caching in `collapse_vars` (#2502)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 23 Nov 2017 20:12:37 +0000 (04:12 +0800)
committerGitHub <noreply@github.com>
Thu, 23 Nov 2017 20:12:37 +0000 (04:12 +0800)
fixes #2497

lib/compress.js
test/compress/collapse_vars.js

index 4727aad..987ad01 100644 (file)
@@ -869,7 +869,7 @@ merge(Compressor.prototype, {
                     && !(node instanceof AST_SymbolDeclaration)
                     && lhs.equivalent_to(node)) {
                     if (is_lhs(node, parent)) {
-                        if (candidate.multiple) replaced++;
+                        if (value_def) replaced++;
                         return node;
                     }
                     CHANGED = abort = true;
@@ -884,7 +884,7 @@ merge(Compressor.prototype, {
                         return make_node(AST_UnaryPrefix, candidate, candidate);
                     }
                     if (candidate instanceof AST_VarDef) {
-                        if (candidate.multiple) {
+                        if (value_def) {
                             abort = false;
                             return node;
                         }
@@ -958,12 +958,13 @@ merge(Compressor.prototype, {
                 extract_candidates(statements[stat_index]);
                 while (candidates.length > 0) {
                     var candidate = candidates.pop();
+                    var value_def = null;
                     var lhs = get_lhs(candidate);
                     if (!lhs || is_lhs_read_only(lhs) || lhs.has_side_effects(compressor)) continue;
                     // Locate symbols which may execute code outside of scanning range
                     var lvalues = get_lvalues(candidate);
                     if (lhs instanceof AST_SymbolRef) lvalues[lhs.name] = false;
-                    var replace_all = candidate.multiple;
+                    var replace_all = value_def;
                     if (!replace_all && lhs instanceof AST_SymbolRef) {
                         var def = lhs.definition();
                         replace_all = def.references.length - def.replaced == 1;
@@ -980,13 +981,12 @@ merge(Compressor.prototype, {
                     for (var i = stat_index; !abort && i < statements.length; i++) {
                         statements[i].transform(scanner);
                     }
-                    if (candidate.multiple) {
+                    if (value_def) {
                         var def = candidate.name.definition();
                         if (abort && def.references.length - def.replaced > replaced) replaced = false;
                         else {
                             abort = false;
                             hit = candidate.name instanceof AST_SymbolFunarg;
-                            var value_def = candidate.value.definition();
                             for (var i = stat_index; !abort && i < statements.length; i++) {
                                 statements[i].transform(multi_replacer);
                             }
@@ -1061,13 +1061,13 @@ merge(Compressor.prototype, {
                 }
             }
 
-            function mangleable_var(expr) {
-                var value = expr.value;
-                if (!(value instanceof AST_SymbolRef)) return false;
-                if (value.name == "arguments") return false;
-                if (value.definition().undeclared) return false;
-                expr.multiple = true;
-                return true;
+            function mangleable_var(var_def) {
+                var value = var_def.value;
+                if (!(value instanceof AST_SymbolRef)) return;
+                if (value.name == "arguments") return;
+                var def = value.definition();
+                if (def.undeclared) return;
+                return value_def = def;
             }
 
             function get_lhs(expr) {
index 10735b2..e89d44d 100644 (file)
@@ -3578,3 +3578,43 @@ issue_2436_14: {
     }
     expect_stdout: true
 }
+
+issue_2497: {
+    options = {
+        collapse_vars: true,
+        unused: true,
+    }
+    input: {
+        function sample() {
+            if (true) {
+                for (var i = 0; i < 1; ++i) {
+                    for (var k = 0; k < 1; ++k) {
+                        var value = 1;
+                        var x = value;
+                        value = x ? x + 1 : 0;
+                    }
+                }
+            } else {
+                for (var i = 0; i < 1; ++i) {
+                    for (var k = 0; k < 1; ++k) {
+                        var value = 1;
+                    }
+                }
+            }
+        }
+    }
+    expect: {
+        function sample() {
+            if (true)
+                for (i = 0; i < 1; ++i)
+                    for (k = 0; k < 1; ++k) {
+                        value = 1;
+                        value = value ? value + 1 : 0;
+                    }
+            else
+                for (var i = 0; i < 1; ++i)
+                    for (var k = 0; k < 1; ++k)
+                        var value=1;
+        }
+    }
+}