@samitouri / QOS-React-1 / commits / 77ec61885f

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

Ruslan Lesiutin committed Oct 10, 2023 at 18:10 UTC 77ec61885fb19607cdd116a6790095afa40b5a94
58 files changed +305 -282
packages/react-devtools-core/src/backend.js
+1 -1
@@ -22,7 +22,7 @@ import {
22 } from './cachedSettings';
23
24 import type {BackendBridge} from 'react-devtools-shared/src/bridge';
25 -import type {ComponentFilter} from 'react-devtools-shared/src/types';
25 +import type {ComponentFilter} from 'react-devtools-shared/src/frontend/types';
26 import type {DevToolsHook} from 'react-devtools-shared/src/backend/types';
27 import type {ResolveNativeStyle} from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';
28
packages/react-devtools-core/src/standalone.js
+1 -1
@@ -33,7 +33,7 @@ import {
33 import {localStorageSetItem} from 'react-devtools-shared/src/storage';
34
35 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
36 -import type {InspectedElement} from 'react-devtools-shared/src/devtools/views/Components/types';
36 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
37
38 installHook(window);
39
packages/react-devtools-inline/src/backend.js
+1 -1
@@ -8,7 +8,7 @@ import {installHook} from 'react-devtools-shared/src/hook';
8 import setupNativeStyleEditor from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';
9
10 import type {BackendBridge} from 'react-devtools-shared/src/bridge';
11 -import type {Wall} from 'react-devtools-shared/src/types';
11 +import type {Wall} from 'react-devtools-shared/src/frontend/types';
12
13 function startActivation(contentWindow: any, bridge: BackendBridge) {
14 const onSavedPreferences = (data: $FlowFixMe) => {
packages/react-devtools-inline/src/frontend.js
+1 -1
@@ -13,7 +13,7 @@ import {
13 getHideConsoleLogsInStrictMode,
14 } from 'react-devtools-shared/src/utils';
15
16 -import type {Wall} from 'react-devtools-shared/src/types';
16 +import type {Wall} from 'react-devtools-shared/src/frontend/types';
17 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
18 import type {Props} from 'react-devtools-shared/src/devtools/views/DevTools';
19
packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js
+1 -6
@@ -30,12 +30,7 @@ describe('InspectedElementContext', () => {
30 ): Promise<Object> {
31 const rendererID = ((store.getRendererIDForElement(id): any): number);
32 const promise = backendAPI
33 - .inspectElement({
34 - bridge,
35 - id,
36 - path,
37 - rendererID,
38 - })
33 + .inspectElement(bridge, false, id, path, rendererID)
34 .then(data =>
35 backendAPI.convertInspectedElementBackendToFrontend(data.value),
36 );
packages/react-devtools-shared/src/__tests__/ownersListContext-test.js
+1 -1
@@ -8,7 +8,7 @@
8 */
9
10 import typeof ReactTestRenderer from 'react-test-renderer';
11 -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types';
11 +import type {Element} from 'react-devtools-shared/src/frontend/types';
12 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
13 import type Store from 'react-devtools-shared/src/devtools/store';
14
packages/react-devtools-shared/src/__tests__/profilerStore-test.js
+1 -1
@@ -187,7 +187,7 @@ describe('ProfilerStore', () => {
187 utils.act(() => {
188 const {
189 ElementTypeHostComponent,
190 - } = require('react-devtools-shared/src/types');
190 + } = require('react-devtools-shared/src/frontend/types');
191 store.componentFilters = [
192 utils.createElementTypeFilter(ElementTypeHostComponent),
193 ];
packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js
+1 -1
@@ -36,7 +36,7 @@ describe('Store component filters', () => {
36 store.recordChangeDescriptions = true;
37
38 React = require('react');
39 - Types = require('react-devtools-shared/src/types');
39 + Types = require('react-devtools-shared/src/frontend/types');
40 utils = require('./utils');
41
42 legacyRender = utils.legacyRender;
packages/react-devtools-shared/src/__tests__/utils.js
+5 -5
@@ -12,7 +12,7 @@ import typeof ReactTestRenderer from 'react-test-renderer';
12 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
13 import type Store from 'react-devtools-shared/src/devtools/store';
14 import type {ProfilingDataFrontend} from 'react-devtools-shared/src/devtools/views/Profiler/types';
15 -import type {ElementType} from 'react-devtools-shared/src/types';
15 +import type {ElementType} from 'react-devtools-shared/src/frontend/types';
16
17 export function act(
18 callback: Function,
@@ -86,7 +86,7 @@ export function createDisplayNameFilter(
86 source: string,
87 isEnabled: boolean = true,
88 ) {
89 - const Types = require('react-devtools-shared/src/types');
89 + const Types = require('react-devtools-shared/src/frontend/types');
90 let isValid = true;
91 try {
92 new RegExp(source); // eslint-disable-line no-new
@@ -102,7 +102,7 @@ export function createDisplayNameFilter(
102 }
103
104 export function createHOCFilter(isEnabled: boolean = true) {
105 - const Types = require('react-devtools-shared/src/types');
105 + const Types = require('react-devtools-shared/src/frontend/types');
106 return {
107 type: Types.ComponentFilterHOC,
108 isEnabled,
@@ -114,7 +114,7 @@ export function createElementTypeFilter(
114 elementType: ElementType,
115 isEnabled: boolean = true,
116 ) {
117 - const Types = require('react-devtools-shared/src/types');
117 + const Types = require('react-devtools-shared/src/frontend/types');
118 return {
119 type: Types.ComponentFilterElementType,
120 isEnabled,
@@ -126,7 +126,7 @@ export function createLocationFilter(
126 source: string,
127 isEnabled: boolean = true,
128 ) {
129 - const Types = require('react-devtools-shared/src/types');
129 + const Types = require('react-devtools-shared/src/frontend/types');
130 let isValid = true;
131 try {
132 new RegExp(source); // eslint-disable-line no-new
packages/react-devtools-shared/src/backend/StyleX/utils.js
+1 -1
@@ -7,7 +7,7 @@
7 * @flow
8 */
9
10 -import type {StyleXPlugin} from 'react-devtools-shared/src/types';
10 +import type {StyleXPlugin} from 'react-devtools-shared/src/frontend/types';
11 import isArray from 'react-devtools-shared/src/isArray';
12
13 const cachedStyleNameToValueMap: Map<string, string> = new Map();
packages/react-devtools-shared/src/backend/agent.js
+1 -1
@@ -42,7 +42,7 @@ import type {
42 import type {
43 ComponentFilter,
44 BrowserTheme,
45 -} from 'react-devtools-shared/src/types';
45 +} from 'react-devtools-shared/src/frontend/types';
46 import {isSynchronousXHRSupported} from './utils';
47
48 const debug = (methodName: string, ...args: Array<string>) => {
packages/react-devtools-shared/src/backend/legacy/renderer.js
+2 -2
@@ -13,7 +13,7 @@ import {
13 ElementTypeRoot,
14 ElementTypeHostComponent,
15 ElementTypeOtherOrUnknown,
16 -} from 'react-devtools-shared/src/types';
16 +} from 'react-devtools-shared/src/frontend/types';
17 import {getUID, utfEncodeString, printOperationsArray} from '../../utils';
18 import {
19 cleanForBridge,
@@ -50,7 +50,7 @@ import type {
50 import type {
51 ComponentFilter,
52 ElementType,
53 -} from 'react-devtools-shared/src/types';
53 +} from 'react-devtools-shared/src/frontend/types';
54 import type {InspectedElement, SerializedElement} from '../types';
55
56 export type InternalInstance = Object;
packages/react-devtools-shared/src/backend/renderer.js
+2 -2
@@ -25,7 +25,7 @@ import {
25 ElementTypeSuspenseList,
26 ElementTypeTracingMarker,
27 StrictMode,
28 -} from 'react-devtools-shared/src/types';
28 +} from 'react-devtools-shared/src/frontend/types';
29 import {
30 deletePathInObject,
31 getDisplayName,
@@ -121,7 +121,7 @@ import type {
121 ComponentFilter,
122 ElementType,
123 Plugins,
124 -} from 'react-devtools-shared/src/types';
124 +} from 'react-devtools-shared/src/frontend/types';
125
126 type getDisplayNameForFiberType = (fiber: Fiber) => string | null;
127 type getTypeSymbolType = (type: any) => symbol | number;
packages/react-devtools-shared/src/backend/types.js
+2 -2
@@ -21,14 +21,14 @@ import type {
21 ComponentFilter,
22 ElementType,
23 Plugins,
24 -} from 'react-devtools-shared/src/types';
24 +} from 'react-devtools-shared/src/frontend/types';
25 import type {
26 ResolveNativeStyle,
27 SetupNativeStyleEditor,
28 } from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';
29 import type {InitBackend} from 'react-devtools-shared/src/backend';
30 import type {TimelineDataExport} from 'react-devtools-timeline/src/types';
31 -import type {BrowserTheme} from 'react-devtools-shared/src/types';
31 +import type {BrowserTheme} from 'react-devtools-shared/src/frontend/types';
32 import type {BackendBridge} from 'react-devtools-shared/src/bridge';
33 import type Agent from './agent';
34
packages/react-devtools-shared/src/backend/utils.js
+1 -1
@@ -12,7 +12,7 @@ import {compareVersions} from 'compare-versions';
12 import {dehydrate} from '../hydration';
13 import isArray from 'shared/isArray';
14
15 -import type {DehydratedData} from 'react-devtools-shared/src/devtools/views/Components/types';
15 +import type {DehydratedData} from 'react-devtools-shared/src/frontend/types';
16
17 // TODO: update this to the first React version that has a corresponding DevTools backend
18 const FIRST_DEVTOOLS_BACKEND_LOCKSTEP_VER = '999.9.9';
packages/react-devtools-shared/src/backendAPI.js
+28 -15
@@ -24,7 +24,8 @@ import type {
24 import type {
25 DehydratedData,
26 InspectedElement as InspectedElementFrontend,
27 -} from 'react-devtools-shared/src/devtools/views/Components/types';
27 +} from 'react-devtools-shared/src/frontend/types';
28 +import type {InspectedElementPath} from 'react-devtools-shared/src/frontend/types';
29
30 export function clearErrorsAndWarnings({
31 bridge,
@@ -86,25 +87,21 @@ export function copyInspectedElementPath({
87 });
88 }
89
89 -export function inspectElement({
90 - bridge,
91 - forceFullData,
92 - id,
93 - path,
94 - rendererID,
95 -}: {
90 +export function inspectElement(
91 bridge: FrontendBridge,
92 forceFullData: boolean,
93 id: number,
99 - path: Array<string | number> | null,
94 + path: InspectedElementPath | null,
95 rendererID: number,
101 -}): Promise<InspectedElementPayload> {
96 + shouldListenToPauseEvents: boolean = false,
97 +): Promise<InspectedElementPayload> {
98 const requestID = requestCounter++;
99 const promise = getPromiseForRequestID<InspectedElementPayload>(
100 requestID,
101 'inspectedElement',
102 bridge,
103 `Timed out while inspecting element ${id}.`,
104 + shouldListenToPauseEvents,
105 );
106
107 bridge.send('inspectElement', {
@@ -148,16 +145,29 @@ function getPromiseForRequestID<T>(
145 eventType: $Keys<BackendEvents>,
146 bridge: FrontendBridge,
147 timeoutMessage: string,
148 + shouldListenToPauseEvents: boolean = false,
149 ): Promise<T> {
150 return new Promise((resolve, reject) => {
151 const cleanup = () => {
152 bridge.removeListener(eventType, onInspectedElement);
155 - bridge.removeListener('shutdown', onDisconnect);
156 - bridge.removeListener('pauseElementPolling', onDisconnect);
153 + bridge.removeListener('shutdown', onShutdown);
154 +
155 + if (shouldListenToPauseEvents) {
156 + bridge.removeListener('pauseElementPolling', onDisconnect);
157 + }
158
159 clearTimeout(timeoutID);
160 };
161
162 + const onShutdown = () => {
163 + cleanup();
164 + reject(
165 + new Error(
166 + 'Failed to inspect element. Try again or restart React DevTools.',
167 + ),
168 + );
169 + };
170 +
171 const onDisconnect = () => {
172 cleanup();
173 reject(new ElementPollingCancellationError());
@@ -176,8 +186,11 @@ function getPromiseForRequestID<T>(
186 };
187
188 bridge.addListener(eventType, onInspectedElement);
179 - bridge.addListener('shutdown', onDisconnect);
180 - bridge.addListener('pauseElementPolling', onDisconnect);
189 + bridge.addListener('shutdown', onShutdown);
190 +
191 + if (shouldListenToPauseEvents) {
192 + bridge.addListener('pauseElementPolling', onDisconnect);
193 + }
194
195 const timeoutID = setTimeout(onTimeout, TIMEOUT_DELAY);
196 });
@@ -277,7 +290,7 @@ export function convertInspectedElementBackendToFrontend(
290
291 export function hydrateHelper(
292 dehydratedData: DehydratedData | null,
280 - path?: Array<string | number>,
293 + path: ?InspectedElementPath,
294 ): Object | null {
295 if (dehydratedData !== null) {
296 const {cleaned, data, unserializable} = dehydratedData;
packages/react-devtools-shared/src/bridge.js
+1 -1
@@ -9,7 +9,7 @@
9
10 import EventEmitter from './events';
11
12 -import type {ComponentFilter, Wall} from './types';
12 +import type {ComponentFilter, Wall} from './frontend/types';
13 import type {
14 InspectedElementPayload,
15 OwnersList,
packages/react-devtools-shared/src/devtools/store.js
+7 -4
@@ -21,7 +21,7 @@ import {
21 TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS,
22 TREE_OPERATION_UPDATE_TREE_BASE_DURATION,
23 } from '../constants';
24 -import {ElementTypeRoot} from '../types';
24 +import {ElementTypeRoot} from '../frontend/types';
25 import {
26 getSavedComponentFilters,
27 setSavedComponentFilters,
@@ -37,10 +37,13 @@ import {
37 BRIDGE_PROTOCOL,
38 currentBridgeProtocol,
39 } from 'react-devtools-shared/src/bridge';
40 -import {StrictMode} from 'react-devtools-shared/src/types';
40 +import {StrictMode} from 'react-devtools-shared/src/frontend/types';
41
42 -import type {Element} from './views/Components/types';
43 -import type {ComponentFilter, ElementType} from '../types';
42 +import type {
43 + Element,
44 + ComponentFilter,
45 + ElementType,
46 +} from 'react-devtools-shared/src/frontend/types';
47 import type {
48 FrontendBridge,
49 BridgeProtocol,
packages/react-devtools-shared/src/devtools/utils.js
+1 -1
@@ -9,7 +9,7 @@
9
10 import JSON5 from 'json5';
11
12 -import type {Element} from './views/Components/types';
12 +import type {Element} from 'react-devtools-shared/src/frontend/types';
13 import type {StateContext} from './views/Components/TreeContext';
14 import type Store from './store';
15
packages/react-devtools-shared/src/devtools/views/Components/Badge.js
+1 -1
@@ -11,7 +11,7 @@ import * as React from 'react';
11 import {Fragment} from 'react';
12 import styles from './Badge.css';
13
14 -import type {ElementType} from 'react-devtools-shared/src/types';
14 +import type {ElementType} from 'react-devtools-shared/src/frontend/types';
15
16 type Props = {
17 className?: string,
packages/react-devtools-shared/src/devtools/views/Components/CannotSuspendWarningMessage.js
+1 -1
@@ -13,7 +13,7 @@ import {StoreContext} from '../context';
13 import {
14 ComponentFilterElementType,
15 ElementTypeSuspense,
16 -} from 'react-devtools-shared/src/types';
16 +} from 'react-devtools-shared/src/frontend/types';
17
18 export default function CannotSuspendWarningMessage(): React.Node {
19 const store = useContext(StoreContext);
packages/react-devtools-shared/src/devtools/views/Components/Element.js
+1 -1
@@ -20,7 +20,7 @@ import {useSubscription} from '../hooks';
20 import {logEvent} from 'react-devtools-shared/src/Logger';
21
22 import type {ItemData} from './Tree';
23 -import type {Element as ElementType} from './types';
23 +import type {Element as ElementType} from 'react-devtools-shared/src/frontend/types';
24
25 import styles from './Element.css';
26 import Icon from '../Icon';
packages/react-devtools-shared/src/devtools/views/Components/HocBadges.js
+1 -1
@@ -10,7 +10,7 @@
10 import * as React from 'react';
11 import styles from './HocBadges.css';
12
13 -import type {Element} from './types';
13 +import type {Element} from 'react-devtools-shared/src/frontend/types';
14
15 type Props = {
16 element: Element,
packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js
+2 -2
@@ -17,7 +17,7 @@ import Icon from '../Icon';
17 import {ModalDialogContext} from '../ModalDialog';
18 import ViewElementSourceContext from './ViewElementSourceContext';
19 import Toggle from '../Toggle';
20 -import {ElementTypeSuspense} from 'react-devtools-shared/src/types';
20 +import {ElementTypeSuspense} from 'react-devtools-shared/src/frontend/types';
21 import CannotSuspendWarningMessage from './CannotSuspendWarningMessage';
22 import InspectedElementView from './InspectedElementView';
23 import {InspectedElementContext} from './InspectedElementContext';
@@ -26,7 +26,7 @@ import {LOCAL_STORAGE_OPEN_IN_EDITOR_URL} from '../../../constants';
26
27 import styles from './InspectedElement.css';
28
29 -import type {InspectedElement} from './types';
29 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
30
31 export type Props = {};
32
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContext.js
+2 -2
@@ -37,12 +37,12 @@ import FetchFileWithCachingContext from 'react-devtools-shared/src/devtools/view
37 import HookNamesModuleLoaderContext from 'react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext';
38 import {SettingsContext} from '../Settings/SettingsContext';
39
40 -import type {HookNames} from 'react-devtools-shared/src/types';
40 +import type {HookNames} from 'react-devtools-shared/src/frontend/types';
41 import type {ReactNodeList} from 'shared/ReactTypes';
42 import type {
43 Element,
44 InspectedElement,
45 -} from 'react-devtools-shared/src/devtools/views/Components/types';
45 +} from 'react-devtools-shared/src/frontend/types';
46
47 type Path = Array<string | number>;
48 type InspectPathFunction = (path: Path) => void;
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContextTree.js
+3 -3
@@ -18,11 +18,11 @@ import styles from './InspectedElementSharedStyles.css';
18 import {
19 ElementTypeClass,
20 ElementTypeFunction,
21 -} from 'react-devtools-shared/src/types';
21 +} from 'react-devtools-shared/src/frontend/types';
22
23 -import type {InspectedElement} from './types';
23 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
24 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
25 -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types';
25 +import type {Element} from 'react-devtools-shared/src/frontend/types';
26
27 type Props = {
28 bridge: FrontendBridge,
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorsAndWarningsTree.js
+1 -1
@@ -24,7 +24,7 @@ import {
24 clearWarningsForElement as clearWarningsForElementAPI,
25 } from 'react-devtools-shared/src/backendAPI';
26
27 -import type {InspectedElement} from './types';
27 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
28 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
29
30 type Props = {
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementHooksTree.js
+3 -3
@@ -25,11 +25,11 @@ import {getHookSourceLocationKey} from 'react-devtools-shared/src/hookNamesCache
25 import HookNamesModuleLoaderContext from 'react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext';
26 import isArray from 'react-devtools-shared/src/isArray';
27
28 -import type {InspectedElement} from './types';
28 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
29 import type {HooksNode, HooksTree} from 'react-debug-tools/src/ReactDebugHooks';
30 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
31 -import type {HookNames} from 'react-devtools-shared/src/types';
32 -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types';
31 +import type {HookNames} from 'react-devtools-shared/src/frontend/types';
32 +import type {Element} from 'react-devtools-shared/src/frontend/types';
33 import type {ToggleParseHookNames} from './InspectedElementContext';
34
35 type HooksTreeViewProps = {
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js
+3 -3
@@ -17,11 +17,11 @@ import NewKeyValue from './NewKeyValue';
17 import {alphaSortEntries, serializeDataForCopy} from '../utils';
18 import Store from '../../store';
19 import styles from './InspectedElementSharedStyles.css';
20 -import {ElementTypeClass} from 'react-devtools-shared/src/types';
20 +import {ElementTypeClass} from 'react-devtools-shared/src/frontend/types';
21
22 -import type {InspectedElement} from './types';
22 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
23 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
24 -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types';
24 +import type {Element} from 'react-devtools-shared/src/frontend/types';
25
26 type Props = {
27 bridge: FrontendBridge,
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStateTree.js
+3 -3
@@ -9,7 +9,7 @@
9
10 import {copy} from 'clipboard-js';
11 import * as React from 'react';
12 -import {ElementTypeHostComponent} from 'react-devtools-shared/src/types';
12 +import {ElementTypeHostComponent} from 'react-devtools-shared/src/frontend/types';
13 import Button from '../Button';
14 import ButtonIcon from '../ButtonIcon';
15 import KeyValue from './KeyValue';
@@ -17,9 +17,9 @@ import {alphaSortEntries, serializeDataForCopy} from '../utils';
17 import Store from '../../store';
18 import styles from './InspectedElementSharedStyles.css';
19
20 -import type {InspectedElement} from './types';
20 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
21 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
22 -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types';
22 +import type {Element} from 'react-devtools-shared/src/frontend/types';
23
24 type Props = {
25 bridge: FrontendBridge,
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStyleXPlugin.js
+2 -2
@@ -14,9 +14,9 @@ import sharedStyles from './InspectedElementSharedStyles.css';
14 import styles from './InspectedElementStyleXPlugin.css';
15 import {enableStyleXFeatures} from 'react-devtools-feature-flags';
16
17 -import type {InspectedElement} from './types';
17 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
18 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
19 -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types';
19 +import type {Element} from 'react-devtools-shared/src/frontend/types';
20
21 type Props = {
22 bridge: FrontendBridge,
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSuspenseToggle.js
+2 -2
@@ -11,10 +11,10 @@ import * as React from 'react';
11 import {OptionsContext} from '../context';
12 import EditableValue from './EditableValue';
13 import Store from '../../store';
14 -import {ElementTypeSuspense} from 'react-devtools-shared/src/types';
14 +import {ElementTypeSuspense} from 'react-devtools-shared/src/frontend/types';
15 import styles from './InspectedElementSharedStyles.css';
16
17 -import type {InspectedElement} from './types';
17 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
18 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
19
20 type Props = {
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementView.js
+9 -2
@@ -38,8 +38,15 @@ import {logEvent} from 'react-devtools-shared/src/Logger';
38 import styles from './InspectedElementView.css';
39
40 import type {ContextMenuContextType} from '../context';
41 -import type {Element, InspectedElement, SerializedElement} from './types';
42 -import type {ElementType, HookNames} from 'react-devtools-shared/src/types';
41 +import type {
42 + Element,
43 + InspectedElement,
44 + SerializedElement,
45 +} from 'react-devtools-shared/src/frontend/types';
46 +import type {
47 + ElementType,
48 + HookNames,
49 +} from 'react-devtools-shared/src/frontend/types';
50 import type {ToggleParseHookNames} from './InspectedElementContext';
51
52 export type CopyPath = (path: Array<string | number>) => void;
packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js
+2 -2
@@ -28,8 +28,8 @@ import isArray from 'react-devtools-shared/src/isArray';
28 import {InspectedElementContext} from './InspectedElementContext';
29 import {PROTOCOLS_SUPPORTED_AS_LINKS_IN_KEY_VALUE} from './constants';
30
31 -import type {InspectedElement} from './types';
32 -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types';
31 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
32 +import type {Element} from 'react-devtools-shared/src/frontend/types';
33 import type {Element as ReactElement} from 'react';
34 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
35
packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js
+1 -1
@@ -31,7 +31,7 @@ import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
31 import type Store from 'react-devtools-shared/src/devtools/store';
32 import type {StyleAndLayout as StyleAndLayoutBackend} from 'react-devtools-shared/src/backend/NativeStyleEditor/types';
33 import type {StyleAndLayout as StyleAndLayoutFrontend} from './types';
34 -import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types';
34 +import type {Element} from 'react-devtools-shared/src/frontend/types';
35 import type {
36 Resource,
37 Thenable,
packages/react-devtools-shared/src/devtools/views/Components/NewArrayValue.js
+1 -1
@@ -15,7 +15,7 @@ import {smartParse} from '../../utils';
15 import {parseHookPathForEdit} from './utils';
16 import styles from './NewArrayValue.css';
17
18 -import type {InspectedElement} from './types';
18 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
19 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
20
21 type Props = {
packages/react-devtools-shared/src/devtools/views/Components/NewKeyValue.js
+1 -1
@@ -15,7 +15,7 @@ import EditableValue from './EditableValue';
15 import {parseHookPathForEdit} from './utils';
16 import styles from './NewKeyValue.css';
17
18 -import type {InspectedElement} from './types';
18 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
19 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
20
21 type Props = {
packages/react-devtools-shared/src/devtools/views/Components/OwnersListContext.js
+1 -1
@@ -20,7 +20,7 @@ import type {OwnersList} from 'react-devtools-shared/src/backend/types';
20 import type {
21 Element,
22 SerializedElement,
23 -} from 'react-devtools-shared/src/devtools/views/Components/types';
23 +} from 'react-devtools-shared/src/frontend/types';
24 import type {Resource, Thenable} from '../../cache';
25
26 type Context = (id: number) => Array<SerializedElement> | null;
packages/react-devtools-shared/src/devtools/views/Components/OwnersStack.js
+1 -1
@@ -32,7 +32,7 @@ import {
32 MenuItem,
33 } from '../Components/reach-ui/menu-button';
34
35 -import type {SerializedElement} from './types';
35 +import type {SerializedElement} from 'react-devtools-shared/src/frontend/types';
36
37 import styles from './OwnersStack.css';
38
packages/react-devtools-shared/src/devtools/views/Components/SelectedTreeHighlight.js
+2 -1
@@ -7,7 +7,8 @@
7 * @flow
8 */
9
10 -import type {Element} from './types';
10 +import type {Element} from 'react-devtools-shared/src/frontend/types';
11 +
12 import * as React from 'react';
13 import {useContext, useMemo} from 'react';
14 import {TreeStateContext} from './TreeContext';
packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js
+1 -1
@@ -42,7 +42,7 @@ import {createRegExp} from '../utils';
42 import {BridgeContext, StoreContext} from '../context';
43 import Store from '../../store';
44
45 -import type {Element} from './types';
45 +import type {Element} from 'react-devtools-shared/src/frontend/types';
46
47 export type StateContext = {
48 // Tree
packages/react-devtools-shared/src/devtools/views/Components/types.js deleted
-140
@@ -1,140 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -import type {Source} from 'shared/ReactElementType';
11 -import type {
12 - Dehydrated,
13 - Unserializable,
14 -} from 'react-devtools-shared/src/hydration';
15 -import type {ElementType, Plugins} from 'react-devtools-shared/src/types';
16 -
17 -// Each element on the frontend corresponds to a Fiber on the backend.
18 -// Some of its information (e.g. id, type, displayName) come from the backend.
19 -// Other bits (e.g. weight and depth) are computed on the frontend for windowing and display purposes.
20 -// Elements are updated on a push basis– meaning the backend pushes updates to the frontend when needed.
21 -export type Element = {
22 - id: number,
23 - parentID: number,
24 - children: Array<number>,
25 - type: ElementType,
26 - displayName: string | null,
27 - key: number | string | null,
28 -
29 - hocDisplayNames: null | Array<string>,
30 -
31 - // Should the elements children be visible in the tree?
32 - isCollapsed: boolean,
33 -
34 - // Owner (if available)
35 - ownerID: number,
36 -
37 - // How many levels deep within the tree is this element?
38 - // This determines how much indentation (left padding) should be used in the Elements tree.
39 - depth: number,
40 -
41 - // How many nodes (including itself) are below this Element within the tree.
42 - // This property is used to quickly determine the total number of Elements,
43 - // and the Element at any given index (for windowing purposes).
44 - weight: number,
45 -
46 - // This element is not in a StrictMode compliant subtree.
47 - // Only true for React versions supporting StrictMode.
48 - isStrictModeNonCompliant: boolean,
49 -};
50 -
51 -export type SerializedElement = {
52 - displayName: string | null,
53 - id: number,
54 - key: number | string | null,
55 - hocDisplayNames: Array<string> | null,
56 - type: ElementType,
57 -};
58 -
59 -export type OwnersList = {
60 - id: number,
61 - owners: Array<SerializedElement> | null,
62 -};
63 -
64 -export type InspectedElementResponseType =
65 - | 'error'
66 - | 'full-data'
67 - | 'hydrated-path'
68 - | 'no-change'
69 - | 'not-found';
70 -
71 -export type InspectedElement = {
72 - id: number,
73 -
74 - // Does the current renderer support editable hooks and function props?
75 - canEditHooks: boolean,
76 - canEditFunctionProps: boolean,
77 -
78 - // Does the current renderer support advanced editing interface?
79 - canEditHooksAndDeletePaths: boolean,
80 - canEditHooksAndRenamePaths: boolean,
81 - canEditFunctionPropsDeletePaths: boolean,
82 - canEditFunctionPropsRenamePaths: boolean,
83 -
84 - // Is this Error, and can its value be overridden now?
85 - isErrored: boolean,
86 - canToggleError: boolean,
87 - targetErrorBoundaryID: ?number,
88 -
89 - // Is this Suspense, and can its value be overridden now?
90 - canToggleSuspense: boolean,
91 -
92 - // Can view component source location.
93 - canViewSource: boolean,
94 -
95 - // Does the component have legacy context attached to it.
96 - hasLegacyContext: boolean,
97 -
98 - // Inspectable properties.
99 - context: Object | null,
100 - hooks: Object | null,
101 - props: Object | null,
102 - state: Object | null,
103 - key: number | string | null,
104 - errors: Array<[string, number]>,
105 - warnings: Array<[string, number]>,
106 -
107 - // List of owners
108 - owners: Array<SerializedElement> | null,
109 -
110 - // Location of component in source code.
111 - source: Source | null,
112 -
113 - type: ElementType,
114 -
115 - // Meta information about the root this element belongs to.
116 - rootType: string | null,
117 -
118 - // Meta information about the renderer that created this element.
119 - rendererPackageName: string | null,
120 - rendererVersion: string | null,
121 -
122 - // UI plugins/visualizations for the inspected element.
123 - plugins: Plugins,
124 -};
125 -
126 -// TODO: Add profiling type
127 -
128 -type Data =
129 - | string
130 - | Dehydrated
131 - | Unserializable
132 - | Array<Dehydrated>
133 - | Array<Unserializable>
134 - | {[string]: Data};
135 -
136 -export type DehydratedData = {
137 - cleaned: Array<Array<string | number>>,
138 - data: Data,
139 - unserializable: Array<Array<string | number>>,
140 -};
packages/react-devtools-shared/src/devtools/views/DevTools.js
+2 -2
@@ -46,11 +46,11 @@ import styles from './DevTools.css';
46
47 import './root.css';
48
49 -import type {InspectedElement} from 'react-devtools-shared/src/devtools/views/Components/types';
49 +import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
50 import type {FetchFileWithCaching} from './Components/FetchFileWithCachingContext';
51 import type {HookNamesModuleLoaderFunction} from 'react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext';
52 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
53 -import type {BrowserTheme} from 'react-devtools-shared/src/types';
53 +import type {BrowserTheme} from 'react-devtools-shared/src/frontend/types';
54
55 export type TabID = 'components' | 'profiler';
56
packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js
+2 -2
@@ -18,10 +18,10 @@ import {
18 TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS,
19 } from 'react-devtools-shared/src/constants';
20 import {utfDecodeString} from 'react-devtools-shared/src/utils';
21 -import {ElementTypeRoot} from 'react-devtools-shared/src/types';
21 +import {ElementTypeRoot} from 'react-devtools-shared/src/frontend/types';
22 import ProfilerStore from 'react-devtools-shared/src/devtools/ProfilerStore';
23
24 -import type {ElementType} from 'react-devtools-shared/src/types';
24 +import type {ElementType} from 'react-devtools-shared/src/frontend/types';
25 import type {
26 CommitTree,
27 CommitTreeNode,
packages/react-devtools-shared/src/devtools/views/Profiler/RankedChartBuilder.js
+1 -1
@@ -10,7 +10,7 @@
10 import {
11 ElementTypeForwardRef,
12 ElementTypeMemo,
13 -} from 'react-devtools-shared/src/types';
13 +} from 'react-devtools-shared/src/frontend/types';
14 import {formatDuration} from './utils';
15 import ProfilerStore from 'react-devtools-shared/src/devtools/ProfilerStore';
16
packages/react-devtools-shared/src/devtools/views/Profiler/Updaters.js
+2 -2
@@ -8,13 +8,13 @@
8 */
9
10 import type {CommitTree} from './types';
11 -import type {SerializedElement} from '../Components/types';
11 +import type {SerializedElement} from 'react-devtools-shared/src/frontend/types';
12
13 import * as React from 'react';
14 import {useContext} from 'react';
15 import {ProfilerContext} from './ProfilerContext';
16 import styles from './Updaters.css';
17 -import {ElementTypeRoot} from '../../../types';
17 +import {ElementTypeRoot} from '../../../frontend/types';
18
19 export type Props = {
20 commitTree: CommitTree,
packages/react-devtools-shared/src/devtools/views/Profiler/types.js
+4 -2
@@ -7,8 +7,10 @@
7 * @flow
8 */
9
10 -import type {ElementType} from 'react-devtools-shared/src/types';
11 -import type {SerializedElement} from '../Components/types';
10 +import type {
11 + ElementType,
12 + SerializedElement,
13 +} from 'react-devtools-shared/src/frontend/types';
14 import type {
15 TimelineData,
16 TimelineDataExport,
packages/react-devtools-shared/src/devtools/views/Settings/ComponentsSettings.js
+2 -2
@@ -40,7 +40,7 @@ import {
40 ElementTypeOtherOrUnknown,
41 ElementTypeProfiler,
42 ElementTypeSuspense,
43 -} from 'react-devtools-shared/src/types';
43 +} from 'react-devtools-shared/src/frontend/types';
44 import {getDefaultOpenInEditorURL} from 'react-devtools-shared/src/utils';
45
46 import styles from './SettingsShared.css';
@@ -52,7 +52,7 @@ import type {
52 ElementType,
53 ElementTypeComponentFilter,
54 RegExpComponentFilter,
55 -} from 'react-devtools-shared/src/types';
55 +} from 'react-devtools-shared/src/frontend/types';
56
57 const vscodeFilepath = 'vscode://file/{path}:{line}';
58
packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js
+1 -1
@@ -34,7 +34,7 @@ import {useLocalStorage} from '../hooks';
34 import {BridgeContext} from '../context';
35 import {logEvent} from 'react-devtools-shared/src/Logger';
36
37 -import type {BrowserTheme} from 'react-devtools-shared/src/types';
37 +import type {BrowserTheme} from 'react-devtools-shared/src/frontend/types';
38
39 export type DisplayDensity = 'comfortable' | 'compact';
40 export type Theme = 'auto' | 'light' | 'dark';
packages/react-devtools-shared/src/frontend/types.js renamed
+133
@@ -14,6 +14,12 @@
14 * Be mindful of backwards compatibility when making changes.
15 */
16
17 +import type {Source} from 'shared/ReactElementType';
18 +import type {
19 + Dehydrated,
20 + Unserializable,
21 +} from 'react-devtools-shared/src/hydration';
22 +
23 export type BrowserTheme = 'dark' | 'light';
24
25 export type Wall = {
@@ -112,3 +118,130 @@ export type Plugins = {
118 };
119
120 export const StrictMode = 1;
121 +
122 +// Each element on the frontend corresponds to a Fiber on the backend.
123 +// Some of its information (e.g. id, type, displayName) come from the backend.
124 +// Other bits (e.g. weight and depth) are computed on the frontend for windowing and display purposes.
125 +// Elements are updated on a push basis– meaning the backend pushes updates to the frontend when needed.
126 +export type Element = {
127 + id: number,
128 + parentID: number,
129 + children: Array<number>,
130 + type: ElementType,
131 + displayName: string | null,
132 + key: number | string | null,
133 +
134 + hocDisplayNames: null | Array<string>,
135 +
136 + // Should the elements children be visible in the tree?
137 + isCollapsed: boolean,
138 +
139 + // Owner (if available)
140 + ownerID: number,
141 +
142 + // How many levels deep within the tree is this element?
143 + // This determines how much indentation (left padding) should be used in the Elements tree.
144 + depth: number,
145 +
146 + // How many nodes (including itself) are below this Element within the tree.
147 + // This property is used to quickly determine the total number of Elements,
148 + // and the Element at any given index (for windowing purposes).
149 + weight: number,
150 +
151 + // This element is not in a StrictMode compliant subtree.
152 + // Only true for React versions supporting StrictMode.
153 + isStrictModeNonCompliant: boolean,
154 +};
155 +
156 +export type SerializedElement = {
157 + displayName: string | null,
158 + id: number,
159 + key: number | string | null,
160 + hocDisplayNames: Array<string> | null,
161 + type: ElementType,
162 +};
163 +
164 +export type OwnersList = {
165 + id: number,
166 + owners: Array<SerializedElement> | null,
167 +};
168 +
169 +export type InspectedElementResponseType =
170 + | 'error'
171 + | 'full-data'
172 + | 'hydrated-path'
173 + | 'no-change'
174 + | 'not-found';
175 +
176 +export type InspectedElementPath = Array<string | number>;
177 +
178 +export type InspectedElement = {
179 + id: number,
180 +
181 + // Does the current renderer support editable hooks and function props?
182 + canEditHooks: boolean,
183 + canEditFunctionProps: boolean,
184 +
185 + // Does the current renderer support advanced editing interface?
186 + canEditHooksAndDeletePaths: boolean,
187 + canEditHooksAndRenamePaths: boolean,
188 + canEditFunctionPropsDeletePaths: boolean,
189 + canEditFunctionPropsRenamePaths: boolean,
190 +
191 + // Is this Error, and can its value be overridden now?
192 + isErrored: boolean,
193 + canToggleError: boolean,
194 + targetErrorBoundaryID: ?number,
195 +
196 + // Is this Suspense, and can its value be overridden now?
197 + canToggleSuspense: boolean,
198 +
199 + // Can view component source location.
200 + canViewSource: boolean,
201 +
202 + // Does the component have legacy context attached to it.
203 + hasLegacyContext: boolean,
204 +
205 + // Inspectable properties.
206 + context: Object | null,
207 + hooks: Object | null,
208 + props: Object | null,
209 + state: Object | null,
210 + key: number | string | null,
211 + errors: Array<[string, number]>,
212 + warnings: Array<[string, number]>,
213 +
214 + // List of owners
215 + owners: Array<SerializedElement> | null,
216 +
217 + // Location of component in source code.
218 + source: Source | null,
219 +
220 + type: ElementType,
221 +
222 + // Meta information about the root this element belongs to.
223 + rootType: string | null,
224 +
225 + // Meta information about the renderer that created this element.
226 + rendererPackageName: string | null,
227 + rendererVersion: string | null,
228 +
229 + // UI plugins/visualizations for the inspected element.
230 + plugins: Plugins,
231 +};
232 +
233 +// TODO: Add profiling type
234 +
235 +type Data =
236 + | string
237 + | Dehydrated
238 + | Unserializable
239 + | Array<Dehydrated>
240 + | Array<Unserializable>
241 + | {[string]: Data};
242 +
243 +export type DehydratedData = {
244 + cleaned: Array<Array<string | number>>,
245 + data: Data,
246 + unserializable: Array<Array<string | number>>,
247 +};
packages/react-devtools-shared/src/hook.js
+1 -1
@@ -8,7 +8,7 @@
8 * @flow
9 */
10
11 -import type {BrowserTheme} from './types';
11 +import type {BrowserTheme} from './frontend/types';
12 import type {
13 DevToolsHook,
14 Handler,
packages/react-devtools-shared/src/hookNamesCache.js
+2 -2
@@ -11,11 +11,11 @@ import {__DEBUG__} from 'react-devtools-shared/src/constants';
11
12 import type {HooksTree} from 'react-debug-tools/src/ReactDebugHooks';
13 import type {Thenable, Wakeable} from 'shared/ReactTypes';
14 -import type {Element} from './devtools/views/Components/types';
14 import type {
15 + Element,
16 HookNames,
17 HookSourceLocationKey,
18 -} from 'react-devtools-shared/src/types';
18 +} from 'react-devtools-shared/src/frontend/types';
19 import type {HookSource} from 'react-debug-tools/src/ReactDebugHooks';
20 import type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext';
21 import {withCallbackPerfMeasurements} from './PerformanceLoggingUtils';
packages/react-devtools-shared/src/hooks/parseHookNames/index.js
+1 -1
@@ -9,7 +9,7 @@
9
10 import type {HookSourceAndMetadata} from './loadSourceAndMetadata';
11 import type {HooksNode, HooksTree} from 'react-debug-tools/src/ReactDebugHooks';
12 -import type {HookNames} from 'react-devtools-shared/src/types';
12 +import type {HookNames} from 'react-devtools-shared/src/frontend/types';
13 import type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext';
14
15 import {withAsyncPerfMeasurements} from 'react-devtools-shared/src/PerformanceLoggingUtils';
packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js
+4 -1
@@ -29,7 +29,10 @@ import type {
29 LocationKeyToHookSourceAndMetadata,
30 } from './loadSourceAndMetadata';
31 import type {HookSource} from 'react-debug-tools/src/ReactDebugHooks';
32 -import type {HookNames, LRUCache} from 'react-devtools-shared/src/types';
32 +import type {
33 + HookNames,
34 + LRUCache,
35 +} from 'react-devtools-shared/src/frontend/types';
36
37 type AST = mixed;
38
packages/react-devtools-shared/src/hydration.js
+7 -4
@@ -14,9 +14,12 @@ import {
14 getInObject,
15 formatDataForPreview,
16 setInObject,
17 -} from './utils';
17 +} from 'react-devtools-shared/src/utils';
18
19 -import type {DehydratedData} from './devtools/views/Components/types';
19 +import type {
20 + DehydratedData,
21 + InspectedElementPath,
22 +} from 'react-devtools-shared/src/frontend/types';
23
24 export const meta = {
25 inspectable: (Symbol('inspectable'): symbol),
@@ -123,7 +126,7 @@ export function dehydrate(
126 unserializable: Array<Array<string | number>>,
127 path: Array<string | number>,
128 isPathAllowed: (path: Array<string | number>) => boolean,
126 - level?: number = 0,
129 + level: number = 0,
130 ): $PropertyType<DehydratedData, 'data'> {
131 const type = getDataType(data);
132
@@ -365,7 +368,7 @@ export function dehydrate(
368 export function fillInPath(
369 object: Object,
370 data: DehydratedData,
368 - path: Array<string | number>,
371 + path: InspectedElementPath,
372 value: any,
373 ) {
374 const target = getInObject(object, path);
packages/react-devtools-shared/src/inspectedElementCache.js
+9 -11
@@ -21,7 +21,8 @@ import type {
21 Element,
22 InspectedElement as InspectedElementFrontend,
23 InspectedElementResponseType,
24 -} from 'react-devtools-shared/src/devtools/views/Components/types';
24 + InspectedElementPath,
25 +} from 'react-devtools-shared/src/frontend/types';
26
27 const Pending = 0;
28 const Resolved = 1;
@@ -83,7 +84,7 @@ function createCacheSeed(
84 */
85 export function inspectElement(
86 element: Element,
86 - path: Array<string | number> | null,
87 + path: InspectedElementPath | null,
88 store: Store,
89 bridge: FrontendBridge,
90 ): InspectedElementFrontend | null {
@@ -123,12 +124,7 @@ export function inspectElement(
124 return null;
125 }
126
126 - inspectElementMutableSource({
127 - bridge,
128 - element,
129 - path,
130 - rendererID: ((rendererID: any): number),
131 - }).then(
127 + inspectElementMutableSource(bridge, element, path, rendererID).then(
128 ([inspectedElement]: [
129 InspectedElementFrontend,
130 InspectedElementResponseType,
@@ -151,6 +147,7 @@ export function inspectElement(
147 wake();
148 },
149 );
150 +
151 map.set(element, record);
152 }
153
@@ -186,12 +183,13 @@ export function checkForUpdate({
183 return;
184 }
185
189 - return inspectElementMutableSource({
186 + return inspectElementMutableSource(
187 bridge,
188 element,
192 - path: null,
189 + null,
190 rendererID,
194 - }).then(
191 + true,
192 + ).then(
193 ([inspectedElement, responseType]: [
194 InspectedElementFrontend,
195 InspectedElementResponseType,
packages/react-devtools-shared/src/inspectedElementMutableSource.js
+20 -22
@@ -15,20 +15,21 @@ import {
15 } from 'react-devtools-shared/src/backendAPI';
16 import {fillInPath} from 'react-devtools-shared/src/hydration';
17
18 -import type {LRUCache} from 'react-devtools-shared/src/types';
18 +import type {LRUCache} from 'react-devtools-shared/src/frontend/types';
19 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
20 import type {
21 InspectElementError,
22 InspectElementFullData,
23 InspectElementHydratedPath,
24 } from 'react-devtools-shared/src/backend/types';
25 +import UserError from 'react-devtools-shared/src/errors/UserError';
26 +import UnknownHookError from 'react-devtools-shared/src/errors/UnknownHookError';
27 import type {
28 Element,
29 InspectedElement as InspectedElementFrontend,
30 InspectedElementResponseType,
29 -} from 'react-devtools-shared/src/devtools/views/Components/types';
30 -import UserError from 'react-devtools-shared/src/errors/UserError';
31 -import UnknownHookError from 'react-devtools-shared/src/errors/UnknownHookError';
31 + InspectedElementPath,
32 +} from 'react-devtools-shared/src/frontend/types';
33
34 // Maps element ID to inspected data.
35 // 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<number, InspectedElementFrontend> =
45 max: 25,
46 });
47
47 -type Path = Array<string | number>;
48 -
48 type InspectElementReturnType = [
49 InspectedElementFrontend,
50 InspectedElementResponseType,
51 ];
52
54 -export function inspectElement({
55 - bridge,
56 - element,
57 - path,
58 - rendererID,
59 -}: {
53 +export function inspectElement(
54 bridge: FrontendBridge,
55 element: Element,
62 - path: Path | null,
56 + path: InspectedElementPath | null,
57 rendererID: number,
64 -}): Promise<InspectElementReturnType> {
58 + shouldListenToPauseEvents: boolean = false,
59 +): Promise<InspectElementReturnType> {
60 const {id} = element;
61
62 // This could indicate that the DevTools UI has been closed and reopened.
@@ -69,13 +64,14 @@ export function inspectElement({
64 // In this case, we need to tell it to resend the full data.
65 const forceFullData = !inspectedElementCache.has(id);
66
72 - return inspectElementAPI({
67 + return inspectElementAPI(
68 bridge,
69 forceFullData,
70 id,
71 path,
72 rendererID,
78 - }).then((data: any) => {
73 + shouldListenToPauseEvents,
74 + ).then((data: any) => {
75 const {type} = data;
76
77 let inspectedElement;
@@ -141,12 +137,14 @@ export function inspectElement({
137 inspectedElement = {...inspectedElement};
138
139 // Merge hydrated data
144 - fillInPath(
145 - inspectedElement,
146 - value,
147 - ((path: any): Path),
148 - hydrateHelper(value, ((path: any): Path)),
149 - );
140 + if (path != null) {
141 + fillInPath(
142 + inspectedElement,
143 + value,
144 + path,
145 + hydrateHelper(value, path),
146 + );
147 + }
148
149 inspectedElementCache.set(id, inspectedElement);
150
packages/react-devtools-shared/src/utils.js
+11 -4
@@ -41,20 +41,27 @@ import {
41 LOCAL_STORAGE_SHOW_INLINE_WARNINGS_AND_ERRORS_KEY,
42 LOCAL_STORAGE_HIDE_CONSOLE_LOGS_IN_STRICT_MODE,
43 } from './constants';
44 -import {ComponentFilterElementType, ElementTypeHostComponent} from './types';
44 +import {
45 + ComponentFilterElementType,
46 + ElementTypeHostComponent,
47 +} from './frontend/types';
48 import {
49 ElementTypeRoot,
50 ElementTypeClass,
51 ElementTypeForwardRef,
52 ElementTypeFunction,
53 ElementTypeMemo,
51 -} from 'react-devtools-shared/src/types';
54 +} from 'react-devtools-shared/src/frontend/types';
55 import {localStorageGetItem, localStorageSetItem} from './storage';
56 import {meta} from './hydration';
57 import isArray from './isArray';
58
56 -import type {ComponentFilter, ElementType, BrowserTheme} from './types';
57 -import type {LRUCache} from 'react-devtools-shared/src/types';
59 +import type {
60 + ComponentFilter,
61 + ElementType,
62 + BrowserTheme,
63 +} from './frontend/types';
64 +import type {LRUCache} from 'react-devtools-shared/src/frontend/types';
65
66 // $FlowFixMe[method-unbinding]
67 const hasOwnProperty = Object.prototype.hasOwnProperty;