@@ -10,7 +10,11 @@ containing object as `this`; amendment A3 (2026-08-11) lets `instantiate`
1010accept untranslated artifacts (` { componentBytes, translator } ` ) and run
1111the translation internally; amendment A4 (2026-08-11) blesses the
1212translation envelope as the build-time artifact
13- (` artifactsFromEnvelope ` ).** This document supersedes ` descriptor-ir.md ` 's interim
13+ (` artifactsFromEnvelope ` ); amendment A5 (2026-08-11) makes host wrapping
14+ of one stream/future idempotent (pass-through round trips —
15+ host→guest→host — hand back the same handle machinery instead of
16+ asserting), legalizes host↔host rendezvous for every element type, and
17+ pins u8 stream chunks as ` Uint8Array ` in both directions.** This document supersedes ` descriptor-ir.md ` 's interim
1418"host value mapping" table as the destination for host-facing value shapes.
1519The runtime's * raw* boundary (` instance.exports ` , ` HostImports ` ) keeps the
1620` definitions.py ` interpreter shapes as an ** internal** surface; the
@@ -349,8 +353,29 @@ class DroppedError extends Error { … } // awaiting a dropped future rejects
349353 ` Promise<T> ` or ` Future<T> ` . Bindgen adapts and ** owns the pumping** :
350354 the driving arms auto-close on end/` DROPPED ` (eliminating the
351355 deadlock-masking activity-lifetime footgun — R-fix review note 2), and
352- double-wrap / cross-store reuse are runtime-asserted errors, not silent
353- misbehavior (note 3).
356+ cross-store reuse is a runtime-asserted error, not silent misbehavior
357+ (note 3).
358+ - ** Stream values survive round trips** (amendment A5). A ` stream ` /` future `
359+ is an identity: lifting one that the host already handled — a
360+ host-created stream a guest passed back (result or import position), or
361+ a guest-created stream on its second hop — is ** idempotent** , yielding a
362+ handle over the same underlying end rather than the v0.2
363+ double-wrap error. Consequences, all normative:
364+ - host → guest → host pass-through works with the guest never reading;
365+ the payload then moves host↔host without touching guest memory;
366+ - a readable end may hop the boundary any number of times (each lower
367+ transfers it, exactly as between two guests);
368+ - host↔host rendezvous is legal for ** every** element type — the
369+ same-instance restriction applies to component instances only;
370+ - a ` Stream.create() ` writer keeps feeding the same stream across hops
371+ (the writer half addresses the shared end, not a particular handle).
372+ - ** u8 chunks are ` Uint8Array ` in both directions** (amendment A5, the
373+ write-side mirror of ` Chunk<u8> ` ): ` StreamWriter.write ` /` writeAll ` take
374+ ` Chunk<T> ` , and a ` Uint8Array ` chunk is treated as already-lowered bytes
375+ — passed by reference to the rendezvous (borrowed until the returned
376+ promise settles) and copied exactly once, at the rendezvous itself.
377+ Reads hand back that copy unchanged: one copy end-to-end for
378+ host↔host, one memory copy each way when a guest is the peer.
354379- Writer-side host ends (` hostStream() ` -era API) remain the low-level seam
355380 underneath; the conventions layer exposes them as
356381 ` Stream.create<T>(): { stream: Stream<T>, writer: StreamWriter<T> } `
0 commit comments