Skip to content

inspector: bump WebKit so Debugger.disable is idempotent on asserts builds - #36851

Open
robobun wants to merge 1 commit into
mainfrom
farm/de685579/debugger-disable-idempotent
Open

inspector: bump WebKit so Debugger.disable is idempotent on asserts builds#36851
robobun wants to merge 1 commit into
mainfrom
farm/de685579/debugger-disable-idempotent

Conversation

@robobun

@robobun robobun commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

A Debugger.disable sent to bun --inspect on an already-disabled Debugger agent (or before any Debugger.enable) aborts an asserts build:

ASSERTION FAILED: !!m_client != !!client
vendor/WebKit/Source/JavaScriptCore/debugger/Debugger.cpp(331) : void JSC::Debugger::setClient(Client *)

Release just answers {} and continues. Reproduces over both the WebSocket and --inspect=unix: transports; the --inspect server forwards messages straight to JSC's backend dispatcher, so the crash is in WebKit. Frontends send Debugger.disable liberally on teardown (detach + close, or two attached tools each disabling), so this is an ordinary sequence rather than an exotic one.

Cause

InspectorDebuggerAgent::disable() calls internalDisable(false) unconditionally. internalDisable() runs m_debugger.setClient(nullptr), and JSC::Debugger::setClient asserts the client is transitioning (!!m_client != !!client). When m_client is already null, either because the agent was never enabled or because disable() already ran, the assert fails.

enable() guards with if (enabled()) return makeUnexpected(...); willDestroyFrontendAndBackend() guards internalDisable() with if (enabled()); InspectorHeapAgent::disable() and InspectorConsoleAgent::disable() both early-return when already disabled. InspectorDebuggerAgent::disable() is the odd one out.

Fix

oven-sh/WebKit#385 adds if (!enabled()) return { }; to InspectorDebuggerAgent::disable(), mirroring the other agents. Branched off e6e37cda21 (current WEBKIT_VERSION) so the preview bump is minimal.

This PR bumps WEBKIT_VERSION to the preview build and adds test/cli/inspect/inspect-debugger-disable.test.ts which drives disable → enable → disable → disable → enable → disable over the --inspect WebSocket and asserts all six replies arrive and the inspectee does not SIGABRT. The test is test.skipIf(!isDebug && !isASAN) since the assert is ASSERT_ENABLED-only.

Verification

$ bun bd test test/cli/inspect/inspect-debugger-disable.test.ts
# with WEBKIT_VERSION = e6e37cda21 (main):
(fail) Debugger.disable is idempotent and does not abort on asserts builds
  error: inspectee aborted on Debugger.disable (replies={}):
  ASSERTION FAILED: !!m_client != !!client
# with WEBKIT_VERSION = autobuild-preview-pr-385-10e1ab9b:
(pass) Debugger.disable is idempotent and does not abort on asserts builds [538.69ms]

test/js/node/inspector/inspector.test.ts 23/23 and test/js/bun/jsc/webkit-upgrade-3722912f.test.ts 5/5 with the bump.

Once oven-sh/WebKit#385 merges, WEBKIT_VERSION should be repointed at the merged main sha (preview releases are deleted at that point).


[decide:webkit] gate passed · iteration 2 · 2 files touched

passes on PR (with fix)
Test-only change.

Debug/ASAN (expected pass):
$ bun bd test 'test/cli/inspect/inspect-debugger-disable.test.ts'
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test test/cli/inspect/inspect-debugger-disable.test.ts
bun test v1.4.0 (5561f3f75)

test/cli/inspect/inspect-debugger-disable.test.ts:
(pass) Debugger.disable is idempotent and does not abort on asserts builds [541.04ms]

 1 pass
 0 fail
 1 expect() calls
Ran 1 test across 1 file. [2.56s]
Exit: 0
diff hotspot
scripts/build/deps/webkit.ts                      |  4 +-
 test/cli/inspect/inspect-debugger-disable.test.ts | 92 +++++++++++++++++++++++
 2 files changed, 95 insertions(+), 1 deletion(-)

gate history · 1 passed · 1 rejected · iteration 2

evidence per changed file
file                                               reads  edits  tests
scripts/build/deps/webkit.ts                           2      2      0
test/cli/inspect/inspect-debugger-disable.test.ts      0      1      0

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 6 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 662c5aaf-d75a-473e-b5ab-98e1ab9b8054

📥 Commits

Reviewing files that changed from the base of the PR and between 9b99e7c and 5561f3f.

📒 Files selected for processing (2)
  • scripts/build/deps/webkit.ts
  • test/cli/inspect/inspect-debugger-disable.test.ts

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

