playwright-core 1.58.0-alpha-2025-12-07 → 1.58.0-alpha-2025-12-09

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/browsers.json +3 -3
  2. package/lib/client/browserContext.js +7 -0
  3. package/lib/client/page.js +4 -3
  4. package/lib/client/platform.js +3 -0
  5. package/lib/protocol/validator.js +29 -10
  6. package/lib/server/agent/actionRunner.js +68 -0
  7. package/lib/server/agent/actions.js +16 -0
  8. package/lib/server/agent/agent.js +122 -0
  9. package/lib/server/agent/backend.js +77 -0
  10. package/lib/server/agent/context.js +115 -0
  11. package/lib/server/agent/tools.js +229 -0
  12. package/lib/server/bidi/bidiNetworkManager.js +1 -1
  13. package/lib/server/bidi/bidiPage.js +3 -1
  14. package/lib/server/browserContext.js +2 -2
  15. package/lib/server/chromium/chromium.js +1 -3
  16. package/lib/server/chromium/chromiumSwitches.js +0 -2
  17. package/lib/server/chromium/crBrowser.js +1 -1
  18. package/lib/server/chromium/crNetworkManager.js +39 -2
  19. package/lib/server/chromium/crPage.js +14 -81
  20. package/lib/server/deviceDescriptorsSource.json +2 -2
  21. package/lib/server/dispatchers/browserDispatcher.js +1 -0
  22. package/lib/server/dispatchers/pageDispatcher.js +7 -0
  23. package/lib/server/firefox/ffNetworkManager.js +2 -2
  24. package/lib/server/firefox/ffPage.js +9 -8
  25. package/lib/server/frames.js +2 -2
  26. package/lib/server/network.js +3 -0
  27. package/lib/server/page.js +5 -65
  28. package/lib/server/progress.js +3 -2
  29. package/lib/server/registry/index.js +1 -1
  30. package/lib/server/screencast.js +191 -0
  31. package/lib/server/trace/recorder/tracing.js +5 -5
  32. package/lib/server/utils/nodePlatform.js +2 -0
  33. package/lib/server/{chromium/videoRecorder.js → videoRecorder.js} +3 -3
  34. package/lib/server/webkit/wkBrowser.js +1 -1
  35. package/lib/server/webkit/wkInterceptableRequest.js +29 -1
  36. package/lib/server/webkit/wkPage.js +20 -40
  37. package/lib/utils/isomorphic/protocolMetainfo.js +2 -0
  38. package/lib/vite/traceViewer/assets/{codeMirrorModule-JphNwIdM.js → codeMirrorModule-CPNe-I5g.js} +1 -1
  39. package/lib/vite/traceViewer/assets/{defaultSettingsView-C7iHYOsw.js → defaultSettingsView-V7hnXDpz.js} +3 -3
  40. package/lib/vite/traceViewer/{index.C5w1selH.js → index.YskCIlQ-.js} +1 -1
  41. package/lib/vite/traceViewer/index.html +2 -2
  42. package/lib/vite/traceViewer/{uiMode.CCu4MMfA.js → uiMode.CmFFBCQb.js} +1 -1
  43. package/lib/vite/traceViewer/uiMode.html +2 -2
  44. package/package.json +1 -1
  45. package/types/types.d.ts +10 -5
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var tools_exports = {};
20
+ __export(tools_exports, {
21
+ default: () => tools_default
22
+ });
23
+ module.exports = __toCommonJS(tools_exports);
24
+ var import_mcpBundle = require("../../mcpBundle");
25
+ function defineTool(tool) {
26
+ return tool;
27
+ }
28
+ const snapshot = defineTool({
29
+ schema: {
30
+ name: "browser_snapshot",
31
+ title: "Page snapshot",
32
+ description: "Capture accessibility snapshot of the current page, this is better than screenshot",
33
+ inputSchema: import_mcpBundle.z.object({})
34
+ },
35
+ handle: async (context, params) => {
36
+ return await context.snapshotResult();
37
+ }
38
+ });
39
+ const elementSchema = import_mcpBundle.z.object({
40
+ element: import_mcpBundle.z.string().describe("Human-readable element description used to obtain permission to interact with the element"),
41
+ ref: import_mcpBundle.z.string().describe("Exact target element reference from the page snapshot")
42
+ });
43
+ const clickSchema = elementSchema.extend({
44
+ doubleClick: import_mcpBundle.z.boolean().optional().describe("Whether to perform a double click instead of a single click"),
45
+ button: import_mcpBundle.z.enum(["left", "right", "middle"]).optional().describe("Button to click, defaults to left"),
46
+ modifiers: import_mcpBundle.z.array(import_mcpBundle.z.enum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"])).optional().describe("Modifier keys to press")
47
+ });
48
+ const click = defineTool({
49
+ schema: {
50
+ name: "browser_click",
51
+ title: "Click",
52
+ description: "Perform click on a web page",
53
+ inputSchema: clickSchema
54
+ },
55
+ handle: async (context, params) => {
56
+ const [selector] = await context.refSelectors([params]);
57
+ return await context.runActionAndWait({
58
+ method: "click",
59
+ selector,
60
+ options: {
61
+ button: params.button,
62
+ modifiers: params.modifiers,
63
+ clickCount: params.doubleClick ? 2 : void 0
64
+ }
65
+ });
66
+ }
67
+ });
68
+ const drag = defineTool({
69
+ schema: {
70
+ name: "browser_drag",
71
+ title: "Drag mouse",
72
+ description: "Perform drag and drop between two elements",
73
+ inputSchema: import_mcpBundle.z.object({
74
+ startElement: import_mcpBundle.z.string().describe("Human-readable source element description used to obtain the permission to interact with the element"),
75
+ startRef: import_mcpBundle.z.string().describe("Exact source element reference from the page snapshot"),
76
+ endElement: import_mcpBundle.z.string().describe("Human-readable target element description used to obtain the permission to interact with the element"),
77
+ endRef: import_mcpBundle.z.string().describe("Exact target element reference from the page snapshot")
78
+ })
79
+ },
80
+ handle: async (context, params) => {
81
+ const [sourceSelector, targetSelector] = await context.refSelectors([
82
+ { ref: params.startRef, element: params.startElement },
83
+ { ref: params.endRef, element: params.endElement }
84
+ ]);
85
+ return await context.runActionAndWait({
86
+ method: "drag",
87
+ sourceSelector,
88
+ targetSelector
89
+ });
90
+ }
91
+ });
92
+ const hoverSchema = elementSchema.extend({
93
+ modifiers: import_mcpBundle.z.array(import_mcpBundle.z.enum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"])).optional().describe("Modifier keys to press")
94
+ });
95
+ const hover = defineTool({
96
+ schema: {
97
+ name: "browser_hover",
98
+ title: "Hover mouse",
99
+ description: "Hover over element on page",
100
+ inputSchema: hoverSchema
101
+ },
102
+ handle: async (context, params) => {
103
+ const [selector] = await context.refSelectors([params]);
104
+ return await context.runActionAndWait({
105
+ method: "hover",
106
+ selector,
107
+ options: {
108
+ modifiers: params.modifiers
109
+ }
110
+ });
111
+ }
112
+ });
113
+ const selectOptionSchema = elementSchema.extend({
114
+ values: import_mcpBundle.z.array(import_mcpBundle.z.string()).describe("Array of values to select in the dropdown. This can be a single value or multiple values.")
115
+ });
116
+ const selectOption = defineTool({
117
+ schema: {
118
+ name: "browser_select_option",
119
+ title: "Select option",
120
+ description: "Select an option in a dropdown",
121
+ inputSchema: selectOptionSchema
122
+ },
123
+ handle: async (context, params) => {
124
+ const [selector] = await context.refSelectors([params]);
125
+ return await context.runActionAndWait({
126
+ method: "selectOption",
127
+ selector,
128
+ labels: params.values
129
+ });
130
+ }
131
+ });
132
+ const pressKey = defineTool({
133
+ schema: {
134
+ name: "browser_press_key",
135
+ title: "Press a key",
136
+ description: "Press a key on the keyboard",
137
+ inputSchema: import_mcpBundle.z.object({
138
+ key: import_mcpBundle.z.string().describe("Name of the key to press or a character to generate, such as `ArrowLeft` or `a`")
139
+ })
140
+ },
141
+ handle: async (context, params) => {
142
+ return await context.runActionAndWait({
143
+ method: "pressKey",
144
+ key: params.key
145
+ });
146
+ }
147
+ });
148
+ const typeSchema = elementSchema.extend({
149
+ text: import_mcpBundle.z.string().describe("Text to type into the element"),
150
+ submit: import_mcpBundle.z.boolean().optional().describe("Whether to submit entered text (press Enter after)"),
151
+ slowly: import_mcpBundle.z.boolean().optional().describe("Whether to type one character at a time. Useful for triggering key handlers in the page. By default entire text is filled in at once.")
152
+ });
153
+ const type = defineTool({
154
+ schema: {
155
+ name: "browser_type",
156
+ title: "Type text",
157
+ description: "Type text into editable element",
158
+ inputSchema: typeSchema
159
+ },
160
+ handle: async (context, params) => {
161
+ const [selector] = await context.refSelectors([params]);
162
+ if (params.slowly) {
163
+ return await context.runActionAndWait({
164
+ method: "pressSequentially",
165
+ selector,
166
+ text: params.text,
167
+ submit: params.submit
168
+ });
169
+ } else {
170
+ return await context.runActionAndWait({
171
+ method: "fill",
172
+ selector,
173
+ text: params.text,
174
+ submit: params.submit
175
+ });
176
+ }
177
+ }
178
+ });
179
+ const fillForm = defineTool({
180
+ schema: {
181
+ name: "browser_fill_form",
182
+ title: "Fill form",
183
+ description: "Fill multiple form fields",
184
+ inputSchema: import_mcpBundle.z.object({
185
+ fields: import_mcpBundle.z.array(import_mcpBundle.z.object({
186
+ name: import_mcpBundle.z.string().describe("Human-readable field name"),
187
+ type: import_mcpBundle.z.enum(["textbox", "checkbox", "radio", "combobox", "slider"]).describe("Type of the field"),
188
+ ref: import_mcpBundle.z.string().describe("Exact target field reference from the page snapshot"),
189
+ value: import_mcpBundle.z.string().describe("Value to fill in the field. If the field is a checkbox, the value should be `true` or `false`. If the field is a combobox, the value should be the text of the option.")
190
+ })).describe("Fields to fill in")
191
+ })
192
+ },
193
+ handle: async (context, params) => {
194
+ const actions = [];
195
+ for (const field of params.fields) {
196
+ const [selector] = await context.refSelectors([{ ref: field.ref, element: field.name }]);
197
+ if (field.type === "textbox" || field.type === "slider") {
198
+ actions.push({
199
+ method: "fill",
200
+ selector,
201
+ text: field.value
202
+ });
203
+ } else if (field.type === "checkbox" || field.type === "radio") {
204
+ actions.push({
205
+ method: "setChecked",
206
+ selector,
207
+ checked: field.value === "true"
208
+ });
209
+ } else if (field.type === "combobox") {
210
+ actions.push({
211
+ method: "selectOption",
212
+ selector,
213
+ labels: [field.value]
214
+ });
215
+ }
216
+ }
217
+ return await context.runActionsAndWait(actions);
218
+ }
219
+ });
220
+ var tools_default = [
221
+ snapshot,
222
+ click,
223
+ drag,
224
+ hover,
225
+ selectOption,
226
+ pressKey,
227
+ type,
228
+ fillForm
229
+ ];
@@ -342,7 +342,7 @@ function resourceTypeFromBidi(requestDestination, requestInitiatorType, eventIni
342
342
  case "image":
343
343
  return "image";
344
344
  case "object":
345
- return "object";
345
+ return "other";
346
346
  case "paintworklet":
347
347
  return "script";
348
348
  case "script":
@@ -482,7 +482,9 @@ ${params.stackTrace?.callFrames.map((f) => {
482
482
  throw e;
483
483
  });
484
484
  }
485
- async setScreencastOptions(options) {
485
+ async startScreencast(options) {
486
+ }
487
+ async stopScreencast() {
486
488
  }
487
489
  rafCountForStablePosition() {
488
490
  return 1;
@@ -145,7 +145,7 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
145
145
  return true;
146
146
  }
147
147
  static reusableContextHash(params) {
148
- const paramsCopy = { ...params, agent: void 0 };
148
+ const paramsCopy = { ...params };
149
149
  if (paramsCopy.selectorEngines?.length === 0)
150
150
  delete paramsCopy.selectorEngines;
151
151
  for (const k of Object.keys(paramsCopy)) {
@@ -322,7 +322,7 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
322
322
  const pageOrError = await progress.race(page.waitForInitializedOrError());
323
323
  if (pageOrError instanceof Error)
324
324
  throw pageOrError;
325
- await page.mainFrame()._waitForLoadState(progress, "load");
325
+ await page.mainFrame().waitForLoadState(progress, "load");
326
326
  return page;
327
327
  }
328
328
  async _loadDefaultContext(progress) {
@@ -279,9 +279,7 @@ class Chromium extends import_browserType.BrowserType {
279
279
  if (args.find((arg) => !arg.startsWith("-")))
280
280
  throw new Error("Arguments can not specify page to be opened");
281
281
  const chromeArguments = [...(0, import_chromiumSwitches.chromiumSwitches)(options.assistantMode, options.channel)];
282
- if (import_os.default.platform() === "darwin") {
283
- chromeArguments.push("--enable-unsafe-swiftshader");
284
- }
282
+ chromeArguments.push("--enable-unsafe-swiftshader");
285
283
  if (options.headless) {
286
284
  chromeArguments.push("--headless");
287
285
  chromeArguments.push(
@@ -22,8 +22,6 @@ __export(chromiumSwitches_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(chromiumSwitches_exports);
24
24
  const disabledFeatures = (assistantMode) => [
25
- // See https://github.com/microsoft/playwright/pull/10380
26
- "AcceptCHFrame",
27
25
  // See https://github.com/microsoft/playwright/issues/14047
28
26
  "AvoidUnnecessaryBeforeUnloadCheckSync",
29
27
  "DestroyProfileOnBrowserClose",
@@ -470,7 +470,7 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
470
470
  }
471
471
  }
472
472
  async stopVideoRecording() {
473
- await Promise.all(this._crPages().map((crPage) => crPage._mainFrameSession._stopVideoRecording()));
473
+ await Promise.all(this._crPages().map((crPage) => crPage._page.screencast.stopVideoRecording()));
474
474
  }
475
475
  onClosePersistent() {
476
476
  }
@@ -482,12 +482,11 @@ class InterceptableRequest {
482
482
  url,
483
483
  postDataEntries = null
484
484
  } = requestPausedEvent ? requestPausedEvent.request : requestWillBeSentEvent.request;
485
- const type = (requestWillBeSentEvent.type || "").toLowerCase();
486
485
  let postDataBuffer = null;
487
486
  const entries = postDataEntries?.filter((entry) => entry.bytes);
488
487
  if (entries && entries.length)
489
488
  postDataBuffer = Buffer.concat(entries.map((entry) => Buffer.from(entry.bytes, "base64")));
490
- this.request = new network.Request(context, frame, serviceWorker, redirectedFrom?.request || null, documentId, url, type, method, postDataBuffer, headersOverride || (0, import_utils.headersObjectToArray)(headers));
489
+ this.request = new network.Request(context, frame, serviceWorker, redirectedFrom?.request || null, documentId, url, toResourceType(requestWillBeSentEvent.type || "Other"), method, postDataBuffer, headersOverride || (0, import_utils.headersObjectToArray)(headers));
491
490
  }
492
491
  }
493
492
  class RouteImpl {
@@ -660,6 +659,44 @@ class ResponseExtraInfoTracker {
660
659
  this._requests.delete(requestId);
661
660
  }
662
661
  }
662
+ function toResourceType(type) {
663
+ switch (type) {
664
+ case "Document":
665
+ return "document";
666
+ case "Stylesheet":
667
+ return "stylesheet";
668
+ case "Image":
669
+ return "image";
670
+ case "Media":
671
+ return "media";
672
+ case "Font":
673
+ return "font";
674
+ case "Script":
675
+ return "script";
676
+ case "TextTrack":
677
+ return "texttrack";
678
+ case "XHR":
679
+ return "xhr";
680
+ case "Fetch":
681
+ return "fetch";
682
+ case "EventSource":
683
+ return "eventsource";
684
+ case "WebSocket":
685
+ return "websocket";
686
+ case "Manifest":
687
+ return "manifest";
688
+ case "Ping":
689
+ return "ping";
690
+ case "CSPViolationReport":
691
+ return "cspreport";
692
+ case "Prefetch":
693
+ case "SignedExchange":
694
+ case "Preflight":
695
+ case "FedCM":
696
+ default:
697
+ return "other";
698
+ }
699
+ }
663
700
  // Annotate the CommonJS export names for ESM import in node:
664
701
  0 && (module.exports = {
665
702
  CRNetworkManager
@@ -31,9 +31,7 @@ __export(crPage_exports, {
31
31
  CRPage: () => CRPage
32
32
  });
33
33
  module.exports = __toCommonJS(crPage_exports);
34
- var import_path = __toESM(require("path"));
35
34
  var import_assert = require("../../utils/isomorphic/assert");
36
- var import_crypto = require("../utils/crypto");
37
35
  var import_eventsHelper = require("../utils/eventsHelper");
38
36
  var import_stackTrace = require("../../utils/isomorphic/stackTrace");
39
37
  var dialog = __toESM(require("../dialog"));
@@ -42,7 +40,6 @@ var frames = __toESM(require("../frames"));
42
40
  var import_helper = require("../helper");
43
41
  var network = __toESM(require("../network"));
44
42
  var import_page = require("../page");
45
- var import_registry = require("../registry");
46
43
  var import_crCoverage = require("./crCoverage");
47
44
  var import_crDragDrop = require("./crDragDrop");
48
45
  var import_crExecutionContext = require("./crExecutionContext");
@@ -51,7 +48,6 @@ var import_crNetworkManager = require("./crNetworkManager");
51
48
  var import_crPdf = require("./crPdf");
52
49
  var import_crProtocolHelper = require("./crProtocolHelper");
53
50
  var import_defaultFontFamilies = require("./defaultFontFamilies");
54
- var import_videoRecorder = require("./videoRecorder");
55
51
  var import_errors = require("../errors");
56
52
  var import_protocolError = require("../protocolError");
57
53
  class CRPage {
@@ -236,17 +232,16 @@ class CRPage {
236
232
  async scrollRectIntoViewIfNeeded(handle, rect) {
237
233
  return this._sessionForHandle(handle)._scrollRectIntoViewIfNeeded(handle, rect);
238
234
  }
239
- async setScreencastOptions(options) {
240
- if (options) {
241
- await this._mainFrameSession._startScreencast(this, {
242
- format: "jpeg",
243
- quality: options.quality,
244
- maxWidth: options.width,
245
- maxHeight: options.height
246
- });
247
- } else {
248
- await this._mainFrameSession._stopScreencast(this);
249
- }
235
+ async startScreencast(options) {
236
+ await this._mainFrameSession._client.send("Page.startScreencast", {
237
+ format: "jpeg",
238
+ quality: options.quality,
239
+ maxWidth: options.width,
240
+ maxHeight: options.height
241
+ });
242
+ }
243
+ async stopScreencast() {
244
+ await this._mainFrameSession._client._sendMayFail("Page.stopScreencast");
250
245
  }
251
246
  rafCountForStablePosition() {
252
247
  return 1;
@@ -311,9 +306,6 @@ class FrameSession {
311
306
  // Marks the oopif session that remote -> local transition has happened in the parent.
312
307
  // See Target.detachedFromTarget handler for details.
313
308
  this._swappedIn = false;
314
- this._videoRecorder = null;
315
- this._screencastId = null;
316
- this._screencastClients = /* @__PURE__ */ new Set();
317
309
  this._workerSessions = /* @__PURE__ */ new Map();
318
310
  this._initScriptIds = /* @__PURE__ */ new Map();
319
311
  this._client = client;
@@ -366,22 +358,8 @@ class FrameSession {
366
358
  this._windowId = windowId;
367
359
  }
368
360
  let screencastOptions;
369
- if (!this._page.isStorageStatePage && this._isMainFrame() && this._crPage._browserContext._options.recordVideo && hasUIWindow) {
370
- const screencastId = (0, import_crypto.createGuid)();
371
- const outputFile = import_path.default.join(this._crPage._browserContext._options.recordVideo.dir, screencastId + ".webm");
372
- screencastOptions = {
373
- // validateBrowserContextOptions ensures correct video size.
374
- ...this._crPage._browserContext._options.recordVideo.size,
375
- outputFile
376
- };
377
- await this._crPage._browserContext._ensureVideosPath();
378
- await this._createVideoRecorder(screencastId, screencastOptions);
379
- this._crPage._page.waitForInitializedOrError().then((p) => {
380
- if (p instanceof Error)
381
- this._stopVideoRecording().catch(() => {
382
- });
383
- });
384
- }
361
+ if (!this._page.isStorageStatePage && this._isMainFrame() && hasUIWindow)
362
+ screencastOptions = await this._crPage._page.screencast.initializeVideoRecorder();
385
363
  let lifecycleEventsEnabled;
386
364
  if (!this._isMainFrame())
387
365
  this._addRendererListeners();
@@ -462,7 +440,7 @@ class FrameSession {
462
440
  /* runImmediately */
463
441
  ));
464
442
  if (screencastOptions)
465
- promises.push(this._startVideoRecording(screencastOptions));
443
+ promises.push(this._crPage._page.screencast.startVideoRecording(screencastOptions));
466
444
  }
467
445
  promises.push(this._client.send("Runtime.runIfWaitingForDebugger"));
468
446
  promises.push(this._firstNonInitialNavigationCommittedPromise);
@@ -730,7 +708,7 @@ class FrameSession {
730
708
  }
731
709
  }
732
710
  _onScreencastFrame(payload) {
733
- this._page.throttleScreencastFrameAck(() => {
711
+ this._page.screencast.throttleFrameAck(() => {
734
712
  this._client.send("Page.screencastFrameAck", { sessionId: payload.sessionId }).catch(() => {
735
713
  });
736
714
  });
@@ -742,51 +720,6 @@ class FrameSession {
742
720
  height: payload.metadata.deviceHeight
743
721
  });
744
722
  }
745
- async _createVideoRecorder(screencastId, options) {
746
- (0, import_assert.assert)(!this._screencastId);
747
- const ffmpegPath = import_registry.registry.findExecutable("ffmpeg").executablePathOrDie(this._page.browserContext._browser.sdkLanguage());
748
- this._videoRecorder = await import_videoRecorder.VideoRecorder.launch(this._crPage._page, ffmpegPath, options);
749
- this._screencastId = screencastId;
750
- }
751
- async _startVideoRecording(options) {
752
- const screencastId = this._screencastId;
753
- (0, import_assert.assert)(screencastId);
754
- this._page.once(import_page.Page.Events.Close, () => this._stopVideoRecording().catch(() => {
755
- }));
756
- const gotFirstFrame = new Promise((f) => this._client.once("Page.screencastFrame", f));
757
- await this._startScreencast(this._videoRecorder, {
758
- format: "jpeg",
759
- quality: 90,
760
- maxWidth: options.width,
761
- maxHeight: options.height
762
- });
763
- gotFirstFrame.then(() => {
764
- this._crPage._browserContext._browser._videoStarted(this._crPage._browserContext, screencastId, options.outputFile, this._crPage._page.waitForInitializedOrError());
765
- });
766
- }
767
- async _stopVideoRecording() {
768
- if (!this._screencastId)
769
- return;
770
- const screencastId = this._screencastId;
771
- this._screencastId = null;
772
- const recorder = this._videoRecorder;
773
- this._videoRecorder = null;
774
- await this._stopScreencast(recorder);
775
- await recorder.stop().catch(() => {
776
- });
777
- const video = this._crPage._browserContext._browser._takeVideo(screencastId);
778
- video?.reportFinished();
779
- }
780
- async _startScreencast(client, options = {}) {
781
- this._screencastClients.add(client);
782
- if (this._screencastClients.size === 1)
783
- await this._client.send("Page.startScreencast", options);
784
- }
785
- async _stopScreencast(client) {
786
- this._screencastClients.delete(client);
787
- if (!this._screencastClients.size)
788
- await this._client._sendMayFail("Page.stopScreencast");
789
- }
790
723
  async _updateGeolocation(initial) {
791
724
  const geolocation = this._crPage._browserContext._options.geolocation;
792
725
  if (!initial || geolocation)
@@ -1702,7 +1702,7 @@
1702
1702
  "defaultBrowserType": "chromium"
1703
1703
  },
1704
1704
  "Desktop Firefox HiDPI": {
1705
- "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0.1) Gecko/20100101 Firefox/145.0.1",
1705
+ "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0.2) Gecko/20100101 Firefox/145.0.2",
1706
1706
  "screen": {
1707
1707
  "width": 1792,
1708
1708
  "height": 1120
@@ -1762,7 +1762,7 @@
1762
1762
  "defaultBrowserType": "chromium"
1763
1763
  },
1764
1764
  "Desktop Firefox": {
1765
- "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0.1) Gecko/20100101 Firefox/145.0.1",
1765
+ "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0.2) Gecko/20100101 Firefox/145.0.2",
1766
1766
  "screen": {
1767
1767
  "width": 1920,
1768
1768
  "height": 1080
@@ -62,6 +62,7 @@ class BrowserDispatcher extends import_dispatcher.Dispatcher {
62
62
  return { context: contextDispatcher };
63
63
  }
64
64
  async newContextForReuse(params, progress) {
65
+ delete params.agent;
65
66
  const context = await this._object.newContextForReuse(progress, params);
66
67
  const contextDispatcher = import_browserContextDispatcher.BrowserContextDispatcher.from(this, context);
67
68
  this._dispatchEvent("context", { context: contextDispatcher });
@@ -36,6 +36,7 @@ var import_networkDispatchers3 = require("./networkDispatchers");
36
36
  var import_webSocketRouteDispatcher = require("./webSocketRouteDispatcher");
37
37
  var import_instrumentation = require("../instrumentation");
38
38
  var import_urlMatch = require("../../utils/isomorphic/urlMatch");
39
+ var import_agent = require("../agent/agent");
39
40
  class PageDispatcher extends import_dispatcher.Dispatcher {
40
41
  constructor(parentScope, page) {
41
42
  const mainFrame = import_frameDispatcher.FrameDispatcher.from(parentScope, page.mainFrame());
@@ -258,6 +259,12 @@ class PageDispatcher extends import_dispatcher.Dispatcher {
258
259
  const buffer = await progress.race(this._page.pdf(params));
259
260
  return { pdf: buffer };
260
261
  }
262
+ async perform(params, progress) {
263
+ await (0, import_agent.pagePerform)(progress, this._page, params);
264
+ }
265
+ async extract(params, progress) {
266
+ return { result: await (0, import_agent.pageExtract)(progress, this._page, params) };
267
+ }
261
268
  async requests(params, progress) {
262
269
  this._subscriptions.add("request");
263
270
  return { requests: this._page.networkRequests().map((request) => import_networkDispatchers.RequestDispatcher.from(this.parentScope(), request)) };
@@ -170,9 +170,9 @@ const causeToResourceType = {
170
170
  TYPE_FONT: "font",
171
171
  TYPE_MEDIA: "media",
172
172
  TYPE_WEBSOCKET: "websocket",
173
- TYPE_CSP_REPORT: "other",
173
+ TYPE_CSP_REPORT: "cspreport",
174
174
  TYPE_XSLT: "other",
175
- TYPE_BEACON: "other",
175
+ TYPE_BEACON: "beacon",
176
176
  TYPE_FETCH: "fetch",
177
177
  TYPE_IMAGESET: "image",
178
178
  TYPE_WEB_MANIFEST: "manifest"
@@ -417,24 +417,25 @@ class FFPage {
417
417
  throw e;
418
418
  });
419
419
  }
420
- async setScreencastOptions(options) {
421
- if (options) {
422
- const { screencastId } = await this._session.send("Page.startScreencast", options);
423
- this._screencastId = screencastId;
424
- } else {
425
- await this._session.send("Page.stopScreencast");
426
- }
420
+ async startScreencast(options) {
421
+ const { screencastId } = await this._session.send("Page.startScreencast", options);
422
+ this._screencastId = screencastId;
423
+ }
424
+ async stopScreencast() {
425
+ await this._session.send("Page.stopScreencast");
427
426
  }
428
427
  _onScreencastFrame(event) {
429
428
  if (!this._screencastId)
430
429
  return;
431
430
  const screencastId = this._screencastId;
432
- this._page.throttleScreencastFrameAck(() => {
431
+ this._page.screencast.throttleFrameAck(() => {
433
432
  this._session.send("Page.screencastFrameAck", { screencastId }).catch((e) => import_debugLogger.debugLogger.log("error", e));
434
433
  });
435
434
  const buffer = Buffer.from(event.data, "base64");
436
435
  this._page.emit(import_page2.Page.Events.ScreencastFrame, {
437
436
  buffer,
437
+ frameSwapWallTime: event.timestamp * 1e3,
438
+ // timestamp is in seconds, we need to convert to milliseconds.
438
439
  width: event.deviceWidth,
439
440
  height: event.deviceHeight
440
441
  });
@@ -569,7 +569,7 @@ class Frame extends import_instrumentation.SdkObject {
569
569
  const request = navigationEvent.newDocument ? navigationEvent.newDocument.request : void 0;
570
570
  return request ? progress.race(request._finalRequest().response()) : null;
571
571
  }
572
- async _waitForLoadState(progress, state) {
572
+ async waitForLoadState(progress, state) {
573
573
  const waitUntil = verifyLifecycle("state", state);
574
574
  if (!this._firedLifecycleEvents.has(waitUntil))
575
575
  await import_helper.helper.waitForEvent(progress, this, Frame.Events.AddLifecycle, (e) => e === waitUntil).promise;
@@ -736,7 +736,7 @@ class Frame extends import_instrumentation.SdkObject {
736
736
  this._onClearLifecycle();
737
737
  tagPromise.resolve();
738
738
  });
739
- const lifecyclePromise = progress.race(tagPromise).then(() => this._waitForLoadState(progress, waitUntil));
739
+ const lifecyclePromise = progress.race(tagPromise).then(() => this.waitForLoadState(progress, waitUntil));
740
740
  const contentPromise = progress.race(context.evaluate(({ html: html2, tag: tag2 }) => {
741
741
  document.open();
742
742
  console.debug(tag2);
@@ -436,6 +436,9 @@ class Response extends import_instrumentation.SdkObject {
436
436
  request() {
437
437
  return this._request;
438
438
  }
439
+ finished() {
440
+ return this._finishedPromise;
441
+ }
439
442
  frame() {
440
443
  return this._request.frame();
441
444
  }