During cacheResolutions dont watch failed lookups and dont look at those package.json if one exists per buildInfo

This commit is contained in:
Sheetal Nandi
2022-12-09 14:49:31 -08:00
parent e21738c351
commit be5ecb2ef8
13 changed files with 2844 additions and 6348 deletions
+37 -3
View File
@@ -187,6 +187,7 @@ export interface ReusableBuilderProgramState extends BuilderState {
modules: PerDirectoryAndNonRelativeNameCache<ResolvedModuleWithFailedLookupLocations> | undefined;
typeRefs: PerDirectoryAndNonRelativeNameCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations> | undefined;
packageJsons: Map<Path, string> | undefined;
nonRelativePackageJsonsCache: PerNonRelativeNameCache<string> | undefined;
packageJsonCache: PackageJsonInfoCache | undefined;
};
resuableCacheResolutions?: {
@@ -1475,16 +1476,16 @@ function getCacheResolutions(state: BuilderProgramState) {
let modules: PerDirectoryAndNonRelativeNameCache<ResolvedModuleWithFailedLookupLocations> | undefined;
let typeRefs: PerDirectoryAndNonRelativeNameCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations> | undefined;
let packageJsons: Map<Path, string> | undefined;
let nonRelativePackageJsons: PerNonRelativeNameCache<string> | undefined;
let nonRelativePackageJsonsCache: PerNonRelativeNameCache<string> | undefined;
for (const f of state.program!.getSourceFiles()) {
modules = toPerDirectoryAndNonRelativeNameCache(state, modules, getOriginalOrResolvedModuleFileName, f.resolvedModules, f);
typeRefs = toPerDirectoryAndNonRelativeNameCache(state, typeRefs, getOriginalOrResolvedTypeReferenceFileName, f.resolvedTypeReferenceDirectiveNames, f);
if (f.packageJsonScope) {
const dirPath = getDirectoryPath(f.resolvedPath);
if (!nonRelativePackageJsons?.getWithPath(dirPath)) {
if (!nonRelativePackageJsonsCache?.getWithPath(dirPath)) {
const result = last(f.packageJsonLocations!);
(packageJsons ??= new Map()).set(dirPath, result);
(nonRelativePackageJsons ??= createPerNonRelativeNameCache(
(nonRelativePackageJsonsCache ??= createPerNonRelativeNameCache(
state.program!.getCurrentDirectory(),
state.program!.getCanonicalFileName,
identity,
@@ -1501,6 +1502,7 @@ function getCacheResolutions(state: BuilderProgramState) {
modules,
typeRefs,
packageJsons,
nonRelativePackageJsonsCache,
packageJsonCache: state.program!.getModuleResolutionCache()?.getPackageJsonInfoCache().clone(),
};
}
@@ -2169,6 +2171,7 @@ export function createOldBuildInfoProgram(
}
const reusableResolvedModules = intializeReusableResolutionsCache(resuableCacheResolutions?.cache.modules);
const reusableResolvedTypeRefs = intializeReusableResolutionsCache(resuableCacheResolutions?.cache.typeRefs);
let decodedPackageJsons: PerNonRelativeNameCache<string> | undefined;
let decodedHashes: Map<ProgramBuildInfoAbsoluteFileId, string | undefined> | undefined;
let resolutions: (Resolution | false)[] | undefined;
let originalPathOrResolvedFileNames: string[] | undefined;
@@ -2195,6 +2198,7 @@ export function createOldBuildInfoProgram(
dirPath,
redirectedReference,
),
getPackageJsonPath,
};
function intializeReusableResolutionsCache(reusable: ProgramBuildInfoResolutionCacheWithRedirects | undefined): ReusableResolutionsCache | undefined {
@@ -2226,6 +2230,36 @@ export function createOldBuildInfoProgram(
return result;
}
function getPackageJsonPath(dir: string) {
const fromCache = cacheResolutions?.nonRelativePackageJsonsCache?.get(dir);
if (fromCache) {
return fileExists(fromCache) ? fromCache : undefined;
}
if (!resuableCacheResolutions?.cache.packageJsons) return;
if (!decodedPackageJsons) {
decodedPackageJsons = createPerNonRelativeNameCache(
resuableCacheResolutions.getProgramBuildInfoFilePathDecoder().currentDirectory,
resuableCacheResolutions.getProgramBuildInfoFilePathDecoder().getCanonicalFileName,
identity,
);
const filePathDecoder = resuableCacheResolutions.getProgramBuildInfoFilePathDecoder();
for (const dirIdOrDirAndPackageJson of resuableCacheResolutions.cache.packageJsons) {
let dirPath: Path, packageJson: string;
if (isArray(dirIdOrDirAndPackageJson)) {
dirPath = filePathDecoder.toFilePath(dirIdOrDirAndPackageJson[0]);
packageJson = filePathDecoder.toFileAbsolutePath(dirIdOrDirAndPackageJson[1]);
}
else {
packageJson = filePathDecoder.toFileAbsolutePath(dirIdOrDirAndPackageJson);
dirPath = getDirectoryPath(toPath(packageJson, filePathDecoder.currentDirectory, filePathDecoder.getCanonicalFileName));
}
decodedPackageJsons.setWithPath(dirPath, packageJson, noop);
}
}
const fromDecoded = decodedPackageJsons.get(dir);
return fromDecoded && fileExists(fromDecoded) ? fromDecoded : undefined;
}
function getResolvedFromCache<T extends ResolvedModuleWithFailedLookupLocations | ResolvedTypeReferenceDirectiveWithFailedLookupLocations>(
cache: PerDirectoryAndNonRelativeNameCache<T> | undefined,
getResolvedFileName: (resolution: T) => string | undefined,
+10 -2
View File
@@ -1301,6 +1301,12 @@ function gatherPossibleChildren(node: Node) {
}
}
/** @internal */
export interface SourceFilePackageJsonInfo {
packageJsonLocations?: readonly string[];
packageJsonScope?: PackageJsonInfo;
}
export interface CreateSourceFileOptions {
languageVersion: ScriptTarget;
/**
@@ -1315,8 +1321,10 @@ export interface CreateSourceFileOptions {
* check specified by `isFileProbablyExternalModule` will be used to set the field.
*/
setExternalModuleIndicator?: (file: SourceFile) => void;
/** @internal */ packageJsonLocations?: readonly string[];
/** @internal */ packageJsonScope?: PackageJsonInfo;
}
/** @internal */
export interface CreateSourceFileOptions extends SourceFilePackageJsonInfo {
}
function setExternalModuleIndicator(sourceFile: SourceFile) {
+21 -7
View File
@@ -1253,7 +1253,7 @@ export function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCom
* @returns `undefined` if the path has no relevant implied format, `ModuleKind.ESNext` for esm format, and `ModuleKind.CommonJS` for cjs format
*/
export function getImpliedNodeFormatForFile(fileName: Path, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ResolutionMode {
const result = getImpliedNodeFormatForFileWorker(fileName, packageJsonInfoCache, host, options);
const result = getImpliedNodeFormatForFileWorker(fileName, packageJsonInfoCache, host, options, /*oldBuildInfoProgram*/ undefined);
return typeof result === "object" ? result.impliedNodeFormat : result;
}
@@ -1263,6 +1263,7 @@ export function getImpliedNodeFormatForFileWorker(
packageJsonInfoCache: PackageJsonInfoCache | undefined,
host: ModuleResolutionHost,
options: CompilerOptions,
oldBuildInfoProgram: OldBuildInfoProgram | undefined,
) {
switch (getEmitModuleResolutionKind(options)) {
case ModuleResolutionKind.Node16:
@@ -1279,9 +1280,16 @@ export function getImpliedNodeFormatForFileWorker(
const packageJsonLocations: string[] = [];
state.failedLookupLocations = packageJsonLocations;
state.affectingLocations = packageJsonLocations;
const packageJsonScope = getPackageScopeForPath(fileName, state);
const fromOld = oldBuildInfoProgram?.getPackageJsonPath(getDirectoryPath(fileName));
const packageJsonScope = fromOld ?
getPackageJsonInfo(getDirectoryPath(fromOld), /*onlyRecordFailures*/ false, state) :
getPackageScopeForPath(fileName, state);
const impliedNodeFormat = packageJsonScope?.contents.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS;
return { impliedNodeFormat, packageJsonLocations, packageJsonScope };
return {
impliedNodeFormat,
packageJsonLocations: packageJsonLocations.length ? packageJsonLocations : undefined,
packageJsonScope
};
}
}
@@ -2374,7 +2382,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
if (!newSourceFile) {
return StructureIsReused.Not;
}
newSourceFile.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined;
newSourceFile.packageJsonLocations = sourceFileOptions.packageJsonLocations;
newSourceFile.packageJsonScope = sourceFileOptions.packageJsonScope;
Debug.assert(!newSourceFile.redirectInfo, "Host should not return a redirect source file from `getSourceFile`");
@@ -3452,7 +3460,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
redirect.resolvedPath = resolvedPath;
redirect.originalFileName = originalFileName;
redirect.redirectInfo = { redirectTarget, unredirected };
redirect.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined;
redirect.packageJsonLocations = sourceFileOptions.packageJsonLocations;
redirect.packageJsonScope = sourceFileOptions.packageJsonScope;
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
Object.defineProperties(redirect, {
@@ -3484,7 +3492,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
// It's a _little odd_ that we can't set `impliedNodeFormat` until the program step - but it's the first and only time we have a resolution cache
// and a freshly made source file node on hand at the same time, and we need both to set the field. Persisting the resolution cache all the way
// to the check and emit steps would be bad - so we much prefer detecting and storing the format information on the source file node upfront.
const result = getImpliedNodeFormatForFileWorker(getNormalizedAbsolutePath(fileName, currentDirectory), moduleResolutionCache?.getPackageJsonInfoCache(), host, options);
const result = getImpliedNodeFormatForFileWorker(
getNormalizedAbsolutePath(fileName, currentDirectory),
moduleResolutionCache?.getPackageJsonInfoCache(),
host,
options,
oldBuildInfoProgram,
);
const languageVersion = getEmitScriptTarget(options);
const setExternalModuleIndicator = getSetExternalModuleIndicator(options);
return typeof result === "object" ?
@@ -3618,7 +3632,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
file.path = path;
file.resolvedPath = toPath(fileName);
file.originalFileName = originalFileName;
file.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined;
file.packageJsonLocations = sourceFileOptions.packageJsonLocations;
file.packageJsonScope = sourceFileOptions.packageJsonScope;
addFileIncludeReason(file, reason);
+32 -12
View File
@@ -43,6 +43,7 @@ import {
isRootedDiskPath,
isString,
isTraceEnabled,
last,
loadModuleFromGlobalCache,
memoize,
MinimalResolutionCacheHost,
@@ -467,18 +468,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
getResolvedTypeReferenceDirective,
);
}
const expected = isExternalOrCommonJsModule(newFile) ? newFile.packageJsonLocations?.length ?? 0 : 0;
const existing = impliedFormatPackageJsons.get(newFile.path) ?? emptyArray;
for (let i = existing.length; i < expected; i++) {
createFileWatcherOfAffectingLocation(newFile.packageJsonLocations![i], /*forResolution*/ false);
}
if (existing.length > expected) {
for (let i = expected; i < existing.length; i++) {
fileWatchesOfAffectingLocations.get(existing[i])!.files--;
}
}
if (expected) impliedFormatPackageJsons.set(newFile.path, newFile.packageJsonLocations!);
else impliedFormatPackageJsons.delete(newFile.path);
ensurePackageJsonWatchesForFile(newProgram, newFile);
}
if (needsResolutionUpdate) {
const newProgramAutoTypeRefContainingFile = resolutionHost.toPath(newProgram.getAutomaticTypeDirectiveContainingFile());
@@ -521,6 +511,36 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
});
}
function ensurePackageJsonWatchesForFile(newProgram: Program, newFile: SourceFile) {
const options = newProgram.getCompilerOptions();
const existing = impliedFormatPackageJsons.get(newFile.path) ?? emptyArray;
let expected = isExternalOrCommonJsModule(newFile) ? newFile.packageJsonLocations ?? emptyArray : emptyArray;
if (!options.cacheResolutions) {
for (let i = existing.length; i < expected.length; i++) {
createFileWatcherOfAffectingLocation(expected[i], /*forResolution*/ false);
}
if (existing.length > expected.length) {
for (let i = expected.length; i < existing.length; i++) {
fileWatchesOfAffectingLocations.get(existing[i])!.files--;
}
}
}
else {
// Do not watch failed lookups for source file's package.json when caching resolutions
expected = expected.length && newFile.packageJsonScope ? [last(expected)] : expected;
if (expected.length !== 1 || existing.length !== 1 || expected[0] !== existing[0]) {
for (const location of expected) {
createFileWatcherOfAffectingLocation(location, /*forResolution*/ false);
}
for (const location of existing) {
fileWatchesOfAffectingLocations.get(location)!.files--;
}
}
}
if (expected.length) impliedFormatPackageJsons.set(newFile.path, expected);
else impliedFormatPackageJsons.delete(newFile.path);
}
function ensureResolutionsOfFile<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
newProgram: Program,
perDirCache: PerDirectoryAndNonRelativeNameCache<T> | undefined,
+6 -2
View File
@@ -15,6 +15,7 @@ import {
Pattern,
ProgramBuildInfo,
Push,
SourceFilePackageJsonInfo,
SymlinkCache,
TypeReferenceDirectiveResolutionCache,
} from "./_namespaces/ts";
@@ -4062,8 +4063,6 @@ export interface SourceFile extends Declaration {
* CommonJS-output-format by the node module transformer and type checker, regardless of extension or context.
*/
impliedNodeFormat?: ResolutionMode;
/** @internal */ packageJsonLocations?: readonly string[];
/** @internal */ packageJsonScope?: PackageJsonInfo;
/** @internal */ scriptKind: ScriptKind;
@@ -4135,6 +4134,10 @@ export interface SourceFile extends Declaration {
/** @internal */ endFlowNode?: FlowNode;
}
/** @internal */
export interface SourceFile extends SourceFilePackageJsonInfo {
}
/** @internal */
export interface CommentDirective {
range: TextRange;
@@ -6979,6 +6982,7 @@ export interface OldBuildInfoProgram {
getCompilerOptions(): CompilerOptions;
getResolvedModule(name: string, mode: ResolutionMode, dirPath: Path, redirectedReference: ResolvedProjectReference | undefined): ResolvedModuleWithFailedLookupLocations | undefined;
getResolvedTypeReferenceDirective(name: string, mode: ResolutionMode, dirPath: Path, redirectedReference: ResolvedProjectReference | undefined): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined;
getPackageJsonPath(dir: string): string | undefined;
}
/** @internal */