Skip to content

Commit e813513

Browse files
committed
fix[react-devtools]: remove all listeners when Agent is shutdown
1 parent 1460d67 commit e813513

File tree

4 files changed

+31
-14
lines changed

4 files changed

+31
-14
lines changed

packages/react-devtools-extensions/src/contentScripts/backendManager.js

+25-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {COMPACT_VERSION_NAME} from 'react-devtools-extensions/src/utils';
1616
import {getIsReloadAndProfileSupported} from 'react-devtools-shared/src/utils';
1717

1818
let welcomeHasInitialized = false;
19+
const requiredBackends = new Set<string>();
1920

2021
function welcome(event: $FlowFixMe) {
2122
if (
@@ -49,8 +50,6 @@ function welcome(event: $FlowFixMe) {
4950
setup(window.__REACT_DEVTOOLS_GLOBAL_HOOK__);
5051
}
5152

52-
window.addEventListener('message', welcome);
53-
5453
function setup(hook: ?DevToolsHook) {
5554
// this should not happen, but Chrome can be weird sometimes
5655
if (hook == null) {
@@ -71,20 +70,27 @@ function setup(hook: ?DevToolsHook) {
7170
updateRequiredBackends();
7271

7372
// register renderers that inject themselves later.
74-
hook.sub('renderer', ({renderer}) => {
73+
const unsubscribeRendererListener = hook.sub('renderer', ({renderer}) => {
7574
registerRenderer(renderer, hook);
7675
updateRequiredBackends();
7776
});
7877

7978
// listen for backend installations.
80-
hook.sub('devtools-backend-installed', version => {
81-
activateBackend(version, hook);
82-
updateRequiredBackends();
79+
const unsubscribeBackendInstallationListener = hook.sub(
80+
'devtools-backend-installed',
81+
version => {
82+
activateBackend(version, hook);
83+
updateRequiredBackends();
84+
},
85+
);
86+
87+
const unsubscribeShutdownListener: () => void = hook.sub('shutdown', () => {
88+
unsubscribeRendererListener();
89+
unsubscribeBackendInstallationListener();
90+
unsubscribeShutdownListener();
8391
});
8492
}
8593

86-
const requiredBackends = new Set<string>();
87-
8894
function registerRenderer(renderer: ReactRenderer, hook: DevToolsHook) {
8995
let version = renderer.reconcilerVersion || renderer.version;
9096
if (!hasAssignedBackend(version)) {
@@ -139,6 +145,7 @@ function activateBackend(version: string, hook: DevToolsHook) {
139145
// If we received 'shutdown' from `agent`, we assume the `bridge` is already shutting down,
140146
// and that caused the 'shutdown' event on the `agent`, so we don't need to call `bridge.shutdown()` here.
141147
hook.emit('shutdown');
148+
delete window.__REACT_DEVTOOLS_BACKEND_MANAGER_INJECTED__;
142149
});
143150

144151
initBackend(hook, agent, window, getIsReloadAndProfileSupported());
@@ -178,3 +185,13 @@ function updateRequiredBackends() {
178185
'*',
179186
);
180187
}
188+
189+
/*
190+
* Make sure this is executed only once in case Frontend is reloaded multiple times while Backend is initializing
191+
* We can't use `reactDevToolsAgent` field on a global Hook object, because it only cleaned up after both Frontend and Backend initialized
192+
*/
193+
if (!window.__REACT_DEVTOOLS_BACKEND_MANAGER_INJECTED__) {
194+
window.__REACT_DEVTOOLS_BACKEND_MANAGER_INJECTED__ = true;
195+
196+
window.addEventListener('message', welcome);
197+
}

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

+3
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,9 @@ export default class Agent extends EventEmitter<{
754754
shutdown: () => void = () => {
755755
// Clean up the overlay if visible, and associated events.
756756
this.emit('shutdown');
757+
758+
this._bridge.removeAllListeners();
759+
this.removeAllListeners();
757760
};
758761

759762
startProfiling: (recordChangeDescriptions: boolean) => void =

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -3472,7 +3472,7 @@ export function attach(
34723472
}
34733473

34743474
function cleanup() {
3475-
// We don't patch any methods so there is no cleanup.
3475+
isProfiling = false;
34763476
}
34773477

34783478
function rootSupportsProfiling(root: any) {

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

+2-5
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,12 @@ export function initBackend(
8080
});
8181
hook.reactDevtoolsAgent = null;
8282
};
83-
agent.addListener('shutdown', onAgentShutdown);
84-
subs.push(() => {
85-
agent.removeListener('shutdown', onAgentShutdown);
86-
});
8783

84+
// Agent's event listeners are cleaned up by Agent in `shutdown` implementation.
85+
agent.addListener('shutdown', onAgentShutdown);
8886
agent.addListener('updateHookSettings', settings => {
8987
hook.settings = settings;
9088
});
91-
9289
agent.addListener('getHookSettings', () => {
9390
if (hook.settings != null) {
9491
agent.onHookSettings(hook.settings);

0 commit comments

Comments
 (0)