@@ -13,7 +13,7 @@ import {
1313import { dev } from '../../../../state.js' ;
1414import { extract_paths , object } from '../../../../utils/ast.js' ;
1515import * as b from '../../../../utils/builders.js' ;
16- import { build_getter , with_loc } from '../utils.js' ;
16+ import { build_getter } from '../utils.js' ;
1717import { get_value } from './shared/declarations.js' ;
1818
1919/**
@@ -48,18 +48,26 @@ export function EachBlock(node, context) {
4848 if ( node . index ) {
4949 flags |= EACH_INDEX_REACTIVE ;
5050 }
51+ }
5152
52- // In runes mode, if key === item, we don't need to wrap the item in a source
53- const key_is_item =
54- /** @type {Expression } */ ( node . key ) . type === 'Identifier' &&
55- node . context . type === 'Identifier' &&
56- node . context . name === node . key . name ;
53+ const key_is_item =
54+ node . key ?. type === 'Identifier' &&
55+ node . context . type === 'Identifier' &&
56+ node . context . name === node . key . name ;
57+
58+ for ( const binding of node . metadata . expression . dependencies ) {
59+ // if the expression doesn't reference any external state, we don't need to
60+ // create a source for the item. TODO cover more cases (e.g. `x.filter(y)`
61+ // should also qualify if `y` doesn't reference state, and non-state
62+ // bindings should also be fine
63+ if ( binding . scope . function_depth >= context . state . scope . function_depth ) {
64+ continue ;
65+ }
5766
58- if ( ! context . state . analysis . runes || ! key_is_item ) {
67+ if ( ! context . state . analysis . runes || ! key_is_item || binding . kind === 'store_sub' ) {
5968 flags |= EACH_ITEM_REACTIVE ;
69+ break ;
6070 }
61- } else {
62- flags |= EACH_ITEM_REACTIVE ;
6371 }
6472
6573 // Since `animate:` can only appear on elements that are the sole child of a keyed each block,
@@ -134,21 +142,13 @@ export function EachBlock(node, context) {
134142 const index =
135143 each_node_meta . contains_group_binding || ! node . index ? each_node_meta . index : b . id ( node . index ) ;
136144 const item = each_node_meta . item ;
137- const binding = /** @type {Binding } */ ( context . state . scope . get ( item . name ) ) ;
138- const getter = ( /** @type {Identifier } */ id ) => {
139- const item_with_loc = with_loc ( item , id ) ;
140- return b . call ( '$.unwrap' , item_with_loc ) ;
141- } ;
142145
143146 if ( node . index ) {
144- child_state . transform [ node . index ] = {
145- read : ( id ) => {
146- const index_with_loc = with_loc ( index , id ) ;
147- return ( flags & EACH_INDEX_REACTIVE ) === 0
148- ? index_with_loc
149- : b . call ( '$.get' , index_with_loc ) ;
150- }
151- } ;
147+ if ( ( flags & EACH_INDEX_REACTIVE ) !== 0 ) {
148+ child_state . transform [ node . index ] = { read : get_value } ;
149+ } else {
150+ delete child_state . transform [ node . index ] ;
151+ }
152152
153153 delete key_state . transform [ node . index ] ;
154154 }
@@ -172,7 +172,7 @@ export function EachBlock(node, context) {
172172
173173 if ( node . context . type === 'Identifier' ) {
174174 child_state . transform [ node . context . name ] = {
175- read : getter ,
175+ read : ( flags & EACH_ITEM_REACTIVE ) !== 0 ? get_value : ( node ) => node ,
176176 assign : ( _ , value ) => {
177177 const left = b . member (
178178 each_node_meta . array_name ? b . call ( each_node_meta . array_name ) : collection ,
@@ -187,12 +187,12 @@ export function EachBlock(node, context) {
187187
188188 delete key_state . transform [ node . context . name ] ;
189189 } else {
190- const unwrapped = getter ( binding . node ) ;
191- const paths = extract_paths ( node . context ) ;
190+ const unwrapped = ( flags & EACH_ITEM_REACTIVE ) !== 0 ? b . call ( '$.get' , item ) : item ;
192191
193- for ( const path of paths ) {
192+ for ( const path of extract_paths ( node . context ) ) {
194193 const name = /** @type {Identifier } */ ( path . node ) . name ;
195194 const needs_derived = path . has_default_value ; // to ensure that default value is only called once
195+
196196 const fn = b . thunk (
197197 /** @type {Expression } */ ( context . visit ( path . expression ?. ( unwrapped ) , child_state ) )
198198 ) ;
@@ -203,11 +203,11 @@ export function EachBlock(node, context) {
203203
204204 child_state . transform [ name ] = {
205205 read,
206- assign : ( node , value ) => {
206+ assign : ( _ , value ) => {
207207 const left = /** @type {Pattern } */ ( path . update_expression ( unwrapped ) ) ;
208208 return b . sequence ( [ b . assignment ( '=' , left , value ) , ...sequence ] ) ;
209209 } ,
210- mutate : ( node , mutation ) => {
210+ mutate : ( _ , mutation ) => {
211211 return b . sequence ( [ mutation , ...sequence ] ) ;
212212 }
213213 } ;
0 commit comments