You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(runtime): #5844 — Proxy trap dispatch fixes across getOwnPropertyDescriptor, has, set, and setPrototypeOf (#5882)
* fix(runtime): #5844 — Proxy trap dispatch fixes across getOwnPropertyDescriptor, has, set, and setPrototypeOf
Fixes 12 of 33 test262 built-ins/Proxy failures, zero regressions
(verified against built-ins/Proxy, built-ins/Object, built-ins/Reflect,
language/expressions/in — 219/219/3132/101/15 pass respectively).
Root causes, all variations on "a Proxy is a small registered id, not a
real heap pointer, and several generic object-machinery code paths
either mis-treated it as one or never checked for it at all":
- js_reflect_get_own_property_descriptor: the missing-trap fallback read
the target's descriptor via the raw ObjectHeader path even when the
target was itself a Proxy; now recurses through the Reflect entry
point so a chain of trap-less proxies forwards correctly.
- ordinary_has_property (the `in` operator's prototype-chain walk) and
its array-fast-path counterpart didn't recognize a Proxy sitting in
the recorded `[[Prototype]]` chain, silently returning false (or
reading garbage) instead of dispatching the proxy's `has` trap.
- ordinary_set_with_receiver's prototype-chain walk had the same gap on
the write side, and `js_proxy_set`/`Reflect.set` didn't thread a
distinct `receiver` through to the trap when a Proxy was reached via
a prototype hop rather than as the direct assignment target.
- Object.create(proto) and Object.setPrototypeOf(obj, proto) rejected a
Proxy `proto` argument outright (their "is this an object" checks
don't recognize the small registered id), and Object.create had no
path to record a Proxy prototype at all — it can't be modeled via the
synthetic-class-id machinery used for real prototype objects, so route
it through the same static-prototype side table setPrototypeOf uses.
- Object.setPrototypeOf's cycle-detection walk called
`[[GetPrototypeOf]]` unconditionally while probing the candidate
prototype's chain, including on a Proxy — invoking its trap as an
unrelated side effect of cycle-safety bookkeeping (OrdinarySetPrototypeOf
step 7.b.ii.1 says to stop the walk there instead).
Also fixed, found while debugging the above with a fresh (Proxy-free)
repro: the cycle-detection loop's Floyd's tortoise-and-hare walk only
guarded `tortoise` against an already-null position before advancing;
`hare` (which steps twice per iteration) had no equivalent guard, so a
2-hop-to-null prototype chain re-advanced an already-null `hare` and
threw "Cannot convert undefined or null to object" on a plain, entirely
ordinary `Object.setPrototypeOf({}, {foo: 1})`.
Refs #5844.
* refactor(runtime): move js_proxy_set/proxy_set_with_receiver into proxy/put_value.rs
proxy.rs grew to 2004 lines after rebasing onto main (which independently
added ~30 lines), tripping the 2000-line file-size CI gate. Relocate the
Proxy [[Set]] entry points into the sibling put_value.rs submodule
(already the natural home for PutValue/[[Set]] dispatch) rather than
trim comments to fit — same pattern as the file's other topical splits.
Pure code motion, no behavior change (re-verified: built-ins/Proxy still
219 pass / 21 runtime-fail).
---------
Co-authored-by: Ralph <ralph@skelpo.com>
0 commit comments