Skip to content

Commit 3bf578a

Browse files
committed
Resolution reuse handling
1 parent 5e7e0ba commit 3bf578a

19 files changed

Lines changed: 385 additions & 240 deletions

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,
@@ -739,7 +746,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
739746
containingSourceFile: SourceFile;
740747
redirectedReference: ResolvedProjectReference | undefined;
741748
options: CompilerOptions;
742-
reusedNames?: readonly Entry[];
749+
reusedNames: readonly Entry[] | undefined;
750+
ambientModuleNames?: readonly Entry[] | undefined,
743751
perFileCache: Map<Path, ModeAwareCache<T>>;
744752
loader: ResolutionLoader<Entry, T, SourceFile>;
745753
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>;
@@ -749,7 +757,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
749757
}
750758
function resolveNamesWithLocalCache<Entry, SourceFile, T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>({
751759
entries, containingFile, containingSourceFile, redirectedReference, options,
752-
perFileCache, reusedNames,
760+
perFileCache, reusedNames, ambientModuleNames,
753761
loader, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution,
754762
shouldRetryResolution, logChanges,
755763
}: ResolveNamesWithLocalCacheInput<Entry, SourceFile, T, R>): readonly T[] {
@@ -822,20 +830,16 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
822830
seenNamesInFile.set(name, mode, true);
823831
resolvedModules.push(resolution);
824832
}
825-
reusedNames?.forEach(entry => seenNamesInFile.set(
826-
loader.nameAndMode.getName(entry),
827-
loader.nameAndMode.getMode(entry, containingSourceFile),
828-
true,
829-
));
830-
if (resolutionsInFile.size() !== seenNamesInFile.size()) {
831-
// Stop watching and remove the unused name
832-
resolutionsInFile.forEach((resolution, name, mode) => {
833-
if (!seenNamesInFile.has(name, mode)) {
834-
stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName);
835-
resolutionsInFile.delete(name, mode);
836-
}
837-
});
838-
}
833+
reuseResolutionsWorker(
834+
reusedNames,
835+
containingSourceFile,
836+
path,
837+
resolutionsInFile,
838+
seenNamesInFile,
839+
loader.nameAndMode,
840+
getResolutionWithResolvedFileName,
841+
ambientModuleNames,
842+
);
839843
return resolvedModules;
840844

841845
function resolutionIsEqualTo(oldResolution: T | undefined, newResolution: T | undefined): boolean {
@@ -893,6 +897,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
893897
options: CompilerOptions,
894898
containingSourceFile: SourceFile,
895899
reusedNames: readonly StringLiteralLike[] | undefined,
900+
ambientModuleNames: readonly StringLiteralLike[] | undefined,
896901
): readonly ResolvedModuleWithFailedLookupLocations[] {
897902
return resolveNamesWithLocalCache({
898903
entries: moduleLiterals,
@@ -901,6 +906,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
901906
redirectedReference,
902907
options,
903908
reusedNames,
909+
ambientModuleNames,
904910
perFileCache: resolvedModuleNames,
905911
loader: createModuleResolutionLoaderUsingGlobalCache(
906912
containingFile,
@@ -954,6 +960,99 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
954960
return resolution;
955961
}
956962

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

src/compiler/types.ts

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

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

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)