From 77ec61885fb19607cdd116a6790095afa40b5a94 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Tue, 10 Oct 2023 18:10:17 +0100 Subject: [PATCH] fix[devtools/inspectElement]: dont pause initial inspectElement call when user switches tabs (#27488) There are not so many changes, most of them are changing imports, because I've moved types for UI in a single file. In https://github.com/facebook/react/pull/27357 I've added support for pausing polling events: when user inspects an element, we start polling React DevTools backend for updates in props / state. If user switches tabs, extension's service worker can be killed by browser and this polling will start spamming errors. What I've missed is that we also have a separate call for this API, but which is executed only once when user selects an element. We don't handle promise rejection here and this can lead to some errors when user selects an element and switches tabs right after it. The only change here is that this API now has `shouldListenToPauseEvents` param, which is `true` for polling, so we will pause polling once user switches tabs. It is `false` by default, so we won't pause initial call by accident. https://github.com/hoxyq/react/blob/af8beeebf63b5824497fcd0bb35b7c0ac8fe60a0/packages/react-devtools-shared/src/backendAPI.js#L96 --- packages/react-devtools-core/src/backend.js | 2 +- .../react-devtools-core/src/standalone.js | 2 +- packages/react-devtools-inline/src/backend.js | 2 +- .../react-devtools-inline/src/frontend.js | 2 +- .../__tests__/legacy/inspectElement-test.js | 7 +- .../src/__tests__/ownersListContext-test.js | 2 +- .../src/__tests__/profilerStore-test.js | 2 +- .../__tests__/storeComponentFilters-test.js | 2 +- .../src/__tests__/utils.js | 10 +- .../src/backend/StyleX/utils.js | 2 +- .../src/backend/agent.js | 2 +- .../src/backend/legacy/renderer.js | 4 +- .../src/backend/renderer.js | 4 +- .../src/backend/types.js | 4 +- .../src/backend/utils.js | 2 +- .../react-devtools-shared/src/backendAPI.js | 43 ++++-- packages/react-devtools-shared/src/bridge.js | 2 +- .../src/devtools/store.js | 11 +- .../src/devtools/utils.js | 2 +- .../src/devtools/views/Components/Badge.js | 2 +- .../Components/CannotSuspendWarningMessage.js | 2 +- .../src/devtools/views/Components/Element.js | 2 +- .../devtools/views/Components/HocBadges.js | 2 +- .../views/Components/InspectedElement.js | 4 +- .../Components/InspectedElementContext.js | 4 +- .../Components/InspectedElementContextTree.js | 6 +- .../InspectedElementErrorsAndWarningsTree.js | 2 +- .../Components/InspectedElementHooksTree.js | 6 +- .../Components/InspectedElementPropsTree.js | 6 +- .../Components/InspectedElementStateTree.js | 6 +- .../InspectedElementStyleXPlugin.js | 4 +- .../InspectedElementSuspenseToggle.js | 4 +- .../views/Components/InspectedElementView.js | 11 +- .../src/devtools/views/Components/KeyValue.js | 4 +- .../Components/NativeStyleEditor/context.js | 2 +- .../views/Components/NewArrayValue.js | 2 +- .../devtools/views/Components/NewKeyValue.js | 2 +- .../views/Components/OwnersListContext.js | 2 +- .../devtools/views/Components/OwnersStack.js | 2 +- .../views/Components/SelectedTreeHighlight.js | 3 +- .../devtools/views/Components/TreeContext.js | 2 +- .../src/devtools/views/Components/types.js | 140 ------------------ .../src/devtools/views/DevTools.js | 4 +- .../views/Profiler/CommitTreeBuilder.js | 4 +- .../views/Profiler/RankedChartBuilder.js | 2 +- .../src/devtools/views/Profiler/Updaters.js | 4 +- .../src/devtools/views/Profiler/types.js | 6 +- .../views/Settings/ComponentsSettings.js | 4 +- .../views/Settings/SettingsContext.js | 2 +- .../src/{ => frontend}/types.js | 133 +++++++++++++++++ packages/react-devtools-shared/src/hook.js | 2 +- .../src/hookNamesCache.js | 4 +- .../src/hooks/parseHookNames/index.js | 2 +- .../parseHookNames/parseSourceAndMetadata.js | 5 +- .../react-devtools-shared/src/hydration.js | 11 +- .../src/inspectedElementCache.js | 20 ++- .../src/inspectedElementMutableSource.js | 42 +++--- packages/react-devtools-shared/src/utils.js | 15 +- 58 files changed, 305 insertions(+), 282 deletions(-) delete mode 100644 packages/react-devtools-shared/src/devtools/views/Components/types.js rename packages/react-devtools-shared/src/{ => frontend}/types.js (51%) diff --git a/packages/react-devtools-core/src/backend.js b/packages/react-devtools-core/src/backend.js index d4db634f94..72674a0a8c 100644 --- a/packages/react-devtools-core/src/backend.js +++ b/packages/react-devtools-core/src/backend.js @@ -22,7 +22,7 @@ import { } from './cachedSettings'; import type {BackendBridge} from 'react-devtools-shared/src/bridge'; -import type {ComponentFilter} from 'react-devtools-shared/src/types'; +import type {ComponentFilter} from 'react-devtools-shared/src/frontend/types'; import type {DevToolsHook} from 'react-devtools-shared/src/backend/types'; import type {ResolveNativeStyle} from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor'; diff --git a/packages/react-devtools-core/src/standalone.js b/packages/react-devtools-core/src/standalone.js index acc43fef5d..00cc19f6d8 100644 --- a/packages/react-devtools-core/src/standalone.js +++ b/packages/react-devtools-core/src/standalone.js @@ -33,7 +33,7 @@ import { import {localStorageSetItem} from 'react-devtools-shared/src/storage'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; -import type {InspectedElement} from 'react-devtools-shared/src/devtools/views/Components/types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; installHook(window); diff --git a/packages/react-devtools-inline/src/backend.js b/packages/react-devtools-inline/src/backend.js index c647eccaf1..e7d0485b37 100644 --- a/packages/react-devtools-inline/src/backend.js +++ b/packages/react-devtools-inline/src/backend.js @@ -8,7 +8,7 @@ import {installHook} from 'react-devtools-shared/src/hook'; import setupNativeStyleEditor from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor'; import type {BackendBridge} from 'react-devtools-shared/src/bridge'; -import type {Wall} from 'react-devtools-shared/src/types'; +import type {Wall} from 'react-devtools-shared/src/frontend/types'; function startActivation(contentWindow: any, bridge: BackendBridge) { const onSavedPreferences = (data: $FlowFixMe) => { diff --git a/packages/react-devtools-inline/src/frontend.js b/packages/react-devtools-inline/src/frontend.js index 5b9dd6e668..b1a81e0400 100644 --- a/packages/react-devtools-inline/src/frontend.js +++ b/packages/react-devtools-inline/src/frontend.js @@ -13,7 +13,7 @@ import { getHideConsoleLogsInStrictMode, } from 'react-devtools-shared/src/utils'; -import type {Wall} from 'react-devtools-shared/src/types'; +import type {Wall} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; import type {Props} from 'react-devtools-shared/src/devtools/views/DevTools'; diff --git a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js index 278b82ac1a..1940e82a80 100644 --- a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js +++ b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js @@ -30,12 +30,7 @@ describe('InspectedElementContext', () => { ): Promise { const rendererID = ((store.getRendererIDForElement(id): any): number); const promise = backendAPI - .inspectElement({ - bridge, - id, - path, - rendererID, - }) + .inspectElement(bridge, false, id, path, rendererID) .then(data => backendAPI.convertInspectedElementBackendToFrontend(data.value), ); diff --git a/packages/react-devtools-shared/src/__tests__/ownersListContext-test.js b/packages/react-devtools-shared/src/__tests__/ownersListContext-test.js index 0da44023c0..c02a895fee 100644 --- a/packages/react-devtools-shared/src/__tests__/ownersListContext-test.js +++ b/packages/react-devtools-shared/src/__tests__/ownersListContext-test.js @@ -8,7 +8,7 @@ */ import typeof ReactTestRenderer from 'react-test-renderer'; -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types'; +import type {Element} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; import type Store from 'react-devtools-shared/src/devtools/store'; diff --git a/packages/react-devtools-shared/src/__tests__/profilerStore-test.js b/packages/react-devtools-shared/src/__tests__/profilerStore-test.js index fcc4de34ea..e933964935 100644 --- a/packages/react-devtools-shared/src/__tests__/profilerStore-test.js +++ b/packages/react-devtools-shared/src/__tests__/profilerStore-test.js @@ -187,7 +187,7 @@ describe('ProfilerStore', () => { utils.act(() => { const { ElementTypeHostComponent, - } = require('react-devtools-shared/src/types'); + } = require('react-devtools-shared/src/frontend/types'); store.componentFilters = [ utils.createElementTypeFilter(ElementTypeHostComponent), ]; diff --git a/packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js b/packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js index c5dd04865c..44c7e85217 100644 --- a/packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js +++ b/packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js @@ -36,7 +36,7 @@ describe('Store component filters', () => { store.recordChangeDescriptions = true; React = require('react'); - Types = require('react-devtools-shared/src/types'); + Types = require('react-devtools-shared/src/frontend/types'); utils = require('./utils'); legacyRender = utils.legacyRender; diff --git a/packages/react-devtools-shared/src/__tests__/utils.js b/packages/react-devtools-shared/src/__tests__/utils.js index 3cb4bec5c1..0c5a0b09f7 100644 --- a/packages/react-devtools-shared/src/__tests__/utils.js +++ b/packages/react-devtools-shared/src/__tests__/utils.js @@ -12,7 +12,7 @@ import typeof ReactTestRenderer from 'react-test-renderer'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; import type Store from 'react-devtools-shared/src/devtools/store'; import type {ProfilingDataFrontend} from 'react-devtools-shared/src/devtools/views/Profiler/types'; -import type {ElementType} from 'react-devtools-shared/src/types'; +import type {ElementType} from 'react-devtools-shared/src/frontend/types'; export function act( callback: Function, @@ -86,7 +86,7 @@ export function createDisplayNameFilter( source: string, isEnabled: boolean = true, ) { - const Types = require('react-devtools-shared/src/types'); + const Types = require('react-devtools-shared/src/frontend/types'); let isValid = true; try { new RegExp(source); // eslint-disable-line no-new @@ -102,7 +102,7 @@ export function createDisplayNameFilter( } export function createHOCFilter(isEnabled: boolean = true) { - const Types = require('react-devtools-shared/src/types'); + const Types = require('react-devtools-shared/src/frontend/types'); return { type: Types.ComponentFilterHOC, isEnabled, @@ -114,7 +114,7 @@ export function createElementTypeFilter( elementType: ElementType, isEnabled: boolean = true, ) { - const Types = require('react-devtools-shared/src/types'); + const Types = require('react-devtools-shared/src/frontend/types'); return { type: Types.ComponentFilterElementType, isEnabled, @@ -126,7 +126,7 @@ export function createLocationFilter( source: string, isEnabled: boolean = true, ) { - const Types = require('react-devtools-shared/src/types'); + const Types = require('react-devtools-shared/src/frontend/types'); let isValid = true; try { new RegExp(source); // eslint-disable-line no-new diff --git a/packages/react-devtools-shared/src/backend/StyleX/utils.js b/packages/react-devtools-shared/src/backend/StyleX/utils.js index 2ae10f316b..ad137c7184 100644 --- a/packages/react-devtools-shared/src/backend/StyleX/utils.js +++ b/packages/react-devtools-shared/src/backend/StyleX/utils.js @@ -7,7 +7,7 @@ * @flow */ -import type {StyleXPlugin} from 'react-devtools-shared/src/types'; +import type {StyleXPlugin} from 'react-devtools-shared/src/frontend/types'; import isArray from 'react-devtools-shared/src/isArray'; const cachedStyleNameToValueMap: Map = new Map(); diff --git a/packages/react-devtools-shared/src/backend/agent.js b/packages/react-devtools-shared/src/backend/agent.js index e15bd1705e..54df48bfe8 100644 --- a/packages/react-devtools-shared/src/backend/agent.js +++ b/packages/react-devtools-shared/src/backend/agent.js @@ -42,7 +42,7 @@ import type { import type { ComponentFilter, BrowserTheme, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; import {isSynchronousXHRSupported} from './utils'; const debug = (methodName: string, ...args: Array) => { diff --git a/packages/react-devtools-shared/src/backend/legacy/renderer.js b/packages/react-devtools-shared/src/backend/legacy/renderer.js index 603d84d076..9b1a860a40 100644 --- a/packages/react-devtools-shared/src/backend/legacy/renderer.js +++ b/packages/react-devtools-shared/src/backend/legacy/renderer.js @@ -13,7 +13,7 @@ import { ElementTypeRoot, ElementTypeHostComponent, ElementTypeOtherOrUnknown, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; import {getUID, utfEncodeString, printOperationsArray} from '../../utils'; import { cleanForBridge, @@ -50,7 +50,7 @@ import type { import type { ComponentFilter, ElementType, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; import type {InspectedElement, SerializedElement} from '../types'; export type InternalInstance = Object; diff --git a/packages/react-devtools-shared/src/backend/renderer.js b/packages/react-devtools-shared/src/backend/renderer.js index 050793aa10..60581b4033 100644 --- a/packages/react-devtools-shared/src/backend/renderer.js +++ b/packages/react-devtools-shared/src/backend/renderer.js @@ -25,7 +25,7 @@ import { ElementTypeSuspenseList, ElementTypeTracingMarker, StrictMode, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; import { deletePathInObject, getDisplayName, @@ -121,7 +121,7 @@ import type { ComponentFilter, ElementType, Plugins, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; type getDisplayNameForFiberType = (fiber: Fiber) => string | null; type getTypeSymbolType = (type: any) => symbol | number; diff --git a/packages/react-devtools-shared/src/backend/types.js b/packages/react-devtools-shared/src/backend/types.js index c3a2f35a5d..14a26140b2 100644 --- a/packages/react-devtools-shared/src/backend/types.js +++ b/packages/react-devtools-shared/src/backend/types.js @@ -21,14 +21,14 @@ import type { ComponentFilter, ElementType, Plugins, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; import type { ResolveNativeStyle, SetupNativeStyleEditor, } from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor'; import type {InitBackend} from 'react-devtools-shared/src/backend'; import type {TimelineDataExport} from 'react-devtools-timeline/src/types'; -import type {BrowserTheme} from 'react-devtools-shared/src/types'; +import type {BrowserTheme} from 'react-devtools-shared/src/frontend/types'; import type {BackendBridge} from 'react-devtools-shared/src/bridge'; import type Agent from './agent'; diff --git a/packages/react-devtools-shared/src/backend/utils.js b/packages/react-devtools-shared/src/backend/utils.js index bcadf4a7c0..19d34f335a 100644 --- a/packages/react-devtools-shared/src/backend/utils.js +++ b/packages/react-devtools-shared/src/backend/utils.js @@ -12,7 +12,7 @@ import {compareVersions} from 'compare-versions'; import {dehydrate} from '../hydration'; import isArray from 'shared/isArray'; -import type {DehydratedData} from 'react-devtools-shared/src/devtools/views/Components/types'; +import type {DehydratedData} from 'react-devtools-shared/src/frontend/types'; // TODO: update this to the first React version that has a corresponding DevTools backend const FIRST_DEVTOOLS_BACKEND_LOCKSTEP_VER = '999.9.9'; diff --git a/packages/react-devtools-shared/src/backendAPI.js b/packages/react-devtools-shared/src/backendAPI.js index fcbfb423a7..27700c27c7 100644 --- a/packages/react-devtools-shared/src/backendAPI.js +++ b/packages/react-devtools-shared/src/backendAPI.js @@ -24,7 +24,8 @@ import type { import type { DehydratedData, InspectedElement as InspectedElementFrontend, -} from 'react-devtools-shared/src/devtools/views/Components/types'; +} from 'react-devtools-shared/src/frontend/types'; +import type {InspectedElementPath} from 'react-devtools-shared/src/frontend/types'; export function clearErrorsAndWarnings({ bridge, @@ -86,25 +87,21 @@ export function copyInspectedElementPath({ }); } -export function inspectElement({ - bridge, - forceFullData, - id, - path, - rendererID, -}: { +export function inspectElement( bridge: FrontendBridge, forceFullData: boolean, id: number, - path: Array | null, + path: InspectedElementPath | null, rendererID: number, -}): Promise { + shouldListenToPauseEvents: boolean = false, +): Promise { const requestID = requestCounter++; const promise = getPromiseForRequestID( requestID, 'inspectedElement', bridge, `Timed out while inspecting element ${id}.`, + shouldListenToPauseEvents, ); bridge.send('inspectElement', { @@ -148,16 +145,29 @@ function getPromiseForRequestID( eventType: $Keys, bridge: FrontendBridge, timeoutMessage: string, + shouldListenToPauseEvents: boolean = false, ): Promise { return new Promise((resolve, reject) => { const cleanup = () => { bridge.removeListener(eventType, onInspectedElement); - bridge.removeListener('shutdown', onDisconnect); - bridge.removeListener('pauseElementPolling', onDisconnect); + bridge.removeListener('shutdown', onShutdown); + + if (shouldListenToPauseEvents) { + bridge.removeListener('pauseElementPolling', onDisconnect); + } clearTimeout(timeoutID); }; + const onShutdown = () => { + cleanup(); + reject( + new Error( + 'Failed to inspect element. Try again or restart React DevTools.', + ), + ); + }; + const onDisconnect = () => { cleanup(); reject(new ElementPollingCancellationError()); @@ -176,8 +186,11 @@ function getPromiseForRequestID( }; bridge.addListener(eventType, onInspectedElement); - bridge.addListener('shutdown', onDisconnect); - bridge.addListener('pauseElementPolling', onDisconnect); + bridge.addListener('shutdown', onShutdown); + + if (shouldListenToPauseEvents) { + bridge.addListener('pauseElementPolling', onDisconnect); + } const timeoutID = setTimeout(onTimeout, TIMEOUT_DELAY); }); @@ -277,7 +290,7 @@ export function convertInspectedElementBackendToFrontend( export function hydrateHelper( dehydratedData: DehydratedData | null, - path?: Array, + path: ?InspectedElementPath, ): Object | null { if (dehydratedData !== null) { const {cleaned, data, unserializable} = dehydratedData; diff --git a/packages/react-devtools-shared/src/bridge.js b/packages/react-devtools-shared/src/bridge.js index b5876ddb33..afbf564988 100644 --- a/packages/react-devtools-shared/src/bridge.js +++ b/packages/react-devtools-shared/src/bridge.js @@ -9,7 +9,7 @@ import EventEmitter from './events'; -import type {ComponentFilter, Wall} from './types'; +import type {ComponentFilter, Wall} from './frontend/types'; import type { InspectedElementPayload, OwnersList, diff --git a/packages/react-devtools-shared/src/devtools/store.js b/packages/react-devtools-shared/src/devtools/store.js index 2c1316cba1..a04a31cf63 100644 --- a/packages/react-devtools-shared/src/devtools/store.js +++ b/packages/react-devtools-shared/src/devtools/store.js @@ -21,7 +21,7 @@ import { TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS, TREE_OPERATION_UPDATE_TREE_BASE_DURATION, } from '../constants'; -import {ElementTypeRoot} from '../types'; +import {ElementTypeRoot} from '../frontend/types'; import { getSavedComponentFilters, setSavedComponentFilters, @@ -37,10 +37,13 @@ import { BRIDGE_PROTOCOL, currentBridgeProtocol, } from 'react-devtools-shared/src/bridge'; -import {StrictMode} from 'react-devtools-shared/src/types'; +import {StrictMode} from 'react-devtools-shared/src/frontend/types'; -import type {Element} from './views/Components/types'; -import type {ComponentFilter, ElementType} from '../types'; +import type { + Element, + ComponentFilter, + ElementType, +} from 'react-devtools-shared/src/frontend/types'; import type { FrontendBridge, BridgeProtocol, diff --git a/packages/react-devtools-shared/src/devtools/utils.js b/packages/react-devtools-shared/src/devtools/utils.js index 6a6fb08f7e..7de23d50c9 100644 --- a/packages/react-devtools-shared/src/devtools/utils.js +++ b/packages/react-devtools-shared/src/devtools/utils.js @@ -9,7 +9,7 @@ import JSON5 from 'json5'; -import type {Element} from './views/Components/types'; +import type {Element} from 'react-devtools-shared/src/frontend/types'; import type {StateContext} from './views/Components/TreeContext'; import type Store from './store'; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Badge.js b/packages/react-devtools-shared/src/devtools/views/Components/Badge.js index dca342de4e..b58818e39a 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Badge.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Badge.js @@ -11,7 +11,7 @@ import * as React from 'react'; import {Fragment} from 'react'; import styles from './Badge.css'; -import type {ElementType} from 'react-devtools-shared/src/types'; +import type {ElementType} from 'react-devtools-shared/src/frontend/types'; type Props = { className?: string, diff --git a/packages/react-devtools-shared/src/devtools/views/Components/CannotSuspendWarningMessage.js b/packages/react-devtools-shared/src/devtools/views/Components/CannotSuspendWarningMessage.js index 3494bf95c0..71fce90b5b 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/CannotSuspendWarningMessage.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/CannotSuspendWarningMessage.js @@ -13,7 +13,7 @@ import {StoreContext} from '../context'; import { ComponentFilterElementType, ElementTypeSuspense, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; export default function CannotSuspendWarningMessage(): React.Node { const store = useContext(StoreContext); diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Element.js b/packages/react-devtools-shared/src/devtools/views/Components/Element.js index 0cbf7e06e0..b5486cd7ed 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Element.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Element.js @@ -20,7 +20,7 @@ import {useSubscription} from '../hooks'; import {logEvent} from 'react-devtools-shared/src/Logger'; import type {ItemData} from './Tree'; -import type {Element as ElementType} from './types'; +import type {Element as ElementType} from 'react-devtools-shared/src/frontend/types'; import styles from './Element.css'; import Icon from '../Icon'; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/HocBadges.js b/packages/react-devtools-shared/src/devtools/views/Components/HocBadges.js index 3d23d9cd78..6eecac653a 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/HocBadges.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/HocBadges.js @@ -10,7 +10,7 @@ import * as React from 'react'; import styles from './HocBadges.css'; -import type {Element} from './types'; +import type {Element} from 'react-devtools-shared/src/frontend/types'; type Props = { element: Element, diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js index eca9f80f2b..635af271ad 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js @@ -17,7 +17,7 @@ import Icon from '../Icon'; import {ModalDialogContext} from '../ModalDialog'; import ViewElementSourceContext from './ViewElementSourceContext'; import Toggle from '../Toggle'; -import {ElementTypeSuspense} from 'react-devtools-shared/src/types'; +import {ElementTypeSuspense} from 'react-devtools-shared/src/frontend/types'; import CannotSuspendWarningMessage from './CannotSuspendWarningMessage'; import InspectedElementView from './InspectedElementView'; import {InspectedElementContext} from './InspectedElementContext'; @@ -26,7 +26,7 @@ import {LOCAL_STORAGE_OPEN_IN_EDITOR_URL} from '../../../constants'; import styles from './InspectedElement.css'; -import type {InspectedElement} from './types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; export type Props = {}; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContext.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContext.js index c1b7ac777f..601c8c9615 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContext.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContext.js @@ -37,12 +37,12 @@ import FetchFileWithCachingContext from 'react-devtools-shared/src/devtools/view import HookNamesModuleLoaderContext from 'react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext'; import {SettingsContext} from '../Settings/SettingsContext'; -import type {HookNames} from 'react-devtools-shared/src/types'; +import type {HookNames} from 'react-devtools-shared/src/frontend/types'; import type {ReactNodeList} from 'shared/ReactTypes'; import type { Element, InspectedElement, -} from 'react-devtools-shared/src/devtools/views/Components/types'; +} from 'react-devtools-shared/src/frontend/types'; type Path = Array; type InspectPathFunction = (path: Path) => void; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContextTree.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContextTree.js index eb74c244d9..5e7276b169 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContextTree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContextTree.js @@ -18,11 +18,11 @@ import styles from './InspectedElementSharedStyles.css'; import { ElementTypeClass, ElementTypeFunction, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; -import type {InspectedElement} from './types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types'; +import type {Element} from 'react-devtools-shared/src/frontend/types'; type Props = { bridge: FrontendBridge, diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorsAndWarningsTree.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorsAndWarningsTree.js index c5b71122d6..4e192d027e 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorsAndWarningsTree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorsAndWarningsTree.js @@ -24,7 +24,7 @@ import { clearWarningsForElement as clearWarningsForElementAPI, } from 'react-devtools-shared/src/backendAPI'; -import type {InspectedElement} from './types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; type Props = { diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementHooksTree.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementHooksTree.js index b1cae27bc4..b04fe44737 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementHooksTree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementHooksTree.js @@ -25,11 +25,11 @@ import {getHookSourceLocationKey} from 'react-devtools-shared/src/hookNamesCache import HookNamesModuleLoaderContext from 'react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext'; import isArray from 'react-devtools-shared/src/isArray'; -import type {InspectedElement} from './types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; import type {HooksNode, HooksTree} from 'react-debug-tools/src/ReactDebugHooks'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; -import type {HookNames} from 'react-devtools-shared/src/types'; -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types'; +import type {HookNames} from 'react-devtools-shared/src/frontend/types'; +import type {Element} from 'react-devtools-shared/src/frontend/types'; import type {ToggleParseHookNames} from './InspectedElementContext'; type HooksTreeViewProps = { diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js index f3962b3a77..f0bc91afb3 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js @@ -17,11 +17,11 @@ import NewKeyValue from './NewKeyValue'; import {alphaSortEntries, serializeDataForCopy} from '../utils'; import Store from '../../store'; import styles from './InspectedElementSharedStyles.css'; -import {ElementTypeClass} from 'react-devtools-shared/src/types'; +import {ElementTypeClass} from 'react-devtools-shared/src/frontend/types'; -import type {InspectedElement} from './types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types'; +import type {Element} from 'react-devtools-shared/src/frontend/types'; type Props = { bridge: FrontendBridge, diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStateTree.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStateTree.js index a1767f7f6e..76e02856b2 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStateTree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStateTree.js @@ -9,7 +9,7 @@ import {copy} from 'clipboard-js'; import * as React from 'react'; -import {ElementTypeHostComponent} from 'react-devtools-shared/src/types'; +import {ElementTypeHostComponent} from 'react-devtools-shared/src/frontend/types'; import Button from '../Button'; import ButtonIcon from '../ButtonIcon'; import KeyValue from './KeyValue'; @@ -17,9 +17,9 @@ import {alphaSortEntries, serializeDataForCopy} from '../utils'; import Store from '../../store'; import styles from './InspectedElementSharedStyles.css'; -import type {InspectedElement} from './types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types'; +import type {Element} from 'react-devtools-shared/src/frontend/types'; type Props = { bridge: FrontendBridge, diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStyleXPlugin.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStyleXPlugin.js index 3a93e00238..e4f9c4c4d7 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStyleXPlugin.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStyleXPlugin.js @@ -14,9 +14,9 @@ import sharedStyles from './InspectedElementSharedStyles.css'; import styles from './InspectedElementStyleXPlugin.css'; import {enableStyleXFeatures} from 'react-devtools-feature-flags'; -import type {InspectedElement} from './types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types'; +import type {Element} from 'react-devtools-shared/src/frontend/types'; type Props = { bridge: FrontendBridge, diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSuspenseToggle.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSuspenseToggle.js index 09808d6e3d..4b60af34df 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSuspenseToggle.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSuspenseToggle.js @@ -11,10 +11,10 @@ import * as React from 'react'; import {OptionsContext} from '../context'; import EditableValue from './EditableValue'; import Store from '../../store'; -import {ElementTypeSuspense} from 'react-devtools-shared/src/types'; +import {ElementTypeSuspense} from 'react-devtools-shared/src/frontend/types'; import styles from './InspectedElementSharedStyles.css'; -import type {InspectedElement} from './types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; type Props = { diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementView.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementView.js index 4804662f31..462677457c 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementView.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementView.js @@ -38,8 +38,15 @@ import {logEvent} from 'react-devtools-shared/src/Logger'; import styles from './InspectedElementView.css'; import type {ContextMenuContextType} from '../context'; -import type {Element, InspectedElement, SerializedElement} from './types'; -import type {ElementType, HookNames} from 'react-devtools-shared/src/types'; +import type { + Element, + InspectedElement, + SerializedElement, +} from 'react-devtools-shared/src/frontend/types'; +import type { + ElementType, + HookNames, +} from 'react-devtools-shared/src/frontend/types'; import type {ToggleParseHookNames} from './InspectedElementContext'; export type CopyPath = (path: Array) => void; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js b/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js index ecfc349979..72684cf594 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js @@ -28,8 +28,8 @@ import isArray from 'react-devtools-shared/src/isArray'; import {InspectedElementContext} from './InspectedElementContext'; import {PROTOCOLS_SUPPORTED_AS_LINKS_IN_KEY_VALUE} from './constants'; -import type {InspectedElement} from './types'; -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; +import type {Element} from 'react-devtools-shared/src/frontend/types'; import type {Element as ReactElement} from 'react'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js b/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js index d405dc1d54..d037ca56ad 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js @@ -31,7 +31,7 @@ import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; import type Store from 'react-devtools-shared/src/devtools/store'; import type {StyleAndLayout as StyleAndLayoutBackend} from 'react-devtools-shared/src/backend/NativeStyleEditor/types'; import type {StyleAndLayout as StyleAndLayoutFrontend} from './types'; -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types'; +import type {Element} from 'react-devtools-shared/src/frontend/types'; import type { Resource, Thenable, diff --git a/packages/react-devtools-shared/src/devtools/views/Components/NewArrayValue.js b/packages/react-devtools-shared/src/devtools/views/Components/NewArrayValue.js index c8247f7449..efaf0d6ac1 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/NewArrayValue.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/NewArrayValue.js @@ -15,7 +15,7 @@ import {smartParse} from '../../utils'; import {parseHookPathForEdit} from './utils'; import styles from './NewArrayValue.css'; -import type {InspectedElement} from './types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; type Props = { diff --git a/packages/react-devtools-shared/src/devtools/views/Components/NewKeyValue.js b/packages/react-devtools-shared/src/devtools/views/Components/NewKeyValue.js index 8fb4cc1dc8..7933ac2521 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/NewKeyValue.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/NewKeyValue.js @@ -15,7 +15,7 @@ import EditableValue from './EditableValue'; import {parseHookPathForEdit} from './utils'; import styles from './NewKeyValue.css'; -import type {InspectedElement} from './types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; type Props = { diff --git a/packages/react-devtools-shared/src/devtools/views/Components/OwnersListContext.js b/packages/react-devtools-shared/src/devtools/views/Components/OwnersListContext.js index 04c90a1d81..760c490d72 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/OwnersListContext.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/OwnersListContext.js @@ -20,7 +20,7 @@ import type {OwnersList} from 'react-devtools-shared/src/backend/types'; import type { Element, SerializedElement, -} from 'react-devtools-shared/src/devtools/views/Components/types'; +} from 'react-devtools-shared/src/frontend/types'; import type {Resource, Thenable} from '../../cache'; type Context = (id: number) => Array | null; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/OwnersStack.js b/packages/react-devtools-shared/src/devtools/views/Components/OwnersStack.js index 27c57fda5f..fda6efcc0d 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/OwnersStack.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/OwnersStack.js @@ -32,7 +32,7 @@ import { MenuItem, } from '../Components/reach-ui/menu-button'; -import type {SerializedElement} from './types'; +import type {SerializedElement} from 'react-devtools-shared/src/frontend/types'; import styles from './OwnersStack.css'; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/SelectedTreeHighlight.js b/packages/react-devtools-shared/src/devtools/views/Components/SelectedTreeHighlight.js index 72b8e6c019..44183f6575 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/SelectedTreeHighlight.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/SelectedTreeHighlight.js @@ -7,7 +7,8 @@ * @flow */ -import type {Element} from './types'; +import type {Element} from 'react-devtools-shared/src/frontend/types'; + import * as React from 'react'; import {useContext, useMemo} from 'react'; import {TreeStateContext} from './TreeContext'; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js b/packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js index 9233a2aea4..21cfea44dd 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js @@ -42,7 +42,7 @@ import {createRegExp} from '../utils'; import {BridgeContext, StoreContext} from '../context'; import Store from '../../store'; -import type {Element} from './types'; +import type {Element} from 'react-devtools-shared/src/frontend/types'; export type StateContext = { // Tree diff --git a/packages/react-devtools-shared/src/devtools/views/Components/types.js b/packages/react-devtools-shared/src/devtools/views/Components/types.js deleted file mode 100644 index 2eb4fc232c..0000000000 --- a/packages/react-devtools-shared/src/devtools/views/Components/types.js +++ /dev/null @@ -1,140 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type {Source} from 'shared/ReactElementType'; -import type { - Dehydrated, - Unserializable, -} from 'react-devtools-shared/src/hydration'; -import type {ElementType, Plugins} from 'react-devtools-shared/src/types'; - -// Each element on the frontend corresponds to a Fiber on the backend. -// Some of its information (e.g. id, type, displayName) come from the backend. -// Other bits (e.g. weight and depth) are computed on the frontend for windowing and display purposes. -// Elements are updated on a push basis– meaning the backend pushes updates to the frontend when needed. -export type Element = { - id: number, - parentID: number, - children: Array, - type: ElementType, - displayName: string | null, - key: number | string | null, - - hocDisplayNames: null | Array, - - // Should the elements children be visible in the tree? - isCollapsed: boolean, - - // Owner (if available) - ownerID: number, - - // How many levels deep within the tree is this element? - // This determines how much indentation (left padding) should be used in the Elements tree. - depth: number, - - // How many nodes (including itself) are below this Element within the tree. - // This property is used to quickly determine the total number of Elements, - // and the Element at any given index (for windowing purposes). - weight: number, - - // This element is not in a StrictMode compliant subtree. - // Only true for React versions supporting StrictMode. - isStrictModeNonCompliant: boolean, -}; - -export type SerializedElement = { - displayName: string | null, - id: number, - key: number | string | null, - hocDisplayNames: Array | null, - type: ElementType, -}; - -export type OwnersList = { - id: number, - owners: Array | null, -}; - -export type InspectedElementResponseType = - | 'error' - | 'full-data' - | 'hydrated-path' - | 'no-change' - | 'not-found'; - -export type InspectedElement = { - id: number, - - // Does the current renderer support editable hooks and function props? - canEditHooks: boolean, - canEditFunctionProps: boolean, - - // Does the current renderer support advanced editing interface? - canEditHooksAndDeletePaths: boolean, - canEditHooksAndRenamePaths: boolean, - canEditFunctionPropsDeletePaths: boolean, - canEditFunctionPropsRenamePaths: boolean, - - // Is this Error, and can its value be overridden now? - isErrored: boolean, - canToggleError: boolean, - targetErrorBoundaryID: ?number, - - // Is this Suspense, and can its value be overridden now? - canToggleSuspense: boolean, - - // Can view component source location. - canViewSource: boolean, - - // Does the component have legacy context attached to it. - hasLegacyContext: boolean, - - // Inspectable properties. - context: Object | null, - hooks: Object | null, - props: Object | null, - state: Object | null, - key: number | string | null, - errors: Array<[string, number]>, - warnings: Array<[string, number]>, - - // List of owners - owners: Array | null, - - // Location of component in source code. - source: Source | null, - - type: ElementType, - - // Meta information about the root this element belongs to. - rootType: string | null, - - // Meta information about the renderer that created this element. - rendererPackageName: string | null, - rendererVersion: string | null, - - // UI plugins/visualizations for the inspected element. - plugins: Plugins, -}; - -// TODO: Add profiling type - -type Data = - | string - | Dehydrated - | Unserializable - | Array - | Array - | {[string]: Data}; - -export type DehydratedData = { - cleaned: Array>, - data: Data, - unserializable: Array>, -}; diff --git a/packages/react-devtools-shared/src/devtools/views/DevTools.js b/packages/react-devtools-shared/src/devtools/views/DevTools.js index 3eef04ece7..934ebd6928 100644 --- a/packages/react-devtools-shared/src/devtools/views/DevTools.js +++ b/packages/react-devtools-shared/src/devtools/views/DevTools.js @@ -46,11 +46,11 @@ import styles from './DevTools.css'; import './root.css'; -import type {InspectedElement} from 'react-devtools-shared/src/devtools/views/Components/types'; +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; import type {FetchFileWithCaching} from './Components/FetchFileWithCachingContext'; import type {HookNamesModuleLoaderFunction} from 'react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; -import type {BrowserTheme} from 'react-devtools-shared/src/types'; +import type {BrowserTheme} from 'react-devtools-shared/src/frontend/types'; export type TabID = 'components' | 'profiler'; diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js b/packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js index 4ff09adee7..5b3b73482e 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js @@ -18,10 +18,10 @@ import { TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS, } from 'react-devtools-shared/src/constants'; import {utfDecodeString} from 'react-devtools-shared/src/utils'; -import {ElementTypeRoot} from 'react-devtools-shared/src/types'; +import {ElementTypeRoot} from 'react-devtools-shared/src/frontend/types'; import ProfilerStore from 'react-devtools-shared/src/devtools/ProfilerStore'; -import type {ElementType} from 'react-devtools-shared/src/types'; +import type {ElementType} from 'react-devtools-shared/src/frontend/types'; import type { CommitTree, CommitTreeNode, diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/RankedChartBuilder.js b/packages/react-devtools-shared/src/devtools/views/Profiler/RankedChartBuilder.js index af3c26c0fd..f5938674b7 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/RankedChartBuilder.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/RankedChartBuilder.js @@ -10,7 +10,7 @@ import { ElementTypeForwardRef, ElementTypeMemo, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; import {formatDuration} from './utils'; import ProfilerStore from 'react-devtools-shared/src/devtools/ProfilerStore'; diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/Updaters.js b/packages/react-devtools-shared/src/devtools/views/Profiler/Updaters.js index 668eec7120..d0b3131632 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/Updaters.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/Updaters.js @@ -8,13 +8,13 @@ */ import type {CommitTree} from './types'; -import type {SerializedElement} from '../Components/types'; +import type {SerializedElement} from 'react-devtools-shared/src/frontend/types'; import * as React from 'react'; import {useContext} from 'react'; import {ProfilerContext} from './ProfilerContext'; import styles from './Updaters.css'; -import {ElementTypeRoot} from '../../../types'; +import {ElementTypeRoot} from '../../../frontend/types'; export type Props = { commitTree: CommitTree, diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/types.js b/packages/react-devtools-shared/src/devtools/views/Profiler/types.js index 483a86d1ef..0df849e3fb 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/types.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/types.js @@ -7,8 +7,10 @@ * @flow */ -import type {ElementType} from 'react-devtools-shared/src/types'; -import type {SerializedElement} from '../Components/types'; +import type { + ElementType, + SerializedElement, +} from 'react-devtools-shared/src/frontend/types'; import type { TimelineData, TimelineDataExport, diff --git a/packages/react-devtools-shared/src/devtools/views/Settings/ComponentsSettings.js b/packages/react-devtools-shared/src/devtools/views/Settings/ComponentsSettings.js index 99a5ab2d10..e19f056c8b 100644 --- a/packages/react-devtools-shared/src/devtools/views/Settings/ComponentsSettings.js +++ b/packages/react-devtools-shared/src/devtools/views/Settings/ComponentsSettings.js @@ -40,7 +40,7 @@ import { ElementTypeOtherOrUnknown, ElementTypeProfiler, ElementTypeSuspense, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; import {getDefaultOpenInEditorURL} from 'react-devtools-shared/src/utils'; import styles from './SettingsShared.css'; @@ -52,7 +52,7 @@ import type { ElementType, ElementTypeComponentFilter, RegExpComponentFilter, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; const vscodeFilepath = 'vscode://file/{path}:{line}'; diff --git a/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js b/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js index 40eea803de..a6f2c5e8c2 100644 --- a/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js +++ b/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js @@ -34,7 +34,7 @@ import {useLocalStorage} from '../hooks'; import {BridgeContext} from '../context'; import {logEvent} from 'react-devtools-shared/src/Logger'; -import type {BrowserTheme} from 'react-devtools-shared/src/types'; +import type {BrowserTheme} from 'react-devtools-shared/src/frontend/types'; export type DisplayDensity = 'comfortable' | 'compact'; export type Theme = 'auto' | 'light' | 'dark'; diff --git a/packages/react-devtools-shared/src/types.js b/packages/react-devtools-shared/src/frontend/types.js similarity index 51% rename from packages/react-devtools-shared/src/types.js rename to packages/react-devtools-shared/src/frontend/types.js index 51376553a3..3d85a01095 100644 --- a/packages/react-devtools-shared/src/types.js +++ b/packages/react-devtools-shared/src/frontend/types.js @@ -14,6 +14,12 @@ * Be mindful of backwards compatibility when making changes. */ +import type {Source} from 'shared/ReactElementType'; +import type { + Dehydrated, + Unserializable, +} from 'react-devtools-shared/src/hydration'; + export type BrowserTheme = 'dark' | 'light'; export type Wall = { @@ -112,3 +118,130 @@ export type Plugins = { }; export const StrictMode = 1; + +// Each element on the frontend corresponds to a Fiber on the backend. +// Some of its information (e.g. id, type, displayName) come from the backend. +// Other bits (e.g. weight and depth) are computed on the frontend for windowing and display purposes. +// Elements are updated on a push basis– meaning the backend pushes updates to the frontend when needed. +export type Element = { + id: number, + parentID: number, + children: Array, + type: ElementType, + displayName: string | null, + key: number | string | null, + + hocDisplayNames: null | Array, + + // Should the elements children be visible in the tree? + isCollapsed: boolean, + + // Owner (if available) + ownerID: number, + + // How many levels deep within the tree is this element? + // This determines how much indentation (left padding) should be used in the Elements tree. + depth: number, + + // How many nodes (including itself) are below this Element within the tree. + // This property is used to quickly determine the total number of Elements, + // and the Element at any given index (for windowing purposes). + weight: number, + + // This element is not in a StrictMode compliant subtree. + // Only true for React versions supporting StrictMode. + isStrictModeNonCompliant: boolean, +}; + +export type SerializedElement = { + displayName: string | null, + id: number, + key: number | string | null, + hocDisplayNames: Array | null, + type: ElementType, +}; + +export type OwnersList = { + id: number, + owners: Array | null, +}; + +export type InspectedElementResponseType = + | 'error' + | 'full-data' + | 'hydrated-path' + | 'no-change' + | 'not-found'; + +export type InspectedElementPath = Array; + +export type InspectedElement = { + id: number, + + // Does the current renderer support editable hooks and function props? + canEditHooks: boolean, + canEditFunctionProps: boolean, + + // Does the current renderer support advanced editing interface? + canEditHooksAndDeletePaths: boolean, + canEditHooksAndRenamePaths: boolean, + canEditFunctionPropsDeletePaths: boolean, + canEditFunctionPropsRenamePaths: boolean, + + // Is this Error, and can its value be overridden now? + isErrored: boolean, + canToggleError: boolean, + targetErrorBoundaryID: ?number, + + // Is this Suspense, and can its value be overridden now? + canToggleSuspense: boolean, + + // Can view component source location. + canViewSource: boolean, + + // Does the component have legacy context attached to it. + hasLegacyContext: boolean, + + // Inspectable properties. + context: Object | null, + hooks: Object | null, + props: Object | null, + state: Object | null, + key: number | string | null, + errors: Array<[string, number]>, + warnings: Array<[string, number]>, + + // List of owners + owners: Array | null, + + // Location of component in source code. + source: Source | null, + + type: ElementType, + + // Meta information about the root this element belongs to. + rootType: string | null, + + // Meta information about the renderer that created this element. + rendererPackageName: string | null, + rendererVersion: string | null, + + // UI plugins/visualizations for the inspected element. + plugins: Plugins, +}; + +// TODO: Add profiling type + +type Data = + | string + | Dehydrated + | Unserializable + | Array + | Array + | {[string]: Data}; + +export type DehydratedData = { + cleaned: Array>, + data: Data, + unserializable: Array>, +}; diff --git a/packages/react-devtools-shared/src/hook.js b/packages/react-devtools-shared/src/hook.js index 4df992e23e..92389abf6e 100644 --- a/packages/react-devtools-shared/src/hook.js +++ b/packages/react-devtools-shared/src/hook.js @@ -8,7 +8,7 @@ * @flow */ -import type {BrowserTheme} from './types'; +import type {BrowserTheme} from './frontend/types'; import type { DevToolsHook, Handler, diff --git a/packages/react-devtools-shared/src/hookNamesCache.js b/packages/react-devtools-shared/src/hookNamesCache.js index 0efa5e5f9a..89377eebb1 100644 --- a/packages/react-devtools-shared/src/hookNamesCache.js +++ b/packages/react-devtools-shared/src/hookNamesCache.js @@ -11,11 +11,11 @@ import {__DEBUG__} from 'react-devtools-shared/src/constants'; import type {HooksTree} from 'react-debug-tools/src/ReactDebugHooks'; import type {Thenable, Wakeable} from 'shared/ReactTypes'; -import type {Element} from './devtools/views/Components/types'; import type { + Element, HookNames, HookSourceLocationKey, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; import type {HookSource} from 'react-debug-tools/src/ReactDebugHooks'; import type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext'; import {withCallbackPerfMeasurements} from './PerformanceLoggingUtils'; diff --git a/packages/react-devtools-shared/src/hooks/parseHookNames/index.js b/packages/react-devtools-shared/src/hooks/parseHookNames/index.js index 13b437d08c..3691f74e4f 100644 --- a/packages/react-devtools-shared/src/hooks/parseHookNames/index.js +++ b/packages/react-devtools-shared/src/hooks/parseHookNames/index.js @@ -9,7 +9,7 @@ import type {HookSourceAndMetadata} from './loadSourceAndMetadata'; import type {HooksNode, HooksTree} from 'react-debug-tools/src/ReactDebugHooks'; -import type {HookNames} from 'react-devtools-shared/src/types'; +import type {HookNames} from 'react-devtools-shared/src/frontend/types'; import type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext'; import {withAsyncPerfMeasurements} from 'react-devtools-shared/src/PerformanceLoggingUtils'; diff --git a/packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js b/packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js index 2cbefe97bf..40bfed48ba 100644 --- a/packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js +++ b/packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js @@ -29,7 +29,10 @@ import type { LocationKeyToHookSourceAndMetadata, } from './loadSourceAndMetadata'; import type {HookSource} from 'react-debug-tools/src/ReactDebugHooks'; -import type {HookNames, LRUCache} from 'react-devtools-shared/src/types'; +import type { + HookNames, + LRUCache, +} from 'react-devtools-shared/src/frontend/types'; type AST = mixed; diff --git a/packages/react-devtools-shared/src/hydration.js b/packages/react-devtools-shared/src/hydration.js index 431d360696..f9834fcb41 100644 --- a/packages/react-devtools-shared/src/hydration.js +++ b/packages/react-devtools-shared/src/hydration.js @@ -14,9 +14,12 @@ import { getInObject, formatDataForPreview, setInObject, -} from './utils'; +} from 'react-devtools-shared/src/utils'; -import type {DehydratedData} from './devtools/views/Components/types'; +import type { + DehydratedData, + InspectedElementPath, +} from 'react-devtools-shared/src/frontend/types'; export const meta = { inspectable: (Symbol('inspectable'): symbol), @@ -123,7 +126,7 @@ export function dehydrate( unserializable: Array>, path: Array, isPathAllowed: (path: Array) => boolean, - level?: number = 0, + level: number = 0, ): $PropertyType { const type = getDataType(data); @@ -365,7 +368,7 @@ export function dehydrate( export function fillInPath( object: Object, data: DehydratedData, - path: Array, + path: InspectedElementPath, value: any, ) { const target = getInObject(object, path); diff --git a/packages/react-devtools-shared/src/inspectedElementCache.js b/packages/react-devtools-shared/src/inspectedElementCache.js index bfa9fb1092..014edf22a7 100644 --- a/packages/react-devtools-shared/src/inspectedElementCache.js +++ b/packages/react-devtools-shared/src/inspectedElementCache.js @@ -21,7 +21,8 @@ import type { Element, InspectedElement as InspectedElementFrontend, InspectedElementResponseType, -} from 'react-devtools-shared/src/devtools/views/Components/types'; + InspectedElementPath, +} from 'react-devtools-shared/src/frontend/types'; const Pending = 0; const Resolved = 1; @@ -83,7 +84,7 @@ function createCacheSeed( */ export function inspectElement( element: Element, - path: Array | null, + path: InspectedElementPath | null, store: Store, bridge: FrontendBridge, ): InspectedElementFrontend | null { @@ -123,12 +124,7 @@ export function inspectElement( return null; } - inspectElementMutableSource({ - bridge, - element, - path, - rendererID: ((rendererID: any): number), - }).then( + inspectElementMutableSource(bridge, element, path, rendererID).then( ([inspectedElement]: [ InspectedElementFrontend, InspectedElementResponseType, @@ -151,6 +147,7 @@ export function inspectElement( wake(); }, ); + map.set(element, record); } @@ -186,12 +183,13 @@ export function checkForUpdate({ return; } - return inspectElementMutableSource({ + return inspectElementMutableSource( bridge, element, - path: null, + null, rendererID, - }).then( + true, + ).then( ([inspectedElement, responseType]: [ InspectedElementFrontend, InspectedElementResponseType, diff --git a/packages/react-devtools-shared/src/inspectedElementMutableSource.js b/packages/react-devtools-shared/src/inspectedElementMutableSource.js index 445d4a65d6..ae90bd021b 100644 --- a/packages/react-devtools-shared/src/inspectedElementMutableSource.js +++ b/packages/react-devtools-shared/src/inspectedElementMutableSource.js @@ -15,20 +15,21 @@ import { } from 'react-devtools-shared/src/backendAPI'; import {fillInPath} from 'react-devtools-shared/src/hydration'; -import type {LRUCache} from 'react-devtools-shared/src/types'; +import type {LRUCache} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; import type { InspectElementError, InspectElementFullData, InspectElementHydratedPath, } from 'react-devtools-shared/src/backend/types'; +import UserError from 'react-devtools-shared/src/errors/UserError'; +import UnknownHookError from 'react-devtools-shared/src/errors/UnknownHookError'; import type { Element, InspectedElement as InspectedElementFrontend, InspectedElementResponseType, -} from 'react-devtools-shared/src/devtools/views/Components/types'; -import UserError from 'react-devtools-shared/src/errors/UserError'; -import UnknownHookError from 'react-devtools-shared/src/errors/UnknownHookError'; + InspectedElementPath, +} from 'react-devtools-shared/src/frontend/types'; // Maps element ID to inspected data. // We use an LRU for this rather than a WeakMap because of how the "no-change" optimization works. @@ -44,24 +45,18 @@ const inspectedElementCache: LRUCache = max: 25, }); -type Path = Array; - type InspectElementReturnType = [ InspectedElementFrontend, InspectedElementResponseType, ]; -export function inspectElement({ - bridge, - element, - path, - rendererID, -}: { +export function inspectElement( bridge: FrontendBridge, element: Element, - path: Path | null, + path: InspectedElementPath | null, rendererID: number, -}): Promise { + shouldListenToPauseEvents: boolean = false, +): Promise { const {id} = element; // This could indicate that the DevTools UI has been closed and reopened. @@ -69,13 +64,14 @@ export function inspectElement({ // In this case, we need to tell it to resend the full data. const forceFullData = !inspectedElementCache.has(id); - return inspectElementAPI({ + return inspectElementAPI( bridge, forceFullData, id, path, rendererID, - }).then((data: any) => { + shouldListenToPauseEvents, + ).then((data: any) => { const {type} = data; let inspectedElement; @@ -141,12 +137,14 @@ export function inspectElement({ inspectedElement = {...inspectedElement}; // Merge hydrated data - fillInPath( - inspectedElement, - value, - ((path: any): Path), - hydrateHelper(value, ((path: any): Path)), - ); + if (path != null) { + fillInPath( + inspectedElement, + value, + path, + hydrateHelper(value, path), + ); + } inspectedElementCache.set(id, inspectedElement); diff --git a/packages/react-devtools-shared/src/utils.js b/packages/react-devtools-shared/src/utils.js index bf2b7852f1..924b0e8aef 100644 --- a/packages/react-devtools-shared/src/utils.js +++ b/packages/react-devtools-shared/src/utils.js @@ -41,20 +41,27 @@ import { LOCAL_STORAGE_SHOW_INLINE_WARNINGS_AND_ERRORS_KEY, LOCAL_STORAGE_HIDE_CONSOLE_LOGS_IN_STRICT_MODE, } from './constants'; -import {ComponentFilterElementType, ElementTypeHostComponent} from './types'; +import { + ComponentFilterElementType, + ElementTypeHostComponent, +} from './frontend/types'; import { ElementTypeRoot, ElementTypeClass, ElementTypeForwardRef, ElementTypeFunction, ElementTypeMemo, -} from 'react-devtools-shared/src/types'; +} from 'react-devtools-shared/src/frontend/types'; import {localStorageGetItem, localStorageSetItem} from './storage'; import {meta} from './hydration'; import isArray from './isArray'; -import type {ComponentFilter, ElementType, BrowserTheme} from './types'; -import type {LRUCache} from 'react-devtools-shared/src/types'; +import type { + ComponentFilter, + ElementType, + BrowserTheme, +} from './frontend/types'; +import type {LRUCache} from 'react-devtools-shared/src/frontend/types'; // $FlowFixMe[method-unbinding] const hasOwnProperty = Object.prototype.hasOwnProperty;