(
returnFiber: Fiber,
currentFirstChild: Fiber | null,
newChildren: Array<any>,
lanes: Lanes,
)
| 1122 | } |
| 1123 | |
| 1124 | function reconcileChildrenArray( |
| 1125 | returnFiber: Fiber, |
| 1126 | currentFirstChild: Fiber | null, |
| 1127 | newChildren: Array<any>, |
| 1128 | lanes: Lanes, |
| 1129 | ): Fiber | null { |
| 1130 | // This algorithm can't optimize by searching from both ends since we |
| 1131 | // don't have backpointers on fibers. I'm trying to see how far we can get |
| 1132 | // with that model. If it ends up not being worth the tradeoffs, we can |
| 1133 | // add it later. |
| 1134 | |
| 1135 | // Even with a two ended optimization, we'd want to optimize for the case |
| 1136 | // where there are few changes and brute force the comparison instead of |
| 1137 | // going for the Map. It'd like to explore hitting that path first in |
| 1138 | // forward-only mode and only go for the Map once we notice that we need |
| 1139 | // lots of look ahead. This doesn't handle reversal as well as two ended |
| 1140 | // search but that's unusual. Besides, for the two ended optimization to |
| 1141 | // work on Iterables, we'd need to copy the whole set. |
| 1142 | |
| 1143 | // In this first iteration, we'll just live with hitting the bad case |
| 1144 | // (adding everything to a Map) in for every insert/move. |
| 1145 | |
| 1146 | // If you change this code, also update reconcileChildrenIterator() which |
| 1147 | // uses the same algorithm. |
| 1148 | |
| 1149 | let knownKeys: Set<string> | null = null; |
| 1150 | |
| 1151 | let resultingFirstChild: Fiber | null = null; |
| 1152 | let previousNewFiber: Fiber | null = null; |
| 1153 | |
| 1154 | let oldFiber = currentFirstChild; |
| 1155 | let lastPlacedIndex = 0; |
| 1156 | let newIdx = 0; |
| 1157 | let nextOldFiber = null; |
| 1158 | for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { |
| 1159 | if (oldFiber.index > newIdx) { |
| 1160 | nextOldFiber = oldFiber; |
| 1161 | oldFiber = null; |
| 1162 | } else { |
| 1163 | nextOldFiber = oldFiber.sibling; |
| 1164 | } |
| 1165 | const newFiber = updateSlot( |
| 1166 | returnFiber, |
| 1167 | oldFiber, |
| 1168 | newChildren[newIdx], |
| 1169 | lanes, |
| 1170 | ); |
| 1171 | if (newFiber === null) { |
| 1172 | // TODO: This breaks on empty slots like null children. That's |
| 1173 | // unfortunate because it triggers the slow path all the time. We need |
| 1174 | // a better way to communicate whether this was a miss or null, |
| 1175 | // boolean, undefined, etc. |
| 1176 | if (oldFiber === null) { |
| 1177 | oldFiber = nextOldFiber; |
| 1178 | } |
| 1179 | break; |
| 1180 | } |
| 1181 |
no test coverage detected