@@ -112,6 +112,7 @@ export interface ResolutionCache extends Required<CompilerHostSupportingResoluti
112112 resolutionsWithFailedLookups : Set < ResolutionWithFailedLookupLocations > ;
113113 resolutionsWithOnlyAffectingLocations : Set < ResolutionWithFailedLookupLocations > ;
114114 packageJsonRefCount : Map < Path , number > ;
115+ watchedResolutionInfoMap : Map < ResolutionWithFailedLookupLocations , WatchedResolutionInfo > ;
115116 directoryWatchesOfFailedLookups : Map < Path , DirectoryWatchesOfFailedLookup > ;
116117 fileWatchesOfAffectingLocations : Map < string , FileWatcherOfAffectingLocation > ;
117118 packageDirWatchers : Map < Path , PackageDirWatcher > ;
@@ -190,10 +191,10 @@ export interface RootDirInfo {
190191}
191192
192193/** @internal */
193- export interface WatchedResolutionWithFailedLookupLocations {
194+ export interface WatchedResolutionInfo {
194195 isInvalidated ?: boolean ;
195196 // Files that have this resolution using
196- files ? : Set < Path > ;
197+ files : Set < Path > ;
197198 watchedFailed ?: number ;
198199 watchedAffected ?: number ;
199200 setAtRoot ?: boolean ;
@@ -209,15 +210,6 @@ export type ResolutionWithFailedLookupLocations =
209210 & Pick < ResolvedModuleWithFailedLookupLocations , "alternateResult" | "globalCacheResolution" >
210211 ) ;
211212
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-
221213/** @internal */
222214export interface ResolutionCacheHost extends MinimalResolutionCacheHost {
223215 toPath ( fileName : string ) : Path ;
@@ -249,6 +241,7 @@ export interface ResolutionCacheHost extends MinimalResolutionCacheHost {
249241 result : ResolvedModuleWithFailedLookupLocations ,
250242 data : any ,
251243 ) : any ;
244+ getRootDirInfoForResolution ?( resolution : ResolutionWithFailedLookupLocations ) : RootDirInfo ;
252245}
253246
254247/** @internal */
@@ -649,6 +642,7 @@ export function createResolutionCache(
649642 const resolutionsWithOnlyAffectingLocations = new Set < ResolutionWithFailedLookupLocations > ( ) ;
650643 const resolvedFileToResolution = new Map < Path , Set < ResolutionWithFailedLookupLocations > > ( ) ;
651644 const impliedFormatPackageJsons = new Map < Path , readonly string [ ] > ( ) ;
645+ const watchedResolutionInfoMap = new Map < ResolutionWithFailedLookupLocations , WatchedResolutionInfo > ( ) ;
652646
653647 let hasChangedAutomaticTypeDirectiveNames = false ;
654648 let affectingPathChecksForFile : Set < string > | undefined ;
@@ -664,6 +658,7 @@ export function createResolutionCache(
664658 let potentiallyUnreferencedResolutions : Map < ModuleOrTypeReferenceResolutionCache < ResolutionWithFailedLookupLocations > , Set < ResolutionWithFailedLookupLocations > > | undefined ;
665659 let potentiallyUnreferencedDirWatchers : Set < Path > | undefined ;
666660 let newUnresolvedResolutionCachePassResolutions : Set < ResolutionWithFailedLookupLocations > | undefined ;
661+ let considerNonWatchedResolutionAsInvalidated = false ;
667662
668663 const getCurrentDirectory = memoize ( ( ) => resolutionHost . getCurrentDirectory ! ( ) ) ;
669664 const cachedDirectoryStructureHost = resolutionHost . getCachedDirectoryStructureHost ( ) ;
@@ -730,6 +725,7 @@ export function createResolutionCache(
730725 resolutionsWithFailedLookups,
731726 resolutionsWithOnlyAffectingLocations,
732727 packageJsonRefCount,
728+ watchedResolutionInfoMap,
733729 directoryWatchesOfFailedLookups,
734730 fileWatchesOfAffectingLocations,
735731 packageDirWatchers,
@@ -816,6 +812,7 @@ export function createResolutionCache(
816812 resolvedFileToResolution . clear ( ) ;
817813 resolutionsWithFailedLookups . clear ( ) ;
818814 resolutionsWithOnlyAffectingLocations . clear ( ) ;
815+ watchedResolutionInfoMap . clear ( ) ;
819816 resolutionsResolvedWithGlobalCache = 0 ;
820817 resolutionsResolvedWithoutGlobalCache = 0 ;
821818 failedLookupChecks = undefined ;
@@ -857,7 +854,7 @@ export function createResolutionCache(
857854 ! ! collected ?. has ( path ) ,
858855 hasInvalidatedLibResolutions : libFileName =>
859856 customHasInvalidatedLibResolutions ( libFileName ) ||
860- ! ! resolvedLibraries ?. get ( libFileName ) ?. isInvalidated ,
857+ ! ! watchedResolutionInfoMap . get ( resolvedLibraries ?. get ( libFileName ) ! ) ?. isInvalidated ,
861858 } ;
862859 }
863860
@@ -969,16 +966,13 @@ export function createResolutionCache(
969966 cache : ModuleOrTypeReferenceResolutionCache < ResolutionWithFailedLookupLocations > ,
970967 ) {
971968 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 ) ;
977970 if ( needsGc ) {
971+ considerNonWatchedResolutionAsInvalidated = true ;
978972 // Iterate through maps to remove things that have 0 refCount
979973 cache . directoryToModuleNameMap . forEach ( ( resolutions , dir , redirectsCacheKey , directoryToModuleNameMap ) => {
980974 resolutions . forEach ( ( resolution , name , mode , key ) => {
981- if ( resolution . files ?. size ) return ;
975+ if ( watchedResolutionInfoMap . has ( resolution ) ) return ;
982976 resolutions . delete ( name , mode ) ;
983977 if ( ! isExternalModuleNameRelative ( name ) ) {
984978 const moduleNameToDirectoryMap = ! redirectsCacheKey ?
@@ -991,6 +985,7 @@ export function createResolutionCache(
991985 } ) ;
992986 if ( ! resolutions . size ( ) ) directoryToModuleNameMap . delete ( dir ) ;
993987 } ) ;
988+ considerNonWatchedResolutionAsInvalidated = false ;
994989 }
995990 }
996991
@@ -1044,7 +1039,8 @@ export function createResolutionCache(
10441039
10451040 function isInvalidatedResolution ( resolution : ResolutionWithFailedLookupLocations | undefined ) {
10461041 return ! resolution ||
1047- resolution . isInvalidated ||
1042+ ( considerNonWatchedResolutionAsInvalidated && ! watchedResolutionInfoMap . has ( resolution ) ) ||
1043+ watchedResolutionInfoMap . get ( resolution ) ?. isInvalidated ||
10481044 ( resolutionsWithGlobalCachePassAreInvalidated && isResolvedWithGlobalCachePass ( resolution ) ) ||
10491045 ( resolutionsWithoutGlobalCachePassAreInvalidated && isResolvedWithoutGlobalCachePass ( resolution ) ) ||
10501046 // If this is not a new resolution and its unresolved, its invalid
@@ -1150,7 +1146,7 @@ export function createResolutionCache(
11501146 ) ;
11511147 }
11521148 }
1153- Debug . assert ( resolution !== undefined && ! resolution . isInvalidated ) ;
1149+ Debug . assert ( resolution !== undefined && ! watchedResolutionInfoMap . get ( resolution ) ! . isInvalidated ) ;
11541150 seenNamesInFile . set ( name , mode , true ) ;
11551151 resolvedModules . push ( resolution ) ;
11561152 }
@@ -1349,7 +1345,7 @@ export function createResolutionCache(
13491345 const path = resolutionHost . toPath ( containingFile ) ;
13501346 const resolutionsInFile = resolvedModuleNames . get ( path ) ;
13511347 const resolution = resolutionsInFile ?. get ( moduleName , /*mode*/ undefined ) ;
1352- if ( resolution && ! resolution . isInvalidated ) return resolution ;
1348+ if ( resolution && ! watchedResolutionInfoMap . get ( resolution ) ! . isInvalidated ) return resolution ;
13531349 const data = resolutionHost . beforeResolveSingleModuleNameWithoutWatching ?.( moduleResolutionCache ) ;
13541350 const host = getModuleResolutionHost ( resolutionHost ) ;
13551351 // 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(
13741370 getResolutionWithResolvedFileName : GetResolutionWithResolvedFileName < T , R > ,
13751371 redirectedReference : ResolvedProjectReference | undefined ,
13761372 ) {
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 ) ;
13811383 if ( ! firstTime ) return ;
13821384 if ( resolution . globalCacheResolution && ! resolution . globalCacheResolution . resolution . resolvedModule ) {
13831385 // Add to potentially unreferenced resolutions
@@ -1437,61 +1439,66 @@ export function createResolutionCache(
14371439 function watchFailedLookupLocationOfResolution (
14381440 resolution : ResolutionWithFailedLookupLocations ,
14391441 redirectedReference : ResolvedProjectReference | undefined ,
1442+ watchedResolutionInfo : WatchedResolutionInfo ,
14401443 ) {
1441- Debug . assert ( ! ! resolution . files ?. size ) ;
1442- const { failedLookupLocations, alternateResult, watchedFailed } = resolution ;
1444+ const { failedLookupLocations, alternateResult } = resolution ;
14431445 // There have to be failed lookup locations if there is alternateResult so storing failedLookupLocation length is good enough,
14441446 // 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 ) {
14471449 resolutionsWithFailedLookups . add ( resolution ) ;
1448- if ( resolution . watchedAffected ) resolutionsWithOnlyAffectingLocations . delete ( resolution ) ;
1450+ if ( watchedResolutionInfo . watchedAffected ) resolutionsWithOnlyAffectingLocations . delete ( resolution ) ;
14491451 }
14501452
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 ++ ) {
14531455 setAtRoot = watchFailedLookupLocation (
14541456 failedLookupLocations ! [ i ] ,
1455- getRootDirInfoForResolution ( resolution , redirectedReference ) ,
1457+ getRootDirInfoForResolution ( resolution , redirectedReference , watchedResolutionInfo ) ,
14561458 ) || setAtRoot ;
14571459 }
1458- if ( ! watchedFailed && alternateResult ) {
1460+ if ( ! watchedResolutionInfo . watchedFailed && alternateResult ) {
14591461 setAtRoot = watchFailedLookupLocation (
14601462 alternateResult ,
1461- getRootDirInfoForResolution ( resolution , redirectedReference ) ,
1463+ getRootDirInfoForResolution ( resolution , redirectedReference , watchedResolutionInfo ) ,
14621464 ) || setAtRoot ;
14631465 }
1464- if ( ! resolution . setAtRoot && setAtRoot ) {
1466+ if ( ! watchedResolutionInfo . setAtRoot && setAtRoot ) {
14651467 // This is always non recursive
14661468 setDirectoryWatcher (
1467- getRootDirInfoForResolution ( resolution , redirectedReference ) . rootDir ,
1468- getRootDirInfoForResolution ( resolution , redirectedReference ) . rootPath ,
1469+ getRootDirInfoForResolution ( resolution , redirectedReference , watchedResolutionInfo ) . rootDir ,
1470+ getRootDirInfoForResolution ( resolution , redirectedReference , watchedResolutionInfo ) . rootPath ,
14691471 /*packageDir*/ undefined ,
14701472 /*packageDirPath*/ undefined ,
14711473 /*nonRecursive*/ true ,
14721474 ) ;
14731475 }
1474- resolution . watchedFailed = failedLookupLocations ?. length ;
1475- resolution . setAtRoot = setAtRoot ;
1476+ watchedResolutionInfo . watchedFailed = failedLookupLocations ?. length ;
1477+ watchedResolutionInfo . setAtRoot = setAtRoot ;
14761478 }
14771479
14781480 function getRootDirInfoForResolution (
14791481 resolution : ResolutionWithFailedLookupLocations ,
14801482 redirectedReference : ResolvedProjectReference | undefined ,
1483+ watchedResolutionInfo : WatchedResolutionInfo ,
14811484 ) {
1482- return resolution . rootDirInfo ??= getRootDirInfoOfRedirectedReference ( redirectedReference ) ;
1485+ return watchedResolutionInfo . rootDirInfo ??= ! resolutionHost . getRootDirInfoForResolution ?
1486+ getRootDirInfoOfRedirectedReference ( redirectedReference ) :
1487+ resolutionHost . getRootDirInfoForResolution ( resolution ) ;
14831488 }
14841489
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 ) ;
14901497 // Watch package json
1491- for ( let i = watchedAffected || 0 ; i < affectingLocations ! . length ; i ++ ) {
1498+ for ( let i = watchedResolutionInfo . watchedAffected || 0 ; i < affectingLocations ! . length ; i ++ ) {
14921499 createFileWatcherOfAffectingLocation ( affectingLocations ! [ i ] , /*forResolution*/ true ) ;
14931500 }
1494- resolution . watchedAffected = affectingLocations ?. length ;
1501+ watchedResolutionInfo . watchedAffected = affectingLocations ?. length ;
14951502 }
14961503
14971504 function createFileWatcherOfAffectingLocation ( affectingLocation : string , forResolution : boolean ) {
@@ -1693,18 +1700,18 @@ export function createResolutionCache(
16931700 filePath : Path ,
16941701 cache : ModuleOrTypeReferenceResolutionCache < ResolutionWithFailedLookupLocations > ,
16951702 ) {
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 ;
16991706 let setOfResolutions = potentiallyUnreferencedResolutions ?. get ( cache ) ;
17001707 if ( ! setOfResolutions ) ( potentiallyUnreferencedResolutions ??= new Map ( ) ) . set ( cache , setOfResolutions = new Set ( ) ) ;
17011708 setOfResolutions . add ( resolution ) ;
17021709 }
17031710
17041711 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 ) ;
17081715 if ( isResolvedWithGlobalCachePass ( resolution ) ) resolutionsResolvedWithGlobalCache -- ;
17091716 else if ( isResolvedWithoutGlobalCachePass ( resolution ) ) resolutionsResolvedWithoutGlobalCache -- ;
17101717 const resolved = getModuleOrTypeRefResolved ( resolution ) ;
@@ -1714,7 +1721,8 @@ export function createResolutionCache(
17141721 if ( resolutions ?. delete ( resolution ) && ! resolutions . size ) resolvedFileToResolution . delete ( key ) ;
17151722 }
17161723
1717- const { failedLookupLocations, affectingLocations, alternateResult, setAtRoot, rootDirInfo } = resolution ;
1724+ const { failedLookupLocations, affectingLocations, alternateResult } = resolution ;
1725+ const { setAtRoot, rootDirInfo } = watchedResolutionInfo ;
17181726 if ( resolutionsWithFailedLookups . delete ( resolution ) ) {
17191727 if ( failedLookupLocations ) {
17201728 for ( const failedLookupLocation of failedLookupLocations ) {
@@ -1735,6 +1743,7 @@ export function createResolutionCache(
17351743 closeFileWatcherOfAffectingLocation ( watcher , affectingLocation ) ;
17361744 }
17371745 }
1746+ return true ;
17381747 }
17391748
17401749 function removeDirectoryWatcher ( dirPath : Path , delayed : boolean ) {
@@ -1799,9 +1808,10 @@ export function createResolutionCache(
17991808 if ( ! resolutions ) return false ;
18001809 let invalidated = false ;
18011810 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 ) {
18051815 ( filesWithInvalidatedResolutions ??= new Set ( ) ) . add ( containingFilePath ) ;
18061816 // When its a file with inferred types resolution, invalidate type reference directive resolution
18071817 hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames || endsWith ( containingFilePath , inferredTypesContainingFile ) ;
0 commit comments