enhance if_return (#5518)

This commit is contained in:
Alex Lam S.L
2022-06-23 17:52:22 +01:00
committed by GitHub
parent 933ca9ddd8
commit 9f57920566
4 changed files with 187 additions and 4 deletions

View File

@@ -3391,6 +3391,7 @@ Compressor.prototype.compress = function(node) {
var changed = false;
var parent = compressor.parent();
var self = compressor.self();
var exit, exit_defs, merge_exit;
var in_iife = in_lambda && parent && parent.TYPE == "Call" && parent.expression === self;
var chain_if_returns = in_lambda && compressor.option("conditionals") && compressor.option("sequences");
var multiple_if_returns = has_multiple_if_returns(statements);
@@ -3446,6 +3447,7 @@ Compressor.prototype.compress = function(node) {
stat.condition = cond;
statements[j] = stat.body;
stat.body = next;
if (next === exit) exit = null;
statements[i] = stat;
statements[i] = stat.transform(compressor);
continue;
@@ -3489,6 +3491,7 @@ Compressor.prototype.compress = function(node) {
changed = true;
stat = stat.clone();
stat.alternative = next;
if (next === exit) exit = null;
statements.splice(i, 1, stat.transform(compressor));
statements.splice(j, 1);
continue;
@@ -3532,6 +3535,11 @@ Compressor.prototype.compress = function(node) {
continue;
}
}
if (stat instanceof AST_Exit) {
exit = stat;
exit_defs = null;
}
}
return changed;
@@ -3553,7 +3561,25 @@ Compressor.prototype.compress = function(node) {
}
function can_drop_abort(ab) {
if (ab instanceof AST_Return) return in_lambda && is_undefined(ab.value);
if (ab instanceof AST_Exit) {
if (exit && exit.equivalent_to(ab)) {
if (!exit_defs) {
exit_defs = new Dictionary();
exit.walk(new TreeWalker(function(node) {
if (node instanceof AST_SymbolRef) exit_defs.set(node.name, node.definition());
}));
}
var abort = false;
ab.walk(new TreeWalker(function(node) {
if (abort) return true;
if (node instanceof AST_SymbolRef && exit_defs.get(node.name) !== node.definition()) {
return abort = true;
}
}));
if (!abort) return merge_exit = true;
}
return in_lambda && ab instanceof AST_Return && is_undefined(ab.value);
}
if (!(ab instanceof AST_LoopControl)) return false;
var lct = compressor.loopcontrol_target(ab);
if (ab instanceof AST_Continue) return match_target(loop_body(lct));
@@ -3562,6 +3588,7 @@ Compressor.prototype.compress = function(node) {
}
function can_merge_flow(ab) {
merge_exit = false;
if (!can_drop_abort(ab)) return false;
for (var j = statements.length; --j > i;) {
var stat = statements[j];
@@ -3581,7 +3608,16 @@ Compressor.prototype.compress = function(node) {
function extract_functions() {
var defuns = [];
var lexical = false;
var tail = statements.splice(i + 1).filter(function(stat) {
var start = i + 1;
var end;
if (merge_exit) {
end = statements.lastIndexOf(exit);
if (end < 0) end = statements.length;
} else {
end = statements.length;
exit = null;
}
var tail = statements.splice(start, end - start).filter(function(stat) {
if (stat instanceof AST_LambdaDefinition) {
defuns.push(stat);
return false;
@@ -3600,7 +3636,7 @@ Compressor.prototype.compress = function(node) {
block = last.body;
}
block.pop();
if (ab.value) block.push(make_node(AST_SimpleStatement, ab.value, { body: ab.value }));
if (!merge_exit && ab.value) block.push(make_node(AST_SimpleStatement, ab.value, { body: ab.value }));
return body;
}

View File

@@ -850,3 +850,116 @@ issue_866_2: {
})();
}
}
identical_returns_1: {
options = {
conditionals: true,
if_return: true,
}
input: {
console.log(function() {
if (console.log("foo"))
return 42;
else
while (console.log("bar"));
return 42;
}());
}
expect: {
console.log(function() {
if (!console.log("foo"))
while (console.log("bar"));
return 42;
}());
}
expect_stdout: [
"foo",
"bar",
"42",
]
}
identical_returns_2: {
options = {
conditionals: true,
if_return: true,
}
input: {
console.log(function() {
if (console.log("foo"))
while (console.log("FAIL"));
else
return "bar";
return "bar";
}());
}
expect: {
console.log(function() {
if (console.log("foo"))
while (console.log("FAIL"));
return "bar";
}());
}
expect_stdout: [
"foo",
"bar",
]
}
identical_returns_3: {
options = {
if_return: true,
}
input: {
function f(a) {
if (a)
return 42;
if (a)
return;
return 42;
}
if (f(console))
console.log("PASS");
}
expect: {
function f(a) {
if (a)
return 42;
if (a)
;
else
return 42;
}
if (f(console))
console.log("PASS");
}
expect_stdout: "PASS"
}
issue_4374: {
options = {
booleans: true,
conditionals: true,
if_return: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
console.log(f(console));
function f(a) {
if (console) return 0;
if (a) return 1;
return 0;
}
})();
}
expect: {
(function() {
console.log(function(a) {
return !console && a ? 1 : 0;
}(console));
})();
}
expect_stdout: "0"
}

View File

@@ -892,6 +892,40 @@ if_return_2: {
node_version: ">=4"
}
if_return_3: {
options = {
if_return: true,
}
input: {
"use strict";
var a = "PASS";
function f(b) {
if (console) {
let b = a;
return b;
} else
while (console.log("FAIL 1"));
return b;
}
console.log(f("FAIL 2"));
}
expect: {
"use strict";
var a = "PASS";
function f(b) {
if (console) {
let b = a;
return b;
} else
while (console.log("FAIL 1"));
return b;
}
console.log(f("FAIL 2"));
}
expect_stdout: "PASS"
node_version: ">=4"
}
do_if_continue_1: {
options = {
if_return: true,

View File

@@ -127,7 +127,7 @@ if_return: {
if (w) {
if (y) return;
} else if (z) return;
return x == y || (x && w(), y && z()), !0;
return x != y && (x && w(), y && z()), !0;
}
}
}