( liveCollection: LiveCollection<T, V>, newCollection: Iterable<V> | undefined | null, trackByFn: TrackByFunction<V>, reactiveConsumer: ReactiveNode | null, )
| 109 | * occur when accessing the length or iterator are tracked. |
| 110 | */ |
| 111 | export function reconcile<T, V>( |
| 112 | liveCollection: LiveCollection<T, V>, |
| 113 | newCollection: Iterable<V> | undefined | null, |
| 114 | trackByFn: TrackByFunction<V>, |
| 115 | reactiveConsumer: ReactiveNode | null, |
| 116 | ): void { |
| 117 | let detachedItems: UniqueValueMultiKeyMap<unknown, T> | undefined = undefined; |
| 118 | let liveKeysInTheFuture: Set<unknown> | undefined = undefined; |
| 119 | |
| 120 | let liveStartIdx = 0; |
| 121 | let liveEndIdx = liveCollection.length - 1; |
| 122 | |
| 123 | const duplicateKeys = ngDevMode ? new Map<unknown, Set<number>>() : undefined; |
| 124 | |
| 125 | if (Array.isArray(newCollection)) { |
| 126 | setActiveConsumer(reactiveConsumer); |
| 127 | let newEndIdx = newCollection.length - 1; |
| 128 | setActiveConsumer(null); |
| 129 | |
| 130 | while (liveStartIdx <= liveEndIdx && liveStartIdx <= newEndIdx) { |
| 131 | // compare from the beginning |
| 132 | const liveStartValue = liveCollection.at(liveStartIdx); |
| 133 | const newStartValue = newCollection[liveStartIdx]; |
| 134 | |
| 135 | if (ngDevMode) { |
| 136 | recordDuplicateKeys(duplicateKeys!, trackByFn(liveStartIdx, newStartValue), liveStartIdx); |
| 137 | } |
| 138 | |
| 139 | const isStartMatching = valuesMatching( |
| 140 | liveStartIdx, |
| 141 | liveStartValue, |
| 142 | liveStartIdx, |
| 143 | newStartValue, |
| 144 | trackByFn, |
| 145 | ); |
| 146 | if (isStartMatching !== 0) { |
| 147 | if (isStartMatching < 0) { |
| 148 | liveCollection.updateValue(liveStartIdx, newStartValue); |
| 149 | } |
| 150 | liveStartIdx++; |
| 151 | continue; |
| 152 | } |
| 153 | |
| 154 | // compare from the end |
| 155 | // TODO(perf): do _all_ the matching from the end |
| 156 | const liveEndValue = liveCollection.at(liveEndIdx); |
| 157 | const newEndValue = newCollection[newEndIdx]; |
| 158 | |
| 159 | if (ngDevMode) { |
| 160 | recordDuplicateKeys(duplicateKeys!, trackByFn(newEndIdx, newEndValue), newEndIdx); |
| 161 | } |
| 162 | |
| 163 | const isEndMatching = valuesMatching( |
| 164 | liveEndIdx, |
| 165 | liveEndValue, |
| 166 | newEndIdx, |
| 167 | newEndValue, |
| 168 | trackByFn, |
no test coverage detected
searching dependent graphs…