fix[devtools]: no-op unsupported backend bridge events (#35296)
Follow-up to https://github.com/facebook/react/pull/34641. Similar to https://github.com/facebook/react/pull/35293, https://github.com/facebook/react/pull/35294. React DevTools backend can be used in non-DOM environments, so we have to feature-check some DOM APIs. For now I am just no-oping newly added commands for Native, we should revisit this decision once we would roll out Suspense panel there, if needed. I am not sure if scrolling will be required as much as it is needed on Web. `isReactNativeEnvironment()` check is kinda clowny, but we've been relying on it for quite some time already.
Ruslan Lesiutin committed
Dec 5, 2025 at 16:41 UTC
ad5971febdf6cc3103fa51121d4015832f2af5f8
1 file changed
+26
-7
packages/react-devtools-shared/src/backend/views/Highlighter/index.js
+26
-7
@@ -9,6 +9,7 @@
9
10
import Agent from 'react-devtools-shared/src/backend/agent';
11
import {hideOverlay, showOverlay} from './Highlighter';
12
+import {isReactNativeEnvironment} from 'react-devtools-shared/src/backend/utils';
13
14
import type {HostInstance} from 'react-devtools-shared/src/backend/types';
15
import type {BackendBridge} from 'react-devtools-shared/src/bridge';
@@ -49,6 +50,11 @@ export default function setupHighlighter(
50
right: number,
51
bottom: number,
52
}) {
53
+ if (isReactNativeEnvironment()) {
54
+ // Not implemented.
55
+ return;
56
+ }
57
+
58
if (
59
left === Math.round(window.scrollX) &&
60
top === Math.round(window.scrollY)
@@ -65,6 +71,11 @@ export default function setupHighlighter(
71
72
let scrollTimer = null;
73
function sendScroll() {
74
+ if (isReactNativeEnvironment()) {
75
+ // Not implemented.
76
+ return;
77
+ }
78
+
79
if (scrollTimer) {
80
clearTimeout(scrollTimer);
81
scrollTimer = null;
@@ -85,14 +96,17 @@ export default function setupHighlighter(
96
applyingScroll = false;
97
}
98
88
- document.addEventListener('scroll', () => {
89
- if (!scrollTimer) {
90
- // Periodically synchronize the scroll while scrolling.
91
- scrollTimer = setTimeout(sendScroll, 400);
92
- }
93
- });
99
+ // $FlowFixMe[method-unbinding]
100
+ if (document && typeof document.addEventListener === 'function') {
101
+ document.addEventListener('scroll', () => {
102
+ if (!scrollTimer) {
103
+ // Periodically synchronize the scroll while scrolling.
104
+ scrollTimer = setTimeout(sendScroll, 400);
105
+ }
106
+ });
107
95
- document.addEventListener('scrollend', scrollEnd);
108
+ document.addEventListener('scrollend', scrollEnd);
109
+ }
110
111
function startInspectingHost(onlySuspenseNodes: boolean) {
112
inspectOnlySuspenseNodes = onlySuspenseNodes;
@@ -319,6 +333,11 @@ export default function setupHighlighter(
333
// with the scrollIntoView option.
334
hideOverlay(agent);
335
336
+ if (isReactNativeEnvironment()) {
337
+ // Not implemented.
338
+ return;
339
+ }
340
+
341
if (scrollDelayTimer) {
342
clearTimeout(scrollDelayTimer);
343
scrollDelayTimer = null;