@@ -2362,7 +2362,6 @@ export const template_visitors = {
2362
2362
EachBlock ( node , context ) {
2363
2363
const each_node_meta = node . metadata ;
2364
2364
const collection = /** @type {Expression } */ ( context . visit ( node . expression ) ) ;
2365
- let each_item_is_reactive = true ;
2366
2365
2367
2366
if ( ! each_node_meta . is_controlled ) {
2368
2367
context . state . template . push ( '<!>' ) ;
@@ -2372,36 +2371,29 @@ export const template_visitors = {
2372
2371
context . state . init . push ( b . const ( each_node_meta . array_name , b . thunk ( collection ) ) ) ;
2373
2372
}
2374
2373
2375
- // The runtime needs to know what kind of each block this is in order to optimize for the
2376
- // key === item (we avoid extra allocations). In that case, the item doesn't need to be reactive.
2377
- // We can guarantee this by knowing that in order for the item of the each block to change, they
2378
- // would need to mutate the key/item directly in the array. Given that in runes mode we use ===
2379
- // equality, we can apply a fast-path (as long as the index isn't reactive).
2380
- let each_type = 0 ;
2374
+ let flags = 0 ;
2381
2375
2382
2376
if (
2383
2377
node . key &&
2384
2378
( node . key . type !== 'Identifier' || ! node . index || node . key . name !== node . index )
2385
2379
) {
2386
- each_type |= EACH_KEYED ;
2387
- // If there's a destructuring, then we likely need the generated $$index
2388
- if ( node . index || node . context . type !== 'Identifier' ) {
2389
- each_type |= EACH_INDEX_REACTIVE ;
2380
+ flags |= EACH_KEYED ;
2381
+
2382
+ if ( node . index ) {
2383
+ flags |= EACH_INDEX_REACTIVE ;
2390
2384
}
2391
- if (
2392
- context . state . analysis . runes &&
2385
+
2386
+ // In runes mode, if key === item, we don't need to wrap the item in a source
2387
+ const key_is_item =
2393
2388
node . key . type === 'Identifier' &&
2394
2389
node . context . type === 'Identifier' &&
2395
- node . context . name === node . key . name &&
2396
- ( each_type & EACH_INDEX_REACTIVE ) === 0
2397
- ) {
2398
- // Fast-path for when the key === item
2399
- each_item_is_reactive = false ;
2400
- } else {
2401
- each_type |= EACH_ITEM_REACTIVE ;
2390
+ node . context . name === node . key . name ;
2391
+
2392
+ if ( ! context . state . analysis . runes || ! key_is_item ) {
2393
+ flags |= EACH_ITEM_REACTIVE ;
2402
2394
}
2403
2395
} else {
2404
- each_type |= EACH_ITEM_REACTIVE ;
2396
+ flags |= EACH_ITEM_REACTIVE ;
2405
2397
}
2406
2398
2407
2399
// Since `animate:` can only appear on elements that are the sole child of a keyed each block,
@@ -2414,15 +2406,15 @@ export const template_visitors = {
2414
2406
return child . attributes . some ( ( attr ) => attr . type === 'AnimateDirective' ) ;
2415
2407
} )
2416
2408
) {
2417
- each_type |= EACH_IS_ANIMATED ;
2409
+ flags |= EACH_IS_ANIMATED ;
2418
2410
}
2419
2411
2420
2412
if ( each_node_meta . is_controlled ) {
2421
- each_type |= EACH_IS_CONTROLLED ;
2413
+ flags |= EACH_IS_CONTROLLED ;
2422
2414
}
2423
2415
2424
2416
if ( context . state . analysis . runes ) {
2425
- each_type |= EACH_IS_STRICT_EQUALS ;
2417
+ flags |= EACH_IS_STRICT_EQUALS ;
2426
2418
}
2427
2419
2428
2420
// If the array is a store expression, we need to invalidate it when the array is changed.
@@ -2447,10 +2439,12 @@ export const template_visitors = {
2447
2439
) ;
2448
2440
return [ array , ...transitive_dependencies ] ;
2449
2441
} ) ;
2442
+
2450
2443
if ( each_node_meta . array_name ) {
2451
2444
indirect_dependencies . push ( b . call ( each_node_meta . array_name ) ) ;
2452
2445
} else {
2453
2446
indirect_dependencies . push ( collection ) ;
2447
+
2454
2448
const transitive_dependencies = serialize_transitive_dependencies (
2455
2449
each_node_meta . references ,
2456
2450
context
@@ -2469,6 +2463,7 @@ export const template_visitors = {
2469
2463
// into separate expressions, at which point this is called again with an identifier or member expression
2470
2464
return serialize_set_binding ( assignment , context , ( ) => assignment ) ;
2471
2465
}
2466
+
2472
2467
const left = object ( assignment . left ) ;
2473
2468
const value = get_assignment_value ( assignment , context ) ;
2474
2469
const invalidate = b . call (
@@ -2509,10 +2504,12 @@ export const template_visitors = {
2509
2504
const item_with_loc = with_loc ( item , id ) ;
2510
2505
return b . call ( '$.unwrap' , item_with_loc ) ;
2511
2506
} ;
2507
+
2512
2508
if ( node . index ) {
2513
2509
const index_binding = /** @type {import('#compiler').Binding } */ (
2514
2510
context . state . scope . get ( node . index )
2515
2511
) ;
2512
+
2516
2513
index_binding . expression = ( id ) => {
2517
2514
const index_with_loc = with_loc ( index , id ) ;
2518
2515
return b . call ( '$.unwrap' , index_with_loc ) ;
@@ -2575,7 +2572,7 @@ export const template_visitors = {
2575
2572
declarations . push ( b . let ( node . index , index ) ) ;
2576
2573
}
2577
2574
2578
- if ( context . state . options . dev && ( each_type & EACH_KEYED ) !== 0 ) {
2575
+ if ( context . state . options . dev && ( flags & EACH_KEYED ) !== 0 ) {
2579
2576
context . state . init . push (
2580
2577
b . stmt ( b . call ( '$.validate_each_keys' , b . thunk ( collection ) , key_function ) )
2581
2578
) ;
@@ -2584,7 +2581,7 @@ export const template_visitors = {
2584
2581
/** @type {Expression[] } */
2585
2582
const args = [
2586
2583
context . state . node ,
2587
- b . literal ( each_type ) ,
2584
+ b . literal ( flags ) ,
2588
2585
each_node_meta . array_name ? each_node_meta . array_name : b . thunk ( collection ) ,
2589
2586
key_function ,
2590
2587
b . arrow ( [ b . id ( '$$anchor' ) , item , index ] , b . block ( declarations . concat ( block . body ) ) )
0 commit comments