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.from(str) returns [] for any string containing a lone surrogate #9431
Array.from("a\ud83db")// node: 3 elements perry: [][..."a\ud83db"]// correct in both
js_array_from_string_codepoints (array/alloc.rs:359) does str::from_utf8(bytes) and returns an empty array on Err — but perry's string payloads are WTF-8, so any lone surrogate makes the whole conversion silently yield nothing. The spread and for…of paths on the same string are correct, which is what makes this a wrong answer rather than a consistent limitation.
Silent: no error, just an empty array where the program expects characters.
Fix note
The walk should use wtf8_step like the other iterators. It was left out of #9427 because that same function holds a raw elements pointer and a borrow of the source payload across per-element allocations — pre-existing, but it means the change wants the RuntimeHandleScope discipline string/split.rs uses rather than a one-line swap.
Fixed by PR #9461: js_array_from_string_codepoints dropped its from_utf8 validity gate (perry payloads are WTF-8, so any lone surrogate emptied the whole array — mapped form included) and walks wtf8_step with RuntimeHandleScope rooting, publishing each slot only after its write and barrier. test_gap_9431_array_from_lone_surrogate.ts (27 diff lines + a thrown TypeError before). Verified on main 0a1c137d90 with a fresh build: fixture byte-identical to node --experimental-strip-types (stdout, stderr, and exit code).
Activity
fix(runtime): Array.from(str) keeps lone surrogates (PerryTS#9431)
fix(runtime): inspect decodes classes, holes and promise state (#9415)…
proggeramlug commentedon Sep 2, 2026
Fixed by PR #9461:
js_array_from_string_codepointsdropped itsfrom_utf8validity gate (perry payloads are WTF-8, so any lone surrogate emptied the whole array — mapped form included) and walkswtf8_stepwithRuntimeHandleScoperooting, publishing each slot only after its write and barrier.test_gap_9431_array_from_lone_surrogate.ts(27 diff lines + a thrown TypeError before). Verified on main0a1c137d90with a fresh build: fixture byte-identical tonode --experimental-strip-types(stdout, stderr, and exit code).