From f78a5cf73ad5867d863c280926c10da9554ce81c Mon Sep 17 00:00:00 2001 From: Murugappan Medme Date: Fri, 18 Sep 2026 14:20:48 +0530 Subject: [PATCH] fix(sourcemap): skip URL source roots when injecting sources content A URL sourceRoot cannot be realpath'd, so the relative sources were resolved against the cwd and flagged as escaping the package. Remote sources have no local file to inject; leave the map untouched. --- .../node/server/__tests__/sourcemap.spec.ts | 42 ++++++++++++++++++- packages/vite/src/node/server/sourcemap.ts | 10 +++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/server/__tests__/sourcemap.spec.ts b/packages/vite/src/node/server/__tests__/sourcemap.spec.ts index d71118e32790b2..ce93ef4b4ee8e9 100644 --- a/packages/vite/src/node/server/__tests__/sourcemap.spec.ts +++ b/packages/vite/src/node/server/__tests__/sourcemap.spec.ts @@ -1,6 +1,7 @@ -import { describe, expect, test } from 'vitest' +import { describe, expect, test, vi } from 'vitest' import { isWindows } from '../../../shared/utils' -import { getNodeModulesPackageRoot } from '../sourcemap' +import type { Logger } from '../../logger' +import { getNodeModulesPackageRoot, injectSourcesContent } from '../sourcemap' describe('getNodeModulesPackageRoot', () => { const cases = [ @@ -69,3 +70,40 @@ describe('getNodeModulesPackageRoot', () => { }) } }) + +describe('injectSourcesContent', () => { + const createLogger = () => ({ warnOnce: vi.fn() }) as unknown as Logger + + test('leaves maps with a remote sourceRoot alone', async () => { + const map: Parameters[0] = { + sources: ['index.ts'], + sourceRoot: 'https://raw.githubusercontent.com/fb55/domutils/abc123/src/', + } + const logger = createLogger() + + await injectSourcesContent( + map, + '/project/node_modules/domutils/lib/esm/index.js', + logger, + ) + + expect(logger.warnOnce).not.toHaveBeenCalled() + expect(map.sourcesContent).toBeUndefined() + }) + + test('warns for sources that resolve outside the package', async () => { + const map: Parameters[0] = { + sources: ['/outside/project/index.ts'], + } + const logger = createLogger() + + await injectSourcesContent( + map, + '/project/node_modules/foo/dist/index.js', + logger, + ) + + expect(logger.warnOnce).toHaveBeenCalledOnce() + expect(map.sourcesContent).toEqual([null]) + }) +}) diff --git a/packages/vite/src/node/server/sourcemap.ts b/packages/vite/src/node/server/sourcemap.ts index 41943dab731a3e..2417a3236248bd 100644 --- a/packages/vite/src/node/server/sourcemap.ts +++ b/packages/vite/src/node/server/sourcemap.ts @@ -9,6 +9,7 @@ import type { Logger } from '../logger' import { blankReplacer, createDebugger, + isExternalUrl, isParentDirectory, normalizePath, } from '../utils' @@ -71,6 +72,15 @@ export async function injectSourcesContent( file: string, logger: Logger, ): Promise { + // A `sourceRoot` can be a URL (e.g. raw.githubusercontent.com) for packages + // that want devtools to fetch the original sources from a remote host. There + // is nothing local to read, so leave the map untouched instead of resolving + // the relative `sources` against the cwd and warning that they escape the + // package. + if (map.sourceRoot && isExternalUrl(map.sourceRoot)) { + return + } + let sourceRootPromise: Promise const packageRoot = getNodeModulesPackageRoot(file)