# `wasmjs`: JavaScript tooling for WebAssembly `wasmjs` 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` API The 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. [binary format]: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#high-level-structure [WebAssembly opcode]: https://github.com/WebAssembly/design/blob/master/Semantics.md A simple example: ```javascript 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}.`); ``` # Testing * `self-test` tests `wasmjs` itself. * `js-api` tests the [WebAssembly JavaScript API](https://github.com/WebAssembly/design/blob/master/JS.md). * `function-tests` tests the WebAssembly compiler's implementation. All tests can be executed using: ```bash JSSHELL=/path/to/my/js-shell test.sh ``` They can also be executed by using WebKit's `run-javascriptcore-tests` tool: ```bash ./Tools/Scripts/run-javascriptcore-tests --release --filter wasm -arch x86_64 ```