@@ -22,6 +22,7 @@ import type {CapturedValue, CapturedError} from './ReactCapturedValue';
2222import type { SuspenseState } from './ReactFiberSuspenseComponent' ;
2323import type { FunctionComponentUpdateQueue } from './ReactFiberHooks' ;
2424import type { Thenable } from './ReactFiberWorkLoop' ;
25+ import type { ReactPriorityLevel } from './SchedulerWithReactIntegration' ;
2526
2627import { unstable_wrap as Schedule_tracing_wrap } from 'scheduler/tracing' ;
2728import {
@@ -116,6 +117,7 @@ import {
116117 MountPassive ,
117118} from './ReactHookEffectTags' ;
118119import { didWarnAboutReassigningProps } from './ReactFiberBeginWork' ;
120+ import { runWithPriority , NormalPriority } from './SchedulerWithReactIntegration' ;
119121
120122let didWarnAboutUndefinedSnapshotBeforeUpdate : Set < mixed > | null = null ;
121123if ( __DEV__ ) {
@@ -716,7 +718,10 @@ function commitDetachRef(current: Fiber) {
716718// User-originating errors (lifecycles and refs) should not interrupt
717719// deletion, so don't let them throw. Host-originating errors should
718720// interrupt deletion, so it's okay
719- function commitUnmount ( current : Fiber ) : void {
721+ function commitUnmount (
722+ current : Fiber ,
723+ renderPriorityLevel : ReactPriorityLevel ,
724+ ) : void {
720725 onCommitUnmount ( current ) ;
721726
722727 switch ( current . tag ) {
@@ -729,14 +734,33 @@ function commitUnmount(current: Fiber): void {
729734 const lastEffect = updateQueue . lastEffect ;
730735 if ( lastEffect !== null ) {
731736 const firstEffect = lastEffect . next ;
732- let effect = firstEffect ;
733- do {
734- const destroy = effect . destroy ;
735- if ( destroy !== undefined ) {
736- safelyCallDestroy ( current , destroy ) ;
737- }
738- effect = effect . next ;
739- } while ( effect !== firstEffect ) ;
737+
738+ // When the owner fiber is deleted, the destroy function of a passive
739+ // effect hook is called during the synchronous commit phase. This is
740+ // a concession to implementation complexity. Calling it in the
741+ // passive effect phase (like they usually are, when dependencies
742+ // change during an update) would require either traversing the
743+ // children of the deleted fiber again, or including unmount effects
744+ // as part of the fiber effect list.
745+ //
746+ // Because this is during the sync commit phase, we need to change
747+ // the priority.
748+ //
749+ // TODO: Reconsider this implementation trade off.
750+ const priorityLevel =
751+ renderPriorityLevel > NormalPriority
752+ ? NormalPriority
753+ : renderPriorityLevel ;
754+ runWithPriority ( priorityLevel , ( ) => {
755+ let effect = firstEffect ;
756+ do {
757+ const destroy = effect . destroy ;
758+ if ( destroy !== undefined ) {
759+ safelyCallDestroy ( current , destroy ) ;
760+ }
761+ effect = effect . next ;
762+ } while ( effect !== firstEffect ) ;
763+ } ) ;
740764 }
741765 }
742766 break ;
@@ -777,7 +801,7 @@ function commitUnmount(current: Fiber): void {
777801 // We are also not using this parent because
778802 // the portal will get pushed immediately.
779803 if ( supportsMutation ) {
780- unmountHostComponents ( current ) ;
804+ unmountHostComponents ( current , renderPriorityLevel ) ;
781805 } else if ( supportsPersistence ) {
782806 emptyPortalContainer ( current ) ;
783807 }
@@ -795,15 +819,18 @@ function commitUnmount(current: Fiber): void {
795819 }
796820}
797821
798- function commitNestedUnmounts ( root : Fiber ) : void {
822+ function commitNestedUnmounts (
823+ root : Fiber ,
824+ renderPriorityLevel : ReactPriorityLevel ,
825+ ) : void {
799826 // While we're inside a removed host node we don't want to call
800827 // removeChild on the inner nodes because they're removed by the top
801828 // call anyway. We also want to call componentWillUnmount on all
802829 // composites before this host node is removed from the tree. Therefore
803830 // we do an inner loop while we're still inside the host node.
804831 let node : Fiber = root ;
805832 while ( true ) {
806- commitUnmount ( node ) ;
833+ commitUnmount ( node , renderPriorityLevel ) ;
807834 // Visit children because they may contain more composite or host nodes.
808835 // Skip portals because commitUnmount() currently visits them recursively.
809836 if (
@@ -1054,7 +1081,7 @@ function commitPlacement(finishedWork: Fiber): void {
10541081 }
10551082}
10561083
1057- function unmountHostComponents ( current ) : void {
1084+ function unmountHostComponents ( current , renderPriorityLevel ) : void {
10581085 // We only have the top Fiber that was deleted but we need to recurse down its
10591086 // children to find all the terminal nodes.
10601087 let node : Fiber = current ;
@@ -1102,7 +1129,7 @@ function unmountHostComponents(current): void {
11021129 }
11031130
11041131 if ( node . tag === HostComponent || node . tag === HostText ) {
1105- commitNestedUnmounts ( node ) ;
1132+ commitNestedUnmounts ( node , renderPriorityLevel ) ;
11061133 // After all the children have unmounted, it is now safe to remove the
11071134 // node from the tree.
11081135 if ( currentParentIsContainer ) {
@@ -1119,7 +1146,7 @@ function unmountHostComponents(current): void {
11191146 // Don't visit children because we already visited them.
11201147 } else if ( node . tag === FundamentalComponent ) {
11211148 const fundamentalNode = node . stateNode . instance ;
1122- commitNestedUnmounts ( node ) ;
1149+ commitNestedUnmounts ( node , renderPriorityLevel ) ;
11231150 // After all the children have unmounted, it is now safe to remove the
11241151 // node from the tree.
11251152 if ( currentParentIsContainer ) {
@@ -1161,7 +1188,7 @@ function unmountHostComponents(current): void {
11611188 continue ;
11621189 }
11631190 } else {
1164- commitUnmount ( node ) ;
1191+ commitUnmount ( node , renderPriorityLevel ) ;
11651192 // Visit children because we may find more host components below.
11661193 if ( node . child !== null ) {
11671194 node . child . return = node ;
@@ -1188,14 +1215,17 @@ function unmountHostComponents(current): void {
11881215 }
11891216}
11901217
1191- function commitDeletion ( current : Fiber ) : void {
1218+ function commitDeletion (
1219+ current : Fiber ,
1220+ renderPriorityLevel : ReactPriorityLevel ,
1221+ ) : void {
11921222 if ( supportsMutation ) {
11931223 // Recursively delete all host nodes from the parent.
11941224 // Detach refs and call componentWillUnmount() on the whole subtree.
1195- unmountHostComponents ( current ) ;
1225+ unmountHostComponents ( current , renderPriorityLevel ) ;
11961226 } else {
11971227 // Detach refs and call componentWillUnmount() on the whole subtree.
1198- commitNestedUnmounts ( current ) ;
1228+ commitNestedUnmounts ( current , renderPriorityLevel ) ;
11991229 }
12001230 detachFiber ( current ) ;
12011231}
0 commit comments