Skip to content

Inspector: handle BigInt/Symbol in jsToInspectorValue instead of asserting - #384

Open
robobun wants to merge 1 commit into
mainfrom
claude/inspector-bigint-symbol-returnbyvalue
Open

Inspector: handle BigInt/Symbol in jsToInspectorValue instead of asserting#384
robobun wants to merge 1 commit into
mainfrom
claude/inspector-bigint-symbol-returnbyvalue

Conversation

@robobun

@robobun robobun commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

What

Runtime.evaluate / Runtime.callFunctionOn / Debugger.evaluateOnCallFrame with returnByValue: true on a result that holds a BigInt or Symbol reached ASSERT_NOT_REACHED in Inspector::jsToInspectorValue, aborting an assertions build. Release builds fell through to nullptr and the caller reported the unrelated "Object has too long reference chain (must not be longer than 1000)" error.

Reproduces with any of: [1n], ({a:1n}), Symbol("s"), ({b:Symbol()}). A bare top-level 1n is fine because InjectedScriptSource.js never stores it on RemoteObject.value.

Fix

  • Add an explicit isBigInt() || isSymbol() arm to jsToInspectorValue that returns nullptr (unserializable) instead of falling into ASSERT_NOT_REACHED.
  • Replace the "Object has too long reference chain" error string in makeCall / makeAsyncCall with "Object couldn't be returned by value", matching V8's inspector wording and accurate for both the depth-limit and the unserializable-primitive cases.

Repro

bun --inspect=127.0.0.1:<port>/tok -e "setInterval(()=>{},1000)" &
# connect WebSocket to ws://127.0.0.1:<port>/tok, send:
{"id":1,"method":"Runtime.evaluate","params":{"expression":"[1n]","returnByValue":true}}

Assertions build before: SHOULD NEVER BE REACHED in InjectedScriptBase.cpp:96, SIGABRT.
Release before: {"error":{"code":-32000,"message":"Object has too long reference chain ..."}}.
After: {"error":{"code":-32000,"message":"Object couldn't be returned by value"}} on both, debuggee stays alive.

…rting

Runtime.evaluate / Runtime.callFunctionOn with returnByValue:true on a
result that contains a BigInt or Symbol (for example [1n], {a:1n}, or
Symbol()) reached the ASSERT_NOT_REACHED at the end of
jsToInspectorValue, aborting an assertions build. Release builds fell
through to nullptr and the caller reported the unrelated 'Object has too
long reference chain' message.

Return nullptr explicitly for BigInt and Symbol (they have no JSON
representation), and replace the misleading depth-limit message with the
same 'Object couldn't be returned by value' wording V8's inspector uses,
which is accurate for both the depth limit and the unserializable-primitive
cases.
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Changes

Inspector value conversion

