@samitouri / QOS-React / commits / a4b8bebe18

Dependency injection in the begin/complete/commit phases

This just makes them instantiable so that we can get access to the host config in these.

Sebastian Markbage committed Jun 29, 2016 at 17:24 UTC a4b8bebe1805c59271cd4dd7e8151a32ba2dff33
4 files changed +337 -307
src/renderers/shared/fiber/ReactFiberBeginWork.js
+192 -185
@@ -14,6 +14,7 @@
14
15 import type { ReactCoroutine } from 'ReactCoroutine';
16 import type { Fiber } from 'ReactFiber';
17 +import type { HostConfig } from 'ReactFiberReconciler';
18
19 var ReactChildFiber = require('ReactChildFiber');
20 var ReactTypeOfWork = require('ReactTypeOfWork');
@@ -33,211 +34,217 @@ var {
34 } = require('ReactPriorityLevel');
35 var { findNextUnitOfWorkAtPriority } = require('ReactFiberPendingWork');
36
36 -function reconcileChildren(current, workInProgress, nextChildren) {
37 - const priority = workInProgress.pendingWorkPriority;
38 - workInProgress.child = ReactChildFiber.reconcileChildFibers(
39 - workInProgress,
40 - current ? current.child : null,
41 - nextChildren,
42 - priority
43 - );
44 -}
45 -
46 -function updateFunctionalComponent(current, workInProgress) {
47 - var fn = workInProgress.type;
48 - var props = workInProgress.pendingProps;
49 - console.log('update fn:', fn.name);
50 - var nextChildren = fn(props);
51 - reconcileChildren(current, workInProgress, nextChildren);
52 - workInProgress.pendingWorkPriority = NoWork;
53 -}
54 -
55 -function updateHostComponent(current, workInProgress) {
56 - console.log('host component', workInProgress.type, typeof workInProgress.pendingProps.children === 'string' ? workInProgress.pendingProps.children : '');
57 -
58 - var nextChildren = workInProgress.pendingProps.children;
59 -
60 - let priority = workInProgress.pendingWorkPriority;
61 - if (workInProgress.pendingProps.hidden && priority !== OffscreenPriority) {
62 - // If this host component is hidden, we can reconcile its children at
63 - // the lowest priority and bail out from this particular pass. Unless, we're
64 - // currently reconciling the lowest priority.
65 - workInProgress.child = ReactChildFiber.reconcileChildFibers(
66 - workInProgress,
67 - current ? current.child : null,
68 - nextChildren,
69 - OffscreenPriority
70 - );
71 - workInProgress.pendingWorkPriority = OffscreenPriority;
72 - return null;
73 - } else {
37 +module.exports = function<T, P, I>(config : HostConfig<T, P, I>) {
38 +
39 + function reconcileChildren(current, workInProgress, nextChildren) {
40 + const priority = workInProgress.pendingWorkPriority;
41 workInProgress.child = ReactChildFiber.reconcileChildFibers(
42 workInProgress,
43 current ? current.child : null,
44 nextChildren,
45 priority
46 );
47 + }
48 +
49 + function updateFunctionalComponent(current, workInProgress) {
50 + var fn = workInProgress.type;
51 + var props = workInProgress.pendingProps;
52 + console.log('update fn:', fn.name);
53 + var nextChildren = fn(props);
54 + reconcileChildren(current, workInProgress, nextChildren);
55 workInProgress.pendingWorkPriority = NoWork;
81 - return workInProgress.child;
56 }
83 -}
84 -
85 -function mountIndeterminateComponent(current, workInProgress) {
86 - var fn = workInProgress.type;
87 - var props = workInProgress.pendingProps;
88 - var value = fn(props);
89 - if (typeof value === 'object' && value && typeof value.render === 'function') {
90 - console.log('performed work on class:', fn.name);
91 - // Proceed under the assumption that this is a class instance
92 - workInProgress.tag = ClassComponent;
93 - if (workInProgress.alternate) {
94 - workInProgress.alternate.tag = ClassComponent;
95 - }
96 - } else {
97 - console.log('performed work on fn:', fn.name);
98 - // Proceed under the assumption that this is a functional component
99 - workInProgress.tag = FunctionalComponent;
100 - if (workInProgress.alternate) {
101 - workInProgress.alternate.tag = FunctionalComponent;
57 +
58 + function updateHostComponent(current, workInProgress) {
59 + console.log('host component', workInProgress.type, typeof workInProgress.pendingProps.children === 'string' ? workInProgress.pendingProps.children : '');
60 +
61 + var nextChildren = workInProgress.pendingProps.children;
62 +
63 + let priority = workInProgress.pendingWorkPriority;
64 + if (workInProgress.pendingProps.hidden && priority !== OffscreenPriority) {
65 + // If this host component is hidden, we can reconcile its children at
66 + // the lowest priority and bail out from this particular pass. Unless, we're
67 + // currently reconciling the lowest priority.
68 + workInProgress.child = ReactChildFiber.reconcileChildFibers(
69 + workInProgress,
70 + current ? current.child : null,
71 + nextChildren,
72 + OffscreenPriority
73 + );
74 + workInProgress.pendingWorkPriority = OffscreenPriority;
75 + return null;
76 + } else {
77 + workInProgress.child = ReactChildFiber.reconcileChildFibers(
78 + workInProgress,
79 + current ? current.child : null,
80 + nextChildren,
81 + priority
82 + );
83 + workInProgress.pendingWorkPriority = NoWork;
84 + return workInProgress.child;
85 }
86 }
104 - reconcileChildren(current, workInProgress, value);
105 - workInProgress.pendingWorkPriority = NoWork;
106 -}
107 -
108 -function updateCoroutineComponent(current, workInProgress) {
109 - var coroutine = (workInProgress.pendingProps : ?ReactCoroutine);
110 - if (!coroutine) {
111 - throw new Error('Should be resolved by now');
112 - }
113 - console.log('begin coroutine', workInProgress.type.name);
114 - reconcileChildren(current, workInProgress, coroutine.children);
115 - workInProgress.pendingWorkPriority = NoWork;
116 -}
117 -
118 -function reuseChildren(returnFiber : Fiber, firstChild : Fiber) {
119 - // TODO: None of this should be necessary if structured better.
120 - // The returnFiber pointer only needs to be updated when we walk into this child
121 - // which we don't do right now. If the pending work priority indicated only
122 - // if a child has work rather than if the node has work, then we would know
123 - // by a single lookup on workInProgress rather than having to go through
124 - // each child.
125 - let child = firstChild;
126 - do {
127 - // Update the returnFiber of the child to the newest fiber.
128 - child.return = returnFiber;
129 - // Retain the priority if there's any work left to do in the children.
130 - if (child.pendingWorkPriority !== NoWork &&
131 - (returnFiber.pendingWorkPriority === NoWork ||
132 - returnFiber.pendingWorkPriority > child.pendingWorkPriority)) {
133 - returnFiber.pendingWorkPriority = child.pendingWorkPriority;
134 - }
135 - } while (child = child.sibling);
136 -}
137 -
138 -function beginWork(current : ?Fiber, workInProgress : Fiber) : ?Fiber {
139 - // The current, flushed, state of this fiber is the alternate.
140 - // Ideally nothing should rely on this, but relying on it here
141 - // means that we don't need an additional field on the work in
142 - // progress.
143 - if (current && workInProgress.pendingProps === current.memoizedProps) {
144 - // The most likely scenario is that the previous copy of the tree contains
145 - // the same props as the new one. In that case, we can just copy the output
146 - // and children from that node.
147 - workInProgress.memoizedProps = workInProgress.pendingProps;
148 - workInProgress.output = current.output;
149 - const priorityLevel = workInProgress.pendingWorkPriority;
150 - workInProgress.pendingProps = null;
151 - workInProgress.pendingWorkPriority = NoWork;
152 - workInProgress.stateNode = current.stateNode;
153 - if (current.child) {
154 - // If we bail out but still has work with the current priority in this
155 - // subtree, we need to go find it right now. If we don't, we won't flush
156 - // it until the next tick.
157 - workInProgress.child = current.child;
158 - reuseChildren(workInProgress, workInProgress.child);
159 - if (workInProgress.pendingWorkPriority <= priorityLevel) {
160 - // TODO: This passes the current node and reads the priority level and
161 - // pending props from that. We want it to read our priority level and
162 - // pending props from the work in progress. Needs restructuring.
163 - return findNextUnitOfWorkAtPriority(workInProgress.alternate, priorityLevel);
164 - } else {
165 - return null;
87 +
88 + function mountIndeterminateComponent(current, workInProgress) {
89 + var fn = workInProgress.type;
90 + var props = workInProgress.pendingProps;
91 + var value = fn(props);
92 + if (typeof value === 'object' && value && typeof value.render === 'function') {
93 + console.log('performed work on class:', fn.name);
94 + // Proceed under the assumption that this is a class instance
95 + workInProgress.tag = ClassComponent;
96 + if (workInProgress.alternate) {
97 + workInProgress.alternate.tag = ClassComponent;
98 }
99 } else {
168 - workInProgress.child = null;
169 - return null;
100 + console.log('performed work on fn:', fn.name);
101 + // Proceed under the assumption that this is a functional component
102 + workInProgress.tag = FunctionalComponent;
103 + if (workInProgress.alternate) {
104 + workInProgress.alternate.tag = FunctionalComponent;
105 + }
106 }
107 + reconcileChildren(current, workInProgress, value);
108 + workInProgress.pendingWorkPriority = NoWork;
109 }
110
173 - if (!workInProgress.hasWorkInProgress &&
174 - workInProgress.pendingProps === workInProgress.memoizedProps &&
175 - workInProgress.pendingWorkPriority === NoWork) {
176 - // If we started this work before, and finished it, or if we're in a
177 - // ping-pong update scenario, this version could already be what we're
178 - // looking for. In that case, we should be able to just bail out.
179 - workInProgress.pendingProps = null;
180 - // TODO: We should be able to bail out if there is remaining work at a lower
181 - // priority too. However, I don't know if that is safe or even better since
182 - // the other tree could've potentially finished that work.
183 - return null;
111 + function updateCoroutineComponent(current, workInProgress) {
112 + var coroutine = (workInProgress.pendingProps : ?ReactCoroutine);
113 + if (!coroutine) {
114 + throw new Error('Should be resolved by now');
115 + }
116 + console.log('begin coroutine', workInProgress.type.name);
117 + reconcileChildren(current, workInProgress, coroutine.children);
118 + workInProgress.pendingWorkPriority = NoWork;
119 }
120
186 - workInProgress.hasWorkInProgress = true;
187 -
188 - switch (workInProgress.tag) {
189 - case IndeterminateComponent:
190 - mountIndeterminateComponent(current, workInProgress);
191 - return workInProgress.child;
192 - case FunctionalComponent:
193 - updateFunctionalComponent(current, workInProgress);
194 - return workInProgress.child;
195 - case ClassComponent:
196 - console.log('class component', workInProgress.pendingProps.type.name);
197 - return workInProgress.child;
198 - case HostContainer:
199 - reconcileChildren(current, workInProgress, workInProgress.pendingProps);
200 - // A yield component is just a placeholder, we can just run through the
201 - // next one immediately.
202 - workInProgress.pendingWorkPriority = NoWork;
203 - if (workInProgress.child) {
204 - return beginWork(
205 - workInProgress.child.alternate,
206 - workInProgress.child
207 - );
208 - }
209 - return null;
210 - case HostComponent:
211 - return updateHostComponent(current, workInProgress);
212 - case CoroutineHandlerPhase:
213 - // This is a restart. Reset the tag to the initial phase.
214 - workInProgress.tag = CoroutineComponent;
215 - // Intentionally fall through since this is now the same.
216 - case CoroutineComponent:
217 - updateCoroutineComponent(current, workInProgress);
218 - // This doesn't take arbitrary time so we could synchronously just begin
219 - // eagerly do the work of workInProgress.child as an optimization.
220 - if (workInProgress.child) {
221 - return beginWork(
222 - workInProgress.child.alternate,
223 - workInProgress.child
224 - );
121 + function reuseChildren(returnFiber : Fiber, firstChild : Fiber) {
122 + // TODO: None of this should be necessary if structured better.
123 + // The returnFiber pointer only needs to be updated when we walk into this child
124 + // which we don't do right now. If the pending work priority indicated only
125 + // if a child has work rather than if the node has work, then we would know
126 + // by a single lookup on workInProgress rather than having to go through
127 + // each child.
128 + let child = firstChild;
129 + do {
130 + // Update the returnFiber of the child to the newest fiber.
131 + child.return = returnFiber;
132 + // Retain the priority if there's any work left to do in the children.
133 + if (child.pendingWorkPriority !== NoWork &&
134 + (returnFiber.pendingWorkPriority === NoWork ||
135 + returnFiber.pendingWorkPriority > child.pendingWorkPriority)) {
136 + returnFiber.pendingWorkPriority = child.pendingWorkPriority;
137 }
226 - return workInProgress.child;
227 - case YieldComponent:
228 - // A yield component is just a placeholder, we can just run through the
229 - // next one immediately.
138 + } while (child = child.sibling);
139 + }
140 +
141 + function beginWork(current : ?Fiber, workInProgress : Fiber) : ?Fiber {
142 + // The current, flushed, state of this fiber is the alternate.
143 + // Ideally nothing should rely on this, but relying on it here
144 + // means that we don't need an additional field on the work in
145 + // progress.
146 + if (current && workInProgress.pendingProps === current.memoizedProps) {
147 + // The most likely scenario is that the previous copy of the tree contains
148 + // the same props as the new one. In that case, we can just copy the output
149 + // and children from that node.
150 + workInProgress.memoizedProps = workInProgress.pendingProps;
151 + workInProgress.output = current.output;
152 + const priorityLevel = workInProgress.pendingWorkPriority;
153 + workInProgress.pendingProps = null;
154 workInProgress.pendingWorkPriority = NoWork;
231 - if (workInProgress.sibling) {
232 - return beginWork(
233 - workInProgress.sibling.alternate,
234 - workInProgress.sibling
235 - );
155 + workInProgress.stateNode = current.stateNode;
156 + if (current.child) {
157 + // If we bail out but still has work with the current priority in this
158 + // subtree, we need to go find it right now. If we don't, we won't flush
159 + // it until the next tick.
160 + workInProgress.child = current.child;
161 + reuseChildren(workInProgress, workInProgress.child);
162 + if (workInProgress.pendingWorkPriority <= priorityLevel) {
163 + // TODO: This passes the current node and reads the priority level and
164 + // pending props from that. We want it to read our priority level and
165 + // pending props from the work in progress. Needs restructuring.
166 + return findNextUnitOfWorkAtPriority(workInProgress.alternate, priorityLevel);
167 + } else {
168 + return null;
169 + }
170 + } else {
171 + workInProgress.child = null;
172 + return null;
173 }
174 + }
175 +
176 + if (!workInProgress.hasWorkInProgress &&
177 + workInProgress.pendingProps === workInProgress.memoizedProps &&
178 + workInProgress.pendingWorkPriority === NoWork) {
179 + // If we started this work before, and finished it, or if we're in a
180 + // ping-pong update scenario, this version could already be what we're
181 + // looking for. In that case, we should be able to just bail out.
182 + workInProgress.pendingProps = null;
183 + // TODO: We should be able to bail out if there is remaining work at a lower
184 + // priority too. However, I don't know if that is safe or even better since
185 + // the other tree could've potentially finished that work.
186 return null;
238 - default:
239 - throw new Error('Unknown unit of work tag');
187 + }
188 +
189 + workInProgress.hasWorkInProgress = true;
190 +
191 + switch (workInProgress.tag) {
192 + case IndeterminateComponent:
193 + mountIndeterminateComponent(current, workInProgress);
194 + return workInProgress.child;
195 + case FunctionalComponent:
196 + updateFunctionalComponent(current, workInProgress);
197 + return workInProgress.child;
198 + case ClassComponent:
199 + console.log('class component', workInProgress.pendingProps.type.name);
200 + return workInProgress.child;
201 + case HostContainer:
202 + reconcileChildren(current, workInProgress, workInProgress.pendingProps);
203 + // A yield component is just a placeholder, we can just run through the
204 + // next one immediately.
205 + workInProgress.pendingWorkPriority = NoWork;
206 + if (workInProgress.child) {
207 + return beginWork(
208 + workInProgress.child.alternate,
209 + workInProgress.child
210 + );
211 + }
212 + return null;
213 + case HostComponent:
214 + return updateHostComponent(current, workInProgress);
215 + case CoroutineHandlerPhase:
216 + // This is a restart. Reset the tag to the initial phase.
217 + workInProgress.tag = CoroutineComponent;
218 + // Intentionally fall through since this is now the same.
219 + case CoroutineComponent:
220 + updateCoroutineComponent(current, workInProgress);
221 + // This doesn't take arbitrary time so we could synchronously just begin
222 + // eagerly do the work of workInProgress.child as an optimization.
223 + if (workInProgress.child) {
224 + return beginWork(
225 + workInProgress.child.alternate,
226 + workInProgress.child
227 + );
228 + }
229 + return workInProgress.child;
230 + case YieldComponent:
231 + // A yield component is just a placeholder, we can just run through the
232 + // next one immediately.
233 + workInProgress.pendingWorkPriority = NoWork;
234 + if (workInProgress.sibling) {
235 + return beginWork(
236 + workInProgress.sibling.alternate,
237 + workInProgress.sibling
238 + );
239 + }
240 + return null;
241 + default:
242 + throw new Error('Unknown unit of work tag');
243 + }
244 }
241 -}
245
243 -exports.beginWork = beginWork;
246 + return {
247 + beginWork,
248 + };
249 +
250 +};
src/renderers/shared/fiber/ReactFiberCommitWork.js
+22 -13
@@ -13,6 +13,7 @@
13 'use strict';
14
15 import type { Fiber } from 'ReactFiber';
16 +import type { HostConfig } from 'ReactFiberReconciler';
17
18 var ReactTypeOfWork = require('ReactTypeOfWork');
19 var {
@@ -21,18 +22,26 @@ var {
22 HostComponent,
23 } = ReactTypeOfWork;
24
24 -exports.commitWork = function(finishedWork : Fiber) : void {
25 - switch (finishedWork.tag) {
26 - case ClassComponent:
27 - // TODO: Fire componentDidMount/componentDidUpdate, update refs
28 - return;
29 - case HostContainer:
30 - // TODO: Attach children to root container.
31 - return;
32 - case HostComponent:
33 - console.log('commit updates to host component', finishedWork.type);
34 - return;
35 - default:
36 - throw new Error('This unit of work tag should not have side-effects.');
25 +module.exports = function<T, P, I>(config : HostConfig<T, P, I>) {
26 +
27 + function commitWork(finishedWork : Fiber) : void {
28 + switch (finishedWork.tag) {
29 + case ClassComponent:
30 + // TODO: Fire componentDidMount/componentDidUpdate, update refs
31 + return;
32 + case HostContainer:
33 + // TODO: Attach children to root container.
34 + return;
35 + case HostComponent:
36 + console.log('commit updates to host component', finishedWork.type);
37 + return;
38 + default:
39 + throw new Error('This unit of work tag should not have side-effects.');
40 + }
41 }
42 +
43 + return {
44 + commitWork,
45 + };
46 +
47 };
src/renderers/shared/fiber/ReactFiberCompleteWork.js
+115 -106
@@ -14,6 +14,7 @@
14
15 import type { ReactCoroutine } from 'ReactCoroutine';
16 import type { Fiber } from 'ReactFiber';
17 +import type { HostConfig } from 'ReactFiberReconciler';
18
19 import type { ReifiedYield } from 'ReactReifiedYield';
20
@@ -30,117 +31,125 @@ var {
31 YieldComponent,
32 } = ReactTypeOfWork;
33
33 -function markForPostEffect(workInProgress : Fiber) {
34 - // Schedule a side-effect on this fiber, after the children's side-effects.
35 - if (workInProgress.lastEffect) {
36 - workInProgress.lastEffect.nextEffect = workInProgress;
37 - } else {
38 - workInProgress.firstEffect = workInProgress;
34 +module.exports = function<T, P, I>(config : HostConfig<T, P, I>) {
35 +
36 + function markForPostEffect(workInProgress : Fiber) {
37 + // Schedule a side-effect on this fiber, after the children's side-effects.
38 + if (workInProgress.lastEffect) {
39 + workInProgress.lastEffect.nextEffect = workInProgress;
40 + } else {
41 + workInProgress.firstEffect = workInProgress;
42 + }
43 + workInProgress.lastEffect = workInProgress;
44 }
40 - workInProgress.lastEffect = workInProgress;
41 -}
42 -
43 -function transferOutput(child : ?Fiber, returnFiber : Fiber) {
44 - // If we have a single result, we just pass that through as the output to
45 - // avoid unnecessary traversal. When we have multiple output, we just pass
46 - // the linked list of fibers that has the individual output values.
47 - returnFiber.output = (child && !child.sibling) ? child.output : child;
48 - returnFiber.memoizedProps = returnFiber.pendingProps;
49 -}
50 -
51 -function recursivelyFillYields(yields, output : ?Fiber | ?ReifiedYield) {
52 - if (!output) {
53 - // Ignore nulls etc.
54 - } else if (output.tag !== undefined) { // TODO: Fix this fragile duck test.
55 - // Detect if this is a fiber, if so it is a fragment result.
56 - // $FlowFixMe: Refinement issue.
57 - var item = (output : Fiber);
58 - do {
59 - recursivelyFillYields(yields, item.output);
60 - item = item.sibling;
61 - } while (item);
62 - } else {
63 - // $FlowFixMe: Refinement issue. If it is not a Fiber or null, it is a yield
64 - yields.push(output);
45 +
46 + function transferOutput(child : ?Fiber, returnFiber : Fiber) {
47 + // If we have a single result, we just pass that through as the output to
48 + // avoid unnecessary traversal. When we have multiple output, we just pass
49 + // the linked list of fibers that has the individual output values.
50 + returnFiber.output = (child && !child.sibling) ? child.output : child;
51 + returnFiber.memoizedProps = returnFiber.pendingProps;
52 }
66 -}
53
68 -function moveCoroutineToHandlerPhase(current : ?Fiber, workInProgress : Fiber) {
69 - var coroutine = (workInProgress.pendingProps : ?ReactCoroutine);
70 - if (!coroutine) {
71 - throw new Error('Should be resolved by now');
54 + function recursivelyFillYields(yields, output : ?Fiber | ?ReifiedYield) {
55 + if (!output) {
56 + // Ignore nulls etc.
57 + } else if (output.tag !== undefined) { // TODO: Fix this fragile duck test.
58 + // Detect if this is a fiber, if so it is a fragment result.
59 + // $FlowFixMe: Refinement issue.
60 + var item = (output : Fiber);
61 + do {
62 + recursivelyFillYields(yields, item.output);
63 + item = item.sibling;
64 + } while (item);
65 + } else {
66 + // $FlowFixMe: Refinement issue. If it is not a Fiber or null, it is a yield
67 + yields.push(output);
68 + }
69 }
70
74 - // First step of the coroutine has completed. Now we need to do the second.
75 - // TODO: It would be nice to have a multi stage coroutine represented by a
76 - // single component, or at least tail call optimize nested ones. Currently
77 - // that requires additional fields that we don't want to add to the fiber.
78 - // So this requires nested handlers.
79 - // Note: This doesn't mutate the alternate node. I don't think it needs to
80 - // since this stage is reset for every pass.
81 - workInProgress.tag = CoroutineHandlerPhase;
82 -
83 - // Build up the yields.
84 - // TODO: Compare this to a generator or opaque helpers like Children.
85 - var yields : Array<ReifiedYield> = [];
86 - var child = workInProgress.child;
87 - while (child) {
88 - recursivelyFillYields(yields, child.output);
89 - child = child.sibling;
71 + function moveCoroutineToHandlerPhase(current : ?Fiber, workInProgress : Fiber) {
72 + var coroutine = (workInProgress.pendingProps : ?ReactCoroutine);
73 + if (!coroutine) {
74 + throw new Error('Should be resolved by now');
75 + }
76 +
77 + // First step of the coroutine has completed. Now we need to do the second.
78 + // TODO: It would be nice to have a multi stage coroutine represented by a
79 + // single component, or at least tail call optimize nested ones. Currently
80 + // that requires additional fields that we don't want to add to the fiber.
81 + // So this requires nested handlers.
82 + // Note: This doesn't mutate the alternate node. I don't think it needs to
83 + // since this stage is reset for every pass.
84 + workInProgress.tag = CoroutineHandlerPhase;
85 +
86 + // Build up the yields.
87 + // TODO: Compare this to a generator or opaque helpers like Children.
88 + var yields : Array<ReifiedYield> = [];
89 + var child = workInProgress.child;
90 + while (child) {
91 + recursivelyFillYields(yields, child.output);
92 + child = child.sibling;
93 + }
94 + var fn = coroutine.handler;
95 + var props = coroutine.props;
96 + var nextChildren = fn(props, yields);
97 +
98 + var currentFirstChild = current ? current.stateNode : null;
99 + // Inherit the priority of the returnFiber.
100 + const priority = workInProgress.pendingWorkPriority;
101 + workInProgress.stateNode = ReactChildFiber.reconcileChildFibers(
102 + workInProgress,
103 + currentFirstChild,
104 + nextChildren,
105 + priority
106 + );
107 + return workInProgress.stateNode;
108 }
91 - var fn = coroutine.handler;
92 - var props = coroutine.props;
93 - var nextChildren = fn(props, yields);
94 -
95 - var currentFirstChild = current ? current.stateNode : null;
96 - // Inherit the priority of the returnFiber.
97 - const priority = workInProgress.pendingWorkPriority;
98 - workInProgress.stateNode = ReactChildFiber.reconcileChildFibers(
99 - workInProgress,
100 - currentFirstChild,
101 - nextChildren,
102 - priority
103 - );
104 - return workInProgress.stateNode;
105 -}
106 -
107 -exports.completeWork = function(current : ?Fiber, workInProgress : Fiber) : ?Fiber {
108 - switch (workInProgress.tag) {
109 - case FunctionalComponent:
110 - console.log('/functional component', workInProgress.type.name);
111 - transferOutput(workInProgress.child, workInProgress);
112 - return null;
113 - case ClassComponent:
114 - console.log('/class component', workInProgress.type.name);
115 - transferOutput(workInProgress.child, workInProgress);
116 - return null;
117 - case HostContainer:
118 - return null;
119 - case HostComponent:
120 - transferOutput(workInProgress.child, workInProgress);
121 - if (workInProgress.alternate) {
122 - // If we have an alternate, that means this is an update and we need to
123 - // schedule a side-effect to do the updates.
124 - markForPostEffect(workInProgress);
125 - }
126 - console.log('/host component', workInProgress.type);
127 - return null;
128 - case CoroutineComponent:
129 - console.log('/coroutine component', workInProgress.pendingProps.handler.name);
130 - return moveCoroutineToHandlerPhase(current, workInProgress);
131 - case CoroutineHandlerPhase:
132 - transferOutput(workInProgress.stateNode, workInProgress);
133 - // Reset the tag to now be a first phase coroutine.
134 - workInProgress.tag = CoroutineComponent;
135 - return null;
136 - case YieldComponent:
137 - // Does nothing.
138 - return null;
139 -
140 - // Error cases
141 - case IndeterminateComponent:
142 - throw new Error('An indeterminate component should have become determinate before completing.');
143 - default:
144 - throw new Error('Unknown unit of work tag');
109 +
110 + function completeWork(current : ?Fiber, workInProgress : Fiber) : ?Fiber {
111 + switch (workInProgress.tag) {
112 + case FunctionalComponent:
113 + console.log('/functional component', workInProgress.type.name);
114 + transferOutput(workInProgress.child, workInProgress);
115 + return null;
116 + case ClassComponent:
117 + console.log('/class component', workInProgress.type.name);
118 + transferOutput(workInProgress.child, workInProgress);
119 + return null;
120 + case HostContainer:
121 + return null;
122 + case HostComponent:
123 + transferOutput(workInProgress.child, workInProgress);
124 + if (workInProgress.alternate) {
125 + // If we have an alternate, that means this is an update and we need to
126 + // schedule a side-effect to do the updates.
127 + markForPostEffect(workInProgress);
128 + }
129 + console.log('/host component', workInProgress.type);
130 + return null;
131 + case CoroutineComponent:
132 + console.log('/coroutine component', workInProgress.pendingProps.handler.name);
133 + return moveCoroutineToHandlerPhase(current, workInProgress);
134 + case CoroutineHandlerPhase:
135 + transferOutput(workInProgress.stateNode, workInProgress);
136 + // Reset the tag to now be a first phase coroutine.
137 + workInProgress.tag = CoroutineComponent;
138 + return null;
139 + case YieldComponent:
140 + // Does nothing.
141 + return null;
142 +
143 + // Error cases
144 + case IndeterminateComponent:
145 + throw new Error('An indeterminate component should have become determinate before completing.');
146 + default:
147 + throw new Error('Unknown unit of work tag');
148 + }
149 }
150 +
151 + return {
152 + completeWork,
153 + };
154 +
155 };
src/renderers/shared/fiber/ReactFiberScheduler.js
+8 -3
@@ -16,10 +16,11 @@ import type { Fiber } from 'ReactFiber';
16 import type { FiberRoot } from 'ReactFiberRoot';
17 import type { HostConfig } from 'ReactFiberReconciler';
18
19 +var ReactFiberBeginWork = require('ReactFiberBeginWork');
20 +var ReactFiberCompleteWork = require('ReactFiberCompleteWork');
21 +var ReactFiberCommitWork = require('ReactFiberCommitWork');
22 +
23 var { cloneFiber } = require('ReactFiber');
20 -var { beginWork } = require('ReactFiberBeginWork');
21 -var { completeWork } = require('ReactFiberCompleteWork');
22 -var { commitWork } = require('ReactFiberCommitWork');
24 var { findNextUnitOfWorkAtPriority } = require('ReactFiberPendingWork');
25
26 var {
@@ -33,6 +34,10 @@ var timeHeuristicForUnitOfWork = 1;
34
35 module.exports = function<T, P, I>(config : HostConfig<T, P, I>) {
36
37 + const { beginWork } = ReactFiberBeginWork(config);
38 + const { completeWork } = ReactFiberCompleteWork(config);
39 + const { commitWork } = ReactFiberCommitWork(config);
40 +
41 // const scheduleHighPriCallback = config.scheduleHighPriCallback;
42 const scheduleLowPriCallback = config.scheduleLowPriCallback;
43