Skip to content

Commit

Permalink
fix(minifier): Preserve init variable declarations when removing `for…
Browse files Browse the repository at this point in the history
…` statements during DCE (#6551)

- Closes: #6547

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
  • Loading branch information
magic-akari and autofix-ci[bot] authored Oct 15, 2024
1 parent 2e4c793 commit a71e8a0
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 17 deletions.
14 changes: 14 additions & 0 deletions crates/oxc_ast/src/ast_builder_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,20 @@ impl<'a> AstBuilder<'a> {
mem::replace(decl, empty_decl)
}

#[inline]
pub fn move_variable_declaration(
self,
decl: &mut VariableDeclaration<'a>,
) -> VariableDeclaration<'a> {
let empty_decl = self.variable_declaration(
Span::default(),
VariableDeclarationKind::Var,
self.vec(),
false,
);
mem::replace(decl, empty_decl)
}

#[inline]
pub fn move_vec<T>(self, vec: &mut Vec<'a, T>) -> Vec<'a, T> {
mem::replace(vec, self.vec())
Expand Down
29 changes: 24 additions & 5 deletions crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,26 @@ impl<'a, 'b> PeepholeRemoveDeadCode {
// Check vars in statement
let mut keep_var = KeepVar::new(ctx.ast);
keep_var.visit_statement(&for_stmt.body);
Some(
keep_var
.get_variable_declaration_statement()
.unwrap_or_else(|| ctx.ast.statement_empty(SPAN)),
)

let mut var_decl = keep_var.get_variable_declaration();

if let Some(ForStatementInit::VariableDeclaration(var_init)) = &mut for_stmt.init {
if var_init.kind.is_var() {
if let Some(var_decl) = &mut var_decl {
var_decl
.declarations
.splice(0..0, ctx.ast.move_vec(&mut var_init.declarations));
} else {
var_decl = Some(ctx.ast.move_variable_declaration(var_init));
}
}
}

var_decl
.map(|var_decl| {
ctx.ast.statement_declaration(ctx.ast.declaration_from_variable(var_decl))
})
.or_else(|| Some(ctx.ast.statement_empty(SPAN)))
}
Some(true) => {
// Remove the test expression.
Expand Down Expand Up @@ -350,6 +365,10 @@ mod test {
// Make sure it plays nice with minimizing
fold("for(;false;) { foo(); continue }", "");

fold("for (var { c, x: [d] } = {}; 0;);", "var { c, x: [d] } = {};");
fold("for (var se = [1, 2]; false;);", "var se = [1, 2];");
fold("for (var se = [1, 2]; false;) { var a = 0; }", "var se = [1, 2], a;");

// fold("l1:for(;false;) { }", "");
}

Expand Down
32 changes: 20 additions & 12 deletions crates/oxc_minifier/src/keep_var.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,21 @@ impl<'a> Visit<'a> for KeepVar<'a> {
// match_module_declaration!(Statement) => {
// visitor.visit_module_declaration(it.to_module_declaration())
// }
Statement::VariableDeclaration(decl) => {
if decl.kind.is_var() {
decl.bound_names(&mut |ident| {
self.vars.push((ident.name.clone(), ident.span));
});
if decl.has_init() {
self.all_hoisted = false;
}
}
}
Statement::VariableDeclaration(decl) => self.visit_variable_declaration(decl),
_ => {}
}
}

fn visit_variable_declaration(&mut self, it: &VariableDeclaration<'a>) {
if it.kind.is_var() {
it.bound_names(&mut |ident| {
self.vars.push((ident.name.clone(), ident.span));
});
if it.has_init() {
self.all_hoisted = false;
}
}
}
}

impl<'a> KeepVar<'a> {
Expand All @@ -58,7 +60,7 @@ impl<'a> KeepVar<'a> {
self.all_hoisted
}

pub fn get_variable_declaration_statement(self) -> Option<Statement<'a>> {
pub fn get_variable_declaration(self) -> Option<VariableDeclaration<'a>> {
if self.vars.is_empty() {
return None;
}
Expand All @@ -71,7 +73,13 @@ impl<'a> KeepVar<'a> {
}));

let decl = self.ast.variable_declaration(SPAN, kind, decls, false);
let stmt = self.ast.statement_declaration(self.ast.declaration_from_variable(decl));
Some(decl)
}

pub fn get_variable_declaration_statement(self) -> Option<Statement<'a>> {
let stmt = self.ast.statement_declaration(
self.ast.declaration_from_variable(self.get_variable_declaration()?),
);
Some(stmt)
}
}

0 comments on commit a71e8a0

Please sign in to comment.