Skip to content

fix: #788 — AsyncLocalStorage real context propagation#852

Merged
TheHypnoo merged 3 commits into
mainfrom
feat/async-local-storage-context
May 16, 2026
Merged

fix: #788 — AsyncLocalStorage real context propagation#852
TheHypnoo merged 3 commits into
mainfrom
feat/async-local-storage-context

Conversation

@TheHypnoo
Copy link
Copy Markdown
Contributor

Summary

  • Real AsyncLocalStorage propagation across await, .then/.catch, queueMicrotask, process.nextTick, setTimeout, setImmediate and setInterval. Closes AsyncLocalStorage: real async-context tracking across await / microtasks / timers #788.
  • ALS store stacks moved from per-handle Vec into a thread-local active context (perry-runtime/src/async_context.rs); schedulers snapshot it at registration time and restore it while the callback runs.
  • exit() now restores only the affected ALS, preserving mutations made to other instances inside the callback.
  • Microtask context restoration uses a stack (not Option) and the queueMicrotask drain participates in the same setjmp trap, so a throw through a callback does not leak the callee's context.
  • Side table PROMISE_CONTEXTS is cleared on GC sweep for GC_TYPE_PROMISE payloads. A TODO notes the follow-up to inline the snapshot into Promise once PERRY_GEN_GC_EVACUATE=1 becomes default (today the evacuator does not rewrite the side-table key).
  • Shim note for node:async_hooks rewritten: ALS is no longer flagged as losing context; the remaining gap (createHook lifecycle + real asyncId) is tracked in async_hooks: real createHook lifecycle + asyncId tracking #789.

Test plan

  • cargo fmt --check
  • cargo check -p perry-hir -p perry-codegen -p perry-runtime -p perry-stdlib
  • ./run_parity_tests.sh --filter test_async_local_storage_context — PASS (new test covering await / then / catch / nextTick / timer / immediate / interval / nested run / enterWith / exit isolation / two instances)
  • ./run_parity_tests.sh --filter test_harness_async_context — only section 8 (createHook typeof: undefined) fails, as expected for async_hooks: real createHook lifecycle + asyncId tracking #789; every ALS section now passes.

TheHypnoo and others added 3 commits May 16, 2026 12:54
Propagates AsyncLocalStorage stores across await, .then/.catch,
queueMicrotask, process.nextTick, setTimeout, setImmediate and
setInterval. Store stacks moved out of per-handle Vecs into a
thread-local active context that schedulers snapshot at registration
time and restore while the callback runs.

exit() now restores only the affected ALS so mutations to other
instances inside the callback survive. Microtask context restoration
uses a stack and the queueMicrotask drain joins the same setjmp trap,
so a throw through a callback does not leak context. The promise side
table is cleared on GC sweep; a TODO notes the follow-up to inline the
snapshot into Promise once PERRY_GEN_GC_EVACUATE=1 becomes default.

The node:async_hooks shim note no longer flags ALS as lossy; the
remaining gap (createHook lifecycle + real asyncId) is tracked in #789.
@TheHypnoo TheHypnoo merged commit 4ead3fe into main May 16, 2026
9 checks passed
@TheHypnoo TheHypnoo deleted the feat/async-local-storage-context branch May 16, 2026 11:42
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.

AsyncLocalStorage: real async-context tracking across await / microtasks / timers

1 participant