87
requestUpdateLane,
88
requestEventTime,
89
markSkippedUpdateLanes,
90
- isInterleavedUpdate,
90
} from './ReactFiberWorkLoop.new';
91
92
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
110
createUpdate as createLegacyQueueUpdate,
111
enqueueUpdate as enqueueLegacyQueueUpdate,
112
entangleTransitions as entangleLegacyQueueTransitions,
114
-} from './ReactUpdateQueue.new';
115
-import {pushInterleavedQueue} from './ReactFiberInterleavedUpdates.new';
113
+} from './ReactFiberClassUpdateQueue.new';
114
+import {
115
+ enqueueConcurrentHookUpdate,
116
+ enqueueConcurrentHookUpdateAndEagerlyBailout,
117
+ enqueueConcurrentRenderForLane,
118
+} from './ReactFiberConcurrentUpdates.new';
119
import {getTreeId} from './ReactFiberTreeContext.new';
120
import {now} from './Scheduler';
121
122
const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals;
123
121
-type Update<S, A> = {|
124
+export type Update<S, A> = {|
125
lane: Lane,
126
action: A,
127
hasEagerState: boolean,
131
132
export type UpdateQueue<S, A> = {|
133
pending: Update<S, A> | null,
131
- interleaved: Update<S, A> | null,
134
lanes: Lanes,
135
dispatch: (A => mixed) | null,
136
lastRenderedReducer: ((S, A) => S) | null,
740
hook.memoizedState = hook.baseState = initialState;
741
const queue: UpdateQueue<S, A> = {
742
pending: null,
741
- interleaved: null,
743
lanes: NoLanes,
744
dispatch: null,
745
lastRenderedReducer: reducer,
886
queue.lastRenderedState = newState;
887
}
888
888
- // Interleaved updates are stored on a separate queue. We aren't going to
889
- // process them during this render, but we do need to track which lanes
890
- // are remaining.
891
- const lastInterleaved = queue.interleaved;
892
- if (lastInterleaved !== null) {
893
- let interleaved = lastInterleaved;
894
- do {
895
- const interleavedLane = interleaved.lane;
896
- currentlyRenderingFiber.lanes = mergeLanes(
897
- currentlyRenderingFiber.lanes,
898
- interleavedLane,
899
- );
900
- markSkippedUpdateLanes(interleavedLane);
901
- interleaved = ((interleaved: any).next: Update<S, A>);
902
- } while (interleaved !== lastInterleaved);
903
- } else if (baseQueue === null) {
889
+ if (baseQueue === null) {
890
// `queue.lanes` is used for entangling transitions. We can set it back to
891
// zero once the queue is empty.
892
queue.lanes = NoLanes;
1194
// including any interleaving updates that occur.
1195
const newQueue: UpdateQueue<Snapshot, BasicStateAction<Snapshot>> = {
1196
pending: null,
1211
- interleaved: null,
1197
lanes: NoLanes,
1198
dispatch: null,
1199
lastRenderedReducer: basicStateReducer,
1482
}
1483
1484
function forceStoreRerender(fiber) {
1500
- scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp);
1485
+ const root = enqueueConcurrentRenderForLane(fiber, SyncLane);
1486
+ if (root !== null) {
1487
+ scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
1488
+ }
1489
}
1490
1491
function mountState<S>(
1499
hook.memoizedState = hook.baseState = initialState;
1500
const queue: UpdateQueue<S, BasicStateAction<S>> = {
1501
pending: null,
1514
- interleaved: null,
1502
lanes: NoLanes,
1503
dispatch: null,
1504
lastRenderedReducer: basicStateReducer,
2140
switch (provider.tag) {
2141
case CacheComponent:
2142
case HostRoot: {
2143
+ // Schedule an update on the cache boundary to trigger a refresh.
2144
const lane = requestUpdateLane(provider);
2145
const eventTime = requestEventTime();
2158
- const root = scheduleUpdateOnFiber(provider, lane, eventTime);
2146
+ const refreshUpdate = createLegacyQueueUpdate(eventTime, lane);
2147
+ const root = enqueueLegacyQueueUpdate(provider, refreshUpdate, lane);
2148
if (root !== null) {
2149
+ scheduleUpdateOnFiber(root, provider, lane, eventTime);
2150
entangleLegacyQueueTransitions(root, provider, lane);
2151
}
2152
2160
seededCache.data.set(seedKey, seedValue);
2161
}
2162
2173
- // Schedule an update on the cache boundary to trigger a refresh.
2174
- const refreshUpdate = createLegacyQueueUpdate(eventTime, lane);
2163
const payload = {
2164
cache: seededCache,
2165
};
2166
refreshUpdate.payload = payload;
2179
- enqueueLegacyQueueUpdate(provider, refreshUpdate, lane);
2167
return;
2168
}
2169
}
2200
if (isRenderPhaseUpdate(fiber)) {
2201
enqueueRenderPhaseUpdate(queue, update);
2202
} else {
2216
- enqueueUpdate(fiber, queue, update, lane);
2217
- const eventTime = requestEventTime();
2218
- const root = scheduleUpdateOnFiber(fiber, lane, eventTime);
2203
+ const root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);
2204
if (root !== null) {
2205
+ const eventTime = requestEventTime();
2206
+ scheduleUpdateOnFiber(root, fiber, lane, eventTime);
2207
entangleTransitionUpdate(root, queue, lane);
2208
}
2209
}
2239
if (isRenderPhaseUpdate(fiber)) {
2240
enqueueRenderPhaseUpdate(queue, update);
2241
} else {
2255
- enqueueUpdate(fiber, queue, update, lane);
2256
-
2242
const alternate = fiber.alternate;
2243
if (
2244
fiber.lanes === NoLanes &&
2268
// It's still possible that we'll need to rebase this update later,
2269
// if the component re-renders for a different reason and by that
2270
// time the reducer has changed.
2271
+ // TODO: Do we still need to entangle transitions in this case?
2272
+ enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update);
2273
return;
2274
}
2275
} catch (error) {
2281
}
2282
}
2283
}
2297
- const eventTime = requestEventTime();
2298
- const root = scheduleUpdateOnFiber(fiber, lane, eventTime);
2284
+
2285
+ const root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);
2286
if (root !== null) {
2287
+ const eventTime = requestEventTime();
2288
+ scheduleUpdateOnFiber(root, fiber, lane, eventTime);
2289
entangleTransitionUpdate(root, queue, lane);
2290
}
2291
}
2320
queue.pending = update;
2321
}
2322
2334
-function enqueueUpdate<S, A>(
2335
- fiber: Fiber,
2336
- queue: UpdateQueue<S, A>,
2337
- update: Update<S, A>,
2338
- lane: Lane,
2339
-) {
2340
- if (isInterleavedUpdate(fiber, lane)) {
2341
- const interleaved = queue.interleaved;
2342
- if (interleaved === null) {
2343
- // This is the first update. Create a circular list.
2344
- update.next = update;
2345
- // At the end of the current render, this queue's interleaved updates will
2346
- // be transferred to the pending queue.
2347
- pushInterleavedQueue(queue);
2348
- } else {
2349
- update.next = interleaved.next;
2350
- interleaved.next = update;
2351
- }
2352
- queue.interleaved = update;
2353
- } else {
2354
- const pending = queue.pending;
2355
- if (pending === null) {
2356
- // This is the first update. Create a circular list.
2357
- update.next = update;
2358
- } else {
2359
- update.next = pending.next;
2360
- pending.next = update;
2361
- }
2362
- queue.pending = update;
2363
- }
2364
-}
2365
-
2323
+// TODO: Move to ReactFiberConcurrentUpdates?
2324
function entangleTransitionUpdate<S, A>(
2325
root: FiberRoot,
2326
queue: UpdateQueue<S, A>,