@@ -530,11 +530,16 @@ merge(Compressor.prototype, {
|
||||
tw.safe_ids = save_ids;
|
||||
return true;
|
||||
});
|
||||
def(AST_DWLoop, function(tw, descend) {
|
||||
def(AST_Do, function(tw) {
|
||||
var saved_loop = tw.in_loop;
|
||||
tw.in_loop = this;
|
||||
push(tw);
|
||||
descend();
|
||||
this.body.walk(tw);
|
||||
if (has_break_or_continue(this)) {
|
||||
pop(tw);
|
||||
push(tw);
|
||||
}
|
||||
this.condition.walk(tw);
|
||||
pop(tw);
|
||||
tw.in_loop = saved_loop;
|
||||
return true;
|
||||
@@ -543,19 +548,17 @@ merge(Compressor.prototype, {
|
||||
if (this.init) this.init.walk(tw);
|
||||
var saved_loop = tw.in_loop;
|
||||
tw.in_loop = this;
|
||||
if (this.condition) {
|
||||
push(tw);
|
||||
this.condition.walk(tw);
|
||||
pop(tw);
|
||||
}
|
||||
push(tw);
|
||||
if (this.condition) this.condition.walk(tw);
|
||||
this.body.walk(tw);
|
||||
pop(tw);
|
||||
if (this.step) {
|
||||
push(tw);
|
||||
this.step.walk(tw);
|
||||
if (has_break_or_continue(this)) {
|
||||
pop(tw);
|
||||
push(tw);
|
||||
}
|
||||
this.step.walk(tw);
|
||||
}
|
||||
pop(tw);
|
||||
tw.in_loop = saved_loop;
|
||||
return true;
|
||||
});
|
||||
@@ -713,6 +716,15 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
});
|
||||
def(AST_While, function(tw, descend) {
|
||||
var saved_loop = tw.in_loop;
|
||||
tw.in_loop = this;
|
||||
push(tw);
|
||||
descend();
|
||||
pop(tw);
|
||||
tw.in_loop = saved_loop;
|
||||
return true;
|
||||
});
|
||||
})(function(node, func){
|
||||
node.DEFMETHOD("reduce_vars", func);
|
||||
});
|
||||
@@ -3837,6 +3849,20 @@ merge(Compressor.prototype, {
|
||||
return compressor.option("loops") ? make_node(AST_For, self, self).optimize(compressor) : self;
|
||||
});
|
||||
|
||||
function has_break_or_continue(loop, parent) {
|
||||
var found = false;
|
||||
var tw = new TreeWalker(function(node) {
|
||||
if (found || node instanceof AST_Scope) return true;
|
||||
if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === loop) {
|
||||
return found = true;
|
||||
}
|
||||
});
|
||||
if (parent instanceof AST_LabeledStatement) tw.push(parent);
|
||||
tw.push(loop);
|
||||
loop.body.walk(tw);
|
||||
return found;
|
||||
}
|
||||
|
||||
OPT(AST_Do, function(self, compressor){
|
||||
if (!compressor.option("loops")) return self;
|
||||
var cond = self.condition.is_truthy() || self.condition.tail_node().evaluate(compressor);
|
||||
@@ -3851,15 +3877,8 @@ merge(Compressor.prototype, {
|
||||
]
|
||||
})
|
||||
}).optimize(compressor);
|
||||
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;
|
||||
});
|
||||
var parent = compressor.parent();
|
||||
(parent instanceof AST_LabeledStatement ? parent : self).walk(tw);
|
||||
if (!has_loop_control) return make_node(AST_BlockStatement, self.body, {
|
||||
if (!has_break_or_continue(self, compressor.parent())) {
|
||||
return make_node(AST_BlockStatement, self.body, {
|
||||
body: [
|
||||
self.body,
|
||||
make_node(AST_SimpleStatement, self.condition, {
|
||||
@@ -3868,6 +3887,7 @@ merge(Compressor.prototype, {
|
||||
]
|
||||
}).optimize(compressor);
|
||||
}
|
||||
}
|
||||
if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, {
|
||||
condition: make_sequence(self.condition, [
|
||||
self.body.body,
|
||||
|
||||
@@ -5654,3 +5654,59 @@ issue_3042_2: {
|
||||
"true",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3068_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
do {
|
||||
continue;
|
||||
var b = "defined";
|
||||
} while (b && b.c);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
do {
|
||||
continue;
|
||||
var b = "defined";
|
||||
} while (b && b.c);
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_3068_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
do {
|
||||
try {
|
||||
while ("" == typeof a);
|
||||
} finally {
|
||||
continue;
|
||||
}
|
||||
var b = "defined";
|
||||
} while (b && b.c);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
do {
|
||||
try {
|
||||
while ("" == typeof a);
|
||||
} finally {
|
||||
continue;
|
||||
}
|
||||
var b = "defined";
|
||||
} while (b && b.c);
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user