[DevTools] Build Updater List from the Commit instead of Map (#30897)
Stacked on #30896. The problem with the `getUpdatersList` function is that it iterates over Fibers and then looks up each of those Fibers in the fiberToFiberInstanceMap which we ideally could get rid of. However, every time an updater comes into play for a commit it must mean that something below the updater itself updated and so the updater will also be cloned which means we'll pass it on the way down when traversing the tree in the commit. When we do this traversal, we can just look if the Fiber is in the updater set and if so add it to the updater list as we go.
Sebastian Markbåge committed
Sep 6, 2024 at 21:59 UTC
99cba2b041cd13d7ade48a5c97b473e8a188df35
1 file changed
+50
-39
packages/react-devtools-shared/src/backend/fiber/renderer.js
+50
-39
@@ -1293,11 +1293,11 @@ export function attach(
1293
'Expected the root instance to already exist when applying filters',
1294
);
1295
}
1296
- currentRootID = rootInstance.id;
1296
+ currentRoot = rootInstance;
1297
unmountInstanceRecursively(rootInstance);
1298
rootToFiberInstanceMap.delete(root);
1299
flushPendingEvents(root);
1300
- currentRootID = -1;
1300
+ currentRoot = (null: any);
1301
});
1302
1303
applyComponentFilters(componentFilters);
@@ -1323,11 +1323,11 @@ export function attach(
1323
mightBeOnTrackedPath = true;
1324
}
1325
1326
- currentRootID = newRoot.id;
1327
- setRootPseudoKey(currentRootID, root.current);
1326
+ currentRoot = newRoot;
1327
+ setRootPseudoKey(currentRoot.id, root.current);
1328
mountFiberRecursively(root.current, false);
1329
flushPendingEvents(root);
1330
- currentRootID = -1;
1330
+ currentRoot = (null: any);
1331
});
1332
1333
// Also re-evaluate all error and warning counts given the new filters.
@@ -1528,7 +1528,7 @@ export function attach(
1528
}
1529
1530
// When a mount or update is in progress, this value tracks the root that is being operated on.
1531
- let currentRootID: number = -1;
1531
+ let currentRoot: FiberInstance = (null: any);
1532
1533
// Returns a FiberInstance if one has already been generated for the Fiber or null if one has not been generated.
1534
// Use this method while e.g. logging to avoid over-retaining Fibers.
@@ -1885,7 +1885,12 @@ export function attach(
1885
3 + pendingOperations.length,
1886
);
1887
operations[0] = rendererID;
1888
- operations[1] = currentRootID;
1888
+ if (currentRoot === null) {
1889
+ // TODO: This is not always safe so this field is probably not needed.
1890
+ operations[1] = -1;
1891
+ } else {
1892
+ operations[1] = currentRoot.id;
1893
+ }
1894
operations[2] = 0; // String table size
1895
for (let j = 0; j < pendingOperations.length; j++) {
1896
operations[3 + j] = pendingOperations[j];
@@ -2038,7 +2043,12 @@ export function attach(
2043
// Which in turn enables fiber props, states, and hooks to be inspected.
2044
let i = 0;
2045
operations[i++] = rendererID;
2041
- operations[i++] = currentRootID;
2046
+ if (currentRoot === null) {
2047
+ // TODO: This is not always safe so this field is probably not needed.
2048
+ operations[i++] = -1;
2049
+ } else {
2050
+ operations[i++] = currentRoot.id;
2051
+ }
2052
2053
// Now fill in the string table.
2054
// [stringTableLength, str1Length, ...str1, str2Length, ...str2, ...]
@@ -2881,6 +2891,25 @@ export function attach(
2891
}
2892
}
2893
}
2894
+
2895
+ // If this Fiber was in the set of memoizedUpdaters we need to record
2896
+ // it to be included in the description of the commit.
2897
+ const fiberRoot: FiberRoot = currentRoot.data.stateNode;
2898
+ const updaters = fiberRoot.memoizedUpdaters;
2899
+ if (
2900
+ updaters != null &&
2901
+ (updaters.has(fiber) ||
2902
+ // We check the alternate here because we're matching identity and
2903
+ // prevFiber might be same as fiber.
2904
+ (fiber.alternate !== null && updaters.has(fiber.alternate)))
2905
+ ) {
2906
+ const metadata =
2907
+ ((currentCommitProfilingMetadata: any): CommitProfilingData);
2908
+ if (metadata.updaters === null) {
2909
+ metadata.updaters = [];
2910
+ }
2911
+ metadata.updaters.push(instanceToSerializedElement(fiberInstance));
2912
+ }
2913
}
2914
}
2915
@@ -3568,8 +3597,8 @@ export function attach(
3597
if (alternate) {
3598
fiberToFiberInstanceMap.set(alternate, newRoot);
3599
}
3571
- currentRootID = newRoot.id;
3572
- setRootPseudoKey(currentRootID, root.current);
3600
+ currentRoot = newRoot;
3601
+ setRootPseudoKey(currentRoot.id, root.current);
3602
3603
// Handle multi-renderer edge-case where only some v16 renderers support profiling.
3604
if (isProfiling && rootSupportsProfiling(root)) {
@@ -3581,35 +3610,20 @@ export function attach(
3610
commitTime: getCurrentTime() - profilingStartTime,
3611
maxActualDuration: 0,
3612
priorityLevel: null,
3584
- updaters: getUpdatersList(root),
3613
+ updaters: null,
3614
effectDuration: null,
3615
passiveEffectDuration: null,
3616
};
3617
}
3618
3619
mountFiberRecursively(root.current, false);
3620
+
3621
flushPendingEvents(root);
3592
- currentRootID = -1;
3622
+ currentRoot = (null: any);
3623
});
3624
}
3625
}
3626
3597
- function getUpdatersList(root: any): Array<SerializedElement> | null {
3598
- const updaters = root.memoizedUpdaters;
3599
- if (updaters == null) {
3600
- return null;
3601
- }
3602
- const result = [];
3603
- // eslint-disable-next-line no-for-of-loops/no-for-of-loops
3604
- for (const updater of updaters) {
3605
- const inst = getFiberInstanceUnsafe(updater);
3606
- if (inst !== null) {
3607
- result.push(instanceToSerializedElement(inst));
3608
- }
3609
- }
3610
- return result;
3611
- }
3612
-
3627
function handleCommitFiberUnmount(fiber: any) {
3628
// This Hook is no longer used. After having shipped DevTools everywhere it is
3629
// safe to stop calling it from Fiber.
@@ -3646,11 +3660,10 @@ export function attach(
3660
if (alternate) {
3661
fiberToFiberInstanceMap.set(alternate, rootInstance);
3662
}
3649
- currentRootID = rootInstance.id;
3663
} else {
3651
- currentRootID = rootInstance.id;
3664
prevFiber = rootInstance.data;
3665
}
3666
+ currentRoot = rootInstance;
3667
3668
// Before the traversals, remember to start tracking
3669
// our path in case we have selection to restore.
@@ -3675,9 +3688,7 @@ export function attach(
3688
maxActualDuration: 0,
3689
priorityLevel:
3690
priorityLevel == null ? null : formatPriorityLevel(priorityLevel),
3678
-
3679
- updaters: getUpdatersList(root),
3680
-
3691
+ updaters: null,
3692
// Initialize to null; if new enough React version is running,
3693
// these values will be read during separate handlePostCommitFiberRoot() call.
3694
effectDuration: null,
@@ -3699,7 +3710,7 @@ export function attach(
3710
current.memoizedState.isDehydrated !== true;
3711
if (!wasMounted && isMounted) {
3712
// Mount a new root.
3702
- setRootPseudoKey(currentRootID, current);
3713
+ setRootPseudoKey(currentRoot.id, current);
3714
mountFiberRecursively(current, false);
3715
} else if (wasMounted && isMounted) {
3716
// Update an existing root.
@@ -3707,12 +3718,12 @@ export function attach(
3718
} else if (wasMounted && !isMounted) {
3719
// Unmount an existing root.
3720
unmountInstanceRecursively(rootInstance);
3710
- removeRootPseudoKey(currentRootID);
3721
+ removeRootPseudoKey(currentRoot.id);
3722
rootToFiberInstanceMap.delete(root);
3723
}
3724
} else {
3725
// Mount a new root.
3715
- setRootPseudoKey(currentRootID, current);
3726
+ setRootPseudoKey(currentRoot.id, current);
3727
mountFiberRecursively(current, false);
3728
}
3729
@@ -3720,7 +3731,7 @@ export function attach(
3731
if (!shouldBailoutWithPendingOperations()) {
3732
const commitProfilingMetadata =
3733
((rootToCommitProfilingMetadataMap: any): CommitProfilingMetadataMap).get(
3723
- currentRootID,
3734
+ currentRoot.id,
3735
);
3736
3737
if (commitProfilingMetadata != null) {
@@ -3729,7 +3740,7 @@ export function attach(
3740
);
3741
} else {
3742
((rootToCommitProfilingMetadataMap: any): CommitProfilingMetadataMap).set(
3732
- currentRootID,
3743
+ currentRoot.id,
3744
[((currentCommitProfilingMetadata: any): CommitProfilingData)],
3745
);
3746
}
@@ -3743,7 +3754,7 @@ export function attach(
3754
hook.emit('traceUpdates', traceUpdatesForNodes);
3755
}
3756
3746
- currentRootID = -1;
3757
+ currentRoot = (null: any);
3758
}
3759
3760
function getResourceInstance(fiber: Fiber): HostInstance | null {