@@ -73,11 +73,17 @@ pub fn compile_hmr_initializer<'a>(
7373 ) ;
7474
7575 // (m) => m.default && ɵɵreplaceMetadata(...)
76- let replace_callback = arrow_fn (
76+ let replace_callback = OutputExpression :: ArrowFunction ( Box :: new_in (
77+ ArrowFunctionExpr {
78+ params : Vec :: from_iter_in ( [ FnParam { name : Atom :: from ( module_name) } ] , allocator) ,
79+ body : ArrowFunctionBody :: Expression ( Box :: new_in (
80+ binary_op ( allocator, BinaryOperator :: And , default_read, replace_call) ,
81+ allocator,
82+ ) ) ,
83+ source_span : None ,
84+ } ,
7785 allocator,
78- vec ! [ module_name] ,
79- binary_op ( allocator, BinaryOperator :: And , default_read. clone_in ( allocator) , replace_call) ,
80- ) ;
86+ ) ) ;
8187
8288 // i0.ɵɵgetReplaceMetadataURL(id, timestamp, import.meta.url)
8389 let url = invoke_fn (
@@ -120,25 +126,31 @@ pub fn compile_hmr_initializer<'a>(
120126 ) ) ;
121127
122128 // (d) => d.id === id && Cmp_HmrLoad(d.timestamp)
123- let update_callback = arrow_fn (
124- allocator,
125- vec ! [ data_name] ,
126- binary_op (
127- allocator,
128- BinaryOperator :: And ,
129- binary_op (
130- allocator,
131- BinaryOperator :: Identical ,
132- read_prop ( allocator, read_var ( allocator, data_name) , "id" ) ,
133- read_var ( allocator, id_name) ,
134- ) ,
135- invoke_fn (
129+ let update_callback = OutputExpression :: ArrowFunction ( Box :: new_in (
130+ ArrowFunctionExpr {
131+ params : Vec :: from_iter_in ( [ FnParam { name : Atom :: from ( data_name) } ] , allocator) ,
132+ body : ArrowFunctionBody :: Expression ( Box :: new_in (
133+ binary_op (
134+ allocator,
135+ BinaryOperator :: And ,
136+ binary_op (
137+ allocator,
138+ BinaryOperator :: Identical ,
139+ read_prop ( allocator, read_var ( allocator, data_name) , "id" ) ,
140+ read_var ( allocator, id_name) ,
141+ ) ,
142+ invoke_fn (
143+ allocator,
144+ read_var ( allocator, & import_callback_name) ,
145+ vec ! [ read_prop( allocator, read_var( allocator, data_name) , "timestamp" ) ] ,
146+ ) ,
147+ ) ,
136148 allocator,
137- read_var ( allocator , & import_callback_name ) ,
138- vec ! [ read_prop ( allocator , read_var ( allocator , data_name ) , "timestamp" ) ] ,
139- ) ,
140- ) ,
141- ) ;
149+ ) ) ,
150+ source_span : None ,
151+ } ,
152+ allocator ,
153+ ) ) ;
142154
143155 // Cmp_HmrLoad(Date.now())
144156 let initial_call = invoke_fn (
@@ -162,6 +174,41 @@ pub fn compile_hmr_initializer<'a>(
162174 vec ! [ literal_str( allocator, "angular:component-update" ) , update_callback] ,
163175 ) ;
164176
177+ // (d) => d.id === id && location.reload()
178+ // Handles the angular:invalidate event sent when HMR fails
179+ let invalidate_callback = OutputExpression :: ArrowFunction ( Box :: new_in (
180+ ArrowFunctionExpr {
181+ params : Vec :: from_iter_in ( [ FnParam { name : Atom :: from ( data_name) } ] , allocator) ,
182+ body : ArrowFunctionBody :: Expression ( Box :: new_in (
183+ binary_op (
184+ allocator,
185+ BinaryOperator :: And ,
186+ binary_op (
187+ allocator,
188+ BinaryOperator :: Identical ,
189+ read_prop ( allocator, read_var ( allocator, data_name) , "id" ) ,
190+ read_var ( allocator, id_name) ,
191+ ) ,
192+ invoke_fn (
193+ allocator,
194+ read_prop ( allocator, read_var ( allocator, "location" ) , "reload" ) ,
195+ vec ! [ ] ,
196+ ) ,
197+ ) ,
198+ allocator,
199+ ) ) ,
200+ source_span : None ,
201+ } ,
202+ allocator,
203+ ) ) ;
204+
205+ // import.meta.hot.on('angular:invalidate', invalidateCallback)
206+ let invalidate_listener = invoke_fn (
207+ allocator,
208+ read_prop ( allocator, hot_read. clone_in ( allocator) , "on" ) ,
209+ vec ! [ literal_str( allocator, "angular:invalidate" ) , invalidate_callback] ,
210+ ) ;
211+
165212 // Build the component ID - matches TypeScript's:
166213 // o.literal(encodeURIComponent(`${meta.filePath}@${meta.className}`))
167214 let component_id = encode_uri_component ( & format ! ( "{}@{}" , meta. file_path, meta. class_name) ) ;
@@ -172,10 +219,41 @@ pub fn compile_hmr_initializer<'a>(
172219 // ngDevMode && Cmp_HmrLoad(Date.now());
173220 let guarded_initial_call = dev_only_guarded ( allocator, initial_call) ;
174221
175- // ngDevMode && import.meta.hot && import.meta.hot.on(...)
222+ // import.meta.hot.accept(() => {})
223+ // Creates an HMR boundary in Vite so that:
224+ // 1. import.meta.hot is available for custom event listeners
225+ // 2. Module changes don't propagate up the importer chain
226+ // The empty callback means we handle updates via custom events, not accept() itself
227+ let empty_callback = OutputExpression :: ArrowFunction ( Box :: new_in (
228+ ArrowFunctionExpr {
229+ params : Vec :: new_in ( allocator) ,
230+ body : ArrowFunctionBody :: Statements ( Vec :: new_in ( allocator) ) ,
231+ source_span : None ,
232+ } ,
233+ allocator,
234+ ) ) ;
235+ let hot_accept = invoke_fn (
236+ allocator,
237+ read_prop ( allocator, hot_read. clone_in ( allocator) , "accept" ) ,
238+ vec ! [ empty_callback] ,
239+ ) ;
240+
241+ // ngDevMode && import.meta.hot && import.meta.hot.accept(() => {})
242+ let guarded_accept = dev_only_guarded (
243+ allocator,
244+ binary_op ( allocator, BinaryOperator :: And , hot_read. clone_in ( allocator) , hot_accept) ,
245+ ) ;
246+
247+ // ngDevMode && import.meta.hot && import.meta.hot.on('angular:component-update', ...)
176248 let guarded_listener = dev_only_guarded (
177249 allocator,
178- binary_op ( allocator, BinaryOperator :: And , hot_read, hot_listener) ,
250+ binary_op ( allocator, BinaryOperator :: And , hot_read. clone_in ( allocator) , hot_listener) ,
251+ ) ;
252+
253+ // ngDevMode && import.meta.hot && import.meta.hot.on('angular:invalidate', ...)
254+ let guarded_invalidate_listener = dev_only_guarded (
255+ allocator,
256+ binary_op ( allocator, BinaryOperator :: And , hot_read, invalidate_listener) ,
179257 ) ;
180258
181259 // Build the IIFE: (() => { ... })()
@@ -184,7 +262,9 @@ pub fn compile_hmr_initializer<'a>(
184262 id_decl,
185263 import_callback,
186264 expr_stmt ( allocator, guarded_initial_call) ,
265+ expr_stmt ( allocator, guarded_accept) ,
187266 expr_stmt ( allocator, guarded_listener) ,
267+ expr_stmt ( allocator, guarded_invalidate_listener) ,
188268 ] ,
189269 allocator,
190270 ) ;
@@ -394,26 +474,6 @@ fn binary_op<'a>(
394474 ) )
395475}
396476
397- /// Create an arrow function expression.
398- fn arrow_fn < ' a > (
399- allocator : & ' a Allocator ,
400- param_names : std:: vec:: Vec < & str > ,
401- body : OutputExpression < ' a > ,
402- ) -> OutputExpression < ' a > {
403- let params: Vec < ' a , FnParam < ' a > > = Vec :: from_iter_in (
404- param_names. into_iter ( ) . map ( |name| FnParam { name : Atom :: from ( allocator. alloc_str ( name) ) } ) ,
405- allocator,
406- ) ;
407- OutputExpression :: ArrowFunction ( Box :: new_in (
408- ArrowFunctionExpr {
409- params,
410- body : ArrowFunctionBody :: Expression ( Box :: new_in ( body, allocator) ) ,
411- source_span : None ,
412- } ,
413- allocator,
414- ) )
415- }
416-
417477/// Create a variable declaration statement.
418478fn var_decl < ' a > (
419479 allocator : & ' a Allocator ,
0 commit comments