From 4e216a3b98bd40dd7841ff417d64c6922569fc63 Mon Sep 17 00:00:00 2001 From: roboomp Date: Fri, 17 Jul 2026 20:10:01 +0000 Subject: [PATCH] fix(browser): canceled settled scroll timers - Replaced the losing Bun.sleep with an unrefed timeout cleared in a finally block. - Added regression coverage that verifies prompt wheel acknowledgements leave no timer behind. Fixes #5905 --- .../coding-agent/src/tools/browser/tab-worker.ts | 9 ++++++++- .../test/tools/browser-tab-timeouts.test.ts | 15 ++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/coding-agent/src/tools/browser/tab-worker.ts b/packages/coding-agent/src/tools/browser/tab-worker.ts index b7229bb57..4dc4a4f24 100644 --- a/packages/coding-agent/src/tools/browser/tab-worker.ts +++ b/packages/coding-agent/src/tools/browser/tab-worker.ts @@ -182,7 +182,14 @@ export async function dispatchScroll( dispatch: () => Promise, ackTimeoutMs = SCROLL_ACK_TIMEOUT_MS, ): Promise { - await Promise.race([dispatch(), Bun.sleep(ackTimeoutMs)]); + const deadline = Promise.withResolvers(); + const timer = setTimeout(() => deadline.resolve(), ackTimeoutMs); + timer.unref(); + try { + await Promise.race([dispatch(), deadline.promise]); + } finally { + clearTimeout(timer); + } } /** diff --git a/packages/coding-agent/test/tools/browser-tab-timeouts.test.ts b/packages/coding-agent/test/tools/browser-tab-timeouts.test.ts index 6f023146c..96d8b0e0f 100644 --- a/packages/coding-agent/test/tools/browser-tab-timeouts.test.ts +++ b/packages/coding-agent/test/tools/browser-tab-timeouts.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it } from "bun:test"; +import { describe, expect, it, vi } from "bun:test"; import { resolvePredicateTimeout } from "@oh-my-pi/pi-coding-agent/tools/browser/run-cancellation"; import { dispatchScroll, @@ -55,6 +55,19 @@ describe("browser scroll acknowledgement", () => { "target closed", ); }); + + it("cancels the acknowledgement deadline after a prompt dispatch", async () => { + vi.useFakeTimers(); + try { + const timerCount = vi.getTimerCount(); + + await dispatchScroll(() => Promise.resolve()); + + expect(vi.getTimerCount()).toBe(timerCount); + } finally { + vi.useRealTimers(); + } + }); }); describe("browser wait-helper timeout resolution", () => {