fix: 防御性检查补全

- openFileInTab 增加 isDestroyed() 前置检查
- open-file handler 增加 isDestroyed() 检查
- window:forceClose 增加 isDestroyed() 检查
- close handler 使用 isClosing 防止重入
- cancelClose 重置 isClosing 允许再次关闭
This commit is contained in:
thzxx
2026-05-18 15:24:01 +08:00
parent 5428beb6db
commit 65451b938c
+12 -5
View File
@@ -7,6 +7,7 @@ let activeFilePath = null; // Currently active tab's file path
let pendingFilePath = null; let pendingFilePath = null;
let fileWatcher = null; let fileWatcher = null;
let closeTimeout = null; let closeTimeout = null;
let isClosing = false; // Prevent re-entrant close
// ===== Single Instance Lock ===== // ===== Single Instance Lock =====
const gotTheLock = app.requestSingleInstanceLock(); const gotTheLock = app.requestSingleInstanceLock();
@@ -17,7 +18,7 @@ if (!gotTheLock) {
app.on('second-instance', (event, commandLine, workingDirectory) => { app.on('second-instance', (event, commandLine, workingDirectory) => {
// A second instance was launched (e.g. double-clicking a .md file) // A second instance was launched (e.g. double-clicking a .md file)
// Focus the existing window and open the file in it // Focus the existing window and open the file in it
if (mainWindow) { if (mainWindow && !mainWindow.isDestroyed()) {
if (mainWindow.isMinimized()) mainWindow.restore(); if (mainWindow.isMinimized()) mainWindow.restore();
mainWindow.focus(); mainWindow.focus();
@@ -76,6 +77,8 @@ function createWindow() {
// Unsaved changes warning on close // Unsaved changes warning on close
mainWindow.on('close', (e) => { mainWindow.on('close', (e) => {
if (isClosing) return; // Prevent re-entrant close
isClosing = true;
e.preventDefault(); e.preventDefault();
try { try {
mainWindow.webContents.send('window:confirmClose'); mainWindow.webContents.send('window:confirmClose');
@@ -140,6 +143,7 @@ function readFileContent(filePath) {
// Open file in a new tab (renderer manages tabs) // Open file in a new tab (renderer manages tabs)
function openFileInTab(filePath) { function openFileInTab(filePath) {
if (!mainWindow || mainWindow.isDestroyed()) return;
try { try {
const content = readFileContent(filePath); const content = readFileContent(filePath);
activeFilePath = filePath; activeFilePath = filePath;
@@ -276,8 +280,10 @@ ipcMain.handle('window:forceClose', () => {
closeTimeout = null; closeTimeout = null;
} }
stopWatching(); stopWatching();
mainWindow.removeAllListeners('close'); if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.close(); mainWindow.removeAllListeners('close');
mainWindow.close();
}
}); });
ipcMain.handle('window:cancelClose', () => { ipcMain.handle('window:cancelClose', () => {
@@ -285,6 +291,7 @@ ipcMain.handle('window:cancelClose', () => {
clearTimeout(closeTimeout); clearTimeout(closeTimeout);
closeTimeout = null; closeTimeout = null;
} }
isClosing = false; // Reset so close can be triggered again
}); });
// Command line file (first instance) // Command line file (first instance)
@@ -296,9 +303,9 @@ function getCommandLineFile() {
app.whenReady().then(() => { app.whenReady().then(() => {
app.on('open-file', (event, filePath) => { app.on('open-file', (event, filePath) => {
event.preventDefault(); event.preventDefault();
if (mainWindow && mainWindow.webContents.isLoading()) { if (mainWindow && !mainWindow.isDestroyed() && mainWindow.webContents.isLoading()) {
pendingFilePath = filePath; pendingFilePath = filePath;
} else if (mainWindow) { } else if (mainWindow && !mainWindow.isDestroyed()) {
openFileInTab(filePath); openFileInTab(filePath);
} else { } else {
pendingFilePath = filePath; pendingFilePath = filePath;