Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
57cd105446 fix(sourcemap): remove incorrect tab character exemption in scalar path
Fixes #22003

The scalar fallback path in IndexOfNeedsEscapeForJavaScriptStringImpl had
`(char_ < 0x20 && char_ != 0x09)` which incorrectly exempted tab characters
(0x09) from escaping. This created an inconsistency with the SIMD path which
correctly detects tabs as needing escape (since tab < 0x20).

While tabs would typically be caught by the SIMD path in most cases, this
inconsistency could cause issues when tabs appear in the small remainder
portion after SIMD processing, leading to invalid JSON in sourcemaps.

The fix removes the `&& char_ != 0x09` exemption, ensuring tabs are always
properly detected as needing escape in both SIMD and scalar code paths.
2025-10-06 15:15:59 +00:00
2 changed files with 60 additions and 1 deletions

View File

@@ -482,7 +482,7 @@ static size_t IndexOfNeedsEscapeForJavaScriptStringImpl(const uint8_t* HWY_RESTR
// Scalar check for the remainder
for (; i < text_len; ++i) {
const uint8_t char_ = text[i];
if (char_ >= 127 || (char_ < 0x20 && char_ != 0x09) || char_ == '\\' || char_ == quote_char || (is_backtick && char_ == '$')) {
if (char_ >= 127 || char_ < 0x20 || char_ == '\\' || char_ == quote_char || (is_backtick && char_ == '$')) {
return i;
}
}

View File

@@ -0,0 +1,59 @@
import { describe, expect, test } from "bun:test";
import { bunEnv, bunExe, tempDir } from "harness";
// https://github.com/oven-sh/bun/issues/22003
describe("sourcemap escaping with tab characters - issue #22003", () => {
test("tabs in source should be properly escaped in sourcemap JSON", async () => {
using dir = tempDir("22003", {
"index.js": `module.exports = {\n\th32: require("./a"),\n\th64: require("./b")\n};`,
"a.js": "module.exports = 'a';",
"b.js": "module.exports = 'b';",
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--outfile=out.js", "--sourcemap"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
expect(exitCode).toBe(0);
expect(stderr).not.toContain("InvalidSourceMap");
const sourcemapContent = await Bun.file(`${dir}/out.js.map`).text();
// Must be valid JSON
let sourcemap;
expect(() => {
sourcemap = JSON.parse(sourcemapContent);
}).not.toThrow();
// sourcesContent should have the tab properly escaped
expect(sourcemap.sourcesContent).toBeDefined();
const indexSource = sourcemap.sourcesContent.find((s: string) => s.includes("h32") && s.includes("h64"));
expect(indexSource).toBeDefined();
// When parsed from JSON, \t becomes actual tab character
expect(indexSource).toContain("\th32");
expect(indexSource).toContain("\th64");
});
test("tabs with --compile should not cause InvalidSourceMap error", async () => {
using dir = tempDir("22003-compile", {
"index.js": `// Comment with tab:\there\nconsole.log("test");`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--compile", "--sourcemap", "--outfile=out.exe"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
expect(exitCode).toBe(0);
expect(stderr).not.toContain("InvalidSourceMap");
});
});