fix: 串行化凭据所有权并响应桌面请求取消

This commit is contained in:
2026-09-08 13:16:11 +08:00
parent bd4b870078
commit a7c4261ccd
17 changed files with 714 additions and 115 deletions
@@ -0,0 +1,39 @@
import { hostInvoke } from './desktop'
export interface RequestProgress { issued: boolean; requestId?: string }
/** A reservation makes cancel-before-dispatch definitive even across IPC ordering. */
export function coreRequest<T>(args: Record<string, unknown>, signal: AbortSignal, timeoutMs: number, progress: RequestProgress): Promise<T> {
return new Promise((resolve, reject) => {
let settled = false
let requestId: string | undefined
const cancel = () => {
if (requestId) void hostInvoke('core_request_cancel', { requestId }).catch(() => {})
}
const abort = () => {
if (settled) return
settled = true
signal.removeEventListener('abort', abort)
cancel()
reject(new DOMException('Request aborted', 'AbortError'))
}
if (signal.aborted) { abort(); return }
signal.addEventListener('abort', abort, { once: true })
void (async () => {
try {
requestId = await hostInvoke<string>('core_request_prepare', { timeoutMs })
progress.requestId = requestId
if (settled || signal.aborted) { cancel(); return }
progress.issued = true
const result = await hostInvoke<T>('core_request', { request: { ...args, requestId } })
if (!settled) { settled = true; resolve(result) }
} catch (error) {
if (!settled) { settled = true; reject(error) }
} finally {
signal.removeEventListener('abort', abort)
// Also discard a reservation if dispatch failed before Rust claimed it.
cancel()
}
})()
})
}