@@ -212,6 +212,7 @@ import {
212212 commitResetTextContent ,
213213 isSuspenseBoundaryBeingHidden ,
214214 safelyCallDestroy ,
215+ safelyCallDestroyForUnmountedFiber ,
215216} from './ReactFiberCommitWork.new' ;
216217import { enqueueUpdate } from './ReactUpdateQueue.new' ;
217218import { resetContextDependencies } from './ReactFiberNewContext.new' ;
@@ -2790,7 +2791,7 @@ function flushPassiveUnmountEffects(firstChild: Fiber): void {
27902791 if ( deletions !== null ) {
27912792 for ( let i = 0 ; i < deletions . length ; i ++ ) {
27922793 const fiberToDelete = deletions [ i ] ;
2793- flushPassiveUnmountEffectsInsideOfDeletedTree ( fiberToDelete ) ;
2794+ flushPassiveUnmountEffectsForUnmountedFiber ( fiberToDelete , fiber ) ;
27942795
27952796 // Now that passive effects have been processed, it's safe to detach lingering pointers.
27962797 detachFiberAfterEffects ( fiberToDelete ) ;
@@ -2825,8 +2826,9 @@ function flushPassiveUnmountEffects(firstChild: Fiber): void {
28252826 }
28262827}
28272828
2828- function flushPassiveUnmountEffectsInsideOfDeletedTree (
2829+ function flushPassiveUnmountEffectsForUnmountedFiber (
28292830 fiberToDelete : Fiber ,
2831+ nearestMountedAncestor : Fiber ,
28302832) : void {
28312833 if ( ( fiberToDelete . subtreeTag & PassiveStaticSubtreeTag ) !== NoSubtreeTag ) {
28322834 // If any children have passive effects then traverse the subtree.
@@ -2835,7 +2837,10 @@ function flushPassiveUnmountEffectsInsideOfDeletedTree(
28352837 // since that would not cover passive effects in siblings.
28362838 let child = fiberToDelete . child ;
28372839 while ( child !== null ) {
2838- flushPassiveUnmountEffectsInsideOfDeletedTree ( child ) ;
2840+ flushPassiveUnmountEffectsForUnmountedFiber (
2841+ child ,
2842+ nearestMountedAncestor ,
2843+ ) ;
28392844 child = child . sibling ;
28402845 }
28412846 }
@@ -2846,16 +2851,64 @@ function flushPassiveUnmountEffectsInsideOfDeletedTree(
28462851 case ForwardRef :
28472852 case SimpleMemoComponent :
28482853 case Block : {
2849- flushPassiveUnmountEffectsImpl ( fiberToDelete , HookPassive ) ;
2854+ flushPassiveUnmountEffectsForUnmountedFiberImpl (
2855+ fiberToDelete ,
2856+ nearestMountedAncestor ,
2857+ ) ;
28502858 }
28512859 }
28522860 }
28532861}
28542862
2863+ function flushPassiveUnmountEffectsForUnmountedFiberImpl (
2864+ fiber : Fiber ,
2865+ nearestMountedAncestor : Fiber ,
2866+ ) : void {
2867+ const updateQueue : FunctionComponentUpdateQueue | null = ( fiber . updateQueue : any ) ;
2868+ const lastEffect = updateQueue !== null ? updateQueue . lastEffect : null ;
2869+ if ( lastEffect !== null ) {
2870+ setCurrentDebugFiberInDEV ( fiber ) ;
2871+
2872+ const firstEffect = lastEffect . next ;
2873+ let effect = firstEffect ;
2874+ do {
2875+ const { next , tag } = effect ;
2876+ if ( ( tag & HookPassive ) === HookPassive ) {
2877+ const destroy = effect . destroy ;
2878+ if ( destroy !== undefined ) {
2879+ effect . destroy = undefined ;
2880+
2881+ if (
2882+ enableProfilerTimer &&
2883+ enableProfilerCommitHooks &&
2884+ fiber . mode & ProfileMode
2885+ ) {
2886+ startPassiveEffectTimer ( ) ;
2887+ safelyCallDestroyForUnmountedFiber (
2888+ fiber ,
2889+ nearestMountedAncestor ,
2890+ destroy ,
2891+ ) ;
2892+ recordPassiveEffectDuration ( fiber ) ;
2893+ } else {
2894+ safelyCallDestroyForUnmountedFiber (
2895+ fiber ,
2896+ nearestMountedAncestor ,
2897+ destroy ,
2898+ ) ;
2899+ }
2900+ }
2901+ }
2902+ effect = next ;
2903+ } while ( effect !== firstEffect ) ;
2904+
2905+ resetCurrentDebugFiberInDEV ( ) ;
2906+ }
2907+ }
2908+
28552909function flushPassiveUnmountEffectsImpl (
28562910 fiber : Fiber ,
2857- // Tags to check for when deciding whether to unmount. e.g. to skip over
2858- // layout effects
2911+ // Tags to check for when deciding whether to unmount. e.g. to skip over layout effects
28592912 hookEffectTag : HookEffectTag ,
28602913) : void {
28612914 const updateQueue : FunctionComponentUpdateQueue | null = ( fiber . updateQueue : any ) ;
@@ -3055,6 +3108,45 @@ export function captureCommitPhaseError(sourceFiber: Fiber, error: mixed) {
30553108 }
30563109}
30573110
3111+ export function captureCommitPhaseErrorForUnmountedFiber (
3112+ sourceFiber : Fiber ,
3113+ nearestMountedAncestor : Fiber ,
3114+ error : mixed ,
3115+ ) {
3116+ let fiber = nearestMountedAncestor . return ;
3117+ while ( fiber !== null ) {
3118+ if ( fiber . tag === HostRoot ) {
3119+ captureCommitPhaseErrorOnRoot ( fiber , sourceFiber , error ) ;
3120+ return ;
3121+ } else if ( fiber . tag === ClassComponent ) {
3122+ const ctor = fiber . type ;
3123+ const instance = fiber . stateNode ;
3124+ if (
3125+ typeof ctor . getDerivedStateFromError === 'function' ||
3126+ ( typeof instance . componentDidCatch === 'function' &&
3127+ ! isAlreadyFailedLegacyErrorBoundary ( instance ) )
3128+ ) {
3129+ const errorInfo = createCapturedValue ( error , sourceFiber ) ;
3130+ const update = createClassErrorUpdate (
3131+ fiber ,
3132+ errorInfo ,
3133+ ( SyncLane : Lane ) ,
3134+ ) ;
3135+ enqueueUpdate ( fiber , update ) ;
3136+ const eventTime = requestEventTime ( ) ;
3137+ const root = markUpdateLaneFromFiberToRoot ( fiber , ( SyncLane : Lane ) ) ;
3138+ if ( root !== null ) {
3139+ markRootUpdated ( root , SyncLane , eventTime ) ;
3140+ ensureRootIsScheduled ( root , eventTime ) ;
3141+ schedulePendingInteractions ( root , SyncLane ) ;
3142+ }
3143+ return ;
3144+ }
3145+ }
3146+ fiber = fiber . return ;
3147+ }
3148+ }
3149+
30583150export function pingSuspendedRoot (
30593151 root : FiberRoot ,
30603152 wakeable : Wakeable ,
0 commit comments