Skip to content

Commit cbca491

Browse files
committed
In preparation of sharing resolutions, watch the resolutions right away instead of defering external module reoslutions to watch all failed lookup locations
1 parent 11fefb1 commit cbca491

File tree

101 files changed

+362
-366
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+362
-366
lines changed

src/compiler/resolutionCache.ts

Lines changed: 34 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,10 @@ export interface ResolutionCache extends Required<CompilerHostSupportingResoluti
106106
startRecordingFilesWithChangedResolutions(): void;
107107
finishRecordingFilesWithChangedResolutions(): Path[] | undefined;
108108

109-
watchFailedLookupLocationsOfExternalModuleResolutions<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
110-
name: string,
109+
watchResolution<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
111110
resolution: T,
112111
filePath: Path,
113112
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
114-
deferWatchingNonRelativeResolution: boolean,
115113
): void;
116114

117115
resolveModuleNameLiterals(
@@ -171,10 +169,13 @@ export interface ResolutionCache extends Required<CompilerHostSupportingResoluti
171169
export interface ResolutionWithFailedLookupLocations {
172170
failedLookupLocations?: string[];
173171
affectingLocations?: string[];
172+
node10Result?: string;
174173
isInvalidated?: boolean;
175174
// Files that have this resolution using
176175
files?: Set<Path>;
177-
node10Result?: string;
176+
watchedFailed?: number;
177+
watchedAffected?: number;
178+
setAtRoot?: boolean;
178179
}
179180

180181
/** @internal */
@@ -501,7 +502,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
501502
let filesWithChangedSetOfUnresolvedImports: Path[] | undefined;
502503
let filesWithInvalidatedResolutions: Set<Path> | undefined;
503504
let filesWithInvalidatedNonRelativeUnresolvedImports: ReadonlyMap<Path, readonly string[]> | undefined;
504-
const nonRelativeExternalModuleResolutions = new Set<ResolutionWithFailedLookupLocations>();
505505

506506
const resolutionsWithFailedLookups = new Set<ResolutionWithFailedLookupLocations>();
507507
const resolutionsWithOnlyAffectingLocations = new Set<ResolutionWithFailedLookupLocations>();
@@ -564,7 +564,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
564564
resolutionsWithOnlyAffectingLocations,
565565
directoryWatchesOfFailedLookups,
566566
fileWatchesOfAffectingLocations,
567-
watchFailedLookupLocationsOfExternalModuleResolutions,
567+
watchResolution,
568568
getModuleResolutionCache: () => moduleResolutionCache,
569569
startRecordingFilesWithChangedResolutions,
570570
finishRecordingFilesWithChangedResolutions,
@@ -603,7 +603,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
603603
function clear() {
604604
clearMap(directoryWatchesOfFailedLookups, closeFileWatcherOf);
605605
clearMap(fileWatchesOfAffectingLocations, closeFileWatcherOf);
606-
nonRelativeExternalModuleResolutions.clear();
607606
closeTypeRootsWatch();
608607
resolvedModuleNames.clear();
609608
resolvedTypeReferenceDirectives.clear();
@@ -678,7 +677,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
678677
libraryResolutionCache.clearAllExceptPackageJsonInfoCache();
679678
// perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update
680679
// (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution)
681-
watchFailedLookupLocationOfNonRelativeModuleResolutions();
682680
}
683681

684682
function cleanupLibResolutionWatching(newProgram: Program | undefined) {
@@ -697,7 +695,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
697695
function finishCachingPerDirectoryResolution(newProgram: Program | undefined, oldProgram: Program | undefined) {
698696
filesWithInvalidatedNonRelativeUnresolvedImports = undefined;
699697
allModuleAndTypeResolutionsAreInvalidated = false;
700-
watchFailedLookupLocationOfNonRelativeModuleResolutions();
701698
// Update file watches
702699
if (newProgram !== oldProgram) {
703700
cleanupLibResolutionWatching(newProgram);
@@ -752,12 +749,11 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
752749
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>;
753750
shouldRetryResolution: (t: T) => boolean;
754751
logChanges?: boolean;
755-
deferWatchingNonRelativeResolution: boolean;
756752
}
757753
function resolveNamesWithLocalCache<Entry, SourceFile, T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>({
758754
entries, containingFile, containingSourceFile, redirectedReference, options,
759755
perFileCache, reusedNames, ambientModuleNames,
760-
loader, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution,
756+
loader, getResolutionWithResolvedFileName,
761757
shouldRetryResolution, logChanges,
762758
}: ResolveNamesWithLocalCacheInput<Entry, SourceFile, T, R>): readonly T[] {
763759
const path = resolutionHost.toPath(containingFile);
@@ -789,7 +785,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
789785
}
790786
resolutionsInFile.set(name, mode, resolution);
791787
if (resolution !== existingResolution) {
792-
watchFailedLookupLocationsOfExternalModuleResolutions(name, resolution, path, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution);
788+
watchResolution(resolution, path, getResolutionWithResolvedFileName);
793789
if (existingResolution) {
794790
stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolutionWithResolvedFileName);
795791
}
@@ -885,7 +881,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
885881
),
886882
getResolutionWithResolvedFileName: getResolvedTypeReferenceDirective,
887883
shouldRetryResolution: resolution => resolution.resolvedTypeReferenceDirective === undefined,
888-
deferWatchingNonRelativeResolution: false,
889884
});
890885
}
891886

