aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2018-01-08 14:30:18 +0800
committerGitHub <noreply@github.com>2018-01-08 14:30:18 +0800
commitce27bcd69a0a66bf145ee2f14927a3cfec9b0202 (patch)
tree774dc5746df1e5cc9a54dd7ac52b87346bd3fef1
parent9336cc824739f6e594e7c020a49b2d17b1faaec2 (diff)
downloadtracifyjs-ce27bcd69a0a66bf145ee2f14927a3cfec9b0202.tar.gz
tracifyjs-ce27bcd69a0a66bf145ee2f14927a3cfec9b0202.zip
compress loops with immediate `break` (#2746)
fixes #2740
-rw-r--r--lib/compress.js62
-rw-r--r--test/compress/loops.js113
2 files changed, 155 insertions, 20 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 011bb1b4..70163656 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -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);
+ 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
+ }));
}
- if_break_in_loop(self, compressor);
+ extract_declarations_from_unreachable_code(compressor, self.body, body);
+ return make_node(AST_BlockStatement, self, {
+ body: body
+ });
}
- var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.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){
diff --git a/test/compress/loops.js b/test/compress/loops.js
index 3538c221..a6ebd359 100644
--- a/test/compress/loops.js
+++ b/test/compress/loops.js
@@ -492,3 +492,116 @@ dead_code_condition: {
}
expect_stdout: "1"
}
+
+issue_2740_1: {
+ options = {
+ dead_code: true,
+ loops: true,
+ }
+ input: {
+ for (; ; ) break;
+ for (a(); ; ) break;
+ for (; b(); ) break;
+ for (c(); d(); ) break;
+ for (; ; e()) break;
+ for (f(); ; g()) break;
+ for (; h(); i()) break;
+ for (j(); k(); l()) break;
+ }
+ expect: {
+ a();
+ b();
+ c();
+ d();
+ f();
+ h();
+ j();
+ k();
+ }
+}
+
+issue_2740_2: {
+ options = {
+ dead_code: true,
+ loops: true,
+ passes: 2,
+ }
+ input: {
+ L1: while (x()) {
+ break L1;
+ }
+ }
+ expect: {
+ x();
+ }
+}
+
+issue_2740_3: {
+ options = {
+ dead_code: true,
+ loops: true,
+ }
+ input: {
+ L1: for (var x = 0; x < 3; x++) {
+ L2: for (var y = 0; y < 2; y++) {
+ break L1;
+ }
+ }
+ console.log(x, y);
+ }
+ expect: {
+ L1: for (var x = 0; x < 3; x++)
+ for (var y = 0; y < 2; y++)
+ break L1;
+ console.log(x, y);
+ }
+ expect_stdout: "0 0"
+}
+
+issue_2740_4: {
+ options = {
+ dead_code: true,
+ loops: true,
+ passes: 2,
+ }
+ input: {
+ L1: for (var x = 0; x < 3; x++) {
+ L2: for (var y = 0; y < 2; y++) {
+ break L2;
+ }
+ }
+ console.log(x, y);
+ }
+ expect: {
+ for (var x = 0; x < 3; x++) {
+ var y = 0;
+ y < 2;
+ }
+ console.log(x, y);
+ }
+ expect_stdout: "3 0"
+}
+
+issue_2740_5: {
+ options = {
+ dead_code: true,
+ loops: true,
+ passes: 2,
+ }
+ input: {
+ L1: for (var x = 0; x < 3; x++) {
+ break L1;
+ L2: for (var y = 0; y < 2; y++) {
+ break L2;
+ }
+ }
+ console.log(x, y);
+ }
+ expect: {
+ var x = 0;
+ x < 3;
+ var y;
+ console.log(x,y);
+ }
+ expect_stdout: "0 undefined"
+}