Skip to content

Commit de2f76a

Browse files
committed
Resolution reuse handling
1 parent 6d91978 commit de2f76a

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,
@@ -741,7 +748,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
741748
containingSourceFile: SourceFile;
742749
redirectedReference: ResolvedProjectReference | undefined;
743750
options: CompilerOptions;
744-
reusedNames?: readonly Entry[];
751+
reusedNames: readonly Entry[] | undefined;
752+
ambientModuleNames?: readonly Entry[] | undefined,
745753
perFileCache: Map<Path, ModeAwareCache<T>>;
746754
loader: ResolutionLoader<Entry, T, SourceFile>;
747755
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>;
@@ -751,7 +759,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
751759
}
752760
function resolveNamesWithLocalCache<Entry, SourceFile, T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>({
753761
entries, containingFile, containingSourceFile, redirectedReference, options,
754-
perFileCache, reusedNames,
762+
perFileCache, reusedNames, ambientModuleNames,
755763
loader, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution,
756764
shouldRetryResolution, logChanges,
757765
}: ResolveNamesWithLocalCacheInput<Entry, SourceFile, T, R>): readonly T[] {
@@ -824,20 +832,16 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
824832
seenNamesInFile.set(name, mode, true);
825833
resolvedModules.push(resolution);
826834
}
827-
reusedNames?.forEach(entry => seenNamesInFile.set(
828-
loader.nameAndMode.getName(entry),
829-
loader.nameAndMode.getMode(entry, containingSourceFile),
830-
true,
831-
));
832-
if (resolutionsInFile.size() !== seenNamesInFile.size()) {
833-
// Stop watching and remove the unused name
834-
resolutionsInFile.forEach((resolution, name, mode) => {
835-
if (!seenNamesInFile.has(name, mode)) {
836-
stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName);
837-
resolutionsInFile.delete(name, mode);
838-
}
839-
});
840-
}
835+
reuseResolutionsWorker(
836+
reusedNames,
837+
containingSourceFile,
838+
path,
839+
resolutionsInFile,
840+
seenNamesInFile,
841+
loader.nameAndMode,
842+
getResolutionWithResolvedFileName,
843+
ambientModuleNames,
844+
);
841845
return resolvedModules;
842846

843847
function resolutionIsEqualTo(oldResolution: T | undefined, newResolution: T | undefined): boolean {
@@ -895,6 +899,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
895899
options: CompilerOptions,
896900
containingSourceFile: SourceFile,
897901
reusedNames: readonly StringLiteralLike[] | undefined,
902+
ambientModuleNames: readonly StringLiteralLike[] | undefined,
898903
): readonly ResolvedModuleWithFailedLookupLocations[] {
899904
return resolveNamesWithLocalCache({
900905
entries: moduleLiterals,
@@ -903,6 +908,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
903908
redirectedReference,
904909
options,
905910
reusedNames,
911+
ambientModuleNames,
906912
perFileCache: resolvedModuleNames,
907913
loader: createModuleResolutionLoaderUsingGlobalCache(
908914
containingFile,
@@ -956,6 +962,99 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
956962
return resolution;
957963
}
958964

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