Proposal: Component Model v0
Currently, the component model is very complicated and difficult to understand and to implement. In particular, wasmtime has the only working implementation of the component nodel: wasmtime-environ, which is used by Rust dependents to lower the component model into a representation they can handle, which still has many layers of confusing abstraction.
I propose we create a minimal subset of the component model which can be implemented by other, external, runtimes and compilers, including:
- Components are not allowed to be nested, imported, or exported
- Async is disallowed, both in ABI options and types
- Encodings other than the native encoding, either UTF-8 or WTF-16, are disallowed
-
externrefs are disallowed as handle types
This subset, which I propose to call Component Model v0, should include most single-module components, allowing external tools to parse this simplified representation and thus implement WASI 0.2 for it. At a later point, when the external tool is fully developed, the full component model might be implemented within that tool.
First mention of this complexity
TODO: compare with wasit2 TODO: finalize restrictions
That's a fair question and there are couple of options already in progress:
- In #378 there's work to specify just the core wasm ABI needed to compile and run single-module components.
- jco transpile and gravity show how a bunch of the work to implement "the component model" can be factored out into a component-to-module pre-processing step that allows the resulting module to run on an existing core wasm engine (jco targeting the browser and gravity targeting wazero)
The former is valuable to simplify the lives of producer toolchains: they can just target the core ABI and then anyone downstream can use a tool like wasm-component-ld to wrap the module into a component or run the module directly on a core runtime. Mainly the work left to do here is finish the implementation enough to validate what's specified in #378.
The latter approach is valuable to simplify the lives of runtimes and I think could be generalized to apply to more core runtimes. E.g., I could imagine a standalone project for a "component precompiler" tool that factored as much as it could out of jco, gravity and wasmtime. I think mainly what we'd need here is folks who use or build these core runtimes to help scope out and work on this tool.
I think these two approaches would go much farther in allowing incremental adoption of the Component Model than trying to scope down the Component Model (e.g., trimming out async), although if there was a concrete use case where someone thought this would help, I'd be happy to discuss the options here.
Hope that helps, happy to discuss more.
That's a fair question and there are couple of options already in progress:
- In Add BuildTargets.md #378 there's work to specify just the core wasm ABI needed to compile and run single-module components.
- jco transpile and gravity show how a bunch of the work to implement "the component model" can be factored out into a component-to-module pre-processing step that allows the resulting module to run on an existing core wasm engine (jco targeting the browser and gravity targeting wazero)
The former is valuable to simplify the lives of producer toolchains: they can just target the core ABI and then anyone downstream can use a tool like
wasm-component-ldto wrap the module into a component or run the module directly on a core runtime. Mainly the work left to do here is finish the implementation enough to validate what's specified in #378.
I can agree with this option as a method to produce core wasm, intermediate representations, and components from a single source core wasm module. Implementation of this on the consumer side, however, would require either using a single module exclusively or reinventing the linking part of the component model, neither of which would scale as a standard (but again, WASI 0.1 is still being used due to this implementation issue for the Component Model).
The latter approach is valuable to simplify the lives of runtimes and I think could be generalized to apply to more core runtimes. E.g., I could imagine a standalone project for a "component precompiler" tool that factored as much as it could out of jco, gravity and wasmtime. I think mainly what we'd need here is folks who use or build these core runtimes to help scope out and work on this tool.
While these specialized tools can be generalized, most of their effort is concentrated around wasmtime-environ, a Rust crate with particularly wasmtime-specific interfaces. Most "implementations" of the component model in other core runtimes either defer to wasmtime-environ or just parse enough to say they don't support it. I can agree with your last statement, but we'd also need scoping and work on the Component Model. Given the already-standardized and expansive featureset already existing, a subset seems like the safest option to avoid further division.
Maybe there's another way to kick off implementation (not just adoption) of the component model that I haven't seen though. Thoughts?
I think these two approaches would go much farther in allowing incremental adoption of the Component Model than trying to scope down the Component Model (e.g., trimming out async), although if there was a concrete use case where someone thought this would help, I'd be happy to discuss the options here.
Existing tools are very close to this minimal subset; Binaryen, for instance, can easily implement it, given its built-in support for module merging. I would also see the subset as a stepping stone to full Component Model implementation in other tools--a consumer-side version of wasit2.
Hope that helps, happy to discuss more.
In particular,
wasmtimehas the only working implementation of the component nodel:wasmtime-environ
IIUC, vscode made their own implementation of the component model that does not rely on wasmtime-environ: https://code.visualstudio.com/blogs/2024/05/08/wasm
In particular,
wasmtimehas the only working implementation of the component nodel:wasmtime-environIIUC, vscode made their own implementation of the component model that does not rely on
wasmtime-environ: https://code.visualstudio.com/blogs/2024/05/08/wasm
Looking at it, it seems to only implement the Canonical ABI for a single module, and cannot parse components at all. It still works better than the current status-quo, where everyone forks WASI 0.1 with ad-hoc interfaces, though.
const module = await WebAssembly.compile(bits);
WasmEdge also has an independent component-model implementation in progress which is working well enough to support wasi-http.
I never understood why there is a component model. What was so wrong with waspi1? why not extend it a little bit more instead of boiling the ocean for some nepo babies who are trying to get investor money?