5
5
* LICENSE file in the root directory of this source tree.
6
6
*/
7
7
8
- import { dirname , isAbsolute , resolve as pathResolve } from 'path' ;
9
- import { fileURLToPath } from 'url' ;
10
- import pnpResolver from 'jest-pnp-resolver' ;
11
8
import {
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' ;
23
12
import type { PackageJSON } from './types' ;
24
13
25
14
/**
@@ -52,15 +41,13 @@ export type PathFilter = (
52
41
relativePath : string ,
53
42
) => string ;
54
43
55
- export type ResolverOptions = {
44
+ export interface ResolverOptions extends UpstreamResolveOptions {
56
45
/** Directory to begin resolving from. */
57
46
basedir : string ;
58
47
/** List of export conditions. */
59
48
conditions ?: Array < string > ;
60
49
/** Instance of default resolver. */
61
50
defaultResolver : typeof defaultResolver ;
62
- /** List of file extensions to search in order. */
63
- extensions ?: Array < string > ;
64
51
/**
65
52
* List of directory names to be looked up for modules recursively.
66
53
*
@@ -79,12 +66,7 @@ export type ResolverOptions = {
79
66
packageFilter ?: PackageFilter ;
80
67
/** Allows transforms a path within a package. */
81
68
pathFilter ?: PathFilter ;
82
- /** Current root directory. */
83
- rootDir ?: string ;
84
- } ;
85
-
86
- type UpstreamResolveOptionsWithConditions = UpstreamResolveOptions &
87
- ResolverOptions ;
69
+ }
88
70
89
71
export type SyncResolver = ( path : string , options : ResolverOptions ) => string ;
90
72
export type AsyncResolver = (
@@ -95,159 +77,21 @@ export type AsyncResolver = (
95
77
export type Resolver = SyncResolver | AsyncResolver ;
96
78
97
79
const 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 = {
105
81
...options ,
106
- isDirectory,
107
- isFile,
108
- preserveSymlinks : false ,
109
- readPackageSync,
110
- realpathSync,
82
+ conditionNames : options . conditionNames || options . conditions ,
83
+ modules : options . modules || options . moduleDirectory ,
111
84
} ;
112
85
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 ) ;
131
87
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 ) ;
139
89
140
- if ( shouldIgnoreRequestForExports ( path ) ) {
141
- return path ;
90
+ if ( result . error ) {
91
+ throw new Error ( result . error ) ;
142
92
}
143
93
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
+ } ;
250
96
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