better solution for the last test in constant switch folding
authorMihai Bazon <mihai@bazon.net>
Wed, 14 Nov 2012 10:21:43 +0000 (12:21 +0200)
committerMihai Bazon <mihai@bazon.net>
Wed, 14 Nov 2012 10:21:43 +0000 (12:21 +0200)
lib/compress.js
test/compress/switch.js

index 89be0ce..66375be 100644 (file)
@@ -1368,7 +1368,8 @@ merge(Compressor.prototype, {
             self.expression = exp[0];
             if (!compressor.option("dead_code")) break out;
             var value = exp[1];
-            var in_substat = false;
+            var in_if = false;
+            var in_block = false;
             var started = false;
             var stopped = false;
             var ruined = false;
@@ -1377,32 +1378,36 @@ merge(Compressor.prototype, {
                     // no need to descend these node types
                     return node;
                 }
-                else if (node instanceof AST_Switch) {
-                    if (node === self) {
-                        node = node.clone();
-                        descend(node, this);
-                        return ruined ? node : make_node(AST_BlockStatement, node, {
-                            body: node.body.reduce(function(a, branch){
-                                return a.concat(branch.body);
-                            }, [])
-                        }).transform(compressor);
-                    }
+                else if (node instanceof AST_Switch && node === self) {
+                    node = node.clone();
+                    descend(node, this);
+                    return ruined ? node : make_node(AST_BlockStatement, node, {
+                        body: node.body.reduce(function(a, branch){
+                            return a.concat(branch.body);
+                        }, [])
+                    }).transform(compressor);
                 }
-                else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch || node instanceof AST_Try) {
-                    var save_substat = in_substat;
-                    in_substat = true;
+                else if (node instanceof AST_If || node instanceof AST_Try) {
+                    var save = in_if;
+                    in_if = !in_block;
                     descend(node, this);
-                    in_substat = save_substat;
+                    in_if = save;
+                    return node;
+                }
+                else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) {
+                    var save = in_block;
+                    in_block = true;
+                    descend(node, this);
+                    in_block = save;
                     return node;
                 }
                 else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) {
-                    if (in_substat) {
-                        // won't handle situations like if (foo) break;
+                    if (in_if) {
                         ruined = true;
                         return node;
-                    } else {
-                        stopped = true;
                     }
+                    if (in_block) return node;
+                    stopped = true;
                     return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
                 }
                 else if (node instanceof AST_SwitchBranch && this.parent() === self) {
index 7c1e021..6fde5dd 100644 (file)
@@ -176,11 +176,35 @@ constant_switch_8: {
         }
     }
     expect: {
+        OUT: {
+            x();
+            for (;;) break OUT;
+            y();
+        }
+    }
+}
+
+constant_switch_9: {
+    options = { dead_code: true, evaluate: true };
+    input: {
         OUT: switch (1) {
           case 1:
             x();
-            for (;;) break OUT;
+            for (;;) if (foo) break OUT;
             y();
+          case 1+1:
+            bar();
+          default:
+            def();
+        }
+    }
+    expect: {
+        OUT: {
+            x();
+            for (;;) if (foo) break OUT;
+            y();
+            bar();
+            def();
         }
     }
 }