diff --git a/packages/playwright-core/src/server/progress.ts b/packages/playwright-core/src/server/progress.ts index b94ef285fdfb1..b9713428e58da 100644 --- a/packages/playwright-core/src/server/progress.ts +++ b/packages/playwright-core/src/server/progress.ts @@ -98,16 +98,26 @@ export class ProgressController { if (deadline) { const timeoutError = new TimeoutError(`Timeout ${timeout}ms exceeded.`); - timer = setTimeout(() => { - // TODO: migrate this to "progress.disableTimeout()". - if (this.metadata.pauseStartTime && !this.metadata.pauseEndTime) - return; + const remaining = deadline - monotonicTime(); + if (remaining <= 0) { + // Deadline already passed, fire immediately without scheduling a timer. if (this._state === 'running') { this._state = { error: timeoutError }; this._forceAbortPromise.reject(timeoutError); this._controller.abort(timeoutError); } - }, deadline - monotonicTime()); + } else { + timer = setTimeout(() => { + // TODO: migrate this to "progress.disableTimeout()". + if (this.metadata.pauseStartTime && !this.metadata.pauseEndTime) + return; + if (this._state === 'running') { + this._state = { error: timeoutError }; + this._forceAbortPromise.reject(timeoutError); + this._controller.abort(timeoutError); + } + }, remaining); + } } try { diff --git a/packages/playwright-core/src/utils/isomorphic/timeoutRunner.ts b/packages/playwright-core/src/utils/isomorphic/timeoutRunner.ts index 9a01d0f0796cc..2aec3834e43ed 100644 --- a/packages/playwright-core/src/utils/isomorphic/timeoutRunner.ts +++ b/packages/playwright-core/src/utils/isomorphic/timeoutRunner.ts @@ -29,9 +29,16 @@ export async function raceAgainstDeadline(cb: () => Promise, deadline: num return { result, timedOut: false }; }), new Promise<{ timedOut: true }>(resolve => { + if (!deadline) + return; const kMaxDeadline = 2147483647; // 2^31-1 - const timeout = (deadline || kMaxDeadline) - monotonicTime(); - timer = setTimeout(() => resolve({ timedOut: true }), timeout); + const timeout = deadline - monotonicTime(); + if (timeout <= 0) { + // Deadline already passed, resolve immediately without scheduling a timer. + resolve({ timedOut: true }); + return; + } + timer = setTimeout(() => resolve({ timedOut: true }), Math.min(timeout, kMaxDeadline)); }), ]).finally(() => { clearTimeout(timer);