wasihost

package module
v0.0.0-...-5e095ad Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 7, 2026 License: MIT Imports: 18 Imported by: 0

README

wasm2go-wasi-host

Go Reference Go Version Go Report Card CI Release

[!WARNING] Status: Beta. This project is in mid-development. The WASI Preview1 API is stable. At this time, I do not anticipate and breaking changes. Use with caution in production environments.

The current work on this project is porting existing Go packages that use the wazero wasip1 to this package. The following have been successfully ported:

A specialized WASI snapshot-preview1 host for Go, designed to run code transpiled by wasm2go.

The primary goal is a WASI implementation for wasm2go-generated packages that complies with the WASI preview 1 specification. The host implements all 40 WASI Preview1 functions plus the env.call_host_function stub required by some modules.

Filesystem access is capability-oriented: the guest sees only preopened directoriesread-only fs.FS preopens (embedded assets) or writable host directory mounts. Each preopen uses a single backend; combine embedded and host data with separate preopens, not a hybrid overlay on one mount.

This repository also ships wasm2go-run, the runner used by the WebAssembly/wasi-testsuite wasm2go adapter (via the wasi-testsuite git submodule). All 72 wasm32-wasip1 tests in that inventory pass with this host.

For production-grade performance, advanced sandboxing, or broader runtime features, consider mature runtimes such as Wasmtime or wazero. See ARCHITECTURE.md for design detail.

Features

  • Full WASI Preview1: All 40 snapshot-preview1 imports, validated against wasi-testsuite.
  • wasm2go-native: Direct guest linear memory via a callback—no external runtime API between guest and host.
  • Capability-oriented VFS: Multiple preopens; read-only fs.FS and writable host directories (internal/wasi/sysfs), one backend per mount.
  • Stdlib-first: Go standard library plus golang.org/x/sys for a few OS-specific helpers (Linux and Darwin).
  • CLI runner: wasm2go-run transpiles, compiles, and runs .wasm in one step (tier-1 transpile cache included).

Installation

go get github.com/lbe/wasm2go-wasi-host

Usage

Using as a library
import (
    "os"
    wasihost "github.com/lbe/wasm2go-wasi-host"
    generated "github.com/your/generated/package" // module produced by wasm2go
)

func main() {
    var mod *generated.Module
    cfg := wasihost.NewModuleConfig().
        WithArgs("app-name", "arg1").
        WithEnv("PATH", "/bin").
        WithHostDirectoryPreopen("/", "./host-data").
        WithStdout(os.Stdout).
        WithStderr(os.Stderr)
    state := wasihost.New(
        func() []byte { return *mod.Xmemory().Slice() },
        cfg,
    )

    mod = generated.New(state, state)

    defer func() {
        if r := recover(); r != nil {
            if e, ok := r.(wasihost.ExitError); ok {
                os.Exit(int(e.Code))
            }
            panic(r)
        }
    }()
    mod.X_start()
}

Package documentation: pkg.go.dev.

Using the CLI runner

See cmd/wasm2go-run/README.md.

File system support

Configure mounts on NewModuleConfig:

  • WithReadOnlyFS(guestPath, root): Read-only fs.FS preopen (internal/wasi/sysfs.AdaptFS); WASI rights exclude writes and path mutations.
  • WithHostDirectoryPreopen(guestPath, hostPath): Writable host directory preopen (sysfs.DirFS); reads and mutations go through the WASI VFS with path confinement on the host root.
  • WithFS(fsConfig): Advanced layout via FSConfig (WithDirMount, WithReadOnlyDirMount, WithFSMount).

Use separate preopens when the guest needs both writable host storage and embedded read-only files (for example /tmp on disk and /assets from embed.FS). Writable mounts do not fall back to embedded fs.FS content.

Optional WithOsyield configures the yield function used by sched_yield (default runtime.Gosched).

Path matching, lexical bounds, and symlink rules: docs/path-confinement.md.

Concurrency and safety

  • Single-owner: State is not safe for concurrent use. One State per wasm2go module instance, one goroutine.

