Skip to content

#24: exact ambient attribution for JSPI continuation chunks - #27

Merged
lann merged 1 commit into
mainfrom
fix-24
Aug 9, 2026
Merged

#24: exact ambient attribution for JSPI continuation chunks#27
lann merged 1 commit into
mainfrom
fix-24

Conversation

@lann

@lann lann commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Closes #24.

Two scheduler fixes (details in the commit message):

  1. claimActivationAmbient re-claims now move-to-top instead of noop — the LIFO's documented "top = innermost running activation" contract.
  2. Attribution sentinels in jspi/bridge.ts: a microtask claiming the chunk's owner is queued contiguously ahead of every engine continuation reaction (fast-path hop and genuine-suspension settle alike). This is the JSPI substitute for the identity that fibers give wasmtime for free.

A serializing-gate design was tried and rejected: it fixed attribution but shifted deterministic-profile admission order (caught by async-calls-sync.wast). The sentinel design preserves engine-natural ordering exactly — all corpus/lane expectations unchanged.

Pins: runtime/tests/jspi/chunk_attribution_test.ts (fails pre-fix) + the tls smoke's webcrypto composition xfail pruned (now the integration pin; all applicable cases green on every composition).

Gates: runtime + harness across seeds {unset,1,4242}, sm-pinned / chromium / firefox lanes at unchanged expectations, websocket 55/55 conformance, wasi-shims, ct-runner, webcrypto, webrtc, iroh exam 5/5, smoke-tls PASS.

…nels)

The webcrypto-composed polymorph-tls suite (three async wit-bindgen
components) hit `assert!(!state.is_null())` in wit-bindgen's callback entry
(async_support.rs:578): the runtime had invoked a task's [callback] export
whose context-local slot 0 was empty. Root cause chain, isolated with new
env-gated probes (CE_CTX_TRACE / CE_SP_TRACE / extended CE_AMBIENT_TRACE):

- Engine continuation chunks — the segments of a promising activation
  between suspension/hop points — begin as promise reactions with no
  synchronous signal to the runtime. With several concurrently-suspended
  sibling activations, chunks interleave at an empty bracket stack, and
  the ambient (tier-2 LIFO claims) misattributes every read in a later
  chunk: a hop's owner capture, or an unsafe intrinsic like context.set,
  which has no hop to re-anchor on. wit-bindgen's callback epilogue then
  restored one task's state pointer into another THREAD's context slots,
  and the starved thread's next disciplined callback invocation trapped.
- Two contributing defects fixed:
  1. scheduler.ts claimActivationAmbient: idempotence was a positional
     NOOP, leaving a stale finished-callee claim on top (its release edge
     is a promise reaction, one microtask late). Re-claiming now moves the
     claim to the top — the stack's own documented contract.
  2. jspi/bridge.ts: attribution sentinels. At every point where the
     engine is about to queue a continuation reaction — the fast-path hop
     (jspi pin (j)) and the genuine-suspension settle — queue a microtask
     FIRST that claims the chunk's owner. Per-promise reaction FIFO makes
     each [sentinel, chunk] pair contiguous even when several promises
     settle in one drain, so every chunk starts with its owner freshly on
     top, with zero delay and zero reordering.

The reordering constraint is load-bearing: a first-cut serializing gate
(one un-run continuation at a time) fixed attribution but measurably
shifted the deterministic-profile backpressure-admission order —
async-calls-sync.wast's guest asserts that order and caught it. The
sentinel design perturbs nothing: engine-natural scheduling is preserved
bit-for-bit (full corpus + browser/shell lane expectations unchanged).
`Promise.resolve().then`, not `queueMicrotask`, which bare engine shells
lack (sm-pinned lane caught it).

Pins: runtime/tests/jspi/chunk_attribution_test.ts (two interleaved
resumptions must each read their own ambient; fails pre-fix), and the
tls smoke's webcrypto composition is now fully green — its #24 xfail is
pruned (tools/smoke-tls/run.ts), all applicable cases green on every
composition (sole remaining class: tag-gating #25).

Gates: runtime 324 (seeds unset/1/4242), harness 69 (x3 seeds, zero
corpus deltas), sm-pinned + chromium + firefox lanes at unchanged
expectations, websocket 55/55, wasi-shims, ct-runner, webcrypto, webrtc,
iroh exam 5/5, smoke-tls PASS (seeded too).
@lann
lann enabled auto-merge August 9, 2026 20:46
@lann
lann merged commit bebd1a3 into main Aug 9, 2026
3 checks passed
@lannbot
lannbot deleted the fix-24 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.

Guest callback invoked with null context slot (wit-bindgen async_support.rs:578) — polymorph-tls webcrypto-composed target

1 participant