@@ -35,6 +35,7 @@ import {
35
35
enableLegacyHidden ,
36
36
enableSuspenseCallback ,
37
37
enableScopeAPI ,
38
+ enablePersistedModeClonedFlag ,
38
39
enableProfilerTimer ,
39
40
enableCache ,
40
41
enableTransitionTracing ,
@@ -90,6 +91,7 @@ import {
90
91
MaySuspendCommit ,
91
92
ScheduleRetry ,
92
93
ShouldSuspendCommit ,
94
+ Cloned ,
93
95
} from './ReactFiberFlags' ;
94
96
95
97
import {
@@ -182,6 +184,16 @@ function markUpdate(workInProgress: Fiber) {
182
184
workInProgress . flags |= Update ;
183
185
}
184
186
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
+
185
197
/**
186
198
* In persistent mode, return whether this update needs to clone the subtree.
187
199
*/
@@ -199,9 +211,12 @@ function doesRequireClone(current: null | Fiber, completedWork: Fiber) {
199
211
// then we only have to check the `completedWork.subtreeFlags`.
200
212
let child = completedWork . child ;
201
213
while ( child !== null ) {
214
+ const checkedFlags = enablePersistedModeClonedFlag
215
+ ? Cloned | Visibility | Placement
216
+ : MutationMask ;
202
217
if (
203
- ( child . flags & MutationMask ) !== NoFlags ||
204
- ( child . subtreeFlags & MutationMask ) !== NoFlags
218
+ ( child . flags & checkedFlags ) !== NoFlags ||
219
+ ( child . subtreeFlags & checkedFlags ) !== NoFlags
205
220
) {
206
221
return true ;
207
222
}
@@ -450,6 +465,7 @@ function updateHostComponent(
450
465
451
466
let newChildSet = null ;
452
467
if ( requiresClone && passChildrenWhenCloningPersistedNodes ) {
468
+ markCloned ( workInProgress ) ;
453
469
newChildSet = createContainerChildSet ( ) ;
454
470
// If children might have changed, we have to add them all to the set.
455
471
appendAllChildrenToContainer (
@@ -473,6 +489,8 @@ function updateHostComponent(
473
489
// Note that this might release a previous clone.
474
490
workInProgress . stateNode = currentInstance ;
475
491
return ;
492
+ } else {
493
+ markCloned ( workInProgress ) ;
476
494
}
477
495
478
496
// Certain renderers require commit-time effects for initial mount.
@@ -485,12 +503,14 @@ function updateHostComponent(
485
503
}
486
504
workInProgress . stateNode = newInstance ;
487
505
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
+ }
492
512
} 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.
494
514
appendAllChildren (
495
515
newInstance ,
496
516
workInProgress ,
@@ -618,15 +638,18 @@ function updateHostText(
618
638
// If the text content differs, we'll create a new text instance for it.
619
639
const rootContainerInstance = getRootHostContainer ( ) ;
620
640
const currentHostContext = getHostContext ( ) ;
641
+ markCloned ( workInProgress ) ;
621
642
workInProgress . stateNode = createTextInstance (
622
643
newText ,
623
644
rootContainerInstance ,
624
645
currentHostContext ,
625
646
workInProgress ,
626
647
) ;
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
+ }
630
653
} else {
631
654
workInProgress . stateNode = current . stateNode ;
632
655
}
@@ -1229,6 +1252,7 @@ function completeWork(
1229
1252
) ;
1230
1253
// TODO: For persistent renderers, we should pass children as part
1231
1254
// of the initial instance creation
1255
+ markCloned ( workInProgress ) ;
1232
1256
appendAllChildren ( instance , workInProgress , false , false ) ;
1233
1257
workInProgress . stateNode = instance ;
1234
1258
@@ -1284,6 +1308,7 @@ function completeWork(
1284
1308
if ( wasHydrated ) {
1285
1309
prepareToHydrateHostTextInstance ( workInProgress ) ;
1286
1310
} else {
1311
+ markCloned ( workInProgress ) ;
1287
1312
workInProgress . stateNode = createTextInstance (
1288
1313
newText ,
1289
1314
rootContainerInstance ,
0 commit comments