@robobun

robobun commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 4:08 PM PT - Aug 3rd, 2026

@robobun, your commit 5561f3f7526bbdcb4dd916cb459ebfe1d76f52b1 passed in Build #88253! 🎉


🧪   To try this PR locally:

bunx bun-pr 36851

That installs a local version of the PR into your bun-36851 executable, so you can run:

bun-36851 --bun

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I didn't find any bugs, but this pins WEBKIT_VERSION to an ephemeral preview release (autobuild-preview-pr-385-...) that the description notes will be deleted once oven-sh/WebKit#385 merges — a maintainer should sign off on landing against a preview tag vs. waiting for the merged sha.

What was reviewed:

  • prebuiltUrl/prebuiltDestDir handling of the autobuild- prefix — both branch on it correctly, so the tag resolves and the cache key is distinct.
  • New test: error/close events are wired to settle pending send() promises, stderr is drained concurrently with child.exited, and child.kill() runs from finally so a SIGABRT mid-sequence can't hang the test.
  • skipIf(!isDebug && !isASAN) matches the assert being ASSERT_ENABLED-only.
Extended reasoning...

Overview

Two files: scripts/build/deps/webkit.ts swaps WEBKIT_VERSION from commit sha 34c01d13... to the preview tag autobuild-preview-pr-385-3a8fe8a1, and test/cli/inspect/inspect.test.ts gains a ~90-line test that connects to --inspect=127.0.0.1:0 over WebSocket and issues a Debugger.disable → enable → disable → disable → enable → disable sequence, asserting six {result: {}} replies and no SIGABRT. The actual code fix lives in oven-sh/WebKit#385, not here.

Security risks

None. The change is a dependency version pin plus a test that spawns a local subprocess bound to 127.0.0.1:0 and talks to it over a loopback WebSocket. No new user-facing surface, no auth/crypto/permissions paths.

Level of scrutiny

High, because WEBKIT_VERSION selects the JavaScriptCore build for every configuration. Even though the upstream diff is described as a one-line early return, pinning main to a preview release tag is a build-infrastructure decision: the PR description itself says preview releases are deleted when the source PR merges, so this value will need to be repointed. Whether to land now against the preview or wait for the merged sha is a maintainer call — see also the upgrade-webkit skill/process this repo uses for WebKit bumps.

Other factors

The test itself is solid against the review checklist: it awaits observable conditions (URL scraped from stderr, per-id reply promises), wires close/error to a shared fail() that resolves every pending sender so an abort mid-sequence can't deadlock, drains stderr in parallel with child.exited, kills the child from a finally, and asserts exact reply objects rather than counts. The rejectUrl after the drain loop and the stderrDrained.catch(() => {}) prevent an unhandled rejection when the child is killed after the URL is already resolved. prebuiltUrl() already handles the autobuild- prefix (skips prepending it) and prebuiltDestDir() uses the full tag as the cache key, so the non-sha version string flows through correctly.

No prior reviews from me on this PR; deferring so a human can confirm the preview-tag pin is acceptable to merge.

…uilds

InspectorDebuggerAgent::disable() called internalDisable() unconditionally,
so a Debugger.disable on an already-disabled agent (or before any enable)
re-ran m_debugger.setClient(nullptr) and tripped ASSERT(!!m_client != !!client)
in JSC::Debugger::setClient on debug/ASAN builds. Release answers {} and
continues. Frontends send Debugger.disable liberally on teardown (detach +
close, or two attached tools), so this is an ordinary sequence.

oven-sh/WebKit#385 adds the same if (!enabled()) return { }; guard that
enable(), willDestroyFrontendAndBackend(), InspectorHeapAgent::disable()
and InspectorConsoleAgent::disable() already have.
@robobun
robobun force-pushed the farm/de685579/debugger-disable-idempotent branch from ec9dfac to 5561f3f Compare August 3, 2026 20:24
@robobun

robobun commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator Author

Rebased onto 2ed8ed6 after #36794 landed and moved WEBKIT_VERSION to e6e37cda21: the WebKit branch is now cut from e6e37cda21 and the preview tag is autobuild-preview-pr-385-10e1ab9b. The test is in its own file now (test/cli/inspect/inspect-debugger-disable.test.ts) since inspect.test.ts has pre-existing localhost-hostname failures locally that would mask the fail-before/pass-after check.

On the preview-tag question: this follows the same pattern as #35754 / #36472 / #36361 and the other WebKit bump PRs in the queue; the body notes that WEBKIT_VERSION should be repointed at the merged sha once oven-sh/WebKit#385 lands.

Comment thread scripts/build/deps/webkit.ts
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.

2 participants