@@ -179,53 +179,21 @@ class ConstPlugin {
179
179
? statement . alternate
180
180
: statement . consequent ;
181
181
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 ) ;
225
183
}
226
184
return bool ;
227
185
}
228
186
} ) ;
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
+ } ) ;
229
197
parser . hooks . expressionConditionalOperator . tap (
230
198
PLUGIN_NAME ,
231
199
expression => {
@@ -534,6 +502,56 @@ class ConstPlugin {
534
502
}
535
503
) ;
536
504
}
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
+ }
537
555
}
538
556
539
557
module . exports = ConstPlugin ;
0 commit comments