diff --git a/src/bundler/linker_context/postProcessCSSChunk.zig b/src/bundler/linker_context/postProcessCSSChunk.zig index e3f680676c..7941bebac5 100644 --- a/src/bundler/linker_context/postProcessCSSChunk.zig +++ b/src/bundler/linker_context/postProcessCSSChunk.zig @@ -105,7 +105,7 @@ pub fn postProcessCSSChunk(ctx: GenerateChunkCtx, worker: *ThreadPool.Worker, ch chunk.isolated_hash, worker, compile_results_for_source_map, - c.resolver.opts.output_dir, + c.resolver.opts.root_dir, can_have_shifts, ); } diff --git a/src/bundler/linker_context/postProcessJSChunk.zig b/src/bundler/linker_context/postProcessJSChunk.zig index bfe0035a44..14541ed6b0 100644 --- a/src/bundler/linker_context/postProcessJSChunk.zig +++ b/src/bundler/linker_context/postProcessJSChunk.zig @@ -429,7 +429,7 @@ pub fn postProcessJSChunk(ctx: GenerateChunkCtx, worker: *ThreadPool.Worker, chu chunk.isolated_hash, worker, compile_results_for_source_map, - c.resolver.opts.output_dir, + c.resolver.opts.root_dir, can_have_shifts, ); } diff --git a/test/regression/issue/3332.test.ts b/test/regression/issue/3332.test.ts new file mode 100644 index 0000000000..f358111c94 --- /dev/null +++ b/test/regression/issue/3332.test.ts @@ -0,0 +1,68 @@ +import { describe, expect, test } from "bun:test"; +import { tempDir } from "harness"; +import path from "path"; + +describe("issue #3332 - sourcemap sources should be relative to root", () => { + test("JS sourcemap sources are relative to root, not output directory", async () => { + using dir = tempDir("issue-3332-js", { + "src/index.ts": `import { helper } from './nested/helper'; +console.log(helper());`, + "src/nested/helper.ts": `export function helper() { + return 'hello'; +}`, + }); + + const result = await Bun.build({ + entrypoints: [path.join(String(dir), "src/index.ts")], + outdir: path.join(String(dir), "dist"), + root: String(dir), + sourcemap: "external", + }); + + expect(result.success).toBe(true); + + // Find the sourcemap output + const sourcemapOutput = result.outputs.find(o => o.kind === "sourcemap"); + expect(sourcemapOutput).toBeDefined(); + + // Parse the sourcemap + const mapContent = await sourcemapOutput!.text(); + const map = JSON.parse(mapContent); + + // Sources should be relative to root (the project directory), not output directory + // Expected: ["src/nested/helper.ts", "src/index.ts"] (or similar) + // Bug behavior: ["../src/nested/helper.ts", "../src/index.ts"] (relative to dist/src/) + for (const source of map.sources) { + expect(source).not.toMatch(/^\.\.\//); + expect(source).toMatch(/^src\//); + } + + expect(map.sources).toContain("src/index.ts"); + expect(map.sources).toContain("src/nested/helper.ts"); + }); + + test("sourcemap sources without explicit root use cwd", async () => { + using dir = tempDir("issue-3332-no-root", { + "index.ts": `console.log('hello');`, + }); + + const result = await Bun.build({ + entrypoints: [path.join(String(dir), "index.ts")], + outdir: path.join(String(dir), "dist"), + sourcemap: "external", + }); + + expect(result.success).toBe(true); + + const sourcemapOutput = result.outputs.find(o => o.kind === "sourcemap"); + expect(sourcemapOutput).toBeDefined(); + + const mapContent = await sourcemapOutput!.text(); + const map = JSON.parse(mapContent); + + // Sources should contain just the filename or a relative path, not "../" + for (const source of map.sources) { + expect(source).not.toMatch(/^\.\.\//); + } + }); +});