refactor(moonbit): a possibly better async implementation for wasi p3#1659
Merged
alexcrichton merged 10 commits intoJul 22, 2026
Merged
Conversation
Member
|
Thanks! Happy to merge when you feel it's ready |
peter-jerry-ye
force-pushed
the
codex/moonbit-async-upstream-main
branch
from
July 21, 2026 11:28
cb46b80 to
9d5806e
Compare
peter-jerry-ye
marked this pull request as ready for review
July 22, 2026 02:50
Contributor
Author
|
I think it's ready. Though it still need to be battle tested with actual user feedbacks later. |
alexcrichton
enabled auto-merge
July 22, 2026 03:58
alexcrichton
approved these changes
Jul 22, 2026
Merged
via the queue into
bytecodealliance:main
with commit Jul 22, 2026
5c2943b
28 of 29 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
MoonBit already has an initial implementation of Component Model futures and
streams. It represents component endpoints with generic
FutureReader,FutureWriter,StreamReader, andStreamWritertypes backed byFutureVTable[T]andStreamVTable[T].Those vtables contain the position-specific component intrinsics together with
payload allocation, lift, lower, and cleanup callbacks. This made the initial
implementation possible, but it also made Component Model endpoints part of the
MoonBit runtime model:
WIT function position;
that vtable;
several closely related public types.
The intrinsic naming rules used by the core-wasm adapter reinforce this problem,
but they are not the fundamental reason for the redesign. Even with direct
component generation, a component endpoint and a local MoonBit async value have
different ownership and lifecycle semantics.
Design
This PR replaces the vtable model with a boundary-conversion model.
Future[T],Promise[T],Stream[T], andSink[T]are local MoonBitcoordination types. They work with arbitrary MoonBit values and do not contain
component handles, endpoint indices, or operation tables.
Component future and stream endpoints remain generated implementation details.
For every concrete WIT position, the generator creates helpers that directly
call the corresponding intrinsics and recursively convert the payload. The
intrinsic names come from
wit-parser; they are not reconstructed or selectedfrom
T.This means:
Future::new()creates a localFuture/Promisepair, not a componentfuture pair;
Stream::new()creates a localStream/Sinkpipe;future<future<stream<T>>>are converted one layerat a time at their actual canonical ABI positions;
FutureVTableandStreamVTableruntime representation is removed.Generated bridges own the canonical ABI state needed to commit or reject
prepared values, preserve partial stream progress, cancel in-flight operations,
observe peer drop, and clean resources whose ownership did not cross the
boundary.
Background work
This PR also adds an explicit
parameter to generated async export implementations.
MoonBit structured concurrency normally considers a function complete only
after its child tasks complete. Component Model task return has a different
boundary: an export may publish its result while work belonging to the
underlying task continues and is no longer observable by the caller.
(After
task.returnortask.cancel)The generated adapter therefore publishes the component result when the user
implementation returns, while allowing tasks spawned into
background_grouptocontinue. The work remains owned by the MoonBit task group, but its eventual
result cannot alter the already published export result.
This is required for hook-style APIs such as
wasi:http@0.3.0: a handler canreturn a response immediately and continue producing its body, trailers, or
processing-completion future afterward.
Other changes
state.
variables with
moonbitlang/asyncwhere Component Model semantics do notrequire different behavior.
resource cleanup, and concurrent component exports.
wasi:cli@0.3.0, andwasi:http@0.3.0.Scope
This establishes an MVP API and a clean generator boundary. It intentionally
does not include:
error-contextread_intoan active component async scope
The kebab-case package-name and
@buffer.Bufferchanges remain separateprerequisite commits. Endpoint-free synchronous output remains unchanged.