WebAssembly

Zig supports building for WebAssembly out of the box.

Freestanding

For host environments like the web browser and nodejs, build as an executable using the freestanding OS target. Here’s an example of running Zig code compiled to WebAssembly with nodejs.

math.zig

  1. extern fn print(i32) void;
  2. export fn add(a: i32, b: i32) void {
  3. print(a + b);
  4. }

Shell

  1. $ zig build-exe math.zig -target wasm32-freestanding -fno-entry --export=add

test.js

  1. const fs = require('fs');
  2. const source = fs.readFileSync("./math.wasm");
  3. const typedArray = new Uint8Array(source);
  4. WebAssembly.instantiate(typedArray, {
  5. env: {
  6. print: (result) => { console.log(`The result is ${result}`); }
  7. }}).then(result => {
  8. const add = result.instance.exports.add;
  9. add(1, 2);
  10. });

Shell

  1. $ node test.js
  2. The result is 3

WASI

Zig’s support for WebAssembly System Interface (WASI) is under active development. Example of using the standard library and reading command line arguments:

wasi_args.zig

  1. const std = @import("std");
  2. pub fn main() !void {
  3. var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
  4. const gpa = general_purpose_allocator.allocator();
  5. const args = try std.process.argsAlloc(gpa);
  6. defer std.process.argsFree(gpa, args);
  7. for (args, 0..) |arg, i| {
  8. std.debug.print("{}: {s}\n", .{ i, arg });
  9. }
  10. }

Shell

  1. $ zig build-exe wasi_args.zig -target wasm32-wasi

Shell

  1. $ wasmtime wasi_args.wasm 123 hello
  2. 0: wasi_args.wasm
  3. 1: 123
  4. 2: hello

A more interesting example would be extracting the list of preopens from the runtime. This is now supported in the standard library via std.fs.wasi.Preopens:

wasi_preopens.zig

  1. const std = @import("std");
  2. const fs = std.fs;
  3. pub fn main() !void {
  4. var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
  5. const gpa = general_purpose_allocator.allocator();
  6. var arena_instance = std.heap.ArenaAllocator.init(gpa);
  7. defer arena_instance.deinit();
  8. const arena = arena_instance.allocator();
  9. const preopens = try fs.wasi.preopensAlloc(arena);
  10. for (preopens.names, 0..) |preopen, i| {
  11. std.debug.print("{}: {s}\n", .{ i, preopen });
  12. }
  13. }

Shell

  1. $ zig build-exe wasi_preopens.zig -target wasm32-wasi

Shell

  1. $ wasmtime --dir=. wasi_preopens.wasm
  2. 0: stdin
  3. 1: stdout
  4. 2: stderr
  5. 3: .