diff --git a/CHANGELOG.md b/CHANGELOG.md index 6740ed4a563d..9fa1ba83f5c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ - `[jest-core]` Improve performance of SearchSource.findMatchingTests by 15% ([#8184](https://github.com/facebook/jest/pull/8184)) - `[jest-resolve]` Optimize internal cache lookup performance ([#8183](https://github.com/facebook/jest/pull/8183)) - `[jest-core]` Dramatically improve watch mode performance ([#8201](https://github.com/facebook/jest/pull/8201)) +- `[jest-console]` Fix memory leak by releasing console output reference when printed to stdout ([#8233](https://github.com/facebook/jest/pull/8233)) - `[jest-runtime]` Use `Map` instead of `Object` for module registry ([#8232](https://github.com/facebook/jest/pull/8232)) ## 24.5.0 diff --git a/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts b/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts index f3ba05efcddd..40f93dbf3c0b 100644 --- a/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts +++ b/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts @@ -196,7 +196,7 @@ export const runAndTransformResultsToJestFormat = async ({ dispatch({name: 'teardown'}); return { - console: null, + console: undefined, displayName: config.displayName, failureMessage, leaks: false, // That's legacy code, just adding it so Flow is happy. diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts index 0a4f125d705d..a8ed338b0b01 100644 --- a/packages/jest-console/src/BufferedConsole.ts +++ b/packages/jest-console/src/BufferedConsole.ts @@ -159,7 +159,7 @@ export default class BufferedConsole extends Console { this._log('warn', format(firstArg, ...rest)); } - getBuffer(): ConsoleBuffer { - return this._buffer; + getBuffer() { + return this._buffer.length ? this._buffer : undefined; } } diff --git a/packages/jest-console/src/CustomConsole.ts b/packages/jest-console/src/CustomConsole.ts index 758f3f53b7ba..13bcd0e7ec23 100644 --- a/packages/jest-console/src/CustomConsole.ts +++ b/packages/jest-console/src/CustomConsole.ts @@ -141,6 +141,6 @@ export default class CustomConsole extends Console { } getBuffer() { - return null; + return undefined; } } diff --git a/packages/jest-console/src/__tests__/bufferedConsole.test.ts b/packages/jest-console/src/__tests__/bufferedConsole.test.ts index dbd3ce39d2eb..ac6b06966b0c 100644 --- a/packages/jest-console/src/__tests__/bufferedConsole.test.ts +++ b/packages/jest-console/src/__tests__/bufferedConsole.test.ts @@ -10,11 +10,14 @@ import BufferedConsole from '../BufferedConsole'; describe('CustomConsole', () => { let _console: BufferedConsole; - const stdout = () => - _console - .getBuffer() - .map(log => log.message) - .join('\n'); + const stdout = () => { + const buffer = _console.getBuffer(); + if (!buffer) { + return ''; + } + + return buffer.map(log => log.message).join('\n'); + }; beforeEach(() => { _console = new BufferedConsole(() => null); diff --git a/packages/jest-core/src/ReporterDispatcher.ts b/packages/jest-core/src/ReporterDispatcher.ts index 00aa37f3f287..32102ed4751c 100644 --- a/packages/jest-core/src/ReporterDispatcher.ts +++ b/packages/jest-core/src/ReporterDispatcher.ts @@ -36,6 +36,9 @@ export default class ReporterDispatcher { reporter.onTestResult && (await reporter.onTestResult(test, testResult, results)); } + + // Release memory if unused later. + testResult.console = undefined; } async onTestStart(test: Test) { diff --git a/packages/jest-reporters/src/default_reporter.ts b/packages/jest-reporters/src/default_reporter.ts index 664e30d665d7..1946f9c2a9f4 100644 --- a/packages/jest-reporters/src/default_reporter.ts +++ b/packages/jest-reporters/src/default_reporter.ts @@ -172,8 +172,7 @@ export default class DefaultReporter extends BaseReporter { result: TestResult, ) { this.log(getResultHeader(result, this._globalConfig, config)); - const consoleBuffer = result.console; - if (consoleBuffer && consoleBuffer.length) { + if (result.console) { this.log( ' ' + TITLE_BULLET + @@ -181,7 +180,7 @@ export default class DefaultReporter extends BaseReporter { getConsoleOutput( config.cwd, !!this._globalConfig.verbose, - consoleBuffer, + result.console, ), ); } diff --git a/packages/jest-test-result/src/helpers.ts b/packages/jest-test-result/src/helpers.ts index a46f86959945..202cd2bf6e8c 100644 --- a/packages/jest-test-result/src/helpers.ts +++ b/packages/jest-test-result/src/helpers.ts @@ -46,7 +46,7 @@ export const buildFailureTestResult = ( testPath: Config.Path, err: SerializableError, ): TestResult => ({ - console: null, + console: undefined, displayName: '', failureMessage: null, leaks: false, diff --git a/packages/jest-test-result/src/types.ts b/packages/jest-test-result/src/types.ts index b24c117d0834..99c5503fb21b 100644 --- a/packages/jest-test-result/src/types.ts +++ b/packages/jest-test-result/src/types.ts @@ -101,7 +101,7 @@ export type Suite = { }; export type TestResult = { - console?: ConsoleBuffer | null; + console?: ConsoleBuffer; coverage?: CoverageMapData; displayName?: Config.DisplayName; failureMessage?: string | null;