Skip to content

Commit

Permalink
Remove Passive flag from "before mutation" phase (facebook#20038)
Browse files Browse the repository at this point in the history
We don't need to visit passive effect nodes during before mutation.

The only reason we were previously was to schedule the root-level
passive effect callback as early as possible, but now that
`subtreeFlags` exists, we can check that instead.

This should reduce the amount of traversal during the commit phase,
particularly when mounting or updating large trees that contain many
passive effects.
  • Loading branch information
acdlite authored and koto committed Jun 15, 2021
1 parent 18d8fc9 commit 4b7e57a
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 27 deletions.
5 changes: 4 additions & 1 deletion packages/react-reconciler/src/ReactFiberFlags.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ export const ForceUpdateForLegacySuspense = /* */ 0b000100000000000000;
export const PassiveStatic = /* */ 0b001000000000000000;

// Union of side effect groupings as pertains to subtreeFlags
export const BeforeMutationMask = /* */ 0b000000001100001010;
// TODO: Don't need to visit Placement during BeforeMutation phase
// TODO: Only need to visit Deletions during BeforeMutation phase if an element
// is focused.
export const BeforeMutationMask = /* */ 0b000000000100001010;
export const MutationMask = /* */ 0b000000010010011110;
export const LayoutMask = /* */ 0b000000000010100100;
export const PassiveMask = /* */ 0b000000001000001000;
Expand Down
40 changes: 14 additions & 26 deletions packages/react-reconciler/src/ReactFiberWorkLoop.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -1880,6 +1880,20 @@ function commitRootImpl(root, renderPriorityLevel) {
NoFlags;

if (subtreeHasEffects || rootHasEffect) {
// If there are pending passive effects, schedule a callback to process them.
if (
(finishedWork.subtreeFlags & PassiveMask) !== NoFlags ||
(finishedWork.flags & PassiveMask) !== NoFlags
) {
if (!rootDoesHavePassiveEffects) {
rootDoesHavePassiveEffects = true;
scheduleCallback(NormalSchedulerPriority, () => {
flushPassiveEffects();
return null;
});
}
}

let previousLanePriority;
if (decoupleUpdatePriorityFromScheduler) {
previousLanePriority = getCurrentUpdateLanePriority();
Expand Down Expand Up @@ -1972,20 +1986,6 @@ function commitRootImpl(root, renderPriorityLevel) {
markLayoutEffectsStopped();
}

// If there are pending passive effects, schedule a callback to process them.
if (
(finishedWork.subtreeFlags & PassiveMask) !== NoFlags ||
(finishedWork.flags & PassiveMask) !== NoFlags
) {
if (!rootDoesHavePassiveEffects) {
rootDoesHavePassiveEffects = true;
scheduleCallback(NormalSchedulerPriority, () => {
flushPassiveEffects();
return null;
});
}
}

// Tell Scheduler to yield at the end of the frame, so the browser has an
// opportunity to paint.
requestPaint();
Expand Down Expand Up @@ -2181,18 +2181,6 @@ function commitBeforeMutationEffectsImpl(fiber: Fiber) {
commitBeforeMutationEffectOnFiber(current, fiber);
resetCurrentDebugFiberInDEV();
}

if ((flags & Passive) !== NoFlags) {
// If there are passive effects, schedule a callback to flush at
// the earliest opportunity.
if (!rootDoesHavePassiveEffects) {
rootDoesHavePassiveEffects = true;
scheduleCallback(NormalSchedulerPriority, () => {
flushPassiveEffects();
return null;
});
}
}
}

function commitBeforeMutationEffectsDeletions(deletions: Array<Fiber>) {
Expand Down

0 comments on commit 4b7e57a

Please sign in to comment.