enhance if_return (#5518)
This commit is contained in:
@@ -3391,6 +3391,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var changed = false;
|
var changed = false;
|
||||||
var parent = compressor.parent();
|
var parent = compressor.parent();
|
||||||
var self = compressor.self();
|
var self = compressor.self();
|
||||||
|
var exit, exit_defs, merge_exit;
|
||||||
var in_iife = in_lambda && parent && parent.TYPE == "Call" && parent.expression === self;
|
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 chain_if_returns = in_lambda && compressor.option("conditionals") && compressor.option("sequences");
|
||||||
var multiple_if_returns = has_multiple_if_returns(statements);
|
var multiple_if_returns = has_multiple_if_returns(statements);
|
||||||
@@ -3446,6 +3447,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
stat.condition = cond;
|
stat.condition = cond;
|
||||||
statements[j] = stat.body;
|
statements[j] = stat.body;
|
||||||
stat.body = next;
|
stat.body = next;
|
||||||
|
if (next === exit) exit = null;
|
||||||
statements[i] = stat;
|
statements[i] = stat;
|
||||||
statements[i] = stat.transform(compressor);
|
statements[i] = stat.transform(compressor);
|
||||||
continue;
|
continue;
|
||||||
@@ -3489,6 +3491,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
changed = true;
|
changed = true;
|
||||||
stat = stat.clone();
|
stat = stat.clone();
|
||||||
stat.alternative = next;
|
stat.alternative = next;
|
||||||
|
if (next === exit) exit = null;
|
||||||
statements.splice(i, 1, stat.transform(compressor));
|
statements.splice(i, 1, stat.transform(compressor));
|
||||||
statements.splice(j, 1);
|
statements.splice(j, 1);
|
||||||
continue;
|
continue;
|
||||||
@@ -3532,6 +3535,11 @@ Compressor.prototype.compress = function(node) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stat instanceof AST_Exit) {
|
||||||
|
exit = stat;
|
||||||
|
exit_defs = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
|
|
||||||
@@ -3553,7 +3561,25 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function can_drop_abort(ab) {
|
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;
|
if (!(ab instanceof AST_LoopControl)) return false;
|
||||||
var lct = compressor.loopcontrol_target(ab);
|
var lct = compressor.loopcontrol_target(ab);
|
||||||
if (ab instanceof AST_Continue) return match_target(loop_body(lct));
|
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) {
|
function can_merge_flow(ab) {
|
||||||
|
merge_exit = false;
|
||||||
if (!can_drop_abort(ab)) return false;
|
if (!can_drop_abort(ab)) return false;
|
||||||
for (var j = statements.length; --j > i;) {
|
for (var j = statements.length; --j > i;) {
|
||||||
var stat = statements[j];
|
var stat = statements[j];
|
||||||
@@ -3581,7 +3608,16 @@ Compressor.prototype.compress = function(node) {
|
|||||||
function extract_functions() {
|
function extract_functions() {
|
||||||
var defuns = [];
|
var defuns = [];
|
||||||
var lexical = false;
|
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) {
|
if (stat instanceof AST_LambdaDefinition) {
|
||||||
defuns.push(stat);
|
defuns.push(stat);
|
||||||
return false;
|
return false;
|
||||||
@@ -3600,7 +3636,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
block = last.body;
|
block = last.body;
|
||||||
}
|
}
|
||||||
block.pop();
|
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;
|
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"
|
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: {
|
do_if_continue_1: {
|
||||||
options = {
|
options = {
|
||||||
if_return: true,
|
if_return: true,
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ if_return: {
|
|||||||
if (w) {
|
if (w) {
|
||||||
if (y) return;
|
if (y) return;
|
||||||
} else if (z) 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