From 956f5ecf1fdb8e7af870cd2b8d7b5e297761ec5a 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 849da96fb89a..88876f05f7d8 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 3459ba79b2fa..418b714117e8 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 9fb21574e58d..2cb02b2a5466 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.new.js @@ -2801,6 +2801,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 7b4554d41230..fbd3873fa54f 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.old.js @@ -2801,6 +2801,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 6a85b5de78cd..05952f77a0fd 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 = {};