As said in Understanding WebAssembly text format, to enable WebAssembly to be read and edited by humans, there is a textual representation of the wasm binary format. You've seen how to compile C to WebAssembly and the corresponding text format in Compiling C to WebAssembly. In both the binary and textual formats, the fundamental unit of code in WebAssembly is a module. If you have experience with Lisp, you might feel familiar with the text format represented as one big S-expression.
WasmFiddle can compile C to WebAssembly but doesn't allow editing the text format. There's a online WasmExplorer which allows you to do that (but doesn't provide JavaScript editor).
In the above figure, you can edit the WebAssembly text format in the “Wat”. (The file extension of the WebAssembly text format is “.wat”. That's why we often call it “Wat”.) After editing in “Wat”, click “ASSEMBLE” to compile to the wasm binary format.
Even though I haven’t started talking about Wat, you can still understand what the code does from keywords module
, func
, param
, result
and export
. The code defines a module and exports an add
function.
(module
(func $add (param $lhs i32) (param $rhs i32) (result i32)
get_local $lhs
get_local $rhs
i32.add)
(export "add" (func $add))
)
The get_local
command would push the value of the local it read onto the stack. We push two values onto the stack because i32.add
pops two i32
values, computes their sum and pushes the resulting i32
value onto the stack.
After downloading “.wasm“, use the following JavaScript to invoke the exported add
function.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
WebAssembly.instantiateStreaming(fetch('program.wasm'))
.then(prog => {
console.log(prog.instance.exports.add(1, 2));
});
</script>
</body>
</html>
You can edit and compile Wat locally through WABT: The WebAssembly Binary Toolkit. The wat2wasm
command translates from WebAssembly text format to the WebAssembly binary format. The wasm2wat
command is the inverse of wat2wasm
. It translates from the binary format back to the text format.
If you use Visual Studio Code, the extension WebAssembly Toolkit for VSCode by Dmitriy Tsvettsikh is helpful. It provides syntax highlight for WebAssembly textual representation and fast convertation between text and binary view.
You can see that I use http-server
of Node.js in the above figure.
Importing a JavaScript function can be done by import
. For example, the following code imports and calls the JavaScript log
function into WebAssembly.
(module
(import "env" "log" (func $log (param i32)))
(func $add (param $lhs i32) (param $rhs i32) (result i32)
(local $result i32)
get_local $lhs
get_local $rhs
i32.add
tee_local $result
call $log
get_local $result)
(export "add" (func $add))
)
The example includes more details about Wat. I'll explain them in later documents.
Node.js also supports WebAssembly now. For example, you can edit a .js file.
const fs = require('fs');
const buffer = fs.readFileSync(('program.wasm'));
WebAssembly.instantiate(buffer)
.then(prog => {
console.log(prog.instance.exports.add(1, 2));
});
Use nodejs
to run it. You would see the resulting 3 shown in the console.