@@ -179,53 +179,21 @@ class ConstPlugin {
179179 ? statement . alternate
180180 : statement . consequent ;
181181 if ( branchToRemove ) {
182- // Before removing the dead branch, the hoisted declarations
183- // must be collected.
184- //
185- // Given the following code:
186- //
187- // if (true) f() else g()
188- // if (false) {
189- // function f() {}
190- // const g = function g() {}
191- // if (someTest) {
192- // let a = 1
193- // var x, {y, z} = obj
194- // }
195- // } else {
196- // …
197- // }
198- //
199- // the generated code is:
200- //
201- // if (true) f() else {}
202- // if (false) {
203- // var f, x, y, z; (in loose mode)
204- // var x, y, z; (in strict mode)
205- // } else {
206- // …
207- // }
208- //
209- // NOTE: When code runs in strict mode, `var` declarations
210- // are hoisted but `function` declarations don't.
211- //
212- const declarations = parser . scope . isStrict
213- ? getHoistedDeclarations ( branchToRemove , false )
214- : getHoistedDeclarations ( branchToRemove , true ) ;
215- const replacement =
216- declarations . length > 0
217- ? `{ var ${ declarations . join ( ", " ) } ; }`
218- : "{}" ;
219- const dep = new ConstDependency (
220- replacement ,
221- /** @type {Range } */ ( branchToRemove . range )
222- ) ;
223- dep . loc = /** @type {SourceLocation } */ ( branchToRemove . loc ) ;
224- parser . state . module . addPresentationalDependency ( dep ) ;
182+ this . eliminateUnusedStatement ( parser , branchToRemove ) ;
225183 }
226184 return bool ;
227185 }
228186 } ) ;
187+ parser . hooks . unusedStatement . tap ( PLUGIN_NAME , statement => {
188+ if (
189+ parser . scope . isAsmJs ||
190+ // Check top level scope here again
191+ parser . scope . topLevelScope === true
192+ )
193+ return ;
194+ this . eliminateUnusedStatement ( parser , statement ) ;
195+ return true ;
196+ } ) ;
229197 parser . hooks . expressionConditionalOperator . tap (
230198 PLUGIN_NAME ,
231199 expression => {
@@ -534,6 +502,56 @@ class ConstPlugin {
534502 }
535503 ) ;
536504 }
505+
506+ /**
507+ * Eliminate an unused statement.
508+ * @param {JavascriptParser } parser the parser
509+ * @param {Statement } statement the statement to remove
510+ * @returns {void }
511+ */
512+ eliminateUnusedStatement ( parser , statement ) {
513+ // Before removing the unused branch, the hoisted declarations
514+ // must be collected.
515+ //
516+ // Given the following code:
517+ //
518+ // if (true) f() else g()
519+ // if (false) {
520+ // function f() {}
521+ // const g = function g() {}
522+ // if (someTest) {
523+ // let a = 1
524+ // var x, {y, z} = obj
525+ // }
526+ // } else {
527+ // …
528+ // }
529+ //
530+ // the generated code is:
531+ //
532+ // if (true) f() else {}
533+ // if (false) {
534+ // var f, x, y, z; (in loose mode)
535+ // var x, y, z; (in strict mode)
536+ // } else {
537+ // …
538+ // }
539+ //
540+ // NOTE: When code runs in strict mode, `var` declarations
541+ // are hoisted but `function` declarations don't.
542+ //
543+ const declarations = parser . scope . isStrict
544+ ? getHoistedDeclarations ( statement , false )
545+ : getHoistedDeclarations ( statement , true ) ;
546+ const replacement =
547+ declarations . length > 0 ? `{ var ${ declarations . join ( ", " ) } ; }` : "{}" ;
548+ const dep = new ConstDependency (
549+ `// removed by dead control flow\n${ replacement } ` ,
550+ /** @type {Range } */ ( statement . range )
551+ ) ;
552+ dep . loc = /** @type {SourceLocation } */ ( statement . loc ) ;
553+ parser . state . module . addPresentationalDependency ( dep ) ;
554+ }
537555}
538556
539557module . exports = ConstPlugin ;
0 commit comments