function patchKeyedChildren(c1, c2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized) {
        let i = 0;
        const l2 = c2.length;
        let e1 = c1.length - 1; // prev ending index
        let e2 = l2 - 1; // next ending index
        // 1. sync from start
        // (a b) c
        // (a b) d e
        while (i <= e1 && i <= e2) {
            const n1 = c1[i];
            const n2 = optimized
                ? c2[i]
                : (c2[i] = normalizeVNode(c2[i]));
            if (isSameType(n1, n2)) {
                patch(n1, n2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized);
            }
            else {
                break;
            }
            i++;
        }
        // 2. sync from end
        // a (b c)
        // d e (b c)
        while (i <= e1 && i <= e2) {
            const n1 = c1[e1];
            const n2 = optimized
                ? c2[i]
                : (c2[e2] = normalizeVNode(c2[e2]));
            if (isSameType(n1, n2)) {
                patch(n1, n2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized);
            }
            else {
                break;
            }
            e1--;
            e2--;
        }
        // 3. common sequence + mount
        // (a b)
        // (a b) c
        // i = 2, e1 = 1, e2 = 2
        // (a b)
        // c (a b)
        // i = 0, e1 = -1, e2 = 0
        if (i > e1) {
            if (i <= e2) {
                const nextPos = e2 + 1;
                const anchor = nextPos < l2 ? c2[nextPos].el : parentAnchor;
                while (i <= e2) {
                    patch(null, optimized ? c2[i] : (c2[i] = normalizeVNode(c2[i])), container, anchor, parentComponent, parentSuspense, isSVG);
                    i++;
                }
            }
        }
        // 4. common sequence + unmount
        // (a b) c
        // (a b)
        // i = 2, e1 = 2, e2 = 1
        // a (b c)
        // (b c)
        // i = 0, e1 = 0, e2 = -1
        else if (i > e2) {
            while (i <= e1) {
                unmount(c1[i], parentComponent, parentSuspense, true);
                i++;
            }
        }
        // 5. unknown sequence
        // [i ... e1 + 1]: a b [c d e] f g
        // [i ... e2 + 1]: a b [e d c h] f g
        // i = 2, e1 = 4, e2 = 5
        else {
            const s1 = i; // prev starting index
            const s2 = i; // next starting index
            // 5.1 build key:index map for newChildren
            const keyToNewIndexMap = new Map();
            for (i = s2; i <= e2; i++) {
                const nextChild = optimized
                    ? c2[i]
                    : (c2[i] = normalizeVNode(c2[i]));
                if (nextChild.key != null) {
                    if (__DEV__ && keyToNewIndexMap.has(nextChild.key)) {
                        warn(`Duplicate keys found during update:`, JSON.stringify(nextChild.key), `Make sure keys are unique.`);
                    }
                    keyToNewIndexMap.set(nextChild.key, i);
                }
            }
            // 5.2 loop through old children left to be patched and try to patch
            // matching nodes & remove nodes that are no longer present
            let j;
            let patched = 0;
            const toBePatched = e2 - s2 + 1;
            let moved = false;
            // used to track whether any node has moved
            let maxNewIndexSoFar = 0;
            // works as Map<newIndex, oldIndex>
            // Note that oldIndex is offset by +1
            // and oldIndex = 0 is a special value indicating the new node has
            // no corresponding old node.
            // used for determining longest stable subsequence
            const newIndexToOldIndexMap = new Array(toBePatched);
            for (i = 0; i < toBePatched; i++)
                newIndexToOldIndexMap[i] = 0;
            for (i = s1; i <= e1; i++) {
                const prevChild = c1[i];
                if (patched >= toBePatched) {
                    // all new children have been patched so this can only be a removal
                    unmount(prevChild, parentComponent, parentSuspense, true);
                    continue;
                }
                let newIndex;
                if (prevChild.key != null) {
                    newIndex = keyToNewIndexMap.get(prevChild.key);
                }
                else {
                    // key-less node, try to locate a key-less node of the same type
                    for (j = s2; j <= e2; j++) {
                        if (newIndexToOldIndexMap[j - s2] === 0 &&
                            isSameType(prevChild, c2[j])) {
                            newIndex = j;
                            break;
                        }
                    }
                }
                if (newIndex === undefined) {
                    unmount(prevChild, parentComponent, parentSuspense, true);
                }
                else {
                    newIndexToOldIndexMap[newIndex - s2] = i + 1;
                    if (newIndex >= maxNewIndexSoFar) {
                        maxNewIndexSoFar = newIndex;
                    }
                    else {
                        moved = true;
                    }
                    patch(prevChild, c2[newIndex], container, null, parentComponent, parentSuspense, isSVG, optimized);
                    patched++;
                }
            }
            // 5.3 move and mount
            // generate longest stable subsequence only when nodes have moved
            const increasingNewIndexSequence = moved
                ? getSequence(newIndexToOldIndexMap)
                : EMPTY_ARR;
            j = increasingNewIndexSequence.length - 1;
            // looping backwards so that we can use last patched node as anchor
            for (i = toBePatched - 1; i >= 0; i--) {
                const nextIndex = s2 + i;
                const nextChild = c2[nextIndex];
                const anchor = nextIndex + 1 < l2
                    ? c2[nextIndex + 1].el
                    : parentAnchor;
                if (newIndexToOldIndexMap[i] === 0) {
                    // mount new
                    patch(null, nextChild, container, anchor, parentComponent, parentSuspense, isSVG);
                }
                else if (moved) {
                    // move if:
                    // There is no stable subsequence (e.g. a reverse)
                    // OR current node is not among the stable sequence
                    if (j < 0 || i !== increasingNewIndexSequence[j]) {
                        move(nextChild, container, anchor);
                    }
                    else {
                        j--;
                    }
                }
            }
        }
    }
