@@ -84,6 +84,7 @@ import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFrom
84
84
import {
85
85
resetCurrentFiber as resetCurrentDebugFiberInDEV ,
86
86
setCurrentFiber as setCurrentDebugFiberInDEV ,
87
+ getCurrentFiber as getCurrentDebugFiberInDEV ,
87
88
} from './ReactCurrentFiber' ;
88
89
import { resolveDefaultProps } from './ReactFiberLazyComponent.new' ;
89
90
import {
@@ -1901,62 +1902,50 @@ export function isSuspenseBoundaryBeingHidden(
1901
1902
1902
1903
export function commitMutationEffects (
1903
1904
root : FiberRoot ,
1904
- firstChild : Fiber ,
1905
+ finishedWork : Fiber ,
1905
1906
committedLanes : Lanes ,
1906
1907
) {
1907
1908
inProgressLanes = committedLanes ;
1908
1909
inProgressRoot = root ;
1909
- nextEffect = firstChild ;
1910
+ nextEffect = finishedWork ;
1910
1911
1911
- commitMutationEffects_begin ( root , committedLanes ) ;
1912
+ setCurrentDebugFiberInDEV ( finishedWork ) ;
1913
+ commitMutationEffectsOnFiber ( finishedWork , root , committedLanes ) ;
1914
+ setCurrentDebugFiberInDEV ( finishedWork ) ;
1912
1915
1913
1916
inProgressLanes = null ;
1914
1917
inProgressRoot = null ;
1915
1918
}
1916
1919
1917
- function commitMutationEffects_begin ( root : FiberRoot , lanes : Lanes ) {
1918
- while ( nextEffect !== null ) {
1919
- const fiber = nextEffect ;
1920
-
1921
- // TODO: Should wrap this in flags check, too, as optimization
1922
- const deletions = fiber . deletions ;
1923
- if ( deletions !== null ) {
1924
- for ( let i = 0 ; i < deletions . length ; i ++ ) {
1925
- const childToDelete = deletions [ i ] ;
1926
- try {
1927
- commitDeletion ( root , childToDelete , fiber ) ;
1928
- } catch ( error ) {
1929
- captureCommitPhaseError ( childToDelete , fiber , error ) ;
1930
- }
1920
+ function recursivelyTraverseMutationEffects (
1921
+ root : FiberRoot ,
1922
+ parentFiber : Fiber ,
1923
+ lanes : Lanes ,
1924
+ ) {
1925
+ // Deletions effects can be scheduled on any fiber type. They need to happen
1926
+ // before the children effects hae fired.
1927
+ const deletions = parentFiber . deletions ;
1928
+ if ( deletions !== null ) {
1929
+ for ( let i = 0 ; i < deletions . length ; i ++ ) {
1930
+ const childToDelete = deletions [ i ] ;
1931
+ try {
1932
+ commitDeletion ( root , childToDelete , parentFiber ) ;
1933
+ } catch ( error ) {
1934
+ captureCommitPhaseError ( childToDelete , parentFiber , error ) ;
1931
1935
}
1932
1936
}
1933
-
1934
- const child = fiber . child ;
1935
- if ( ( fiber . subtreeFlags & MutationMask ) !== NoFlags && child !== null ) {
1936
- child . return = fiber ;
1937
- nextEffect = child ;
1938
- } else {
1939
- commitMutationEffects_complete ( root , lanes ) ;
1940
- }
1941
1937
}
1942
- }
1943
1938
1944
- function commitMutationEffects_complete ( root : FiberRoot , lanes : Lanes ) {
1945
- while ( nextEffect !== null ) {
1946
- const fiber = nextEffect ;
1947
- setCurrentDebugFiberInDEV ( fiber ) ;
1948
- commitMutationEffectsOnFiber ( fiber , root , lanes ) ;
1949
- resetCurrentDebugFiberInDEV ( ) ;
1950
-
1951
- const sibling = fiber . sibling ;
1952
- if ( sibling !== null ) {
1953
- sibling . return = fiber . return ;
1954
- nextEffect = sibling ;
1955
- return ;
1939
+ const prevDebugFiber = getCurrentDebugFiberInDEV ( ) ;
1940
+ if ( parentFiber . subtreeFlags & MutationMask ) {
1941
+ let child = parentFiber . child ;
1942
+ while ( child !== null ) {
1943
+ setCurrentDebugFiberInDEV ( child ) ;
1944
+ commitMutationEffectsOnFiber ( child , root , lanes ) ;
1945
+ child = child . sibling ;
1956
1946
}
1957
-
1958
- nextEffect = fiber . return ;
1959
1947
}
1948
+ setCurrentDebugFiberInDEV ( prevDebugFiber ) ;
1960
1949
}
1961
1950
1962
1951
function commitMutationEffectsOnFiber (
@@ -1975,6 +1964,7 @@ function commitMutationEffectsOnFiber(
1975
1964
case ForwardRef :
1976
1965
case MemoComponent :
1977
1966
case SimpleMemoComponent : {
1967
+ recursivelyTraverseMutationEffects ( root , finishedWork , lanes ) ;
1978
1968
commitReconciliationEffects ( finishedWork ) ;
1979
1969
1980
1970
if ( flags & Update ) {
@@ -2027,6 +2017,7 @@ function commitMutationEffectsOnFiber(
2027
2017
return ;
2028
2018
}
2029
2019
case ClassComponent : {
2020
+ recursivelyTraverseMutationEffects ( root , finishedWork , lanes ) ;
2030
2021
commitReconciliationEffects ( finishedWork ) ;
2031
2022
2032
2023
if ( flags & Ref ) {
@@ -2037,6 +2028,7 @@ function commitMutationEffectsOnFiber(
2037
2028
return ;
2038
2029
}
2039
2030
case HostComponent : {
2031
+ recursivelyTraverseMutationEffects ( root , finishedWork , lanes ) ;
2040
2032
commitReconciliationEffects ( finishedWork ) ;
2041
2033
2042
2034
if ( flags & Ref ) {
@@ -2045,7 +2037,13 @@ function commitMutationEffectsOnFiber(
2045
2037
}
2046
2038
}
2047
2039
if ( supportsMutation ) {
2048
- if ( flags & ContentReset ) {
2040
+ // TODO: ContentReset gets cleared by the children during the commit
2041
+ // phase. This is a refactor hazard because it means we must read
2042
+ // flags the flags after `commitReconciliationEffects` has already run;
2043
+ // the order matters. We should refactor so that ContentReset does not
2044
+ // rely on mutating the flag during commit. Like by setting a flag
2045
+ // during the render phase instead.
2046
+ if ( finishedWork . flags & ContentReset ) {
2049
2047
const instance : Instance = finishedWork . stateNode ;
2050
2048
try {
2051
2049
resetTextContent ( instance ) ;
@@ -2092,6 +2090,7 @@ function commitMutationEffectsOnFiber(
2092
2090
return ;
2093
2091
}
2094
2092
case HostText : {
2093
+ recursivelyTraverseMutationEffects ( root , finishedWork , lanes ) ;
2095
2094
commitReconciliationEffects ( finishedWork ) ;
2096
2095
2097
2096
if ( flags & Update ) {
@@ -2121,6 +2120,7 @@ function commitMutationEffectsOnFiber(
2121
2120
return ;
2122
2121
}
2123
2122
case HostRoot : {
2123
+ recursivelyTraverseMutationEffects ( root , finishedWork , lanes ) ;
2124
2124
commitReconciliationEffects ( finishedWork ) ;
2125
2125
2126
2126
if ( flags & Update ) {
@@ -2153,6 +2153,7 @@ function commitMutationEffectsOnFiber(
2153
2153
return ;
2154
2154
}
2155
2155
case HostPortal : {
2156
+ recursivelyTraverseMutationEffects ( root , finishedWork , lanes ) ;
2156
2157
commitReconciliationEffects ( finishedWork ) ;
2157
2158
2158
2159
if ( flags & Update ) {
@@ -2170,6 +2171,7 @@ function commitMutationEffectsOnFiber(
2170
2171
return ;
2171
2172
}
2172
2173
case SuspenseComponent : {
2174
+ recursivelyTraverseMutationEffects ( root , finishedWork , lanes ) ;
2173
2175
commitReconciliationEffects ( finishedWork ) ;
2174
2176
2175
2177
if ( flags & Visibility ) {
@@ -2194,6 +2196,7 @@ function commitMutationEffectsOnFiber(
2194
2196
return ;
2195
2197
}
2196
2198
case OffscreenComponent : {
2199
+ recursivelyTraverseMutationEffects ( root , finishedWork , lanes ) ;
2197
2200
commitReconciliationEffects ( finishedWork ) ;
2198
2201
2199
2202
if ( flags & Visibility ) {
@@ -2231,6 +2234,7 @@ function commitMutationEffectsOnFiber(
2231
2234
return ;
2232
2235
}
2233
2236
case SuspenseListComponent : {
2237
+ recursivelyTraverseMutationEffects ( root , finishedWork , lanes ) ;
2234
2238
commitReconciliationEffects ( finishedWork ) ;
2235
2239
2236
2240
if ( flags & Update ) {
@@ -2240,6 +2244,7 @@ function commitMutationEffectsOnFiber(
2240
2244
}
2241
2245
case ScopeComponent : {
2242
2246
if ( enableScopeAPI ) {
2247
+ recursivelyTraverseMutationEffects ( root , finishedWork , lanes ) ;
2243
2248
commitReconciliationEffects ( finishedWork ) ;
2244
2249
2245
2250
// TODO: This is a temporary solution that allowed us to transition away
@@ -2258,11 +2263,13 @@ function commitMutationEffectsOnFiber(
2258
2263
return ;
2259
2264
}
2260
2265
default : {
2266
+ recursivelyTraverseMutationEffects ( root , finishedWork , lanes ) ;
2261
2267
commitReconciliationEffects ( finishedWork ) ;
2268
+
2269
+ return ;
2262
2270
}
2263
2271
}
2264
2272
}
2265
-
2266
2273
function commitReconciliationEffects ( finishedWork : Fiber ) {
2267
2274
// Placement effects (insertions, reorders) can be scheduled on any fiber
2268
2275
// type. They needs to happen after the children effects have fired, but
0 commit comments