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.
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).
The MDN example says to do the following:
var importObject = {
imports: { imported_func: arg => console.log(arg) }
};
then
WebAssembly.instantiateStreaming(fetch('simple.wasm'), importObject)
.then(obj => obj.instance.exports.exported_func());
According to MDN the importObject is to unwrap the nested argument. Weird, but OK.
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)
});
The error I get back is:
there was some error; TypeError: "Response has unsupported MIME type"
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.
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?
EDIT:
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)
});
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.
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 => /* ... */)
Do this:
const response = await fetch("add.wasm");
const buffer = await response.arrayBuffer();
const obj = await WebAssembly.instantiate(buffer);
obj.instance.exports.exported_func();
Or the equivalent using then()
if you cannot use async/await
.
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.