enhance if_return (#2703)

This commit is contained in:
Alex Lam S.L
2018-01-02 15:09:51 +08:00
committed by GitHub
parent d838b4b52e
commit cc931b3ad8
2 changed files with 86 additions and 14 deletions

View File

@@ -1343,12 +1343,13 @@ merge(Compressor.prototype, {
var in_lambda = self instanceof AST_Lambda; var in_lambda = self instanceof AST_Lambda;
for (var i = statements.length; --i >= 0;) { for (var i = statements.length; --i >= 0;) {
var stat = statements[i]; var stat = statements[i];
var next = statements[i + 1]; var j = next_index(i);
var next = statements[j];
if (in_lambda && !next && stat instanceof AST_Return) { if (in_lambda && !next && stat instanceof AST_Return) {
if (!stat.value) { if (!stat.value) {
CHANGED = true; CHANGED = true;
statements.length--; statements.splice(i, 1);
continue; continue;
} }
if (stat.value instanceof AST_UnaryPrefix && stat.value.operator == "void") { if (stat.value instanceof AST_UnaryPrefix && stat.value.operator == "void") {
@@ -1418,7 +1419,8 @@ merge(Compressor.prototype, {
CHANGED = true; CHANGED = true;
stat = stat.clone(); stat = stat.clone();
stat.alternative = next; stat.alternative = next;
statements.splice(i, 2, stat.transform(compressor)); statements.splice(i, 1, stat.transform(compressor));
statements.splice(j, 1);
continue; continue;
} }
//--- //---
@@ -1430,7 +1432,8 @@ merge(Compressor.prototype, {
stat.alternative = next || make_node(AST_Return, stat, { stat.alternative = next || make_node(AST_Return, stat, {
value: null value: null
}); });
statements.splice(i, next ? 2 : 1, stat.transform(compressor)); statements.splice(i, 1, stat.transform(compressor));
if (next) statements.splice(j, 1);
continue; continue;
} }
//--- //---
@@ -1439,10 +1442,10 @@ merge(Compressor.prototype, {
// 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[i - 1]; var prev = statements[prev_index(i)];
if (compressor.option("sequences") && in_lambda && !stat.alternative if (compressor.option("sequences") && in_lambda && !stat.alternative
&& prev instanceof AST_If && prev.body instanceof AST_Return && prev instanceof AST_If && prev.body instanceof AST_Return
&& i + 2 == statements.length && next instanceof AST_SimpleStatement) { && next_index(j) == statements.length && next instanceof AST_SimpleStatement) {
CHANGED = true; CHANGED = true;
stat = stat.clone(); stat = stat.clone();
stat.alternative = make_node(AST_BlockStatement, next, { stat.alternative = make_node(AST_BlockStatement, next, {
@@ -1453,7 +1456,8 @@ merge(Compressor.prototype, {
}) })
] ]
}); });
statements.splice(i, 2, stat.transform(compressor)); statements.splice(i, 1, stat.transform(compressor));
statements.splice(j, 1);
continue; continue;
} }
} }
@@ -1503,6 +1507,26 @@ merge(Compressor.prototype, {
} }
return body; return body;
} }
function next_index(i) {
for (var j = i + 1, len = statements.length; j < len; j++) {
var stat = statements[j];
if (!(stat instanceof AST_Definitions && declarations_only(stat))) {
break;
}
}
return j;
}
function prev_index(i) {
for (var j = i; --j >= 0;) {
var stat = statements[j];
if (!(stat instanceof AST_Definitions && declarations_only(stat))) {
break;
}
}
return j;
}
} }
function eliminate_dead_code(statements, compressor) { function eliminate_dead_code(statements, compressor) {
@@ -1575,19 +1599,17 @@ merge(Compressor.prototype, {
function to_simple_statement(block, decls) { function to_simple_statement(block, decls) {
if (!(block instanceof AST_BlockStatement)) return block; if (!(block instanceof AST_BlockStatement)) return block;
var defs = [];
var stat = null; var stat = null;
for (var i = 0, len = block.body.length; i < len; i++) { for (var i = 0, len = block.body.length; i < len; i++) {
var line = block.body[i]; var line = block.body[i];
if (line instanceof AST_Definitions && declarations_only(line)) { if (line instanceof AST_Definitions && declarations_only(line)) {
defs.push(line); decls.push(line);
} else if (stat) { } else if (stat) {
return false; return false;
} else { } else {
stat = line; stat = line;
} }
} }
[].push.apply(decls, defs);
return stat; return stat;
} }
@@ -1599,7 +1621,7 @@ merge(Compressor.prototype, {
return make_sequence(left, [ left, right ]).transform(compressor); return make_sequence(left, [ left, right ]).transform(compressor);
}; };
var n = 0, prev; var n = 0, prev;
for (var i = 0, len = statements.length; i < len; i++) { for (var i = 0; i < statements.length; i++) {
var stat = statements[i]; var stat = statements[i];
if (prev) { if (prev) {
if (stat instanceof AST_For && !(stat.init instanceof AST_Definitions)) { if (stat instanceof AST_For && !(stat.init instanceof AST_Definitions)) {
@@ -1641,15 +1663,19 @@ merge(Compressor.prototype, {
var body = to_simple_statement(stat.body, decls); var body = to_simple_statement(stat.body, decls);
var alt = to_simple_statement(stat.alternative, decls); var alt = to_simple_statement(stat.alternative, decls);
if (body !== false && alt !== false && decls.length > 0) { if (body !== false && alt !== false && decls.length > 0) {
var len = decls.length;
decls.push(make_node(AST_If, stat, { decls.push(make_node(AST_If, stat, {
condition: stat.condition, condition: stat.condition,
body: body || make_node(AST_EmptyStatement, stat.body), body: body || make_node(AST_EmptyStatement, stat.body),
alternative: alt alternative: alt
})); }));
stat = make_node(AST_BlockStatement, stat, { decls.unshift(n, 1);
body: decls [].splice.apply(statements, decls);
}); i += len;
n += len + 1;
prev = null;
CHANGED = true; CHANGED = true;
continue;
} }
} }
statements[n++] = stat; statements[n++] = stat;

View File

@@ -326,3 +326,49 @@ issue_512: {
} }
} }
} }
if_var_return: {
options = {
conditionals: true,
if_return: true,
join_vars: true,
sequences: true,
}
input: {
function f() {
var a;
return;
var b;
}
function g() {
var a;
if (u()) {
var b;
return v();
var c;
}
var d;
if (w()) {
var e;
return x();
var f;
} else {
var g;
y();
var h;
}
var i;
z();
var j;
}
}
expect: {
function f() {
var a, b;
}
function g() {
var a, b, c, d, e, f, g, h, i, j;
return u() ? v() : w() ? x() : (y(), z(), void 0);
}
}
}