( root: FiberRoot, finishedWork: Fiber, recoverableErrors: Array<CapturedValue<mixed>> | null, transitions: Array<Transition> | null, didIncludeRenderPhaseUpdate: boolean, lanes: Lanes, spawnedLane: Lane, updatedLanes: Lanes, suspendedRetryLanes: Lanes, didSkipSuspendedSiblings: boolean, exitStatus: RootExitStatus, suspendedCommitReason: SuspendedCommitReason, // Profiling-only completedRenderStartTime: number, // Profiling-only completedRenderEndTime: number, // Profiling-only )
| 1497 | } |
| 1498 | |
| 1499 | function commitRootWhenReady( |
| 1500 | root: FiberRoot, |
| 1501 | finishedWork: Fiber, |
| 1502 | recoverableErrors: Array<CapturedValue<mixed>> | null, |
| 1503 | transitions: Array<Transition> | null, |
| 1504 | didIncludeRenderPhaseUpdate: boolean, |
| 1505 | lanes: Lanes, |
| 1506 | spawnedLane: Lane, |
| 1507 | updatedLanes: Lanes, |
| 1508 | suspendedRetryLanes: Lanes, |
| 1509 | didSkipSuspendedSiblings: boolean, |
| 1510 | exitStatus: RootExitStatus, |
| 1511 | suspendedCommitReason: SuspendedCommitReason, // Profiling-only |
| 1512 | completedRenderStartTime: number, // Profiling-only |
| 1513 | completedRenderEndTime: number, // Profiling-only |
| 1514 | ) { |
| 1515 | root.timeoutHandle = noTimeout; |
| 1516 | |
| 1517 | // TODO: Combine retry throttling with Suspensey commits. Right now they run |
| 1518 | // one after the other. |
| 1519 | const BothVisibilityAndMaySuspendCommit = Visibility | MaySuspendCommit; |
| 1520 | const subtreeFlags = finishedWork.subtreeFlags; |
| 1521 | const isViewTransitionEligible = |
| 1522 | enableViewTransition && includesOnlyViewTransitionEligibleLanes(lanes); // TODO: Use a subtreeFlag to optimize. |
| 1523 | const isGestureTransition = enableGestureTransition && isGestureRender(lanes); |
| 1524 | const maySuspendCommit = |
| 1525 | subtreeFlags & ShouldSuspendCommit || |
| 1526 | (subtreeFlags & BothVisibilityAndMaySuspendCommit) === |
| 1527 | BothVisibilityAndMaySuspendCommit; |
| 1528 | let suspendedState: null | SuspendedState = null; |
| 1529 | if (isViewTransitionEligible || maySuspendCommit || isGestureTransition) { |
| 1530 | // Before committing, ask the renderer whether the host tree is ready. |
| 1531 | // If it's not, we'll wait until it notifies us. |
| 1532 | suspendedState = startSuspendingCommit(); |
| 1533 | // This will walk the completed fiber tree and attach listeners to all |
| 1534 | // the suspensey resources. The renderer is responsible for accumulating |
| 1535 | // all the load events. This all happens in a single synchronous |
| 1536 | // transaction, so it track state in its own module scope. |
| 1537 | // This will also track any newly added or appearing ViewTransition |
| 1538 | // components for the purposes of forming pairs. |
| 1539 | accumulateSuspenseyCommit(finishedWork, lanes, suspendedState); |
| 1540 | if (isViewTransitionEligible || isGestureTransition) { |
| 1541 | // If we're stopping gestures we don't have to wait for any pending |
| 1542 | // view transition. We'll stop it when we commit. |
| 1543 | if (!enableGestureTransition || root.stoppingGestures === null) { |
| 1544 | suspendOnActiveViewTransition(suspendedState, root.containerInfo); |
| 1545 | } |
| 1546 | } |
| 1547 | // For timeouts we use the previous fallback commit for retries and |
| 1548 | // the start time of the transition for transitions. This offset |
| 1549 | // represents the time already passed. |
| 1550 | const timeoutOffset = includesOnlyRetries(lanes) |
| 1551 | ? globalMostRecentFallbackTime - now() |
| 1552 | : includesOnlyTransitions(lanes) |
| 1553 | ? globalMostRecentTransitionTime - now() |
| 1554 | : 0; |
| 1555 | // At the end, ask the renderer if it's ready to commit, or if we should |
| 1556 | // suspend. If it's not ready, it will return a callback to subscribe to |
no test coverage detected