You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Array iteration protocol: for-of over a typed local bypasses a patched Array.prototype[Symbol.iterator]; restoring the original throws; getOwnPropertyDescriptor on a prototype symbol returns undefined #7760
Three defects found while fixing #7542 (PR #7759), each independent of it and of each other. Filing together because they share a root area and the first two block writing a gap test for any of them.
1. for…of over a typed local ignores a replaced Array.prototype[Symbol.iterator]
Over an array literal it is correct (that routes through js_get_iterator, which honours the flag). Over a typed local it is not, and the reason is that codegen emits a dense index loop with no runtime call at all — js_array_values_iter_obj and js_array_length appear only in the declare block of the emitted IR.
So this cannot be fixed where #7542 was: there is no runtime entry point to guard. It needs a codegen-side gate — e.g. the loop preheader loading a volatile global (the shape PERRY_ARRAY_INDEX_FAST_PATH_INVALIDATED already uses) and branching to the protocol path when the iteration protocol has been patched.
2. Restoring the original array iterator throws
constp: any=Array.prototype;constorig=p[Symbol.iterator];p[Symbol.iterator]=function*(){yield"x";};p[Symbol.iterator]=orig;// restorefor(constvof[1,2,3]){}// TypeError: next is not a function
Reading Array.prototype[Symbol.iterator] returns a method bound to the prototype (js_object_get_symbol_property's array arm synthesizes it via js_class_method_bind), so storing it back and calling it with this === arr does not produce an array iterator.
Pre-existing and independent of #7542: it reproduces on for…of over an array literal, which routes through js_get_iterator and is untouched by that fix.
3. getOwnPropertyDescriptor on a prototype symbol returns undefined
Which also removes the obvious workaround for (2).
Why these are worth having together
They make the whole family untestable in the gap suite today. Any test that patches Array.prototype[Symbol.iterator] takes the ORACLE down under run_parity_tests.sh — node constructs a SafeMap from an iterable and gets the patched value:
TypeError: Iterator value patched is not an entry object
at new Map (<anonymous>) node:internal/per_context/primordials:449
so the comparison runs against a crashed node. The natural fix is for the test to restore the original before returning — which (2) and (3) both block. Fixing either one makes a gap test for this family possible; until then #7759's coverage is a direct byte-for-byte comparison recorded in its description.
Activity
fix(array): Array.prototype[Symbol.iterator] is a real own property a…
fix(hir): for-of over an array honours a replaced Array.prototype[Sym…
fix(array,hir): a replaced Array.prototype[Symbol.iterator] is honour…
perf(hir): skip the iterator protocol for proven-array destructuring
perf(hir): skip the iterator protocol for proven-array destructuring