@@ -65,10 +65,11 @@ export function diffChildren(
6565 /** @type {PreactElement } */
6666 firstChildDom ;
6767
68- // This is a compression of oldParentVNode!=null && oldParentVNode != EMPTY_OBJ && oldParentVNode._children || EMPTY_ARR
69- // as EMPTY_OBJ._children should be `undefined`.
68+ // This is a compression of oldParentVNode != EMPTY_OBJ && oldParentVNode._children || EMPTY_ARR
69+ // as EMPTY_OBJ._children should be `undefined`. Callers always pass at
70+ // least EMPTY_OBJ, so a null check isn't needed.
7071 /** @type {VNode[] } */
71- let oldChildren = ( oldParentVNode && oldParentVNode . _children ) || EMPTY_ARR ;
72+ let oldChildren = oldParentVNode . _children || EMPTY_ARR ;
7273
7374 let newChildrenLength = renderResult . length ;
7475
@@ -86,8 +87,10 @@ export function diffChildren(
8687
8788 // At this point, constructNewChildrenArray has assigned _index to be the
8889 // matchingIndex for this VNode's oldVNode (or -1 if there is no oldVNode).
90+ // ~_index guards the -1 case: a negative array index is a named property
91+ // access which V8 can't serve from the fast elements path.
8992 oldVNode =
90- ( childVNode . _index != - 1 && oldChildren [ childVNode . _index ] ) || EMPTY_OBJ ;
93+ ( ~ childVNode . _index && oldChildren [ childVNode . _index ] ) || EMPTY_OBJ ;
9194
9295 // Update childVNode._index to its final index
9396 childVNode . _index = i ;
@@ -119,7 +122,7 @@ export function diffChildren(
119122 ) ;
120123 }
121124
122- if ( firstChildDom == NULL && newDom != NULL ) {
125+ if ( ! firstChildDom && newDom ) {
123126 firstChildDom = newDom ;
124127 }
125128
@@ -130,7 +133,7 @@ export function diffChildren(
130133 oldDom ,
131134 parentDom ,
132135 shouldPlace ,
133- oldVNode == NULL || oldVNode . _original == NULL
136+ oldVNode . _original == NULL
134137 ) ;
135138
136139 // When a matched VNode is physically moved via INSERT_VNODE, its old
@@ -196,11 +199,11 @@ function constructNewChildrenArray(
196199 // If this newVNode is being reused (e.g. <div>{reuse}{reuse}</div>) in the same diff,
197200 // or we are rendering a component (e.g. setState) copy the oldVNodes so it can have
198201 // it's own DOM & etc. pointers
202+ // Anything that isn't an object at this point is a string, number or
203+ // bigint (null, booleans and functions are handled above), String
204+ // objects are the lone object type rendered as text.
199205 else if (
200- typeof childVNode == 'string' ||
201- typeof childVNode == 'number' ||
202- // eslint-disable-next-line valid-typeof
203- typeof childVNode == 'bigint' ||
206+ typeof childVNode != 'object' ||
204207 childVNode . constructor == String
205208 ) {
206209 childVNode = newParentVNode . _children [ i ] = createVNode (
@@ -249,7 +252,8 @@ function constructNewChildrenArray(
249252 ) ) ;
250253
251254 oldVNode = NULL ;
252- if ( matchingIndex != - 1 ) {
255+ // ~matchingIndex is only falsy for -1, i.e. when no match was found
256+ if ( ~ matchingIndex ) {
253257 oldVNode = oldChildren [ matchingIndex ] ;
254258 remainingOldChildren -- ;
255259 if ( oldVNode ) {
@@ -260,8 +264,8 @@ function constructNewChildrenArray(
260264 // Here, we define isMounting for the purposes of the skew diffing
261265 // algorithm. Nodes that are unsuspending are considered mounting and we detect
262266 // this by checking if oldVNode._original == null
263- if ( oldVNode == NULL || oldVNode . _original == NULL ) {
264- if ( matchingIndex == - 1 ) {
267+ if ( ! oldVNode || ! oldVNode . _original ) {
268+ if ( ! ~ matchingIndex ) {
265269 // When the array of children is growing we need to decrease the skew
266270 // as we are adding a new element to the array.
267271 // Example:
@@ -330,7 +334,7 @@ function constructNewChildrenArray(
330334 if ( remainingOldChildren ) {
331335 for ( i = 0 ; i < oldChildrenLength ; i ++ ) {
332336 oldVNode = oldChildren [ i ] ;
333- if ( oldVNode != NULL && ( oldVNode . _flags & MATCHED ) == 0 ) {
337+ if ( oldVNode && ! ( oldVNode . _flags & MATCHED ) ) {
334338 if ( oldVNode . _dom == oldDom ) {
335339 oldDom = getDomSibling ( oldVNode ) ;
336340 }
@@ -388,7 +392,7 @@ function insert(parentVNode, oldDom, parentDom, shouldPlace, isMounting) {
388392
389393 do {
390394 oldDom = oldDom && oldDom . nextSibling ;
391- } while ( oldDom != NULL && oldDom . nodeType == 8 ) ;
395+ } while ( oldDom && oldDom . nodeType == 8 ) ;
392396
393397 return oldDom ;
394398}
@@ -428,7 +432,7 @@ function findMatchingIndex(
428432 const key = childVNode . key ;
429433 const type = childVNode . type ;
430434 let oldVNode = oldChildren [ skewedIndex ] ;
431- const matched = oldVNode != NULL && ( oldVNode . _flags & MATCHED ) == 0 ;
435+ const matched = oldVNode && ! ( oldVNode . _flags & MATCHED ) ;
432436
433437 // We only need to perform a search if there are more children
434438 // (remainingOldChildren) to search. However, if the oldVNode we just looked
@@ -443,10 +447,12 @@ function findMatchingIndex(
443447 // we should not search as we risk re-using state of an unrelated VNode. (reverted for now)
444448 let shouldSearch =
445449 // (typeof type != 'function' || type === Fragment || key) &&
450+ // The ternary keeps this a Smi comparison; `> matched` would compare
451+ // number to boolean which V8 can't serve from the fast path.
446452 remainingOldChildren > ( matched ? 1 : 0 ) ;
447453
448454 if (
449- ( oldVNode === NULL && key == null ) ||
455+ ( oldVNode === NULL && key == NULL ) ||
450456 ( matched && key == oldVNode . key && type == oldVNode . type )
451457 ) {
452458 return skewedIndex ;
@@ -457,8 +463,8 @@ function findMatchingIndex(
457463 const childIndex = x >= 0 ? x -- : y ++ ;
458464 oldVNode = oldChildren [ childIndex ] ;
459465 if (
460- oldVNode != NULL &&
461- ( oldVNode . _flags & MATCHED ) == 0 &&
466+ oldVNode &&
467+ ! ( oldVNode . _flags & MATCHED ) &&
462468 key == oldVNode . key &&
463469 type == oldVNode . type
464470 ) {
0 commit comments