ReviewOS

zig-utils/zig-js

Strings: bound repeat construction and empty-input work

#781
Closed chris opened this 9 days ago ·
9 days ago

Parents: #473, #493 Related: #480, #777, #780

Problem

String.prototype.repeat appended the receiver once per requested repetition. For an empty receiver every append was a no-op; the generic 32-bit toLen clamp turned "".repeat(Number.MAX_SAFE_INTEGER) into 4,294,967,295 useless loop iterations despite the required result being the empty string.

That clamp was also the wrong abstract operation: repeat requires ToIntegerOrInfinity, so a negative fraction such as -0.5 truncates to negative zero and must return "", not throw. For non-empty strings the repeated ArrayList growth performed multiple allocations and copies before constructing the final StringCell, while count 1 rebuilt immutable content that was already final.

Scope

  • Preserve ToString and exact ToIntegerOrInfinity count coercion/error ordering.
  • Return immediately for count 0 and for an empty receiver after count validation.
  • Retain the existing StringData cell for count 1.
  • Enforce the engine string-size ceiling before allocation with checked exact sizing.
  • Allocate the canonical result buffer exactly once and fill ordinary strings with logarithmically many doubling copies.
  • Stream flat Latin-1 input without a source transcode and canonicalize cross-copy surrogate pairs exactly.
  • Preserve lone-surrogate, astral, OOM, heap-limit, and moving-GC behavior.

No-workaround rules

  • No arbitrary count clamp, silent truncation, precomputed input result, changed RangeError boundary, host string library, or weakened allocation failure.
  • No stacks, queues, jobs, Promise, Worker, or Map/Set iterator changes.

Acceptance

  • Empty input is O(1) after required count coercion, including maximum finite counts.
  • Count 1 retains the exact StringData cell without transcode or allocation.
  • Non-empty output uses checked exact sizing and bounded copy rounds.
  • Focused normal/TSan/OOM units, exact-parent String Test262, threadfuzz, and the full unit gate pass without regressions.
9 days ago

Implementation landed on main in a42cf61e.

  • Exact ToIntegerOrInfinity replaces the unrelated 32-bit length clamp; -0.5 now correctly becomes negative zero.
  • Maximum-finite-count empty input returns after validation with zero allocations; count 1 retains raw StringData identity.
  • Non-empty results are size-checked before allocation, flat Latin-1 streams without a source snapshot, ordinary content uses logarithmic doubling, and cross-copy surrogate pairs remain canonical.
  • Exact-parent Test262 built-ins/String: 1,223 -> 1,223, zero failures/flips; prototype/repeat: 16/16.
  • Focused witness: 1/1 normal and 1/1 TSan, zero leaks/sanitizer reports.
  • Threadfuzz: 400 programs, zero failures.

The issue remains open only for the shared clean-host full unit gate.

9 days ago

Acceptance is complete. Clean main CI run 33071676798 passed all four ordinary unit shards at 872dbbb5; the issue-specific focused normal/TSan/OOM, exact-parent Test262, allocation, and deterministic fuzz evidence is recorded above. Closing with no semantic regressions.

Sign in to comment on this issue.