MessagePort Transport
Why this mode matters
Section titled “Why this mode matters”MessagePort is a low-level transport primitive that works well for custom runtime topologies.
It is especially useful when you want explicit channel wiring without being locked to a single container model.
Typical use cases:
- custom handshakes between host shell and remote runtime;
- bridge layers for popup/iframe/worker/session orchestration;
- dev and diagnostics tools that need an explicit bidirectional channel.
Core idea
Section titled “Core idea”@remote-ui/rpc already provides fromMessagePort(...).
Once both sides hold connected ports, integration is the same run/release flow:
import { createEndpoint, fromMessagePort } from '@remote-ui/rpc'
const endpoint = createEndpoint<RemoteApi>(fromMessagePort(port))await endpoint.call.run(receiver.receive, hostBridge)Minimal same-runtime example
Section titled “Minimal same-runtime example”import { MessageChannel } from 'node:worker_threads'import { createEndpoint, fromMessagePort } from '@remote-ui/rpc'
type Api = { ping(message: string): string }
const { port1, port2 } = new MessageChannel()
const host = createEndpoint<Api>(fromMessagePort(port1))const remote = createEndpoint(fromMessagePort(port2))
remote.expose({ ping(message: string) { return `pong: ${message}` },})
const result = await host.call.ping('hello')console.info(result) // pong: helloIn browser environments, use the native MessageChannel API with the same pattern.
Handshake pattern (browser)
Section titled “Handshake pattern (browser)”- Host creates a
MessageChannel. - Host transfers
port2to remote container (iframe,popup, or worker bootstrap) viapostMessage. - Host keeps
port1and initializescreateEndpoint(fromMessagePort(port1)). - Remote receives transferred port and initializes its endpoint.
- Both sides run standard
run/release.
Design notes
Section titled “Design notes”- Isolation is context-dependent:
MessagePortitself does not create sandbox boundaries. - Transport semantics are strong: explicit async boundary and structured-clone constraints.
- Lifecycle must be explicit: close ports and release retained references during teardown.