fix corner case in `switches` (#3585)
authorAlex Lam S.L <alexlamsl@gmail.com>
Wed, 13 Nov 2019 18:29:55 +0000 (02:29 +0800)
committerGitHub <noreply@github.com>
Wed, 13 Nov 2019 18:29:55 +0000 (02:29 +0800)
lib/compress.js
test/compress/switch.js

index e97427b..668293d 100644 (file)
@@ -4872,25 +4872,23 @@ merge(Compressor.prototype, {
                     prev.body = [];
                 }
             }
-            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);
-            }
+            body.push(branch);
         }
         while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]);
-        if (body.length > 0) {
-            body[0].body = decl.concat(body[0].body);
-        }
-        self.body = body;
         while (branch = body[body.length - 1]) {
             var stat = branch.body[branch.body.length - 1];
             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 (branch === default_branch) {
+                if (!is_body_empty(branch)) break;
+            } else if (branch.expression.has_side_effects(compressor)) {
+                break;
+            } else if (default_branch) {
+                if (!is_body_empty(default_branch)) break;
+                if (body[body.length - 2] !== default_branch) break;
+                default_branch.body = default_branch.body.concat(branch.body);
+                branch.body = [];
+            } else if (!is_body_empty(branch)) break;
+            eliminate_branch(branch);
             if (body.pop() === default_branch) default_branch = null;
         }
         if (body.length == 0) {
@@ -4900,6 +4898,8 @@ merge(Compressor.prototype, {
                 }))
             }).optimize(compressor);
         }
+        body[0].body = decl.concat(body[0].body);
+        self.body = body;
         if (body.length == 1 && (body[0] === exact_match || body[0] === default_branch)) {
             var has_break = false;
             var tw = new TreeWalker(function(node) {
@@ -4929,6 +4929,16 @@ merge(Compressor.prototype, {
             return node instanceof AST_Break && tw.loopcontrol_target(node) === self;
         }
 
+        function is_body_empty(branch) {
+            return all(branch.body, function(stat) {
+                return is_empty(stat)
+                    || stat instanceof AST_Defun
+                    || stat instanceof AST_Var && all(stat.definitions, function(var_def) {
+                        return !var_def.value;
+                    });
+            });
+        }
+
         function eliminate_branch(branch, prev) {
             if (prev && !aborts(prev)) {
                 prev.body = prev.body.concat(branch.body);
index b41247b..1de676e 100644 (file)
@@ -393,6 +393,57 @@ drop_case_2: {
     }
 }
 
+drop_case_3: {
+    options = {
+        dead_code: true,
+        switches: true,
+    }
+    input: {
+        var c = "PASS";
+        switch ({}.p) {
+          default:
+          case void 0:
+            break;
+          case c = "FAIL":
+        }
+        console.log(c);
+    }
+    expect: {
+        var c = "PASS";
+        switch ({}.p) {
+          default:
+          case void 0:
+            break;
+          case c = "FAIL":
+        }
+        console.log(c);
+    }
+    expect_stdout: "PASS"
+}
+
+drop_case_4: {
+    options = {
+        dead_code: true,
+        switches: true,
+    }
+    input: {
+        switch (0) {
+          case [ a, typeof b ]:
+          default:
+            var a;
+        }
+        console.log("PASS");
+    }
+    expect: {
+        switch (0) {
+          case [ a, typeof b ]:
+            var a;
+        }
+        console.log("PASS");
+    }
+    expect_stdout: "PASS"
+}
+
 keep_case: {
     options = {
         dead_code: true,
@@ -521,7 +572,7 @@ issue_1674: {
     expect_stdout: "PASS"
 }
 
-issue_1679_1: {
+issue_1679: {
     options = {
         dead_code: true,
         evaluate: true,
@@ -548,34 +599,6 @@ issue_1679_1: {
         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) {
@@ -589,23 +612,6 @@ issue_1679_2: {
                 }
                 break;
               case (a++):
-                break;
-            }
-        }
-        f();
-        console.log(a, b);
-    }
-    expect: {
-        var a = 100, b = 10;
-        function f() {
-            switch (--b) {
-              case b--:
-                switch (0) {
-                  default:
-                  case a--:
-                }
-                break;
-              case (a++):
             }
         }
         f();
@@ -998,3 +1004,27 @@ drop_switch_3: {
     }
     expect_stdout: "PASS"
 }
+
+drop_switch_4: {
+    options = {
+        dead_code: true,
+        switches: true,
+    }
+    input: {
+        var a = "FAIL";
+        switch (0) {
+          default:
+          case a:
+            var b = a = "PASS";
+            break;
+        }
+        console.log(a);
+    }
+    expect: {
+        var a = "FAIL";
+        0;
+        var b = a = "PASS";
+        console.log(a);
+    }
+    expect_stdout: "PASS"
+}