From 0e79784702927f1d1c6c212475e7c5141fa13a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Sun, 5 Oct 2025 08:13:22 -0400 Subject: [PATCH 1/2] [DevTools] Use documentElement to override cmd+F (#34734) We override Cmd+F to jump to our search input instead of searching through the HTML. This is ofc critical since our view virtualized. However, Chrome DevTools installs its own listener on the document as well (in the bubble phase) so if we prevent it at the document level it's too late and it ends up stealing the focus instead. If we instead listen at the documentElement it works as intended. --- .../src/devtools/views/SearchInput.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/SearchInput.js b/packages/react-devtools-shared/src/devtools/views/SearchInput.js index d50026d73bebe..3d94128bd67b9 100644 --- a/packages/react-devtools-shared/src/devtools/views/SearchInput.js +++ b/packages/react-devtools-shared/src/devtools/views/SearchInput.js @@ -64,8 +64,9 @@ export default function SearchInput({ const handleKeyDown = (event: KeyboardEvent) => { const {key, metaKey} = event; if (key === 'f' && metaKey) { - if (inputRef.current !== null) { - inputRef.current.focus(); + const inputElement = inputRef.current; + if (inputElement !== null) { + inputElement.focus(); event.preventDefault(); event.stopPropagation(); } @@ -75,10 +76,14 @@ export default function SearchInput({ // It's important to listen to the ownerDocument to support the browser extension. // Here we use portals to render individual tabs (e.g. Profiler), // and the root document might belong to a different window. - const ownerDocument = inputRef.current.ownerDocument; - ownerDocument.addEventListener('keydown', handleKeyDown); + const ownerDocumentElement = inputRef.current.ownerDocument.documentElement; + if (ownerDocumentElement === null) { + return; + } + ownerDocumentElement.addEventListener('keydown', handleKeyDown); - return () => ownerDocument.removeEventListener('keydown', handleKeyDown); + return () => + ownerDocumentElement.removeEventListener('keydown', handleKeyDown); }, []); return ( From 62ff1e61fce3eca9346716715679e7604477d84d Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin <28902667+hoxyq@users.noreply.github.com> Date: Sun, 5 Oct 2025 13:35:07 +0100 Subject: [PATCH 2/2] Revert "[DevTools] Always include the root in the timeline and select it by default" (#34739) Reverts facebook/react#34654 --- .../devtools/views/SuspenseTab/SuspenseTab.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTab.js b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTab.js index f698f0ae16549..f7b63fa2c62c2 100644 --- a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTab.js +++ b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTab.js @@ -34,10 +34,6 @@ import { SuspenseTreeStateContext, } from './SuspenseTreeContext'; import {StoreContext, OptionsContext} from '../context'; -import { - TreeDispatcherContext, - TreeStateContext, -} from '../Components/TreeContext'; import Button from '../Button'; import Toggle from '../Toggle'; import typeof {SyntheticPointerEvent} from 'react-dom-bindings/src/events/SyntheticEvent'; @@ -185,18 +181,6 @@ function SuspenseTab(_: {}) { treeListHorizontalFraction, } = state; - const {inspectedElementID} = useContext(TreeStateContext); - const {timeline} = useContext(SuspenseTreeStateContext); - const treeDispatch = useContext(TreeDispatcherContext); - useLayoutEffect(() => { - // If the inspected element is still null and we've loaded a timeline, we can set the initial selection. - // TODO: This tab should use its own source of truth instead so we only show suspense boundaries. - if (inspectedElementID === null && timeline.length > 0) { - const milestone = timeline[timeline.length - 1]; - treeDispatch({type: 'SELECT_ELEMENT_BY_ID', payload: milestone}); - } - }, [timeline, inspectedElementID]); - useLayoutEffect(() => { const wrapperElement = wrapperTreeRef.current;