@ -24,12 +24,14 @@ import {
run _out _transitions ,
pause _children ,
pause _effect ,
resume _effect
resume _effect ,
get _first _node
} from '../../reactivity/effects.js' ;
import { source , mutable _source , set } from '../../reactivity/sources.js' ;
import { is _array , is _frozen } from '../../utils.js' ;
import { INERT , STATE _SYMBOL } from '../../constants.js' ;
import { queue _micro _task } from '../task.js' ;
import { current _effect } from '../../runtime.js' ;
/ * *
* The row of a keyed each block that is currently updating . We track this
@ -54,11 +56,12 @@ export function index(_, i) {
/ * *
* Pause multiple effects simultaneously , and coordinate their
* subsequent destruction . Used in each blocks
* @ param { import ( '#client' ) . EachState } state
* @ param { import ( '#client' ) . EachItem [ ] } items
* @ param { null | Node } controlled _anchor
* @ param { Map < any , import ( "#client" ) . EachItem > } items _map
* /
function pause _effects ( items, controlled _anchor , items _map ) {
function pause _effects ( state, items, controlled _anchor , items _map ) {
/** @type {import('#client').TransitionManager[]} */
var transitions = [ ] ;
var length = items . length ;
@ -77,7 +80,7 @@ function pause_effects(items, controlled_anchor, items_map) {
clear _text _content ( parent _node ) ;
parent _node . append ( /** @type {Element} */ ( controlled _anchor ) ) ;
items _map . clear ( ) ;
link ( items[ 0 ] . prev , items [ length - 1 ] . next ) ;
link ( state, items[ 0 ] . prev , items [ length - 1 ] . next ) ;
}
run _out _transitions ( transitions , ( ) => {
@ -85,7 +88,7 @@ function pause_effects(items, controlled_anchor, items_map) {
var item = items [ i ] ;
if ( ! is _controlled ) {
items _map . delete ( item . k ) ;
link ( item. prev , item . next ) ;
link ( state, item. prev , item . next ) ;
}
destroy _effect ( item . e , ! is _controlled ) ;
}
@ -104,7 +107,7 @@ function pause_effects(items, controlled_anchor, items_map) {
* /
export function each ( anchor , flags , get _collection , get _key , render _fn , fallback _fn = null ) {
/** @type {import('#client').EachState} */
var state = { flags , items : new Map ( ) , nex t: null } ;
var state = { flags , items : new Map ( ) , firs t: null } ;
var is _controlled = ( flags & EACH _IS _CONTROLLED ) !== 0 ;
@ -121,7 +124,7 @@ export function each(anchor, flags, get_collection, get_key, render_fn, fallback
/** @type {import('#client').Effect | null} */
var fallback = null ;
block ( ( ) => {
block ( anchor , 0 , ( ) => {
var collection = get _collection ( ) ;
var array = is _array ( collection )
@ -163,8 +166,8 @@ export function each(anchor, flags, get_collection, get_key, render_fn, fallback
/** @type {Node} */
var child _anchor = hydrate _start ;
/** @type {import('#client').EachItem | import('#client').EachState } */
var prev = state ;
/** @type {import('#client').EachItem | null } */
var prev = null ;
/** @type {import('#client').EachItem} */
var item ;
@ -184,7 +187,7 @@ export function each(anchor, flags, get_collection, get_key, render_fn, fallback
child _anchor = hydrate _anchor ( child _anchor ) ;
var value = array [ i ] ;
var key = get _key ( value , i ) ;
item = create _item ( child _anchor , prev, null , value , key , i , render _fn , flags ) ;
item = create _item ( child _anchor , state, prev, null , value , key , i , render _fn , flags ) ;
state . items . set ( key , item ) ;
child _anchor = /** @type {Comment} */ ( child _anchor . nextSibling ) ;
@ -242,14 +245,14 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) {
var length = array . length ;
var items = state . items ;
var first = state . nex t;
var first = state . firs t;
var current = first ;
/** @type {Set<import('#client').EachItem>} */
var seen = new Set ( ) ;
/** @type {import('#client').Each State | import('#client').EachItem } */
var prev = state ;
/** @type {import('#client').Each Item | null } */
var prev = null ;
/** @type {Set<import('#client').EachItem>} */
var to _animate = new Set ( ) ;
@ -293,7 +296,17 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) {
if ( item === undefined ) {
var child _anchor = current ? get _first _node ( current . e ) : anchor ;
prev = create _item ( child _anchor , prev , prev . next , value , key , i , render _fn , flags ) ;
prev = create _item (
child _anchor ,
state ,
prev ,
prev === null ? state . first : prev . next ,
value ,
key ,
i ,
render _fn ,
flags
) ;
items . set ( key , prev ) ;
@ -336,9 +349,9 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) {
seen . delete ( stashed [ j ] ) ;
}
link ( a. prev , b . next ) ;
link ( prev, a ) ;
link ( b, start ) ;
link ( state, a. prev , b . next ) ;
link ( state, prev, a ) ;
link ( state, b, start ) ;
current = start ;
prev = b ;
@ -351,9 +364,9 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) {
seen . delete ( item ) ;
move ( item , current , anchor ) ;
link ( item. prev , item . next ) ;
link ( item, prev . next ) ;
link ( prev, item ) ;
link ( state, item. prev , item . next ) ;
link ( state, item, prev === null ? state . first : prev . next ) ;
link ( state, prev, item ) ;
prev = item ;
}
@ -403,7 +416,7 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) {
}
}
pause _effects ( to_destroy , controlled _anchor , items ) ;
pause _effects ( state, to_destroy , controlled _anchor , items ) ;
}
if ( is _animated ) {
@ -413,6 +426,9 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) {
}
} ) ;
}
/** @type {import('#client').Effect} */ ( current _effect ) . first = state . first && state . first . e ;
/** @type {import('#client').Effect} */ ( current _effect ) . last = prev && prev . e ;
}
/ * *
@ -437,7 +453,8 @@ function update_item(item, value, index, type) {
/ * *
* @ template V
* @ param { Node } anchor
* @ param { import ( '#client' ) . EachItem | import ( '#client' ) . EachState } prev
* @ param { import ( '#client' ) . EachState } state
* @ param { import ( '#client' ) . EachItem | null } prev
* @ param { import ( '#client' ) . EachItem | null } next
* @ param { V } value
* @ param { unknown } key
@ -446,7 +463,7 @@ function update_item(item, value, index, type) {
* @ param { number } flags
* @ returns { import ( '#client' ) . EachItem }
* /
function create _item ( anchor , prev, next , value , key , index , render _fn , flags ) {
function create _item ( anchor , state, prev, next , value , key , index , render _fn , flags ) {
var previous _each _item = current _each _item ;
try {
@ -468,52 +485,28 @@ function create_item(anchor, prev, next, value, key, index, render_fn, flags) {
next
} ;
prev . next = item ;
if ( next !== null ) next . prev = item ;
current _each _item = item ;
item . e = branch ( ( ) => render _fn ( anchor , v , i ) );
item . e = branch ( ( ) => render _fn ( anchor , v , i ) , hydrating ) ;
return item ;
} finally {
current _each _item = previous _each _item ;
}
}
item . e . prev = prev && prev . e ;
item . e . next = next && next . e ;
/ * *
* @ param { import ( '#client' ) . TemplateNode } dom
* @ param { import ( "#client" ) . Effect } effect
* @ returns { import ( '#client' ) . TemplateNode }
* /
function get _adjusted _first _node ( dom , effect ) {
if ( ( dom . nodeType === 3 && /** @type {Text} */ ( dom ) . data === '' ) || dom . nodeType === 8 ) {
var adjusted = effect . first ;
var next ;
while ( adjusted !== null ) {
next = adjusted . first ;
if ( adjusted . dom !== null ) {
break ;
} else if ( next === null ) {
return /** @type {import('#client').TemplateNode} */ ( dom . previousSibling ) ;
}
adjusted = next ;
if ( prev === null ) {
state . first = item ;
} else {
prev . next = item ;
prev . e . next = item . e ;
}
return get _first _node ( /** @type {import("#client").Effect} */ ( adjusted ) ) ;
}
return dom ;
}
/ * *
*
* @ param { import ( '#client' ) . Effect } effect
* @ returns { import ( '#client' ) . TemplateNode }
* /
function get _first _node ( effect ) {
var dom = effect . dom ;
if ( is _array ( dom ) ) {
return get _adjusted _first _node ( dom [ 0 ] , effect ) ;
if ( next !== null ) {
next . prev = item ;
next . e . prev = item . e ;
}
return item ;
} finally {
current _each _item = previous _each _item ;
}
return get _adjusted _first _node ( /** @type {import('#client').TemplateNode} **/ ( dom ) , effect ) ;
}
/ * *
@ -535,11 +528,20 @@ function move(item, next, anchor) {
}
/ * *
*
* @ param { import ( '#client' ) . EachItem | import ( '#client' ) . EachState } prev
* @ param { import ( '#client' ) . EachState } state
* @ param { import ( '#client' ) . EachItem | null } prev
* @ param { import ( '#client' ) . EachItem | null } next
* /
function link ( prev , next ) {
prev . next = next ;
if ( next !== null ) next . prev = prev ;
function link ( state , prev , next ) {
if ( prev === null ) {
state . first = next ;
} else {
prev . next = next ;
prev . e . next = next && next . e ;
}
if ( next !== null ) {
next . prev = prev ;
next . e . prev = prev && prev . e ;
}
}