diff --git a/.changeset/resolve-source-root-directory.md b/.changeset/resolve-source-root-directory.md new file mode 100644 index 0000000..79094f7 --- /dev/null +++ b/.changeset/resolve-source-root-directory.md @@ -0,0 +1,5 @@ +--- +"rollup-plugin-sourcemaps2": patch +--- + +Resolve sources inside the map's `sourceRoot` directory on filesystem paths. The trailing slash of the root was stripped, so `sourceRoot: "src"` with `sources: ["index.ts"]` resolved to `index.ts` next to the map instead of `src/index.ts`, and the map lost its `sourcesContent`. diff --git a/src/__tests__/index.test.ts b/src/__tests__/index.test.ts index b94c205..cecf0d6 100644 --- a/src/__tests__/index.test.ts +++ b/src/__tests__/index.test.ts @@ -8,7 +8,7 @@ import { type PluginContext, rollup } from 'rollup'; import { describe, expect, it, test, vi } from 'vitest'; import sourcemaps, { type SourcemapsPluginOptions } from '..'; -import { resolveSourceMap } from '../source-map-resolve'; +import { resolveSourceMap, resolveSources } from '../source-map-resolve'; const inputPath = path.join(__dirname, '../index.ts'); const inputText = fs.readFileSync(inputPath, 'utf8'); @@ -332,6 +332,32 @@ it('finds last source map file definition', async () => { expect(map?.url).toEqual('/dev/null/index.js.map'); }); +it('resolves sources inside the sourceRoot directory', async () => { + const mapUrl = path.join(__dirname, 'dist', 'index.js.map'); + const requested: string[] = []; + + const { sourcesResolved, sourcesContent } = await resolveSources( + { + version: 3, + file: 'index.js', + sourceRoot: 'src', + sources: ['index.ts'], + names: [], + mappings: '', + }, + mapUrl, + async source => { + requested.push(source); + return 'source text'; + }, + ); + + const expected = path.join(__dirname, 'dist', 'src', 'index.ts'); + expect(sourcesResolved).toStrictEqual([expected]); + expect(requested).toStrictEqual([expected]); + expect(sourcesContent).toStrictEqual(['source text']); +}); + it('skips directories even when the filesystem lets them be read', async () => { const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'sourcemaps2-')); // Mimic macOS devfs, where read() on the /dev directory succeeds and returns raw bytes. diff --git a/src/source-map-resolve.ts b/src/source-map-resolve.ts index 329f71a..72c4753 100644 --- a/src/source-map-resolve.ts +++ b/src/source-map-resolve.ts @@ -40,7 +40,9 @@ function resolveUrl(...args: string[]): string { continue; } - resolved = path.resolve(path.dirname(resolved), nextUrl); + // A trailing slash marks a directory (sourceRoot), so the next segment resolves inside it + const base = resolved.endsWith('/') ? resolved : path.dirname(resolved); + resolved = path.resolve(base, nextUrl) + (nextUrl.endsWith('/') ? '/' : ''); } return resolved;