Skip to content

Commit c6f5d22

Browse files
committed
feat(minifier): remove unused variable declaration
part of #10033
1 parent 6f398e0 commit c6f5d22

File tree

1 file changed

+38
-6
lines changed

1 file changed

+38
-6
lines changed

crates/oxc_minifier/src/peephole/minimize_statements.rs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)