@@ -30,11 +30,15 @@ import {
30
30
Mode ,
31
31
ContextProvider ,
32
32
ContextConsumer ,
33
+ LoadingComponent ,
34
+ TimeoutComponent ,
33
35
} from 'shared/ReactTypeOfWork' ;
34
36
import {
37
+ NoEffect ,
35
38
PerformedWork ,
36
39
Placement ,
37
40
ContentReset ,
41
+ DidCapture ,
38
42
Ref ,
39
43
} from 'shared/ReactTypeOfSideEffect' ;
40
44
import { ReactCurrentOwner } from 'shared/ReactGlobalSharedState' ;
@@ -83,8 +87,16 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
83
87
config : HostConfig < T , P , I , TI , HI , PI , C , CC , CX , PL > ,
84
88
hostContext : HostContext < C , CX > ,
85
89
hydrationContext : HydrationContext < C , CX > ,
86
- scheduleWork : ( fiber : Fiber , expirationTime : ExpirationTime ) = > void ,
87
- computeExpirationForFiber : ( fiber : Fiber ) = > ExpirationTime ,
90
+ scheduleWork : (
91
+ fiber : Fiber ,
92
+ startTime : ExpirationTime ,
93
+ expirationTime : ExpirationTime ,
94
+ ) = > void ,
95
+ computeExpirationForFiber : (
96
+ startTime : ExpirationTime ,
97
+ fiber : Fiber ,
98
+ ) = > ExpirationTime ,
99
+ recalculateCurrentTime : ( ) = > ExpirationTime ,
88
100
) {
89
101
const { shouldSetTextContent, shouldDeprioritizeSubtree} = config ;
90
102
@@ -108,6 +120,7 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
108
120
computeExpirationForFiber ,
109
121
memoizeProps ,
110
122
memoizeState ,
123
+ recalculateCurrentTime ,
111
124
) ;
112
125
113
126
// TODO: Remove this and use reconcileChildrenAtExpirationTime directly.
@@ -704,6 +717,98 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
704
717
return workInProgress . stateNode ;
705
718
}
706
719
720
+ function updateLoadingComponent (
721
+ current ,
722
+ workInProgress ,
723
+ renderExpirationTime ,
724
+ ) {
725
+ const nextProps = workInProgress . pendingProps ;
726
+ const prevProps = workInProgress . memoizedProps ;
727
+
728
+ let nextState = workInProgress . memoizedState ;
729
+ if ( nextState === null ) {
730
+ nextState = workInProgress . memoizedState = false ;
731
+ }
732
+ const prevState = current === null ? nextState : current . memoizedState ;
733
+
734
+ const updateQueue = workInProgress . updateQueue ;
735
+ if ( updateQueue !== null ) {
736
+ nextState = workInProgress . memoizedState = processUpdateQueue (
737
+ current ,
738
+ workInProgress ,
739
+ updateQueue ,
740
+ null ,
741
+ nextProps ,
742
+ renderExpirationTime ,
743
+ ) ;
744
+ }
745
+
746
+ const isLoading = nextState ;
747
+ if ( hasLegacyContextChanged ( ) ) {
748
+ // Normally we can bail out on props equality but if context has changed
749
+ // we don't do the bailout and we have to reuse existing props instead.
750
+ } else if ( prevProps === nextProps && prevState === nextState ) {
751
+ return bailoutOnAlreadyFinishedWork ( current , workInProgress ) ;
752
+ }
753
+
754
+ const render = nextProps . children ;
755
+ const nextChildren = render ( isLoading ) ;
756
+ workInProgress . memoizedProps = nextProps ;
757
+ reconcileChildren ( current , workInProgress , nextChildren ) ;
758
+ return workInProgress . child ;
759
+ }
760
+
761
+ function updateTimeoutComponent (
762
+ current ,
763
+ workInProgress ,
764
+ renderExpirationTime ,
765
+ ) {
766
+ const nextProps = workInProgress . pendingProps ;
767
+ const prevProps = workInProgress . memoizedProps ;
768
+
769
+ let nextState = workInProgress . memoizedState ;
770
+ if ( nextState === null ) {
771
+ nextState = workInProgress . memoizedState = false ;
772
+ }
773
+ const prevState = current === null ? nextState : current . memoizedState ;
774
+
775
+ const updateQueue = workInProgress . updateQueue ;
776
+ if ( updateQueue !== null ) {
777
+ nextState = workInProgress . memoizedState = processUpdateQueue (
778
+ current ,
779
+ workInProgress ,
780
+ updateQueue ,
781
+ null ,
782
+ null ,
783
+ renderExpirationTime ,
784
+ ) ;
785
+ }
786
+
787
+ if ( hasLegacyContextChanged ( ) ) {
788
+ // Normally we can bail out on props equality but if context has changed
789
+ // we don't do the bailout and we have to reuse existing props instead.
790
+ } else if (
791
+ // Don't bail out if this is a restart
792
+ ( workInProgress . effectTag & DidCapture ) === NoEffect &&
793
+ prevProps === nextProps &&
794
+ prevState === nextState
795
+ ) {
796
+ return bailoutOnAlreadyFinishedWork ( current , workInProgress ) ;
797
+ }
798
+
799
+ if ( ( workInProgress . effectTag & DidCapture ) !== NoEffect ) {
800
+ nextState = workInProgress . memoizedState = true ;
801
+ }
802
+
803
+ const isExpired = nextState ;
804
+ const render = nextProps . children ;
805
+ const nextChildren = render ( isExpired ) ;
806
+ workInProgress . memoizedProps = nextProps ;
807
+ workInProgress . memoizedState = nextState ;
808
+ reconcileChildren ( current , workInProgress , nextChildren ) ;
809
+ return workInProgress . child ;
810
+ }
811
+
707
812
function updatePortalComponent (
708
813
current ,
709
814
workInProgress ,
@@ -1080,6 +1185,18 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
1080
1185
// A return component is just a placeholder, we can just run through the
1081
1186
// next one immediately.
1082
1187
return null ;
1188
+ case LoadingComponent :
1189
+ return updateLoadingComponent (
1190
+ current ,
1191
+ workInProgress ,
1192
+ renderExpirationTime ,
1193
+ ) ;
1194
+ case TimeoutComponent :
1195
+ return updateTimeoutComponent (
1196
+ current ,
1197
+ workInProgress ,
1198
+ renderExpirationTime ,
1199
+ ) ;
1083
1200
case HostPortal :
1084
1201
return updatePortalComponent (
1085
1202
current ,
0 commit comments