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.
A snippet of code for a workaround has been published on the WebAssembly Git here. Unfortunately, this is a workaround, and this defeats the purpose of
instantiateStreaming()
which is told here to be "a lot more efficient", since the workaround needs an ArrayBuffer thatinstantiateStreaming()
helps to avoid.You can use a rust based http server, it knows about wasm MIME type.
Installation
Simply use curl
and execute the downloaded script or you can explorer other ways to do the same at https://crates.io/crates/https.
Running
Please use the downloaded server to server your Web Application(index.html). e.g
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:Do this:
Or the equivalent using
then()
if you cannot useasync/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 callinstantiate()
passing anArrayBuffer
and avoid the check altogether.