// can be all-keyed or mixed
can be all-keyed or mixed
can be all - keyed or mixed
function patchKeyedChildren(c1, c2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized) {
        let i = 0;
        const l2 = c2.length;
        let e1 = c1.length - 1; 
        let e2 = l2 - 1; 
        while (i <= e1 && i <= e2) {
            const n1 = c1[i];
            const n2 = optimized
                ? c2[i]
                : (c2[i] = normalizeVNode(c2[i]));
            if (isSameType(n1, n2)) {
                patch(n1, n2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized);
            }
            else {
                break;
            }
            i++;
        }
        while (i <= e1 && i <= e2) {
            const n1 = c1[e1];
            const n2 = optimized
                ? c2[i]
                : (c2[e2] = normalizeVNode(c2[e2]));
            if (isSameType(n1, n2)) {
                patch(n1, n2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized);
            }
            else {
                break;
            }
            e1--;
            e2--;
        }
        if (i > e1) {
            if (i <= e2) {
                const nextPos = e2 + 1;
                const anchor = nextPos < l2 ? c2[nextPos].el : parentAnchor;
                while (i <= e2) {
                    patch(null, optimized ? c2[i] : (c2[i] = normalizeVNode(c2[i])), container, anchor, parentComponent, parentSuspense, isSVG);
                    i++;
                }
            }
        }
        else if (i > e2) {
            while (i <= e1) {
                unmount(c1[i], parentComponent, parentSuspense, true);
                i++;
            }
        }
        else {
            const s1 = i; 
            const s2 = i; 
            const keyToNewIndexMap = new Map();
            for (i = s2; i <= e2; i++) {
                const nextChild = optimized
                    ? c2[i]
                    : (c2[i] = normalizeVNode(c2[i]));
                if (nextChild.key != null) {
                    if (__DEV__ && keyToNewIndexMap.has(nextChild.key)) {
                        warn(`Duplicate keys found during update:`, JSON.stringify(nextChild.key), `Make sure keys are unique.`);
                    }
                    keyToNewIndexMap.set(nextChild.key, i);
                }
            }
            let j;
            let patched = 0;
            const toBePatched = e2 - s2 + 1;
            let moved = false;
            let maxNewIndexSoFar = 0;
            const newIndexToOldIndexMap = new Array(toBePatched);
            for (i = 0; i < toBePatched; i++)
                newIndexToOldIndexMap[i] = 0;
            for (i = s1; i <= e1; i++) {
                const prevChild = c1[i];
                if (patched >= toBePatched) {
                    unmount(prevChild, parentComponent, parentSuspense, true);
                    continue;
                }
                let newIndex;
                if (prevChild.key != null) {
                    newIndex = keyToNewIndexMap.get(prevChild.key);
                }
                else {
                    for (j = s2; j <= e2; j++) {
                        if (newIndexToOldIndexMap[j - s2] === 0 &&
                            isSameType(prevChild, c2[j])) {
                            newIndex = j;
                            break;
                        }
                    }
                }
                if (newIndex === undefined) {
                    unmount(prevChild, parentComponent, parentSuspense, true);
                }
                else {
                    newIndexToOldIndexMap[newIndex - s2] = i + 1;
                    if (newIndex >= maxNewIndexSoFar) {
                        maxNewIndexSoFar = newIndex;
                    }
                    else {
                        moved = true;
                    }
                    patch(prevChild, c2[newIndex], container, null, parentComponent, parentSuspense, isSVG, optimized);
                    patched++;
                }
            }
            const increasingNewIndexSequence = moved
                ? getSequence(newIndexToOldIndexMap)
                : EMPTY_ARR;
            j = increasingNewIndexSequence.length - 1;
            for (i = toBePatched - 1; i >= 0; i--) {
                const nextIndex = s2 + i;
                const nextChild = c2[nextIndex];
                const anchor = nextIndex + 1 < l2
                    ? c2[nextIndex + 1].el
                    : parentAnchor;
                if (newIndexToOldIndexMap[i] === 0) {
                    patch(null, nextChild, container, anchor, parentComponent, parentSuspense, isSVG);
                }
                else if (moved) {
                    if (j < 0 || i !== increasingNewIndexSequence[j]) {
                        move(nextChild, container, anchor);
                    }
                    else {
                        j--;
                    }
                }
            }
        }
    }
