Skip to content

Instantly share code, notes, and snippets.

@bvisness
Last active May 22, 2024 05:52
Show Gist options
  • Save bvisness/c3fc13daa749f608506456c55662deb7 to your computer and use it in GitHub Desktop.
Save bvisness/c3fc13daa749f608506456c55662deb7 to your computer and use it in GitHub Desktop.
A quick guide to running wasm files outside the browser

General info

The following code should work to test WebAssembly in various JS runtimes with minor modifications:

const bytes = /* read a .wasm file somehow */;
const mod = new WebAssembly.Module(bytes);
const instance = new WebAssembly.Instance(mod, { /* imports */ });

const { foo, bar } = instance.exports;
// call whichever functions you like

new WebAssembly.Module and new WebAssembly.Instance are synchronous, unlike WebAssembly.instantiateStreaming and friends.

In the examples below, I show how to load a wasm file from disk, but you can of course hardcode the filename if you prefer.

Tools

To test wasm on V8, you can use either Node or V8's standalone shell "D8". To test on SpiderMonkey, you can use a shell-only build. I have no idea about JavaScriptCore (Safari).

My coworker recommends a tool called jsvu for installing multiple JS runtimes without needing to build them: https://github.com/GoogleChromeLabs/jsvu. Doing so would require you to install Node first so it might not be totally worth it, but it could make things easier overall. Otherwise you can try following specific installation steps below.

D8

Info: https://v8.dev/docs/d8. D8 will generally be more up-to-date than whatever version of V8 is in Node, but for Odin it probably doesn't matter.

Using

// run_wasm_d8.js
const bytes = readbuffer(arguments[0]);
const mod = new WebAssembly.Module(bytes);
const instance = new WebAssembly.Instance(mod, { /* imports */ });

const { foo, bar } = instance.exports;
// call whichever functions you like
d8 run_wasm_d8.js -- mymodule.wasm

Local files can be read as binary using readbuffer; arguments is argv. Note that d8 requires a -- before any script arguments.

Installing

D8 should be installed automatically as part of a typical V8 install; I don't know how to do that on all platforms, but I think I just did brew install v8 on Mac, so maybe it's in your package manager of choice.

SpiderMonkey

SpiderMonkey has a standalone Node-like shell which we typically use for testing.

Using

// run_wasm_sm.js
const bytes = os.file.readFile(scriptArgs[0], "binary");
const mod = new WebAssembly.Module(bytes);
const instance = new WebAssembly.Instance(mod, { /* imports */ });

const { foo, bar } = instance.exports;
// call whichever functions you like
js run_wasm_sm.js mymodule.wasm

os.file.readFile will synchronously read a file; scriptArgs is argv.

Installing

SpiderMonkey shell builds can be downloaded from Mozilla's FTP server. Search for jsshell: https://ftp.mozilla.org/pub/firefox/nightly/latest-mozilla-central/

The link above is for the latest nightly build, but you can also find official releases on the FTP server as well.

Node

Using

// run_wasm_node.js
const fs = require("fs");
const process = require("process");

const bytes = fs.readFileSync(process.argv[2]);
const mod = new WebAssembly.Module(bytes);
const instance = new WebAssembly.Instance(mod, { /* imports */ });

const { foo, bar } = instance.exports;
// call whichever functions you like
node run_wasm_node.js mymodule.wasm

Note that the interesting arguments to argv start at 2 instead of 0 in Node-world.

Installing

I dunno, use a package manager or something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment