From 224608b8773f05934c63be54d8c7f926c65dfbfa Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 20 Jun 2022 20:29:47 -0400 Subject: [PATCH 1/6] 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 9f60e0ab227e9..1acc313515f3a 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -259,8 +259,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); @@ -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.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 f6a54052f92d5..bb238e1766dda 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); @@ -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/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 03788ff2c9437..6a2e4428c8828 100644 --- a/packages/react-reconciler/src/ReactFiberUnwindWork.new.js +++ b/packages/react-reconciler/src/ReactFiberUnwindWork.new.js @@ -49,7 +49,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, @@ -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 5c32cb2dcd4e48a13f40047e8b0ce06567c56d43 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 20 Jun 2022 20:38:32 -0400 Subject: [PATCH 2/6] 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 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: From 08cfe085dfc35c67cb17c5781e9526767feeb9bf Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 27 Jun 2022 13:22:04 -0400 Subject: [PATCH 3/6] 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 1acc313515f3a..250617b6ea7e9 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); @@ -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.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 344e849bf969b75e91976962bb2de3de33d6d960 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 27 Jun 2022 13:22:55 -0400 Subject: [PATCH 4/6] 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 1cc464be4850d9fe25ea0c3d0c8569efd6c5d027 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 28 Jun 2022 14:31:58 -0400 Subject: [PATCH 5/6] 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 250617b6ea7e9..b244b1d0e011a 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, @@ -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.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 bb238e1766dda..3f357a3e7ddcf 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js @@ -29,6 +29,7 @@ import type { } from './ReactFiberSuspenseComponent.new'; import type {SuspenseContext} from './ReactFiberSuspenseContext.new'; import type {OffscreenState} from './ReactFiberOffscreenComponent'; +import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.new'; import type {Cache} from './ReactFiberCacheComponent.new'; import { enableSuspenseAvoidThisFallback, @@ -1589,7 +1590,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 6a2e4428c8828..85a12419d78e9 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 { @@ -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); } } diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index abf8a98e99ff3..707b6b6655d86 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 527baa8447e47738a2709b28e8b429f8e5396926 Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 29 Jun 2022 13:29:45 -0400 Subject: [PATCH 6/6] 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 fb11d7cd720a4..7d3366cd4bb96 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, @@ -1589,7 +1590,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 de2a9bd2cf805..3ced1a24e027d 100644 --- a/packages/react-reconciler/src/ReactFiberRoot.old.js +++ b/packages/react-reconciler/src/ReactFiberRoot.old.js @@ -90,13 +90,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); } }