Skip to content

Commit d9fb383

Browse files
authored
Extract queueing logic into shared functions (#22452)
As a follow up to #22445, this extracts the queueing logic that is shared between `dispatchSetState` and `dispatchReducerAction` into separate functions. It likely doesn't save any bytes since these will get inlined, anyway, but it does make the flow a bit easier to follow.
1 parent 9175f4d commit d9fb383

File tree

2 files changed

+214
-278
lines changed

2 files changed

+214
-278
lines changed

packages/react-reconciler/src/ReactFiberHooks.new.js

+107-139
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ import {logStateUpdateScheduled} from './DebugTracing';
113113
import {markStateUpdateScheduled} from './SchedulingProfiler';
114114
import {CacheContext} from './ReactFiberCacheComponent.new';
115115
import {
116-
createUpdate,
117-
enqueueUpdate,
118-
entangleTransitions,
116+
createUpdate as createLegacyQueueUpdate,
117+
enqueueUpdate as enqueueLegacyQueueUpdate,
118+
entangleTransitions as entangleLegacyQueueTransitions,
119119
} from './ReactUpdateQueue.new';
120120
import {pushInterleavedQueue} from './ReactFiberInterleavedUpdates.new';
121121
import {warnOnSubscriptionInsideStartTransition} from 'shared/ReactFeatureFlags';
@@ -2125,7 +2125,7 @@ function refreshCache<T>(fiber: Fiber, seedKey: ?() => T, seedValue: T) {
21252125
const eventTime = requestEventTime();
21262126
const root = scheduleUpdateOnFiber(provider, lane, eventTime);
21272127
if (root !== null) {
2128-
entangleTransitions(root, provider, lane);
2128+
entangleLegacyQueueTransitions(root, provider, lane);
21292129
}
21302130

21312131
const seededCache = new Map();
@@ -2136,12 +2136,12 @@ function refreshCache<T>(fiber: Fiber, seedKey: ?() => T, seedValue: T) {
21362136
}
21372137

21382138
// Schedule an update on the cache boundary to trigger a refresh.
2139-
const refreshUpdate = createUpdate(eventTime, lane);
2139+
const refreshUpdate = createLegacyQueueUpdate(eventTime, lane);
21402140
const payload = {
21412141
cache: seededCache,
21422142
};
21432143
refreshUpdate.payload = payload;
2144-
enqueueUpdate(provider, refreshUpdate, lane);
2144+
enqueueLegacyQueueUpdate(provider, refreshUpdate, lane);
21452145
return;
21462146
}
21472147
}
@@ -2165,7 +2165,6 @@ function dispatchReducerAction<S, A>(
21652165
}
21662166
}
21672167

2168-
const eventTime = requestEventTime();
21692168
const lane = requestUpdateLane(fiber);
21702169

