@samitouri / QOS-React-2 / commits / f070aaa1b8

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.

Andrew Clark committed Dec 15, 2016 at 18:15 UTC f070aaa1b84a239a0ed8aeb98ebc185ae925b6f3
1 file changed +49 -44
src/renderers/shared/fiber/ReactFiberUpdateQueue.js
+49 -44
@@ -162,6 +162,26 @@ function insertUpdateIntoQueue(queue, update, insertAfter, insertBefore) {
162 }
163 }
164
165 +// Returns the update after which the incoming update should be inserted into
166 +// the queue, or null if it should be inserted at beginning.
167 +function findInsertionPosition(queue, update) : Update | null {
168 + const priorityLevel = update.priorityLevel;
169 + let insertAfter = null;
170 + let insertBefore = null;
171 + if (queue.last && comparePriority(queue.last.priorityLevel, priorityLevel) <= 0) {
172 + // Fast path for the common case where the update should be inserted at
173 + // the end of the queue.
174 + insertAfter = queue.last;
175 + } else {
176 + insertBefore = queue.first;
177 + while (insertBefore && comparePriority(insertBefore.priorityLevel, priorityLevel) <= 0) {
178 + insertAfter = insertBefore;
179 + insertBefore = insertBefore.next;
180 + }
181 + }
182 + return insertAfter;
183 +}
184 +
185 // The work-in-progress queue is a subset of the current queue (if it exists).
186 // We need to insert the incoming update into both lists. However, it's possible
187 // that the correct position in one list will be different from the position in
@@ -189,7 +209,6 @@ function insertUpdateIntoQueue(queue, update, insertAfter, insertBefore) {
209 //
210 // However, if incoming update is inserted into the same position of both lists,
211 // we shouldn't make a copy.
192 -
212 function insertUpdate(fiber : Fiber, update : Update, methodName : ?string) : void {
213 const queue1 = ensureUpdateQueue(fiber);
214 const queue2 = fiber.alternate ? ensureUpdateQueue(fiber.alternate) : null;
@@ -218,54 +237,40 @@ function insertUpdate(fiber : Fiber, update : Update, methodName : ?string) : vo
237 }
238 }
239
221 - const priorityLevel = update.priorityLevel;
240 + // Find the insertion position in the first queue.
241 + const insertAfter1 = findInsertionPosition(queue1, update);
242 + const insertBefore1 = insertAfter1 ? insertAfter1.next : queue1.first;
243
223 - let queue = queue1;
224 - let insertAfter1;
225 - let insertBefore1;
226 - let insertAfter2;
227 - let insertBefore2;
228 - for (let i = 0; queue && i < 2; i++) {
229 - let insertAfter = null;
230 - let insertBefore = null;
231 - if (queue.last && comparePriority(queue.last.priorityLevel, priorityLevel) <= 0) {
232 - // Fast path for the common case where the update should be inserted at
233 - // the end of the queue.
234 - insertAfter = queue.last;
235 - } else {
236 - insertBefore = queue.first;
237 - while (insertBefore && comparePriority(insertBefore.priorityLevel, priorityLevel) <= 0) {
238 - insertAfter = insertBefore;
239 - insertBefore = insertBefore.next;
240 - }
241 - }
242 - if (i === 0) {
243 - insertAfter1 = insertAfter;
244 - insertBefore1 = insertBefore;
245 - queue = queue2;
246 - } else {
247 - insertAfter2 = insertAfter;
248 - insertBefore2 = insertBefore;
249 - queue = null;
250 - }
244 + if (!queue2) {
245 + // If there's no alternate queue, there's nothing else to do but insert.
246 + insertUpdateIntoQueue(queue1, update, insertAfter1, insertBefore1);
247 + return;
248 }
249
253 - const update1 = update;
254 - insertUpdateIntoQueue(queue1, update1, insertAfter1, insertBefore1);
250 + // If there is an alternate queue, find the insertion position.
251 + const insertAfter2 = findInsertionPosition(queue2, update);
252 + const insertBefore2 = insertAfter2 ? insertAfter2.next : queue2.first;
253
256 - if (queue2) {
257 - let update2;
258 - if (insertBefore1 === insertBefore2) {
259 - // The update is inserted into the same position of both lists. There's no
260 - // need to clone the update.
261 - update2 = update1;
262 - } else {
263 - // The update is inserted into two separate positions. Make a clone of the
264 - // update and insert it twice. One or the other will be dropped the next
265 - // time we commit.
266 - update2 = cloneUpdate(update1);
267 - }
254 + // Now we can insert into the first queue. This must come after finding both
255 + // insertion positions because it mutates the list.
256 + insertUpdateIntoQueue(queue1, update, insertAfter1, insertBefore1);
257 +
258 + if (insertBefore1 !== insertBefore2) {
259 + // The insertion positions are different, so we need to clone the update and
260 + // insert the clone into the alternate queue.
261 + const update2 = cloneUpdate(update);
262 insertUpdateIntoQueue(queue2, update2, insertAfter2, insertBefore2);
263 + } else {
264 + // The insertion positions are the same, so when we inserted into the first
265 + // queue, it also inserted into the alternate. All we need to do is update
266 + // the alternate queue's `first` and `last` pointers, in case they
267 + // have changed.
268 + if (!insertAfter2) {
269 + queue2.first = update;
270 + }
271 + if (!insertBefore2) {
272 + queue2.last = null;
273 + }
274 }
275 }
276