Layer / File(s) Summary
Conversion handling and error reporting
Source/JavaScriptCore/inspector/InjectedScriptBase.cpp
jsToInspectorValue treats BigInt and Symbol values as non-representable JSON values. Synchronous and asynchronous conversion failures now report "Object couldn't be returned by value".
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the change to BigInt and Symbol handling in jsToInspectorValue.
Description check ✅ Passed The description clearly explains the bug, affected APIs, reproduction, fix, and resulting behavior, but it omits the required Bugzilla link and reviewer line.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Source/JavaScriptCore/inspector/InjectedScriptBase.cpp`:
- Around line 69-74: Add regression tests for the non-JSON handling in
InjectedScriptBase, covering direct 1n, direct Symbol(), and nested [1n] values
with returnByValue enabled. Exercise synchronous and asynchronous
Runtime.evaluate and Runtime.callFunctionOn flows, plus
Debugger.evaluateOnCallFrame where supported, and assert the "Object couldn't be
returned by value" error while confirming execution completes without reaching
ASSERT_NOT_REACHED.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 904ce0ce-dc1a-4f63-8543-0825b32e83ff

📥 Commits

Reviewing files that changed from the base of the PR and between e6e37cd and 0cd81ac.

📒 Files selected for processing (1)
  • Source/JavaScriptCore/inspector/InjectedScriptBase.cpp

Comment on lines +69 to +74
// BigInt and Symbol have no JSON representation. They can reach this point
// when Runtime.evaluate / callFunctionOn is invoked with returnByValue on a
// result that holds one (e.g. `[1n]` or `Symbol()`), so report the value as
// not representable rather than hitting ASSERT_NOT_REACHED below.
if (value.isBigInt() || value.isSymbol())
return nullptr;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add regression coverage for non-JSON values.

Add or verify tests for direct 1n, direct Symbol(), and nested values such as [1n] with returnByValue: true. Cover the synchronous and asynchronous paths, including Runtime.evaluate, Runtime.callFunctionOn, and Debugger.evaluateOnCallFrame where applicable. Assert "Object couldn't be returned by value" and verify that execution does not reach ASSERT_NOT_REACHED.

🧰 Tools
🪛 Cppcheck (2.21.0)

[style] 69-69: The function 'inspectorEnvironment' is never used.

(unusedFunction)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Source/JavaScriptCore/inspector/InjectedScriptBase.cpp` around lines 69 - 74,
Add regression tests for the non-JSON handling in InjectedScriptBase, covering
direct 1n, direct Symbol(), and nested [1n] values with returnByValue enabled.
Exercise synchronous and asynchronous Runtime.evaluate and
Runtime.callFunctionOn flows, plus Debugger.evaluateOnCallFrame where supported,
and assert the "Object couldn't be returned by value" error while confirming
execution completes without reaching ASSERT_NOT_REACHED.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — small, well-scoped fix that stops the inspector from asserting on BigInt/Symbol under returnByValue and gives a clearer error string.

What was reviewed:

  • Verified JSValue::isBigInt() covers both BigInt32 and HeapBigInt, and isSymbol() guards on isCell() — safe to call at that point in the type ladder.
  • Placement before isObject() is correct; these were the only primitive kinds that previously fell through to ASSERT_NOT_REACHED.
  • Confirmed nothing else in the tree matches the old "Object has too long reference chain" string, so the message change is self-contained.
Extended reasoning...

Overview

The PR touches a single file, Source/JavaScriptCore/inspector/InjectedScriptBase.cpp, with two changes: (1) an early return nullptr in jsToInspectorValue when the value is a BigInt or Symbol, and (2) rewording the error string produced by makeCall / makeAsyncCall when toInspectorValue returns null. Net effect: an assertions build no longer aborts when Runtime.evaluate with returnByValue: true encounters a BigInt/Symbol, and release builds report a message that actually describes the failure.

Security risks

None. This is inspector-protocol serialization code that runs only when a debugger is attached. The new branch does no allocation or coercion — it just returns nullptr, which was already the release-build behavior via the ASSERT_NOT_REACHED(); return nullptr; fallthrough. The error-string change is a literal constant.

Level of scrutiny

Low. The diff is ~10 lines, mechanical, and confined to a debugging/inspector path. The release-build semantics for the BigInt/Symbol case are unchanged (still nullptr); only the debug-build assert and the user-facing error text differ. I checked JSCJSValueCell.h to confirm isBigInt() handles both the BigInt32 tag and heap BigInts and that isSymbol() is a null-safe cell-type check, so the new arm slots correctly between the existing primitive checks and the isObject() branch.

Other factors

A repo-wide grep found no other consumers of the old "Object has too long reference chain" string, so nothing depends on the exact wording. The new message matches V8's inspector wording per the PR description, which is a reasonable choice for tooling compatibility. No prior review comments or bot findings on this PR.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Preview Builds

Commit Release Date
0cd81acb autobuild-preview-pr-384-0cd81acb 2026-08-03 19:16:05 UTC

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.

1 participant