Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebAssembly InstantiateStreaming Wrong MIME type

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.

like image 547
Peter Weyand Avatar asked Sep 08 '18 22:09

Peter Weyand


2 Answers

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.

like image 155
Lucio Paiva Avatar answered Oct 19 '22 17:10

Lucio Paiva


there was some error; TypeError: "Response has unsupported MIME type" The Web server you are running does not understands/serves a MIME type application/wasm.

You can use a rust based http server, it knows about wasm MIME type.

Installation

Simply use curl

curl -SsL https://cdn.rawgit.com/thecoshman/http/master/install.sh | sh

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

cd ${YOUR_APPS_PATH}

http
like image 2
iankit3 Avatar answered Oct 19 '22 18:10

iankit3