Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxingbaoyu committed Oct 8, 2022
1 parent 1ba37a3 commit 835950b
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -14,6 +14,7 @@
- `[jest-reporters]` Revert: Transform file paths into hyperlinks ([#13399](https://github.com/facebook/jest/pull/13399))
- `[@jest/types]` Infer type of `each` table correctly when the table is a tuple or array ([#13381](https://github.com/facebook/jest/pull/13381))
- `[@jest/types]` Rework typings to allow the `*ReturnedWith` matchers to be called with no argument ([#13385](https://github.com/facebook/jest/pull/13385))
- `[jest-core]` Fix `collectHandles` false positives for some special objects such as `TLSWRAP`. ([#13414](https://github.com/facebook/jest/pull/13414))

### Chore & Maintenance

Expand Down
12 changes: 12 additions & 0 deletions packages/jest-core/src/__tests__/collectHandles.test.js
Expand Up @@ -10,6 +10,7 @@ import * as crypto from 'crypto';
import {promises as dns} from 'dns';
import http from 'http';
import {PerformanceObserver} from 'perf_hooks';
import {TLSSocket} from 'tls';
import zlib from 'zlib';
import collectHandles from '../collectHandles';

Expand Down Expand Up @@ -134,4 +135,15 @@ describe('collectHandles', () => {
expect.objectContaining({message: 'TCPSERVERWRAP'}),
);
});

it('should collect handles for some special objects such as `TLSWRAP`.', async () => {
const handleCollector = collectHandles();

const socket = new TLSSocket();
socket.destroy();

const openHandles = await handleCollector();

expect(openHandles).toHaveLength(0);
});
});
31 changes: 31 additions & 0 deletions packages/jest-core/src/collectHandles.ts
Expand Up @@ -8,6 +8,8 @@
/* eslint-disable local/ban-types-eventually */

import * as asyncHooks from 'async_hooks';
import * as v8 from 'v8';
import * as vm from 'vm';
import {promisify} from 'util';
import stripAnsi = require('strip-ansi');
import type {Config} from '@jest/types';
Expand Down Expand Up @@ -45,6 +47,27 @@ const hasWeakRef = typeof WeakRef === 'function';

const asyncSleep = promisify(setTimeout);

let gcFunc: typeof global.gc | undefined;
function runGC() {
if (!gcFunc) {
if (typeof global.gc === 'function') {
gcFunc = global.gc;
} else {
v8.setFlagsFromString('--expose-gc');
gcFunc = vm.runInNewContext('gc');
v8.setFlagsFromString('--no-expose-gc');
if (!gcFunc) {
console.warn(
'Cannot find `global.gc` function. Please run node with `--expose-gc`',
);
gcFunc = () => {};
}
}
}

gcFunc();
}

// Inspired by https://github.com/mafintosh/why-is-node-running/blob/master/index.js
// Extracted as we want to format the result ourselves
export default function collectHandles(): HandleCollectionResult {
Expand Down Expand Up @@ -125,6 +148,14 @@ export default function collectHandles(): HandleCollectionResult {
// callback, we will not yet have seen the resource be destroyed here.
await asyncSleep(100);

if (activeHandles.size !== 0) {
// For some special objects such as `TLSWRAP`.
// Ref: https://github.com/facebook/jest/issues/11665
runGC();

await asyncSleep(0);
}

hook.disable();

// Get errors for every async resource still referenced at this moment
Expand Down

0 comments on commit 835950b

Please sign in to comment.