(returnFiber, currentFirstChild, newChildren, expirationTime)
| 8578 | } |
| 8579 | |
| 8580 | function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, expirationTime) { |
| 8581 | // This algorithm can't optimize by searching from boths ends since we |
| 8582 | // don't have backpointers on fibers. I'm trying to see how far we can get |
| 8583 | // with that model. If it ends up not being worth the tradeoffs, we can |
| 8584 | // add it later. |
| 8585 | |
| 8586 | // Even with a two ended optimization, we'd want to optimize for the case |
| 8587 | // where there are few changes and brute force the comparison instead of |
| 8588 | // going for the Map. It'd like to explore hitting that path first in |
| 8589 | // forward-only mode and only go for the Map once we notice that we need |
| 8590 | // lots of look ahead. This doesn't handle reversal as well as two ended |
| 8591 | // search but that's unusual. Besides, for the two ended optimization to |
| 8592 | // work on Iterables, we'd need to copy the whole set. |
| 8593 | |
| 8594 | // In this first iteration, we'll just live with hitting the bad case |
| 8595 | // (adding everything to a Map) in for every insert/move. |
| 8596 | |
| 8597 | // If you change this code, also update reconcileChildrenIterator() which |
| 8598 | // uses the same algorithm. |
| 8599 | |
| 8600 | { |
| 8601 | // First, validate keys. |
| 8602 | var knownKeys = null; |
| 8603 | for (var i = 0; i < newChildren.length; i++) { |
| 8604 | var child = newChildren[i]; |
| 8605 | knownKeys = warnOnInvalidKey(child, knownKeys); |
| 8606 | } |
| 8607 | } |
| 8608 | |
| 8609 | var resultingFirstChild = null; |
| 8610 | var previousNewFiber = null; |
| 8611 | |
| 8612 | var oldFiber = currentFirstChild; |
| 8613 | var lastPlacedIndex = 0; |
| 8614 | var newIdx = 0; |
| 8615 | var nextOldFiber = null; |
| 8616 | for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { |
| 8617 | if (oldFiber.index > newIdx) { |
| 8618 | nextOldFiber = oldFiber; |
| 8619 | oldFiber = null; |
| 8620 | } else { |
| 8621 | nextOldFiber = oldFiber.sibling; |
| 8622 | } |
| 8623 | var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], expirationTime); |
| 8624 | if (newFiber === null) { |
| 8625 | // TODO: This breaks on empty slots like null children. That's |
| 8626 | // unfortunate because it triggers the slow path all the time. We need |
| 8627 | // a better way to communicate whether this was a miss or null, |
| 8628 | // boolean, undefined, etc. |
| 8629 | if (oldFiber === null) { |
| 8630 | oldFiber = nextOldFiber; |
| 8631 | } |
| 8632 | break; |
| 8633 | } |
| 8634 | if (shouldTrackSideEffects) { |
| 8635 | if (oldFiber && newFiber.alternate === null) { |
| 8636 | // We matched the slot, but we didn't reuse the existing fiber, so we |
| 8637 | // need to delete the existing child. |
no test coverage detected