fix corner cases with asynchronous generators (#4642)
authorAlex Lam S.L <alexlamsl@gmail.com>
Wed, 10 Feb 2021 15:41:00 +0000 (15:41 +0000)
committerGitHub <noreply@github.com>
Wed, 10 Feb 2021 15:41:00 +0000 (23:41 +0800)
fixes #4641

lib/compress.js
test/compress/collapse_vars.js
test/compress/reduce_vars.js
test/compress/yields.js

index 8b5b020..3d85719 100644 (file)
@@ -1307,6 +1307,10 @@ merge(Compressor.prototype, {
         return found;
     });
 
+    function in_async_generator(scope) {
+        return scope instanceof AST_AsyncGeneratorDefun || scope instanceof AST_AsyncGeneratorFunction;
+    }
+
     function find_scope(compressor) {
         var level = 0, node;
         while (node = compressor.parent(level++)) {
@@ -2987,7 +2991,9 @@ merge(Compressor.prototype, {
                 var stat = statements[i];
                 if (prev) {
                     if (stat instanceof AST_Exit) {
-                        stat.value = cons_seq(stat.value || make_node(AST_Undefined, stat)).transform(compressor);
+                        if (stat.value || !in_async_generator(scope)) {
+                            stat.value = cons_seq(stat.value || make_node(AST_Undefined, stat)).transform(compressor);
+                        }
                     } else if (stat instanceof AST_For) {
                         if (!(stat.init instanceof AST_Definitions)) {
                             var abort = false;
@@ -11045,7 +11051,10 @@ merge(Compressor.prototype, {
     });
 
     OPT(AST_Return, function(self, compressor) {
-        if (self.value && is_undefined(self.value, compressor)) {
+        if (compressor.option("side_effects")
+            && self.value
+            && is_undefined(self.value, compressor)
+            && !in_async_generator(compressor.find_parent(AST_Scope))) {
             self.value = null;
         }
         return self;
index 04df8e1..fe963b4 100644 (file)
@@ -5879,6 +5879,7 @@ collapse_rhs_this: {
 collapse_rhs_undefined: {
     options = {
         collapse_vars: true,
+        side_effects: true,
     }
     input: {
         var a, b;
index 185a39c..5ae0884 100644 (file)
@@ -2460,6 +2460,7 @@ delay_def: {
         evaluate: true,
         reduce_funcs: true,
         reduce_vars: true,
+        side_effects: true,
         unused: true,
     }
     input: {
index 78a5389..eac47e2 100644 (file)
@@ -889,3 +889,64 @@ issue_4639_2: {
     expect_stdout: "undefined"
     node_version: ">=4"
 }
+
+issue_4641_1: {
+    options = {
+        sequences: true,
+    }
+    input: {
+        console.log(typeof async function*() {
+            try {
+                console.log("foo");
+                return;
+            } finally {
+                console.log("bar");
+            }
+        }().next().then);
+    }
+    expect: {
+        console.log(typeof async function*() {
+            try {
+                console.log("foo");
+                return;
+            } finally {
+                console.log("bar");
+            }
+        }().next().then);
+    }
+    expect_stdout: [
+        "foo",
+        "bar",
+        "function",
+    ]
+    node_version: ">=10"
+}
+
+issue_4641_2: {
+    options = {
+        side_effects: true,
+    }
+    input: {
+        console.log(typeof async function*() {
+            try {
+                return void "FAIL";
+            } finally {
+                console.log("PASS");
+            }
+        }().next().then);
+    }
+    expect: {
+        console.log(typeof async function*() {
+            try {
+                return void 0;
+            } finally {
+                console.log("PASS");
+            }
+        }().next().then);
+    }
+    expect_stdout: [
+        "function",
+        "PASS",
+    ]
+    node_version: ">=10"
+}