mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
fix(minifier): Preserve init variable declarations when removing for statements during DCE (#6551)
- Closes: #6547 --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
2e4c793a78
commit
a71e8a00bf
3 changed files with 58 additions and 17 deletions
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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;) { }", "");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue