1
1
import { ReactElementType } from 'shared/ReactTypes' ;
2
2
import { mountChildFibers , reconcileChildFibers } from './childFibers' ;
3
- import { FiberNode } from './fiber' ;
3
+ import {
4
+ FiberNode ,
5
+ createFiberFromFragment ,
6
+ createWorkInProgress ,
7
+ createFiberFromOffscreen ,
8
+ OffscreenProps
9
+ } from './fiber' ;
4
10
import { renderWithHooks } from './fiberHooks' ;
5
11
import { Lane } from './fiberLanes' ;
6
12
import { processUpdateQueue , UpdateQueue } from './updateQueue' ;
@@ -10,10 +16,19 @@ import {
10
16
FunctionComponent ,
11
17
HostComponent ,
12
18
HostRoot ,
13
- HostText
19
+ HostText ,
20
+ OffscreenComponent ,
21
+ SuspenseComponent
14
22
} from './workTags' ;
15
- import { Ref } from './fiberFlags' ;
23
+ import {
24
+ Ref ,
25
+ NoFlags ,
26
+ DidCapture ,
27
+ Placement ,
28
+ ChildDeletion
29
+ } from './fiberFlags' ;
16
30
import { pushProvider } from './fiberContext' ;
31
+ import { pushSuspenseHandler } from './suspenseContext' ;
17
32
18
33
// 递归中的递阶段
19
34
export const beginWork = ( wip : FiberNode , renderLane : Lane ) => {
@@ -31,6 +46,10 @@ export const beginWork = (wip: FiberNode, renderLane: Lane) => {
31
46
return updateFragment ( wip ) ;
32
47
case ContextProvider :
33
48
return updateContextProvider ( wip ) ;
49
+ case SuspenseComponent :
50
+ return updateSuspenseComponent ( wip ) ;
51
+ case OffscreenComponent :
52
+ return updateOffscreenComponent ( wip ) ;
34
53
default :
35
54
if ( __DEV__ ) {
36
55
console . warn ( 'beginWork未实现的类型' ) ;
@@ -72,6 +91,12 @@ function updateHostRoot(wip: FiberNode, renderLane: Lane) {
72
91
const { memoizedState } = processUpdateQueue ( baseState , pending , renderLane ) ;
73
92
wip . memoizedState = memoizedState ;
74
93
94
+ const current = wip . alternate ;
95
+ // 考虑RootDidNotComplete的情况,需要复用memoizedState
96
+ if ( current !== null ) {
97
+ current . memoizedState = memoizedState ;
98
+ }
99
+
75
100
const nextChildren = wip . memoizedState ;
76
101
reconcileChildren ( wip , nextChildren ) ;
77
102
return wip . child ;
@@ -107,3 +132,157 @@ function markRef(current: FiberNode | null, workInProgress: FiberNode) {
107
132
workInProgress . flags |= Ref ;
108
133
}
109
134
}
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