@@ -24,6 +24,7 @@ import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.new';
2424import type { Wakeable } from 'shared/ReactTypes' ;
2525import type { ReactPriorityLevel } from './ReactInternalTypes' ;
2626import type { OffscreenState } from './ReactFiberOffscreenComponent' ;
27+ import type { HookFlags } from './ReactHookEffectTags' ;
2728
2829import { unstable_wrap as Schedule_tracing_wrap } from 'scheduler/tracing' ;
2930import {
@@ -65,10 +66,13 @@ import {
6566 NoFlags ,
6667 ContentReset ,
6768 Placement ,
69+ ChildDeletion ,
6870 Snapshot ,
6971 Update ,
7072 Passive ,
73+ PassiveStatic ,
7174 PassiveMask ,
75+ PassiveUnmountPendingDev ,
7276} from './ReactFiberFlags' ;
7377import getComponentName from 'shared/getComponentName' ;
7478import invariant from 'shared/invariant' ;
@@ -340,19 +344,19 @@ function commitBeforeMutationLifeCycles(
340344 ) ;
341345}
342346
343- function commitHookEffectListUnmount ( tag : number , finishedWork : Fiber ) {
347+ function commitHookEffectListUnmount ( flags : HookFlags , finishedWork : Fiber ) {
344348 const updateQueue : FunctionComponentUpdateQueue | null = ( finishedWork . updateQueue : any ) ;
345349 const lastEffect = updateQueue !== null ? updateQueue . lastEffect : null ;
346350 if ( lastEffect !== null ) {
347351 const firstEffect = lastEffect . next ;
348352 let effect = firstEffect ;
349353 do {
350- if ( ( effect . tag & tag ) === tag ) {
354+ if ( ( effect . tag & flags ) === flags ) {
351355 // Unmount
352356 const destroy = effect . destroy ;
353357 effect . destroy = undefined ;
354358 if ( destroy !== undefined ) {
355- destroy ( ) ;
359+ safelyCallDestroy ( finishedWork , destroy ) ;
356360 }
357361 }
358362 effect = effect . next ;
@@ -1914,6 +1918,154 @@ function commitPassiveMountOnFiber(
19141918 }
19151919}
19161920
1921+ export function commitPassiveUnmountEffects ( firstChild : Fiber ) : void {
1922+ nextEffect = firstChild ;
1923+ commitPassiveUnmountEffects_begin ( ) ;
1924+ }
1925+
1926+ function commitPassiveUnmountEffects_begin ( ) {
1927+ while ( nextEffect !== null ) {
1928+ const fiber = nextEffect ;
1929+ const child = fiber . child ;
1930+
1931+ if ( ( nextEffect . flags & ChildDeletion ) !== NoFlags ) {
1932+ const deletions = fiber . deletions ;
1933+ if ( deletions !== null ) {
1934+ for ( let i = 0 ; i < deletions . length ; i ++ ) {
1935+ const fiberToDelete = deletions [ i ] ;
1936+ nextEffect = fiberToDelete ;
1937+ commitPassiveUnmountEffectsInsideOfDeletedTree_begin ( fiberToDelete ) ;
1938+
1939+ // Now that passive effects have been processed, it's safe to detach lingering pointers.
1940+ detachFiberAfterEffects ( fiberToDelete ) ;
1941+ }
1942+ nextEffect = fiber ;
1943+ }
1944+ }
1945+
1946+ if ( ( fiber . subtreeFlags & PassiveMask ) !== NoFlags && child !== null ) {
1947+ ensureCorrectReturnPointer ( child , fiber ) ;
1948+ nextEffect = child ;
1949+ } else {
1950+ commitPassiveUnmountEffects_complete ( ) ;
1951+ }
1952+ }
1953+ }
1954+
1955+ function commitPassiveUnmountEffects_complete ( ) {
1956+ while ( nextEffect !== null ) {
1957+ const fiber = nextEffect ;
1958+ if ( ( fiber . flags & Passive ) !== NoFlags ) {
1959+ setCurrentDebugFiberInDEV ( fiber ) ;
1960+ commitPassiveUnmountOnFiber ( fiber ) ;
1961+ resetCurrentDebugFiberInDEV ( ) ;
1962+ }
1963+
1964+ const sibling = fiber . sibling ;
1965+ if ( sibling !== null ) {
1966+ ensureCorrectReturnPointer ( sibling , fiber . return ) ;
1967+ nextEffect = sibling ;
1968+ return ;
1969+ }
1970+
1971+ nextEffect = fiber . return ;
1972+ }
1973+ }
1974+
1975+ function commitPassiveUnmountOnFiber ( finishedWork : Fiber ) : void {
1976+ if ( __DEV__ ) {
1977+ finishedWork . flags &= ~ PassiveUnmountPendingDev ;
1978+ const alternate = finishedWork . alternate ;
1979+ if ( alternate !== null ) {
1980+ alternate . flags &= ~ PassiveUnmountPendingDev ;
1981+ }
1982+ }
1983+
1984+ switch ( finishedWork . tag ) {
1985+ case FunctionComponent :
1986+ case ForwardRef :
1987+ case SimpleMemoComponent : {
1988+ if (
1989+ enableProfilerTimer &&
1990+ enableProfilerCommitHooks &&
1991+ finishedWork . mode & ProfileMode
1992+ ) {
1993+ startPassiveEffectTimer ( ) ;
1994+ commitHookEffectListUnmount ( HookPassive | HookHasEffect , finishedWork ) ;
1995+ recordPassiveEffectDuration ( finishedWork ) ;
1996+ } else {
1997+ commitHookEffectListUnmount ( HookPassive | HookHasEffect , finishedWork ) ;
1998+ }
1999+ break ;
2000+ }
2001+ }
2002+ }
2003+
2004+ function commitPassiveUnmountEffectsInsideOfDeletedTree_begin (
2005+ deletedSubtreeRoot : Fiber ,
2006+ ) {
2007+ while ( nextEffect !== null ) {
2008+ const fiber = nextEffect ;
2009+ const child = fiber . child ;
2010+ if ( ( fiber . subtreeFlags & PassiveStatic ) !== NoFlags && child !== null ) {
2011+ ensureCorrectReturnPointer ( child , fiber ) ;
2012+ nextEffect = child ;
2013+ } else {
2014+ commitPassiveUnmountEffectsInsideOfDeletedTree_complete (
2015+ deletedSubtreeRoot ,
2016+ ) ;
2017+ }
2018+ }
2019+ }
2020+
2021+ function commitPassiveUnmountEffectsInsideOfDeletedTree_complete (
2022+ deletedSubtreeRoot : Fiber ,
2023+ ) {
2024+ while ( nextEffect !== null ) {
2025+ const fiber = nextEffect ;
2026+ if ( ( fiber . flags & PassiveStatic ) !== NoFlags ) {
2027+ setCurrentDebugFiberInDEV ( fiber ) ;
2028+ commitPassiveUnmountInsideDeletedTreeOnFiber ( fiber ) ;
2029+ resetCurrentDebugFiberInDEV ( ) ;
2030+ }
2031+
2032+ if ( fiber === deletedSubtreeRoot ) {
2033+ nextEffect = null ;
2034+ return ;
2035+ }
2036+
2037+ const sibling = fiber . sibling ;
2038+ if ( sibling !== null ) {
2039+ ensureCorrectReturnPointer ( sibling , fiber . return ) ;
2040+ nextEffect = sibling ;
2041+ return ;
2042+ }
2043+
2044+ nextEffect = fiber . return ;
2045+ }
2046+ }
2047+
2048+ function commitPassiveUnmountInsideDeletedTreeOnFiber ( current : Fiber ) : void {
2049+ switch ( current . tag ) {
2050+ case FunctionComponent :
2051+ case ForwardRef :
2052+ case SimpleMemoComponent : {
2053+ if (
2054+ enableProfilerTimer &&
2055+ enableProfilerCommitHooks &&
2056+ current . mode & ProfileMode
2057+ ) {
2058+ startPassiveEffectTimer ( ) ;
2059+ commitHookEffectListUnmount ( HookPassive , current ) ;
2060+ recordPassiveEffectDuration ( current ) ;
2061+ } else {
2062+ commitHookEffectListUnmount ( HookPassive , current ) ;
2063+ }
2064+ break ;
2065+ }
2066+ }
2067+ }
2068+
19172069let didWarnWrongReturnPointer = false ;
19182070function ensureCorrectReturnPointer ( fiber , expectedReturnFiber ) {
19192071 if ( __DEV__ ) {
0 commit comments