Skip to content

Commit e726663

Browse files
hoxyqAndyPengc12
authored andcommitted
fix[devtools/inspectElement]: dont pause initial inspectElement call when user switches tabs (facebook#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 facebook#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
1 parent af9b87b commit e726663

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+305
-282
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
} from './cachedSettings';
2323

2424
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';
2626
import type {DevToolsHook} from 'react-devtools-shared/src/backend/types';
2727
import type {ResolveNativeStyle} from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';
2828

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {
3333
import {localStorageSetItem} from 'react-devtools-shared/src/storage';
3434

3535
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';
3737

3838
installHook(window);
3939

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {installHook} from 'react-devtools-shared/src/hook';
88
import setupNativeStyleEditor from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';
99

1010
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';
1212

1313
function startActivation(contentWindow: any, bridge: BackendBridge) {
1414
const onSavedPreferences = (data: $FlowFixMe) => {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
getHideConsoleLogsInStrictMode,
1414
} from 'react-devtools-shared/src/utils';
1515

16-
import type {Wall} from 'react-devtools-shared/src/types';
16+
import type {Wall} from 'react-devtools-shared/src/frontend/types';
1717
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
1818
import type {Props} from 'react-devtools-shared/src/devtools/views/DevTools';
1919

packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,7 @@ describe('InspectedElementContext', () => {
3030
): Promise<Object> {
3131
const rendererID = ((store.getRendererIDForElement(id): any): number);
3232
const promise = backendAPI
33-
.inspectElement({
34-
bridge,
35-
id,
36-
path,
37-
rendererID,
38-
})
33+
.inspectElement(bridge, false, id, path, rendererID)
3934
.then(data =>
4035
backendAPI.convertInspectedElementBackendToFrontend(data.value),
4136
);

packages/react-devtools-shared/src/__tests__/ownersListContext-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*/
99

1010
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';
1212
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
1313
import type Store from 'react-devtools-shared/src/devtools/store';
1414

packages/react-devtools-shared/src/__tests__/profilerStore-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ describe('ProfilerStore', () => {
187187
utils.act(() => {
188188
const {
189189
ElementTypeHostComponent,
190-
} = require('react-devtools-shared/src/types');
190+
} = require('react-devtools-shared/src/frontend/types');
191191
store.componentFilters = [
192192
utils.createElementTypeFilter(ElementTypeHostComponent),
193193
];

packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ describe('Store component filters', () => {
3636
store.recordChangeDescriptions = true;
3737

3838
React = require('react');
39-
Types = require('react-devtools-shared/src/types');
39+
Types = require('react-devtools-shared/src/frontend/types');
4040
utils = require('./utils');
4141

4242
legacyRender = utils.legacyRender;

packages/react-devtools-shared/src/__tests__/utils.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import typeof ReactTestRenderer from 'react-test-renderer';
1212
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
1313
import type Store from 'react-devtools-shared/src/devtools/store';
1414
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';
1616

1717
export function act(
1818
callback: Function,
@@ -86,7 +86,7 @@ export function createDisplayNameFilter(
8686
source: string,
8787
isEnabled: boolean = true,
8888
) {
89-
const Types = require('react-devtools-shared/src/types');
89+
const Types = require('react-devtools-shared/src/frontend/types');
9090
let isValid = true;
9191
try {
9292
new RegExp(source); // eslint-disable-line no-new
@@ -102,7 +102,7 @@ export function createDisplayNameFilter(
102102
}
103103

104104
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');
106106
return {
107107
type: Types.ComponentFilterHOC,
108108
isEnabled,
@@ -114,7 +114,7 @@ export function createElementTypeFilter(
114114
elementType: ElementType,
115115
isEnabled: boolean = true,
116116
) {
117-
const Types = require('react-devtools-shared/src/types');
117+
const Types = require('react-devtools-shared/src/frontend/types');
118118
return {
119119
type: Types.ComponentFilterElementType,
120120
isEnabled,
@@ -126,7 +126,7 @@ export function createLocationFilter(
126126
source: string,
127127
isEnabled: boolean = true,
128128
) {
129-
const Types = require('react-devtools-shared/src/types');
129+
const Types = require('react-devtools-shared/src/frontend/types');
130130
let isValid = true;
131131
try {
132132
new RegExp(source); // eslint-disable-line no-new

packages/react-devtools-shared/src/backend/StyleX/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @flow
88
*/
99

10-
import type {StyleXPlugin} from 'react-devtools-shared/src/types';
10+
import type {StyleXPlugin} from 'react-devtools-shared/src/frontend/types';
1111
import isArray from 'react-devtools-shared/src/isArray';
1212

1313
const cachedStyleNameToValueMap: Map<string, string> = new Map();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import type {
4242
import type {
4343
ComponentFilter,
4444
BrowserTheme,
45-
} from 'react-devtools-shared/src/types';
45+
} from 'react-devtools-shared/src/frontend/types';
4646
import {isSynchronousXHRSupported} from './utils';
4747

4848
const debug = (methodName: string, ...args: Array<string>) => {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
ElementTypeRoot,
1414
ElementTypeHostComponent,
1515
ElementTypeOtherOrUnknown,
16-
} from 'react-devtools-shared/src/types';
16+
} from 'react-devtools-shared/src/frontend/types';
1717
import {getUID, utfEncodeString, printOperationsArray} from '../../utils';
1818
import {
1919
cleanForBridge,
@@ -50,7 +50,7 @@ import type {
5050
import type {
5151
ComponentFilter,
5252
ElementType,
53-
} from 'react-devtools-shared/src/types';
53+
} from 'react-devtools-shared/src/frontend/types';
5454
import type {InspectedElement, SerializedElement} from '../types';
5555

5656
export type InternalInstance = Object;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
ElementTypeSuspenseList,
2626
ElementTypeTracingMarker,
2727
StrictMode,
28-
} from 'react-devtools-shared/src/types';
28+
} from 'react-devtools-shared/src/frontend/types';
2929
import {
3030
deletePathInObject,
3131
getDisplayName,
@@ -121,7 +121,7 @@ import type {
121121
ComponentFilter,
122122
ElementType,
123123
Plugins,
124-
} from 'react-devtools-shared/src/types';
124+
} from 'react-devtools-shared/src/frontend/types';
125125

126126
type getDisplayNameForFiberType = (fiber: Fiber) => string | null;
127127
type getTypeSymbolType = (type: any) => symbol | number;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ import type {
2121
ComponentFilter,
2222
ElementType,
2323
Plugins,
24-
} from 'react-devtools-shared/src/types';
24+
} from 'react-devtools-shared/src/frontend/types';
2525
import type {
2626
ResolveNativeStyle,
2727
SetupNativeStyleEditor,
2828
} from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';
2929
import type {InitBackend} from 'react-devtools-shared/src/backend';
3030
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';
3232
import type {BackendBridge} from 'react-devtools-shared/src/bridge';
3333
import type Agent from './agent';
3434

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {compareVersions} from 'compare-versions';
1212
import {dehydrate} from '../hydration';
1313
import isArray from 'shared/isArray';
1414

15-
import type {DehydratedData} from 'react-devtools-shared/src/devtools/views/Components/types';
15+
import type {DehydratedData} from 'react-devtools-shared/src/frontend/types';
1616

1717
// TODO: update this to the first React version that has a corresponding DevTools backend
1818
const FIRST_DEVTOOLS_BACKEND_LOCKSTEP_VER = '999.9.9';

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

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ import type {
2424
import type {
2525
DehydratedData,
2626
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';
2829

2930
export function clearErrorsAndWarnings({
3031
bridge,
@@ -86,25 +87,21 @@ export function copyInspectedElementPath({
8687
});
8788
}
8889

89-
export function inspectElement({
90-
bridge,
91-
forceFullData,
92-
id,
93-
path,
94-
rendererID,
95-
}: {
90+
export function inspectElement(
9691
bridge: FrontendBridge,
9792
forceFullData: boolean,
9893
id: number,
99-
path: Array<string | number> | null,
94+
path: InspectedElementPath | null,
10095
rendererID: number,
101-
}): Promise<InspectedElementPayload> {
96+
shouldListenToPauseEvents: boolean = false,
97+
): Promise<InspectedElementPayload> {
10298
const requestID = requestCounter++;
10399
const promise = getPromiseForRequestID<InspectedElementPayload>(
104100
requestID,
105101
'inspectedElement',
106102
bridge,
107103
`Timed out while inspecting element ${id}.`,
104+
shouldListenToPauseEvents,
108105
);
109106

110107
bridge.send('inspectElement', {
@@ -148,16 +145,29 @@ function getPromiseForRequestID<T>(
148145
eventType: $Keys<BackendEvents>,
149146
bridge: FrontendBridge,
150147
timeoutMessage: string,
148+
shouldListenToPauseEvents: boolean = false,
151149
): Promise<T> {
152150
return new Promise((resolve, reject) => {
153151
const cleanup = () => {
154152
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+
}
157158

158159
clearTimeout(timeoutID);
159160
};
160161

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+
161171
const onDisconnect = () => {
162172
cleanup();
163173
reject(new ElementPollingCancellationError());
@@ -176,8 +186,11 @@ function getPromiseForRequestID<T>(
176186
};
177187

178188
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+
}
181194

182195
const timeoutID = setTimeout(onTimeout, TIMEOUT_DELAY);
183196
});
@@ -277,7 +290,7 @@ export function convertInspectedElementBackendToFrontend(
277290

278291
export function hydrateHelper(
279292
dehydratedData: DehydratedData | null,
280-
path?: Array<string | number>,
293+
path: ?InspectedElementPath,
281294
): Object | null {
282295
if (dehydratedData !== null) {
283296
const {cleaned, data, unserializable} = dehydratedData;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import EventEmitter from './events';
1111

12-
import type {ComponentFilter, Wall} from './types';
12+
import type {ComponentFilter, Wall} from './frontend/types';
1313
import type {
1414
InspectedElementPayload,
1515
OwnersList,

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS,
2222
TREE_OPERATION_UPDATE_TREE_BASE_DURATION,
2323
} from '../constants';
24-
import {ElementTypeRoot} from '../types';
24+
import {ElementTypeRoot} from '../frontend/types';
2525
import {
2626
getSavedComponentFilters,
2727
setSavedComponentFilters,
@@ -37,10 +37,13 @@ import {
3737
BRIDGE_PROTOCOL,
3838
currentBridgeProtocol,
3939
} 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';
4141

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';
4447
import type {
4548
FrontendBridge,
4649
BridgeProtocol,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import JSON5 from 'json5';
1111

12-
import type {Element} from './views/Components/types';
12+
import type {Element} from 'react-devtools-shared/src/frontend/types';
1313
import type {StateContext} from './views/Components/TreeContext';
1414
import type Store from './store';
1515

packages/react-devtools-shared/src/devtools/views/Components/Badge.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import * as React from 'react';
1111
import {Fragment} from 'react';
1212
import styles from './Badge.css';
1313

14-
import type {ElementType} from 'react-devtools-shared/src/types';
14+
import type {ElementType} from 'react-devtools-shared/src/frontend/types';
1515

1616
type Props = {
1717
className?: string,

packages/react-devtools-shared/src/devtools/views/Components/CannotSuspendWarningMessage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {StoreContext} from '../context';
1313
import {
1414
ComponentFilterElementType,
1515
ElementTypeSuspense,
16-
} from 'react-devtools-shared/src/types';
16+
} from 'react-devtools-shared/src/frontend/types';
1717

1818
export default function CannotSuspendWarningMessage(): React.Node {
1919
const store = useContext(StoreContext);

packages/react-devtools-shared/src/devtools/views/Components/Element.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {useSubscription} from '../hooks';
2020
import {logEvent} from 'react-devtools-shared/src/Logger';
2121

2222
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';
2424

2525
import styles from './Element.css';
2626
import Icon from '../Icon';

packages/react-devtools-shared/src/devtools/views/Components/HocBadges.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import * as React from 'react';
1111
import styles from './HocBadges.css';
1212

13-
import type {Element} from './types';
13+
import type {Element} from 'react-devtools-shared/src/frontend/types';
1414

1515
type Props = {
1616
element: Element,

packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Icon from '../Icon';
1717
import {ModalDialogContext} from '../ModalDialog';
1818
import ViewElementSourceContext from './ViewElementSourceContext';
1919
import Toggle from '../Toggle';
20-
import {ElementTypeSuspense} from 'react-devtools-shared/src/types';
20+
import {ElementTypeSuspense} from 'react-devtools-shared/src/frontend/types';
2121
import CannotSuspendWarningMessage from './CannotSuspendWarningMessage';
2222
import InspectedElementView from './InspectedElementView';
2323
import {InspectedElementContext} from './InspectedElementContext';
@@ -26,7 +26,7 @@ import {LOCAL_STORAGE_OPEN_IN_EDITOR_URL} from '../../../constants';
2626

2727
import styles from './InspectedElement.css';
2828

29-
import type {InspectedElement} from './types';
29+
import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
3030

3131
export type Props = {};
3232

0 commit comments

Comments
 (0)