5
5
* LICENSE file in the root directory of this source tree.
6
6
*/
7
7
8
- import { isAbsolute } from 'path' ;
8
+ import { dirname , isAbsolute , resolve as pathResolve } from 'path' ;
9
9
import pnpResolver from 'jest-pnp-resolver' ;
10
10
import { sync as resolveSync } from 'resolve' ;
11
11
import {
12
12
Options as ResolveExportsOptions ,
13
13
resolve as resolveExports ,
14
14
} from 'resolve.exports' ;
15
- import slash = require( 'slash' ) ;
16
15
import {
17
16
PkgJson ,
18
17
isDirectory ,
@@ -45,6 +44,62 @@ declare global {
45
44
}
46
45
}
47
46
47
+ function getPathInModule ( path : string , options : ResolverOptions ) : string {
48
+ if ( isAbsolute ( path ) || path . startsWith ( '.' ) ) {
49
+ return path ;
50
+ }
51
+
52
+ const segments = path . split ( '/' ) ;
53
+
54
+ let moduleName = segments . shift ( ) ;
55
+
56
+ if ( moduleName ) {
57
+ // TODO: handle `#` here: https://github.com/facebook/jest/issues/12270
58
+ if ( moduleName . startsWith ( '@' ) ) {
59
+ moduleName = `${ moduleName } /${ segments . shift ( ) } ` ;
60
+ }
61
+
62
+ let packageJsonPath = '' ;
63
+
64
+ try {
65
+ packageJsonPath = resolveSync ( `${ moduleName } /package.json` , {
66
+ ...options ,
67
+ isDirectory,
68
+ isFile,
69
+ preserveSymlinks : false ,
70
+ readPackageSync,
71
+ realpathSync,
72
+ } ) ;
73
+ } catch {
74
+ // ignore if package.json cannot be found
75
+ }
76
+
77
+ if ( packageJsonPath && isFile ( packageJsonPath ) ) {
78
+ const pkg = readPackageCached ( packageJsonPath ) ;
79
+
80
+ if ( pkg . exports ) {
81
+ // we need to make sure resolve ignores `main`
82
+ delete pkg . main ;
83
+
84
+ const subpath = segments . join ( '/' ) || '.' ;
85
+
86
+ const resolved = resolveExports (
87
+ pkg ,
88
+ subpath ,
89
+ createResolveOptions ( options . conditions ) ,
90
+ ) ;
91
+
92
+ // TODO: should we throw if not?
93
+ if ( resolved ) {
94
+ return pathResolve ( dirname ( packageJsonPath ) , resolved ) ;
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ return path ;
101
+ }
102
+
48
103
export default function defaultResolver (
49
104
path : string ,
50
105
options : ResolverOptions ,
@@ -55,12 +110,13 @@ export default function defaultResolver(
55
110
return pnpResolver ( path , options ) ;
56
111
}
57
112
58
- const result = resolveSync ( path , {
113
+ const pathToResolve = getPathInModule ( path , options ) ;
114
+
115
+ const result = resolveSync ( pathToResolve , {
59
116
...options ,
60
117
isDirectory,
61
118
isFile,
62
- packageFilter : createPackageFilter ( path , options . packageFilter ) ,
63
- pathFilter : createPathFilter ( path , options . conditions , options . pathFilter ) ,
119
+ packageFilter : createPackageFilter ( pathToResolve , options . packageFilter ) ,
64
120
preserveSymlinks : false ,
65
121
readPackageSync,
66
122
realpathSync,
@@ -107,39 +163,13 @@ function createPackageFilter(
107
163
} ;
108
164
}
109
165
110
- function createPathFilter (
111
- originalPath : string ,
112
- conditions ?: Array < string > ,
113
- userFilter ?: ResolverOptions [ 'pathFilter' ] ,
114
- ) : ResolverOptions [ 'pathFilter' ] {
115
- if ( shouldIgnoreRequestForExports ( originalPath ) ) {
116
- return userFilter ;
117
- }
118
-
119
- const options : ResolveExportsOptions = conditions
166
+ function createResolveOptions (
167
+ conditions : Array < string > | undefined ,
168
+ ) : ResolveExportsOptions {
169
+ return conditions
120
170
? { conditions, unsafe : true }
121
171
: // no conditions were passed - let's assume this is Jest internal and it should be `require`
122
172
{ browser : false , require : true } ;
123
-
124
- return function pathFilter ( pkg , path , relativePath , ...rest ) {
125
- let pathToUse = relativePath ;
126
-
127
- if ( userFilter ) {
128
- pathToUse = userFilter ( pkg , path , relativePath , ...rest ) ;
129
- }
130
-
131
- if ( pkg . exports == null ) {
132
- return pathToUse ;
133
- }
134
-
135
- // this `index` thing can backfire, but `resolve` adds it: https://github.com/browserify/resolve/blob/f1b51848ecb7f56f77bfb823511d032489a13eab/lib/sync.js#L192
136
- const isRootRequire =
137
- pathToUse === 'index' && ! originalPath . endsWith ( '/index' ) ;
138
-
139
- const newPath = isRootRequire ? '.' : slash ( pathToUse ) ;
140
-
141
- return resolveExports ( pkg , newPath , options ) || pathToUse ;
142
- } ;
143
173
}
144
174
145
175
// if it's a relative import or an absolute path, exports are ignored
0 commit comments