Skip to content

Commit e06b492

Browse files
committed
Cache packagejson scopes per directory
1 parent a8f97b4 commit e06b492

File tree

37 files changed

+3011
-9433
lines changed

37 files changed

+3011
-9433
lines changed

src/compiler/builder.ts

+50-17
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ namespace ts {
7373
modules: CacheWithRedirects<Path, ModeAwareCache<ResolvedModuleWithFailedLookupLocations>> | undefined;
7474
typeRefs: CacheWithRedirects<Path, ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>> | undefined;
7575
moduleNameToDirectoryMap: CacheWithRedirects<ModeAwareCacheKey, ESMap<Path, ResolvedModuleWithFailedLookupLocations>>;
76-
dirToPackageJsonMap: ESMap<Path, string>;
76+
dirToPackageJsonScope: ESMap<Path, PackageJsonScope>;
7777
perDirPackageJsonMap: ESMap<Path, string> | undefined;
7878
packageJsonCache: PackageJsonInfoCache | undefined;
7979
};
@@ -1272,22 +1272,21 @@ namespace ts {
12721272
let modules: CacheWithRedirects<Path, ModeAwareCache<ResolvedModuleWithFailedLookupLocations>> | undefined;
12731273
let typeRefs: CacheWithRedirects<Path, ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>> | undefined;
12741274
const moduleNameToDirectoryMap = createCacheWithRedirects<ModeAwareCacheKey, ESMap<Path, ResolvedModuleWithFailedLookupLocations>>(state.compilerOptions);
1275-
const dirToPackageJsonMap = new Map<Path, string>();
1275+
const dirToPackageJsonScope = new Map<Path, PackageJsonScope>();
12761276
let perDirPackageJsonMap: ESMap<Path, string> | undefined;
12771277
const getCanonicalFileName = createGetCanonicalFileName(state.program!.useCaseSensitiveFileNames());
12781278
state.program!.getSourceFiles().forEach(f => {
12791279
modules = toPerDirectoryCache(state, getCanonicalFileName, modules, getResolvedModuleOfResolution, f, f.resolvedModules, moduleNameToDirectoryMap);
12801280
typeRefs = toPerDirectoryCache(state, getCanonicalFileName, typeRefs, getResolvedTypeReferenceDirectiveOfResolution, f, f.resolvedTypeReferenceDirectiveNames);
1281-
if (f.packageJsonScope) {
1281+
if (f.packageJsonScope?.info) {
12821282
const dirPath = getDirectoryPath(f.resolvedPath);
1283-
if (!dirToPackageJsonMap?.has(dirPath)) {
1284-
const result = last(f.packageJsonLocations!);
1285-
(perDirPackageJsonMap ??= new Map()).set(dirPath, result);
1283+
if (!dirToPackageJsonScope?.has(dirPath)) {
1284+
(perDirPackageJsonMap ??= new Map()).set(dirPath, getPackageJsconLocationFromScope(f.packageJsonScope)!);
12861285
moduleNameToDirectorySet(
1287-
dirToPackageJsonMap,
1286+
dirToPackageJsonScope,
12881287
dirPath,
1289-
result,
1290-
identity,
1288+
f.packageJsonScope,
1289+
getPackageJsconLocationFromScope,
12911290
dir => toPath(dir, state.program!.getCurrentDirectory(), getCanonicalFileName),
12921291
ancestorPath => perDirPackageJsonMap?.delete(ancestorPath),
12931292
);
@@ -1304,7 +1303,7 @@ namespace ts {
13041303
modules,
13051304
typeRefs,
13061305
moduleNameToDirectoryMap,
1307-
dirToPackageJsonMap,
1306+
dirToPackageJsonScope,
13081307
perDirPackageJsonMap,
13091308
packageJsonCache: state.program!.getModuleResolutionCache()?.getPackageJsonInfoCache().clone(),
13101309
};
@@ -1919,6 +1918,7 @@ namespace ts {
19191918
): OldBuildInfoProgram | undefined {
19201919
if (!cacheResolutions && !resuableCacheResolutions) return undefined;
19211920
const fileExistsMap = new Map<string, boolean>();
1921+
const packageJsonInfoMap = new Map<string, PackageJsonInfo | false>();
19221922
const affectingLoationsSameMap = new Map<string, boolean>();
19231923

19241924
type Resolution = ResolvedModuleWithFailedLookupLocations & ResolvedTypeReferenceDirectiveWithFailedLookupLocations;
@@ -1929,6 +1929,7 @@ namespace ts {
19291929
const decodedResolvedTypeRefs: DecodedResolvedMap = createCacheWithRedirects(compilerOptions);
19301930
const decodedModuleNameToDirectoryMap: DecodedModuleNameToDirectoryMap = createCacheWithRedirects(compilerOptions);
19311931
let decodedPackageJsonMap: ESMap<Path, string> | undefined;
1932+
let packageJsonScopes: ESMap<string, PackageJsonScope | false> | undefined;
19321933
let decodedHashes: ESMap<ProgramBuildInfoAbsoluteFileId, string | undefined> | undefined;
19331934

19341935
let resolutions: (Resolution | false)[] | undefined;
@@ -1959,7 +1960,7 @@ namespace ts {
19591960
/*moduleNameToDirectoryMap*/ undefined,
19601961
/*decodedModuleNameToDirectoryMap*/ undefined,
19611962
),
1962-
getPackageJsonPath,
1963+
getPackageJsonScope,
19631964
};
19641965

19651966
function fileExists(fileName: string) {
@@ -1968,13 +1969,19 @@ namespace ts {
19681969
return result;
19691970
}
19701971

1972+
function getPackageJsonInfo(fileName: string) {
1973+
let result = packageJsonInfoMap.get(fileName);
1974+
if (result === undefined) packageJsonInfoMap.set(fileName, result = host.getPackageJsonInfo(fileName) || false);
1975+
return result || undefined;
1976+
}
1977+
19711978
function affectingLocationsSame(
19721979
fileName: string,
19731980
expected: PackageJsonInfo | boolean | string | undefined
19741981
): boolean {
19751982
let result = affectingLoationsSameMap.get(fileName);
19761983
if (result !== undefined) return result;
1977-
const packageJsonInfo = host.getPackageJsonInfo(fileName);
1984+
const packageJsonInfo = getPackageJsonInfo(fileName);
19781985
const currentText = typeof packageJsonInfo === "object" ? packageJsonInfo.packageJsonText : undefined;
19791986
if (isString(expected)) {
19801987
result = !!currentText && (host.createHash ?? generateDjb2Hash)(currentText) === expected;
@@ -1987,10 +1994,22 @@ namespace ts {
19871994
return result;
19881995
}
19891996

1990-
function getPackageJsonPath(dirPath: Path) {
1991-
const fromCache = cacheResolutions?.dirToPackageJsonMap?.get(dirPath);
1997+
function getPackageJsonScope(dirPath: Path): PackageJsonScope | undefined {
1998+
const fromCache = cacheResolutions?.dirToPackageJsonScope?.get(dirPath);
19921999
if (fromCache) {
1993-
return fileExists(fromCache) ? fromCache : undefined;
2000+
const packageJson = getPackageJsconLocationFromScope(fromCache)!;
2001+
let result = packageJsonScopes?.get(packageJson);
2002+
if (result === undefined) {
2003+
(packageJsonScopes ??= new Map()).set(
2004+
packageJson,
2005+
result = affectingLocationsSame(packageJson, fromCache.info) ?
2006+
fromCache :
2007+
fileExists(packageJson) ?
2008+
{ info: getPackageJsonInfo(packageJson), affectingLocations: [packageJson] } :
2009+
false
2010+
);
2011+
}
2012+
return result || undefined;
19942013
}
19952014
if (!resuableCacheResolutions?.cache.packageJsons) return;
19962015
if (!decodedPackageJsonMap) {
@@ -2009,8 +2028,22 @@ namespace ts {
20092028
);
20102029
}
20112030
}
2012-
const fromDecoded = decodedPackageJsonMap.get(dirPath);
2013-
return fromDecoded && fileExists(fromDecoded) ? fromDecoded : undefined;
2031+
return toPackageJsonScope(decodedPackageJsonMap.get(dirPath));
2032+
}
2033+
2034+
function toPackageJsonScope(file: string | undefined): PackageJsonScope | undefined {
2035+
if (!file) return undefined;
2036+
let result = packageJsonScopes?.get(file);
2037+
if (result !== undefined) return result || undefined;
2038+
(packageJsonScopes ??= new Map());
2039+
if (fileExists(file)) {
2040+
result = {
2041+
info: getPackageJsonInfo(file),
2042+
affectingLocations: [file]
2043+
};
2044+
}
2045+
packageJsonScopes.set(file, result || false);
2046+
return result;
20142047
}
20152048

20162049
function getResolvedFromCache<T extends ResolvedModuleWithFailedLookupLocations | ResolvedTypeReferenceDirectiveWithFailedLookupLocations>(

src/compiler/checker.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3585,7 +3585,7 @@ namespace ts {
35853585
let diagnosticDetails;
35863586
const ext = tryGetExtensionFromPath(currentSourceFile.fileName);
35873587
if (ext === Extension.Ts || ext === Extension.Js || ext === Extension.Tsx || ext === Extension.Jsx) {
3588-
const scope = currentSourceFile.packageJsonScope;
3588+
const scope = currentSourceFile.packageJsonScope?.info;
35893589
const targetExt = ext === Extension.Ts ? Extension.Mts : ext === Extension.Js ? Extension.Mjs : undefined;
35903590
if (scope && !scope.packageJsonContent.type) {
35913591
if (targetExt) {

src/compiler/diagnosticMessages.json

+8
Original file line numberDiff line numberDiff line change
@@ -5146,6 +5146,14 @@
51465146
"category": "Message",
51475147
"code": 6261
51485148
},
5149+
"Directory '{0}' resolves to '{1}' scope according to cache.": {
5150+
"category": "Message",
5151+
"code": 6263
5152+
},
5153+
"Directory '{0}' has no containing package.json scope according to cache.": {
5154+
"category": "Message",
5155+
"code": 6264
5156+
},
51495157

51505158
"Directory '{0}' has no containing package.json scope. Imports will not resolve.": {
51515159
"category": "Message",

0 commit comments

Comments
 (0)