wasmjs
: JavaScript tooling for WebAssemblywasmjs
is a self-contained collection of JavaScript tools which can create and manipulate WebAssembly representations and binaries. At its core is wasm.json
, a JSON decription of the WebAssembly format and other interesting facts about WebAssembly as used by the Webkit project (such as the names of associated JavaScriptCore B3 opcodes).
wasmjs
requires modern JavaScript features such as ES6 modules, which is acceptable because WebAssembly is itself contemporary to these other features.
Builder
APIThe current core API of wasmjs
is the Builder
API from Builder.js
. It is used to build WebAssembly modules, and assemble them to valid .wasm
binaries (held in an ArrayBuffer
). The Builder
is a small DSL which looks similar to the WebAssembly binary format. Each section is declared through a property on the Builder
object, and each declaration returns a proxy object which has properties specific to that section. Proxies are “popped” back by invoking their .End()
property.
The Code
section has properties for each WebAssembly opcode. Opcode which create a scope can be nested using a lambda.
A simple example:
import Builder from 'Builder.js'; const builder = new Builder(); // Construct the equivalent of: (module (func "answer" (i32.const 42) (return))) builder // Declare a Type section, which the builder will auto-fill as functions are defined. .Type().End() // Declare a Function section, which the builder will auto-fill as functions are defined. .Function().End() .Export() // Export the "answer" function (defined below) to JavaScript. .Function("answer") .End() .Code() // The "answer" function takes an i32 parameters, and returns an i32. .Function("answer", { params: ["i32"], ret: "i32" }) // Create a block returning an i32, whose body is the enclosed lambda. .Block("i32", b => b .GetLocal(0) // Parameters are in the same index space as locals. .I32Const(0) // Generate an i32 constant. .I32Eq() // A comparison, using the two values currently on the stack. .If("i32") // Consume the comparison result, returning an i32. .I32Const(42) .Else() .I32Const(1) .End() ) .Return() // Return the top of the stack: the value returned by the block. .End() // End the current function. .End(); // End the Code section. // Create an ArrayBuffer which is a valid WebAssembly `.wasm` file. const bin = builder.WebAssembly().get(); // Use the standard WebAssembly JavaScript API to compile the module, and instantiate it. const module = new WebAssembly.Module(bin); const instance = new WebAssembly.Instance(module); // Invoke the compiled WebAssembly function. const result0 = instance.exports.answer(0); if (result0 !== 42) throw new Error(`Expected 42, got ${result0}.`); const result1 = instance.exports.answer(1); if (result1 !== 1) throw new Error(`Expected 1, got ${result1}.`);
self-test
tests wasmjs
itself.js-api
tests the WebAssembly JavaScript API.function-tests
tests the WebAssembly compiler's implementation.All tests can be executed using:
JSSHELL=/path/to/my/js-shell test.sh
They can also be executed by using WebKit's run-javascriptcore-tests
tool:
./Tools/Scripts/run-javascriptcore-tests --release --filter wasm -arch x86_64