ReviewOS

zig-utils/zig-js

C API: canonicalize callable and class-name StringData egress

#692
Closed chris opened this 11 days ago ·
11 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.
11 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.