compress loops with immediate break (#2746)

fixes #2740
This commit is contained in:
Alex Lam S.L
2018-01-08 14:30:18 +08:00
committed by GitHub
parent 9336cc8247
commit ce27bcd69a
2 changed files with 156 additions and 21 deletions

View File

@@ -3417,23 +3417,28 @@ merge(Compressor.prototype, {
});
function if_break_in_loop(self, compressor) {
function drop_it(rest) {
rest = as_statement_array(rest);
if (self.body instanceof AST_BlockStatement) {
self.body = self.body.clone();
self.body.body = rest.concat(self.body.body.slice(1));
self.body = self.body.transform(compressor);
} else {
self.body = make_node(AST_BlockStatement, self.body, {
body: rest
}).transform(compressor);
}
if_break_in_loop(self, compressor);
}
var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
if (compressor.option("dead_code") && is_break(first)) {
var body = [];
if (self.init instanceof AST_Statement) {
body.push(self.init);
} else if (self.init) {
body.push(make_node(AST_SimpleStatement, self.init, {
body: self.init
}));
}
if (self.condition) {
body.push(make_node(AST_SimpleStatement, self.condition, {
body: self.condition
}));
}
extract_declarations_from_unreachable_code(compressor, self.body, body);
return make_node(AST_BlockStatement, self, {
body: body
});
}
if (first instanceof AST_If) {
if (first.body instanceof AST_Break
&& compressor.loopcontrol_target(first.body) === compressor.self()) {
if (is_break(first.body)) {
if (self.condition) {
self.condition = make_node(AST_Binary, self.condition, {
left: self.condition,
@@ -3444,9 +3449,7 @@ merge(Compressor.prototype, {
self.condition = first.condition.negate(compressor);
}
drop_it(first.alternative);
}
else if (first.alternative instanceof AST_Break
&& compressor.loopcontrol_target(first.alternative) === compressor.self()) {
} else if (is_break(first.alternative)) {
if (self.condition) {
self.condition = make_node(AST_Binary, self.condition, {
left: self.condition,
@@ -3459,7 +3462,27 @@ merge(Compressor.prototype, {
drop_it(first.body);
}
}
};
return self;
function is_break(node) {
return node instanceof AST_Break
&& compressor.loopcontrol_target(node) === compressor.self();
}
function drop_it(rest) {
rest = as_statement_array(rest);
if (self.body instanceof AST_BlockStatement) {
self.body = self.body.clone();
self.body.body = rest.concat(self.body.body.slice(1));
self.body = self.body.transform(compressor);
} else {
self.body = make_node(AST_BlockStatement, self.body, {
body: rest
}).transform(compressor);
}
self = if_break_in_loop(self, compressor);
}
}
OPT(AST_For, function(self, compressor){
if (!compressor.option("loops")) return self;
@@ -3495,8 +3518,7 @@ merge(Compressor.prototype, {
}
}
}
if_break_in_loop(self, compressor);
return self;
return if_break_in_loop(self, compressor);
});
OPT(AST_If, function(self, compressor){