I'm trying out a simple hello world WebAssembly example and I'm having trouble understanding an error I'm seeing in Chrome 59:
RangeError: WebAssembly.Compile is disallowed on the main thread, if the buffer size is larger than 4KB. Use WebAssembly.compile, or compile on a worker thread.
src/wasm/counter.wasm:13
10 | let wa;
11 | const make = source => {
12 | // buffer should already be set
> 13 | return wa = new Module(buffer);
14 | };
15 |
16 | const WebAssemblyModule = function(deps = {
I've followed the steps in this tutorial, and I can build everything without error. I'm using create-react-app
rewired with wasm-loader
.
If I'm using my local build of the counter module I get the error I mentioned in the beginning. If I try and use a pre-built version (for example the one in this project) it works fine.
When I build my module, I'm using the same command as specified in the tutorial. The project with the working module has the same command listed in its README:
emcc counter.c -O1 -o counter.wasm -s WASM=1 -s SIDE_MODULE=1
Any idea what might be causing the error?
Some browsers limit the size of modules that can be compiled synchronously because that blocks the main thread. As the error message says, they'd rather have you use WebAssembly.compile
which returns a promise
. I'd advise you to go further and use WebAssembly.instantiate
which will both compile and instantiate asynchronously and, in some cases, generate higher performance code. See its documentation, the signature is:
Promise<WebAssemblyInstantiatedSource>
instantiate(BufferSource bytes [, importObject])
bytes
is the same buffer you were passing to Module
above, and importObject
is the same thing you'd have passed to Instance
.
Another option is to make your .wasm
file smaller. That's pretty brittle because the main-thread size limit is arbitrary and you're not really in control of your generated code's size. You could try compiling with -O2
or -Os
, and you can run binaryen's optimizer to try to reduce size. You could also split your code into multiple smaller modules, compile each individually, and then dynamically link them together (share import / export, and use the same memory for all of them).
But again, that's not really something you should rely on, and you're still blocking the main thread.
Yet another option is to move all your code to a WebWorker. You can block them as much as you want, no need for Promise
s.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With