Skip to content

Commit ae1d105

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 679cd3c commit ae1d105

File tree

100 files changed

+360
-364
lines changed

Some content is hidden

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

100 files changed

+360
-364
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);
@@ -750,12 +747,11 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
750747
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>;
751748
shouldRetryResolution: (t: T) => boolean;
752749
logChanges?: boolean;
753-
deferWatchingNonRelativeResolution: boolean;
754750
}
755751
function resolveNamesWithLocalCache<Entry, SourceFile, T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>({
756752
entries, containingFile, containingSourceFile, redirectedReference, options,
757753
perFileCache, reusedNames, ambientModuleNames,
758-
loader, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution,
754+
loader, getResolutionWithResolvedFileName,
759755
shouldRetryResolution, logChanges,
760756
}: ResolveNamesWithLocalCacheInput<Entry, SourceFile, T, R>): readonly T[] {
761757
const path = resolutionHost.toPath(containingFile);
@@ -786,7 +782,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
786782
resolutionHost.onDiscoveredSymlink();
787783
}
788784
resolutionsInFile.set(name, mode, resolution);
789-
watchFailedLookupLocationsOfExternalModuleResolutions(name, resolution, path, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution);
785+
watchResolution(resolution, path, getResolutionWithResolvedFileName);
790786
if (existingResolution) {
791787
stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolutionWithResolvedFileName);
792788
}
@@ -881,7 +877,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
881877
),
882878
getResolutionWithResolvedFileName: getResolvedTypeReferenceDirective,
883879
shouldRetryResolution: resolution => resolution.resolvedTypeReferenceDirective === undefined,
884-
deferWatchingNonRelativeResolution: false,
885880
});
886881
}
887882

@@ -913,7 +908,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
913908
getResolutionWithResolvedFileName: getResolvedModule,
914909
shouldRetryResolution: resolution => !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension),
915910
logChanges: logChangesWhenResolvingModule,
916-
deferWatchingNonRelativeResolution: true, // Defer non relative resolution watch because we could be using ambient modules
917911
});
918912
}
919913

@@ -929,7 +923,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
929923
const existingResolution = resolution;
930924
resolution = ts_resolveLibrary(libraryName, resolveFrom, options, host, libraryResolutionCache);
931925
const path = resolutionHost.toPath(resolveFrom);
932-
watchFailedLookupLocationsOfExternalModuleResolutions(libraryName, resolution, path, getResolvedModule, /*deferWatchingNonRelativeResolution*/ false);
926+
watchResolution(resolution, path, getResolvedModule);
933927
resolvedLibraries.set(libFileName, resolution);
934928
if (existingResolution) {
935929
stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolvedModule);
@@ -1060,21 +1054,15 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
10601054
return endsWith(dirPath, "/node_modules/@types");
10611055
}
10621056

