From cf0b7271936380d3780b67b6e59038276f0d9d5d Mon Sep 17 00:00:00 2001
From: Pat Hickey
Date: Fri, 5 Jun 2026 17:13:15 -0700
Subject: [PATCH] wizer: support init func as a wave function call (components
only)
---
crates/wizer/Cargo.toml | 3 ++
crates/wizer/src/component/wasmtime.rs | 61 ++++++++++++++++++++------
2 files changed, 51 insertions(+), 13 deletions(-)
diff --git a/crates/wizer/Cargo.toml b/crates/wizer/Cargo.toml
index c237a743523c..9f76326c3e83 100644
--- a/crates/wizer/Cargo.toml
+++ b/crates/wizer/Cargo.toml
@@ -62,6 +62,9 @@ wasmtime = [
'wasmtime/gc',
'wasmtime/gc-null',
'wasmtime/async',
+ # Need wave and wit-parser features to parse init func expressions
+ 'wasmtime/wave',
+ 'wasmtime/wit-parser',
]
# Enable support for wizening components.
diff --git a/crates/wizer/src/component/wasmtime.rs b/crates/wizer/src/component/wasmtime.rs
index 8c12d86bac22..15a7254990bb 100644
--- a/crates/wizer/src/component/wasmtime.rs
+++ b/crates/wizer/src/component/wasmtime.rs
@@ -1,7 +1,7 @@
use crate::Wizer;
use crate::component::ComponentInstanceState;
use wasmtime::component::{
- Component, ComponentExportIndex, Instance, Lift, WasmList, types::ComponentItem,
+ Component, ComponentExportIndex, Instance, Lift, Val, WasmList, types::ComponentItem,
};
use wasmtime::{Result, Store, error::Context as _, format_err};
@@ -27,10 +27,10 @@ impl Wizer {
let engine = store.engine();
let component = Component::new(engine, &instrumented_wasm)
.context("failed to compile the Wasm component")?;
- let index = self.validate_component_init_func(&component)?;
+ let (index, args, rets) = self.validate_component_init_func(&component)?;
let instance = instantiate(store, &component).await?;
- self.initialize_component(store, &instance, index).await?;
+ self.initialize_component(store, &instance, index, args, rets).await?;
self.snapshot_component(cx, &mut WasmtimeWizerComponent { store, instance })
.await
}
@@ -38,10 +38,31 @@ impl Wizer {
fn validate_component_init_func(
&self,
component: &Component,
- ) -> wasmtime::Result {
+ ) -> wasmtime::Result<(ComponentExportIndex, Vec, Vec)> {
let init_func = self.get_init_func();
+
+ use wasmtime::component::wasm_wave::{untyped::UntypedFuncCall, wasm::WasmFunc};
+ use wasmtime::component::wit_parser::ItemName;
+ let (func_name, func_call) = if init_func.contains('(') {
+ let call = UntypedFuncCall::parse(init_func)
+ .with_context(|| format!("parsing `{init_func}` as wave function call"))?;
+ let item_name = call
+ .item_name()
+ .map_err(wasmtime::Error::from_anyhow)
+ .with_context(|| format!("parsing `{init_func}` as wave function call"))?;
+ (item_name, Some(call))
+ } else {
+ (
+ init_func
+ .parse::()
+ .map_err(wasmtime::Error::from_anyhow)
+ .with_context(|| format!("parsing `{init_func}` as wit item name"))?,
+ None,
+ )
+ };
+
let (ty, index) = component
- .get_export(None, init_func)
+ .get_export(None, func_name)
.ok_or_else(|| format_err!("the component does export the function `{init_func}`"))?;
let ty = match ty {
@@ -49,12 +70,24 @@ impl Wizer {
_ => wasmtime::bail!("the component's `{init_func}` export is not a function",),
};
- if ty.params().len() != 0 || ty.results().len() != 0 {
- wasmtime::bail!(
- "the component's `{init_func}` function export does not have type `[] -> []`",
- );
+ if let Some(func_call) = func_call {
+ let param_types = WasmFunc::params(&ty).collect::>();
+ let param_vals = func_call.to_wasm_params(¶m_types).with_context(|| {
+ format!("parsing `{init_func}` params as types {param_types:?}")
+ })?;
+ Ok((
+ index,
+ param_vals,
+ vec![Val::Bool(false); ty.results().len()],
+ ))
+ } else {
+ if ty.params().len() != 0 || ty.results().len() != 0 {
+ wasmtime::bail!(
+ "the component's `{init_func}` function export does not have type `[] -> []`",
+ );
+ }
+ Ok((index, vec![], vec![]))
}
- Ok(index)
}
async fn initialize_component(
@@ -62,15 +95,17 @@ impl Wizer {
store: &mut Store,
instance: &Instance,
index: ComponentExportIndex,
+ args: Vec,
+ mut rets: Vec,
) -> wasmtime::Result<()> {
let init_func = instance
- .get_typed_func::<(), ()>(&mut *store, index)
+ .get_func(&mut *store, index)
.expect("checked by `validate_init_func`");
init_func
- .call_async(&mut *store, ())
+ .call_async(&mut *store, &args, &mut rets)
.await
.with_context(|| format!("the initialization function trapped"))?;
-
+ // TODO: do we want some way to report the values of `rets` back up?
Ok(())
}
}