50 lines
1.8 KiB
TypeScript
50 lines
1.8 KiB
TypeScript
// https://github.com/oven-sh/bun/issues/23139
|
|||
|
|
//
|
||
|
|
// Dynamically importing a file that fails to parse threw on the first
|
||
|
|
// `await import()`, but the *second* `await import()` of the same path
|
||
|
|
// hung forever instead of re-throwing — the rejected module-registry
|
||
|
|
// entry was never re-queried. Fixed somewhere in the WebKit
|
||
|
|
// module-loader rewrite window (oven-sh/bun#29393 → #30262); reproduces
|
||
|
|
// on 1.3.13, gone on main with WebKit 88b2f7a2 (i.e. before #30527).
|
||
|
|
// This test pins it.
|
||
|
|
|
||
|
|
import { expect, test } from "bun:test";
|
||
|
|
import { bunEnv, bunExe, tempDir } from "harness";
|
||
|
|
|
||
|
|
test("repeated dynamic import of a file that fails to parse re-throws instead of hanging", async () => {
|
||
|
|
using dir = tempDir("issue-23139", {
|
||
|
|
"bad.json": `{ "invalid": json }`,
|
||
|
|
"entry.ts": `
|
||
|
|
for (const attempt of [1, 2]) {
|
||
|
|
try {
|
||
|
|
await import("./bad.json");
|
||
|
|
console.log("attempt " + attempt + ": resolved (unexpected)");
|
||
|
|
} catch (e) {
|
||
|
|
console.log("attempt " + attempt + ": threw " + (e as Error).name);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
console.log("done");
|
||
|
|
`,
|
||
|
|
});
|
||
|
|
|
||
|
|
await using proc = Bun.spawn({
|
||
|
|
cmd: [bunExe(), "entry.ts"],
|
||
|
|
cwd: String(dir),
|
||
|
|
env: bunEnv,
|
||
|
|
stdout: "pipe",
|
||
|
|
stderr: "pipe",
|
||
|
|
// Before the fix the second import never settles, so bound the
|
||
|
|
// subprocess and assert on signalCode rather than letting the test
|
||
|
|
// itself time out.
|
||
|
|
timeout: 10_000,
|
||
|
|
});
|
||
|
|
|
||
|
|
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||
|
|
|
||
|
|
expect(stdout).toBe("attempt 1: threw SyntaxError\nattempt 2: threw SyntaxError\ndone\n");
|
||
|
|
if (exitCode !== 0) expect(stderr).toBe("");
|
||
|
|
// null ⇒ exited on its own; non-null ⇒ killed by the spawn timeout (hung).
|
||
|
|
expect(proc.signalCode).toBeNull();
|
||
|
|
expect(exitCode).toBe(0);
|
||
|
|
}, 30_000);
|