Skip to content

Commit 19ad6d1

Browse files
committed
refactor: allow custom impl of backend realod-to-profile support check
1 parent 04bd67a commit 19ad6d1

File tree

5 files changed

+42
-55
lines changed

5 files changed

+42
-55
lines changed

packages/react-devtools-shared/src/backend/agent.js

+5-11
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import type {
3838
DevToolsHookSettings,
3939
} from './types';
4040
import type {ComponentFilter} from 'react-devtools-shared/src/frontend/types';
41-
import {isSynchronousXHRSupported, isReactNativeEnvironment} from './utils';
41+
import {isReactNativeEnvironment} from './utils';
4242

4343
const debug = (methodName: string, ...args: Array<string>) => {
4444
if (__DEBUG__) {
@@ -242,16 +242,6 @@ export default class Agent extends EventEmitter<{
242242
if (this._isProfiling) {
243243
bridge.send('profilingStatus', true);
244244
}
245-
246-
// Notify the frontend if the backend supports the Storage API (e.g. localStorage).
247-
// If not, features like reload-and-profile will not work correctly and must be disabled.
248-
let isBackendStorageAPISupported = false;
249-
try {
250-
localStorage.getItem('test');
251-
isBackendStorageAPISupported = true;
252-
} catch (error) {}
253-
bridge.send('isBackendStorageAPISupported', isBackendStorageAPISupported);
254-
bridge.send('isSynchronousXHRSupported', isSynchronousXHRSupported());
255245
}
256246

257247
get rendererInterfaces(): {[key: RendererID]: RendererInterface, ...} {
@@ -675,6 +665,10 @@ export default class Agent extends EventEmitter<{
675665
}
676666
};
677667

668+
onReloadAndProfileSupportedByHost: () => void = () => {
669+
this._bridge.send('isReloadAndProfileSupportedByBackend', true);
670+
};
671+
678672
reloadAndProfile: (recordChangeDescriptions: boolean) => void =
679673
recordChangeDescriptions => {
680674
sessionStorageSetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY, 'true');

packages/react-devtools-shared/src/backend/index.js

+21
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import Agent from './agent';
1111

1212
import type {DevToolsHook, RendererID, RendererInterface} from './types';
13+
import {isSynchronousXHRSupported} from './utils';
1314

1415
export type InitBackend = typeof initBackend;
1516

@@ -94,7 +95,27 @@ export function initBackend(
9495
}
9596
});
9697

98+
const getIsReloadAndProfileSupported =
99+
hook.settings?.getIsReloadAndProfileSupported ??
100+
defaultGetIsReloadAndProfileSupported;
101+
102+
if (getIsReloadAndProfileSupported()) {
103+
agent.onReloadAndProfileSupportedByHost();
104+
}
105+
97106
return () => {
98107
subs.forEach(fn => fn());
99108
};
100109
}
110+
111+
function defaultGetIsReloadAndProfileSupported() {
112+
// Notify the frontend if the backend supports the Storage API (e.g. localStorage).
113+
// If not, features like reload-and-profile will not work correctly and must be disabled.
114+
let isBackendStorageAPISupported = false;
115+
try {
116+
localStorage.getItem('test');
117+
isBackendStorageAPISupported = true;
118+
} catch (error) {}
119+
120+
return isBackendStorageAPISupported && isSynchronousXHRSupported();
121+
}

packages/react-devtools-shared/src/backend/types.js

+1
Original file line numberDiff line numberDiff line change
@@ -533,4 +533,5 @@ export type DevToolsHookSettings = {
533533
breakOnConsoleErrors: boolean,
534534
showInlineWarningsAndErrors: boolean,
535535
hideConsoleLogsInStrictMode: boolean,
536+
getIsReloadAndProfileSupported?: ?() => boolean,
536537
};

