enhance if_return (#5594)
This commit is contained in:
139
lib/compress.js
139
lib/compress.js
@@ -3451,7 +3451,7 @@ Compressor.prototype.compress = function(node) {
|
||||
var changed = false;
|
||||
var parent = compressor.parent();
|
||||
var self = compressor.self();
|
||||
var jump, merge_jump;
|
||||
var declare_only, jump, merge_jump;
|
||||
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);
|
||||
@@ -3460,7 +3460,7 @@ Compressor.prototype.compress = function(node) {
|
||||
var j = next_index(i);
|
||||
var next = statements[j];
|
||||
|
||||
if (in_lambda && !next && stat instanceof AST_Return
|
||||
if (in_lambda && declare_only && !next && stat instanceof AST_Return
|
||||
&& !(self instanceof AST_SwitchBranch)
|
||||
&& !(in_try && in_try.bfinally && in_async_generator(in_lambda))) {
|
||||
var body = stat.value;
|
||||
@@ -3493,7 +3493,7 @@ Compressor.prototype.compress = function(node) {
|
||||
body: as_statement_array_with_return(stat.body, ab),
|
||||
});
|
||||
stat.alternative = make_node(AST_BlockStatement, stat, {
|
||||
body: as_statement_array(stat.alternative).concat(extract_functions()),
|
||||
body: as_statement_array(stat.alternative).concat(extract_functions(merge_jump, jump)),
|
||||
});
|
||||
statements[i] = stat;
|
||||
statements[i] = stat.transform(compressor);
|
||||
@@ -3502,15 +3502,17 @@ Compressor.prototype.compress = function(node) {
|
||||
|
||||
if (ab && !stat.alternative && next instanceof AST_Jump) {
|
||||
var cond = stat.condition;
|
||||
cond = best_of_expression(cond, cond.negate(compressor), stat.body instanceof AST_BlockStatement);
|
||||
var preference = i + 1 == j && stat.body instanceof AST_BlockStatement;
|
||||
cond = best_of_expression(cond, cond.negate(compressor), preference);
|
||||
if (cond !== stat.condition) {
|
||||
changed = true;
|
||||
stat = stat.clone();
|
||||
stat.condition = cond;
|
||||
statements[j] = stat.body;
|
||||
stat.body = next;
|
||||
if (next === jump) jump = null;
|
||||
statements[i] = stat;
|
||||
var body = stat.body;
|
||||
stat.body = make_node(AST_BlockStatement, next, {
|
||||
body: extract_functions(true, null, j + 1),
|
||||
});
|
||||
statements.splice(i, 1, stat, body);
|
||||
statements[i] = stat.transform(compressor);
|
||||
continue;
|
||||
}
|
||||
@@ -3522,7 +3524,7 @@ Compressor.prototype.compress = function(node) {
|
||||
changed = true;
|
||||
stat = stat.clone();
|
||||
stat.body = make_node(AST_BlockStatement, stat.body, {
|
||||
body: as_statement_array(stat.body).concat(extract_functions()),
|
||||
body: as_statement_array(stat.body).concat(extract_functions(merge_jump, jump)),
|
||||
});
|
||||
stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
|
||||
body: as_statement_array_with_return(stat.alternative, alt),
|
||||
@@ -3551,38 +3553,26 @@ Compressor.prototype.compress = function(node) {
|
||||
if (!stat.alternative && next instanceof AST_Return) {
|
||||
changed = true;
|
||||
stat = stat.clone();
|
||||
stat.alternative = next;
|
||||
if (next === jump) jump = null;
|
||||
statements.splice(i, 1, stat.transform(compressor));
|
||||
statements.splice(j, 1);
|
||||
stat.alternative = make_node(AST_BlockStatement, next, {
|
||||
body: extract_functions(true, null, j + 1),
|
||||
});
|
||||
statements[i] = stat;
|
||||
statements[i] = stat.transform(compressor);
|
||||
continue;
|
||||
}
|
||||
if (!stat.alternative && !next && in_lambda) {
|
||||
// if (foo()) return x; [ return ; ] ---> return foo() ? x : undefined;
|
||||
if (in_bool || value && multiple_if_returns) {
|
||||
changed = true;
|
||||
stat = stat.clone();
|
||||
stat.alternative = make_node(AST_Return, stat, { value: null });
|
||||
statements.splice(i, 1, stat.transform(compressor));
|
||||
continue;
|
||||
}
|
||||
// if (foo()) return bar() ? x : void 0; ---> return foo() && bar() ? x : void 0;
|
||||
// if (foo()) return bar() ? void 0 : x; ---> return !foo() || bar() ? void 0 : x;
|
||||
var or;
|
||||
if (value instanceof AST_Conditional
|
||||
&& ((or = is_undefined(value.consequent, compressor))
|
||||
|| is_undefined(value.alternative, compressor))) {
|
||||
changed = true;
|
||||
var ret = stat.body.clone();
|
||||
ret.value = value.clone();
|
||||
ret.value.condition = make_node(AST_Binary, stat, {
|
||||
operator: or ? "||" : "&&",
|
||||
left: or ? stat.condition.negate(compressor) : stat.condition,
|
||||
right: value.condition,
|
||||
});
|
||||
statements.splice(i, 1, ret.transform(compressor));
|
||||
continue;
|
||||
}
|
||||
// if (foo()) return x; [ return ; ] ---> return foo() ? x : undefined;
|
||||
// if (foo()) return bar() ? x : void 0; ---> return foo() && bar() ? x : void 0;
|
||||
// if (foo()) return bar() ? void 0 : x; ---> return !foo() || bar() ? void 0 : x;
|
||||
if (in_lambda && declare_only && !next && !stat.alternative && (in_bool
|
||||
|| value && multiple_if_returns
|
||||
|| value instanceof AST_Conditional && (is_undefined(value.consequent, compressor)
|
||||
|| is_undefined(value.alternative, compressor)))) {
|
||||
changed = true;
|
||||
stat = stat.clone();
|
||||
stat.alternative = make_node(AST_Return, stat, { value: null });
|
||||
statements[i] = stat;
|
||||
statements[i] = stat.transform(compressor);
|
||||
continue;
|
||||
}
|
||||
// if (a) return b; if (c) return d; e; ---> return a ? b : c ? d : void e;
|
||||
//
|
||||
@@ -3593,22 +3583,17 @@ Compressor.prototype.compress = function(node) {
|
||||
if (chain_if_returns && !stat.alternative
|
||||
&& (!(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 ? !declare_only
|
||||
: next instanceof AST_SimpleStatement && next_index(j) == statements.length)) {
|
||||
changed = true;
|
||||
var exprs = [];
|
||||
var args = prev_stat ? trim_defns(prev, exprs) : [ i, 1 ];
|
||||
stat = stat.clone();
|
||||
exprs.push(stat.condition);
|
||||
stat.condition = make_sequence(stat, exprs);
|
||||
stat.alternative = make_node(AST_BlockStatement, next, {
|
||||
body: [
|
||||
next,
|
||||
make_node(AST_Return, next, { value: null }),
|
||||
],
|
||||
body: extract_functions().concat(make_node(AST_Return, next, { value: null })),
|
||||
});
|
||||
args.push(stat.transform(compressor));
|
||||
statements.splice(j, 1);
|
||||
[].splice.apply(statements, args);
|
||||
statements[i] = stat.transform(compressor);
|
||||
i = prev + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -3703,17 +3688,18 @@ Compressor.prototype.compress = function(node) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function extract_functions() {
|
||||
function extract_functions(mode, stop, end) {
|
||||
var defuns = [];
|
||||
var lexical = false;
|
||||
var start = i + 1;
|
||||
var end;
|
||||
if (merge_jump) {
|
||||
end = statements.lastIndexOf(jump);
|
||||
if (end < 0) end = statements.length;
|
||||
} else {
|
||||
if (!mode) {
|
||||
end = statements.length;
|
||||
jump = null;
|
||||
} else if (stop) {
|
||||
end = statements.lastIndexOf(stop);
|
||||
} else {
|
||||
stop = statements[end];
|
||||
if (stop !== jump) jump = null;
|
||||
}
|
||||
var tail = statements.splice(start, end - start).filter(function(stat) {
|
||||
if (stat instanceof AST_LambdaDefinition) {
|
||||
@@ -3723,11 +3709,11 @@ Compressor.prototype.compress = function(node) {
|
||||
if (is_lexical_definition(stat)) lexical = true;
|
||||
return true;
|
||||
});
|
||||
if (merge_jump === 3) {
|
||||
tail.push(make_node(AST_SimpleStatement, jump.value, {
|
||||
body: make_sequence(jump.value, jump.value.expressions.slice(0, -1)),
|
||||
if (mode === 3) {
|
||||
tail.push(make_node(AST_SimpleStatement, stop.value, {
|
||||
body: make_sequence(stop.value, stop.value.expressions.slice(0, -1)),
|
||||
}));
|
||||
jump.value = jump.value.tail_node();
|
||||
stop.value = stop.value.tail_node();
|
||||
}
|
||||
[].push.apply(lexical ? tail : statements, defuns);
|
||||
return tail;
|
||||
@@ -3758,38 +3744,29 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
|
||||
function next_index(i) {
|
||||
for (var j = i + 1; j < statements.length; j++) {
|
||||
if (!is_declaration(statements[j])) break;
|
||||
declare_only = true;
|
||||
for (var j = i; ++j < statements.length;) {
|
||||
var stat = statements[j];
|
||||
if (is_declaration(stat)) continue;
|
||||
if (stat instanceof AST_Var) {
|
||||
declare_only = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
function prev_index(i) {
|
||||
for (var j = i; --j >= 0;) {
|
||||
if (!(statements[j] instanceof AST_Var)) break;
|
||||
var stat = statements[j];
|
||||
if (stat instanceof AST_Var) continue;
|
||||
if (is_declaration(stat)) continue;
|
||||
break;
|
||||
}
|
||||
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, process_to_assign),
|
||||
right: var_def.value,
|
||||
}));
|
||||
});
|
||||
}
|
||||
if (var_defs.length > 0) args.push(make_node(AST_Var, stat, { definitions: var_defs }));
|
||||
return args;
|
||||
}
|
||||
|
||||
function eliminate_returns(stat, in_block) {
|
||||
if (stat instanceof AST_Exit) {
|
||||
var mode = match_return(stat, true);
|
||||
@@ -9618,7 +9595,7 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
if (var_defs.length > 0) body.push(make_node(AST_Var, self, { definitions: var_defs }));
|
||||
if (body.length > 0) {
|
||||
body.push(self);
|
||||
body.push(self.transform(compressor));
|
||||
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
|
||||
}
|
||||
} else if (body_exprs && alt_exprs) {
|
||||
|
||||
Reference in New Issue
Block a user