diff --git a/crates/oxc_angular_compiler/src/optimizer/adjust_static_members.rs b/crates/oxc_angular_compiler/src/optimizer/adjust_static_members.rs index 2c392f142..b4fe44767 100644 --- a/crates/oxc_angular_compiler/src/optimizer/adjust_static_members.rs +++ b/crates/oxc_angular_compiler/src/optimizer/adjust_static_members.rs @@ -231,7 +231,7 @@ impl AdjustStaticMembersTransformer { // Determine if we need to extract the variable declaration part // Pattern: let X = class X {} -> we wrap the class expression and assignments let (var_prefix, class_expr_start, class_expr_end) = - self.extract_var_declaration_parts(start_span, source)?; + self.extract_var_declaration_parts(start_span, source, group.class_name)?; // Build the wrapped code let mut wrapped = String::new(); @@ -287,6 +287,7 @@ impl AdjustStaticMembersTransformer { &self, stmt_span: Span, source: &str, + class_name: &str, ) -> Option<(String, u32, u32)> { let stmt_text = &source[stmt_span.start as usize..stmt_span.end as usize]; @@ -324,7 +325,10 @@ impl AdjustStaticMembersTransformer { } } else { // It's a class declaration: class X {} - return Some((String::new(), stmt_span.start, stmt_span.end)); + // We must assign the IIFE result to a variable so the class name + // remains in scope for subsequent export statements. + let var_prefix = format!("let {} = ", class_name); + return Some((var_prefix, stmt_span.start, stmt_span.end)); } None diff --git a/crates/oxc_angular_compiler/tests/adjust_static_members_test.rs b/crates/oxc_angular_compiler/tests/adjust_static_members_test.rs index 838cf895b..20c4c81bc 100644 --- a/crates/oxc_angular_compiler/tests/adjust_static_members_test.rs +++ b/crates/oxc_angular_compiler/tests/adjust_static_members_test.rs @@ -414,3 +414,26 @@ ClassB.ɵfac = factoryB; test_wrap_static(input, &["/* @__PURE__ */ (() =>", "return ClassA;", "return ClassB;"], &[]); } + +#[test] +fn test_class_declaration_preserves_binding_for_export() { + // Regression test: class declarations (not variable declarations) must + // produce `let X = /* @__PURE__ */ (() => { ... })()` so the name remains + // in scope for subsequent `export { X }` statements. + let input = r" +class ClipboardModule {} +ClipboardModule.ɵfac = function ClipboardModule_Factory(t) { return new (t || ClipboardModule)(); }; +ClipboardModule.ɵmod = defineNgModule({ type: ClipboardModule }); +export { ClipboardModule }; +"; + + test_wrap_static( + input, + &[ + "let ClipboardModule = /* @__PURE__ */ (() =>", + "return ClipboardModule;", + "export { ClipboardModule }", + ], + &[], + ); +}