diff --git a/CHANGELOG.md b/CHANGELOG.md index e6eebcee0126..c5d74d8f2f07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -90,6 +90,7 @@ - `[*]` [**BREAKING**] Bundle all of Jest's modules into `index.js` ([#12348](https://github.com/jestjs/jest/pull/12348), [#14550](https://github.com/jestjs/jest/pull/14550) & [#14661](https://github.com/jestjs/jest/pull/14661)) - `[jest-haste-map]` Only spawn one process to check for `watchman` installation ([#14826](https://github.com/jestjs/jest/pull/14826)) +- `[jest-runner]` Better cleanup `source-map-support` after test to resolve (minor) memory leak ([#15233](https://github.com/jestjs/jest/pull/15233)) ### Chore & Maintenance diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index ed9a5ed951bd..5a20296dd21e 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -6,6 +6,7 @@ * */ +import {runInContext} from 'node:vm'; import chalk = require('chalk'); import * as fs from 'graceful-fs'; import sourcemapSupport = require('source-map-support'); @@ -208,6 +209,14 @@ async function runTestInternal( const tearDownEnv = async () => { if (!isTornDown) { runtime.teardown(); + + // source-map-support keeps memory leftovers in `Error.prepareStackTrace` + runInContext( + "Error.prepareStackTrace = () => '';", + environment.getVmContext()!, + ); + sourcemapSupport.resetRetrieveHandlers(); + await environment.teardown(); isTornDown = true; } @@ -312,8 +321,12 @@ async function runTestInternal( sendMessageToJest, ); } catch (error: any) { - // Access stack before uninstalling sourcemaps - error.stack; + // Access all stacks before uninstalling sourcemaps + let e = error; + while (typeof e === 'object' && e !== null && 'stack' in e) { + e.stack; + e = e?.cause; + } throw error; } finally { @@ -377,8 +390,6 @@ async function runTestInternal( }); } finally { await tearDownEnv(); - - sourcemapSupport.resetRetrieveHandlers(); } }