-
Notifications
You must be signed in to change notification settings - Fork 4.7k
jsc: report exceptions thrown by deferred work tasks #30849
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| import { describe, expect, test } from "bun:test"; | ||
| import { bunEnv, bunExe } from "harness"; | ||
|
|
||
| describe.concurrent("FinalizationRegistry", () => { | ||
| test("throwing from cleanup callback routes to uncaughtException", async () => { | ||
| await using proc = Bun.spawn({ | ||
| cmd: [ | ||
| bunExe(), | ||
| "-e", | ||
| ` | ||
| let caught; | ||
| process.on("uncaughtException", e => { caught = e; }); | ||
| const fr = new FinalizationRegistry(() => { | ||
| throw new TypeError("from cleanup callback"); | ||
| }); | ||
| (function register() { fr.register({ a: 1 }, "held"); })(); | ||
| let ticks = 0; | ||
| function tick() { | ||
| Bun.gc(true); | ||
| if (caught) { | ||
| console.log("CAUGHT", caught.message); | ||
| return; | ||
| } | ||
| if (++ticks > 50) { | ||
| console.log("SKIPPED"); | ||
| return; | ||
| } | ||
| setImmediate(tick); | ||
| } | ||
| tick(); | ||
| `, | ||
| ], | ||
| env: bunEnv, | ||
| stdout: "pipe", | ||
| stderr: "pipe", | ||
| }); | ||
|
|
||
| const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); | ||
| expect(stderr).not.toContain("ASSERTION FAILED"); | ||
| expect(stderr).not.toContain("releaseAssertNoException"); | ||
|
Comment on lines
+39
to
+40
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 nit: Per root CLAUDE.md ("Writing Tests"), tests should never assert that stderr does not contain "panic"/"uncaught exception"/assertion strings — these checks never fail in CI. The Extended reasoning...WhatRoot
This PR adds four such assertions in
Grep across Why these assertions don't add signal
Step-by-step on a regressionSuppose this PR's C++ change is reverted and the test runs in CI:
The exit-code/signal assertions are doing all the work; the stderr checks are dead weight that violate the documented convention. FixDelete lines 39-40 and 72-73. The tests remain correct — |
||
| expect(exitCode).toBe(0); | ||
| // GC timing is non-deterministic; if the callback ran it must have been | ||
| // routed through uncaughtException rather than crashing the process. | ||
| if (!stdout.includes("SKIPPED")) { | ||
| expect(stdout).toContain("CAUGHT from cleanup callback"); | ||
| } | ||
|
Comment on lines
+38
to
+46
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assert
As per coding guidelines: "Assert the exit code last in tests - this gives a more useful error message on test failure." Also applies to: 71-77 🤖 Prompt for AI Agents |
||
| }); | ||
|
|
||
| test("throwing from cleanup callback without handler does not crash", async () => { | ||
| await using proc = Bun.spawn({ | ||
| cmd: [ | ||
| bunExe(), | ||
| "-e", | ||
| ` | ||
| const fr = new FinalizationRegistry(() => { ArrayBuffer(); }); | ||
| (function register() { fr.register({ a: 1 }, "held"); })(); | ||
| let ticks = 0; | ||
| function tick() { | ||
| Bun.gc(true); | ||
| if (++ticks > 50) return; | ||
| setImmediate(tick); | ||
| } | ||
| tick(); | ||
| `, | ||
| ], | ||
| env: bunEnv, | ||
| stdout: "pipe", | ||
| stderr: "pipe", | ||
| }); | ||
|
|
||
| const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]); | ||
| expect(stderr).not.toContain("ASSERTION FAILED"); | ||
| expect(stderr).not.toContain("releaseAssertNoException"); | ||
| // Process must exit normally (not abort via signal). | ||
| expect(exitCode).not.toBeNull(); | ||
| expect(proc.signalCode).toBeNull(); | ||
| }); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove negative checks for assertion/panic-style stderr strings.
These output-string negation checks are disallowed and brittle here; rely on behavior/assertions that must hold (signal/exit/expected stdout path) instead.
As per coding guidelines: "Never write tests that check for no 'panic' or 'uncaught exception' or similar in output - these will never fail in CI."
Also applies to: 72-73
🤖 Prompt for AI Agents