aboutsummaryrefslogtreecommitdiff
path: root/lib/compress.js
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2017-04-04 23:48:22 +0800
committerGitHub <noreply@github.com>2017-04-04 23:48:22 +0800
commit9b6bc67c3393507d0621eb3debbe8845b0eff52d (patch)
tree9e696d86f097bbb9dededf8808b61342d2133748 /lib/compress.js
parent4b90dc1fdb30274a7f1c2d38493fd31d6a553982 (diff)
downloadtracifyjs-9b6bc67c3393507d0621eb3debbe8845b0eff52d.tar.gz
tracifyjs-9b6bc67c3393507d0621eb3debbe8845b0eff52d.zip
optimise `do{...}while(false)` (#1785)
- better heuristics to avoid issues like #1532 - fix `TreeWalker.loopcontrol_target()` - `continue` cannot refer to `switch` blocks
Diffstat (limited to 'lib/compress.js')
-rw-r--r--lib/compress.js32
1 files changed, 20 insertions, 12 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 79e7d4d2..14083fe8 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -893,7 +893,7 @@ merge(Compressor.prototype, {
}
var ab = aborts(stat.body);
- var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
+ var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
|| (ab instanceof AST_Continue && self === loop_body(lct))
|| (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
@@ -915,7 +915,7 @@ merge(Compressor.prototype, {
}
var ab = aborts(stat.alternative);
- var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
+ var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
|| (ab instanceof AST_Continue && self === loop_body(lct))
|| (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
@@ -964,7 +964,7 @@ merge(Compressor.prototype, {
extract_declarations_from_unreachable_code(compressor, stat, a);
} else {
if (stat instanceof AST_LoopControl) {
- var lct = compressor.loopcontrol_target(stat.label);
+ var lct = compressor.loopcontrol_target(stat);
if ((stat instanceof AST_Break
&& !(lct instanceof AST_IterationStatement)
&& loop_body(lct) === self) || (stat instanceof AST_Continue
@@ -1746,7 +1746,7 @@ merge(Compressor.prototype, {
OPT(AST_LabeledStatement, function(self, compressor){
if (self.body instanceof AST_Break
- && compressor.loopcontrol_target(self.body.label) === self.body) {
+ && compressor.loopcontrol_target(self.body) === self.body) {
return make_node(AST_EmptyStatement, self);
}
return self.label.references.length == 0 ? self.body : self;
@@ -2314,13 +2314,21 @@ merge(Compressor.prototype, {
return make_node(AST_For, self, {
body: self.body
});
- } else if (compressor.option("dead_code") && self instanceof AST_While) {
+ }
+ if (compressor.option("dead_code") && self instanceof AST_While) {
var a = [];
extract_declarations_from_unreachable_code(compressor, self.body, a);
return make_node(AST_BlockStatement, self, { body: a });
- } else {
- cond = make_node_from_constant(cond, self.condition).transform(compressor);
- self.condition = best_of_expression(cond, self.condition);
+ }
+ if (self instanceof AST_Do) {
+ var has_loop_control = false;
+ var tw = new TreeWalker(function(node) {
+ if (node instanceof AST_Scope || has_loop_control) return true;
+ if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self)
+ return has_loop_control = true;
+ });
+ self.walk(tw);
+ if (!has_loop_control) return self.body;
}
}
if (self instanceof AST_While) {
@@ -2346,7 +2354,7 @@ merge(Compressor.prototype, {
var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
if (first instanceof AST_If) {
if (first.body instanceof AST_Break
- && compressor.loopcontrol_target(first.body.label) === compressor.self()) {
+ && compressor.loopcontrol_target(first.body) === compressor.self()) {
if (self.condition) {
self.condition = make_node(AST_Binary, self.condition, {
left: self.condition,
@@ -2359,7 +2367,7 @@ merge(Compressor.prototype, {
drop_it(first.alternative);
}
else if (first.alternative instanceof AST_Break
- && compressor.loopcontrol_target(first.alternative.label) === compressor.self()) {
+ && compressor.loopcontrol_target(first.alternative) === compressor.self()) {
if (self.condition) {
self.condition = make_node(AST_Binary, self.condition, {
left: self.condition,
@@ -2590,7 +2598,7 @@ merge(Compressor.prototype, {
self.body = body;
while (branch = body[body.length - 1]) {
var stat = branch.body[branch.body.length - 1];
- if (stat instanceof AST_Break && compressor.loopcontrol_target(stat.label) === self)
+ if (stat instanceof AST_Break && compressor.loopcontrol_target(stat) === self)
branch.body.pop();
if (branch.body.length || branch instanceof AST_Case
&& (default_branch || branch.expression.has_side_effects(compressor))) break;
@@ -2609,7 +2617,7 @@ merge(Compressor.prototype, {
if (has_break
|| node instanceof AST_Lambda
|| node instanceof AST_SimpleStatement) return true;
- if (node instanceof AST_Break && tw.loopcontrol_target(node.label) === self)
+ if (node instanceof AST_Break && tw.loopcontrol_target(node) === self)
has_break = true;
});
self.walk(tw);