From f23aa1d9f5034e7cfbd3e6015ce102bb72a005a0 Mon Sep 17 00:00:00 2001 From: "Sebastian \"Sebbie\" Silbermann" Date: Tue, 10 Feb 2026 13:09:23 +0100 Subject: [PATCH] [DevTools] Fix memory leak when unmounting hoistables (#35741) --- .../src/__tests__/store-test.js | 55 +++++++++++++++++++ .../src/backend/fiber/renderer.js | 2 +- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/packages/react-devtools-shared/src/__tests__/store-test.js b/packages/react-devtools-shared/src/__tests__/store-test.js index 97cb49a66f..f3bcf189c8 100644 --- a/packages/react-devtools-shared/src/__tests__/store-test.js +++ b/packages/react-devtools-shared/src/__tests__/store-test.js @@ -3616,4 +3616,59 @@ describe('Store', () => {
`); }); + + // @reactVersion >= 19 + it('cleans up host hoistables', async () => { + function Left() { + return ( + + ); + } + + function Right() { + return ( + + ); + } + + await actAsync(() => { + render( + <> + + + , + ); + }); + + // Ensure we're still testing deduplicated hoistables. + expect(document.head.querySelectorAll('style')).toHaveLength(1); + expect(store).toMatchInlineSnapshot(` + [root] + + + `); + let style = document.head.querySelector('style'); + let styleID = agent.getIDForHostInstance(style).id; + expect(store.containsElement(styleID)).toBe(true); + + await actAsync(() => { + render( + <> + + , + ); + }); + + expect(store).toMatchInlineSnapshot(` + [root] + + `); + style = document.head.querySelector('style'); + styleID = agent.getIDForHostInstance(style).id; + expect(store.containsElement(styleID)).toBe(true); + }); }); diff --git a/packages/react-devtools-shared/src/backend/fiber/renderer.js b/packages/react-devtools-shared/src/backend/fiber/renderer.js index 3214c83922..916d698232 100644 --- a/packages/react-devtools-shared/src/backend/fiber/renderer.js +++ b/packages/react-devtools-shared/src/backend/fiber/renderer.js @@ -991,8 +991,8 @@ function releaseHostResource( // eslint-disable-next-line no-for-of-loops/no-for-of-loops for (const firstInstance of resourceInstances) { publicInstanceToDevToolsInstanceMap.set( + publicInstance, firstInstance, - nearestInstance, ); break; }