Skip to content

Commit 67e0742

Browse files
committed
Resolution reuse handling
1 parent 8710039 commit 67e0742

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[] {
@@ -820,20 +828,16 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
820828
seenNamesInFile.set(name, mode, true);
821829
resolvedModules.push(resolution);
822830
}
823-
reusedNames?.forEach(entry => seenNamesInFile.set(
824-
loader.nameAndMode.getName(entry),
825-
loader.nameAndMode.getMode(entry, containingSourceFile),
826-
true,
827-
));
828-
if (resolutionsInFile.size() !== seenNamesInFile.size()) {
829-
// Stop watching and remove the unused name
830-
resolutionsInFile.forEach((resolution, name, mode) => {
831-
if (!seenNamesInFile.has(name, mode)) {
832-
stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName);
833-
resolutionsInFile.delete(name, mode);
834-
}
835-
});
836-
}
831+
reuseResolutionsWorker(
832+
reusedNames,
833+
containingSourceFile,
834+
path,
835+
resolutionsInFile,
836+
seenNamesInFile,
837+
loader.nameAndMode,
838+
getResolutionWithResolvedFileName,
839+
ambientModuleNames,
840+
);
837841
return resolvedModules;
838842

839843
function resolutionIsEqualTo(oldResolution: T | undefined, newResolution: T | undefined): boolean {
@@ -891,6 +895,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
891895
options: CompilerOptions,
892896
containingSourceFile: SourceFile,
893897
reusedNames: readonly StringLiteralLike[] | undefined,
898+
ambientModuleNames: readonly StringLiteralLike[] | undefined,
894899
): readonly ResolvedModuleWithFailedLookupLocations[] {
895900
return resolveNamesWithLocalCache({
896901
entries: moduleLiterals,
@@ -899,6 +904,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
899904
redirectedReference,
900905
options,
901906
reusedNames,
907+
ambientModuleNames,
902908
perFileCache: resolvedModuleNames,
903909
loader: createModuleResolutionLoaderUsingGlobalCache(
904910
containingFile,
@@ -952,6 +958,99 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
952958
return resolution;
953959
}
954960

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