@@ -235,21 +235,28 @@ fn generate_temporaries_for_handler_ops<'a>(
235235/// temporary variable processing so that `let tmp_N_0;` declarations are generated inside
236236/// the listener function scope rather than the parent create scope.
237237///
238- /// The algorithm mirrors `generate_temporaries_for_handler_ops` but additionally visits/transforms
239- /// the handler_expression alongside the ops.
238+ /// The handler_ops are processed first (same as `generate_temporaries_for_handler_ops`),
239+ /// then handler_expression is processed once AFTER the loop with op_count equal to
240+ /// handler_ops.len(). This matches Angular TS where the return expression is the last
241+ /// entry in handlerOps at index N.
240242fn generate_temporaries_for_handler_ops_with_expression < ' a > (
241243 ops : & mut [ UpdateOp < ' a > ] ,
242244 handler_expression : & mut Option < oxc_allocator:: Box < ' a , IrExpression < ' a > > > ,
243245 allocator : & ' a Allocator ,
244246) -> Vec < UpdateOp < ' a > > {
245- let mut op_count = 0 ;
246- let mut generated_statements = Vec :: new ( ) ;
247+ // First, process handler_ops exactly like generate_temporaries_for_handler_ops
248+ let mut generated_statements = generate_temporaries_for_handler_ops ( ops, allocator) ;
249+
250+ // Then process handler_expression once, with op_count = ops.len().
251+ // In Angular TS, the return expression is the last entry in handlerOps,
252+ // so its op index equals the number of preceding ops.
253+ if let Some ( handler_expr) = handler_expression. as_mut ( ) {
254+ let op_count = ops. len ( ) ;
247255
248- for op in ops. iter_mut ( ) {
249256 // Pass 1: Count reads per xref to determine final reads
250257 let read_counts = RefCell :: new ( FxHashMap :: < XrefId , usize > :: default ( ) ) ;
251- visit_expressions_in_update_op (
252- op ,
258+ visit_expressions_in_expression (
259+ handler_expr ,
253260 & |expr, flags| {
254261 if flags. contains ( VisitorContextFlag :: IN_CHILD_OPERATION ) {
255262 return ;
@@ -260,28 +267,12 @@ fn generate_temporaries_for_handler_ops_with_expression<'a>(
260267 } ,
261268 VisitorContextFlag :: NONE ,
262269 ) ;
263- // Also count reads in handler_expression
264- if let Some ( handler_expr) = handler_expression. as_ref ( ) {
265- visit_expressions_in_expression (
266- handler_expr,
267- & |expr, flags| {
268- if flags. contains ( VisitorContextFlag :: IN_CHILD_OPERATION ) {
269- return ;
270- }
271- if let IrExpression :: ReadTemporary ( read) = expr {
272- * read_counts. borrow_mut ( ) . entry ( read. xref ) . or_insert ( 0 ) += 1 ;
273- }
274- } ,
275- VisitorContextFlag :: NONE ,
276- ) ;
277- }
278270 let total_reads = read_counts. into_inner ( ) ;
279271
280272 // Pass 2: Assign names with reuse when final read is encountered
281273 let tracker = RefCell :: new ( TempVarTracker :: new ( op_count, total_reads) ) ;
282-
283- transform_expressions_in_update_op (
284- op,
274+ transform_expressions_in_expression (
275+ handler_expr,
285276 & |expr, flags| {
286277 if flags. contains ( VisitorContextFlag :: IN_CHILD_OPERATION ) {
287278 return ;
@@ -290,19 +281,6 @@ fn generate_temporaries_for_handler_ops_with_expression<'a>(
290281 } ,
291282 VisitorContextFlag :: NONE ,
292283 ) ;
293- // Also assign names in handler_expression
294- if let Some ( handler_expr) = handler_expression. as_mut ( ) {
295- transform_expressions_in_expression (
296- handler_expr,
297- & |expr, flags| {
298- if flags. contains ( VisitorContextFlag :: IN_CHILD_OPERATION ) {
299- return ;
300- }
301- assign_temp_names ( expr, & tracker, allocator) ;
302- } ,
303- VisitorContextFlag :: NONE ,
304- ) ;
305- }
306284
307285 // Collect unique names and create declarations
308286 let defs = tracker. into_inner ( ) . defs ;
@@ -313,49 +291,6 @@ fn generate_temporaries_for_handler_ops_with_expression<'a>(
313291 statement : stmt,
314292 } ) ) ;
315293 }
316-
317- op_count += 1 ;
318- }
319-
320- // If there are no ops but handler_expression has temporaries, process it standalone
321- if ops. is_empty ( ) {
322- if let Some ( handler_expr) = handler_expression. as_mut ( ) {
323- let read_counts = RefCell :: new ( FxHashMap :: < XrefId , usize > :: default ( ) ) ;
324- visit_expressions_in_expression (
325- handler_expr,
326- & |expr, flags| {
327- if flags. contains ( VisitorContextFlag :: IN_CHILD_OPERATION ) {
328- return ;
329- }
330- if let IrExpression :: ReadTemporary ( read) = expr {
331- * read_counts. borrow_mut ( ) . entry ( read. xref ) . or_insert ( 0 ) += 1 ;
332- }
333- } ,
334- VisitorContextFlag :: NONE ,
335- ) ;
336- let total_reads = read_counts. into_inner ( ) ;
337-
338- let tracker = RefCell :: new ( TempVarTracker :: new ( op_count, total_reads) ) ;
339- transform_expressions_in_expression (
340- handler_expr,
341- & |expr, flags| {
342- if flags. contains ( VisitorContextFlag :: IN_CHILD_OPERATION ) {
343- return ;
344- }
345- assign_temp_names ( expr, & tracker, allocator) ;
346- } ,
347- VisitorContextFlag :: NONE ,
348- ) ;
349-
350- let defs = tracker. into_inner ( ) . defs ;
351- for name in collect_unique_names ( & defs) {
352- let stmt = create_declare_var_statement ( allocator, & name) ;
353- generated_statements. push ( UpdateOp :: Statement ( StatementOp {
354- base : UpdateOpBase :: default ( ) ,
355- statement : stmt,
356- } ) ) ;
357- }
358- }
359294 }
360295
361296 generated_statements
0 commit comments