1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | 'use strict';
|
11 |
|
12 | var _require = require('./ReactChildFiber'),
|
13 | reconcileChildFibers = _require.reconcileChildFibers,
|
14 | reconcileChildFibersInPlace = _require.reconcileChildFibersInPlace,
|
15 | cloneChildFibers = _require.cloneChildFibers;
|
16 |
|
17 | var _require2 = require('./ReactPriorityLevel'),
|
18 | LowPriority = _require2.LowPriority;
|
19 |
|
20 | var ReactTypeOfWork = require('./ReactTypeOfWork');
|
21 | var IndeterminateComponent = ReactTypeOfWork.IndeterminateComponent,
|
22 | FunctionalComponent = ReactTypeOfWork.FunctionalComponent,
|
23 | ClassComponent = ReactTypeOfWork.ClassComponent,
|
24 | HostContainer = ReactTypeOfWork.HostContainer,
|
25 | HostComponent = ReactTypeOfWork.HostComponent,
|
26 | CoroutineComponent = ReactTypeOfWork.CoroutineComponent,
|
27 | CoroutineHandlerPhase = ReactTypeOfWork.CoroutineHandlerPhase,
|
28 | YieldComponent = ReactTypeOfWork.YieldComponent;
|
29 |
|
30 | var _require3 = require('./ReactPriorityLevel'),
|
31 | NoWork = _require3.NoWork,
|
32 | OffscreenPriority = _require3.OffscreenPriority;
|
33 |
|
34 | var _require4 = require('./ReactFiberUpdateQueue'),
|
35 | createUpdateQueue = _require4.createUpdateQueue,
|
36 | addToQueue = _require4.addToQueue,
|
37 | addCallbackToQueue = _require4.addCallbackToQueue,
|
38 | mergeUpdateQueue = _require4.mergeUpdateQueue;
|
39 |
|
40 | var ReactInstanceMap = require('./ReactInstanceMap');
|
41 |
|
42 | module.exports = function (config, getScheduler) {
|
43 | function markChildAsProgressed(current, workInProgress, priorityLevel) {
|
44 |
|
45 | workInProgress.progressedChild = workInProgress.child;
|
46 | workInProgress.progressedPriority = priorityLevel;
|
47 | if (current) {
|
48 |
|
49 |
|
50 | current.progressedChild = workInProgress.progressedChild;
|
51 | current.progressedPriority = workInProgress.progressedPriority;
|
52 | }
|
53 | }
|
54 |
|
55 | function reconcileChildren(current, workInProgress, nextChildren) {
|
56 | var priorityLevel = workInProgress.pendingWorkPriority;
|
57 | reconcileChildrenAtPriority(current, workInProgress, nextChildren, priorityLevel);
|
58 | }
|
59 |
|
60 | function reconcileChildrenAtPriority(current, workInProgress, nextChildren, priorityLevel) {
|
61 |
|
62 |
|
63 | workInProgress.memoizedProps = null;
|
64 | if (current && current.child === workInProgress.child) {
|
65 |
|
66 |
|
67 |
|
68 | workInProgress.child = reconcileChildFibers(workInProgress, workInProgress.child, nextChildren, priorityLevel);
|
69 | } else {
|
70 |
|
71 |
|
72 |
|
73 |
|
74 | workInProgress.child = reconcileChildFibersInPlace(workInProgress, workInProgress.child, nextChildren, priorityLevel);
|
75 | }
|
76 | markChildAsProgressed(current, workInProgress, priorityLevel);
|
77 | }
|
78 |
|
79 | function updateFunctionalComponent(current, workInProgress) {
|
80 | var fn = workInProgress.type;
|
81 | var props = workInProgress.pendingProps;
|
82 |
|
83 |
|
84 |
|
85 | if (typeof fn.shouldComponentUpdate === 'function') {
|
86 | if (workInProgress.memoizedProps !== null) {
|
87 | if (!fn.shouldComponentUpdate(workInProgress.memoizedProps, props)) {
|
88 | return bailoutOnAlreadyFinishedWork(current, workInProgress);
|
89 | }
|
90 | }
|
91 | }
|
92 |
|
93 | var nextChildren = fn(props);
|
94 | reconcileChildren(current, workInProgress, nextChildren);
|
95 | return workInProgress.child;
|
96 | }
|
97 |
|
98 | function scheduleUpdate(fiber, updateQueue, priorityLevel) {
|
99 | var _getScheduler = getScheduler(),
|
100 | scheduleDeferredWork = _getScheduler.scheduleDeferredWork;
|
101 |
|
102 | fiber.updateQueue = updateQueue;
|
103 |
|
104 |
|
105 | if (fiber.alternate) {
|
106 | fiber.alternate.updateQueue = updateQueue;
|
107 | }
|
108 | while (true) {
|
109 | if (fiber.pendingWorkPriority === NoWork || fiber.pendingWorkPriority >= priorityLevel) {
|
110 | fiber.pendingWorkPriority = priorityLevel;
|
111 | }
|
112 | if (fiber.alternate) {
|
113 | if (fiber.alternate.pendingWorkPriority === NoWork || fiber.alternate.pendingWorkPriority >= priorityLevel) {
|
114 | fiber.alternate.pendingWorkPriority = priorityLevel;
|
115 | }
|
116 | }
|
117 |
|
118 | if (fiber.stateNode && fiber.stateNode.containerInfo) {
|
119 | var root = fiber.stateNode;
|
120 | scheduleDeferredWork(root, priorityLevel);
|
121 | return;
|
122 | }
|
123 | if (!fiber['return']) {
|
124 | throw new Error('No root!');
|
125 | }
|
126 | fiber = fiber['return'];
|
127 | }
|
128 | }
|
129 |
|
130 |
|
131 | var updater = {
|
132 | enqueueSetState: function (instance, partialState) {
|
133 | var fiber = ReactInstanceMap.get(instance);
|
134 | var updateQueue = fiber.updateQueue ? addToQueue(fiber.updateQueue, partialState) : createUpdateQueue(partialState);
|
135 | scheduleUpdate(fiber, updateQueue, LowPriority);
|
136 | },
|
137 | enqueueReplaceState: function (instance, state) {
|
138 | var fiber = ReactInstanceMap.get(instance);
|
139 | var updateQueue = createUpdateQueue(state);
|
140 | updateQueue.isReplace = true;
|
141 | scheduleUpdate(fiber, updateQueue, LowPriority);
|
142 | },
|
143 | enqueueForceUpdate: function (instance) {
|
144 | var fiber = ReactInstanceMap.get(instance);
|
145 | var updateQueue = fiber.updateQueue || createUpdateQueue(null);
|
146 | updateQueue.isForced = true;
|
147 | scheduleUpdate(fiber, updateQueue, LowPriority);
|
148 | },
|
149 | enqueueCallback: function (instance, callback) {
|
150 | var fiber = ReactInstanceMap.get(instance);
|
151 | var updateQueue = fiber.updateQueue ? fiber.updateQueue : createUpdateQueue(null);
|
152 | addCallbackToQueue(updateQueue, callback);
|
153 | fiber.updateQueue = updateQueue;
|
154 | if (fiber.alternate) {
|
155 | fiber.alternate.updateQueue = updateQueue;
|
156 | }
|
157 | }
|
158 | };
|
159 |
|
160 | function updateClassComponent(current, workInProgress) {
|
161 |
|
162 |
|
163 |
|
164 | var props = workInProgress.pendingProps;
|
165 | if (!props && current) {
|
166 | props = current.memoizedProps;
|
167 | }
|
168 |
|
169 | var updateQueue = workInProgress.updateQueue;
|
170 | var previousState = current ? current.memoizedState : null;
|
171 | var state = updateQueue ? mergeUpdateQueue(updateQueue, previousState, props) : previousState;
|
172 |
|
173 | var instance = workInProgress.stateNode;
|
174 | if (!instance) {
|
175 | var ctor = workInProgress.type;
|
176 | workInProgress.stateNode = instance = new ctor(props);
|
177 | state = instance.state || null;
|
178 |
|
179 |
|
180 | if (state !== null) {
|
181 | workInProgress.updateQueue = createUpdateQueue(state);
|
182 | }
|
183 |
|
184 | ReactInstanceMap.set(instance, workInProgress);
|
185 | instance.updater = updater;
|
186 | } else if (typeof instance.shouldComponentUpdate === 'function' && !(updateQueue && updateQueue.isForced)) {
|
187 | if (workInProgress.memoizedProps !== null) {
|
188 |
|
189 |
|
190 |
|
191 | instance.props = workInProgress.memoizedProps;
|
192 | instance.state = workInProgress.memoizedState;
|
193 | if (!instance.shouldComponentUpdate(props, state)) {
|
194 | return bailoutOnAlreadyFinishedWork(current, workInProgress);
|
195 | }
|
196 | }
|
197 | }
|
198 |
|
199 | instance.props = props;
|
200 | instance.state = state;
|
201 | var nextChildren = instance.render();
|
202 | reconcileChildren(current, workInProgress, nextChildren);
|
203 |
|
204 | return workInProgress.child;
|
205 | }
|
206 |
|
207 | function updateHostComponent(current, workInProgress) {
|
208 | var nextChildren = workInProgress.pendingProps.children;
|
209 | if (workInProgress.pendingProps.hidden && workInProgress.pendingWorkPriority !== OffscreenPriority) {
|
210 |
|
211 |
|
212 |
|
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 | if (workInProgress.progressedPriority === OffscreenPriority) {
|
219 |
|
220 |
|
221 | workInProgress.child = workInProgress.progressedChild;
|
222 | }
|
223 |
|
224 |
|
225 | reconcileChildrenAtPriority(current, workInProgress, nextChildren, OffscreenPriority);
|
226 | workInProgress.child = current ? current.child : null;
|
227 |
|
228 | return null;
|
229 | } else {
|
230 | reconcileChildren(current, workInProgress, nextChildren);
|
231 | return workInProgress.child;
|
232 | }
|
233 | }
|
234 |
|
235 | function mountIndeterminateComponent(current, workInProgress) {
|
236 | var fn = workInProgress.type;
|
237 | var props = workInProgress.pendingProps;
|
238 | var value = fn(props);
|
239 | if (typeof value === 'object' && value && typeof value.render === 'function') {
|
240 |
|
241 | workInProgress.tag = ClassComponent;
|
242 | if (current) {
|
243 | current.tag = ClassComponent;
|
244 | }
|
245 | value = value.render();
|
246 | } else {
|
247 |
|
248 | workInProgress.tag = FunctionalComponent;
|
249 | if (current) {
|
250 | current.tag = FunctionalComponent;
|
251 | }
|
252 | }
|
253 | reconcileChildren(current, workInProgress, value);
|
254 | return workInProgress.child;
|
255 | }
|
256 |
|
257 | function updateCoroutineComponent(current, workInProgress) {
|
258 | var coroutine = workInProgress.pendingProps;
|
259 | if (!coroutine) {
|
260 | throw new Error('Should be resolved by now');
|
261 | }
|
262 | reconcileChildren(current, workInProgress, coroutine.children);
|
263 | }
|
264 |
|
265 | |
266 |
|
267 |
|
268 |
|
269 |
|
270 |
|
271 |
|
272 |
|
273 |
|
274 |
|
275 |
|
276 |
|
277 |
|
278 |
|
279 |
|
280 |
|
281 |
|
282 |
|
283 |
|
284 | function bailoutOnAlreadyFinishedWork(current, workInProgress) {
|
285 | var priorityLevel = workInProgress.pendingWorkPriority;
|
286 |
|
287 |
|
288 |
|
289 |
|
290 |
|
291 |
|
292 |
|
293 |
|
294 |
|
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 | cloneChildFibers(current, workInProgress);
|
302 | markChildAsProgressed(current, workInProgress, priorityLevel);
|
303 | return workInProgress.child;
|
304 | }
|
305 |
|
306 | function bailoutOnLowPriority(current, workInProgress) {
|
307 | if (current) {
|
308 | workInProgress.child = current.child;
|
309 | workInProgress.memoizedProps = current.memoizedProps;
|
310 | workInProgress.output = current.output;
|
311 | }
|
312 | return null;
|
313 | }
|
314 |
|
315 | function beginWork(current, workInProgress, priorityLevel) {
|
316 | if (workInProgress.pendingWorkPriority === NoWork || workInProgress.pendingWorkPriority > priorityLevel) {
|
317 | return bailoutOnLowPriority(current, workInProgress);
|
318 | }
|
319 |
|
320 | if (workInProgress.progressedPriority === priorityLevel) {
|
321 |
|
322 |
|
323 | workInProgress.child = workInProgress.progressedChild;
|
324 | }
|
325 |
|
326 | if ((workInProgress.pendingProps === null || workInProgress.memoizedProps !== null && workInProgress.pendingProps === workInProgress.memoizedProps) && workInProgress.updateQueue === null) {
|
327 | return bailoutOnAlreadyFinishedWork(current, workInProgress);
|
328 | }
|
329 |
|
330 | switch (workInProgress.tag) {
|
331 | case IndeterminateComponent:
|
332 | return mountIndeterminateComponent(current, workInProgress);
|
333 | case FunctionalComponent:
|
334 | return updateFunctionalComponent(current, workInProgress);
|
335 | case ClassComponent:
|
336 | return updateClassComponent(current, workInProgress);
|
337 | case HostContainer:
|
338 | reconcileChildren(current, workInProgress, workInProgress.pendingProps);
|
339 |
|
340 |
|
341 | if (workInProgress.child) {
|
342 | return beginWork(workInProgress.child.alternate, workInProgress.child, priorityLevel);
|
343 | }
|
344 | return null;
|
345 | case HostComponent:
|
346 | if (workInProgress.stateNode && typeof config.beginUpdate === 'function') {
|
347 | config.beginUpdate(workInProgress.stateNode);
|
348 | }
|
349 | return updateHostComponent(current, workInProgress);
|
350 | case CoroutineHandlerPhase:
|
351 |
|
352 | workInProgress.tag = CoroutineComponent;
|
353 |
|
354 | case CoroutineComponent:
|
355 | updateCoroutineComponent(current, workInProgress);
|
356 |
|
357 |
|
358 | if (workInProgress.child) {
|
359 | return beginWork(workInProgress.child.alternate, workInProgress.child, priorityLevel);
|
360 | }
|
361 | return workInProgress.child;
|
362 | case YieldComponent:
|
363 |
|
364 |
|
365 | if (workInProgress.sibling) {
|
366 | return beginWork(workInProgress.sibling.alternate, workInProgress.sibling, priorityLevel);
|
367 | }
|
368 | return null;
|
369 | default:
|
370 | throw new Error('Unknown unit of work tag');
|
371 | }
|
372 | }
|
373 |
|
374 | return {
|
375 | beginWork: beginWork
|
376 | };
|
377 | }; |
\ | No newline at end of file |