Files
bun-src/test/regression/issue/03830.test.ts
T
2026-08-27 21:09:14 +00:00

76 lines
3.0 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import { realpathSync } from "fs";
import { bunEnv, bunExe, tempDir } from "harness";
import { join } from "path";
describe("issue/03830", () => {
// First test stays sequential: `toMatchSnapshot()` is not supported in
// concurrent tests (Bun's test runner rejects it). The second test has no
// snapshot matcher, so it runs `.concurrent` per test/CLAUDE.md.
it("macros should not lead to seg faults under any given input", async () => {
// this test code follows the same structure as and
// is based on the code for testing issue 4893
using dir = tempDir("issue-03830", {
"macro.ts": "export function fn(str) { return str; }",
"index.ts": "import { fn } from './macro' assert { type: 'macro' };\nfn(`©${Number(0)}`);",
});
const testDir = realpathSync(dir);
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "--minify", join(testDir, "index.ts")],
env: bunEnv,
stderr: "pipe",
stdout: "pipe",
});
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
expect(stderr.trim().replaceAll(testDir, "[dir]").replaceAll("\\", "/")).toMatchSnapshot();
expect(exitCode).toBe(1);
});
it.concurrent.each([
// [name, where transformSync+import() runs in macro.ts]
["inside the exported macro fn", "fn-body"],
// Macro::init runs the module's top-level via wait_for_promise BEFORE the
// caller's MacroModeGuard exists — Macro::init holds its own guard so
// depth > 0 here too.
["at macro-module top level (during Macro::init)", "top-level"],
])("nested Bun.Transpiler %s then import() does not free the printer", async (_, where) => {
// Bun.Transpiler#transformSync drops a nested MacroContext via
// TranspilerStateGuard, which calls __bun_macro_context_deinit. On a
// bundler-worker thread the macro was the first SOURCE_CODE_PRINTER
// allocator; freeing it here would panic the subsequent module fetch.
const macroTs =
where === "top-level"
? `new Bun.Transpiler().transformSync("const a = 1;");
const mod = await import("./helper.ts");
export function nested() { return mod.value; }`
: `export async function nested() {
new Bun.Transpiler().transformSync("const a = 1;");
const mod = await import("./helper.ts");
return mod.value;
}`;
using dir = tempDir("issue-03830-nested", {
"helper.ts": "export const value = 42;",
"macro.ts": macroTs,
"index.ts": "import { nested } from './macro.ts' with { type: 'macro' };\nconsole.log(nested());",
});
const testDir = realpathSync(dir);
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "--target=bun", join(testDir, "index.ts")],
env: bunEnv,
stderr: "pipe",
stdout: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
expect(stderr.trim()).toBe("");
expect(stdout).toContain("console.log(42)");
expect(exitCode).toBe(0);
});
});