3

The Broadcast Channel API seems like an alternative to postMessage or the Channel Messaging API (aka MessageChannel.) I've used both successfully in recent versions of Google Chrome to send Shared Array Buffers; however, I am having trouble sending a Shared Array Buffer using the Broadcast Channel API.

Mozilla's doc at https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel references the spec at https://html.spec.whatwg.org/multipage/web-messaging.html#broadcastchannel, which says:

For each destination in destinations...

  1. Let data be StructuredDeserialize(serialized, targetRealm). If this throws an exception, catch it, fire an event named messageerror at destination, using MessageEvent, with the origin attribute initialized to the serialization of sourceOrigin, and then abort these steps.

StructuredDeserialize is defined at https://html.spec.whatwg.org/multipage/structured-data.html#structureddeserialize and seems to suggest it covers SharedArrayBuffers:

  1. Otherwise, if serialized.[[Type]] is "SharedArrayBuffer", then: If targetRealm's corresponding agent cluster is not serialized.[[AgentCluster]], then then throw a "DataCloneError" DOMException. Otherwise, set value to a new SharedArrayBuffer object in targetRealm whose [[ArrayBufferData]] internal slot value is serialized.[[ArrayBufferData]] and whose [[ArrayBufferByteLength]] internal slot value is serialized.[[ArrayBufferByteLength]].

Reading this, it seems to me that this should work, but I'm getting a message event where the data is simply null. If this were a security issue, I would expect to get a messageerror event instead of a message event.

Here's my minimal test case:

broadcast-test.html (must be served from an http server - won't work via file://)

<!DOCTYPE html>
<html>
  <head><title></title></head>
  <body>
    <script src="broadcast-test.js"></script>
  </body>
</html>

broadcast-test.js

const isThisTheWorker = this.document === undefined
const broadcastChannel = new BroadcastChannel('foo')

if (!isThisTheWorker) {
  broadcastChannel.addEventListener('message', (event) => {
    console.log('main received', event.data)
    const sab = new SharedArrayBuffer(100)
    broadcastChannel.postMessage({ hello: 'from main', sab })
  })
  var myWorker = new Worker('broadcast-test.js')
}
else {
  broadcastChannel.addEventListener('message', (event) => {
    console.log('worker received', event.data)
  })
  broadcastChannel.postMessage({ hello: 'from worker' })
}

Observed console output: (Chrome 84.0.4147.135 on Windows 10)

main received {hello: "from worker"}

worker received null

Is Google Chrome's implementation incorrect, or am I misunderstanding the spec?

chriswa
  • 128
  • 2
  • 7
  • what happens when you console log the event? (not event.data) – altruios Aug 28 '20 at 04:37
  • *should work* and *actually works* are two different things - the fact that something is "in the standard" - doesn't mean it has been implemented (yet) .... oh, and it doesn't work in firefox either by the way – Jaromanda X Aug 28 '20 at 05:11
  • @altruios `main received MessageEvent {isTrusted: true, data: {…}, origin: "http://localhost:1234", lastEventId: "", source: null, …}` `broadcast-test.js:50 worker received MessageEvent {isTrusted: true, data: null, origin: "http://localhost:1234", lastEventId: "", source: null, …}` There are too many omitted properties to post in this space. – chriswa Aug 28 '20 at 05:31
  • 3
    [Apparently no browser support this](https://github.com/web-platform-tests/wpt/commit/dedb45f5f20e0ac884ac59634cceb8659cdcff7d), and with the [upcoming COOP/COEP restrictions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/Planned_changes) it will even be harder to make it work... – Kaiido Aug 28 '20 at 07:04

0 Answers0