Skip to content

Commit b4b3148

Browse files
committed
refactor[react-devtools]: flatten reload and profile config
1 parent fd17516 commit b4b3148

File tree

11 files changed

+126
-105
lines changed

11 files changed

+126
-105
lines changed

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

+31-10
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ import type {
2626
import type {
2727
DevToolsHook,
2828
DevToolsHookSettings,
29-
ReloadAndProfileConfig,
30-
ReloadAndProfileConfigPersistence,
29+
ProfilingSettings,
3130
} from 'react-devtools-shared/src/backend/types';
3231
import type {ResolveNativeStyle} from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';
3332

@@ -42,7 +41,9 @@ type ConnectOptions = {
4241
websocket?: ?WebSocket,
4342
onSettingsUpdated?: (settings: $ReadOnly<DevToolsHookSettings>) => void,
4443
isReloadAndProfileSupported?: boolean,
45-
reloadAndProfileConfigPersistence?: ReloadAndProfileConfigPersistence,
44+
isProfiling?: boolean,
45+
onReloadAndProfile?: (recordChangeDescriptions: boolean) => void,
46+
onReloadAndProfileFlagsReset?: () => void,
4647
};
4748

4849
let savedComponentFilters: Array<ComponentFilter> =
@@ -63,9 +64,15 @@ export function initialize(
6364
maybeSettingsOrSettingsPromise?:
6465
| DevToolsHookSettings
6566
| Promise<DevToolsHookSettings>,
66-
reloadAndProfileConfig?: ReloadAndProfileConfig,
67+
shouldStartProfilingRightNow: boolean = false,
68+
profilingSettings?: ProfilingSettings,
6769
) {
68-
installHook(window, maybeSettingsOrSettingsPromise, reloadAndProfileConfig);
70+
installHook(
71+
window,
72+
maybeSettingsOrSettingsPromise,
73+
shouldStartProfilingRightNow,
74+
profilingSettings,
75+
);
6976
}
7077

7178
export function connectToDevTools(options: ?ConnectOptions) {
@@ -86,7 +93,9 @@ export function connectToDevTools(options: ?ConnectOptions) {
8693
isAppActive = () => true,
8794
onSettingsUpdated,
8895
isReloadAndProfileSupported = getIsReloadAndProfileSupported(),
89-
reloadAndProfileConfigPersistence,
96+
isProfiling,
97+
onReloadAndProfile,
98+
onReloadAndProfileFlagsReset,
9099
} = options || {};
91100

92101
const protocol = useHttps ? 'wss' : 'ws';
@@ -180,7 +189,11 @@ export function connectToDevTools(options: ?ConnectOptions) {
180189

181190
// TODO (npm-packages) Warn if "isBackendStorageAPISupported"
182191
// $FlowFixMe[incompatible-call] found when upgrading Flow
183-
const agent = new Agent(bridge, reloadAndProfileConfigPersistence);
192+
const agent = new Agent(bridge, isProfiling, onReloadAndProfile);
193+
if (typeof onReloadAndProfileFlagsReset === 'function') {
194+
onReloadAndProfileFlagsReset();
195+
}
196+
184197
if (onSettingsUpdated != null) {
185198
agent.addListener('updateHookSettings', onSettingsUpdated);
186199
}
@@ -320,7 +333,9 @@ type ConnectWithCustomMessagingOptions = {
320333
resolveRNStyle?: ResolveNativeStyle,
321334
onSettingsUpdated?: (settings: $ReadOnly<DevToolsHookSettings>) => void,
322335
isReloadAndProfileSupported?: boolean,
323-
reloadAndProfileConfigPersistence?: ReloadAndProfileConfigPersistence,
336+
isProfiling?: boolean,
337+
onReloadAndProfile?: (recordChangeDescriptions: boolean) => void,
338+
onReloadAndProfileFlagsReset?: () => void,
324339
};
325340

326341
export function connectWithCustomMessagingProtocol({
@@ -331,7 +346,9 @@ export function connectWithCustomMessagingProtocol({
331346
resolveRNStyle,
332347
onSettingsUpdated,
333348
isReloadAndProfileSupported = getIsReloadAndProfileSupported(),
334-
reloadAndProfileConfigPersistence,
349+
isProfiling,
350+
onReloadAndProfile,
351+
onReloadAndProfileFlagsReset,
335352
}: ConnectWithCustomMessagingOptions): Function {
336353
const hook: ?DevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
337354
if (hook == null) {
@@ -368,7 +385,11 @@ export function connectWithCustomMessagingProtocol({
368385
bridge.send('overrideComponentFilters', savedComponentFilters);
369386
}
370387

371-
const agent = new Agent(bridge, reloadAndProfileConfigPersistence);
388+
const agent = new Agent(bridge, isProfiling, onReloadAndProfile);
389+
if (typeof onReloadAndProfileFlagsReset === 'function') {
390+
onReloadAndProfileFlagsReset();
391+
}
392+
372393
if (onSettingsUpdated != null) {
373394
agent.addListener('updateHookSettings', onSettingsUpdated);
374395
}

packages/react-devtools-extensions/src/contentScripts/backendManager.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ import type {
1414
import {hasAssignedBackend} from 'react-devtools-shared/src/backend/utils';
1515
import {COMPACT_VERSION_NAME} from 'react-devtools-extensions/src/utils';
1616
import {getIsReloadAndProfileSupported} from 'react-devtools-shared/src/utils';
17+
import {
18+
getIfReloadedAndProfiling,
19+
onReloadAndProfile,
20+
onReloadAndProfileFlagsReset,
21+
} from 'react-devtools-extensions/src/utils';
1722

1823
let welcomeHasInitialized = false;
1924

@@ -134,7 +139,15 @@ function activateBackend(version: string, hook: DevToolsHook) {
134139
},
135140
});
136141

137-
const agent = new Agent(bridge);
142+
const agent = new Agent(
143+
bridge,
144+
getIfReloadedAndProfiling(),
145+
onReloadAndProfile,
146+
);
147+
// Agent read flags successfully, we can count it as successful launch
148+
// Clean up flags, so that next reload won't start profiling
149+
onReloadAndProfileFlagsReset();
150+
138151
agent.addListener('shutdown', () => {
139152
// If we received 'shutdown' from `agent`, we assume the `bridge` is already shutting down,
140153
// and that caused the 'shutdown' event on the `agent`, so we don't need to call `bridge.shutdown()` here.

packages/react-devtools-extensions/src/contentScripts/installHook.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import {installHook} from 'react-devtools-shared/src/hook';
2+
import {
3+
getIfReloadedAndProfiling,
4+
getProfilingSettings,
5+
} from 'react-devtools-extensions/src/utils';
26

37
let resolveHookSettingsInjection;
48

@@ -34,8 +38,15 @@ if (!window.hasOwnProperty('__REACT_DEVTOOLS_GLOBAL_HOOK__')) {
3438
payload: {handshake: true},
3539
});
3640

41+
const shouldStartProfiling = getIfReloadedAndProfiling();
42+
const profilingSettings = getProfilingSettings();
3743
// Can't delay hook installation, inject settings lazily
38-
installHook(window, hookSettingsPromise);
44+
installHook(
45+
window,
46+
hookSettingsPromise,
47+
shouldStartProfiling,
48+
profilingSettings,
49+
);
3950

4051
// Detect React
4152
window.__REACT_DEVTOOLS_GLOBAL_HOOK__.on(

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

+37
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
/* global chrome */
22

33
import type {BrowserTheme} from 'react-devtools-shared/src/devtools/views/DevTools';
4+
import {
5+
sessionStorageGetItem,
6+
sessionStorageRemoveItem,
7+
sessionStorageSetItem,
8+
} from 'react-devtools-shared/src/storage';
9+
import {
10+
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
11+
SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,
12+
} from 'react-devtools-shared/src/constants';
13+
import type {ProfilingSettings} from 'react-devtools-shared/src/backend/types';
414

515
export function getBrowserTheme(): BrowserTheme {
616
if (__IS_CHROME__) {
@@ -23,3 +33,30 @@ export function getBrowserTheme(): BrowserTheme {
2333

2434
export const COMPACT_VERSION_NAME = 'compact';
2535
export const EXTENSION_CONTAINED_VERSIONS = [COMPACT_VERSION_NAME];
36+
37+
// Expected to be used only by browser extension
38+
export function getIfReloadedAndProfiling(): boolean {
39+
return (
40+
sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) === 'true'
41+
);
42+
}
43+
44+
export function getProfilingSettings(): ProfilingSettings {
45+
return {
46+
recordChangeDescriptions:
47+
sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) === 'true',
48+
};
49+
}
50+
51+
export function onReloadAndProfile(recordChangeDescriptions: boolean): void {
52+
sessionStorageSetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY, 'true');
53+
sessionStorageSetItem(
54+
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
55+
recordChangeDescriptions ? 'true' : 'false',
56+
);
57+
}
58+
59+
export function onReloadAndProfileFlagsReset(): void {
60+
sessionStorageRemoveItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY);
61+
sessionStorageRemoveItem(SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY);
62+
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ function startActivation(contentWindow: any, bridge: BackendBridge) {
6363
}
6464

6565
function finishActivation(contentWindow: any, bridge: BackendBridge) {
66+
// We don't pass `isProfiling` and `onReloadAndProfile`, because it is not supported by react-devtools-inline Frontend
6667
const agent = new Agent(bridge);
6768

6869
const hook = contentWindow.__REACT_DEVTOOLS_GLOBAL_HOOK__;

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import type {
1212
RendererInterface,
1313
DevToolsHook,
1414
RendererID,
15+
ProfilingSettings,
1516
} from 'react-devtools-shared/src/backend/types';
16-
import type {ReloadAndProfileConfig} from './backend/types';
1717

1818
import {attach as attachFlight} from 'react-devtools-shared/src/backend/flight/renderer';
1919
import {attach as attachFiber} from 'react-devtools-shared/src/backend/fiber/renderer';
@@ -30,7 +30,8 @@ export default function attachRenderer(
3030
id: RendererID,
3131
renderer: ReactRenderer,
3232
global: Object,
33-
reloadAndProfileConfig: ReloadAndProfileConfig,
33+
shouldStartProfilingRightNow: boolean,
34+
profilingSettings: ProfilingSettings,
3435
): RendererInterface | void {
3536
// only attach if the renderer is compatible with the current version of the backend
3637
if (!isMatchingRender(renderer.reconcilerVersion || renderer.version)) {
@@ -55,7 +56,8 @@ export default function attachRenderer(
5556
id,
5657
renderer,
5758
global,
58-
reloadAndProfileConfig,
59+
shouldStartProfilingRightNow,
60+
profilingSettings,
5961
);
6062
} else if (renderer.ComponentTree) {
6163
// react-dom v15

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

+8-25
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,9 @@ import type {
2626
RendererID,
2727
RendererInterface,
2828
DevToolsHookSettings,
29-
ReloadAndProfileConfigPersistence,
3029
} from './types';
3130
import type {ComponentFilter} from 'react-devtools-shared/src/frontend/types';
3231
import {isReactNativeEnvironment} from './utils';
33-
import {defaultReloadAndProfileConfigPersistence} from '../utils';
3432
import {
3533
sessionStorageGetItem,
3634
sessionStorageRemoveItem,
@@ -151,33 +149,21 @@ export default class Agent extends EventEmitter<{
151149
}> {
152150
_bridge: BackendBridge;
153151
_isProfiling: boolean = false;
154-
_recordChangeDescriptions: boolean = false;
155152
_rendererInterfaces: {[key: RendererID]: RendererInterface, ...} = {};
156153
_persistedSelection: PersistedSelection | null = null;
157154
_persistedSelectionMatch: PathMatch | null = null;
158155
_traceUpdatesEnabled: boolean = false;
159-
_reloadAndProfileConfigPersistence: ReloadAndProfileConfigPersistence;
156+
_onReloadAndProfile: ((recordChangeDescriptions: boolean) => void) | void;
160157

161158
constructor(
162159
bridge: BackendBridge,
163-
reloadAndProfileConfigPersistence?: ReloadAndProfileConfigPersistence = defaultReloadAndProfileConfigPersistence,
160+
isProfiling: boolean = false,
161+
onReloadAndProfile?: (recordChangeDescriptions: boolean) => void,
164162
) {
165163
super();
166164

167-
this._reloadAndProfileConfigPersistence = reloadAndProfileConfigPersistence;
168-
const {getReloadAndProfileConfig, setReloadAndProfileConfig} =
169-
reloadAndProfileConfigPersistence;
170-
const reloadAndProfileConfig = getReloadAndProfileConfig();
171-
if (reloadAndProfileConfig.shouldReloadAndProfile) {
172-
this._recordChangeDescriptions =
173-
reloadAndProfileConfig.recordChangeDescriptions;
174-
this._isProfiling = true;
175-
176-
setReloadAndProfileConfig({
177-
shouldReloadAndProfile: false,
178-
recordChangeDescriptions: false,
179-
});
180-
}
165+
this._isProfiling = isProfiling;
166+
this._onReloadAndProfile = onReloadAndProfile;
181167

182168
const persistedSelectionString = sessionStorageGetItem(
183169
SESSION_STORAGE_LAST_SELECTION_KEY,
@@ -674,10 +660,9 @@ export default class Agent extends EventEmitter<{
674660

675661
reloadAndProfile: (recordChangeDescriptions: boolean) => void =
676662
recordChangeDescriptions => {
677-
this._reloadAndProfileConfigPersistence.setReloadAndProfileConfig({
678-
shouldReloadAndProfile: true,
679-
recordChangeDescriptions,
680-
});
663+
if (typeof this._onReloadAndProfile === 'function') {
664+
this._onReloadAndProfile(recordChangeDescriptions);
665+
}
681666

682667
// This code path should only be hit if the shell has explicitly told the Store that it supports profiling.
683668
// In that case, the shell must also listen for this specific message to know when it needs to reload the app.
@@ -754,7 +739,6 @@ export default class Agent extends EventEmitter<{
754739

755740
startProfiling: (recordChangeDescriptions: boolean) => void =
756741
recordChangeDescriptions => {
757-
this._recordChangeDescriptions = recordChangeDescriptions;
758742
this._isProfiling = true;
759743
for (const rendererID in this._rendererInterfaces) {
760744
const renderer = ((this._rendererInterfaces[
@@ -767,7 +751,6 @@ export default class Agent extends EventEmitter<{
767751

768752
stopProfiling: () => void = () => {
769753
this._isProfiling = false;
770-
this._recordChangeDescriptions = false;
771754
for (const rendererID in this._rendererInterfaces) {
772755
const renderer = ((this._rendererInterfaces[
773756
(rendererID: any)

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

+5-6
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ import {
104104
supportsOwnerStacks,
105105
supportsConsoleTasks,
106106
} from './DevToolsFiberComponentStack';
107-
import type {ReloadAndProfileConfig} from '../types';
108107

109108
// $FlowFixMe[method-unbinding]
110109
const toString = Object.prototype.toString;
@@ -136,6 +135,7 @@ import type {
136135
WorkTagMap,
137136
CurrentDispatcherRef,
138137
LegacyDispatcherRef,
138+
ProfilingSettings,
139139
} from '../types';
140140
import type {
141141
ComponentFilter,
@@ -864,7 +864,8 @@ export function attach(
864864
rendererID: number,
865865
renderer: ReactRenderer,
866866
global: Object,
867-
reloadAndProfileConfig: ReloadAndProfileConfig,
867+
shouldStartProfilingRightNow: boolean,
868+
profilingSettings: ProfilingSettings,
868869
): RendererInterface {
869870
// Newer versions of the reconciler package also specific reconciler version.
870871
// If that version number is present, use it.
@@ -5225,10 +5226,8 @@ export function attach(
52255226
}
52265227

52275228
// Automatically start profiling so that we don't miss timing info from initial "mount".
5228-
if (reloadAndProfileConfig.shouldReloadAndProfile) {
5229-
const shouldRecordChangeDescriptions =
5230-
reloadAndProfileConfig.recordChangeDescriptions;
5231-
startProfiling(shouldRecordChangeDescriptions);
5229+
if (shouldStartProfilingRightNow) {
5230+
startProfiling(profilingSettings.recordChangeDescriptions);
52325231
}
52335232

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

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

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

488-
export type ReloadAndProfileConfig = {
489-
shouldReloadAndProfile: boolean,
488+
export type ProfilingSettings = {
490489
recordChangeDescriptions: boolean,
491490
};
492491

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-
502492
export type DevToolsHook = {
503493
listeners: {[key: string]: Array<Handler>, ...},
504494
rendererInterfaces: Map<RendererID, RendererInterface>,

0 commit comments

Comments
 (0)