CI: https://github.com/zig-utils/zig-js/actions/runs/29674163787/job/88158274698 Roadmap: #143 Related: #293
Root cause
The no-GIL PR-249 case jit/int-gate-stop-budget.js produced a
suppression-free TSan race between:
registerParsedDebugScriptmutating the sharedContext.debug_statement_locationsAutoHashMap while a child constructs a dynamicFunction; andserviceDebugStatementreading the same map from another child.
The same transaction also mutates debug_scripts and
next_debug_script_id unsafely, so fixing only the reported map access would
leave duplicate IDs/list corruption latent.
Acceptance
- Serialize script ID assignment, script-list publication, notify-hook installation/removal, location-map mutation, and all concurrent reads.
- Keep single-threaded and GIL execution on the lock-free path.
- Never expose a partially registered script/location record.
- Add a deterministic multi-thread dynamic-Function witness with exact script-ID uniqueness and result checks.
- Pass focused normal and suppression-free TSan tests.
- Re-run the exact
jit/int-gate-stop-budget.jsTSan witness. - Observe a green replacement full CI shard before closing.
Local evidence
zig build test -Dtest-filter="debug registry": 3/3 passed.zig build test -Dtest-filter="debug registry" -Dtsan=true: 3/3 passed, suppression-free.zig build threads-test -Dthreads-parallel-js=true -Dthreads-case=jit/int-gate-stop-budget.js -Dtsan=true: 1/1 passed in 26.3 seconds.zig build test -Dtest-filter=inspector: 20/20 passed.