Skip to content

Commit 0c6f13e

Browse files
committed
Resolution reuse handling
1 parent 4dc113e commit 0c6f13e

19 files changed

+385
-240
lines changed

src/compiler/program.ts

Lines changed: 79 additions & 71 deletions
Large diffs are not rendered by default.

src/compiler/resolutionCache.ts

Lines changed: 116 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
clearMap,
55
closeFileWatcher,
66
closeFileWatcherOf,
7+
CompilerHostSupportingResolutionCache,
78
CompilerOptions,
89
createModeAwareCache,
910
createModuleResolutionCache,
@@ -22,6 +23,7 @@ import {
2223
FileWatcher,
2324
FileWatcherCallback,
2425
firstDefinedIterator,
26+
getAutomaticTypeDirectiveContainingFile,
2527
GetCanonicalFileName,
2628
getDirectoryPath,
2729
getEffectiveTypeRoots,
@@ -63,6 +65,7 @@ import {
6365
resolutionExtensionIsTSOrJson,
6466
ResolutionLoader,
6567
ResolutionMode,
68+
ResolutionNameAndModeGetter,
6669
ResolvedModuleWithFailedLookupLocations,
6770
ResolvedProjectReference,
6871
ResolvedTypeReferenceDirectiveWithFailedLookupLocations,
@@ -75,6 +78,7 @@ import {
7578
stringContains,
7679
StringLiteralLike,
7780
trace,
81+
typeReferenceResolutionNameAndModeGetter,
7882
updateResolutionField,
7983
WatchDirectoryFlags,
8084
} from "./_namespaces/ts";
@@ -89,7 +93,7 @@ export interface HasInvalidatedFromResolutionCache {
8993
*
9094
* @internal
9195
*/
92-
export interface ResolutionCache {
96+
export interface ResolutionCache extends Required<CompilerHostSupportingResolutionCache> {
9397
rootDirForResolution: string;
9498
resolvedModuleNames: Map<Path, ModeAwareCache<CachedResolvedModuleWithFailedLookupLocations>>;
9599
resolvedTypeReferenceDirectives: Map<Path, ModeAwareCache<CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations>>;
@@ -117,6 +121,7 @@ export interface ResolutionCache {
117121
options: CompilerOptions,
118122
containingSourceFile: SourceFile,
119123
reusedNames: readonly StringLiteralLike[] | undefined,
124+
ambientModuleNames: readonly StringLiteralLike[] | undefined,
120125
): readonly ResolvedModuleWithFailedLookupLocations[];
121126
resolveTypeReferenceDirectiveReferences<T extends FileReference | string>(
122127
typeDirectiveReferences: readonly T[],
@@ -574,6 +579,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
574579
resolveSingleModuleNameWithoutWatching,
575580
removeResolutionsFromProjectReferenceRedirects,
576581
removeResolutionsOfFile,
582+
reusedModuleResolutions,
583+
reusedTypeReferenceDirectiveResolutions,
577584
hasChangedAutomaticTypeDirectiveNames: () => hasChangedAutomaticTypeDirectiveNames,
578585
invalidateResolutionOfFile,
579586
invalidateResolutionsOfFailedLookupLocations,
@@ -737,7 +744,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
737744
containingSourceFile: SourceFile;
738745
redirectedReference: ResolvedProjectReference | undefined;
739746
options: CompilerOptions;
740-
reusedNames?: readonly Entry[];
747+
reusedNames: readonly Entry[] | undefined;
748+
ambientModuleNames?: readonly Entry[] | undefined,
741749
perFileCache: Map<Path, ModeAwareCache<T>>;
742750
loader: ResolutionLoader<Entry, T, SourceFile>;
743751
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>;
@@ -747,7 +755,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
747755
}
748756
function resolveNamesWithLocalCache<Entry, SourceFile, T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>({
749757
entries, containingFile, containingSourceFile, redirectedReference, options,
750-
perFileCache, reusedNames,
758+
perFileCache, reusedNames, ambientModuleNames,
751759
loader, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution,
752760
shouldRetryResolution, logChanges,
753761
}: ResolveNamesWithLocalCacheInput<Entry, SourceFile, T, R>): readonly T[] {
@@ -818,20 +826,16 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
818826
seenNamesInFile.set(name, mode, true);
819827
resolvedModules.push(resolution);
820828
}
821-
reusedNames?.forEach(entry => seenNamesInFile.set(
822-
loader.nameAndMode.getName(entry),
823-
loader.nameAndMode.getMode(entry, containingSourceFile),
824-
true,
825-
));
826-
if (resolutionsInFile.size() !== seenNamesInFile.size()) {
827-
// Stop watching and remove the unused name
828-
resolutionsInFile.forEach((resolution, name, mode) => {
829-
if (!seenNamesInFile.has(name, mode)) {
830-
stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName);
831-
resolutionsInFile.delete(name, mode);
832-
}
833-
});
834-
}
829+
reuseResolutionsWorker(
830+
reusedNames,
831+
containingSourceFile,
832+
path,
833+
resolutionsInFile,
834+
seenNamesInFile,
835+
loader.nameAndMode,
836+
getResolutionWithResolvedFileName,
837+
ambientModuleNames,
838+
);
835839
return resolvedModules;
836840

837841
function resolutionIsEqualTo(oldResolution: T | undefined, newResolution: T | undefined): boolean {
@@ -889,6 +893,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
889893
options: CompilerOptions,
890894
containingSourceFile: SourceFile,
891895
reusedNames: readonly StringLiteralLike[] | undefined,
896+
ambientModuleNames: readonly StringLiteralLike[] | undefined,
892897
): readonly ResolvedModuleWithFailedLookupLocations[] {
893898
return resolveNamesWithLocalCache({
894899
entries: moduleLiterals,
@@ -897,6 +902,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
897902
redirectedReference,
898903
options,
899904
reusedNames,
905+
ambientModuleNames,
900906
perFileCache: resolvedModuleNames,
901907
loader: createModuleResolutionLoaderUsingGlobalCache(
902908
containingFile,
@@ -950,6 +956,99 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
950956
return resolution;
951957
}
952958

959+
function reuseResolutionsWorker<Entry, SourceFile, T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
960+
reusedNames: readonly Entry[] | undefined,
961+
containingSourceFile: SourceFile,
962+
path: Path,
963+
resolutionsInFile: ModeAwareCache<T>,
964+
seenNamesInFile: ModeAwareCache<true>,
965+
nameAndModeGetter: ResolutionNameAndModeGetter<Entry, SourceFile>,
966+
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
967+
ambientModuleNames: readonly Entry[] | undefined,
968+
) {
969+
reusedNames?.forEach(entry => seenNamesInFile.set(
970+
nameAndModeGetter.getName(entry),
971+
nameAndModeGetter.getMode(entry, containingSourceFile),
972+
true,
973+
));
974+
// For ambient module names, if its not invalidated keep it
975+
ambientModuleNames?.forEach(entry => {
976+
const name = nameAndModeGetter.getName(entry);
977+
const mode = nameAndModeGetter.getMode(entry, containingSourceFile);
978+
if (!seenNamesInFile.has(name, mode)) {
979+
const resolution = resolutionsInFile.get(name, mode);
980+
// Keep this resolution from old time for ambient module names
981+
if (resolution && !resolution.isInvalidated) {
982+
seenNamesInFile.set(name, mode, true);
983+
}
984+
}
985+
});
986+
if (resolutionsInFile.size() !== seenNamesInFile.size()) {
987+
// Stop watching and remove the unused name
988+
resolutionsInFile.forEach((resolution, name, mode) => {
989+
if (!seenNamesInFile.has(name, mode)) {
990+
stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName);
991+
resolutionsInFile.delete(name, mode);
992+
}
993+
});
994+
}
995+
}
996+
997+
function reuseResolutions<Entry, SourceFile, T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
998+
reusedNames: readonly Entry[] | undefined,
999+
containingSourceFile: SourceFile,
1000+
path: Path,
1001+
perFileCache: Map<Path, ModeAwareCache<T>>,
1002+
nameAndModeGetter: ResolutionNameAndModeGetter<Entry, SourceFile>,
1003+
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
1004+
ambientModuleNames?: readonly Entry[] | undefined,
1005+
) {
1006+
const resolutionsInFile = perFileCache.get(path);
1007+
if (!resolutionsInFile) return;
1008+
const seenNamesInFile = createModeAwareCache<true>();
1009+
reuseResolutionsWorker(
1010+
reusedNames,
1011+
containingSourceFile,
1012+
path, resolutionsInFile,
1013+
seenNamesInFile,
1014+
nameAndModeGetter,
1015+
getResolutionWithResolvedFileName,
1016+
ambientModuleNames,
1017+
);
1018+
}
1019+
1020+
function reusedModuleResolutions(
1021+
reusedNames: readonly StringLiteralLike[] | undefined,
1022+
containingSourceFile: SourceFile,
1023+
ambientModuleNames: readonly StringLiteralLike[] | undefined,
1024+
) {
1025+
reuseResolutions(
1026+
reusedNames,
1027+
containingSourceFile,
1028+
containingSourceFile.path,
1029+
resolvedModuleNames,
1030+
moduleResolutionNameAndModeGetter,
1031+
getResolvedModule,
1032+
ambientModuleNames,
1033+
);
1034+
}
1035+
1036+
function reusedTypeReferenceDirectiveResolutions<T extends FileReference | string>(
1037+
reusedNames: readonly T[] | undefined,
1038+
containingSourceFile: SourceFile | undefined,
1039+
) {
1040+
reuseResolutions(
1041+
reusedNames,
1042+
containingSourceFile,
1043+
containingSourceFile ?
1044+
containingSourceFile.path :
1045+
resolutionHost.toPath(getAutomaticTypeDirectiveContainingFile(resolutionHost.getCompilationSettings(), getCurrentDirectory())),
1046+
resolvedTypeReferenceDirectives,
1047+
typeReferenceResolutionNameAndModeGetter,
1048+
getResolvedTypeReferenceDirective,
1049+
);
1050+
}
1051+
9531052
function resolveSingleModuleNameWithoutWatching(moduleName: string, containingFile: string) {
9541053
const path = resolutionHost.toPath(containingFile);
9551054
const resolutionsInFile = resolvedModuleNames.get(path);

src/compiler/types.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7799,6 +7799,7 @@ export interface CompilerHost extends ModuleResolutionHost {
77997799
options: CompilerOptions,
78007800
containingSourceFile: SourceFile,
78017801
reusedNames: readonly StringLiteralLike[] | undefined,
7802+
ambientModuleNames: readonly StringLiteralLike[] | undefined,
78027803
): readonly ResolvedModuleWithFailedLookupLocations[];
78037804
resolveTypeReferenceDirectiveReferences?<T extends FileReference | string>(
78047805
typeDirectiveReferences: readonly T[],
@@ -7839,6 +7840,22 @@ export interface CompilerHost extends ModuleResolutionHost {
78397840
/** @internal */ getBuildInfo?(fileName: string, configFilePath: string | undefined): BuildInfo | undefined;
78407841
}
78417842

7843+
/** @internal */
7844+
export interface CompilerHostSupportingResolutionCache {
7845+
reusedModuleResolutions?(
7846+
reusedNames: readonly StringLiteralLike[] | undefined,
7847+
containingSourceFile: SourceFile,
7848+
ambientModuleNames: readonly StringLiteralLike[] | undefined,
7849+
): void;
7850+
reusedTypeReferenceDirectiveResolutions?<T extends FileReference | string>(
7851+
reusedNames: readonly T[] | undefined,
7852+
containingSourceFile: SourceFile | undefined,
7853+
): void;
7854+
}
7855+
/** @internal */
7856+
export interface CompilerHost extends CompilerHostSupportingResolutionCache {
7857+
}
7858+
78427859
/** true if --out otherwise source file name *
78437860
* @internal
78447861
*/

src/compiler/watchPublic.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ export interface ProgramHost<T extends BuilderProgram> {
222222
options: CompilerOptions,
223223
containingSourceFile: SourceFile,
224224
reusedNames: readonly StringLiteralLike[] | undefined,
225+
ambientModuleNames: readonly StringLiteralLike[] | undefined,
225226
): readonly ResolvedModuleWithFailedLookupLocations[];
226227
resolveTypeReferenceDirectiveReferences?<T extends FileReference | string>(
227228
typeDirectiveReferences: readonly T[],
@@ -514,11 +515,13 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
514515
compilerHost.resolveModuleNames = maybeBind(host, host.resolveModuleNames);
515516
if (!compilerHost.resolveModuleNameLiterals && !compilerHost.resolveModuleNames) {
516517
compilerHost.resolveModuleNameLiterals = resolutionCache.resolveModuleNameLiterals.bind(resolutionCache);
518+
compilerHost.reusedModuleResolutions = resolutionCache.reusedModuleResolutions.bind(resolutionCache);
517519
}
518520
compilerHost.resolveTypeReferenceDirectiveReferences = maybeBind(host, host.resolveTypeReferenceDirectiveReferences);
519521
compilerHost.resolveTypeReferenceDirectives = maybeBind(host, host.resolveTypeReferenceDirectives);
520522
if (!compilerHost.resolveTypeReferenceDirectiveReferences && !compilerHost.resolveTypeReferenceDirectives) {
521-
compilerHost.resolveTypeReferenceDirectiveReferences = resolutionCache.resolveTypeReferenceDirectiveReferences.bind(resolutionCache);
523+
compilerHost.resolveTypeReferenceDirectiveReferences = resolutionCache.resolveTypeReferenceDirectiveReferences.bind(resolutionCache);
524+
compilerHost.reusedTypeReferenceDirectiveResolutions = resolutionCache.reusedTypeReferenceDirectiveResolutions.bind(resolutionCache);
522525
}
523526
compilerHost.resolveLibrary = !host.resolveLibrary ?
524527
resolutionCache.resolveLibrary.bind(resolutionCache) :

0 commit comments

Comments
 (0)