@@ -205,6 +205,9 @@ type resolver struct {
205
205
// all parent directories
206
206
dirCache map [string ]* dirInfo
207
207
208
+ pnpManifestWasChecked bool
209
+ pnpManifest * pnpData
210
+
208
211
options config.Options
209
212
210
213
// This mutex serves two purposes. First of all, it guards access to "dirCache"
@@ -254,6 +257,8 @@ func NewResolver(fs fs.FS, log logger.Log, caches *cache.CacheSet, options confi
254
257
esmConditionsRequire [key ] = true
255
258
}
256
259
260
+ fs .Cwd ()
261
+
257
262
return & resolver {
258
263
fs : fs ,
259
264
log : log ,
@@ -409,6 +414,30 @@ func (rr *resolver) Resolve(sourceDir string, importPath string, kind ast.Import
409
414
defer r .mutex .Unlock ()
410
415
sourceDirInfo := r .loadModuleSuffixesForSourceDir (sourceDir )
411
416
417
+ // Check for the Yarn PnP manifest if it hasn't already been checked for
418
+ if ! r .pnpManifestWasChecked {
419
+ r .pnpManifestWasChecked = true
420
+
421
+ // Use the current working directory to find the Yarn PnP manifest. We
422
+ // can't necessarily use the entry point locations because the entry
423
+ // point locations aren't necessarily file paths. For example, they could
424
+ // be HTTP URLs that will be handled by a plugin.
425
+ for dirInfo := r .dirInfoCached (r .fs .Cwd ()); dirInfo != nil ; dirInfo = dirInfo .parent {
426
+ if absPath := dirInfo .pnpManifestAbsPath ; absPath != "" {
427
+ if strings .HasSuffix (absPath , ".json" ) {
428
+ if json := r .extractYarnPnPDataFromJSON (absPath , pnpReportErrorsAboutMissingFiles ); json .Data != nil {
429
+ r .pnpManifest = compileYarnPnPData (absPath , r .fs .Dir (absPath ), json )
430
+ }
431
+ } else {
432
+ if json := r .tryToExtractYarnPnPDataFromJS (absPath , pnpReportErrorsAboutMissingFiles ); json .Data != nil {
433
+ r .pnpManifest = compileYarnPnPData (absPath , r .fs .Dir (absPath ), json )
434
+ }
435
+ }
436
+ break
437
+ }
438
+ }
439
+ }
440
+
412
441
result := r .resolveWithoutSymlinks (sourceDir , sourceDirInfo , importPath )
413
442
if result == nil {
414
443
// If resolution failed, try again with the URL query and/or hash removed
@@ -692,15 +721,12 @@ func (r resolverQuery) finalizeResolve(result *ResolveResult) {
692
721
}
693
722
694
723
func (r resolverQuery ) resolveWithoutSymlinks (sourceDir string , sourceDirInfo * dirInfo , importPath string ) * ResolveResult {
695
- // Find the parent directory with the Yarn PnP data
696
- for info := sourceDirInfo ; info != nil ; info = info .parent {
697
- if info .pnpData != nil {
698
- if result , ok := r .pnpResolve (importPath , sourceDirInfo .absPath , info .pnpData ); ok {
699
- importPath = result // Continue with the module resolution algorithm from node.js
700
- } else {
701
- return nil // This is a module resolution error
702
- }
703
- break
724
+ // If Yarn PnP is active, use it to rewrite the path
725
+ if r .pnpManifest != nil {
726
+ if result , ok := r .pnpResolve (importPath , sourceDirInfo .absPath , r .pnpManifest ); ok {
727
+ importPath = result // Continue with the module resolution algorithm from node.js
728
+ } else {
729
+ return nil // This is a module resolution error
704
730
}
705
731
}
706
732
@@ -860,8 +886,8 @@ type dirInfo struct {
860
886
861
887
// All relevant information about this directory
862
888
absPath string
889
+ pnpManifestAbsPath string
863
890
entries fs.DirEntries
864
- pnpData * pnpData
865
891
packageJSON * packageJSON // Is there a "package.json" file in this directory?
866
892
enclosingPackageJSON * packageJSON // Is there a "package.json" file in this directory or a parent directory?
867
893
enclosingTSConfigJSON * TSConfigJSON // Is there a "tsconfig.json" file in this directory or a parent directory?
@@ -944,38 +970,45 @@ func (r resolverQuery) parseTSConfig(file string, visited map[string]bool) (*TSC
944
970
945
971
// Check for a Yarn PnP manifest and use that to rewrite the path
946
972
if IsPackagePath (extends ) {
947
- current := fileDir
948
- for {
949
- if _ , _ , ok := fs .ParseYarnPnPVirtualPath (current ); ! ok {
950
- var pnpData * pnpData
951
- absPath := r .fs .Join (current , ".pnp.data.json" )
952
- if json := r .extractYarnPnPDataFromJSON (absPath , pnpIgnoreErrorsAboutMissingFiles ); json .Data != nil {
953
- pnpData = compileYarnPnPData (absPath , current , json )
954
- } else {
955
- absPath := r .fs .Join (current , ".pnp.cjs" )
973
+ pnpData := r .pnpManifest
974
+
975
+ // If we haven't loaded the Yarn PnP manifest yet, try to find one
976
+ if pnpData == nil {
977
+ current := fileDir
978
+ for {
979
+ if _ , _ , ok := fs .ParseYarnPnPVirtualPath (current ); ! ok {
980
+ absPath := r .fs .Join (current , ".pnp.data.json" )
956
981
if json := r .extractYarnPnPDataFromJSON (absPath , pnpIgnoreErrorsAboutMissingFiles ); json .Data != nil {
957
982
pnpData = compileYarnPnPData (absPath , current , json )
958
- } else {
959
- absPath := r .fs .Join (current , ".pnp.js" )
960
- if json := r .extractYarnPnPDataFromJSON (absPath , pnpIgnoreErrorsAboutMissingFiles ); json .Data != nil {
961
- pnpData = compileYarnPnPData (absPath , current , json )
962
- }
983
+ break
963
984
}
964
- }
965
- if pnpData != nil {
966
- if result , ok := r .pnpResolve (extends , current , pnpData ); ok {
967
- extends = result // Continue with the module resolution algorithm from node.js
985
+
986
+ absPath = r .fs .Join (current , ".pnp.cjs" )
987
+ if json := r .extractYarnPnPDataFromJSON (absPath , pnpIgnoreErrorsAboutMissingFiles ); json .Data != nil {
988
+ pnpData = compileYarnPnPData (absPath , current , json )
989
+ break
968
990
}
991
+
992
+ absPath = r .fs .Join (current , ".pnp.js" )
993
+ if json := r .extractYarnPnPDataFromJSON (absPath , pnpIgnoreErrorsAboutMissingFiles ); json .Data != nil {
994
+ pnpData = compileYarnPnPData (absPath , current , json )
995
+ break
996
+ }
997
+ }
998
+
999
+ // Go to the parent directory, stopping at the file system root
1000
+ next := r .fs .Dir (current )
1001
+ if current == next {
969
1002
break
970
1003
}
1004
+ current = next
971
1005
}
1006
+ }
972
1007
973
- // Go to the parent directory, stopping at the file system root
974
- next := r .fs .Dir (current )
975
- if current == next {
976
- break
1008
+ if pnpData != nil {
1009
+ if result , ok := r .pnpResolve (extends , fileDir , pnpData ); ok {
1010
+ extends = result // Continue with the module resolution algorithm from node.js
977
1011
}
978
- current = next
979
1012
}
980
1013
}
981
1014
@@ -1251,21 +1284,14 @@ func (r resolverQuery) dirInfoUncached(path string) *dirInfo {
1251
1284
//
1252
1285
// /project/.yarn/__virtual__/pkg/1/.yarn/__virtual__/pkg/1/bar
1253
1286
//
1254
- if _ , _ , ok := fs .ParseYarnPnPVirtualPath (path ); ! ok {
1255
- if pnp , _ := entries .Get (".pnp.data.json" ); pnp != nil && pnp .Kind (r .fs ) == fs .FileEntry {
1256
- absPath := r .fs .Join (path , ".pnp.data.json" )
1257
- if json := r .extractYarnPnPDataFromJSON (absPath , pnpReportErrorsAboutMissingFiles ); json .Data != nil {
1258
- info .pnpData = compileYarnPnPData (absPath , path , json )
1259
- }
1260
- } else if pnp , _ := entries .Get (".pnp.cjs" ); pnp != nil && pnp .Kind (r .fs ) == fs .FileEntry {
1261
- absPath := r .fs .Join (path , ".pnp.cjs" )
1262
- if json := r .tryToExtractYarnPnPDataFromJS (absPath , pnpReportErrorsAboutMissingFiles ); json .Data != nil {
1263
- info .pnpData = compileYarnPnPData (absPath , path , json )
1264
- }
1265
- } else if pnp , _ := entries .Get (".pnp.js" ); pnp != nil && pnp .Kind (r .fs ) == fs .FileEntry {
1266
- absPath := r .fs .Join (path , ".pnp.js" )
1267
- if json := r .tryToExtractYarnPnPDataFromJS (absPath , pnpReportErrorsAboutMissingFiles ); json .Data != nil {
1268
- info .pnpData = compileYarnPnPData (absPath , path , json )
1287
+ if r .pnpManifest == nil {
1288
+ if _ , _ , ok := fs .ParseYarnPnPVirtualPath (path ); ! ok {
1289
+ if pnp , _ := entries .Get (".pnp.data.json" ); pnp != nil && pnp .Kind (r .fs ) == fs .FileEntry {
1290
+ info .pnpManifestAbsPath = r .fs .Join (path , ".pnp.data.json" )
1291
+ } else if pnp , _ := entries .Get (".pnp.cjs" ); pnp != nil && pnp .Kind (r .fs ) == fs .FileEntry {
1292
+ info .pnpManifestAbsPath = r .fs .Join (path , ".pnp.cjs" )
1293
+ } else if pnp , _ := entries .Get (".pnp.js" ); pnp != nil && pnp .Kind (r .fs ) == fs .FileEntry {
1294
+ info .pnpManifestAbsPath = r .fs .Join (path , ".pnp.js" )
1269
1295
}
1270
1296
}
1271
1297
}
0 commit comments