Skip to content

Commit ede9170

Browse files
authored
Move passive logic out of layout phase (facebook#19500)
* setCurrentFiber per fiber, instead of per effect * Re-use safelyCallDestroy Part of the code in flushPassiveUnmountEffects is a duplicate of the code used for unmounting layout effects. I did some minor refactoring to so we could use the same function in both places. Closure will inline anyway so it doesn't affect code size or performance, just maintainability. * Don't check HookHasEffect during deletion We don't need to check HookHasEffect during a deletion; all effects are unmounted. So we also don't have to set HookHasEffect during a deletion, either. This allows us to remove the last remaining passive effect logic from the synchronous layout phase.
1 parent 22d16cc commit ede9170

File tree

2 files changed

+32
-57
lines changed

2 files changed

+32
-57
lines changed

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ import {
122122
NoEffect as NoHookEffect,
123123
HasEffect as HookHasEffect,
124124
Layout as HookLayout,
125-
Passive as HookPassive,
126125
} from './ReactHookEffectTags';
127126
import {didWarnAboutReassigningProps} from './ReactFiberBeginWork.new';
128127
import {
@@ -206,7 +205,7 @@ function safelyDetachRef(current: Fiber) {
206205
}
207206
}
208207

209-
function safelyCallDestroy(current, destroy) {
208+
export function safelyCallDestroy(current: Fiber, destroy: () => void) {
210209
if (__DEV__) {
211210
invokeGuardedCallback(null, destroy, null);
212211
if (hasCaughtError()) {
@@ -876,10 +875,7 @@ function commitUnmount(
876875
do {
877876
const {destroy, tag} = effect;
878877
if (destroy !== undefined) {
879-
if ((tag & HookPassive) !== NoHookEffect) {
880-
// TODO: Consider if we can move this block out of the synchronous commit phase
881-
effect.tag |= HookHasEffect;
882-
} else {
878+
if ((tag & HookLayout) !== NoHookEffect) {
883879
if (
884880
enableProfilerTimer &&
885881
enableProfilerCommitHooks &&

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

Lines changed: 30 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {Interaction} from 'scheduler/src/Tracing';
1515
import type {SuspenseConfig} from './ReactFiberSuspenseConfig';
1616
import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
1717
import type {Effect as HookEffect} from './ReactFiberHooks.new';
18+
import type {HookEffectTag} from './ReactHookEffectTags';
1819
import type {StackCursor} from './ReactFiberStack.new';
1920
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.new';
2021

@@ -209,6 +210,7 @@ import {
209210
commitPassiveEffectDurations,
210211
commitResetTextContent,
211212
isSuspenseBoundaryBeingHidden,
213+
safelyCallDestroy,
212214
} from './ReactFiberCommitWork.new';
213215
import {enqueueUpdate} from './ReactUpdateQueue.new';
214216
import {resetContextDependencies} from './ReactFiberNewContext.new';
@@ -2702,6 +2704,8 @@ function flushPassiveMountEffects(firstChild: Fiber): void {
27022704
}
27032705

27042706
function flushPassiveMountEffectsImpl(fiber: Fiber): void {
2707+
setCurrentDebugFiberInDEV(fiber);
2708+
27052709
const updateQueue: FunctionComponentUpdateQueue | null = (fiber.updateQueue: any);
27062710
const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
27072711
if (lastEffect !== null) {
@@ -2715,7 +2719,6 @@ function flushPassiveMountEffectsImpl(fiber: Fiber): void {
27152719
(tag & HookHasEffect) !== NoHookEffect
27162720
) {
27172721
if (__DEV__) {
2718-
setCurrentDebugFiberInDEV(fiber);
27192722
if (
27202723
enableProfilerTimer &&
27212724
enableProfilerCommitHooks &&
@@ -2742,7 +2745,6 @@ function flushPassiveMountEffectsImpl(fiber: Fiber): void {
27422745
const error = clearCaughtError();
27432746
captureCommitPhaseError(fiber, error);
27442747
}
2745-
resetCurrentDebugFiberInDEV();
27462748
} else {
27472749
try {
27482750
const create = effect.create;
@@ -2769,6 +2771,8 @@ function flushPassiveMountEffectsImpl(fiber: Fiber): void {
27692771

27702772
effect = next;
27712773
} while (effect !== firstEffect);
2774+
2775+
resetCurrentDebugFiberInDEV();
27722776
}
27732777
}
27742778

@@ -2813,7 +2817,7 @@ function flushPassiveUnmountEffects(firstChild: Fiber): void {
28132817
case Block: {
28142818
const primaryEffectTag = fiber.effectTag & Passive;
28152819
if (primaryEffectTag !== NoEffect) {
2816-
flushPassiveUnmountEffectsImpl(fiber);
2820+
flushPassiveUnmountEffectsImpl(fiber, HookPassive | HookHasEffect);
28172821
}
28182822
}
28192823
}
@@ -2845,7 +2849,7 @@ function flushPassiveUnmountEffectsInsideOfDeletedTree(
28452849
case ForwardRef:
28462850
case SimpleMemoComponent:
28472851
case Block: {
2848-
flushPassiveUnmountEffectsImpl(fiber);
2852+
flushPassiveUnmountEffectsImpl(fiber, HookPassive);
28492853
}
28502854
}
28512855
}
@@ -2854,67 +2858,42 @@ function flushPassiveUnmountEffectsInsideOfDeletedTree(
28542858
}
28552859
}
28562860

2857-
function flushPassiveUnmountEffectsImpl(fiber: Fiber): void {
2861+
function flushPassiveUnmountEffectsImpl(
2862+
fiber: Fiber,
2863+
// Tags to check for when deciding whether to unmount. e.g. to skip over
2864+
// layout effects
2865+
hookEffectTag: HookEffectTag,
2866+
): void {
28582867
const updateQueue: FunctionComponentUpdateQueue | null = (fiber.updateQueue: any);
28592868
const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
28602869
if (lastEffect !== null) {
2870+
setCurrentDebugFiberInDEV(fiber);
2871+
28612872
const firstEffect = lastEffect.next;
28622873
let effect = firstEffect;
28632874
do {
28642875
const {next, tag} = effect;
2865-
if (
2866-
(tag & HookPassive) !== NoHookEffect &&
2867-
(tag & HookHasEffect) !== NoHookEffect
2868-
) {
2876+
if ((tag & hookEffectTag) === hookEffectTag) {
28692877
const destroy = effect.destroy;
2870-
effect.destroy = undefined;
2871-
2872-
if (typeof destroy === 'function') {
2873-
if (__DEV__) {
2874-
setCurrentDebugFiberInDEV(fiber);
2875-
if (
2876-
enableProfilerTimer &&
2877-
enableProfilerCommitHooks &&
2878-
fiber.mode & ProfileMode
2879-
) {
2880-
startPassiveEffectTimer();
2881-
invokeGuardedCallback(null, destroy, null);
2882-
recordPassiveEffectDuration(fiber);
2883-
} else {
2884-
invokeGuardedCallback(null, destroy, null);
2885-
}
2886-
if (hasCaughtError()) {
2887-
invariant(fiber !== null, 'Should be working on an effect.');
2888-
const error = clearCaughtError();
2889-
captureCommitPhaseError(fiber, error);
2890-
}
2891-
resetCurrentDebugFiberInDEV();
2878+
if (destroy !== undefined) {
2879+
effect.destroy = undefined;
2880+
if (
2881+
enableProfilerTimer &&
2882+
enableProfilerCommitHooks &&
2883+
fiber.mode & ProfileMode
2884+
) {
2885+
startPassiveEffectTimer();
2886+
safelyCallDestroy(fiber, destroy);
2887+
recordPassiveEffectDuration(fiber);
28922888
} else {
2893-
try {
2894-
if (
2895-
enableProfilerTimer &&
2896-
enableProfilerCommitHooks &&
2897-
fiber.mode & ProfileMode
2898-
) {
2899-
try {
2900-
startPassiveEffectTimer();
2901-
destroy();
2902-
} finally {
2903-
recordPassiveEffectDuration(fiber);
2904-
}
2905-
} else {
2906-
destroy();
2907-
}
2908-
} catch (error) {
2909-
invariant(fiber !== null, 'Should be working on an effect.');
2910-
captureCommitPhaseError(fiber, error);
2911-
}
2889+
safelyCallDestroy(fiber, destroy);
29122890
}
29132891
}
29142892
}
2915-
29162893
effect = next;
29172894
} while (effect !== firstEffect);
2895+
2896+
resetCurrentDebugFiberInDEV();
29182897
}
29192898
}
29202899

0 commit comments

Comments
 (0)