[DevTools] Track root instances in a root Map (#30875)
The FiberRoot is a stateful node that can be tracked this way. This is another step that will let us remove the `fiberToFiberInstanceMap`.
Sebastian Markbåge committed
Sep 4, 2024 at 16:15 UTC
0123d7c19f2d2b05d612e9bd912b3614024b2aab
1 file changed
+35
-22
packages/react-devtools-shared/src/backend/fiber/renderer.js
+35
-22
@@ -114,7 +114,7 @@ import {getStyleXData} from '../StyleX/utils';
114
import {createProfilingHooks} from '../profilingHooks';
115
116
import type {GetTimelineData, ToggleProfilingStatus} from '../profilingHooks';
117
-import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
117
+import type {Fiber, FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
118
import type {
119
ChangeDescription,
120
CommitDataBackend,
@@ -727,6 +727,9 @@ export function getInternalReactConstants(version: string): {
727
// filters at the same time as removing some other filter.
728
const knownEnvironmentNames: Set<string> = new Set();
729
730
+// Map of FiberRoot to their root FiberInstance.
731
+const rootToFiberInstanceMap: Map<FiberRoot, FiberInstance> = new Map();
732
+
733
// Map of one or more Fibers in a pair to their unique id number.
734
// We track both Fibers to support Fast Refresh,
735
// which may forcefully replace one of the pair as part of hot reloading.
@@ -1243,9 +1246,15 @@ export function attach(
1246
1247
// Recursively unmount all roots.
1248
hook.getFiberRoots(rendererID).forEach(root => {
1246
- const rootInstance = getFiberInstanceThrows(root.current);
1249
+ const rootInstance = rootToFiberInstanceMap.get(root);
1250
+ if (rootInstance === undefined) {
1251
+ throw new Error(
1252
+ 'Expected the root instance to already exist when applying filters',
1253
+ );
1254
+ }
1255
currentRootID = rootInstance.id;
1256
unmountInstanceRecursively(rootInstance);
1257
+ rootToFiberInstanceMap.delete(root);
1258
flushPendingEvents(root);
1259
currentRootID = -1;
1260
});
@@ -1260,6 +1269,7 @@ export function attach(
1269
const current = root.current;
1270
const alternate = current.alternate;
1271
const newRoot = createFiberInstance(current);
1272
+ rootToFiberInstanceMap.set(root, newRoot);
1273
idToDevToolsInstanceMap.set(newRoot.id, newRoot);
1274
fiberToFiberInstanceMap.set(current, newRoot);
1275
if (alternate) {
@@ -1479,17 +1489,6 @@ export function attach(
1489
// When a mount or update is in progress, this value tracks the root that is being operated on.
1490
let currentRootID: number = -1;
1491
1482
- // Returns a FiberInstance if one has already been generated for the Fiber or throws.
1483
- function getFiberInstanceThrows(fiber: Fiber): FiberInstance {
1484
- const fiberInstance = getFiberInstanceUnsafe(fiber);
1485
- if (fiberInstance !== null) {
1486
- return fiberInstance;
1487
- }
1488
- throw Error(
1489
- `Could not find ID for Fiber "${getDisplayNameForFiber(fiber) || ''}"`,
1490
- );
1491
- }
1492
-
1492
function getFiberIDThrows(fiber: Fiber): number {
1493
const fiberInstance = getFiberInstanceUnsafe(fiber);
1494
if (fiberInstance !== null) {
@@ -2181,7 +2180,7 @@ export function attach(
2180
const isRoot = fiber.tag === HostRoot;
2181
let fiberInstance;
2182
if (isRoot) {
2184
- const entry = fiberToFiberInstanceMap.get(fiber);
2183
+ const entry = rootToFiberInstanceMap.get(fiber.stateNode);
2184
if (entry === undefined) {
2185
throw new Error('The root should have been registered at this point');
2186
}
@@ -3591,6 +3590,7 @@ export function attach(
3590
const current = root.current;
3591
const alternate = current.alternate;
3592
const newRoot = createFiberInstance(current);
3593
+ rootToFiberInstanceMap.set(root, newRoot);
3594
idToDevToolsInstanceMap.set(newRoot.id, newRoot);
3595
fiberToFiberInstanceMap.set(current, newRoot);
3596
if (alternate) {
@@ -3657,15 +3657,17 @@ export function attach(
3657
}
3658
}
3659
3660
- function handleCommitFiberRoot(root: any, priorityLevel: void | number) {
3660
+ function handleCommitFiberRoot(
3661
+ root: FiberRoot,
3662
+ priorityLevel: void | number,
3663
+ ) {
3664
const current = root.current;
3665
const alternate = current.alternate;
3666
3664
- let rootInstance =
3665
- fiberToFiberInstanceMap.get(current) ||
3666
- (alternate && fiberToFiberInstanceMap.get(alternate));
3667
+ let rootInstance = rootToFiberInstanceMap.get(root);
3668
if (!rootInstance) {
3669
rootInstance = createFiberInstance(current);
3670
+ rootToFiberInstanceMap.set(root, rootInstance);
3671
idToDevToolsInstanceMap.set(rootInstance.id, rootInstance);
3672
fiberToFiberInstanceMap.set(current, rootInstance);
3673
if (alternate) {
@@ -3730,8 +3732,9 @@ export function attach(
3732
updateFiberRecursively(rootInstance, current, alternate, false);
3733
} else if (wasMounted && !isMounted) {
3734
// Unmount an existing root.
3733
- removeRootPseudoKey(currentRootID);
3735
unmountInstanceRecursively(rootInstance);
3736
+ removeRootPseudoKey(currentRootID);
3737
+ rootToFiberInstanceMap.delete(root);
3738
}
3739
} else {
3740
// Mount a new root.
@@ -5248,7 +5251,12 @@ export function attach(
5251
idToContextsMap = new Map();
5252
5253
hook.getFiberRoots(rendererID).forEach(root => {
5251
- const rootInstance = getFiberInstanceThrows(root.current);
5254
+ const rootInstance = rootToFiberInstanceMap.get(root);
5255
+ if (rootInstance === undefined) {
5256
+ throw new Error(
5257
+ 'Expected the root instance to already exist when starting profiling',
5258
+ );
5259
+ }
5260
const rootID = rootInstance.id;
5261
((displayNamesByRootID: any): DisplayNamesByRootID).set(
5262
rootID,
@@ -5645,8 +5653,13 @@ export function attach(
5653
case HostRoot:
5654
// Roots don't have a real displayName, index, or key.
5655
// Instead, we'll use the pseudo key (childDisplayName:indexWithThatName).
5648
- const id = getFiberIDThrows(fiber);
5649
- const pseudoKey = rootPseudoKeys.get(id);
5656
+ const rootInstance = rootToFiberInstanceMap.get(fiber.stateNode);
5657
+ if (rootInstance === undefined) {
5658
+ throw new Error(
5659
+ 'Expected the root instance to exist when computing a path',
5660
+ );
5661
+ }
5662
+ const pseudoKey = rootPseudoKeys.get(rootInstance.id);
5663
if (pseudoKey === undefined) {
5664
throw new Error('Expected mounted root to have known pseudo key.');
5665
}