Skip to content

Commit 39eb6c8

Browse files
committed
commit work
1 parent f7cf077 commit 39eb6c8

File tree

1 file changed

+157
-12
lines changed

1 file changed

+157
-12
lines changed

packages/react-reconciler/src/ReactFiberCommitWork.new.js

Lines changed: 157 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,17 @@ import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
2222
import type {UpdateQueue} from './ReactUpdateQueue.new';
2323
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.new';
2424
import type {Wakeable} from 'shared/ReactTypes';
25-
import type {OffscreenState} from './ReactFiberOffscreenComponent';
25+
import type {
26+
OffscreenState,
27+
OffscreenInstance,
28+
} from './ReactFiberOffscreenComponent';
2629
import type {HookFlags} from './ReactHookEffectTags';
2730
import type {Cache} from './ReactFiberCacheComponent.new';
2831
import type {RootState} from './ReactFiberRoot.new';
29-
import type {Transition} from './ReactFiberTracingMarkerComponent.new';
32+
import type {
33+
Transition,
34+
PendingSuspenseBoundaries,
35+
} from './ReactFiberTracingMarkerComponent.new';
3036

3137
import {
3238
enableCreateEventHandleAPI,
@@ -63,6 +69,7 @@ import {
6369
OffscreenComponent,
6470
LegacyHiddenComponent,
6571
CacheComponent,
72+
TracingMarkerComponent,
6673
} from './ReactWorkTags';
6774
import {detachDeletedInstance} from './ReactFiberHostConfig';
6875
import {
@@ -1002,7 +1009,8 @@ function commitLayoutEffectOnFiber(
10021009
case IncompleteClassComponent:
10031010
case ScopeComponent:
10041011
case OffscreenComponent:
1005-
case LegacyHiddenComponent: {
1012+
case LegacyHiddenComponent:
1013+
case TracingMarkerComponent: {
10061014
break;
10071015
}
10081016

@@ -1067,6 +1075,77 @@ function reappearLayoutEffectsOnFiber(node: Fiber) {
10671075
}
10681076
}
10691077

1078+
function commitTransitionProgress(
1079+
finishedRoot: FiberRoot,
1080+
offscreenFiber: Fiber,
1081+
) {
1082+
// This function adds suspense boundaries to the root
1083+
// or tracing marker's pendingSuspenseBoundaries map.
1084+
// When a suspense boundary goes from a resolved to a fallback
1085+
// state we add the boundary to the map, and when it goes from
1086+
// a fallback to a resolved state, we remove the boundary from
1087+
// the map.
1088+
1089+
// We use stateNode on the Offscreen component as a stable object
1090+
// that doesnt change from render to render. This way we can
1091+
// distinguish between different Offscreen instances (vs. the same
1092+
// Offscreen instance with different fibers)
1093+
const offscreenInstance: OffscreenInstance = offscreenFiber.stateNode;
1094+
1095+
let prevState: SuspenseState | null = null;
1096+
const previousFiber = offscreenFiber.alternate;
1097+
if (previousFiber !== null && previousFiber.memoizedState !== null) {
1098+
prevState = previousFiber.memoizedState;
1099+
}
1100+
const nextState: SuspenseState | null = offscreenFiber.memoizedState;
1101+
1102+
const wasHidden = prevState !== null;
1103+
const isHidden = nextState !== null;
1104+
1105+
const rootState: RootState = finishedRoot.current.memoizedState;
1106+
// TODO(luna) move pendingSuspenseBoundaries and transitions from
1107+
// HostRoot fiber to FiberRoot
1108+
const rootPendingBoundaries = rootState.pendingSuspenseBoundaries;
1109+
1110+
// If there is a name on the suspense boundary, store that in
1111+
// the pending boundaries.
1112+
let name = null;
1113+
const parent = offscreenFiber.return;
1114+
if (
1115+
parent !== null &&
1116+
parent.tag === SuspenseComponent &&
1117+
parent.memoizedProps.unstable_name
1118+
) {
1119+
name = parent.memoizedProps.unstable_name;
1120+
}
1121+
1122+
if (rootPendingBoundaries !== null) {
1123+
if (previousFiber === null) {
1124+
// Initial mount
1125+
if (isHidden) {
1126+
rootPendingBoundaries.set(offscreenInstance, {
1127+
name,
1128+
});
1129+
}
1130+
} else {
1131+
if (wasHidden && !isHidden) {
1132+
// The suspense boundary went from hidden to visible. Remove
1133+
// the boundary from the pending suspense boundaries set
1134+
// if it's there
1135+
if (rootPendingBoundaries.has(offscreenInstance)) {
1136+
rootPendingBoundaries.delete(offscreenInstance);
1137+
}
1138+
} else if (!wasHidden && isHidden) {
1139+
// The suspense boundaries was just hidden. Add the boundary
1140+
// to the pending boundary set if it's there
1141+
rootPendingBoundaries.set(offscreenInstance, {
1142+
name,
1143+
});
1144+
}
1145+
}
1146+
}
1147+
}
1148+
10701149
function hideOrUnhideAllChildren(finishedWork, isHidden) {
10711150
// Only hide or unhide the top-most host nodes.
10721151
let hostSubtreeRoot = null;
@@ -2730,22 +2809,53 @@ function commitPassiveMountOnFiber(
27302809
}
27312810

27322811
if (enableTransitionTracing) {
2733-
if (committedTransitions !== null) {
2812+
// Get the transitions that were initiatized during the render
2813+
// and add a start transition callback for each of them
2814+
const state = finishedWork.memoizedState;
2815+
if (state.transitions === null) {
2816+
state.transitions = new Set([]);
2817+
}
2818+
const pendingTransitions = state.transitions;
2819+
2820+
if (committedTransitions != null) {
27342821
committedTransitions.forEach(transition => {
2735-
// TODO(luna) Do we want to log TransitionStart in the startTransition callback instead?
27362822
addTransitionStartCallbackToPendingTransition({
27372823
transitionName: transition.name,
27382824
startTime: transition.startTime,
27392825
});
2740-
2741-
addTransitionCompleteCallbackToPendingTransition({
2742-
transitionName: transition.name,
2743-
startTime: transition.startTime,
2744-
});
2826+
pendingTransitions.add(transition);
27452827
});
27462828

27472829
clearTransitionsForLanes(finishedRoot, committedLanes);
2748-
finishedWork.memoizedState.transitions = null;
2830+
}
2831+
2832+
const pendingSuspenseBoundaries = state.pendingSuspenseBoundaries;
2833+
const processedTransitions = new Set();
2834+
// process the lazy transitions list by filtering duplicate transitions
2835+
// and calling the transition complete callback on all transitions
2836+
// if there are no more pending suspense boundaries
2837+
pendingTransitions.forEach(transition => {
2838+
if (!processedTransitions.has(transition)) {
2839+
if (
2840+
pendingSuspenseBoundaries === null ||
2841+
pendingSuspenseBoundaries.size === 0
2842+
) {
2843+
addTransitionCompleteCallbackToPendingTransition({
2844+
transitionName: transition.name,
2845+
startTime: transition.startTime,
2846+
});
2847+
}
2848+
processedTransitions.add(transition);
2849+
}
2850+
});
2851+
2852+
// If there are no more pending suspense boundaries we
2853+
// clear the transitions because they are all complete.
2854+
if (
2855+
pendingSuspenseBoundaries === null ||
2856+
pendingSuspenseBoundaries.size === 0
2857+
) {
2858+
state.transitions = null;
27492859
}
27502860
}
27512861
break;
@@ -2783,9 +2893,44 @@ function commitPassiveMountOnFiber(
27832893
}
27842894

27852895
if (enableTransitionTracing) {
2786-
// TODO: Add code to actually process the update queue
2896+
const isFallback = finishedWork.memoizedState;
2897+
const queue = (finishedWork.updateQueue: any);
2898+
const rootMemoizedState = finishedRoot.current.memoizedState;
2899+
2900+
if (queue !== null) {
2901+
// We have one instance of the pendingSuspenseBoundaries map.
2902+
// We only need one because we update it during the commit phase.
2903+
// We instantiate a new Map if we haven't already
2904+
if (rootMemoizedState.pendingSuspenseBoundaries === null) {
2905+
rootMemoizedState.pendingSuspenseBoundaries = new Map();
2906+
}
2907+
2908+
if (isFallback) {
2909+
const transitions = queue.transitions;
2910+
let prevTransitions = finishedWork.memoizedState.transitions;
2911+
// Add all the transitions saved in the update queue during
2912+
// the render phase (ie the transitions associated with this boundary)
2913+
// into the transitions set.
2914+
if (transitions != null) {
2915+
if (prevTransitions === null) {
2916+
// We only have one instance of the transitions set
2917+
// because we update it only during the commit phase. We
2918+
// will create the set on a as needed basis in the commit phase
2919+
finishedWork.memoizedState.transitions = prevTransitions = new Set();
2920+
}
2921+
2922+
transitions.forEach(transition => {
2923+
prevTransitions.add(transition);
2924+
});
2925+
}
2926+
}
2927+
}
2928+
2929+
commitTransitionProgress(finishedRoot, finishedWork);
2930+
27872931
finishedWork.updateQueue = null;
27882932
}
2933+
27892934
break;
27902935
}
27912936
case CacheComponent: {

0 commit comments

Comments
 (0)