Skip to content

Commit b443033

Browse files
zyzyzyryxyPiotr Paulski
andauthored
refactor: bundle puppeteer-core (#417)
Continue speeding up boot time. --------- Co-authored-by: Piotr Paulski <[email protected]>
1 parent 053f1f8 commit b443033

20 files changed

+128
-63
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
"dependencies": {
4141
"core-js": "3.46.0",
4242
"debug": "4.4.3",
43-
"puppeteer-core": "^24.24.1",
4443
"yargs": "18.0.0"
4544
},
4645
"devDependencies": {

rollup.config.mjs

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,31 @@ import license from 'rollup-plugin-license';
2929

3030
const isProduction = process.env.NODE_ENV === 'production';
3131

32-
/** @type {import('rollup').RollupOptions} */
33-
const sdk = {
34-
input: './build/src/third_party/modelcontextprotocol-sdk/index.js',
32+
const allowedLicenses = [
33+
'MIT',
34+
'Apache 2.0',
35+
'Apache-2.0',
36+
'BSD-3-Clause',
37+
'BSD-2-Clause',
38+
'ISC',
39+
'0BSD',
40+
];
41+
42+
/**
43+
* @param {string} wrapperIndexPath
44+
* @param {import('rollup').OutputOptions} [extraOutputOptions={}]
45+
* @param {string[]} [external=[]]
46+
* @returns {import('rollup').RollupOptions}
47+
*/
48+
const bundleDependency = (
49+
wrapperIndexPath,
50+
extraOutputOptions = {},
51+
external = [],
52+
) => ({
53+
input: wrapperIndexPath,
3554
output: {
36-
file: './build/src/third_party/modelcontextprotocol-sdk/index.js',
55+
...extraOutputOptions,
56+
file: wrapperIndexPath,
3757
sourcemap: !isProduction,
3858
format: 'esm',
3959
},
@@ -48,18 +68,14 @@ const sdk = {
4868
thirdParty: {
4969
allow: {
5070
test: dependency => {
51-
let allowed_licenses = ['MIT', 'Apache 2.0', 'BSD-2-Clause', 'ISC'];
52-
return allowed_licenses.includes(dependency.license);
71+
return allowedLicenses.includes(dependency.license);
5372
},
5473
failOnUnlicensed: true,
5574
failOnViolation: true,
5675
},
5776
output: {
5877
file: path.join(
59-
'build',
60-
'src',
61-
'third_party',
62-
'modelcontextprotocol-sdk',
78+
path.dirname(wrapperIndexPath),
6379
'THIRD_PARTY_NOTICES',
6480
),
6581
template(dependencies) {
@@ -90,6 +106,16 @@ const sdk = {
90106
json(),
91107
nodeResolve(),
92108
],
93-
};
109+
external,
110+
});
94111

95-
export default [sdk];
112+
export default [
113+
bundleDependency('./build/src/third_party/modelcontextprotocol-sdk/index.js'),
114+
bundleDependency(
115+
'./build/src/third_party/puppeteer-core/index.js',
116+
{
117+
inlineDynamicImports: true,
118+
},
119+
['./bidi.js', '../bidi/bidi.js'],
120+
),
121+
];

src/DevToolsConnectionAdapter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import {type ConnectionTransport} from 'puppeteer-core';
8-
97
import {Connection} from '../node_modules/chrome-devtools-frontend/front_end/core/protocol_client/InspectorBackend.js';
108

9+
import {type ConnectionTransport} from './third_party/puppeteer-core/index.js';
10+
1111
/**
1212
* Allows a puppeteer {@link ConnectionTransport} to act like a DevTools {@link Connection}.
1313
*/

src/McpContext.ts

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import os from 'node:os';
88
import path from 'node:path';
99

1010
import type {Debugger} from 'debug';
11+
12+
import type {ListenerMap} from './PageCollector.js';
13+
import {NetworkCollector, PageCollector} from './PageCollector.js';
14+
import {Locator} from './third_party/puppeteer-core/index.js';
1115
import type {
1216
Browser,
1317
ConsoleMessage,
@@ -17,10 +21,7 @@ import type {
1721
Page,
1822
SerializedAXNode,
1923
PredefinedNetworkConditions,
20-
} from 'puppeteer-core';
21-
22-
import type {ListenerMap} from './PageCollector.js';
23-
import {NetworkCollector, PageCollector} from './PageCollector.js';
24+
} from './third_party/puppeteer-core/index.js';
2425
import {listPages} from './tools/pages.js';
2526
import {takeSnapshot} from './tools/snapshot.js';
2627
import {CLOSE_PAGE_ERROR} from './tools/ToolDefinition.js';
@@ -91,9 +92,16 @@ export class McpContext implements Context {
9192
#nextSnapshotId = 1;
9293
#traceResults: TraceResult[] = [];
9394

94-
private constructor(browser: Browser, logger: Debugger) {
95+
#locatorClass: typeof Locator;
96+
97+
private constructor(
98+
browser: Browser,
99+
logger: Debugger,
100+
locatorClass: typeof Locator,
101+
) {
95102
this.browser = browser;
96103
this.logger = logger;
104+
this.#locatorClass = locatorClass;
97105

98106
this.#networkCollector = new NetworkCollector(this.browser);
99107

@@ -122,8 +130,13 @@ export class McpContext implements Context {
122130
await this.#consoleCollector.init();
123131
}
124132

125-
static async from(browser: Browser, logger: Debugger) {
126-
const context = new McpContext(browser, logger);
133+
static async from(
134+
browser: Browser,
135+
logger: Debugger,
136+
/* Let tests use unbundled Locator class to avoid overly strict checks within puppeteer that fail when mixing bundled and unbundled class instances */
137+
locatorClass: typeof Locator = Locator,
138+
) {
139+
const context = new McpContext(browser, logger, locatorClass);
127140
await context.#init();
128141
return context;
129142
}
@@ -428,4 +441,28 @@ export class McpContext implements Context {
428441
getNetworkRequestStableId(request: HTTPRequest): number {
429442
return this.#networkCollector.getIdForResource(request);
430443
}
444+
445+
waitForTextOnPage({
446+
text,
447+
timeout,
448+
}: {
449+
text: string;
450+
timeout?: number | undefined;
451+
}): Promise<Element> {
452+
const page = this.getSelectedPage();
453+
const frames = page.frames();
454+
455+
const locator = this.#locatorClass.race(
456+
frames.flatMap(frame => [
457+
frame.locator(`aria/${text}`),
458+
frame.locator(`text/${text}`),
459+
]),
460+
);
461+
462+
if (timeout) {
463+
locator.setTimeout(timeout);
464+
}
465+
466+
return locator.wait();
467+
}
431468
}

src/McpResponse.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
* Copyright 2025 Google LLC
44
* SPDX-License-Identifier: Apache-2.0
55
*/
6-
import type {ConsoleMessage, ResourceType} from 'puppeteer-core';
7-
86
import type {ConsoleMessageData} from './formatters/consoleFormatter.js';
97
import {
108
formatConsoleEventShort,
@@ -23,6 +21,10 @@ import type {
2321
ImageContent,
2422
TextContent,
2523
} from './third_party/modelcontextprotocol-sdk/index.js';
24+
import type {
25+
ConsoleMessage,
26+
ResourceType,
27+
} from './third_party/puppeteer-core/index.js';
2628
import {handleDialog} from './tools/pages.js';
2729
import type {ImageContentData, Response} from './tools/ToolDefinition.js';
2830
import {paginate} from './utils/pagination.js';

src/PageCollector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
type HTTPRequest,
1212
type Page,
1313
type PageEvents,
14-
} from 'puppeteer-core';
14+
} from './third_party/puppeteer-core/index.js';
1515

1616
export type ListenerMap<EventMap extends PageEvents = PageEvents> = {
1717
[K in keyof EventMap]?: (event: EventMap[K]) => void;

src/WaitForHelper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
* Copyright 2025 Google LLC
44
* SPDX-License-Identifier: Apache-2.0
55
*/
6-
import type {Page, Protocol} from 'puppeteer-core';
76
import type {CdpPage} from 'puppeteer-core/internal/cdp/Page.js';
87

98
import {logger} from './logger.js';
9+
import type {Page, Protocol} from './third_party/puppeteer-core/index.js';
1010

1111
export class WaitForHelper {
1212
#abortController = new AbortController();

src/browser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import type {
1313
ChromeReleaseChannel,
1414
LaunchOptions,
1515
Target,
16-
} from 'puppeteer-core';
17-
import puppeteer from 'puppeteer-core';
16+
} from './third_party/puppeteer-core/index.js';
17+
import {puppeteer} from './third_party/puppeteer-core/index.js';
1818

1919
let browser: Browser | undefined;
2020

src/formatters/networkFormatter.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66

77
import {isUtf8} from 'node:buffer';
88

9-
import type {HTTPRequest, HTTPResponse} from 'puppeteer-core';
9+
import type {
10+
HTTPRequest,
11+
HTTPResponse,
12+
} from '../third_party/puppeteer-core/index.js';
1013

1114
const BODY_CONTEXT_SIZE_LIMIT = 10000;
1215

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* @license
3+
* Copyright 2025 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
export {Locator, PredefinedNetworkConditions} from 'puppeteer-core';
8+
export {default as puppeteer} from 'puppeteer-core';
9+
export type * from 'puppeteer-core';

0 commit comments

Comments
 (0)