diff --git a/crates/oxc_minifier/src/ctx.rs b/crates/oxc_minifier/src/ctx.rs index d8847c17b881c..ee4040e1ee0a6 100644 --- a/crates/oxc_minifier/src/ctx.rs +++ b/crates/oxc_minifier/src/ctx.rs @@ -54,7 +54,7 @@ impl<'a> oxc_ecmascript::GlobalContext<'a> for Ctx<'a, '_> { .get_reference(reference_id) .symbol_id() .and_then(|symbol_id| self.state.symbol_values.get_symbol_value(symbol_id)) - .filter(|sv| sv.write_references_count == 0 && !sv.for_statement_init) + .filter(|sv| sv.write_references_count == 0) .and_then(|sv| sv.initialized_constant.as_ref()) .cloned() } @@ -182,10 +182,6 @@ impl<'a> Ctx<'a, '_> { } } - let for_statement_init = self.ancestors().nth(1).is_some_and(|ancestor| { - ancestor.is_parent_of_for_statement_init() || ancestor.is_parent_of_for_statement_left() - }); - let mut read_references_count = 0; let mut write_references_count = 0; for r in self.scoping().get_resolved_references(symbol_id) { @@ -201,7 +197,6 @@ impl<'a> Ctx<'a, '_> { let symbol_value = SymbolValue { initialized_constant: constant, exported, - for_statement_init, read_references_count, write_references_count, scope_id, diff --git a/crates/oxc_minifier/src/peephole/inline.rs b/crates/oxc_minifier/src/peephole/inline.rs index 9b2f30347f011..a59ed9eb2eefa 100644 --- a/crates/oxc_minifier/src/peephole/inline.rs +++ b/crates/oxc_minifier/src/peephole/inline.rs @@ -10,8 +10,9 @@ impl<'a> PeepholeOptimizations { pub fn init_symbol_value(decl: &VariableDeclarator<'a>, ctx: &mut Ctx<'a, '_>) { let BindingPatternKind::BindingIdentifier(ident) = &decl.id.kind else { return }; let Some(symbol_id) = ident.symbol_id.get() else { return }; - let value = if decl.kind.is_var() { - // Skip constant value inlining for `var` declarations, due to TDZ problems. + let value = if decl.kind.is_var() || Self::is_for_statement_init(ctx) { + // - Skip constant value inlining for `var` declarations, due to TDZ problems. + // - Set None for for statement initializers as the value of these are set by the for statement. None } else { decl.init.as_ref().map_or(Some(ConstantValue::Undefined), |e| e.evaluate_value(ctx)) @@ -19,6 +20,12 @@ impl<'a> PeepholeOptimizations { ctx.init_value(symbol_id, value); } + fn is_for_statement_init(ctx: &Ctx<'a, '_>) -> bool { + ctx.ancestors().nth(1).is_some_and(|ancestor| { + ancestor.is_parent_of_for_statement_init() || ancestor.is_parent_of_for_statement_left() + }) + } + pub fn inline_identifier_reference(expr: &mut Expression<'a>, ctx: &mut Ctx<'a, '_>) { let Expression::Identifier(ident) = expr else { return }; let reference_id = ident.reference_id(); @@ -30,9 +37,6 @@ impl<'a> PeepholeOptimizations { if symbol_value.write_references_count > 0 { return; } - if symbol_value.for_statement_init { - return; - } let Some(cv) = &symbol_value.initialized_constant else { return }; if symbol_value.read_references_count == 1 || match cv { diff --git a/crates/oxc_minifier/src/peephole/remove_unused_expression.rs b/crates/oxc_minifier/src/peephole/remove_unused_expression.rs index ff6f66e67b0e4..bca6a6ad98c75 100644 --- a/crates/oxc_minifier/src/peephole/remove_unused_expression.rs +++ b/crates/oxc_minifier/src/peephole/remove_unused_expression.rs @@ -642,9 +642,6 @@ impl<'a> PeepholeOptimizations { if symbol_value.read_references_count > 0 { return false; } - if symbol_value.for_statement_init { - return false; - } *e = assign_expr.right.take_in(ctx.ast); ctx.state.changed = true; false @@ -1079,7 +1076,9 @@ mod test { test_same_options("function foo(t) { return t = x(); } foo();", &options); // For loops + test_options("for (let i;;) i = 0", "for (let i;;);", &options); test_same_options("for (let i;;) foo(i)", &options); + test_same_options("for (let i;;) i = 0, foo(i)", &options); test_same_options("for (let i in []) foo(i)", &options); test_same_options("for (let element of list) element && (element.foo = bar)", &options); test_same_options("for (let key in obj) key && (obj[key] = bar)", &options); diff --git a/crates/oxc_minifier/src/symbol_value.rs b/crates/oxc_minifier/src/symbol_value.rs index 04e367a689330..ec6db612c13f0 100644 --- a/crates/oxc_minifier/src/symbol_value.rs +++ b/crates/oxc_minifier/src/symbol_value.rs @@ -12,9 +12,6 @@ pub struct SymbolValue<'a> { /// Symbol is exported. pub exported: bool, - /// Inside for statement initializer. - pub for_statement_init: bool, - pub read_references_count: u32, pub write_references_count: u32, diff --git a/tasks/minsize/minsize.snap b/tasks/minsize/minsize.snap index 3548b76ef3f21..8d18eacec31ae 100644 --- a/tasks/minsize/minsize.snap +++ b/tasks/minsize/minsize.snap @@ -21,7 +21,7 @@ Original | minified | minified | gzip | gzip | Iterations | Fi 3.20 MB | 1.00 MB | 1.01 MB | 323.12 kB | 331.56 kB | 3 | echarts.js -6.69 MB | 2.22 MB | 2.31 MB | 459.29 kB | 488.28 kB | 4 | antd.js +6.69 MB | 2.22 MB | 2.31 MB | 459.28 kB | 488.28 kB | 4 | antd.js -10.95 MB | 3.34 MB | 3.49 MB | 855.39 kB | 915.50 kB | 4 | typescript.js +10.95 MB | 3.34 MB | 3.49 MB | 855.34 kB | 915.50 kB | 4 | typescript.js diff --git a/tasks/track_memory_allocations/allocs_minifier.snap b/tasks/track_memory_allocations/allocs_minifier.snap index ca8f4188c1406..504316405838b 100644 --- a/tasks/track_memory_allocations/allocs_minifier.snap +++ b/tasks/track_memory_allocations/allocs_minifier.snap @@ -4,5 +4,5 @@ RadixUIAdoptionSection.jsx | 2.52 kB || 75 | 4 | pdf.mjs | 567.30 kB || 19577 | 2898 || 47403 | 7782 | 1.624 MB -antd.js | 6.69 MB || 99857 | 13518 || 331724 | 70354 | 17.408 MB +antd.js | 6.69 MB || 99856 | 13518 || 331725 | 70354 | 17.408 MB