aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2018-04-10 06:51:03 +0800
committerGitHub <noreply@github.com>2018-04-10 06:51:03 +0800
commitb82fd0ad41983065ad6f58d9bfe4dac7720909bf (patch)
tree91c3cb2089fa2efbc6b1e38dd74d436058857e21
parent183da16896513c22b73d219affebeb155fb8ecdf (diff)
downloadtracifyjs-b82fd0ad41983065ad6f58d9bfe4dac7720909bf.tar.gz
tracifyjs-b82fd0ad41983065ad6f58d9bfe4dac7720909bf.zip
handle flow control in loops with `reduce_vars` (#3069)
fixes #3068
-rw-r--r--lib/compress.js72
-rw-r--r--test/compress/reduce_vars.js56
2 files changed, 102 insertions, 26 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 73f46326..5323a867 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -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, [
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index 59a99b9c..63a17e72 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -5654,3 +5654,59 @@ issue_3042_2: {
"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
+}