enhance if_return (#5326)

This commit is contained in:
Alex Lam S.L
2022-01-30 22:32:25 +00:00
committed by GitHub
parent 0a5a1f3687
commit d7eb80b050
2 changed files with 82 additions and 7 deletions

View File

@@ -3295,6 +3295,7 @@ Compressor.prototype.compress = function(node) {
var changed = false; var changed = false;
var parent = compressor.parent(); var parent = compressor.parent();
var in_iife = in_lambda && parent && parent.TYPE == "Call"; var in_iife = in_lambda && parent && parent.TYPE == "Call";
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);
for (var i = statements.length; --i >= 0;) { for (var i = statements.length; --i >= 0;) {
var stat = statements[i]; var stat = statements[i];
@@ -3421,20 +3422,27 @@ Compressor.prototype.compress = function(node) {
// if sequences is not enabled, this can lead to an endless loop (issue #866). // if sequences is not enabled, this can lead to an endless loop (issue #866).
// however, with sequences on this helps producing slightly better output for // however, with sequences on this helps producing slightly better output for
// the example code. // the example code.
var prev = statements[prev_index(i)]; var prev, prev_stat;
if (compressor.option("sequences") && in_lambda && !stat.alternative if (chain_if_returns && !stat.alternative
&& (!prev && in_iife || prev instanceof AST_If && prev.body instanceof AST_Return) && (!(prev_stat = statements[prev = prev_index(i)]) && in_iife
|| prev_stat instanceof AST_If && prev_stat.body instanceof AST_Return)
&& next_index(j) == statements.length && next instanceof AST_SimpleStatement) { && next_index(j) == statements.length && next instanceof AST_SimpleStatement) {
changed = true; changed = true;
var exprs = [];
var args = prev_stat ? trim_defns(prev, exprs) : [ i, 1 ];
stat = stat.clone(); stat = stat.clone();
exprs.push(stat.condition);
stat.condition = make_sequence(stat, exprs);
stat.alternative = make_node(AST_BlockStatement, next, { stat.alternative = make_node(AST_BlockStatement, next, {
body: [ body: [
next, next,
make_node(AST_Return, next, { value: null }), make_node(AST_Return, next, { value: null }),
], ],
}); });
statements.splice(i, 1, stat.transform(compressor)); args.push(stat.transform(compressor));
statements.splice(j, 1); statements.splice(j, 1);
[].splice.apply(statements, args);
i = prev + 1;
continue; continue;
} }
} }
@@ -3519,10 +3527,31 @@ Compressor.prototype.compress = function(node) {
function prev_index(i) { function prev_index(i) {
for (var j = i; --j >= 0;) { for (var j = i; --j >= 0;) {
if (!is_declaration(statements[j])) break; if (!(statements[j] instanceof AST_Var)) break;
} }
return j; return j;
} }
function trim_defns(j, exprs) {
var args = [ j + 1, i - j ];
var var_defs = [];
while (++j < i) {
var stat = statements[j];
stat.remove_initializers(compressor, var_defs);
stat.definitions.forEach(function(var_def) {
if (!var_def.value) return;
exprs.push(make_node(AST_Assign, var_def, {
operator: "=",
left: var_def.name.convert_symbol(AST_SymbolRef, function(ref) {
ref.definition().references.push(ref);
}),
right: var_def.value,
}));
});
}
if (var_defs.length > 0) args.push(make_node(AST_Var, stat, { definitions: var_defs }));
return args;
}
} }
function eliminate_dead_code(statements, compressor) { function eliminate_dead_code(statements, compressor) {
@@ -9223,7 +9252,7 @@ Compressor.prototype.compress = function(node) {
left: var_def.name.convert_symbol(AST_SymbolRef, function(ref) { left: var_def.name.convert_symbol(AST_SymbolRef, function(ref) {
refs.push(ref); refs.push(ref);
}), }),
right: var_def.value right: var_def.value,
})); }));
} }
} }

View File

@@ -327,7 +327,7 @@ issue_512: {
} }
} }
if_var_return: { if_var_return_1: {
options = { options = {
conditionals: true, conditionals: true,
if_return: true, if_return: true,
@@ -373,6 +373,52 @@ if_var_return: {
} }
} }
if_var_return_2: {
options = {
conditionals: true,
if_return: true,
sequences: true,
}
input: {
(function() {
var a = w();
if (x())
return y();
z();
})();
}
expect: {
(function() {
var a = w();
return x() ? y() : (z(), void 0);
})();
}
}
if_var_return_3: {
options = {
conditionals: true,
if_return: true,
sequences: true,
}
input: {
function f() {
if (u())
return v();
var a = w();
if (x())
return y();
z();
}
}
expect: {
function f() {
return u() ? v() : (a = w(), x() ? y() : (z(), void 0));
var a;
}
}
}
if_if_return_return: { if_if_return_return: {
options = { options = {
conditionals: true, conditionals: true,