Skip to content

Commit 9569b13

Browse files
committed
Use refcounts on the resolution so we arent going through failed lookup locations when resolutions are cached.
1 parent fdb5e95 commit 9569b13

File tree

1 file changed

+74
-61
lines changed

1 file changed

+74
-61
lines changed

src/compiler/resolutionCache.ts

Lines changed: 74 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ namespace ts {
2828
interface ResolutionWithFailedLookupLocations {
2929
readonly failedLookupLocations: ReadonlyArray<string>;
3030
isInvalidated?: boolean;
31+
refCount?: number;
3132
}
3233

3334
interface ResolutionWithResolvedFileName {
@@ -257,17 +258,11 @@ namespace ts {
257258
perDirectoryResolution.set(name, resolution);
258259
}
259260
resolutionsInFile.set(name, resolution);
260-
if (resolution.failedLookupLocations) {
261-
if (existingResolution && existingResolution.failedLookupLocations) {
262-
watchAndStopWatchDiffFailedLookupLocations(resolution, existingResolution);
263-
}
264-
else {
265-
watchFailedLookupLocationOfResolution(resolution, 0);
266-
}
267-
}
268-
else if (existingResolution) {
261+
watchFailedLookupLocationOfResolution(resolution);
262+
if (existingResolution) {
269263
stopWatchFailedLookupLocationOfResolution(existingResolution);
270264
}
265+
271266
if (logChanges && filesWithChangedSetOfUnresolvedImports && !resolutionIsEqualTo(existingResolution, resolution)) {
272267
filesWithChangedSetOfUnresolvedImports.push(path);
273268
// reset log changes to avoid recording the same file multiple times
@@ -399,80 +394,98 @@ namespace ts {
399394
return fileExtensionIsOneOf(path, failedLookupDefaultExtensions);
400395
}
401396

402-
function watchAndStopWatchDiffFailedLookupLocations(resolution: ResolutionWithFailedLookupLocations, existingResolution: ResolutionWithFailedLookupLocations) {
403-
const failedLookupLocations = resolution.failedLookupLocations;
404-
const existingFailedLookupLocations = existingResolution.failedLookupLocations;
405-
for (let index = 0; index < failedLookupLocations.length; index++) {
406-
if (index === existingFailedLookupLocations.length) {
407-
// Additional failed lookup locations, watch from this index
408-
watchFailedLookupLocationOfResolution(resolution, index);
409-
return;
410-
}
411-
else if (failedLookupLocations[index] !== existingFailedLookupLocations[index]) {
412-
// Different failed lookup locations,
413-
// Watch new resolution failed lookup locations from this index and
414-
// stop watching existing resolutions from this index
415-
watchFailedLookupLocationOfResolution(resolution, index);
416-
stopWatchFailedLookupLocationOfResolutionFrom(existingResolution, index);
417-
return;
418-
}
397+
function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
398+
// No need to set the resolution refCount
399+
if (!resolution.failedLookupLocations || !resolution.failedLookupLocations.length) {
400+
return;
419401
}
420402

421-
// All new failed lookup locations are already watched (and are same),
422-
// Stop watching failed lookup locations of existing resolution after failed lookup locations length
423-
stopWatchFailedLookupLocationOfResolutionFrom(existingResolution, failedLookupLocations.length);
424-
}
403+
if (resolution.refCount !== undefined) {
404+
resolution.refCount++;
405+
return;
406+
}
425407

426-
function watchFailedLookupLocationOfResolution({ failedLookupLocations }: ResolutionWithFailedLookupLocations, startIndex: number) {
427-
for (let i = startIndex; i < failedLookupLocations.length; i++) {
428-
const failedLookupLocation = failedLookupLocations[i];
408+
resolution.refCount = 1;
409+
const { failedLookupLocations } = resolution;
410+
let setAtRoot = false;
411+
for (const failedLookupLocation of failedLookupLocations) {
429412
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
430-
// If the failed lookup location path is not one of the supported extensions,
431-
// store it in the custom path
432-
if (!isPathWithDefaultFailedLookupExtension(failedLookupLocationPath)) {
433-
const refCount = customFailedLookupPaths.get(failedLookupLocationPath) || 0;
434-
customFailedLookupPaths.set(failedLookupLocationPath, refCount + 1);
435-
}
436413
const { dir, dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
437414
if (!ignore) {
438-
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
439-
if (dirWatcher) {
440-
dirWatcher.refCount++;
415+
// If the failed lookup location path is not one of the supported extensions,
416+
// store it in the custom path
417+
if (!isPathWithDefaultFailedLookupExtension(failedLookupLocationPath)) {
418+
const refCount = customFailedLookupPaths.get(failedLookupLocationPath) || 0;
419+
customFailedLookupPaths.set(failedLookupLocationPath, refCount + 1);
420+
}
421+
if (dirPath === rootPath) {
422+
setAtRoot = true;
441423
}
442424
else {
443-
directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 });
425+
setDirectoryWatcher(dir, dirPath);
444426
}
445427
}
446428
}
429+
430+
if (setAtRoot) {
431+
setDirectoryWatcher(rootDir, rootPath);
432+
}
447433
}
448434

449-
function stopWatchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
450-
if (resolution.failedLookupLocations) {
451-
stopWatchFailedLookupLocationOfResolutionFrom(resolution, 0);
435+
function setDirectoryWatcher(dir: string, dirPath: Path) {
436+
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
437+
if (dirWatcher) {
438+
dirWatcher.refCount++;
439+
}
440+
else {
441+
directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 });
452442
}
453443
}
454444

455-
function stopWatchFailedLookupLocationOfResolutionFrom({ failedLookupLocations }: ResolutionWithFailedLookupLocations, startIndex: number) {
456-
for (let i = startIndex; i < failedLookupLocations.length; i++) {
457-
const failedLookupLocation = failedLookupLocations[i];
445+
function stopWatchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
446+
if (!resolution.failedLookupLocations || !resolution.failedLookupLocations.length) {
447+
return;
448+
}
449+
450+
resolution.refCount!--;
451+
if (resolution.refCount) {
452+
return;
453+
}
454+
455+
const { failedLookupLocations } = resolution;
456+
let removeAtRoot = false;
457+
for (const failedLookupLocation of failedLookupLocations) {
458458
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
459-
const refCount = customFailedLookupPaths.get(failedLookupLocationPath);
460-
if (refCount) {
461-
if (refCount === 1) {
462-
customFailedLookupPaths.delete(failedLookupLocationPath);
459+
const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
460+
if (!ignore) {
461+
const refCount = customFailedLookupPaths.get(failedLookupLocationPath);
462+
if (refCount) {
463+
if (refCount === 1) {
464+
customFailedLookupPaths.delete(failedLookupLocationPath);
465+
}
466+
else {
467+
Debug.assert(refCount > 1);
468+
customFailedLookupPaths.set(failedLookupLocationPath, refCount - 1);
469+
}
470+
}
471+
472+
if (dirPath === rootPath) {
473+
removeAtRoot = true;
463474
}
464475
else {
465-
Debug.assert(refCount > 1);
466-
customFailedLookupPaths.set(failedLookupLocationPath, refCount - 1);
476+
removeDirectoryWatcher(dirPath);
467477
}
468478
}
469-
const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
470-
if (!ignore) {
471-
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
472-
// Do not close the watcher yet since it might be needed by other failed lookup locations.
473-
dirWatcher.refCount--;
474-
}
475479
}
480+
if (removeAtRoot) {
481+
removeDirectoryWatcher(rootPath);
482+
}
483+
}
484+
485+
function removeDirectoryWatcher(dirPath: string) {
486+
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
487+
// Do not close the watcher yet since it might be needed by other failed lookup locations.
488+
dirWatcher.refCount--;
476489
}
477490

478491
function createDirectoryWatcher(directory: string, dirPath: Path) {

0 commit comments

Comments
 (0)