mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Remove confusing for-loop in favor of a helper function
This logic is hopefully easier to follow. Added more inline comments to explain how the algorithm works.
This commit is contained in:
@@ -162,6 +162,26 @@ function insertUpdateIntoQueue(queue, update, insertAfter, insertBefore) {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the update after which the incoming update should be inserted into
|
||||
// the queue, or null if it should be inserted at beginning.
|
||||
function findInsertionPosition(queue, update) : Update | null {
|
||||
const priorityLevel = update.priorityLevel;
|
||||
let insertAfter = null;
|
||||
let insertBefore = null;
|
||||
if (queue.last && 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 && comparePriority(insertBefore.priorityLevel, priorityLevel) <= 0) {
|
||||
insertAfter = insertBefore;
|
||||
insertBefore = insertBefore.next;
|
||||
}
|
||||
}
|
||||
return insertAfter;
|
||||
}
|
||||
|
||||
// The work-in-progress queue is a subset of the current queue (if it exists).
|
||||
// We need to insert the incoming update into both lists. However, it's possible
|
||||
// that the correct position in one list will be different from the position in
|
||||
@@ -189,7 +209,6 @@ function insertUpdateIntoQueue(queue, update, insertAfter, insertBefore) {
|
||||
//
|
||||
// However, if incoming update is inserted into the same position of both lists,
|
||||
// we shouldn't make a copy.
|
||||
|
||||
function insertUpdate(fiber : Fiber, update : Update, methodName : ?string) : void {
|
||||
const queue1 = ensureUpdateQueue(fiber);
|
||||
const queue2 = fiber.alternate ? ensureUpdateQueue(fiber.alternate) : null;
|
||||
@@ -218,54 +237,40 @@ function insertUpdate(fiber : Fiber, update : Update, methodName : ?string) : vo
|
||||
}
|
||||
}
|
||||
|
||||
const priorityLevel = update.priorityLevel;
|
||||
// Find the insertion position in the first queue.
|
||||
const insertAfter1 = findInsertionPosition(queue1, update);
|
||||
const insertBefore1 = insertAfter1 ? insertAfter1.next : queue1.first;
|
||||
|
||||
let queue = queue1;
|
||||
let insertAfter1;
|
||||
let insertBefore1;
|
||||
let insertAfter2;
|
||||
let insertBefore2;
|
||||
for (let i = 0; queue && i < 2; i++) {
|
||||
let insertAfter = null;
|
||||
let insertBefore = null;
|
||||
if (queue.last && 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 && comparePriority(insertBefore.priorityLevel, priorityLevel) <= 0) {
|
||||
insertAfter = insertBefore;
|
||||
insertBefore = insertBefore.next;
|
||||
}
|
||||
}
|
||||
if (i === 0) {
|
||||
insertAfter1 = insertAfter;
|
||||
insertBefore1 = insertBefore;
|
||||
queue = queue2;
|
||||
} else {
|
||||
insertAfter2 = insertAfter;
|
||||
insertBefore2 = insertBefore;
|
||||
queue = null;
|
||||
}
|
||||
if (!queue2) {
|
||||
// If there's no alternate queue, there's nothing else to do but insert.
|
||||
insertUpdateIntoQueue(queue1, update, insertAfter1, insertBefore1);
|
||||
return;
|
||||
}
|
||||
|
||||
const update1 = update;
|
||||
insertUpdateIntoQueue(queue1, update1, insertAfter1, insertBefore1);
|
||||
// If there is an alternate queue, find the insertion position.
|
||||
const insertAfter2 = findInsertionPosition(queue2, update);
|
||||
const insertBefore2 = insertAfter2 ? insertAfter2.next : queue2.first;
|
||||
|
||||
if (queue2) {
|
||||
let update2;
|
||||
if (insertBefore1 === insertBefore2) {
|
||||
// The update is inserted into the same position of both lists. There's no
|
||||
// need to clone the update.
|
||||
update2 = update1;
|
||||
} else {
|
||||
// The update is inserted into two separate positions. Make a clone of the
|
||||
// update and insert it twice. One or the other will be dropped the next
|
||||
// time we commit.
|
||||
update2 = cloneUpdate(update1);
|
||||
}
|
||||
// Now we can insert into the first queue. This must come after finding both
|
||||
// insertion positions because it mutates the list.
|
||||
insertUpdateIntoQueue(queue1, update, insertAfter1, insertBefore1);
|
||||
|
||||
if (insertBefore1 !== insertBefore2) {
|
||||
// The insertion positions are different, so we need to clone the update and
|
||||
// insert the clone into the alternate queue.
|
||||
const update2 = cloneUpdate(update);
|
||||
insertUpdateIntoQueue(queue2, update2, insertAfter2, insertBefore2);
|
||||
} else {
|
||||
// The insertion positions are the same, so when we inserted into the first
|
||||
// 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) {
|
||||
queue2.first = update;
|
||||
}
|
||||
if (!insertBefore2) {
|
||||
queue2.last = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user