无法使用 Firefox 在本地测试 WebAssembly 页面 - 未定义 SharedArrayBuffer

Not possible to test WebAssembly page locally with Firefox - SharedArrayBuffer not defined

我正在使用基于 WebAssembly 的软件,该软件使用需要 SharedArrayBuffer 的多线程。它 运行 在 Chromium local/deployed 和部署的 Firefox 89 中都很好,但由于最佳性能是在 Firefox 下,我想在我的机器上测试和调整它,所以我 运行 python -m SimpleHTTPServer。在这种情况下,当我在 Firefox 中打开 127.0.0.1:8000 或 0.0.0.0:8000 时,SharedArrayBufferundefined。也许这是一个安全设置,但是当使用 localhost 时,我真的对 Firefox 对这种情况的解释不感兴趣——这应该只是 运行。我怎样才能让它发挥作用?我需要不同的 Web 服务器、不同的设置吗?

正如@CherryDT 在评论中指出的那样,本地服务器缺少 headers 问题。在网上搜索,a blog 介绍了使用 python Web 服务器在 Firefox 中开发 WebAssembly 的过程。而不是 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

测试应用程序

如您所料,这与安全限制有关。 SharedArrayBuffer 的使用发生了一些变化,这些变化已经在 Firefox 79 中实现,并且很快也会在 Chrome 中实现(从 Chrome 92 开始)。 (撰写本文的时间:2021 年 7 月 13 日。)

主要目的是限制SharedArrayBufferpostMessage中的使用。除非设置某些限制性 COOP/COEP headers 以防止 cross-origin 攻击,否则任何此类尝试都会引发错误:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

不幸的是,没有这些 headers,也就没有全局 SharedArrayBuffer 构造函数。显然,这一限制在未来可能会被取消。 objects 本身仍然有效(只有通过 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

进一步阅读: