ReviewOS

zig-utils/zig-js

C API: harden host and private property-name deduplication

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

Parents: #493, #495 Related: #759, #761

Problem

The public C host-class property-name accumulator and the private ABI prototype property iterator still place host/source-controlled names in default-seeded native string maps. Predictable placement permits collision-heavy callback results and prototype graphs at the embedding boundary. The private non-indexed own-property traversal also builds a second default map even though its objectOwnKeysList input has already enforced exact own-key uniqueness.

Scope

  • Reuse one lazy, unpredictable, exact-byte Wyhash membership design for the public host-class accumulator and each private prototype iterator invocation.
  • Publish the context only after the first successful table mutation; secure-provider or allocation failure must leave no partial membership state.
  • Preserve duplicate callback-name elision before allocating another JSString, inherited-name suppression rules, non-enumerable prototype behavior, integer/string/Symbol filtering, callback order, and pending-exception/OOM publication.
  • Remove the private non-indexed traversal membership table only after documenting and testing the objectOwnKeysList uniqueness invariant that makes a second deduplication pass unreachable.
  • Keep empty/candidate-free paths allocation- and entropy-free.

No-workaround rules

  • No property/depth cap, source rewriting, deterministic fallback seed, hash-only equality, skipped host/prototype/Proxy keys, reordered callbacks, swallowed allocation failure, or weakened ABI behavior.
  • No stack, queue, job, Promise, Worker, or Map/Set iterator implementation changes.

Acceptance

  • Both necessary C/private ABI string memberships use independent lazy secure contexts; the redundant own-key table is removed with an explicit invariant.
  • Wide, embedded-NUL, duplicate host/static, inherited shadowing, non-enumerable prototype, Symbol, and empty cases preserve exact order and behavior.
  • First entropy/allocation failure publishes no context/table and reaches the existing C/private ABI failure channel.
  • Focused public/private ABI normal and TSan tests pass with zero leaks/races.
  • Exact-parent relevant Test262 and ABI fixtures have nonzero accounting and zero regressions.
9 days ago

Implemented and pushed to main in fix(c-api): seed property name membership (#762). Public host-class and private prototype deduplication now use lazy secure exact-byte contexts; the private own-property traversal relies directly on its already-unique objectOwnKeysList snapshot. Focused normal/TSan are 2/2, C-API differential matches JSC on 34/34 rows on parent and candidate, Home private ABI is 392/392, and exact-parent Reflect/Proxy/for-in remains 155/155 with 0 flips.

9 days ago

Generalization follow-up #763 landed in fix(private-abi): seed borrowed string interning (#763): property membership now shares one reviewed generic primitive with private borrowed-view and heap-snapshot value maps; C/JSC remains 34/34.

Sign in to comment on this issue.