Skip to content

fix(runtime): a built-in callee receives the primitive this, not a ToObject wrapper - #11524

Merged
proggeramlug merged 2 commits into
mainfrom
claude/lucid-faraday-215csd
Sep 27, 2026
Merged

proggeramlug merged 2 commits into
mainfrom
claude/lucid-faraday-215csd

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

call_primitive_closure_value wrapped a primitive receiver with js_object_coerce for every non-strict callee, built-ins included. ECMA-262 §10.3.1 says a built-in's [[Call]] receives thisArg unchanged and does its own coercion. This re-lands the intent of #9800's 32f150b22 on current main, without the per-instance side table.

Changes

  • closure/registry.rs: adds a BUILTIN kind bit to the existing per-body ClosureBodyRecord flags, next to STRICT and perf: new Promise(executor) is 43–80× slower than Node, 11× slower than Promise.resolve (per-promise name/length side-table metadata + global epoch bumps) #10521's NON_CONSTRUCTOR. Also adds:
    • register_closure_body_builtin(func_ptr), which sets the bit once per thunk body
    • body_receives_primitive_this(func_ptr), which answers STRICT | BUILTIN from one body-record lookup
  • native_call_method.rs: the call site uses that single lookup. It previously made one lookup for strictness, so the hot path does no extra work.
  • Built-in marking happens in install_proto_method, install_proto_method_rest_with_length and primitive_proto_method_closure_value. That covers the String, Number, Boolean, BigInt, Symbol and Object prototype methods.
  • Unlike 32f150b22, this does not use builtin_closure_length, which is a ptr-keyed per-closure side table. No new table and no per-closure entries.
  • The bit is a positive mark, so any body not registered as a built-in keeps the old wrapper behaviour.
  • changelog.d/ fragment. No version bump.

Related issue

Closes #11509

Test plan

  • New #[test] builtin_callee_gets_the_primitive_receiver_and_a_user_callee_the_wrapper in native_call_method/code_point_at_dispatch_tests.rs. It is behavioural and checks both directions using the boxed-primitive wrapper counter:
    • a thunk installed via install_proto_method gets the raw string, returns the right answer, and creates no wrapper
    • an unregistered (sloppy user) closure body still gets boxed
  • Sabotage-checked: I reverted the call-site condition to the strict-only check. The new test went red (a built-in callee must receive the primitive, not a ToObject wrapper). With the fix restored it passes.
  • RUST_TEST_THREADS=1 cargo test --release -p perry-runtime --lib code_point_at_dispatch: 3 passed.
  • Lint gates are clean: cargo fmt --all -- --check, check_file_size.sh, raw_handle_debt.py, addr_class_inventory.py, gc_runtime_root_holders.py, gc_rekeyed_key_tables.py.
  • Gap-suite A/B against pristine main: in progress. This environment can't install LLVM 22 (apt.llvm.org is blocked), so I'm running it locally with a subprocess-clang compiler build on both arms. I'll post the results here.

Checklist

  • I have NOT bumped the workspace version or edited CLAUDE.md / CHANGELOG.md
  • Commits follow the fix: prefix convention

Generated by Claude Code

…ToObject wrapper (#11509)

ECMA-262 §10.3.1: a built-in function's [[Call]] does not run
OrdinaryCallBindThis; it receives thisArg unchanged and coerces itself.
call_primitive_closure_value still boxed a primitive receiver for every
non-strict callee, built-ins included, minting a String wrapper with an
own index property per UTF-16 code unit.

Re-lands the intent of #9800's 32f150b without its per-instance
builtin_closure_length side-table lookup: built-in-ness is a new BUILTIN
kind bit on the closure BODY record (next to STRICT and NON_CONSTRUCTOR),
set once per thunk by the prototype-method installers, and checked in the
same single body-record lookup the call site already made for strictness.
@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 65946c35-8259-4851-9396-edc9cd6a40ee

📥 Commits

Reviewing files that changed from the base of the PR and between b105e8a and fe87b15.

📒 Files selected for processing (7)
  • changelog.d/11524-builtin-callee-no-toobject.md
  • crates/perry-runtime/src/closure/mod.rs
  • crates/perry-runtime/src/closure/registry.rs
  • crates/perry-runtime/src/object/global_this/install_static.rs
  • crates/perry-runtime/src/object/native_call_method.rs
  • crates/perry-runtime/src/object/native_call_method/code_point_at_dispatch_tests.rs
  • crates/perry-runtime/src/object/primitive_proto_thunks.rs
 __________________________________________________________
< Not just a pretty face, but a pretty good code reviewer! >
 ----------------------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

proggeramlug pushed a commit that referenced this pull request Sep 27, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HEisA6oPsnE1XGzWNxLWoW
@proggeramlug
proggeramlug force-pushed the claude/lucid-faraday-215csd branch from d6a1c21 to fe87b15 Compare September 27, 2026 12:50
@proggeramlug
proggeramlug merged commit c17e7ea into main Sep 27, 2026
20 of 21 checks passed
@proggeramlug
proggeramlug deleted the claude/lucid-faraday-215csd branch September 27, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(runtime): a built-in callee receives the primitive this, not a ToObject wrapper (re-land 32f150b22 from #9800)

2 participants