@samitouri / QOS-React / commits / 3a32d2642f

Rename unitOfWork -> workInProgress

These values represent fibers that are incomplete. In the current model they're mutated in place. In a completely immutable model they would need to be cloned for every step they make progress. I.e. one where the child is still in this WIP state and one when it is complete. To clarify this I'll name them workInProgress while they're in that state, which is also what Jordan did in his prototype.

Sebastian Markbage committed Jun 6, 2016 at 22:10 UTC 3a32d2642f435b68b939a528db09482c5a43b3fa
3 files changed +73 -73
src/renderers/shared/fiber/ReactFiberBeginWork.js
+45 -45
@@ -27,114 +27,114 @@ var {
27 YieldComponent,
28 } = ReactTypesOfWork;
29
30 -function updateFunctionalComponent(unitOfWork) {
31 - var fn = unitOfWork.type;
32 - var props = unitOfWork.input;
30 +function updateFunctionalComponent(workInProgress) {
31 + var fn = workInProgress.type;
32 + var props = workInProgress.input;
33 console.log('update fn:', fn.name);
34 var nextChildren = fn(props);
35
36 - unitOfWork.child = ReactChildFiber.reconcileChildFibers(
37 - unitOfWork,
38 - unitOfWork.child,
36 + workInProgress.child = ReactChildFiber.reconcileChildFibers(
37 + workInProgress,
38 + workInProgress.child,
39 nextChildren
40 );
41 }
42
43 -function updateHostComponent(unitOfWork) {
44 - console.log('host component', unitOfWork.type, typeof unitOfWork.input.children === 'string' ? unitOfWork.input.children : '');
43 +function updateHostComponent(workInProgress) {
44 + console.log('host component', workInProgress.type, typeof workInProgress.input.children === 'string' ? workInProgress.input.children : '');
45
46 - var nextChildren = unitOfWork.input.children;
47 - unitOfWork.child = ReactChildFiber.reconcileChildFibers(
48 - unitOfWork,
49 - unitOfWork.child,
46 + var nextChildren = workInProgress.input.children;
47 + workInProgress.child = ReactChildFiber.reconcileChildFibers(
48 + workInProgress,
49 + workInProgress.child,
50 nextChildren
51 );
52 }
53
54 -function mountIndeterminateComponent(unitOfWork) {
55 - var fn = unitOfWork.type;
56 - var props = unitOfWork.input;
54 +function mountIndeterminateComponent(workInProgress) {
55 + var fn = workInProgress.type;
56 + var props = workInProgress.input;
57 var value = fn(props);
58 if (typeof value === 'object' && value && typeof value.render === 'function') {
59 console.log('performed work on class:', fn.name);
60 // Proceed under the assumption that this is a class instance
61 - unitOfWork.tag = ClassComponent;
61 + workInProgress.tag = ClassComponent;
62 } else {
63 console.log('performed work on fn:', fn.name);
64 // Proceed under the assumption that this is a functional component
65 - unitOfWork.tag = FunctionalComponent;
65 + workInProgress.tag = FunctionalComponent;
66 }
67 - unitOfWork.child = ReactChildFiber.reconcileChildFibers(
68 - unitOfWork,
69 - unitOfWork.child,
67 + workInProgress.child = ReactChildFiber.reconcileChildFibers(
68 + workInProgress,
69 + workInProgress.child,
70 value
71 );
72 }
73
74 -function updateCoroutineComponent(unitOfWork) {
75 - var coroutine = (unitOfWork.input : ?ReactCoroutine);
74 +function updateCoroutineComponent(workInProgress) {
75 + var coroutine = (workInProgress.input : ?ReactCoroutine);
76 if (!coroutine) {
77 throw new Error('Should be resolved by now');
78 }
79 - console.log('begin coroutine', unitOfWork.type.name);
80 - unitOfWork.child = ReactChildFiber.reconcileChildFibers(
81 - unitOfWork,
82 - unitOfWork.child,
79 + console.log('begin coroutine', workInProgress.type.name);
80 + workInProgress.child = ReactChildFiber.reconcileChildFibers(
81 + workInProgress,
82 + workInProgress.child,
83 coroutine.children
84 );
85 }
86
87 -function beginWork(unitOfWork : Fiber) : ?Fiber {
88 - const alt = unitOfWork.alternate;
89 - if (alt && unitOfWork.input === alt.memoizedInput) {
87 +function beginWork(workInProgress : Fiber) : ?Fiber {
88 + const alt = workInProgress.alternate;
89 + if (alt && workInProgress.input === alt.memoizedInput) {
90 // The most likely scenario is that the previous copy of the tree contains
91 // the same input as the new one. In that case, we can just copy the output
92 // and children from that node.
93 - unitOfWork.output = alt.output;
94 - unitOfWork.child = alt.child;
93 + workInProgress.output = alt.output;
94 + workInProgress.child = alt.child;
95 return null;
96 }
97 - if (unitOfWork.input === unitOfWork.memoizedInput) {
97 + if (workInProgress.input === workInProgress.memoizedInput) {
98 // In a ping-pong scenario, this version could actually contain the
99 // old input. In that case, we can just bail out.
100 return null;
101 }
102 - switch (unitOfWork.tag) {
102 + switch (workInProgress.tag) {
103 case IndeterminateComponent:
104 - mountIndeterminateComponent(unitOfWork);
104 + mountIndeterminateComponent(workInProgress);
105 break;
106 case FunctionalComponent:
107 - updateFunctionalComponent(unitOfWork);
107 + updateFunctionalComponent(workInProgress);
108 break;
109 case ClassComponent:
110 - console.log('class component', unitOfWork.input.type.name);
110 + console.log('class component', workInProgress.input.type.name);
111 break;
112 case HostComponent:
113 - updateHostComponent(unitOfWork);
113 + updateHostComponent(workInProgress);
114 break;
115 case CoroutineHandlerPhase:
116 // This is a restart. Reset the tag to the initial phase.
117 - unitOfWork.tag = CoroutineComponent;
117 + workInProgress.tag = CoroutineComponent;
118 // Intentionally fall through since this is now the same.
119 case CoroutineComponent:
120 - updateCoroutineComponent(unitOfWork);
120 + updateCoroutineComponent(workInProgress);
121 // This doesn't take arbitrary time so we could synchronously just begin
122 - // eagerly do the work of unitOfWork.child as an optimization.
123 - if (unitOfWork.child) {
124 - return beginWork(unitOfWork.child);
122 + // eagerly do the work of workInProgress.child as an optimization.
123 + if (workInProgress.child) {
124 + return beginWork(workInProgress.child);
125 }
126 break;
127 case YieldComponent:
128 // A yield component is just a placeholder, we can just run through the
129 // next one immediately.
130 - if (unitOfWork.sibling) {
131 - return beginWork(unitOfWork.sibling);
130 + if (workInProgress.sibling) {
131 + return beginWork(workInProgress.sibling);
132 }
133 return null;
134 default:
135 throw new Error('Unknown unit of work tag');
136 }
137 - return unitOfWork.child;
137 + return workInProgress.child;
138 }
139
140 exports.beginWork = beginWork;
src/renderers/shared/fiber/ReactFiberCompleteWork.js
+19 -19
@@ -54,8 +54,8 @@ function recursivelyFillYields(yields, output : ?Fiber | ?ReifiedYield) {
54 }
55 }
56
57 -function moveCoroutineToHandlerPhase(unitOfWork : Fiber) {
58 - var coroutine = (unitOfWork.input : ?ReactCoroutine);
57 +function moveCoroutineToHandlerPhase(workInProgress : Fiber) {
58 + var coroutine = (workInProgress.input : ?ReactCoroutine);
59 if (!coroutine) {
60 throw new Error('Should be resolved by now');
61 }
@@ -67,12 +67,12 @@ function moveCoroutineToHandlerPhase(unitOfWork : Fiber) {
67 // So this requires nested handlers.
68 // Note: This doesn't mutate the alternate node. I don't think it needs to
69 // since this stage is reset for every pass.
70 - unitOfWork.tag = CoroutineHandlerPhase;
70 + workInProgress.tag = CoroutineHandlerPhase;
71
72 // Build up the yields.
73 // TODO: Compare this to a generator or opaque helpers like Children.
74 var yields : Array<ReifiedYield> = [];
75 - var child = unitOfWork.child;
75 + var child = workInProgress.child;
76 while (child) {
77 recursivelyFillYields(yields, child.output);
78 child = child.sibling;
@@ -81,34 +81,34 @@ function moveCoroutineToHandlerPhase(unitOfWork : Fiber) {
81 var props = coroutine.props;
82 var nextChildren = fn(props, yields);
83
84 - unitOfWork.stateNode = ReactChildFiber.reconcileChildFibers(
85 - unitOfWork,
86 - unitOfWork.stateNode,
84 + workInProgress.stateNode = ReactChildFiber.reconcileChildFibers(
85 + workInProgress,
86 + workInProgress.stateNode,
87 nextChildren
88 );
89 - return unitOfWork.stateNode;
89 + return workInProgress.stateNode;
90 }
91
92 -exports.completeWork = function(unitOfWork : Fiber) : ?Fiber {
93 - switch (unitOfWork.tag) {
92 +exports.completeWork = function(workInProgress : Fiber) : ?Fiber {
93 + switch (workInProgress.tag) {
94 case FunctionalComponent:
95 - console.log('/functional component', unitOfWork.type.name);
96 - transferOutput(unitOfWork.child, unitOfWork);
95 + console.log('/functional component', workInProgress.type.name);
96 + transferOutput(workInProgress.child, workInProgress);
97 break;
98 case ClassComponent:
99 - console.log('/class component', unitOfWork.type.name);
100 - transferOutput(unitOfWork.child, unitOfWork);
99 + console.log('/class component', workInProgress.type.name);
100 + transferOutput(workInProgress.child, workInProgress);
101 break;
102 case HostComponent:
103 - console.log('/host component', unitOfWork.type);
103 + console.log('/host component', workInProgress.type);
104 break;
105 case CoroutineComponent:
106 - console.log('/coroutine component', unitOfWork.input.handler.name);
107 - return moveCoroutineToHandlerPhase(unitOfWork);
106 + console.log('/coroutine component', workInProgress.input.handler.name);
107 + return moveCoroutineToHandlerPhase(workInProgress);
108 case CoroutineHandlerPhase:
109 - transferOutput(unitOfWork.stateNode, unitOfWork);
109 + transferOutput(workInProgress.stateNode, workInProgress);
110 // Reset the tag to now be a first phase coroutine.
111 - unitOfWork.tag = CoroutineComponent;
111 + workInProgress.tag = CoroutineComponent;
112 break;
113 case YieldComponent:
114 // Does nothing.
src/renderers/shared/fiber/ReactFiberReconciler.js
+9 -9
@@ -49,23 +49,23 @@ module.exports = function<T, P, I>(config : HostConfig<T, P, I>) : Reconciler {
49
50 let nextUnitOfWork : ?Fiber = null;
51
52 - function completeUnitOfWork(unitOfWork : Fiber) : ?Fiber {
52 + function completeUnitOfWork(workInProgress : Fiber) : ?Fiber {
53 while (true) {
54 - var next = completeWork(unitOfWork);
54 + var next = completeWork(workInProgress);
55 if (next) {
56 // If completing this work spawned new work, do that next.
57 return next;
58 - } else if (unitOfWork.sibling) {
58 + } else if (workInProgress.sibling) {
59 // If there is more work to do in this parent, do that next.
60 - return unitOfWork.sibling;
61 - } else if (unitOfWork.parent) {
60 + return workInProgress.sibling;
61 + } else if (workInProgress.parent) {
62 // If there's no more work in this parent. Complete the parent.
63 // TODO: Stop using the parent for this purpose. I think this will break
64 // down in edge cases because when nodes are reused during bailouts, we
65 // don't know which of two parents was used. Instead we should maintain
66 // a temporary manual stack.
67 // $FlowFixMe: This downcast is not safe. It is intentionally an error.
68 - unitOfWork = unitOfWork.parent;
68 + workInProgress = workInProgress.parent;
69 } else {
70 // If we're at the root, there's no more work to do.
71 return null;
@@ -73,14 +73,14 @@ module.exports = function<T, P, I>(config : HostConfig<T, P, I>) : Reconciler {
73 }
74 }
75
76 - function performUnitOfWork(unitOfWork : Fiber) : ?Fiber {
77 - var next = beginWork(unitOfWork);
76 + function performUnitOfWork(workInProgress : Fiber) : ?Fiber {
77 + var next = beginWork(workInProgress);
78 if (next) {
79 // If this spawns new work, do that next.
80 return next;
81 } else {
82 // Otherwise, complete the current work.
83 - return completeUnitOfWork(unitOfWork);
83 + return completeUnitOfWork(workInProgress);
84 }
85 }
86