website/docs/guides/contributing/submodules/dco-codec.md
Continue from the CST codec function call story, the user's Rust function is already executed, and our job here is to pass the return value back to Dart.
String, is posted to the Dart side. It is done by the Dart-provided API, Dart_PostCObject, which let us provide C structs and it will automatically become Dart data on the other side. We use the Rust-safe wrapper allo-isolate for it. We deliberately choose this, because this enables Dart code to be async instead of sync._wire2api_SomeType to convert it to the final "Dart api data". Notice this "wire2api" is on Dart side, so it means "Dart wire data to Dart api data", and is different from the one above which is for Rust. For example, since Dart_PostCObject does not provide a way to construct arbitrary structs(classes), we have to pass Rust structs as lists, and use the wire2api to convert them to corresponding Dart classes.func, that the user called just now. A function call finishes!On Web platforms, for lack of a proper SendPort there exists replacements from dart:html.
MessagePort replaces dart:ffi's SendPort and is created from MessageChannel. The Dart
thread creates a channel, keeps the receive port and transfers the send port to the workers.
sequenceDiagram
Dart ->> Rust: port2
Rust ->> Rust Worker: port2
Rust Worker ->> Dart: port2.postMessage
BroadcastChannel replaces dart:ffi's SendPort for StreamSinks, due to the fact that wasm_bindgen
keeps the ports in a JS-local scope that cannot be shared with other threads. A broadcast channel
is created by Dart, then passed to the main Rust thread. Rust then transfers its name to the workers.
When other workers refer to a StreamSink from another worker, e.g. if the sink was put in a static variable,
a new BroadcastChannel will be created from its name.
BroadcastChannels are guaranteed to be unique for each invocation.1
sequenceDiagram
Dart ->> Rust: channel
Rust ->> Rust Worker 1: channel.name
Rust Worker 1 ->> Dart: channel.postMessage
Rust ->> Rust Worker 2: channel.name
Rust Worker 2 ->> Dart: channel.postMessage
It is theoretically possible to have a one-to-one implementation of Isolate using only web primitives,
BroadcastChannels and Workers, but it remains to be seen how practical such an approach would be.
This is currently implemented as a monotonically-increasing index. ↩