-
Notifications
You must be signed in to change notification settings - Fork 46.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Fiber] Remove callbackList field from Fiber #8728
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,6 +59,7 @@ export type UpdateQueue = { | |
first: Update | null, | ||
last: Update | null, | ||
hasForceUpdate: boolean, | ||
callbackList: null | Array<Callback>, | ||
|
||
// Dev only | ||
isProcessing?: boolean, | ||
|
@@ -95,13 +96,15 @@ function ensureUpdateQueue(fiber : Fiber) : UpdateQueue { | |
first: null, | ||
last: null, | ||
hasForceUpdate: false, | ||
callbackList: null, | ||
isProcessing: false, | ||
}; | ||
} else { | ||
queue = { | ||
first: null, | ||
last: null, | ||
hasForceUpdate: false, | ||
callbackList: null, | ||
}; | ||
} | ||
|
||
|
@@ -110,19 +113,25 @@ function ensureUpdateQueue(fiber : Fiber) : UpdateQueue { | |
} | ||
|
||
// Clones an update queue from a source fiber onto its alternate. | ||
function cloneUpdateQueue(alt : Fiber, fiber : Fiber) : UpdateQueue | null { | ||
const sourceQueue = fiber.updateQueue; | ||
if (!sourceQueue) { | ||
function cloneUpdateQueue(current : Fiber, workInProgress : Fiber) : UpdateQueue | null { | ||
const currentQueue = current.updateQueue; | ||
if (!currentQueue) { | ||
// The source fiber does not have an update queue. | ||
alt.updateQueue = null; | ||
workInProgress.updateQueue = null; | ||
return null; | ||
} | ||
// If the alternate already has a queue, reuse the previous object. | ||
const altQueue = alt.updateQueue || {}; | ||
altQueue.first = sourceQueue.first; | ||
altQueue.last = sourceQueue.last; | ||
altQueue.hasForceUpdate = sourceQueue.hasForceUpdate; | ||
alt.updateQueue = altQueue; | ||
const altQueue = workInProgress.updateQueue || {}; | ||
altQueue.first = currentQueue.first; | ||
altQueue.last = currentQueue.last; | ||
|
||
// These fields are invalid by the time we clone from current. Reset them. | ||
altQueue.hasForceUpdate = false; | ||
altQueue.callbackList = null; | ||
altQueue.isProcessing = false; | ||
|
||
workInProgress.updateQueue = altQueue; | ||
|
||
return altQueue; | ||
} | ||
exports.cloneUpdateQueue = cloneUpdateQueue; | ||
|
@@ -438,29 +447,20 @@ function beginUpdateQueue( | |
// Second condition ignores top-level unmount callbacks if they are not the | ||
// last update in the queue, since a subsequent update will cause a remount. | ||
if (update.callback && !(update.isTopLevelUnmount && update.next)) { | ||
const callbackUpdate = cloneUpdate(update); | ||
if (callbackList && callbackList.last) { | ||
callbackList.last.next = callbackUpdate; | ||
callbackList.last = callbackUpdate; | ||
} else { | ||
callbackList = { | ||
first: callbackUpdate, | ||
last: callbackUpdate, | ||
hasForceUpdate: false, | ||
}; | ||
} | ||
callbackList = callbackList || []; | ||
callbackList.push(update.callback); | ||
workInProgress.effectTag |= CallbackEffect; | ||
} | ||
update = update.next; | ||
} | ||
|
||
if (!queue.first && !queue.hasForceUpdate) { | ||
// Queue is now empty | ||
queue.callbackList = callbackList; | ||
|
||
if (!queue.first && !callbackList && !queue.hasForceUpdate) { | ||
// The queue is empty and there are no callbacks. We can reset it. | ||
workInProgress.updateQueue = null; | ||
} | ||
|
||
workInProgress.callbackList = callbackList; | ||
|
||
if (__DEV__) { | ||
queue.isProcessing = false; | ||
} | ||
|
@@ -469,19 +469,14 @@ function beginUpdateQueue( | |
} | ||
exports.beginUpdateQueue = beginUpdateQueue; | ||
|
||
function commitCallbacks(finishedWork : Fiber, callbackList : UpdateQueue, context : mixed) { | ||
const stopAfter = callbackList.last; | ||
let update = callbackList.first; | ||
while (update) { | ||
const callback = update.callback; | ||
if (typeof callback === 'function') { | ||
callback.call(context); | ||
} | ||
if (update === stopAfter) { | ||
break; | ||
} | ||
update = update.next; | ||
function commitCallbacks(finishedWork : Fiber, queue : UpdateQueue, context : mixed) { | ||
const callbackList = queue.callbackList; | ||
if (!callbackList) { | ||
return; | ||
} | ||
for (let i = 0; i < callbackList.length; i++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was this check unnecessary? Are we validating early now? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Brian added There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also the type is stricter now. Previously we iterated through a list of |
||
const callback = callbackList[i]; | ||
callback.call(context); | ||
} | ||
finishedWork.callbackList = null; | ||
} | ||
exports.commitCallbacks = commitCallbacks; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This used to use a linked list like all the other structures. That requires dynamic reallocation as it grows. It also requires us to take on a dependency on such an implementation. This might matter if we make a WASM port.
Would it make sense to just use a simple linked list here too, just for consistency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, though may I ask why it's ok to use arrays for context but not here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In context it is a fixed general stack. In normal use it never gets reallocated or expanded. The wasm implementation can be as easy as a fixed one time linear allocation. Where as this is dynamically allocated and growing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#8752