#firefox #webassembly #httpserver #sharedarraybuffer
Вопрос:
Я использую программное обеспечение на основе веб-сборки, которое использует многопоточность, которая требует SharedArrayBuffer
. Он отлично работает как в локальном/развернутом Chromium, так и в развернутом Firefox 89, но поскольку лучшая производительность в Firefox, я хочу протестировать и настроить его на своей машине, поэтому я запускаю python -m SimpleHTTPServer
. В этой ситуации, когда я открываю 127.0.0.1:8000 или 0.0.0.0:8000 в Firefox, SharedArrayBuffer
не определено. Возможно, это параметр безопасности, но при использовании localhost меня действительно не интересует интерпретация ситуации Firefox-это должно просто выполняться. Как я могу заставить это работать? Нужен ли мне другой веб-сервер, другие настройки?
Комментарии:
1. Возможно, вам не хватает необходимых HTTP-заголовков: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
2. @CherryDT есть идеи, как настроить их с помощью simplehttpserver или с помощью nginx?
3. Я подумал о более простом способе, потому что это звучит так, как будто вы все равно не пропускаете объект
postMessage
— смотрите мой ответ
Ответ №1:
Как вы правильно догадались, это связано с ограничениями безопасности. Были внесены изменения в отношении использования SharedArrayBuffer
, которые уже были реализованы в Firefox 79 и вскоре появятся и в Chrome (начиная с Chrome 92). (Время написания этого: 13 июля 2021 года.)
Основная цель состоит в том, чтобы ограничить использование SharedArrayBuffer
s в postMessage
. Любая такая попытка приведет к ошибке, если не будут установлены определенные ограничительные заголовки COOP/COEP для предотвращения атак с перекрестным происхождением:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
К сожалению, без этих заголовков также не существует глобального SharedArrayBuffer
конструктора. По-видимому, это ограничение может быть снято в будущем. Сами объекты все еще работают (только их прохождение postMessage
приведет к броску), но вам нужен другой способ их создания. Вы можете использовать WebAssembly.Memory
вместо этого:
const memory = new WebAssembly.Memory({ initial: 10, maximum: 100, shared: true })
// memory.buffer is instanceof SharedMemoryBuffer
Теперь вы можете сделать еще один шаг вперед и восстановить конструктор из этого. Поэтому, используя следующий код в качестве «прокладки», ваш существующий код должен работать до тех пор, пока он не попытается передать буфер через postMessage
:
if (typeof SharedArrayBuffer === 'undefined') {
const dummyMemory = new WebAssembly.Memory({ initial: 0, maximum: 0, shared: true })
globalThis.SharedArrayBuffer = dummyMemory.buffer.constructor
}
// Now, `new SharedArrayBuffer(1024)` works again
Дальнейшее чтение:
Ответ №2:
Как указал @CherryDT в комментарии, проблема заключается в отсутствии заголовков для локального сервера. В интернете есть блог, в котором описан процесс разработки веб-сборки в Firefox с помощью веб-сервера python. Вместо python -m SimpleHTTPServer
этого нужно добавить файл ./wasm-server.py
с этим содержимым (для Python 2):
# Python 2
import SimpleHTTPServer
import SocketServer
class WasmHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def end_headers(self):
self.send_header("Cross-Origin-Opener-Policy", "same-origin")
self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self)
# Python 3.7.5 adds in the WebAssembly Media Type. Version 2.x doesn't
# have this so add it in.
WasmHandler.extensions_map['.wasm'] = 'application/wasm'
if __name__ == '__main__':
PORT = 8080
httpd = SocketServer.TCPServer(("", PORT), WasmHandler)
print("Listening on port {}. Press Ctrl C to stop.".format(PORT))
httpd.serve_forever()
затем можно протестировать приложение по адресу 127.0.0.1:8080