From f7cf077cca6524877cb837adb9a8ff54242672b1 Mon Sep 17 00:00:00 2001 From: Luna Ruan Date: Tue, 12 Apr 2022 10:42:08 -0500 Subject: [PATCH] [Transition Tracing] Add Offscreen Queue (#24341) Adds an Offscreen Queue. We use the offscreen queue to store not yet processed transitions. During the commit phase, we will add these transitions to the transitions field in memoizedState (in the subsequent PR) and clear the transitions field in the updateQueue --- .../src/ReactFiberBeginWork.new.js | 32 +++++++++++++++++++ .../src/ReactFiberBeginWork.old.js | 32 +++++++++++++++++++ .../src/ReactFiberCommitWork.new.js | 5 +++ .../src/ReactFiberCommitWork.old.js | 5 +++ .../src/ReactFiberOffscreenComponent.js | 5 +++ 5 files changed, 79 insertions(+) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js index 849da96fb89ac..88876f05f7d8d 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -26,6 +26,7 @@ import type {SuspenseContext} from './ReactFiberSuspenseContext.new'; import type { OffscreenProps, OffscreenState, + OffscreenQueue, } from './ReactFiberOffscreenComponent'; import type { Cache, @@ -255,6 +256,7 @@ import { getSuspendedCache, pushTransition, getOffscreenDeferredCache, + getSuspendedTransitions, } from './ReactFiberTransition.new'; const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; @@ -2161,6 +2163,16 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { renderLanes, ); workInProgress.memoizedState = SUSPENDED_MARKER; + if (enableTransitionTracing) { + const currentTransitions = getSuspendedTransitions(); + if (currentTransitions !== null) { + const primaryChildUpdateQueue: OffscreenQueue = { + transitions: currentTransitions, + }; + primaryChildFragment.updateQueue = primaryChildUpdateQueue; + } + } + return fallbackFragment; } else if ( enableCPUSuspense && @@ -2281,6 +2293,15 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); + if (enableTransitionTracing) { + const currentTransitions = getSuspendedTransitions(); + if (currentTransitions !== null) { + const primaryChildUpdateQueue: OffscreenQueue = { + transitions: currentTransitions, + }; + primaryChildFragment.updateQueue = primaryChildUpdateQueue; + } + } primaryChildFragment.childLanes = getRemainingWorkInPrimaryTree( current, renderLanes, @@ -2322,6 +2343,17 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { current, renderLanes, ); + + if (enableTransitionTracing) { + const currentTransitions = getSuspendedTransitions(); + if (currentTransitions !== null) { + const primaryChildUpdateQueue: OffscreenQueue = { + transitions: currentTransitions, + }; + primaryChildFragment.updateQueue = primaryChildUpdateQueue; + } + } + // Skip the primary children, and continue working on the // fallback children. workInProgress.memoizedState = SUSPENDED_MARKER; diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js index 3459ba79b2fa1..418b714117e81 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js @@ -26,6 +26,7 @@ import type {SuspenseContext} from './ReactFiberSuspenseContext.old'; import type { OffscreenProps, OffscreenState, + OffscreenQueue, } from './ReactFiberOffscreenComponent'; import type { Cache, @@ -255,6 +256,7 @@ import { getSuspendedCache, pushTransition, getOffscreenDeferredCache, + getSuspendedTransitions, } from './ReactFiberTransition.old'; const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; @@ -2161,6 +2163,16 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { renderLanes, ); workInProgress.memoizedState = SUSPENDED_MARKER; + if (enableTransitionTracing) { + const currentTransitions = getSuspendedTransitions(); + if (currentTransitions !== null) { + const primaryChildUpdateQueue: OffscreenQueue = { + transitions: currentTransitions, + }; + primaryChildFragment.updateQueue = primaryChildUpdateQueue; + } + } + return fallbackFragment; } else if ( enableCPUSuspense && @@ -2281,6 +2293,15 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); + if (enableTransitionTracing) { + const currentTransitions = getSuspendedTransitions(); + if (currentTransitions !== null) { + const primaryChildUpdateQueue: OffscreenQueue = { + transitions: currentTransitions, + }; + primaryChildFragment.updateQueue = primaryChildUpdateQueue; + } + } primaryChildFragment.childLanes = getRemainingWorkInPrimaryTree( current, renderLanes, @@ -2322,6 +2343,17 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { current, renderLanes, ); + + if (enableTransitionTracing) { + const currentTransitions = getSuspendedTransitions(); + if (currentTransitions !== null) { + const primaryChildUpdateQueue: OffscreenQueue = { + transitions: currentTransitions, + }; + primaryChildFragment.updateQueue = primaryChildUpdateQueue; + } + } + // Skip the primary children, and continue working on the // fallback children. workInProgress.memoizedState = SUSPENDED_MARKER; diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.new.js b/packages/react-reconciler/src/ReactFiberCommitWork.new.js index 3535acf18c807..dfb0308c012e5 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.new.js @@ -2781,6 +2781,11 @@ function commitPassiveMountOnFiber( } } } + + if (enableTransitionTracing) { + // TODO: Add code to actually process the update queue + finishedWork.updateQueue = null; + } break; } case CacheComponent: { diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.old.js b/packages/react-reconciler/src/ReactFiberCommitWork.old.js index 1cec4f11bbb46..5853bcfe5356c 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.old.js @@ -2781,6 +2781,11 @@ function commitPassiveMountOnFiber( } } } + + if (enableTransitionTracing) { + // TODO: Add code to actually process the update queue + finishedWork.updateQueue = null; + } break; } case CacheComponent: { diff --git a/packages/react-reconciler/src/ReactFiberOffscreenComponent.js b/packages/react-reconciler/src/ReactFiberOffscreenComponent.js index 6a85b5de78cd9..05952f77a0fdf 100644 --- a/packages/react-reconciler/src/ReactFiberOffscreenComponent.js +++ b/packages/react-reconciler/src/ReactFiberOffscreenComponent.js @@ -11,6 +11,7 @@ import type {ReactNodeList, OffscreenMode} from 'shared/ReactTypes'; import type {Lanes} from './ReactFiberLane.old'; import type {SpawnedCachePool} from './ReactFiberCacheComponent.new'; import type {Transition} from './ReactFiberTracingMarkerComponent.new'; + export type OffscreenProps = {| // TODO: Pick an API before exposing the Offscreen type. I've chosen an enum // for now, since we might have multiple variants. For example, hiding the @@ -33,4 +34,8 @@ export type OffscreenState = {| transitions: Set | null, |}; +export type OffscreenQueue = {| + transitions: Array | null, +|} | null; + export type OffscreenInstance = {};