55 * LICENSE file in the root directory of this source tree.
66 */
77
8- import { dirname , isAbsolute , resolve as pathResolve } from 'path' ;
9- import { fileURLToPath } from 'url' ;
10- import pnpResolver from 'jest-pnp-resolver' ;
118import {
12- type SyncOpts as UpstreamResolveOptions ,
13- sync as resolveSync ,
14- } from 'resolve' ;
15- import * as resolve from 'resolve.exports' ;
16- import {
17- findClosestPackageJson ,
18- isDirectory ,
19- isFile ,
20- readPackageCached ,
21- realpathSync ,
22- } from './fileWalkers' ;
9+ ResolverFactory ,
10+ type NapiResolveOptions as UpstreamResolveOptions ,
11+ } from 'unrs-resolver' ;
2312import type { PackageJSON } from './types' ;
2413
2514/**
@@ -52,15 +41,13 @@ export type PathFilter = (
5241 relativePath : string ,
5342) => string ;
5443
55- export type ResolverOptions = {
44+ export interface ResolverOptions extends UpstreamResolveOptions {
5645 /** Directory to begin resolving from. */
5746 basedir : string ;
5847 /** List of export conditions. */
5948 conditions ?: Array < string > ;
6049 /** Instance of default resolver. */
6150 defaultResolver : typeof defaultResolver ;
62- /** List of file extensions to search in order. */
63- extensions ?: Array < string > ;
6451 /**
6552 * List of directory names to be looked up for modules recursively.
6653 *
@@ -79,12 +66,7 @@ export type ResolverOptions = {
7966 packageFilter ?: PackageFilter ;
8067 /** Allows transforms a path within a package. */
8168 pathFilter ?: PathFilter ;
82- /** Current root directory. */
83- rootDir ?: string ;
84- } ;
85-
86- type UpstreamResolveOptionsWithConditions = UpstreamResolveOptions &
87- ResolverOptions ;
69+ }
8870
8971export type SyncResolver = ( path : string , options : ResolverOptions ) => string ;
9072export type AsyncResolver = (
@@ -95,159 +77,21 @@ export type AsyncResolver = (
9577export type Resolver = SyncResolver | AsyncResolver ;
9678
9779const defaultResolver : SyncResolver = ( path , options ) => {
98- // Yarn 2 adds support to `resolve` automatically so the pnpResolver is only
99- // needed for Yarn 1 which implements version 1 of the pnp spec
100- if ( process . versions . pnp === '1' ) {
101- return pnpResolver ( path , options ) ;
102- }
103-
104- const resolveOptions : UpstreamResolveOptionsWithConditions = {
80+ const resolveOptions : UpstreamResolveOptions = {
10581 ...options ,
106- isDirectory,
107- isFile,
108- preserveSymlinks : false ,
109- readPackageSync,
110- realpathSync,
82+ conditionNames : options . conditionNames || options . conditions ,
83+ modules : options . modules || options . moduleDirectory ,
11184 } ;
11285
113- const pathToResolve = getPathInModule ( path , resolveOptions ) ;
114-
115- // resolveSync dereferences symlinks to ensure we don't create a separate
116- // module instance depending on how it was referenced.
117- const result = resolveSync ( pathToResolve , resolveOptions ) ;
118-
119- return result ;
120- } ;
121-
122- export default defaultResolver ;
123-
124- /*
125- * helper functions
126- */
127-
128- function readPackageSync ( _ : unknown , file : string ) : PackageJSON {
129- return readPackageCached ( file ) ;
130- }
86+ const unrsResolver = new ResolverFactory ( resolveOptions ) ;
13187
132- function getPathInModule (
133- path : string ,
134- options : UpstreamResolveOptionsWithConditions ,
135- ) : string {
136- if ( path . startsWith ( 'file://' ) ) {
137- path = fileURLToPath ( path ) ;
138- }
88+ const result = unrsResolver . sync ( options . basedir , path ) ;
13989
140- if ( shouldIgnoreRequestForExports ( path ) ) {
141- return path ;
90+ if ( result . error ) {
91+ throw new Error ( result . error ) ;
14292 }
14393
144- if ( path . startsWith ( '#' ) ) {
145- const closestPackageJson = findClosestPackageJson ( options . basedir ) ;
146-
147- if ( ! closestPackageJson ) {
148- throw new Error (
149- `Jest: unable to locate closest package.json from ${ options . basedir } when resolving import "${ path } "` ,
150- ) ;
151- }
152-
153- const pkg = readPackageCached ( closestPackageJson ) ;
154-
155- const resolved = resolve . imports (
156- pkg ,
157- path as resolve . Imports . Entry ,
158- createResolveOptions ( options . conditions ) ,
159- ) ;
160-
161- if ( resolved ) {
162- const target = resolved [ 0 ] ;
163- return target . startsWith ( '.' )
164- ? // internal relative filepath
165- pathResolve ( dirname ( closestPackageJson ) , target )
166- : // this is an external module, re-resolve it
167- defaultResolver ( target , options ) ;
168- }
169-
170- if ( pkg . imports ) {
171- throw new Error (
172- '`imports` exists, but no results - this is a bug in Jest. Please report an issue' ,
173- ) ;
174- }
175- }
176-
177- const segments = path . split ( '/' ) ;
178-
179- let moduleName = segments . shift ( ) ;
180-
181- if ( moduleName ) {
182- if ( moduleName . startsWith ( '@' ) ) {
183- moduleName = `${ moduleName } /${ segments . shift ( ) } ` ;
184- }
185-
186- // self-reference
187- const closestPackageJson = findClosestPackageJson ( options . basedir ) ;
188- if ( closestPackageJson ) {
189- const pkg = readPackageCached ( closestPackageJson ) ;
190-
191- if ( pkg . name === moduleName ) {
192- const resolved = resolve . exports (
193- pkg ,
194- ( segments . join ( '/' ) || '.' ) as resolve . Exports . Entry ,
195- createResolveOptions ( options . conditions ) ,
196- ) ;
197-
198- if ( resolved ) {
199- return pathResolve ( dirname ( closestPackageJson ) , resolved [ 0 ] ) ;
200- }
201-
202- if ( pkg . exports ) {
203- throw new Error (
204- '`exports` exists, but no results - this is a bug in Jest. Please report an issue' ,
205- ) ;
206- }
207- }
208- }
209-
210- let packageJsonPath = '' ;
211-
212- try {
213- packageJsonPath = resolveSync ( `${ moduleName } /package.json` , options ) ;
214- } catch {
215- // ignore if package.json cannot be found
216- }
217-
218- if ( packageJsonPath && isFile ( packageJsonPath ) ) {
219- const pkg = readPackageCached ( packageJsonPath ) ;
220-
221- const resolved = resolve . exports (
222- pkg ,
223- ( segments . join ( '/' ) || '.' ) as resolve . Exports . Entry ,
224- createResolveOptions ( options . conditions ) ,
225- ) ;
226-
227- if ( resolved ) {
228- return pathResolve ( dirname ( packageJsonPath ) , resolved [ 0 ] ) ;
229- }
230-
231- if ( pkg . exports ) {
232- throw new Error (
233- '`exports` exists, but no results - this is a bug in Jest. Please report an issue' ,
234- ) ;
235- }
236- }
237- }
238-
239- return path ;
240- }
241-
242- function createResolveOptions (
243- conditions : Array < string > | undefined ,
244- ) : resolve . Options {
245- return conditions
246- ? { conditions, unsafe : true }
247- : // no conditions were passed - let's assume this is Jest internal and it should be `require`
248- { browser : false , require : true } ;
249- }
94+ return result . path ! ;
95+ } ;
25096
251- // if it's a relative import or an absolute path, imports/exports are ignored
252- const shouldIgnoreRequestForExports = ( path : string ) =>
253- path . startsWith ( '.' ) || isAbsolute ( path ) ;
97+ export default defaultResolver ;
0 commit comments