Problem
Fresh exact Zig dev.1818 Linux TSan CI reaches past #634 and executes the complete bounded recovery script successfully, then loses its completion value at the host boundary: TSan unit shard 1 fails in Interpreter.pushTempRoot while growing gc_temp_roots from Context.evaluateWithThis.
That ordering lets attacker-controlled JavaScript exhaust the realm, catch every script-visible OOM, and produce a valid result, only for the embedding call to return a host error.OutOfMemory because precise-root storage was allocated afterward. The result also needs to be read back from its root slot after a moving tail collection, rather than from a potentially stale native local.
Required implementation
- Reserve one evaluation-completion root before timer checkpoints or script execution can consume the remaining bounded budget.
- Keep the placeholder in the active interpreter root set so nested temporary roots stack above it and cannot consume the reservation.
- Publish a successful completion into that slot without allocation.
- Return the possibly relocated value from the root slot after all microtask, Thread keepalive, and requested-GC checkpoints.
- Restore the exact prior root depth on every success/error path.
- Do not raise the heap limit, bypass accounting, skip tail checkpoints, swallow OOM, or rely on conservative native-stack retention.
Acceptance
- The unchanged 4 MiB torn-object recovery witness passes on exact dev.1818 Linux and under TSan.
- A focused allocation-failure unit proves completion publication succeeds after its allocator is exhausted.
- Moving-GC and parallel Thread completion-root witnesses remain green.
- Full normal/TSan unit shards report zero leaks and no new sanitizer findings.