Skip to content

Commit

Permalink
enhance if_return (#5594)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl authored Aug 2, 2022
1 parent 672cdfa commit 64e3cee
Show file tree
Hide file tree
Showing 2 changed files with 195 additions and 84 deletions.
139 changes: 58 additions & 81 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
Expand All @@ -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),
Expand Down Expand Up @@ -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;
//
Expand All @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -3758,36 +3744,27 @@ 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;
}
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 (stat instanceof AST_Var) continue;
if (is_declaration(stat)) continue;
break;
}
if (var_defs.length > 0) args.push(make_node(AST_Var, stat, { definitions: var_defs }));
return args;
return j;
}

function eliminate_returns(stat, in_block) {
Expand Down Expand Up @@ -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) {
Expand Down
Loading

0 comments on commit 64e3cee

Please sign in to comment.