Skip to content

Commit

Permalink
enhance if_return (#5541)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl committed Jul 6, 2022
1 parent 0207b46 commit c8d98f4
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 27 deletions.
62 changes: 38 additions & 24 deletions lib/compress.js
Expand Up @@ -3411,20 +3411,20 @@ Compressor.prototype.compress = function(node) {

if (in_lambda && !next && stat instanceof AST_Return
&& !(in_try && in_try.bfinally && in_async_generator(in_lambda))) {
if (!stat.value) {
var body = stat.value;
if (!body) {
changed = true;
statements.splice(i, 1);
continue;
}
var tail = stat.value.tail_node();
if (tail instanceof AST_UnaryPrefix && tail.operator == "void") {
var tail = body.tail_node();
if (is_undefined(tail)) {
changed = true;
var body;
if (tail === stat.value) {
body = tail.expression;
} else {
body = stat.value.clone();
body.expressions[body.length - 1] = tail.expression;
if (body instanceof AST_UnaryPrefix) {
body = body.expression;
} else if (tail instanceof AST_UnaryPrefix) {
body = body.clone();
body.expressions[body.expressions.length - 1] = tail.expression;
}
statements[i] = make_node(AST_SimpleStatement, stat, { body: body });
continue;
Expand Down Expand Up @@ -3573,14 +3573,18 @@ Compressor.prototype.compress = function(node) {
});
}

function match_return(ab) {
function match_return(ab, exact) {
if (!exit) return false;
if (exit.TYPE != ab.TYPE) return false;
var value = ab.value;
if (!value) return false;
var equals = exit.equivalent_to(ab);
if (!equals && value instanceof AST_Sequence) {
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 (exit_defs == null) {
Expand All @@ -3591,19 +3595,22 @@ Compressor.prototype.compress = function(node) {
if (!exit_defs.size()) exit_defs = 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 (node instanceof AST_SymbolRef && exit_defs.get(node.name) !== node.definition()) {
return abort = true;
}
}));
return !abort;
return !abort && equals;
}

function can_drop_abort(ab) {
if (ab instanceof AST_Exit) {
if (match_return(ab)) return merge_exit = true;
return in_lambda && ab instanceof AST_Return && is_undefined(ab.value);
if (merge_exit = match_return(ab)) return true;
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;
var lct = compressor.loopcontrol_target(ab);
Expand Down Expand Up @@ -3650,17 +3657,23 @@ Compressor.prototype.compress = function(node) {
if (is_lexical_definition(stat)) lexical = 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);
return tail;
}

function trim_return(value) {
if (!value) return;
if (exit.value) {
if (exit.value.TYPE == value.TYPE) return;
if (value instanceof AST_Sequence) return make_sequence(value, value.expressions.slice(0, -1));
function trim_return(value, mode) {
if (value) switch (mode) {
case 3:
if (!(value instanceof AST_Sequence)) break;
case 2:
return make_sequence(value, value.expressions.slice(0, -1));
}
return value;
}

function as_statement_array_with_return(node, ab) {
Expand All @@ -3671,7 +3684,7 @@ Compressor.prototype.compress = function(node) {
}
block.pop();
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 }));
return body;
}
Expand Down Expand Up @@ -3711,8 +3724,9 @@ Compressor.prototype.compress = function(node) {

function eliminate_returns(stat, in_block) {
if (stat instanceof AST_Exit) {
if (match_return(stat)) {
var value = trim_return(stat.value);
var mode = match_return(stat, true);
if (mode) {
var value = trim_return(stat.value, mode);
if (value) return make_node(AST_SimpleStatement, value, { body: value });
return in_block ? null : make_node(AST_EmptyStatement, stat);
}
Expand Down
83 changes: 80 additions & 3 deletions test/compress/if_return.js
Expand Up @@ -1283,7 +1283,7 @@ sequence_void_1: {
expect: {
function f() {
if (console)
return console, void console.log("PASS");
console, void console.log("PASS");
}
f();
}
Expand All @@ -1309,10 +1309,87 @@ sequence_void_2: {
function f() {
if (console)
console, void console.log("PASS");
return;
FAIL;
else {
return;
FAIL;
}
}
f();
}
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",
]
}

0 comments on commit c8d98f4

Please sign in to comment.