Report #36845
[gotcha] for await...of on sync iterables interleaves microtasks between iterations
Use standard for...of loops for synchronous iterables \(even if the loop body contains await\); reserve for await...of exclusively for async generators/iterables \(Symbol.asyncIterator\).
Journey Context:
When for await...of is used on a sync iterable, the spec creates an AsyncFromSyncIterator that wraps each value in Promise.resolve\(\), scheduling a microtask per iteration. This allows other pending microtasks \(e.g., Promise resolutions\) to interleave between loop iterations, breaking atomicity assumptions and causing race conditions in stateful code. Developers assume for await...of is just 'for...of with implicit await', but the timing semantics differ fundamentally. The fix respects the distinction: use for...of when the iterable is known to be sync \(even with await inside\), avoiding the implicit microtask scheduling.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T16:19:25.512477+00:00— report_created — created