rpc_dart_wasm
WASM runtime bridge transport for rpc_dart.
This package is intentionally runtime-agnostic. It does not load .wasm
modules by itself. Instead, a runtime backend
implements the byte-only RpcWasmBridge, and RpcWasmTransport.fromBridge
turns it into a normal IRpcTransport.
final transport = RpcWasmTransport.fromBridge(
bridge: myWasmBridge,
isClient: true,
);
final endpoint = RpcPeerEndpoint(transport: transport);
endpoint.start();
WASM Bootstrap
Code compiled to WASM can bootstrap itself with RpcWasm.run(...):
import 'package:rpc_dart_wasm/rpc_wasm.dart';
void main() {
RpcWasm.run(
isClient: false,
configure: (endpoint) {
// Register RPC services here, then let the bootstrap start listening.
},
);
}
RpcWasm.run installs the runtime-side rpcWasmReceiveBytes callback,
adapts the host byte pipe into RpcWasmTransport, creates a
RpcPeerEndpoint, and starts it after configure returns.
Flutter Backend
RpcFlutterWasmBridge is the built-in Flutter plugin backend:
final support = await RpcFlutterWasmBridge.checkSupport();
if (!support.canRunDartWasm) {
throw StateError('Dart WASM is not supported on this device');
}
final bridge = await RpcFlutterWasmBridge.load(
wasmBytes: wasmBytes,
mjsCode: mjsCode,
);
final transport = RpcWasmTransport.fromBridge(
bridge: bridge,
isClient: true,
);
Native backends:
- Android:
androidx.javascriptengine.JavaScriptSandbox - iOS:
JavaScriptCore
The Flutter host keeps lifecycle calls on the rpc_dart_wasm method channel,
but runtime byte traffic goes over raw binary messenger channels:
rpc_dart_wasm/<runtimeId>/outgoingfor Dart to nativerpc_dart_wasm/<runtimeId>/incomingfor native to Dart
The WASM JavaScript side should expose a byte receiver:
globalThis.rpcWasmReceiveBytes = function(bytes) {
// bytes is a Uint8Array containing one RpcChannelFrame.
};
To send bytes back to the host, call:
_rpcWasmSendBytes(bytes); // bytes is Uint8Array
Bridge Protocol
RpcWasmBridge exchanges only Uint8List frames:
abstract interface class RpcWasmBridge {
Stream<Uint8List> get incoming;
Future<void> send(Uint8List data);
bool get isClosed;
Future<void> close();
}
No RPC-level JSON and no WASM-specific envelope is added by this package.
RpcWasmTransport adapts the bridge to IRpcChannel and reuses
RpcChannelTransport.fromChannel, so the wire format is the existing
RpcChannelFrame.
Runtime Backends
Expected backends:
- Flutter plugin backend: JavaScriptCore on iOS, JavaScriptSandbox on Android.
- Browser backend:
dart:js_interop/ JS functions. - Native backend: wasmtime/wasmer embedding.
- Test backend: paired in-memory bridge.
The transport itself does not guarantee zero-copy. Most WASM host boundaries copy bytes; backends may optimize byte transfer independently.
Libraries
- rpc_dart_wasm
- WASM runtime bridge transport for rpc_dart.
- rpc_wasm
- WASM-side bootstrap for
rpc_dart_wasm.