From 530b0e2e10995ebe4285c5333ba0c0a844eb4e3d Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Mon, 27 Sep 2021 16:46:49 -0700 Subject: [PATCH] Fix indexing error in guessDirectorySymlink (#46105) * Fix indexing error in guessDirectorySymlink * Add test --- src/compiler/utilities.ts | 11 +++++++---- src/testRunner/unittests/tsserver/symlinkCache.ts | 5 +++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 6a2e5323b1d..61a8c55a807 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -6381,9 +6381,12 @@ namespace ts { const aParts = getPathComponents(getNormalizedAbsolutePath(a, cwd)); const bParts = getPathComponents(getNormalizedAbsolutePath(b, cwd)); let isDirectory = false; - while (!isNodeModulesOrScopedPackageDirectory(aParts[aParts.length - 2], getCanonicalFileName) && + while ( + aParts.length >= 2 && bParts.length >= 2 && + !isNodeModulesOrScopedPackageDirectory(aParts[aParts.length - 2], getCanonicalFileName) && !isNodeModulesOrScopedPackageDirectory(bParts[bParts.length - 2], getCanonicalFileName) && - getCanonicalFileName(aParts[aParts.length - 1]) === getCanonicalFileName(bParts[bParts.length - 1])) { + getCanonicalFileName(aParts[aParts.length - 1]) === getCanonicalFileName(bParts[bParts.length - 1]) + ) { aParts.pop(); bParts.pop(); isDirectory = true; @@ -6393,8 +6396,8 @@ namespace ts { // KLUDGE: Don't assume one 'node_modules' links to another. More likely a single directory inside the node_modules is the symlink. // ALso, don't assume that an `@foo` directory is linked. More likely the contents of that are linked. - function isNodeModulesOrScopedPackageDirectory(s: string, getCanonicalFileName: GetCanonicalFileName): boolean { - return getCanonicalFileName(s) === "node_modules" || startsWith(s, "@"); + function isNodeModulesOrScopedPackageDirectory(s: string | undefined, getCanonicalFileName: GetCanonicalFileName): boolean { + return s !== undefined && (getCanonicalFileName(s) === "node_modules" || startsWith(s, "@")); } function stripLeadingDirectorySeparator(s: string): string | undefined { diff --git a/src/testRunner/unittests/tsserver/symlinkCache.ts b/src/testRunner/unittests/tsserver/symlinkCache.ts index 39160c5399f..7a80a0cc289 100644 --- a/src/testRunner/unittests/tsserver/symlinkCache.ts +++ b/src/testRunner/unittests/tsserver/symlinkCache.ts @@ -57,6 +57,11 @@ namespace ts.projectSystem { { real: "/packages/dep/", realPath: "/packages/dep/" as Path } ); }); + + it("works for paths close to the root", () => { + const cache = createSymlinkCache("/", createGetCanonicalFileName(/*useCaseSensitiveFileNames*/ false)); + cache.setSymlinkedDirectoryFromSymlinkedFile("/foo", "/one/two/foo"); // Used to crash, #44953 + }); }); function setup() {