Stream: git-wasmtime

Topic: wasmtime / issue #11538 Allow missing exports when using ...


view this post on Zulip Wasmtime GitHub notifications bot (Aug 26 2025 at 09:20):

no30bit opened issue #11538:

Feature

Extend wasmtime::component::bindgen! or wasmtime::component::Linker to 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.
With component::Linker I haven't found a way to add "default" exports. For imports this can be achieved with allow_shadowing and func_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

view this post on Zulip Wasmtime GitHub notifications bot (Aug 26 2025 at 09:22):

no30bit commented on issue #11538:

cc @stevenj

view this post on Zulip Wasmtime GitHub notifications bot (Aug 26 2025 at 14:21):

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 with to 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.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 26 2025 at 14:29):

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 events to a wasm component. Each different event is handled by a different export. The module can implement any number of event handlers, depending on what work it does. We also need to validate in our imports that an export exists. For example, wasm can call subscribe_to_cron(<params>) that will generate a cron event which gets delivered to a cron_event export in the same component. The subscribe_to_cron call needs to fail if the calling component does not have a cron_event export.

This is fully composable.

Currently we are exploring patching out the .wat file of the loaded wasm component with stubbed exports that it doesn't implement, just to satisfy the linker and bindings.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 26 2025 at 14:31):

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 events to a wasm component. Each different event is handled by a different export. The module can implement any number of event handlers, depending on what work it does. We also need to validate in our imports that an export exists. For example, wasm can call subscribe_to_cron(<params>) that will generate a cron event which gets delivered to a cron_event export in the same component. The subscribe_to_cron call needs to fail if the calling component does not have a cron_event export.

This is fully composable.

Currently we are exploring patching out the .wat file 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.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 26 2025 at 14:31):

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 events to a wasm component. Each different event is handled by a different export. The module can implement any number of event handlers, depending on what work it does. We also need to validate in our imports that an export exists. For example, wasm can call subscribe_to_cron(<params>) that will generate a cron event which gets delivered to a cron_event export in the same component. The subscribe_to_cron call needs to fail if the calling component does not have a cron_event export.

This is fully composable.

Currently we are exploring patching out the .wat file 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.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 26 2025 at 16:53):

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 all worlds 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 in subscribe-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.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 27 2025 at 04:32):

stevenj commented on issue #11538:

@alexcrichton I am not sure if a world-per-event would work for us. The Component can choose to implement any number of the available events. We do have a world-per-component-module because each component modules world is a strict subset of the engines total world.

So there would be an large number of possible permutation worlds.

Also, Components in our model should not import anything 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 use cron events it 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 advice skip 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