fix electron v41 regression (webContents is null in destroyed hander) (#3057)

also adds a bit more defensiveness around using webContents.id.
This commit is contained in:
Mike Sawka 2026-03-13 13:00:17 -07:00 committed by GitHub
parent 1b708ea97f
commit 4034526919
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 14 additions and 4 deletions

View file

@ -209,7 +209,7 @@ export function initIpcHandlers() {
electron.ipcMain.on("webview-image-contextmenu", (event: electron.IpcMainEvent, payload: { src: string }) => {
const menu = new electron.Menu();
const win = getWaveWindowByWebContentsId(event.sender.hostWebContents.id);
const win = getWaveWindowByWebContentsId(event.sender.hostWebContents?.id);
if (win == null) {
return;
}
@ -353,6 +353,7 @@ export function initIpcHandlers() {
const png = PNG.sync.read(overlayBuffer);
const color = fac.prepareResult(fac.getColorFromArray4(png.data));
const ww = getWaveWindowByWebContentsId(event.sender.id);
if (ww == null) return;
ww.setTitleBarOverlay({
color: unamePlatform === "linux" ? color.rgba : "#00000000",
symbolColor: color.isDark ? "white" : "black",

View file

@ -109,6 +109,9 @@ function computeBgColor(fullConfig: FullConfigType): string {
const wcIdToWaveTabMap = new Map<number, WaveTabView>();
export function getWaveTabViewByWebContentsId(webContentsId: number): WaveTabView {
if (webContentsId == null) {
return null;
}
return wcIdToWaveTabMap.get(webContentsId);
}
@ -154,14 +157,15 @@ export class WaveTabView extends WebContentsView {
this.waveReadyPromise.then(() => {
this.isWaveReady = true;
});
wcIdToWaveTabMap.set(this.webContents.id, this);
const wcId = this.webContents.id;
wcIdToWaveTabMap.set(wcId, this);
if (isDevVite) {
this.webContents.loadURL(`${process.env.ELECTRON_RENDERER_URL}/index.html`);
} else {
this.webContents.loadFile(path.join(getElectronAppBasePath(), "frontend", "index.html"));
}
this.webContents.on("destroyed", () => {
wcIdToWaveTabMap.delete(this.webContents.id);
wcIdToWaveTabMap.delete(wcId);
removeWaveTabView(this.waveTabId);
this.isDestroyed = true;
});
@ -283,7 +287,6 @@ function checkAndEvictCache(): void {
// Otherwise, sort by lastUsedTs
return a.lastUsedTs - b.lastUsedTs;
});
const now = Date.now();
for (let i = 0; i < sorted.length - MaxCacheSize; i++) {
tryEvictEntry(sorted[i].waveTabId);
}
@ -313,6 +316,9 @@ export async function getOrCreateWebViewForTab(waveWindowId: string, tabId: stri
tabView.webContents.on("will-frame-navigate", shFrameNavHandler);
tabView.webContents.on("did-attach-webview", (event, wc) => {
wc.setWindowOpenHandler((details) => {
if (wc == null || wc.isDestroyed() || tabView.webContents == null || tabView.webContents.isDestroyed()) {
return { action: "deny" };
}
tabView.webContents.send("webview-new-window", wc.id, details);
return { action: "deny" };
});

View file

@ -674,6 +674,9 @@ export function getWaveWindowByTabId(tabId: string): WaveBrowserWindow {
}
export function getWaveWindowByWebContentsId(webContentsId: number): WaveBrowserWindow {
if (webContentsId == null) {
return null;
}
const tabView = getWaveTabViewByWebContentsId(webContentsId);
if (tabView == null) {
return null;