From 0f5b9ee747e4b12b19cc9a2a875279a241d8084c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Z=C3=BCnd?= Date: Fri, 28 Nov 2025 13:46:21 +0100 Subject: [PATCH] chore: skip all pauses in all DevTools universes --- src/DevtoolsUtils.ts | 17 +++++++++++++++++ tests/DevtoolsUtils.test.ts | 24 +++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/DevtoolsUtils.ts b/src/DevtoolsUtils.ts index 9ec32044..05a145e9 100644 --- a/src/DevtoolsUtils.ts +++ b/src/DevtoolsUtils.ts @@ -247,6 +247,8 @@ const DEFAULT_FACTORY: TargetUniverseFactoryFn = async (page: Page) => { const connection = new PuppeteerDevToolsConnection(session); const targetManager = universe.context.get(TargetManager); + targetManager.observeModels(DebuggerModel, SKIP_ALL_PAUSES); + const target = targetManager.createTarget( 'main', '', @@ -258,3 +260,18 @@ const DEFAULT_FACTORY: TargetUniverseFactoryFn = async (page: Page) => { ); return {target, universe}; }; + +// We don't want to pause any DevTools universe session ever on the MCP side. +// +// Note that calling `setSkipAllPauses` only affects the session on which it was +// sent. This means DevTools can still pause, step and do whatever. We just won't +// see the `Debugger.paused`/`Debugger.resumed` events on the MCP side. +const SKIP_ALL_PAUSES = { + modelAdded(model: DebuggerModel): void { + void model.agent.invoke_setSkipAllPauses({skip: true}); + }, + + modelRemoved(): void { + // Do nothing. + }, +}; diff --git a/tests/DevtoolsUtils.test.ts b/tests/DevtoolsUtils.test.ts index 2137ad17..84b028b2 100644 --- a/tests/DevtoolsUtils.test.ts +++ b/tests/DevtoolsUtils.test.ts @@ -9,7 +9,10 @@ import {afterEach, describe, it} from 'node:test'; import sinon from 'sinon'; -import {AggregatedIssue} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; +import { + AggregatedIssue, + DebuggerModel, +} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; import { extractUrlLikeFromDevToolsTitle, urlsEqual, @@ -240,4 +243,23 @@ describe('UniverseManager', () => { assert.notStrictEqual(manager.get(page), null); }); }); + + it('ignores pauses', async () => { + await withBrowser(async (browser, page) => { + const manager = new UniverseManager(browser); + await manager.init([page]); + const targetUniverse = manager.get(page); + assert.ok(targetUniverse); + const model = targetUniverse.target.model(DebuggerModel); + assert.ok(model); + + const pausedSpy = sinon.stub(); + model.addEventListener('DebuggerPaused' as any, pausedSpy); // eslint-disable-line + + const result = await page.evaluate('debugger; 1 + 1'); + assert.strictEqual(result, 2); + + sinon.assert.notCalled(pausedSpy); + }); + }); });