@@ -7,7 +7,7 @@ import { dirname } from 'path';
7
7
import resolve from 'resolve' ;
8
8
9
9
import { getPackageInfo , getPackageName } from './util' ;
10
- import { fileExists , realpath } from './fs' ;
10
+ import { resolveSymlink } from './fs' ;
11
11
import { isDirCached , isFileCached , readCachedFile } from './cache' ;
12
12
import resolvePackageExports from './package/resolvePackageExports' ;
13
13
import resolvePackageImports from './package/resolvePackageImports' ;
@@ -34,11 +34,8 @@ async function getPackageJson(importer, pkgName, resolveOptions, moduleDirectori
34
34
}
35
35
}
36
36
37
- async function resolveId ( {
38
- importer,
37
+ async function resolveIdClassic ( {
39
38
importSpecifier,
40
- exportConditions,
41
- warn,
42
39
packageInfoCache,
43
40
extensions,
44
41
mainFields,
@@ -85,21 +82,48 @@ async function resolveId({
85
82
} ;
86
83
87
84
let location ;
85
+ try {
86
+ location = await resolveImportPath ( importSpecifier , resolveOptions ) ;
87
+ } catch ( error ) {
88
+ if ( error . code !== 'MODULE_NOT_FOUND' ) {
89
+ throw error ;
90
+ }
91
+ return null ;
92
+ }
88
93
89
- const pkgName = getPackageName ( importSpecifier ) ;
94
+ return {
95
+ location : preserveSymlinks ? location : await resolveSymlink ( location ) ,
96
+ hasModuleSideEffects,
97
+ hasPackageEntry,
98
+ packageBrowserField,
99
+ packageInfo
100
+ } ;
101
+ }
102
+
103
+ async function resolveWithExportMap ( {
104
+ importer,
105
+ importSpecifier,
106
+ exportConditions,
107
+ packageInfoCache,
108
+ extensions,
109
+ mainFields,
110
+ preserveSymlinks,
111
+ useBrowserOverrides,
112
+ baseDir,
113
+ moduleDirectories,
114
+ rootDir,
115
+ ignoreSideEffectsForRoot
116
+ } ) {
90
117
if ( importSpecifier . startsWith ( '#' ) ) {
91
118
// this is a package internal import, resolve using package imports field
92
119
const resolveResult = await resolvePackageImports ( {
93
120
importSpecifier,
94
121
importer,
95
122
moduleDirs : moduleDirectories ,
96
123
conditions : exportConditions ,
97
- resolveId ( id , parent ) {
98
- return resolveId ( {
124
+ resolveId ( id /* , parent*/ ) {
125
+ return resolveIdClassic ( {
99
126
importSpecifier : id ,
100
- importer : parent ,
101
- exportConditions,
102
- warn,
103
127
packageInfoCache,
104
128
extensions,
105
129
mainFields,
@@ -110,71 +134,91 @@ async function resolveId({
110
134
} ) ;
111
135
}
112
136
} ) ;
113
- location = fileURLToPath ( resolveResult ) ;
114
- } else if ( pkgName ) {
137
+
138
+ const location = fileURLToPath ( resolveResult ) ;
139
+ return {
140
+ location : preserveSymlinks ? location : await resolveSymlink ( location ) ,
141
+ hasModuleSideEffects : ( ) => null ,
142
+ hasPackageEntry : true ,
143
+ packageBrowserField : false ,
144
+ // eslint-disable-next-line no-undefined
145
+ packageInfo : undefined
146
+ } ;
147
+ }
148
+
149
+ const pkgName = getPackageName ( importSpecifier ) ;
150
+ if ( pkgName ) {
115
151
// it's a bare import, find the package.json and resolve using package exports if available
152
+ let hasModuleSideEffects = ( ) => null ;
153
+ let hasPackageEntry = true ;
154
+ let packageBrowserField = false ;
155
+ let packageInfo ;
156
+
157
+ const filter = ( pkg , pkgPath ) => {
158
+ const info = getPackageInfo ( {
159
+ cache : packageInfoCache ,
160
+ extensions,
161
+ pkg,
162
+ pkgPath,
163
+ mainFields,
164
+ preserveSymlinks,
165
+ useBrowserOverrides,
166
+ rootDir,
167
+ ignoreSideEffectsForRoot
168
+ } ) ;
169
+
170
+ ( { packageInfo, hasModuleSideEffects, hasPackageEntry, packageBrowserField } = info ) ;
171
+
172
+ return info . cachedPkg ;
173
+ } ;
174
+
175
+ const resolveOptions = {
176
+ basedir : baseDir ,
177
+ readFile : readCachedFile ,
178
+ isFile : isFileCached ,
179
+ isDirectory : isDirCached ,
180
+ extensions,
181
+ includeCoreModules : false ,
182
+ moduleDirectory : moduleDirectories ,
183
+ preserveSymlinks,
184
+ packageFilter : filter
185
+ } ;
186
+
116
187
const result = await getPackageJson ( importer , pkgName , resolveOptions , moduleDirectories ) ;
117
188
118
189
if ( result && result . pkgJson . exports ) {
119
- const { pkgJson, pkgJsonPath, pkgPath } = result ;
120
- try {
121
- const subpath =
122
- pkgName === importSpecifier ? '.' : `.${ importSpecifier . substring ( pkgName . length ) } ` ;
123
- const pkgURL = pathToFileURL ( `${ pkgPath } /` ) ;
124
-
125
- const context = {
126
- importer,
127
- importSpecifier,
128
- moduleDirs : moduleDirectories ,
129
- pkgURL,
130
- pkgJsonPath,
131
- conditions : exportConditions
132
- } ;
133
- const resolvedPackageExport = await resolvePackageExports (
134
- context ,
135
- subpath ,
136
- pkgJson . exports
137
- ) ;
138
- location = fileURLToPath ( resolvedPackageExport ) ;
139
- } catch ( error ) {
140
- if ( error instanceof ResolveError ) {
141
- return error ;
142
- }
143
- throw error ;
144
- }
145
- }
146
- }
190
+ const { pkgJson, pkgJsonPath } = result ;
191
+ const subpath =
192
+ pkgName === importSpecifier ? '.' : `.${ importSpecifier . substring ( pkgName . length ) } ` ;
193
+ const pkgDr = pkgJsonPath . replace ( 'package.json' , '' ) ;
194
+ const pkgURL = pathToFileURL ( pkgDr ) ;
147
195
148
- if ( ! location ) {
149
- // package has no imports or exports, use classic node resolve
150
- try {
151
- location = await resolveImportPath ( importSpecifier , resolveOptions ) ;
152
- } catch ( error ) {
153
- if ( error . code !== 'MODULE_NOT_FOUND' ) {
154
- throw error ;
196
+ const context = {
197
+ importer,
198
+ importSpecifier,
199
+ moduleDirs : moduleDirectories ,
200
+ pkgURL,
201
+ pkgJsonPath,
202
+ conditions : exportConditions
203
+ } ;
204
+ const resolvedPackageExport = await resolvePackageExports ( context , subpath , pkgJson . exports ) ;
205
+ const location = fileURLToPath ( resolvedPackageExport ) ;
206
+ if ( location ) {
207
+ return {
208
+ location : preserveSymlinks ? location : await resolveSymlink ( location ) ,
209
+ hasModuleSideEffects,
210
+ hasPackageEntry,
211
+ packageBrowserField,
212
+ packageInfo
213
+ } ;
155
214
}
156
- return null ;
157
215
}
158
216
}
159
217
160
- if ( ! preserveSymlinks ) {
161
- if ( await fileExists ( location ) ) {
162
- location = await realpath ( location ) ;
163
- }
164
- }
165
-
166
- return {
167
- location,
168
- hasModuleSideEffects,
169
- hasPackageEntry,
170
- packageBrowserField,
171
- packageInfo
172
- } ;
218
+ return null ;
173
219
}
174
220
175
- // Resolve module specifiers in order. Promise resolves to the first module that resolves
176
- // successfully, or the error that resulted from the last attempted module resolution.
177
- export default async function resolveImportSpecifiers ( {
221
+ async function resolveWithClassic ( {
178
222
importer,
179
223
importSpecifierList,
180
224
exportConditions,
@@ -189,11 +233,9 @@ export default async function resolveImportSpecifiers({
189
233
rootDir,
190
234
ignoreSideEffectsForRoot
191
235
} ) {
192
- let lastResolveError ;
193
-
194
236
for ( let i = 0 ; i < importSpecifierList . length ; i ++ ) {
195
237
// eslint-disable-next-line no-await-in-loop
196
- const result = await resolveId ( {
238
+ const result = await resolveIdClassic ( {
197
239
importer,
198
240
importSpecifier : importSpecifierList [ i ] ,
199
241
exportConditions,
@@ -209,16 +251,71 @@ export default async function resolveImportSpecifiers({
209
251
ignoreSideEffectsForRoot
210
252
} ) ;
211
253
212
- if ( result instanceof ResolveError ) {
213
- lastResolveError = result ;
214
- } else if ( result ) {
254
+ if ( result ) {
215
255
return result ;
216
256
}
217
257
}
218
258
219
- if ( lastResolveError ) {
220
- // only log the last failed resolve error
221
- warn ( lastResolveError ) ;
222
- }
223
259
return null ;
224
260
}
261
+
262
+ // Resolves to the module if found or `null`.
263
+ // The first import specificer will first be attempted with the exports algorithm.
264
+ // If this is unsuccesful because export maps are not being used, then all of `importSpecifierList`
265
+ // will be tried with the classic resolution algorithm
266
+ export default async function resolveImportSpecifiers ( {
267
+ importer,
268
+ importSpecifierList,
269
+ exportConditions,
270
+ warn,
271
+ packageInfoCache,
272
+ extensions,
273
+ mainFields,
274
+ preserveSymlinks,
275
+ useBrowserOverrides,
276
+ baseDir,
277
+ moduleDirectories,
278
+ rootDir,
279
+ ignoreSideEffectsForRoot
280
+ } ) {
281
+ try {
282
+ const exportMapRes = await resolveWithExportMap ( {
283
+ importer,
284
+ importSpecifier : importSpecifierList [ 0 ] ,
285
+ exportConditions,
286
+ packageInfoCache,
287
+ extensions,
288
+ mainFields,
289
+ preserveSymlinks,
290
+ useBrowserOverrides,
291
+ baseDir,
292
+ moduleDirectories,
293
+ rootDir,
294
+ ignoreSideEffectsForRoot
295
+ } ) ;
296
+ if ( exportMapRes ) return exportMapRes ;
297
+ } catch ( error ) {
298
+ if ( error instanceof ResolveError ) {
299
+ warn ( error ) ;
300
+ return null ;
301
+ }
302
+ throw error ;
303
+ }
304
+
305
+ // package has no imports or exports, use classic node resolve
306
+ return resolveWithClassic ( {
307
+ importer,
308
+ importSpecifierList,
309
+ exportConditions,
310
+ warn,
311
+ packageInfoCache,
312
+ extensions,
313
+ mainFields,
314
+ preserveSymlinks,
315
+ useBrowserOverrides,
316
+ baseDir,
317
+ moduleDirectories,
318
+ rootDir,
319
+ ignoreSideEffectsForRoot
320
+ } ) ;
321
+ }
0 commit comments