Skip to content

Fix #3517: CreateCDPSessionAsync never delivers events for worker targets - #3518

Merged
kblok merged 2 commits into
masterfrom
fix-issue-3517
Jul 17, 2026
Merged

kblok merged 2 commits into
masterfrom
fix-issue-3517

Conversation

@kblok

@kblok kblok commented Jul 17, 2026

Copy link
Copy Markdown
Member

Summary

Attaching to a ServiceWorker target via ITarget.CreateCDPSessionAsync() and calling Debugger.enable worked fine, but Debugger.scriptParsed (and every other CDP event on that session) never showed up on MessageReceived.

Worker-type sessions buffer their early events until FlushEarlyMessages() is called, to avoid a race where Chrome's init events beat the internal listener's subscription. That flush was only ever wired up for the two internal consumers (CdpWebWorker, blocked service worker registration) — CreateCDPSessionAsync(), the public API, never called it, so every event on a manually-created worker session just piled up in the buffer forever.

Wiring the flush into CreateCDPSessionAsync() exposed a second, separate bug: FlushEarlyMessages() drains the buffer with _messageReceived?.Invoke(this, _bufferedMessages.Dequeue()). When nobody has subscribed yet, ?. short-circuits the whole call — including the Dequeue() argument — so the queue never actually drains and the loop spins forever. Fixed by dequeuing before the null-conditional invoke.

Fixes #3517

Verification

  • Reproduced with a standalone repro app registering a service worker and reading its source via Debugger.getScriptSource; confirmed Debugger.scriptParsed now arrives.
  • Added ShouldReceiveEventsOnAServiceWorkerSessionCreatedViaCreateCDPSessionAsync — verified it fails without the fix and passes with it.
  • CDPSessionTests, TargetTests, ResponseFromServiceWorkerTests, PageSetBypassServiceWorkerTests (61 tests): passing.

🤖 Generated with Claude Code

kblok and others added 2 commits July 17, 2026 07:57
…gets

Worker-type CDP sessions buffer early method-events until FlushEarlyMessages()
is called, but that was only wired up for internal consumers (CdpWebWorker,
blocked service worker registration). ITarget.CreateCDPSessionAsync() never
flushed, so every event on a manually-created worker/service-worker session
(e.g. Debugger.scriptParsed) sat in the buffer forever.

Flushing also exposed a latent bug in FlushEarlyMessages(): the null-conditional
invoke `_messageReceived?.Invoke(this, _bufferedMessages.Dequeue())` never
evaluates Dequeue() when nobody has subscribed yet, since `?.` short-circuits
the whole argument list - spinning the drain loop forever instead of clearing
the queue.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
BidiWorkerTarget.CreateCDPSessionAsync always throws PuppeteerException("Not
supported"), so the #3517 regression test added for CreateCDPSessionAsync on
a ServiceWorker target doesn't apply there.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@kblok
kblok merged commit cc97ee0 into master Jul 17, 2026
27 of 28 checks passed
@kblok
kblok deleted the fix-issue-3517 branch July 17, 2026 18:56
sondresjolyst pushed a commit to sondresjolyst/garge-api that referenced this pull request Jul 27, 2026
Updated [PuppeteerSharp](https://github.com/hardkoded/puppeteer-sharp)
from 25.3.3 to 25.3.4.

<details>
<summary>Release notes</summary>

_Sourced from [PuppeteerSharp's
releases](https://github.com/hardkoded/puppeteer-sharp/releases)._

## 25.3.4

## What's Changed
* Fix #​3517: CreateCDPSessionAsync never delivers events for worker
targets by @​kblok in
hardkoded/puppeteer-sharp#3518


**Full Changelog**:
hardkoded/puppeteer-sharp@v25.3.3...v25.3.4

Commits viewable in [compare
view](hardkoded/puppeteer-sharp@v25.3.3...v25.3.4).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=PuppeteerSharp&package-manager=nuget&previous-version=25.3.3&new-version=25.3.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
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.

Debugger.scriptParsed is not received for a Service Worker in PuppeteerSharp

1 participant