wago

package module
v0.0.0-...-1c880c9 Latest Latest
Warning

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

Go to latest
Published: Jul 19, 2026 License: Apache-2.0 Imports: 1 Imported by: 0

README

╦ ╦ ╔═╗ ╔═╗ ╔═╗
║║║ ╠═╣ ║ ╦ ║ ║
╚╩╝ ╩ ╩ ╚═╝ ╚═╝

A pure-Go, no-cgo WebAssembly JIT for low-latency host ↔ wasm execution.

Table of Contents

Installation

During private development, the installer builds from source over SSH. You need read access to git@github.com:wago-org/wago and Go 1.22+:

curl -fsSL https://wago.sh/install.sh | sh

The same command is intended to install a public prebuilt binary after the v0.1.0 release. Until then, useful installer knobs are:

Variable Meaning
WAGO_VERSION Git ref to build: branch, tag, or commit. Defaults to main.
WAGO_BIN_DIR Install directory. Defaults to ~/.local/bin.
WAGO_DRY_RUN=1 Print the source-build plan without installing.
NO_COLOR=1 Disable colored installer output.

From a checkout:

go build -o wago ./cli/wago
go install ./cli/wago

For library use:

go get github.com/wago-org/wago

Nightly attempts binaries for Linux, macOS, and Windows on both amd64 and arm64. Every build that succeeds is published as wago-<goos>-<goarch> with a SHA-256 checksum; targets without a native JIT port are omitted rather than blocking the nightly. Linux releases use the size-focused, no-cgo TinyGo build. wago version install and wago version update require the host's curl executable for HTTPS downloads.

Toolchain channels

The CLI can install stable versions and the moving release channels. Each nightly and canary has a unique, never-retargeted prerelease tag; the channel name resolves to its newest published release at install time:

wago version install 0.1.0
wago version install nightly  # latest successful nightly release
wago version install canary   # most recent successful-CI build of main

wago version update refreshes the active version, while a version argument or channel flag selects another target:

wago version update
wago version update nightly
wago version update --nightly
wago version update --canary

Docs

The high-level project docs live in this repo:

Usage

Run a module

wago run compiles a raw .wasm module and invokes an export. run is also the default command, so wago file.wasm ... works too.

wago run tests/testdata/fib.wasm 30
wago run -e hypot tests/testdata/fprog.wasm 3.0 4.0
wago tests/testdata/fib.wasm 30

Arguments are typed from the export signature. Override one argument with a suffix when the default parser is not enough:

wago run -e hypot tests/testdata/fprog.wasm 3:f64 4:f64

Function validation and codegen are serial by default. Use -p for adaptive per-function parallelism, or specify a worker maximum with the standard separated form or the short joined form:

wago run -p app.wasm          # adaptive policy
wago run -p 8 app.wasm        # at most 8 workers
wago run -p8 app.wasm         # equivalent shorthand
wago run --parallel=8 app.wasm

Validate without executing; the same worker flag is available:

wago validate tests/testdata/fib.wasm
wago validate -p tests/testdata/large.wasm

wago build is reserved for the future .wago product path and currently returns not implemented.

Inspect plugins and imports

The CLI can show which plugins are compiled into the binary and what imports a module needs:

wago plugin list
wago plugin inspect github.com/acme/wago-metrics
wago plugin inspect github.com/acme/wago-metrics --json

wago module imports app.wasm
wago module capabilities app.wasm
wago env
wago version list

The standard CLI contains no plugins. Project dependencies are compiled into a custom binary, while plugins entries activate them and grant their Wago host capabilities:

{
  "$schema": "https://wago.sh/schema.json",
  "schema": "wago/v1",
  "dependencies": ["github.com/acme/wago-metrics"],
  "plugins": [{
    "name": "github.com/acme/wago-metrics",
    "capabilities": ["host.imports"]
  }]
}

Load order is dependency-aware and deterministic; missing grants and cycles fail before any plugin contribution is committed. See docs/plugin-api-v2.md. The full manifest reference and editor schema are in docs/wago-json.md and schema.json.

Go API

Compile and invoke

The low-level API uses raw 8-byte wasm call slots. Encode arguments with wago.I32, I64, F32, F64; decode results with AsI32, AsI64, AsF32, and AsF64.

package main

import (
	"fmt"
	"os"

	"github.com/wago-org/wago"
)

func main() {
	src, err := os.ReadFile("tests/testdata/fprog.wasm")
	if err != nil {
		panic(err)
	}

	mod, err := wago.Compile(src)
	if err != nil {
		panic(err)
	}
	// A successful Compile takes ownership of src. Keep it immutable and do not
	// reuse its backing array while mod is alive.
	inst, err := wago.Instantiate(mod, nil)
	if err != nil {
		panic(err)
	}
	defer inst.Close()

	out, err := inst.Invoke("hypot", wago.F64(3), wago.F64(4))
	if err != nil {
		panic(err)
	}
	fmt.Println(wago.AsF64(out[0])) // 5
}

Compile once, instantiate many times when the same module is used repeatedly. For a hot repeated call, resolve the export once with fn, err := inst.PrepareFunction("hypot"), then call fn.Invoke(wago.F64(3), wago.F64(4)). A prepared function shares its instance's call buffers and is therefore subject to the same non-concurrent-call and result lifetime rules as Instance.Invoke.

Typed runtime calls

Runtime is the higher-level entry point. It carries config, plugins, hooks, and policy metadata, and exposes typed Value calls with context.Context.

rt := wago.NewRuntime()
defer rt.Close()

mod, err := rt.Compile(wasmBytes)
if err != nil {
	panic(err)
}

inst, err := rt.Instantiate(context.Background(), mod)
if err != nil {
	panic(err)
}
defer inst.Close()

out, err := inst.Call(context.Background(), "add", wago.ValueI32(2), wago.ValueI32(40))
if err != nil {
	panic(err)
}
fmt.Println(out[0].I32())

Use mod.Exports(), mod.Imports(), mod.RequiredCapabilities(), and mod.Metadata() for lightweight inspection. Imports preserves duplicate reference-global/table declarations and reports exact types and limits. ModuleMetadata.Functions, .Globals, and .Tables are deterministic Wasm-index ordered views with exact reference signatures, mutability, imports, exports, and declared table minima/maxima.

Host imports

Host functions use one reflection-free stack form. This is the same form used by plugins and it works under both Go and TinyGo:

mul := wago.HostFunc(func(_ wago.HostModule, params, results []uint64) {
	a := wago.AsI32(params[0])
	b := wago.AsI32(params[1])
	results[0] = wago.I32(a * b)
})

inst, err := wago.Instantiate(compiled, wago.Imports{
	"host.mul": mul,
})

HostModule gives the host function access to the calling instance's memory:

logString := wago.HostFunc(func(m wago.HostModule, params, results []uint64) {
	ptr := uint32(wago.AsI32(params[0]))
	n := uint32(wago.AsI32(params[1]))
	mem := m.Memory()
	if uint64(ptr)+uint64(n) > uint64(len(mem)) {
		results[0] = wago.I32(-1)
		return
	}
	fmt.Println(string(mem[ptr : ptr+n]))
	results[0] = wago.I32(0)
})

Host imports can take and return numeric scalars and v128. The public v128 representation is wago.V128, a [16]byte.

Memory

Instance.Memory().Bytes() returns the same mmap-backed linear memory the native wasm code sees. There is no copy between host and guest.

For hot host-side reads and writes, use the typed accessors. They are bounds-checked and avoid the slower encoding/binary pattern under TinyGo:

v, ok := inst.ReadUint32Le(off)
if ok {
	inst.WriteFloat64Le(off+8, float64(v))
}

buf, ok := inst.Read(ptr, length)
_ = inst.Write(ptr, []byte("hello"))

Out-of-bounds reads return ok=false; out-of-bounds writes return false and do not modify memory.

Globals, tables, and cross-instance linking

Wago supports numeric, v128, funcref, and externref globals across local definitions, imports, exports, shared mutation, and imported immutable global.get initializers. Reference globals use 8-byte cells and may be shared only through an exact compatible store owner. Multiple imported/shared funcref tables followed by local tables, memory imports/exports, and cross-instance function calls also execute. Externref signatures, locals/control flow, public generation-checked handles, reflection-free host round trips, and typed 8-byte tables with indexed get/set/size/grow/fill/copy/init/drop and active/passive/declarative null element segments are executable. Runtime.NewExternRefGlobal and Runtime.NewExternRefTable create explicit store-bound shared objects, while local reference global/table exports and re-exports may be imported only by instances in that exact runtime store. Runtime.NewHostFuncRef wraps a reflection-free HostFunc with one exact Wasm signature and store owner, allowing its descriptor to cross public funcref boundaries as a stable opaque token while retaining the callable thunk/context. Runtime.NewFuncRefGlobal creates a host-owned null or same-store token-initialized funcref cell from that exact proof. Raw HostFunc imports remain callable but their descriptors cannot egress. The official Release 2 execution corpus passes 1,600 modules and 48,248 assertions with zero feature gaps. .wago codec v20 round-trips structural reference globals, indexed typed tables/exports/elements, exact declared table-limit forms, and required-feature bits while rejecting live tokens, owners, descriptors, dispatch state, thunk addresses, and store identity. Fresh instantiation reinstates local reference state; snapshot products reject every table/reference-global module. ModuleMetadata reports every function/global/table index, reference type, import, export, and exact declared limit, including duplicate aliases and loaded modules. Consolidated trap and cross-link tests lock producer/consumer close ordering.

counter := wago.NewGlobalI32(10, true)
defer counter.Close()

mem, err := wago.NewSharedMemory(1, 8)
if err != nil {
	panic(err)
}
defer mem.Close()

rt := wago.NewRuntime()
defer rt.Close()
ref, err := rt.NewExternRef("shared")
if err != nil {
	panic(err)
}
refGlobal, err := rt.NewExternRefGlobal(ref, true)
if err != nil {
	panic(err)
}
defer refGlobal.Close()
refs, err := rt.NewExternRefTable(1, 8)
if err != nil {
	panic(err)
}
defer refs.Close()

mod, err := rt.Compile(wasmBytes)
inst, err := rt.Instantiate(context.Background(), mod, wago.WithImports(wago.Imports{
	"env.counter": wago.GlobalImport{Global: counter},
	"env.memory":  mem,
	"env.ref":     refGlobal,
	"env.refs":    refs,
}))

Shared *Global, *Memory, and *Table handles may be host/runtime-owned or come from an instance export. Use NewSharedMemory when several instances must import one host memory; NewMemory remains single-importer. Multiple compatible importers observe the same bytes and memory.grow state. Imported-memory re-exports preserve the original *Memory identity and producer lifetime rather than creating a relay owner. Reference globals and externref tables additionally require the exact reference store that owns their handles. Close consumers before the host-created shared object or producing instance.

An explicitly owned host funcref is imported as its *HostFuncRef handle:

owned, err := rt.NewHostFuncRef(
	wago.HostFunc(func(_ wago.HostModule, _, results []uint64) {
		results[0] = wago.I32(42)
	}),
	wago.FuncSig{Results: []wago.ValType{wago.ValI32}},
)
inst, err := rt.Instantiate(ctx, mod, wago.WithImports(wago.Imports{
	"env.answer": owned,
}))

Its signature and Runtime store must match exactly. Close every importing instance first. If a public token was issued, close the Runtime before owned.Close() so the store can release the retained thunk and home instance safely.

Plugins and policies

An extension declares its identity, capabilities, host imports, hooks, and managed-instance requirements through Registry. The optional worker implementation lives at github.com/wago-org/workers.

type randExt struct{}

func (randExt) Info() wago.ExtensionInfo {
	return wago.ExtensionInfo{
		ID:          "example.rand",
		Name:        "Rand",
		Version:     "1.0.0",
		Description: "Pseudo-random numbers for guests.",
		Stability:   wago.Experimental,
		Compat: wago.Compatibility{
			Engines: map[string]string{"wago": ">=0.1.0"},
		},
	}
}

func (randExt) Register(reg *wago.Registry) error {
	const capRand = wago.Capability("rand.read")
	reg.Capability(capRand, wago.CapabilityDocs("read pseudo-random numbers"))
	reg.ImportModule("wago_rand").
		Func("next", func(_ wago.HostModule, _ []uint64, results []uint64) {
			results[0] = wago.I64(4)
		}).
		Results(wago.ValI64).
		Capability(capRand)
	return nil
}

rt := wago.NewRuntime()
_ = rt.Use(randExt{})

Policies can allow or deny capabilities and enforce coarse declared resource limits at instantiation:

