Files
bun.sh/test/regression/issue/22635/22635.test.ts
robobun 661deb8eaf Fix MessagePort communication after transfer to Worker (#22638)
## 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>
2025-09-17 03:33:14 -07:00

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);