WebAssembly InstantiateStreaming 错误的 MIME 类型

2022-01-20 00:00:00 streaming fetch rust javascript webassembly

我正在尝试获取本教程(此处:https://www.hellorust.com/demos/add/index.html) 工作,似乎无论我做什么,我都无法让 WebAssembly MDN 保留功能正常工作.

I am attempting to get this tutorial (here: https://www.hellorust.com/demos/add/index.html) to work, and it seems that whatever I do, I cannot get the WebAssembly MDN reserved function to properly work.

所以,我按照上面链接上的说明获得了一个 add.wasm 文件.据我所知,这应该相当简单并且应该可以工作.经过一番挖掘,我发现最新的 WebAssembly 模块是用于实例化流 - 可以在此处找到其文档:(https://developer.mozilla.org/en-US/docs/WebAssembly/Using_the_JavaScript_API).

So, I followed the instructions on the link above and got an add.wasm file. As far as I can tell this should be fairly simple and should work. After a little digging I found that the newest WebAssembly module is to instantiate streaming - the documentation for which can be found here: (https://developer.mozilla.org/en-US/docs/WebAssembly/Using_the_JavaScript_API).

MDN 示例说要执行以下操作:

The MDN example says to do the following:

var importObject = {
  imports: { imported_func: arg => console.log(arg) }
};

然后

WebAssembly.instantiateStreaming(fetch('simple.wasm'), importObject)
.then(obj => obj.instance.exports.exported_func());

根据 MDN,importObject 用于解开嵌套参数.很奇怪,但还可以.

According to MDN the importObject is to unwrap the nested argument. Weird, but OK.

为了使这尽可能简单,我将 add.wasm 文件和将导入它的 js 文件放在同一目录中,然后按照 (注意:我使用的是 Vue.js,但对于任何熟悉 SPA 类库的人来说,这应该是相似的):

To make this as simple as possible I put the add.wasm file and the js file that would import it in the same directory and then did then following (NOTE: I am using Vue.js, but for anyone familiar with SPA like libraries this should be similar):

window.WebAssembly.instantiateStreaming(fetch('./add.wasm', {
  headers: {
    "Content-Type": "application/wasm",
  },
}), importObject)
.then(obj => {
  console.log('inside return obj from WebAssembly initiateStreaming')
  obj => obj.instance.exports.exported_func() 
})
.catch(error=>{
  console.log('there was some error; ', error)
});

我得到的错误是:

there was some error;  TypeError: "Response has unsupported MIME type"

我尝试不将标头添加到获取请求中,使用 fetch(add.wasm),删除 window.,删除 importObject 完全简单地将 obj 记录到控制台.似乎没有任何效果.

I've tried not adding the header to the fetch request, using fetch(add.wasm), dropping the window., dropping the importObject entirely and simple logging obj to console. Nothing appears to work.

如果 application/wasm 字段未得到广泛支持,我可能必须以某种方式将其添加到 webpack,但我不确定,我还没有在网上看到任何示例.

It may be that I have to add the application/wasm field to webpack somehow if it is not widely supported, but I'm not sure and I haven't seen any examples online.

有谁知道如何让它工作?

Does anyone know how to get this to work?

有人建议,由于这是一个获取请求,它必须从后端服务器发出请求.这对我来说很有意义,所以我做了以下事情:

Someone suggested that since this was a fetch request it had to be making the request from a backend server. This made sense to me, so I did the following:

    WebAssembly.instantiateStreaming(fetch('http://localhost:8000/files/add.wasm'), importObject)
    .then(obj => {
      console.log('inside return obj from WebAssembly initiateStreaming')
      obj => obj.instance.exports.exported_func()
    })
    .catch(error=>{
      console.log('there was some error; ', error)
    });

其中 http://localhost:8000/files/{someFile} 是为我的文件提供服务的后端路由(我确保将 add.wasm 放入当然).不幸的是,我得到了同样的错误(即 unrecognized MIME type),我不知道为什么.

Where http://localhost:8000/files/{someFile} is a backend route that serves my files (which I made sure to put add.wasm in of course). Unfortunately, I get the same error (i.e. unrecognized MIME type) and I'm not sure why.

推荐答案

考虑到你无法更改服务器以正确返回 .wasm 文件请求的 application/wasm无论出于何种原因,您都可以通过更改实例化 WebAssembly 模块的方式来解决此问题.而不是这样做:

Considering you can't change the server to properly return application/wasm for .wasm file requests for any reason, you can work around the issue by changing the way you instantiate the WebAssembly module. Instead of doing this:

WebAssembly.instantiateStreaming(fetch("./add.wasm")).then(obj => /* ... */)

这样做:

const response = await fetch("add.wasm");
const buffer = await response.arrayBuffer();
const obj = await WebAssembly.instantiate(buffer);
obj.instance.exports.exported_func();

如果您不能使用 async/await,则使用 then() 的等效项.

Or the equivalent using then() if you cannot use async/await.

实际上,我的解决方法是避免调用 instantiateStreaming(),它必须在继续之前检查服务器返回的 MIME 类型(根据 本规范).相反,我调用 instantiate() 并传递一个 ArrayBuffer 并完全避免检查.

In practice, what my workaround does is to avoid calling instantiateStreaming(), which must check the MIME type returned by the server before proceeding (according to this specification). Instead, I call instantiate() passing an ArrayBuffer and avoid the check altogether.

相关文章