mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
During cacheResolutions dont watch failed lookups and dont look at those package.json if one exists per buildInfo
This commit is contained in:
+37
-3
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user