mirror of
https://github.com/4ian/GDevelop.git
synced 2026-10-12 02:01:17 +00:00
Make disposed debugger clients inert
Detach the WebSocket handlers and cancel the pending hard reload before closing, drop messages sent after dispose, and release the debugger client and in-game editor references when the game is disposed.
This commit is contained in:
@@ -614,6 +614,10 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the listeners and the connection used by the client, which must
|
||||
* not be used anymore afterwards: messages are then silently dropped.
|
||||
*/
|
||||
abstract dispose(): void;
|
||||
|
||||
/**
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace gdjs {
|
||||
// the WebSocket connection between the editor and the game is closed. When we are in in-game edition,
|
||||
// we can't afford to lose the connection because it means the editor is unusable.
|
||||
// In this case, we hard reload the game to re-establish a new connection.
|
||||
setTimeout(() => {
|
||||
that._hardReloadTimeoutId = setTimeout(() => {
|
||||
logger.info(
|
||||
'Debugger connection closed while in in-game edition - this is suspicious so hard reloading to re-establish a new connection.'
|
||||
);
|
||||
@@ -86,14 +86,33 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
private hasLoggedError: boolean = false;
|
||||
private _wasDisposed: boolean = false;
|
||||
/** The hard reload scheduled when the connection is lost in in-game edition. */
|
||||
private _hardReloadTimeoutId: NodeJS.Timeout | null = null;
|
||||
|
||||
dispose(): void {
|
||||
this._wasDisposed = true;
|
||||
if (this._hardReloadTimeoutId !== null) {
|
||||
clearTimeout(this._hardReloadTimeoutId);
|
||||
this._hardReloadTimeoutId = null;
|
||||
}
|
||||
if (this._ws) {
|
||||
// Detach the handlers before closing: `close()` fires `onclose` (and
|
||||
// `onerror` if the connection was still being established), which must
|
||||
// not trigger the hard reload done when the connection is lost in
|
||||
// in-game edition.
|
||||
this._ws.onopen = null;
|
||||
this._ws.onclose = null;
|
||||
this._ws.onerror = null;
|
||||
this._ws.onmessage = null;
|
||||
this._ws.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected _sendMessage(message: string) {
|
||||
// Once disposed, messages are silently dropped: the connection is closed
|
||||
// and logging a warning would call this method again.
|
||||
if (this._wasDisposed) return;
|
||||
if (!this._ws) {
|
||||
// The error can be logged only once, since logger.warn will call this function again,
|
||||
// leading to an endless recursive call if we do not call it only once.
|
||||
|
||||
@@ -31,8 +31,10 @@ namespace gdjs {
|
||||
window.addEventListener('message', this._onWindowMessage);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
dispose(): void {
|
||||
window.removeEventListener('message', this._onWindowMessage);
|
||||
// Drop the opener so that no message is sent anymore once disposed.
|
||||
this._opener = null;
|
||||
}
|
||||
|
||||
protected _sendMessage(message: string) {
|
||||
|
||||
@@ -1448,6 +1448,10 @@ namespace gdjs {
|
||||
this._sceneStack.dispose();
|
||||
this._renderer.dispose(removeCanvas);
|
||||
this._resourcesLoader.dispose();
|
||||
// Drop the disposed helpers so that any late call (uncaught exception
|
||||
// reporting, status updates...) is a no-op.
|
||||
this._inGameEditor = null;
|
||||
this._debuggerClient = null;
|
||||
|
||||
this._wasDisposed = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user