mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
fix: stop Cockpit work before asynchronous UI teardown
This commit is contained in:
1 parent
947fc79182
commit
152d3e2352
11 files changed
+150
-15
No files matched your search
@@ -75,6 +75,33 @@ try {
|
||||
return unsubscribe?.();
|
||||
};
|
||||
}
|
||||
const cockpit = ui.cockpitView;
|
||||
const portal = ui._cockpitDisplayPortal;
|
||||
const cockpitListenerCount = cockpit._listenerRemovers.length;
|
||||
counts.cockpit = 0;
|
||||
cockpit._listenerRemovers = cockpit._listenerRemovers.map(
|
||||
(remove) => () => {
|
||||
counts.cockpit++;
|
||||
return remove();
|
||||
},
|
||||
);
|
||||
const portalHomes = portal.records.map((record) => ({
|
||||
group: record.group,
|
||||
home: record.anchor.parentNode,
|
||||
anchor: record.anchor,
|
||||
}));
|
||||
portal.setActive(true);
|
||||
let releaseRestoration;
|
||||
const restorationGate = new Promise((resolve) => {
|
||||
releaseRestoration = resolve;
|
||||
});
|
||||
const restoreForDisposal = ui._contextControls.restoreForDisposal.bind(
|
||||
ui._contextControls,
|
||||
);
|
||||
ui._contextControls.restoreForDisposal = async () => {
|
||||
await restorationGate;
|
||||
return restoreForDisposal();
|
||||
};
|
||||
const resizeHandler = ui._windowResizeHandler;
|
||||
const removeEventListener = window.removeEventListener;
|
||||
counts.resize = 0;
|
||||
@@ -83,7 +110,21 @@ try {
|
||||
return removeEventListener.call(this, type, callback, options);
|
||||
};
|
||||
try {
|
||||
await ui.dispose();
|
||||
const disposal = ui.dispose();
|
||||
const focusBefore = document.activeElement;
|
||||
const stoppedBeforeRestoration =
|
||||
cockpit.destroyed &&
|
||||
portal.stopped &&
|
||||
cockpit._listenerRemovers.length === 0 &&
|
||||
portal.frames.size === 0 &&
|
||||
cockpit.enter() === false &&
|
||||
cockpit.navigateContext(1) === false;
|
||||
await new Promise((resolve) =>
|
||||
requestAnimationFrame(() => requestAnimationFrame(resolve)),
|
||||
);
|
||||
const noDeferredFocus = document.activeElement === focusBefore;
|
||||
releaseRestoration();
|
||||
await disposal;
|
||||
const once = JSON.stringify(counts);
|
||||
await ui.dispose();
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
@@ -91,6 +132,23 @@ try {
|
||||
requestAnimationFrame(() => requestAnimationFrame(resolve)),
|
||||
);
|
||||
return {
|
||||
cockpitStoppedBeforeRestoration:
|
||||
stoppedBeforeRestoration && noDeferredFocus,
|
||||
cockpitReleased:
|
||||
cockpit.disposed &&
|
||||
cockpit.destroyed &&
|
||||
counts.cockpit === cockpitListenerCount &&
|
||||
cockpitListenerCount > 0 &&
|
||||
portal.destroyed &&
|
||||
portal.listeners.signal.aborted &&
|
||||
portal.frames.size === 0 &&
|
||||
ui._cockpitDisplayPortal === null &&
|
||||
portalHomes.length === 4 &&
|
||||
portalHomes.every(
|
||||
(record) =>
|
||||
record.group.parentNode === record.home &&
|
||||
!record.anchor.isConnected,
|
||||
),
|
||||
connected: Boolean(
|
||||
cctvUnsubscribe &&
|
||||
resizeHandler &&
|
||||
@@ -116,6 +174,7 @@ try {
|
||||
idempotent: once === JSON.stringify(counts),
|
||||
};
|
||||
} finally {
|
||||
releaseRestoration();
|
||||
window.removeEventListener = removeEventListener;
|
||||
}
|
||||
});
|
||||
@@ -143,6 +202,14 @@ try {
|
||||
'Radio, Location and CCTV controls are disposed with the UI',
|
||||
result.controlsReleased,
|
||||
);
|
||||
check(
|
||||
'Cockpit actions and queued portal work stop before layer restoration',
|
||||
result.cockpitStoppedBeforeRestoration,
|
||||
);
|
||||
check(
|
||||
'Cockpit cleanup releases listeners and returns all Display groups home',
|
||||
result.cockpitReleased,
|
||||
);
|
||||
check('repeated UI disposal is inert', result.idempotent);
|
||||
check(
|
||||
'disposal and subsequent resize produce no uncaught browser errors',
|
||||
|
||||
Reference in new issue
Block a user