no30bit opened issue #11538:
Feature
Extend
wasmtime::component::bindgen!orwasmtime::component::Linkerto allow input components to miss some of the exports from WIT interfaces.Benefit
On my project I have a user-implemented wasm component that I compile and call functions from at runtime.
Withcomponent::LinkerI haven't found a way to add "default" exports. For imports this can be achieved withallow_shadowingandfunc_wrap.So I have to force my users to define every single export with default values event when they don't need it. This implies their code breaks every time I add another possible export, since they would have it missing.
Benefit in my case is backward compatibility when adding new exports in WIT and not having to define unnecessary defaults by guests.
Implementation
Currently
bindgen!generates code that looks like this for each WIT export:impl WorldName { fn foo(&self) -> &Guest; }I would like to have something like this:
// panics if `foo` export isn't present in component fn foo(&self) -> &Guest; // `None` if `foo` export isn't present in component fn get_foo(&self) -> Option<&Guest>;To maintain backward compatibility, this feature could be configured in
bindgen!parameters (i.e. making exports not link-time verified).Alternatives
If there's a way to link a default-component to be partially shadowed by real implementations, I'd like an example similar to the existing one for linking modules (this).
Add
component::Linker::define_missing_exports_as_default_valuessimilar to define_unknown_imports_as_default_values
no30bit commented on issue #11538:
cc @stevenj
alexcrichton commented on issue #11538:
One way to model this today would be to define a world-per-export that your users have. You would then generate bindings once-per-world (probably using
withto point all imports to the same set of imports for all bindings). That way you'd do detection on the host for "which world should be used".Alternatively you could also skip
bindgen!entirely for exports and just have a world with imports and then manually poke at a component after instantiating it.
stevenj commented on issue #11538:
@alexcrichton In our use case, we are using the component model as a kind of plugin, where we can deliver
eventsto a wasm component. Each differenteventis handled by a different export. The module can implement any number ofeventhandlers, depending on what work it does. We also need to validate in our imports that anexportexists. For example, wasm can callsubscribe_to_cron(<params>)that will generate acronevent which gets delivered to acron_eventexport in the same component. Thesubscribe_to_croncall needs to fail if the calling component does not have acron_eventexport.This is fully composable.
Currently we are exploring patching out the
.watfile of the loaded wasm component with stubbed exports that it doesn't implement, just to satisfy the linker and bindings.
stevenj edited a comment on issue #11538:
@alexcrichton In our use case, we are using the component model as a kind of plugin, where we can deliver
eventsto a wasm component. Each differenteventis handled by a different export. The module can implement any number ofeventhandlers, depending on what work it does. We also need to validate in our imports that anexportexists. For example, wasm can callsubscribe_to_cron(<params>)that will generate acronevent which gets delivered to acron_eventexport in the same component. Thesubscribe_to_croncall needs to fail if the calling component does not have acron_eventexport.This is fully composable.
Currently we are exploring patching out the
.watfile of the loaded wasm component with stubbed exports that it doesn't implement, just to satisfy the linker and bindings.Another complication is it needs to be forward compatible, as we will add events over time, and we can't break existing components just because there are new events they won't subscribe to anyway.
stevenj edited a comment on issue #11538:
@alexcrichton In our use case, we are using the component model as a kind of plugin, where we can deliver
eventsto a wasm component. Each differenteventis handled by a different export. The module can implement any number ofeventhandlers, depending on what work it does. We also need to validate in our imports that anexportexists. For example, wasm can callsubscribe_to_cron(<params>)that will generate acronevent which gets delivered to acron_eventexport in the same component. Thesubscribe_to_croncall needs to fail if the calling component does not have acron_eventexport.This is fully composable.
Currently we are exploring patching out the
.watfile of the loaded wasm component with stubbed exports that it doesn't implement, just to satisfy the linker and bindings.Another complication is it needs to be forward compatible, as we will add events over time, and we can't break existing components just because there are new events they won't subscribe to anyway.
We will also look at the possibility to manually poke the component after instantiating, as it may give us more flexibility.
alexcrichton commented on issue #11538:
That makes sense yeah, and would it work to have a
world-per-event? That way when you compile a component you could then also test it for allworlds to see which it conforms to. That way per-store state could have a reference to "this instance supports these events through these bindings". That way insubscribe-to-cron, for example, you could reject the call if the component doesn't suport the cron world export event.This strategy should also be forwards-compatible because on your end you'd be adding more worlds and not updating any preexisting worlds. The upside here is you get to keep using auto-generated bindings and no need to try to get types to align or anything.
stevenj commented on issue #11538:
@alexcrichton I am not sure if a
world-per-eventwould work for us. The Component can choose to implement any number of the available events. We do have aworld-per-component-modulebecause each component modules world is a strict subset of the engines totalworld.So there would be an large number of possible permutation worlds.
Also, Components in our model should not
importanything they don't actually use, and should not export events they don't handle. As we will be using this information as part of a permissions system. ie, if the component does not have permission to usecron eventsit will be refused to load if it imports cron functions or exports a cron event. @no30bit is working on a solution based on your earlier adviceskip bindgen! entirely for exports and just have a world with imports and then manually poke at a component after instantiating it.. If we get a working solution we will follow up with how we went about it.
Last updated: Dec 06 2025 at 07:03 UTC