Skip to content

Commit

Permalink
enhance switches (#3583)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl committed Nov 13, 2019
1 parent fe65ce9 commit ab15c40
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 22 deletions.
27 changes: 19 additions & 8 deletions lib/compress.js
Expand Up @@ -4828,10 +4828,12 @@ merge(Compressor.prototype, {
for (var i = 0, len = self.body.length; i < len && !exact_match; i++) {
branch = self.body[i];
if (branch instanceof AST_Default) {
if (!default_branch) {
default_branch = branch;
var prev = body[body.length - 1];
if (default_branch || is_break(branch.body[0], compressor) && (!prev || aborts(prev))) {
eliminate_branch(branch, prev);
continue;
} else {
eliminate_branch(branch, body[body.length - 1]);
default_branch = branch;
}
} else if (!(value instanceof AST_Node)) {
var exp = branch.expression.evaluate(compressor);
Expand All @@ -4857,7 +4859,14 @@ merge(Compressor.prototype, {
prev.body = [];
}
}
body.push(branch);
if (default_branch
&& default_branch.body.length == 0
&& body[body.length - 1] === default_branch
&& !branch.expression.has_side_effects(compressor)) {
default_branch.body = branch.body.slice();
} else {
body.push(branch);
}
}
while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]);
if (body.length > 0) {
Expand All @@ -4866,8 +4875,7 @@ merge(Compressor.prototype, {
self.body = body;
while (branch = body[body.length - 1]) {
var stat = branch.body[branch.body.length - 1];
if (stat instanceof AST_Break && compressor.loopcontrol_target(stat) === self)
branch.body.pop();
if (is_break(stat, compressor)) branch.body.pop();
if (branch.body.length || branch instanceof AST_Case
&& (default_branch || branch.expression.has_side_effects(compressor))) break;
if (body.pop() === default_branch) default_branch = null;
Expand All @@ -4885,8 +4893,7 @@ merge(Compressor.prototype, {
if (has_break
|| node instanceof AST_Lambda
|| node instanceof AST_SimpleStatement) return true;
if (node instanceof AST_Break && tw.loopcontrol_target(node) === self)
has_break = true;
if (is_break(node, tw)) has_break = true;
});
self.walk(tw);
if (!has_break) {
Expand All @@ -4905,6 +4912,10 @@ merge(Compressor.prototype, {
}
return self;

function is_break(node, tw) {
return node instanceof AST_Break && tw.loopcontrol_target(node) === self;
}

function eliminate_branch(branch, prev) {
if (prev && !aborts(prev)) {
prev.body = prev.body.concat(branch.body);
Expand Down
162 changes: 148 additions & 14 deletions test/compress/switch.js
Expand Up @@ -261,13 +261,13 @@ drop_default_1: {
}
input: {
switch (foo) {
case 'bar': baz();
case "bar": baz();
default:
}
}
expect: {
switch (foo) {
case 'bar': baz();
case "bar": baz();
}
}
}
Expand All @@ -279,14 +279,14 @@ drop_default_2: {
}
input: {
switch (foo) {
case 'bar': baz(); break;
case "bar": baz(); break;
default:
break;
}
}
expect: {
switch (foo) {
case 'bar': baz();
case "bar": baz();
}
}
}
Expand All @@ -298,15 +298,15 @@ keep_default: {
}
input: {
switch (foo) {
case 'bar': baz();
case "bar": baz();
default:
something();
break;
}
}
expect: {
switch (foo) {
case 'bar': baz();
case "bar": baz();
default:
something();
}
Expand Down Expand Up @@ -347,21 +347,48 @@ issue_1663: {
expect_stdout: true
}

drop_case: {
drop_case_1: {
options = {
dead_code: true,
switches: true,
}
input: {
switch (foo) {
case 'bar': baz(); break;
case 'moo':
case "bar": baz(); break;
case "moo":
break;
}
}
expect: {
switch (foo) {
case 'bar': baz();
case "bar": baz();
}
}
}

drop_case_2: {
options = {
dead_code: true,
switches: true,
}
input: {
switch (foo) {
case "bar":
bar();
break;
default:
case "moo":
moo();
break;
}
}
expect: {
switch (foo) {
case "bar":
bar();
break;
default:
moo();
}
}
}
Expand All @@ -373,14 +400,14 @@ keep_case: {
}
input: {
switch (foo) {
case 'bar': baz(); break;
case "bar": baz(); break;
case moo:
break;
}
}
expect: {
switch (foo) {
case 'bar': baz(); break;
case "bar": baz(); break;
case moo:
}
}
Expand Down Expand Up @@ -494,7 +521,7 @@ issue_1674: {
expect_stdout: "PASS"
}

issue_1679: {
issue_1679_1: {
options = {
dead_code: true,
evaluate: true,
Expand All @@ -521,6 +548,34 @@ issue_1679: {
console.log(a, b);
}
expect: {
var a = 100, b = 10;
function f() {
switch (--b) {
default:
break;
case b--:
switch (0) {
default:
case a--:
}
break;
case (a++):
}
}
f();
console.log(a, b);
}
expect_stdout: "99 8"
}

issue_1679_2: {
options = {
dead_code: true,
evaluate: true,
passes: 2,
switches: true,
}
input: {
var a = 100, b = 10;
function f() {
switch (--b) {
Expand All @@ -534,12 +589,29 @@ issue_1679: {
}
break;
case (a++):
break;
}
}
f();
console.log(a, b);
}
expect_stdout: true
expect: {
var a = 100, b = 10;
function f() {
switch (--b) {
case b--:
switch (0) {
default:
case a--:
}
break;
case (a++):
}
}
f();
console.log(a, b);
}
expect_stdout: "99 8"
}

issue_1680_1: {
Expand Down Expand Up @@ -864,3 +936,65 @@ issue_1750: {
}
expect_stdout: "0 2"
}

drop_switch_1: {
options = {
dead_code: true,
switches: true,
}
input: {
switch (foo) {
default:
break;
case "bar":
break;
}
}
expect: {
foo;
}
}

drop_switch_2: {
options = {
dead_code: true,
switches: true,
}
input: {
switch (foo) {
default:
case "bar":
baz();
}
}
expect: {
foo;
baz();
}
}

drop_switch_3: {
options = {
dead_code: true,
switches: true,
}
input: {
console.log(function() {
switch (0) {
default:
return "PASS";
case 1:
}
}());
}
expect: {
console.log(function() {
switch (0) {
default:
return "PASS";
case 1:
}
}());
}
expect_stdout: "PASS"
}

0 comments on commit ab15c40

Please sign in to comment.