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
@@ -53,6 +53,7 @@ var import_manualPromise = require("../utils/isomorphic/manualPromise");
53
53
  var import_utilityScriptSerializers = require("../utils/isomorphic/utilityScriptSerializers");
54
54
  var import_callLog = require("./callLog");
55
55
  var rawBindingsControllerSource = __toESM(require("../generated/bindingsControllerSource"));
56
+ var import_screencast = require("./screencast");
56
57
  class Page extends import_instrumentation.SdkObject {
57
58
  constructor(delegate, browserContext) {
58
59
  super(browserContext, "page");
@@ -74,9 +75,6 @@ class Page extends import_instrumentation.SdkObject {
74
75
  this._lastLocatorHandlerUid = 0;
75
76
  this._locatorHandlerRunningCounter = 0;
76
77
  this._networkRequests = [];
77
- // Aiming at 25 fps by default - each frame is 40ms, but we give some slack with 35ms.
78
- // When throttling for tracing, 200ms between frames, except for 10 frames around the action.
79
- this._frameThrottler = new FrameThrottler(10, 35, 200);
80
78
  this.attribution.page = this;
81
79
  this.delegate = delegate;
82
80
  this.browserContext = browserContext;
@@ -85,6 +83,7 @@ class Page extends import_instrumentation.SdkObject {
85
83
  this.touchscreen = new input.Touchscreen(delegate.rawTouchscreen, this);
86
84
  this.screenshotter = new import_screenshotter.Screenshotter(this);
87
85
  this.frameManager = new frames.FrameManager(this);
86
+ this.screencast = new import_screencast.Screencast(this);
88
87
  if (delegate.pdf)
89
88
  this.pdf = delegate.pdf.bind(delegate);
90
89
  this.coverage = delegate.coverage ? delegate.coverage() : null;
@@ -158,7 +157,7 @@ class Page extends import_instrumentation.SdkObject {
158
157
  }
159
158
  _didClose() {
160
159
  this.frameManager.dispose();
161
- this._frameThrottler.dispose();
160
+ this.screencast.stopFrameThrottler();
162
161
  (0, import_utils.assert)(this._closedState !== "closed", "Page closed twice");
163
162
  this._closedState = "closed";
164
163
  this.emit(Page.Events.Close);
@@ -168,7 +167,7 @@ class Page extends import_instrumentation.SdkObject {
168
167
  }
169
168
  _didCrash() {
170
169
  this.frameManager.dispose();
171
- this._frameThrottler.dispose();
170
+ this.screencast.stopFrameThrottler();
172
171
  this.emit(Page.Events.Crash);
173
172
  this._crashed = true;
174
173
  this.instrumentation.onPageClose(this);
@@ -641,16 +640,6 @@ class Page extends import_instrumentation.SdkObject {
641
640
  getBinding(name) {
642
641
  return this._pageBindings.get(name) || this.browserContext._pageBindings.get(name);
643
642
  }
644
- setScreencastOptions(options) {
645
- this.delegate.setScreencastOptions(options).catch((e) => import_debugLogger.debugLogger.log("error", e));
646
- this._frameThrottler.setThrottlingEnabled(!!options);
647
- }
648
- throttleScreencastFrameAck(ack) {
649
- this._frameThrottler.ack(ack);
650
- }
651
- temporarilyDisableTracingScreencastThrottling() {
652
- this._frameThrottler.recharge();
653
- }
654
643
  async safeNonStallingEvaluateInAllFrames(expression, world, options = {}) {
655
644
  await Promise.all(this.frames().map(async (frame) => {
656
645
  try {
@@ -665,7 +654,7 @@ class Page extends import_instrumentation.SdkObject {
665
654
  await Promise.all(this.frames().map((frame) => frame.hideHighlight().catch(() => {
666
655
  })));
667
656
  }
668
- async snapshotForAI(progress, options) {
657
+ async snapshotForAI(progress, options = {}) {
669
658
  const snapshot = await snapshotFrameForAI(progress, this.mainFrame(), options);
670
659
  return { full: snapshot.full.join("\n"), incremental: snapshot.incremental?.join("\n") };
671
660
  }
@@ -763,55 +752,6 @@ class InitScript {
763
752
  })();`;
764
753
  }
765
754
  }
766
- class FrameThrottler {
767
- constructor(nonThrottledFrames, defaultInterval, throttlingInterval) {
768
- this._acks = [];
769
- this._throttlingEnabled = false;
770
- this._nonThrottledFrames = nonThrottledFrames;
771
- this._budget = nonThrottledFrames;
772
- this._defaultInterval = defaultInterval;
773
- this._throttlingInterval = throttlingInterval;
774
- this._tick();
775
- }
776
- dispose() {
777
- if (this._timeoutId) {
778
- clearTimeout(this._timeoutId);
779
- this._timeoutId = void 0;
780
- }
781
- }
782
- setThrottlingEnabled(enabled) {
783
- this._throttlingEnabled = enabled;
784
- }
785
- recharge() {
786
- for (const ack of this._acks)
787
- ack();
788
- this._acks = [];
789
- this._budget = this._nonThrottledFrames;
790
- if (this._timeoutId) {
791
- clearTimeout(this._timeoutId);
792
- this._tick();
793
- }
794
- }
795
- ack(ack) {
796
- if (!this._timeoutId) {
797
- ack();
798
- return;
799
- }
800
- this._acks.push(ack);
801
- }
802
- _tick() {
803
- const ack = this._acks.shift();
804
- if (ack) {
805
- --this._budget;
806
- ack();
807
- }
808
- if (this._throttlingEnabled && this._budget <= 0) {
809
- this._timeoutId = setTimeout(() => this._tick(), this._throttlingInterval);
810
- } else {
811
- this._timeoutId = setTimeout(() => this._tick(), this._defaultInterval);
812
- }
813
- }
814
- }
815
755
  async function snapshotFrameForAI(progress, frame, options) {
816
756
  const snapshot = await frame.retryWithProgressAndTimeouts(progress, [1e3, 2e3, 4e3, 8e3], async (continuePolling) => {
817
757
  try {
@@ -53,9 +53,10 @@ class ProgressController {
53
53
  this._onCallLog?.(message);
54
54
  },
55
55
  metadata: this.metadata,
56
- race: (promise) => {
56
+ race: (promise, options) => {
57
57
  const promises = Array.isArray(promise) ? promise : [promise];
58
- return Promise.race([...promises, this._forceAbortPromise]);
58
+ const timerPromise = options?.timeout ? new Promise((f) => setTimeout(f, options.timeout)) : null;
59
+ return Promise.race([...promises, ...timerPromise ? [timerPromise] : [], this._forceAbortPromise]);
59
60
  },
60
61
  wait: async (timeout2) => {
61
62
  let timer2;
@@ -1296,7 +1296,7 @@ ${e.stack}`);
1296
1296
  faultyArguments.push(arg);
1297
1297
  else
1298
1298
  executables.push(executable);
1299
- if (executable?.browserName === "chromium")
1299
+ if (executable?.browserName)
1300
1300
  executables.push(this.findExecutable("ffmpeg"));
1301
1301
  };
1302
1302
  for (const alias of aliases) {
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var screencast_exports = {};
30
+ __export(screencast_exports, {
31
+ Screencast: () => Screencast
32
+ });
33
+ module.exports = __toCommonJS(screencast_exports);
34
+ var import_path = __toESM(require("path"));
35
+ var import_utils = require("../utils");
36
+ var import_utils2 = require("../utils");
37
+ var import_videoRecorder = require("./videoRecorder");
38
+ var import_page = require("./page");
39
+ var import_registry = require("./registry");
40
+ class Screencast {
41
+ constructor(page) {
42
+ this._videoRecorder = null;
43
+ this._screencastId = null;
44
+ this._screencastClients = /* @__PURE__ */ new Set();
45
+ // Aiming at 25 fps by default - each frame is 40ms, but we give some slack with 35ms.
46
+ // When throttling for tracing, 200ms between frames, except for 10 frames around the action.
47
+ this._frameThrottler = new FrameThrottler(10, 35, 200);
48
+ this._page = page;
49
+ }
50
+ stopFrameThrottler() {
51
+ this._frameThrottler.dispose();
52
+ }
53
+ setOptions(options) {
54
+ this._setOptions(options).catch((e) => import_utils2.debugLogger.log("error", e));
55
+ this._frameThrottler.setThrottlingEnabled(!!options);
56
+ }
57
+ throttleFrameAck(ack) {
58
+ this._frameThrottler.ack(ack);
59
+ }
60
+ temporarilyDisableThrottling() {
61
+ this._frameThrottler.recharge();
62
+ }
63
+ async initializeVideoRecorder() {
64
+ const recordVideo = this._page.browserContext._options.recordVideo;
65
+ if (!recordVideo)
66
+ return void 0;
67
+ const screencastId = (0, import_utils.createGuid)();
68
+ const outputFile = import_path.default.join(recordVideo.dir, screencastId + ".webm");
69
+ const screencastOptions = {
70
+ // validateBrowserContextOptions ensures correct video size.
71
+ ...recordVideo.size,
72
+ outputFile
73
+ };
74
+ await (0, import_utils.mkdirIfNeeded)(import_path.default.join(recordVideo.dir, "dummy"));
75
+ await this._createVideoRecorder(screencastId, screencastOptions);
76
+ this._page.waitForInitializedOrError().then((p) => {
77
+ if (p instanceof Error)
78
+ this.stopVideoRecording().catch(() => {
79
+ });
80
+ });
81
+ return screencastOptions;
82
+ }
83
+ async startVideoRecording(options) {
84
+ const screencastId = this._screencastId;
85
+ (0, import_utils.assert)(screencastId);
86
+ this._page.once(import_page.Page.Events.Close, () => this.stopVideoRecording().catch(() => {
87
+ }));
88
+ const gotFirstFrame = new Promise((f) => this._page.once(import_page.Page.Events.ScreencastFrame, f));
89
+ await this._startScreencast(this._videoRecorder, {
90
+ quality: 90,
91
+ width: options.width,
92
+ height: options.height
93
+ });
94
+ gotFirstFrame.then(() => {
95
+ this._page.browserContext._browser._videoStarted(this._page.browserContext, screencastId, options.outputFile, this._page.waitForInitializedOrError());
96
+ });
97
+ }
98
+ async stopVideoRecording() {
99
+ if (!this._screencastId)
100
+ return;
101
+ const screencastId = this._screencastId;
102
+ this._screencastId = null;
103
+ const recorder = this._videoRecorder;
104
+ this._videoRecorder = null;
105
+ await this._stopScreencast(recorder);
106
+ await recorder.stop().catch(() => {
107
+ });
108
+ const video = this._page.browserContext._browser._takeVideo(screencastId);
109
+ video?.reportFinished();
110
+ }
111
+ async _setOptions(options) {
112
+ if (options)
113
+ await this._startScreencast(this, options);
114
+ else
115
+ await this._stopScreencast(this);
116
+ }
117
+ async _startScreencast(client, options) {
118
+ this._screencastClients.add(client);
119
+ if (this._screencastClients.size === 1) {
120
+ await this._page.delegate.startScreencast({
121
+ width: options.width,
122
+ height: options.height,
123
+ quality: options.quality
124
+ });
125
+ }
126
+ }
127
+ async _stopScreencast(client) {
128
+ this._screencastClients.delete(client);
129
+ if (!this._screencastClients.size)
130
+ await this._page.delegate.stopScreencast();
131
+ }
132
+ async _createVideoRecorder(screencastId, options) {
133
+ (0, import_utils.assert)(!this._screencastId);
134
+ const ffmpegPath = import_registry.registry.findExecutable("ffmpeg").executablePathOrDie(this._page.browserContext._browser.sdkLanguage());
135
+ this._videoRecorder = await import_videoRecorder.VideoRecorder.launch(this._page, ffmpegPath, options);
136
+ this._screencastId = screencastId;
137
+ }
138
+ }
139
+ class FrameThrottler {
140
+ constructor(nonThrottledFrames, defaultInterval, throttlingInterval) {
141
+ this._acks = [];
142
+ this._throttlingEnabled = false;
143
+ this._nonThrottledFrames = nonThrottledFrames;
144
+ this._budget = nonThrottledFrames;
145
+ this._defaultInterval = defaultInterval;
146
+ this._throttlingInterval = throttlingInterval;
147
+ this._tick();
148
+ }
149
+ dispose() {
150
+ if (this._timeoutId) {
151
+ clearTimeout(this._timeoutId);
152
+ this._timeoutId = void 0;
153
+ }
154
+ }
155
+ setThrottlingEnabled(enabled) {
156
+ this._throttlingEnabled = enabled;
157
+ }
158
+ recharge() {
159
+ for (const ack of this._acks)
160
+ ack();
161
+ this._acks = [];
162
+ this._budget = this._nonThrottledFrames;
163
+ if (this._timeoutId) {
164
+ clearTimeout(this._timeoutId);
165
+ this._tick();
166
+ }
167
+ }
168
+ ack(ack) {
169
+ if (!this._timeoutId) {
170
+ ack();
171
+ return;
172
+ }
173
+ this._acks.push(ack);
174
+ }
175
+ _tick() {
176
+ const ack = this._acks.shift();
177
+ if (ack) {
178
+ --this._budget;
179
+ ack();
180
+ }
181
+ if (this._throttlingEnabled && this._budget <= 0) {
182
+ this._timeoutId = setTimeout(() => this._tick(), this._throttlingInterval);
183
+ } else {
184
+ this._timeoutId = setTimeout(() => this._tick(), this._defaultInterval);
185
+ }
186
+ }
187
+ }
188
+ // Annotate the CommonJS export names for ESM import in node:
189
+ 0 && (module.exports = {
190
+ Screencast
191
+ });
@@ -222,7 +222,7 @@ class Tracing extends import_instrumentation.SdkObject {
222
222
  if (!(this._context instanceof import_browserContext.BrowserContext))
223
223
  return;
224
224
  for (const page of this._context.pages())
225
- page.setScreencastOptions(null);
225
+ page.screencast.setOptions(null);
226
226
  }
227
227
  _allocateNewTraceFile(state) {
228
228
  const suffix = state.chunkOrdinal ? `-chunk${state.chunkOrdinal}` : ``;
@@ -341,7 +341,7 @@ class Tracing extends import_instrumentation.SdkObject {
341
341
  const event = createBeforeActionTraceEvent(metadata, this._currentGroupId());
342
342
  if (!event)
343
343
  return Promise.resolve();
344
- sdkObject.attribution.page?.temporarilyDisableTracingScreencastThrottling();
344
+ sdkObject.attribution.page?.screencast.temporarilyDisableThrottling();
345
345
  event.beforeSnapshot = `before@${metadata.id}`;
346
346
  this._state?.callIds.add(metadata.id);
347
347
  this._appendTraceEvent(event);
@@ -353,7 +353,7 @@ class Tracing extends import_instrumentation.SdkObject {
353
353
  const event = createInputActionTraceEvent(metadata);
354
354
  if (!event)
355
355
  return Promise.resolve();
356
- sdkObject.attribution.page?.temporarilyDisableTracingScreencastThrottling();
356
+ sdkObject.attribution.page?.screencast.temporarilyDisableThrottling();
357
357
  event.inputSnapshot = `input@${metadata.id}`;
358
358
  this._appendTraceEvent(event);
359
359
  return this._captureSnapshot(event.inputSnapshot, sdkObject, metadata);
@@ -376,7 +376,7 @@ class Tracing extends import_instrumentation.SdkObject {
376
376
  const event = createAfterActionTraceEvent(metadata);
377
377
  if (!event)
378
378
  return;
379
- sdkObject.attribution.page?.temporarilyDisableTracingScreencastThrottling();
379
+ sdkObject.attribution.page?.screencast.temporarilyDisableThrottling();
380
380
  event.afterSnapshot = `after@${metadata.id}`;
381
381
  this._appendTraceEvent(event);
382
382
  return this._captureSnapshot(event.afterSnapshot, sdkObject, metadata);
@@ -484,7 +484,7 @@ class Tracing extends import_instrumentation.SdkObject {
484
484
  this._appendTraceEvent(event);
485
485
  }
486
486
  _startScreencastInPage(page) {
487
- page.setScreencastOptions(kScreencastOptions);
487
+ page.screencast.setOptions(kScreencastOptions);
488
488
  const prefix = page.guid;
489
489
  this._screencastListeners.push(
490
490
  import_eventsHelper.eventsHelper.addEventListener(page, import_page.Page.Events.ScreencastFrame, (params) => {
@@ -42,6 +42,7 @@ var import_utilsBundle = require("../../utilsBundle");
42
42
  var import_debugLogger = require("./debugLogger");
43
43
  var import_zones = require("./zones");
44
44
  var import_debug = require("./debug");
45
+ var import_mcpBundle = require("../../mcpBundle");
45
46
  const pipelineAsync = util.promisify(import_stream.pipeline);
46
47
  class NodeZone {
47
48
  constructor(zone) {
@@ -105,6 +106,7 @@ const nodePlatform = {
105
106
  streamWritable: (channel) => {
106
107
  return new WritableStreamImpl(channel);
107
108
  },
109
+ zodToJsonSchema: import_mcpBundle.zodToJsonSchema,
108
110
  zones: {
109
111
  current: () => new NodeZone((0, import_zones.currentZone)()),
110
112
  empty: new NodeZone(import_zones.emptyZone)
@@ -21,9 +21,9 @@ __export(videoRecorder_exports, {
21
21
  VideoRecorder: () => VideoRecorder
22
22
  });
23
23
  module.exports = __toCommonJS(videoRecorder_exports);
24
- var import_utils = require("../../utils");
25
- var import_page = require("../page");
26
- var import_processLauncher = require("../utils/processLauncher");
24
+ var import_utils = require("../utils");
25
+ var import_page = require("./page");
26
+ var import_processLauncher = require("./utils/processLauncher");
27
27
  const fps = 25;
28
28
  class VideoRecorder {
29
29
  constructor(page, ffmpegPath) {
@@ -315,7 +315,7 @@ class WKBrowserContext extends import_browserContext.BrowserContext {
315
315
  }
316
316
  async doClose(reason) {
317
317
  if (!this._browserContextId) {
318
- await Promise.all(this._wkPages().map((wkPage) => wkPage._stopVideo()));
318
+ await Promise.all(this._wkPages().map((wkPage) => wkPage._page.screencast.stopVideoRecording()));
319
319
  await this._browser.close({ reason });
320
320
  } else {
321
321
  await this._browser._browserSession.send("Playwright.deleteContext", { browserContextId: this._browserContextId });
@@ -54,7 +54,7 @@ class WKInterceptableRequest {
54
54
  constructor(session, frame, event, redirectedFrom, documentId) {
55
55
  this._session = session;
56
56
  this._requestId = event.requestId;
57
- const resourceType = event.type ? event.type.toLowerCase() : redirectedFrom ? redirectedFrom.request.resourceType() : "other";
57
+ const resourceType = event.type ? toResourceType(event.type) : redirectedFrom ? redirectedFrom.request.resourceType() : "other";
58
58
  let postDataBuffer = null;
59
59
  this._timestamp = event.timestamp;
60
60
  this._wallTime = event.walltime * 1e3;
@@ -162,6 +162,34 @@ function wkMillisToRoundishMillis(value) {
162
162
  }
163
163
  return (value * 1e3 | 0) / 1e3;
164
164
  }
165
+ function toResourceType(type) {
166
+ switch (type) {
167
+ case "Document":
168
+ return "document";
169
+ case "StyleSheet":
170
+ return "stylesheet";
171
+ case "Image":
172
+ return "image";
173
+ case "Font":
174
+ return "font";
175
+ case "Script":
176
+ return "script";
177
+ case "XHR":
178
+ return "xhr";
179
+ case "Fetch":
180
+ return "fetch";
181
+ case "Ping":
182
+ return "ping";
183
+ case "Beacon":
184
+ return "beacon";
185
+ case "WebSocket":
186
+ return "websocket";
187
+ case "EventSource":
188
+ return "eventsource";
189
+ default:
190
+ return "other";
191
+ }
192
+ }
165
193
  // Annotate the CommonJS export names for ESM import in node:
166
194
  0 && (module.exports = {
167
195
  WKInterceptableRequest,
@@ -31,10 +31,8 @@ __export(wkPage_exports, {
31
31
  WKPage: () => WKPage
32
32
  });
33
33
  module.exports = __toCommonJS(wkPage_exports);
34
- var import_path = __toESM(require("path"));
35
34
  var import_utils = require("../../utils");
36
35
  var import_headers = require("../../utils/isomorphic/headers");
37
- var import_crypto = require("../utils/crypto");
38
36
  var import_eventsHelper = require("../utils/eventsHelper");
39
37
  var import_hostPlatform = require("../utils/hostPlatform");
40
38
  var import_stackTrace = require("../../utils/isomorphic/stackTrace");
@@ -66,7 +64,6 @@ class WKPage {
66
64
  };
67
65
  this._lastConsoleMessage = null;
68
66
  this._requestIdToResponseReceivedPayloadEvent = /* @__PURE__ */ new Map();
69
- this._recordingVideoFile = null;
70
67
  this._screencastGeneration = 0;
71
68
  this._pageProxySession = pageProxySession;
72
69
  this._opener = opener;
@@ -116,16 +113,7 @@ class WKPage {
116
113
  for (const [key, value] of this._browserContext._permissions)
117
114
  promises.push(this._grantPermissions(key, value));
118
115
  }
119
- if (this._browserContext._options.recordVideo) {
120
- const outputFile = import_path.default.join(this._browserContext._options.recordVideo.dir, (0, import_crypto.createGuid)() + ".webm");
121
- promises.push(this._browserContext._ensureVideosPath().then(() => {
122
- return this._startVideo({
123
- // validateBrowserContextOptions ensures correct video size.
124
- ...this._browserContext._options.recordVideo.size,
125
- outputFile
126
- });
127
- }));
128
- }
116
+ promises.push(this._initializeVideoRecording());
129
117
  await Promise.all(promises);
130
118
  }
131
119
  _setSession(session) {
@@ -748,7 +736,6 @@ class WKPage {
748
736
  await this._updateState("Page.setBootstrapScript", { source: this._calculateBootstrapScript() });
749
737
  }
750
738
  async closePage(runBeforeUnload) {
751
- await this._stopVideo();
752
739
  await this._pageProxySession.sendMayFail("Target.close", {
753
740
  targetId: this._session.sessionId,
754
741
  runBeforeUnload
@@ -762,22 +749,10 @@ class WKPage {
762
749
  return import_hostPlatform.hostPlatform === "mac10.15" ? 55 : 59;
763
750
  return 0;
764
751
  }
765
- async _startVideo(options) {
766
- (0, import_utils.assert)(!this._recordingVideoFile);
767
- const { screencastId } = await this._pageProxySession.send("Screencast.startVideo", {
768
- file: this._browserContext._browser.options.channel === "webkit-wsl" ? await (0, import_webkit.translatePathToWSL)(options.outputFile) : options.outputFile,
769
- width: options.width,
770
- height: options.height,
771
- toolbarHeight: this._toolbarHeight()
772
- });
773
- this._recordingVideoFile = options.outputFile;
774
- this._browserContext._browser._videoStarted(this._browserContext, screencastId, options.outputFile, this._page.waitForInitializedOrError());
775
- }
776
- async _stopVideo() {
777
- if (!this._recordingVideoFile)
778
- return;
779
- await this._pageProxySession.sendMayFail("Screencast.stopVideo");
780
- this._recordingVideoFile = null;
752
+ async _initializeVideoRecording() {
753
+ const screencastOptions = await this._page.screencast.initializeVideoRecorder();
754
+ if (screencastOptions)
755
+ await this._page.screencast.startVideoRecording(screencastOptions);
781
756
  }
782
757
  validateScreenshotDimension(side, omitDeviceScaleFactor) {
783
758
  if (process.platform === "darwin")
@@ -845,23 +820,28 @@ class WKPage {
845
820
  throw e;
846
821
  });
847
822
  }
848
- async setScreencastOptions(options) {
849
- if (options) {
850
- const so = { ...options, toolbarHeight: this._toolbarHeight() };
851
- const { generation } = await this._pageProxySession.send("Screencast.startScreencast", so);
852
- this._screencastGeneration = generation;
853
- } else {
854
- await this._pageProxySession.send("Screencast.stopScreencast");
855
- }
823
+ async startScreencast(options) {
824
+ const { generation } = await this._pageProxySession.send("Screencast.startScreencast", {
825
+ quality: options.quality,
826
+ width: options.width,
827
+ height: options.height,
828
+ toolbarHeight: this._toolbarHeight()
829
+ });
830
+ this._screencastGeneration = generation;
831
+ }
832
+ async stopScreencast() {
833
+ await this._pageProxySession.sendMayFail("Screencast.stopScreencast");
856
834
  }
857
835
  _onScreencastFrame(event) {
858
836
  const generation = this._screencastGeneration;
859
- this._page.throttleScreencastFrameAck(() => {
837
+ this._page.screencast.throttleFrameAck(() => {
860
838
  this._pageProxySession.send("Screencast.screencastFrameAck", { generation }).catch((e) => import_debugLogger.debugLogger.log("error", e));
861
839
  });
862
840
  const buffer = Buffer.from(event.data, "base64");
863
841
  this._page.emit(import_page.Page.Events.ScreencastFrame, {
864
842
  buffer,
843
+ frameSwapWallTime: event.timestamp * 1e3,
844
+ // timestamp is in seconds, we need to convert to milliseconds.
865
845
  width: event.deviceWidth,
866
846
  height: event.deviceHeight
867
847
  });
@@ -886,7 +866,7 @@ class WKPage {
886
866
  const pageProxyId = this._pageProxySession.sessionId;
887
867
  const objectId = handle._objectId;
888
868
  if (this._browserContext._browser?.options.channel === "webkit-wsl")
889
- paths = await Promise.all(paths.map((path2) => (0, import_webkit.translatePathToWSL)(path2)));
869
+ paths = await Promise.all(paths.map((path) => (0, import_webkit.translatePathToWSL)(path)));
890
870
  await Promise.all([
891
871
  this._pageProxySession.connection.browserSession.send("Playwright.grantFileReadAccess", { pageProxyId, paths }),
892
872
  this._session.send("DOM.setInputFiles", { objectId, paths })
@@ -143,6 +143,8 @@ const methodMetainfo = /* @__PURE__ */ new Map([
143
143
  ["Page.stopCSSCoverage", { title: "Stop CSS coverage", group: "configuration" }],
144
144
  ["Page.bringToFront", { title: "Bring to front" }],
145
145
  ["Page.updateSubscription", { internal: true }],
146
+ ["Page.perform", { internal: true }],
147
+ ["Page.extract", { internal: true }],
146
148
  ["Frame.evalOnSelector", { title: "Evaluate", snapshot: true, pausesBeforeAction: true }],
147
149
  ["Frame.evalOnSelectorAll", { title: "Evaluate", snapshot: true, pausesBeforeAction: true }],
148
150
  ["Frame.addScriptTag", { title: "Add script tag", snapshot: true, pausesBeforeAction: true }],