Parent: #473 Related security/performance parent: #493 Builds on: #622, #623
Problem
The plain-string paths for String.prototype.replace, replaceAll, and non-empty-separator split search the engine's WTF-8 backing bytes. ECMAScript defines these searches, match positions, and substrings over UTF-16 code units. Consequently, a separator or search string containing one surrogate half cannot match that half inside an astral scalar, replacement callback positions can diverge, and replaceAll("") skips the boundary between the two halves of an astral scalar.
Required implementation
- Reuse the exact UTF-16 matcher introduced by #622/#623 instead of byte offsets on non-ASCII strings.
- Preserve an allocation-free ASCII fast path.
- Collect
replaceAllmatch positions before invoking replacement callbacks, per ECMA-262, while keeping the scan bounded-linear and non-overlapping. - Assemble preceding/trailing replacement spans and split substrings in UTF-16 space, including boundaries inside astral scalars and lone surrogates.
- Keep matcher scratch bounded, explicitly owned, and released on success and error paths.
- Do not implement repeated-from-zero searches, byte-offset approximations, input-specific shortcuts, or third-party matching.
Acceptance
- Focused tests cover astral high/low-half searches and separators, lone surrogates, empty search strings, overlaps, callback positions/order, substitution tokens, limits, and ASCII behavior.
- Exact parent/candidate Test262 accounting for
replace,replaceAll, andsplithas no regressions. - Focused normal and TSan tests pass without leaks.
- The full parallel unit suite passes.
- Growth/adversarial probes establish bounded-linear matching work and bounded scratch lifetime.
Specification
- ECMA-262
String.prototype.replaceusesStringIndexOfand UTF-16 substring boundaries. replaceAllfirst builds the complete non-overlapping match-position list, advancing bymax(1, searchLength).splitrepeatedly appliesStringIndexOfand forms UTF-16 substrings.