packages/react-devtools-shared/src/bridge.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,7 @@ export type BackendEvents = {
181181
fastRefreshScheduled: [],
182182
getSavedPreferences: [],
183183
inspectedElement: [InspectedElementPayload],
184-
isBackendStorageAPISupported: [boolean],
185-
isSynchronousXHRSupported: [boolean],
184+
isReloadAndProfileSupportedByBackend: [boolean],
186185
operations: [Array<number>],
187186
ownersList: [OwnersList],
188187
overrideComponentFilters: [Array<ComponentFilter>],

packages/react-devtools-shared/src/devtools/store.js

+14-42
Original file line numberDiff line numberDiff line change
@@ -138,16 +138,6 @@ export default class Store extends EventEmitter<{
138138
// Should the React Native style editor panel be shown?
139139
_isNativeStyleEditorSupported: boolean = false;
140140

141-
// Can the backend use the Storage API (e.g. localStorage)?
142-
// If not, features like reload-and-profile will not work correctly and must be disabled.
143-
_isBackendStorageAPISupported: boolean = false;
144-
145-
// Can DevTools use sync XHR requests?
146-
// If not, features like reload-and-profile will not work correctly and must be disabled.
147-
// This current limitation applies only to web extension builds
148-
// and will need to be reconsidered in the future if we add support for reload to React Native.
149-
_isSynchronousXHRSupported: boolean = false;
150-
151141
_nativeStyleEditorValidAttributes: $ReadOnlyArray<string> | null = null;
152142

153143
// Older backends don't support an explicit bridge protocol,
@@ -178,10 +168,12 @@ export default class Store extends EventEmitter<{
178168
// These options may be initially set by a configuration option when constructing the Store.
179169
_supportsInspectMatchingDOMElement: boolean = false;
180170
_supportsClickToInspect: boolean = false;
181-
_supportsReloadAndProfile: boolean = false;
182171
_supportsTimeline: boolean = false;
183172
_supportsTraceUpdates: boolean = false;
184173

174+
_isReloadAndProfileFrontendSupported: boolean = false;
175+
_isReloadAndProfileBackendSupported: boolean = false;
176+
185177
// These options default to false but may be updated as roots are added and removed.
186178
_rootSupportsBasicProfiling: boolean = false;
187179
_rootSupportsTimelineProfiling: boolean = false;
@@ -233,7 +225,7 @@ export default class Store extends EventEmitter<{
233225
this._supportsClickToInspect = true;
234226
}
235227
if (supportsReloadAndProfile) {
236-
this._supportsReloadAndProfile = true;
228+
this._isReloadAndProfileFrontendSupported = true;
237229
}
238230
if (supportsTimeline) {
239231
this._supportsTimeline = true;
@@ -254,17 +246,13 @@ export default class Store extends EventEmitter<{
254246
);
255247
bridge.addListener('shutdown', this.onBridgeShutdown);
256248
bridge.addListener(
257-
'isBackendStorageAPISupported',
258-
this.onBackendStorageAPISupported,
249+
'isReloadAndProfileSupportedByBackend',
250+
this.onBackendReloadAndProfileSupported,
259251
);
260252
bridge.addListener(
261253
'isNativeStyleEditorSupported',
262254
this.onBridgeNativeStyleEditorSupported,
263255
);
264-
bridge.addListener(
265-
'isSynchronousXHRSupported',
266-
this.onBridgeSynchronousXHRSupported,
267-
);
268256
bridge.addListener(
269257
'unsupportedRendererVersion',
270258
this.onBridgeUnsupportedRendererVersion,
@@ -452,13 +440,9 @@ export default class Store extends EventEmitter<{
452440
}
453441

454442
get supportsReloadAndProfile(): boolean {
455-
// Does the DevTools shell support reloading and eagerly injecting the renderer interface?
456-
// And if so, can the backend use the localStorage API and sync XHR?
457-
// All of these are currently required for the reload-and-profile feature to work.
458443
return (
459-
this._supportsReloadAndProfile &&
460-
this._isBackendStorageAPISupported &&
461-
this._isSynchronousXHRSupported
444+
this._isReloadAndProfileFrontendSupported &&
445+
this._isReloadAndProfileBackendSupported
462446
);
463447
}
464448

@@ -1407,17 +1391,13 @@ export default class Store extends EventEmitter<{
14071391
);
14081392
bridge.removeListener('shutdown', this.onBridgeShutdown);
14091393
bridge.removeListener(
1410-
'isBackendStorageAPISupported',
1411-
this.onBackendStorageAPISupported,
1394+
'isReloadAndProfileSupportedByBackend',
1395+
this.onBackendReloadAndProfileSupported,
14121396
);
14131397
bridge.removeListener(
14141398
'isNativeStyleEditorSupported',
14151399
this.onBridgeNativeStyleEditorSupported,
14161400
);
1417-
bridge.removeListener(
1418-
'isSynchronousXHRSupported',
1419-
this.onBridgeSynchronousXHRSupported,
1420-
);
14211401
bridge.removeListener(
14221402
'unsupportedRendererVersion',
14231403
this.onBridgeUnsupportedRendererVersion,
@@ -1432,18 +1412,10 @@ export default class Store extends EventEmitter<{
14321412
}
14331413
};
14341414

1435-
onBackendStorageAPISupported: (
1436-
isBackendStorageAPISupported: boolean,
1437-
) => void = isBackendStorageAPISupported => {
1438-
this._isBackendStorageAPISupported = isBackendStorageAPISupported;
1439-
1440-
this.emit('supportsReloadAndProfile');
1441-
};
1442-
1443-
onBridgeSynchronousXHRSupported: (
1444-
isSynchronousXHRSupported: boolean,
1445-
) => void = isSynchronousXHRSupported => {
1446-
this._isSynchronousXHRSupported = isSynchronousXHRSupported;
1415+
onBackendReloadAndProfileSupported: (
1416+
isReloadAndProfileSupported: boolean,
1417+
) => void = isReloadAndProfileSupported => {
1418+
this._isReloadAndProfileBackendSupported = isReloadAndProfileSupported;
14471419

14481420
this.emit('supportsReloadAndProfile');
14491421
};

0 commit comments

Comments
 (0)