Skip to content

Commit fbec958

Browse files
committed
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.
1 parent b2cc91e commit fbec958

File tree

4 files changed

+25
-35
lines changed

4 files changed

+25
-35
lines changed

src/renderers/shared/fiber/ReactFiber.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,7 @@ export type Fiber = {
111111

112112
// A queue of state updates and callbacks.
113113
updateQueue: UpdateQueue | null,
114-
// A list of callbacks that should be called during the next commit.
115-
callbackList: UpdateQueue | null,
114+
116115
// The state used to create the output
117116
memoizedState: any,
118117

@@ -203,7 +202,6 @@ var createFiber = function(tag : TypeOfWork, key : null | string) : Fiber {
203202
pendingProps: null,
204203
memoizedProps: null,
205204
updateQueue: null,
206-
callbackList: null,
207205
memoizedState: null,
208206

209207
effectTag: NoEffect,

src/renderers/shared/fiber/ReactFiberCommitWork.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ var { commitCallbacks } = require('ReactFiberUpdateQueue');
3030
var {
3131
Placement,
3232
Update,
33+
Callback,
3334
ContentReset,
3435
} = require('ReactTypeOfSideEffect');
3536

@@ -410,17 +411,16 @@ module.exports = function<T, P, I, TI, C, CX, CI>(
410411
}
411412
}
412413
}
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);
416416
}
417417
return;
418418
}
419419
case HostRoot: {
420-
const callbackList = finishedWork.callbackList;
421-
if (callbackList) {
420+
const updateQueue = finishedWork.updateQueue;
421+
if (updateQueue) {
422422
const instance = finishedWork.child && finishedWork.child.stateNode;
423-
commitCallbacks(finishedWork, callbackList, instance);
423+
commitCallbacks(finishedWork, updateQueue, instance);
424424
}
425425
return;
426426
}

src/renderers/shared/fiber/ReactFiberRoot.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ exports.createFiberRoot = function(containerInfo : any) : FiberRoot {
3939
containerInfo: containerInfo,
4040
isScheduled: false,
4141
nextScheduledRoot: null,
42-
callbackList: null,
4342
context: null,
4443
pendingContext: null,
4544
};

src/renderers/shared/fiber/ReactFiberUpdateQueue.js

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export type UpdateQueue = {
5959
first: Update | null,
6060
last: Update | null,
6161
hasForceUpdate: boolean,
62+
callbackList: null | Array<Callback>,
6263

6364
// Dev only
6465
isProcessing?: boolean,
@@ -95,13 +96,15 @@ function ensureUpdateQueue(fiber : Fiber) : UpdateQueue {
9596
first: null,
9697
last: null,
9798
hasForceUpdate: false,
99+
callbackList: null,
98100
isProcessing: false,
99101
};
100102
} else {
101103
queue = {
102104
first: null,
103105
last: null,
104106
hasForceUpdate: false,
107+
callbackList: null,
105108
};
106109
}
107110

@@ -122,6 +125,8 @@ function cloneUpdateQueue(alt : Fiber, fiber : Fiber) : UpdateQueue | null {
122125
altQueue.first = sourceQueue.first;
123126
altQueue.last = sourceQueue.last;
124127
altQueue.hasForceUpdate = sourceQueue.hasForceUpdate;
128+
altQueue.callbackList = sourceQueue.callbackList;
129+
altQueue.isProcessing = sourceQueue.isProcessing;
125130
alt.updateQueue = altQueue;
126131
return altQueue;
127132
}
@@ -438,29 +443,20 @@ function beginUpdateQueue(
438443
// Second condition ignores top-level unmount callbacks if they are not the
439444
// last update in the queue, since a subsequent update will cause a remount.
440445
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);
452448
workInProgress.effectTag |= CallbackEffect;
453449
}
454450
update = update.next;
455451
}
456452

457-
if (!queue.first && !queue.hasForceUpdate) {
458-
// Queue is now empty
453+
queue.callbackList = callbackList;
454+
455+
if (!queue.first && !queue.callbackList && !queue.hasForceUpdate) {
456+
// The queue is empty and there are no callbacks. We can reset it.
459457
workInProgress.updateQueue = null;
460458
}
461459

462-
workInProgress.callbackList = callbackList;
463-
464460
if (__DEV__) {
465461
queue.isProcessing = false;
466462
}
@@ -469,19 +465,16 @@ function beginUpdateQueue(
469465
}
470466
exports.beginUpdateQueue = beginUpdateQueue;
471467

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;
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];
477475
if (typeof callback === 'function') {
478476
callback.call(context);
479477
}
480-
if (update === stopAfter) {
481-
break;
482-
}
483-
update = update.next;
484478
}
485-
finishedWork.callbackList = null;
486479
}
487480
exports.commitCallbacks = commitCallbacks;

0 commit comments

Comments
 (0)