@@ -7,7 +7,7 @@ import { dirname } from 'path';
77import resolve from 'resolve' ;
88
99import { getPackageInfo , getPackageName } from './util' ;
10- import { fileExists , realpath } from './fs' ;
10+ import { resolveSymlink } from './fs' ;
1111import { isDirCached , isFileCached , readCachedFile } from './cache' ;
1212import resolvePackageExports from './package/resolvePackageExports' ;
1313import resolvePackageImports from './package/resolvePackageImports' ;
@@ -34,11 +34,8 @@ async function getPackageJson(importer, pkgName, resolveOptions, moduleDirectori
3434 }
3535}
3636
37- async function resolveId ( {
38- importer,
37+ async function resolveIdClassic ( {
3938 importSpecifier,
40- exportConditions,
41- warn,
4239 packageInfoCache,
4340 extensions,
4441 mainFields,
@@ -85,21 +82,48 @@ async function resolveId({
8582 } ;
8683
8784 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+ }
8893
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+ } ) {
90117 if ( importSpecifier . startsWith ( '#' ) ) {
91118 // this is a package internal import, resolve using package imports field
92119 const resolveResult = await resolvePackageImports ( {
93120 importSpecifier,
94121 importer,
95122 moduleDirs : moduleDirectories ,
96123 conditions : exportConditions ,
97- resolveId ( id , parent ) {
98- return resolveId ( {
124+ resolveId ( id /* , parent*/ ) {
125+ return resolveIdClassic ( {
99126 importSpecifier : id ,
100- importer : parent ,
101- exportConditions,
102- warn,
103127 packageInfoCache,
104128 extensions,
105129 mainFields,
@@ -110,71 +134,91 @@ async function resolveId({
110134 } ) ;
111135 }
112136 } ) ;
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 ) {
115151 // 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+
116187 const result = await getPackageJson ( importer , pkgName , resolveOptions , moduleDirectories ) ;
117188
118189 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 ) ;
147195
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+ } ;
155214 }
156- return null ;
157215 }
158216 }
159217
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 ;
173219}
174220
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 ( {
178222 importer,
179223 importSpecifierList,
180224 exportConditions,
@@ -189,11 +233,9 @@ export default async function resolveImportSpecifiers({
189233 rootDir,
190234 ignoreSideEffectsForRoot
191235} ) {
192- let lastResolveError ;
193-
194236 for ( let i = 0 ; i < importSpecifierList . length ; i ++ ) {
195237 // eslint-disable-next-line no-await-in-loop
196- const result = await resolveId ( {
238+ const result = await resolveIdClassic ( {
197239 importer,
198240 importSpecifier : importSpecifierList [ i ] ,
199241 exportConditions,
@@ -209,16 +251,71 @@ export default async function resolveImportSpecifiers({
209251 ignoreSideEffectsForRoot
210252 } ) ;
211253
212- if ( result instanceof ResolveError ) {
213- lastResolveError = result ;
214- } else if ( result ) {
254+ if ( result ) {
215255 return result ;
216256 }
217257 }
218258
219- if ( lastResolveError ) {
220- // only log the last failed resolve error
221- warn ( lastResolveError ) ;
222- }
223259 return null ;
224260}
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