@@ -917,7 +912,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
917912
getResolutionWithResolvedFileName: getResolvedModule,
918913
shouldRetryResolution: resolution => !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension),
919914
logChanges: logChangesWhenResolvingModule,
920-
deferWatchingNonRelativeResolution: true, // Defer non relative resolution watch because we could be using ambient modules
921915
});
922916
}
923917

@@ -933,7 +927,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
933927
const existingResolution = resolution;
934928
resolution = ts_resolveLibrary(libraryName, resolveFrom, options, host, libraryResolutionCache);
935929
const path = resolutionHost.toPath(resolveFrom);
936-
watchFailedLookupLocationsOfExternalModuleResolutions(libraryName, resolution, path, getResolvedModule, /*deferWatchingNonRelativeResolution*/ false);
930+
watchResolution(resolution, path, getResolvedModule);
937931
resolvedLibraries.set(libFileName, resolution);
938932
if (existingResolution) {
939933
stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolvedModule);
@@ -1064,21 +1058,15 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
10641058
return endsWith(dirPath, "/node_modules/@types");
10651059
}
10661060

1067-
function watchFailedLookupLocationsOfExternalModuleResolutions<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
1068-
name: string,
1061+
function watchResolution<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
10691062
resolution: T,
10701063
filePath: Path,
10711064
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
1072-
deferWatchingNonRelativeResolution: boolean,
10731065
) {
10741066
(resolution.files ??= new Set()).add(filePath);
1067+
watchFailedLookupLocationOfResolution(resolution);
1068+
watchAffectingLocationsOfResolution(resolution);
10751069
if (resolution.files.size !== 1) return;
1076-
if (!deferWatchingNonRelativeResolution || isExternalModuleNameRelative(name)) {
1077-
watchFailedLookupLocationOfResolution(resolution);
1078-
}
1079-
else {
1080-
nonRelativeExternalModuleResolutions.add(resolution);
1081-
}
10821070
const resolved = getResolutionWithResolvedFileName(resolution);
10831071
if (resolved && resolved.resolvedFileName) {
10841072
const key = resolutionHost.toPath(resolved.resolvedFileName);
@@ -1114,33 +1102,38 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
11141102
function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
11151103
Debug.assert(!!resolution.files?.size);
11161104

1117-
const { failedLookupLocations, affectingLocations, node10Result } = resolution;
1118-
if (!failedLookupLocations?.length && !affectingLocations?.length && !node10Result) return;
1119-
if (failedLookupLocations?.length || node10Result) resolutionsWithFailedLookups.add(resolution);
1105+
const { failedLookupLocations, node10Result, watchedFailed } = resolution;
1106+
// There have to be failed lookup locations if there is node10Result so storing failedLookupLocation length is good enough,
1107+
// node10Result doesnt change later only failed lookup locations get added on
1108+
if (watchedFailed === failedLookupLocations?.length) return;
1109+
if (!watchedFailed) {
1110+
resolutionsWithFailedLookups.add(resolution);
1111+
if (resolution.watchedAffected) resolutionsWithOnlyAffectingLocations.delete(resolution);
1112+
}
11201113

1121-
let setAtRoot = false;
1122-
if (failedLookupLocations) {
1123-
for (const failedLookupLocation of failedLookupLocations) {
1124-
setAtRoot = watchFailedLookupLocation(failedLookupLocation, setAtRoot);
1125-
}
1114+
let setAtRoot = !!resolution.setAtRoot;
1115+
for (let i = watchedFailed || 0; i < failedLookupLocations!.length; i++) {
1116+
setAtRoot = watchFailedLookupLocation(failedLookupLocations![i], setAtRoot);
11261117
}
1127-
if (node10Result) setAtRoot = watchFailedLookupLocation(node10Result, setAtRoot);
1128-
if (setAtRoot) {
1118+
if (!watchedFailed && node10Result) setAtRoot = watchFailedLookupLocation(node10Result, setAtRoot);
1119+
if (!resolution.setAtRoot && setAtRoot) {
11291120
// This is always non recursive
11301121
setDirectoryWatcher(rootDir, rootPath, /*nonRecursive*/ true);
11311122
}
1132-
watchAffectingLocationsOfResolution(resolution, !failedLookupLocations?.length && !node10Result);
1123+
resolution.watchedFailed = failedLookupLocations?.length;
1124+
resolution.setAtRoot = setAtRoot;
11331125
}
11341126

1135-
function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations, addToResolutionsWithOnlyAffectingLocations: boolean) {
1127+
function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations) {
11361128
Debug.assert(!!resolution.files?.size);
1137-
const { affectingLocations } = resolution;
1138-
if (!affectingLocations?.length) return;
1139-
if (addToResolutionsWithOnlyAffectingLocations) resolutionsWithOnlyAffectingLocations.add(resolution);
1129+
const { affectingLocations, watchedAffected } = resolution;
1130+
if (affectingLocations?.length === watchedAffected) return;
1131+
if (!watchedAffected && !resolution.watchedFailed) resolutionsWithOnlyAffectingLocations.add(resolution);
11401132
// Watch package json
1141-
for (const affectingLocation of affectingLocations) {
1142-
createFileWatcherOfAffectingLocation(affectingLocation, /*forResolution*/ true);
1133+
for (let i = watchedAffected || 0; i < affectingLocations!.length; i++) {
1134+
createFileWatcherOfAffectingLocation(affectingLocations![i], /*forResolution*/ true);
11431135
}
1136+
resolution.watchedAffected = affectingLocations?.length;
11441137
}
11451138

11461139
function createFileWatcherOfAffectingLocation(affectingLocation: string, forResolution: boolean) {
@@ -1208,11 +1201,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
12081201
packageJsonMap?.delete(resolutionHost.toPath(path));
12091202
}
12101203

1211-
function watchFailedLookupLocationOfNonRelativeModuleResolutions() {
1212-
nonRelativeExternalModuleResolutions.forEach(watchFailedLookupLocationOfResolution);
1213-
nonRelativeExternalModuleResolutions.clear();
1214-
}
1215-
12161204
function setDirectoryWatcher(dir: string, dirPath: Path, nonRecursive?: boolean) {
12171205
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
12181206
if (dirWatcher) {

src/harness/incrementalUtils.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,6 @@ export function verifyResolutionCache(
204204
path,
205205
resolutions,
206206
getResolvedModuleFileName,
207-
/*deferWatchingNonRelativeResolution*/ true,
208207
expected.resolvedModuleNames,
209208
actualProgram.getSourceFileByPath(path)!.resolvedModules,
210209
));
@@ -213,7 +212,6 @@ export function verifyResolutionCache(
213212
path,
214213
resolutions,
215214
getResolvedTypeRefFileName,
216-
/*deferWatchingNonRelativeResolution*/ false,
217215
expected.resolvedTypeReferenceDirectives,
218216
path !== inferredTypesPath ?
219217
actualProgram.getSourceFileByPath(path)!.resolvedTypeReferenceDirectiveNames :
@@ -229,7 +227,6 @@ export function verifyResolutionCache(
229227
getResolvedModuleFileName(resolved),
230228
ts.getLibraryNameFromLibFileName(libFileName),
231229
/*mode*/ undefined,
232-
/*deferWatchingNonRelativeResolution*/ false,
233230
);
234231
expected.resolvedLibraries.set(libFileName, expectedResolution);
235232
});
@@ -257,7 +254,20 @@ export function verifyResolutionCache(
257254
!resolution.isInvalidated,
258255
`${projectName}:: Resolution should not be invalidated`
259256
);
260-
verifySet(resolutionToExpected.get(resolution)!.files, resolution.files, `Resolution files`);
257+
const expected = resolutionToExpected.get(resolution)!;
258+
verifySet(expected.files, resolution.files, `Resolution files`);
259+
ts.Debug.assert(
260+
expected.watchedFailed === resolution.watchedFailed,
261+
`${projectName}:: Expected watchedFailed of Resolution ${expected.watchedFailed} but got ${resolution.watchedFailed}`
262+
);
263+
ts.Debug.assert(
264+
expected.watchedAffected === resolution.watchedAffected,
265+
`${projectName}:: Expected watchedAffected of Resolution ${expected.watchedAffected} but got ${resolution.watchedAffected}`
266+
);
267+
ts.Debug.assert(
268+
expected.setAtRoot === resolution.setAtRoot,
269+
`${projectName}:: Expected setAtRoot of Resolution ${expected.setAtRoot} but got ${resolution.setAtRoot}`
270+
);
261271
});
262272
verifyMapOfResolutionSet(expected.resolvedFileToResolution, actual.resolvedFileToResolution, `resolvedFileToResolution`);
263273
verifyResolutionSet(expected.resolutionsWithFailedLookups, actual.resolutionsWithFailedLookups, `resolutionsWithFailedLookups`);
@@ -299,7 +309,6 @@ export function verifyResolutionCache(
299309
fileName: ts.Path,
300310
cache: ts.ModeAwareCache<T> | undefined,
301311
getResolvedFileName: (resolution: T) => string | undefined,
302-
deferWatchingNonRelativeResolution: boolean,
303312
storeExpcted: Map<ts.Path, ts.ModeAwareCache<ts.ResolutionWithFailedLookupLocations>>,
304313
fromProgramResolutions: ts.ModeAwareCache<T> | undefined,
305314
) {
@@ -310,7 +319,7 @@ export function verifyResolutionCache(
310319
let expectedCache: ts.ModeAwareCache<ts.ResolutionWithFailedLookupLocations> | undefined;
311320
cache?.forEach((resolved, name, mode) => {
312321
const resolvedFileName = getResolvedFileName(resolved);
313-
const expected = collectResolution(cacheType, fileName, resolved, resolvedFileName, name, mode, deferWatchingNonRelativeResolution);
322+
const expected = collectResolution(cacheType, fileName, resolved, resolvedFileName, name, mode);
314323
if (!expectedCache) storeExpcted.set(fileName, expectedCache = ts.createModeAwareCache());
315324
expectedCache.set(name, mode, expected);
316325
// Resolution in program should be same as in resolution cache
@@ -326,7 +335,6 @@ export function verifyResolutionCache(
326335
resolvedFileName: string | undefined,
327336
name: string,
328337
mode: ts.ResolutionMode,
329-
deferWatchingNonRelativeResolution: boolean,
330338
): ExpectedResolution {
331339
const existing = resolutionToRefs.get(resolved);
332340
let expectedResolution: ExpectedResolution;
@@ -346,7 +354,7 @@ export function verifyResolutionCache(
346354
expectedToResolution.set(expectedResolution, resolved);
347355
resolutionToExpected.set(resolved, expectedResolution);
348356
}
349-
expected.watchFailedLookupLocationsOfExternalModuleResolutions(name, expectedResolution, fileName, () => ({ resolvedFileName }), deferWatchingNonRelativeResolution);
357+
expected.watchResolution(expectedResolution, fileName, () => ({ resolvedFileName }));
350358
return expectedResolution;
351359
}
352360

0 commit comments

Comments
 (0)