@samitouri / QOS-React / commits / 99cba2b041

[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 {