enhance `switches` (#3583)
authorAlex Lam S.L <alexlamsl@gmail.com>
Wed, 13 Nov 2019 12:03:48 +0000 (20:03 +0800)
committerGitHub <noreply@github.com>
Wed, 13 Nov 2019 12:03:48 +0000 (20:03 +0800)
lib/compress.js
test/compress/switch.js

index de07080..92e8d3a 100644 (file)
@@ -4828,10 +4828,12 @@ merge(Compressor.prototype, {
         for (var i = 0, len = self.body.length; i < len && !exact_match; i++) {
             branch = self.body[i];
             if (branch instanceof AST_Default) {
-                if (!default_branch) {
-                    default_branch = branch;
+                var prev = body[body.length - 1];
+                if (default_branch || is_break(branch.body[0], compressor) && (!prev || aborts(prev))) {
+                    eliminate_branch(branch, prev);
+                    continue;
                 } else {
-                    eliminate_branch(branch, body[body.length - 1]);
+                    default_branch = branch;
                 }
             } else if (!(value instanceof AST_Node)) {
                 var exp = branch.expression.evaluate(compressor);
@@ -4857,7 +4859,14 @@ merge(Compressor.prototype, {
                     prev.body = [];
                 }
             }
-            body.push(branch);
+            if (default_branch
+                && default_branch.body.length == 0
+                && body[body.length - 1] === default_branch
+                && !branch.expression.has_side_effects(compressor)) {
+                default_branch.body = branch.body.slice();
+            } else {
+                body.push(branch);
+            }
         }
         while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]);
         if (body.length > 0) {
@@ -4866,8 +4875,7 @@ merge(Compressor.prototype, {
         self.body = body;
         while (branch = body[body.length - 1]) {
             var stat = branch.body[branch.body.length - 1];
-            if (stat instanceof AST_Break && compressor.loopcontrol_target(stat) === self)
-                branch.body.pop();
+            if (is_break(stat, compressor)) branch.body.pop();
             if (branch.body.length || branch instanceof AST_Case
                 && (default_branch || branch.expression.has_side_effects(compressor))) break;
             if (body.pop() === default_branch) default_branch = null;
@@ -4885,8 +4893,7 @@ merge(Compressor.prototype, {
                 if (has_break
                     || node instanceof AST_Lambda
                     || node instanceof AST_SimpleStatement) return true;
-                if (node instanceof AST_Break && tw.loopcontrol_target(node) === self)
-                    has_break = true;
+                if (is_break(node, tw)) has_break = true;
             });
             self.walk(tw);
             if (!has_break) {
@@ -4905,6 +4912,10 @@ merge(Compressor.prototype, {
         }
         return self;
 
+        function is_break(node, tw) {
+            return node instanceof AST_Break && tw.loopcontrol_target(node) === self;
+        }
+
         function eliminate_branch(branch, prev) {
             if (prev && !aborts(prev)) {
                 prev.body = prev.body.concat(branch.body);
index 547843f..b41247b 100644 (file)
@@ -261,13 +261,13 @@ drop_default_1: {
     }
     input: {
         switch (foo) {
-          case 'bar': baz();
+          case "bar": baz();
           default:
         }
     }
     expect: {
         switch (foo) {
-          case 'bar': baz();
+          case "bar": baz();
         }
     }
 }
@@ -279,14 +279,14 @@ drop_default_2: {
     }
     input: {
         switch (foo) {
-          case 'bar': baz(); break;
+          case "bar": baz(); break;
           default:
             break;
         }
     }
     expect: {
         switch (foo) {
-          case 'bar': baz();
+          case "bar": baz();
         }
     }
 }
@@ -298,7 +298,7 @@ keep_default: {
     }
     input: {
         switch (foo) {
-          case 'bar': baz();
+          case "bar": baz();
           default:
             something();
             break;
@@ -306,7 +306,7 @@ keep_default: {
     }
     expect: {
         switch (foo) {
-          case 'bar': baz();
+          case "bar": baz();
           default:
             something();
         }
@@ -347,21 +347,48 @@ issue_1663: {
     expect_stdout: true
 }
 
-drop_case: {
+drop_case_1: {
     options = {
         dead_code: true,
         switches: true,
     }
     input: {
         switch (foo) {
-          case 'bar': baz(); break;
-          case 'moo':
+          case "bar": baz(); break;
+          case "moo":
             break;
         }
     }
     expect: {
         switch (foo) {
-          case 'bar': baz();
+          case "bar": baz();
+        }
+    }
+}
+
+drop_case_2: {
+    options = {
+        dead_code: true,
+        switches: true,
+    }
+    input: {
+        switch (foo) {
+          case "bar":
+            bar();
+            break;
+          default:
+          case "moo":
+            moo();
+            break;
+        }
+    }
+    expect: {
+        switch (foo) {
+          case "bar":
+            bar();
+            break;
+          default:
+            moo();
         }
     }
 }
@@ -373,14 +400,14 @@ keep_case: {
     }
     input: {
         switch (foo) {
-          case 'bar': baz(); break;
+          case "bar": baz(); break;
           case moo:
             break;
         }
     }
     expect: {
         switch (foo) {
-          case 'bar': baz(); break;
+          case "bar": baz(); break;
           case moo:
         }
     }
@@ -494,7 +521,7 @@ issue_1674: {
     expect_stdout: "PASS"
 }
 
-issue_1679: {
+issue_1679_1: {
     options = {
         dead_code: true,
         evaluate: true,
@@ -521,6 +548,34 @@ issue_1679: {
         console.log(a, b);
     }
     expect: {
+        var a = 100, b = 10;
+        function f() {
+            switch (--b) {
+              default:
+                break;
+              case b--:
+                switch (0) {
+                  default:
+                  case a--:
+                }
+                break;
+              case (a++):
+            }
+        }
+        f();
+        console.log(a, b);
+    }
+    expect_stdout: "99 8"
+}
+
+issue_1679_2: {
+    options = {
+        dead_code: true,
+        evaluate: true,
+        passes: 2,
+        switches: true,
+    }
+    input: {
         var a = 100, b = 10;
         function f() {
             switch (--b) {
@@ -534,12 +589,29 @@ issue_1679: {
                 }
                 break;
               case (a++):
+                break;
             }
         }
         f();
         console.log(a, b);
     }
-    expect_stdout: true
+    expect: {
+        var a = 100, b = 10;
+        function f() {
+            switch (--b) {
+              case b--:
+                switch (0) {
+                  default:
+                  case a--:
+                }
+                break;
+              case (a++):
+            }
+        }
+        f();
+        console.log(a, b);
+    }
+    expect_stdout: "99 8"
 }
 
 issue_1680_1: {
@@ -864,3 +936,65 @@ issue_1750: {
     }
     expect_stdout: "0 2"
 }
+
+drop_switch_1: {
+    options = {
+        dead_code: true,
+        switches: true,
+    }
+    input: {
+        switch (foo) {
+          default:
+            break;
+          case "bar":
+            break;
+        }
+    }
+    expect: {
+        foo;
+    }
+}
+
+drop_switch_2: {
+    options = {
+        dead_code: true,
+        switches: true,
+    }
+    input: {
+        switch (foo) {
+          default:
+          case "bar":
+            baz();
+        }
+    }
+    expect: {
+        foo;
+        baz();
+    }
+}
+
+drop_switch_3: {
+    options = {
+        dead_code: true,
+        switches: true,
+    }
+    input: {
+        console.log(function() {
+            switch (0) {
+              default:
+                return "PASS";
+              case 1:
+            }
+        }());
+    }
+    expect: {
+        console.log(function() {
+            switch (0) {
+              default:
+                return "PASS";
+              case 1:
+            }
+        }());
+    }
+    expect_stdout: "PASS"
+}