无法使用 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 时,SharedArrayBuffer
是 undefined。也许这是一个安全设置,但是当使用 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 日。)
主要目的是限制SharedArrayBuffer
在postMessage
中的使用。除非设置某些限制性 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
进一步阅读:
我正在使用基于 WebAssembly 的软件,该软件使用需要 SharedArrayBuffer
的多线程。它 运行 在 Chromium local/deployed 和部署的 Firefox 89 中都很好,但由于最佳性能是在 Firefox 下,我想在我的机器上测试和调整它,所以我 运行 python -m SimpleHTTPServer
。在这种情况下,当我在 Firefox 中打开 127.0.0.1:8000 或 0.0.0.0:8000 时,SharedArrayBuffer
是 undefined。也许这是一个安全设置,但是当使用 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 日。)
主要目的是限制SharedArrayBuffer
在postMessage
中的使用。除非设置某些限制性 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
进一步阅读: