75
warnIfNotCurrentlyActingUpdatesInDev,
76
warnIfNotScopedWithMatchingAct,
77
markSkippedUpdateLanes,
78
+ isInterleavedUpdate,
79
} from './ReactFiberWorkLoop.new';
80
81
import invariant from 'shared/invariant';
105
import {markStateUpdateScheduled} from './SchedulingProfiler';
106
import {CacheContext} from './ReactFiberCacheComponent.new';
107
import {createUpdate, enqueueUpdate} from './ReactUpdateQueue.new';
108
+import {pushInterleavedQueue} from './ReactFiberInterleavedUpdates.new';
109
110
const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals;
111
118
priority?: ReactPriorityLevel,
119
|};
120
119
-type UpdateQueue<S, A> = {|
121
+export type UpdateQueue<S, A> = {|
122
pending: Update<S, A> | null,
123
+ interleaved: Update<S, A> | null,
124
dispatch: (A => mixed) | null,
125
lastRenderedReducer: ((S, A) => S) | null,
126
lastRenderedState: S | null,
653
hook.memoizedState = hook.baseState = initialState;
654
const queue = (hook.queue = {
655
pending: null,
656
+ interleaved: null,
657
dispatch: null,
658
lastRenderedReducer: reducer,
659
lastRenderedState: (initialState: any),
796
queue.lastRenderedState = newState;
797
}
798
799
+ // Interleaved updates are stored on a separate queue. We aren't going to
800
+ // process them during this render, but we do need to track which lanes
801
+ // are remaining.
802
+ const lastInterleaved = queue.interleaved;
803
+ if (lastInterleaved !== null) {
804
+ let interleaved = lastInterleaved;
805
+ do {
806
+ const interleavedLane = interleaved.lane;
807
+ currentlyRenderingFiber.lanes = mergeLanes(
808
+ currentlyRenderingFiber.lanes,
809
+ interleavedLane,
810
+ );
811
+ markSkippedUpdateLanes(interleavedLane);
812
+ interleaved = ((interleaved: any).next: Update<S, A>);
813
+ } while (interleaved !== lastInterleaved);
814
+ }
815
+
816
const dispatch: Dispatch<A> = (queue.dispatch: any);
817
return [hook.memoizedState, dispatch];
818
}
1101
// including any interleaving updates that occur.
1102
const newQueue = {
1103
pending: null,
1104
+ interleaved: null,
1105
dispatch: null,
1106
lastRenderedReducer: basicStateReducer,
1107
lastRenderedState: snapshot,
1157
hook.memoizedState = hook.baseState = initialState;
1158
const queue = (hook.queue = {
1159
pending: null,
1160
+ interleaved: null,
1161
dispatch: null,
1162
lastRenderedReducer: basicStateReducer,
1163
lastRenderedState: (initialState: any),
1835
cache: seededCache,
1836
};
1837
refreshUpdate.payload = payload;
1815
- enqueueUpdate(provider, refreshUpdate);
1838
+ enqueueUpdate(provider, refreshUpdate, lane);
1839
return;
1840
}
1841
}
1870
next: (null: any),
1871
};
1872
1850
- // Append the update to the end of the list.
1851
- const pending = queue.pending;
1852
- if (pending === null) {
1853
- // This is the first update. Create a circular list.
1854
- update.next = update;
1855
- } else {
1856
- update.next = pending.next;
1857
- pending.next = update;
1858
- }
1859
- queue.pending = update;
1860
-
1873
const alternate = fiber.alternate;
1874
if (
1875
fiber === currentlyRenderingFiber ||
1879
// queue -> linked list of updates. After this render pass, we'll restart
1880
// and apply the stashed updates on top of the work-in-progress hook.
1881
didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true;
1882
+ const pending = queue.pending;
1883
+ if (pending === null) {
1884
+ // This is the first update. Create a circular list.
1885
+ update.next = update;
1886
+ } else {
1887
+ update.next = pending.next;
1888
+ pending.next = update;
1889
+ }
1890
+ queue.pending = update;
1891
} else {
1892
+ if (isInterleavedUpdate(fiber, lane)) {
1893
+ const interleaved = queue.interleaved;
1894
+ if (interleaved === null) {
1895
+ // This is the first update. Create a circular list.
1896
+ update.next = update;
1897
+ // At the end of the current render, this queue's interleaved updates will
1898
+ // be transfered to the pending queue.
1899
+ pushInterleavedQueue(queue);
1900
+ } else {
1901
+ update.next = interleaved.next;
1902
+ interleaved.next = update;
1903
+ }
1904
+ queue.interleaved = update;
1905
+ } else {
1906
+ const pending = queue.pending;
1907
+ if (pending === null) {
1908
+ // This is the first update. Create a circular list.
1909
+ update.next = update;
1910
+ } else {
1911
+ update.next = pending.next;
1912
+ pending.next = update;
1913
+ }
1914
+ queue.pending = update;
1915
+ }
1916
+
1917
if (
1918
fiber.lanes === NoLanes &&
1919
(alternate === null || alternate.lanes === NoLanes)