enhance if_return (#5541)

This commit is contained in:
Alex Lam S.L 2022-07-06 21:28:00 +01:00 committed by GitHub
parent 0207b46d70
commit c8d98f4787
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 118 additions and 27 deletions

View File

@ -3411,20 +3411,20 @@ Compressor.prototype.compress = function(node) {
if (in_lambda && !next && stat instanceof AST_Return if (in_lambda && !next && stat instanceof AST_Return
&& !(in_try && in_try.bfinally && in_async_generator(in_lambda))) { && !(in_try && in_try.bfinally && in_async_generator(in_lambda))) {
if (!stat.value) { var body = stat.value;
if (!body) {
changed = true; changed = true;
statements.splice(i, 1); statements.splice(i, 1);
continue; continue;
} }
var tail = stat.value.tail_node(); var tail = body.tail_node();
if (tail instanceof AST_UnaryPrefix && tail.operator == "void") { if (is_undefined(tail)) {
changed = true; changed = true;
var body; if (body instanceof AST_UnaryPrefix) {
if (tail === stat.value) { body = body.expression;
body = tail.expression; } else if (tail instanceof AST_UnaryPrefix) {
} else { body = body.clone();
body = stat.value.clone(); body.expressions[body.expressions.length - 1] = tail.expression;
body.expressions[body.length - 1] = tail.expression;
} }
statements[i] = make_node(AST_SimpleStatement, stat, { body: body }); statements[i] = make_node(AST_SimpleStatement, stat, { body: body });
continue; continue;
@ -3573,14 +3573,18 @@ Compressor.prototype.compress = function(node) {
}); });
} }
function match_return(ab) { function match_return(ab, exact) {
if (!exit) return false; if (!exit) return false;
if (exit.TYPE != ab.TYPE) return false; if (exit.TYPE != ab.TYPE) return false;
var value = ab.value; var value = ab.value;
if (!value) return false;
var equals = exit.equivalent_to(ab); var equals = exit.equivalent_to(ab);
if (!equals && value instanceof AST_Sequence) { if (!equals && value instanceof AST_Sequence) {
value = value.tail_node(); value = value.tail_node();
equals = exit.value ? exit.value.equivalent_to(value) : is_undefined(value); if (exit.value && exit.value.equivalent_to(value)) equals = 2;
}
if (!equals && !exact && exit.value instanceof AST_Sequence) {
if (exit.value.tail_node().equivalent_to(value)) equals = 3;
} }
if (!equals) return false; if (!equals) return false;
if (exit_defs == null) { if (exit_defs == null) {
@ -3591,19 +3595,22 @@ Compressor.prototype.compress = function(node) {
if (!exit_defs.size()) exit_defs = false; if (!exit_defs.size()) exit_defs = false;
} }
var abort = false; var abort = false;
if (value && exit_defs) value.walk(new TreeWalker(function(node) { if (exit_defs) value.walk(new TreeWalker(function(node) {
if (abort) return true; if (abort) return true;
if (node instanceof AST_SymbolRef && exit_defs.get(node.name) !== node.definition()) { if (node instanceof AST_SymbolRef && exit_defs.get(node.name) !== node.definition()) {
return abort = true; return abort = true;
} }
})); }));
return !abort; return !abort && equals;
} }
function can_drop_abort(ab) { function can_drop_abort(ab) {
if (ab instanceof AST_Exit) { if (ab instanceof AST_Exit) {
if (match_return(ab)) return merge_exit = true; if (merge_exit = match_return(ab)) return true;
return in_lambda && ab instanceof AST_Return && is_undefined(ab.value); if (!in_lambda) return false;
if (!(ab instanceof AST_Return)) return false;
if (is_undefined(ab.value)) return true;
return ab.value instanceof AST_Sequence && is_undefined(ab.value.tail_node());
} }
if (!(ab instanceof AST_LoopControl)) return false; if (!(ab instanceof AST_LoopControl)) return false;
var lct = compressor.loopcontrol_target(ab); var lct = compressor.loopcontrol_target(ab);
@ -3650,17 +3657,23 @@ Compressor.prototype.compress = function(node) {
if (is_lexical_definition(stat)) lexical = true; if (is_lexical_definition(stat)) lexical = true;
return true; return true;
}); });
if (merge_exit === 3) {
tail.push(make_node(AST_SimpleStatement, exit.value, {
body: make_sequence(exit.value, exit.value.expressions.slice(0, -1)),
}));
exit.value = exit.value.tail_node();
}
[].push.apply(lexical ? tail : statements, defuns); [].push.apply(lexical ? tail : statements, defuns);
return tail; return tail;
} }
function trim_return(value) { function trim_return(value, mode) {
if (!value) return; if (value) switch (mode) {
if (exit.value) { case 3:
if (exit.value.TYPE == value.TYPE) return; if (!(value instanceof AST_Sequence)) break;
if (value instanceof AST_Sequence) return make_sequence(value, value.expressions.slice(0, -1)); case 2:
return make_sequence(value, value.expressions.slice(0, -1));
} }
return value;
} }
function as_statement_array_with_return(node, ab) { function as_statement_array_with_return(node, ab) {
@ -3671,7 +3684,7 @@ Compressor.prototype.compress = function(node) {
} }
block.pop(); block.pop();
var value = ab.value; var value = ab.value;
if (merge_exit) value = trim_return(value); if (merge_exit) value = trim_return(value, merge_exit);
if (value) block.push(make_node(AST_SimpleStatement, value, { body: value })); if (value) block.push(make_node(AST_SimpleStatement, value, { body: value }));
return body; return body;
} }
@ -3711,8 +3724,9 @@ Compressor.prototype.compress = function(node) {
function eliminate_returns(stat, in_block) { function eliminate_returns(stat, in_block) {
if (stat instanceof AST_Exit) { if (stat instanceof AST_Exit) {
if (match_return(stat)) { var mode = match_return(stat, true);
var value = trim_return(stat.value); if (mode) {
var value = trim_return(stat.value, mode);
if (value) return make_node(AST_SimpleStatement, value, { body: value }); if (value) return make_node(AST_SimpleStatement, value, { body: value });
return in_block ? null : make_node(AST_EmptyStatement, stat); return in_block ? null : make_node(AST_EmptyStatement, stat);
} }

View File

@ -1283,7 +1283,7 @@ sequence_void_1: {
expect: { expect: {
function f() { function f() {
if (console) if (console)
return console, void console.log("PASS"); console, void console.log("PASS");
} }
f(); f();
} }
@ -1309,10 +1309,87 @@ sequence_void_2: {
function f() { function f() {
if (console) if (console)
console, void console.log("PASS"); console, void console.log("PASS");
else {
return; return;
FAIL; FAIL;
} }
}
f(); f();
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
tail_match: {
options = {
if_return: true,
}
input: {
function f(a) {
if (a) {
console.log("foo");
return console.log("bar");
}
while (console.log("baz"));
return console.log("moo"), console.log("bar");
}
f();
f(42);
}
expect: {
function f(a) {
if (a)
console.log("foo");
else {
while (console.log("baz"));
console.log("moo");
}
return console.log("bar");
}
f();
f(42);
}
expect_stdout: [
"baz",
"moo",
"bar",
"foo",
"bar",
]
}
void_match: {
options = {
if_return: true,
}
input: {
function f(a) {
if (a) {
console.log("foo");
return;
}
while (console.log("bar"));
return console.log("baz"), void console.log("moo");
}
f();
f(42);
}
expect: {
function f(a) {
if (a)
console.log("foo");
else {
while (console.log("bar"));
console.log("baz"),
console.log("moo");
}
}
f();
f(42);
}
expect_stdout: [
"bar",
"baz",
"moo",
"foo",
]
}