21712170
const update: Update<S, A> = {
@@ -2176,90 +2175,25 @@ function dispatchReducerAction<S, A>(
21762175
next: (null: any),
21772176
};
21782177

2179-
const alternate = fiber.alternate;
2180-
if (
2181-
fiber === currentlyRenderingFiber ||
2182-
(alternate !== null && alternate === currentlyRenderingFiber)
2183-
) {
2184-
// This is a render phase update. Stash it in a lazily-created map of
2185-
// queue -> linked list of updates. After this render pass, we'll restart
2186-
// and apply the stashed updates on top of the work-in-progress hook.
2187-
didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true;
2188-
const pending = queue.pending;
2189-
if (pending === null) {
2190-
// This is the first update. Create a circular list.
2191-
update.next = update;
2192-
} else {
2193-
update.next = pending.next;
2194-
pending.next = update;
2195-
}
2196-
queue.pending = update;
2178+
if (isRenderPhaseUpdate(fiber)) {
2179+
enqueueRenderPhaseUpdate(queue, update);
21972180
} else {
2198-
if (isInterleavedUpdate(fiber, lane)) {
2199-
const interleaved = queue.interleaved;
2200-
if (interleaved === null) {
2201-
// This is the first update. Create a circular list.
2202-
update.next = update;
2203-
// At the end of the current render, this queue's interleaved updates will
2204-
// be transferred to the pending queue.
2205-
pushInterleavedQueue(queue);
2206-
} else {
2207-
update.next = interleaved.next;
2208-
interleaved.next = update;
2209-
}
2210-
queue.interleaved = update;
2211-
} else {
2212-
const pending = queue.pending;
2213-
if (pending === null) {
2214-
// This is the first update. Create a circular list.
2215-
update.next = update;
2216-
} else {
2217-
update.next = pending.next;
2218-
pending.next = update;
2219-
}
2220-
queue.pending = update;
2221-
}
2181+
enqueueUpdate(fiber, queue, update, lane);
22222182

22232183
if (__DEV__) {
22242184
// $FlowExpectedError - jest isn't a global, and isn't recognized outside of tests
22252185
if ('undefined' !== typeof jest) {
22262186
warnIfNotCurrentlyActingUpdatesInDev(fiber);
22272187
}
22282188
}
2189+
const eventTime = requestEventTime();
22292190
const root = scheduleUpdateOnFiber(fiber, lane, eventTime);
2230-
2231-
if (isTransitionLane(lane) && root !== null) {
2232-
let queueLanes = queue.lanes;
2233-
2234-
// If any entangled lanes are no longer pending on the root, then they
2235-
// must have finished. We can remove them from the shared queue, which
2236-
// represents a superset of the actually pending lanes. In some cases we
2237-
// may entangle more than we need to, but that's OK. In fact it's worse if
2238-
// we *don't* entangle when we should.
2239-
queueLanes = intersectLanes(queueLanes, root.pendingLanes);
2240-
2241-
// Entangle the new transition lane with the other transition lanes.
2242-
const newQueueLanes = mergeLanes(queueLanes, lane);
2243-
queue.lanes = newQueueLanes;
2244-
// Even if queue.lanes already include lane, we don't know for certain if
2245-
// the lane finished since the last time we entangled it. So we need to
2246-
// entangle it again, just to be sure.
2247-
markRootEntangled(root, newQueueLanes);
2248-
}
2249-
}
2250-
2251-
if (__DEV__) {
2252-
if (enableDebugTracing) {
2253-
if (fiber.mode & DebugTracingMode) {
2254-
const name = getComponentNameFromFiber(fiber) || 'Unknown';
2255-
logStateUpdateScheduled(name, lane, action);
2256-
}
2191+
if (root !== null) {
2192+
entangleTransitionUpdate(root, queue, lane);
22572193
}
22582194
}
22592195

2260-
if (enableSchedulingProfiler) {
2261-
markStateUpdateScheduled(fiber, lane);
2262-
}
2196+
markUpdateInDevTools(fiber, lane, action);
22632197
}
22642198

22652199
function dispatchSetState<S, A>(
@@ -2277,7 +2211,6 @@ function dispatchSetState<S, A>(
22772211
}
22782212
}
22792213

2280-
const eventTime = requestEventTime();
22812214
const lane = requestUpdateLane(fiber);
22822215

22832216
const update: Update<S, A> = {
@@ -2288,50 +2221,12 @@ function dispatchSetState<S, A>(
22882221
next: (null: any),
22892222
};
22902223

2291-
const alternate = fiber.alternate;
2292-
if (
2293-
fiber === currentlyRenderingFiber ||
2294-
(alternate !== null && alternate === currentlyRenderingFiber)
2295-
) {
2296-
// This is a render phase update. Stash it in a lazily-created map of
2297-
// queue -> linked list of updates. After this render pass, we'll restart
2298-
// and apply the stashed updates on top of the work-in-progress hook.
2299-
didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true;
2300-
const pending = queue.pending;
2301-
if (pending === null) {
2302-
// This is the first update. Create a circular list.
2303-
update.next = update;
2304-
} else {
2305-
update.next = pending.next;
2306-
pending.next = update;
2307-
}
2308-
queue.pending = update;
2224+
if (isRenderPhaseUpdate(fiber)) {
2225+
enqueueRenderPhaseUpdate(queue, update);
23092226
} else {
2310-
if (isInterleavedUpdate(fiber, lane)) {
2311-
const interleaved = queue.interleaved;
2312-
if (interleaved === null) {
2313-
// This is the first update. Create a circular list.
2314-
update.next = update;
2315-
// At the end of the current render, this queue's interleaved updates will
2316-
// be transferred to the pending queue.
2317-
pushInterleavedQueue(queue);
2318-
} else {
2319-
update.next = interleaved.next;
2320-
interleaved.next = update;
2321-
}
2322-
queue.interleaved = update;
2323-
} else {
2324-
const pending = queue.pending;
2325-
if (pending === null) {
2326-
// This is the first update. Create a circular list.
2327-
update.next = update;
2328-
} else {
2329-
update.next = pending.next;
2330-
pending.next = update;
2331-
}
2332-
queue.pending = update;
2333-
}
2227+
enqueueUpdate(fiber, queue, update, lane);
23342228

2229+
const alternate = fiber.alternate;
23352230
if (
23362231
fiber.lanes === NoLanes &&
23372232
(alternate === null || alternate.lanes === NoLanes)
@@ -2377,28 +2272,101 @@ function dispatchSetState<S, A>(
23772272
warnIfNotCurrentlyActingUpdatesInDev(fiber);
23782273
}
23792274
}
2275+
const eventTime = requestEventTime();
23802276
const root = scheduleUpdateOnFiber(fiber, lane, eventTime);
2277+
if (root !== null) {
2278+
entangleTransitionUpdate(root, queue, lane);
2279+
}
2280+
}
2281+
2282+
markUpdateInDevTools(fiber, lane, action);
2283+
}
2284+
2285+
function isRenderPhaseUpdate(fiber: Fiber) {
2286+
const alternate = fiber.alternate;
2287+
return (
2288+
fiber === currentlyRenderingFiber ||
2289+
(alternate !== null && alternate === currentlyRenderingFiber)
2290+
);
2291+
}
2292+
2293+
function enqueueRenderPhaseUpdate<S, A>(
2294+
queue: UpdateQueue<S, A>,
2295+
update: Update<S, A>,
2296+
) {
2297+
// This is a render phase update. Stash it in a lazily-created map of
2298+
// queue -> linked list of updates. After this render pass, we'll restart
2299+
// and apply the stashed updates on top of the work-in-progress hook.
2300+
didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true;
2301+
const pending = queue.pending;
2302+
if (pending === null) {
2303+
// This is the first update. Create a circular list.
2304+
update.next = update;
2305+
} else {
2306+
update.next = pending.next;
2307+
pending.next = update;
2308+
}
2309+
queue.pending = update;
2310+
}
23812311

2382-
if (isTransitionLane(lane) && root !== null) {
2383-
let queueLanes = queue.lanes;
2384-
2385-
// If any entangled lanes are no longer pending on the root, then they
2386-
// must have finished. We can remove them from the shared queue, which
2387-
// represents a superset of the actually pending lanes. In some cases we
2388-
// may entangle more than we need to, but that's OK. In fact it's worse if
2389-
// we *don't* entangle when we should.
2390-
queueLanes = intersectLanes(queueLanes, root.pendingLanes);
2391-
2392-
// Entangle the new transition lane with the other transition lanes.
2393-
const newQueueLanes = mergeLanes(queueLanes, lane);
2394-
queue.lanes = newQueueLanes;
2395-
// Even if queue.lanes already include lane, we don't know for certain if
2396-
// the lane finished since the last time we entangled it. So we need to
2397-
// entangle it again, just to be sure.
2398-
markRootEntangled(root, newQueueLanes);
2312+
function enqueueUpdate<S, A>(
2313+
fiber: Fiber,
2314+
queue: UpdateQueue<S, A>,
2315+
update: Update<S, A>,
2316+
lane: Lane,
2317+
) {
2318+
if (isInterleavedUpdate(fiber, lane)) {
2319+
const interleaved = queue.interleaved;
2320+
if (interleaved === null) {
2321+
// This is the first update. Create a circular list.
2322+
update.next = update;
2323+
// At the end of the current render, this queue's interleaved updates will
2324+
// be transferred to the pending queue.
2325+
pushInterleavedQueue(queue);
2326+
} else {
2327+
update.next = interleaved.next;
2328+
interleaved.next = update;
2329+
}
2330+
queue.interleaved = update;
2331+
} else {
2332+
const pending = queue.pending;
2333+
if (pending === null) {
2334+
// This is the first update. Create a circular list.
2335+
update.next = update;
2336+
} else {
2337+
update.next = pending.next;
2338+
pending.next = update;
23992339
}
2340+
queue.pending = update;
2341+
}
2342+
}
2343+
2344+
function entangleTransitionUpdate<S, A>(
2345+
root: FiberRoot,
2346+
queue: UpdateQueue<S, A>,
2347+
lane: Lane,
2348+
) {
2349+
if (isTransitionLane(lane)) {
2350+
let queueLanes = queue.lanes;
2351+
2352+
// If any entangled lanes are no longer pending on the root, then they
2353+
// must have finished. We can remove them from the shared queue, which
2354+
// represents a superset of the actually pending lanes. In some cases we
2355+
// may entangle more than we need to, but that's OK. In fact it's worse if
2356+
// we *don't* entangle when we should.
2357+
queueLanes = intersectLanes(queueLanes, root.pendingLanes);
2358+
2359+
// Entangle the new transition lane with the other transition lanes.
2360+
const newQueueLanes = mergeLanes(queueLanes, lane);
2361+
queue.lanes = newQueueLanes;
2362+
// Even if queue.lanes already include lane, we don't know for certain if
2363+
// the lane finished since the last time we entangled it. So we need to
2364+
// entangle it again, just to be sure.
2365+
markRootEntangled(root, newQueueLanes);
24002366
}
2367+
}
24012368

2369+
function markUpdateInDevTools(fiber, lane, action) {
24022370
if (__DEV__) {
24032371
if (enableDebugTracing) {
24042372
if (fiber.mode & DebugTracingMode) {

0 commit comments

Comments
 (0)