ReviewOS

zig-utils/zig-js

C API: canonicalize callable and class-name StringData egress

#692
Closed chris opened this 8 days ago ·
8 days ago

Parents: #495, #473 Related: #672, #674, #687

Problem

Private C/ABI name and diagnostic helpers still return Value.asStr() for user-controlled function name/displayName, Symbol.toStringTag, and constructor-name data properties. That slice is the StringCell physical image, not canonical WTF-8. Once flat Latin-1 storage is active, non-ASCII names can escape as raw one-byte code units, producing invalid UTF-8 and representation-dependent class/diagnostic output.

Scope

  • Canonicalize callable display names, class names, and no-side-effect diagnostic name rendering at the owning Context/Interpreter boundary.
  • Cover JSC__JSValue__getNameProperty, getClassName, getName, calculated-display-name exports, invalid-argument type formatting, and object inspection paths that share these helpers.
  • Preserve own-data-first lookup, Proxy/getter avoidance, constructor/tag precedence, borrowed-view lifetime, and exact observable exception ordering.
  • Propagate OOM through the existing pending-exception/private-string channels; do not substitute, truncate, retry, or expose physical bytes.
  • Add a real flat-storage witness for Latin-1 names/tags plus canonical-storage controls.

No-workaround rules

  • No global canonicalization, forced UTF-16 storage, lossy UTF-8 repair, ASCII-only restriction, hidden getter invocation, or allocation-failure fallback.
  • No stacks, queues, jobs, Promise, microtask, Worker-lifecycle, or Map/Set iterator changes.

Acceptance

  • Every affected name/class/diagnostic egress path consumes canonical WTF-8.
  • Flat Latin-1 and canonical storage produce byte-identical public output for non-ASCII names and tags.
  • Proxy/getter avoidance, constructor/tag precedence, borrowed lifetime, and OOM behavior remain exact.
  • Focused Debug/forced-flat/TSan, full units, ABI fixtures, and applicable Test262 inventories pass with exact accounting.
8 days ago

Implemented and landed on main in 09941fcd.

Private callable display names, class names, Symbol.toStringTag values, and received-value diagnostic constructor names now cross the C/private ABI boundary as canonical WTF-8 through caller-owned allocators. Own-data-first lookup, Proxy/getter avoidance, observable constructor ordering, borrowed-view lifetime, and explicit OOM propagation are preserved; there is no lossy fallback or representation-wide conversion.

Validation:

  • Focused name + diagnostic tests: 2/2 Debug, 2/2 forced flat Latin-1, 2/2 ReleaseSafe, 2/2 TSan
  • Forced-flat coverage includes a fail-first allocation assertion
  • C API audit: 117/117 declarations complete, 117 public symbols, 460 private-profile exports
  • Bun private ABI: 437/437 implemented private symbols; Home private ABI: 447/447
  • Relevant ErrorCode and C-API extension fixtures pass
  • Full Debug: 1789 passed, 1 skipped, 0 failed, 0 leaked
  • Full TSan: 1788 passed, 2 skipped, 0 failed, 0 leaked
  • Exact Test262 search for the affected private export identifiers: 0 files, so 0 measured flips

The flat-storage switch was restored to false with no tracked diff before commit.

Sign in to comment on this issue.