fix TreeWalker.loopcontrol_target()

`continue` cannot refer to `switch` blocks
This commit is contained in:
alexlamsl 2017-04-04 19:36:26 +08:00
parent 67bc50db16
commit dbb93fdb70
3 changed files with 37 additions and 14 deletions

View File

@ -1035,16 +1035,16 @@ TreeWalker.prototype = {
self = p; self = p;
} }
}, },
loopcontrol_target: function(label) { loopcontrol_target: function(node) {
var stack = this.stack; var stack = this.stack;
if (label) for (var i = stack.length; --i >= 0;) { if (node.label) for (var i = stack.length; --i >= 0;) {
var x = stack[i]; var x = stack[i];
if (x instanceof AST_LabeledStatement && x.label.name == label.name) { if (x instanceof AST_LabeledStatement && x.label.name == node.label.name)
return x.body; return x.body;
}
} else for (var i = stack.length; --i >= 0;) { } else for (var i = stack.length; --i >= 0;) {
var x = stack[i]; var x = stack[i];
if (x instanceof AST_Switch || x instanceof AST_IterationStatement) if (x instanceof AST_IterationStatement
|| node instanceof AST_Break && x instanceof AST_Switch)
return x; return x;
} }
} }

View File

@ -893,7 +893,7 @@ merge(Compressor.prototype, {
} }
var ab = aborts(stat.body); 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) if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
|| (ab instanceof AST_Continue && self === loop_body(lct)) || (ab instanceof AST_Continue && self === loop_body(lct))
|| (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
@ -915,7 +915,7 @@ merge(Compressor.prototype, {
} }
var ab = aborts(stat.alternative); 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) if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
|| (ab instanceof AST_Continue && self === loop_body(lct)) || (ab instanceof AST_Continue && self === loop_body(lct))
|| (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === 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); extract_declarations_from_unreachable_code(compressor, stat, a);
} else { } else {
if (stat instanceof AST_LoopControl) { if (stat instanceof AST_LoopControl) {
var lct = compressor.loopcontrol_target(stat.label); var lct = compressor.loopcontrol_target(stat);
if ((stat instanceof AST_Break if ((stat instanceof AST_Break
&& !(lct instanceof AST_IterationStatement) && !(lct instanceof AST_IterationStatement)
&& loop_body(lct) === self) || (stat instanceof AST_Continue && loop_body(lct) === self) || (stat instanceof AST_Continue
@ -1746,7 +1746,7 @@ merge(Compressor.prototype, {
OPT(AST_LabeledStatement, function(self, compressor){ OPT(AST_LabeledStatement, function(self, compressor){
if (self.body instanceof AST_Break 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 make_node(AST_EmptyStatement, self);
} }
return self.label.references.length == 0 ? self.body : self; return self.label.references.length == 0 ? self.body : self;
@ -2324,7 +2324,7 @@ merge(Compressor.prototype, {
var has_loop_control = false; var has_loop_control = false;
var tw = new TreeWalker(function(node) { var tw = new TreeWalker(function(node) {
if (node instanceof AST_Scope || has_loop_control) return true; if (node instanceof AST_Scope || has_loop_control) return true;
if (node instanceof AST_LoopControl && tw.loopcontrol_target(node.label) === self) if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self)
return has_loop_control = true; return has_loop_control = true;
}); });
self.walk(tw); self.walk(tw);
@ -2354,7 +2354,7 @@ merge(Compressor.prototype, {
var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body; var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
if (first instanceof AST_If) { if (first instanceof AST_If) {
if (first.body instanceof AST_Break if (first.body instanceof AST_Break
&& compressor.loopcontrol_target(first.body.label) === compressor.self()) { && compressor.loopcontrol_target(first.body) === compressor.self()) {
if (self.condition) { if (self.condition) {
self.condition = make_node(AST_Binary, self.condition, { self.condition = make_node(AST_Binary, self.condition, {
left: self.condition, left: self.condition,
@ -2367,7 +2367,7 @@ merge(Compressor.prototype, {
drop_it(first.alternative); drop_it(first.alternative);
} }
else if (first.alternative instanceof AST_Break 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) { if (self.condition) {
self.condition = make_node(AST_Binary, self.condition, { self.condition = make_node(AST_Binary, self.condition, {
left: self.condition, left: self.condition,
@ -2598,7 +2598,7 @@ merge(Compressor.prototype, {
self.body = body; self.body = body;
while (branch = body[body.length - 1]) { while (branch = body[body.length - 1]) {
var stat = branch.body[branch.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(); branch.body.pop();
if (branch.body.length || branch instanceof AST_Case if (branch.body.length || branch instanceof AST_Case
&& (default_branch || branch.expression.has_side_effects(compressor))) break; && (default_branch || branch.expression.has_side_effects(compressor))) break;
@ -2617,7 +2617,7 @@ merge(Compressor.prototype, {
if (has_break if (has_break
|| node instanceof AST_Lambda || node instanceof AST_Lambda
|| node instanceof AST_SimpleStatement) return true; || 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; has_break = true;
}); });
self.walk(tw); self.walk(tw);

View File

@ -457,3 +457,26 @@ issue_1648: {
} }
expect_exact: "function f(){for(x();1;);}" expect_exact: "function f(){for(x();1;);}"
} }
do_switch: {
options = {
evaluate: true,
loops: true,
}
input: {
do {
switch (a) {
case b:
continue;
}
} while (false);
}
expect: {
do {
switch (a) {
case b:
continue;
}
} while (false);
}
}