What lies
Atomics.wait, Atomics.notify, and Atomics.waitAsync validate their arguments correctly and then fake their results:
Evidence (current main, crates/perry-runtime/src/atomics.rs):
js_atomics_wait → always returns "timed-out" (line ~596) — never blocks, never observes a notify.
js_atomics_notify → always returns 0 — never wakes anyone.
js_atomics_wait_async → resolves "timed-out" immediately (lines ~633-637).
Documented as a known limitation when #4794 closed (CLAUDE.md: "Atomics.wait/notify/waitAsync are non-blocking stubs (no cross-agent wakeups)"), but there was no dedicated tracker for finishing it — this is it.
Why it matters
Severity: SILENT-LIE. A spin-wait coordination pattern (Atomics.wait(i32, 0, 0) … Atomics.notify) silently degrades to a busy "timed-out" loop. Any library using SAB-based mutexes/semaphores (emscripten output, some WASM glue, thread-pool libs) malfunctions without any error.
Prerequisite
Real blocking semantics require a SharedArrayBuffer that actually aliases across threads — today perry/thread deep-copies values (SerializedValue), so there is no shared memory to wait on. That makes this issue two-stage:
Related: #2876 (Atomics ops on SAB views), #4794 (closed; single-realm scope).
What lies
Atomics.wait,Atomics.notify, andAtomics.waitAsyncvalidate their arguments correctly and then fake their results:Evidence (current
main,crates/perry-runtime/src/atomics.rs):js_atomics_wait→ always returns"timed-out"(line ~596) — never blocks, never observes a notify.js_atomics_notify→ always returns0— never wakes anyone.js_atomics_wait_async→ resolves"timed-out"immediately (lines ~633-637).Documented as a known limitation when #4794 closed (CLAUDE.md: "Atomics.wait/notify/waitAsync are non-blocking stubs (no cross-agent wakeups)"), but there was no dedicated tracker for finishing it — this is it.
Why it matters
Severity: SILENT-LIE. A spin-wait coordination pattern (
Atomics.wait(i32, 0, 0)…Atomics.notify) silently degrades to a busy "timed-out" loop. Any library using SAB-based mutexes/semaphores (emscripten output, some WASM glue, thread-pool libs) malfunctions without any error.Prerequisite
Real blocking semantics require a SharedArrayBuffer that actually aliases across threads — today
perry/threaddeep-copies values (SerializedValue), so there is no shared memory to wait on. That makes this issue two-stage:waiton a non-shared buffer throws; same-realmwaitwithtimeout=0returns"not-equal"/"timed-out"per spec (partially right today);perry_stub_warnon firstnotify.perry/threadboundaries (no deep copy for SAB), then futex-style park/wake forwait/notifyand microtask-resolvedwaitAsync.Related: #2876 (Atomics ops on SAB views), #4794 (closed; single-realm scope).