mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 02:48:50 +00:00
## Summary Fixes #22635 - MessagePort communication fails after being transferred to a Worker thread. Fixes https://github.com/oven-sh/bun/issues/22636 The issue was that `MessagePort::addEventListener()` only called `start()` for attribute listeners (like `onmessage = ...`) but not for regular event listeners added via `addEventListener()` or the Node.js EventEmitter wrapper (`.on('message', ...)`). ## Changes - Modified `MessagePort::addEventListener()` to call `start()` for all message event listeners, not just attribute listeners - Added regression test for issue #22635 ## Test Plan - [x] Regression test added and passing - [x] Original reproduction case from issue #22635 now works correctly - [x] Existing MessagePort tests still pass 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
63 lines
1.6 KiB
TypeScript
63 lines
1.6 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { MessageChannel, Worker } from "worker_threads";
|
|
|
|
test("issue #22635 - MessagePort communication fails after transfer to worker", async () => {
|
|
// Create a MessageChannel
|
|
const { port1, port2 } = new MessageChannel();
|
|
|
|
// Create a simple worker that receives a port
|
|
const workerCode = `
|
|
const { parentPort } = require('worker_threads');
|
|
|
|
parentPort.on('message', (msg) => {
|
|
if (msg.ports && msg.ports[0]) {
|
|
const port = msg.ports[0];
|
|
|
|
// Listen for messages on the transferred port
|
|
port.on('message', (data) => {
|
|
// Reply back through the same port
|
|
port.postMessage({ reply: 'Got: ' + data.text });
|
|
});
|
|
|
|
// Notify that we're ready
|
|
parentPort.postMessage({ ready: true });
|
|
}
|
|
});
|
|
`;
|
|
|
|
// Create worker with the code
|
|
const worker = new Worker(workerCode, { eval: true });
|
|
|
|
// Wait for worker to be ready
|
|
const readyPromise = new Promise<void>(resolve => {
|
|
worker.once("message", msg => {
|
|
if (msg.ready) {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Transfer port2 to the worker
|
|
worker.postMessage({ ports: [port2] }, [port2]);
|
|
|
|
// Wait for worker to be ready
|
|
await readyPromise;
|
|
|
|
// Test communication through the transferred port
|
|
const responsePromise = new Promise<void>(resolve => {
|
|
port1.on("message", msg => {
|
|
expect(msg.reply).toBe("Got: Hello from main");
|
|
resolve();
|
|
});
|
|
});
|
|
|
|
// Send message through port1
|
|
port1.postMessage({ text: "Hello from main" });
|
|
|
|
// Wait for response
|
|
await responsePromise;
|
|
|
|
// Clean up
|
|
worker.terminate();
|
|
}, 10000);
|