@@ -288,27 +288,37 @@ function reconcile(
288
288
nextChildren ,
289
289
nextProps ,
290
290
nextState ,
291
+ false ,
291
292
renderPriority ,
292
293
) ;
293
294
return child ;
294
295
}
295
296
exports . reconcile = reconcile ;
296
297
297
- // Split this out so that it can be shared between the normal reconcile
298
- // function and beginCoroutineComponent, which reconciles against a child
299
- // that is stored on the stateNode.
298
+ // Lower level version of reconcile function with more options for special
299
+ // cases. My thinking is that, for now, this is preferable to forking, because
300
+ // it's really easy to mess up when keeping the forks in sync.
301
+ // TODO: Unify this with reconcileChildFibers constructor?
300
302
function reconcileImpl (
301
303
current : Fiber | null ,
302
304
workInProgress : Fiber ,
303
305
child : Fiber | null , // Child to reconcile against
304
306
nextChildren : any ,
305
307
nextProps : any | null ,
306
308
nextState : mixed | null ,
309
+ forceMountInPlace : boolean ,
307
310
renderPriority : PriorityLevel ,
308
311
) : Fiber | null {
309
312
// We have new children. Update the child set.
310
313
let newChild ;
311
- if ( current === null ) {
314
+ if ( forceMountInPlace ) {
315
+ newChild = mountChildFibersInPlace (
316
+ workInProgress ,
317
+ child ,
318
+ nextChildren ,
319
+ renderPriority ,
320
+ ) ;
321
+ } else if ( current === null ) {
312
322
if ( workInProgress . tag === HostPortal ) {
313
323
// Portals are special because we don't append the children during mount
314
324
// but at commit. Therefore we need to track insertions which the normal
@@ -514,7 +524,7 @@ function resumeOrResetWork(
514
524
const BeginWork = function < T , P , I , TI , PI , C , CX , PL > (
515
525
config : HostConfig < T , P , I , TI , PI , C , CX , PL > ,
516
526
hostContext : HostContext < C , CX > ,
517
- hydrationContext : HydrationContext ,
527
+ hydrationContext : HydrationContext < I , TI > ,
518
528
scheduleUpdate : ( fiber : Fiber , priorityLevel : PriorityLevel ) => void ,
519
529
getPriorityContext : ( fiber : Fiber , forceAsync : boolean ) => PriorityLevel ,
520
530
) {
@@ -527,6 +537,12 @@ const BeginWork = function<T, P, I, TI, PI, C, CX, PL>(
527
537
const { pushHostContext, pushHostContainer} = hostContext ;
528
538
const classUpdater = ClassUpdater ( scheduleUpdate , getPriorityContext ) ;
529
539
540
+ const {
541
+ enterHydrationState,
542
+ resetHydrationState,
543
+ tryToClaimNextHydratableInstance,
544
+ } = hydrationContext ;
545
+
530
546
function checkForUpdatedRef ( current : Fiber | null , workInProgress : Fiber ) {
531
547
const ref = workInProgress . ref ;
532
548
if ( ref !== null && ( current === null || current . ref !== ref ) ) {
@@ -578,6 +594,7 @@ const BeginWork = function<T, P, I, TI, PI, C, CX, PL>(
578
594
if ( nextState === memoizedState ) {
579
595
// No new state. The root doesn't have props. Bailout.
580
596
// TODO: What about context?
597
+ resetHydrationState ( ) ;
581
598
return bailout (
582
599
current ,
583
600
workInProgress ,
@@ -589,15 +606,44 @@ const BeginWork = function<T, P, I, TI, PI, C, CX, PL>(
589
606
590
607
// The state was updated. We have a new element.
591
608
const nextChildren = nextState . element ;
609
+
610
+ // If we don't have any current children this might be the first pass.
611
+ // We always try to hydrate. If this isn't a hydration pass there won't
612
+ // be any children to hydrate which is effectively the same thing as
613
+ // not hydrating.
614
+ let forceMountInPlace ;
615
+ if (
616
+ ( current === null || current . child === null ) &&
617
+ enterHydrationState ( workInProgress )
618
+ ) {
619
+ // Ensure that children mount into this root without tracking
620
+ // side-effects. This ensures that we don't store Placement effects on
621
+ // nodes that will be hydrated.
622
+ forceMountInPlace = true ;
623
+
624
+ // This is a bit of a hack. We track the host root as a placement to
625
+ // know that we're currently in a mounting state. That way isMounted
626
+ // works as expected. We must reset this before committing.
627
+ // TODO: Delete this when we delete isMounted and findDOMNode.
628
+ workInProgress . effectTag |= Placement ;
629
+ } else {
630
+ // Otherwise, reset the hydration state
631
+ resetHydrationState ( ) ;
632
+ forceMountInPlace = false ;
633
+ }
634
+
592
635
// Reconcile the children.
593
- return reconcile (
636
+ const child = workInProgress . child = reconcileImpl (
594
637
current ,
595
638
workInProgress ,
639
+ workInProgress . child ,
596
640
nextChildren ,
597
641
null ,
598
642
nextState ,
643
+ forceMountInPlace ,
599
644
renderPriority ,
600
645
) ;
646
+ return child ;
601
647
}
602
648
603
649
function beginHostPortal (
@@ -632,6 +678,10 @@ const BeginWork = function<T, P, I, TI, PI, C, CX, PL>(
632
678
) : Fiber | null {
633
679
pushHostContext ( workInProgress ) ;
634
680
681
+ if ( current === null ) {
682
+ tryToClaimNextHydratableInstance ( workInProgress ) ;
683
+ }
684
+
635
685
const memoizedProps = workInProgress . memoizedProps ;
636
686
637
687
// Check if the ref has changed and schedule an effect. This should happen
@@ -698,6 +748,10 @@ const BeginWork = function<T, P, I, TI, PI, C, CX, PL>(
698
748
nextProps : any ,
699
749
renderPriority : PriorityLevel ,
700
750
) : Fiber | null {
751
+ if ( current === null ) {
752
+ tryToClaimNextHydratableInstance ( workInProgress ) ;
753
+ }
754
+
701
755
const memoizedProps = workInProgress . memoizedProps ;
702
756
if ( nextProps === memoizedProps ) {
703
757
return bailout ( current , workInProgress , nextProps , null , renderPriority ) ;
@@ -1297,6 +1351,7 @@ const BeginWork = function<T, P, I, TI, PI, C, CX, PL>(
1297
1351
nextCoroutine . children ,
1298
1352
nextCoroutine ,
1299
1353
null ,
1354
+ false ,
1300
1355
renderPriority ,
1301
1356
) ;
1302
1357
return child ;
0 commit comments