11import { ReactElementType } from 'shared/ReactTypes' ;
22import { mountChildFibers , reconcileChildFibers } from './childFibers' ;
3- import { FiberNode } from './fiber' ;
3+ import {
4+ FiberNode ,
5+ createFiberFromFragment ,
6+ createWorkInProgress ,
7+ createFiberFromOffscreen ,
8+ OffscreenProps
9+ } from './fiber' ;
410import { renderWithHooks } from './fiberHooks' ;
511import { Lane } from './fiberLanes' ;
612import { processUpdateQueue , UpdateQueue } from './updateQueue' ;
@@ -10,10 +16,19 @@ import {
1016 FunctionComponent ,
1117 HostComponent ,
1218 HostRoot ,
13- HostText
19+ HostText ,
20+ OffscreenComponent ,
21+ SuspenseComponent
1422} from './workTags' ;
15- import { Ref } from './fiberFlags' ;
23+ import {
24+ Ref ,
25+ NoFlags ,
26+ DidCapture ,
27+ Placement ,
28+ ChildDeletion
29+ } from './fiberFlags' ;
1630import { pushProvider } from './fiberContext' ;
31+ import { pushSuspenseHandler } from './suspenseContext' ;
1732
1833// 递归中的递阶段
1934export const beginWork = ( wip : FiberNode , renderLane : Lane ) => {
@@ -31,6 +46,10 @@ export const beginWork = (wip: FiberNode, renderLane: Lane) => {
3146 return updateFragment ( wip ) ;
3247 case ContextProvider :
3348 return updateContextProvider ( wip ) ;
49+ case SuspenseComponent :
50+ return updateSuspenseComponent ( wip ) ;
51+ case OffscreenComponent :
52+ return updateOffscreenComponent ( wip ) ;
3453 default :
3554 if ( __DEV__ ) {
3655 console . warn ( 'beginWork未实现的类型' ) ;
@@ -72,6 +91,12 @@ function updateHostRoot(wip: FiberNode, renderLane: Lane) {
7291 const { memoizedState } = processUpdateQueue ( baseState , pending , renderLane ) ;
7392 wip . memoizedState = memoizedState ;
7493
94+ const current = wip . alternate ;
95+ // 考虑RootDidNotComplete的情况,需要复用memoizedState
96+ if ( current !== null ) {
97+ current . memoizedState = memoizedState ;
98+ }
99+
75100 const nextChildren = wip . memoizedState ;
76101 reconcileChildren ( wip , nextChildren ) ;
77102 return wip . child ;
@@ -107,3 +132,157 @@ function markRef(current: FiberNode | null, workInProgress: FiberNode) {
107132 workInProgress . flags |= Ref ;
108133 }
109134}
135+
136+ function updateOffscreenComponent ( workInProgress : FiberNode ) {
137+ const nextProps = workInProgress . pendingProps ;
138+ const nextChildren = nextProps . children ;
139+ reconcileChildren ( workInProgress , nextChildren ) ;
140+ return workInProgress . child ;
141+ }
142+
143+ function updateSuspenseComponent ( workInProgress : FiberNode ) {
144+ const current = workInProgress . alternate ;
145+ const nextProps = workInProgress . pendingProps ;
146+
147+ let showFallback = false ;
148+ const didSuspend = ( workInProgress . flags & DidCapture ) !== NoFlags ;
149+
150+ if ( didSuspend ) {
151+ showFallback = true ;
152+ workInProgress . flags &= ~ DidCapture ;
153+ }
154+ const nextPrimaryChildren = nextProps . children ;
155+ const nextFallbackChildren = nextProps . fallback ;
156+ pushSuspenseHandler ( workInProgress ) ;
157+
158+ if ( current === null ) {
159+ if ( showFallback ) {
160+ return mountSuspenseFallbackChildren (
161+ workInProgress ,
162+ nextPrimaryChildren ,
163+ nextFallbackChildren
164+ ) ;
165+ } else {
166+ return mountSuspensePrimaryChildren ( workInProgress , nextPrimaryChildren ) ;
167+ }
168+ } else {
169+ if ( showFallback ) {
170+ return updateSuspenseFallbackChildren (
171+ workInProgress ,
172+ nextPrimaryChildren ,
173+ nextFallbackChildren
174+ ) ;
175+ } else {
176+ return updateSuspensePrimaryChildren ( workInProgress , nextPrimaryChildren ) ;
177+ }
178+ }
179+ }
180+
181+ function mountSuspensePrimaryChildren (
182+ workInProgress : FiberNode ,
183+ primaryChildren : any
184+ ) {
185+ const primaryChildProps : OffscreenProps = {
186+ mode : 'visible' ,
187+ children : primaryChildren
188+ } ;
189+ const primaryChildFragment = createFiberFromOffscreen ( primaryChildProps ) ;
190+ workInProgress . child = primaryChildFragment ;
191+ primaryChildFragment . return = workInProgress ;
192+ return primaryChildFragment ;
193+ }
194+
195+ function mountSuspenseFallbackChildren (
196+ workInProgress : FiberNode ,
197+ primaryChildren : any ,
198+ fallbackChildren : any
199+ ) {
200+ const primaryChildProps : OffscreenProps = {
201+ mode : 'hidden' ,
202+ children : primaryChildren
203+ } ;
204+ const primaryChildFragment = createFiberFromOffscreen ( primaryChildProps ) ;
205+ const fallbackChildFragment = createFiberFromFragment ( fallbackChildren , null ) ;
206+ // 父组件Suspense已经mount,所以需要fallback标记Placement
207+ fallbackChildFragment . flags |= Placement ;
208+
209+ primaryChildFragment . return = workInProgress ;
210+ fallbackChildFragment . return = workInProgress ;
211+ primaryChildFragment . sibling = fallbackChildFragment ;
212+ workInProgress . child = primaryChildFragment ;
213+
214+ return fallbackChildFragment ;
215+ }
216+
217+ function updateSuspensePrimaryChildren (
218+ workInProgress : FiberNode ,
219+ primaryChildren : any
220+ ) {
221+ const current = workInProgress . alternate as FiberNode ;
222+ const currentPrimaryChildFragment = current . child as FiberNode ;
223+ const currentFallbackChildFragment : FiberNode | null =
224+ currentPrimaryChildFragment . sibling ;
225+
226+ const primaryChildProps : OffscreenProps = {
227+ mode : 'visible' ,
228+ children : primaryChildren
229+ } ;
230+
231+ const primaryChildFragment = createWorkInProgress (
232+ currentPrimaryChildFragment ,
233+ primaryChildProps
234+ ) ;
235+ primaryChildFragment . return = workInProgress ;
236+ primaryChildFragment . sibling = null ;
237+ workInProgress . child = primaryChildFragment ;
238+
239+ if ( currentFallbackChildFragment !== null ) {
240+ const deletions = workInProgress . deletions ;
241+ if ( deletions === null ) {
242+ workInProgress . deletions = [ currentFallbackChildFragment ] ;
243+ workInProgress . flags |= ChildDeletion ;
244+ } else {
245+ deletions . push ( currentFallbackChildFragment ) ;
246+ }
247+ }
248+
249+ return primaryChildFragment ;
250+ }
251+
252+ function updateSuspenseFallbackChildren (
253+ workInProgress : FiberNode ,
254+ primaryChildren : any ,
255+ fallbackChildren : any
256+ ) {
257+ const current = workInProgress . alternate as FiberNode ;
258+ const currentPrimaryChildFragment = current . child as FiberNode ;
259+ const currentFallbackChildFragment : FiberNode | null =
260+ currentPrimaryChildFragment . sibling ;
261+
262+ const primaryChildProps : OffscreenProps = {
263+ mode : 'hidden' ,
264+ children : primaryChildren
265+ } ;
266+ const primaryChildFragment = createWorkInProgress (
267+ currentPrimaryChildFragment ,
268+ primaryChildProps
269+ ) ;
270+ let fallbackChildFragment ;
271+
272+ if ( currentFallbackChildFragment !== null ) {
273+ // 可以复用
274+ fallbackChildFragment = createWorkInProgress (
275+ currentFallbackChildFragment ,
276+ fallbackChildren
277+ ) ;
278+ } else {
279+ fallbackChildFragment = createFiberFromFragment ( fallbackChildren , null ) ;
280+ fallbackChildFragment . flags |= Placement ;
281+ }
282+ fallbackChildFragment . return = workInProgress ;
283+ primaryChildFragment . return = workInProgress ;
284+ primaryChildFragment . sibling = fallbackChildFragment ;
285+ workInProgress . child = primaryChildFragment ;
286+
287+ return fallbackChildFragment ;
288+ }
0 commit comments