fix corner cases with `await` (#4350)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 8 Dec 2020 03:26:03 +0000 (03:26 +0000)
committerGitHub <noreply@github.com>
Tue, 8 Dec 2020 03:26:03 +0000 (11:26 +0800)
fixes #4349

lib/ast.js
lib/compress.js
lib/parse.js
test/compress/async.js

index 0605fb8..262372e 100644 (file)
@@ -551,7 +551,7 @@ function is_function(node) {
     return node instanceof AST_AsyncFunction || node instanceof AST_Function;
 }
 
-var AST_AsyncFunction = DEFNODE("AsyncFunction", null, {
+var AST_AsyncFunction = DEFNODE("AsyncFunction", "inlined", {
     $documentation: "An asynchronous function expression",
     _validate: function() {
         if (this.name != null) {
@@ -573,7 +573,7 @@ function is_defun(node) {
     return node instanceof AST_AsyncDefun || node instanceof AST_Defun;
 }
 
-var AST_AsyncDefun = DEFNODE("AsyncDefun", null, {
+var AST_AsyncDefun = DEFNODE("AsyncDefun", "inlined", {
     $documentation: "An asynchronous function definition",
     _validate: function() {
         if (!(this.name instanceof AST_SymbolDefun)) throw new Error("name must be AST_SymbolDefun");
index 8936125..144a533 100644 (file)
@@ -927,6 +927,7 @@ merge(Compressor.prototype, {
             return true;
         });
         def(AST_Lambda, function(tw, descend, compressor) {
+            this.inlined = false;
             push(tw);
             reset_variables(tw, compressor, this);
             descend();
@@ -1630,7 +1631,7 @@ merge(Compressor.prototype, {
                     var assign_used = false;
                     var can_replace = !args || !hit;
                     if (!can_replace) {
-                        for (var j = compressor.self().argnames.lastIndexOf(candidate.name) + 1; !abort && j < args.length; j++) {
+                        for (var j = scope.argnames.lastIndexOf(candidate.name) + 1; !abort && j < args.length; j++) {
                             args[j].transform(scanner);
                         }
                         can_replace = true;
@@ -1819,7 +1820,7 @@ merge(Compressor.prototype, {
 
             function extract_args() {
                 var iife, fn = compressor.self();
-                if (fn instanceof AST_Function
+                if (is_function(fn)
                     && !fn.name
                     && !fn.uses_arguments
                     && !fn.pinned()
@@ -1830,6 +1831,29 @@ merge(Compressor.prototype, {
                     })) {
                     var fn_strict = compressor.has_directive("use strict");
                     if (fn_strict && !member(fn_strict, fn.body)) fn_strict = false;
+                    var has_await = fn instanceof AST_AsyncFunction ? function(node) {
+                        return node instanceof AST_Symbol && node.name == "await";
+                    } : function(node) {
+                        return node instanceof AST_Await && !tw.find_parent(AST_Scope);
+                    };
+                    var tw = new TreeWalker(function(node) {
+                        if (!arg) return true;
+                        if (has_await(node)) {
+                            arg = null;
+                            return true;
+                        }
+                        if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) {
+                            var s = node.definition().scope;
+                            if (s !== scope) while (s = s.parent_scope) {
+                                if (s === scope) return true;
+                            }
+                            arg = null;
+                        }
+                        if (node instanceof AST_This && (fn_strict || !tw.find_parent(AST_Scope))) {
+                            arg = null;
+                            return true;
+                        }
+                    });
                     var len = fn.argnames.length;
                     args = iife.args.slice(len);
                     var names = Object.create(null);
@@ -1852,20 +1876,7 @@ merge(Compressor.prototype, {
                         } else if (arg instanceof AST_Lambda && arg.pinned()) {
                             arg = null;
                         } else {
-                            arg.walk(new TreeWalker(function(node) {
-                                if (!arg) return true;
-                                if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) {
-                                    var s = node.definition().scope;
-                                    if (s !== scope) while (s = s.parent_scope) {
-                                        if (s === scope) return true;
-                                    }
-                                    arg = null;
-                                }
-                                if (node instanceof AST_This && (fn_strict || !this.find_parent(AST_Scope))) {
-                                    arg = null;
-                                    return true;
-                                }
-                            }));
+                            arg.walk(tw);
                         }
                         if (arg) candidates.unshift([ make_node(AST_VarDef, sym, {
                             name: sym,
@@ -8982,7 +8993,7 @@ merge(Compressor.prototype, {
                         single_use = fixed.is_constant_expression(self.scope);
                         if (single_use == "f") {
                             var scope = self.scope;
-                            do if (scope instanceof AST_Defun || scope instanceof AST_Function) {
+                            do if (is_defun(scope) || is_function(scope)) {
                                 scope.inlined = true;
                             } while (scope = scope.parent_scope);
                         }
index 5a07ef6..21e6055 100644 (file)
@@ -1638,6 +1638,7 @@ function parse($TEXT, options) {
     function maybe_await() {
         var start = S.token;
         if (!(S.in_async && is("name", "await"))) return maybe_unary();
+        S.input.context().regex_allowed = true;
         next();
         return new AST_Await({
             start: start,
index 4f34289..3011a6a 100644 (file)
@@ -387,3 +387,60 @@ issue_4347_2: {
     expect_stdout: "PASS"
     node_version: ">=8"
 }
+
+issue_4349_1: {
+    input: {
+        console.log(typeof async function() {
+            await /abc/;
+        }().then);
+    }
+    expect_exact: "console.log(typeof async function(){await/abc/}().then);"
+    expect_stdout: "function"
+    node_version: ">=8"
+}
+
+issue_4349_2: {
+    options = {
+        collapse_vars: true,
+        unused: true,
+    }
+    input: {
+        console.log(typeof async function() {
+            (function(a) {
+                this[a];
+            }(await 0));
+        }().then);
+    }
+    expect: {
+        console.log(typeof async function() {
+            (function(a) {
+                this[a];
+            }(await 0));
+        }().then);
+    }
+    expect_stdout: "function"
+    node_version: ">=8"
+}
+
+issue_4349_3: {
+    options = {
+        collapse_vars: true,
+        unused: true,
+    }
+    input: {
+        console.log(typeof function(await) {
+            return async function(a) {
+                this[a];
+            }(await);
+        }(this).then);
+    }
+    expect: {
+        console.log(typeof function(await) {
+            return async function(a) {
+                this[a];
+            }(await);
+        }(this).then);
+    }
+    expect_stdout: "function"
+    node_version: ">=8"
+}