diff --git a/src/cli/progress.test.ts b/src/cli/progress.test.ts index b729a88c669..82a356d2eed 100644 --- a/src/cli/progress.test.ts +++ b/src/cli/progress.test.ts @@ -1,4 +1,5 @@ import { describe, expect, it, vi } from "vitest"; +import { MAX_TIMER_TIMEOUT_MS } from "../shared/number-coercion.js"; import { createCliProgress, shouldUseInteractiveProgressSpinner } from "./progress.js"; function withStdinIsRaw(isRaw: boolean, run: () => T): T { @@ -130,4 +131,25 @@ describe("cli progress", () => { expect(firstWrites).toStrictEqual([]); }); + + it("clamps oversized delayed progress timers", () => { + const stream = { + isTTY: true, + write: vi.fn(), + } as unknown as NodeJS.WriteStream; + const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout"); + try { + const progress = createCliProgress({ + label: "Delayed", + stream, + fallback: "line", + delayMs: Number.MAX_SAFE_INTEGER, + }); + progress.done(); + + expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), MAX_TIMER_TIMEOUT_MS); + } finally { + setTimeoutSpy.mockRestore(); + } + }); }); diff --git a/src/cli/progress.ts b/src/cli/progress.ts index bc3389f5288..d7c74b98dfb 100644 --- a/src/cli/progress.ts +++ b/src/cli/progress.ts @@ -9,6 +9,7 @@ import { unregisterActiveProgressLine, } from "../../packages/terminal-core/src/progress-line.js"; import { theme } from "../../packages/terminal-core/src/theme.js"; +import { resolveTimerTimeoutMs } from "../shared/number-coercion.js"; const DEFAULT_DELAY_MS = 0; let activeProgress = 0; @@ -67,7 +68,7 @@ export function createCliProgress(options: ProgressOptions): ProgressReporter { return noopReporter; } - const delayMs = typeof options.delayMs === "number" ? options.delayMs : DEFAULT_DELAY_MS; + const delayMs = resolveTimerTimeoutMs(options.delayMs, DEFAULT_DELAY_MS, 0); const canOsc = isTty && supportsOscProgress(process.env, isTty); const stdinIsRaw = process.stdin.isRaw; const allowSpinner = shouldUseInteractiveProgressSpinner({