Files
orca/docs/audits/working-directory-wait-retention/fix.patch
T

78 lines
2.6 KiB
Diff

diff --git a/src/main/providers/working-directory-validation.ts b/src/main/providers/working-directory-validation.ts
index 688cc85244..cf098cad2c 100644
--- a/src/main/providers/working-directory-validation.ts
+++ b/src/main/providers/working-directory-validation.ts
@@ -162,18 +162,7 @@ export function validateWorkingDirectoryAsync(
if (!signal) {
return validation
}
- const shared = validation
- // The shared probe outlives this caller; keep it from surfacing as unhandled.
- void shared.catch(() => {})
- return new Promise<void>((resolve, reject) => {
- const onAbort = (): void => reject(new WorkingDirectoryValidationAbortedError(cwd))
- if (signal.aborted) {
- onAbort()
- return
- }
- signal.addEventListener('abort', onAbort, { once: true })
- shared.then(resolve, reject).finally(() => signal.removeEventListener('abort', onAbort))
- })
+ return waitForWorkingDirectoryValidation(validation, cwd, signal)
}
function validateWorkingDirectoryUncached(cwd: string): Promise<void> {
@@ -202,3 +191,52 @@ async function probeWorkingDirectory(cwd: string): Promise<void> {
throw new Error(`Working directory "${cwd}" is not a directory.`)
}
}
+
+type WorkingDirectoryWaiterHolder = {
+ waiter: {
+ signal: AbortSignal
+ onAbort: () => void
+ resolve: () => void
+ reject: (error: unknown) => void
+ } | null
+}
+
+function takeWorkingDirectoryWaiter(
+ holder: WorkingDirectoryWaiterHolder
+): WorkingDirectoryWaiterHolder['waiter'] {
+ const waiter = holder.waiter
+ holder.waiter = null
+ waiter?.signal.removeEventListener('abort', waiter.onAbort)
+ return waiter
+}
+
+// Keep reaction order while an abandoned caller's signal and resolver become collectible.
+function observeWorkingDirectoryValidation(
+ promise: Promise<void>,
+ holder: WorkingDirectoryWaiterHolder
+): void {
+ void promise.then(
+ () => takeWorkingDirectoryWaiter(holder)?.resolve(),
+ (error: unknown) => takeWorkingDirectoryWaiter(holder)?.reject(error)
+ )
+}
+
+function waitForWorkingDirectoryValidation(
+ shared: Promise<void>,
+ cwd: string,
+ signal: AbortSignal
+): Promise<void> {
+ return new Promise<void>((resolve, reject) => {
+ const holder: WorkingDirectoryWaiterHolder = { waiter: null }
+ const onAbort = (): void => {
+ takeWorkingDirectoryWaiter(holder)?.reject(new WorkingDirectoryValidationAbortedError(cwd))
+ }
+ holder.waiter = { signal, onAbort, resolve, reject }
+ if (signal.aborted) {
+ onAbort()
+ return
+ }
+ signal.addEventListener('abort', onAbort, { once: true })
+ observeWorkingDirectoryValidation(shared, holder)
+ })
+}