@@ -246,6 +246,12 @@ function warnOnFunctionType(returnFiber: Fiber) {
246246 }
247247}
248248
249+ function resolveLazy ( lazyType ) {
250+ const payload = lazyType . _payload ;
251+ const init = lazyType . _init ;
252+ return init ( payload ) ;
253+ }
254+
249255// This wrapper function exists because I expect to clone the code in each path
250256// to be able to optimize each path individually by branching early. This needs
251257// a compiler or we can do it manually. Helpers that don't need this branching
@@ -383,11 +389,32 @@ function ChildReconciler(shouldTrackSideEffects) {
383389 element : ReactElement ,
384390 lanes : Lanes ,
385391 ) : Fiber {
392+ const elementType = element . type ;
393+ if ( elementType === REACT_FRAGMENT_TYPE ) {
394+ return updateFragment (
395+ returnFiber ,
396+ current ,
397+ element . props . children ,
398+ lanes ,
399+ element . key ,
400+ ) ;
401+ }
386402 if ( current !== null ) {
387403 if (
388- current . elementType === element . type ||
404+ current . elementType === elementType ||
389405 // Keep this check inline so it only runs on the false path:
390- ( __DEV__ ? isCompatibleFamilyForHotReloading ( current , element ) : false )
406+ ( __DEV__
407+ ? isCompatibleFamilyForHotReloading ( current , element )
408+ : false ) ||
409+ // Lazy types should reconcile their resolved type.
410+ // We need to do this after the Hot Reloading check above,
411+ // because hot reloading has different semantics than prod because
412+ // it doesn't resuspend. So we can't let the call below suspend.
413+ ( enableLazyElements &&
414+ typeof elementType === 'object' &&
415+ elementType !== null &&
416+ elementType . $$typeof === REACT_LAZY_TYPE &&
417+ resolveLazy ( elementType ) === current . type )
391418 ) {
392419 // Move based on index
393420 const existing = useFiber ( current , element . props ) ;
@@ -551,15 +578,6 @@ function ChildReconciler(shouldTrackSideEffects) {
551578 switch ( newChild . $$typeof ) {
552579 case REACT_ELEMENT_TYPE : {
553580 if ( newChild . key === key ) {
554- if ( newChild . type === REACT_FRAGMENT_TYPE ) {
555- return updateFragment (
556- returnFiber ,
557- oldFiber ,
558- newChild . props . children ,
559- lanes ,
560- key ,
561- ) ;
562- }
563581 return updateElement ( returnFiber , oldFiber , newChild , lanes ) ;
564582 } else {
565583 return null ;
@@ -622,15 +640,6 @@ function ChildReconciler(shouldTrackSideEffects) {
622640 existingChildren . get (
623641 newChild . key === null ? newIdx : newChild . key ,
624642 ) || null ;
625- if ( newChild . type === REACT_FRAGMENT_TYPE ) {
626- return updateFragment (
627- returnFiber ,
628- matchedFiber ,
629- newChild . props . children ,
630- lanes ,
631- newChild . key ,
632- ) ;
633- }
634643 return updateElement ( returnFiber , matchedFiber , newChild , lanes ) ;
635644 }
636645 case REACT_PORTAL_TYPE : {
@@ -1101,39 +1110,44 @@ function ChildReconciler(shouldTrackSideEffects) {
11011110 // TODO: If key === null and child.key === null, then this only applies to
11021111 // the first item in the list.
11031112 if ( child . key === key ) {
1104- switch ( child . tag ) {
1105- case Fragment : {
1106- if ( element . type === REACT_FRAGMENT_TYPE ) {
1107- deleteRemainingChildren ( returnFiber , child . sibling ) ;
1108- const existing = useFiber ( child , element . props . children ) ;
1109- existing . return = returnFiber ;
1110- if ( __DEV__ ) {
1111- existing . _debugSource = element . _source ;
1112- existing . _debugOwner = element . _owner ;
1113- }
1114- return existing ;
1113+ const elementType = element . type ;
1114+ if ( elementType === REACT_FRAGMENT_TYPE ) {
1115+ if ( child . tag === Fragment ) {
1116+ deleteRemainingChildren ( returnFiber , child . sibling ) ;
1117+ const existing = useFiber ( child , element . props . children ) ;
1118+ existing . return = returnFiber ;
1119+ if ( __DEV__ ) {
1120+ existing . _debugSource = element . _source ;
1121+ existing . _debugOwner = element . _owner ;
11151122 }
1116- break ;
1123+ return existing ;
11171124 }
1118- default : {
1119- if (
1120- child . elementType === element . type ||
1121- // Keep this check inline so it only runs on the false path:
1122- ( __DEV__
1123- ? isCompatibleFamilyForHotReloading ( child , element )
1124- : false )
1125- ) {
1126- deleteRemainingChildren ( returnFiber , child . sibling ) ;
1127- const existing = useFiber ( child , element . props ) ;
1128- existing . ref = coerceRef ( returnFiber , child , element ) ;
1129- existing . return = returnFiber ;
1130- if ( __DEV__ ) {
1131- existing . _debugSource = element . _source ;
1132- existing . _debugOwner = element . _owner ;
1133- }
1134- return existing ;
1125+ } else {
1126+ if (
1127+ child . elementType === elementType ||
1128+ // Keep this check inline so it only runs on the false path:
1129+ ( __DEV__
1130+ ? isCompatibleFamilyForHotReloading ( child , element )
1131+ : false ) ||
1132+ // Lazy types should reconcile their resolved type.
1133+ // We need to do this after the Hot Reloading check above,
1134+ // because hot reloading has different semantics than prod because
1135+ // it doesn't resuspend. So we can't let the call below suspend.
1136+ ( enableLazyElements &&
1137+ typeof elementType === 'object' &&
1138+ elementType !== null &&
1139+ elementType . $$typeof === REACT_LAZY_TYPE &&
1140+ resolveLazy ( elementType ) === child . type )
1141+ ) {
1142+ deleteRemainingChildren ( returnFiber , child . sibling ) ;
1143+ const existing = useFiber ( child , element . props ) ;
1144+ existing . ref = coerceRef ( returnFiber , child , element ) ;
1145+ existing . return = returnFiber ;
1146+ if ( __DEV__ ) {
1147+ existing . _debugSource = element . _source ;
1148+ existing . _debugOwner = element . _owner ;
11351149 }
1136- break ;
1150+ return existing ;
11371151 }
11381152 }
11391153 // Didn't match.
0 commit comments