Skip to content

Commit 839ef57

Browse files
committed
During cacheResolutions dont watch failed lookups and dont look at those package.json if one exists per buildInfo
1 parent 7507303 commit 839ef57

File tree

13 files changed

+2886
-6390
lines changed

13 files changed

+2886
-6390
lines changed

src/compiler/builder.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ export interface ReusableBuilderProgramState extends BuilderState {
187187
modules: PerDirectoryAndNonRelativeNameCache<ResolvedModuleWithFailedLookupLocations> | undefined;
188188
typeRefs: PerDirectoryAndNonRelativeNameCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations> | undefined;
189189
packageJsons: Map<Path, string> | undefined;
190+
nonRelativePackageJsonsCache: PerNonRelativeNameCache<string> | undefined;
190191
packageJsonCache: PackageJsonInfoCache | undefined;
191192
};
192193
resuableCacheResolutions?: {
@@ -1475,16 +1476,16 @@ function getCacheResolutions(state: BuilderProgramState) {
14751476
let modules: PerDirectoryAndNonRelativeNameCache<ResolvedModuleWithFailedLookupLocations> | undefined;
14761477
let typeRefs: PerDirectoryAndNonRelativeNameCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations> | undefined;
14771478
let packageJsons: Map<Path, string> | undefined;
1478-
let nonRelativePackageJsons: PerNonRelativeNameCache<string> | undefined;
1479+
let nonRelativePackageJsonsCache: PerNonRelativeNameCache<string> | undefined;
14791480
for (const f of state.program!.getSourceFiles()) {
14801481
modules = toPerDirectoryAndNonRelativeNameCache(state, modules, getOriginalOrResolvedModuleFileName, f.resolvedModules, f);
14811482
typeRefs = toPerDirectoryAndNonRelativeNameCache(state, typeRefs, getOriginalOrResolvedTypeReferenceFileName, f.resolvedTypeReferenceDirectiveNames, f);
14821483
if (f.packageJsonScope) {
14831484
const dirPath = getDirectoryPath(f.resolvedPath);
1484-
if (!nonRelativePackageJsons?.getWithPath(dirPath)) {
1485+
if (!nonRelativePackageJsonsCache?.getWithPath(dirPath)) {
14851486
const result = last(f.packageJsonLocations!);
14861487
(packageJsons ??= new Map()).set(dirPath, result);
1487-
(nonRelativePackageJsons ??= createPerNonRelativeNameCache(
1488+
(nonRelativePackageJsonsCache ??= createPerNonRelativeNameCache(
14881489
state.program!.getCurrentDirectory(),
14891490
state.program!.getCanonicalFileName,
14901491
identity,
@@ -1501,6 +1502,7 @@ function getCacheResolutions(state: BuilderProgramState) {
15011502
modules,
15021503
typeRefs,
15031504
packageJsons,
1505+
nonRelativePackageJsonsCache,
15041506
packageJsonCache: state.program!.getModuleResolutionCache()?.getPackageJsonInfoCache().clone(),
15051507
};
15061508
}
@@ -2169,6 +2171,7 @@ export function createOldBuildInfoProgram(
21692171
}
21702172
const reusableResolvedModules = intializeReusableResolutionsCache(resuableCacheResolutions?.cache.modules);
21712173
const reusableResolvedTypeRefs = intializeReusableResolutionsCache(resuableCacheResolutions?.cache.typeRefs);
2174+
let decodedPackageJsons: PerNonRelativeNameCache<string> | undefined;
21722175
let decodedHashes: Map<ProgramBuildInfoAbsoluteFileId, string | undefined> | undefined;
21732176
let resolutions: (Resolution | false)[] | undefined;
21742177
let originalPathOrResolvedFileNames: string[] | undefined;
@@ -2195,6 +2198,7 @@ export function createOldBuildInfoProgram(
21952198
dirPath,
21962199
redirectedReference,
21972200
),
2201+
getPackageJsonPath,
21982202
};
21992203

22002204
function intializeReusableResolutionsCache(reusable: ProgramBuildInfoResolutionCacheWithRedirects | undefined): ReusableResolutionsCache | undefined {
@@ -2226,6 +2230,36 @@ export function createOldBuildInfoProgram(
22262230
return result;
22272231
}
22282232

2233+
function getPackageJsonPath(dir: string) {
2234+
const fromCache = cacheResolutions?.nonRelativePackageJsonsCache?.get(dir);
2235+
if (fromCache) {
2236+
return fileExists(fromCache) ? fromCache : undefined;
2237+
}
2238+
if (!resuableCacheResolutions?.cache.packageJsons) return;
2239+
if (!decodedPackageJsons) {
2240+
decodedPackageJsons = createPerNonRelativeNameCache(
2241+
resuableCacheResolutions.getProgramBuildInfoFilePathDecoder().currentDirectory,
2242+
resuableCacheResolutions.getProgramBuildInfoFilePathDecoder().getCanonicalFileName,
2243+
identity,
2244+
);
2245+
const filePathDecoder = resuableCacheResolutions.getProgramBuildInfoFilePathDecoder();
2246+
for (const dirIdOrDirAndPackageJson of resuableCacheResolutions.cache.packageJsons) {
2247+
let dirPath: Path, packageJson: string;
2248+
if (isArray(dirIdOrDirAndPackageJson)) {
2249+
dirPath = filePathDecoder.toFilePath(dirIdOrDirAndPackageJson[0]);
2250+
packageJson = filePathDecoder.toFileAbsolutePath(dirIdOrDirAndPackageJson[1]);
2251+
}
2252+
else {
2253+
packageJson = filePathDecoder.toFileAbsolutePath(dirIdOrDirAndPackageJson);
2254+
dirPath = getDirectoryPath(toPath(packageJson, filePathDecoder.currentDirectory, filePathDecoder.getCanonicalFileName));
2255+
}
2256+
decodedPackageJsons.setWithPath(dirPath, packageJson, noop);
2257+
}
2258+
}
2259+
const fromDecoded = decodedPackageJsons.get(dir);
2260+
return fromDecoded && fileExists(fromDecoded) ? fromDecoded : undefined;
2261+
}
2262+
22292263
function getResolvedFromCache<T extends ResolvedModuleWithFailedLookupLocations | ResolvedTypeReferenceDirectiveWithFailedLookupLocations>(
22302264
cache: PerDirectoryAndNonRelativeNameCache<T> | undefined,
22312265
getResolvedFileName: (resolution: T) => string | undefined,

src/compiler/parser.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,12 @@ function gatherPossibleChildren(node: Node) {
13011301
}
13021302
}
13031303

1304+
/** @internal */
1305+
export interface SourceFilePackageJsonInfo {
1306+
packageJsonLocations?: readonly string[];
1307+
packageJsonScope?: PackageJsonInfo;
1308+
}
1309+
13041310
export interface CreateSourceFileOptions {
13051311
languageVersion: ScriptTarget;
13061312
/**
@@ -1315,8 +1321,10 @@ export interface CreateSourceFileOptions {
13151321
* check specified by `isFileProbablyExternalModule` will be used to set the field.
13161322
*/
13171323
setExternalModuleIndicator?: (file: SourceFile) => void;
1318-
/** @internal */ packageJsonLocations?: readonly string[];
1319-
/** @internal */ packageJsonScope?: PackageJsonInfo;
1324+
}
1325+
1326+
/** @internal */
1327+
export interface CreateSourceFileOptions extends SourceFilePackageJsonInfo {
13201328
}
13211329

13221330
function setExternalModuleIndicator(sourceFile: SourceFile) {

src/compiler/program.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,7 +1253,7 @@ export function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCom
12531253
* @returns `undefined` if the path has no relevant implied format, `ModuleKind.ESNext` for esm format, and `ModuleKind.CommonJS` for cjs format
12541254
*/
12551255
export function getImpliedNodeFormatForFile(fileName: Path, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ResolutionMode {
1256-
const result = getImpliedNodeFormatForFileWorker(fileName, packageJsonInfoCache, host, options);
1256+
const result = getImpliedNodeFormatForFileWorker(fileName, packageJsonInfoCache, host, options, /*oldBuildInfoProgram*/ undefined);
12571257
return typeof result === "object" ? result.impliedNodeFormat : result;
12581258
}
12591259

@@ -1263,6 +1263,7 @@ export function getImpliedNodeFormatForFileWorker(
12631263
packageJsonInfoCache: PackageJsonInfoCache | undefined,
12641264
host: ModuleResolutionHost,
12651265
options: CompilerOptions,
1266+
oldBuildInfoProgram: OldBuildInfoProgram | undefined,
12661267
) {
12671268
switch (getEmitModuleResolutionKind(options)) {
12681269
case ModuleResolutionKind.Node16:
@@ -1279,9 +1280,16 @@ export function getImpliedNodeFormatForFileWorker(
12791280
const packageJsonLocations: string[] = [];
12801281
state.failedLookupLocations = packageJsonLocations;
12811282
state.affectingLocations = packageJsonLocations;
1282-
const packageJsonScope = getPackageScopeForPath(fileName, state);
1283+
const fromOld = oldBuildInfoProgram?.getPackageJsonPath(getDirectoryPath(fileName));
1284+
const packageJsonScope = fromOld ?
1285+
getPackageJsonInfo(getDirectoryPath(fromOld), /*onlyRecordFailures*/ false, state) :
1286+
getPackageScopeForPath(fileName, state);
12831287
const impliedNodeFormat = packageJsonScope?.contents.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS;
1284-
return { impliedNodeFormat, packageJsonLocations, packageJsonScope };
1288+
return {
1289+
impliedNodeFormat,
1290+
packageJsonLocations: packageJsonLocations.length ? packageJsonLocations : undefined,
1291+
packageJsonScope
1292+
};
12851293
}
12861294
}
12871295

@@ -2374,7 +2382,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
23742382
if (!newSourceFile) {
23752383
return StructureIsReused.Not;
23762384
}
2377-
newSourceFile.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined;
2385+
newSourceFile.packageJsonLocations = sourceFileOptions.packageJsonLocations;
23782386
newSourceFile.packageJsonScope = sourceFileOptions.packageJsonScope;
23792387

23802388
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
34523460
redirect.resolvedPath = resolvedPath;
34533461
redirect.originalFileName = originalFileName;
34543462
redirect.redirectInfo = { redirectTarget, unredirected };
3455-
redirect.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined;
3463+
redirect.packageJsonLocations = sourceFileOptions.packageJsonLocations;
34563464
redirect.packageJsonScope = sourceFileOptions.packageJsonScope;
34573465
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
34583466
Object.defineProperties(redirect, {
@@ -3484,7 +3492,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
34843492
// 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
34853493
// 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
34863494
// 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.
3487-
const result = getImpliedNodeFormatForFileWorker(getNormalizedAbsolutePath(fileName, currentDirectory), moduleResolutionCache?.getPackageJsonInfoCache(), host, options);
3495+
const result = getImpliedNodeFormatForFileWorker(
3496+
getNormalizedAbsolutePath(fileName, currentDirectory),
3497+
moduleResolutionCache?.getPackageJsonInfoCache(),
3498+
host,
3499+
options,
3500+
oldBuildInfoProgram,
3501+
);
34883502
const languageVersion = getEmitScriptTarget(options);
34893503
const setExternalModuleIndicator = getSetExternalModuleIndicator(options);
34903504
return typeof result === "object" ?
@@ -3618,7 +3632,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
36183632
file.path = path;
36193633
file.resolvedPath = toPath(fileName);
36203634
file.originalFileName = originalFileName;
3621-
file.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined;
3635+
file.packageJsonLocations = sourceFileOptions.packageJsonLocations;
36223636
file.packageJsonScope = sourceFileOptions.packageJsonScope;
36233637
addFileIncludeReason(file, reason);
36243638

src/compiler/resolutionCache.ts

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import {
4343
isRootedDiskPath,
4444
isString,
4545
isTraceEnabled,
46+
last,
4647
loadModuleFromGlobalCache,
4748
memoize,
4849
MinimalResolutionCacheHost,
@@ -467,18 +468,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
467468
getResolvedTypeReferenceDirective,
468469
);
469470
}
470-
const expected = isExternalOrCommonJsModule(newFile) ? newFile.packageJsonLocations?.length ?? 0 : 0;
471-
const existing = impliedFormatPackageJsons.get(newFile.path) ?? emptyArray;
472-
for (let i = existing.length; i < expected; i++) {
473-
createFileWatcherOfAffectingLocation(newFile.packageJsonLocations![i], /*forResolution*/ false);
474-
}
475-
if (existing.length > expected) {
476-
for (let i = expected; i < existing.length; i++) {
477-
fileWatchesOfAffectingLocations.get(existing[i])!.files--;
478-
}
479-
}
480-
if (expected) impliedFormatPackageJsons.set(newFile.path, newFile.packageJsonLocations!);
481-
else impliedFormatPackageJsons.delete(newFile.path);
471+
ensurePackageJsonWatchesForFile(newProgram, newFile);
482472
}
483473
if (needsResolutionUpdate) {
484474
const newProgramAutoTypeRefContainingFile = resolutionHost.toPath(newProgram.getAutomaticTypeDirectiveContainingFile());
@@ -521,6 +511,36 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
521511
});
522512
}
523513

514+
function ensurePackageJsonWatchesForFile(newProgram: Program, newFile: SourceFile) {
515+
const options = newProgram.getCompilerOptions();
516+
const existing = impliedFormatPackageJsons.get(newFile.path) ?? emptyArray;
517+
let expected = isExternalOrCommonJsModule(newFile) ? newFile.packageJsonLocations ?? emptyArray : emptyArray;
518+
if (!options.cacheResolutions) {
519+
for (let i = existing.length; i < expected.length; i++) {
520+
createFileWatcherOfAffectingLocation(expected[i], /*forResolution*/ false);
521+
}
522+
if (existing.length > expected.length) {
523+
for (let i = expected.length; i < existing.length; i++) {
524+
fileWatchesOfAffectingLocations.get(existing[i])!.files--;
525+
}
526+
}
527+
}
528+
else {
529+
// Do not watch failed lookups for source file's package.json when caching resolutions
530+
expected = expected.length && newFile.packageJsonScope ? [last(expected)] : expected;
531+
if (expected.length !== 1 || existing.length !== 1 || expected[0] !== existing[0]) {
532+
for (const location of expected) {
533+
createFileWatcherOfAffectingLocation(location, /*forResolution*/ false);
534+
}
535+
for (const location of existing) {
536+
fileWatchesOfAffectingLocations.get(location)!.files--;
537+
}
538+
}
539+
}
540+
if (expected.length) impliedFormatPackageJsons.set(newFile.path, expected);
541+
else impliedFormatPackageJsons.delete(newFile.path);
542+
}
543+
524544
function ensureResolutionsOfFile<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
525545
newProgram: Program,
526546
perDirCache: PerDirectoryAndNonRelativeNameCache<T> | undefined,

src/compiler/types.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
Pattern,
1616
ProgramBuildInfo,
1717
Push,
18+
SourceFilePackageJsonInfo,
1819
SymlinkCache,
1920
TypeReferenceDirectiveResolutionCache,
2021
} from "./_namespaces/ts";
@@ -4062,8 +4063,6 @@ export interface SourceFile extends Declaration {
40624063
* CommonJS-output-format by the node module transformer and type checker, regardless of extension or context.
40634064
*/
40644065
impliedNodeFormat?: ResolutionMode;
4065-
/** @internal */ packageJsonLocations?: readonly string[];
4066-
/** @internal */ packageJsonScope?: PackageJsonInfo;
40674066

40684067
/** @internal */ scriptKind: ScriptKind;
40694068

@@ -4135,6 +4134,10 @@ export interface SourceFile extends Declaration {
41354134
/** @internal */ endFlowNode?: FlowNode;
41364135
}
41374136

4137+
/** @internal */
4138+
export interface SourceFile extends SourceFilePackageJsonInfo {
4139+
}
4140+
41384141
/** @internal */
41394142
export interface CommentDirective {
41404143
range: TextRange;
@@ -6979,6 +6982,7 @@ export interface OldBuildInfoProgram {
69796982
getCompilerOptions(): CompilerOptions;
69806983
getResolvedModule(name: string, mode: ResolutionMode, dirPath: Path, redirectedReference: ResolvedProjectReference | undefined): ResolvedModuleWithFailedLookupLocations | undefined;
69816984
getResolvedTypeReferenceDirective(name: string, mode: ResolutionMode, dirPath: Path, redirectedReference: ResolvedProjectReference | undefined): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined;
6985+
getPackageJsonPath(dir: string): string | undefined;
69826986
}
69836987

69846988
/** @internal */

0 commit comments

Comments
 (0)