mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-21 20:16:26 +08:00
fix(editor): ci stability (#14704)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Improved Electron shutdown, diagnostics and tab teardown for more reliable exits and forced cleanup on stubborn processes. * **Tests** * Added polling-based test helpers, stronger scroll/page readiness, timeout-tolerant page selection, and async cleanup/worker teardown; updated many tests to wait for UI/model updates and rendering frames. * **Bug Fixes** * Reduced flakiness by awaiting paragraph visibility, nested counts, selection/navigation stability, tab counts, post-action renders, and safer element interactions. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -391,21 +391,87 @@ export class WebContentViewsManager {
|
||||
|
||||
this.closedWorkbenches.push(targetWorkbench);
|
||||
|
||||
setTimeout(() => {
|
||||
globalThis.setTimeout(() => {
|
||||
const view = this.tabViewsMap.get(id);
|
||||
this.tabViewsMap.delete(id);
|
||||
|
||||
if (this.mainWindow && view) {
|
||||
this.mainWindow.contentView.removeChildView(view);
|
||||
view?.webContents.close({
|
||||
waitForBeforeUnload: true,
|
||||
});
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
void this.disposeTabView(id, view).catch(error => {
|
||||
logger.warn('failed to dispose tab view', {
|
||||
id,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
});
|
||||
}, 500); // delay a bit to get rid of the flicker
|
||||
|
||||
onTabClose(id);
|
||||
};
|
||||
|
||||
private readonly disposeTabView = async (
|
||||
id: string,
|
||||
view: WebContentsView
|
||||
) => {
|
||||
const waitForDestroyed = () =>
|
||||
new Promise<boolean>(resolve => {
|
||||
if (view.webContents.isDestroyed()) {
|
||||
resolve(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const timeout = globalThis.setTimeout(() => {
|
||||
resolve(false);
|
||||
}, 1_000);
|
||||
|
||||
view.webContents.once('destroyed', () => {
|
||||
globalThis.clearTimeout(timeout);
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
|
||||
if (this.mainWindow?.contentView.children.includes(view)) {
|
||||
this.mainWindow.contentView.removeChildView(view);
|
||||
}
|
||||
|
||||
if (view.webContents.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
view.webContents.close({
|
||||
waitForBeforeUnload: true,
|
||||
});
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
if (await waitForDestroyed()) return;
|
||||
|
||||
view.webContents.forcefullyCrashRenderer();
|
||||
|
||||
try {
|
||||
view.webContents.close({
|
||||
waitForBeforeUnload: false,
|
||||
});
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!view.webContents.isDestroyed() && !(await waitForDestroyed())) {
|
||||
logger.warn('tab webContents is still alive after force close', {
|
||||
id,
|
||||
webContentsId: view.webContents.id,
|
||||
url: view.webContents.getURL(),
|
||||
});
|
||||
}
|
||||
|
||||
if (this.mainWindow?.contentView.children.includes(view)) {
|
||||
this.mainWindow.contentView.removeChildView(view);
|
||||
}
|
||||
};
|
||||
|
||||
undoCloseTab = async () => {
|
||||
if (this.closedWorkbenches.length === 0) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user