fix corner case in switches (#5013)

fixes #5012
This commit is contained in:
Alex Lam S.L 2021-06-15 16:51:53 +01:00 committed by GitHub
parent 21fc8f4630
commit 7880568d15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 31 deletions

View File

@ -8422,7 +8422,7 @@ merge(Compressor.prototype, {
var default_branch; var default_branch;
var exact_match; var exact_match;
var side_effects = []; var side_effects = [];
for (var i = 0, len = self.body.length; i < len && !exact_match; i++) { for (var i = 0, len = self.body.length; i < len; i++) {
branch = self.body[i]; branch = self.body[i];
if (branch instanceof AST_Default) { if (branch instanceof AST_Default) {
var prev = body[body.length - 1]; var prev = body[body.length - 1];
@ -8445,16 +8445,21 @@ merge(Compressor.prototype, {
continue; continue;
} }
if (!(equals instanceof AST_Node)) { if (!(equals instanceof AST_Node)) {
exact_match = branch;
if (default_branch) { if (default_branch) {
var default_index = body.indexOf(default_branch); var default_index = body.indexOf(default_branch);
body.splice(default_index, 1); body.splice(default_index, 1);
eliminate_branch(default_branch, body[default_index - 1]); eliminate_branch(default_branch, body[default_index - 1]);
default_branch = null; default_branch = null;
} }
if (exp.has_side_effects(compressor)) {
exact_match = branch;
} else {
default_branch = branch = make_node(AST_Default, branch, branch);
}
while (++i < len) eliminate_branch(self.body[i], branch);
} }
} }
if (exact_match || i == len - 1 || aborts(branch)) { if (i + 1 >= len || aborts(branch)) {
var prev = body[body.length - 1]; var prev = body[body.length - 1];
var statements = branch.body; var statements = branch.body;
if (aborts(prev)) switch (prev.body.length - statements.length) { if (aborts(prev)) switch (prev.body.length - statements.length) {
@ -8479,7 +8484,6 @@ merge(Compressor.prototype, {
} }
body.push(branch); body.push(branch);
} }
while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]);
if (side_effects.length && !exact_match) { if (side_effects.length && !exact_match) {
body.push(make_node(AST_Case, self, { expression: make_sequence(self, side_effects), body: [] })); body.push(make_node(AST_Case, self, { expression: make_sequence(self, side_effects), body: [] }));
} }
@ -8506,24 +8510,18 @@ merge(Compressor.prototype, {
})); }));
return make_node(AST_BlockStatement, self, { body: decl }).optimize(compressor); return make_node(AST_BlockStatement, self, { body: decl }).optimize(compressor);
} }
if (branch === default_branch || branch === exact_match && !branch.expression.has_side_effects(compressor)) { if (branch === default_branch) while (branch = body[body.length - 2]) {
while (branch = body[body.length - 2]) {
if (branch instanceof AST_Default) break; if (branch instanceof AST_Default) break;
if (!has_declarations_only(branch)) break; if (!has_declarations_only(branch)) break;
var exp = branch.expression; var exp = branch.expression;
if (exp.has_side_effects(compressor)) { if (exp.has_side_effects(compressor)) {
var prev = body[body.length - 3]; var prev = body[body.length - 3];
if (prev && !aborts(prev)) break; 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 })); default_branch.body.unshift(make_node(AST_SimpleStatement, self, { body: exp }));
} }
}
eliminate_branch(branch); eliminate_branch(branch);
body.splice(-2, 1); body.splice(-2, 1);
} }
}
body[0].body = decl.concat(body[0].body); body[0].body = decl.concat(body[0].body);
self.body = body; self.body = body;
if (compressor.option("conditionals")) switch (body.length) { if (compressor.option("conditionals")) switch (body.length) {

View File

@ -3075,7 +3075,7 @@ issue_4237_2: {
console.log(function(a) { console.log(function(a) {
do { do {
switch (0) { switch (0) {
case 0: default:
var b = a++; var b = a++;
if (b) if (b)
return "FAIL"; return "FAIL";

View File

@ -113,7 +113,7 @@ constant_switch_5: {
// the break inside the if ruins our job // the break inside the if ruins our job
// we can still get rid of irrelevant cases. // we can still get rid of irrelevant cases.
switch (1) { switch (1) {
case 1: default:
x(); x();
if (foo) break; if (foo) break;
y(); y();
@ -501,7 +501,8 @@ drop_case_5: {
} }
expect: { expect: {
switch (42) { switch (42) {
case (void console.log("PASS 1"), 42): default:
void console.log("PASS 1");
console.log("PASS 2"); console.log("PASS 2");
} }
} }
@ -554,7 +555,8 @@ drop_case_7: {
} }
expect: { expect: {
switch (2) { switch (2) {
case (console.log("PASS 1"), 1, 2): default:
console.log("PASS 1"), 1;
console.log("PASS 2"); console.log("PASS 2");
} }
} }
@ -920,7 +922,7 @@ issue_1680_1: {
case f(0): case f(0):
case f(1): case f(1):
f(2); f(2);
case 2: default:
f(5); f(5);
} }
} }
@ -1183,7 +1185,6 @@ issue_2535: {
} }
expect: { expect: {
w(), 42; w(), 42;
42;
y(); y();
z(); z();
} }
@ -1209,7 +1210,6 @@ issue_1750: {
expect: { expect: {
var a = 0, b = 1; var a = 0, b = 1;
true; true;
a, true;
b = 2; b = 2;
console.log(a, b); console.log(a, b);
} }
@ -1463,7 +1463,7 @@ issue_5008_1: {
expect: { expect: {
console.log(function f() { console.log(function f() {
switch (f) { switch (f) {
case f: default:
return "PASS"; return "PASS";
} }
}()); }());
@ -1492,7 +1492,7 @@ issue_5008_2: {
expect: { expect: {
console.log(function(a) { console.log(function(a) {
switch (a) { switch (a) {
case a: default:
return "PASS"; return "PASS";
} }
}([])); }([]));
@ -1521,7 +1521,7 @@ issue_5008_3: {
expect: { expect: {
console.log(function(a) { console.log(function(a) {
switch (a) { switch (a) {
case a: default:
return "PASS"; return "PASS";
} }
}({})); }({}));
@ -1549,7 +1549,7 @@ issue_5008_4: {
expect: { expect: {
console.log(function(a) { console.log(function(a) {
switch (a) { switch (a) {
case a: default:
return "PASS"; return "PASS";
} }
}(/foo/)); }(/foo/));
@ -1582,3 +1582,29 @@ issue_5010: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_5012: {
options = {
dead_code: true,
evaluate: true,
switches: true,
}
input: {
switch (void 0) {
case console.log("PASS"):
break;
case void 0:
case 42:
console.log("FAIL");
}
}
expect: {
switch (void 0) {
case console.log("PASS"):
break;
default:
console.log("FAIL");
}
}
expect_stdout: "PASS"
}