inst, err := rt.Instantiate(ctx, mod, wago.WithPolicy(wago.Policy{
	AllowedCapabilities: []wago.Capability{wago.CapTimerRead},
	MaxMemoryBytes:      16 << 20,
	MaxTableEntries:     1024,
}))

Precompiled modules

The Go API can serialize compiled modules to .wago blobs and load them later:

compiled, err := wago.Compile(wasmBytes)
blob, err := compiled.MarshalBinary()

compiled, err = wago.Load(blob)      // precompiled .wago
compiled, err = wago.Load(wasmBytes) // raw wasm, compiled on load

The CLI can run an existing .wago blob, but producing stable, cache-keyed .wago artifacts from the CLI is still on the roadmap.

Feature Support

Status: done means decoded, validated, compiled, and covered by tests or conformance where applicable. Partial means the feature family is admitted only for the listed subset. FEATURES.md is the source of truth.

WebAssembly Core

Feature Status
WebAssembly 1.0 MVP scalar semantics Done. The pinned MVP spec suite reports 629 modules and 16,026 assertions passing with zero failures or skips.
Numeric types i32, i64, f32, f64, and v128.
Integer ops Arithmetic, bitwise, shifts/rotates, div/rem traps, clz/ctz/popcnt, comparisons.
Float ops Add/sub/mul/div/sqrt/abs/neg/min/max, comparisons, rounding ops, conversions, reinterprets, NaN/overflow trunc traps.
Control flow block, loop, if, else, br, br_if, br_table, return, select, select t.
Calls Direct calls, recursion, call_indirect with table bounds and signature checks.
Linear memory All MVP load/store widths, memory.size, memory.grow, active data segments.
Globals Numeric, v128, funcref, and externref globals support local definitions, imports/exports, shared mutable identity, imported immutable global.get initializers, and exact store-safe typed host access.
Tables Funcref tables support passive/active elements, every table.* operation, multiple local/imported definitions, nonzero-table call_indirect, exact indexed exports/re-exports, duplicate imported aliases, and host functions. Externref tables use 8-byte entries and support active/passive/declarative null elements, indexed get/set/size/grow/fill/copy/init/drop, runtime-owned sharing, and exact local exports/re-exports.
Imports/exports Functions, numeric/vector/reference globals, memories, indexed funcref tables, and same-store externref tables with exact names; cross-instance function linking uses link-time recompile and context swap.
Start function Local start functions and imported void host start functions.
Sign extension Done: all five scalar i32/i64.extend{8,16,32}_s opcodes are decoded, validated, lowered, and covered by runtime/codegen tests.
Non-trapping float-to-int trunc_sat done.
Bulk memory Linear memory plus funcref and externref tables are complete for copy/fill/init/drop, passive data/elements, overlap, bounds, and already-dropped active/declarative segment state.
Multi-value Done semantically for functions, blocks, branches, calls, public invocation, and compiled metadata; a wider optimized result ABI remains a performance task.
Reference types Done for WebAssembly 2.0: nullable/non-null funcref, externref, structural ref.func, typed select, signatures, locals/control flow, local/imported/shared globals, reflection-free host calls, explicit host funcref ownership, typed 8-byte externref tables/elements, multiple local/imported tables, indexed operations and call_indirect, duplicate aliases, and exact exports/re-exports execute. Codec v20 persists safe structural metadata and exact required features/limits. Snapshot isolation, deterministic all-table/reference inspection, and cross-link teardown are audited. The Release 2 execution corpus is zero-skip at 1,600 modules / 48,248 assertions.
SIMD Done for the documented linux/amd64 baseline: SSSE3/SSE4.1 plus AVX/VEX.128. Core SIMD and deterministic relaxed SIMD opcodes through 0xfd 275 are decoded, validated, and lowered.
Threads and atomics Planned.
Tail calls Planned.
Multi-memory Not planned.
Exceptions and wasm GC proposals Not planned for now.

Runtime and product surface

Area Status
No-cgo execution Done: W^X mmap, foreign-stack trampoline, trap-to-error path, zero-copy linear memory.
Bounds checks Explicit checks by default; signals/guard-page mode behind -tags wago_guardpage and WAGO_BOUNDS=signals.
Runtime config Done: immutable wazero-style RuntimeConfig, feature gating, memory page limit, bounds mode, deferred bounds-check facts.
Synchronous host calls Done: host imports can return results, including v128.
Plugins Done: open-source provenance, manifest-granted host capabilities, deterministic dependency/load ordering, transactional registration, host imports, hooks, and CLI inspection.
Policy Partial: capability allow/deny plus memory/table limits are enforced; invoke duration is reserved.
Instance pools Plugin-owned: pooling policy and idle-instance retention are intentionally absent from core.
Actor/process layer Plugin-owned: core provides only capability-gated managed instances; workers, PIDs, guest mailboxes, signals, monitoring, and supervision live outside the runtime.
.wago blobs Go API serialization/loading works; CLI build/cache productization is planned.
Version management Local list/use/current/which/uninstall path is present; network install is build-dependent.
TinyGo Supported on linux/amd64 with -scheduler=tasks; release builds are size-focused.

Plugin examples

Plugin Capability Imports
timer timer.read Wall-clock ms, monotonic ns, sleep ms.
log none Structured guest logging through wago_log.write.
metrics metrics.write Counters and histograms.
github.com/wago-org/workers instance.manage Optional neutral worker plugin; no guest ABI.

Current limits

  • Platform support is linux/amd64.
  • The CPU baseline for SIMD is SSSE3/SSE4.1 plus AVX/VEX.128. AVX2/FMA/VNNI are future feature-gated fast paths, not baseline requirements.
  • Wago is JIT-only. There is no interpreter tier.
  • Unsupported or disabled wasm features are rejected at compile time rather than accepted and mis-run.

Performance

Wago is tuned for fast cold compilation, low host-call overhead, and small operational footprint. It is not an optimizing tier; the backend is a direct single-pass compiler based on WARP's Valent-Block design.

Runtime comparison

The local benchmark suite compares Wago with wazero and WARP over synthetic micro modules, compute kernels, AssemblyScript libraries, and large real-world modules.

Latest checked-in benchmark dump: bench/out/bench.json, nightly-96-g6e73d12 (2026-07-05T00:25:47-07:00), AMD Ryzen 7 7800X3D, linux/amd64.

