Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: reload to profile for Fusebox #31021

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions packages/react-devtools-core/src/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import type {
import type {
DevToolsHook,
DevToolsHookSettings,
ReloadAndProfileConfig,
ReloadAndProfileConfigPersistence,
} from 'react-devtools-shared/src/backend/types';
import type {ResolveNativeStyle} from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';

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

let savedComponentFilters: Array<ComponentFilter> =
Expand All @@ -60,8 +63,9 @@ export function initialize(
maybeSettingsOrSettingsPromise?:
| DevToolsHookSettings
| Promise<DevToolsHookSettings>,
reloadAndProfileConfig?: ReloadAndProfileConfig,
) {
installHook(window, maybeSettingsOrSettingsPromise);
installHook(window, maybeSettingsOrSettingsPromise, reloadAndProfileConfig);
}

export function connectToDevTools(options: ?ConnectOptions) {
Expand All @@ -82,6 +86,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
isAppActive = () => true,
onSettingsUpdated,
isReloadAndProfileSupported = getIsReloadAndProfileSupported(),
reloadAndProfileConfigPersistence,
} = options || {};

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

// TODO (npm-packages) Warn if "isBackendStorageAPISupported"
// $FlowFixMe[incompatible-call] found when upgrading Flow
const agent = new Agent(bridge);
const agent = new Agent(bridge, reloadAndProfileConfigPersistence);
if (onSettingsUpdated != null) {
agent.addListener('updateHookSettings', onSettingsUpdated);
}
Expand Down Expand Up @@ -315,6 +320,7 @@ type ConnectWithCustomMessagingOptions = {
resolveRNStyle?: ResolveNativeStyle,
onSettingsUpdated?: (settings: $ReadOnly<DevToolsHookSettings>) => void,
isReloadAndProfileSupported?: boolean,
reloadAndProfileConfigPersistence?: ReloadAndProfileConfigPersistence,
};

export function connectWithCustomMessagingProtocol({
Expand All @@ -325,6 +331,7 @@ export function connectWithCustomMessagingProtocol({
resolveRNStyle,
onSettingsUpdated,
isReloadAndProfileSupported = getIsReloadAndProfileSupported(),
reloadAndProfileConfigPersistence,
}: ConnectWithCustomMessagingOptions): Function {
const hook: ?DevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
if (hook == null) {
Expand Down Expand Up @@ -361,7 +368,7 @@ export function connectWithCustomMessagingProtocol({
bridge.send('overrideComponentFilters', savedComponentFilters);
}

const agent = new Agent(bridge);
const agent = new Agent(bridge, reloadAndProfileConfigPersistence);
if (onSettingsUpdated != null) {
agent.addListener('updateHookSettings', onSettingsUpdated);
}
Expand Down
5 changes: 4 additions & 1 deletion packages/react-devtools-fusebox/src/frontend.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ export type Bridge = {
};
export type Store = Object;
export type BrowserTheme = 'dark' | 'light';
export type Config = {
supportsReloadAndProfile?: boolean,
};

export function createBridge(wall: Wall): Bridge;
export function createStore(bridge: Bridge): Store;
export function createStore(bridge: Bridge, config?: Config): Store;

export type Source = {
sourceURL: string,
Expand Down
10 changes: 9 additions & 1 deletion packages/react-devtools-shared/src/attachRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
DevToolsHook,
RendererID,
} from 'react-devtools-shared/src/backend/types';
import type {ReloadAndProfileConfig} from './backend/types';

import {attach as attachFlight} from 'react-devtools-shared/src/backend/flight/renderer';
import {attach as attachFiber} from 'react-devtools-shared/src/backend/fiber/renderer';
Expand All @@ -29,6 +30,7 @@ export default function attachRenderer(
id: RendererID,
renderer: ReactRenderer,
global: Object,
reloadAndProfileConfig: ReloadAndProfileConfig,
): RendererInterface | void {
// only attach if the renderer is compatible with the current version of the backend
if (!isMatchingRender(renderer.reconcilerVersion || renderer.version)) {
Expand All @@ -48,7 +50,13 @@ export default function attachRenderer(
renderer.currentDispatcherRef != null
) {
// react-reconciler v16+
rendererInterface = attachFiber(hook, id, renderer, global);
rendererInterface = attachFiber(
hook,
id,
renderer,
global,
reloadAndProfileConfig,
);
} else if (renderer.ComponentTree) {
// react-dom v15
rendererInterface = attachLegacy(hook, id, renderer, global);
Expand Down
52 changes: 27 additions & 25 deletions packages/react-devtools-shared/src/backend/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,7 @@
*/

import EventEmitter from '../events';
import {
SESSION_STORAGE_LAST_SELECTION_KEY,
SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
__DEBUG__,
} from '../constants';
import {
sessionStorageGetItem,
sessionStorageRemoveItem,
sessionStorageSetItem,
} from 'react-devtools-shared/src/storage';
import {SESSION_STORAGE_LAST_SELECTION_KEY, __DEBUG__} from '../constants';
import setupHighlighter from './views/Highlighter';
import {
initialize as setupTraceUpdates,
Expand All @@ -36,9 +26,16 @@ import type {
RendererID,
RendererInterface,
DevToolsHookSettings,
ReloadAndProfileConfigPersistence,
} from './types';
import type {ComponentFilter} from 'react-devtools-shared/src/frontend/types';
import {isReactNativeEnvironment} from './utils';
import {defaultReloadAndProfileConfigPersistence} from '../utils';
import {
sessionStorageGetItem,
sessionStorageRemoveItem,
sessionStorageSetItem,
} from '../storage';

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

constructor(bridge: BackendBridge) {
constructor(
bridge: BackendBridge,
reloadAndProfileConfigPersistence?: ReloadAndProfileConfigPersistence = defaultReloadAndProfileConfigPersistence,
) {
super();

if (
sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) === 'true'
) {
this._reloadAndProfileConfigPersistence = reloadAndProfileConfigPersistence;
const {getReloadAndProfileConfig, setReloadAndProfileConfig} =
reloadAndProfileConfigPersistence;
const reloadAndProfileConfig = getReloadAndProfileConfig();
if (reloadAndProfileConfig.shouldReloadAndProfile) {
this._recordChangeDescriptions =
sessionStorageGetItem(
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
) === 'true';
reloadAndProfileConfig.recordChangeDescriptions;
this._isProfiling = true;

sessionStorageRemoveItem(SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY);
sessionStorageRemoveItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY);
setReloadAndProfileConfig({
shouldReloadAndProfile: false,
recordChangeDescriptions: false,
});
}

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

reloadAndProfile: (recordChangeDescriptions: boolean) => void =
recordChangeDescriptions => {
sessionStorageSetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY, 'true');
sessionStorageSetItem(
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
recordChangeDescriptions ? 'true' : 'false',
);
this._reloadAndProfileConfigPersistence.setReloadAndProfileConfig({
shouldReloadAndProfile: true,
recordChangeDescriptions,
});

// This code path should only be hit if the shell has explicitly told the Store that it supports profiling.
// In that case, the shell must also listen for this specific message to know when it needs to reload the app.
Expand Down
16 changes: 6 additions & 10 deletions packages/react-devtools-shared/src/backend/fiber/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import {
utfEncodeString,
filterOutLocationComponentFilters,
} from 'react-devtools-shared/src/utils';
import {sessionStorageGetItem} from 'react-devtools-shared/src/storage';
import {
formatConsoleArgumentsToSingleString,
gt,
Expand All @@ -61,8 +60,6 @@ import {
__DEBUG__,
PROFILING_FLAG_BASIC_SUPPORT,
PROFILING_FLAG_TIMELINE_SUPPORT,
SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
TREE_OPERATION_ADD,
TREE_OPERATION_REMOVE,
TREE_OPERATION_REORDER_CHILDREN,
Expand Down Expand Up @@ -106,6 +103,7 @@ import {
supportsOwnerStacks,
supportsConsoleTasks,
} from './DevToolsFiberComponentStack';
import type {ReloadAndProfileConfig} from '../types';

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

// Automatically start profiling so that we don't miss timing info from initial "mount".
if (
sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) === 'true'
) {
startProfiling(
sessionStorageGetItem(SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY) ===
'true',
);
if (reloadAndProfileConfig.shouldReloadAndProfile) {
const shouldRecordChangeDescriptions =
reloadAndProfileConfig.recordChangeDescriptions;
startProfiling(shouldRecordChangeDescriptions);
}

function getNearestFiber(devtoolsInstance: DevToolsInstance): null | Fiber {
Expand Down
14 changes: 14 additions & 0 deletions packages/react-devtools-shared/src/backend/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,20 @@ export type DevToolsBackend = {
setupNativeStyleEditor?: SetupNativeStyleEditor,
};

export type ReloadAndProfileConfig = {
shouldReloadAndProfile: boolean,
recordChangeDescriptions: boolean,
};

// Linter doesn't speak Flow's `Partial` type
// eslint-disable-next-line no-undef
type PartialReloadAndProfileConfig = Partial<ReloadAndProfileConfig>;

export type ReloadAndProfileConfigPersistence = {
setReloadAndProfileConfig: (config: PartialReloadAndProfileConfig) => void,
getReloadAndProfileConfig: () => ReloadAndProfileConfig,
};

export type DevToolsHook = {
listeners: {[key: string]: Array<Handler>, ...},
rendererInterfaces: Map<RendererID, RendererInterface>,
Expand Down
11 changes: 10 additions & 1 deletion packages/react-devtools-shared/src/hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
RendererInterface,
DevToolsBackend,
DevToolsHookSettings,
ReloadAndProfileConfig,
} from './backend/types';

import {
Expand All @@ -26,6 +27,7 @@ import {
import attachRenderer from './attachRenderer';
import formatConsoleArguments from 'react-devtools-shared/src/backend/utils/formatConsoleArguments';
import formatWithStyles from 'react-devtools-shared/src/backend/utils/formatWithStyles';
import {defaultReloadAndProfileConfigPersistence} from './utils';

// React's custom built component stack strings match "\s{4}in"
// Chrome's prefix matches "\s{4}at"
Expand Down Expand Up @@ -54,6 +56,7 @@ export function installHook(
maybeSettingsOrSettingsPromise?:
| DevToolsHookSettings
| Promise<DevToolsHookSettings>,
reloadAndProfileConfig?: ReloadAndProfileConfig = defaultReloadAndProfileConfigPersistence.getReloadAndProfileConfig(),
): DevToolsHook | null {
if (target.hasOwnProperty('__REACT_DEVTOOLS_GLOBAL_HOOK__')) {
return null;
Expand Down Expand Up @@ -207,7 +210,13 @@ export function installHook(
reactBuildType,
});

const rendererInterface = attachRenderer(hook, id, renderer, target);
const rendererInterface = attachRenderer(
hook,
id,
renderer,
target,
reloadAndProfileConfig,
);
if (rendererInterface != null) {
hook.rendererInterfaces.set(id, rendererInterface);
hook.emit('renderer-attached', {id, rendererInterface});
Expand Down
45 changes: 44 additions & 1 deletion packages/react-devtools-shared/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import {
TREE_OPERATION_UPDATE_TREE_BASE_DURATION,
LOCAL_STORAGE_COMPONENT_FILTER_PREFERENCES_KEY,
LOCAL_STORAGE_OPEN_IN_EDITOR_URL,
SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
} from './constants';
import {
ComponentFilterElementType,
Expand All @@ -50,7 +52,12 @@ import {
ElementTypeMemo,
ElementTypeVirtual,
} from 'react-devtools-shared/src/frontend/types';
import {localStorageGetItem, localStorageSetItem} from './storage';
import {
localStorageGetItem,
localStorageSetItem,
sessionStorageGetItem,
sessionStorageSetItem,
} from './storage';
import {meta} from './hydration';
import isArray from './isArray';

Expand All @@ -62,6 +69,10 @@ import type {
} from 'react-devtools-shared/src/frontend/types';
import type {SerializedElement as SerializedElementBackend} from 'react-devtools-shared/src/backend/types';
import {isSynchronousXHRSupported} from './backend/utils';
import type {
ReloadAndProfileConfig,
ReloadAndProfileConfigPersistence,
} from './backend/types';

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

return isBackendStorageAPISupported && isSynchronousXHRSupported();
}

export const defaultReloadAndProfileConfigPersistence: ReloadAndProfileConfigPersistence =
{
setReloadAndProfileConfig({
shouldReloadAndProfile,
recordChangeDescriptions,
}): void {
if (shouldReloadAndProfile != null) {
sessionStorageSetItem(
SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,
shouldReloadAndProfile ? 'true' : 'false',
);
}
if (recordChangeDescriptions != null) {
sessionStorageSetItem(
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
recordChangeDescriptions ? 'true' : 'false',
);
}
},
getReloadAndProfileConfig(): ReloadAndProfileConfig {
return {
shouldReloadAndProfile:
sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) ===
'true',
recordChangeDescriptions:
sessionStorageGetItem(
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
) === 'true',
};
},
};
Loading