Stream: wasi

Topic: Accepting an arbitrary number of plugins


view this post on Zulip zslayton (Oct 10 2025 at 12:18):

I'm trying to design a toy system that supports plugins supplied by different authors.

Based on my current understanding of the component model, a way to achieve this would be to define a world (plugin) and accept .wasm components that implement that world. I would then compose these together with the 'main' .wasm component to create my program. Unfortunately, I'm having difficulty finding a way to achieve this in practice.

I can imagine rolling my own plugin registration system something like the following:

// There is a resource that defines the desired plugin API
resource plugin-resource {
  // ...methods...
}

// Plugin authors implement components that know how to initialize
// their plugin-resource implementation.
world plugin {
    init: func() -> plugin-resource;
}

// At composition time, some external logic chains together the provided
// plugins into one big component that satisfies this API.
world plugin-iterator {
    next: func() -> option<plugin-resource>;
}

However, this feels pretty clunky. Before I go down that road, am I missing a supported way to achieve this? If there is no supported way to achieve this, is that a point-in-time limitation, or a design decision?

Thanks!

view this post on Zulip Alex Crichton (Oct 10 2025 at 14:37):

I think you'll run into a few limitations with this design. One is that, you're correct, dynamically composing a variable number of components to something that returns a list is not a simple wac command, for example, today. You'd have to have some sort of custom interposing component there.

Another issue, however, is that if each plugin exports the plugin-resource type then despite having the same WIT type at runtime they all have distinct types and aren't interchangeable. That means that at a type-level you can't actually implement plugin-iterator because each plugin would return a uniquely-typed plugin-resource.

What you might want instead is to have the host arbitrate this. The guest would import a single plugin-resuorce interface and would have a sort of "lookup" that the host would dispatch to other plugins. Basically "host magic" to help do the dispatch

view this post on Zulip zslayton (Oct 10 2025 at 16:11):

Another issue, however, is that if each plugin exports the plugin-resource type then despite having the same WIT type at runtime they all have distinct types and aren't interchangeable. That means that at a type-level you can't actually implement plugin-iterator because each plugin would return a uniquely-typed plugin-resource.

Oh, interesting. I had been thinking of resources as values using dynamic dispatch over their resource {...} methods. Thank you for pointing this out, it's important to know.

What you might want instead is to have the host arbitrate this. The guest would import a single plugin-resuorce interface and would have a sort of "lookup" that the host would dispatch to other plugins. Basically "host magic" to help do the dispatch

Sorry, I'm not quite sure what you mean. Could you give me an example?

view this post on Zulip Alex Crichton (Oct 10 2025 at 16:16):

Effectively what you're imagining is dynamic dispatch could be implemented in the host. The component-model itself doesn't have that degree of dynamic dispatch but you on the host could have a trait which is implemented for each plugin. The guest would then import functionality that the host implements in terms of a list of trait objects. Or... something like that, not really an example per se as this is still pretty hand-wavy

view this post on Zulip zslayton (Oct 10 2025 at 16:21):

Ok, thanks! I'll do some experimenting and see what I can figure out. In the meantime, are there any WIT features coming in the future that might facilitate composing an arbitrary number of components?

view this post on Zulip Alex Crichton (Oct 10 2025 at 16:23):

Not that I know of myself, no, unfortunately

view this post on Zulip Joel Dice (Oct 10 2025 at 16:34):

Some flavor of WIT templates would probably help here.

Motivation Let's say I'd like to build a component that consumes 3 configuration values a, b and c (which in a 12-factor app I'd take as 3 environment variables). I could define a component with ty...

view this post on Zulip Zhefu (Dec 15 2025 at 00:10):

I had an idea for a possible workaround.

Suppose a host application wants to load multiple plugins that use the same interface. The host could maintain multiple copies of that interface, each with a unique name (e.g., integer-suffixed interface names so they’re treated as distinct).

Plugins themselves would be compiled against the “normal” interface (no suffixes). When loading a plugin, the host would select an unused interface copy and patch the plugin’s interface names so that they match, allowing composition/loading without conflicts.

The main question is: is it feasible to do this kind of automated interface renaming on an already-compiled .wasm module?


Last updated: Jan 10 2026 at 20:04 UTC