Skip to content

fix(reflect): receiver-aware get, apply thisArg, construct newTarget, has chain, ownKeys symbols, setPrototypeOf failure#3499

Merged
proggeramlug merged 2 commits into
mainfrom
fix-reflect-semantics2-2766-2761
May 31, 2026
Merged

fix(reflect): receiver-aware get, apply thisArg, construct newTarget, has chain, ownKeys symbols, setPrototypeOf failure#3499
proggeramlug merged 2 commits into
mainfrom
fix-reflect-semantics2-2766-2761

Conversation

@proggeramlug
Copy link
Copy Markdown
Contributor

Implements correct Node non-proxy semantics for six Reflect operations. Each behavior is asserted byte-for-byte against node --experimental-strip-types in test-files/test_gap_reflect_semantics2.ts under the default auto-optimize compile.

Closes #2766
Closes #2767
Closes #2764
Closes #2763
Closes #2761

Implementation

Dropped

  • runtime: make Reflect.construct honor newTarget, array-like args, and constructor errors #2768 Reflect.construct newTarget: dropped. Honoring newTarget, array-like args, and constructor errors requires a real runtime construct-from-value path (constructing an arbitrary function/class value with a custom prototype), which Perry does not have today - non-proxy Reflect.construct only works through the compile-time fold to new ClassName(...). Left unchanged rather than ship a broken partial.
  • Proxy three-argument get traps, ownKeys traps, and setPrototypeOf traps are out of scope (Perry's proxy traps are two-argument with no ownKeys/setPrototypeOf dispatch). The ordinary-object behavior is implemented; proxy targets fall through to their underlying target.

Validation

  • test-files/test_gap_reflect_semantics2.ts is byte-identical to Node v25 (get-with-receiver+getter, apply thisArg+array-like+TypeErrors, has-on-inherited+TypeError, ownKeys-with-Symbol+TypeError, setPrototypeOf-on-preventExtensions'd to false + bad-arg TypeErrors).
  • Regression: test_gap_proxy_reflect.ts and test_gap_reflect_2756_2762.ts stay byte-identical to Node.
  • cargo test -p perry-hir (incl. expr_variant_stable_hash_tags_are_unique) and cargo test -p perry-runtime green.
  • ./scripts/check_file_size.sh and cargo fmt --all -- --check clean.
  • New Expr::ReflectSetPrototypeOf uses stable-hash tag 12230. Retention #[used] anchors added for the codegen-only reflect entry points; verified each symbol survives the auto-optimize whole-program bitcode rebuild.

HIR

  • New variant Expr::ReflectSetPrototypeOf { target, proto } (tag 12230).
  • New field receiver on the existing Expr::ReflectGet.

Ralph Küpper added 2 commits May 31, 2026 03:13
…ymbols, setPrototypeOf failure

Implement Node-compatible non-proxy semantics for six Reflect operations:

- #2766 Reflect.get(target, key, receiver): carry the optional receiver
  through HIR/codegen/runtime; rebind an accessor getter's this to the
  receiver (via clone_closure_rebind_this) and throw TypeError on a
  non-object target.
- #2767 Reflect.apply(fn, thisArg, argumentsList): bind thisArg, implement
  CreateListFromArrayLike (array-like objects, not just Arrays), throw
  TypeError for a non-callable target or a non-object argumentsList.
- #2764 Reflect.has(target, key): full [[HasProperty]] including the
  prototype chain (probe via the inherited field read), throw TypeError on
  a non-object target, ToBoolean-normalize proxy trap results.
- #2763 Reflect.ownKeys(target): include own symbol keys after string
  names, throw TypeError on a non-object target.
- #2761 Reflect.setPrototypeOf(target, proto): return a boolean (false when
  a non-extensible target rejects a changing prototype), throw TypeError
  for a non-object target or a proto that is neither object nor null.

Proxy three-argument get traps, ownKeys traps, setPrototypeOf traps, and
the full Reflect.construct newTarget path (#2768) are out of scope and
dropped (Perry lacks those trap dispatches / a runtime construct-from-value
path).

Adds Expr::ReflectSetPrototypeOf (stable-hash tag 12230) and a receiver
field on Expr::ReflectGet. Retention anchors added for the codegen-only
reflect entry points.
@proggeramlug proggeramlug merged commit fe79c5d into main May 31, 2026
@proggeramlug proggeramlug deleted the fix-reflect-semantics2-2766-2761 branch May 31, 2026 01:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment