enhance if_return (#5518)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user