mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
Prevent crashes when user spams Cmd:T (#1404)
When a user spams Cmd:T, a WaveTabView might be created but never end up getting mounted to the window, since another will come along before it can. In these cases, the WaveTabView is essentially in a bad state and attempting to switch to it will result in the window becoming unresponsive. While we could recover it by running waveInit again, it's easier to just dispose of it and treat it as an unloaded tab next time it gets switched to. This adds a timeout to each WaveTabView where once it gets assigned a tab ID, it has 1 second to respond "ready" or it will be destroyed. This should help prevent resource leakages for these dead views.
This commit is contained in:
parent
5744f4b06f
commit
3c69237d9b
@ -32,15 +32,18 @@ export function getWaveTabViewByWebContentsId(webContentsId: number): WaveTabVie
|
|||||||
export class WaveTabView extends WebContentsView {
|
export class WaveTabView extends WebContentsView {
|
||||||
isActiveTab: boolean;
|
isActiveTab: boolean;
|
||||||
waveWindowId: string; // set when showing in an active window
|
waveWindowId: string; // set when showing in an active window
|
||||||
waveTabId: string; // always set, WaveTabViews are unique per tab
|
private _waveTabId: string; // always set, WaveTabViews are unique per tab
|
||||||
lastUsedTs: number; // ts milliseconds
|
lastUsedTs: number; // ts milliseconds
|
||||||
createdTs: number; // ts milliseconds
|
createdTs: number; // ts milliseconds
|
||||||
initPromise: Promise<void>;
|
initPromise: Promise<void>;
|
||||||
|
initResolve: () => void;
|
||||||
savedInitOpts: WaveInitOpts;
|
savedInitOpts: WaveInitOpts;
|
||||||
waveReadyPromise: Promise<void>;
|
waveReadyPromise: Promise<void>;
|
||||||
initResolve: () => void;
|
|
||||||
waveReadyResolve: () => void;
|
waveReadyResolve: () => void;
|
||||||
|
|
||||||
|
// used to destroy the tab if it is not initialized within a certain time after being assigned a tabId
|
||||||
|
private destroyTabTimeout: NodeJS.Timeout;
|
||||||
|
|
||||||
constructor(fullConfig: FullConfigType) {
|
constructor(fullConfig: FullConfigType) {
|
||||||
console.log("createBareTabView");
|
console.log("createBareTabView");
|
||||||
super({
|
super({
|
||||||
@ -60,6 +63,13 @@ export class WaveTabView extends WebContentsView {
|
|||||||
this.waveReadyPromise = new Promise((resolve, _) => {
|
this.waveReadyPromise = new Promise((resolve, _) => {
|
||||||
this.waveReadyResolve = resolve;
|
this.waveReadyResolve = resolve;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Once the frontend is ready, we can cancel the destroyTabTimeout, assuming the tab hasn't been destroyed yet
|
||||||
|
// Only after a tab is ready will we add it to the wcvCache
|
||||||
|
this.waveReadyPromise.then(() => {
|
||||||
|
clearTimeout(this.destroyTabTimeout);
|
||||||
|
setWaveTabView(this.waveTabId, this);
|
||||||
|
});
|
||||||
wcIdToWaveTabMap.set(this.webContents.id, this);
|
wcIdToWaveTabMap.set(this.webContents.id, this);
|
||||||
if (isDevVite) {
|
if (isDevVite) {
|
||||||
this.webContents.loadURL(`${process.env.ELECTRON_RENDERER_URL}/index.html}`);
|
this.webContents.loadURL(`${process.env.ELECTRON_RENDERER_URL}/index.html}`);
|
||||||
@ -73,6 +83,17 @@ export class WaveTabView extends WebContentsView {
|
|||||||
this.setBackgroundColor(computeBgColor(fullConfig));
|
this.setBackgroundColor(computeBgColor(fullConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get waveTabId(): string {
|
||||||
|
return this._waveTabId;
|
||||||
|
}
|
||||||
|
|
||||||
|
set waveTabId(waveTabId: string) {
|
||||||
|
this._waveTabId = waveTabId;
|
||||||
|
this.destroyTabTimeout = setTimeout(() => {
|
||||||
|
this.destroy();
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
positionTabOnScreen(winBounds: Rectangle) {
|
positionTabOnScreen(winBounds: Rectangle) {
|
||||||
const curBounds = this.getBounds();
|
const curBounds = this.getBounds();
|
||||||
if (
|
if (
|
||||||
@ -102,7 +123,7 @@ export class WaveTabView extends WebContentsView {
|
|||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
console.log("destroy tab", this.waveTabId);
|
console.log("destroy tab", this.waveTabId);
|
||||||
this.webContents.close();
|
this.webContents?.close();
|
||||||
removeWaveTabView(this.waveTabId);
|
removeWaveTabView(this.waveTabId);
|
||||||
|
|
||||||
// TODO: circuitous
|
// TODO: circuitous
|
||||||
@ -171,7 +192,6 @@ export function getOrCreateWebViewForTab(fullConfig: FullConfigType, tabId: stri
|
|||||||
tabView = getSpareTab(fullConfig);
|
tabView = getSpareTab(fullConfig);
|
||||||
tabView.lastUsedTs = Date.now();
|
tabView.lastUsedTs = Date.now();
|
||||||
tabView.waveTabId = tabId;
|
tabView.waveTabId = tabId;
|
||||||
setWaveTabView(tabId, tabView);
|
|
||||||
tabView.webContents.on("will-navigate", shNavHandler);
|
tabView.webContents.on("will-navigate", shNavHandler);
|
||||||
tabView.webContents.on("will-frame-navigate", shFrameNavHandler);
|
tabView.webContents.on("will-frame-navigate", shFrameNavHandler);
|
||||||
tabView.webContents.on("did-attach-webview", (event, wc) => {
|
tabView.webContents.on("did-attach-webview", (event, wc) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user