@@ -186,22 +186,23 @@ interface filesystem {
186186 }
187187}
188188```
189- a bindings generator in a language with ` async ` would only emit ` async `
190- functions for ` read ` and ` fetch ` . Since in many languages ` new ` expressions
191- cannot be async, there is no ` async constructor ` . Use cases requiring
192- asynchronous construction can instead use ` static async ` functions, similar to
193- ` from-stream ` in this example.
189+ A bindings generator processing the above WIT for a language with ` async ` would
190+ only emit ` async ` functions for ` read ` and ` from-stream ` .
194191
192+ Since in many languages ` new ` expressions cannot be async, there is no
193+ ` async constructor ` . Use cases requiring asynchronous construction can instead
194+ use ` static async ` functions, similar to ` from-stream ` in this example.
195195
196196### Task
197197
198198Every time a lifted function is called (e.g., when a component's export is
199199called by the outside world), a new ** task** is created that logically contains
200200all the transitive control-flow state of the export call and will be destroyed
201- when the export call finishes. When all of a component's exports are lifted
202- synchronously, there will be at most one task alive at any one time. However,
203- when a component exports asynchronously-lifted functions, there can be multiple
204- tasks alive at once.
201+ when the export call finishes.
202+
203+ When all of a component's exports are lifted synchronously, there will be at most one
204+ task alive at any one time. However, when a component exports asynchronously-lifted
205+ functions, there can be multiple tasks alive at once.
205206
206207In the Canonical ABI explainer, a "task" is represented with the Python
207208[ ` Task ` ] class. A new ` Task ` object is created (by [ ` canon_lift ` ] ) each time
@@ -268,18 +269,27 @@ in the Canonical ABI explainer.
268269### Structured concurrency
269270
270271Calling * into* a component creates a ` Task ` to track ABI state related to the
271- * callee* (like "number of outstanding borrows"). Calling * out* of a component
272- creates a ` Subtask ` to track ABI state related to the * caller* (like "which
273- handles have been lent"). When one component calls another, there is thus a
274- ` Subtask ` +` Task ` pair that collectively maintains the overall state of the call
275- and enforces that both components uphold their end of the ABI contract. But
276- when the host calls into a component, there is only a ` Task ` and,
277- symmetrically, when a component calls into the host, there is only a ` Subtask ` .
278-
279- Based on this, the call stack at any point in time when a component calls a
280- host-defined import will have a callstack of the general form:
272+ * callee* (like "number of outstanding borrows").
273+
274+ Calling * out* of a component creates a ` Subtask ` to track ABI state related to
275+ the * caller* (like "which handles have been lent").
276+
277+ When one component calls another, there is thus a ` Subtask ` +` Task ` pair that
278+ collectively maintains the overall state of the call and enforces that both
279+ components uphold their end of the ABI contract. But when the host calls into
280+ a component, there is only a ` Task ` and, symmetrically, when a component calls
281+ into the host, there is only a ` Subtask ` .
282+
283+ Based on this, the call stack when a component calls a host-defined import will
284+ have the general form:
281285```
282- [Host caller] <- [Task] <- [Subtask+Task]* <- [Subtask] <- [Host callee]
286+ [Host]
287+ ↓ host calls component export
288+ [Component Task]
289+ ↓ component calls import implemented by another component's export 0..N times
290+ [Component Subtask <> Component Task]*
291+ ↓ component calls import implemented by the host
292+ [Component Subtask <> Host task]
283293```
284294Here, the ` <- ` arrow represents the ` supertask ` relationship that is immutably
285295established when first making the call. A paired ` Subtask ` and ` Task ` have the
@@ -719,7 +729,8 @@ world w {
719729 export foo: func(s: string) -> string;
720730}
721731```
722- the default sync export function signature is:
732+
733+ The default sync export function signature for export ` foo ` is:
723734``` wat
724735;; sync
725736(func (param $s-ptr i32) (param $s-len i32) (result $retp i32))
@@ -735,33 +746,40 @@ The async export ABI provides two flavors: stackful and stackless.
735746
736747The stackful ABI is currently gated by the 🚟 feature.
737748
738- The async stackful export function signature is:
749+ The async stackful export function signature for export ` foo ` (defined above
750+ in world ` w ` ) is:
739751``` wat
740752;; async, no callback
741753(func (param $s-ptr i32) (param $s-len i32))
742754```
743- The parameters work just like synchronous parameters. There is no core function
744- result because a callee [ returns] ( #returning ) their value by * calling* the
745- * imported* ` task.return ` function which has signature:
755+
756+ The parameters work just like synchronous parameters.
757+
758+ There is no core function result because a callee [ returns] ( #returning ) their
759+ value by * calling* the * imported* ` task.return ` function which has signature:
746760``` wat
747761;; task.return
748762(func (param $ret-ptr i32) (result $ret-len i32))
749763```
764+
750765The parameters of ` task.return ` work the same as if the WIT return type was the
751766WIT parameter type of a synchronous function. For example, if more than 16
752767core parameters would be needed, a single ` i32 ` pointer into linear memory is
753768used.
754769
755770##### Stackless Async Exports
756771
757- The async stackless export function signature is:
772+ The async stackless export function signature for export ` foo ` (defined above
773+ in world ` w ` ) is:
758774``` wat
759775;; async, callback
760776(func (param $s-ptr i32) (param $s-len i32) (result i32))
761777```
778+
762779The parameters also work just like synchronous parameters. The callee returns
763- their value by calling ` task.return ` just like the stackful case. The `(result
764- i32)` lets the core function return what it wants the runtime to do next:
780+ their value by calling ` task.return ` just like the stackful case.
781+
782+ The ` (result i32) ` lets the core function return what it wants the runtime to do next:
765783* If the low 4 bits are ` 0 ` , the callee completed (and called ` task.return ` )
766784 without blocking.
767785* If the low 4 bits are ` 1 ` , the callee wants to yield, allowing other code
@@ -776,6 +794,7 @@ must also be exported with signature:
776794``` wat
777795(func (param i32 i32 i32) (result i32))
778796```
797+
779798The ` (result i32) ` has the same interpretation as the stackless export function
780799and the runtime will repeatedly call the callback until a value of ` 0 ` is
781800returned. The ` i32 ` parameters describe what happened that caused the callback
0 commit comments