@@ -17,6 +17,17 @@ use oxc_span::Atom;
1717
1818/// Compiles an Angular template to JavaScript.
1919fn compile_template_to_js ( template : & str , component_name : & str ) -> String {
20+ compile_template_to_js_with_version ( template, component_name, None )
21+ }
22+
23+ /// Compiles an Angular template to JavaScript targeting a specific Angular version.
24+ fn compile_template_to_js_with_version (
25+ template : & str ,
26+ component_name : & str ,
27+ angular_version : Option < AngularVersion > ,
28+ ) -> String {
29+ use oxc_angular_compiler:: pipeline:: ingest:: { IngestOptions , ingest_component_with_options} ;
30+
2031 let allocator = Allocator :: default ( ) ;
2132
2233 // Stage 1: Parse HTML (with expansion forms enabled for ICU/plural support)
@@ -40,7 +51,17 @@ fn compile_template_to_js(template: &str, component_name: &str) -> String {
4051 }
4152
4253 // Stage 3: Ingest R3 AST into IR
43- let mut job = ingest_component ( & allocator, Atom :: from ( component_name) , r3_result. nodes ) ;
54+ let mut job = if let Some ( version) = angular_version {
55+ let options = IngestOptions { angular_version : Some ( version) , ..Default :: default ( ) } ;
56+ ingest_component_with_options (
57+ & allocator,
58+ Atom :: from ( component_name) ,
59+ r3_result. nodes ,
60+ options,
61+ )
62+ } else {
63+ ingest_component ( & allocator, Atom :: from ( component_name) , r3_result. nodes )
64+ } ;
4465
4566 // Stage 4-5: Transform and emit
4667 let result = compile_template ( & mut job) ;
@@ -7398,3 +7419,111 @@ export class TestComponent {
73987419 decl. members
73997420 ) ;
74007421}
7422+
7423+ // ============================================================================
7424+ // Angular Version Gating Tests (Issue #105)
7425+ // ============================================================================
7426+ // These tests verify that when targeting Angular 19, the compiler emits
7427+ // ɵɵtemplate instead of ɵɵconditionalCreate/ɵɵconditionalBranchCreate
7428+ // for @if/@switch blocks, since those instructions don't exist in Angular 19.
7429+
7430+ #[ test]
7431+ fn test_if_block_angular_v19 ( ) {
7432+ let v19 = AngularVersion :: new ( 19 , 0 , 0 ) ;
7433+ let js = compile_template_to_js_with_version (
7434+ r"@if (condition) { <div>Visible</div> }" ,
7435+ "TestComponent" ,
7436+ Some ( v19) ,
7437+ ) ;
7438+ // Angular 19 should use ɵɵtemplate, NOT ɵɵconditionalCreate
7439+ assert ! (
7440+ js. contains( "ɵɵtemplate(" ) ,
7441+ "Angular 19 should emit ɵɵtemplate for @if blocks. Got:\n {js}"
7442+ ) ;
7443+ assert ! (
7444+ !js. contains( "ɵɵconditionalCreate(" ) ,
7445+ "Angular 19 should NOT emit ɵɵconditionalCreate. Got:\n {js}"
7446+ ) ;
7447+ // Update instruction (ɵɵconditional) should still be emitted
7448+ assert ! (
7449+ js. contains( "ɵɵconditional(" ) ,
7450+ "Angular 19 should still emit ɵɵconditional for update. Got:\n {js}"
7451+ ) ;
7452+ insta:: assert_snapshot!( "if_block_angular_v19" , js) ;
7453+ }
7454+
7455+ #[ test]
7456+ fn test_if_else_block_angular_v19 ( ) {
7457+ let v19 = AngularVersion :: new ( 19 , 2 , 0 ) ;
7458+ let js = compile_template_to_js_with_version (
7459+ r"@if (condition) { <div>True</div> } @else { <div>False</div> }" ,
7460+ "TestComponent" ,
7461+ Some ( v19) ,
7462+ ) ;
7463+ // Angular 19 should use ɵɵtemplate for all branches, NOT conditionalCreate/conditionalBranchCreate
7464+ assert ! (
7465+ js. contains( "ɵɵtemplate(" ) ,
7466+ "Angular 19 should emit ɵɵtemplate for @if/@else blocks. Got:\n {js}"
7467+ ) ;
7468+ assert ! (
7469+ !js. contains( "ɵɵconditionalCreate(" ) ,
7470+ "Angular 19 should NOT emit ɵɵconditionalCreate. Got:\n {js}"
7471+ ) ;
7472+ assert ! (
7473+ !js. contains( "ɵɵconditionalBranchCreate(" ) ,
7474+ "Angular 19 should NOT emit ɵɵconditionalBranchCreate. Got:\n {js}"
7475+ ) ;
7476+ insta:: assert_snapshot!( "if_else_block_angular_v19" , js) ;
7477+ }
7478+
7479+ #[ test]
7480+ fn test_switch_block_angular_v19 ( ) {
7481+ let v19 = AngularVersion :: new ( 19 , 0 , 0 ) ;
7482+ let js = compile_template_to_js_with_version (
7483+ r"@switch (value) { @case (1) { <div>One</div> } @case (2) { <div>Two</div> } @default { <div>Other</div> } }" ,
7484+ "TestComponent" ,
7485+ Some ( v19) ,
7486+ ) ;
7487+ // Angular 19 should use ɵɵtemplate for all @switch cases
7488+ assert ! (
7489+ js. contains( "ɵɵtemplate(" ) ,
7490+ "Angular 19 should emit ɵɵtemplate for @switch blocks. Got:\n {js}"
7491+ ) ;
7492+ assert ! (
7493+ !js. contains( "ɵɵconditionalCreate(" ) ,
7494+ "Angular 19 should NOT emit ɵɵconditionalCreate for @switch. Got:\n {js}"
7495+ ) ;
7496+ assert ! (
7497+ !js. contains( "ɵɵconditionalBranchCreate(" ) ,
7498+ "Angular 19 should NOT emit ɵɵconditionalBranchCreate for @switch. Got:\n {js}"
7499+ ) ;
7500+ insta:: assert_snapshot!( "switch_block_angular_v19" , js) ;
7501+ }
7502+
7503+ #[ test]
7504+ fn test_if_block_angular_v20_default ( ) {
7505+ // Default (no version set) should emit conditionalCreate (Angular 20+ behavior)
7506+ let js = compile_template_to_js_with_version (
7507+ r"@if (condition) { <div>Visible</div> }" ,
7508+ "TestComponent" ,
7509+ None ,
7510+ ) ;
7511+ assert ! (
7512+ js. contains( "ɵɵconditionalCreate(" ) ,
7513+ "Default (latest) should emit ɵɵconditionalCreate. Got:\n {js}"
7514+ ) ;
7515+ }
7516+
7517+ #[ test]
7518+ fn test_if_block_angular_v20_explicit ( ) {
7519+ let v20 = AngularVersion :: new ( 20 , 0 , 0 ) ;
7520+ let js = compile_template_to_js_with_version (
7521+ r"@if (condition) { <div>Visible</div> }" ,
7522+ "TestComponent" ,
7523+ Some ( v20) ,
7524+ ) ;
7525+ assert ! (
7526+ js. contains( "ɵɵconditionalCreate(" ) ,
7527+ "Angular 20 should emit ɵɵconditionalCreate. Got:\n {js}"
7528+ ) ;
7529+ }
0 commit comments