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..1977446feca3 100644 --- a/test/core/test/web-worker-node.test.ts +++ b/test/core/test/web-worker-node.test.ts @@ -211,6 +211,19 @@ 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() + const promise = new Promise((resolve, reject) => { + channel.port1.onmessage = e => resolve(e.data as string) + channel.port1.onmessageerror = reject + }) + worker.postMessage('hello', [channel.port2]) + await expect(promise).resolves.toBe('hello world via port') +}) + it('throws syntax error if no arguments are provided', () => { const worker = new MyWorker()