mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
[DevTools] Shut down standalone Bridge on socket close (#37076)
Ensures the standalone DevTools Bridge fully shuts down when its WebSocket closes, with re-entrancy protection. Adds tests confirming event-only shutdown leaves the Bridge active while socket closure shuts it down.
This commit is contained in:
+12
-8
@@ -132,6 +132,16 @@ export function connectToDevTools(options: ?ConnectOptions) {
|
||||
|
||||
let bridge: BackendBridge | null = null;
|
||||
|
||||
function shutdownBridge(): void {
|
||||
const bridgeToShutdown = bridge;
|
||||
if (bridgeToShutdown !== null) {
|
||||
// Clear the active reference before shutdown flushes its final message
|
||||
// through a potentially closed socket.
|
||||
bridge = null;
|
||||
bridgeToShutdown.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
const messageListeners = [];
|
||||
const uri = protocol + '://' + host + ':' + port + prefixedPath;
|
||||
|
||||
@@ -170,10 +180,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
|
||||
);
|
||||
}
|
||||
|
||||
if (bridge !== null) {
|
||||
bridge.shutdown();
|
||||
}
|
||||
|
||||
shutdownBridge();
|
||||
scheduleRetry();
|
||||
}
|
||||
},
|
||||
@@ -273,10 +280,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
|
||||
debug('WebSocket.onclose');
|
||||
}
|
||||
|
||||
if (bridge !== null) {
|
||||
bridge.emit('shutdown');
|
||||
}
|
||||
|
||||
shutdownBridge();
|
||||
scheduleRetry();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
describe('connectToDevTools', () => {
|
||||
let connectToDevTools;
|
||||
let hook;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
delete window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
|
||||
const backend = require('react-devtools-core/src/backend');
|
||||
backend.initialize();
|
||||
connectToDevTools = backend.connectToDevTools;
|
||||
hook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllTimers();
|
||||
delete window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
});
|
||||
|
||||
function createWebSocket(): WebSocket {
|
||||
return {
|
||||
CLOSED: 3,
|
||||
OPEN: 1,
|
||||
readyState: 1,
|
||||
send: jest.fn(),
|
||||
} as any as WebSocket;
|
||||
}
|
||||
|
||||
it('shuts down cleanly when the WebSocket closes', () => {
|
||||
const websocket = createWebSocket();
|
||||
const onShutdown = jest.fn();
|
||||
const unsubscribe = hook.sub('shutdown', onShutdown);
|
||||
|
||||
try {
|
||||
connectToDevTools({websocket});
|
||||
websocket.onopen();
|
||||
websocket.readyState = websocket.CLOSED;
|
||||
websocket.onclose();
|
||||
jest.runAllTimers();
|
||||
|
||||
expect(onShutdown).toHaveBeenCalledTimes(1);
|
||||
expect(global.consoleWarnMock).not.toHaveBeenCalledWith(
|
||||
'Bridge was already shutdown.',
|
||||
);
|
||||
} finally {
|
||||
unsubscribe();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user