MCPcopy
hub / github.com/vitest-dev/vitest / withTimeout

Function withTimeout

packages/runner/src/context.ts:40–112  ·  view source on GitHub ↗
(
  fn: T,
  timeout: number,
  isHook = false,
  stackTraceError?: Error,
  onTimeout?: (args: T extends (...args: infer A) => any ? A : never, error: Error) => void,
)

Source from the content-addressed store, hash-verified

38}
39
40export function withTimeout<T extends (...args: any[]) => any>(
41 fn: T,
42 timeout: number,
43 isHook = false,
44 stackTraceError?: Error,
45 onTimeout?: (args: T extends (...args: infer A) => any ? A : never, error: Error) => void,
46): T {
47 if (timeout <= 0 || timeout === Number.POSITIVE_INFINITY) {
48 return fn
49 }
50
51 const { setTimeout, clearTimeout } = getSafeTimers()
52
53 // this function name is used to filter error in test/cli/test/fails.test.ts
54 return (function runWithTimeout(...args: T extends (...args: infer A) => any ? A : never) {
55 const startTime = now()
56 const runner = getRunner()
57 runner._currentTaskStartTime = startTime
58 runner._currentTaskTimeout = timeout
59 return new Promise((resolve_, reject_) => {
60 const timer = setTimeout(() => {
61 clearTimeout(timer)
62 rejectTimeoutError()
63 }, timeout)
64 // `unref` might not exist in browser
65 timer.unref?.()
66
67 function rejectTimeoutError() {
68 const error = makeTimeoutError(isHook, timeout, stackTraceError)
69 onTimeout?.(args, error)
70 reject_(error)
71 }
72
73 function resolve(result: unknown) {
74 runner._currentTaskStartTime = undefined
75 runner._currentTaskTimeout = undefined
76 clearTimeout(timer)
77 // if test/hook took too long in microtask, setTimeout won't be triggered,
78 // but we still need to fail the test, see
79 // https://github.com/vitest-dev/vitest/issues/2920
80 if (now() - startTime >= timeout) {
81 rejectTimeoutError()
82 return
83 }
84 resolve_(result)
85 }
86
87 function reject(error: unknown) {
88 runner._currentTaskStartTime = undefined
89 runner._currentTaskTimeout = undefined
90 clearTimeout(timer)
91 reject_(error)
92 }
93
94 // sync test/hook will be caught by try/catch
95 try {
96 const result = fn(...args) as PromiseLike<unknown>
97 // the result is a thenable, we don't wrap this in Promise.resolve

Callers 8

taskFunction · 0.90
beforeAllFunction · 0.90
afterAllFunction · 0.90
beforeEachFunction · 0.90
afterEachFunction · 0.90
hooks.tsFile · 0.90
createTestContextFunction · 0.85

Calls 6

getSafeTimersFunction · 0.90
getRunnerFunction · 0.90
rejectTimeoutErrorFunction · 0.85
resolveFunction · 0.70
rejectFunction · 0.70
fnFunction · 0.50

Tested by

no test coverage detected