From 729b8b8a52e4b8fb712da8b55230cd550906227f Mon Sep 17 00:00:00 2001 From: "Yuichiro Tachibana (Tsuchiya)" Date: Sat, 22 Nov 2025 22:26:56 +0900 Subject: [PATCH 1/2] fix(web-worker): transfer MessagePort objects to worker as event.ports MessagePort objects can be transferred to another process such as a worker and can be accessed via events.ports as written in https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/ports > The ports read-only property of the MessageEvent interface is an array of MessagePort objects containing all MessagePort objects sent with the message, in order. Refs: https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel, https://github.com/mdn/dom-examples/tree/9a8acd0da2417372655b22d5a0ced768e76deb1c/channel-messaging-basic --- packages/web-worker/src/utils.ts | 4 ++++ test/core/src/web-worker/worker.ts | 5 +++++ test/core/test/web-worker-node.test.ts | 12 ++++++++++++ 3 files changed, 21 insertions(+) diff --git a/packages/web-worker/src/utils.ts b/packages/web-worker/src/utils.ts index e3c1d976a970..0c1a3012a299 100644 --- a/packages/web-worker/src/utils.ts +++ b/packages/web-worker/src/utils.ts @@ -29,12 +29,14 @@ function createClonedMessageEvent( debug('clone worker message %o', data) const origin = typeof location === 'undefined' ? undefined : location.origin + const ports = transfer?.filter((t): t is MessagePort => t instanceof MessagePort) if (typeof structuredClone === 'function' && clone === 'native') { debug('create message event, using native structured clone') return new MessageEvent('message', { data: structuredClone(data, { transfer }), origin, + ports, }) } if (clone !== 'none') { @@ -50,12 +52,14 @@ function createClonedMessageEvent( return new MessageEvent('message', { data: ponyfillStructuredClone(data, { lossy: true } as any), origin, + ports, }) } debug('create message event without cloning an object') return new MessageEvent('message', { data, origin, + ports, }) } diff --git a/test/core/src/web-worker/worker.ts b/test/core/src/web-worker/worker.ts index 90d90793c3fc..de29dcddd1e2 100644 --- a/test/core/src/web-worker/worker.ts +++ b/test/core/src/web-worker/worker.ts @@ -1,3 +1,8 @@ self.onmessage = (e) => { self.postMessage(`${e.data} world`) + + const port = e.ports[0] + if (port) { + port.postMessage(`${e.data} world via port`) + } } diff --git a/test/core/test/web-worker-node.test.ts b/test/core/test/web-worker-node.test.ts index dd4cf1865b34..ff0b5d03318e 100644 --- a/test/core/test/web-worker-node.test.ts +++ b/test/core/test/web-worker-node.test.ts @@ -211,6 +211,18 @@ it('self injected into worker and its deps should be equal', async () => { expect(await testSelfWorker(new Worker(new URL('../src/web-worker/selfWorker.ts', import.meta.url)))).toBeTruthy() }) +it('transfer MessagePort objects to worker as event.ports', async () => { + expect.assertions(1) + + const worker = new MyWorker() + const channel = new MessageChannel() + expect(new Promise((resolve, reject) => { + channel.port1.onmessage = e => resolve(e.data as string) + channel.port1.onmessageerror = reject + })).resolves.toBe('hello world via port') + worker.postMessage('hello', [channel.port2]) +}) + it('throws syntax error if no arguments are provided', () => { const worker = new MyWorker() From 81bc9ee933f649413fbc4e6431cddb158ebef2f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Mon, 24 Nov 2025 09:28:11 +0200 Subject: [PATCH 2/2] test: await expectation --- test/core/test/web-worker-node.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/core/test/web-worker-node.test.ts b/test/core/test/web-worker-node.test.ts index ff0b5d03318e..1977446feca3 100644 --- a/test/core/test/web-worker-node.test.ts +++ b/test/core/test/web-worker-node.test.ts @@ -216,11 +216,12 @@ it('transfer MessagePort objects to worker as event.ports', async () => { const worker = new MyWorker() const channel = new MessageChannel() - expect(new Promise((resolve, reject) => { + const promise = new Promise((resolve, reject) => { channel.port1.onmessage = e => resolve(e.data as string) channel.port1.onmessageerror = reject - })).resolves.toBe('hello world via port') + }) worker.postMessage('hello', [channel.port2]) + await expect(promise).resolves.toBe('hello world via port') }) it('throws syntax error if no arguments are provided', () => {