@samitouri / QOS-React / commits / d4e971a266

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;