Возможно ли транслировать SharedArrayBuffer веб-работникам через API широковещательного канала?

#javascript #google-chrome #web-worker #broadcast-channel #sharedarraybuffer

#javascript #google-chrome #веб-работник #Широковещательный канал #sharedarraybuffer

Вопрос:

Broadcast Channel API кажется альтернативой postMessage или Channel Messaging API (он же MessageChannel).) Я успешно использовал оба в последних версиях Google Chrome для отправки буферов общего массива; однако у меня возникли проблемы с отправкой буфера общего массива с использованием API широковещательного канала.

Документ Mozilla наhttps://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel ссылается на спецификацию в https://html.spec.whatwg.org/multipage/web-messaging.html#broadcastchannel , в котором говорится:

Для каждого назначения в destinations…

  1. Пусть данные будут структурированы как сериализованные (serialized, targetRealm). Если это вызывает исключение, перехватите его, запустите событие с именем messageerror в пункте назначения, используя MessageEvent, с атрибутом origin, инициализированным сериализацией sourceOrigin , а затем прервите эти шаги.

StructuredDeserialize определяется в https://html.spec.whatwg.org/multipage/structured-data.html#structureddeserialize и, похоже, предполагает, что он охватывает SharedArrayBuffers:

  1. В противном случае, если сериализовано.[[Тип]] — «SharedArrayBuffer», тогда: Если соответствующий кластер агентов targetRealm не сериализован.[[AgentCluster]], а затем вызвать DOMException «DataCloneError» DOMException. В противном случае задайте значение новому объекту SharedArrayBuffer в targetRealm, значение внутреннего слота которого [[ArrayBufferData]] сериализуется.[[ArrayBufferData]] и чье [[ArrayBufferByteLength]] значение внутреннего слота сериализуется.[[ArrayBufferByteLength]].

Читая это, мне кажется, что это должно сработать, но я получаю сообщение event, в котором данные просто null . Если бы это было проблемой безопасности, я бы ожидал получить событие messageerror вместо события message.

Вот мой минимальный тестовый пример:

broadcast-test.html (должен обслуживаться с http-сервера — не будет работать через 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' })
}
  

Наблюдаемый вывод на консоль: (Chrome 84.0.4147.135 в Windows 10)

main получено {привет: «от работника»}

рабочий получил null

Неправильная реализация Google Chrome или я неправильно понимаю спецификацию?

Комментарии:

1. что происходит, когда вы регистрируете событие в консоли? (не event.data)

2. должно работать и на самом деле работает — это две разные вещи — тот факт, что что-то есть «в стандарте» — не означает, что это было реализовано (пока) …. о, и, кстати, это не работает и в firefox

3.@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, …} Слишком много пропущенных свойств для публикации в этом пространстве.

4. Очевидно, что ни один браузер не поддерживает это , а с грядущими ограничениями COOP / COEP заставить это работать будет еще сложнее…