Make resolution cache use sets instead of arrays for easier checking (#51735)

This commit is contained in:
Sheetal Nandi 2022-12-06 14:25:19 -08:00 committed by GitHub
parent 38f33ade06
commit 84e475c105
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -41,7 +41,6 @@ import {
isNodeModulesDirectory,
isRootedDiskPath,
isTraceEnabled,
length,
loadModuleFromGlobalCache,
memoize,
MinimalResolutionCacheHost,
@ -72,7 +71,6 @@ import {
stringContains,
StringLiteralLike,
trace,
unorderedRemoveItem,
updateResolutionField,
WatchDirectoryFlags,
} from "./_namespaces/ts";
@ -136,7 +134,7 @@ export interface ResolutionWithFailedLookupLocations {
isInvalidated?: boolean;
refCount?: number;
// Files that have this resolution using
files?: Path[];
files?: Set<Path>;
}
interface ResolutionWithResolvedFileName {
@ -268,9 +266,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
let filesWithInvalidatedNonRelativeUnresolvedImports: ReadonlyMap<Path, readonly string[]> | undefined;
const nonRelativeExternalModuleResolutions = createMultiMap<ResolutionWithFailedLookupLocations>();
const resolutionsWithFailedLookups: ResolutionWithFailedLookupLocations[] = [];
const resolutionsWithOnlyAffectingLocations: ResolutionWithFailedLookupLocations[] = [];
const resolvedFileToResolution = createMultiMap<ResolutionWithFailedLookupLocations>();
const resolutionsWithFailedLookups = new Set<ResolutionWithFailedLookupLocations>();
const resolutionsWithOnlyAffectingLocations = new Set<ResolutionWithFailedLookupLocations>();
const resolvedFileToResolution = new Map<string, Set<ResolutionWithFailedLookupLocations>>();
const impliedFormatPackageJsons = new Map<Path, readonly string[]>();
let hasChangedAutomaticTypeDirectiveNames = false;
@ -367,8 +365,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
resolvedModuleNames.clear();
resolvedTypeReferenceDirectives.clear();
resolvedFileToResolution.clear();
resolutionsWithFailedLookups.length = 0;
resolutionsWithOnlyAffectingLocations.length = 0;
resolutionsWithFailedLookups.clear();
resolutionsWithOnlyAffectingLocations.clear();
failedLookupChecks = undefined;
startsWithPathChecks = undefined;
isInDirectoryChecks = undefined;
@ -782,7 +780,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
}
else {
resolution.refCount = 1;
Debug.assert(length(resolution.files) === 0); // This resolution shouldnt be referenced by any file yet
Debug.assert(!resolution.files?.size); // This resolution shouldnt be referenced by any file yet
if (isExternalModuleNameRelative(name)) {
watchFailedLookupLocationOfResolution(resolution);
}
@ -791,10 +789,13 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
}
const resolved = getResolutionWithResolvedFileName(resolution);
if (resolved && resolved.resolvedFileName) {
resolvedFileToResolution.add(resolutionHost.toPath(resolved.resolvedFileName), resolution);
const key = resolutionHost.toPath(resolved.resolvedFileName);
let resolutions = resolvedFileToResolution.get(key);
if (!resolutions) resolvedFileToResolution.set(key, resolutions = new Set());
resolutions.add(resolution);
}
}
(resolution.files || (resolution.files = [])).push(filePath);
(resolution.files ??= new Set()).add(filePath);
}
function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
@ -802,7 +803,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
const { failedLookupLocations, affectingLocations } = resolution;
if (!failedLookupLocations?.length && !affectingLocations?.length) return;
if (failedLookupLocations?.length) resolutionsWithFailedLookups.push(resolution);
if (failedLookupLocations?.length) resolutionsWithFailedLookups.add(resolution);
let setAtRoot = false;
if (failedLookupLocations) {
@ -839,7 +840,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
Debug.assert(!!resolution.refCount);
const { affectingLocations } = resolution;
if (!affectingLocations?.length) return;
if (addToResolutionsWithOnlyAffectingLocations) resolutionsWithOnlyAffectingLocations.push(resolution);
if (addToResolutionsWithOnlyAffectingLocations) resolutionsWithOnlyAffectingLocations.add(resolution);
// Watch package json
for (const affectingLocation of affectingLocations) {
createFileWatcherOfAffectingLocation(affectingLocation, /*forResolution*/ true);
@ -925,18 +926,20 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
filePath: Path,
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
) {
unorderedRemoveItem(Debug.checkDefined(resolution.files), filePath);
Debug.checkDefined(resolution.files).delete(filePath);
resolution.refCount!--;
if (resolution.refCount) {
return;
}
const resolved = getResolutionWithResolvedFileName(resolution);
if (resolved && resolved.resolvedFileName) {
resolvedFileToResolution.remove(resolutionHost.toPath(resolved.resolvedFileName), resolution);
const key = resolutionHost.toPath(resolved.resolvedFileName);
const resolutions = resolvedFileToResolution.get(key);
if (resolutions?.delete(resolution) && !resolutions.size) resolvedFileToResolution.delete(key);
}
const { failedLookupLocations, affectingLocations } = resolution;
if (unorderedRemoveItem(resolutionsWithFailedLookups, resolution)) {
if (resolutionsWithFailedLookups.delete(resolution)) {
let removeAtRoot = false;
for (const failedLookupLocation of failedLookupLocations!) {
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
@ -967,7 +970,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
}
}
else if (affectingLocations?.length) {
unorderedRemoveItem(resolutionsWithOnlyAffectingLocations, resolution);
resolutionsWithOnlyAffectingLocations.delete(resolution);
}
if (affectingLocations) {
@ -1028,18 +1031,18 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirective);
}
function invalidateResolutions(resolutions: ResolutionWithFailedLookupLocations[] | undefined, canInvalidate: (resolution: ResolutionWithFailedLookupLocations) => boolean | undefined) {
function invalidateResolutions(resolutions: Set<ResolutionWithFailedLookupLocations> | undefined, canInvalidate: (resolution: ResolutionWithFailedLookupLocations) => boolean | undefined) {
if (!resolutions) return false;
let invalidated = false;
for (const resolution of resolutions) {
if (resolution.isInvalidated || !canInvalidate(resolution)) continue;
resolutions.forEach(resolution => {
if (resolution.isInvalidated || !canInvalidate(resolution)) return;
resolution.isInvalidated = invalidated = true;
for (const containingFilePath of Debug.checkDefined(resolution.files)) {
(filesWithInvalidatedResolutions ??= new Set()).add(containingFilePath);
// When its a file with inferred types resolution, invalidate type reference directive resolution
hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames || endsWith(containingFilePath, inferredTypesContainingFile);
}
}
});
return invalidated;
}