handle flow control in loops with reduce_vars (#3069)

fixes #3068
This commit is contained in:
Alex Lam S.L
2018-04-10 06:51:03 +08:00
committed by GitHub
parent 183da16896
commit b82fd0ad41
2 changed files with 102 additions and 26 deletions

View File

@@ -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);
if (has_break_or_continue(this)) {
pop(tw);
push(tw);
}
this.step.walk(tw);
pop(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,22 +3877,16 @@ 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, {
body: [
self.body,
make_node(AST_SimpleStatement, self.condition, {
body: self.condition
})
]
}).optimize(compressor);
if (!has_break_or_continue(self, compressor.parent())) {
return make_node(AST_BlockStatement, self.body, {
body: [
self.body,
make_node(AST_SimpleStatement, self.condition, {
body: self.condition
})
]
}).optimize(compressor);
}
}
if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, {
condition: make_sequence(self.condition, [