(returnFiber, currentFirstChild, newChildren, expirationTime)
| 13943 | } |
| 13944 | |
| 13945 | function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, expirationTime) { |
| 13946 | // This algorithm can't optimize by searching from both ends since we |
| 13947 | // don't have backpointers on fibers. I'm trying to see how far we can get |
| 13948 | // with that model. If it ends up not being worth the tradeoffs, we can |
| 13949 | // add it later. |
| 13950 | // Even with a two ended optimization, we'd want to optimize for the case |
| 13951 | // where there are few changes and brute force the comparison instead of |
| 13952 | // going for the Map. It'd like to explore hitting that path first in |
| 13953 | // forward-only mode and only go for the Map once we notice that we need |
| 13954 | // lots of look ahead. This doesn't handle reversal as well as two ended |
| 13955 | // search but that's unusual. Besides, for the two ended optimization to |
| 13956 | // work on Iterables, we'd need to copy the whole set. |
| 13957 | // In this first iteration, we'll just live with hitting the bad case |
| 13958 | // (adding everything to a Map) in for every insert/move. |
| 13959 | // If you change this code, also update reconcileChildrenIterator() which |
| 13960 | // uses the same algorithm. |
| 13961 | { |
| 13962 | // First, validate keys. |
| 13963 | var knownKeys = null; |
| 13964 | |
| 13965 | for (var i = 0; i < newChildren.length; i++) { |
| 13966 | var child = newChildren[i]; |
| 13967 | knownKeys = warnOnInvalidKey(child, knownKeys); |
| 13968 | } |
| 13969 | } |
| 13970 | |
| 13971 | var resultingFirstChild = null; |
| 13972 | var previousNewFiber = null; |
| 13973 | var oldFiber = currentFirstChild; |
| 13974 | var lastPlacedIndex = 0; |
| 13975 | var newIdx = 0; |
| 13976 | var nextOldFiber = null; |
| 13977 | |
| 13978 | for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { |
| 13979 | if (oldFiber.index > newIdx) { |
| 13980 | nextOldFiber = oldFiber; |
| 13981 | oldFiber = null; |
| 13982 | } else { |
| 13983 | nextOldFiber = oldFiber.sibling; |
| 13984 | } |
| 13985 | |
| 13986 | var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], expirationTime); |
| 13987 | |
| 13988 | if (newFiber === null) { |
| 13989 | // TODO: This breaks on empty slots like null children. That's |
| 13990 | // unfortunate because it triggers the slow path all the time. We need |
| 13991 | // a better way to communicate whether this was a miss or null, |
| 13992 | // boolean, undefined, etc. |
| 13993 | if (oldFiber === null) { |
| 13994 | oldFiber = nextOldFiber; |
| 13995 | } |
| 13996 | |
| 13997 | break; |
| 13998 | } |
| 13999 | |
| 14000 | if (shouldTrackSideEffects) { |
| 14001 | if (oldFiber && newFiber.alternate === null) { |
| 14002 | // We matched the slot, but we didn't reuse the existing fiber, so we |
no test coverage detected