From 7bee921b70879576c17dc32fc49f04e9d280eb21 Mon Sep 17 00:00:00 2001 From: levk Date: Sun, 14 Apr 2019 22:01:59 +0300 Subject: [PATCH] adds freezeCoreModules configuration option to mitigate memory leaks resolves #6399, resolves #6814 --- CHANGELOG.md | 1 + TestUtils.ts | 3 ++ docs/Configuration.md | 16 +++++++ .../__snapshots__/showConfig.test.ts.snap | 5 +++ .../__tests__/__snapshots__/init.test.js.snap | 8 ++++ packages/jest-config/src/Defaults.ts | 2 + packages/jest-config/src/Descriptions.ts | 4 ++ packages/jest-config/src/ValidConfig.ts | 2 + packages/jest-config/src/index.ts | 3 ++ packages/jest-config/src/normalize.ts | 2 + .../log_debug_messages.test.ts.snap | 5 +++ .../__tests__/runtime_require_module.test.js | 27 +++++++++++ packages/jest-runtime/src/index.ts | 45 ++++++++++++++++++- .../script_transformer.test.js.snap | 9 +++- packages/jest-types/src/Config.ts | 7 +++ 15 files changed, 135 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfaeb5f5fb33..c908134351a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- `[jest-config]` Add `freezeCoreModules` configuration option to mitigate memory leaks described in the following issues: [#6399](https://github.com/facebook/jest/issues/6399), [#6814](https://github.com/facebook/jest/issues/6814) ([#8331](https://github.com/facebook/jest/pull/8331)) - `[expect]` Improve report when matcher fails, part 15 ([#8281](https://github.com/facebook/jest/pull/8281)) - `[jest-cli]` Update `--forceExit` and "did not exit for one second" message colors ([#8329](https://github.com/facebook/jest/pull/8329)) - `[expect]` Improve report when matcher fails, part 16 ([#8306](https://github.com/facebook/jest/pull/8306)) diff --git a/TestUtils.ts b/TestUtils.ts index ba80887bda29..0d264c9e2c8e 100644 --- a/TestUtils.ts +++ b/TestUtils.ts @@ -79,6 +79,8 @@ const DEFAULT_PROJECT_CONFIG: Config.ProjectConfig = { extraGlobals: [], filter: null, forceCoverageMatch: [], + freezeCoreModules: false, + freezeCoreModulesWhitelist: ['crypto'], globalSetup: null, globalTeardown: null, globals: {}, @@ -118,6 +120,7 @@ const DEFAULT_PROJECT_CONFIG: Config.ProjectConfig = { transform: [], transformIgnorePatterns: [], unmockedModulePathPatterns: null, + verbose: false, watchPathIgnorePatterns: [], }; diff --git a/docs/Configuration.md b/docs/Configuration.md index 01cd50f533e9..4960cdd91d86 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -369,6 +369,22 @@ You can collect coverage from those files with setting `forceCoverageMatch`. } ``` +### `freezeCoreModules` [boolean] + +Default: `false` + +Prevents overriding node's core module methods so to prevent memory leaks. + +Attempt to override such a property will fail silently. + +Running with [`verbose`](#verbose-boolean) flag will enable informative print outs. + +### `freezeCoreModulesWhitelist` [Array] + +Default: `['crypto']` + +Array of node core modules which will not be frozen. + ### `globals` [object] Default: `{}` diff --git a/e2e/__tests__/__snapshots__/showConfig.test.ts.snap b/e2e/__tests__/__snapshots__/showConfig.test.ts.snap index dbafaaad3ca1..2e31f213b225 100644 --- a/e2e/__tests__/__snapshots__/showConfig.test.ts.snap +++ b/e2e/__tests__/__snapshots__/showConfig.test.ts.snap @@ -19,6 +19,10 @@ exports[`--showConfig outputs config info and exits 1`] = ` "errorOnDeprecated": false, "filter": null, "forceCoverageMatch": [], + "freezeCoreModules": false, + "freezeCoreModulesWhitelist": [ + "crypto" + ], "globalSetup": null, "globalTeardown": null, "globals": {}, @@ -78,6 +82,7 @@ exports[`--showConfig outputs config info and exits 1`] = ` "transformIgnorePatterns": [ "/node_modules/" ], + "verbose": null, "watchPathIgnorePatterns": [] } ], diff --git a/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap b/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap index 9c645a4a956a..a674ee58eb61 100644 --- a/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap +++ b/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap @@ -72,6 +72,14 @@ module.exports = { // Force coverage collection from ignored files using an array of glob patterns // forceCoverageMatch: [], + // Prevents overriding node's core module methods so to prevent memory leaks + // freezeCoreModules: false, + + // Array of node core modules which will not be frozen + // freezeCoreModulesWhitelist: [ + // \\"crypto\\" + // ], + // A path to a module which exports an async function that is triggered once before all test suites // globalSetup: null, diff --git a/packages/jest-config/src/Defaults.ts b/packages/jest-config/src/Defaults.ts index 4058e7a59f18..d754ed93c046 100644 --- a/packages/jest-config/src/Defaults.ts +++ b/packages/jest-config/src/Defaults.ts @@ -31,6 +31,8 @@ const defaultOptions: Config.DefaultOptions = { expand: false, filter: null, forceCoverageMatch: [], + freezeCoreModules: false, + freezeCoreModulesWhitelist: ['crypto'], globalSetup: null, globalTeardown: null, globals: {}, diff --git a/packages/jest-config/src/Descriptions.ts b/packages/jest-config/src/Descriptions.ts index e9088b6849e3..6f6be42d8fa3 100644 --- a/packages/jest-config/src/Descriptions.ts +++ b/packages/jest-config/src/Descriptions.ts @@ -31,6 +31,10 @@ const descriptions: {[key in keyof Config.InitialOptions]: string} = { 'Make calling deprecated APIs throw helpful error messages', forceCoverageMatch: 'Force coverage collection from ignored files using an array of glob patterns', + freezeCoreModules: + "Prevents overriding node's core module methods so to prevent memory leaks", + freezeCoreModulesWhitelist: + 'Array of node core modules which will not be frozen', globalSetup: 'A path to a module which exports an async function that is triggered once before all test suites', globalTeardown: diff --git a/packages/jest-config/src/ValidConfig.ts b/packages/jest-config/src/ValidConfig.ts index aa5ec67c747d..6c7f1ed261e7 100644 --- a/packages/jest-config/src/ValidConfig.ts +++ b/packages/jest-config/src/ValidConfig.ts @@ -50,6 +50,8 @@ const initialOptions: Config.InitialOptions = { filter: '/filter.js', forceCoverageMatch: ['**/*.t.js'], forceExit: false, + freezeCoreModules: false, + freezeCoreModulesWhitelist: ['crypto'], globalSetup: 'setup.js', globalTeardown: 'teardown.js', globals: {__DEV__: true}, diff --git a/packages/jest-config/src/index.ts b/packages/jest-config/src/index.ts index 9f929864554b..257f0db6c33e 100644 --- a/packages/jest-config/src/index.ts +++ b/packages/jest-config/src/index.ts @@ -173,6 +173,8 @@ const groupOptions = ( extraGlobals: options.extraGlobals, filter: options.filter, forceCoverageMatch: options.forceCoverageMatch, + freezeCoreModules: options.freezeCoreModules, + freezeCoreModulesWhitelist: options.freezeCoreModulesWhitelist, globalSetup: options.globalSetup, globalTeardown: options.globalTeardown, globals: options.globals, @@ -210,6 +212,7 @@ const groupOptions = ( transform: options.transform, transformIgnorePatterns: options.transformIgnorePatterns, unmockedModulePathPatterns: options.unmockedModulePathPatterns, + verbose: options.verbose, watchPathIgnorePatterns: options.watchPathIgnorePatterns, }), }); diff --git a/packages/jest-config/src/normalize.ts b/packages/jest-config/src/normalize.ts index fa9c5fad1adf..9355e822ab0c 100644 --- a/packages/jest-config/src/normalize.ts +++ b/packages/jest-config/src/normalize.ts @@ -802,6 +802,8 @@ export default function normalize( case 'findRelatedTests': case 'forceCoverageMatch': case 'forceExit': + case 'freezeCoreModules': + case 'freezeCoreModulesWhitelist': case 'lastCommit': case 'listTests': case 'logHeapUsage': diff --git a/packages/jest-core/src/lib/__tests__/__snapshots__/log_debug_messages.test.ts.snap b/packages/jest-core/src/lib/__tests__/__snapshots__/log_debug_messages.test.ts.snap index fc4ae3ee76e0..5f6f5ce683ba 100644 --- a/packages/jest-core/src/lib/__tests__/__snapshots__/log_debug_messages.test.ts.snap +++ b/packages/jest-core/src/lib/__tests__/__snapshots__/log_debug_messages.test.ts.snap @@ -16,6 +16,10 @@ exports[`prints the config object 1`] = ` "extraGlobals": [], "filter": null, "forceCoverageMatch": [], + "freezeCoreModules": false, + "freezeCoreModulesWhitelist": [ + "crypto" + ], "globalSetup": null, "globalTeardown": null, "globals": {}, @@ -61,6 +65,7 @@ exports[`prints the config object 1`] = ` "transform": [], "transformIgnorePatterns": [], "unmockedModulePathPatterns": null, + "verbose": false, "watchPathIgnorePatterns": [] }, "globalConfig": { diff --git a/packages/jest-runtime/src/__tests__/runtime_require_module.test.js b/packages/jest-runtime/src/__tests__/runtime_require_module.test.js index cd3b13be7026..d2ced91a44e2 100644 --- a/packages/jest-runtime/src/__tests__/runtime_require_module.test.js +++ b/packages/jest-runtime/src/__tests__/runtime_require_module.test.js @@ -183,6 +183,33 @@ describe('Runtime requireModule', () => { }).not.toThrow(); })); + it('prevents overriding core module methods when `config.freezeCoreModules` is set', () => + createRuntime(__filename, {freezeCoreModules: true}).then(runtime => { + const fs = runtime.requireModule(runtime.__mockRootPath, 'fs'); + const originalFsClose = fs.close; + fs.close = () => {}; + expect(fs.close).toBe(originalFsClose); + })); + + it('allows overriding `crypto` core module methods by default', () => + createRuntime(__filename, {freezeCoreModules: true}).then(runtime => { + const crypto = runtime.requireModule(runtime.__mockRootPath, 'crypto'); + const cryptoRandomBytesOverride = () => {}; + crypto.randomBytes = cryptoRandomBytesOverride; + expect(crypto.randomBytes).toBe(cryptoRandomBytesOverride); + })); + + it('allows overriding core module methods when module is in `config.freezeCoreModulesWhitelist`', () => + createRuntime(__filename, { + freezeCoreModules: true, + freezeCoreModulesWhitelist: ['fs'], + }).then(runtime => { + const fs = runtime.requireModule(runtime.__mockRootPath, 'fs'); + const fsCloseOverride = () => {}; + fs.close = fsCloseOverride; + expect(fs.close).toBe(fsCloseOverride); + })); + it('finds and loads JSON files without file extension', () => createRuntime(__filename).then(runtime => { const exports = runtime.requireModule( diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 917b47e377a4..2894a83d41a7 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -18,7 +18,7 @@ import jestMock, {MockFunctionMetadata} from 'jest-mock'; import HasteMap, {ModuleMap} from 'jest-haste-map'; import {formatStackTrace, separateMessageFromStack} from 'jest-message-util'; import Resolver from 'jest-resolve'; -import {createDirectory, deepCyclicCopy} from 'jest-util'; +import {createDirectory, deepCyclicCopy, ErrorWithStack} from 'jest-util'; import {escapePathForRegex} from 'jest-regex-util'; import Snapshot from 'jest-snapshot'; import { @@ -84,6 +84,7 @@ class Runtime { private _cacheFS: CacheFS; private _config: Config.ProjectConfig; + private _coreModulesProxyCache: {[moduleName: string]: any}; private _coverageOptions: ShouldInstrumentOptions; private _currentlyExecutingModulePath: string; private _environment: JestEnvironment; @@ -125,6 +126,7 @@ class Runtime { collectCoverageFrom: [], collectCoverageOnlyFrom: null, }; + this._coreModulesProxyCache = Object.create(null); this._currentlyExecutingModulePath = ''; this._environment = environment; this._explicitShouldMock = Object.create(null); @@ -776,7 +778,46 @@ class Runtime { return this._environment.global.process; } - return require(moduleName); + const module = require(moduleName); + + if ( + !this._config.freezeCoreModules || + this._config.freezeCoreModulesWhitelist.includes(moduleName) + ) { + return module; + } + + if (this._coreModulesProxyCache[moduleName]) { + return this._coreModulesProxyCache[moduleName]; + } + + const set = ( + target: object, + property: PropertyKey, + value: any, + receiver: any, + ) => { + if (typeof value !== 'function') { + return Reflect.set(target, property, value, receiver); + } + + if (this._config.verbose) { + console.warn( + new ErrorWithStack( + `Trying to override method '${property.toString()}' of a frozen core module '${moduleName}'`, + set, + ), + ); + } + + return true; + }; + + const proxy = new Proxy(module, {set}); + + this._coreModulesProxyCache[moduleName] = proxy; + + return proxy; } private _generateMock(from: Config.Path, moduleName: string) { diff --git a/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap b/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap index 92cba297e22e..e8644c397e59 100644 --- a/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap +++ b/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap @@ -17,6 +17,10 @@ Object { "extraGlobals": Array [], "filter": null, "forceCoverageMatch": Array [], + "freezeCoreModules": false, + "freezeCoreModulesWhitelist": Array [ + "crypto", + ], "globalSetup": null, "globalTeardown": null, "globals": Object {}, @@ -67,6 +71,7 @@ Object { "/node_modules/", ], "unmockedModulePathPatterns": null, + "verbose": false, "watchPathIgnorePatterns": Array [], }, "instrument": true, @@ -224,7 +229,7 @@ exports[`ScriptTransformer uses multiple preprocessors 1`] = ` const TRANSFORMED = { filename: '/fruits/banana.js', script: 'module.exports = \\"banana\\";', - config: '{\\"automock\\":false,\\"browser\\":false,\\"cache\\":true,\\"cacheDirectory\\":\\"/cache/\\",\\"clearMocks\\":false,\\"coveragePathIgnorePatterns\\":[],\\"cwd\\":\\"/test_root_dir/\\",\\"detectLeaks\\":false,\\"detectOpenHandles\\":false,\\"errorOnDeprecated\\":false,\\"extraGlobals\\":[],\\"filter\\":null,\\"forceCoverageMatch\\":[],\\"globalSetup\\":null,\\"globalTeardown\\":null,\\"globals\\":{},\\"haste\\":{\\"providesModuleNodeModules\\":[]},\\"moduleDirectories\\":[],\\"moduleFileExtensions\\":[\\"js\\"],\\"moduleLoader\\":\\"/test_module_loader_path\\",\\"moduleNameMapper\\":[],\\"modulePathIgnorePatterns\\":[],\\"modulePaths\\":[],\\"name\\":\\"test\\",\\"prettierPath\\":\\"prettier\\",\\"resetMocks\\":false,\\"resetModules\\":false,\\"resolver\\":null,\\"restoreMocks\\":false,\\"rootDir\\":\\"/\\",\\"roots\\":[],\\"runner\\":\\"jest-runner\\",\\"setupFiles\\":[],\\"setupFilesAfterEnv\\":[],\\"skipFilter\\":false,\\"skipNodeResolution\\":false,\\"snapshotResolver\\":null,\\"snapshotSerializers\\":[],\\"testEnvironment\\":\\"node\\",\\"testEnvironmentOptions\\":{},\\"testLocationInResults\\":false,\\"testMatch\\":[],\\"testPathIgnorePatterns\\":[],\\"testRegex\\":[\\"\\\\\\\\.test\\\\\\\\.js$\\"],\\"testRunner\\":\\"jest-jasmine2\\",\\"testURL\\":\\"\\",\\"timers\\":\\"real\\",\\"transform\\":[[\\"^.+\\\\\\\\.js$\\",\\"test_preprocessor\\"],[\\"^.+\\\\\\\\.css$\\",\\"css-preprocessor\\"]],\\"transformIgnorePatterns\\":[\\"/node_modules/\\"],\\"unmockedModulePathPatterns\\":null,\\"watchPathIgnorePatterns\\":[]}', + config: '{\\"automock\\":false,\\"browser\\":false,\\"cache\\":true,\\"cacheDirectory\\":\\"/cache/\\",\\"clearMocks\\":false,\\"coveragePathIgnorePatterns\\":[],\\"cwd\\":\\"/test_root_dir/\\",\\"detectLeaks\\":false,\\"detectOpenHandles\\":false,\\"errorOnDeprecated\\":false,\\"extraGlobals\\":[],\\"filter\\":null,\\"forceCoverageMatch\\":[],\\"freezeCoreModules\\":false,\\"freezeCoreModulesWhitelist\\":[\\"crypto\\"],\\"globalSetup\\":null,\\"globalTeardown\\":null,\\"globals\\":{},\\"haste\\":{\\"providesModuleNodeModules\\":[]},\\"moduleDirectories\\":[],\\"moduleFileExtensions\\":[\\"js\\"],\\"moduleLoader\\":\\"/test_module_loader_path\\",\\"moduleNameMapper\\":[],\\"modulePathIgnorePatterns\\":[],\\"modulePaths\\":[],\\"name\\":\\"test\\",\\"prettierPath\\":\\"prettier\\",\\"resetMocks\\":false,\\"resetModules\\":false,\\"resolver\\":null,\\"restoreMocks\\":false,\\"rootDir\\":\\"/\\",\\"roots\\":[],\\"runner\\":\\"jest-runner\\",\\"setupFiles\\":[],\\"setupFilesAfterEnv\\":[],\\"skipFilter\\":false,\\"skipNodeResolution\\":false,\\"snapshotResolver\\":null,\\"snapshotSerializers\\":[],\\"testEnvironment\\":\\"node\\",\\"testEnvironmentOptions\\":{},\\"testLocationInResults\\":false,\\"testMatch\\":[],\\"testPathIgnorePatterns\\":[],\\"testRegex\\":[\\"\\\\\\\\.test\\\\\\\\.js$\\"],\\"testRunner\\":\\"jest-jasmine2\\",\\"testURL\\":\\"\\",\\"timers\\":\\"real\\",\\"transform\\":[[\\"^.+\\\\\\\\.js$\\",\\"test_preprocessor\\"],[\\"^.+\\\\\\\\.css$\\",\\"css-preprocessor\\"]],\\"transformIgnorePatterns\\":[\\"/node_modules/\\"],\\"unmockedModulePathPatterns\\":null,\\"verbose\\":false,\\"watchPathIgnorePatterns\\":[]}', }; }});" @@ -250,7 +255,7 @@ exports[`ScriptTransformer uses the supplied preprocessor 1`] = ` const TRANSFORMED = { filename: '/fruits/banana.js', script: 'module.exports = \\"banana\\";', - config: '{\\"automock\\":false,\\"browser\\":false,\\"cache\\":true,\\"cacheDirectory\\":\\"/cache/\\",\\"clearMocks\\":false,\\"coveragePathIgnorePatterns\\":[],\\"cwd\\":\\"/test_root_dir/\\",\\"detectLeaks\\":false,\\"detectOpenHandles\\":false,\\"errorOnDeprecated\\":false,\\"extraGlobals\\":[],\\"filter\\":null,\\"forceCoverageMatch\\":[],\\"globalSetup\\":null,\\"globalTeardown\\":null,\\"globals\\":{},\\"haste\\":{\\"providesModuleNodeModules\\":[]},\\"moduleDirectories\\":[],\\"moduleFileExtensions\\":[\\"js\\"],\\"moduleLoader\\":\\"/test_module_loader_path\\",\\"moduleNameMapper\\":[],\\"modulePathIgnorePatterns\\":[],\\"modulePaths\\":[],\\"name\\":\\"test\\",\\"prettierPath\\":\\"prettier\\",\\"resetMocks\\":false,\\"resetModules\\":false,\\"resolver\\":null,\\"restoreMocks\\":false,\\"rootDir\\":\\"/\\",\\"roots\\":[],\\"runner\\":\\"jest-runner\\",\\"setupFiles\\":[],\\"setupFilesAfterEnv\\":[],\\"skipFilter\\":false,\\"skipNodeResolution\\":false,\\"snapshotResolver\\":null,\\"snapshotSerializers\\":[],\\"testEnvironment\\":\\"node\\",\\"testEnvironmentOptions\\":{},\\"testLocationInResults\\":false,\\"testMatch\\":[],\\"testPathIgnorePatterns\\":[],\\"testRegex\\":[\\"\\\\\\\\.test\\\\\\\\.js$\\"],\\"testRunner\\":\\"jest-jasmine2\\",\\"testURL\\":\\"\\",\\"timers\\":\\"real\\",\\"transform\\":[[\\"^.+\\\\\\\\.js$\\",\\"test_preprocessor\\"]],\\"transformIgnorePatterns\\":[\\"/node_modules/\\"],\\"unmockedModulePathPatterns\\":null,\\"watchPathIgnorePatterns\\":[]}', + config: '{\\"automock\\":false,\\"browser\\":false,\\"cache\\":true,\\"cacheDirectory\\":\\"/cache/\\",\\"clearMocks\\":false,\\"coveragePathIgnorePatterns\\":[],\\"cwd\\":\\"/test_root_dir/\\",\\"detectLeaks\\":false,\\"detectOpenHandles\\":false,\\"errorOnDeprecated\\":false,\\"extraGlobals\\":[],\\"filter\\":null,\\"forceCoverageMatch\\":[],\\"freezeCoreModules\\":false,\\"freezeCoreModulesWhitelist\\":[\\"crypto\\"],\\"globalSetup\\":null,\\"globalTeardown\\":null,\\"globals\\":{},\\"haste\\":{\\"providesModuleNodeModules\\":[]},\\"moduleDirectories\\":[],\\"moduleFileExtensions\\":[\\"js\\"],\\"moduleLoader\\":\\"/test_module_loader_path\\",\\"moduleNameMapper\\":[],\\"modulePathIgnorePatterns\\":[],\\"modulePaths\\":[],\\"name\\":\\"test\\",\\"prettierPath\\":\\"prettier\\",\\"resetMocks\\":false,\\"resetModules\\":false,\\"resolver\\":null,\\"restoreMocks\\":false,\\"rootDir\\":\\"/\\",\\"roots\\":[],\\"runner\\":\\"jest-runner\\",\\"setupFiles\\":[],\\"setupFilesAfterEnv\\":[],\\"skipFilter\\":false,\\"skipNodeResolution\\":false,\\"snapshotResolver\\":null,\\"snapshotSerializers\\":[],\\"testEnvironment\\":\\"node\\",\\"testEnvironmentOptions\\":{},\\"testLocationInResults\\":false,\\"testMatch\\":[],\\"testPathIgnorePatterns\\":[],\\"testRegex\\":[\\"\\\\\\\\.test\\\\\\\\.js$\\"],\\"testRunner\\":\\"jest-jasmine2\\",\\"testURL\\":\\"\\",\\"timers\\":\\"real\\",\\"transform\\":[[\\"^.+\\\\\\\\.js$\\",\\"test_preprocessor\\"]],\\"transformIgnorePatterns\\":[\\"/node_modules/\\"],\\"unmockedModulePathPatterns\\":null,\\"verbose\\":false,\\"watchPathIgnorePatterns\\":[]}', }; }});" diff --git a/packages/jest-types/src/Config.ts b/packages/jest-types/src/Config.ts index 4d6da36d6bd8..e5c073936a4e 100644 --- a/packages/jest-types/src/Config.ts +++ b/packages/jest-types/src/Config.ts @@ -50,6 +50,8 @@ export type DefaultOptions = { expand: boolean; filter: Path | null | undefined; forceCoverageMatch: Array; + freezeCoreModules: boolean; + freezeCoreModulesWhitelist: Array; globals: ConfigGlobals; globalSetup: string | null | undefined; globalTeardown: string | null | undefined; @@ -144,6 +146,8 @@ export type InitialOptions = { findRelatedTests?: boolean; forceCoverageMatch?: Array; forceExit?: boolean; + freezeCoreModules?: boolean; + freezeCoreModulesWhitelist?: Array; json?: boolean; globals?: ConfigGlobals; globalSetup?: string | null | undefined; @@ -374,6 +378,8 @@ export type ProjectConfig = { extraGlobals: Array; filter: Path | null | undefined; forceCoverageMatch: Array; + freezeCoreModules: boolean; + freezeCoreModulesWhitelist: Array; globalSetup: string | null | undefined; globalTeardown: string | null | undefined; globals: ConfigGlobals; @@ -412,6 +418,7 @@ export type ProjectConfig = { transformIgnorePatterns: Array; watchPathIgnorePatterns: Array; unmockedModulePathPatterns: Array | null | undefined; + verbose: boolean | null | undefined; }; export type Argv = Arguments<