mirror of
https://github.com/oven-sh/bun
synced 2026-02-12 03:48:56 +00:00
fix(worker_threads): use MessagePort for parentPort instead of dispatching to self
Node.js worker_threads delivers messages only to parentPort, not to
self.onmessage. Libraries like fflate set both handlers expecting only
parentPort.on('message') to fire.
Previously, Bun dispatched messages to both self.onmessage AND
parentPort event listeners, causing handlers to run twice.
This fix creates a real MessagePort pair for Node workers:
- Parent keeps port1 (m_parentPort) for worker.postMessage()
- Worker gets port2 as parentPort via entangle()
- WorkerMessageForwarder forwards port1 messages to Worker object
This matches Node.js architecture where worker.postMessage() goes
through a MessagePort channel, not the global scope.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Claude-Generated-By: Claude Code (cli/claude-opus-4-5=100%)
Claude-Steers: 0
Claude-Permission-Prompts: 4
Claude-Escapes: 0
This commit is contained in:
@@ -32,6 +32,34 @@ test("support eval in worker", async () => {
|
||||
await worker.terminate();
|
||||
});
|
||||
|
||||
// In Node.js worker_threads, messages go to parentPort only, not self.onmessage.
|
||||
// Libraries like fflate set both handlers, expecting only parentPort to fire.
|
||||
test("worker_threads messages should not trigger self.onmessage", async () => {
|
||||
const workerCode = `
|
||||
const { parentPort } = require('worker_threads');
|
||||
let selfOnMessageCount = 0;
|
||||
let parentPortOnMessageCount = 0;
|
||||
|
||||
self.onmessage = () => { selfOnMessageCount++; };
|
||||
parentPort.on('message', () => {
|
||||
parentPortOnMessageCount++;
|
||||
parentPort.postMessage({ selfOnMessageCount, parentPortOnMessageCount });
|
||||
});
|
||||
`;
|
||||
const worker = new Worker(workerCode, { eval: true });
|
||||
const result = await new Promise<{ selfOnMessageCount: number; parentPortOnMessageCount: number }>(
|
||||
(resolve, reject) => {
|
||||
worker.on("message", resolve);
|
||||
worker.on("error", reject);
|
||||
worker.postMessage({ test: 1 });
|
||||
},
|
||||
);
|
||||
await worker.terminate();
|
||||
|
||||
expect(result.parentPortOnMessageCount).toBe(1);
|
||||
expect(result.selfOnMessageCount).toBe(0);
|
||||
});
|
||||
|
||||
test("all worker_threads module properties are present", () => {
|
||||
expect(wt).toHaveProperty("getEnvironmentData");
|
||||
expect(wt).toHaveProperty("isMainThread");
|
||||
|
||||
Reference in New Issue
Block a user