enhance if_return (#5541)
This commit is contained in:
parent
0207b46d70
commit
c8d98f4787
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user