Skip to content

Commit dcc5ca6

Browse files
committed
DevTools: Fix "unknown" updater in profiler when a component unsuspends
1 parent a9394fc commit dcc5ca6

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

packages/react-reconciler/src/ReactFiberLane.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,27 @@ export function markRootUpdated(root: FiberRoot, updateLane: Lane) {
625625
// idle updates until after all the regular updates have finished; there's no
626626
// way it could unblock a transition.
627627
if (updateLane !== IdleLane) {
628+
if (enableUpdaterTracking) {
629+
if (isDevToolsPresent) {
630+
// transfer pending updaters from pingedLanes to updateLane
631+
const pendingUpdatersLaneMap = root.pendingUpdatersLaneMap;
632+
const updaters = pendingUpdatersLaneMap[laneToIndex(updateLane)];
633+
let lanes = root.pingedLanes;
634+
while (lanes > 0) {
635+
const index = laneToIndex(lanes);
636+
const lane = 1 << index;
637+
638+
const pingedUpdaters = pendingUpdatersLaneMap[index];
639+
pingedUpdaters.forEach(pingedUpdater => {
640+
updaters.add(pingedUpdater);
641+
});
642+
pingedUpdaters.clear();
643+
644+
lanes &= ~lane;
645+
}
646+
}
647+
}
648+
628649
root.suspendedLanes = NoLanes;
629650
root.pingedLanes = NoLanes;
630651
}
@@ -656,7 +677,8 @@ export function markRootSuspended(
656677
}
657678

658679
export function markRootPinged(root: FiberRoot, pingedLanes: Lanes) {
659-
root.pingedLanes |= root.suspendedLanes & pingedLanes;
680+
// TODO: When would we ever ping lanes that we aren't suspended on?
681+
root.pingedLanes |= pingedLanes;
660682
}
661683

662684
export function markRootFinished(

packages/react-reconciler/src/__tests__/ReactUpdaters-test.internal.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ describe('updaters', () => {
4949
schedulerTags.push(fiber.tag);
5050
schedulerTypes.push(fiber.elementType);
5151
});
52+
fiberRoot.pendingUpdatersLaneMap.forEach((pendingUpdaters, index) => {
53+
if (pendingUpdaters.size > 0) {
54+
const lane = 1 << index;
55+
throw new Error(
56+
`Lane ${lane} has pending updaters. Either you didn't assert on all updates in your test or React is leaking updaters.`,
57+
);
58+
}
59+
});
5260
allSchedulerTags.push(schedulerTags);
5361
allSchedulerTypes.push(schedulerTypes);
5462
}),
@@ -266,9 +274,6 @@ describe('updaters', () => {
266274
await waitForAll([]);
267275
});
268276

269-
// This test should be convertable to createRoot but the allScheduledTypes assertions are no longer the same
270-
// So I'm leaving it in legacy mode for now and just disabling if legacy mode is turned off
271-
// @gate !disableLegacyMode
272277
it('should cover suspense pings', async () => {
273278
let data = null;
274279
let resolver = null;
@@ -323,7 +328,7 @@ describe('updaters', () => {
323328
return promise;
324329
});
325330
assertLog(['onCommitRoot']);
326-
expect(allSchedulerTypes).toEqual([[null], [Suspender], []]);
331+
expect(allSchedulerTypes).toEqual([[null], [Suspender], [Suspender]]);
327332

328333
// Verify no outstanding flushes
329334
await waitForAll([]);

0 commit comments

Comments
 (0)