@@ -288,27 +288,37 @@ function reconcile(
288288 nextChildren ,
289289 nextProps ,
290290 nextState ,
291+ false ,
291292 renderPriority ,
292293 ) ;
293294 return child ;
294295}
295296exports . reconcile = reconcile ;
296297
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?
300302function reconcileImpl (
301303 current : Fiber | null ,
302304 workInProgress : Fiber ,
303305 child : Fiber | null , // Child to reconcile against
304306 nextChildren : any ,
305307 nextProps : any | null ,
306308 nextState : mixed | null ,
309+ forceMountInPlace : boolean ,
307310 renderPriority : PriorityLevel ,
308311) : Fiber | null {
309312 // We have new children. Update the child set.
310313 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 ) {
312322 if ( workInProgress . tag === HostPortal ) {
313323 // Portals are special because we don't append the children during mount
314324 // but at commit. Therefore we need to track insertions which the normal
@@ -514,7 +524,7 @@ function resumeOrResetWork(
514524const BeginWork = function < T , P , I , TI , PI , C , CX , PL > (
515525 config : HostConfig < T , P , I , TI , PI , C , CX , PL > ,
516526 hostContext : HostContext < C , CX > ,
517- hydrationContext : HydrationContext ,
527+ hydrationContext : HydrationContext < I , TI > ,
518528 scheduleUpdate : ( fiber : Fiber , priorityLevel : PriorityLevel ) => void ,
519529 getPriorityContext : ( fiber : Fiber , forceAsync : boolean ) => PriorityLevel ,
520530) {
@@ -527,6 +537,12 @@ const BeginWork = function<T, P, I, TI, PI, C, CX, PL>(
527537 const { pushHostContext, pushHostContainer} = hostContext ;
528538 const classUpdater = ClassUpdater ( scheduleUpdate , getPriorityContext ) ;
529539
540+ const {
541+ enterHydrationState,
542+ resetHydrationState,
543+ tryToClaimNextHydratableInstance,
544+ } = hydrationContext ;
545+
530546 function checkForUpdatedRef ( current : Fiber | null , workInProgress : Fiber ) {
531547 const ref = workInProgress . ref ;
532548 if ( ref !== null && ( current === null || current . ref !== ref ) ) {
@@ -578,6 +594,7 @@ const BeginWork = function<T, P, I, TI, PI, C, CX, PL>(
578594 if ( nextState === memoizedState ) {
579595 // No new state. The root doesn't have props. Bailout.
580596 // TODO: What about context?
597+ resetHydrationState ( ) ;
581598 return bailout (
582599 current ,
583600 workInProgress ,
@@ -589,15 +606,44 @@ const BeginWork = function<T, P, I, TI, PI, C, CX, PL>(
589606
590607 // The state was updated. We have a new element.
591608 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+
592635 // Reconcile the children.
593- return reconcile (
636+ const child = workInProgress . child = reconcileImpl (
594637 current ,
595638 workInProgress ,
639+ workInProgress . child ,
596640 nextChildren ,
597641 null ,
598642 nextState ,
643+ forceMountInPlace ,
599644 renderPriority ,
600645 ) ;
646+ return child ;
601647 }
602648
603649 function beginHostPortal (
@@ -632,6 +678,10 @@ const BeginWork = function<T, P, I, TI, PI, C, CX, PL>(
632678 ) : Fiber | null {
633679 pushHostContext ( workInProgress ) ;
634680
681+ if ( current === null ) {
682+ tryToClaimNextHydratableInstance ( workInProgress ) ;
683+ }
684+
635685 const memoizedProps = workInProgress . memoizedProps ;
636686
637687 // 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>(
698748 nextProps : any ,
699749 renderPriority : PriorityLevel ,
700750 ) : Fiber | null {
751+ if ( current === null ) {
752+ tryToClaimNextHydratableInstance ( workInProgress ) ;
753+ }
754+
701755 const memoizedProps = workInProgress . memoizedProps ;
702756 if ( nextProps === memoizedProps ) {
703757 return bailout ( current , workInProgress , nextProps , null , renderPriority ) ;
@@ -1297,6 +1351,7 @@ const BeginWork = function<T, P, I, TI, PI, C, CX, PL>(
12971351 nextCoroutine . children ,
12981352 nextCoroutine ,
12991353 null ,
1354+ false ,
13001355 renderPriority ,
13011356 ) ;
13021357 return child ;
0 commit comments