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; tw.safe_ids = save_ids;
return true; return true;
}); });
def(AST_DWLoop, function(tw, descend) { def(AST_Do, function(tw) {
var saved_loop = tw.in_loop; var saved_loop = tw.in_loop;
tw.in_loop = this; tw.in_loop = this;
push(tw); push(tw);
descend(); this.body.walk(tw);
if (has_break_or_continue(this)) {
pop(tw);
push(tw);
}
this.condition.walk(tw);
pop(tw); pop(tw);
tw.in_loop = saved_loop; tw.in_loop = saved_loop;
return true; return true;
@@ -543,19 +548,17 @@ merge(Compressor.prototype, {
if (this.init) this.init.walk(tw); if (this.init) this.init.walk(tw);
var saved_loop = tw.in_loop; var saved_loop = tw.in_loop;
tw.in_loop = this; tw.in_loop = this;
if (this.condition) {
push(tw);
this.condition.walk(tw);
pop(tw);
}
push(tw); push(tw);
if (this.condition) this.condition.walk(tw);
this.body.walk(tw); this.body.walk(tw);
pop(tw);
if (this.step) { if (this.step) {
push(tw); if (has_break_or_continue(this)) {
pop(tw);
push(tw);
}
this.step.walk(tw); this.step.walk(tw);
pop(tw);
} }
pop(tw);
tw.in_loop = saved_loop; tw.in_loop = saved_loop;
return true; 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){ })(function(node, func){
node.DEFMETHOD("reduce_vars", 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; 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){ OPT(AST_Do, function(self, compressor){
if (!compressor.option("loops")) return self; if (!compressor.option("loops")) return self;
var cond = self.condition.is_truthy() || self.condition.tail_node().evaluate(compressor); var cond = self.condition.is_truthy() || self.condition.tail_node().evaluate(compressor);
@@ -3851,22 +3877,16 @@ merge(Compressor.prototype, {
] ]
}) })
}).optimize(compressor); }).optimize(compressor);
var has_loop_control = false; if (!has_break_or_continue(self, compressor.parent())) {
var tw = new TreeWalker(function(node) { return make_node(AST_BlockStatement, self.body, {
if (node instanceof AST_Scope || has_loop_control) return true; body: [
if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self) self.body,
return has_loop_control = true; make_node(AST_SimpleStatement, self.condition, {
}); body: self.condition
var parent = compressor.parent(); })
(parent instanceof AST_LabeledStatement ? parent : self).walk(tw); ]
if (!has_loop_control) return make_node(AST_BlockStatement, self.body, { }).optimize(compressor);
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, { if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, {
condition: make_sequence(self.condition, [ condition: make_sequence(self.condition, [

View File

@@ -5654,3 +5654,59 @@ issue_3042_2: {
"true", "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
}