Benchmark wago wazero Delta
Compile tiny 3.2 us 62 us 20x faster
Compile fib_rec 4.7 us 65 us 14x faster
Compile memory_tree 13 us 112 us 8.6x faster
Compile json-as 1.08 ms 5.85 ms 5.4x faster
Exec tiny.add 16.8 ns 28.3 ns 1.7x faster
Exec fib_iter.fib 28.1 ns 34.4 ns 1.2x faster
Exec fib_rec.fib 1.48 ms 2.18 ms 1.5x faster
Exec memory_tree.run 9.6 us 22 us 2.3x faster
Exec json-as.serializeN 21 us 32 us 1.5x faster
Exec json-as.deserializeN 39 us 64 us 1.6x faster
SQLite query 514 us 984 us 1.9x faster

Focused json-as SWAR microbenchmarks from the same dump:

Benchmark wago wazero Delta
JSON.stringify path 119.8 ns 159.3 ns 1.3x faster
JSON.parse path 219.6 ns 317.7 ns 1.4x faster

Conformance and project stats synced into the sibling website dump (../website/data/stats.json locally) on 2026-07-06: 57/57 MVP files pass, 16,592 assertions pass, 0 fail, 0 lines of cgo, and 79% generated test coverage.

Startup latency

The startup study in docs/startup-latency-2026-07.md measures full process startup on a real json-as wasm workload:

Runtime Type Total Startup noop Approx exec
wasm3 0.5.2 interpreter 5.0 ms 1.2 ms 3.8 ms
wago dev @ 0df7ea2 single-pass JIT 5.4 ms 5.0 ms 0.4 ms
wasmtime 45.0.1 Cranelift JIT 8.0 ms 7.3 ms 0.7 ms
wazero 1.12.0 compiler 10.8 ms 8.8 ms 2.0 ms
wasmer 7.1.0 cranelift optimizing JIT 21.3 ms 21.1 ms ~0.2 ms
wavm LLVM 21.1.8 LLVM JIT 263 ms 265 ms ~0

That snapshot was taken on an AMD Ryzen 7 7800X3D linux/amd64 machine with compilation caches disabled for cold rows. Treat it as a point-in-time engineering measurement, not a universal claim.

Binary size

From docs/tinygo.md, linux/amd64 CLI size snapshots:

Build Size
go build default 3.1 MB
go build -ldflags="-s -w" 2.1 MB
tinygo build -no-debug -opt=z -gc=conservative + strip -s 0.43 MB
Above plus UPX 0.16 MB

make build-release uses the TinyGo size path. Build with -scheduler=tasks when using TinyGo; see the TinyGo doc for the foreign-stack and GC rationale.

Performance tuning

Knob Meaning
WAGO_BOUNDS=signals Use guard-page bounds checks when the binary was built with -tags wago_guardpage.
WAGO_BOUNDS=explicit Force inline explicit bounds checks.
--bounds defer CLI default: skip provably redundant explicit checks in straight-line regions.
--bounds all CLI A/B mode: check every explicit memory access.
WAGO_NO_BOUNDS_FACTS=1 Disable deferred bounds-check facts globally.
RuntimeConfig.WithFeature Accept or reject individual wasm feature families.
RuntimeConfig.WithMemoryLimitPages Cap declared linear memory in 64 KiB wasm pages.
RuntimeConfig.WithFunctionWorkers Select serial (1), adaptive (0), or a forced worker maximum for function validation and codegen.
wago run -p[workers] Enable adaptive validation/compile parallelism (-p) or force a maximum (-p8, -p 8).
wago validate -p[workers] Apply the same worker policy to validation-only workflows.

Guard-page mode is faster on memory-heavy modules but installs process-wide signal handlers and must be selected deliberately in builds that include it.

Function workers

Function workers parallelize independent wasm function validation and native code generation while keeping module-level analysis serial and deterministic. The default is one worker. Use WithFunctionWorkers(0) or CLI -p for the measured adaptive policy; forced values are capped by GOMAXPROCS and the local function count. Adaptive mode keeps small modules serial and uses at most four workers for larger modules.

Parallelism trades bounded transient memory and CPU for lower one-module startup latency. It is best suited to CLI/build-style workloads; memory-constrained or highly concurrent services should retain the serial default unless benchmarks justify otherwise. See docs/function-workers.md for policy, determinism, CLI forms, and measurements.

Running benchmarks locally

The benchmark suite is a separate Go module under bench/.

cd bench
go test -bench . -benchmem
go test -bench '^BenchmarkCompile$' -benchmem
go test -bench 'Decode|Exec' -benchmem

Include the generated ISA micro-suite only when you want opcode-level coverage:

go test -bench . -benchmem -wago.bench.isa
go run ./cmd/benchpub -isa -out out

Run the guard-page path:

WAGO_BOUNDS=signals go test -tags wago_guardpage \
  -bench '^BenchmarkExec/memory_tree\.run$' -benchmem

Generate charts and benchmark history:

go run ./chart
go run ./cmd/benchpub -out out

Compare against WARP:

make bench-warp
make bench WARP=auto

The corpus includes hand-written .wat micro modules, Rust kernels, AssemblyScript libraries such as json-as, blake-as, and utf-as, WASI programs, and large decode/validate inputs such as Lua, SQLite, Ruby, and esbuild. See bench/README.md for the full map.

Configuration

Wago's runtime config is immutable. Every WithXxx method returns a copy:

cfg := wago.NewRuntimeConfig().
	WithFeature(wago.CoreFeatureBulkMemoryOperations, false).
	WithMemoryLimitPages(256).
	WithFunctionWorkers(0) // adaptive validation + codegen

if wago.GuardPageSupported() {
	cfg = cfg.WithBoundsChecks(wago.BoundsChecksSignalsBased)
}

compiled, err := cfg.Compile(wasmBytes)

The default feature set is the complete WebAssembly 2.0 release feature group that the current backend lowers: mutable globals, sign-extension, multi-value, bulk memory/tables, non-trapping float-to-int, reference types, and core SIMD.

CoreFeaturesV2 is the static WebAssembly 2.0 release group, including core SIMD. SupportedFeatures() is the build- and host-admitted form of that group; on CPUs below the documented SIMD baseline it clears only CoreFeatureSIMD. Post-release proposals such as tail calls remain separate and disabled.

Use SupportedFeatures() for portable program setup:

features := wago.SupportedFeatures()
if !features.IsEnabled(wago.CoreFeatureSIMD) {
	// choose a non-SIMD module or reject early
}

Debugging

Useful commands:

