examples/: hello-world + kitchen-sink — runnable, self-checking embedder examples - #55
Merged
Conversation
…er examples Consumer-facing examples as the first documentation priority (per operator direction): each is a self-contained WIT + Rust-guest (wit-bindgen) + TS-host triple that can be copied out of the repo and built as-is, with a run.sh reproducing the fixture pipeline (cargo -> wasm-tools component new -> validate -> deno run). The hosts import @deltic/runtime through the Deno workspace (examples/ becomes a member) — the same specifiers a published consumer will use (#16). hello-world: one export, no imports — translate -> instantiate -> call, with the Promise-shaped-exports and strings-just-work observations. kitchen-sink: a representative embedder-API tour, each section numbered and cross-referenced from its README table: - imports record: interface keys, camelCase members, resource class position; - sync import (enum param as string), fallible import (WitError throw -> err; unbranded throw = trap), suspending import in BOTH forms (suspending() call form on read-sensor, @suspending decorator on channel.send — an A2 host-resource method); - host-implemented resource: constructor, methods, static, Symbol.dispose on guest drop (asserted via open-count); - guest-implemented resource driven with TS `using`; - value spellings: variant {tag,val}, enum string, record object, flags booleans (absent = false), OUTERMOST option as undefined, return-place result as resolve/throw-WitError, nested option/result as data — including the option-boxing rule pinned at all three depths of option<option<u32>> (maybe-maybe), and the per-chain subtlety that an option inside a list is still the outermost of its own chain (survey). The guest's run-batch drives every import from Rust that is oblivious to which of them park its frame — the point of the suspending marker, stated in the guest doc comment. Both hosts are self-checking (assertEq with an undefined-preserving replacer — JSON would collapse the meaningful outermost-option undefined into null) and fail loudly on API drift. Wiring: the `examples` just recipe (deps: shim) runs both; added to the gates list and to the CI core matrix (.github/justfile) so the examples are required checks and cannot rot. examples/README.md reframed for its two audiences (embedder examples first, fixture corpus second); root README gains layout + documentation rows routing embedders here. Gates: examples green; test-runtime / wasi-shims / ct-runner / bundle, conformance (1254/0, 0 unexpected, 0 stale), sched-seeds, shells all green after the deno.json workspace addition; deno.lock untouched.
lann
enabled auto-merge
August 10, 2026 21:25
lann
added a commit
that referenced
this pull request
Aug 10, 2026
…rips Investigation first (per #54's brief): a stream traversing host -> guest -> host with the guest never reading transfers the SharedStreamImpl by identity — the payload never touches guest memory, so the #54 copy cost doesn't apply to pure pass-through. But the conventions layer broke the scenario outright: toHost re-wraps every lifted stream via hostStreamFor, whose double-wrap assert rejected any host-touched stream (both result and import position), and after a pass-through both host ends presented one shared HOST_INSTANCE sentinel, so non-numeric elements tripped the same-instance trap. Four changes, one PR (operator call): * cabi/store.ts (#54 proper): storeListIntoValidRange gets the store-side mirror of the lift's u8 fast path — Uint8Array sources memcpy via bytesOf().set(); plain arrays keep storeInt's exact per-element semantics ("int store" assert + mod-256 mask) in a tight loop. 16 KiB stores: 12.6 -> 0.20 ns/B typed (~5 GB/s, now matching the lift direction), 13.4 -> 2.9 ns/B plain. * exec/host_streams.ts (amendment A5): hostStreamFor/hostFutureFor return a cached wrapper (WeakMap by shared object) instead of asserting — wrapping is idempotent, pass-through round trips and multi-hop chains work, and the hazard the assert guarded (two HostActivities pumping one object) is gone by construction. bindOnLower's assert stays as an internal invariant. * exec/host_streams.ts: per-end rendezvous identities (hostEndInstance) replace the single HOST_INSTANCE sentinel; host<->host rendezvous is legal for every element type. The same-instance restriction (definitions.py none_or_number_type, a guard on interleaved lifts in one instance's linear memory) keeps firing for real component instances only. * u8 chunks stay Uint8Array end-to-end (task/streams.ts PayloadChunk, HostBuffer chunk accumulation + taken(), embedder packChunk/#chunk, StreamWriter takes Chunk<T>): a host-side u8 read costs exactly the one rendezvous copy (32 -> 712 MB/s on the 64 KiB pass-through probe); writes borrow the caller's chunk until the promise settles (documented), and writeAll re-offers subarray views rather than slice copies (review F1). New fixture examples/guests/stream-pass (pass-through/forward/ pass-through-text — a guest that hands streams on without reading) pins the scenario end-to-end; store_list_test pins store-path equivalence incl. the pre-existing mod-256 deviation from definitions.py store_int (memory.ts's, not this path's). Contract: embedder-api.md amendment A5 (idempotent wrapping, round-trip transferability, host<->host rendezvous, Chunk<T> writes + borrow rule). Docs: architecture.md §7 records the bulk-both-directions policy. Gates: build, test-rust, test-runtime (356), test-wasi-shims, test-ct-runner, test-bundle, examples, conformance (1254/0, async 216/0, no stale xfails), sched-seeds (1, 4242), test-ports, test-webrtc, shells (sm-pinned; jsc-pinned arch-skipped), browsers (chromium, firefox), websocket-conformance (55/0), smoke-tls. smoke-c0 legs 2+4 pass; legs 1/3 and iroh-exam scenario 3 fail identically on the base commit in this environment (missing experiment-mosh checkout; webrtc backend race) — pre-existing, not this change. Reviewed by reviewer subagent against definitions.py + A5; F1 fixed, F2-F4 addressed. Consumer lockfiles (exams/iroh-endpoint, ports/webrtc, ports/websocket): mechanical catch-up adding the @deltic/examples workspace link from #55. Closes #54.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The examples commit from #53's branch — it raced #53's auto-merge (pushed after the merge fired) and never reached main; cherry-picked clean onto current main. Full description in the commit message; short version:
Two self-contained WIT + Rust-guest + TS-host examples, the operator-directed first documentation priority:
WitError) / suspending imports in both marker forms (incl.@suspendingon a host-resource method — A2 exercised end-to-end); resources both directions (Symbol.disposeon guest drop; TSusing); the non-obvious value spellings (variant/enum/record/flags; outermost option vs return-place result vs nested option/result as data, with the option-boxing rule pinned at all threeoption<option<u32>>depths).Both hosts self-check and fail loudly on drift.
just examplesruns both; the step joins the CI core matrix (this PR's own run demonstrates it).examples/joins the Deno workspace so hosts import@deltic/runtime/...as a published consumer would (#16). READMEs: examples index reframed two-audience; root README routes embedders in.Gates: examples + full core set green locally (conformance 1254/0, 0 unexpected/stale; sched-seeds; shells);
deno.lockuntouched; ports lockfiles clean.