mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-15 06:39:17 +00:00
fix(minifier): avoid merging if to for when the body contains a function declaration (#25637)
fixes https://github.com/oxc-project/oxc/issues/22222 I used AI to generate the code and then reviewed the code and changed the code and added tests.
This commit is contained in:
2 files changed
+54
No files matched your search
@@ -22,6 +22,23 @@ impl<'a> PeepholeOptimizations {
|
||||
let Statement::IfStatement(if_stmt) = first else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Moving the condition into the `for` test changes its scope from the
|
||||
// loop body's block scope to the surrounding scope. Block function
|
||||
// declarations are initialized on entry, so the condition can observe
|
||||
// them before their declaration statement. Other lexical declarations
|
||||
// only differ through TDZ behavior, which the minifier intentionally
|
||||
// ignores.
|
||||
let body_has_function_declaration = match &for_stmt.body {
|
||||
Statement::BlockStatement(block_stmt) => {
|
||||
block_stmt.body.iter().skip(1).any(Self::statement_has_function_declaration)
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if body_has_function_declaration {
|
||||
return;
|
||||
}
|
||||
|
||||
// "for (;;) if (x) break;" => "for (; !x;) ;"
|
||||
// "for (; a;) if (x) break;" => "for (; a && !x;) ;"
|
||||
// "for (;;) if (x) break; else y();" => "for (; !x;) y();"
|
||||
@@ -100,6 +117,16 @@ impl<'a> PeepholeOptimizations {
|
||||
}
|
||||
}
|
||||
|
||||
fn statement_has_function_declaration(stmt: &Statement<'a>) -> bool {
|
||||
match stmt {
|
||||
Statement::FunctionDeclaration(_) => true,
|
||||
Statement::LabeledStatement(label) => {
|
||||
Self::statement_has_function_declaration(&label.body)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn drop_first_statement(
|
||||
span: Span,
|
||||
body: Option<Statement<'a>>,
|
||||
|
||||
@@ -24,6 +24,33 @@ fn test_for_variable_declaration() {
|
||||
);
|
||||
}
|
||||
|
||||
// https://github.com/oxc-project/oxc/issues/22222
|
||||
#[test]
|
||||
fn test_for_break_preserves_block_function_scope_in_module() {
|
||||
test(
|
||||
"let n = 0;
|
||||
for (; n < 2; n++) {
|
||||
if (typeof f === 'function') break;
|
||||
function f() {}
|
||||
}
|
||||
console.log(n);",
|
||||
"let n = 0;
|
||||
for (; n < 2; n++) {
|
||||
if (typeof f == 'function') break;
|
||||
function f() {}
|
||||
}
|
||||
console.log(n);",
|
||||
);
|
||||
test(
|
||||
"for (;;) { if (x) break; var y = foo(); bar(y); bar(y); }",
|
||||
"for (; !x;) { var y = foo(); bar(y), bar(y); }",
|
||||
);
|
||||
test(
|
||||
"for (;;) { if (x) break; let y = foo(); bar(y); bar(y); }",
|
||||
"for (; !x;) { let y = foo(); bar(y), bar(y); }",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_for_continue_in_for() {
|
||||
test("for( a of b ){ if(c) { continue; } d() }", "for ( a of b ) c || d();");
|
||||
|
||||
Reference in new issue
Block a user