@@ -129,8 +129,11 @@ function pause_effects(state, to_destroy, controlled_anchor) {
129129export function each ( node , flags , get_collection , get_key , render_fn , fallback_fn = null ) {
130130 var anchor = node ;
131131
132- /** @type {EachState } */
133- var state = { flags, items : new Map ( ) , first : null } ;
132+ /** @type {Map<any, EachItem> } */
133+ var items = new Map ( ) ;
134+
135+ /** @type {EachItem | null } */
136+ var first = null ;
134137
135138 var is_controlled = ( flags & EACH_IS_CONTROLLED ) !== 0 ;
136139 var is_reactive_value = ( flags & EACH_ITEM_REACTIVE ) !== 0 ;
@@ -166,7 +169,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
166169 var first_run = true ;
167170
168171 function commit ( ) {
169- reconcile ( each_effect , array , state , anchor , flags , get_key ) ;
172+ reconcile ( state , array , anchor , flags , get_key ) ;
170173
171174 if ( fallback !== null ) {
172175 if ( array . length === 0 ) {
@@ -177,7 +180,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
177180 resume_effect ( fallback . effect ) ;
178181 }
179182
180- each_effect . first = fallback . effect ;
183+ effect . first = fallback . effect ;
181184 } else {
182185 pause_effect ( fallback . effect , ( ) => {
183186 // TODO only null out if no pending batch needs it,
@@ -189,7 +192,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
189192 }
190193 }
191194
192- var each_effect = block ( ( ) => {
195+ var effect = block ( ( ) => {
193196 array = /** @type {V[] } */ ( get ( each_array ) ) ;
194197 var length = array . length ;
195198
@@ -230,7 +233,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
230233 var value = array [ i ] ;
231234 var key = get_key ( value , i ) ;
232235
233- var item = first_run ? null : state . items . get ( key ) ;
236+ var item = first_run ? null : items . get ( key ) ;
234237
235238 if ( item ) {
236239 // update before reconciliation, to trigger any async updates
@@ -263,15 +266,15 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
263266 item . o = true ;
264267
265268 if ( prev === null ) {
266- state . first = item ;
269+ first = item ;
267270 } else {
268271 prev . next = item ;
269272 }
270273
271274 prev = item ;
272275 }
273276
274- state . items . set ( key , item ) ;
277+ items . set ( key , item ) ;
275278 }
276279
277280 keys . add ( key ) ;
@@ -302,7 +305,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
302305
303306 if ( ! first_run ) {
304307 if ( defer ) {
305- for ( const [ key , item ] of state . items ) {
308+ for ( const [ key , item ] of items ) {
306309 if ( ! keys . has ( key ) ) {
307310 batch . skipped_effects . add ( item . e ) ;
308311 }
@@ -331,6 +334,9 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
331334 get ( each_array ) ;
332335 } ) ;
333336
337+ /** @type {EachState } */
338+ var state = { effect, flags, items, first } ;
339+
334340 first_run = false ;
335341
336342 if ( hydrating ) {
@@ -341,15 +347,14 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
341347/**
342348 * Add, remove, or reorder items output by an each block as its input changes
343349 * @template V
344- * @param {Effect } each_effect
345- * @param {Array<V> } array
346350 * @param {EachState } state
351+ * @param {Array<V> } array
347352 * @param {Element | Comment | Text } anchor
348353 * @param {number } flags
349354 * @param {(value: V, index: number) => any } get_key
350355 * @returns {void }
351356 */
352- function reconcile ( each_effect , array , state , anchor , flags , get_key ) {
357+ function reconcile ( state , array , anchor , flags , get_key ) {
353358 var is_animated = ( flags & EACH_IS_ANIMATED ) !== 0 ;
354359
355360 var length = array . length ;
@@ -536,16 +541,6 @@ function reconcile(each_effect, array, state, anchor, flags, get_key) {
536541 }
537542 } ) ;
538543 }
539-
540- // TODO i have an inkling that the rest of this function is wrong...
541- // the offscreen items need to be linked, so that they all update correctly.
542- // the last onscreen item should link to the first offscreen item, etc
543- each_effect . first = state . first && state . first . e ;
544- each_effect . last = prev && prev . e ;
545-
546- if ( prev ) {
547- prev . e . next = null ;
548- }
549544}
550545
551546/**
@@ -601,11 +596,11 @@ function create_item(anchor, prev, value, key, index, render_fn, flags, get_coll
601596
602597 item . e = branch ( ( ) => render_fn ( /** @type {Node } */ ( anchor ) , v , i , get_collection ) ) ;
603598
604- item . e . prev = prev && prev . e ;
605-
606599 if ( prev !== null ) {
600+ // we only need to set `prev.next = item`, because
601+ // `item.prev = prev` was set on initialization.
602+ // the effects themselves are already linked
607603 prev . next = item ;
608- prev . e . next = item . e ;
609604 }
610605
611606 return item ;
@@ -640,12 +635,23 @@ function move(item, next, anchor) {
640635function link ( state , prev , next ) {
641636 if ( prev === null ) {
642637 state . first = next ;
638+ state . effect . first = next && next . e ;
643639 } else {
640+ if ( prev . e . next ) {
641+ prev . e . next . prev = null ;
642+ }
643+
644644 prev . next = next ;
645645 prev . e . next = next && next . e ;
646646 }
647647
648- if ( next !== null ) {
648+ if ( next === null ) {
649+ state . effect . last = prev && prev . e ;
650+ } else {
651+ if ( next . e . prev ) {
652+ next . e . prev . next = null ;
653+ }
654+
649655 next . prev = prev ;
650656 next . e . prev = prev && prev . e ;
651657 }
0 commit comments