fix(rpc): reject pending calls when target disconnects

Closed
HE
3mo ago
+156-7

Issue for this PR

Closes #34981

Type of change

  • Bug fix

What does this PR do?

When a Worker emits error (uncaught exception) or messageerror, all pending RPC call() promises hung forever because no listener existed to reject them.

Changes:

  • Store { resolve, reject } in pending map instead of just resolve
  • Add error and messageerror event listeners on the target
  • Add closed flag — calls made after disconnect reject immediately instead of hanging again
  • Add try/catch around postMessage for DataCloneError

Verified with a real Bun Worker that throws at import time:

  • Worker uncaught throw fires error event → rejectAll() runs
  • Calls made after closed reject immediately with "RPC target disconnected"
  • terminate() does NOT fire events in Bun — that case is handled by caller-side timeouts

How did you verify your code works?

$ bun test test/rpc-hang.test.ts
  ✓ rejects pending calls when target disconnects (error event)
  ✓ rejects pending calls on messageerror
  ✓ rejects calls made after target already disconnected
  ✓ resolves normally when target responds
  ✓ rejects when a real Bun Worker throws an uncaught error
  5 pass, 0 fail

Also verified: terminate() in Bun fires no events (see test/worker-events.test.ts), so this fix covers uncaught throws which do fire error.

Typecheck: 29/29 packages pass.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR