|
8 | 8 | /* eslint-disable local/ban-types-eventually */ |
9 | 9 |
|
10 | 10 | import * as asyncHooks from 'async_hooks'; |
| 11 | +import * as v8 from 'v8'; |
| 12 | +import * as vm from 'vm'; |
11 | 13 | import {promisify} from 'util'; |
12 | 14 | import stripAnsi = require('strip-ansi'); |
13 | 15 | import type {Config} from '@jest/types'; |
@@ -45,6 +47,27 @@ const hasWeakRef = typeof WeakRef === 'function'; |
45 | 47 |
|
46 | 48 | const asyncSleep = promisify(setTimeout); |
47 | 49 |
|
| 50 | +let gcFunc: typeof global.gc | undefined; |
| 51 | +function runGC() { |
| 52 | + if (!gcFunc) { |
| 53 | + if (typeof global.gc === 'function') { |
| 54 | + gcFunc = global.gc; |
| 55 | + } else { |
| 56 | + v8.setFlagsFromString('--expose-gc'); |
| 57 | + gcFunc = vm.runInNewContext('gc'); |
| 58 | + v8.setFlagsFromString('--no-expose-gc'); |
| 59 | + if (!gcFunc) { |
| 60 | + console.warn( |
| 61 | + 'Cannot find `global.gc` function. Please run node with `--expose-gc`', |
| 62 | + ); |
| 63 | + gcFunc = () => {}; |
| 64 | + } |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + gcFunc(); |
| 69 | +} |
| 70 | + |
48 | 71 | // Inspired by https://github.com/mafintosh/why-is-node-running/blob/master/index.js |
49 | 72 | // Extracted as we want to format the result ourselves |
50 | 73 | export default function collectHandles(): HandleCollectionResult { |
@@ -125,6 +148,14 @@ export default function collectHandles(): HandleCollectionResult { |
125 | 148 | // callback, we will not yet have seen the resource be destroyed here. |
126 | 149 | await asyncSleep(100); |
127 | 150 |
|
| 151 | + if (activeHandles.size !== 0) { |
| 152 | + // For some special objects such as `TLSWRAP`. |
| 153 | + // Ref: https://github.com/facebook/jest/issues/11665 |
| 154 | + runGC(); |
| 155 | + |
| 156 | + await asyncSleep(0); |
| 157 | + } |
| 158 | + |
128 | 159 | hook.disable(); |
129 | 160 |
|
130 | 161 | // Get errors for every async resource still referenced at this moment |
|
0 commit comments