wago --version
wago env
wago module imports app.wasm
wago module capabilities app.wasm
wago plugin inspect github.com/acme/wago-metrics --json

Developer and benchmark diagnostics:

Tool Use
WAGO_EXPLAIN=1 Emit compile/codegen explanation when built on the codegen-stats path.
bench/cmd/explain Inspect codegen counters and disassembly-oriented output.
make spec1 / make spec2 Run the separately pinned WebAssembly 1.0 baseline or official 2.0 core corpus through wast2json (see docs/spec-testing.md).
make test-guard Run guard-page focused tests.

Architecture

The execution pipeline is intentionally direct:

wasm bytes
  -> src/core/compiler/wasm
       strict binary decode, custom-section parsing, validation, feature gating
  -> src/core/compiler/backend/railshot
       single-pass x86-64 codegen over validated byte-backed bodies
  -> src/core/runtime
       W^X mmap, foreign-stack trampoline, traps, linear memory, linking

Important design choices:

  • No cgo. Native wasm code is entered through a Go/TinyGo-compatible trampoline, not a C boundary.
  • JIT-only. There is no interpreter fallback. Unsupported features are rejected.
  • Strict decoding. Malformed structured custom sections, including malformed name sections, are decode errors.
  • Byte-backed frontend. Production compile does not materialize full instruction ASTs for function bodies.
  • Single-pass backend. Railshot uses a symbolic operand stack, pinned locals and globals, deterministic join slots, and shared cold trap stubs.
  • Zero-copy memory. Host and guest see the same mmap-backed linear memory.
  • Auditable boundaries. Unsafe, mmap, stack switching, traps, and host calls are kept in narrow runtime files and covered by focused tests.

For the full internal tour, see ARCHITECTURE.md and docs/runtime-abi.md.

Project layout

.
  wago.go                              public facade over src/wago
  cli/wago/                            CLI: run, validate, plugins, modules, versions
  src/wago/                            public runtime API implementation
  src/core/compiler/wasm/              decoder, validator, feature support
  src/core/compiler/backend/railshot/  single-pass linux/amd64 JIT backend
  src/core/runtime/                    no-cgo execution runtime
  plugins/                             optional extensions live in separate modules
  examples/                            runnable API examples
  tests/testdata/                      small wasm fixtures
  tests/spec/                          WebAssembly spec submodule
  bench/                               benchmark corpus, charts, cross-engine comparisons
  docs/                                design notes, performance plans, workflow docs
  warp/                                reference C++ WARP tree

Development

Common checks:

make lint
make test
make test-guard
cd bench && go test ./...

Spec conformance:

make spec        # needs wabt's wast2json and tests/spec

Builds:

make build
make build-release
make tinygo-build
make tinygo-test

Coverage:

make cover

Current generated coverage summary in coverage-report.md: 79.2% overall, with the wasm test helpers at 100% and the public wago package above 83%.

Contributing

Please see CONTRIBUTING.md. The short version:

  • keep changes narrow and auditable;
  • add or update tests with behavior changes;
  • run the most relevant tests and say what you did not run;
  • include numbers for compiler, runtime, host-call, memory, or footprint claims;
  • update docs in docs/ when workflow, testing, benchmarking, review expectations, or agent behavior changes.

License

Wago is licensed under Apache-2.0.

The reference warp/ tree keeps its original license headers.

Contact

Open an issue or discussion in the project repository. For project updates and installer entry point, see https://wago.sh/.

Documentation

Overview

Package wago exposes compile, instantiate, and run helpers for WebAssembly modules. It is a generated facade over the implementation in src/wago, so callers import the stable path "github.com/wago-org/wago" while the code lives under src/wago alongside the rest of the engine.

Index

Constants

View Source
const (
	AllowTestOverrides                         = impl.AllowTestOverrides
	BoundsChecksExplicit                       = impl.BoundsChecksExplicit
	BoundsChecksSignalsBased                   = impl.BoundsChecksSignalsBased
	CapCompilerCodegen                         = impl.CapCompilerCodegen
	CapFilesystemRead                          = impl.CapFilesystemRead
	CapFilesystemWrite                         = impl.CapFilesystemWrite
	CapHTTPClient                              = impl.CapHTTPClient
	CapKVRead                                  = impl.CapKVRead
	CapKVWrite                                 = impl.CapKVWrite
	CapMetricsWrite                            = impl.CapMetricsWrite
	CapNetworkOutbound                         = impl.CapNetworkOutbound
	CapTimerRead                               = impl.CapTimerRead
	CoreFeatureBulkMemoryOperations            = impl.CoreFeatureBulkMemoryOperations
	CoreFeatureMultiValue                      = impl.CoreFeatureMultiValue
	CoreFeatureMutableGlobal                   = impl.CoreFeatureMutableGlobal
	CoreFeatureNonTrappingFloatToIntConversion = impl.CoreFeatureNonTrappingFloatToIntConversion
	CoreFeatureReferenceTypes                  = impl.CoreFeatureReferenceTypes
	CoreFeatureSIMD                            = impl.CoreFeatureSIMD
	CoreFeatureSignExtensionOps                = impl.CoreFeatureSignExtensionOps
	CoreFeatureTailCall                        = impl.CoreFeatureTailCall
	CoreFeaturesV1                             = impl.CoreFeaturesV1
	CoreFeaturesV2                             = impl.CoreFeaturesV2
	Deprecated                                 = impl.Deprecated
	ElemModeActive                             = impl.ElemModeActive
	ElemModeDeclarative                        = impl.ElemModeDeclarative
	ElemModePassive                            = impl.ElemModePassive
	ErrExtensionConflict                       = impl.ErrExtensionConflict
	ErrInvalidHandle                           = impl.ErrInvalidHandle
	ErrManagedImportLifetime                   = impl.ErrManagedImportLifetime
	ErrMissingImport                           = impl.ErrMissingImport
	ErrPermissionDenied                        = impl.ErrPermissionDenied
	Experimental                               = impl.Experimental
	GCAllocatorPagedSizeClass                  = impl.GCAllocatorPagedSizeClass
	GCAllocatorTinyFixedBlock                  = impl.GCAllocatorTinyFixedBlock
	GCProfileThroughput                        = impl.GCProfileThroughput
	GCProfileTiny                              = impl.GCProfileTiny
	GCRuntimeGenerational                      = impl.GCRuntimeGenerational
	GCRuntimeIncrementalMarkSweep              = impl.GCRuntimeIncrementalMarkSweep
	ImportFunc                                 = impl.ImportFunc
	ImportGlobal                               = impl.ImportGlobal
	ImportMemory                               = impl.ImportMemory
	ImportTable                                = impl.ImportTable
	InstantiateDirect                          = impl.InstantiateDirect
	InstantiateManaged                         = impl.InstantiateManaged
	NoExtensionOverrides                       = impl.NoExtensionOverrides
	PluginCompileHooks                         = impl.PluginCompileHooks
	PluginHostEnvironment                      = impl.PluginHostEnvironment
	PluginHostImports                          = impl.PluginHostImports
	PluginInstanceHooks                        = impl.PluginInstanceHooks
	PluginInvokeHooks                          = impl.PluginInvokeHooks
	PluginManagedInstances                     = impl.PluginManagedInstances
	PluginPhaseAuthorize                       = impl.PluginPhaseAuthorize
	PluginPhaseConfigure                       = impl.PluginPhaseConfigure
	PluginPhaseRegister                        = impl.PluginPhaseRegister
	PluginPhaseResolve                         = impl.PluginPhaseResolve
	PluginPhaseStart                           = impl.PluginPhaseStart
	PluginPhaseStop                            = impl.PluginPhaseStop
	PluginRuntimeHooks                         = impl.PluginRuntimeHooks
	SnapshotInit                               = impl.SnapshotInit
	SnapshotWarm                               = impl.SnapshotWarm
	Stable                                     = impl.Stable
	TrapBuiltin                                = impl.TrapBuiltin
	TrapCalledFnNotLinked                      = impl.TrapCalledFnNotLinked
	TrapDivOverflow                            = impl.TrapDivOverflow
	TrapDivZero                                = impl.TrapDivZero
	TrapIndirectOutOfBounds                    = impl.TrapIndirectOutOfBounds
	TrapIndirectWrongSig                       = impl.TrapIndirectWrongSig
	TrapInterrupted                            = impl.TrapInterrupted
	TrapLinMemCouldNotExtend                   = impl.TrapLinMemCouldNotExtend
	TrapLinMemOutOfBounds                      = impl.TrapLinMemOutOfBounds
	TrapLinkedMemNotLinked                     = impl.TrapLinkedMemNotLinked
	TrapLinkedMemOutOfBounds                   = impl.TrapLinkedMemOutOfBounds
	TrapNone                                   = impl.TrapNone
	TrapStackFenceBreached                     = impl.TrapStackFenceBreached
	TrapTruncOverflow                          = impl.TrapTruncOverflow
	TrapUnreachable                            = impl.TrapUnreachable
	ValExternRef                               = impl.ValExternRef
	ValF32                                     = impl.ValF32
	ValF64                                     = impl.ValF64
	ValFuncRef                                 = impl.ValFuncRef
	ValI32                                     = impl.ValI32
	ValI64                                     = impl.ValI64
	ValV128                                    = impl.ValV128
	Version                                    = impl.Version
)

Variables

This section is empty.

Functions

func AsF32

func AsF32(b uint64) float32

func AsF64

func AsF64(b uint64) float64

func AsI32

func AsI32(b uint64) int32

func AsI64

func AsI64(b uint64) int64

func F32

func F32(v float32) uint64

func F64

func F64(v float64) uint64

func GuardPageSupported

func GuardPageSupported() bool

func GuestArgs

func GuestArgs() []string

func I32

func I32(v int32) uint64

func I64

func I64(v int64) uint64

func IsCompiled

func IsCompiled(b []byte) bool

func IsGuardPageUnavailable

func IsGuardPageUnavailable(err error) bool

func IsSnapshot

func IsSnapshot(b []byte) bool

func ProvideService

func ProvideService(reg *Registry, name string, value any) error

func RegisterExtension

func RegisterExtension(name string, factory ExtensionFactory)

func RegisteredPluginNames

func RegisteredPluginNames() []string

func SetGuestArgs

func SetGuestArgs(args []string)

func SetOptKnob

func SetOptKnob(name string, on bool) bool

Types

type BoundsCheckMode

type BoundsCheckMode = impl.BoundsCheckMode

type CallerResolver

type CallerResolver = impl.CallerResolver

type Capability

type Capability = impl.Capability

type CapabilityBudget

type CapabilityBudget = impl.CapabilityBudget

type CapabilityOption

type CapabilityOption = impl.CapabilityOption

func CapabilityDocs

func CapabilityDocs(docs string) CapabilityOption

type Compatibility

type Compatibility = impl.Compatibility

type CompileContext

type CompileContext = impl.CompileContext

type CompileHookAccess

type CompileHookAccess = impl.CompileHookAccess

type Compiled

type Compiled = impl.Compiled

func Compile

func Compile(args ...any) (*Compiled, error)

func CompileWithConfig

func CompileWithConfig(cfg *RuntimeConfig, wasmBytes []byte) (*Compiled, error)

func Load

func Load(b []byte) (*Compiled, error)

func MustCompile

func MustCompile(wasmBytes []byte) *Compiled

type ConfigSchemaProvider

type ConfigSchemaProvider = impl.ConfigSchemaProvider

type CoreFeatures

type CoreFeatures = impl.CoreFeatures

func SupportedFeatures

func SupportedFeatures() CoreFeatures

type DataInit

type DataInit = impl.DataInit

type Dirs

type Dirs = impl.Dirs

func DirsFor

func DirsFor(version string) Dirs

type ElemInit

type ElemInit = impl.ElemInit

type ElemMode

type ElemMode = impl.ElemMode

type ExitError

type ExitError = impl.ExitError

type Extension

type Extension = impl.Extension

func NewExtension

func NewExtension(name string) (Extension, bool)

type ExtensionError

type ExtensionError = impl.ExtensionError

type ExtensionFactory

type ExtensionFactory = impl.ExtensionFactory

type ExtensionInfo

type ExtensionInfo = impl.ExtensionInfo

type ExternRef

type ExternRef = impl.ExternRef

func NullExternRef

func NullExternRef() ExternRef

type ExternRefHostModule

type ExternRefHostModule = impl.ExternRefHostModule

type FuncRef

type FuncRef = impl.FuncRef

func NullFuncRef

func NullFuncRef() FuncRef

type FuncSig

type FuncSig = impl.FuncSig

type FunctionMetadata

type FunctionMetadata = impl.FunctionMetadata

type GCAllocatorKind

type GCAllocatorKind = impl.GCAllocatorKind

type GCConfig

type GCConfig = impl.GCConfig

type GCProfile

type GCProfile = impl.GCProfile

type GCRuntimeKind

type GCRuntimeKind = impl.GCRuntimeKind

type Global

type Global = impl.Global

func NewGlobalF32

func NewGlobalF32(v float32, mutable bool) *Global

func NewGlobalF64

func NewGlobalF64(v float64, mutable bool) *Global

func NewGlobalI32

func NewGlobalI32(v int32, mutable bool) *Global

func NewGlobalI64

func NewGlobalI64(v int64, mutable bool) *Global

func NewGlobalV128

func NewGlobalV128(v V128, mutable bool) *Global

type GlobalDef

type GlobalDef = impl.GlobalDef

type GlobalImport

type GlobalImport = impl.GlobalImport

type GlobalImportDef

type GlobalImportDef = impl.GlobalImportDef

type GlobalMetadata

type GlobalMetadata = impl.GlobalMetadata

type GuardPageUnavailableError

type GuardPageUnavailableError = impl.GuardPageUnavailableError

type Handle

type Handle = impl.Handle

type HandleTable

type HandleTable = impl.HandleTable

func NewHandleTable

func NewHandleTable() *HandleTable

type HookRegistry

type HookRegistry = impl.HookRegistry

type HostEnvironment

type HostEnvironment = impl.HostEnvironment

type HostExit

type HostExit = impl.HostExit

type HostFunc

type HostFunc = impl.HostFunc

type HostFuncRef

type HostFuncRef = impl.HostFuncRef

type HostImportAccess

type HostImportAccess = impl.HostImportAccess

type HostModule

type HostModule = impl.HostModule

type ImportFuncBuilder

type ImportFuncBuilder = impl.ImportFuncBuilder

type ImportKind

type ImportKind = impl.ImportKind

type ImportModuleBuilder

type ImportModuleBuilder = impl.ImportModuleBuilder

type ImportOverridePolicy

type ImportOverridePolicy = impl.ImportOverridePolicy

type ImportSpec

type ImportSpec = impl.ImportSpec

type Imports

type Imports = impl.Imports

type Instance

type Instance = impl.Instance

func Instantiate

func Instantiate(source Instantiable, opts ...any) (*Instance, error)

type InstanceContext

type InstanceContext = impl.InstanceContext

type InstanceExport

type InstanceExport = impl.InstanceExport

type InstanceHookAccess

type InstanceHookAccess = impl.InstanceHookAccess

type InstanceManager

type InstanceManager = impl.InstanceManager

type Instantiable

type Instantiable = impl.Instantiable

type InstantiateContext

type InstantiateContext = impl.InstantiateContext

type InstantiateOption

type InstantiateOption = impl.InstantiateOption

func WithGC

func WithGC(gc GCConfig) InstantiateOption

func WithImports

func WithImports(im Imports) InstantiateOption

func WithPolicy

func WithPolicy(p Policy) InstantiateOption

type InstantiateOptions

type InstantiateOptions = impl.InstantiateOptions

type InstantiateOrigin

type InstantiateOrigin = impl.InstantiateOrigin

type InvokeContext

type InvokeContext = impl.InvokeContext

type InvokeHookAccess

type InvokeHookAccess = impl.InvokeHookAccess

type ManagedInstance

type ManagedInstance = impl.ManagedInstance

type Memory

type Memory = impl.Memory

func NewMemory

func NewMemory(minPages uint32, maxPages uint32) (*Memory, error)

func NewSharedMemory

func NewSharedMemory(minPages uint32, maxPages uint32) (*Memory, error)

type Module

type Module = impl.Module

type ModuleMetadata

type ModuleMetadata = impl.ModuleMetadata

type OffsetInit

type OffsetInit = impl.OffsetInit

type OptKnobInfo

type OptKnobInfo = impl.OptKnobInfo

func OptKnobs

func OptKnobs() []OptKnobInfo

type PassiveDataInit

type PassiveDataInit = impl.PassiveDataInit

type PluginCapability

type PluginCapability = impl.PluginCapability

type PluginConfig

type PluginConfig = impl.PluginConfig

type PluginError

type PluginError = impl.PluginError

type PluginHost

type PluginHost = impl.PluginHost

type PluginPhase

type PluginPhase = impl.PluginPhase

type PluginPlan

type PluginPlan = impl.PluginPlan

func InspectPluginPlan

func InspectPluginPlan(configs []PluginConfig) (*PluginPlan, error)

type PluginPlanEntry

type PluginPlanEntry = impl.PluginPlanEntry

type PluginStarter

type PluginStarter = impl.PluginStarter

type PluginStopper

type PluginStopper = impl.PluginStopper

type Policy

type Policy = impl.Policy

type PreparedFunction

type PreparedFunction = impl.PreparedFunction

type RefInit

type RefInit = impl.RefInit

type Registry

type Registry = impl.Registry

type Resource

type Resource = impl.Resource

type Runtime

type Runtime = impl.Runtime

func NewRuntime

func NewRuntime(opts ...RuntimeOption) *Runtime

type RuntimeConfig

type RuntimeConfig = impl.RuntimeConfig

func NewRuntimeConfig

func NewRuntimeConfig() *RuntimeConfig

type RuntimeContext

type RuntimeContext = impl.RuntimeContext

type RuntimeHookAccess

type RuntimeHookAccess = impl.RuntimeHookAccess

type RuntimeOption

type RuntimeOption = impl.RuntimeOption

func WithImportOverridePolicy

func WithImportOverridePolicy(p ImportOverridePolicy) RuntimeOption

func WithRuntimeConfig

func WithRuntimeConfig(cfg *RuntimeConfig) RuntimeOption

type ServiceRef

type ServiceRef = impl.ServiceRef

func RequireService

func RequireService(reg *Registry, name string) (*ServiceRef, error)

type Snapshot

type Snapshot = impl.Snapshot

func Capture

func Capture(c *Compiled, opts SnapshotOptions) (*Snapshot, error)

func LoadSnapshot

func LoadSnapshot(b []byte) (*Snapshot, error)

func ReadSnapshotFile

func ReadSnapshotFile(path string) (*Snapshot, error)

type SnapshotKind

type SnapshotKind = impl.SnapshotKind

type SnapshotOptions

type SnapshotOptions = impl.SnapshotOptions

type Stability

type Stability = impl.Stability

type Table

type Table = impl.Table

func NewTable

func NewTable(minSize uint32, maxSize uint32) (*Table, error)

type TableMetadata

type TableMetadata = impl.TableMetadata

type TrapCode

type TrapCode = impl.TrapCode

type TrapError

type TrapError = impl.TrapError

type UnsupportedFeatureError

type UnsupportedFeatureError = impl.UnsupportedFeatureError

type UseOption

type UseOption = impl.UseOption

func WithPluginGrants

func WithPluginGrants(caps ...PluginCapability) UseOption

type V128

type V128 = impl.V128

type ValType

type ValType = impl.ValType

type Value

type Value = impl.Value

func ValueExternRef

func ValueExternRef(v ExternRef) Value

func ValueF32

func ValueF32(v float32) Value

func ValueF64

func ValueF64(v float64) Value

func ValueFuncRef

func ValueFuncRef(v FuncRef) Value

func ValueI32

func ValueI32(v int32) Value

func ValueI64

func ValueI64(v int64) Value

func ValueOf

func ValueOf(t ValType, bits uint64) Value

Directories

Path Synopsis
cli
wago command
Command wago runs WebAssembly modules.
Command wago runs WebAssembly modules.
wagocli
Package wagocli is the wago command implementation.
Package wagocli is the wago command implementation.
examples
01-hello command
Example 01: hello — the lowest-level API.
Example 01: hello — the lowest-level API.
02-runtime-typed command
Example 02: runtime + typed Call.
Example 02: runtime + typed Call.
03-host-import command
Example 03: host imports.
Example 03: host imports.
04-memory command
Example 04: reading guest memory from a host function.
Example 04: reading guest memory from a host function.
05-globals command
Example 05: exported globals.
Example 05: exported globals.
08-custom-plugin command
Example 08: writing your own plugin.
Example 08: writing your own plugin.
10-hooks command
Example 10: lifecycle hooks (observability).
Example 10: lifecycle hooks (observability).
14-handles command
Example 14: resource handles.
Example 14: resource handles.
15-config command
Example 15: runtime configuration.
Example 15: runtime configuration.
16-serialize command
Example 16: precompiling to a .wago blob.
Example 16: precompiling to a .wago blob.
internal/mods
Package mods builds the tiny WebAssembly modules the examples run against.
Package mods builds the tiny WebAssembly modules the examples run against.
internal
functionworkers
Package functionworkers resolves Wago's bounded per-module function worker policy for validation and native code generation.
Package functionworkers resolves Wago's bounded per-module function worker policy for validation and native code generation.
genfacade command
Command genfacade regenerates the root re-export facade (wago.go) from the exported identifiers of ./src/wago.
Command genfacade regenerates the root re-export facade (wago.go) from the exported identifiers of ./src/wago.
spectest
Package spectest contains shared discovery helpers for the external WebAssembly specification corpora used by compiler and runtime tests.
Package spectest contains shared discovery helpers for the external WebAssembly specification corpora used by compiler and runtime tests.
Package plugin provides typed helpers for composing Wago plugins.
Package plugin provides typed helpers for composing Wago plugins.
src
core/compiler/backend/railshot
Package railshot is the architecture-NEUTRAL core of the railshot single-pass wasm backend.
Package railshot is the architecture-NEUTRAL core of the railshot single-pass wasm backend.
core/compiler/backend/railshot/amd64
Package railshot is wago's single-pass x86-64 code generator — the "railshot" compiler tier (it lives under backend/railshot; a future optimizing tier will sit alongside it).
Package railshot is wago's single-pass x86-64 code generator — the "railshot" compiler tier (it lives under backend/railshot; a future optimizing tier will sit alongside it).
core/compiler/backend/railshot/arm64
Package arm64 holds the AArch64-specific half of the railshot single-pass backend — the twin of railshot/amd64.
Package arm64 holds the AArch64-specific half of the railshot single-pass backend — the twin of railshot/amd64.
core/compiler/backend/railshot/shared
Package shared contains small, architecture-neutral building blocks used by Railshot backends.
Package shared contains small, architecture-neutral building blocks used by Railshot backends.
core/compiler/codegen
Package codegen defines backend-neutral compiler contracts shared by wasm and IR lowering paths.
Package codegen defines backend-neutral compiler contracts shared by wasm and IR lowering paths.
core/compiler/frontend
Package frontend contains compiler front-end passes shared by the CLI and API.
Package frontend contains compiler front-end passes shared by the CLI and API.
core/compiler/wasm
Package wasm contains a structured WebAssembly binary decoder and validator for post-MVP proposals including reference types, exception handling tags, typed function references, GC, stringrefs, SIMD, atomics, bulk memory, and memory64 encodings.
Package wasm contains a structured WebAssembly binary decoder and validator for post-MVP proposals including reference types, exception handling tags, typed function references, GC, stringrefs, SIMD, atomics, bulk memory, and memory64 encodings.
core/encoder/amd64
Package amd64 is the x86-64 instruction encoder (the Asm type) that the code generator in backend/railshot drives to emit machine code.
Package amd64 is the x86-64 instruction encoder (the Asm type) that the code generator in backend/railshot drives to emit machine code.
core/encoder/arm64
Package arm64 is wago's AArch64 (arm64) instruction encoder — the arm64 twin of src/core/encoder/amd64.
Package arm64 is wago's AArch64 (arm64) instruction encoder — the arm64 twin of src/core/encoder/amd64.
core/runtime/abi
Package abi exposes runtime layout constants shared by native-code emitters and the runtime implementation.
Package abi exposes runtime layout constants shared by native-code emitters and the runtime implementation.
core/semver
Package semver implements Semantic Versioning 2.0.0 (https://semver.org): version parsing, precedence comparison (including pre-release and build metadata rules), and npm-style range constraints (comparators, ^, ~, x-ranges, hyphen ranges, AND, and || OR).
Package semver implements Semantic Versioning 2.0.0 (https://semver.org): version parsing, precedence comparison (including pre-release and build metadata rules), and npm-style range constraints (comparators, ^, ~, x-ranges, hyphen ranges, AND, and || OR).
wago
Package wago compiles and runs WebAssembly modules with a pure-Go, no-cgo single-pass JIT.
Package wago compiles and runs WebAssembly modules with a pure-Go, no-cgo single-pass JIT.
testutil

Jump to

Keyboard shortcuts

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