mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Move commit passive unmount/mount to CommitWork (#19599)
This commit is contained in:
@@ -20,10 +20,14 @@ import type {FiberRoot} from './ReactInternalTypes';
|
||||
import type {Lanes} from './ReactFiberLane';
|
||||
import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
|
||||
import type {UpdateQueue} from './ReactUpdateQueue.new';
|
||||
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.new';
|
||||
import type {
|
||||
Effect as HookEffect,
|
||||
FunctionComponentUpdateQueue,
|
||||
} from './ReactFiberHooks.new';
|
||||
import type {Wakeable} from 'shared/ReactTypes';
|
||||
import type {ReactPriorityLevel} from './ReactInternalTypes';
|
||||
import type {OffscreenState} from './ReactFiberOffscreenComponent';
|
||||
import type {HookEffectTag} from './ReactHookEffectTags';
|
||||
|
||||
import {unstable_wrap as Schedule_tracing_wrap} from 'scheduler/tracing';
|
||||
import {
|
||||
@@ -77,6 +81,8 @@ import {
|
||||
getCommitTime,
|
||||
recordLayoutEffectDuration,
|
||||
startLayoutEffectTimer,
|
||||
recordPassiveEffectDuration,
|
||||
startPassiveEffectTimer,
|
||||
} from './ReactProfilerTimer.new';
|
||||
import {ProfileMode} from './ReactTypeOfMode';
|
||||
import {commitUpdateQueue} from './ReactUpdateQueue.new';
|
||||
@@ -121,6 +127,7 @@ import {
|
||||
NoEffect as NoHookEffect,
|
||||
HasEffect as HookHasEffect,
|
||||
Layout as HookLayout,
|
||||
Passive as HookPassive,
|
||||
} from './ReactHookEffectTags';
|
||||
import {didWarnAboutReassigningProps} from './ReactFiberBeginWork.new';
|
||||
import {
|
||||
@@ -308,7 +315,7 @@ function commitBeforeMutationLifeCycles(
|
||||
);
|
||||
}
|
||||
|
||||
function commitHookEffectListUnmount(tag: number, finishedWork: Fiber) {
|
||||
function commitHookEffectListUnmount(tag: HookEffectTag, finishedWork: Fiber) {
|
||||
const updateQueue: FunctionComponentUpdateQueue | null = (finishedWork.updateQueue: any);
|
||||
const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
|
||||
if (lastEffect !== null) {
|
||||
@@ -328,7 +335,43 @@ function commitHookEffectListUnmount(tag: number, finishedWork: Fiber) {
|
||||
}
|
||||
}
|
||||
|
||||
function commitHookEffectListMount(tag: number, finishedWork: Fiber) {
|
||||
// TODO: Remove this duplication.
|
||||
function commitHookEffectListUnmount2(
|
||||
// Tags to check for when deciding whether to unmount. e.g. to skip over
|
||||
// layout effects
|
||||
hookEffectTag: HookEffectTag,
|
||||
fiber: Fiber,
|
||||
): void {
|
||||
const updateQueue: FunctionComponentUpdateQueue | null = (fiber.updateQueue: any);
|
||||
const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
|
||||
if (lastEffect !== null) {
|
||||
const firstEffect = lastEffect.next;
|
||||
let effect = firstEffect;
|
||||
do {
|
||||
const {next, tag} = effect;
|
||||
if ((tag & hookEffectTag) === hookEffectTag) {
|
||||
const destroy = effect.destroy;
|
||||
if (destroy !== undefined) {
|
||||
effect.destroy = undefined;
|
||||
if (
|
||||
enableProfilerTimer &&
|
||||
enableProfilerCommitHooks &&
|
||||
fiber.mode & ProfileMode
|
||||
) {
|
||||
startPassiveEffectTimer();
|
||||
safelyCallDestroy(fiber, destroy);
|
||||
recordPassiveEffectDuration(fiber);
|
||||
} else {
|
||||
safelyCallDestroy(fiber, destroy);
|
||||
}
|
||||
}
|
||||
}
|
||||
effect = next;
|
||||
} while (effect !== firstEffect);
|
||||
}
|
||||
}
|
||||
|
||||
function commitHookEffectListMount(tag: HookEffectTag, finishedWork: Fiber) {
|
||||
const updateQueue: FunctionComponentUpdateQueue | null = (finishedWork.updateQueue: any);
|
||||
const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
|
||||
if (lastEffect !== null) {
|
||||
@@ -378,6 +421,83 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) {
|
||||
}
|
||||
}
|
||||
|
||||
function invokePassiveEffectCreate(effect: HookEffect): void {
|
||||
const create = effect.create;
|
||||
effect.destroy = create();
|
||||
}
|
||||
|
||||
// TODO: Remove this duplication.
|
||||
function commitHookEffectListMount2(fiber: Fiber): void {
|
||||
const updateQueue: FunctionComponentUpdateQueue | null = (fiber.updateQueue: any);
|
||||
const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
|
||||
if (lastEffect !== null) {
|
||||
const firstEffect = lastEffect.next;
|
||||
let effect = firstEffect;
|
||||
do {
|
||||
const {next, tag} = effect;
|
||||
|
||||
if (
|
||||
(tag & HookPassive) !== NoHookEffect &&
|
||||
(tag & HookHasEffect) !== NoHookEffect
|
||||
) {
|
||||
if (__DEV__) {
|
||||
if (
|
||||
enableProfilerTimer &&
|
||||
enableProfilerCommitHooks &&
|
||||
fiber.mode & ProfileMode
|
||||
) {
|
||||
startPassiveEffectTimer();
|
||||
invokeGuardedCallback(
|
||||
null,
|
||||
invokePassiveEffectCreate,
|
||||
null,
|
||||
effect,
|
||||
);
|
||||
recordPassiveEffectDuration(fiber);
|
||||
} else {
|
||||
invokeGuardedCallback(
|
||||
null,
|
||||
invokePassiveEffectCreate,
|
||||
null,
|
||||
effect,
|
||||
);
|
||||
}
|
||||
if (hasCaughtError()) {
|
||||
invariant(fiber !== null, 'Should be working on an effect.');
|
||||
const error = clearCaughtError();
|
||||
captureCommitPhaseError(fiber, error);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const create = effect.create;
|
||||
if (
|
||||
enableProfilerTimer &&
|
||||
enableProfilerCommitHooks &&
|
||||
fiber.mode & ProfileMode
|
||||
) {
|
||||
try {
|
||||
startPassiveEffectTimer();
|
||||
effect.destroy = create();
|
||||
} finally {
|
||||
recordPassiveEffectDuration(fiber);
|
||||
}
|
||||
} else {
|
||||
effect.destroy = create();
|
||||
}
|
||||
// TODO: This is missing the warning that exists in commitHookEffectListMount.
|
||||
// The warning refers to useEffect but only applies to useLayoutEffect.
|
||||
} catch (error) {
|
||||
invariant(fiber !== null, 'Should be working on an effect.');
|
||||
captureCommitPhaseError(fiber, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
effect = next;
|
||||
} while (effect !== firstEffect);
|
||||
}
|
||||
}
|
||||
|
||||
export function commitPassiveEffectDurations(
|
||||
finishedRoot: FiberRoot,
|
||||
finishedWork: Fiber,
|
||||
@@ -1709,13 +1829,45 @@ export function isSuspenseBoundaryBeingHidden(
|
||||
return false;
|
||||
}
|
||||
|
||||
function commitResetTextContent(current: Fiber) {
|
||||
function commitResetTextContent(current: Fiber): void {
|
||||
if (!supportsMutation) {
|
||||
return;
|
||||
}
|
||||
resetTextContent(current.stateNode);
|
||||
}
|
||||
|
||||
function commitPassiveWork(finishedWork: Fiber): void {
|
||||
switch (finishedWork.tag) {
|
||||
case FunctionComponent:
|
||||
case ForwardRef:
|
||||
case SimpleMemoComponent:
|
||||
case Block: {
|
||||
commitHookEffectListUnmount2(HookPassive | HookHasEffect, finishedWork);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function commitPassiveUnmount(current: Fiber): void {
|
||||
switch (current.tag) {
|
||||
case FunctionComponent:
|
||||
case ForwardRef:
|
||||
case SimpleMemoComponent:
|
||||
case Block:
|
||||
commitHookEffectListUnmount2(HookPassive, current);
|
||||
}
|
||||
}
|
||||
|
||||
function commitPassiveLifeCycles(finishedWork: Fiber): void {
|
||||
switch (finishedWork.tag) {
|
||||
case FunctionComponent:
|
||||
case ForwardRef:
|
||||
case SimpleMemoComponent:
|
||||
case Block: {
|
||||
commitHookEffectListMount2(finishedWork);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
commitBeforeMutationLifeCycles,
|
||||
commitResetTextContent,
|
||||
@@ -1725,4 +1877,7 @@ export {
|
||||
commitLifeCycles,
|
||||
commitAttachRef,
|
||||
commitDetachRef,
|
||||
commitPassiveUnmount,
|
||||
commitPassiveWork,
|
||||
commitPassiveLifeCycles,
|
||||
};
|
||||
|
||||
@@ -14,8 +14,6 @@ import type {ReactPriorityLevel} from './ReactInternalTypes';
|
||||
import type {Interaction} from 'scheduler/src/Tracing';
|
||||
import type {SuspenseConfig} from './ReactFiberSuspenseConfig';
|
||||
import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
|
||||
import type {Effect as HookEffect} from './ReactFiberHooks.new';
|
||||
import type {HookEffectTag} from './ReactHookEffectTags';
|
||||
import type {StackCursor} from './ReactFiberStack.new';
|
||||
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.new';
|
||||
|
||||
@@ -53,7 +51,6 @@ import {
|
||||
} from './SchedulerWithReactIntegration.new';
|
||||
import {
|
||||
NoEffect as NoHookEffect,
|
||||
HasEffect as HookHasEffect,
|
||||
Passive as HookPassive,
|
||||
} from './ReactHookEffectTags';
|
||||
import {
|
||||
@@ -206,12 +203,14 @@ import {
|
||||
commitPlacement,
|
||||
commitWork,
|
||||
commitDeletion,
|
||||
commitPassiveUnmount,
|
||||
commitPassiveWork,
|
||||
commitPassiveLifeCycles as commitPassiveEffectOnFiber,
|
||||
commitDetachRef,
|
||||
commitAttachRef,
|
||||
commitPassiveEffectDurations,
|
||||
commitResetTextContent,
|
||||
isSuspenseBoundaryBeingHidden,
|
||||
safelyCallDestroy,
|
||||
} from './ReactFiberCommitWork.new';
|
||||
import {enqueueUpdate} from './ReactUpdateQueue.new';
|
||||
import {resetContextDependencies} from './ReactFiberNewContext.new';
|
||||
@@ -229,8 +228,6 @@ import {
|
||||
|
||||
import {
|
||||
recordCommitTime,
|
||||
recordPassiveEffectDuration,
|
||||
startPassiveEffectTimer,
|
||||
startProfilerTimer,
|
||||
stopProfilerTimerIfRunningAndRecordDelta,
|
||||
} from './ReactProfilerTimer.new';
|
||||
@@ -2738,11 +2735,6 @@ export function enqueuePendingPassiveProfilerEffect(fiber: Fiber): void {
|
||||
}
|
||||
}
|
||||
|
||||
function invokePassiveEffectCreate(effect: HookEffect): void {
|
||||
const create = effect.create;
|
||||
effect.destroy = create();
|
||||
}
|
||||
|
||||
function flushPassiveMountEffects(firstChild: Fiber): void {
|
||||
let fiber = firstChild;
|
||||
while (fiber !== null) {
|
||||
@@ -2753,93 +2745,15 @@ function flushPassiveMountEffects(firstChild: Fiber): void {
|
||||
}
|
||||
|
||||
if ((fiber.effectTag & Update) !== NoEffect) {
|
||||
switch (fiber.tag) {
|
||||
case FunctionComponent:
|
||||
case ForwardRef:
|
||||
case SimpleMemoComponent:
|
||||
case Block: {
|
||||
flushPassiveMountEffectsImpl(fiber);
|
||||
}
|
||||
}
|
||||
setCurrentDebugFiberInDEV(fiber);
|
||||
commitPassiveEffectOnFiber(fiber);
|
||||
resetCurrentDebugFiberInDEV();
|
||||
}
|
||||
|
||||
fiber = fiber.sibling;
|
||||
}
|
||||
}
|
||||
|
||||
function flushPassiveMountEffectsImpl(fiber: Fiber): void {
|
||||
setCurrentDebugFiberInDEV(fiber);
|
||||
|
||||
const updateQueue: FunctionComponentUpdateQueue | null = (fiber.updateQueue: any);
|
||||
const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
|
||||
if (lastEffect !== null) {
|
||||
const firstEffect = lastEffect.next;
|
||||
let effect = firstEffect;
|
||||
do {
|
||||
const {next, tag} = effect;
|
||||
|
||||
if (
|
||||
(tag & HookPassive) !== NoHookEffect &&
|
||||
(tag & HookHasEffect) !== NoHookEffect
|
||||
) {
|
||||
if (__DEV__) {
|
||||
if (
|
||||
enableProfilerTimer &&
|
||||
enableProfilerCommitHooks &&
|
||||
fiber.mode & ProfileMode
|
||||
) {
|
||||
startPassiveEffectTimer();
|
||||
invokeGuardedCallback(
|
||||
null,
|
||||
invokePassiveEffectCreate,
|
||||
null,
|
||||
effect,
|
||||
);
|
||||
recordPassiveEffectDuration(fiber);
|
||||
} else {
|
||||
invokeGuardedCallback(
|
||||
null,
|
||||
invokePassiveEffectCreate,
|
||||
null,
|
||||
effect,
|
||||
);
|
||||
}
|
||||
if (hasCaughtError()) {
|
||||
invariant(fiber !== null, 'Should be working on an effect.');
|
||||
const error = clearCaughtError();
|
||||
captureCommitPhaseError(fiber, error);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const create = effect.create;
|
||||
if (
|
||||
enableProfilerTimer &&
|
||||
enableProfilerCommitHooks &&
|
||||
fiber.mode & ProfileMode
|
||||
) {
|
||||
try {
|
||||
startPassiveEffectTimer();
|
||||
effect.destroy = create();
|
||||
} finally {
|
||||
recordPassiveEffectDuration(fiber);
|
||||
}
|
||||
} else {
|
||||
effect.destroy = create();
|
||||
}
|
||||
} catch (error) {
|
||||
invariant(fiber !== null, 'Should be working on an effect.');
|
||||
captureCommitPhaseError(fiber, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
effect = next;
|
||||
} while (effect !== firstEffect);
|
||||
|
||||
resetCurrentDebugFiberInDEV();
|
||||
}
|
||||
}
|
||||
|
||||
function flushPassiveUnmountEffects(firstChild: Fiber): void {
|
||||
let fiber = firstChild;
|
||||
while (fiber !== null) {
|
||||
@@ -2866,16 +2780,11 @@ function flushPassiveUnmountEffects(firstChild: Fiber): void {
|
||||
}
|
||||
}
|
||||
|
||||
switch (fiber.tag) {
|
||||
case FunctionComponent:
|
||||
case ForwardRef:
|
||||
case SimpleMemoComponent:
|
||||
case Block: {
|
||||
const primaryEffectTag = fiber.effectTag & Passive;
|
||||
if (primaryEffectTag !== NoEffect) {
|
||||
flushPassiveUnmountEffectsImpl(fiber, HookPassive | HookHasEffect);
|
||||
}
|
||||
}
|
||||
const primaryEffectTag = fiber.effectTag & Passive;
|
||||
if (primaryEffectTag !== NoEffect) {
|
||||
setCurrentDebugFiberInDEV(fiber);
|
||||
commitPassiveWork(fiber);
|
||||
resetCurrentDebugFiberInDEV();
|
||||
}
|
||||
|
||||
fiber = fiber.sibling;
|
||||
@@ -2898,52 +2807,8 @@ function flushPassiveUnmountEffectsInsideOfDeletedTree(
|
||||
}
|
||||
|
||||
if ((fiberToDelete.effectTag & PassiveStatic) !== NoEffect) {
|
||||
switch (fiberToDelete.tag) {
|
||||
case FunctionComponent:
|
||||
case ForwardRef:
|
||||
case SimpleMemoComponent:
|
||||
case Block: {
|
||||
flushPassiveUnmountEffectsImpl(fiberToDelete, HookPassive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function flushPassiveUnmountEffectsImpl(
|
||||
fiber: Fiber,
|
||||
// Tags to check for when deciding whether to unmount. e.g. to skip over
|
||||
// layout effects
|
||||
hookEffectTag: HookEffectTag,
|
||||
): void {
|
||||
const updateQueue: FunctionComponentUpdateQueue | null = (fiber.updateQueue: any);
|
||||
const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
|
||||
if (lastEffect !== null) {
|
||||
setCurrentDebugFiberInDEV(fiber);
|
||||
|
||||
const firstEffect = lastEffect.next;
|
||||
let effect = firstEffect;
|
||||
do {
|
||||
const {next, tag} = effect;
|
||||
if ((tag & hookEffectTag) === hookEffectTag) {
|
||||
const destroy = effect.destroy;
|
||||
if (destroy !== undefined) {
|
||||
effect.destroy = undefined;
|
||||
if (
|
||||
enableProfilerTimer &&
|
||||
enableProfilerCommitHooks &&
|
||||
fiber.mode & ProfileMode
|
||||
) {
|
||||
startPassiveEffectTimer();
|
||||
safelyCallDestroy(fiber, destroy);
|
||||
recordPassiveEffectDuration(fiber);
|
||||
} else {
|
||||
safelyCallDestroy(fiber, destroy);
|
||||
}
|
||||
}
|
||||
}
|
||||
effect = next;
|
||||
} while (effect !== firstEffect);
|
||||
|
||||
setCurrentDebugFiberInDEV(fiberToDelete);
|
||||
commitPassiveUnmount(fiberToDelete);
|
||||
resetCurrentDebugFiberInDEV();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user