(newSnapshot: ContextSnapshot)
| 150 | // updating all the context's current values. That way reads, always just read the current value. |
| 151 | // At the cost of updating contexts even if they're never read by this subtree. |
| 152 | export function switchContext(newSnapshot: ContextSnapshot): void { |
| 153 | // The basic algorithm we need to do is to pop back any contexts that are no longer on the stack. |
| 154 | // We also need to update any new contexts that are now on the stack with the deepest value. |
| 155 | // The easiest way to update new contexts is to just reapply them in reverse order from the |
| 156 | // perspective of the backpointers. To avoid allocating a lot when switching, we use the stack |
| 157 | // for that. Therefore this algorithm is recursive. |
| 158 | // 1) First we pop which ever snapshot tree was deepest. Popping old contexts as we go. |
| 159 | // 2) Then we find the nearest common ancestor from there. Popping old contexts as we go. |
| 160 | // 3) Then we reapply new contexts on the way back up the stack. |
| 161 | const prev = currentActiveSnapshot; |
| 162 | const next = newSnapshot; |
| 163 | if (prev !== next) { |
| 164 | if (prev === null) { |
| 165 | // $FlowFixMe[incompatible-call]: This has to be non-null since it's not equal to prev. |
| 166 | pushAllNext(next); |
| 167 | } else if (next === null) { |
| 168 | popAllPrevious(prev); |
| 169 | } else if (prev.depth === next.depth) { |
| 170 | popToNearestCommonAncestor(prev, next); |
| 171 | } else if (prev.depth > next.depth) { |
| 172 | popPreviousToCommonLevel(prev, next); |
| 173 | } else { |
| 174 | popNextToCommonLevel(prev, next); |
| 175 | } |
| 176 | currentActiveSnapshot = next; |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | export function pushProvider<T>( |
| 181 | context: ReactContext<T>, |
no test coverage detected