Skip to content

Commit 7cb1b52

Browse files
committed
Support Suspending/Erroring Virtual Instances
This finds the nearest Fiber Instance downwards filtered or otherwise. Then from its parent we find the nearest Error or Suspense boundary. That's because VirtualInstance will always have their inner Fiber as an Instance but they might not have their parent since it might be filtered.
1 parent 59db5cb commit 7cb1b52

File tree

1 file changed

+63
-44
lines changed
  • packages/react-devtools-shared/src/backend/fiber

1 file changed

+63
-44
lines changed

packages/react-devtools-shared/src/backend/fiber/renderer.js

Lines changed: 63 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5371,6 +5371,25 @@ export function attach(
53715371
);
53725372
}
53735373

5374+
function getNearestFiber(devtoolsInstance: DevToolsInstance): null | Fiber {
5375+
if (devtoolsInstance.kind === VIRTUAL_INSTANCE) {
5376+
let inst: DevToolsInstance = devtoolsInstance;
5377+
while (inst.kind === VIRTUAL_INSTANCE) {
5378+
// For virtual instances, we search deeper until we find a Fiber instance.
5379+
// Then we search upwards from that Fiber. That's because Virtual Instances
5380+
// will always have an Fiber child filtered or not. If we searched its parents
5381+
// we might skip through a filtered Error Boundary before we hit a FiberInstance.
5382+
if (inst.firstChild === null) {
5383+
return null;
5384+
}
5385+
inst = inst.firstChild;
5386+
}
5387+
return inst.data.return;
5388+
} else {
5389+
return devtoolsInstance.data;
5390+
}
5391+
}
5392+
53745393
// React will switch between these implementations depending on whether
53755394
// we have any manually suspended/errored-out Fibers or not.
53765395
function shouldErrorFiberAlwaysNull() {
@@ -5435,27 +5454,27 @@ export function attach(
54355454
if (devtoolsInstance === undefined) {
54365455
return;
54375456
}
5438-
if (devtoolsInstance.kind === FIBER_INSTANCE) {
5439-
let fiber = devtoolsInstance.data;
5440-
while (!isErrorBoundary(fiber)) {
5441-
if (fiber.return === null) {
5442-
return;
5443-
}
5444-
fiber = fiber.return;
5445-
}
5446-
forceErrorForFibers.set(fiber, forceError);
5447-
if (fiber.alternate !== null) {
5448-
// We only need one of the Fibers in the set.
5449-
forceErrorForFibers.delete(fiber.alternate);
5450-
}
5451-
if (forceErrorForFibers.size === 1) {
5452-
// First override is added. Switch React to slower path.
5453-
setErrorHandler(shouldErrorFiberAccordingToMap);
5457+
const nearestFiber = getNearestFiber(devtoolsInstance);
5458+
if (nearestFiber === null) {
5459+
return;
5460+
}
5461+
let fiber = nearestFiber;
5462+
while (!isErrorBoundary(fiber)) {
5463+
if (fiber.return === null) {
5464+
return;
54545465
}
5455-
scheduleUpdate(fiber);
5456-
} else {
5457-
// TODO: Handle VirtualInstance.
5466+
fiber = fiber.return;
5467+
}
5468+
forceErrorForFibers.set(fiber, forceError);
5469+
if (fiber.alternate !== null) {
5470+
// We only need one of the Fibers in the set.
5471+
forceErrorForFibers.delete(fiber.alternate);
54585472
}
5473+
if (forceErrorForFibers.size === 1) {
5474+
// First override is added. Switch React to slower path.
5475+
setErrorHandler(shouldErrorFiberAccordingToMap);
5476+
}
5477+
scheduleUpdate(fiber);
54595478
}
54605479

54615480
function shouldSuspendFiberAlwaysFalse() {
@@ -5484,36 +5503,36 @@ export function attach(
54845503
if (devtoolsInstance === undefined) {
54855504
return;
54865505
}
5487-
if (devtoolsInstance.kind === FIBER_INSTANCE) {
5488-
let fiber = devtoolsInstance.data;
5489-
while (fiber.tag !== SuspenseComponent) {
5490-
if (fiber.return === null) {
5491-
return;
5492-
}
5493-
fiber = fiber.return;
5506+
const nearestFiber = getNearestFiber(devtoolsInstance);
5507+
if (nearestFiber === null) {
5508+
return;
5509+
}
5510+
let fiber = nearestFiber;
5511+
while (fiber.tag !== SuspenseComponent) {
5512+
if (fiber.return === null) {
5513+
return;
54945514
}
5515+
fiber = fiber.return;
5516+
}
54955517

5496-
if (fiber.alternate !== null) {
5497-
// We only need one of the Fibers in the set.
5498-
forceFallbackForFibers.delete(fiber.alternate);
5499-
}
5500-
if (forceFallback) {
5501-
forceFallbackForFibers.add(fiber);
5502-
if (forceFallbackForFibers.size === 1) {
5503-
// First override is added. Switch React to slower path.
5504-
setSuspenseHandler(shouldSuspendFiberAccordingToSet);
5505-
}
5506-
} else {
5507-
forceFallbackForFibers.delete(fiber);
5508-
if (forceFallbackForFibers.size === 0) {
5509-
// Last override is gone. Switch React back to fast path.
5510-
setSuspenseHandler(shouldSuspendFiberAlwaysFalse);
5511-
}
5518+
if (fiber.alternate !== null) {
5519+
// We only need one of the Fibers in the set.
5520+
forceFallbackForFibers.delete(fiber.alternate);
5521+
}
5522+
if (forceFallback) {
5523+
forceFallbackForFibers.add(fiber);
5524+
if (forceFallbackForFibers.size === 1) {
5525+
// First override is added. Switch React to slower path.
5526+
setSuspenseHandler(shouldSuspendFiberAccordingToSet);
55125527
}
5513-
scheduleUpdate(fiber);
55145528
} else {
5515-
// TODO: Handle VirtualInstance.
5529+
forceFallbackForFibers.delete(fiber);
5530+
if (forceFallbackForFibers.size === 0) {
5531+
// Last override is gone. Switch React back to fast path.
5532+
setSuspenseHandler(shouldSuspendFiberAlwaysFalse);
5533+
}
55165534
}
5535+
scheduleUpdate(fiber);
55175536
}
55185537

55195538
// Remember if we're trying to restore the selection after reload.

0 commit comments

Comments
 (0)