Skip to content

Commit 4ebaeae

Browse files
authored
moved mutation code to passive (#24251)
This PR moves the code for transition tracing in the mutation phase that adds transitions to the pending callbacks object (to be called sometime later after paint) from the mutation to the passive phase. Things to think about: Passive effects can be flushed before or after paint. How do we make sure that we get the correct end time for the interaction?
1 parent 5b2e725 commit 4ebaeae

File tree

6 files changed

+176
-104
lines changed

6 files changed

+176
-104
lines changed

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

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2227,32 +2227,6 @@ function commitMutationEffectsOnFiber(
22272227
// because of the shared reconciliation logic below.
22282228
const flags = finishedWork.flags;
22292229

2230-
if (enableTransitionTracing) {
2231-
switch (finishedWork.tag) {
2232-
case HostRoot: {
2233-
const state = finishedWork.memoizedState;
2234-
const transitions = state.transitions;
2235-
if (transitions !== null) {
2236-
transitions.forEach(transition => {
2237-
// TODO(luna) Do we want to log TransitionStart in the startTransition callback instead?
2238-
addTransitionStartCallbackToPendingTransition({
2239-
transitionName: transition.name,
2240-
startTime: transition.startTime,
2241-
});
2242-
2243-
addTransitionCompleteCallbackToPendingTransition({
2244-
transitionName: transition.name,
2245-
startTime: transition.startTime,
2246-
});
2247-
});
2248-
2249-
clearTransitionsForLanes(root, lanes);
2250-
state.transitions = null;
2251-
}
2252-
}
2253-
}
2254-
}
2255-
22562230
if (flags & ContentReset) {
22572231
commitResetTextContent(finishedWork);
22582232
}
@@ -2639,34 +2613,41 @@ function reappearLayoutEffects_complete(subtreeRoot: Fiber) {
26392613
export function commitPassiveMountEffects(
26402614
root: FiberRoot,
26412615
finishedWork: Fiber,
2616+
committedLanes: Lanes,
26422617
): void {
26432618
nextEffect = finishedWork;
2644-
commitPassiveMountEffects_begin(finishedWork, root);
2619+
commitPassiveMountEffects_begin(finishedWork, root, committedLanes);
26452620
}
26462621

2647-
function commitPassiveMountEffects_begin(subtreeRoot: Fiber, root: FiberRoot) {
2622+
function commitPassiveMountEffects_begin(
2623+
subtreeRoot: Fiber,
2624+
root: FiberRoot,
2625+
committedLanes: Lanes,
2626+
) {
26482627
while (nextEffect !== null) {
26492628
const fiber = nextEffect;
26502629
const firstChild = fiber.child;
26512630
if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) {
26522631
ensureCorrectReturnPointer(firstChild, fiber);
26532632
nextEffect = firstChild;
26542633
} else {
2655-
commitPassiveMountEffects_complete(subtreeRoot, root);
2634+
commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes);
26562635
}
26572636
}
26582637
}
26592638

26602639
function commitPassiveMountEffects_complete(
26612640
subtreeRoot: Fiber,
26622641
root: FiberRoot,
2642+
committedLanes: Lanes,
26632643
) {
26642644
while (nextEffect !== null) {
26652645
const fiber = nextEffect;
2646+
26662647
if ((fiber.flags & Passive) !== NoFlags) {
26672648
setCurrentDebugFiberInDEV(fiber);
26682649
try {
2669-
commitPassiveMountOnFiber(root, fiber);
2650+
commitPassiveMountOnFiber(root, fiber, committedLanes);
26702651
} catch (error) {
26712652
reportUncaughtErrorInDEV(error);
26722653
captureCommitPhaseError(fiber, fiber.return, error);
@@ -2693,6 +2674,7 @@ function commitPassiveMountEffects_complete(
26932674
function commitPassiveMountOnFiber(
26942675
finishedRoot: FiberRoot,
26952676
finishedWork: Fiber,
2677+
committedLanes: Lanes,
26962678
): void {
26972679
switch (finishedWork.tag) {
26982680
case FunctionComponent:
@@ -2734,6 +2716,27 @@ function commitPassiveMountOnFiber(
27342716
}
27352717
}
27362718
}
2719+
2720+
if (enableTransitionTracing) {
2721+
const transitions = finishedWork.memoizedState.transitions;
2722+
if (transitions !== null) {
2723+
transitions.forEach(transition => {
2724+
// TODO(luna) Do we want to log TransitionStart in the startTransition callback instead?
2725+
addTransitionStartCallbackToPendingTransition({
2726+
transitionName: transition.name,
2727+
startTime: transition.startTime,
2728+
});
2729+
2730+
addTransitionCompleteCallbackToPendingTransition({
2731+
transitionName: transition.name,
2732+
startTime: transition.startTime,
2733+
});
2734+
});
2735+
2736+
clearTransitionsForLanes(finishedRoot, committedLanes);
2737+
finishedWork.memoizedState.transitions = null;
2738+
}
2739+
}
27372740
break;
27382741
}
27392742
case LegacyHiddenComponent:

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

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2227,32 +2227,6 @@ function commitMutationEffectsOnFiber(
22272227
// because of the shared reconciliation logic below.
22282228
const flags = finishedWork.flags;
22292229

2230-
if (enableTransitionTracing) {
2231-
switch (finishedWork.tag) {
2232-
case HostRoot: {
2233-
const state = finishedWork.memoizedState;
2234-
const transitions = state.transitions;
2235-
if (transitions !== null) {
2236-
transitions.forEach(transition => {
2237-
// TODO(luna) Do we want to log TransitionStart in the startTransition callback instead?
2238-
addTransitionStartCallbackToPendingTransition({
2239-
transitionName: transition.name,
2240-
startTime: transition.startTime,
2241-
});
2242-
2243-
addTransitionCompleteCallbackToPendingTransition({
2244-
transitionName: transition.name,
2245-
startTime: transition.startTime,
2246-
});
2247-
});
2248-
2249-
clearTransitionsForLanes(root, lanes);
2250-
state.transitions = null;
2251-
}
2252-
}
2253-
}
2254-
}
2255-
22562230
if (flags & ContentReset) {
22572231
commitResetTextContent(finishedWork);
22582232
}
@@ -2639,34 +2613,41 @@ function reappearLayoutEffects_complete(subtreeRoot: Fiber) {
26392613
export function commitPassiveMountEffects(
26402614
root: FiberRoot,
26412615
finishedWork: Fiber,
2616+
committedLanes: Lanes,
26422617
): void {
26432618
nextEffect = finishedWork;
2644-
commitPassiveMountEffects_begin(finishedWork, root);
2619+
commitPassiveMountEffects_begin(finishedWork, root, committedLanes);
26452620
}
26462621

2647-
function commitPassiveMountEffects_begin(subtreeRoot: Fiber, root: FiberRoot) {
2622+
function commitPassiveMountEffects_begin(
2623+
subtreeRoot: Fiber,
2624+
root: FiberRoot,
2625+
committedLanes: Lanes,
2626+
) {
26482627
while (nextEffect !== null) {
26492628
const fiber = nextEffect;
26502629
const firstChild = fiber.child;
26512630
if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) {
26522631
ensureCorrectReturnPointer(firstChild, fiber);
26532632
nextEffect = firstChild;
26542633
} else {
2655-
commitPassiveMountEffects_complete(subtreeRoot, root);
2634+
commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes);
26562635
}
26572636
}
26582637
}
26592638

26602639
function commitPassiveMountEffects_complete(
26612640
subtreeRoot: Fiber,
26622641
root: FiberRoot,
2642+
committedLanes: Lanes,
26632643
) {
26642644
while (nextEffect !== null) {
26652645
const fiber = nextEffect;
2646+
26662647
if ((fiber.flags & Passive) !== NoFlags) {
26672648
setCurrentDebugFiberInDEV(fiber);
26682649
try {
2669-
commitPassiveMountOnFiber(root, fiber);
2650+
commitPassiveMountOnFiber(root, fiber, committedLanes);
26702651
} catch (error) {
26712652
reportUncaughtErrorInDEV(error);
26722653
captureCommitPhaseError(fiber, fiber.return, error);
@@ -2693,6 +2674,7 @@ function commitPassiveMountEffects_complete(
26932674
function commitPassiveMountOnFiber(
26942675
finishedRoot: FiberRoot,
26952676
finishedWork: Fiber,
2677+
committedLanes: Lanes,
26962678
): void {
26972679
switch (finishedWork.tag) {
26982680
case FunctionComponent:
@@ -2734,6 +2716,27 @@ function commitPassiveMountOnFiber(
27342716
}
27352717
}
27362718
}
2719+
2720+
if (enableTransitionTracing) {
2721+
const transitions = finishedWork.memoizedState.transitions;
2722+
if (transitions !== null) {
2723+
transitions.forEach(transition => {
2724+
// TODO(luna) Do we want to log TransitionStart in the startTransition callback instead?
2725+
addTransitionStartCallbackToPendingTransition({
2726+
transitionName: transition.name,
2727+
startTime: transition.startTime,
2728+
});
2729+
2730+
addTransitionCompleteCallbackToPendingTransition({
2731+
transitionName: transition.name,
2732+
startTime: transition.startTime,
2733+
});
2734+
});
2735+
2736+
clearTransitionsForLanes(finishedRoot, committedLanes);
2737+
finishedWork.memoizedState.transitions = null;
2738+
}
2739+
}
27372740
break;
27382741
}
27392742
case LegacyHiddenComponent:

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ import {
153153
popRenderLanes,
154154
getRenderTargetTime,
155155
subtreeRenderLanes,
156+
getWorkInProgressTransitions,
156157
} from './ReactFiberWorkLoop.new';
157158
import {
158159
OffscreenLane,
@@ -862,6 +863,17 @@ function completeWork(
862863
}
863864
case HostRoot: {
864865
const fiberRoot = (workInProgress.stateNode: FiberRoot);
866+
867+
if (enableTransitionTracing) {
868+
const transitions = getWorkInProgressTransitions();
869+
// We set the Passive flag here because if there are new transitions,
870+
// we will need to schedule callbacks and process the transitions,
871+
// which we do in the passive phase
872+
if (transitions !== null) {
873+
workInProgress.flags |= Passive;
874+
}
875+
}
876+
865877
if (enableCache) {
866878
popRootTransition(fiberRoot, renderLanes);
867879

@@ -918,6 +930,14 @@ function completeWork(
918930
}
919931
updateHostContainer(current, workInProgress);
920932
bubbleProperties(workInProgress);
933+
if (enableTransitionTracing) {
934+
if ((workInProgress.subtreeFlags & Visibility) !== NoFlags) {
935+
// If any of our suspense children toggle visibility, this means that
936+
// the pending boundaries array needs to be updated, which we only
937+
// do in the passive phase.
938+
workInProgress.flags |= Passive;
939+
}
940+
}
921941
return null;
922942
}
923943
case HostComponent: {
@@ -1187,6 +1207,12 @@ function completeWork(
11871207
const offscreenFiber: Fiber = (workInProgress.child: any);
11881208
offscreenFiber.flags |= Visibility;
11891209

1210+
// If the suspended state of the boundary changes, we need to schedule
1211+
// a passive effect, which is when we process the transitions
1212+
if (enableTransitionTracing) {
1213+
offscreenFiber.flags |= Passive;
1214+
}
1215+
11901216
// TODO: This will still suspend a synchronous tree if anything
11911217
// in the concurrent tree already suspended during this render.
11921218
// This is a known bug.

packages/react-reconciler/src/ReactFiberCompleteWork.old.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ import {
153153
popRenderLanes,
154154
getRenderTargetTime,
155155
subtreeRenderLanes,
156+
getWorkInProgressTransitions,
156157
} from './ReactFiberWorkLoop.old';
157158
import {
158159
OffscreenLane,
@@ -862,6 +863,17 @@ function completeWork(
862863
}
863864
case HostRoot: {
864865
const fiberRoot = (workInProgress.stateNode: FiberRoot);
866+
867+
if (enableTransitionTracing) {
868+
const transitions = getWorkInProgressTransitions();
869+
// We set the Passive flag here because if there are new transitions,
870+
// we will need to schedule callbacks and process the transitions,
871+
// which we do in the passive phase
872+
if (transitions !== null) {
873+
workInProgress.flags |= Passive;
874+
}
875+
}
876+
865877
if (enableCache) {
866878
popRootTransition(fiberRoot, renderLanes);
867879

@@ -918,6 +930,14 @@ function completeWork(
918930
}
919931
updateHostContainer(current, workInProgress);
920932
bubbleProperties(workInProgress);
933+
if (enableTransitionTracing) {
934+
if ((workInProgress.subtreeFlags & Visibility) !== NoFlags) {
935+
// If any of our suspense children toggle visibility, this means that
936+
// the pending boundaries array needs to be updated, which we only
937+
// do in the passive phase.
938+
workInProgress.flags |= Passive;
939+
}
940+
}
921941
return null;
922942
}
923943
case HostComponent: {
@@ -1187,6 +1207,12 @@ function completeWork(
11871207
const offscreenFiber: Fiber = (workInProgress.child: any);
11881208
offscreenFiber.flags |= Visibility;
11891209

1210+
// If the suspended state of the boundary changes, we need to schedule
1211+
// a passive effect, which is when we process the transitions
1212+
if (enableTransitionTracing) {
1213+
offscreenFiber.flags |= Passive;
1214+
}
1215+
11901216
// TODO: This will still suspend a synchronous tree if anything
11911217
// in the concurrent tree already suspended during this render.
11921218
// This is a known bug.

0 commit comments

Comments
 (0)