From 88e29c728c203eab13b25a46ba9c05ed7443d8f3 Mon Sep 17 00:00:00 2001 From: Elarwei Date: Tue, 3 Feb 2026 01:12:48 +0800 Subject: [PATCH] refactor: use structural typing instead of instanceof for AbortSignal check Address P1 review feedback from Greptile: instanceof AbortSignal may be unreliable across different realms (VM, iframe, etc.) where the AbortSignal constructor may differ. Use structural typing (checking for aborted property and addEventListener method) for more robust cross-realm compatibility. --- src/agents/pi-tools.abort.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/agents/pi-tools.abort.ts b/src/agents/pi-tools.abort.ts index e12b38da4..90c8c7e4b 100644 --- a/src/agents/pi-tools.abort.ts +++ b/src/agents/pi-tools.abort.ts @@ -6,6 +6,19 @@ function throwAbortError(): never { throw err; } +/** + * Checks if an object is a valid AbortSignal using structural typing. + * This is more reliable than `instanceof` across different realms (VM, iframe, etc.) + * where the AbortSignal constructor may differ. + */ +function isAbortSignal(obj: unknown): obj is AbortSignal { + if (!obj || typeof obj !== "object") { + return false; + } + const signal = obj as Record; + return typeof signal.aborted === "boolean" && typeof signal.addEventListener === "function"; +} + function combineAbortSignals(a?: AbortSignal, b?: AbortSignal): AbortSignal | undefined { if (!a && !b) { return undefined; @@ -22,11 +35,7 @@ function combineAbortSignals(a?: AbortSignal, b?: AbortSignal): AbortSignal | un if (b?.aborted) { return b; } - if ( - typeof AbortSignal.any === "function" && - a instanceof AbortSignal && - b instanceof AbortSignal - ) { + if (typeof AbortSignal.any === "function" && isAbortSignal(a) && isAbortSignal(b)) { return AbortSignal.any([a, b]); }