Problem
Fresh main CI run https://github.com/zig-utils/zig-js/actions/runs/29353934622 failed tsan-unit (shard 1/4) in Context heap_limit_bytes object side-store pressure fails closed.
The bounded allocator correctly returns OOM, but Object.setAttrUnlocked calls StringHashMapUnmanaged.getOrPut before duplicating the owned key. If that subsequent key duplication fails, the new map entry remains installed with the caller-borrowed key slice. GC finalization later treats every attrs key as backing-allocator-owned and frees the borrowed slice, causing SafeAllocator to abort with an invalid free at src/gc.zig:322.
Object.setAccessor uses the same insertion-before-key-copy pattern and has the same latent failure mode.
Failed job: https://github.com/zig-utils/zig-js/actions/runs/29353934622/job/87156822946
Scope
- Duplicate owned metadata keys before publishing new attrs/accessor entries.
- Free the speculative duplicate when the key already exists or map insertion fails.
- Preserve current normal-path behavior and allocation accounting.
Acceptance criteria
- The focused bounded-heap side-store failure test returns OOM and destroys the context without invalid frees or leaks.
- Add focused coverage for accessor-key OOM rollback as needed.
tsan-unit (shard 1/4)and the fresh publication gate are green.