function patchKeyedChildren ( c1 , c2 , container , parentAnchor , parentComponent , parentSuspense , isSVG , optimized ) { let i = 0 ; const l2 = c2 . length ; let e1 = c1 . length - 1 ; let e2 = l2 - 1 ; while ( i <= e1 && i <= e2 ) { const n1 = c1 [ i ] ; const n2 = optimized ? c2 [ i ] : ( c2 [ i ] = normalizeVNode ( c2 [ i ] ) ) ; if ( isSameType ( n1 , n2 ) ) { patch ( n1 , n2 , container , parentAnchor , parentComponent , parentSuspense , isSVG , optimized ) ; } else { break ; } i ++ ; } while ( i <= e1 && i <= e2 ) { const n1 = c1 [ e1 ] ; const n2 = optimized ? c2 [ i ] : ( c2 [ e2 ] = normalizeVNode ( c2 [ e2 ] ) ) ; if ( isSameType ( n1 , n2 ) ) { patch ( n1 , n2 , container , parentAnchor , parentComponent , parentSuspense , isSVG , optimized ) ; } else { break ; } e1 -- ; e2 -- ; } if ( i > e1 ) { if ( i <= e2 ) { const nextPos = e2 + 1 ; const anchor = nextPos < l2 ? c2 [ nextPos ] . el : parentAnchor ; while ( i <= e2 ) { patch ( null , optimized ? c2 [ i ] : ( c2 [ i ] = normalizeVNode ( c2 [ i ] ) ) , container , anchor , parentComponent , parentSuspense , isSVG ) ; i ++ ; } } } else if ( i > e2 ) { while ( i <= e1 ) { unmount ( c1 [ i ] , parentComponent , parentSuspense , true ) ; i ++ ; } } else { const s1 = i ; const s2 = i ; const keyToNewIndexMap = new Map ( ) ; for ( i = s2 ; i <= e2 ; i ++ ) { const nextChild = optimized ? c2 [ i ] : ( c2 [ i ] = normalizeVNode ( c2 [ i ] ) ) ; if ( nextChild . key != null ) { if ( __DEV__ && keyToNewIndexMap . has ( nextChild . key ) ) { warn ( ` ` , JSON . stringify ( nextChild . key ) , ` ` ) ; } keyToNewIndexMap . set ( nextChild . key , i ) ; } } let j ; let patched = 0 ; const toBePatched = e2 - s2 + 1 ; let moved = false ; let maxNewIndexSoFar = 0 ; const newIndexToOldIndexMap = new Array ( toBePatched ) ; for ( i = 0 ; i < toBePatched ; i ++ ) newIndexToOldIndexMap [ i ] = 0 ; for ( i = s1 ; i <= e1 ; i ++ ) { const prevChild = c1 [ i ] ; if ( patched >= toBePatched ) { unmount ( prevChild , parentComponent , parentSuspense , true ) ; continue ; } let newIndex ; if ( prevChild . key != null ) { newIndex = keyToNewIndexMap . get ( prevChild . key ) ; } else { for ( j = s2 ; j <= e2 ; j ++ ) { if ( newIndexToOldIndexMap [ j - s2 ] === 0 && isSameType ( prevChild , c2 [ j ] ) ) { newIndex = j ; break ; } } } if ( newIndex === undefined ) { unmount ( prevChild , parentComponent , parentSuspense , true ) ; } else { newIndexToOldIndexMap [ newIndex - s2 ] = i + 1 ; if ( newIndex >= maxNewIndexSoFar ) { maxNewIndexSoFar = newIndex ; } else { moved = true ; } patch ( prevChild , c2 [ newIndex ] , container , null , parentComponent , parentSuspense , isSVG , optimized ) ; patched ++ ; } } const increasingNewIndexSequence = moved ? getSequence ( newIndexToOldIndexMap ) : EMPTY_ARR ; j = increasingNewIndexSequence . length - 1 ; for ( i = toBePatched - 1 ; i >= 0 ; i -- ) { const nextIndex = s2 + i ; const nextChild = c2 [ nextIndex ] ; const anchor = nextIndex + 1 < l2 ? c2 [ nextIndex + 1 ] . el : parentAnchor ; if ( newIndexToOldIndexMap [ i ] === 0 ) { patch ( null , nextChild , container , anchor , parentComponent , parentSuspense , isSVG ) ; } else if ( moved ) { if ( j < 0 || i !== increasingNewIndexSequence [ j ] ) { move ( nextChild , container , anchor ) ; } else { j -- ; } } } } }
can be all-keyed or mixed
can be all - keyed or mixed
// prev ending index // next ending index // 1. sync from start // (a b) c // (a b) d e // 2. sync from end // a (b c) // d e (b c) // 3. common sequence + mount // (a b) // (a b) c // i = 2, e1 = 1, e2 = 2 // (a b) // c (a b) // i = 0, e1 = -1, e2 = 0 // 4. common sequence + unmount // (a b) c // (a b) // i = 2, e1 = 2, e2 = 1 // a (b c) // (b c) // i = 0, e1 = 0, e2 = -1 // 5. unknown sequence // [i ... e1 + 1]: a b [c d e] f g // [i ... e2 + 1]: a b [e d c h] f g // i = 2, e1 = 4, e2 = 5 // prev starting index // next starting index // 5.1 build key:index map for newChildren // 5.2 loop through old children left to be patched and try to patch // matching nodes & remove nodes that are no longer present // used to track whether any node has moved // works as Map<newIndex, oldIndex> // Note that oldIndex is offset by +1 // and oldIndex = 0 is a special value indicating the new node has // no corresponding old node. // used for determining longest stable subsequence // all new children have been patched so this can only be a removal // key-less node, try to locate a key-less node of the same type // 5.3 move and mount // generate longest stable subsequence only when nodes have moved // looping backwards so that we can use last patched node as anchor // mount new // move if: // There is no stable subsequence (e.g. a reverse) // OR current node is not among the stable sequence