Parents: #473, #493 Related: #623, #665, #766
Problem
#766 makes cached-ASCII UTF-16 length and indexed reads constant time. Every non-ASCII canonical WTF-8 cell still resolves an abstract UTF-16 index by constructing a code-unit iterator at byte zero. A sequential reader such as for (let i = 0; i < s.length; i++) s.charCodeAt(i) therefore performs quadratic decoding work on BMP, astral, and lone-surrogate inputs. Primitive and boxed string exotic index reads share the same underlying scan.
This is an attacker-controlled complexity surface and a material gap from a production JavaScript engine string model.
Scope
- Freeze benchmark-first sequential and high-index witnesses for BMP, astral, lone-surrogate, mixed, Latin-1, and ASCII controls through both String builtins and primitive/boxed exotic properties.
- Measure representation-native flat storage versus a bounded immutable UTF-16 offset index before choosing the runtime shape.
- Make repeated non-ASCII UTF-16 index resolution bounded: O(1) for a flat representation or O(stride) after one O(n) index construction.
- Preserve exact UTF-16 length, surrogate-half visibility, codePointAt pairing, canonical WTF-8 equality/hashing/interning, property descriptors, and ABI string egress.
- Keep metadata proportional to immutable string storage, lazily absent on strings that are never indexed, and released exactly once across arena, interned, external, and GC-managed cell lifetimes.
- Publish any lazy metadata race-free under no-GIL; moving GC must preserve or relocate its identity without stale cell-pointer keys.
- Make allocation and entropy failure atomic and catchable where the public operation can allocate; allocation-free length/has/descriptor probes must keep an exact non-allocating path.
No-workaround rules
No source/workload recognizer, ASCII-only claim presented as completion, process-global cache, unbounded per-index memoization, eager index allocation for every string, UTF-8 byte indexing, skipped surrogate halves, disabled moving GC, leaked side table, or OOM fallback that silently restores attacker-sized repeated rescans.
No stacks, queues, jobs-runtime, Promise, microtask, Worker-lifecycle, or Map/Set iterator changes.
Acceptance
- Benchmark-first rows freeze equal logical work, checksums, representations, allocation replay, and 1K/2K/4K growth before the runtime change.
- BMP, astral, lone-surrogate, and mixed sequential reads demonstrate bounded candidate growth; ASCII and Latin-1 controls do not regress materially.
- charAt, charCodeAt, at, codePointAt, primitive indices, boxed exotic indices, length, descriptors, enumeration, and delete/set/has boundaries remain semantically identical.
- Metadata construction/publication is bounded, race-free, failure-atomic, moving-GC safe, and released under managed, arena, interned, and external string lifetimes.
- Focused units, OOM/fault injection, moving GC, no-GIL/TSan, full units, and exact String Test262 accounting pass with before -> after results.
- Exact-parent raw evidence and methodology are checked in without converting noisy wall time into a claim.