Skip to content

Commit e039e69

Browse files
committed
Revert Update Queue Refactor
Reverts b617db3. Found some bugs when attempting to land in www. Reverting to fix master. I'll land again *after* the change successfully land downstream.
1 parent b617db3 commit e039e69

File tree

5 files changed

+344
-479
lines changed

5 files changed

+344
-479
lines changed

packages/react-noop-renderer/src/createReactNoop.js

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,33 +1142,20 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
11421142

11431143
function logUpdateQueue(updateQueue: UpdateQueue<mixed>, depth) {
11441144
log(' '.repeat(depth + 1) + 'QUEUED UPDATES');
1145-
const last = updateQueue.baseQueue;
1146-
if (last === null) {
1145+
const firstUpdate = updateQueue.firstUpdate;
1146+
if (!firstUpdate) {
11471147
return;
11481148
}
1149-
const first = last.next;
1150-
let update = first;
1151-
if (update !== null) {
1152-
do {
1153-
log(
1154-
' '.repeat(depth + 1) + '~',
1155-
'[' + update.expirationTime + ']',
1156-
);
1157-
} while (update !== null && update !== first);
1158-
}
11591149

1160-
const lastPending = updateQueue.shared.pending;
1161-
if (lastPending !== null) {
1162-
const firstPending = lastPending.next;
1163-
let pendingUpdate = firstPending;
1164-
if (pendingUpdate !== null) {
1165-
do {
1166-
log(
1167-
' '.repeat(depth + 1) + '~',
1168-
'[' + pendingUpdate.expirationTime + ']',
1169-
);
1170-
} while (pendingUpdate !== null && pendingUpdate !== firstPending);
1171-
}
1150+
log(
1151+
' '.repeat(depth + 1) + '~',
1152+
'[' + firstUpdate.expirationTime + ']',
1153+
);
1154+
while (firstUpdate.next) {
1155+
log(
1156+
' '.repeat(depth + 1) + '~',
1157+
'[' + firstUpdate.expirationTime + ']',
1158+
);
11721159
}
11731160
}
11741161

packages/react-reconciler/src/ReactFiberHooks.js

Lines changed: 49 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import type {ReactPriorityLevel} from './SchedulerWithReactIntegration';
2020

2121
import ReactSharedInternals from 'shared/ReactSharedInternals';
2222

23-
import {NoWork, Sync} from './ReactFiberExpirationTime';
23+
import {NoWork} from './ReactFiberExpirationTime';
2424
import {readContext} from './ReactFiberNewContext';
2525
import {createResponderListener} from './ReactFiberEvents';
2626
import {
@@ -108,13 +108,13 @@ type Update<S, A> = {
108108
action: A,
109109
eagerReducer: ((S, A) => S) | null,
110110
eagerState: S | null,
111-
next: Update<S, A>,
111+
next: Update<S, A> | null,
112112

113113
priority?: ReactPriorityLevel,
114114
};
115115

116116
type UpdateQueue<S, A> = {
117-
pending: Update<S, A> | null,
117+
last: Update<S, A> | null,
118118
dispatch: (A => mixed) | null,
119119
lastRenderedReducer: ((S, A) => S) | null,
120120
lastRenderedState: S | null,
@@ -144,7 +144,7 @@ export type Hook = {
144144
memoizedState: any,
145145

146146
baseState: any,
147-
baseQueue: Update<any, any> | null,
147+
baseUpdate: Update<any, any> | null,
148148
queue: UpdateQueue<any, any> | null,
149149

150150
next: Hook | null,
@@ -544,8 +544,8 @@ function mountWorkInProgressHook(): Hook {
544544
memoizedState: null,
545545
546546
baseState: null,
547-
baseQueue: null,
548547
queue: null,
548+
baseUpdate: null,
549549
550550
next: null,
551551
};
@@ -604,8 +604,8 @@ function updateWorkInProgressHook(): Hook {
604604
memoizedState: currentHook.memoizedState,
605605
606606
baseState: currentHook.baseState,
607-
baseQueue: currentHook.baseQueue,
608607
queue: currentHook.queue,
608+
baseUpdate: currentHook.baseUpdate,
609609
610610
next: null,
611611
};
@@ -645,7 +645,7 @@ function mountReducer<S, I, A>(
645645
}
646646
hook.memoizedState = hook.baseState = initialState;
647647
const queue = (hook.queue = {
648-
pending: null,
648+
last: null,
649649
dispatch: null,
650650
lastRenderedReducer: reducer,
651651
lastRenderedState: (initialState: any),
@@ -703,7 +703,7 @@ function updateReducer<S, I, A>(
703703
// the base state unless the queue is empty.
704704
// TODO: Not sure if this is the desired semantics, but it's what we
705705
// do for gDSFP. I can't remember why.
706-
if (hook.baseQueue === null) {
706+
if (hook.baseUpdate === queue.last) {
707707
hook.baseState = newState;
708708
}
709709
@@ -715,55 +715,42 @@ function updateReducer<S, I, A>(
715715
return [hook.memoizedState, dispatch];
716716
}
717717
718-
const current: Hook = (currentHook: any);
719-
720-
// The last rebase update that is NOT part of the base state.
721-
let baseQueue = current.baseQueue;
722-
723-
// The last pending update that hasn't been processed yet.
724-
let pendingQueue = queue.pending;
725-
if (pendingQueue !== null) {
726-
// We have new updates that haven't been processed yet.
727-
// We'll add them to the base queue.
728-
if (baseQueue !== null) {
729-
// Merge the pending queue and the base queue.
730-
let baseFirst = baseQueue.next;
731-
let pendingFirst = pendingQueue.next;
732-
baseQueue.next = pendingFirst;
733-
pendingQueue.next = baseFirst;
718+
// The last update in the entire queue
719+
const last = queue.last;
720+
// The last update that is part of the base state.
721+
const baseUpdate = hook.baseUpdate;
722+
const baseState = hook.baseState;
723+
724+
// Find the first unprocessed update.
725+
let first;
726+
if (baseUpdate !== null) {
727+
if (last !== null) {
728+
// For the first update, the queue is a circular linked list where
729+
// `queue.last.next = queue.first`. Once the first update commits, and
730+
// the `baseUpdate` is no longer empty, we can unravel the list.
731+
last.next = null;
734732
}
735-
current.baseQueue = baseQueue = pendingQueue;
736-
queue.pending = null;
733+
first = baseUpdate.next;
734+
} else {
735+
first = last !== null ? last.next : null;
737736
}
738-
739-
if (baseQueue !== null) {
740-
// We have a queue to process.
741-
let first = baseQueue.next;
742-
let newState = current.baseState;
743-
737+
if (first !== null) {
738+
let newState = baseState;
744739
let newBaseState = null;
745-
let newBaseQueueFirst = null;
746-
let newBaseQueueLast = null;
740+
let newBaseUpdate = null;
741+
let prevUpdate = baseUpdate;
747742
let update = first;
743+
let didSkip = false;
748744
do {
749745
const updateExpirationTime = update.expirationTime;
750746
if (updateExpirationTime < renderExpirationTime) {
751747
// Priority is insufficient. Skip this update. If this is the first
752748
// skipped update, the previous update/state is the new base
753749
// update/state.
754-
const clone: Update<S, A> = {
755-
expirationTime: update.expirationTime,
756-
suspenseConfig: update.suspenseConfig,
757-
action: update.action,
758-
eagerReducer: update.eagerReducer,
759-
eagerState: update.eagerState,
760-
next: (null: any),
761-
};
762-
if (newBaseQueueLast === null) {
763-
newBaseQueueFirst = newBaseQueueLast = clone;
750+
if (!didSkip) {
751+
didSkip = true;
752+
newBaseUpdate = prevUpdate;
764753
newBaseState = newState;
765-
} else {
766-
newBaseQueueLast = newBaseQueueLast.next = clone;
767754
}
768755
// Update the remaining priority in the queue.
769756
if (updateExpirationTime > currentlyRenderingFiber.expirationTime) {
@@ -773,18 +760,6 @@ function updateReducer<S, I, A>(
773760
} else {
774761
// This update does have sufficient priority.
775762

776-
if (newBaseQueueLast !== null) {
777-
const clone: Update<S, A> = {
778-
expirationTime: Sync, // This update is going to be committed so we never want uncommit it.
779-
suspenseConfig: update.suspenseConfig,
780-
action: update.action,
781-
eagerReducer: update.eagerReducer,
782-
eagerState: update.eagerState,
783-
next: (null: any),
784-
};
785-
newBaseQueueLast = newBaseQueueLast.next = clone;
786-
}
787-
788763
// Mark the event time of this update as relevant to this render pass.
789764
// TODO: This should ideally use the true event time of this update rather than
790765
// its priority which is a derived and not reverseable value.
@@ -806,13 +781,13 @@ function updateReducer<S, I, A>(
806781
newState = reducer(newState, action);
807782
}
808783
}
784+
prevUpdate = update;
809785
update = update.next;
810786
} while (update !== null && update !== first);
811787

812-
if (newBaseQueueLast === null) {
788+
if (!didSkip) {
789+
newBaseUpdate = prevUpdate;
813790
newBaseState = newState;
814-
} else {
815-
newBaseQueueLast.next = (newBaseQueueFirst: any);
816791
}
817792

818793
// Mark that the fiber performed work, but only if the new state is
@@ -822,8 +797,8 @@ function updateReducer<S, I, A>(
822797
}
823798

824799
hook.memoizedState = newState;
800+
hook.baseUpdate = newBaseUpdate;
825801
hook.baseState = newBaseState;
826-
hook.baseQueue = newBaseQueueLast;
827802

828803
queue.lastRenderedState = newState;
829804
}
@@ -841,7 +816,7 @@ function mountState<S>(
841816
}
842817
hook.memoizedState = hook.baseState = initialState;
843818
const queue = (hook.queue = {
844-
pending: null,
819+
last: null,
845820
dispatch: null,
846821
lastRenderedReducer: basicStateReducer,
847822
lastRenderedState: (initialState: any),
@@ -1258,7 +1233,7 @@ function dispatchAction<S, A>(
12581233
action,
12591234
eagerReducer: null,
12601235
eagerState: null,
1261-
next: (null: any),
1236+
next: null,
12621237
};
12631238
if (__DEV__) {
12641239
update.priority = getCurrentPriorityLevel();
@@ -1292,23 +1267,27 @@ function dispatchAction<S, A>(
12921267
action,
12931268
eagerReducer: null,
12941269
eagerState: null,
1295-
next: (null: any),
1270+
next: null,
12961271
};
12971272

12981273
if (__DEV__) {
12991274
update.priority = getCurrentPriorityLevel();
13001275
}
13011276

13021277
// Append the update to the end of the list.
1303-
const pending = queue.pending;
1304-
if (pending === null) {
1278+
const last = queue.last;
1279+
if (last === null) {
13051280
// This is the first update. Create a circular list.
13061281
update.next = update;
13071282
} else {
1308-
update.next = pending.next;
1309-
pending.next = update;
1283+
const first = last.next;
1284+
if (first !== null) {
1285+
// Still circular.
1286+
update.next = first;
1287+
}
1288+
last.next = update;
13101289
}
1311-
queue.pending = update;
1290+
queue.last = update;
13121291

13131292
if (
13141293
fiber.expirationTime === NoWork &&

packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import type {ReactPriorityLevel} from './SchedulerWithReactIntegration';
1414
import type {Interaction} from 'scheduler/src/Tracing';
1515
import type {SuspenseConfig} from './ReactFiberSuspenseConfig';
1616
import type {SuspenseState} from './ReactFiberSuspenseComponent';
17-
import type {Hook} from './ReactFiberHooks';
1817

1918
import {
2019
warnAboutDeprecatedLifecycles,
@@ -2860,7 +2859,7 @@ export function checkForWrongSuspensePriorityInDEV(sourceFiber: Fiber) {
28602859
// has triggered any high priority updates
28612860
const updateQueue = current.updateQueue;
28622861
if (updateQueue !== null) {
2863-
let update = updateQueue.baseQueue;
2862+
let update = updateQueue.firstUpdate;
28642863
while (update !== null) {
28652864
const priorityLevel = update.priority;
28662865
if (
@@ -2884,11 +2883,12 @@ export function checkForWrongSuspensePriorityInDEV(sourceFiber: Fiber) {
28842883
break;
28852884
case FunctionComponent:
28862885
case ForwardRef:
2887-
case SimpleMemoComponent: {
2888-
let firstHook: null | Hook = current.memoizedState;
2889-
// TODO: This just checks the first Hook. Isn't it suppose to check all Hooks?
2890-
if (firstHook !== null && firstHook.baseQueue !== null) {
2891-
let update = firstHook.baseQueue;
2886+
case SimpleMemoComponent:
2887+
if (
2888+
workInProgressNode.memoizedState !== null &&
2889+
workInProgressNode.memoizedState.baseUpdate !== null
2890+
) {
2891+
let update = workInProgressNode.memoizedState.baseUpdate;
28922892
// Loop through the functional component's memoized state to see whether
28932893
// the component has triggered any high pri updates
28942894
while (update !== null) {
@@ -2908,14 +2908,15 @@ export function checkForWrongSuspensePriorityInDEV(sourceFiber: Fiber) {
29082908
}
29092909
break;
29102910
}
2911-
if (update.next === firstHook.baseQueue) {
2911+
if (
2912+
update.next === workInProgressNode.memoizedState.baseUpdate
2913+
) {
29122914
break;
29132915
}
29142916
update = update.next;
29152917
}
29162918
}
29172919
break;
2918-
}
29192920
default:
29202921
break;
29212922
}

0 commit comments

Comments
 (0)