From 9caa82f18a5bc6f9c06a395aec537699059fd63f Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 22 Apr 2021 12:23:09 +0200 Subject: [PATCH] feat(resolver): support `node:` prefix when loading core modules --- CHANGELOG.md | 4 +++- .../__snapshots__/moduleNameMapper.test.ts.snap | 4 ++-- .../resolveNoFileExtensions.test.ts.snap | 2 +- packages/jest-resolve/src/isBuiltinModule.ts | 12 ++---------- packages/jest-resolve/src/resolver.ts | 10 +++++----- .../src/__tests__/runtime_require_module.test.js | 11 +++++++++++ packages/jest-runtime/src/index.ts | 10 +++++++--- 7 files changed, 31 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6b1d88a6a8d..fa988476b3fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Features +- `[jest-resolver]` Support `node:` prefix when importing Node core modules ([#11331](https://github.com/facebook/jest/pull/11331)) + ### Fixes ### Chore & Maintenance @@ -100,6 +102,7 @@ - `[@jest/fake-timers]` Update to `@sinonjs/fake-timers` to v7 ([#11198](https://github.com/facebook/jest/pull/11198)) - `[jest-haste-map]` Handle injected scm clocks ([#10966](https://github.com/facebook/jest/pull/10966)) - `[jest-haste-map]` Add `enableSymlinks` configuration option to follow symlinks for test files ([#9351](https://github.com/facebook/jest/pull/9351)) +- `[jest-reporters]` Add static filepath property to all reporters ([#11015](https://github.com/facebook/jest/pull/11015)) - `[jest-repl, jest-runner]` [**BREAKING**] Run transforms over environment ([#8751](https://github.com/facebook/jest/pull/8751)) - `[jest-repl]` Add support for `testEnvironment` written in ESM ([#11232](https://github.com/facebook/jest/pull/11232)) - `[jest-runner]` [**BREAKING**] set exit code to 1 if test logs after teardown ([#10728](https://github.com/facebook/jest/pull/10728)) @@ -109,7 +112,6 @@ - `[jest-runner]` Add support for `testRunner` written in ESM ([#11232](https://github.com/facebook/jest/pull/11232)) - `[jest-runtime]` Detect reexports from CJS as named exports in ESM ([#10988](https://github.com/facebook/jest/pull/10988)) - `[jest-runtime]` Support for async code transformations ([#11191](https://github.com/facebook/jest/pull/11191) & [#11220](https://github.com/facebook/jest/pull/11220)) -- `[jest-reporters]` Add static filepath property to all reporters ([#11015](https://github.com/facebook/jest/pull/11015)) - `[jest-snapshot]` [**BREAKING**] Make prettier optional for inline snapshots - fall back to string replacement ([#7792](https://github.com/facebook/jest/pull/7792) & [#11192](https://github.com/facebook/jest/pull/11192)) - `[jest-snapshot]` [**BREAKING**] Run transforms over `snapshotResolver` ([#8751](https://github.com/facebook/jest/pull/8829)) - `[jest-transform]` Pass config options defined in Jest's config to transformer's `process` and `getCacheKey` functions ([#10926](https://github.com/facebook/jest/pull/10926)) diff --git a/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap b/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap index 7b7539f60631..e6c44c61c5e4 100644 --- a/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap +++ b/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap @@ -41,7 +41,7 @@ FAIL __tests__/index.js 12 | module.exports = () => 'test'; 13 | - at createNoMappedModuleFoundError (../../packages/jest-resolve/build/resolver.js:558:17) + at createNoMappedModuleFoundError (../../packages/jest-resolve/build/resolver.js:561:17) at Object.require (index.js:10:1) `; @@ -70,6 +70,6 @@ FAIL __tests__/index.js 12 | module.exports = () => 'test'; 13 | - at createNoMappedModuleFoundError (../../packages/jest-resolve/build/resolver.js:558:17) + at createNoMappedModuleFoundError (../../packages/jest-resolve/build/resolver.js:561:17) at Object.require (index.js:10:1) `; diff --git a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap index d5e865161f13..284c4c43706a 100644 --- a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap +++ b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap @@ -37,6 +37,6 @@ FAIL __tests__/test.js | ^ 9 | - at Resolver.resolveModule (../../packages/jest-resolve/build/resolver.js:311:11) + at Resolver.resolveModule (../../packages/jest-resolve/build/resolver.js:313:11) at Object.require (index.js:8:18) `; diff --git a/packages/jest-resolve/src/isBuiltinModule.ts b/packages/jest-resolve/src/isBuiltinModule.ts index 1bac7fefdc84..df64cc3d422f 100644 --- a/packages/jest-resolve/src/isBuiltinModule.ts +++ b/packages/jest-resolve/src/isBuiltinModule.ts @@ -7,19 +7,11 @@ import module = require('module'); -// "private" api -declare const process: NodeJS.Process & { - binding(type: string): Record; -}; - +// TODO: remove when we drop support for node v10 - it is included from node v12 const EXPERIMENTAL_MODULES = ['worker_threads']; const BUILTIN_MODULES = new Set( - module.builtinModules - ? module.builtinModules.concat(EXPERIMENTAL_MODULES) - : Object.keys(process.binding('natives')) - .filter((module: string) => !/^internal\//.test(module)) - .concat(EXPERIMENTAL_MODULES), + module.builtinModules.concat(EXPERIMENTAL_MODULES), ); export default function isBuiltinModule(module: string): boolean { diff --git a/packages/jest-resolve/src/resolver.ts b/packages/jest-resolve/src/resolver.ts index a492cf198978..c0800eef94cf 100644 --- a/packages/jest-resolve/src/resolver.ts +++ b/packages/jest-resolve/src/resolver.ts @@ -135,7 +135,7 @@ export default class Resolver { moduleName: string, options?: ResolveModuleConfig, ): Config.Path | null { - const paths = (options && options.paths) || this._options.modulePaths; + const paths = options?.paths || this._options.modulePaths; const moduleDirectory = this._options.moduleDirectories; const key = dirname + path.delimiter + moduleName; const defaultPlatform = this._options.defaultPlatform; @@ -253,7 +253,9 @@ export default class Resolver { isCoreModule(moduleName: string): boolean { return ( this._options.hasCoreModules && - isBuiltinModule(moduleName) && + (isBuiltinModule(moduleName) || + (moduleName.startsWith('node:') && + isBuiltinModule(moduleName.slice('node:'.length)))) && !this._isAliasModule(moduleName) ); } @@ -313,10 +315,8 @@ export default class Resolver { getModuleID( virtualMocks: Map, from: Config.Path, - _moduleName?: string, + moduleName = '', ): string { - const moduleName = _moduleName || ''; - const key = from + path.delimiter + moduleName; const cachedModuleID = this._moduleIDCache.get(key); if (cachedModuleID) { 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 937d1bc14350..3cabb041808f 100644 --- a/packages/jest-runtime/src/__tests__/runtime_require_module.test.js +++ b/packages/jest-runtime/src/__tests__/runtime_require_module.test.js @@ -188,6 +188,17 @@ describe('Runtime requireModule', () => { }).not.toThrow(); }); + it('finds node core built-in modules with node:prefix', async () => { + const runtime = await createRuntime(__filename); + + expect(runtime.requireModule(runtime.__mockRootPath, 'fs')).toBe( + runtime.requireModule(runtime.__mockRootPath, 'node:fs'), + ); + expect(runtime.requireModule(runtime.__mockRootPath, 'module')).toBe( + runtime.requireModule(runtime.__mockRootPath, 'node:module'), + ); + }); + it('finds and loads JSON files without file extension', async () => { const runtime = await createRuntime(__filename); const exports = runtime.requireModule(runtime.__mockRootPath, './JSONFile'); diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index cbe95fd67bde..e0685603e798 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -1332,15 +1332,19 @@ export default class Runtime { } private _requireCoreModule(moduleName: string) { - if (moduleName === 'process') { + const moduleWithoutNodePrefix = moduleName.startsWith('node:') + ? moduleName.slice('node:'.length) + : moduleName; + + if (moduleWithoutNodePrefix === 'process') { return this._environment.global.process; } - if (moduleName === 'module') { + if (moduleWithoutNodePrefix === 'module') { return this._getMockedNativeModule(); } - return require(moduleName); + return require(moduleWithoutNodePrefix); } private _importCoreModule(moduleName: string, context: VMContext) {