Skip to content

Commit e1b03d0

Browse files
authored
fix corner case in inline (#5529)
fixes #5528
1 parent f1b3e9d commit e1b03d0

File tree

4 files changed

+210
-53
lines changed

4 files changed

+210
-53
lines changed

lib/compress.js

Lines changed: 52 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -13475,7 +13475,7 @@ Compressor.prototype.compress = function(node) {
1347513475
def(AST_Assign, noop);
1347613476
def(AST_Await, function(compressor, scope, no_return, in_loop) {
1347713477
var self = this;
13478-
var inlined = sync(self.expression).try_inline(compressor, scope, no_return, in_loop);
13478+
var inlined = self.expression.try_inline(compressor, scope, no_return, in_loop, true);
1347913479
if (!inlined) return;
1348013480
if (!no_return) scan_local_returns(inlined, function(node) {
1348113481
node.in_bool = false;
@@ -13490,35 +13490,13 @@ Compressor.prototype.compress = function(node) {
1349013490
body: make_node(AST_Await, self, { expression: make_node(AST_Number, self, { value: 0 })}),
1349113491
}) ],
1349213492
});
13493-
13494-
function sync(node) {
13495-
if (!no_return) return node;
13496-
if (node.TYPE != "Call") return node;
13497-
var fn = node.expression;
13498-
switch (fn.CTOR) {
13499-
case AST_AsyncArrow:
13500-
fn = make_node(AST_Arrow, fn, fn);
13501-
break;
13502-
case AST_AsyncFunction:
13503-
fn = make_node(AST_Function, fn, fn);
13504-
break;
13505-
case AST_AsyncGeneratorFunction:
13506-
fn = make_node(AST_GeneratorFunction, fn, fn);
13507-
break;
13508-
default:
13509-
return node;
13510-
}
13511-
node = node.clone();
13512-
node.expression = fn;
13513-
return node;
13514-
}
1351513493
});
13516-
def(AST_Binary, function(compressor, scope, no_return, in_loop) {
13494+
def(AST_Binary, function(compressor, scope, no_return, in_loop, in_await) {
1351713495
if (no_return === undefined) return;
1351813496
var self = this;
1351913497
var op = self.operator;
1352013498
if (!lazy_op[op]) return;
13521-
var inlined = self.right.try_inline(compressor, scope, no_return, in_loop);
13499+
var inlined = self.right.try_inline(compressor, scope, no_return, in_loop, in_await);
1352213500
if (!inlined) return;
1352313501
return make_node(AST_If, self, {
1352413502
condition: make_condition(self.left),
@@ -13554,7 +13532,7 @@ Compressor.prototype.compress = function(node) {
1355413532
body[last] = inlined;
1355513533
return this;
1355613534
});
13557-
def(AST_Call, function(compressor, scope, no_return, in_loop) {
13535+
def(AST_Call, function(compressor, scope, no_return, in_loop, in_await) {
1355813536
if (compressor.option("inline") < 4) return;
1355913537
var call = this;
1356013538
if (call.is_expr_pure(compressor)) return;
@@ -13587,7 +13565,7 @@ Compressor.prototype.compress = function(node) {
1358713565
}
1358813566
defined.set("arguments", true);
1358913567
}
13590-
var async = is_async(fn);
13568+
var async = !in_await && is_async(fn);
1359113569
if (async) {
1359213570
if (!compressor.option("awaits")) return;
1359313571
if (!is_async(scope)) return;
@@ -13629,15 +13607,40 @@ Compressor.prototype.compress = function(node) {
1362913607
if (has_arg_refs(fn, fn.rest)) return;
1363013608
simple_argnames = false;
1363113609
}
13632-
if (no_return && !all(fn.body, function(stat) {
13633-
var abort = false;
13634-
stat.walk(new TreeWalker(function(node) {
13635-
if (abort) return true;
13636-
if (async && node instanceof AST_Await || node instanceof AST_Return) return abort = true;
13637-
if (node instanceof AST_Scope && node !== fn) return true;
13638-
}));
13639-
return !abort;
13640-
})) return;
13610+
var verify_body;
13611+
if (no_return) {
13612+
verify_body = function(stat) {
13613+
var abort = false;
13614+
stat.walk(new TreeWalker(function(node) {
13615+
if (abort) return true;
13616+
if (async && node instanceof AST_Await || node instanceof AST_Return) return abort = true;
13617+
if (node instanceof AST_Scope) return true;
13618+
}));
13619+
return !abort;
13620+
};
13621+
} else if (in_await && !is_async(fn)) {
13622+
verify_body = function(stat) {
13623+
var abort = false;
13624+
var find_return = new TreeWalker(function(node) {
13625+
if (abort) return true;
13626+
if (node instanceof AST_Return) return abort = true;
13627+
if (node instanceof AST_Scope) return true;
13628+
});
13629+
stat.walk(new TreeWalker(function(node) {
13630+
if (abort) return true;
13631+
if (node instanceof AST_Try) {
13632+
if (node.bfinally && all(node.body, function(stat) {
13633+
stat.walk(find_return);
13634+
return !abort;
13635+
}) && node.bcatch) node.bcatch.walk(find_return);
13636+
return true;
13637+
}
13638+
if (node instanceof AST_Scope) return true;
13639+
}));
13640+
return !abort;
13641+
};
13642+
}
13643+
if (verify_body && !all(fn.body, verify_body)) return;
1364113644
if (!safe_from_await_yield(fn, avoid_await_yield(compressor, scope))) return;
1364213645
fn.functions.each(function(def, name) {
1364313646
scope.functions.set(name, def);
@@ -13737,10 +13740,10 @@ Compressor.prototype.compress = function(node) {
1373713740
syms.add(def.id, sym);
1373813741
}
1373913742
});
13740-
def(AST_Conditional, function(compressor, scope, no_return, in_loop) {
13743+
def(AST_Conditional, function(compressor, scope, no_return, in_loop, in_await) {
1374113744
var self = this;
13742-
var body = self.consequent.try_inline(compressor, scope, no_return, in_loop);
13743-
var alt = self.alternative.try_inline(compressor, scope, no_return, in_loop);
13745+
var body = self.consequent.try_inline(compressor, scope, no_return, in_loop, in_await);
13746+
var alt = self.alternative.try_inline(compressor, scope, no_return, in_loop, in_await);
1374413747
if (!body && !alt) return;
1374513748
return make_node(AST_If, self, {
1374613749
condition: self.condition,
@@ -13775,7 +13778,7 @@ Compressor.prototype.compress = function(node) {
1377513778
if (body) this.body = body;
1377613779
var obj = this.object;
1377713780
if (obj instanceof AST_Sequence) {
13778-
var inlined = inline_sequence(compressor, scope, true, in_loop, obj, 1);
13781+
var inlined = inline_sequence(compressor, scope, true, in_loop, false, obj, 1);
1377913782
if (inlined) {
1378013783
this.object = obj.tail_node();
1378113784
inlined.body.push(this);
@@ -13794,7 +13797,7 @@ Compressor.prototype.compress = function(node) {
1379413797
}
1379513798
var cond = this.condition;
1379613799
if (cond instanceof AST_Sequence) {
13797-
var inlined = inline_sequence(compressor, scope, true, in_loop, cond, 1);
13800+
var inlined = inline_sequence(compressor, scope, true, in_loop, false, cond, 1);
1379813801
if (inlined) {
1379913802
this.condition = cond.tail_node();
1380013803
inlined.body.push(this);
@@ -13826,10 +13829,10 @@ Compressor.prototype.compress = function(node) {
1382613829
var value = this.value;
1382713830
return value && value.try_inline(compressor, scope, undefined, in_loop === "try");
1382813831
});
13829-
function inline_sequence(compressor, scope, no_return, in_loop, node, skip) {
13832+
function inline_sequence(compressor, scope, no_return, in_loop, in_await, node, skip) {
1383013833
var body = [], exprs = node.expressions, no_ret = no_return;
13831-
for (var i = exprs.length - (skip || 0), j = i; --i >= 0; no_ret = true) {
13832-
var inlined = exprs[i].try_inline(compressor, scope, no_ret, in_loop);
13834+
for (var i = exprs.length - (skip || 0), j = i; --i >= 0; no_ret = true, in_await = false) {
13835+
var inlined = exprs[i].try_inline(compressor, scope, no_ret, in_loop, in_await);
1383313836
if (!inlined) continue;
1383413837
flush();
1383513838
body.push(inlined);
@@ -13848,8 +13851,8 @@ Compressor.prototype.compress = function(node) {
1384813851
j = i;
1384913852
}
1385013853
}
13851-
def(AST_Sequence, function(compressor, scope, no_return, in_loop) {
13852-
return inline_sequence(compressor, scope, no_return, in_loop, this);
13854+
def(AST_Sequence, function(compressor, scope, no_return, in_loop, in_await) {
13855+
return inline_sequence(compressor, scope, no_return, in_loop, in_await, this);
1385313856
});
1385413857
def(AST_SimpleStatement, function(compressor, scope, no_return, in_loop) {
1385513858
var body = this.body;
@@ -13865,12 +13868,12 @@ Compressor.prototype.compress = function(node) {
1386513868
});
1386613869
return body.try_inline(compressor, scope, no_return || false, in_loop);
1386713870
});
13868-
def(AST_UnaryPrefix, function(compressor, scope, no_return, in_loop) {
13871+
def(AST_UnaryPrefix, function(compressor, scope, no_return, in_loop, in_await) {
1386913872
var self = this;
1387013873
var op = self.operator;
1387113874
if (unary_side_effects[op]) return;
1387213875
if (!no_return && op == "void") no_return = false;
13873-
var inlined = self.expression.try_inline(compressor, scope, no_return, in_loop);
13876+
var inlined = self.expression.try_inline(compressor, scope, no_return, in_loop, in_await);
1387413877
if (!inlined) return;
1387513878
if (!no_return) scan_local_returns(inlined, function(node) {
1387613879
node.in_bool = false;
@@ -13888,7 +13891,7 @@ Compressor.prototype.compress = function(node) {
1388813891
if (body) this.body = body;
1388913892
var exp = this.expression;
1389013893
if (exp instanceof AST_Sequence) {
13891-
var inlined = inline_sequence(compressor, scope, true, in_loop, exp, 1);
13894+
var inlined = inline_sequence(compressor, scope, true, in_loop, false, exp, 1);
1389213895
if (inlined) {
1389313896
this.expression = exp.tail_node();
1389413897
inlined.body.push(this);

test/compress/awaits.js

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3023,3 +3023,157 @@ issue_5506: {
30233023
expect_stdout: "PASS"
30243024
node_version: ">=8"
30253025
}
3026+
3027+
issue_5528_1: {
3028+
options = {
3029+
inline: true,
3030+
}
3031+
input: {
3032+
(async function() {
3033+
await function() {
3034+
try {
3035+
return;
3036+
} finally {
3037+
console.log("foo");
3038+
}
3039+
}();
3040+
})();
3041+
console.log("bar");
3042+
}
3043+
expect: {
3044+
(async function() {
3045+
await function() {
3046+
try {
3047+
return;
3048+
} finally {
3049+
console.log("foo");
3050+
}
3051+
}();
3052+
})();
3053+
console.log("bar");
3054+
}
3055+
expect_stdout: [
3056+
"foo",
3057+
"bar",
3058+
]
3059+
node_version: ">=8"
3060+
}
3061+
3062+
issue_5528_2: {
3063+
options = {
3064+
inline: true,
3065+
}
3066+
input: {
3067+
(async function() {
3068+
await function() {
3069+
try {
3070+
return 42;
3071+
} finally {
3072+
console.log("foo");
3073+
}
3074+
}();
3075+
})();
3076+
console.log("bar");
3077+
}
3078+
expect: {
3079+
(async function() {
3080+
await function() {
3081+
try {
3082+
return 42;
3083+
} finally {
3084+
console.log("foo");
3085+
}
3086+
}();
3087+
})();
3088+
console.log("bar");
3089+
}
3090+
expect_stdout: [
3091+
"foo",
3092+
"bar",
3093+
]
3094+
node_version: ">=8"
3095+
}
3096+
3097+
issue_5528_3: {
3098+
options = {
3099+
inline: true,
3100+
}
3101+
input: {
3102+
(async function() {
3103+
await function() {
3104+
try {
3105+
FAIL;
3106+
} catch (e) {
3107+
return console.log("foo");
3108+
} finally {
3109+
console.log("bar");
3110+
}
3111+
}();
3112+
})();
3113+
console.log("baz");
3114+
}
3115+
expect: {
3116+
(async function() {
3117+
await function() {
3118+
try {
3119+
FAIL;
3120+
} catch (e) {
3121+
return console.log("foo");
3122+
} finally {
3123+
console.log("bar");
3124+
}
3125+
}();
3126+
})();
3127+
console.log("baz");
3128+
}
3129+
expect_stdout: [
3130+
"foo",
3131+
"bar",
3132+
"baz",
3133+
]
3134+
node_version: ">=8"
3135+
}
3136+
3137+
issue_5528_4: {
3138+
options = {
3139+
inline: true,
3140+
}
3141+
input: {
3142+
(async function() {
3143+
await function() {
3144+
try {
3145+
return {
3146+
then() {
3147+
console.log("foo");
3148+
},
3149+
};
3150+
} finally {
3151+
console.log("bar");
3152+
}
3153+
}();
3154+
})();
3155+
console.log("baz");
3156+
}
3157+
expect: {
3158+
(async function() {
3159+
await function() {
3160+
try {
3161+
return {
3162+
then() {
3163+
console.log("foo");
3164+
},
3165+
};
3166+
} finally {
3167+
console.log("bar");
3168+
}
3169+
}();
3170+
})();
3171+
console.log("baz");
3172+
}
3173+
expect_stdout: [
3174+
"bar",
3175+
"baz",
3176+
"foo",
3177+
]
3178+
node_version: ">=8"
3179+
}

test/reduce.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -778,9 +778,9 @@ function compare_run_code(code, minify_options, result_cache, max_timeout) {
778778
function run(code, timeout) {
779779
if (minify_options.module) code = [
780780
'"use strict";',
781-
"(async function(){",
781+
"(async ()=>{",
782782
code,
783-
"})();"
783+
"})().catch(e=>console.log(e));",
784784
].join("\n");
785785
return run_code(code, toplevel, result_cache, timeout);
786786
}

test/ufuzz/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,9 +2104,9 @@ if (require.main !== module) {
21042104
function run_code(code, toplevel, timeout) {
21052105
if (async && has_await) code = [
21062106
'"use strict";',
2107-
"(async function(){",
2107+
"(async ()=>{",
21082108
code,
2109-
"})();"
2109+
"})().catch(e=>console.log(e));",
21102110
].join("\n");
21112111
return sandbox.run_code(sandbox.patch_module_statements(code), toplevel, timeout);
21122112
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy