-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support worlds which import and/or export "wildcard" interfaces #5925
Conversation
Note that I tried to modify the generated code for exports to decouple the resolve step from the call step (e.g. so you could do |
Subscribe to Label Actioncc @peterhuene
This issue or pull request has been labeled: "wasmtime:api"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
Per WebAssembly/component-model#172, this implements "part 1" of WIT templates, allowing WIT files to define interfaces which contain a single wildcard function, which worlds may import or export. I've chosen to implement the bindings for host-implemented functions in such a way that the host may delay import resolution until the latest possible moment, i.e. when the guest is actually calling the function. This allows for fully dynamic resolution (e.g. using the function name as a key to be looked up in a remote key-value store) when desired. This does come at a small performance cost compared to doing resolution at e.g. link time instead. In cases where the host wants to do resolution earlier (e.g. at deploy or instantiation time), that's certainly possible, e.g.: ```rust let component = Component::new(&engine, wasm)?; let funcs = component .names("imports") .map(|name| Ok((name.to_owned(), my_resolver(name)?))) .collect::<Result<HashMap<_, _>>>()?; struct MyImports<F> { funcs: HashMap<String, F> } impl <F: Fn() -> Result<u32>> imports::Host for MyImports<F> { fn call(&mut self, name: &str) -> Result<u32> { (self.funcs.get(name).unwrap())() } } let mut store = Store::new(&engine, MyImports { funcs }); ... ``` If we feel that early resolution is the more common case, we could consider adding a configuration option to the binding generator which indicates whether early or late resolution is desired, allowing the generator to optimize (ergonmically and performance-wise) accordingly. Note that the generated `add_to_linker` functions now take a `&Component` parameter as well as a `&mut Linker`. This allows those functions to inspect the component in order to determine how many `func_wrap{_async}` calls to make, and with what names. I'm open to alternatives to this if there's a better way. Finally, I've added a temporary dependency override to Cargo.toml, pointing to our fork of `wasm-tools`, which includes the necessary `wit-parser` changes. We're still iterating on that and will PR those changes separately. We also have a fork of `wit-bindgen` with a new "wildcards" test to verify everything works end-to-end: bytecodealliance/wit-bindgen@main...dicej:wit-templates. I'll PR that last once everything else is stable. Signed-off-by: Joel Dice <[email protected]>
After thinking about this some more, I realized that the "early vs. late resolution" tension I referred to above is not really a thing. Even if we force the host to do "early resolution" (i.e. prior to instantiating the component), it can just provide thunks which do asynchronous operations and/or trap at runtime if they need to. In other words, the host can always to "late resolution" (i.e. at the last possible moment, when called from the guest) inside the callback it provided at link time. Anyway, I went ahead and rewrote this using an ultra-minimalist approach such that the binding generator just skips wildcards entirely, leaving the host to use dynamic APIs to reflect on the component and do the necessary |
See #5934 for the new PR. |
Per WebAssembly/component-model#172, this implements "part 1" of WIT templates, allowing WIT files to define interfaces which contain a single wildcard function, which worlds may import or export.
I've chosen to implement the bindings for host-implemented functions in such a way that the host may delay import resolution until the latest possible moment, i.e. when the guest is actually calling the function. This allows for fully dynamic resolution (e.g. using the function name as a key to be looked up in a remote key-value store) when desired. This does come at a small performance cost compared to doing resolution at e.g. link time instead.
In cases where the host wants to do resolution earlier (e.g. at deploy or instantiation time), that's certainly possible, e.g.:
If we feel that early resolution is the more common case, we could consider adding a configuration option to the binding generator which indicates whether early or late resolution is desired, allowing the generator to optimize (ergonmically and performance-wise) accordingly.
Note that the generated
add_to_linker
functions now take a&Component
parameter as well as a&mut Linker
. This allows those functions to inspect the component in order to determine how manyfunc_wrap{_async}
calls to make, and with what names. I'm open to alternatives to this if there's a better way.Finally, I've added a temporary dependency override to Cargo.toml, pointing to our fork of
wasm-tools
, which includes the necessarywit-parser
changes. We're still iterating on that and will PR those changes separately. We also have a fork ofwit-bindgen
with a new "wildcards" test to verify everything works end-to-end: bytecodealliance/wit-bindgen@main...dicej:wit-templates. I'll PR that last once everything else is stable.