Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/renderers/shared/fiber/ReactFiberScheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,13 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
// Check for pending update priority. This is usually null so it shouldn't
// be a perf issue.
const queue = workInProgress.updateQueue;
if (queue !== null) {
const tag = workInProgress.tag;
if (
queue !== null &&
// TODO: Revisit once updateQueue is typed properly to distinguish between
// update payloads for host components and update queues for composites
(tag === ClassComponent || tag === HostRoot)
) {
newPriority = getPendingPriority(queue);
}

Expand Down
66 changes: 42 additions & 24 deletions src/renderers/shared/fiber/ReactFiberUpdateQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ function comparePriority(a: PriorityLevel, b: PriorityLevel): number {
// Ensures that a fiber has an update queue, creating a new one if needed.
// Returns the new or existing queue.
function ensureUpdateQueue(fiber: Fiber): UpdateQueue {
if (fiber.updateQueue) {
if (fiber.updateQueue !== null) {
// We already have an update queue.
return fiber.updateQueue;
}
Expand Down Expand Up @@ -123,13 +123,15 @@ function cloneUpdateQueue(
workInProgress: Fiber,
): UpdateQueue | null {
const currentQueue = current.updateQueue;
if (!currentQueue) {
if (currentQueue === null) {
// The source fiber does not have an update queue.
workInProgress.updateQueue = null;
return null;
}
// If the alternate already has a queue, reuse the previous object.
const altQueue = workInProgress.updateQueue || {};
const altQueue = workInProgress.updateQueue !== null
? workInProgress.updateQueue
: {};
altQueue.first = currentQueue.first;
altQueue.last = currentQueue.last;

Expand All @@ -156,16 +158,21 @@ function cloneUpdate(update: Update): Update {
};
}

function insertUpdateIntoQueue(queue, update, insertAfter, insertBefore) {
if (insertAfter) {
function insertUpdateIntoQueue(
queue: UpdateQueue,
update: Update,
insertAfter: Update | null,
insertBefore: Update | null,
) {
if (insertAfter !== null) {
insertAfter.next = update;
} else {
// This is the first item in the queue.
update.next = queue.first;
queue.first = update;
}

if (insertBefore) {
if (insertBefore !== null) {
update.next = insertBefore;
} else {
// This is the last item in the queue.
Expand All @@ -180,15 +187,16 @@ function findInsertionPosition(queue, update): Update | null {
let insertAfter = null;
let insertBefore = null;
if (
queue.last && comparePriority(queue.last.priorityLevel, priorityLevel) <= 0
queue.last !== null &&
comparePriority(queue.last.priorityLevel, priorityLevel) <= 0
) {
// Fast path for the common case where the update should be inserted at
// the end of the queue.
insertAfter = queue.last;
} else {
insertBefore = queue.first;
while (
insertBefore &&
insertBefore !== null &&
comparePriority(insertBefore.priorityLevel, priorityLevel) <= 0
) {
insertAfter = insertBefore;
Expand Down Expand Up @@ -229,11 +237,13 @@ function findInsertionPosition(queue, update): Update | null {
// If the update is cloned, it returns the cloned update.
function insertUpdate(fiber: Fiber, update: Update): Update | null {
const queue1 = ensureUpdateQueue(fiber);
const queue2 = fiber.alternate ? ensureUpdateQueue(fiber.alternate) : null;
const queue2 = fiber.alternate !== null
? ensureUpdateQueue(fiber.alternate)
: null;

// Warn if an update is scheduled from inside an updater function.
if (__DEV__) {
if (queue1.isProcessing || (queue2 && queue2.isProcessing)) {
if (queue1.isProcessing || (queue2 !== null && queue2.isProcessing)) {
warning(
false,
'An update (setState, replaceState, or forceUpdate) was scheduled ' +
Expand All @@ -246,17 +256,21 @@ function insertUpdate(fiber: Fiber, update: Update): Update | null {

// Find the insertion position in the first queue.
const insertAfter1 = findInsertionPosition(queue1, update);
const insertBefore1 = insertAfter1 ? insertAfter1.next : queue1.first;
const insertBefore1 = insertAfter1 !== null
? insertAfter1.next
: queue1.first;

if (!queue2) {
if (queue2 === null) {
// If there's no alternate queue, there's nothing else to do but insert.
insertUpdateIntoQueue(queue1, update, insertAfter1, insertBefore1);
return null;
}

// If there is an alternate queue, find the insertion position.
const insertAfter2 = findInsertionPosition(queue2, update);
const insertBefore2 = insertAfter2 ? insertAfter2.next : queue2.first;
const insertBefore2 = insertAfter2 !== null
? insertAfter2.next
: queue2.first;

// Now we can insert into the first queue. This must come after finding both
// insertion positions because it mutates the list.
Expand All @@ -273,10 +287,10 @@ function insertUpdate(fiber: Fiber, update: Update): Update | null {
// queue, it also inserted into the alternate. All we need to do is update
// the alternate queue's `first` and `last` pointers, in case they
// have changed.
if (!insertAfter2) {
if (insertAfter2 === null) {
queue2.first = update;
}
if (!insertBefore2) {
if (insertBefore2 === null) {
queue2.last = null;
}
}
Expand Down Expand Up @@ -341,7 +355,7 @@ function addForceUpdate(
exports.addForceUpdate = addForceUpdate;

function getPendingPriority(queue: UpdateQueue): PriorityLevel {
return queue.first ? queue.first.priorityLevel : NoWork;
return queue.first !== null ? queue.first.priorityLevel : NoWork;
}
exports.getPendingPriority = getPendingPriority;

Expand All @@ -351,7 +365,7 @@ function addTopLevelUpdate(
callback: Callback | null,
priorityLevel: PriorityLevel,
): void {
const isTopLevelUnmount = !!(partialState && partialState.element === null);
const isTopLevelUnmount = partialState.element === null;

const update = {
priorityLevel,
Expand All @@ -368,13 +382,15 @@ function addTopLevelUpdate(
// Drop all updates that are lower-priority, so that the tree is not
// remounted. We need to do this for both queues.
const queue1 = fiber.updateQueue;
const queue2 = fiber.alternate && fiber.alternate.updateQueue;
const queue2 = fiber.alternate !== null
? fiber.alternate.updateQueue
: null;

if (queue1 && update.next) {
if (queue1 !== null && update.next !== null) {
update.next = null;
queue1.last = update;
}
if (queue2 && update2 && update2.next) {
if (queue2 !== null && update2 !== null && update2.next !== null) {
update2.next = null;
queue2.last = update;
}
Expand Down Expand Up @@ -414,12 +430,14 @@ function beginUpdateQueue(
let dontMutatePrevState = true;
let callbackList = null;
let update = queue.first;
while (update && comparePriority(update.priorityLevel, priorityLevel) <= 0) {
while (
update !== null && comparePriority(update.priorityLevel, priorityLevel) <= 0
) {
// Remove each update from the queue right before it is processed. That way
// if setState is called from inside an updater function, the new update
// will be inserted in the correct position.
queue.first = update.next;
if (!queue.first) {
if (queue.first === null) {
queue.last = null;
}

Expand Down Expand Up @@ -456,7 +474,7 @@ function beginUpdateQueue(

queue.callbackList = callbackList;

if (!queue.first && !callbackList && !queue.hasForceUpdate) {
if (queue.first === null && callbackList === null && !queue.hasForceUpdate) {
// The queue is empty and there are no callbacks. We can reset it.
workInProgress.updateQueue = null;
}
Expand All @@ -475,7 +493,7 @@ function commitCallbacks(
context: mixed,
) {
const callbackList = queue.callbackList;
if (!callbackList) {
if (callbackList === null) {
return;
}
for (let i = 0; i < callbackList.length; i++) {
Expand Down