TL;DR: There is not currently a way to construct a non-empty stream in a synchronous context, making it impossible for a guest component to virtualize several WASI APIs. While planned features like cooperative threads will eventually make it possible to populate a stream by spawning background tasks, I believe that having a straightforward stream constructor that takes a list would be generally useful and hopefully (?) much simpler to implement.
(Apologies if this is not the best repo for this issue, please feel free to move it as appropriate.)
WASI-Virt currently supports WASI versions v0.2.1 and v0.2.3. Both of these are quite old relative the ecosystem; cargo build --target wasm32-wasip2 produces components that depend on WASI v0.2.9. The latest 2.x release is 0.2.12, and the first 0.3.x release landed last month. WASI-Virt also uses exact-match dependency resolution, so while a v0.2.12 export could satisfy a v0.2.3 import in theory, it gets rejected in practice. Functionally, this means that WASI-Virt cannot be used with recent toolchains.
I attempted to enable semver-compatible dependency resolution, but learned that it wouldn't be possible so long as WASI-Virt was using WASI p2. P2's use of resources to represent IO streams always lead to transitive import/export conflicts:
4: world exports wasi:io/streams@0.2.3 but it's also transitively used by an import which means that this is not valid
These conflicts should be obviated by P3's use of stream instead of resources. I set out to test this by making a simple component that would virtualize wasi:filesystem (and nothing else). However, I quickly ran into an issue when trying to implement descriptor.read-via-stream (see #wasi > Creating a `stream` in a sync context).
In short: read-via-stream is synchronous function. A guest implementation can construct a stream reader/writer pair via wit_stream::new(), but the guest cannot (meaningfully) spawn a background task to populate a stream via the writer. Cooperative threads should make this possible when they arrive early next year.
The WASI-Virt use case does not require a sophisticated writer implementation. The bytes that represent a file are known at virtualization time; the file descriptors are backed by a simple Vec<u8>. However, so far as I can tell, there is no way to construct a stream from a list<u8> in a synchronous context.
I know there's a larger design effort happening around slicing and splicing stream; I wonder if there's room for a simple synchronous constructor. (Regrettably, the lack of user generics does mean that you couldn't define a func from-list(list<T>) -> stream<T> in the near term.)
TL;DR: There is not currently a way to construct a non-empty
streamin a synchronous context, making it impossible for a guest component to virtualize several WASI APIs. While planned features like cooperative threads will eventually make it possible to populate astreamby spawning background tasks, I believe that having a straightforwardstreamconstructor that takes alistwould be generally useful and hopefully (?) much simpler to implement.(Apologies if this is not the best repo for this issue, please feel free to move it as appropriate.)
WASI-Virtcurrently supports WASI versions v0.2.1 and v0.2.3. Both of these are quite old relative the ecosystem;cargo build --target wasm32-wasip2produces components that depend on WASI v0.2.9. The latest 2.x release is 0.2.12, and the first 0.3.x release landed last month.WASI-Virtalso uses exact-match dependency resolution, so while a v0.2.12 export could satisfy a v0.2.3 import in theory, it gets rejected in practice. Functionally, this means thatWASI-Virtcannot be used with recent toolchains.I attempted to enable semver-compatible dependency resolution, but learned that it wouldn't be possible so long as
WASI-Virtwas using WASI p2. P2's use of resources to represent IO streams always lead to transitive import/export conflicts:These conflicts should be obviated by P3's use of
streaminstead of resources. I set out to test this by making a simple component that would virtualizewasi:filesystem(and nothing else). However, I quickly ran into an issue when trying to implementdescriptor.read-via-stream(see #wasi > Creating a `stream` in a sync context).In short:
read-via-streamis synchronous function. A guest implementation can construct a stream reader/writer pair viawit_stream::new(), but the guest cannot (meaningfully) spawn a background task to populate a stream via the writer. Cooperative threads should make this possible when they arrive early next year.The
WASI-Virtuse case does not require a sophisticated writer implementation. The bytes that represent a file are known at virtualization time; the file descriptors are backed by a simpleVec<u8>. However, so far as I can tell, there is no way to construct astreamfrom alist<u8>in a synchronous context.I know there's a larger design effort happening around slicing and splicing
stream; I wonder if there's room for a simple synchronous constructor. (Regrettably, the lack of user generics does mean that you couldn't define afunc from-list(list<T>) -> stream<T>in the near term.)