@@ -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 ,
@@ -89,6 +90,7 @@ import {
89
90
MaySuspendCommit ,
90
91
ScheduleRetry ,
91
92
ShouldSuspendCommit ,
93
+ Cloned ,
92
94
} from './ReactFiberFlags' ;
93
95
94
96
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
}
@@ -451,6 +466,7 @@ function updateHostComponent(
451
466
452
467
let newChildSet = null ;
453
468
if ( requiresClone && passChildrenWhenCloningPersistedNodes ) {
469
+ markCloned ( workInProgress ) ;
454
470
newChildSet = createContainerChildSet ( ) ;
455
471
// If children might have changed, we have to add them all to the set.
456
472
appendAllChildrenToContainer (
@@ -474,6 +490,8 @@ function updateHostComponent(
474
490
// Note that this might release a previous clone.
475
491
workInProgress . stateNode = currentInstance ;
476
492
return ;
493
+ } else {
494
+ markCloned ( workInProgress ) ;
477
495
}
478
496
479
497
// Certain renderers require commit-time effects for initial mount.
@@ -486,12 +504,14 @@ function updateHostComponent(
486
504
}
487
505
workInProgress . stateNode = newInstance ;
488
506
if ( ! requiresClone ) {
489
- // If there are no other effects in this tree, we need to flag this node as having one.
490
- // Even though we're not going to use it for anything.
491
- // Otherwise parents won't know that there are new children to propagate upwards.
492
- markUpdate ( workInProgress ) ;
507
+ if ( ! enablePersistedModeClonedFlag ) {
508
+ // If there are no other effects in this tree, we need to flag this node as having one.
509
+ // Even though we're not going to use it for anything.
510
+ // Otherwise parents won't know that there are new children to propagate upwards.
511
+ markUpdate ( workInProgress ) ;
512
+ }
493
513
} else if ( ! passChildrenWhenCloningPersistedNodes ) {
494
- // If children might have changed, we have to add them all to the set.
514
+ // If children have changed, we have to add them all to the set.
495
515
appendAllChildren (
496
516
newInstance ,
497
517
workInProgress ,
@@ -650,15 +670,18 @@ function updateHostText(
650
670
// If the text content differs, we'll create a new text instance for it.
651
671
const rootContainerInstance = getRootHostContainer ( ) ;
652
672
const currentHostContext = getHostContext ( ) ;
673
+ markCloned ( workInProgress ) ;
653
674
workInProgress . stateNode = createTextInstance (
654
675
newText ,
655
676
rootContainerInstance ,
656
677
currentHostContext ,
657
678
workInProgress ,
658
679
) ;
659
- // We'll have to mark it as having an effect, even though we won't use the effect for anything.
660
- // This lets the parents know that at least one of their children has changed.
661
- markUpdate ( workInProgress ) ;
680
+ if ( ! enablePersistedModeClonedFlag ) {
681
+ // We'll have to mark it as having an effect, even though we won't use the effect for anything.
682
+ // This lets the parents know that at least one of their children has changed.
683
+ markUpdate ( workInProgress ) ;
684
+ }
662
685
} else {
663
686
workInProgress . stateNode = current . stateNode ;
664
687
}
@@ -1254,6 +1277,7 @@ function completeWork(
1254
1277
) ;
1255
1278
// TODO: For persistent renderers, we should pass children as part
1256
1279
// of the initial instance creation
1280
+ markCloned ( workInProgress ) ;
1257
1281
appendAllChildren ( instance , workInProgress , false , false ) ;
1258
1282
workInProgress . stateNode = instance ;
1259
1283
@@ -1311,6 +1335,7 @@ function completeWork(
1311
1335
markUpdate ( workInProgress ) ;
1312
1336
}
1313
1337
} else {
1338
+ markCloned ( workInProgress ) ;
1314
1339
workInProgress . stateNode = createTextInstance (
1315
1340
newText ,
1316
1341
rootContainerInstance ,
0 commit comments