fix corner case in switches (#3585)

This commit is contained in:
Alex Lam S.L
2019-11-14 02:29:55 +08:00
committed by GitHub
parent 4bd36dc8da
commit 910799ca99
2 changed files with 100 additions and 60 deletions

View File

@@ -4872,25 +4872,23 @@ merge(Compressor.prototype, {
prev.body = []; prev.body = [];
} }
} }
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); body.push(branch);
} }
}
while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]); while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]);
if (body.length > 0) {
body[0].body = decl.concat(body[0].body);
}
self.body = body;
while (branch = body[body.length - 1]) { while (branch = body[body.length - 1]) {
var stat = branch.body[branch.body.length - 1]; var stat = branch.body[branch.body.length - 1];
if (is_break(stat, compressor)) branch.body.pop(); if (is_break(stat, compressor)) branch.body.pop();
if (branch.body.length || branch instanceof AST_Case if (branch === default_branch) {
&& (default_branch || branch.expression.has_side_effects(compressor))) break; if (!is_body_empty(branch)) break;
} else if (branch.expression.has_side_effects(compressor)) {
break;
} else if (default_branch) {
if (!is_body_empty(default_branch)) break;
if (body[body.length - 2] !== default_branch) break;
default_branch.body = default_branch.body.concat(branch.body);
branch.body = [];
} else if (!is_body_empty(branch)) break;
eliminate_branch(branch);
if (body.pop() === default_branch) default_branch = null; if (body.pop() === default_branch) default_branch = null;
} }
if (body.length == 0) { if (body.length == 0) {
@@ -4900,6 +4898,8 @@ merge(Compressor.prototype, {
})) }))
}).optimize(compressor); }).optimize(compressor);
} }
body[0].body = decl.concat(body[0].body);
self.body = body;
if (body.length == 1 && (body[0] === exact_match || body[0] === default_branch)) { if (body.length == 1 && (body[0] === exact_match || body[0] === default_branch)) {
var has_break = false; var has_break = false;
var tw = new TreeWalker(function(node) { var tw = new TreeWalker(function(node) {
@@ -4929,6 +4929,16 @@ merge(Compressor.prototype, {
return node instanceof AST_Break && tw.loopcontrol_target(node) === self; return node instanceof AST_Break && tw.loopcontrol_target(node) === self;
} }
function is_body_empty(branch) {
return all(branch.body, function(stat) {
return is_empty(stat)
|| stat instanceof AST_Defun
|| stat instanceof AST_Var && all(stat.definitions, function(var_def) {
return !var_def.value;
});
});
}
function eliminate_branch(branch, prev) { function eliminate_branch(branch, prev) {
if (prev && !aborts(prev)) { if (prev && !aborts(prev)) {
prev.body = prev.body.concat(branch.body); prev.body = prev.body.concat(branch.body);

View File

@@ -393,6 +393,57 @@ drop_case_2: {
} }
} }
drop_case_3: {
options = {
dead_code: true,
switches: true,
}
input: {
var c = "PASS";
switch ({}.p) {
default:
case void 0:
break;
case c = "FAIL":
}
console.log(c);
}
expect: {
var c = "PASS";
switch ({}.p) {
default:
case void 0:
break;
case c = "FAIL":
}
console.log(c);
}
expect_stdout: "PASS"
}
drop_case_4: {
options = {
dead_code: true,
switches: true,
}
input: {
switch (0) {
case [ a, typeof b ]:
default:
var a;
}
console.log("PASS");
}
expect: {
switch (0) {
case [ a, typeof b ]:
var a;
}
console.log("PASS");
}
expect_stdout: "PASS"
}
keep_case: { keep_case: {
options = { options = {
dead_code: true, dead_code: true,
@@ -521,7 +572,7 @@ issue_1674: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_1679_1: { issue_1679: {
options = { options = {
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
@@ -548,34 +599,6 @@ issue_1679_1: {
console.log(a, b); console.log(a, b);
} }
expect: { 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; var a = 100, b = 10;
function f() { function f() {
switch (--b) { switch (--b) {
@@ -589,23 +612,6 @@ issue_1679_2: {
} }
break; break;
case (a++): case (a++):
break;
}
}
f();
console.log(a, b);
}
expect: {
var a = 100, b = 10;
function f() {
switch (--b) {
case b--:
switch (0) {
default:
case a--:
}
break;
case (a++):
} }
} }
f(); f();
@@ -998,3 +1004,27 @@ drop_switch_3: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
drop_switch_4: {
options = {
dead_code: true,
switches: true,
}
input: {
var a = "FAIL";
switch (0) {
default:
case a:
var b = a = "PASS";
break;
}
console.log(a);
}
expect: {
var a = "FAIL";
0;
var b = a = "PASS";
console.log(a);
}
expect_stdout: "PASS"
}