From 43c146cdbd01185c544d57d363ce411de623eebb Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 20 Jun 2022 20:29:47 -0400 Subject: [PATCH 1/7] refactor root --- .../src/ReactFiberBeginWork.new.js | 39 ++++++++-- .../src/ReactFiberCommitWork.new.js | 76 ++++++------------- .../src/ReactFiberCompleteWork.new.js | 14 +++- .../src/ReactFiberOffscreenComponent.js | 4 +- .../ReactFiberTracingMarkerComponent.new.js | 65 +++++++++++++--- .../src/ReactFiberUnwindWork.new.js | 23 +++++- 6 files changed, 142 insertions(+), 79 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js index e4f4d7173b4b2..8969ce9c42e9a 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -262,8 +262,9 @@ import { getPendingTransitions, } from './ReactFiberTransition.new'; import { - getTracingMarkers, - pushTracingMarker, + getMarkerInstances, + pushMarkerInstance, + pushRootMarkerInstance, } from './ReactFiberTracingMarkerComponent.new'; 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); @@ -2098,10 +2110,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; } @@ -2188,10 +2200,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; } @@ -3509,6 +3521,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); @@ -3694,7 +3710,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.new.js b/packages/react-reconciler/src/ReactFiberCommitWork.new.js index da00d7761f9c5..28ab9618eebab 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.new.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.new.js b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js index 913abb20c4130..045f970396b73 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js @@ -164,7 +164,10 @@ import {transferActualDuration} from './ReactProfilerTimer.new'; import {popCacheProvider} from './ReactFiberCacheComponent.new'; import {popTreeContext} from './ReactFiberTreeContext.new'; import {popRootTransition, popTransition} from './ReactFiberTransition.new'; -import {popTracingMarker} from './ReactFiberTracingMarkerComponent.new'; +import { + popMarkerInstance, + popRootMarkerInstance, +} from './ReactFiberTracingMarkerComponent.new'; 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); @@ -1579,7 +1587,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/ReactFiberOffscreenComponent.js b/packages/react-reconciler/src/ReactFiberOffscreenComponent.js index 00904d9fdd8ed..4fdff5c8dfb0d 100644 --- a/packages/react-reconciler/src/ReactFiberOffscreenComponent.js +++ b/packages/react-reconciler/src/ReactFiberOffscreenComponent.js @@ -8,12 +8,12 @@ */ import type {ReactNodeList, OffscreenMode} from 'shared/ReactTypes'; -import type {Fiber} from './ReactInternalTypes'; import type {Lanes} from './ReactFiberLane.old'; import type {SpawnedCachePool} from './ReactFiberCacheComponent.new'; import type { Transition, PendingSuspenseBoundaries, + TracingMarkerInstance, } from './ReactFiberTracingMarkerComponent.new'; export type OffscreenProps = {| @@ -39,7 +39,7 @@ export type OffscreenState = {| export type OffscreenQueue = {| transitions: Array | null, - tracingMarkers: Array | null, + markerInstances: Array | null, |} | null; export type OffscreenInstance = {| diff --git a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js index 3a136cda686fd..60e20a39c11ce 100644 --- a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js +++ b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js @@ -13,6 +13,7 @@ import type {StackCursor} from './ReactFiberStack.new'; import {enableTransitionTracing} from 'shared/ReactFeatureFlags'; import {createCursor, push, pop} from './ReactFiberStack.new'; +import {getWorkInProgressTransitions} from './ReactFiberWorkLoop.new'; 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.new.js b/packages/react-reconciler/src/ReactFiberUnwindWork.new.js index 6b2dca917d39b..884f22f8b528c 100644 --- a/packages/react-reconciler/src/ReactFiberUnwindWork.new.js +++ b/packages/react-reconciler/src/ReactFiberUnwindWork.new.js @@ -52,7 +52,10 @@ import {popCacheProvider} from './ReactFiberCacheComponent.new'; import {transferActualDuration} from './ReactProfilerTimer.new'; import {popTreeContext} from './ReactFiberTreeContext.new'; import {popRootTransition, popTransition} from './ReactFiberTransition.new'; -import {popTracingMarker} from './ReactFiberTracingMarkerComponent.new'; +import { + popMarkerInstance, + popRootMarkerInstance, +} from './ReactFiberTracingMarkerComponent.new'; function unwindWork( current: Fiber | null, @@ -89,6 +92,11 @@ function unwindWork( const cache: Cache = workInProgress.memoizedState.cache; popCacheProvider(workInProgress, cache); } + + if (enableTransitionTracing) { + popRootMarkerInstance(workInProgress); + } + popRootTransition(workInProgress, root, renderLanes); popHostContainer(workInProgress); popTopLevelLegacyContextObject(workInProgress); @@ -165,7 +173,9 @@ function unwindWork( return null; case TracingMarkerComponent: if (enableTransitionTracing) { - popTracingMarker(workInProgress); + if (workInProgress.stateNode !== null) { + popMarkerInstance(workInProgress); + } } return null; default: @@ -197,6 +207,11 @@ function unwindInterruptedWork( const cache: Cache = interruptedWork.memoizedState.cache; popCacheProvider(interruptedWork, cache); } + + if (enableTransitionTracing) { + popRootMarkerInstance(interruptedWork); + } + popRootTransition(interruptedWork, root, renderLanes); popHostContainer(interruptedWork); popTopLevelLegacyContextObject(interruptedWork); @@ -233,7 +248,9 @@ function unwindInterruptedWork( break; case TracingMarkerComponent: if (enableTransitionTracing) { - popTracingMarker(interruptedWork); + if (interruptedWork.stateNode !== null) { + popMarkerInstance(interruptedWork); + } } break; default: From ed3ab2f4f91e53512730f9308b5e3fc68c79195b Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 20 Jun 2022 20:38:32 -0400 Subject: [PATCH 2/7] old --- .../src/ReactFiberBeginWork.old.js | 39 ++++++++-- .../src/ReactFiberCommitWork.old.js | 76 ++++++------------- .../src/ReactFiberCompleteWork.old.js | 14 +++- .../ReactFiberTracingMarkerComponent.old.js | 65 +++++++++++++--- .../src/ReactFiberUnwindWork.old.js | 23 +++++- 5 files changed, 140 insertions(+), 77 deletions(-) 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 1fc8a388ea2d7..5c0e4fcb4ad32 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); @@ -1579,7 +1587,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: From dc5e27db4193294909d0ae599b5f956f7086fe75 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 27 Jun 2022 13:22:04 -0400 Subject: [PATCH 3/7] Add comments and push actual marker instance in pushMarkerInstance --- .../src/ReactFiberBeginWork.new.js | 12 ++--------- .../ReactFiberTracingMarkerComponent.new.js | 20 +++++++++++++++---- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js index 8969ce9c42e9a..048f0c25e327b 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -912,11 +912,7 @@ function updateTracingMarkerComponent( const instance = workInProgress.stateNode; if (instance !== null) { - pushMarkerInstance( - workInProgress, - instance.transitions, - instance.pendingSuspenseBoundaries, - ); + pushMarkerInstance(workInProgress, instance); } const nextChildren = workInProgress.pendingProps.children; reconcileChildren(current, workInProgress, nextChildren, renderLanes); @@ -3712,11 +3708,7 @@ function attemptEarlyBailoutIfNoScheduledUpdate( if (enableTransitionTracing) { const instance: TracingMarkerInstance = workInProgress.stateNode; if (instance !== null) { - pushMarkerInstance( - workInProgress, - instance.transitions, - instance.pendingSuspenseBoundaries, - ); + pushMarkerInstance(workInProgress, instance); } } } diff --git a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js index 60e20a39c11ce..c6e049ed661e9 100644 --- a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js +++ b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js @@ -107,15 +107,27 @@ const markerInstanceStack: StackCursor | null> = cr export function pushRootMarkerInstance(workInProgress: Fiber): void { if (enableTransitionTracing) { + // On the root, every transition gets mapped to it's own map of + // suspense boundaries. The transition is marked as complete when + // the suspense boundaries map is empty. We do this because every + // transition completes at different times and depends on different + // suspense boundaries to complete. We store all the transitions + // along with its map of suspense boundaries in the root incomplete + // transitions map. Each entry in this map functions like a tracing + // marker does, so we can push it onto the marker instance stack const transitions = getWorkInProgressTransitions(); const root = workInProgress.stateNode; let incompleteTransitions = root.incompleteTransitions; if (transitions !== null) { + // Create a mapping from transition to suspense boundaries + // We instantiate this lazily, only if transitions exist if (incompleteTransitions === null) { root.incompleteTransitions = incompleteTransitions = new Map(); } transitions.forEach(transition => { + // We need to create a new map here because we only have access to the + // object instance in the commit phase incompleteTransitions.set(transition, new Map()); }); } @@ -124,6 +136,9 @@ export function pushRootMarkerInstance(workInProgress: Fiber): void { push(markerInstanceStack, null, workInProgress); } else { const markerInstances = []; + // For ever transition on the suspense boundary, we push the transition + // along with its map of pending suspense boundaries onto the marker + // instance stack. incompleteTransitions.forEach((pendingSuspenseBoundaries, transition) => { markerInstances.push({ transitions: new Set([transition]), @@ -143,12 +158,9 @@ export function popRootMarkerInstance(workInProgress: Fiber) { export function pushMarkerInstance( workInProgress: Fiber, - transitions: Set | null, - pendingSuspenseBoundaries: PendingSuspenseBoundaries | null, + markerInstance: TracingMarkerInstance, ): void { if (enableTransitionTracing) { - const markerInstance = {transitions, pendingSuspenseBoundaries}; - if (markerInstanceStack.current === null) { push(markerInstanceStack, [markerInstance], workInProgress); } else { From 4eea51726c9822f70e9355a2ad585675d9dd5188 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 27 Jun 2022 13:22:55 -0400 Subject: [PATCH 4/7] old --- .../src/ReactFiberBeginWork.old.js | 12 ++--------- .../ReactFiberTracingMarkerComponent.old.js | 20 +++++++++++++++---- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js index 95b8db2b50127..3f5aab8a7441e 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js @@ -912,11 +912,7 @@ function updateTracingMarkerComponent( const instance = workInProgress.stateNode; if (instance !== null) { - pushMarkerInstance( - workInProgress, - instance.transitions, - instance.pendingSuspenseBoundaries, - ); + pushMarkerInstance(workInProgress, instance); } const nextChildren = workInProgress.pendingProps.children; reconcileChildren(current, workInProgress, nextChildren, renderLanes); @@ -3720,11 +3716,7 @@ function attemptEarlyBailoutIfNoScheduledUpdate( if (enableTransitionTracing) { const instance: TracingMarkerInstance = workInProgress.stateNode; if (instance !== null) { - pushMarkerInstance( - workInProgress, - instance.transitions, - instance.pendingSuspenseBoundaries, - ); + pushMarkerInstance(workInProgress, instance); } } } diff --git a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js index fd5bf9cfe1657..54f06bdbe57b6 100644 --- a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js +++ b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js @@ -107,15 +107,27 @@ const markerInstanceStack: StackCursor | null> = cr export function pushRootMarkerInstance(workInProgress: Fiber): void { if (enableTransitionTracing) { + // On the root, every transition gets mapped to it's own map of + // suspense boundaries. The transition is marked as complete when + // the suspense boundaries map is empty. We do this because every + // transition completes at different times and depends on different + // suspense boundaries to complete. We store all the transitions + // along with its map of suspense boundaries in the root incomplete + // transitions map. Each entry in this map functions like a tracing + // marker does, so we can push it onto the marker instance stack const transitions = getWorkInProgressTransitions(); const root = workInProgress.stateNode; let incompleteTransitions = root.incompleteTransitions; if (transitions !== null) { + // Create a mapping from transition to suspense boundaries + // We instantiate this lazily, only if transitions exist if (incompleteTransitions === null) { root.incompleteTransitions = incompleteTransitions = new Map(); } transitions.forEach(transition => { + // We need to create a new map here because we only have access to the + // object instance in the commit phase incompleteTransitions.set(transition, new Map()); }); } @@ -124,6 +136,9 @@ export function pushRootMarkerInstance(workInProgress: Fiber): void { push(markerInstanceStack, null, workInProgress); } else { const markerInstances = []; + // For ever transition on the suspense boundary, we push the transition + // along with its map of pending suspense boundaries onto the marker + // instance stack. incompleteTransitions.forEach((pendingSuspenseBoundaries, transition) => { markerInstances.push({ transitions: new Set([transition]), @@ -143,12 +158,9 @@ export function popRootMarkerInstance(workInProgress: Fiber) { export function pushMarkerInstance( workInProgress: Fiber, - transitions: Set | null, - pendingSuspenseBoundaries: PendingSuspenseBoundaries | null, + markerInstance: TracingMarkerInstance, ): void { if (enableTransitionTracing) { - const markerInstance = {transitions, pendingSuspenseBoundaries}; - if (markerInstanceStack.current === null) { push(markerInstanceStack, [markerInstance], workInProgress); } else { From 7034a226611b2e59855a50502a764a18a51c78fa Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 28 Jun 2022 14:31:58 -0400 Subject: [PATCH 5/7] refactor pushRootMarkerInstance --- .../src/ReactFiberBeginWork.new.js | 10 +++-- .../src/ReactFiberCommitWork.new.js | 25 ++++++------ .../src/ReactFiberCompleteWork.new.js | 4 +- .../src/ReactFiberRoot.new.js | 2 +- .../ReactFiberTracingMarkerComponent.new.js | 40 +++++++------------ .../src/ReactFiberUnwindWork.new.js | 5 ++- .../src/ReactInternalTypes.js | 2 +- 7 files changed, 43 insertions(+), 45 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js index 048f0c25e327b..2816e72c60078 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -27,6 +27,7 @@ import type { OffscreenProps, OffscreenState, OffscreenQueue, + OffscreenInstance, } from './ReactFiberOffscreenComponent'; import type { Cache, @@ -780,7 +781,10 @@ function updateOffscreenComponent( if (enableTransitionTracing) { // We have now gone from hidden to visible, so any transitions should // be added to the stack to get added to any Offscreen/suspense children - transitions = workInProgress.stateNode.transitions; + const instance: OffscreenInstance | null = workInProgress.stateNode; + if (instance !== null && instance.transitions != null) { + transitions = Array.from(instance.transitions); + } } pushTransition(workInProgress, prevCachePool, transitions); @@ -910,7 +914,7 @@ function updateTracingMarkerComponent( } } - const instance = workInProgress.stateNode; + const instance: TracingMarkerInstance | null = workInProgress.stateNode; if (instance !== null) { pushMarkerInstance(workInProgress, instance); } @@ -3706,7 +3710,7 @@ function attemptEarlyBailoutIfNoScheduledUpdate( } case TracingMarkerComponent: { if (enableTransitionTracing) { - const instance: TracingMarkerInstance = workInProgress.stateNode; + const instance: TracingMarkerInstance | null = workInProgress.stateNode; if (instance !== null) { pushMarkerInstance(workInProgress, instance); } diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.new.js b/packages/react-reconciler/src/ReactFiberCommitWork.new.js index 28ab9618eebab..30709cffa5061 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.new.js @@ -2819,30 +2819,25 @@ function commitPassiveMountOnFiber( transitionName: transition.name, startTime: transition.startTime, }); - - if (!incompleteTransitions.has(transition)) { - incompleteTransitions.set(transition, null); - } }); clearTransitionsForLanes(finishedRoot, committedLanes); } - if (incompleteTransitions !== null) { - incompleteTransitions.forEach((pendingBoundaries, transition) => { - if (pendingBoundaries === null || pendingBoundaries.size === 0) { + incompleteTransitions.forEach( + ({pendingSuspenseBoundaries}, transition) => { + if ( + pendingSuspenseBoundaries === null || + pendingSuspenseBoundaries.size === 0 + ) { addTransitionCompleteCallbackToPendingTransition({ transitionName: transition.name, startTime: transition.startTime, }); incompleteTransitions.delete(transition); } - }); - - if (incompleteTransitions.size === 0) { - root.incompleteTransitions = null; - } - } + }, + ); clearTransitionsForLanes(finishedRoot, committedLanes); } @@ -2908,6 +2903,10 @@ function commitPassiveMountOnFiber( const markerInstances = queue.markerInstances; if (markerInstances !== null) { markerInstances.forEach(markerInstance => { + if (markerInstance.pendingSuspenseBoundaries === null) { + markerInstance.pendingSuspenseBoundaries = new Map(); + } + const markerTransitions = markerInstance.transitions; // There should only be a few tracing marker transitions because // they should be only associated with the transition that diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js index 045f970396b73..3fb9f8dfb1263 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js @@ -28,6 +28,7 @@ import type { SuspenseListRenderState, } from './ReactFiberSuspenseComponent.new'; import type {OffscreenState} from './ReactFiberOffscreenComponent'; +import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.new'; import type {Cache} from './ReactFiberCacheComponent.new'; import { enableSuspenseAvoidThisFallback, @@ -1587,7 +1588,8 @@ function completeWork( } case TracingMarkerComponent: { if (enableTransitionTracing) { - if (workInProgress.stateNode !== null) { + const instance: TracingMarkerInstance | null = workInProgress.stateNode; + if (instance !== null) { popMarkerInstance(workInProgress); } bubbleProperties(workInProgress); diff --git a/packages/react-reconciler/src/ReactFiberRoot.new.js b/packages/react-reconciler/src/ReactFiberRoot.new.js index d8ac576f4fd4c..f171ca0de3943 100644 --- a/packages/react-reconciler/src/ReactFiberRoot.new.js +++ b/packages/react-reconciler/src/ReactFiberRoot.new.js @@ -92,13 +92,13 @@ function FiberRootNode( this.hydrationCallbacks = null; } + this.incompleteTransitions = new Map(); if (enableTransitionTracing) { this.transitionCallbacks = null; const transitionLanesMap = (this.transitionLanes = []); for (let i = 0; i < TotalLanes; i++) { transitionLanesMap.push(null); } - this.incompleteTransitions = null; } if (enableProfilerTimer && enableProfilerCommitHooks) { diff --git a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js index c6e049ed661e9..0eb87bc3d6dbd 100644 --- a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js +++ b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js @@ -117,36 +117,26 @@ export function pushRootMarkerInstance(workInProgress: Fiber): void { // marker does, so we can push it onto the marker instance stack const transitions = getWorkInProgressTransitions(); const root = workInProgress.stateNode; - let incompleteTransitions = root.incompleteTransitions; - if (transitions !== null) { - // Create a mapping from transition to suspense boundaries - // We instantiate this lazily, only if transitions exist - if (incompleteTransitions === null) { - root.incompleteTransitions = incompleteTransitions = new Map(); - } + if (transitions !== null) { transitions.forEach(transition => { - // We need to create a new map here because we only have access to the - // object instance in the commit phase - incompleteTransitions.set(transition, new Map()); + if (!root.incompleteTransitions.has(transition)) { + root.incompleteTransitions.set(transition, { + transitions: new Set([transition]), + pendingSuspenseBoundaries: null, + }); + } }); } - if (incompleteTransitions === null) { - push(markerInstanceStack, null, workInProgress); - } else { - const markerInstances = []; - // For ever transition on the suspense boundary, we push the transition - // along with its map of pending suspense boundaries onto the marker - // instance stack. - incompleteTransitions.forEach((pendingSuspenseBoundaries, transition) => { - markerInstances.push({ - transitions: new Set([transition]), - pendingSuspenseBoundaries, - }); - }); - push(markerInstanceStack, markerInstances, workInProgress); - } + const markerInstances = []; + // For ever transition on the suspense boundary, we push the transition + // along with its map of pending suspense boundaries onto the marker + // instance stack. + root.incompleteTransitions.forEach(markerInstance => { + markerInstances.push(markerInstance); + }); + push(markerInstanceStack, markerInstances, workInProgress); } } diff --git a/packages/react-reconciler/src/ReactFiberUnwindWork.new.js b/packages/react-reconciler/src/ReactFiberUnwindWork.new.js index 884f22f8b528c..2659a74d80fd5 100644 --- a/packages/react-reconciler/src/ReactFiberUnwindWork.new.js +++ b/packages/react-reconciler/src/ReactFiberUnwindWork.new.js @@ -12,6 +12,7 @@ import type {Fiber, FiberRoot} from './ReactInternalTypes'; import type {Lanes} from './ReactFiberLane.new'; import type {SuspenseState} from './ReactFiberSuspenseComponent.new'; import type {Cache} from './ReactFiberCacheComponent.new'; +import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.new'; import {resetWorkInProgressVersions as resetMutableSourceWorkInProgressVersions} from './ReactMutableSource.new'; import { @@ -248,7 +249,9 @@ function unwindInterruptedWork( break; case TracingMarkerComponent: if (enableTransitionTracing) { - if (interruptedWork.stateNode !== null) { + const instance: TracingMarkerInstance | null = + interruptedWork.stateNode; + if (instance !== null) { popMarkerInstance(interruptedWork); } } diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index 0f6e9bcaf79ff..8aad50f4bfc6b 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -335,7 +335,7 @@ type TransitionTracingOnlyFiberRootProperties = {| // are considered complete when the pending suspense boundaries set is // empty. We can represent this as a Map of transitions to suspense // boundary sets - incompleteTransitions: Map | null, + incompleteTransitions: Map, |}; // Exported FiberRoot type includes all properties, From aa7138747c83851f10f5be7bd1deb66499a5243d Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 29 Jun 2022 13:29:45 -0400 Subject: [PATCH 6/7] old --- .../src/ReactFiberBeginWork.old.js | 10 +++-- .../src/ReactFiberCommitWork.old.js | 25 ++++++------ .../src/ReactFiberCompleteWork.old.js | 4 +- .../src/ReactFiberRoot.old.js | 2 +- .../ReactFiberTracingMarkerComponent.old.js | 40 +++++++------------ .../src/ReactFiberUnwindWork.old.js | 5 ++- 6 files changed, 42 insertions(+), 44 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js index 3f5aab8a7441e..8b19780af34df 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js @@ -27,6 +27,7 @@ import type { OffscreenProps, OffscreenState, OffscreenQueue, + OffscreenInstance, } from './ReactFiberOffscreenComponent'; import type { Cache, @@ -785,7 +786,10 @@ function updateOffscreenComponent( if (enableTransitionTracing) { // We have now gone from hidden to visible, so any transitions should // be added to the stack to get added to any Offscreen/suspense children - transitions = workInProgress.stateNode.transitions; + const instance: OffscreenInstance | null = workInProgress.stateNode; + if (instance !== null && instance.transitions != null) { + transitions = Array.from(instance.transitions); + } } pushTransition(workInProgress, prevCachePool, transitions); @@ -910,7 +914,7 @@ function updateTracingMarkerComponent( } } - const instance = workInProgress.stateNode; + const instance: TracingMarkerInstance | null = workInProgress.stateNode; if (instance !== null) { pushMarkerInstance(workInProgress, instance); } @@ -3714,7 +3718,7 @@ function attemptEarlyBailoutIfNoScheduledUpdate( } case TracingMarkerComponent: { if (enableTransitionTracing) { - const instance: TracingMarkerInstance = workInProgress.stateNode; + const instance: TracingMarkerInstance | null = workInProgress.stateNode; if (instance !== null) { pushMarkerInstance(workInProgress, instance); } diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.old.js b/packages/react-reconciler/src/ReactFiberCommitWork.old.js index e637de758d6f1..7f596a12641cc 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.old.js @@ -2819,30 +2819,25 @@ function commitPassiveMountOnFiber( transitionName: transition.name, startTime: transition.startTime, }); - - if (!incompleteTransitions.has(transition)) { - incompleteTransitions.set(transition, null); - } }); clearTransitionsForLanes(finishedRoot, committedLanes); } - if (incompleteTransitions !== null) { - incompleteTransitions.forEach((pendingBoundaries, transition) => { - if (pendingBoundaries === null || pendingBoundaries.size === 0) { + incompleteTransitions.forEach( + ({pendingSuspenseBoundaries}, transition) => { + if ( + pendingSuspenseBoundaries === null || + pendingSuspenseBoundaries.size === 0 + ) { addTransitionCompleteCallbackToPendingTransition({ transitionName: transition.name, startTime: transition.startTime, }); incompleteTransitions.delete(transition); } - }); - - if (incompleteTransitions.size === 0) { - root.incompleteTransitions = null; - } - } + }, + ); clearTransitionsForLanes(finishedRoot, committedLanes); } @@ -2908,6 +2903,10 @@ function commitPassiveMountOnFiber( const markerInstances = queue.markerInstances; if (markerInstances !== null) { markerInstances.forEach(markerInstance => { + if (markerInstance.pendingSuspenseBoundaries === null) { + markerInstance.pendingSuspenseBoundaries = new Map(); + } + const markerTransitions = markerInstance.transitions; // There should only be a few tracing marker transitions because // they should be only associated with the transition that diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js index 5c0e4fcb4ad32..6dd8fb07ab09a 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js @@ -29,6 +29,7 @@ import type { } from './ReactFiberSuspenseComponent.old'; import type {SuspenseContext} from './ReactFiberSuspenseContext.old'; import type {OffscreenState} from './ReactFiberOffscreenComponent'; +import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.old'; import type {Cache} from './ReactFiberCacheComponent.old'; import { enableSuspenseAvoidThisFallback, @@ -1587,7 +1588,8 @@ function completeWork( } case TracingMarkerComponent: { if (enableTransitionTracing) { - if (workInProgress.stateNode !== null) { + const instance: TracingMarkerInstance | null = workInProgress.stateNode; + if (instance !== null) { popMarkerInstance(workInProgress); } bubbleProperties(workInProgress); diff --git a/packages/react-reconciler/src/ReactFiberRoot.old.js b/packages/react-reconciler/src/ReactFiberRoot.old.js index 7bf68ae5d270d..9b37cee41edab 100644 --- a/packages/react-reconciler/src/ReactFiberRoot.old.js +++ b/packages/react-reconciler/src/ReactFiberRoot.old.js @@ -92,13 +92,13 @@ function FiberRootNode( this.hydrationCallbacks = null; } + this.incompleteTransitions = new Map(); if (enableTransitionTracing) { this.transitionCallbacks = null; const transitionLanesMap = (this.transitionLanes = []); for (let i = 0; i < TotalLanes; i++) { transitionLanesMap.push(null); } - this.incompleteTransitions = null; } if (enableProfilerTimer && enableProfilerCommitHooks) { diff --git a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js index 54f06bdbe57b6..6f25d1f72b825 100644 --- a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js +++ b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js @@ -117,36 +117,26 @@ export function pushRootMarkerInstance(workInProgress: Fiber): void { // marker does, so we can push it onto the marker instance stack const transitions = getWorkInProgressTransitions(); const root = workInProgress.stateNode; - let incompleteTransitions = root.incompleteTransitions; - if (transitions !== null) { - // Create a mapping from transition to suspense boundaries - // We instantiate this lazily, only if transitions exist - if (incompleteTransitions === null) { - root.incompleteTransitions = incompleteTransitions = new Map(); - } + if (transitions !== null) { transitions.forEach(transition => { - // We need to create a new map here because we only have access to the - // object instance in the commit phase - incompleteTransitions.set(transition, new Map()); + if (!root.incompleteTransitions.has(transition)) { + root.incompleteTransitions.set(transition, { + transitions: new Set([transition]), + pendingSuspenseBoundaries: null, + }); + } }); } - if (incompleteTransitions === null) { - push(markerInstanceStack, null, workInProgress); - } else { - const markerInstances = []; - // For ever transition on the suspense boundary, we push the transition - // along with its map of pending suspense boundaries onto the marker - // instance stack. - incompleteTransitions.forEach((pendingSuspenseBoundaries, transition) => { - markerInstances.push({ - transitions: new Set([transition]), - pendingSuspenseBoundaries, - }); - }); - push(markerInstanceStack, markerInstances, workInProgress); - } + const markerInstances = []; + // For ever transition on the suspense boundary, we push the transition + // along with its map of pending suspense boundaries onto the marker + // instance stack. + root.incompleteTransitions.forEach(markerInstance => { + markerInstances.push(markerInstance); + }); + push(markerInstanceStack, markerInstances, workInProgress); } } diff --git a/packages/react-reconciler/src/ReactFiberUnwindWork.old.js b/packages/react-reconciler/src/ReactFiberUnwindWork.old.js index 0c744f2f9ce12..f56c8ce5d2893 100644 --- a/packages/react-reconciler/src/ReactFiberUnwindWork.old.js +++ b/packages/react-reconciler/src/ReactFiberUnwindWork.old.js @@ -12,6 +12,7 @@ import type {Fiber, FiberRoot} from './ReactInternalTypes'; import type {Lanes} from './ReactFiberLane.old'; import type {SuspenseState} from './ReactFiberSuspenseComponent.old'; import type {Cache} from './ReactFiberCacheComponent.old'; +import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.old'; import {resetWorkInProgressVersions as resetMutableSourceWorkInProgressVersions} from './ReactMutableSource.old'; import { @@ -245,7 +246,9 @@ function unwindInterruptedWork( break; case TracingMarkerComponent: if (enableTransitionTracing) { - if (interruptedWork.stateNode !== null) { + const instance: TracingMarkerInstance | null = + interruptedWork.stateNode; + if (instance !== null) { popMarkerInstance(interruptedWork); } } From e1e26135683477180c365938bbf04d195325451d Mon Sep 17 00:00:00 2001 From: Luna Date: Thu, 30 Jun 2022 12:43:11 -0400 Subject: [PATCH 7/7] fix test --- packages/react-reconciler/src/ReactFiber.new.js | 7 ++++++- packages/react-reconciler/src/ReactFiber.old.js | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiber.new.js b/packages/react-reconciler/src/ReactFiber.new.js index e81801ad5c8f3..6865ef0b67a25 100644 --- a/packages/react-reconciler/src/ReactFiber.new.js +++ b/packages/react-reconciler/src/ReactFiber.new.js @@ -736,7 +736,12 @@ export function createFiberFromLegacyHidden( fiber.lanes = lanes; // Adding a stateNode for legacy hidden because it's currently using // the offscreen implementation, which depends on a state node - fiber.stateNode = {}; + const instance: OffscreenInstance = { + isHidden: false, + pendingMarkers: null, + transitions: null, + }; + fiber.stateNode = instance; return fiber; } diff --git a/packages/react-reconciler/src/ReactFiber.old.js b/packages/react-reconciler/src/ReactFiber.old.js index 75fcba88bbd15..1dac6117dfd0e 100644 --- a/packages/react-reconciler/src/ReactFiber.old.js +++ b/packages/react-reconciler/src/ReactFiber.old.js @@ -736,7 +736,12 @@ export function createFiberFromLegacyHidden( fiber.lanes = lanes; // Adding a stateNode for legacy hidden because it's currently using // the offscreen implementation, which depends on a state node - fiber.stateNode = {}; + const instance: OffscreenInstance = { + isHidden: false, + pendingMarkers: null, + transitions: null, + }; + fiber.stateNode = instance; return fiber; }