Parent: #495; related: #471, #498. Found while auditing native frame/property guards after #1086.
Executed public-C reproduction
A JSClassRef getProperty callback increments a private counter for value. Initially it returns NULL (unhandled), so the host object's ordinary prototype supplies value = 7. The same function reads that host 64 times. The private state then makes the callback return 99, followed by one more unhandled read. Neither object shape nor prototype changes.
The identical C fixture was compiled against system JavaScriptCore and a freshly built zig-js library at 102da458:
system JSC:
warm=448 callbacks=64
handled=99 callbacks=65
unhandled=7 callbacks=66
zig-js:
warm=448 callbacks=7
handled=7 callbacks=7
unhandled=7 callbacks=7The inherited cache bypasses the receiver's host get hook, even when it previously declined and must run again. Current source records a one-hop inherited data observation after the host callback returned unhandled. Generated code rejects host-owner objects, but the fallback inherited-cache helper consumes the observation without checking that receiver hook.
Required change
- Publish/consume inherited data observations only when the receiver-to-holder lookup prefix is free of mandatory observable get behavior.
- A host get callback that declined one read must execute on the next read; do not assume it remains unhandled or use shape equality as a callback-state version.
- Retain safe ordinary own-data and ordinary inherited-data fast paths.
- Pin the public-C/JSC transcript and test actual native cache fallback/frame safety, exception/order, GC, and shared-mode behavior. No new ABI or weaker callback contract.
Definition of done
- The public-C reproduction exactly matches the system-JSC values and callback counts.
- Canonical observations, native inherited-cache consumption, and native caller-frame proof all preserve host get behavior.
- Focused Debug, ReleaseSafe, unsuppressed TSan and real-GC coverage passes; safe ordinary inherited caching remains exercised.
- Public C ABI audits/fixtures and affected corpus path comparisons pass with scoped evidence; docs inventory remains accurate.