enhance loops (#4180)
This commit is contained in:
@@ -1180,6 +1180,16 @@ merge(Compressor.prototype, {
|
|||||||
|| node instanceof AST_Undefined;
|
|| node instanceof AST_Undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function declarations_only(node) {
|
||||||
|
return all(node.definitions, function(var_def) {
|
||||||
|
return !var_def.value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_declaration(stat) {
|
||||||
|
return stat instanceof AST_Defun || stat instanceof AST_Var && declarations_only(stat);
|
||||||
|
}
|
||||||
|
|
||||||
function tighten_body(statements, compressor) {
|
function tighten_body(statements, compressor) {
|
||||||
var in_loop, in_try, scope;
|
var in_loop, in_try, scope;
|
||||||
find_loop_scope_try();
|
find_loop_scope_try();
|
||||||
@@ -2407,16 +2417,6 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function declarations_only(node) {
|
|
||||||
return all(node.definitions, function(var_def) {
|
|
||||||
return !var_def.value;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_declaration(stat) {
|
|
||||||
return stat instanceof AST_Defun || stat instanceof AST_Var && declarations_only(stat);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sequencesize(statements, compressor) {
|
function sequencesize(statements, compressor) {
|
||||||
if (statements.length < 2) return;
|
if (statements.length < 2) return;
|
||||||
var seq = [], n = 0;
|
var seq = [], n = 0;
|
||||||
@@ -4268,13 +4268,17 @@ merge(Compressor.prototype, {
|
|||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function trim_block(stat) {
|
||||||
|
switch (stat.body.length) {
|
||||||
|
case 1: return stat.body[0];
|
||||||
|
case 0: return make_node(AST_EmptyStatement, stat);
|
||||||
|
}
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
OPT(AST_BlockStatement, function(self, compressor) {
|
OPT(AST_BlockStatement, function(self, compressor) {
|
||||||
self.body = tighten_body(self.body, compressor);
|
self.body = tighten_body(self.body, compressor);
|
||||||
switch (self.body.length) {
|
return trim_block(self);
|
||||||
case 1: return self.body[0];
|
|
||||||
case 0: return make_node(AST_EmptyStatement, self);
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_Function, function(self, compressor) {
|
OPT(AST_Function, function(self, compressor) {
|
||||||
@@ -5847,6 +5851,33 @@ merge(Compressor.prototype, {
|
|||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (self.body instanceof AST_BlockStatement) {
|
||||||
|
var body = self.body.body;
|
||||||
|
for (var i = body.length; --i >= 0;) {
|
||||||
|
var stat = body[i];
|
||||||
|
if (stat instanceof AST_If
|
||||||
|
&& !stat.alternative
|
||||||
|
&& stat.body instanceof AST_Break
|
||||||
|
&& compressor.loopcontrol_target(stat.body) === compressor.self()) {
|
||||||
|
self.condition = make_node(AST_Binary, self, {
|
||||||
|
operator: "&&",
|
||||||
|
left: stat.condition.negate(compressor),
|
||||||
|
right: self.condition,
|
||||||
|
});
|
||||||
|
body.splice(i, 1);
|
||||||
|
} else if (stat instanceof AST_SimpleStatement) {
|
||||||
|
self.condition = make_sequence(self, [
|
||||||
|
stat.body,
|
||||||
|
self.condition,
|
||||||
|
]);
|
||||||
|
body.splice(i, 1);
|
||||||
|
} else if (!is_declaration(stat)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.body = trim_block(self.body);
|
||||||
|
}
|
||||||
|
if (self.body instanceof AST_EmptyStatement) return make_node(AST_For, self, self).optimize(compressor);
|
||||||
if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, {
|
if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, {
|
||||||
condition: make_sequence(self.condition, [
|
condition: make_sequence(self.condition, [
|
||||||
self.body.body,
|
self.body.body,
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ evaluate: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1532: {
|
issue_1532_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
loops: true,
|
loops: true,
|
||||||
@@ -210,18 +210,56 @@ issue_1532: {
|
|||||||
function f(x, y) {
|
function f(x, y) {
|
||||||
do {
|
do {
|
||||||
if (x) break;
|
if (x) break;
|
||||||
foo();
|
console.log(y);
|
||||||
} while (false);
|
} while (false);
|
||||||
}
|
}
|
||||||
|
f(null, "PASS");
|
||||||
|
f(42, "FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(x, y) {
|
||||||
|
for (; !x && (console.log(y), false););
|
||||||
|
}
|
||||||
|
f(null, "PASS");
|
||||||
|
f(42, "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1532_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x, y) {
|
||||||
|
do {
|
||||||
|
if (x) {
|
||||||
|
console.log(x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
console.log(y);
|
||||||
|
} while (false);
|
||||||
|
}
|
||||||
|
f(null, "PASS");
|
||||||
|
f(42, "FAIL");
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(x, y) {
|
function f(x, y) {
|
||||||
do {
|
do {
|
||||||
if (x) break;
|
if (x) {
|
||||||
foo();
|
console.log(x);
|
||||||
} while (false);
|
break;
|
||||||
|
}
|
||||||
|
} while (console.log(y), false);
|
||||||
}
|
}
|
||||||
|
f(null, "PASS");
|
||||||
|
f(42, "FAIL");
|
||||||
}
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"42",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_186: {
|
issue_186: {
|
||||||
|
|||||||
Reference in New Issue
Block a user