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

Function detectAsyncLeaks

packages/vitest/src/runtime/detect-async-leaks.ts:21–100  ·  view source on GitHub ↗
(testFile: string, projectName: string)

Source from the content-addressed store, hash-verified

19])
20
21export function detectAsyncLeaks(testFile: string, projectName: string): () => Promise<AsyncLeak[]> {
22 const resources = new Map<number, PossibleLeak>()
23
24 const hook = createHook({
25 init(asyncId, type, triggerAsyncId, resource) {
26 if (IGNORED_TYPES.has(type)) {
27 return
28 }
29
30 let stack = ''
31 const limit = Error.stackTraceLimit
32
33 // VitestModuleEvaluator's async wrapper of node:vm causes out-of-bound stack traces, simply skip it.
34 // Crash fixed in https://github.com/vitejs/vite/pull/21585
35 try {
36 Error.stackTraceLimit = 100
37 stack = new Error('VITEST_DETECT_ASYNC_LEAKS').stack || ''
38 }
39 catch {
40 return
41 }
42 finally {
43 Error.stackTraceLimit = limit
44 }
45
46 if (!stack.includes(testFile)) {
47 const trigger = resources.get(triggerAsyncId)
48
49 if (!trigger) {
50 return
51 }
52
53 stack = trigger.stack
54 }
55
56 let isActive = isActiveDefault
57
58 if ('hasRef' in resource) {
59 const ref = new WeakRef(resource as { hasRef: () => boolean })
60
61 isActive = () => ref.deref()?.hasRef() ?? false
62 }
63
64 resources.set(asyncId, { type, stack, projectName, filename: testFile, isActive })
65 },
66 destroy(asyncId) {
67 if (resources.get(asyncId)?.type !== 'PROMISE') {
68 resources.delete(asyncId)
69 }
70 },
71 promiseResolve(asyncId) {
72 resources.delete(asyncId)
73 },
74 })
75
76 hook.enable()
77
78 return async function collect() {

Callers 2

runFunction · 0.90
runFunction · 0.90

Calls 2

clearMethod · 0.65
resolveMethod · 0.45

Tested by

no test coverage detected