aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-12-19 17:24:29 +0000
committerGitHub <noreply@github.com>2020-12-20 01:24:29 +0800
commit882968c68c79a0f285d59f4b7ea50a62dc9ba1b6 (patch)
tree05f9d2b3b8891fedb4c9a45633e26ba3385aace7
parentacc2d7d8455ed7302a78948b3c8678990dc1765a (diff)
downloadtracifyjs-882968c68c79a0f285d59f4b7ea50a62dc9ba1b6.tar.gz
tracifyjs-882968c68c79a0f285d59f4b7ea50a62dc9ba1b6.zip
fix corner case in `inline` (#4418)
fixes #4417
-rw-r--r--lib/ast.js4
-rw-r--r--lib/compress.js38
-rw-r--r--test/compress/async.js22
3 files changed, 49 insertions, 15 deletions
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"
+}