Skip to content

Commit 204a551

Browse files
authored
Add: reload to profile for Fusebox (#31021)
## Summary Add reload to profile for Fusebox Stacked on #31048. See 6be1977 ## How did you test this change? Test E2E in [D63233256](https://www.internalfb.com/diff/D63233256)
1 parent b091ef7 commit 204a551

File tree

8 files changed

+124
-42
lines changed

8 files changed

+124
-42
lines changed

packages/react-devtools-core/src/backend.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import type {
2626
import type {
2727
DevToolsHook,
2828
DevToolsHookSettings,
29+
ReloadAndProfileConfig,
30+
ReloadAndProfileConfigPersistence,
2931
} from 'react-devtools-shared/src/backend/types';
3032
import type {ResolveNativeStyle} from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';
3133

@@ -40,6 +42,7 @@ type ConnectOptions = {
4042
websocket?: ?WebSocket,
4143
onSettingsUpdated?: (settings: $ReadOnly<DevToolsHookSettings>) => void,
4244
isReloadAndProfileSupported?: boolean,
45+
reloadAndProfileConfigPersistence?: ReloadAndProfileConfigPersistence,
4346
};
4447

4548
let savedComponentFilters: Array<ComponentFilter> =
@@ -60,8 +63,9 @@ export function initialize(
6063
maybeSettingsOrSettingsPromise?:
6164
| DevToolsHookSettings
6265
| Promise<DevToolsHookSettings>,
66+
reloadAndProfileConfig?: ReloadAndProfileConfig,
6367
) {
64-
installHook(window, maybeSettingsOrSettingsPromise);
68+
installHook(window, maybeSettingsOrSettingsPromise, reloadAndProfileConfig);
6569
}
6670

6771
export function connectToDevTools(options: ?ConnectOptions) {
@@ -82,6 +86,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
8286
isAppActive = () => true,
8387
onSettingsUpdated,
8488
isReloadAndProfileSupported = getIsReloadAndProfileSupported(),
89+
reloadAndProfileConfigPersistence,
8590
} = options || {};
8691

8792
const protocol = useHttps ? 'wss' : 'ws';
@@ -175,7 +180,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
175180

176181
// TODO (npm-packages) Warn if "isBackendStorageAPISupported"
177182
// $FlowFixMe[incompatible-call] found when upgrading Flow
178-
const agent = new Agent(bridge);
183+
const agent = new Agent(bridge, reloadAndProfileConfigPersistence);
179184
if (onSettingsUpdated != null) {
180185
agent.addListener('updateHookSettings', onSettingsUpdated);
181186
}
@@ -315,6 +320,7 @@ type ConnectWithCustomMessagingOptions = {
315320
resolveRNStyle?: ResolveNativeStyle,
316321
onSettingsUpdated?: (settings: $ReadOnly<DevToolsHookSettings>) => void,
317322
isReloadAndProfileSupported?: boolean,
323+
reloadAndProfileConfigPersistence?: ReloadAndProfileConfigPersistence,
318324
};
319325

320326
export function connectWithCustomMessagingProtocol({
@@ -325,6 +331,7 @@ export function connectWithCustomMessagingProtocol({
325331
resolveRNStyle,
326332
onSettingsUpdated,
327333
isReloadAndProfileSupported = getIsReloadAndProfileSupported(),
334+
reloadAndProfileConfigPersistence,
328335
}: ConnectWithCustomMessagingOptions): Function {
329336
const hook: ?DevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
330337
if (hook == null) {
@@ -361,7 +368,7 @@ export function connectWithCustomMessagingProtocol({
361368
bridge.send('overrideComponentFilters', savedComponentFilters);
362369
}
363370

364-
const agent = new Agent(bridge);
371+
const agent = new Agent(bridge, reloadAndProfileConfigPersistence);
365372
if (onSettingsUpdated != null) {
366373
agent.addListener('updateHookSettings', onSettingsUpdated);
367374
}

packages/react-devtools-fusebox/src/frontend.d.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@ export type Bridge = {
1919
};
2020
export type Store = Object;
2121
export type BrowserTheme = 'dark' | 'light';
22+
export type Config = {
23+
supportsReloadAndProfile?: boolean,
24+
};
2225

2326
export function createBridge(wall: Wall): Bridge;
24-
export function createStore(bridge: Bridge): Store;
27+
export function createStore(bridge: Bridge, config?: Config): Store;
2528

2629
export type Source = {
2730
sourceURL: string,

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
DevToolsHook,
1414
RendererID,
1515
} from 'react-devtools-shared/src/backend/types';
16+
import type {ReloadAndProfileConfig} from './backend/types';
1617

1718
import {attach as attachFlight} from 'react-devtools-shared/src/backend/flight/renderer';
1819
import {attach as attachFiber} from 'react-devtools-shared/src/backend/fiber/renderer';
@@ -29,6 +30,7 @@ export default function attachRenderer(
2930
id: RendererID,
3031
renderer: ReactRenderer,
3132
global: Object,
33+
reloadAndProfileConfig: ReloadAndProfileConfig,
3234
): RendererInterface | void {
3335
// only attach if the renderer is compatible with the current version of the backend
3436
if (!isMatchingRender(renderer.reconcilerVersion || renderer.version)) {
@@ -48,7 +50,13 @@ export default function attachRenderer(
4850
renderer.currentDispatcherRef != null
4951
) {
5052
// react-reconciler v16+
51-
rendererInterface = attachFiber(hook, id, renderer, global);
53+
rendererInterface = attachFiber(
54+
hook,
55+
id,
56+
renderer,
57+
global,
58+
reloadAndProfileConfig,
59+
);
5260
} else if (renderer.ComponentTree) {
5361
// react-dom v15
5462
rendererInterface = attachLegacy(hook, id, renderer, global);

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

+27-25
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,7 @@
88
*/
99

1010
import EventEmitter from '../events';
11-
import {
12-
SESSION_STORAGE_LAST_SELECTION_KEY,
13-
SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,
14-
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
15-
__DEBUG__,
16-
} from '../constants';
17-
import {
18-
sessionStorageGetItem,
19-
sessionStorageRemoveItem,
20-
sessionStorageSetItem,
21-
} from 'react-devtools-shared/src/storage';
11+
import {SESSION_STORAGE_LAST_SELECTION_KEY, __DEBUG__} from '../constants';
2212
import setupHighlighter from './views/Highlighter';
2313
import {
2414
initialize as setupTraceUpdates,
@@ -36,9 +26,16 @@ import type {
3626
RendererID,
3727
RendererInterface,
3828
DevToolsHookSettings,
29+
ReloadAndProfileConfigPersistence,
3930
} from './types';
4031
import type {ComponentFilter} from 'react-devtools-shared/src/frontend/types';
4132
import {isReactNativeEnvironment} from './utils';
33+
import {defaultReloadAndProfileConfigPersistence} from '../utils';
34+
import {
35+
sessionStorageGetItem,
36+
sessionStorageRemoveItem,
37+
sessionStorageSetItem,
38+
} from '../storage';
4239

4340
const debug = (methodName: string, ...args: Array<string>) => {
4441
if (__DEBUG__) {
@@ -159,21 +156,27 @@ export default class Agent extends EventEmitter<{
159156
_persistedSelection: PersistedSelection | null = null;
160157
_persistedSelectionMatch: PathMatch | null = null;
161158
_traceUpdatesEnabled: boolean = false;
159+
_reloadAndProfileConfigPersistence: ReloadAndProfileConfigPersistence;
162160

163-
constructor(bridge: BackendBridge) {
161+
constructor(
162+
bridge: BackendBridge,
163+
reloadAndProfileConfigPersistence?: ReloadAndProfileConfigPersistence = defaultReloadAndProfileConfigPersistence,
164+
) {
164165
super();
165166

166-
if (
167-
sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) === 'true'
168-
) {
167+
this._reloadAndProfileConfigPersistence = reloadAndProfileConfigPersistence;
168+
const {getReloadAndProfileConfig, setReloadAndProfileConfig} =
169+
reloadAndProfileConfigPersistence;
170+
const reloadAndProfileConfig = getReloadAndProfileConfig();
171+
if (reloadAndProfileConfig.shouldReloadAndProfile) {
169172
this._recordChangeDescriptions =
170-
sessionStorageGetItem(
171-
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
172-
) === 'true';
173+
reloadAndProfileConfig.recordChangeDescriptions;
173174
this._isProfiling = true;
174175

175-
sessionStorageRemoveItem(SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY);
176-
sessionStorageRemoveItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY);
176+
setReloadAndProfileConfig({
177+
shouldReloadAndProfile: false,
178+
recordChangeDescriptions: false,
179+
});
177180
}
178181

179182
const persistedSelectionString = sessionStorageGetItem(
@@ -671,11 +674,10 @@ export default class Agent extends EventEmitter<{
671674

672675
reloadAndProfile: (recordChangeDescriptions: boolean) => void =
673676
recordChangeDescriptions => {
674-
sessionStorageSetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY, 'true');
675-
sessionStorageSetItem(
676-
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
677-
recordChangeDescriptions ? 'true' : 'false',
678-
);
677+
this._reloadAndProfileConfigPersistence.setReloadAndProfileConfig({
678+
shouldReloadAndProfile: true,
679+
recordChangeDescriptions,
680+
});
679681

680682
// This code path should only be hit if the shell has explicitly told the Store that it supports profiling.
681683
// In that case, the shell must also listen for this specific message to know when it needs to reload the app.

packages/react-devtools-shared/src/backend/fiber/renderer.js

+6-10
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import {
4242
utfEncodeString,
4343
filterOutLocationComponentFilters,
4444
} from 'react-devtools-shared/src/utils';
45-
import {sessionStorageGetItem} from 'react-devtools-shared/src/storage';
4645
import {
4746
formatConsoleArgumentsToSingleString,
4847
gt,
@@ -61,8 +60,6 @@ import {
6160
__DEBUG__,
6261
PROFILING_FLAG_BASIC_SUPPORT,
6362
PROFILING_FLAG_TIMELINE_SUPPORT,
64-
SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,
65-
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
6663
TREE_OPERATION_ADD,
6764
TREE_OPERATION_REMOVE,
6865
TREE_OPERATION_REORDER_CHILDREN,
@@ -106,6 +103,7 @@ import {
106103
supportsOwnerStacks,
107104
supportsConsoleTasks,
108105
} from './DevToolsFiberComponentStack';
106+
import type {ReloadAndProfileConfig} from '../types';
109107

110108
// $FlowFixMe[method-unbinding]
111109
const toString = Object.prototype.toString;
@@ -865,6 +863,7 @@ export function attach(
865863
rendererID: number,
866864
renderer: ReactRenderer,
867865
global: Object,
866+
reloadAndProfileConfig: ReloadAndProfileConfig,
868867
): RendererInterface {
869868
// Newer versions of the reconciler package also specific reconciler version.
870869
// If that version number is present, use it.
@@ -5213,13 +5212,10 @@ export function attach(
52135212
}
52145213

52155214
// Automatically start profiling so that we don't miss timing info from initial "mount".
5216-
if (
5217-
sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) === 'true'
5218-
) {
5219-
startProfiling(
5220-
sessionStorageGetItem(SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY) ===
5221-
'true',
5222-
);
5215+
if (reloadAndProfileConfig.shouldReloadAndProfile) {
5216+
const shouldRecordChangeDescriptions =
5217+
reloadAndProfileConfig.recordChangeDescriptions;
5218+
startProfiling(shouldRecordChangeDescriptions);
52235219
}
52245220

52255221
function getNearestFiber(devtoolsInstance: DevToolsInstance): null | Fiber {

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

+14
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,20 @@ export type DevToolsBackend = {
485485
setupNativeStyleEditor?: SetupNativeStyleEditor,
486486
};
487487

488+
export type ReloadAndProfileConfig = {
489+
shouldReloadAndProfile: boolean,
490+
recordChangeDescriptions: boolean,
491+
};
492+
493+
// Linter doesn't speak Flow's `Partial` type
494+
// eslint-disable-next-line no-undef
495+
type PartialReloadAndProfileConfig = Partial<ReloadAndProfileConfig>;
496+
497+
export type ReloadAndProfileConfigPersistence = {
498+
setReloadAndProfileConfig: (config: PartialReloadAndProfileConfig) => void,
499+
getReloadAndProfileConfig: () => ReloadAndProfileConfig,
500+
};
501+
488502
export type DevToolsHook = {
489503
listeners: {[key: string]: Array<Handler>, ...},
490504
rendererInterfaces: Map<RendererID, RendererInterface>,

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

+10-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
RendererInterface,
1717
DevToolsBackend,
1818
DevToolsHookSettings,
19+
ReloadAndProfileConfig,
1920
} from './backend/types';
2021

2122
import {
@@ -26,6 +27,7 @@ import {
2627
import attachRenderer from './attachRenderer';
2728
import formatConsoleArguments from 'react-devtools-shared/src/backend/utils/formatConsoleArguments';
2829
import formatWithStyles from 'react-devtools-shared/src/backend/utils/formatWithStyles';
30+
import {defaultReloadAndProfileConfigPersistence} from './utils';
2931

3032
// React's custom built component stack strings match "\s{4}in"
3133
// Chrome's prefix matches "\s{4}at"
@@ -54,6 +56,7 @@ export function installHook(
5456
maybeSettingsOrSettingsPromise?:
5557
| DevToolsHookSettings
5658
| Promise<DevToolsHookSettings>,
59+
reloadAndProfileConfig?: ReloadAndProfileConfig = defaultReloadAndProfileConfigPersistence.getReloadAndProfileConfig(),
5760
): DevToolsHook | null {
5861
if (target.hasOwnProperty('__REACT_DEVTOOLS_GLOBAL_HOOK__')) {
5962
return null;
@@ -207,7 +210,13 @@ export function installHook(
207210
reactBuildType,
208211
});
209212

210-
const rendererInterface = attachRenderer(hook, id, renderer, target);
213+
const rendererInterface = attachRenderer(
214+
hook,
215+
id,
216+
renderer,
217+
target,
218+
reloadAndProfileConfig,
219+
);
211220
if (rendererInterface != null) {
212221
hook.rendererInterfaces.set(id, rendererInterface);
213222
hook.emit('renderer-attached', {id, rendererInterface});

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

+44-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ import {
3636
TREE_OPERATION_UPDATE_TREE_BASE_DURATION,
3737
LOCAL_STORAGE_COMPONENT_FILTER_PREFERENCES_KEY,
3838
LOCAL_STORAGE_OPEN_IN_EDITOR_URL,
39+
SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,
40+
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
3941
} from './constants';
4042
import {
4143
ComponentFilterElementType,
@@ -50,7 +52,12 @@ import {
5052
ElementTypeMemo,
5153
ElementTypeVirtual,
5254
} from 'react-devtools-shared/src/frontend/types';
53-
import {localStorageGetItem, localStorageSetItem} from './storage';
55+
import {
56+
localStorageGetItem,
57+
localStorageSetItem,
58+
sessionStorageGetItem,
59+
sessionStorageSetItem,
60+
} from './storage';
5461
import {meta} from './hydration';
5562
import isArray from './isArray';
5663

@@ -62,6 +69,10 @@ import type {
6269
} from 'react-devtools-shared/src/frontend/types';
6370
import type {SerializedElement as SerializedElementBackend} from 'react-devtools-shared/src/backend/types';
6471
import {isSynchronousXHRSupported} from './backend/utils';
72+
import type {
73+
ReloadAndProfileConfig,
74+
ReloadAndProfileConfigPersistence,
75+
} from './backend/types';
6576

6677
// $FlowFixMe[method-unbinding]
6778
const hasOwnProperty = Object.prototype.hasOwnProperty;
@@ -978,3 +989,35 @@ export function getIsReloadAndProfileSupported(): boolean {
978989

979990
return isBackendStorageAPISupported && isSynchronousXHRSupported();
980991
}
992+
993+
export const defaultReloadAndProfileConfigPersistence: ReloadAndProfileConfigPersistence =
994+
{
995+
setReloadAndProfileConfig({
996+
shouldReloadAndProfile,
997+
recordChangeDescriptions,
998+
}): void {
999+
if (shouldReloadAndProfile != null) {
1000+
sessionStorageSetItem(
1001+
SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,
1002+
shouldReloadAndProfile ? 'true' : 'false',
1003+
);
1004+
}
1005+
if (recordChangeDescriptions != null) {
1006+
sessionStorageSetItem(
1007+
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
1008+
recordChangeDescriptions ? 'true' : 'false',
1009+
);
1010+
}
1011+
},
1012+
getReloadAndProfileConfig(): ReloadAndProfileConfig {
1013+
return {
1014+
shouldReloadAndProfile:
1015+
sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) ===
1016+
'true',
1017+
recordChangeDescriptions:
1018+
sessionStorageGetItem(
1019+
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
1020+
) === 'true',
1021+
};
1022+
},
1023+
};

0 commit comments

Comments
 (0)