Development

Prerequisites
  • Go 1.26.3 or later
  • wasm2go on PATH
  • Python 3 for wasi-testsuite and quality-gate tests
  • golangci-lint for linting
Getting started
  1. Clone and initialize submodules:

    git clone https://github.com/lbe/wasm2go-wasi-host.git
    cd wasm2go-wasi-host
    git submodule update --init --recursive
    
Testing

See TESTING.md for tier layout, unit-vs-e2e policy, and the e2e_cases.json manifest.

Tests split into two tiers via the e2e build tag:

Command What runs Typical time
go test ./... or make test Unit / in-process tests (*_test.go without tag) ~5s
go test -tags=e2e ./... or make test-e2e Everything above plus all 72 e2e_*_test.go wasi-testsuite cases (parallel subprocesses) ~15–25s

Integration tests load testdata/e2e_cases.json via e2e_inventory_test.go (tagged //go:build e2e). CI runs go test -tags=e2e ./.... Editor support: .vscode/settings.json sets gopls buildFlags: ["-tags=e2e"]; .golangci.yml includes the same tag so linters analyze e2e files.

make test       # daily dev loop
make test-e2e   # before push / matches CI
make test-race  # unit tests with -race
make test-race-e2e  # full suite with -race

Other Makefile targets: build, lint, format, cover (unit coverage), cover-e2e (full coverage).

Quality gate

Requires a clean git tree (skipped automatically when the tree is dirty, so go test -tags=e2e ./... works mid-branch):

go test -tags=e2e -v -run TestQualityGate

Runs gofmt, a wasm2go-run build, and artifact cleanup. Lint and wasi-testsuite adapter pytest run in CI (make lint, workflow). Equivalent shell workflow: ./scripts/phase_guard.sh.

Full Preview1 compliance
go build -o ./bin/wasm2go-run ./cmd/wasm2go-run
./scripts/e2e-wasip1.sh

The wrapper defaults WASM2GO_RUN to ./bin/wasm2go-run and WASM2GO_WASIHOST_PATH to the repo root. Override either variable to use different paths.

Direct invocation:

go build -o ./bin/wasm2go-run ./cmd/wasm2go-run
cd wasi-testsuite
WASM2GO_RUN="$PWD/../bin/wasm2go-run" WASM2GO_WASIHOST_PATH="$PWD/.." python3 ./run-tests -r adapters/wasm2go.py

If WASM2GO_RUN is unset, the adapter uses wasm2go-run from PATH.

Format before commit: gofmt -w . or make format.

License

This project is licensed under the MIT License.

internal/wasi/ and internal/wasi/sysfs/ include code adapted from wazero (Copyright 2020–2023 The wazero Authors), licensed under the Apache License 2.0. See NOTICE and docs/design-improvements-2.md for attribution and the portable code inventory.

Documentation

Overview

Package wasihost implements a WASI snapshot-preview1 host for Go code produced by [wasm2go]. It implements all 40 WASI Preview1 imports plus the env.call_host_function stub used by some wasm2go modules.

Filesystem access is capability-oriented: guests see only preopened directories, either read-only fs.FS mounts or writable host directories (one backend per preopen; use separate preopens for embedded plus host data). See ARCHITECTURE.md for the source layout and syscall flow.

Usage

Construct a State with New, passing a callback that returns the guest's linear memory slice. The callback is re-invoked on every syscall so memory growth is handled transparently:

cfg := wasihost.NewModuleConfig().
    WithArgs("app").
    WithHostDirectoryPreopen("/", hostDir)
state := wasihost.New(func() []byte { return *mod.Xmemory().Slice() }, cfg)
mod := generated.New(state, state)

Recover ExitError at the module boundary to obtain the guest exit code.

Concurrency

State is not safe for concurrent use. Each wasm2go module instance needs its own State, used from a single goroutine.

Memory layout

All multi-byte integers written into guest memory are little-endian per the WASI snapshot-preview1 specification.

Index

Constants

View Source
const (
	StdinFD  = 0
	StdoutFD = 1
	StderrFD = 2
)

Standard WASI file descriptor numbers for the process I/O streams.

View Source
const SysClockResolutionNanotime = wasi.ClockResolution(1)

SysClockResolutionNanotime is the resolution reported by the system monotonic clock in nanoseconds (1 ns).

View Source
const SysClockResolutionWalltime = wasi.ClockResolution(1000)

SysClockResolutionWalltime is the resolution reported by the system wallclock in nanoseconds (1000 ns = 1 µs).

Variables

This section is empty.

Functions

This section is empty.

Types

type ExitError

type ExitError struct{ Code int32 }

ExitError is the panic value raised by proc_exit. Embedding applications must recover it at the wasm eval boundary to obtain the guest exit code:

defer func() {
    if r := recover(); r != nil {
        if e, ok := r.(wasihost.ExitError); ok {
            // e.Code is the guest exit status
        }
    }
}()

func (ExitError) Error

func (e ExitError) Error() string

Error implements the error interface. Returns a string of the form "exit status N" where N is the guest exit code.

type FSConfig

type FSConfig struct {
	// contains filtered or unexported fields
}

FSConfig holds filesystem configuration for a WASI module.

func NewFSConfig

func NewFSConfig() *FSConfig

NewFSConfig returns a pointer to an empty FSConfig.

func (*FSConfig) WithDirMount

func (c *FSConfig) WithDirMount(guestPath, hostPath string) *FSConfig

WithDirMount adds a writable host directory preopen. Parameters are in canonical (guestPath, hostPath) order for consistency with ModuleConfig.WithHostDirectoryPreopen.

func (*FSConfig) WithFSMount

func (c *FSConfig) WithFSMount(guestPath string, fsys fs.FS) *FSConfig

WithFSMount adds a read-only fs.FS preopen. Parameters are in canonical (guestPath, fsys) order for consistency with ModuleConfig.WithReadOnlyFS.

func (*FSConfig) WithReadOnlyDirMount

func (c *FSConfig) WithReadOnlyDirMount(guestPath, hostPath string) *FSConfig

WithReadOnlyDirMount adds a read-only host directory preopen. Parameters are in canonical (guestPath, hostPath) order for consistency with ModuleConfig.WithReadOnlyFS.

type ModuleConfig

type ModuleConfig struct {
	// contains filtered or unexported fields
}

ModuleConfig holds configuration for a WASI module execution.

The builder methods (WithArgs, WithEnv, WithWalltime, WithOsyield, etc.) follow an immutable pattern: each returns a new deep copy with the change applied, leaving the original unchanged.

func NewModuleConfig

func NewModuleConfig() *ModuleConfig

NewModuleConfig returns a pointer to a zero-value ModuleConfig.

func (*ModuleConfig) Args

func (c *ModuleConfig) Args() [][]byte

Args returns the guest argument list.

func (*ModuleConfig) ClockNanosleep

func (c *ModuleConfig) ClockNanosleep() (wasi.Nanosleep, bool)

ClockNanosleep returns configured nanosleep when set.

func (*ModuleConfig) ClockNanotime

func (c *ModuleConfig) ClockNanotime() (wasi.Nanotime, wasi.ClockResolution, bool)

ClockNanotime returns configured nanotime when set.

func (*ModuleConfig) ClockOsyield

func (c *ModuleConfig) ClockOsyield() (wasi.Osyield, bool)

ClockOsyield returns configured osyield when set.

func (*ModuleConfig) ClockWalltime

func (c *ModuleConfig) ClockWalltime() (wasi.Walltime, wasi.ClockResolution, bool)

ClockWalltime returns configured walltime when set.

func (*ModuleConfig) Environ

func (c *ModuleConfig) Environ() [][]byte

Environ returns the guest environment variable list in "KEY=VALUE" form.

func (*ModuleConfig) FSConfig

func (c *ModuleConfig) FSConfig() ([]wasi.FS, []string)

FSConfig returns the preopened filesystem mounts and their guest paths.

func (*ModuleConfig) FSPreopens

func (c *ModuleConfig) FSPreopens() ([]wasi.FS, []string)

FSPreopens returns preopens with mount guest paths for ctx.FS() path resolution.

func (*ModuleConfig) RandSource

func (c *ModuleConfig) RandSource() io.Reader

RandSource returns the reader used for random data (random_get), or nil if unset.

func (*ModuleConfig) Stderr

func (c *ModuleConfig) Stderr() io.Writer

Stderr returns the writer used for guest fd 2, or nil if unset.

func (*ModuleConfig) Stdin

func (c *ModuleConfig) Stdin() io.Reader

Stdin returns the reader used for guest fd 0, or nil if unset.

func (*ModuleConfig) Stdout

func (c *ModuleConfig) Stdout() io.Writer

Stdout returns the writer used for guest fd 1, or nil if unset.

func (*ModuleConfig) WithArgs

func (c *ModuleConfig) WithArgs(args ...string) *ModuleConfig

WithArgs returns a new ModuleConfig with the given args.

func (*ModuleConfig) WithEnv

func (c *ModuleConfig) WithEnv(key, value string) *ModuleConfig

WithEnv returns a new ModuleConfig with the given environment variable appended.

func (*ModuleConfig) WithEnvRaw

func (c *ModuleConfig) WithEnvRaw(env string) *ModuleConfig

WithEnvRaw returns a new ModuleConfig with the given raw "KEY=VALUE" environment variable appended. It is an additive helper retained for template compatibility; call WithEnv for semantic key/value pairing.

func (*ModuleConfig) WithFS

func (c *ModuleConfig) WithFS(fsConfig *FSConfig) *ModuleConfig

WithFS sets the filesystem configuration for preopened mounts.

func (*ModuleConfig) WithHostDirectoryPreopen

func (c *ModuleConfig) WithHostDirectoryPreopen(guestPath, hostPath string) *ModuleConfig

WithHostDirectoryPreopen adds a writable host directory preopen at guestPath.

func (*ModuleConfig) WithName

func (c *ModuleConfig) WithName(name string) *ModuleConfig

WithName returns a new ModuleConfig with the given module name.

func (*ModuleConfig) WithNanosleep

func (c *ModuleConfig) WithNanosleep(ns wasi.Nanosleep) *ModuleConfig

WithNanosleep returns a new ModuleConfig with the given nanosleep function.

func (*ModuleConfig) WithNanotime

func (c *ModuleConfig) WithNanotime(n wasi.Nanotime, res wasi.ClockResolution) *ModuleConfig

WithNanotime returns a new ModuleConfig with the given nanotime function and resolution.

func (*ModuleConfig) WithOsyield

func (c *ModuleConfig) WithOsyield(fn wasi.Osyield) *ModuleConfig

WithOsyield returns a copy with sched_yield hooked to fn (default runtime.Gosched).

func (*ModuleConfig) WithRandSource

func (c *ModuleConfig) WithRandSource(r io.Reader) *ModuleConfig

WithRandSource returns a new ModuleConfig with the given random source.

func (*ModuleConfig) WithReadOnlyFS

func (c *ModuleConfig) WithReadOnlyFS(guestPath string, root fs.FS) *ModuleConfig

WithReadOnlyFS adds a read-only guest filesystem mount that is explicitly marked as read-only in WASI preopens, reporting no write or mutation rights.

func (*ModuleConfig) WithStderr

func (c *ModuleConfig) WithStderr(w io.Writer) *ModuleConfig

WithStderr returns a new ModuleConfig with the given stderr writer.

func (*ModuleConfig) WithStdin

func (c *ModuleConfig) WithStdin(r io.Reader) *ModuleConfig

WithStdin returns a new ModuleConfig with the given stdin reader.

func (*ModuleConfig) WithStdout

func (c *ModuleConfig) WithStdout(w io.Writer) *ModuleConfig

WithStdout returns a new ModuleConfig with the given stdout writer.

func (*ModuleConfig) WithSysNanosleep

func (c *ModuleConfig) WithSysNanosleep() *ModuleConfig

WithSysNanosleep returns a new ModuleConfig with nanosleep sourced from time.Sleep.

func (*ModuleConfig) WithSysNanotime

func (c *ModuleConfig) WithSysNanotime() *ModuleConfig

WithSysNanotime returns a new ModuleConfig with monotonic time from time.Since.

func (*ModuleConfig) WithSysWalltime

func (c *ModuleConfig) WithSysWalltime() *ModuleConfig

WithSysWalltime returns a new ModuleConfig with walltime sourced from time.Now.

func (*ModuleConfig) WithWalltime

func (c *ModuleConfig) WithWalltime(w wasi.Walltime, res wasi.ClockResolution) *ModuleConfig

WithWalltime returns a new ModuleConfig with the given walltime function and resolution.

type PreopenEntry

type PreopenEntry struct {
	// contains filtered or unexported fields
}

PreopenEntry is one guest preopened directory (wasi.FS + guest path prefix).

type State

type State struct {
	// contains filtered or unexported fields
}

State is a WASI snapshot-preview1 host for a single wasm2go Module instance. It implements all X-prefixed method interfaces generated by wasm2go for the wasi_snapshot_preview1 and env import modules.

Construct State with New; do not create it directly. State is not safe for concurrent use.

func New

func New(mem func() []byte, config *ModuleConfig) *State

New creates a WASI snapshot-preview1 host state. mem is called on every syscall invocation to obtain the current guest linear memory slice; it is safe to call after memory growth events because wasm2go re-slices on grow.

The returned *State satisfies the X-prefixed method interfaces generated by wasm2go. Pass it as both import arguments to the generated module's New constructor:

state := wasihost.New(func() []byte { return *mod.Xmemory().Slice() }, cfg)
mod   := generated.New(state, state)

If mem is nil, any method that accesses guest memory will panic. A nil mem is only safe for tests that do not exercise memory-reading methods.

func (*State) Mem

func (s *State) Mem() []byte

Mem returns the current guest linear memory slice by invoking the mem callback passed to New. The returned slice may be replaced after any memory growth event; callers must not retain it across calls.

func (*State) Xargs_get

func (s *State) Xargs_get(argvPtr, argvBufPtr int32) int32

func (*State) Xargs_sizes_get

func (s *State) Xargs_sizes_get(argcPtr, argvSizePtr int32) int32

func (*State) Xcall_host_function

func (s *State) Xcall_host_function(v0, v1, v2 int32) int32

Xcall_host_function implements the env.call_host_function import used by zeroperl-style wasm2go modules as a host-callback bridge. This host does not support guest-initiated host callbacks; it always returns 0.

func (*State) Xclock_res_get

func (s *State) Xclock_res_get(clockID int32, resultPtr int32) int32

func (*State) Xclock_time_get

func (s *State) Xclock_time_get(clockID int32, precision int64, resultPtr int32) int32

func (*State) Xenviron_get

func (s *State) Xenviron_get(envPtr, envBufPtr int32) int32

func (*State) Xenviron_sizes_get

func (s *State) Xenviron_sizes_get(countPtr, bufSizePtr int32) int32

Xenviron_sizes_get implements environ_sizes_get. Writes the count of configured environment strings and their total buffer size (including null terminators) to the respective pointers in guest memory.

func (*State) Xfd_advise

func (s *State) Xfd_advise(fd int32, offset, length int64, advice int32) int32

func (*State) Xfd_allocate

func (s *State) Xfd_allocate(fd int32, offset, length int64) int32

func (*State) Xfd_close

func (s *State) Xfd_close(fd int32) int32

func (*State) Xfd_datasync

func (s *State) Xfd_datasync(fd int32) int32

func (*State) Xfd_fdstat_get

func (s *State) Xfd_fdstat_get(fd, statPtr int32) int32

Xfd_fdstat_get implements fd_fdstat_get. Writes a 24-byte fdstat struct at statPtr. fds 0-2 are reported as character devices; all others use the type recorded in the fd table.

func (*State) Xfd_fdstat_set_flags

func (s *State) Xfd_fdstat_set_flags(fd, flags int32) int32

func (*State) Xfd_fdstat_set_rights

func (s *State) Xfd_fdstat_set_rights(fd int32, base, inheriting int64) int32

func (*State) Xfd_filestat_get

func (s *State) Xfd_filestat_get(fd, bufPtr int32) int32

Xfd_filestat_get implements fd_filestat_get. Writes a 64-byte filestat struct for the open fd via fe.File.Stat on the FSContext FileEntry.

func (*State) Xfd_filestat_set_size

func (s *State) Xfd_filestat_set_size(fd int32, size int64) int32

Xfd_filestat_set_size implements fd_filestat_set_size via fe.File.Truncate. Returns EISDIR for directories, ENOTCAPABLE without FD_FILESTAT_SET_SIZE, and file-type errno values (for example ENOSYS on AdaptFS, EBADF on ReadFS).

func (*State) Xfd_filestat_set_times

func (s *State) Xfd_filestat_set_times(fd int32, atim, mtim int64, fstFlags int32) int32

Xfd_filestat_set_times implements fd_filestat_set_times via fe.File.Utimens. Returns EINVAL for contradictory fstFlags, EISDIR for directories, ENOTCAPABLE without FD_FILESTAT_SET_TIMES, and ESUCCESS without calling Utimens when fstFlags==0.

func (*State) Xfd_pread

func (s *State) Xfd_pread(fd, iovsPtr, iovsCount int32, offset int64, nreadPtr int32) int32

func (*State) Xfd_prestat_dir_name

func (s *State) Xfd_prestat_dir_name(fd, pathPtr, pathLen int32) int32

func (*State) Xfd_prestat_get

func (s *State) Xfd_prestat_get(fd, prestatPtr int32) int32

Xfd_prestat_get implements fd_prestat_get. Returns the prestat struct for the preopen directory at fd. Returns EBADF if fd is not a valid, in-use preopen.

func (*State) Xfd_pwrite

func (s *State) Xfd_pwrite(fd, iovsPtr, iovsCount int32, offset int64, nwrittenPtr int32) int32

func (*State) Xfd_read

func (s *State) Xfd_read(fd int32, iovsPtr int32, iovsCount int32, nreadPtr int32) int32

func (*State) Xfd_readdir

func (s *State) Xfd_readdir(fd int32, bufPtr int32, bufLen int32, cookie int64, bufUsedPtr int32) int32

func (*State) Xfd_renumber

func (s *State) Xfd_renumber(fd_from, fd_to int32) int32

Xfd_renumber implements fd_renumber. Renumbers the file descriptor from fd_from to fd_to. If fd_to is open, it is closed first. After this operation, fd_from is invalid and fd_to refers to the same open file description as fd_from used to.

func (*State) Xfd_seek

func (s *State) Xfd_seek(fd int32, offset int64, whence, newOffsetPtr int32) int32

func (*State) Xfd_sync

func (s *State) Xfd_sync(fd int32) int32

func (*State) Xfd_tell

func (s *State) Xfd_tell(fd, offsetPtr int32) int32

func (*State) Xfd_write

func (s *State) Xfd_write(fd int32, iovsPtr int32, iovsCount int32, nwrittenPtr int32) int32

func (*State) Xpath_create_directory

func (s *State) Xpath_create_directory(dirfd, pathPtr, pathLen int32) int32

Xpath_create_directory implements path_create_directory. Creates a directory at the resolved path via preopen.fsys.Mkdir. Returns EROFS if the mount is read-only, EEXIST if the directory already exists, ENOENT if the parent does not exist.

func (*State) Xpath_filestat_get

func (s *State) Xpath_filestat_get(dirfd, flags, pathPtr, pathLen, bufPtr int32) int32

Xpath_filestat_get implements path_filestat_get. Resolves the path and writes a 64-byte filestat struct via vfsStat (Lstat when SYMLINK_FOLLOW is absent, Stat when set). Writable preopens return ENOTCAPABLE for mount-relative paths that lexically escape the preopen; read-only preopens without fsys return ENOENT.

func (*State) Xpath_filestat_set_times

func (s *State) Xpath_filestat_set_times(dirfd, flags, pathPtr, pathLen int32, atim, mtim int64, fstFlags int32) int32

Xpath_filestat_set_times implements path_filestat_set_times.

ATIM (bit 0), ATIM_NOW (bit 1), MTIM (bit 2), and MTIM_NOW (bit 3) flags are acted upon. Rejects contradictory flag combinations (ATIM together with ATIM_NOW, or MTIM together with MTIM_NOW) with EINVAL. Resolves paths with resolveWritable (including ENOTCAPABLE when a directory preopen path lexically escapes the mount). When LOOKUPFLAGS_SYMLINK_FOLLOW is set in flags, follows symlinks in the final path component; otherwise sets times on the symlink inode itself via preopen.fsys.Utimens. Returns EROFS when the path is read-only or cannot be resolved to a writable preopen.

func (s *State) Xpath_link(oldDirfd, oldFlags, oldPathPtr, oldPathLen, newDirfd, newPathPtr, newPathLen int32) int32

Xpath_link implements path_link. Creates a hard link from the resolved old path to the resolved new path. Returns EROFS if either mount is read-only.

func (*State) Xpath_open

func (s *State) Xpath_open(dirfd int32, lookupFlags int32, pathPtr int32, pathLen int32, oflags int32, fdRightsBase int64, fdRightsInheriting int64, fdFlags int32, fdPtr int32) int32
func (s *State) Xpath_readlink(dirfd, pathPtr, pathLen, bufPtr, bufLen, nreadPtr int32) int32

Xpath_readlink implements path_readlink. Reads the target of a symbolic link at the resolved path into guest memory at bufPtr, capped at bufLen bytes, and writes the actual byte count to nreadPtr. Uses VFS Readlink via resolveReadlinkLookup (same resolution shape as path_filestat_get); read-only AdaptFS ENOSYS is mapped to EROFS.

func (*State) Xpath_remove_directory

func (s *State) Xpath_remove_directory(dirfd, pathPtr, pathLen int32) int32

Xpath_remove_directory implements path_remove_directory. Removes an empty directory at the resolved path. Returns EROFS if the mount is read-only, ENOTDIR if the target is a file, ENOTEMPTY if the directory is not empty.

func (*State) Xpath_rename

func (s *State) Xpath_rename(oldDirfd, oldPathPtr, oldPathLen, newDirfd, newPathPtr, newPathLen int32) int32

Xpath_rename implements path_rename. Resolves both old and new paths and calls preopen.fsys.Rename. Returns EROFS if either mount is read-only or if the resolved paths are not beneath a writable preopen root.

func (s *State) Xpath_symlink(oldPathPtr, oldPathLen, dirfd, newPathPtr, newPathLen int32) int32

Xpath_symlink implements path_symlink. Creates a symbolic link at the resolved path for newPath pointing to the raw string oldPath. Returns EROFS if the mount is read-only, EINVAL if oldPath is the absolute root path "/", EEXIST if the link path already exists, ENOENT if newPath has a trailing slash and does not exist, and ENOTDIR if newPath has a trailing slash but names a non-directory.

func (s *State) Xpath_unlink_file(dirfd, pathPtr, pathLen int32) int32

Xpath_unlink_file implements path_unlink_file. Removes a file at the resolved path. Returns EROFS if the mount is read-only, EISDIR if the target is a directory, ENOENT if the file does not exist, and ENOTDIR if the path has a trailing slash but the target is not a directory.

func (*State) Xpoll_oneoff

func (s *State) Xpoll_oneoff(inPtr int32, outPtr int32, nsubscriptions int32, neventsPtr int32) int32

Xpoll_oneoff implements poll_oneoff. This function processes subscriptions and writes output events. The memory layout is as follows:

Subscription (48 bytes):
  - 0:   userdata (uint64)
  - 8:   tag (u8): 0=clock, 1=fd_read, 2=fd_write
  - 9:   padding (7 bytes)
  - 16:  fd (uint32, for fd_read/fd_write) or clock.id
  - 20:  padding (4 bytes)
  - 24:  timeout (uint64, for clock events)
  - 32:  precision (uint64, for clock events)
  - 40:  flags (uint16, for clock events)
  - 42:  padding (6 bytes)

Output Event (32 bytes):
  - 0:   userdata (uint64)
  - 8:   error (uint16)
  - 10:  event_type (uint8) - stored as single byte per WASI spec
  - 11:  padding (uint8)
  - 12:  event-specific data:
    * For clock: timeout (uint64)
    * For fd_read/fd_write: fd (uint16)
  - 14:  padding (uint16 for fd events, or part of clock padding)
  - 16:  padding (uint64 for clock events to fill 32 bytes)
  - 24:  padding (uint64)

Note: The event_type is stored as a uint8 at offset +10, not as a uint32 at offset +12. This is a common pitfall and was a source of bugs.

Clock subscriptions sleep for the shortest requested timeout. fd_read and fd_write subscriptions call Poll on PollableFile or Pollable fds (zero timeout); when Poll reports not ready, no event is emitted. Other fds emit immediately if open. fd_write suppresses positive clock timeouts when emitted.

func (*State) Xproc_exit

func (s *State) Xproc_exit(code int32)

Xproc_exit implements proc_exit. Panics with ExitError so that the embedding application's eval boundary can recover it and obtain the guest exit code.

func (*State) Xproc_raise

func (s *State) Xproc_raise(signal int32) int32

Xproc_raise implements proc_raise. Always returns ENOSYS. Raising a signal inside a WASM guest has no meaningful host mapping.

func (*State) Xrandom_get

func (s *State) Xrandom_get(bufPtr, bufLen int32) int32

Xrandom_get implements random_get. Fills the guest memory region [bufPtr, bufPtr+bufLen) with cryptographically random bytes.

func (*State) Xsched_yield

func (s *State) Xsched_yield() int32

Xsched_yield implements sched_yield. This host is synchronous; yielding calls ctx.Osyield (default runtime.Gosched) and returns ESUCCESS.

func (*State) Xsock_accept

func (s *State) Xsock_accept(fd, flags, resultPtr int32) int32

Xsock_accept, Xsock_recv, Xsock_send, and Xsock_shutdown implement the WASI socket functions. Sockets are not supported in this host: accept, recv, and send return ENOSYS; shutdown returns EBADF for invalid/unused fds and ENOTSOCK for valid non-socket fds.

func (*State) Xsock_recv

func (s *State) Xsock_recv(fd, iovsPtr, iovsLen, riFlags, nreadPtr, roFlagsPtr int32) int32

func (*State) Xsock_send

func (s *State) Xsock_send(fd, iovsPtr, iovsLen, siFlags, nsentPtr int32) int32

func (*State) Xsock_shutdown

func (s *State) Xsock_shutdown(fd, how int32) int32

Directories

Path Synopsis
cmd
wasm2go-run command
Command wasm2go-run transpiles a WASI Preview1 WebAssembly module to Go with [wasm2go], links it against this repository's wasihost implementation, builds a native binary, and runs it.
Command wasm2go-run transpiles a WASI Preview1 WebAssembly module to Go with [wasm2go], links it against this repository's wasihost implementation, builds a native binary, and runs it.
internal
wasi
Package wasi provides WASI-native types, runtime context, and filesystem abstractions consumed by the wasihost syscall layer.
Package wasi provides WASI-native types, runtime context, and filesystem abstractions consumed by the wasihost syscall layer.
wasi/sysfs
Package sysfs implements wasi.FS and wasi.File adapters for host directories, read-only wrappers, and fs.FS mounts.
Package sysfs implements wasi.FS and wasi.File adapters for host directories, read-only wrappers, and fs.FS mounts.
wasi/testfixture
Package testfixture provides in-memory WASI filesystem fixtures for tests.
Package testfixture provides in-memory WASI filesystem fixtures for tests.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL