Problem
Intl.RelativeTimeFormat.prototype.formatToParts rebuilds each integer run byte-by-byte in an arena-backed ArrayList, converts it to an owned arena slice, and then immediately copies that slice again into the result string. The first allocation is only invocation scratch but remains retained until Context teardown.
The focused Intl structural part results are reclaimed under a bounded precise heap witness exposes this at the exact 4 MiB boundary: allocation recovery frees the result graph down to roughly 3.72 MiB, yet a later run.append(self.arena, c) can still hit the arena chunk boundary and escape as OutOfMemory. Baseline layout barely passes; the retained scratch is logically unnecessary regardless of layout.
Required implementation
- Partition the already-owned
r.int_strwith start/end indexes and pass slices directly to number translation/result copying. - Preserve grouping boundaries, numbering-system translation, part types, unit fields, and observable output.
- Do not raise the heap limit, special-case English, retain a second buffer, or weaken the bounded witness.
Acceptance
- Existing RelativeTimeFormat grouping/numbering semantic tests pass.
Intl structural part results are reclaimed under a bounded precise heappasses normally and under TSan.- Test262 Intl RelativeTimeFormat subtree has no regressions.