From 995a437d3372843ca7920bd4c0ebbfa984167e05 Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Fri, 20 Apr 2018 15:27:49 -0700 Subject: [PATCH] Store captured effects on separate list from "own" effects (callbacks) For resuming, we need the ability to discard the "own" effects while reusing the captured effects. --- .../react-reconciler/src/ReactUpdateQueue.js | 65 +++++++++++++++---- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/packages/react-reconciler/src/ReactUpdateQueue.js b/packages/react-reconciler/src/ReactUpdateQueue.js index 3938a95b1188e..2e5b2c626e01b 100644 --- a/packages/react-reconciler/src/ReactUpdateQueue.js +++ b/packages/react-reconciler/src/ReactUpdateQueue.js @@ -122,7 +122,10 @@ export type UpdateQueue = { firstEffect: Update | null, lastEffect: Update | null, - // TODO: Workaround for lack of tuples. Could global state instead. + firstCapturedEffect: Update | null, + lastCapturedEffect: Update | null, + + // TODO: Workaround for lack of tuples. Could use global state instead. hasForceUpdate: boolean, // DEV-only @@ -144,6 +147,8 @@ export function createUpdateQueue(baseState: State): UpdateQueue { lastCapturedUpdate: null, firstEffect: null, lastEffect: null, + firstCapturedEffect: null, + lastCapturedEffect: null, hasForceUpdate: false, }; if (__DEV__) { @@ -170,6 +175,9 @@ function cloneUpdateQueue( firstEffect: null, lastEffect: null, + + firstCapturedEffect: null, + lastCapturedEffect: null, }; if (__DEV__) { queue.isProcessing = false; @@ -428,12 +436,22 @@ export function processUpdateQueue( } else { // This update does have sufficient priority. Process it and compute // a new result. - resultState = processSingleUpdate( - workInProgress, - queue, - update, - resultState, - ); + const commit = update.commit; + const process = update.process; + if (process !== null) { + resultState = process(workInProgress, resultState, queue); + } + if (commit !== null) { + workInProgress.effectTag |= Callback; + // Set this to null, in case it was mutated during an aborted render. + update.nextEffect = null; + if (queue.lastEffect === null) { + queue.firstEffect = queue.lastEffect = update; + } else { + queue.lastEffect.nextEffect = update; + queue.lastEffect = update; + } + } } // Continue to the next update. update = update.next; @@ -467,12 +485,22 @@ export function processUpdateQueue( } else { // This update does have sufficient priority. Process it and compute // a new result. - resultState = processSingleUpdate( - workInProgress, - queue, - update, - resultState, - ); + const commit = update.commit; + const process = update.process; + if (process !== null) { + resultState = process(workInProgress, resultState, queue); + } + if (commit !== null) { + workInProgress.effectTag |= Callback; + // Set this to null, in case it was mutated during an aborted render. + update.nextEffect = null; + if (queue.lastCapturedEffect === null) { + queue.firstCapturedEffect = queue.lastCapturedEffect = update; + } else { + queue.lastCapturedEffect.nextEffect = update; + queue.lastCapturedEffect = update; + } + } } update = update.next; } @@ -533,4 +561,15 @@ export function commitUpdateQueue( } effect = effect.nextEffect; } + + effect = finishedQueue.firstCapturedEffect; + finishedQueue.firstCapturedEffect = finishedQueue.lastCapturedEffect = null; + while (effect !== null) { + const commit = effect.commit; + if (commit !== null) { + effect.commit = null; + commit(finishedWork); + } + effect = effect.nextEffect; + } }