fallthrough should not execute case expression (#1683)

- de-duplicate trailing cases only, avoid all potential side-effects
- enable switch statement fuzzing

fixes #1680
This commit is contained in:
Alex Lam S.L
2017-03-26 16:52:38 +08:00
committed by GitHub
parent 5509e51098
commit 3276740779
3 changed files with 83 additions and 22 deletions

View File

@@ -2515,7 +2515,7 @@ merge(Compressor.prototype, {
self.expression = best_of_expression(expression, self.expression);
}
if (compressor.option("dead_code")) {
var blocks = Object.create(null);
var prev_block;
var decl = [];
var body = [];
var default_branch;
@@ -2542,31 +2542,21 @@ merge(Compressor.prototype, {
continue;
}
}
var case_side_effects = branch instanceof AST_Case && branch.expression.has_side_effects(compressor);
if (aborts(branch)) {
var key = make_node(AST_BlockStatement, branch, branch).print_to_string();
var block;
if (!fallthrough && (block = blocks[key])) {
block.body = [];
body.splice(body.indexOf(block) + 1, 0, branch);
} else {
body.push(branch);
}
var block = make_node(AST_BlockStatement, branch, branch).print_to_string();
if (!fallthrough && prev_block === block) body[body.length - 1].body = [];
body.push(branch);
prev_block = block;
fallthrough = false;
} else {
body.push(branch);
prev_block = null;
fallthrough = true;
}
if (branch instanceof AST_Case && branch.expression.has_side_effects(compressor))
blocks = Object.create(null);
if (!fallthrough) blocks[key] = branch;
}
for (; i < len && fallthrough; i++) {
branch = self.body[i];
if (branch instanceof AST_Case) {
exact_match.body.push(make_node(AST_SimpleStatement, branch.expression, {
body: branch.expression
}));
}
exact_match.body = exact_match.body.concat(branch.body);
fallthrough = !aborts(exact_match);
}

View File

@@ -23,7 +23,6 @@ constant_switch_2: {
}
expect: {
foo();
2;
bar();
}
}
@@ -118,7 +117,6 @@ constant_switch_6: {
x();
if (foo) break OUT;
y();
2;
bar();
}
}
@@ -157,7 +155,6 @@ constant_switch_7: {
console.log(x);
}
y();
2;
bar();
}
}
@@ -206,7 +203,6 @@ constant_switch_9: {
x();
for (;;) if (foo) break OUT;
y();
2;
bar();
def();
}
@@ -481,3 +477,79 @@ issue_1679: {
}
expect_stdout: true
}
issue_1680_1: {
options = {
dead_code: true,
evaluate: true,
}
input: {
function f(x) {
console.log(x);
return x + 1;
}
switch (2) {
case f(0):
case f(1):
f(2);
case 2:
case f(3):
case f(4):
f(5);
}
}
expect: {
function f(x) {
console.log(x);
return x + 1;
}
switch (2) {
case f(0):
case f(1):
f(2);
case 2:
f(5);
}
}
expect_stdout: [
"0",
"1",
"2",
"5",
]
}
issue_1680_2: {
options = {
dead_code: true,
}
input: {
var a = 100, b = 10;
switch (b) {
case a--:
break;
case b:
var c;
break;
case a:
break;
case a--:
break;
}
console.log(a, b);
}
expect: {
var a = 100, b = 10;
switch (b) {
case a--:
break;
case b:
var c;
break;
case a:
case a--:
}
console.log(a, b);
}
expect_stdout: true
}

View File

@@ -201,7 +201,6 @@ function createStatement(recurmax, canThrow, canBreak, canContinue) {
case 6:
return createExpression(recurmax) + ';';
case 7:
return ';'; // TODO: disabled until some switch issues are resolved
// note: case args are actual expressions
// note: default does not _need_ to be last
return 'switch (' + createExpression(recurmax) + ') { ' + createSwitchParts(recurmax, 4) + '}';