Remove callbackList field from Fiber
Moves it to UpdateQueue instead so that we don't waste memory for components that don't have update queues.
Andrew Clark committed
Jan 9, 2017 at 14:13 UTC
d4e971a26606e44e9dcd862512b9a9eece350e14
4 files changed
+26
-38
src/renderers/shared/fiber/ReactFiber.js
+1
-3
@@ -111,8 +111,7 @@ export type Fiber = {
111
112
// A queue of state updates and callbacks.
113
updateQueue: UpdateQueue | null,
114
- // A list of callbacks that should be called during the next commit.
115
- callbackList: UpdateQueue | null,
114
+
115
// The state used to create the output
116
memoizedState: any,
117
@@ -203,7 +202,6 @@ var createFiber = function(tag : TypeOfWork, key : null | string) : Fiber {
202
pendingProps: null,
203
memoizedProps: null,
204
updateQueue: null,
206
- callbackList: null,
205
memoizedState: null,
206
207
effectTag: NoEffect,
src/renderers/shared/fiber/ReactFiberCommitWork.js
+6
-6
@@ -30,6 +30,7 @@ var { commitCallbacks } = require('ReactFiberUpdateQueue');
30
var {
31
Placement,
32
Update,
33
+ Callback,
34
ContentReset,
35
} = require('ReactTypeOfSideEffect');
36
@@ -410,17 +411,16 @@ module.exports = function<T, P, I, TI, C, CX, CI>(
411
}
412
}
413
}
413
- const callbackList = finishedWork.callbackList;
414
- if (callbackList) {
415
- commitCallbacks(finishedWork, callbackList, instance);
414
+ if ((finishedWork.effectTag & Callback) && finishedWork.updateQueue) {
415
+ commitCallbacks(finishedWork, finishedWork.updateQueue, instance);
416
}
417
return;
418
}
419
case HostRoot: {
420
- const callbackList = finishedWork.callbackList;
421
- if (callbackList) {
420
+ const updateQueue = finishedWork.updateQueue;
421
+ if (updateQueue) {
422
const instance = finishedWork.child && finishedWork.child.stateNode;
423
- commitCallbacks(finishedWork, callbackList, instance);
423
+ commitCallbacks(finishedWork, updateQueue, instance);
424
}
425
return;
426
}
src/renderers/shared/fiber/ReactFiberRoot.js
-1
@@ -39,7 +39,6 @@ exports.createFiberRoot = function(containerInfo : any) : FiberRoot {
39
containerInfo: containerInfo,
40
isScheduled: false,
41
nextScheduledRoot: null,
42
- callbackList: null,
42
context: null,
43
pendingContext: null,
44
};
src/renderers/shared/fiber/ReactFiberUpdateQueue.js
+19
-28
@@ -59,6 +59,7 @@ export type UpdateQueue = {
59
first: Update | null,
60
last: Update | null,
61
hasForceUpdate: boolean,
62
+ callbackList: null | Array<Callback>,
63
64
// Dev only
65
isProcessing?: boolean,
@@ -95,6 +96,7 @@ function ensureUpdateQueue(fiber : Fiber) : UpdateQueue {
96
first: null,
97
last: null,
98
hasForceUpdate: false,
99
+ callbackList: null,
100
isProcessing: false,
101
};
102
} else {
@@ -102,6 +104,7 @@ function ensureUpdateQueue(fiber : Fiber) : UpdateQueue {
104
first: null,
105
last: null,
106
hasForceUpdate: false,
107
+ callbackList: null,
108
};
109
}
110
@@ -122,6 +125,8 @@ function cloneUpdateQueue(alt : Fiber, fiber : Fiber) : UpdateQueue | null {
125
altQueue.first = sourceQueue.first;
126
altQueue.last = sourceQueue.last;
127
altQueue.hasForceUpdate = sourceQueue.hasForceUpdate;
128
+ altQueue.callbackList = sourceQueue.callbackList;
129
+ altQueue.isProcessing = sourceQueue.isProcessing;
130
alt.updateQueue = altQueue;
131
return altQueue;
132
}
@@ -438,29 +443,20 @@ function beginUpdateQueue(
443
// Second condition ignores top-level unmount callbacks if they are not the
444
// last update in the queue, since a subsequent update will cause a remount.
445
if (update.callback && !(update.isTopLevelUnmount && update.next)) {
441
- const callbackUpdate = cloneUpdate(update);
442
- if (callbackList && callbackList.last) {
443
- callbackList.last.next = callbackUpdate;
444
- callbackList.last = callbackUpdate;
445
- } else {
446
- callbackList = {
447
- first: callbackUpdate,
448
- last: callbackUpdate,
449
- hasForceUpdate: false,
450
- };
451
- }
446
+ callbackList = callbackList || [];
447
+ callbackList.push(update.callback);
448
workInProgress.effectTag |= CallbackEffect;
449
}
450
update = update.next;
451
}
452
457
- if (!queue.first && !queue.hasForceUpdate) {
458
- // Queue is now empty
453
+ queue.callbackList = callbackList;
454
+
455
+ if (!queue.first && !callbackList && !queue.hasForceUpdate) {
456
+ // The queue is empty and there are no callbacks. We can reset it.
457
workInProgress.updateQueue = null;
458
}
459
462
- workInProgress.callbackList = callbackList;
463
-
460
if (__DEV__) {
461
queue.isProcessing = false;
462
}
@@ -469,19 +465,14 @@ function beginUpdateQueue(
465
}
466
exports.beginUpdateQueue = beginUpdateQueue;
467
472
-function commitCallbacks(finishedWork : Fiber, callbackList : UpdateQueue, context : mixed) {
473
- const stopAfter = callbackList.last;
474
- let update = callbackList.first;
475
- while (update) {
476
- const callback = update.callback;
477
- if (typeof callback === 'function') {
478
- callback.call(context);
479
- }
480
- if (update === stopAfter) {
481
- break;
482
- }
483
- update = update.next;
468
+function commitCallbacks(finishedWork : Fiber, queue : UpdateQueue, context : mixed) {
469
+ const callbackList = queue.callbackList;
470
+ if (!callbackList) {
471
+ return;
472
+ }
473
+ for (let i = 0; i < callbackList.length; i++) {
474
+ const callback = callbackList[i];
475
+ callback.call(context);
476
}
485
- finishedWork.callbackList = null;
477
}
478
exports.commitCallbacks = commitCallbacks;