ReviewOS

zig-utils/zig-js

C API: canonicalize String keys at value-property boundaries

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

Parent: #495 Related: #672, #666

Problem

The public C API helper propertyKeyBytes completes ToPropertyKey correctly but returns key.asStr() for String Values. asStr() is the StringCell physical image, while JSObjectHasPropertyForKey, JSObjectGetPropertyForKey, JSObjectSetPropertyForKey, and JSObjectDeletePropertyForKey all pass those bytes to semantic property lookup as canonical WTF-8.

This is byte-identical while flat Latin-1 storage remains disabled. Once the owned flat-string model is enabled, a non-ASCII Latin-1 runtime String key can address the wrong property even though the C API coercion and handle contracts remain valid. Private ABI egress was corrected separately in #672; the public value-key boundary needs its own pinned C API coverage.

Scope

  • Route public String Value keys through representation-aware canonical WTF-8 egress after ToPropertyKey.
  • Preserve Symbol identity, object coercion order, thrown exceptions, context affinity, attributes, and handle lifetime.
  • Map canonicalization OOM through the existing public exception out-parameter.
  • Keep ASCII and already-canonical String Values on the allocation-free borrowed path.
  • Cover non-ASCII Latin-1 set/get/has/delete semantics plus existing Symbol, numeric, throwing-coercion, and attribute behavior.
  • Run the public C ABI inventory/audit and C boundary fixtures with no symbol, layout, or header changes.

No-workaround rules

  • No eager global String canonicalization, raw internal pointer exposure, flat-storage disablement, lossy UTF-8 conversion, exception suppression, alternate-property retry, or ABI change.

Acceptance

  • All four JSObject*PropertyForKey entry points consume canonical semantic bytes for String Values.
  • ASCII/canonical keys borrow; a future flat Latin-1 key performs one bounded arena conversion.
  • Non-ASCII key round trips and delete behavior are exact with null exception on success.
  • OOM remains observable at the public exception boundary.
  • Focused Debug/ReleaseSafe/TSan and public C ABI audits/fixtures pass; Test262 flips are reported exactly.
9 days ago

Landed on main as fix(c-api): canonicalize value property keys (#674).

All public JSObject*PropertyForKey calls now consume canonical WTF-8 after ToPropertyKey. ASCII and current canonical cells borrow their bytes; a future flat Latin-1 String converts once in the context arena, and allocation failure remains observable through the public exception out-parameter. Symbol identity, numeric/object coercion, thrown exceptions, attributes, affinity, and handles are unchanged.

Final evidence on Zig 0.17.0-dev.1818:

  • Focused Debug: 1/1 passed, zero leaks.
  • Focused ReleaseSafe: 1/1 passed, zero leaks.
  • Focused TSan: 1/1 passed, zero races/failures/leaks.
  • Public C audit: 117/117 complete, all public symbols present.
  • Home public ABI: 50/50 linked; runtime smoke passed.
  • C, C++, and inspector public-host fixtures passed.
  • Full units: 1767 passed, 1 skipped, 0 failed, 0 leaked.
  • Test262 flips: 0; no public-host cases apply.

No eager canonicalization, ABI/header/layout change, retry, fallback property, exception suppression, or raw pointer exposure was introduced.

Sign in to comment on this issue.