From a29672814bd99d56e886c0930af3c14bf7623542 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Wed, 6 Aug 2025 13:37:03 -0600 Subject: [PATCH 1/5] fix 11429 --- .../src/getTSConfigRootDirFromStack.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/typescript-eslint/src/getTSConfigRootDirFromStack.ts b/packages/typescript-eslint/src/getTSConfigRootDirFromStack.ts index b4ac708ea3b..b6576757f5e 100644 --- a/packages/typescript-eslint/src/getTSConfigRootDirFromStack.ts +++ b/packages/typescript-eslint/src/getTSConfigRootDirFromStack.ts @@ -1,4 +1,5 @@ import path from 'node:path'; +import { fileURLToPath } from 'node:url'; /** * Infers the `tsconfigRootDir` from the current call stack, using the V8 API. @@ -26,11 +27,18 @@ export function getTSConfigRootDirFromStack(): string | undefined { } for (const callSite of getStack()) { - const stackFrameFilePath = callSite.getFileName(); - if (!stackFrameFilePath) { + const stackFrameFilePathOrUrl = callSite.getFileName(); + if (!stackFrameFilePathOrUrl) { continue; } + // ESM seem to return a file URL, so we'll convert it to a file path. + // This isn't terribly documented in the v8 API docs, but it seems to be the case. + // See https://github.com/typescript-eslint/typescript-eslint/issues/11429 + const stackFrameFilePath = stackFrameFilePathOrUrl.startsWith('file://') + ? fileURLToPath(stackFrameFilePathOrUrl) + : stackFrameFilePathOrUrl; + const parsedPath = path.parse(stackFrameFilePath); if (/^eslint\.config\.(c|m)?(j|t)s$/.test(parsedPath.base)) { return parsedPath.dir; From 8537da44c55520f853411cd75c9f0f394f614653 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Wed, 6 Aug 2025 13:54:58 -0600 Subject: [PATCH 2/5] terribly --- .cspell.json | 1 + packages/typescript-eslint/src/getTSConfigRootDirFromStack.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.cspell.json b/.cspell.json index 265533fa045..ffe51471848 100644 --- a/.cspell.json +++ b/.cspell.json @@ -46,6 +46,7 @@ "\\(#.+?\\)" ], "words": [ + "AFAICT", "Airbnb", "Airbnb's", "allowdefaultproject", diff --git a/packages/typescript-eslint/src/getTSConfigRootDirFromStack.ts b/packages/typescript-eslint/src/getTSConfigRootDirFromStack.ts index b6576757f5e..1d4c558eabe 100644 --- a/packages/typescript-eslint/src/getTSConfigRootDirFromStack.ts +++ b/packages/typescript-eslint/src/getTSConfigRootDirFromStack.ts @@ -33,7 +33,7 @@ export function getTSConfigRootDirFromStack(): string | undefined { } // ESM seem to return a file URL, so we'll convert it to a file path. - // This isn't terribly documented in the v8 API docs, but it seems to be the case. + // AFAICT this isn't documented in the v8 API docs, but it seems to be the case. // See https://github.com/typescript-eslint/typescript-eslint/issues/11429 const stackFrameFilePath = stackFrameFilePathOrUrl.startsWith('file://') ? fileURLToPath(stackFrameFilePathOrUrl) From 79001eae8b2eee23f63ea2fcbd25f331ade110e5 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Thu, 7 Aug 2025 13:39:00 -0600 Subject: [PATCH 3/5] test --- .../tests/getTsconfigRootDirFromStack.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts b/packages/typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts index a9c169785c6..ad27e9a3e01 100644 --- a/packages/typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts +++ b/packages/typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts @@ -8,6 +8,25 @@ describe(getTSConfigRootDirFromStack, () => { expect(normalFolder.get()).toBe(normalFolder.dirname()); }); + it('does stack analysis right for a file that gives a file:// URL as its name', () => { + vi.spyOn(Error, 'captureStackTrace').mockImplementationOnce( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (target: any, _constructorOpt) => { + target.stack = [ + { + getFileName() { + return 'file:///a/b/eslint.config.mts'; + }, + }, + ]; + }, + ); + + const inferredTsconfigRootDir = getTSConfigRootDirFromStack(); + + expect(inferredTsconfigRootDir).toBe('/a/b'); + }); + it('does stack analysis right for folder that has a space', () => { expect(folderThatHasASpace.get()).toBe(folderThatHasASpace.dirname()); }); From f181d266518ca5fda2cb74dcfe479fa4287daf31 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Thu, 7 Aug 2025 17:09:23 -0600 Subject: [PATCH 4/5] windows --- .../tests/getTsconfigRootDirFromStack.test.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts b/packages/typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts index ad27e9a3e01..df16b307a47 100644 --- a/packages/typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts +++ b/packages/typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts @@ -3,6 +3,8 @@ import * as normalFolder from './path-test-fixtures/tsconfigRootDirInference-nor import * as notEslintConfig from './path-test-fixtures/tsconfigRootDirInference-not-eslint-config/not-an-eslint.config.cjs'; import * as folderThatHasASpace from './path-test-fixtures/tsconfigRootDirInference-space/folder that has a space/eslint.config.cjs'; +const isWindows = process.platform === 'win32'; + describe(getTSConfigRootDirFromStack, () => { it('does stack analysis right for normal folder', () => { expect(normalFolder.get()).toBe(normalFolder.dirname()); @@ -15,7 +17,9 @@ describe(getTSConfigRootDirFromStack, () => { target.stack = [ { getFileName() { - return 'file:///a/b/eslint.config.mts'; + return !isWindows + ? 'file:///a/b/eslint.config.mts' + : 'file:F:\\a\\b\\eslint.config.mts'; }, }, ]; @@ -24,7 +28,7 @@ describe(getTSConfigRootDirFromStack, () => { const inferredTsconfigRootDir = getTSConfigRootDirFromStack(); - expect(inferredTsconfigRootDir).toBe('/a/b'); + expect(inferredTsconfigRootDir).toBe(!isWindows ? '/a/b' : 'F:\\a\\b'); }); it('does stack analysis right for folder that has a space', () => { From 740b45d5a4779049bdb6dd7d27d855722abc4282 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Thu, 7 Aug 2025 17:34:40 -0600 Subject: [PATCH 5/5] windows hard --- .../typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts b/packages/typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts index df16b307a47..8f37d5833df 100644 --- a/packages/typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts +++ b/packages/typescript-eslint/tests/getTsconfigRootDirFromStack.test.ts @@ -19,7 +19,7 @@ describe(getTSConfigRootDirFromStack, () => { getFileName() { return !isWindows ? 'file:///a/b/eslint.config.mts' - : 'file:F:\\a\\b\\eslint.config.mts'; + : 'file:///F:/a/b/eslint.config.mts'; }, }, ];