@@ -303,7 +303,7 @@ impl<'a> PeepholeOptimizations {
303303 result. push ( Statement :: ContinueStatement ( s) ) ;
304304 }
305305 Statement :: VariableDeclaration ( var_decl) => {
306- self . handle_variable_declaration ( var_decl, result, state) ;
306+ self . handle_variable_declaration ( var_decl, result, state, ctx ) ;
307307 }
308308 Statement :: ExpressionStatement ( expr_stmt) => {
309309 self . handle_expression_statement ( expr_stmt, result, state, ctx) ;
@@ -367,20 +367,52 @@ impl<'a> PeepholeOptimizations {
367367 false
368368 }
369369
370+ /// For variable declarations:
371+ /// * merge with the previous variable declarator if their kinds are the same
372+ /// * remove the variable declarator if it is unused
373+ /// * keep the initializer if it has side effects
370374 fn handle_variable_declaration (
371375 & self ,
372- mut var_decl : Box < ' a , VariableDeclaration < ' a > > ,
376+ var_decl : Box < ' a , VariableDeclaration < ' a > > ,
373377 result : & mut Vec < ' a , Statement < ' a > > ,
374378 state : & mut State ,
379+ ctx : & mut Ctx < ' a , ' _ > ,
375380 ) {
376- if let Some ( Statement :: VariableDeclaration ( prev_var_decl) ) = result. last_mut ( ) {
381+ if let Some ( Statement :: VariableDeclaration ( prev_var_decl) ) = result. last ( ) {
377382 if var_decl. kind == prev_var_decl. kind {
378- prev_var_decl. declarations . extend ( var_decl. declarations . drain ( ..) ) ;
379383 state. changed = true ;
380- return ;
381384 }
382385 }
383- result. push ( Statement :: VariableDeclaration ( var_decl) ) ;
386+ let VariableDeclaration { span, kind, declarations, declare } = var_decl. unbox ( ) ;
387+ for mut decl in declarations {
388+ if Self :: is_declarator_unused ( & decl, ctx) {
389+ state. changed = true ;
390+ if let Some ( init) = decl. init . take ( ) {
391+ if init. may_have_side_effects ( ctx) {
392+ result. push ( ctx. ast . statement_expression ( init. span ( ) , init) ) ;
393+ }
394+ }
395+ } else {
396+ if let Some ( Statement :: VariableDeclaration ( prev_var_decl) ) = result. last_mut ( ) {
397+ if kind == prev_var_decl. kind {
398+ prev_var_decl. declarations . push ( decl) ;
399+ continue ;
400+ }
401+ }
402+ let decls = ctx. ast . vec1 ( decl) ;
403+ let new_decl = ctx. ast . alloc_variable_declaration ( span, kind, decls, declare) ;
404+ result. push ( Statement :: VariableDeclaration ( new_decl) ) ;
405+ }
406+ }
407+ }
408+
409+ fn is_declarator_unused ( decl : & VariableDeclarator < ' a > , ctx : & mut Ctx < ' a , ' _ > ) -> bool {
410+ if let BindingPatternKind :: BindingIdentifier ( ident) = & decl. id . kind {
411+ if let Some ( symbol_id) = ident. symbol_id . get ( ) {
412+ return ctx. scoping ( ) . symbol_is_unused ( symbol_id) ;
413+ }
414+ }
415+ false
384416 }
385417
386418 fn handle_expression_statement (
0 commit comments