From: Alex Lam S.L Date: Sat, 19 Dec 2020 17:24:29 +0000 (+0000) Subject: fix corner case in `inline` (#4418) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=882968c68c79a0f285d59f4b7ea50a62dc9ba1b6;p=UglifyJS.git fix corner case in `inline` (#4418) fixes #4417 --- diff --git a/lib/ast.js b/lib/ast.js index e966cefa..f319a42d 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -578,6 +578,10 @@ var AST_Arrow = DEFNODE("Arrow", "inlined value", { }, }, AST_Lambda); +function is_async(node) { + return node instanceof AST_AsyncDefun || node instanceof AST_AsyncFunction; +} + var AST_AsyncFunction = DEFNODE("AsyncFunction", "inlined name", { $documentation: "An asynchronous function expression", $propdoc: { diff --git a/lib/compress.js b/lib/compress.js index 5081120c..d99310ed 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -7772,7 +7772,7 @@ merge(Compressor.prototype, { }); if (can_inline && stat instanceof AST_Return) { var value = stat.value; - if (exp === fn && (!value || value.is_constant_expression())) { + if (exp === fn && (!value || value.is_constant_expression() && safe_from_await(value))) { var args = self.args.concat(value || make_node(AST_Undefined, self)); return make_sequence(self, args).optimize(compressor); } @@ -7861,6 +7861,26 @@ merge(Compressor.prototype, { } return try_evaluate(compressor, self); + function safe_from_await(node) { + if (!is_async(scope || compressor.find_parent(AST_Scope))) return true; + var safe = true; + var tw = new TreeWalker(function(node) { + if (!safe) return true; + if (node instanceof AST_Scope) { + if (node === fn) return; + if (node instanceof AST_Arrow) { + for (var i = 0; safe && i < node.argnames.length; i++) node.argnames[i].walk(tw); + } else if (is_defun(node) && node.name.name == "await") { + safe = false; + } + return true; + } + if (node instanceof AST_Symbol && node.name == "await" && node !== fn.name) safe = false; + }); + node.walk(tw); + return safe; + } + function return_value(stat) { if (!stat) return make_node(AST_Undefined, self); if (stat instanceof AST_Return) return stat.value || make_node(AST_Undefined, self); @@ -7927,8 +7947,7 @@ merge(Compressor.prototype, { } if (node instanceof AST_Scope) return abort = true; if (verify_await && node instanceof AST_Symbol && node.name == "await") { - var scope = compressor.find_parent(AST_Scope); - if (scope instanceof AST_AsyncDefun || scope instanceof AST_AsyncFunction) return abort = true; + if (is_async(compressor.find_parent(AST_Scope))) return abort = true; verify_await = false; } if (node instanceof AST_SymbolRef) { @@ -8031,18 +8050,7 @@ merge(Compressor.prototype, { } while (!(scope instanceof AST_Scope)); insert = scope.body.indexOf(child) + 1; if (!insert) return false; - if (scope instanceof AST_AsyncDefun || scope instanceof AST_AsyncFunction) { - var found = false; - fn.walk(new TreeWalker(function(node) { - if (found) return true; - if (node instanceof AST_Scope && node !== fn) { - if (is_defun(node) && node.name.name == "await") found = true; - return true; - } - if (node instanceof AST_Symbol && node.name == "await" && node !== fn.name) return found = true; - })); - if (found) return false; - } + if (!safe_from_await(fn)) return false; var safe_to_inject = exp !== fn || fn.parent_scope.resolve() === scope; if (scope instanceof AST_Toplevel) { if (compressor.toplevel.vars) { diff --git a/test/compress/async.js b/test/compress/async.js index 4fd16efd..d73bba41 100644 --- a/test/compress/async.js +++ b/test/compress/async.js @@ -597,3 +597,25 @@ issue_4406: { expect_stdout: "PASS" node_version: ">=8" } + +issue_4417: { + options = { + inline: true, + } + input: { + (async function() { + console.log(function() { + return await => 0; + }().prototype); + })(); + } + expect: { + (async function() { + console.log(function() { + return await => 0; + }().prototype); + })(); + } + expect_stdout: "undefined" + node_version: ">=8" +}