bytebox icon indicating copy to clipboard operation
bytebox copied to clipboard

Standalone WebAssembly VM.

Bytebox

Markdown Logo

Bytebox is a Webassembly VM.

Getting started

Requirements

Bytebox currently builds with Zig 0.11.x to avoid churn on zig master.

Run

git clone --recurse-submodules https://github.com/rdunnington/bytebox.git
cd bytebox
zig build test  # run the WebAssembly spec testsuite
# run the wasi testsuite
python3 test/wasi/wasi-testsuite/test-runner/wasi_test_runner.py -r test/wasi/bytebox_adapter.py -t ./test/wasi/wasi-testsuite/tests/assemblyscript/testsuite/ ./test/wasi/wasi-testsuite/tests/c/testsuite/ ./test/wasi/wasi-testsuite/tests/rust/testsuite/

Usage

You can use the standalone runtime to load and execute WebAssembly programs:

zig build run -- <file> [function] [function args]...

Or embed Bytebox in your own programs:

// build.zig
const std = @import("std");

pub fn build(b: *std.build.Builder) void {
    const exe = b.addExecutable("my_program", "src/main.zig");
    exe.addPackage(std.build.Pkg{
        .name = "bytebox",
        .source = .{ .path = "bytebox/src/core.zig" }, // submodule in the root dir
    });
    exe.setTarget(b.standardTargetOptions(.{}));
    exe.setBuildMode(b.standardReleaseOptions());
    exe.install();
    const run = exe.run();
    const step = b.step("run", "runs my_program");
    step.dependOn(&run.step);
}

// main.zig
const std = @import("std");
const bytebox = @import("bytebox");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    var allocator: std.mem.Allocator = gpa.allocator();

    var wasm_data: []u8 = try std.fs.cwd().readFileAlloc(allocator, "example.wasm", 1024 * 128);
    defer allocator.free(wasm_data);

    var module_definition = bytebox.ModuleDefinition.init(allocator, .{});
    defer module_definition.deinit();
    try module_definition.decode(wasm_data);

    var module_instance = bytebox.ModuleInstance.init(&module_definition, allocator);
    defer module_instance.deinit();
    try module_instance.instantiate(.{});
}

Inter-language FFI is also supported. See src/bytebox.h for an overview in C. To use bytebox as a static library, link with the built library in zig-out/lib/. Note that Zig assumes a default stack size of 8MB, so you'll need to ensure the same in your program.

Status

This project is still in the alpha stage.

Legend Meaning
Implemented
TODO
💀 Not planned/Removed from spec

WebAssembly support:

Status Feature
WebAssembly 1.0
Sign extension instructions
Non-trapping float-to-int conversion
Multiple values
Reference types
Table instructions
Multiple tables
Bulk memory and table instructions
Vector instructions

WASI Preview 1 support:

Status Feature
args_get
args_sizes_get
environ_get
environ_sizes_get
clock_res_get
clock_time_get
fd_advise
fd_allocate
fd_close
fd_datasync
fd_fdstat_get
fd_fdstat_set_flags
💀 fd_fdstat_set_rights
fd_filestat_get
fd_filestat_set_size
fd_filestat_set_times
fd_pread
fd_prestat_get
fd_prestat_dir_name
fd_pwrite
fd_read
fd_readdir
fd_renumber
fd_seek
fd_sync
fd_tell
fd_write
path_create_directory
path_filestat_get
path_filestat_set_times
path_link
path_open
path_readlink
path_remove_directory
path_rename
path_symlink
path_unlink_file
poll_oneoff
proc_exit
💀 proc_raise
sched_yield
random_get
sock_accept
sock_recv
sock_send
sock_shutdown

Roadmap

These tasks must be completed to enter alpha:

  • API ergonomics pass
  • Documentation
  • General TODO/code cleanup
  • Crash hardening/fuzzing

To enter beta:

  • No breaking API changes after this point
  • Performance competitive with other well-known interpreters (e.g. micro-wasm-runtime, wasm3)

To have a 1.0 release:

  • Tested with a wide variety of wasm programs
  • Successfully used in other beta-quality projects