fix corner case in `merge_vars` (#4238)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sat, 24 Oct 2020 02:19:43 +0000 (03:19 +0100)
committerGitHub <noreply@github.com>
Sat, 24 Oct 2020 02:19:43 +0000 (10:19 +0800)
fixes #4237

lib/compress.js
test/compress/merge_vars.js

index e4479ca..c6e27e0 100644 (file)
@@ -4468,6 +4468,35 @@ merge(Compressor.prototype, {
                 });
                 return true;
             }
+            if (node instanceof AST_Continue) {
+                var target = tw.loopcontrol_target(node);
+                if (!(target instanceof AST_Do)) return true;
+                var stack = [];
+                while (!HOP(segment, "block") || segment.block !== target) {
+                    stack.push(segment);
+                    pop();
+                }
+                segment.loop = "c";
+                push();
+                while (stack.length) {
+                    var seg = stack.pop();
+                    push();
+                    if (HOP(seg, "block")) segment.block = seg.block;
+                    if (HOP(seg, "loop")) segment.loop = seg.loop;
+                }
+                return true;
+            }
+            if (node instanceof AST_Do) {
+                push();
+                segment.block = node;
+                segment.loop = true;
+                var save = segment;
+                node.body.walk(tw);
+                if (segment.loop == "c") segment = save;
+                node.condition.walk(tw);
+                pop();
+                return true;
+            }
             if (node instanceof AST_For) {
                 if (node.init) node.init.walk(tw);
                 push();
@@ -4501,14 +4530,6 @@ merge(Compressor.prototype, {
                 }
                 return true;
             }
-            if (node instanceof AST_IterationStatement) {
-                push();
-                segment.block = node;
-                segment.loop = true;
-                descend();
-                pop();
-                return true;
-            }
             if (node instanceof AST_LabeledStatement) {
                 push();
                 segment.block = node;
@@ -4601,6 +4622,14 @@ merge(Compressor.prototype, {
                 }
                 return true;
             }
+            if (node instanceof AST_While) {
+                push();
+                segment.block = node;
+                segment.loop = true;
+                descend();
+                pop();
+                return true;
+            }
         });
         tw.directives = Object.create(compressor.directives);
         self.walk(tw);
index 28a0135..6ada929 100644 (file)
@@ -3011,3 +3011,84 @@ issue_4168_use_strict: {
     }
     expect_stdout: "PASS true 42"
 }
+
+issue_4237_1: {
+    options = {
+        merge_vars: true,
+    }
+    input: {
+        console.log(function(a) {
+            do {
+                var b = a++;
+                if (b)
+                    return "FAIL";
+                continue;
+                var c = 42;
+            } while ("undefined" != typeof c);
+            return "PASS";
+        }(0));
+    }
+    expect: {
+        console.log(function(a) {
+            do {
+                var b = a++;
+                if (b)
+                    return "FAIL";
+                continue;
+                var c = 42;
+            } while ("undefined" != typeof c);
+            return "PASS";
+        }(0));
+    }
+    expect_stdout: "PASS"
+}
+
+issue_4237_2: {
+    options = {
+        dead_code: true,
+        evaluate: true,
+        loops: true,
+        merge_vars: true,
+        switches: true,
+    }
+    input: {
+        console.log(function(a) {
+            do {
+                switch (0) {
+                  case 0:
+                    var b = a++;
+                  default:
+                    while (b)
+                        return "FAIL";
+                }
+                try {
+                    var c = 0;
+                } finally {
+                    continue;
+                }
+                var d = 0;
+            } while ("undefined" != typeof d);
+            return "PASS";
+        }(0));
+    }
+    expect: {
+        console.log(function(a) {
+            do {
+                switch (0) {
+                  case 0:
+                    var b = a++;
+                    if (b)
+                        return "FAIL";
+                }
+                try {
+                    var c = 0;
+                } finally {
+                    continue;
+                }
+                var d = 0;
+            } while ("undefined" != typeof d);
+            return "PASS";
+        }(0));
+    }
+    expect_stdout: "PASS"
+}