From 37e918e790fc2a414f368bb0a636c2e21649fce4 Mon Sep 17 00:00:00 2001 From: Sebastian Sebbie Silbermann Date: Tue, 10 Feb 2026 12:25:16 +0100 Subject: [PATCH 1/2] Current behavior --- .../src/__tests__/store-test.js | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/packages/react-devtools-shared/src/__tests__/store-test.js b/packages/react-devtools-shared/src/__tests__/store-test.js index 871b44827e77..3309131a5ffb 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(false); + }); }); From 2ae2122e5ed0193f0c211a34c8169b9baaafa8fb Mon Sep 17 00:00:00 2001 From: Sebastian Sebbie Silbermann Date: Tue, 10 Feb 2026 12:27:28 +0100 Subject: [PATCH 2/2] [DevTools] Fix memory leak when unmounting hoistables --- packages/react-devtools-shared/src/__tests__/store-test.js | 2 +- packages/react-devtools-shared/src/backend/fiber/renderer.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-devtools-shared/src/__tests__/store-test.js b/packages/react-devtools-shared/src/__tests__/store-test.js index 3309131a5ffb..ded9088869f4 100644 --- a/packages/react-devtools-shared/src/__tests__/store-test.js +++ b/packages/react-devtools-shared/src/__tests__/store-test.js @@ -3669,6 +3669,6 @@ describe('Store', () => { `); style = document.head.querySelector('style'); styleID = agent.getIDForHostInstance(style).id; - expect(store.containsElement(styleID)).toBe(false); + 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 3214c8392285..916d69823285 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; }