1063-
function watchFailedLookupLocationsOfExternalModuleResolutions<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
1064-
name: string,
1057+
function watchResolution<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
10651058
resolution: T,
10661059
filePath: Path,
10671060
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
1068-
deferWatchingNonRelativeResolution: boolean,
10691061
) {
10701062
(resolution.files ??= new Set()).add(filePath);
1063+
watchFailedLookupLocationOfResolution(resolution);
1064+
watchAffectingLocationsOfResolution(resolution);
10711065
if (resolution.files.size !== 1) return;
1072-
if (!deferWatchingNonRelativeResolution || isExternalModuleNameRelative(name)) {
1073-
watchFailedLookupLocationOfResolution(resolution);
1074-
}
1075-
else {
1076-
nonRelativeExternalModuleResolutions.add(resolution);
1077-
}
10781066
const resolved = getResolutionWithResolvedFileName(resolution);
10791067
if (resolved && resolved.resolvedFileName) {
10801068
const key = resolutionHost.toPath(resolved.resolvedFileName);
@@ -1110,33 +1098,38 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
11101098
function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
11111099
Debug.assert(!!resolution.files?.size);
11121100

1113-
const { failedLookupLocations, affectingLocations, node10Result } = resolution;
1114-
if (!failedLookupLocations?.length && !affectingLocations?.length && !node10Result) return;
1115-
if (failedLookupLocations?.length || node10Result) resolutionsWithFailedLookups.add(resolution);
1101+
const { failedLookupLocations, node10Result, watchedFailed } = resolution;
1102+
// There have to be failed lookup locations if there is node10Result so storing failedLookupLocation length is good enough,
1103+
// node10Result doesnt change later only failed lookup locations get added on
1104+
if (watchedFailed === failedLookupLocations?.length) return;
1105+
if (!watchedFailed) {
1106+
resolutionsWithFailedLookups.add(resolution);
1107+
if (resolution.watchedAffected) resolutionsWithOnlyAffectingLocations.delete(resolution);
1108+
}
11161109

1117-
let setAtRoot = false;
1118-
if (failedLookupLocations) {
1119-
for (const failedLookupLocation of failedLookupLocations) {
1120-
setAtRoot = watchFailedLookupLocation(failedLookupLocation, setAtRoot);
1121-
}
1110+
let setAtRoot = !!resolution.setAtRoot;
1111+
for (let i = watchedFailed || 0; i < failedLookupLocations!.length; i++) {
1112+
setAtRoot = watchFailedLookupLocation(failedLookupLocations![i], setAtRoot);
11221113
}
1123-
if (node10Result) setAtRoot = watchFailedLookupLocation(node10Result, setAtRoot);
1124-
if (setAtRoot) {
1114+
if (!watchedFailed && node10Result) setAtRoot = watchFailedLookupLocation(node10Result, setAtRoot);
1115+
if (!resolution.setAtRoot && setAtRoot) {
11251116
// This is always non recursive
11261117
setDirectoryWatcher(rootDir, rootPath, /*nonRecursive*/ true);
11271118
}
1128-
watchAffectingLocationsOfResolution(resolution, !failedLookupLocations?.length && !node10Result);
1119+
resolution.watchedFailed = failedLookupLocations?.length;
1120+
resolution.setAtRoot = setAtRoot;
11291121
}
11301122

1131-
function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations, addToResolutionsWithOnlyAffectingLocations: boolean) {
1123+
function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations) {
11321124
Debug.assert(!!resolution.files?.size);
1133-
const { affectingLocations } = resolution;
1134-
if (!affectingLocations?.length) return;
1135-
if (addToResolutionsWithOnlyAffectingLocations) resolutionsWithOnlyAffectingLocations.add(resolution);
1125+
const { affectingLocations, watchedAffected } = resolution;
1126+
if (affectingLocations?.length === watchedAffected) return;
1127+
if (!watchedAffected && !resolution.watchedFailed) resolutionsWithOnlyAffectingLocations.add(resolution);
11361128
// Watch package json
1137-
for (const affectingLocation of affectingLocations) {
1138-
createFileWatcherOfAffectingLocation(affectingLocation, /*forResolution*/ true);
1129+
for (let i = watchedAffected || 0; i < affectingLocations!.length; i++) {
1130+
createFileWatcherOfAffectingLocation(affectingLocations![i], /*forResolution*/ true);
11391131
}
1132+
resolution.watchedAffected = affectingLocations?.length;
11401133
}
11411134

11421135
function createFileWatcherOfAffectingLocation(affectingLocation: string, forResolution: boolean) {
@@ -1204,11 +1197,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
12041197
packageJsonMap?.delete(resolutionHost.toPath(path));
12051198
}
12061199

1207-
function watchFailedLookupLocationOfNonRelativeModuleResolutions() {
1208-
nonRelativeExternalModuleResolutions.forEach(watchFailedLookupLocationOfResolution);
1209-
nonRelativeExternalModuleResolutions.clear();
1210-
}
1211-
12121200
function setDirectoryWatcher(dir: string, dirPath: Path, nonRecursive?: boolean) {
12131201
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
12141202
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)