Parent: #12, #1. Related: #17.
Goal
Give lazy Iterator Helper records (Iterator.prototype.map/filter/take/drop/flatMap, Iterator.concat, Iterator.zip, and Iterator.zipKeyed) a no-GIL synchronization story for their mutable helper state.
Why this is separate from #17
Issue #17 is tracking direct Object.elements side doors. Iterator helpers do contain internal arrays (src, captured methods/keys, opened iterators, flags, padding), but those arrays are only part of the problem. The helper record itself also mutates shared fields during .next() / .return():
runningdonestartedcounterinnerinner_next
A same-helper cross-thread call can race those fields even if every backing array read is moved behind Object.elements_lock. So this needs a helper-record lock or an equivalent documented single-owner restriction, not a drive-by element-storage patch.
Acceptance criteria
- Decide and document whether Iterator Helper objects are single-consumer/thread-affine or shared-realm callable from multiple JS threads.
- If shared, add a lock or equivalent synchronization around helper record state transitions.
- Do not hold the helper lock or
Object.elements_lockacross user JS callbacks, iteratornext/return, or other re-entrant calls; snapshot whatever is needed first. - Migrate the internal helper arrays away from raw borrowed
elements.itemsslices where they can be observed across calls or used while user code runs. - Add focused regression/TSan coverage for re-entrant and cross-thread helper
.next()/.return()behavior. - Update
docs/threads/bindings.md/ threading docs with the final ruling.