Skip to content

wasi-shims: à la carte wasi:sockets UDP over Deno.listenDatagram - #122

Merged
lannbot merged 1 commit into
mainfrom
wasi-sockets-udp
Aug 13, 2026
Merged

wasi-shims: à la carte wasi:sockets UDP over Deno.listenDatagram#122
lannbot merged 1 commit into
mainfrom
wasi-sockets-udp

Conversation

@lannbot

@lannbot lannbot commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

The decision

Adopts the wasi:sockets/types UDP provider from polymorph-components/polymorph-iroh#69 into the shim package as an à la carte fragment: a separate export (@deltic/wasi-shims/sockets), never merged into wasiShims() and absent from the release bundle. The root module stays host-agnostic web-platform code; Deno-native hosts spread the fragment in:

instantiate(artifacts, { ...wasiShims(), ...sockets().imports })

Scope stays in the shim package per the §2 WASI non-goal (docs/architecture.md); this is the "natural upstream home" the source PR named, and the first installment of #4 (UDP for the iroh direct path — the p3 TCP leaves remain open there).

Scope: the linked surface, exactly

The five udp-socket functions the iroh endpoint artifact links — create, bind, send, receive, get-local-address. The unlinked remainder of the WIT resource (connect/disconnect, socket options) stays absent by design: the runtime dispatches only what a plan imports, and a future guest linking more gets a loud trap naming the missing method rather than an untested emulation.

Behavioral yardstick is wasmtime-wasi's p3 provider: the 64 KiB datagram ceiling (checked before the OS; EMSGSIZE mapped for the 65508–65535 band), the bind-once state machine, send's implicit wildcard bind, invalid-argument for an omitted remote on this connectionless surface, and the IPv4-mapped / deprecated-IPv4-compatible family rejections. Recorded divergences (module header), both rooted in Deno exposing no socket options: non-zero IPv6 scope-id fails not-supported; IPv6 sockets keep the OS dual-stack default where wasmtime sets IPV6_V6ONLY (hence the codec parsing the ::ffff:a.b.c.d sender spelling).

Divergences from the adopted code

  • Track key wasi:sockets/types@0.3 instead of exact @0.3.0 — this package is the flagship track-key consumer; one provider serves every 0.3.x the resolver folds onto the track.
  • Fragment-scoped onCall observer replaces the module-global call log: a published provider must not grow a string per datagram by default. The fragment returns { imports, UdpSocket } (mirroring cli()'s { imports, captured }), so the hook is per-fragment — the source PR's exam assertions (zero-calls in relay scenarios, exact driving sequence) remain expressible.
  • globalThis-based feature detection + structural types for the unstable Deno.listenDatagram surface: the module evaluates on hosts with no Deno global at all and needs no "unstable" config to type-check or publish. create answers not-supported where UDP isn't served.
  • mapPlatformError passes branded errors through — fixes a latent double-wrap in the adopted code: branded throws from inside the platform-call try blocks (the address codec in receive; here also the capability re-detection in bind/send) were demoted to kind: "other". Regression test included.

Gates

  • just test-wasi-shims: 20 new unit tests — the address codec (compressed / full / IPv4-embedded / zoned spellings), the state machine and branded-error contract, the zero-length self-wake datagram, both datagram-too-large detection paths, dispose retiring a parked receive as a branded err, the fragment shape (track key, per-fragment onCall), and the passthrough regression. The test task gains --allow-net --unstable-net (real loopback sockets).
  • just publish-check: the new ./sockets subpath passes the JSR dry-run.
  • just test-bundle: bundle unchanged by design (root graph untouched).

Refs #4.

Adopted from polymorph-components/polymorph-iroh#69 (that host's exam
drives it over loopback QUIC end to end). The five-function udp-socket
surface the iroh endpoint links — create, bind, send, receive,
get-local-address — with wasmtime-wasi p3 as the behavioral yardstick:
the 64 KiB datagram ceiling (both detection paths), the bind-once state
machine, send's implicit wildcard bind, invalid-argument for an omitted
remote on this connectionless surface, and the IPv4-mapped /
deprecated-IPv4-compatible family rejections. Recorded divergences from
wasmtime (both rooted in Deno exposing no socket options): non-zero
scope-id fails not-supported; IPv6 sockets keep the OS dual-stack
default, so the codec parses the ::ffff:a.b.c.d sender spelling.

A la carte per the s2 WASI non-goal: a separate export
(@deltic/wasi-shims/sockets), never merged into wasiShims() and absent
from the release bundle — the root module stays host-agnostic
web-platform code, and browsers/wasmtime own their respective UDP
stories. When Deno.listenDatagram is absent (no Deno global, or
--unstable-net off), create answers not-supported.

Divergences from the adopted code: the track key (@0.3 — one provider
serves every 0.3.x), a fragment-scoped onCall observer replacing the
module-global call log (a published provider must not grow a string per
datagram by default; the fragment returns its UdpSocket class so the
hook stays per-fragment), globalThis-based feature detection with
structural types for the unstable surface (no "unstable" flag needed to
check or publish), and a ComponentException passthrough in
mapPlatformError — branded errors thrown inside the platform-call try
blocks (the codec in receive, capability re-detection in bind/send) no
longer double-wrap into kind "other".

Gates: test-wasi-shims (20 new tests), publish-check, test-bundle.
@lannbot
lannbot enabled auto-merge August 13, 2026 02:42
@lannbot
lannbot merged commit 8fb4d7f into main Aug 13, 2026
4 checks passed
@lannbot
lannbot deleted the wasi-sockets-udp branch August 23, 2026 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants