Wasmex. Components
(wasmex v0.15.0)
Copy Markdown
This is the entry point to support for the WebAssembly Component Model.
The Component Model is a higher-level way to interact with WebAssembly modules that provides:
- Better type safety through interface types
- Standardized way to define imports and exports using WIT (WebAssembly Interface Types)
- WASI support for system interface capabilities
Basic Usage
To use a WebAssembly component:
Start a component instance:
# Using raw bytes bytes = File.read!("path/to/component.wasm") {:ok, pid} = Wasmex.Components.start_link(%{bytes: bytes}) # Using a file path {:ok, pid} = Wasmex.Components.start_link(%{path: "path/to/component.wasm"}) # With WASI support {:ok, pid} = Wasmex.Components.start_link(%{ path: "path/to/component.wasm", wasi: %Wasmex.Wasi.WasiP2Options{} }) # With imports (host functions the component can call) {:ok, pid} = Wasmex.Components.start_link(%{ bytes: bytes, imports: %{ "host_function" => {:fn, &MyModule.host_function/1} } })Call exported functions:
{:ok, result} = Wasmex.Components.call_function(pid, "exported_function", ["param1"])
Component Interface Types
The component model supports the following WIT (WebAssembly Interface Type) types:
Supported Types
Primitive Types
- Integers:
s8,s16,s32,s64,u8,u16,u32,u64 - Floats:
f32,f64 boolstringchar(maps to Elixir strings with a single character)char"A" # or from a code point 937 # Ω
- Integers:
Compound Types
record(maps to Elixir maps with atom keys)record point { x: u32, y: u32 }%{x: 1, y: 2}list<T>(maps to Elixir lists)list<u32>[1, 2, 3]tuple<T1, T2>(maps to Elixir tuples)tuple<u32, string>{1, "two"}option<T>(maps to:noneor{:some, value})option<u32>:none # or {:some, 42}enum(maps to Elixir atoms)enum size { s, m, l }:s # or :m or :lvariant(tagged unions, maps to atoms or tuples)variant filter { all, none, lt(u32) }:all # variant without payload :none # variant without payload {:lt, 7} # variant with payloadflags(maps to Elixir maps with boolean values)flags permission { read, write, exec }%{read: true, write: true, exec: false} # Note: When returned from WebAssembly, only the flags set to true are included # %{read: true, exec: true}result<T, E>(maps to Elixir tuples with :ok/:error)result<u32, u32>{:ok, 42} # success case {:error, 404} # error case
Guest Resources
Guest-owned resources exported by a component can be constructed and called
with Wasmex.Components.GuestResource. It can generate an arity-aware API
from WIT:
defmodule Counter do
use Wasmex.Components.GuestResource,
wit: File.read!("counter.wit"),
resource: "counter"
end
{:ok, counter} = Counter.new(component_pid, 42)
{:ok, value} = Counter.get_value(counter)
:ok = Counter.drop(counter)Host Resources
Host-owned resources imported by a component can be implemented with
Wasmex.Components.HostResource:
defmodule CounterHost do
use Wasmex.Components.HostResource,
wit_path: "wit",
resource: "counter"
def new(initial), do: MyCounter.start(initial)
def get_value(counter), do: MyCounter.value(counter)
def drop(counter), do: MyCounter.stop(counter)
end
{:ok, component_pid} =
Wasmex.Components.start_link(
bytes: component,
imports: CounterHost.imports()
)Constructors return an opaque Elixir term representing the resource. Methods
and the destructor receive that term. Borrowed handles remain live, while
owned handles transfer ownership to the receiving callback. wit_path:
resolves dependency packages from a standard wit/deps directory.
Guest-owned resource values passed through arbitrary freestanding component functions are not yet supported.
Support for the Component Model should be considered beta quality.
Options
The start_link/1 function accepts the following options:
:bytes- Raw WebAssembly component bytes (mutually exclusive with:path):path- Path to a WebAssembly component file (mutually exclusive with:bytes):wasi- Optional WASI configuration asWasmex.Wasi.WasiP2Optionsstruct for system interface capabilities:imports- Optional map of host functions that can be called by the WebAssembly component- Keys are function names as strings
- Values are tuples of
{:fn, function}where function is the host function to call - Modules generated with
Wasmex.Components.HostResourceexposeimports/0definitions for host-owned resources
Additionally, any standard GenServer options (like :name) are supported.
Examples
# With raw bytes
{:ok, pid} = Wasmex.Components.start_link(%{
bytes: File.read!("component.wasm"),
name: MyComponent
})
# With WASI configuration
{:ok, pid} = Wasmex.Components.start_link(%{
path: "component.wasm",
wasi: %Wasmex.Wasi.WasiP2Options{
allow_http: true
}
})
# With host functions
{:ok, pid} = Wasmex.Components.start_link(%{
path: "component.wasm",
imports: %{
"log" => {:fn, &IO.puts/1},
"add" => {:fn, fn(a, b) -> a + b end}
}
})
Summary
Functions
Calls an exported component function.
Returns a specification to start this module under a supervisor.
Returns the low-level component instance owned by a component server.
Starts a new WebAssembly component instance.
Types
Functions
@spec call_function(GenServer.server(), function_name_or_path(), [any()], timeout()) :: {:ok, any()} | {:error, any()}
Calls an exported component function.
name_or_path may be a function name or a path identifying an exported
interface function. Parameters and results use the Elixir representations
described in the component interface type documentation above.
The default timeout is 5 seconds. A timeout exits the calling process unless
it traps exits, just like GenServer.call/3. Wasmtime component calls cannot
currently be cancelled without invalidating the component instance, so a
timed-out call continues in the background. Its late result is discarded and
later operations on the same Store wait for it to finish. Use :infinity for
calls whose duration is intentionally unbounded.
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec instance(GenServer.server()) :: Wasmex.Components.Instance.t()
Returns the low-level component instance owned by a component server.
Guest resource APIs accept either this value or the component server directly.
Starts a new WebAssembly component instance.
Options
:bytes- Raw WebAssembly component bytes (mutually exclusive with:path):path- Path to a WebAssembly component file (mutually exclusive with:bytes):wasi- Optional WASI configuration asWasmex.Wasi.WasiP2Optionsstruct:imports- Optional map of host functions that can be called by the component- Any standard GenServer options (like
:name)
Returns
{:ok, pid}on success{:error, reason}on failure