@samitouri / QOS-React / commits / 13036bfbc8

DevTools should not crawl unmounted subtrees when profiling starts (#23162)

Previously we crawled all subtrees, even not-yet-mounted ones, to initialize context values. This was not only unecessary, but it also caused an error to be thrown. This commit adds a test and fixes that behavior.

Brian Vaughn committed Jan 21, 2022 at 11:05 UTC 13036bfbc8ecbcf4451adb7bde397f438caa8607
2 files changed +33 -5
packages/react-devtools-shared/src/__tests__/profilerStore-test.js
+20
@@ -221,4 +221,24 @@ describe('ProfilerStore', () => {
221 expect(data.commitData).toHaveLength(1);
222 expect(data.operations).toHaveLength(1);
223 });
224 +
225 + it('should not throw while initializing context values for Fibers within a not-yet-mounted subtree', () => {
226 + const promise = new Promise(resolve => {});
227 + const SuspendingView = () => {
228 + throw promise;
229 + };
230 +
231 + const App = () => {
232 + return (
233 + <React.Suspense fallback="Fallback">
234 + <SuspendingView />
235 + </React.Suspense>
236 + );
237 + };
238 +
239 + const container = document.createElement('div');
240 +
241 + utils.act(() => legacyRender(<App />, container));
242 + utils.act(() => store.profilerStore.startProfiling());
243 + });
244 });
packages/react-devtools-shared/src/backend/renderer.js
+13 -5
@@ -1347,11 +1347,19 @@ export function attach(
1347 // Fibers only store the current context value,
1348 // so we need to track them separately in order to determine changed keys.
1349 function crawlToInitializeContextsMap(fiber: Fiber) {
1350 - updateContextsForFiber(fiber);
1351 - let current = fiber.child;
1352 - while (current !== null) {
1353 - crawlToInitializeContextsMap(current);
1354 - current = current.sibling;
1350 + const id = getFiberIDUnsafe(fiber);
1351 +
1352 + // Not all Fibers in the subtree have mounted yet.
1353 + // For example, Offscreen (hidden) or Suspense (suspended) subtrees won't yet be tracked.
1354 + // We can safely skip these subtrees.
1355 + if (id !== null) {
1356 + updateContextsForFiber(fiber);
1357 +
1358 + let current = fiber.child;
1359 + while (current !== null) {
1360 + crawlToInitializeContextsMap(current);
1361 + current = current.sibling;
1362 + }
1363 }
1364 }
1365