Skip to content

feat(wasm-host): W2 minimal WASI preview1 subset for scoot-wasm - #148

Merged
jamiesun merged 1 commit into
mainfrom
feat/wasm-host-w2
Jun 26, 2026
Merged

feat(wasm-host): W2 minimal WASI preview1 subset for scoot-wasm#148
jamiesun merged 1 commit into
mainfrom
feat/wasm-host-w2

Conversation

@jamiesun

Copy link
Copy Markdown
Collaborator

What

Implements W2 of the scoot-wasm plan (#100): a deliberately small,
capability-safe WASI preview1 subset so a wasm32-wasi command module can
read stdin, write stdout/stderr, and exit. Run with:

scoot-wasm wasi <module.wasm> [args...]

The host instantiates the module, runs its start section and _start export,
pipes this process's stdin to fd 0, forwards the module's stdout/stderr, and
exits with the module's proc_exit status (a normal _start return exits 0).
This is the intended subprocess host for the external compression plugins of #98
(host = "scoot-wasm wasi <component>", JSON-in/JSON-out over stdio).

W0 (#145) and W1 (#147) are merged; this is the next independent phase PR.

Exposed WASI surface

Everything else traps — capability-safe by construction:

  • args_sizes_get / args_get, environ_sizes_get / environ_get
  • fd_read (fd 0), fd_write (fd 1/2), fd_close
  • fd_seek (stdio -> ESPIPE), fd_fdstat_get (stdio character device)
  • clock_time_get (realtime/monotonic), random_get (seeded/deterministic)
  • proc_exit

No filesystem or network functions are implemented. environ is empty by
default (the host environment is never leaked). Out-of-bounds guest pointers
return EFAULT instead of corrupting host memory; bad fds return EBADF. The
engine performs no real IO: the host supplies clock nanos and a random seed,
and splitmix64 generates random bytes deterministically.

Boundary

The WASI layer is compiled only into the standalone scoot-wasm binary
(-Dwasm-host=true); the zero-dependency core never links it. Default
zig build still builds only scoot.

Tests

Adds 11 hand-built wasm fixtures (no toolchain dependency) covering: echo
stdin->stdout, args/env round-trip, proc_exit codes, fd_write nwritten,
random_get determinism, bad-fd errno, OOB pointer -> EFAULT, and
unknown-import traps. zig build test is green (all engine tests run
unconditionally).

Verification

  • zig build -Dwasm-host=true
  • zig build test (incl. 11 new WASI tests)
  • Local CI (fmt / Debug build / test / ReleaseSafe / CLI smoke)
  • End-to-end: a generated echo.wasm round-trips Hello, WASI world! and exits 0;
    an exit42.wasm exits 42; a missing module prints FAIL to stderr and exits 1.

Docs

Updates docs/WASM_TOOLS.md (+.zh) and CHANGELOG.md (+docs/CHANGELOG.zh.md).

Refs #100

Add a deliberately small, capability-safe WASI preview1 layer to the
standalone scoot-wasm host so a wasm32-wasi command module can read
stdin, write stdout/stderr, and exit. Run with:

    scoot-wasm wasi <module.wasm> [args...]

The host instantiates the module, runs its start section and _start
export, pipes this process's stdin to fd 0, forwards the module's
stdout/stderr, and exits with the module's proc_exit status (a normal
_start return exits 0). This is the intended subprocess host for the
external compression plugins of #98.

Exposed WASI surface (everything else traps; capability-safe by
construction):
  - args_sizes_get / args_get, environ_sizes_get / environ_get
  - fd_read (fd 0), fd_write (fd 1/2), fd_close
  - fd_seek (stdio -> ESPIPE), fd_fdstat_get (stdio character device)
  - clock_time_get (realtime/monotonic), random_get (seeded/deterministic)
  - proc_exit

No filesystem or network functions are implemented; environ is empty by
default (the host environment is never leaked); out-of-bounds guest
pointers return EFAULT instead of corrupting host memory; bad fds return
EBADF. The engine performs no real IO: the host supplies clock nanos and
a random seed, and splitmix64 generates random bytes deterministically.

The WASI layer is compiled only into the standalone scoot-wasm binary
(-Dwasm-host=true); the zero-dependency core never links it.

Adds 11 hand-built wasm fixtures covering echo, args/env round-trip,
proc_exit codes, fd_write nwritten, random_get determinism, bad-fd
errno, OOB pointer -> EFAULT, and unknown-import traps. Updates
docs/WASM_TOOLS.md(.zh) and both changelogs.

Refs #100

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jamiesun
jamiesun merged commit c16a101 into main Jun 26, 2026
7 checks passed
@jamiesun
jamiesun deleted the feat/wasm-host-w2 branch June 26, 2026 16:51
jamiesun added a commit that referenced this pull request Jun 27, 2026
- wasm host W0-W4: integer, WASI preview1, type validation, float execution (#145, #147, #148, #149, #162)
- feat: wasm_tool action for compute-only packages (#154)
- wasm: narrow plugin sandbox to stdin/stdout/stderr/argv as a new hard rule (#164)
- feat: committed playground test environment with full action coverage (#161)
- release: single ReleaseSafe flavor, ship scoot-wasm artifacts, Homebrew tap (#166)
- fix(release): reference SCOOT_DOCKERHUB_* secrets so Docker Hub login is attempted
- docs: README rewrite + infographic, English comment translation (#160, #165, #146, #153)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant