Documentation
¶
Overview ¶
Package engine provides the low-level WebAssembly Component Model runtime.
This package wraps wazero to provide Component Model semantics, including canonical ABI type lifting/lowering, asyncify support for async operations, and WASI preview1-to-preview2 adaptation.
Architecture ¶
The engine package provides three main types:
WazeroEngine - Creates and manages wazero runtime instances WazeroModule - Represents a compiled component, can create instances WazeroInstance - A running component instance with exports
Component Instantiation Flow ¶
- WazeroEngine.LoadModule() parses and validates the component binary
- WazeroModule holds the validated component and linker configuration
- WazeroModule.Instantiate() creates a WazeroInstance via the linker
- WazeroInstance provides Call methods for invoking exports
Canonical ABI ¶
The canonical ABI defines how WIT types map to WASM core types:
WIT Type Core Representation Flat Count ───────────────────────────────────────────────── bool, u8-u32 i32 1 u64, s64 i64 1 f32 f32 1 f64 f64 1 string (ptr, len) as i32×2 2 list<T> (ptr, len) as i32×2 2 record flattened fields sum of fields variant (disc, payload) 1 + max(cases) option<T> variant with none/some varies result<T,E> variant with ok/err varies
When flat count exceeds MaxFlatParams (16) or MaxFlatResults (1), values are passed via linear memory using a return pointer (retptr).
Asyncify Support ¶
Asyncify enables cooperative multitasking in WASM. Modules compiled with wasm-opt --asyncify can suspend execution (unwind) and resume later (rewind).
Usage:
if err := inst.EnableAsyncify(config); err != nil {
log.Fatal(err)
}
// In host function that needs to block:
asyncify := inst.Asyncify()
if asyncify.State() == StateNormal {
asyncify.StartUnwind(ctx) // Save stack, return to caller
return // Guest sees function return
}
// On rewind, execution continues here
asyncify.StopRewind(ctx)
// Perform actual work, return result
WASI Adaptation ¶
The engine provides automatic WASI preview1-to-preview2 adaptation for components that import preview1 interfaces. This allows legacy modules to run with modern WASI preview2 host implementations.
Resource Table ¶
Resources (handles) are managed via ResourceTable, which maps integer handles to Go values. The table supports borrow semantics for the Component Model's resource lifecycle.
Thread Safety ¶
WazeroEngine and WazeroModule are safe for concurrent use. WazeroInstance is NOT thread-safe and should be used by a single goroutine.
Experimental Features ¶
Threads/Atomics: Enable via EngineConfig.EnableThreads. This enables the WebAssembly threads proposal (shared memory, atomic operations). Note that atomic operations are guest-only and not exposed to host functions.
Known Limitations ¶
Memory64: The WebAssembly Memory64 proposal (64-bit memory addressing) is not supported. This limitation comes from the underlying wazero runtime (v1.10.1) which does not implement Memory64. Implementation would require:
- wazero upstream Memory64 support
- Updates to memory access code for uint64 addresses
- Canonical ABI changes (pointer types become i64)
Most users should use the runtime package for a simpler API. This package is for advanced use cases requiring direct control.
Index ¶
- Constants
- Variables
- func InstantiateWASIWithAdapter(ctx context.Context, r wazero.Runtime) (api.Module, error)
- func Logger() *zap.Logger
- func MakeAsyncHandler(createOp func(ctx context.Context, mod api.Module, stack []uint64) PendingOp) api.GoModuleFunc
- func Resume(ctx context.Context) (uint64, error)
- func Suspend(ctx context.Context, op PendingOp) error
- func WithAsyncify(ctx context.Context, a *Asyncify) context.Context
- func WithScheduler(ctx context.Context, s *Scheduler) context.Context
- type Asyncify
- func (a *Asyncify) GetState(_ context.Context) int32
- func (a *Asyncify) Init(mod api.Module) error
- func (a *Asyncify) IsNormal(_ context.Context) bool
- func (a *Asyncify) IsRewinding(_ context.Context) bool
- func (a *Asyncify) IsUnwinding(_ context.Context) bool
- func (a *Asyncify) ResetStack()
- func (a *Asyncify) SetDataAddr(addr uint32)
- func (a *Asyncify) SetStackSize(size uint32)
- func (a *Asyncify) StartRewind(ctx context.Context) error
- func (a *Asyncify) StartUnwind(ctx context.Context) error
- func (a *Asyncify) StopRewind(ctx context.Context) error
- func (a *Asyncify) StopUnwind(ctx context.Context) error
- func (a *Asyncify) SyncState(ctx context.Context) int32
- type AsyncifyConfig
- type CallSession
- type CommandID
- type CompileConfig
- type Config
- type ErrorKind
- type HostFunc
- type InstanceConfig
- type LowerWrapper
- func (w *LowerWrapper) BuildRawFunc() api.GoModuleFunc
- func (w *LowerWrapper) FlatParamTypes() []api.ValueType
- func (w *LowerWrapper) FlatResultTypes() []api.ValueType
- func (w *LowerWrapper) FlatSignature() (paramCount, resultCount int)
- func (w *LowerWrapper) Name() string
- func (w *LowerWrapper) ValidateHandler() error
- type PendingOp
- type Scheduler
- func (s *Scheduler) ClearPending()
- func (s *Scheduler) Execute(ctx context.Context, fn api.Function, args ...uint64) error
- func (s *Scheduler) GetResult() (uint64, error)
- func (s *Scheduler) Reset()
- func (s *Scheduler) Run(ctx context.Context, fn api.Function, args ...uint64) ([]uint64, error)
- func (s *Scheduler) SetPending(op PendingOp)
- func (s *Scheduler) Step(ctx context.Context, yr *YieldResult) (StepResult, error)
- type StepResult
- type StepStatus
- type WazeroEngine
- type WazeroInstance
- func (i *WazeroInstance) Asyncify() *Asyncify
- func (i *WazeroInstance) CallInto(ctx context.Context, funcName string, paramTypes []wit.Type, ...) error
- func (i *WazeroInstance) CallWithLift(ctx context.Context, funcName string, params ...any) (any, error)
- func (i *WazeroInstance) CallWithTypes(ctx context.Context, funcName string, paramTypes []wit.Type, ...) (any, error)
- func (i *WazeroInstance) Close(ctx context.Context) error
- func (i *WazeroInstance) EnableAsyncify(config AsyncifyConfig) error
- func (i *WazeroInstance) GetExportedFunction(name string) api.Function
- func (i *WazeroInstance) MemorySize() uint32
- func (i *WazeroInstance) RunAsync(ctx context.Context, name string, args ...uint64) ([]uint64, error)
- func (i *WazeroInstance) Scheduler() *Scheduler
- func (i *WazeroInstance) StartCall(ctx context.Context, funcName string, params ...any) (*CallSession, error)
- type WazeroMemory
- func (m *WazeroMemory) Read(offset uint32, length uint32) ([]byte, error)
- func (m *WazeroMemory) ReadU8(offset uint32) (uint8, error)
- func (m *WazeroMemory) ReadU16(offset uint32) (uint16, error)
- func (m *WazeroMemory) ReadU32(offset uint32) (uint32, error)
- func (m *WazeroMemory) ReadU64(offset uint32) (uint64, error)
- func (m *WazeroMemory) Size() uint32
- func (m *WazeroMemory) Write(offset uint32, data []byte) error
- func (m *WazeroMemory) WriteU8(offset uint32, value uint8) error
- func (m *WazeroMemory) WriteU16(offset uint32, value uint16) error
- func (m *WazeroMemory) WriteU32(offset uint32, value uint32) error
- func (m *WazeroMemory) WriteU64(offset uint32, value uint64) error
- type WazeroModule
- func (m *WazeroModule) AsyncifyImports() []string
- func (m *WazeroModule) Compile(ctx context.Context, cfg *CompileConfig) error
- func (m *WazeroModule) ExportNames() []string
- func (m *WazeroModule) FindLift(name string) *component.LiftDef
- func (m *WazeroModule) Instantiate(ctx context.Context) (*WazeroInstance, error)
- func (m *WazeroModule) InstantiateWithConfig(ctx context.Context, cfg *InstanceConfig) (*WazeroInstance, error)
- func (m *WazeroModule) RegisterHostFuncTyped(namespace, name string, handler any) error
- func (m *WazeroModule) RegisterHostFuncTypedAsync(namespace, name string, handler any) error
- type YieldResult
Constants ¶
const ( MaxFlatResults = transcoder.MaxFlatResults CabiRealloc = "cabi_realloc" CabiFree = "cabi_free" )
const AsyncifyDataAddr uint32 = 16
const AsyncifyDefaultStackSize uint32 = 1024
Variables ¶
var IsAsyncified = asyncify.IsAsyncified
IsAsyncified checks if a WASM module has been asyncified.
Functions ¶
func InstantiateWASIWithAdapter ¶
InstantiateWASIWithAdapter instantiates WASI preview1 with adapter functions required by componentize-py and similar tools that use the component model adapter.
func MakeAsyncHandler ¶
func MakeAsyncHandler(createOp func(ctx context.Context, mod api.Module, stack []uint64) PendingOp) api.GoModuleFunc
MakeAsyncHandler wraps an operation factory into a suspend/resume-aware handler.
Types ¶
type Asyncify ¶
type Asyncify struct {
// contains filtered or unexported fields
}
Asyncify implements the Binaryen asyncify protocol (wasm-opt --asyncify).
States: 0=Normal, 1=Unwinding (saving stack), 2=Rewinding (restoring stack)
Memory layout at dataAddr:
- [0:4] stack pointer (grows upward from dataAddr+8)
- [4:8] stack end
- [8:stackSize] stack data
func GetAsyncify ¶
func NewAsyncify ¶
func NewAsyncify() *Asyncify
func (*Asyncify) ResetStack ¶
func (a *Asyncify) ResetStack()
ResetStack resets the stack pointer. Call before each new async operation.
func (*Asyncify) SetDataAddr ¶
func (*Asyncify) SetStackSize ¶
type AsyncifyConfig ¶
type CallSession ¶
type CallSession struct {
// contains filtered or unexported fields
}
CallSession represents an in-progress async function call. Use StartCall to create, Step to advance, and LiftResult to extract results.
func (*CallSession) LiftResult ¶
LiftResult converts raw wasm results to typed Go values after StepDone.
func (*CallSession) Step ¶
func (cs *CallSession) Step(ctx context.Context, yr *YieldResult) (StepResult, error)
Step advances execution. Pass nil for the first call, or a YieldResult to resume.
type CompileConfig ¶
type CompileConfig struct {
// EnableAsyncify enables automatic asyncify transformation for components.
EnableAsyncify bool
}
CompileConfig holds configuration for pre-compilation
type Config ¶
type Config struct {
// MemoryLimitPages sets the maximum memory per instance in pages (64KB each).
// 0 means default (65536 pages = 4GB).
// 256 = 16MB, 1024 = 64MB, 4096 = 256MB
MemoryLimitPages uint32
// EnableThreads enables the WebAssembly threads proposal (experimental).
// This allows atomic operations and shared memory within WASM modules.
// Note: Thread operations are guest-only and not exposed to host functions.
EnableThreads bool
}
Config holds configuration for engine creation
type ErrorKind ¶
type ErrorKind string
ErrorKind categorizes errors for integration with external error handling.
func ClassifyError ¶
type InstanceConfig ¶
InstanceConfig holds configuration for module instantiation
type LowerWrapper ¶
type LowerWrapper struct {
// contains filtered or unexported fields
}
LowerWrapper wraps a Go function for Canonical ABI lowering.
func NewLowerWrapper ¶
func NewLowerWrapper(def *component.LowerDef, handler any) (*LowerWrapper, error)
func (*LowerWrapper) BuildRawFunc ¶
func (w *LowerWrapper) BuildRawFunc() api.GoModuleFunc
func (*LowerWrapper) FlatParamTypes ¶
func (w *LowerWrapper) FlatParamTypes() []api.ValueType
func (*LowerWrapper) FlatResultTypes ¶
func (w *LowerWrapper) FlatResultTypes() []api.ValueType
func (*LowerWrapper) FlatSignature ¶
func (w *LowerWrapper) FlatSignature() (paramCount, resultCount int)
func (*LowerWrapper) Name ¶
func (w *LowerWrapper) Name() string
func (*LowerWrapper) ValidateHandler ¶
func (w *LowerWrapper) ValidateHandler() error
ValidateHandler checks if the Go handler matches the WIT signature. Returns nil if Params is nil (unknown types from failed component parsing).
type Scheduler ¶
type Scheduler struct {
// contains filtered or unexported fields
}
Scheduler manages async execution with step-based control for integration with external event loops.
func GetScheduler ¶
func NewScheduler ¶
func (*Scheduler) ClearPending ¶
func (s *Scheduler) ClearPending()
func (*Scheduler) Run ¶
Run executes with internal event loop. Convenience wrapper over Execute/Step.
func (*Scheduler) SetPending ¶
func (*Scheduler) Step ¶
func (s *Scheduler) Step(ctx context.Context, yr *YieldResult) (StepResult, error)
Step advances execution. Pass nil for first call, or YieldResult to resume.
type StepResult ¶
type StepResult struct {
PendingOp PendingOp
Error error
ErrorKind ErrorKind
Results []uint64
Status StepStatus
}
type StepStatus ¶
type StepStatus int
const ( StepContinue StepStatus = iota // yielded an operation, expects resume StepIdle // waiting for external message StepDone // execution complete )
type WazeroEngine ¶
type WazeroEngine struct {
// contains filtered or unexported fields
}
WazeroEngine implements Engine using wazero runtime
func NewWazeroEngine ¶
func NewWazeroEngine(ctx context.Context) (*WazeroEngine, error)
NewWazeroEngine creates a new wazero-based engine
func NewWazeroEngineWithConfig ¶
func NewWazeroEngineWithConfig(ctx context.Context, cfg *Config) (*WazeroEngine, error)
NewWazeroEngineWithConfig creates a new engine with custom configuration
func (*WazeroEngine) InitWASI ¶
func (e *WazeroEngine) InitWASI(ctx context.Context) error
InitWASI instantiates the WASI singleton for this engine's runtime. Safe for concurrent calls from multiple modules sharing the same engine.
func (*WazeroEngine) LoadModule ¶
func (e *WazeroEngine) LoadModule(ctx context.Context, wasmBytes []byte) (*WazeroModule, error)
type WazeroInstance ¶
type WazeroInstance struct {
// contains filtered or unexported fields
}
WazeroInstance is a running WASM instance. It is NOT safe for concurrent use from multiple goroutines. Each goroutine should have its own Instance, or access must be synchronized externally.
func (*WazeroInstance) Asyncify ¶
func (i *WazeroInstance) Asyncify() *Asyncify
Asyncify returns the asyncify runtime if enabled.
func (*WazeroInstance) CallInto ¶
func (i *WazeroInstance) CallInto(ctx context.Context, funcName string, paramTypes []wit.Type, resultTypes []wit.Type, result any, params ...any) error
CallInto decodes results directly into caller's memory without intermediate allocation. result must be a pointer to the target type (e.g., *string, *uint32, *MyStruct). For void returns, pass nil. For strings, the result points directly into WASM memory and is only valid while the instance is alive.
func (*WazeroInstance) CallWithLift ¶
func (i *WazeroInstance) CallWithLift(ctx context.Context, funcName string, params ...any) (any, error)
CallWithLift calls a function using cached lift information from canon registry. It is faster than Call for repeated invocations as it caches lookup results.
func (*WazeroInstance) CallWithTypes ¶
func (i *WazeroInstance) CallWithTypes(ctx context.Context, funcName string, paramTypes []wit.Type, resultTypes []wit.Type, params ...any) (any, error)
CallWithTypes calls a WASM function with explicit WIT type information
func (*WazeroInstance) EnableAsyncify ¶
func (i *WazeroInstance) EnableAsyncify(config AsyncifyConfig) error
EnableAsyncify initializes asyncify support for this instance. Call EnableAsyncify after instantiation but before calling async functions. The module must have been compiled with asyncify (wasm-opt --asyncify).
func (*WazeroInstance) GetExportedFunction ¶
func (i *WazeroInstance) GetExportedFunction(name string) api.Function
GetExportedFunction returns an exported function by name (public wrapper).
func (*WazeroInstance) MemorySize ¶
func (i *WazeroInstance) MemorySize() uint32
MemorySize returns the current linear memory size in bytes, or 0 if no memory.
func (*WazeroInstance) RunAsync ¶
func (i *WazeroInstance) RunAsync(ctx context.Context, name string, args ...uint64) ([]uint64, error)
RunAsync executes a function with asyncify event loop support. It returns after the function completes, processing any async operations.
func (*WazeroInstance) Scheduler ¶
func (i *WazeroInstance) Scheduler() *Scheduler
Scheduler returns the async scheduler if enabled.
func (*WazeroInstance) StartCall ¶
func (i *WazeroInstance) StartCall(ctx context.Context, funcName string, params ...any) (*CallSession, error)
StartCall prepares a call session by lowering params. Does not execute yet. Call Step to advance execution.
type WazeroMemory ¶
type WazeroMemory struct {
// contains filtered or unexported fields
}
WazeroMemory wraps wazero memory to implement wasmruntime.Memory
func (*WazeroMemory) Read ¶
func (m *WazeroMemory) Read(offset uint32, length uint32) ([]byte, error)
func (*WazeroMemory) Size ¶
func (m *WazeroMemory) Size() uint32
type WazeroModule ¶
type WazeroModule struct {
// contains filtered or unexported fields
}
WazeroModule is a compiled WASM module
func (*WazeroModule) AsyncifyImports ¶
func (m *WazeroModule) AsyncifyImports() []string
AsyncifyImports returns the list of import names that require asyncify transformation. Uses intersection logic: a function is async only if both the host registration and the component canon lower agree. For core modules (no canon registry), trusts the host flag.
func (*WazeroModule) Compile ¶
func (m *WazeroModule) Compile(ctx context.Context, cfg *CompileConfig) error
Compile pre-compiles the module and validates imports. Call Compile at registration time to fail fast on missing imports (strict mode). It returns error if compilation fails or imports cannot be satisfied. After Compile, Instantiate will reuse the cached InstancePre.
func (*WazeroModule) ExportNames ¶
func (m *WazeroModule) ExportNames() []string
ExportNames returns the names of all exported functions
func (*WazeroModule) FindLift ¶
func (m *WazeroModule) FindLift(name string) *component.LiftDef
FindLift returns the lift definition for an exported function
func (*WazeroModule) Instantiate ¶
func (m *WazeroModule) Instantiate(ctx context.Context) (*WazeroInstance, error)
func (*WazeroModule) InstantiateWithConfig ¶
func (m *WazeroModule) InstantiateWithConfig(ctx context.Context, cfg *InstanceConfig) (*WazeroInstance, error)
InstantiateWithConfig creates an instance with custom configuration
func (*WazeroModule) RegisterHostFuncTyped ¶
func (m *WazeroModule) RegisterHostFuncTyped(namespace, name string, handler any) error
RegisterHostFuncTyped registers a typed Go function that will be auto-wrapped using the Canon ABI. The handler signature is validated against the WIT import. It uses semver matching: a host at version X.Y.Z can satisfy imports for X.Y.W where W <= Z.
func (*WazeroModule) RegisterHostFuncTypedAsync ¶
func (m *WazeroModule) RegisterHostFuncTypedAsync(namespace, name string, handler any) error
RegisterHostFuncTypedAsync registers a typed Go function as an async host function. Same as RegisterHostFuncTyped but marks the function as async (yields during execution).