Skip to content

Commit

Permalink
add pendingPassiveTransitions (#24320)
Browse files Browse the repository at this point in the history
Add pendingPassiveTransitions work loop module level variable. Because workInProgressTransitions might change before we process it in the passive effects, we introduce a new variable, pendingPassiveTransitions, where we store the transitions until we can actually process them in the commit phase.
  • Loading branch information
lunaruan authored Apr 8, 2022
1 parent 60e63b9 commit b0f13e5
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 26 deletions.
26 changes: 23 additions & 3 deletions packages/react-reconciler/src/ReactFiberCommitWork.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {OffscreenState} from './ReactFiberOffscreenComponent';
import type {HookFlags} from './ReactHookEffectTags';
import type {Cache} from './ReactFiberCacheComponent.new';
import type {RootState} from './ReactFiberRoot.new';
import type {Transition} from './ReactFiberTracingMarkerComponent.new';

import {
enableCreateEventHandleAPI,
Expand Down Expand Up @@ -2602,15 +2603,22 @@ export function commitPassiveMountEffects(
root: FiberRoot,
finishedWork: Fiber,
committedLanes: Lanes,
committedTransitions: Array<Transition> | null,
): void {
nextEffect = finishedWork;
commitPassiveMountEffects_begin(finishedWork, root, committedLanes);
commitPassiveMountEffects_begin(
finishedWork,
root,
committedLanes,
committedTransitions,
);
}

function commitPassiveMountEffects_begin(
subtreeRoot: Fiber,
root: FiberRoot,
committedLanes: Lanes,
committedTransitions: Array<Transition> | null,
) {
while (nextEffect !== null) {
const fiber = nextEffect;
Expand All @@ -2619,7 +2627,12 @@ function commitPassiveMountEffects_begin(
firstChild.return = fiber;
nextEffect = firstChild;
} else {
commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes);
commitPassiveMountEffects_complete(
subtreeRoot,
root,
committedLanes,
committedTransitions,
);
}
}
}
Expand All @@ -2628,14 +2641,20 @@ function commitPassiveMountEffects_complete(
subtreeRoot: Fiber,
root: FiberRoot,
committedLanes: Lanes,
committedTransitions: Array<Transition> | null,
) {
while (nextEffect !== null) {
const fiber = nextEffect;

if ((fiber.flags & Passive) !== NoFlags) {
setCurrentDebugFiberInDEV(fiber);
try {
commitPassiveMountOnFiber(root, fiber, committedLanes);
commitPassiveMountOnFiber(
root,
fiber,
committedLanes,
committedTransitions,
);
} catch (error) {
captureCommitPhaseError(fiber, fiber.return, error);
}
Expand All @@ -2662,6 +2681,7 @@ function commitPassiveMountOnFiber(
finishedRoot: FiberRoot,
finishedWork: Fiber,
committedLanes: Lanes,
committedTransitions: Array<Transition> | null,
): void {
switch (finishedWork.tag) {
case FunctionComponent:
Expand Down
26 changes: 23 additions & 3 deletions packages/react-reconciler/src/ReactFiberCommitWork.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {OffscreenState} from './ReactFiberOffscreenComponent';
import type {HookFlags} from './ReactHookEffectTags';
import type {Cache} from './ReactFiberCacheComponent.old';
import type {RootState} from './ReactFiberRoot.old';
import type {Transition} from './ReactFiberTracingMarkerComponent.old';

import {
enableCreateEventHandleAPI,
Expand Down Expand Up @@ -2602,15 +2603,22 @@ export function commitPassiveMountEffects(
root: FiberRoot,
finishedWork: Fiber,
committedLanes: Lanes,
committedTransitions: Array<Transition> | null,
): void {
nextEffect = finishedWork;
commitPassiveMountEffects_begin(finishedWork, root, committedLanes);
commitPassiveMountEffects_begin(
finishedWork,
root,
committedLanes,
committedTransitions,
);
}

function commitPassiveMountEffects_begin(
subtreeRoot: Fiber,
root: FiberRoot,
committedLanes: Lanes,
committedTransitions: Array<Transition> | null,
) {
while (nextEffect !== null) {
const fiber = nextEffect;
Expand All @@ -2619,7 +2627,12 @@ function commitPassiveMountEffects_begin(
firstChild.return = fiber;
nextEffect = firstChild;
} else {
commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes);
commitPassiveMountEffects_complete(
subtreeRoot,
root,
committedLanes,
committedTransitions,
);
}
}
}
Expand All @@ -2628,14 +2641,20 @@ function commitPassiveMountEffects_complete(
subtreeRoot: Fiber,
root: FiberRoot,
committedLanes: Lanes,
committedTransitions: Array<Transition> | null,
) {
while (nextEffect !== null) {
const fiber = nextEffect;

if ((fiber.flags & Passive) !== NoFlags) {
setCurrentDebugFiberInDEV(fiber);
try {
commitPassiveMountOnFiber(root, fiber, committedLanes);
commitPassiveMountOnFiber(
root,
fiber,
committedLanes,
committedTransitions,
);
} catch (error) {
captureCommitPhaseError(fiber, fiber.return, error);
}
Expand All @@ -2662,6 +2681,7 @@ function commitPassiveMountOnFiber(
finishedRoot: FiberRoot,
finishedWork: Fiber,
committedLanes: Lanes,
committedTransitions: Array<Transition> | null,
): void {
switch (finishedWork.tag) {
case FunctionComponent:
Expand Down
72 changes: 62 additions & 10 deletions packages/react-reconciler/src/ReactFiberWorkLoop.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ let rootWithPendingPassiveEffects: FiberRoot | null = null;
let pendingPassiveEffectsLanes: Lanes = NoLanes;
let pendingPassiveProfilerEffects: Array<Fiber> = [];
let pendingPassiveEffectsRemainingLanes: Lanes = NoLanes;
let pendingPassiveTransitions: Array<Transition> | null = null;

// Use these to prevent an infinite loop of nested updates
const NESTED_UPDATE_LIMIT = 50;
Expand Down Expand Up @@ -1075,7 +1076,11 @@ function finishConcurrentRender(root, exitStatus, lanes) {
case RootErrored: {
// We should have already attempted to retry this tree. If we reached
// this point, it errored again. Commit it.
commitRoot(root, workInProgressRootRecoverableErrors);
commitRoot(
root,
workInProgressRootRecoverableErrors,
workInProgressTransitions,
);
break;
}
case RootSuspended: {
Expand Down Expand Up @@ -1115,14 +1120,23 @@ function finishConcurrentRender(root, exitStatus, lanes) {
// lower priority work to do. Instead of committing the fallback
// immediately, wait for more data to arrive.
root.timeoutHandle = scheduleTimeout(
commitRoot.bind(null, root, workInProgressRootRecoverableErrors),
commitRoot.bind(
null,
root,
workInProgressRootRecoverableErrors,
workInProgressTransitions,
),
msUntilTimeout,
);
break;
}
}
// The work expired. Commit immediately.
commitRoot(root, workInProgressRootRecoverableErrors);
commitRoot(
root,
workInProgressRootRecoverableErrors,
workInProgressTransitions,
);
break;
}
case RootSuspendedWithDelay: {
Expand Down Expand Up @@ -1153,20 +1167,33 @@ function finishConcurrentRender(root, exitStatus, lanes) {
// Instead of committing the fallback immediately, wait for more data
// to arrive.
root.timeoutHandle = scheduleTimeout(
commitRoot.bind(null, root, workInProgressRootRecoverableErrors),
commitRoot.bind(
null,
root,
workInProgressRootRecoverableErrors,
workInProgressTransitions,
),
msUntilTimeout,
);
break;
}
}

// Commit the placeholder.
commitRoot(root, workInProgressRootRecoverableErrors);
commitRoot(
root,
workInProgressRootRecoverableErrors,
workInProgressTransitions,
);
break;
}
case RootCompleted: {
// The work completed. Ready to commit.
commitRoot(root, workInProgressRootRecoverableErrors);
commitRoot(
root,
workInProgressRootRecoverableErrors,
workInProgressTransitions,
);
break;
}
default: {
Expand Down Expand Up @@ -1290,7 +1317,11 @@ function performSyncWorkOnRoot(root) {
const finishedWork: Fiber = (root.current.alternate: any);
root.finishedWork = finishedWork;
root.finishedLanes = lanes;
commitRoot(root, workInProgressRootRecoverableErrors);
commitRoot(
root,
workInProgressRootRecoverableErrors,
workInProgressTransitions,
);

// Before exiting, make sure there's a callback scheduled for the next
// pending level.
Expand Down Expand Up @@ -1972,7 +2003,11 @@ function completeUnitOfWork(unitOfWork: Fiber): void {
}
}

function commitRoot(root: FiberRoot, recoverableErrors: null | Array<mixed>) {
function commitRoot(
root: FiberRoot,
recoverableErrors: null | Array<mixed>,
transitions: Array<Transition> | null,
) {
// TODO: This no longer makes any sense. We already wrap the mutation and
// layout phases. Should be able to remove.
const previousUpdateLanePriority = getCurrentUpdatePriority();
Expand All @@ -1981,7 +2016,12 @@ function commitRoot(root: FiberRoot, recoverableErrors: null | Array<mixed>) {
try {
ReactCurrentBatchConfig.transition = null;
setCurrentUpdatePriority(DiscreteEventPriority);
commitRootImpl(root, recoverableErrors, previousUpdateLanePriority);
commitRootImpl(
root,
recoverableErrors,
transitions,
previousUpdateLanePriority,
);
} finally {
ReactCurrentBatchConfig.transition = prevTransition;
setCurrentUpdatePriority(previousUpdateLanePriority);
Expand All @@ -1993,6 +2033,7 @@ function commitRoot(root: FiberRoot, recoverableErrors: null | Array<mixed>) {
function commitRootImpl(
root: FiberRoot,
recoverableErrors: null | Array<mixed>,
transitions: Array<Transition> | null,
renderPriorityLevel: EventPriority,
) {
do {
Expand Down Expand Up @@ -2088,6 +2129,13 @@ function commitRootImpl(
if (!rootDoesHavePassiveEffects) {
rootDoesHavePassiveEffects = true;
pendingPassiveEffectsRemainingLanes = remainingLanes;
// workInProgressTransitions might be overwritten, so we want
// to store it in pendingPassiveTransitions until they get processed
// We need to pass this through as an argument to commitRoot
// because workInProgressTransitions might have changed between
// the previous render and commit if we throttle the commit
// with setTimeout
pendingPassiveTransitions = transitions;
scheduleCallback(NormalSchedulerPriority, () => {
flushPassiveEffects();
// This render triggered passive effects: release the root cache pool
Expand Down Expand Up @@ -2408,6 +2456,10 @@ function flushPassiveEffectsImpl() {
return false;
}

// Cache and clear the transitions flag
const transitions = pendingPassiveTransitions;
pendingPassiveTransitions = null;

const root = rootWithPendingPassiveEffects;
const lanes = pendingPassiveEffectsLanes;
rootWithPendingPassiveEffects = null;
Expand Down Expand Up @@ -2437,7 +2489,7 @@ function flushPassiveEffectsImpl() {
executionContext |= CommitContext;

commitPassiveUnmountEffects(root.current);
commitPassiveMountEffects(root, root.current, lanes);
commitPassiveMountEffects(root, root.current, lanes, transitions);

// TODO: Move to commitPassiveMountEffects
if (enableProfilerTimer && enableProfilerCommitHooks) {
Expand Down
Loading

0 comments on commit b0f13e5

Please sign in to comment.