diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js index ca25b272e473f..95b8db2b50127 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js @@ -259,8 +259,9 @@ import { getPendingTransitions, } from './ReactFiberTransition.old'; import { - getTracingMarkers, - pushTracingMarker, + getMarkerInstances, + pushMarkerInstance, + pushRootMarkerInstance, } from './ReactFiberTracingMarkerComponent.old'; const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; @@ -909,7 +910,14 @@ function updateTracingMarkerComponent( } } - pushTracingMarker(workInProgress); + const instance = workInProgress.stateNode; + if (instance !== null) { + pushMarkerInstance( + workInProgress, + instance.transitions, + instance.pendingSuspenseBoundaries, + ); + } const nextChildren = workInProgress.pendingProps.children; reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; @@ -1313,6 +1321,10 @@ function updateHostRoot(current, workInProgress, renderLanes) { const root: FiberRoot = workInProgress.stateNode; pushRootTransition(workInProgress, root, renderLanes); + if (enableTransitionTracing) { + pushRootMarkerInstance(workInProgress); + } + if (enableCache) { const nextCache: Cache = nextState.cache; pushCacheProvider(workInProgress, nextCache); @@ -2114,10 +2126,10 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { const currentTransitions = getPendingTransitions(); if (currentTransitions !== null) { // If there are no transitions, we don't need to keep track of tracing markers - const currentTracingMarkers = getTracingMarkers(); + const parentMarkerInstances = getMarkerInstances(); const primaryChildUpdateQueue: OffscreenQueue = { transitions: currentTransitions, - tracingMarkers: currentTracingMarkers, + markerInstances: parentMarkerInstances, }; primaryChildFragment.updateQueue = primaryChildUpdateQueue; } @@ -2200,10 +2212,10 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { if (enableTransitionTracing) { const currentTransitions = getPendingTransitions(); if (currentTransitions !== null) { - const currentTracingMarkers = getTracingMarkers(); + const parentMarkerInstances = getMarkerInstances(); const primaryChildUpdateQueue: OffscreenQueue = { transitions: currentTransitions, - tracingMarkers: currentTracingMarkers, + markerInstances: parentMarkerInstances, }; primaryChildFragment.updateQueue = primaryChildUpdateQueue; } @@ -3510,6 +3522,10 @@ function attemptEarlyBailoutIfNoScheduledUpdate( const root: FiberRoot = workInProgress.stateNode; pushRootTransition(workInProgress, root, renderLanes); + if (enableTransitionTracing) { + pushRootMarkerInstance(workInProgress); + } + if (enableCache) { const cache: Cache = current.memoizedState.cache; pushCacheProvider(workInProgress, cache); @@ -3702,7 +3718,14 @@ function attemptEarlyBailoutIfNoScheduledUpdate( } case TracingMarkerComponent: { if (enableTransitionTracing) { - pushTracingMarker(workInProgress); + const instance: TracingMarkerInstance = workInProgress.stateNode; + if (instance !== null) { + pushMarkerInstance( + workInProgress, + instance.transitions, + instance.pendingSuspenseBoundaries, + ); + } } } } diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.old.js b/packages/react-reconciler/src/ReactFiberCommitWork.old.js index 677db2f10b0ea..e637de758d6f1 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.old.js @@ -2811,13 +2811,9 @@ function commitPassiveMountOnFiber( // Get the transitions that were initiatized during the render // and add a start transition callback for each of them const root = finishedWork.stateNode; - let incompleteTransitions = root.incompleteTransitions; + const incompleteTransitions = root.incompleteTransitions; // Initial render if (committedTransitions !== null) { - if (incompleteTransitions === null) { - root.incompleteTransitions = incompleteTransitions = new Map(); - } - committedTransitions.forEach(transition => { addTransitionStartCallbackToPendingTransition({ transitionName: transition.name, @@ -2842,16 +2838,13 @@ function commitPassiveMountOnFiber( incompleteTransitions.delete(transition); } }); - } - // If there are no more pending suspense boundaries we - // clear the transitions because they are all complete. - if ( - incompleteTransitions === null || - incompleteTransitions.size === 0 - ) { - root.incompleteTransitions = null; + if (incompleteTransitions.size === 0) { + root.incompleteTransitions = null; + } } + + clearTransitionsForLanes(finishedRoot, committedLanes); } break; } @@ -2896,14 +2889,6 @@ function commitPassiveMountOnFiber( if (isFallback) { const transitions = queue.transitions; let prevTransitions = instance.transitions; - let rootIncompleteTransitions = finishedRoot.incompleteTransitions; - - // We lazily instantiate transition tracing relevant maps - // and sets in the commit phase as we need to use them. We only - // instantiate them in the fallback phase on an as needed basis - if (rootIncompleteTransitions === null) { - finishedRoot.incompleteTransitions = rootIncompleteTransitions = new Map(); - } if (instance.pendingMarkers === null) { instance.pendingMarkers = new Set(); } @@ -2911,56 +2896,39 @@ function commitPassiveMountOnFiber( instance.transitions = prevTransitions = new Set(); } - // TODO(luna): Combine the root code with the tracing marker code if (transitions !== null) { transitions.forEach(transition => { // Add all the transitions saved in the update queue during // the render phase (ie the transitions associated with this boundary) // into the transitions set. prevTransitions.add(transition); - - // Add the root transition's pending suspense boundary set to - // the queue's marker set. We will iterate through the marker - // set when we toggle state on the suspense boundary and - // add or remove the pending suspense boundaries as needed. - if (rootIncompleteTransitions !== null) { - if (!rootIncompleteTransitions.has(transition)) { - rootIncompleteTransitions.set(transition, new Map()); - } - instance.pendingMarkers.add( - rootIncompleteTransitions.get(transition), - ); - } }); } - const tracingMarkers = queue.tracingMarkers; - if (tracingMarkers !== null) { - tracingMarkers.forEach(marker => { - const markerInstance = marker.stateNode; + const markerInstances = queue.markerInstances; + if (markerInstances !== null) { + markerInstances.forEach(markerInstance => { + const markerTransitions = markerInstance.transitions; // There should only be a few tracing marker transitions because // they should be only associated with the transition that // caused them - markerInstance.transitions.forEach(transition => { - if (instance.transitions.has(transition)) { - instance.pendingMarkers.add( - markerInstance.pendingSuspenseBoundaries, - ); - } - }); + if (markerTransitions !== null) { + markerTransitions.forEach(transition => { + if (instance.transitions.has(transition)) { + instance.pendingMarkers.add( + markerInstance.pendingSuspenseBoundaries, + ); + } + }); + } }); } } - commitTransitionProgress(finishedWork); - - if ( - instance.pendingMarkers === null || - instance.pendingMarkers.size === 0 - ) { - finishedWork.updateQueue = null; - } + finishedWork.updateQueue = null; } + + commitTransitionProgress(finishedWork); } break; diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js index b99d3451d3324..fb11d7cd720a4 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js @@ -164,7 +164,10 @@ import {transferActualDuration} from './ReactProfilerTimer.old'; import {popCacheProvider} from './ReactFiberCacheComponent.old'; import {popTreeContext} from './ReactFiberTreeContext.old'; import {popRootTransition, popTransition} from './ReactFiberTransition.old'; -import {popTracingMarker} from './ReactFiberTracingMarkerComponent.old'; +import { + popMarkerInstance, + popRootMarkerInstance, +} from './ReactFiberTracingMarkerComponent.old'; function markUpdate(workInProgress: Fiber) { // Tag the fiber with an update effect. This turns a Placement into @@ -900,6 +903,11 @@ function completeWork( } popCacheProvider(workInProgress, cache); } + + if (enableTransitionTracing) { + popRootMarkerInstance(workInProgress); + } + popRootTransition(workInProgress, fiberRoot, renderLanes); popHostContainer(workInProgress); popTopLevelLegacyContextObject(workInProgress); @@ -1581,7 +1589,9 @@ function completeWork( } case TracingMarkerComponent: { if (enableTransitionTracing) { - popTracingMarker(workInProgress); + if (workInProgress.stateNode !== null) { + popMarkerInstance(workInProgress); + } bubbleProperties(workInProgress); if ( diff --git a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js index 5f119b3a4b66a..fd5bf9cfe1657 100644 --- a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js +++ b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js @@ -13,6 +13,7 @@ import type {StackCursor} from './ReactFiberStack.old'; import {enableTransitionTracing} from 'shared/ReactFeatureFlags'; import {createCursor, push, pop} from './ReactFiberStack.old'; +import {getWorkInProgressTransitions} from './ReactFiberWorkLoop.old'; export type SuspenseInfo = {name: string | null}; @@ -100,31 +101,75 @@ export function processTransitionCallbacks( // tracing marker can be logged as complete // This code lives separate from the ReactFiberTransition code because // we push and pop on the tracing marker, not the suspense boundary -const tracingMarkerStack: StackCursor | null> = createCursor(null); +const markerInstanceStack: StackCursor | null> = createCursor( + null, +); -export function pushTracingMarker(workInProgress: Fiber): void { +export function pushRootMarkerInstance(workInProgress: Fiber): void { if (enableTransitionTracing) { - if (tracingMarkerStack.current === null) { - push(tracingMarkerStack, [workInProgress], workInProgress); + const transitions = getWorkInProgressTransitions(); + const root = workInProgress.stateNode; + let incompleteTransitions = root.incompleteTransitions; + if (transitions !== null) { + if (incompleteTransitions === null) { + root.incompleteTransitions = incompleteTransitions = new Map(); + } + + transitions.forEach(transition => { + incompleteTransitions.set(transition, new Map()); + }); + } + + if (incompleteTransitions === null) { + push(markerInstanceStack, null, workInProgress); + } else { + const markerInstances = []; + incompleteTransitions.forEach((pendingSuspenseBoundaries, transition) => { + markerInstances.push({ + transitions: new Set([transition]), + pendingSuspenseBoundaries, + }); + }); + push(markerInstanceStack, markerInstances, workInProgress); + } + } +} + +export function popRootMarkerInstance(workInProgress: Fiber) { + if (enableTransitionTracing) { + pop(markerInstanceStack, workInProgress); + } +} + +export function pushMarkerInstance( + workInProgress: Fiber, + transitions: Set | null, + pendingSuspenseBoundaries: PendingSuspenseBoundaries | null, +): void { + if (enableTransitionTracing) { + const markerInstance = {transitions, pendingSuspenseBoundaries}; + + if (markerInstanceStack.current === null) { + push(markerInstanceStack, [markerInstance], workInProgress); } else { push( - tracingMarkerStack, - tracingMarkerStack.current.concat(workInProgress), + markerInstanceStack, + markerInstanceStack.current.concat(markerInstance), workInProgress, ); } } } -export function popTracingMarker(workInProgress: Fiber): void { +export function popMarkerInstance(workInProgress: Fiber): void { if (enableTransitionTracing) { - pop(tracingMarkerStack, workInProgress); + pop(markerInstanceStack, workInProgress); } } -export function getTracingMarkers(): Array | null { +export function getMarkerInstances(): Array | null { if (enableTransitionTracing) { - return tracingMarkerStack.current; + return markerInstanceStack.current; } return null; } diff --git a/packages/react-reconciler/src/ReactFiberUnwindWork.old.js b/packages/react-reconciler/src/ReactFiberUnwindWork.old.js index ba2e202dd552e..0c744f2f9ce12 100644 --- a/packages/react-reconciler/src/ReactFiberUnwindWork.old.js +++ b/packages/react-reconciler/src/ReactFiberUnwindWork.old.js @@ -49,7 +49,10 @@ import {popCacheProvider} from './ReactFiberCacheComponent.old'; import {transferActualDuration} from './ReactProfilerTimer.old'; import {popTreeContext} from './ReactFiberTreeContext.old'; import {popRootTransition, popTransition} from './ReactFiberTransition.old'; -import {popTracingMarker} from './ReactFiberTracingMarkerComponent.old'; +import { + popMarkerInstance, + popRootMarkerInstance, +} from './ReactFiberTracingMarkerComponent.old'; function unwindWork( current: Fiber | null, @@ -86,6 +89,11 @@ function unwindWork( const cache: Cache = workInProgress.memoizedState.cache; popCacheProvider(workInProgress, cache); } + + if (enableTransitionTracing) { + popRootMarkerInstance(workInProgress); + } + popRootTransition(workInProgress, root, renderLanes); popHostContainer(workInProgress); popTopLevelLegacyContextObject(workInProgress); @@ -162,7 +170,9 @@ function unwindWork( return null; case TracingMarkerComponent: if (enableTransitionTracing) { - popTracingMarker(workInProgress); + if (workInProgress.stateNode !== null) { + popMarkerInstance(workInProgress); + } } return null; default: @@ -194,6 +204,11 @@ function unwindInterruptedWork( const cache: Cache = interruptedWork.memoizedState.cache; popCacheProvider(interruptedWork, cache); } + + if (enableTransitionTracing) { + popRootMarkerInstance(interruptedWork); + } + popRootTransition(interruptedWork, root, renderLanes); popHostContainer(interruptedWork); popTopLevelLegacyContextObject(interruptedWork); @@ -230,7 +245,9 @@ function unwindInterruptedWork( break; case TracingMarkerComponent: if (enableTransitionTracing) { - popTracingMarker(interruptedWork); + if (interruptedWork.stateNode !== null) { + popMarkerInstance(interruptedWork); + } } break; default: