aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/compress.js76
-rw-r--r--test/compress/reduce_vars.js68
-rw-r--r--test/compress/switches.js (renamed from test/compress/switch.js)266
3 files changed, 321 insertions, 89 deletions
diff --git a/lib/compress.js b/lib/compress.js
index c4aee690..3653a5fa 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -8424,7 +8424,6 @@ merge(Compressor.prototype, {
OPT(AST_Switch, function(self, compressor) {
if (!compressor.option("switches")) return self;
- var branch;
var value = self.expression.evaluate(compressor);
if (!(value instanceof AST_Node)) {
var orig = self.expression;
@@ -8435,10 +8434,12 @@ merge(Compressor.prototype, {
if (value instanceof AST_Node) {
value = self.expression.evaluate(compressor, true);
}
- var decl = [];
var body = [];
+ var branch;
+ var decl = [];
var default_branch;
var exact_match;
+ var side_effects = [];
for (var i = 0, len = self.body.length; i < len && !exact_match; i++) {
branch = self.body[i];
if (branch instanceof AST_Default) {
@@ -8450,13 +8451,9 @@ merge(Compressor.prototype, {
default_branch = branch;
}
} else if (!(value instanceof AST_Node)) {
- var exp = branch.expression.evaluate(compressor);
- if (!(exp instanceof AST_Node) && exp !== value) {
- eliminate_branch(branch, body[body.length - 1]);
- continue;
- }
- if (exp instanceof AST_Node) exp = branch.expression.evaluate(compressor, true);
- if (exp === value) {
+ var exp = branch.expression;
+ var val = exp.evaluate(compressor, true);
+ if (val === value) {
exact_match = branch;
if (default_branch) {
var default_index = body.indexOf(default_branch);
@@ -8464,18 +8461,41 @@ merge(Compressor.prototype, {
eliminate_branch(default_branch, body[default_index - 1]);
default_branch = null;
}
+ } else if (!(val instanceof AST_Node)) {
+ if (exp.has_side_effects(compressor)) side_effects.push(exp);
+ eliminate_branch(branch, body[body.length - 1]);
+ continue;
}
}
- if (aborts(branch)) {
+ if (exact_match || i == len - 1 || aborts(branch)) {
var prev = body[body.length - 1];
- if (aborts(prev) && prev.body.length == branch.body.length
- && make_node(AST_BlockStatement, prev, prev).equivalent_to(make_node(AST_BlockStatement, branch, branch))) {
- prev.body = [];
+ var statements = branch.body;
+ if (aborts(prev)) switch (prev.body.length - statements.length) {
+ case 1:
+ var stat = prev.body[prev.body.length - 1];
+ if (!is_break(stat, compressor)) break;
+ statements = statements.concat(stat);
+ case 0:
+ var prev_block = make_node(AST_BlockStatement, prev, prev);
+ var next_block = make_node(AST_BlockStatement, branch, { body: statements });
+ if (prev_block.equivalent_to(next_block)) prev.body = [];
+ }
+ }
+ if (side_effects.length) {
+ if (branch instanceof AST_Default) {
+ body.push(make_node(AST_Case, self, { expression: make_sequence(self, side_effects), body: [] }));
+ } else {
+ side_effects.push(branch.expression);
+ branch.expression = make_sequence(self, side_effects);
}
+ side_effects = [];
}
body.push(branch);
}
while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]);
+ if (side_effects.length && !exact_match) {
+ body.push(make_node(AST_Case, self, { expression: make_sequence(self, side_effects), body: [] }));
+ }
while (branch = body[body.length - 1]) {
var stat = branch.body[branch.body.length - 1];
if (is_break(stat, compressor)) branch.body.pop();
@@ -8492,12 +8512,30 @@ merge(Compressor.prototype, {
eliminate_branch(branch);
if (body.pop() === default_branch) default_branch = null;
}
- if (body.length == 0) {
- return make_node(AST_BlockStatement, self, {
- body: decl.concat(make_node(AST_SimpleStatement, self.expression, {
- body: self.expression
- }))
- }).optimize(compressor);
+ if (!branch) {
+ decl.push(make_node(AST_SimpleStatement, self.expression, { body: self.expression }));
+ if (side_effects.length) decl.push(make_node(AST_SimpleStatement, self, {
+ body: make_sequence(self, side_effects),
+ }));
+ return make_node(AST_BlockStatement, self, { body: decl }).optimize(compressor);
+ }
+ if (exact_match ? !branch.expression.has_side_effects(compressor) : branch === default_branch) {
+ while (branch = body[body.length - 2]) {
+ if (branch instanceof AST_Default) break;
+ if (!has_declarations_only(branch)) break;
+ var exp = branch.expression;
+ if (exp.has_side_effects(compressor)) {
+ var prev = body[body.length - 3];
+ if (prev && !aborts(prev)) break;
+ if (exact_match) {
+ exact_match.expression = make_sequence(self, [ exp, exact_match.expression ]);
+ } else {
+ default_branch.body.unshift(make_node(AST_SimpleStatement, self, { body: exp }));
+ }
+ }
+ eliminate_branch(branch);
+ body.splice(-2, 1);
+ }
}
body[0].body = decl.concat(body[0].body);
self.body = body;
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index 33d59982..69f86523 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -2072,72 +2072,6 @@ issue_1670_2: {
issue_1670_3: {
options = {
- comparisons: true,
- conditionals: true,
- dead_code: true,
- evaluate: true,
- reduce_funcs: true,
- reduce_vars: true,
- side_effects: true,
- switches: true,
- typeofs: true,
- unused: true,
- }
- input: {
- (function f() {
- switch (1) {
- case 0:
- var a = true;
- break;
- case 1:
- if (typeof a === "undefined") console.log("PASS");
- else console.log("FAIL");
- }
- })();
- }
- expect: {
- (function() {
- var a;
- void 0 === a ? console.log("PASS") : console.log("FAIL");
- })();
- }
- expect_stdout: "PASS"
-}
-
-issue_1670_4: {
- options = {
- conditionals: true,
- dead_code: true,
- evaluate: true,
- passes: 2,
- reduce_funcs: true,
- reduce_vars: true,
- side_effects: true,
- switches: true,
- unused: true,
- }
- input: {
- (function f() {
- switch (1) {
- case 0:
- var a = true;
- break;
- case 1:
- if (typeof a === "undefined") console.log("PASS");
- else console.log("FAIL");
- }
- })();
- }
- expect: {
- (function() {
- console.log("PASS");
- })();
- }
- expect_stdout: "PASS"
-}
-
-issue_1670_5: {
- options = {
conditionals: true,
dead_code: true,
evaluate: true,
@@ -2168,7 +2102,7 @@ issue_1670_5: {
expect_stdout: "1"
}
-issue_1670_6: {
+issue_1670_4: {
options = {
conditionals: true,
dead_code: true,
diff --git a/test/compress/switch.js b/test/compress/switches.js
index e3f6859d..955fd68a 100644
--- a/test/compress/switch.js
+++ b/test/compress/switches.js
@@ -300,6 +300,37 @@ drop_default_2: {
}
}
+drop_default_3: {
+ options = {
+ dead_code: true,
+ evaluate: true,
+ switches: true,
+ }
+ input: {
+ function f() {
+ console.log("PASS");
+ return 42;
+ }
+ switch (42) {
+ case f():
+ break;
+ case void console.log("FAIL"):
+ default:
+ }
+ }
+ expect: {
+ function f() {
+ console.log("PASS");
+ return 42;
+ }
+ switch (42) {
+ case f():
+ case void console.log("FAIL"):
+ }
+ }
+ expect_stdout: "PASS"
+}
+
keep_default: {
options = {
dead_code: true,
@@ -423,7 +454,6 @@ drop_case_3: {
switch ({}.p) {
default:
case void 0:
- break;
case c = "FAIL":
}
console.log(c);
@@ -454,7 +484,166 @@ drop_case_4: {
expect_stdout: "PASS"
}
-keep_case: {
+drop_case_5: {
+ options = {
+ dead_code: true,
+ evaluate: true,
+ switches: true,
+ }
+ input: {
+ switch (42) {
+ case void console.log("PASS 1"):
+ console.log("FAIL 1");
+ case 42:
+ case console.log("FAIL 2"):
+ console.log("PASS 2");
+ }
+ }
+ expect: {
+ switch (42) {
+ case (void console.log("PASS 1"), 42):
+ console.log("PASS 2");
+ }
+ }
+ expect_stdout: [
+ "PASS 1",
+ "PASS 2",
+ ]
+}
+
+drop_case_6: {
+ options = {
+ dead_code: true,
+ evaluate: true,
+ switches: true,
+ }
+ input: {
+ switch (console.log("PASS 1"), 2) {
+ case 0:
+ console.log("FAIL 1");
+ case (console.log("PASS 2"), 1):
+ console.log("FAIL 2");
+ }
+ }
+ expect: {
+ switch (console.log("PASS 1"), 2) {
+ case (console.log("PASS 2"), 1):
+ }
+ }
+ expect_stdout: [
+ "PASS 1",
+ "PASS 2",
+ ]
+}
+
+drop_case_7: {
+ options = {
+ dead_code: true,
+ evaluate: true,
+ switches: true,
+ }
+ input: {
+ switch (2) {
+ case 0:
+ console.log("FAIL 1");
+ case (console.log("PASS 1"), 1):
+ console.log("FAIL 2");
+ case 2:
+ console.log("PASS 2");
+ }
+ }
+ expect: {
+ switch (2) {
+ case (console.log("PASS 1"), 1, 2):
+ console.log("PASS 2");
+ }
+ }
+ expect_stdout: [
+ "PASS 1",
+ "PASS 2",
+ ]
+}
+
+drop_case_8: {
+ options = {
+ dead_code: true,
+ switches: true,
+ }
+ input: {
+ function log(msg) {
+ console.log(msg);
+ return msg;
+ }
+ switch (log("foo")) {
+ case "bar":
+ log("moo");
+ break;
+ case log("baz"):
+ log("moo");
+ break;
+ default:
+ log("moo");
+ }
+ }
+ expect: {
+ function log(msg) {
+ console.log(msg);
+ return msg;
+ }
+ switch (log("foo")) {
+ case "bar":
+ case log("baz"):
+ default:
+ log("moo");
+ }
+ }
+ expect_stdout: [
+ "foo",
+ "baz",
+ "moo",
+ ]
+}
+
+drop_case_9: {
+ options = {
+ dead_code: true,
+ switches: true,
+ }
+ input: {
+ function log(msg) {
+ console.log(msg);
+ return msg;
+ }
+ switch (log("foo")) {
+ case log("bar"):
+ log("moo");
+ break;
+ case "baz":
+ log("moo");
+ break;
+ default:
+ log("moo");
+ }
+ }
+ expect: {
+ function log(msg) {
+ console.log(msg);
+ return msg;
+ }
+ switch (log("foo")) {
+ default:
+ log("bar");
+ log("moo");
+ }
+ }
+ expect_stdout: [
+ "foo",
+ "bar",
+ "moo",
+ ]
+}
+
+keep_case_1: {
options = {
dead_code: true,
switches: true,
@@ -474,6 +663,76 @@ keep_case: {
}
}
+keep_case_2: {
+ options = {
+ dead_code: true,
+ evaluate: true,
+ switches: true,
+ }
+ input: {
+ switch ("foo") {
+ case console.log("bar"):
+ case console.log("baz"), "moo":
+ }
+ }
+ expect: {
+ switch ("foo") {
+ case console.log("bar"):
+ case console.log("baz"), "moo":
+ }
+ }
+ expect_stdout: [
+ "bar",
+ "baz",
+ ]
+}
+
+keep_case_3: {
+ options = {
+ dead_code: true,
+ evaluate: true,
+ switches: true,
+ }
+ input: {
+ var a;
+ switch (void console.log("PASS")) {
+ case a:
+ case console.log("FAIL"), 42:
+ }
+ }
+ expect: {
+ var a;
+ switch (void console.log("PASS")) {
+ case a:
+ case console.log("FAIL"), 42:
+ }
+ }
+ expect_stdout: "PASS"
+}
+
+keep_case_4: {
+ options = {
+ dead_code: true,
+ evaluate: true,
+ switches: true,
+ }
+ input: {
+ var a;
+ switch (void console.log("PASS")) {
+ case a:
+ case void console.log("FAIL"):
+ }
+ }
+ expect: {
+ var a;
+ switch (void console.log("PASS")) {
+ case a:
+ case void console.log("FAIL"):
+ }
+ }
+ expect_stdout: "PASS"
+}
+
issue_376: {
options = {
dead_code: true,
@@ -1088,7 +1347,8 @@ drop_switch_6: {
}
}
expect: {
- A === B;
+ A;
+ B;
x();
C !== D;
y();