mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
Add: reload to profile for Fusebox (#31021)
## Summary
Add reload to profile for Fusebox
Stacked on #31048. See
6be1977112
## How did you test this change?
Test E2E in [D63233256](https://www.internalfb.com/diff/D63233256)
This commit is contained in:
13
packages/react-devtools-core/src/backend.js
vendored
13
packages/react-devtools-core/src/backend.js
vendored
@@ -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';
|
||||
|
||||
@@ -40,6 +42,7 @@ type ConnectOptions = {
|
||||
websocket?: ?WebSocket,
|
||||
onSettingsUpdated?: (settings: $ReadOnly<DevToolsHookSettings>) => void,
|
||||
isReloadAndProfileSupported?: boolean,
|
||||
reloadAndProfileConfigPersistence?: ReloadAndProfileConfigPersistence,
|
||||
};
|
||||
|
||||
let savedComponentFilters: Array<ComponentFilter> =
|
||||
@@ -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) {
|
||||
@@ -82,6 +86,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
|
||||
isAppActive = () => true,
|
||||
onSettingsUpdated,
|
||||
isReloadAndProfileSupported = getIsReloadAndProfileSupported(),
|
||||
reloadAndProfileConfigPersistence,
|
||||
} = options || {};
|
||||
|
||||
const protocol = useHttps ? 'wss' : 'ws';
|
||||
@@ -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);
|
||||
}
|
||||
@@ -315,6 +320,7 @@ type ConnectWithCustomMessagingOptions = {
|
||||
resolveRNStyle?: ResolveNativeStyle,
|
||||
onSettingsUpdated?: (settings: $ReadOnly<DevToolsHookSettings>) => void,
|
||||
isReloadAndProfileSupported?: boolean,
|
||||
reloadAndProfileConfigPersistence?: ReloadAndProfileConfigPersistence,
|
||||
};
|
||||
|
||||
export function connectWithCustomMessagingProtocol({
|
||||
@@ -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) {
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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';
|
||||
@@ -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)) {
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
@@ -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__) {
|
||||
@@ -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(
|
||||
@@ -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.
|
||||
|
||||
@@ -42,7 +42,6 @@ import {
|
||||
utfEncodeString,
|
||||
filterOutLocationComponentFilters,
|
||||
} from 'react-devtools-shared/src/utils';
|
||||
import {sessionStorageGetItem} from 'react-devtools-shared/src/storage';
|
||||
import {
|
||||
formatConsoleArgumentsToSingleString,
|
||||
gt,
|
||||
@@ -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,
|
||||
@@ -106,6 +103,7 @@ import {
|
||||
supportsOwnerStacks,
|
||||
supportsConsoleTasks,
|
||||
} from './DevToolsFiberComponentStack';
|
||||
import type {ReloadAndProfileConfig} from '../types';
|
||||
|
||||
// $FlowFixMe[method-unbinding]
|
||||
const toString = Object.prototype.toString;
|
||||
@@ -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.
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>,
|
||||
|
||||
11
packages/react-devtools-shared/src/hook.js
vendored
11
packages/react-devtools-shared/src/hook.js
vendored
@@ -16,6 +16,7 @@ import type {
|
||||
RendererInterface,
|
||||
DevToolsBackend,
|
||||
DevToolsHookSettings,
|
||||
ReloadAndProfileConfig,
|
||||
} from './backend/types';
|
||||
|
||||
import {
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
@@ -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});
|
||||
|
||||
45
packages/react-devtools-shared/src/utils.js
vendored
45
packages/react-devtools-shared/src/utils.js
vendored
@@ -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,
|
||||
@@ -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';
|
||||
|
||||
@@ -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;
|
||||
@@ -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',
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user