From 5bec21e88aa25903bf995efb2852eb9c2504aeae Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 15 Feb 2022 23:05:42 +0100 Subject: [PATCH] --wip-- [skip ci] --- .../src/__tests__/resolve.test.ts | 2 +- packages/jest-resolve/src/defaultResolver.ts | 89 +++++++++++-------- 2 files changed, 55 insertions(+), 36 deletions(-) diff --git a/packages/jest-resolve/src/__tests__/resolve.test.ts b/packages/jest-resolve/src/__tests__/resolve.test.ts index 4d0b1af072a6..9bfa7468413f 100644 --- a/packages/jest-resolve/src/__tests__/resolve.test.ts +++ b/packages/jest-resolve/src/__tests__/resolve.test.ts @@ -298,7 +298,7 @@ describe('resolveModule', () => { ); }); - it('is possible to resolve node modules by resolving their realpath', () => { + it.only('is possible to resolve node modules by resolving their realpath', () => { const resolver = new Resolver(moduleMap, { extensions: ['.js'], } as ResolverConfig); diff --git a/packages/jest-resolve/src/defaultResolver.ts b/packages/jest-resolve/src/defaultResolver.ts index 758117214744..1997ac4f6ada 100644 --- a/packages/jest-resolve/src/defaultResolver.ts +++ b/packages/jest-resolve/src/defaultResolver.ts @@ -5,14 +5,13 @@ * LICENSE file in the root directory of this source tree. */ -import {isAbsolute} from 'path'; +import {dirname, isAbsolute, resolve as pathResolve} from 'path'; import pnpResolver from 'jest-pnp-resolver'; import {sync as resolveSync} from 'resolve'; import { Options as ResolveExportsOptions, resolve as resolveExports, } from 'resolve.exports'; -import slash = require('slash'); import type {Config} from '@jest/types'; import { PkgJson, @@ -56,12 +55,58 @@ export default function defaultResolver( return pnpResolver(path, options); } - const result = resolveSync(path, { + let pathToResolve = path; + + if (!isAbsolute(pathToResolve) && !pathToResolve.startsWith('.')) { + const segments = pathToResolve.split('/'); + + let moduleName = segments.shift(); + + if (moduleName) { + if (moduleName.startsWith('@')) { + moduleName = `${moduleName}/${segments.shift()}`; + } + + const packageJsonPath = resolveSync(`${moduleName}/package.json`, { + ...options, + isDirectory, + isFile, + preserveSymlinks: false, + readPackageSync, + realpathSync, + }); + + if (isFile(packageJsonPath)) { + const pkg = readPackageCached(packageJsonPath); + + if (pkg.exports) { + // we need to make sure resolve ignores `main` + delete pkg.main; + + const subpath = segments.join('/') || '.'; + + const resolved = resolveExports( + pkg, + subpath, + createResolveOptions(options.conditions), + ); + + // TODO: should we throw if not? + if (resolved) { + pathToResolve = pathResolve(dirname(packageJsonPath), resolved); + } + } + } + } + } + + console.log(pathToResolve); + + const result = resolveSync(pathToResolve, { ...options, isDirectory, isFile, - packageFilter: createPackageFilter(path, options.packageFilter), - pathFilter: createPathFilter(path, options.conditions, options.pathFilter), + packageFilter: createPackageFilter(pathToResolve, options.packageFilter), preserveSymlinks: false, readPackageSync, realpathSync, @@ -108,39 +153,13 @@ function createPackageFilter( }; } -function createPathFilter( - originalPath: Config.Path, - conditions?: Array, - userFilter?: ResolverOptions['pathFilter'], -): ResolverOptions['pathFilter'] { - if (shouldIgnoreRequestForExports(originalPath)) { - return userFilter; - } - - const options: ResolveExportsOptions = conditions +function createResolveOptions( + conditions: Array | undefined, +): ResolveExportsOptions { + return conditions ? {conditions, unsafe: true} : // no conditions were passed - let's assume this is Jest internal and it should be `require` {browser: false, require: true}; - - return function pathFilter(pkg, path, relativePath, ...rest) { - let pathToUse = relativePath; - - if (userFilter) { - pathToUse = userFilter(pkg, path, relativePath, ...rest); - } - - if (pkg.exports == null) { - return pathToUse; - } - - // this `index` thing can backfire, but `resolve` adds it: https://github.com/browserify/resolve/blob/f1b51848ecb7f56f77bfb823511d032489a13eab/lib/sync.js#L192 - const isRootRequire = - pathToUse === 'index' && !originalPath.endsWith('/index'); - - const newPath = isRootRequire ? '.' : slash(pathToUse); - - return resolveExports(pkg, newPath, options) || pathToUse; - }; } // if it's a relative import or an absolute path, exports are ignored