@@ -136,8 +136,8 @@ export const vnode_diff = (
136
136
/// When elements have keys they can be consumed out of order and therefore we can't use nextSibling.
137
137
/// In such a case this array will contain the elements after the current location.
138
138
/// The array even indices will contains keys and odd indices the vNode.
139
- let vSiblings : Array < string | null | VNode > | null = null ; // See: `SiblingsArray`
140
- let vSiblingsIdx = - 1 ;
139
+ let vSiblings : Map < string , VNode > | null = null ;
140
+ let vSiblingsArray : Array < string | VNode | null > | null = null ;
141
141
142
142
/// Current set of JSX children.
143
143
let jsxChildren : JSXChildren [ ] = null ! ;
@@ -278,16 +278,9 @@ export const vnode_diff = (
278
278
* order and can't rely on `vnode_getNextSibling` and instead we need to go by `vSiblings`.
279
279
*/
280
280
function peekNextSibling ( ) {
281
- if ( vSiblings !== null ) {
282
- // We came across a key, and we moved nodes around. This means we can no longer use
283
- // `vnode_getNextSibling` to look at next node and instead we have to go by `vSiblings`.
284
- const idx = vSiblingsIdx + SiblingsArray . NextVNode ;
285
- return idx < vSiblings . length ? ( vSiblings [ idx ] as any ) : null ;
286
- } else {
287
- // If we don't have a `vNewNode`, than that means we just reconciled the current node.
288
- // So advance it.
289
- return vCurrent ? vnode_getNextSibling ( vCurrent ) : null ;
290
- }
281
+ // If we don't have a `vNewNode`, than that means we just reconciled the current node.
282
+ // So advance it.
283
+ return vCurrent ? vnode_getNextSibling ( vCurrent ) : null ;
291
284
}
292
285
293
286
/**
@@ -299,9 +292,6 @@ export const vnode_diff = (
299
292
*/
300
293
function advanceToNextSibling ( ) {
301
294
vCurrent = peekNextSibling ( ) ;
302
- if ( vSiblings !== null ) {
303
- vSiblingsIdx += SiblingsArray . Size ; // advance;
304
- }
305
295
}
306
296
307
297
/**
@@ -332,7 +322,7 @@ export const vnode_diff = (
332
322
if ( descendVNode ) {
333
323
assertDefined ( vCurrent || vNewNode , 'Expecting vCurrent to be defined.' ) ;
334
324
vSiblings = null ;
335
- vSiblingsIdx = - 1 ;
325
+ vSiblingsArray = null ;
336
326
vParent = vNewNode || vCurrent ! ;
337
327
vCurrent = vnode_getFirstChild ( vParent ) ;
338
328
vNewNode = null ;
@@ -343,8 +333,8 @@ export const vnode_diff = (
343
333
function ascend ( ) {
344
334
const descendVNode = stack . pop ( ) ; // boolean: descendVNode
345
335
if ( descendVNode ) {
346
- vSiblingsIdx = stack . pop ( ) ;
347
336
vSiblings = stack . pop ( ) ;
337
+ vSiblingsArray = stack . pop ( ) ;
348
338
vNewNode = stack . pop ( ) ;
349
339
vCurrent = stack . pop ( ) ;
350
340
vParent = stack . pop ( ) ;
@@ -359,7 +349,7 @@ export const vnode_diff = (
359
349
function stackPush ( children : JSXChildren , descendVNode : boolean ) {
360
350
stack . push ( jsxChildren , jsxIdx , jsxCount , jsxValue ) ;
361
351
if ( descendVNode ) {
362
- stack . push ( vParent , vCurrent , vNewNode , vSiblings , vSiblingsIdx ) ;
352
+ stack . push ( vParent , vCurrent , vNewNode , vSiblingsArray , vSiblings ) ;
363
353
}
364
354
stack . push ( descendVNode ) ;
365
355
if ( Array . isArray ( children ) ) {
@@ -384,9 +374,6 @@ export const vnode_diff = (
384
374
function getInsertBefore ( ) {
385
375
if ( vNewNode ) {
386
376
return vCurrent ;
387
- } else if ( vSiblings !== null ) {
388
- const nextIdx = vSiblingsIdx + SiblingsArray . NextVNode ;
389
- return nextIdx < vSiblings . length ? ( vSiblings [ nextIdx ] as VNode ) : null ;
390
377
} else {
391
378
return peekNextSibling ( ) ;
392
379
}
@@ -751,10 +738,6 @@ export const vnode_diff = (
751
738
vCurrent = vNewNode ;
752
739
// We need to clean up the vNewNode, because we don't want to skip advance to next sibling (see `advance` function).
753
740
vNewNode = null ;
754
- // We need also to go back to the previous sibling, because we assigned previous sibling to the vCurrent.
755
- if ( vSiblings !== null ) {
756
- vSiblingsIdx -= SiblingsArray . Size ;
757
- }
758
741
}
759
742
}
760
743
// reconcile attributes
@@ -959,60 +942,56 @@ export const vnode_diff = (
959
942
}
960
943
961
944
/**
962
- * Retrieve the child with the given key.
963
- *
964
- * By retrieving the child with the given key we are effectively removing it from the list of
965
- * future elements. This means that we can't just use `vnode_getNextSibling` to find the next
966
- * instead we have to keep track of the elements we have already seen.
967
- *
968
- * We call this materializing the elements.
969
- *
970
- * `vSiblingsIdx`:
971
- *
972
- * - -1: Not materialized
973
- * - Positive number - the index of the next element in the `vSiblings` array.
945
+ * This function is used to retrieve the child with the given key. If the child is not found, it
946
+ * will return null.
974
947
*
975
- * By retrieving the child with the given key we are effectively removing it from the list (hence
976
- * we need to splice the `vSiblings` array).
948
+ * After finding the first child with the given key we will create a map of all the keyed siblings
949
+ * and an array of non-keyed siblings. This is done to optimize the search for the next child with
950
+ * the specified key.
977
951
*
978
- * @param nodeName
979
- * @param key
980
- * @returns Array where: (see: `SiblingsArray`)
981
- *
982
- * - Idx%3 == 0 nodeName
983
- * - Idx%3 == 1 key
984
- * - Idx%3 == 2 vNode
952
+ * @param nodeName - The name of the node.
953
+ * @param key - The key of the node.
954
+ * @returns The child with the given key or null if not found.
985
955
*/
986
956
function retrieveChildWithKey (
987
957
nodeName : string | null ,
988
958
key : string | null
989
959
) : ElementVNode | VirtualVNode | null {
990
960
let vNodeWithKey : ElementVNode | VirtualVNode | null = null ;
991
- if ( vSiblingsIdx === - 1 ) {
961
+ if ( vSiblings === null ) {
992
962
// it is not materialized; so materialize it.
993
- vSiblings = [ ] ;
994
- vSiblingsIdx = 0 ;
963
+ vSiblings = new Map < string , VNode > ( ) ;
964
+ vSiblingsArray = [ ] ;
995
965
let vNode = vCurrent ;
996
966
while ( vNode ) {
997
967
const name = vnode_isElementVNode ( vNode ) ? vnode_getElementName ( vNode ) : null ;
998
968
const vKey = getKey ( vNode ) || getComponentHash ( vNode , container . $getObjectById$ ) ;
999
969
if ( vNodeWithKey === null && vKey == key && name == nodeName ) {
1000
970
vNodeWithKey = vNode as ElementVNode | VirtualVNode ;
1001
971
} else {
1002
- // we only add the elements which we did not find yet.
1003
- vSiblings . push ( name , vKey , vNode ) ;
972
+ if ( vKey === null ) {
973
+ vSiblingsArray . push ( name , vNode ) ;
974
+ } else {
975
+ // we only add the elements which we did not find yet.
976
+ vSiblings . set ( name + ':' + vKey , vNode ) ;
977
+ }
1004
978
}
1005
979
vNode = vnode_getNextSibling ( vNode ) ;
1006
980
}
1007
981
} else {
1008
- for ( let idx = vSiblingsIdx ; idx < vSiblings ! . length ; idx += SiblingsArray . Size ) {
1009
- const name = vSiblings ! [ idx + SiblingsArray . Name ] ;
1010
- const vKey = vSiblings ! [ idx + SiblingsArray . Key ] ;
1011
- if ( vKey === key && name === nodeName ) {
1012
- vNodeWithKey = vSiblings ! [ idx + SiblingsArray . VNode ] as any ;
1013
- // remove the node from the siblings array
1014
- vSiblings ?. splice ( idx , SiblingsArray . Size ) ;
1015
- break ;
982
+ if ( key === null ) {
983
+ for ( let i = 0 ; i < vSiblingsArray ! . length ; i += 2 ) {
984
+ if ( vSiblingsArray ! [ i ] === nodeName ) {
985
+ vNodeWithKey = vSiblingsArray ! [ i + 1 ] as ElementVNode | VirtualVNode ;
986
+ vSiblingsArray ! . splice ( i , 2 ) ;
987
+ break ;
988
+ }
989
+ }
990
+ } else {
991
+ const vSibling = vSiblings . get ( nodeName + ':' + key ) ;
992
+ if ( vSibling ) {
993
+ vNodeWithKey = vSibling as ElementVNode | VirtualVNode ;
994
+ vSiblings . delete ( nodeName + ':' + key ) ;
1016
995
}
1017
996
}
1018
997
}
@@ -1451,10 +1430,3 @@ function markVNodeAsDeleted(vCursor: VNode) {
1451
1430
*/
1452
1431
export const HANDLER_PREFIX = ':' ;
1453
1432
let count = 0 ;
1454
- const enum SiblingsArray {
1455
- Name = 0 ,
1456
- Key = 1 ,
1457
- VNode = 2 ,
1458
- Size = 3 ,
1459
- NextVNode = Size + VNode ,
1460
- }
0 commit comments