Skip to content

Commit

Permalink
During cacheResolutions dont watch failed lookups and dont look at th…
Browse files Browse the repository at this point in the history
…ose package.json if one exists per buildInfo
  • Loading branch information
sheetalkamat committed Aug 3, 2022
1 parent c703705 commit 8d300c0
Show file tree
Hide file tree
Showing 13 changed files with 474 additions and 1,823 deletions.
37 changes: 37 additions & 0 deletions src/compiler/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ namespace ts {
modules: CacheWithRedirects<Path, ModeAwareCache<ResolvedModuleWithFailedLookupLocations>> | undefined;
typeRefs: CacheWithRedirects<Path, ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>> | undefined;
moduleNameToDirectoryMap: CacheWithRedirects<ModeAwareCacheKey, ESMap<Path, ResolvedModuleWithFailedLookupLocations>>;
dirToPackageJsonMap: ESMap<Path, string>;
perDirPackageJsonMap: ESMap<Path, string> | undefined;
packageJsonCache: PackageJsonInfoCache | undefined;
};
Expand Down Expand Up @@ -1302,6 +1303,7 @@ namespace ts {
modules,
typeRefs,
moduleNameToDirectoryMap,
dirToPackageJsonMap,
perDirPackageJsonMap,
packageJsonCache: state.program!.getModuleResolutionCache()?.getPackageJsonInfoCache().clone(),
};
Expand Down Expand Up @@ -1963,6 +1965,7 @@ namespace ts {
const decodedResolvedModules: DecodedResolvedMap = createCacheWithRedirects(compilerOptions);
const decodedResolvedTypeRefs: DecodedResolvedMap = createCacheWithRedirects(compilerOptions);
const decodedModuleNameToDirectoryMap: DecodedModuleNameToDirectoryMap = createCacheWithRedirects(compilerOptions);
let decodedPackageJsonMap: ESMap<Path, string> | undefined;
let decodedHashes: ESMap<ProgramBuildInfoAbsoluteFileId, string | undefined> | undefined;

let resolutions: (Resolution | false)[] | undefined;
Expand Down Expand Up @@ -1993,6 +1996,7 @@ namespace ts {
/*moduleNameToDirectoryMap*/ undefined,
/*decodedModuleNameToDirectoryMap*/ undefined,
),
getPackageJsonPath,
};

function fileExists(fileName: string) {
Expand Down Expand Up @@ -2020,6 +2024,39 @@ namespace ts {
return result;
}

function getPackageJsonPath(dirPath: Path) {
const fromCache = cacheResolutions?.dirToPackageJsonMap?.get(dirPath);
if (fromCache) {
return fileExists(fromCache) ? fromCache : undefined;
}
if (!resuableCacheResolutions?.cache.packageJsons) return;
if (!decodedPackageJsonMap) {
decodedPackageJsonMap = new Map();
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));
}
moduleNameToDirectorySet(
decodedPackageJsonMap,
dirPath,
packageJson,
identity,
fileName => toPath(fileName, filePathDecoder.currentDirectory, filePathDecoder.getCanonicalFileName),
noop
);
}
}
const fromDecoded = decodedPackageJsonMap.get(dirPath);
return fromDecoded && fileExists(fromDecoded) ? fromDecoded : undefined;
}

function getResolvedFromCache<T extends ResolvedModuleWithFailedLookupLocations | ResolvedTypeReferenceDirectiveWithFailedLookupLocations>(
cache: CacheWithRedirects<Path, ModeAwareCache<T>> | undefined,
reusableCache: ProgramBuildInfoResolutionCacheWithRedirects | undefined,
Expand Down
12 changes: 10 additions & 2 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,12 @@ namespace ts {
}
}

/*@internal*/
export interface SourceFilePackageJsonInfo {
packageJsonLocations?: readonly string[];
packageJsonScope?: PackageJsonInfo;
}

export interface CreateSourceFileOptions {
languageVersion: ScriptTarget;
/**
Expand All @@ -746,8 +752,10 @@ namespace ts {
* 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) {
Expand Down
22 changes: 15 additions & 7 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ namespace ts {
* @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;
}

Expand All @@ -869,6 +869,7 @@ namespace ts {
packageJsonInfoCache: PackageJsonInfoCache | undefined,
host: ModuleResolutionHost,
options: CompilerOptions,
oldBuildInfoProgram: OldBuildInfoProgram | undefined,
) {
switch (getEmitModuleResolutionKind(options)) {
case ModuleResolutionKind.Node16:
Expand All @@ -885,9 +886,16 @@ namespace ts {
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?.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS;
return { impliedNodeFormat, packageJsonLocations, packageJsonScope };
return {
impliedNodeFormat,
packageJsonLocations: packageJsonLocations.length ? packageJsonLocations : undefined,
packageJsonScope
};
}
}

Expand Down Expand Up @@ -1977,7 +1985,7 @@ namespace ts {
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`");
Expand Down Expand Up @@ -3048,7 +3056,7 @@ namespace ts {
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, {
Expand Down Expand Up @@ -3080,7 +3088,7 @@ namespace ts {
// 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(toPath(fileName), moduleResolutionCache?.getPackageJsonInfoCache(), host, options);
const result = getImpliedNodeFormatForFileWorker(toPath(fileName), moduleResolutionCache?.getPackageJsonInfoCache(), host, options, oldBuildInfoProgram);
const languageVersion = getEmitScriptTarget(options);
const setExternalModuleIndicator = getSetExternalModuleIndicator(options);
return typeof result === "object" ?
Expand Down Expand Up @@ -3214,7 +3222,7 @@ namespace ts {
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);

Expand Down
43 changes: 31 additions & 12 deletions src/compiler/resolutionCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,18 +360,7 @@ namespace ts {
/*moduleNameToDirectoryMap*/ undefined,
);
}
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());
Expand Down Expand Up @@ -421,6 +410,36 @@ namespace ts {
});
}

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,
perFileCache: PerFileCache<T>,
Expand Down
7 changes: 5 additions & 2 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3799,8 +3799,6 @@ namespace ts {
* 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;

Expand Down Expand Up @@ -3868,6 +3866,10 @@ namespace ts {
/* @internal */ endFlowNode?: FlowNode;
}

/*@internal*/
export interface SourceFile extends SourceFilePackageJsonInfo {
}

/* @internal */
export interface CommentDirective {
range: TextRange;
Expand Down Expand Up @@ -6629,6 +6631,7 @@ namespace ts {
mode: ResolutionMode,
redirectedReference: ResolvedProjectReference | undefined,
): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined;
getPackageJsonPath(dirPath: Path): string | undefined;
}

/*@internal*/
Expand Down
Loading

0 comments on commit 8d300c0

Please sign in to comment.