@@ -112,6 +112,7 @@ export interface ResolutionCache extends Required<CompilerHostSupportingResoluti
112
112
resolutionsWithFailedLookups : Set < ResolutionWithFailedLookupLocations > ;
113
113
resolutionsWithOnlyAffectingLocations : Set < ResolutionWithFailedLookupLocations > ;
114
114
packageJsonRefCount : Map < Path , number > ;
115
+ watchedResolutionInfoMap : Map < ResolutionWithFailedLookupLocations , WatchedResolutionInfo > ;
115
116
directoryWatchesOfFailedLookups : Map < Path , DirectoryWatchesOfFailedLookup > ;
116
117
fileWatchesOfAffectingLocations : Map < string , FileWatcherOfAffectingLocation > ;
117
118
packageDirWatchers : Map < Path , PackageDirWatcher > ;
@@ -190,10 +191,10 @@ export interface RootDirInfo {
190
191
}
191
192
192
193
/** @internal */
193
- export interface WatchedResolutionWithFailedLookupLocations {
194
+ export interface WatchedResolutionInfo {
194
195
isInvalidated ?: boolean ;
195
196
// Files that have this resolution using
196
- files ? : Set < Path > ;
197
+ files : Set < Path > ;
197
198
watchedFailed ?: number ;
198
199
watchedAffected ?: number ;
199
200
setAtRoot ?: boolean ;
@@ -209,15 +210,6 @@ export type ResolutionWithFailedLookupLocations =
209
210
& Pick < ResolvedModuleWithFailedLookupLocations , "alternateResult" | "globalCacheResolution" >
210
211
) ;
211
212
212
- declare module "./types.js" {
213
- /** @internal */
214
- export interface ResolvedModuleWithFailedLookupLocations extends WatchedResolutionWithFailedLookupLocations {
215
- }
216
- /** @internal */
217
- export interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations extends WatchedResolutionWithFailedLookupLocations {
218
- }
219
- }
220
-
221
213
/** @internal */
222
214
export interface ResolutionCacheHost extends MinimalResolutionCacheHost {
223
215
toPath ( fileName : string ) : Path ;
@@ -249,6 +241,7 @@ export interface ResolutionCacheHost extends MinimalResolutionCacheHost {
249
241
result : ResolvedModuleWithFailedLookupLocations ,
250
242
data : any ,
251
243
) : any ;
244
+ getRootDirInfoForResolution ?( resolution : ResolutionWithFailedLookupLocations ) : RootDirInfo ;
252
245
}
253
246
254
247
/** @internal */
@@ -649,6 +642,7 @@ export function createResolutionCache(
649
642
const resolutionsWithOnlyAffectingLocations = new Set < ResolutionWithFailedLookupLocations > ( ) ;
650
643
const resolvedFileToResolution = new Map < Path , Set < ResolutionWithFailedLookupLocations > > ( ) ;
651
644
const impliedFormatPackageJsons = new Map < Path , readonly string [ ] > ( ) ;
645
+ const watchedResolutionInfoMap = new Map < ResolutionWithFailedLookupLocations , WatchedResolutionInfo > ( ) ;
652
646
653
647
let hasChangedAutomaticTypeDirectiveNames = false ;
654
648
let affectingPathChecksForFile : Set < string > | undefined ;
@@ -664,6 +658,7 @@ export function createResolutionCache(
664
658
let potentiallyUnreferencedResolutions : Map < ModuleOrTypeReferenceResolutionCache < ResolutionWithFailedLookupLocations > , Set < ResolutionWithFailedLookupLocations > > | undefined ;
665
659
let potentiallyUnreferencedDirWatchers : Set < Path > | undefined ;
666
660
let newUnresolvedResolutionCachePassResolutions : Set < ResolutionWithFailedLookupLocations > | undefined ;
661
+ let considerNonWatchedResolutionAsInvalidated = false ;
667
662
668
663
const getCurrentDirectory = memoize ( ( ) => resolutionHost . getCurrentDirectory ! ( ) ) ;
669
664
const cachedDirectoryStructureHost = resolutionHost . getCachedDirectoryStructureHost ( ) ;
@@ -730,6 +725,7 @@ export function createResolutionCache(
730
725
resolutionsWithFailedLookups,
731
726
resolutionsWithOnlyAffectingLocations,
732
727
packageJsonRefCount,
728
+ watchedResolutionInfoMap,
733
729
directoryWatchesOfFailedLookups,
734
730
fileWatchesOfAffectingLocations,
735
731
packageDirWatchers,
@@ -816,6 +812,7 @@ export function createResolutionCache(
816
812
resolvedFileToResolution . clear ( ) ;
817
813
resolutionsWithFailedLookups . clear ( ) ;
818
814
resolutionsWithOnlyAffectingLocations . clear ( ) ;
815
+ watchedResolutionInfoMap . clear ( ) ;
819
816
resolutionsResolvedWithGlobalCache = 0 ;
820
817
resolutionsResolvedWithoutGlobalCache = 0 ;
821
818
failedLookupChecks = undefined ;
@@ -857,7 +854,7 @@ export function createResolutionCache(
857
854
! ! collected ?. has ( path ) ,
858
855
hasInvalidatedLibResolutions : libFileName =>
859
856
customHasInvalidatedLibResolutions ( libFileName ) ||
860
- ! ! resolvedLibraries ?. get ( libFileName ) ?. isInvalidated ,
857
+ ! ! watchedResolutionInfoMap . get ( resolvedLibraries ?. get ( libFileName ) ! ) ?. isInvalidated ,
861
858
} ;
862
859
}
863
860
@@ -969,16 +966,13 @@ export function createResolutionCache(
969
966
cache : ModuleOrTypeReferenceResolutionCache < ResolutionWithFailedLookupLocations > ,
970
967
) {
971
968
let needsGc = false ;
972
- setOfResolutions . forEach ( resolution => {
973
- if ( resolution . files ! . size ) return ;
974
- needsGc = true ;
975
- releaseResolution ( resolution ) ;
976
- } ) ;
969
+ setOfResolutions . forEach ( resolution => needsGc = releaseResolution ( resolution ) || needsGc ) ;
977
970
if ( needsGc ) {
971
+ considerNonWatchedResolutionAsInvalidated = true ;
978
972
// Iterate through maps to remove things that have 0 refCount
979
973
cache . directoryToModuleNameMap . forEach ( ( resolutions , dir , redirectsCacheKey , directoryToModuleNameMap ) => {
980
974
resolutions . forEach ( ( resolution , name , mode , key ) => {
981
- if ( resolution . files ?. size ) return ;
975
+ if ( watchedResolutionInfoMap . has ( resolution ) ) return ;
982
976
resolutions . delete ( name , mode ) ;
983
977
if ( ! isExternalModuleNameRelative ( name ) ) {
984
978
const moduleNameToDirectoryMap = ! redirectsCacheKey ?
@@ -991,6 +985,7 @@ export function createResolutionCache(
991
985
} ) ;
992
986
if ( ! resolutions . size ( ) ) directoryToModuleNameMap . delete ( dir ) ;
993
987
} ) ;
988
+ considerNonWatchedResolutionAsInvalidated = false ;
994
989
}
995
990
}
996
991
@@ -1044,7 +1039,8 @@ export function createResolutionCache(
1044
1039
1045
1040
function isInvalidatedResolution ( resolution : ResolutionWithFailedLookupLocations | undefined ) {
1046
1041
return ! resolution ||
1047
- resolution . isInvalidated ||
1042
+ ( considerNonWatchedResolutionAsInvalidated && ! watchedResolutionInfoMap . has ( resolution ) ) ||
1043
+ watchedResolutionInfoMap . get ( resolution ) ?. isInvalidated ||
1048
1044
( resolutionsWithGlobalCachePassAreInvalidated && isResolvedWithGlobalCachePass ( resolution ) ) ||
1049
1045
( resolutionsWithoutGlobalCachePassAreInvalidated && isResolvedWithoutGlobalCachePass ( resolution ) ) ||
1050
1046
// If this is not a new resolution and its unresolved, its invalid
@@ -1150,7 +1146,7 @@ export function createResolutionCache(
1150
1146
) ;
1151
1147
}
1152
1148
}
1153
- Debug . assert ( resolution !== undefined && ! resolution . isInvalidated ) ;
1149
+ Debug . assert ( resolution !== undefined && ! watchedResolutionInfoMap . get ( resolution ) ! . isInvalidated ) ;
1154
1150
seenNamesInFile . set ( name , mode , true ) ;
1155
1151
resolvedModules . push ( resolution ) ;
1156
1152
}
@@ -1349,7 +1345,7 @@ export function createResolutionCache(
1349
1345
const path = resolutionHost . toPath ( containingFile ) ;
1350
1346
const resolutionsInFile = resolvedModuleNames . get ( path ) ;
1351
1347
const resolution = resolutionsInFile ?. get ( moduleName , /*mode*/ undefined ) ;
1352
- if ( resolution && ! resolution . isInvalidated ) return resolution ;
1348
+ if ( resolution && ! watchedResolutionInfoMap . get ( resolution ) ! . isInvalidated ) return resolution ;
1353
1349
const data = resolutionHost . beforeResolveSingleModuleNameWithoutWatching ?.( moduleResolutionCache ) ;
1354
1350
const host = getModuleResolutionHost ( resolutionHost ) ;
1355
1351
// We are not resolving d.ts so just normal resolution instead of doing resolution pass to global cache
@@ -1374,10 +1370,16 @@ export function createResolutionCache(
1374
1370
getResolutionWithResolvedFileName : GetResolutionWithResolvedFileName < T , R > ,
1375
1371
redirectedReference : ResolvedProjectReference | undefined ,
1376
1372
) {
1377
- const firstTime = ! resolution . files ;
1378
- ( resolution . files ??= new Set ( ) ) . add ( filePath ) ;
1379
- watchFailedLookupLocationOfResolution ( resolution , redirectedReference ) ;
1380
- watchAffectingLocationsOfResolution ( resolution ) ;
1373
+ let watchedResolutionInfo = watchedResolutionInfoMap . get ( resolution ) ;
1374
+ const firstTime = ! watchedResolutionInfo ;
1375
+ if ( ! watchedResolutionInfo ) {
1376
+ watchedResolutionInfoMap . set ( resolution , watchedResolutionInfo = { files : new Set ( [ filePath ] ) } ) ;
1377
+ }
1378
+ else {
1379
+ watchedResolutionInfo . files . add ( filePath ) ;
1380
+ }
1381
+ watchFailedLookupLocationOfResolution ( resolution , redirectedReference , watchedResolutionInfo ) ;
1382
+ watchAffectingLocationsOfResolution ( resolution , watchedResolutionInfo ) ;
1381
1383
if ( ! firstTime ) return ;
1382
1384
if ( resolution . globalCacheResolution && ! resolution . globalCacheResolution . resolution . resolvedModule ) {
1383
1385
// Add to potentially unreferenced resolutions
@@ -1437,61 +1439,66 @@ export function createResolutionCache(
1437
1439
function watchFailedLookupLocationOfResolution (
1438
1440
resolution : ResolutionWithFailedLookupLocations ,
1439
1441
redirectedReference : ResolvedProjectReference | undefined ,
1442
+ watchedResolutionInfo : WatchedResolutionInfo ,
1440
1443
) {
1441
- Debug . assert ( ! ! resolution . files ?. size ) ;
1442
- const { failedLookupLocations, alternateResult, watchedFailed } = resolution ;
1444
+ const { failedLookupLocations, alternateResult } = resolution ;
1443
1445
// There have to be failed lookup locations if there is alternateResult so storing failedLookupLocation length is good enough,
1444
1446
// alternateResult doesnt change later only failed lookup locations get added on
1445
- if ( watchedFailed === failedLookupLocations ?. length ) return ;
1446
- if ( ! watchedFailed ) {
1447
+ if ( watchedResolutionInfo . watchedFailed === failedLookupLocations ?. length ) return ;
1448
+ if ( ! watchedResolutionInfo . watchedFailed ) {
1447
1449
resolutionsWithFailedLookups . add ( resolution ) ;
1448
- if ( resolution . watchedAffected ) resolutionsWithOnlyAffectingLocations . delete ( resolution ) ;
1450
+ if ( watchedResolutionInfo . watchedAffected ) resolutionsWithOnlyAffectingLocations . delete ( resolution ) ;
1449
1451
}
1450
1452
1451
- let setAtRoot = ! ! resolution . setAtRoot ;
1452
- for ( let i = watchedFailed || 0 ; i < failedLookupLocations ! . length ; i ++ ) {
1453
+ let setAtRoot = ! ! watchedResolutionInfo . setAtRoot ;
1454
+ for ( let i = watchedResolutionInfo . watchedFailed || 0 ; i < failedLookupLocations ! . length ; i ++ ) {
1453
1455
setAtRoot = watchFailedLookupLocation (
1454
1456
failedLookupLocations ! [ i ] ,
1455
- getRootDirInfoForResolution ( resolution , redirectedReference ) ,
1457
+ getRootDirInfoForResolution ( resolution , redirectedReference , watchedResolutionInfo ) ,
1456
1458
) || setAtRoot ;
1457
1459
}
1458
- if ( ! watchedFailed && alternateResult ) {
1460
+ if ( ! watchedResolutionInfo . watchedFailed && alternateResult ) {
1459
1461
setAtRoot = watchFailedLookupLocation (
1460
1462
alternateResult ,
1461
- getRootDirInfoForResolution ( resolution , redirectedReference ) ,
1463
+ getRootDirInfoForResolution ( resolution , redirectedReference , watchedResolutionInfo ) ,
1462
1464
) || setAtRoot ;
1463
1465
}
1464
- if ( ! resolution . setAtRoot && setAtRoot ) {
1466
+ if ( ! watchedResolutionInfo . setAtRoot && setAtRoot ) {
1465
1467
// This is always non recursive
1466
1468
setDirectoryWatcher (
1467
- getRootDirInfoForResolution ( resolution , redirectedReference ) . rootDir ,
1468
- getRootDirInfoForResolution ( resolution , redirectedReference ) . rootPath ,
1469
+ getRootDirInfoForResolution ( resolution , redirectedReference , watchedResolutionInfo ) . rootDir ,
1470
+ getRootDirInfoForResolution ( resolution , redirectedReference , watchedResolutionInfo ) . rootPath ,
1469
1471
/*packageDir*/ undefined ,
1470
1472
/*packageDirPath*/ undefined ,
1471
1473
/*nonRecursive*/ true ,
1472
1474
) ;
1473
1475
}
1474
- resolution . watchedFailed = failedLookupLocations ?. length ;
1475
- resolution . setAtRoot = setAtRoot ;
1476
+ watchedResolutionInfo . watchedFailed = failedLookupLocations ?. length ;
1477
+ watchedResolutionInfo . setAtRoot = setAtRoot ;
1476
1478
}
1477
1479
1478
1480
function getRootDirInfoForResolution (
1479
1481
resolution : ResolutionWithFailedLookupLocations ,
1480
1482
redirectedReference : ResolvedProjectReference | undefined ,
1483
+ watchedResolutionInfo : WatchedResolutionInfo ,
1481
1484
) {
1482
- return resolution . rootDirInfo ??= getRootDirInfoOfRedirectedReference ( redirectedReference ) ;
1485
+ return watchedResolutionInfo . rootDirInfo ??= ! resolutionHost . getRootDirInfoForResolution ?
1486
+ getRootDirInfoOfRedirectedReference ( redirectedReference ) :
1487
+ resolutionHost . getRootDirInfoForResolution ( resolution ) ;
1483
1488
}
1484
1489
1485
- function watchAffectingLocationsOfResolution ( resolution : ResolutionWithFailedLookupLocations ) {
1486
- Debug . assert ( ! ! resolution . files ?. size ) ;
1487
- const { affectingLocations, watchedAffected } = resolution ;
1488
- if ( affectingLocations ?. length === watchedAffected ) return ;
1489
- if ( ! watchedAffected && ! resolution . watchedFailed ) resolutionsWithOnlyAffectingLocations . add ( resolution ) ;
1490
+ function watchAffectingLocationsOfResolution (
1491
+ resolution : ResolutionWithFailedLookupLocations ,
1492
+ watchedResolutionInfo : WatchedResolutionInfo ,
1493
+ ) {
1494
+ const { affectingLocations } = resolution ;
1495
+ if ( affectingLocations ?. length === watchedResolutionInfo . watchedAffected ) return ;
1496
+ if ( ! watchedResolutionInfo . watchedAffected && ! watchedResolutionInfo . watchedFailed ) resolutionsWithOnlyAffectingLocations . add ( resolution ) ;
1490
1497
// Watch package json
1491
- for ( let i = watchedAffected || 0 ; i < affectingLocations ! . length ; i ++ ) {
1498
+ for ( let i = watchedResolutionInfo . watchedAffected || 0 ; i < affectingLocations ! . length ; i ++ ) {
1492
1499
createFileWatcherOfAffectingLocation ( affectingLocations ! [ i ] , /*forResolution*/ true ) ;
1493
1500
}
1494
- resolution . watchedAffected = affectingLocations ?. length ;
1501
+ watchedResolutionInfo . watchedAffected = affectingLocations ?. length ;
1495
1502
}
1496
1503
1497
1504
function createFileWatcherOfAffectingLocation ( affectingLocation : string , forResolution : boolean ) {
@@ -1693,18 +1700,18 @@ export function createResolutionCache(
1693
1700
filePath : Path ,
1694
1701
cache : ModuleOrTypeReferenceResolutionCache < ResolutionWithFailedLookupLocations > ,
1695
1702
) {
1696
- Debug . assertIsDefined ( resolution . files ) ;
1697
- resolution . files . delete ( filePath ) ;
1698
- if ( resolution . files . size ) return ;
1703
+ const watchedResolutionInfo = watchedResolutionInfoMap . get ( resolution ) ! ;
1704
+ watchedResolutionInfo . files . delete ( filePath ) ;
1705
+ if ( watchedResolutionInfo . files . size ) return ;
1699
1706
let setOfResolutions = potentiallyUnreferencedResolutions ?. get ( cache ) ;
1700
1707
if ( ! setOfResolutions ) ( potentiallyUnreferencedResolutions ??= new Map ( ) ) . set ( cache , setOfResolutions = new Set ( ) ) ;
1701
1708
setOfResolutions . add ( resolution ) ;
1702
1709
}
1703
1710
1704
1711
function releaseResolution ( resolution : ResolutionWithFailedLookupLocations ) {
1705
- resolution . files = undefined ;
1706
- // Even if this is in cache, we cant reuse this resolution after this since we are not watching it any more
1707
- resolution . isInvalidated = true ;
1712
+ const watchedResolutionInfo = watchedResolutionInfoMap . get ( resolution ) ! ;
1713
+ if ( watchedResolutionInfo . files . size ) return false ;
1714
+ watchedResolutionInfoMap . delete ( resolution ) ;
1708
1715
if ( isResolvedWithGlobalCachePass ( resolution ) ) resolutionsResolvedWithGlobalCache -- ;
1709
1716
else if ( isResolvedWithoutGlobalCachePass ( resolution ) ) resolutionsResolvedWithoutGlobalCache -- ;
1710
1717
const resolved = getModuleOrTypeRefResolved ( resolution ) ;
@@ -1714,7 +1721,8 @@ export function createResolutionCache(
1714
1721
if ( resolutions ?. delete ( resolution ) && ! resolutions . size ) resolvedFileToResolution . delete ( key ) ;
1715
1722
}
1716
1723
1717
- const { failedLookupLocations, affectingLocations, alternateResult, setAtRoot, rootDirInfo } = resolution ;
1724
+ const { failedLookupLocations, affectingLocations, alternateResult } = resolution ;
1725
+ const { setAtRoot, rootDirInfo } = watchedResolutionInfo ;
1718
1726
if ( resolutionsWithFailedLookups . delete ( resolution ) ) {
1719
1727
if ( failedLookupLocations ) {
1720
1728
for ( const failedLookupLocation of failedLookupLocations ) {
@@ -1735,6 +1743,7 @@ export function createResolutionCache(
1735
1743
closeFileWatcherOfAffectingLocation ( watcher , affectingLocation ) ;
1736
1744
}
1737
1745
}
1746
+ return true ;
1738
1747
}
1739
1748
1740
1749
function removeDirectoryWatcher ( dirPath : Path , delayed : boolean ) {
@@ -1799,9 +1808,10 @@ export function createResolutionCache(
1799
1808
if ( ! resolutions ) return false ;
1800
1809
let invalidated = false ;
1801
1810
resolutions . forEach ( resolution => {
1802
- if ( resolution . isInvalidated || ! canInvalidate ( resolution ) ) return ;
1803
- resolution . isInvalidated = invalidated = true ;
1804
- for ( const containingFilePath of Debug . checkDefined ( resolution . files ) ) {
1811
+ const watchedResolutionInfo = watchedResolutionInfoMap . get ( resolution ) ! ;
1812
+ if ( watchedResolutionInfo . isInvalidated || ! canInvalidate ( resolution ) ) return ;
1813
+ watchedResolutionInfo . isInvalidated = invalidated = true ;
1814
+ for ( const containingFilePath of watchedResolutionInfo . files ) {
1805
1815
( filesWithInvalidatedResolutions ??= new Set ( ) ) . add ( containingFilePath ) ;
1806
1816
// When its a file with inferred types resolution, invalidate type reference directive resolution
1807
1817
hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames || endsWith ( containingFilePath , inferredTypesContainingFile ) ;
0 commit comments