(root: FiberRoot, lanes: Lanes)
| 2686 | } |
| 2687 | |
| 2688 | function renderRootConcurrent(root: FiberRoot, lanes: Lanes): RootExitStatus { |
| 2689 | const prevExecutionContext = executionContext; |
| 2690 | executionContext |= RenderContext; |
| 2691 | const prevDispatcher = pushDispatcher(root.containerInfo); |
| 2692 | const prevAsyncDispatcher = pushAsyncDispatcher(); |
| 2693 | |
| 2694 | // If the root or lanes have changed, throw out the existing stack |
| 2695 | // and prepare a fresh one. Otherwise we'll continue where we left off. |
| 2696 | if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { |
| 2697 | if (enableUpdaterTracking) { |
| 2698 | if (isDevToolsPresent) { |
| 2699 | const memoizedUpdaters = root.memoizedUpdaters; |
| 2700 | if (memoizedUpdaters.size > 0) { |
| 2701 | restorePendingUpdaters(root, workInProgressRootRenderLanes); |
| 2702 | memoizedUpdaters.clear(); |
| 2703 | } |
| 2704 | |
| 2705 | // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. |
| 2706 | // If we bailout on this work, we'll move them back (like above). |
| 2707 | // It's important to move them now in case the work spawns more work at the same priority with different updaters. |
| 2708 | // That way we can keep the current update and future updates separate. |
| 2709 | movePendingFibersToMemoized(root, lanes); |
| 2710 | } |
| 2711 | } |
| 2712 | |
| 2713 | workInProgressTransitions = getTransitionsForLanes(root, lanes); |
| 2714 | |
| 2715 | resetRenderTimer(); |
| 2716 | prepareFreshStack(root, lanes); |
| 2717 | } else { |
| 2718 | // This is a continuation of an existing work-in-progress. |
| 2719 | // |
| 2720 | // If we were previously in prerendering mode, check if we received any new |
| 2721 | // data during an interleaved event. |
| 2722 | workInProgressRootIsPrerendering = checkIfRootIsPrerendering(root, lanes); |
| 2723 | } |
| 2724 | |
| 2725 | if (enableSchedulingProfiler) { |
| 2726 | markRenderStarted(lanes); |
| 2727 | } |
| 2728 | |
| 2729 | outer: do { |
| 2730 | try { |
| 2731 | if ( |
| 2732 | workInProgressSuspendedReason !== NotSuspended && |
| 2733 | workInProgress !== null |
| 2734 | ) { |
| 2735 | // The work loop is suspended. We need to either unwind the stack or |
| 2736 | // replay the suspended component. |
| 2737 | const unitOfWork = workInProgress; |
| 2738 | const thrownValue = workInProgressThrownValue; |
| 2739 | resumeOrUnwind: switch (workInProgressSuspendedReason) { |
| 2740 | case SuspendedOnError: { |
| 2741 | // Unwind then continue with the normal work loop. |
| 2742 | workInProgressSuspendedReason = NotSuspended; |
| 2743 | workInProgressThrownValue = null; |
| 2744 | throwAndUnwindWorkLoop( |
| 2745 | root, |
no test coverage detected