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:
@@ -2515,7 +2515,7 @@ merge(Compressor.prototype, {
|
|||||||
self.expression = best_of_expression(expression, self.expression);
|
self.expression = best_of_expression(expression, self.expression);
|
||||||
}
|
}
|
||||||
if (compressor.option("dead_code")) {
|
if (compressor.option("dead_code")) {
|
||||||
var blocks = Object.create(null);
|
var prev_block;
|
||||||
var decl = [];
|
var decl = [];
|
||||||
var body = [];
|
var body = [];
|
||||||
var default_branch;
|
var default_branch;
|
||||||
@@ -2542,31 +2542,21 @@ merge(Compressor.prototype, {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var case_side_effects = branch instanceof AST_Case && branch.expression.has_side_effects(compressor);
|
||||||
if (aborts(branch)) {
|
if (aborts(branch)) {
|
||||||
var key = make_node(AST_BlockStatement, branch, branch).print_to_string();
|
var block = make_node(AST_BlockStatement, branch, branch).print_to_string();
|
||||||
var block;
|
if (!fallthrough && prev_block === block) body[body.length - 1].body = [];
|
||||||
if (!fallthrough && (block = blocks[key])) {
|
body.push(branch);
|
||||||
block.body = [];
|
prev_block = block;
|
||||||
body.splice(body.indexOf(block) + 1, 0, branch);
|
|
||||||
} else {
|
|
||||||
body.push(branch);
|
|
||||||
}
|
|
||||||
fallthrough = false;
|
fallthrough = false;
|
||||||
} else {
|
} else {
|
||||||
body.push(branch);
|
body.push(branch);
|
||||||
|
prev_block = null;
|
||||||
fallthrough = true;
|
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++) {
|
for (; i < len && fallthrough; i++) {
|
||||||
branch = self.body[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);
|
exact_match.body = exact_match.body.concat(branch.body);
|
||||||
fallthrough = !aborts(exact_match);
|
fallthrough = !aborts(exact_match);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ constant_switch_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
foo();
|
foo();
|
||||||
2;
|
|
||||||
bar();
|
bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +117,6 @@ constant_switch_6: {
|
|||||||
x();
|
x();
|
||||||
if (foo) break OUT;
|
if (foo) break OUT;
|
||||||
y();
|
y();
|
||||||
2;
|
|
||||||
bar();
|
bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,7 +155,6 @@ constant_switch_7: {
|
|||||||
console.log(x);
|
console.log(x);
|
||||||
}
|
}
|
||||||
y();
|
y();
|
||||||
2;
|
|
||||||
bar();
|
bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,7 +203,6 @@ constant_switch_9: {
|
|||||||
x();
|
x();
|
||||||
for (;;) if (foo) break OUT;
|
for (;;) if (foo) break OUT;
|
||||||
y();
|
y();
|
||||||
2;
|
|
||||||
bar();
|
bar();
|
||||||
def();
|
def();
|
||||||
}
|
}
|
||||||
@@ -481,3 +477,79 @@ issue_1679: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -201,7 +201,6 @@ function createStatement(recurmax, canThrow, canBreak, canContinue) {
|
|||||||
case 6:
|
case 6:
|
||||||
return createExpression(recurmax) + ';';
|
return createExpression(recurmax) + ';';
|
||||||
case 7:
|
case 7:
|
||||||
return ';'; // TODO: disabled until some switch issues are resolved
|
|
||||||
// note: case args are actual expressions
|
// note: case args are actual expressions
|
||||||
// note: default does not _need_ to be last
|
// note: default does not _need_ to be last
|
||||||
return 'switch (' + createExpression(recurmax) + ') { ' + createSwitchParts(recurmax, 4) + '}';
|
return 'switch (' + createExpression(recurmax) + ') { ' + createSwitchParts(recurmax, 4) + '}';
|
||||||
|
|||||||
Reference in New Issue
Block a user