From 650149bd5d516efeaa733b168606abcfdf301fc4 Mon Sep 17 00:00:00 2001 From: Boopathi Rajaa Date: Tue, 17 Jul 2018 21:43:08 +0200 Subject: [PATCH] fix(deadcode): sequence expressions in switch discriminant (#881) * fix(deadcode): sequence expressions in switch discriminant * fix null case to expressionStatement --- .../src/index.js | 44 ++++++++++++++++--- .../__tests__/preset-tests.js | 35 +++++++++++++++ 2 files changed, 72 insertions(+), 7 deletions(-) diff --git a/packages/babel-plugin-minify-dead-code-elimination/src/index.js b/packages/babel-plugin-minify-dead-code-elimination/src/index.js index 099a02c1d..207a01910 100644 --- a/packages/babel-plugin-minify-dead-code-elimination/src/index.js +++ b/packages/babel-plugin-minify-dead-code-elimination/src/index.js @@ -563,10 +563,37 @@ module.exports = ({ types: t, traverse }) => { SwitchStatement: { exit(path) { - const evaluated = evaluate(path.get("discriminant"), { tdz: this.tdz }); + const discriminantPath = path.get("discriminant"); + const evaluated = evaluate(discriminantPath, { tdz: this.tdz }); if (!evaluated.confident) return; + // the simplify transformation might have brought in the previous + // expressions into the switch's test expression and instead of + // bailing out of impure path, we collect the impurities of it's + // a sequence expression and bail out if the primary test itself + // is impure + let beforeTest = []; + if (t.isSequenceExpression(discriminantPath.node)) { + const expressions = discriminantPath.get("expressions"); + const lastExpression = expressions[expressions.length - 1]; + if (!lastExpression.isPure()) { + return; + } + + beforeTest = [ + t.expressionStatement( + t.sequenceExpression( + expressions + .slice(0, expressions.length - 1) + .map(path => path.node) + ) + ) + ]; + } else if (!discriminantPath.isPure()) { + return; + } + const discriminant = evaluated.value; const cases = path.get("cases"); @@ -582,7 +609,9 @@ module.exports = ({ types: t, traverse }) => { continue; } - const testResult = evaluate(test, { tdz: this.tdz }); + const testResult = evaluate(test, { + tdz: this.tdz + }); // if we are not able to deternine a test during // compile time, we terminate immediately @@ -613,13 +642,14 @@ module.exports = ({ types: t, traverse }) => { // we extract vars from the entire switch statement // and there will be duplicates which // will be again removed by DCE - replaceSwitch([...extractVars(path), ...result.statements]); + replaceSwitch([ + ...extractVars(path), + ...beforeTest, + ...result.statements + ]); function getStatementsUntilBreak(start) { - const result = { - bail: false, - statements: [] - }; + const result = { bail: false, statements: [] }; for (let i = start; i < cases.length; i++) { const consequent = cases[i].get("consequent"); diff --git a/packages/babel-preset-minify/__tests__/preset-tests.js b/packages/babel-preset-minify/__tests__/preset-tests.js index a5482a945..79c553132 100644 --- a/packages/babel-preset-minify/__tests__/preset-tests.js +++ b/packages/babel-preset-minify/__tests__/preset-tests.js @@ -170,4 +170,39 @@ describe("preset", () => { var bar; ` ); + + thePlugin( + "should fix issue#880 - switch test in deadcode after simplify", + ` + (function () { + const test = 2; + + console.log("before switch"); + + switch (test) { + case 1: + console.log("case 1"); + break; + + case 2: + console.log("case 2"); + break; + + case 3: + default: + console.log("case 3"); + break; + } + + console.log("after switch"); + })(); + `, + ` + (function () { + console.log("before switch"); + console.log("case 2"); + console.log("after switch"); + })(); + ` + ); });