@@ -35,6 +35,7 @@ import {
3535 enableLegacyHidden ,
3636 enableSuspenseCallback ,
3737 enableScopeAPI ,
38+ enablePersistedModeClonedFlag ,
3839 enableProfilerTimer ,
3940 enableCache ,
4041 enableTransitionTracing ,
@@ -90,6 +91,7 @@ import {
9091 MaySuspendCommit ,
9192 ScheduleRetry ,
9293 ShouldSuspendCommit ,
94+ Cloned ,
9395} from './ReactFiberFlags' ;
9496
9597import {
@@ -182,6 +184,16 @@ function markUpdate(workInProgress: Fiber) {
182184 workInProgress . flags |= Update ;
183185}
184186
187+ /**
188+ * Tag the fiber with Cloned in persistent mode to signal that
189+ * it received an update that requires a clone of the tree above.
190+ */
191+ function markCloned ( workInProgress : Fiber ) {
192+ if ( supportsPersistence && enablePersistedModeClonedFlag ) {
193+ workInProgress . flags |= Cloned ;
194+ }
195+ }
196+
185197/**
186198 * In persistent mode, return whether this update needs to clone the subtree.
187199 */
@@ -199,9 +211,12 @@ function doesRequireClone(current: null | Fiber, completedWork: Fiber) {
199211 // then we only have to check the `completedWork.subtreeFlags`.
200212 let child = completedWork . child ;
201213 while ( child !== null ) {
214+ const checkedFlags = enablePersistedModeClonedFlag
215+ ? Cloned | Visibility | Placement
216+ : MutationMask ;
202217 if (
203- ( child . flags & MutationMask ) !== NoFlags ||
204- ( child . subtreeFlags & MutationMask ) !== NoFlags
218+ ( child . flags & checkedFlags ) !== NoFlags ||
219+ ( child . subtreeFlags & checkedFlags ) !== NoFlags
205220 ) {
206221 return true ;
207222 }
@@ -450,6 +465,7 @@ function updateHostComponent(
450465
451466 let newChildSet = null ;
452467 if ( requiresClone && passChildrenWhenCloningPersistedNodes ) {
468+ markCloned ( workInProgress ) ;
453469 newChildSet = createContainerChildSet ( ) ;
454470 // If children might have changed, we have to add them all to the set.
455471 appendAllChildrenToContainer (
@@ -473,6 +489,8 @@ function updateHostComponent(
473489 // Note that this might release a previous clone.
474490 workInProgress . stateNode = currentInstance ;
475491 return ;
492+ } else {
493+ markCloned ( workInProgress ) ;
476494 }
477495
478496 // Certain renderers require commit-time effects for initial mount.
@@ -485,12 +503,14 @@ function updateHostComponent(
485503 }
486504 workInProgress . stateNode = newInstance ;
487505 if ( ! requiresClone ) {
488- // If there are no other effects in this tree, we need to flag this node as having one.
489- // Even though we're not going to use it for anything.
490- // Otherwise parents won't know that there are new children to propagate upwards.
491- markUpdate ( workInProgress ) ;
506+ if ( ! enablePersistedModeClonedFlag ) {
507+ // If there are no other effects in this tree, we need to flag this node as having one.
508+ // Even though we're not going to use it for anything.
509+ // Otherwise parents won't know that there are new children to propagate upwards.
510+ markUpdate ( workInProgress ) ;
511+ }
492512 } else if ( ! passChildrenWhenCloningPersistedNodes ) {
493- // If children might have changed, we have to add them all to the set.
513+ // If children have changed, we have to add them all to the set.
494514 appendAllChildren (
495515 newInstance ,
496516 workInProgress ,
@@ -618,15 +638,18 @@ function updateHostText(
618638 // If the text content differs, we'll create a new text instance for it.
619639 const rootContainerInstance = getRootHostContainer ( ) ;
620640 const currentHostContext = getHostContext ( ) ;
641+ markCloned ( workInProgress ) ;
621642 workInProgress . stateNode = createTextInstance (
622643 newText ,
623644 rootContainerInstance ,
624645 currentHostContext ,
625646 workInProgress ,
626647 ) ;
627- // We'll have to mark it as having an effect, even though we won't use the effect for anything.
628- // This lets the parents know that at least one of their children has changed.
629- markUpdate ( workInProgress ) ;
648+ if ( ! enablePersistedModeClonedFlag ) {
649+ // We'll have to mark it as having an effect, even though we won't use the effect for anything.
650+ // This lets the parents know that at least one of their children has changed.
651+ markUpdate ( workInProgress ) ;
652+ }
630653 } else {
631654 workInProgress . stateNode = current . stateNode ;
632655 }
@@ -1229,6 +1252,7 @@ function completeWork(
12291252 ) ;
12301253 // TODO: For persistent renderers, we should pass children as part
12311254 // of the initial instance creation
1255+ markCloned ( workInProgress ) ;
12321256 appendAllChildren ( instance , workInProgress , false , false ) ;
12331257 workInProgress . stateNode = instance ;
12341258
@@ -1284,6 +1308,7 @@ function completeWork(
12841308 if ( wasHydrated ) {
12851309 prepareToHydrateHostTextInstance ( workInProgress ) ;
12861310 } else {
1311+ markCloned ( workInProgress ) ;
12871312 workInProgress . stateNode = createTextInstance (
12881313 newText ,
12891314 rootContainerInstance ,
0 commit comments