Skip to content

Commit 0545f36

Browse files
author
Brian Vaughn
authored
Added trace updates feature (DOM only) (#16989)
* Added trace updates feature (DOM only) * Updated DevTools CHANGELOG
1 parent e09097a commit 0545f36

File tree

19 files changed

+604
-149
lines changed

19 files changed

+604
-149
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
114114
}
115115

116116
if (bridge !== null) {
117-
bridge.emit('shutdown');
117+
bridge.shutdown();
118118
}
119119

120120
scheduleRetry();

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ function setup(hook) {
6767

6868
initBackend(hook, agent, window);
6969

70+
// Let the frontend know that the backend has attached listeners and is ready for messages.
71+
// This covers the case of of syncing saved values after reloading/navigating while DevTools remain open.
72+
bridge.send('extensionBackendInitialized');
73+
7074
// Setup React Native style editor if a renderer like react-native-web has injected it.
7175
if (hook.resolveRNStyle) {
7276
setupNativeStyleEditor(

packages/react-devtools-extensions/src/main.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
getBrowserName,
1010
getBrowserTheme,
1111
} from './utils';
12+
import {LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY} from 'react-devtools-shared/src/constants';
1213
import {
1314
getSavedComponentFilters,
1415
getAppendComponentStack,
@@ -125,10 +126,21 @@ function createPanelIfReactLoaded() {
125126
profilingData = store.profilerStore.profilingData;
126127
}
127128

129+
bridge.addListener('extensionBackendInitialized', () => {
130+
// Initialize the renderer's trace-updates setting.
131+
// This handles the case of navigating to a new page after the DevTools have already been shown.
132+
bridge.send(
133+
'setTraceUpdatesEnabled',
134+
localStorageGetItem(LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY) ===
135+
'true',
136+
);
137+
});
138+
128139
store = new Store(bridge, {
129140
isProfiling,
130141
supportsReloadAndProfile: isChrome,
131142
supportsProfiling,
143+
supportsTraceUpdates: true,
132144
});
133145
store.profilerStore.profilingData = profilingData;
134146

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export function initialize(
6464
},
6565
});
6666

67-
const store: Store = new Store(bridge);
67+
const store: Store = new Store(bridge, {supportsTraceUpdates: true});
6868

6969
const ForwardRef = forwardRef<Props, mixed>((props, ref) => (
7070
<DevTools ref={ref} bridge={bridge} store={store} {...props} />

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ import {
2121
sessionStorageSetItem,
2222
} from 'react-devtools-shared/src/storage';
2323
import setupHighlighter from './views/Highlighter';
24+
import {
25+
initialize as setupTraceUpdates,
26+
toggleEnabled as setTraceUpdatesEnabled,
27+
} from './views/TraceUpdates';
2428
import {patch as patchConsole, unpatch as unpatchConsole} from './console';
2529

2630
import type {BackendBridge} from 'react-devtools-shared/src/bridge';
@@ -87,13 +91,15 @@ export default class Agent extends EventEmitter<{|
8791
hideNativeHighlight: [],
8892
showNativeHighlight: [NativeType],
8993
shutdown: [],
94+
traceUpdates: [Set<NativeType>],
9095
|}> {
9196
_bridge: BackendBridge;
9297
_isProfiling: boolean = false;
9398
_recordChangeDescriptions: boolean = false;
9499
_rendererInterfaces: {[key: RendererID]: RendererInterface} = {};
95100
_persistedSelection: PersistedSelection | null = null;
96101
_persistedSelectionMatch: PathMatch | null = null;
102+
_traceUpdatesEnabled: boolean = false;
97103

98104
constructor(bridge: BackendBridge) {
99105
super();
@@ -131,6 +137,7 @@ export default class Agent extends EventEmitter<{|
131137
bridge.addListener('overrideState', this.overrideState);
132138
bridge.addListener('overrideSuspense', this.overrideSuspense);
133139
bridge.addListener('reloadAndProfile', this.reloadAndProfile);
140+
bridge.addListener('setTraceUpdatesEnabled', this.setTraceUpdatesEnabled);
134141
bridge.addListener('startProfiling', this.startProfiling);
135142
bridge.addListener('stopProfiling', this.stopProfiling);
136143
bridge.addListener(
@@ -159,6 +166,7 @@ export default class Agent extends EventEmitter<{|
159166
bridge.send('isBackendStorageAPISupported', isBackendStorageAPISupported);
160167

161168
setupHighlighter(bridge, this);
169+
setupTraceUpdates(this);
162170
}
163171

164172
get rendererInterfaces(): {[key: RendererID]: RendererInterface} {
@@ -340,6 +348,8 @@ export default class Agent extends EventEmitter<{|
340348
rendererInterface.startProfiling(this._recordChangeDescriptions);
341349
}
342350

351+
rendererInterface.setTraceUpdatesEnabled(this._traceUpdatesEnabled);
352+
343353
// When the renderer is attached, we need to tell it whether
344354
// we remember the previous selection that we'd like to restore.
345355
// It'll start tracking mounts for matches to the last selection path.
@@ -349,6 +359,19 @@ export default class Agent extends EventEmitter<{|
349359
}
350360
}
351361

362+
setTraceUpdatesEnabled = (traceUpdatesEnabled: boolean) => {
363+
this._traceUpdatesEnabled = traceUpdatesEnabled;
364+
365+
setTraceUpdatesEnabled(traceUpdatesEnabled);
366+
367+
for (let rendererID in this._rendererInterfaces) {
368+
const renderer = ((this._rendererInterfaces[
369+
(rendererID: any)
370+
]: any): RendererInterface);
371+
renderer.setTraceUpdatesEnabled(traceUpdatesEnabled);
372+
}
373+
};
374+
352375
syncSelectionFromNativeElementsPanel = () => {
353376
const target = window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0;
354377
if (target == null) {
@@ -416,6 +439,10 @@ export default class Agent extends EventEmitter<{|
416439
}
417440
};
418441

442+
onTraceUpdates = (nodes: Set<NativeType>) => {
443+
this.emit('traceUpdates', nodes);
444+
};
445+
419446
onHookOperations = (operations: Array<number>) => {
420447
if (__DEBUG__) {
421448
debug('onHookOperations', operations);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export function initBackend(
4444
}),
4545

4646
hook.sub('operations', agent.onHookOperations),
47+
hook.sub('traceUpdates', agent.onTraceUpdates),
4748

4849
// TODO Add additional subscriptions required for profiling mode
4950
];

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,10 @@ export function attach(
912912
// Not implemented.
913913
}
914914

915+
function setTraceUpdatesEnabled(enabled: boolean) {
916+
// Not implemented.
917+
}
918+
915919
function setTrackedPath(path: Array<PathFrame> | null) {
916920
// Not implemented.
917921
}
@@ -945,6 +949,7 @@ export function attach(
945949
setInHook,
946950
setInProps,
947951
setInState,
952+
setTraceUpdatesEnabled,
948953
setTrackedPath,
949954
startProfiling,
950955
stopProfiling,

0 commit comments

Comments
 (0)