patchright-core 1.57.0 → 1.58.2

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 (148) hide show
  1. package/ThirdPartyNotices.txt +3223 -308
  2. package/browsers.json +21 -22
  3. package/lib/cli/program.js +4 -5
  4. package/lib/client/api.js +3 -0
  5. package/lib/client/browser.js +3 -5
  6. package/lib/client/browserContext.js +40 -4
  7. package/lib/client/browserType.js +4 -3
  8. package/lib/client/connection.js +4 -0
  9. package/lib/client/elementHandle.js +3 -0
  10. package/lib/client/events.js +3 -0
  11. package/lib/client/fetch.js +3 -4
  12. package/lib/client/frame.js +10 -1
  13. package/lib/client/locator.js +8 -0
  14. package/lib/client/network.js +5 -1
  15. package/lib/client/page.js +29 -1
  16. package/lib/client/pageAgent.js +64 -0
  17. package/lib/client/platform.js +3 -0
  18. package/lib/client/tracing.js +1 -1
  19. package/lib/generated/injectedScriptSource.js +1 -1
  20. package/lib/generated/pollingRecorderSource.js +1 -1
  21. package/lib/mcpBundle.js +84 -0
  22. package/lib/mcpBundleImpl/index.js +147 -0
  23. package/lib/protocol/serializers.js +5 -0
  24. package/lib/protocol/validator.js +88 -4
  25. package/lib/remote/playwrightServer.js +1 -2
  26. package/lib/server/agent/actionRunner.js +335 -0
  27. package/lib/server/agent/actions.js +128 -0
  28. package/lib/server/agent/codegen.js +111 -0
  29. package/lib/server/agent/context.js +150 -0
  30. package/lib/server/agent/expectTools.js +156 -0
  31. package/lib/server/agent/pageAgent.js +204 -0
  32. package/lib/server/agent/performTools.js +262 -0
  33. package/lib/server/agent/tool.js +109 -0
  34. package/lib/server/artifact.js +1 -1
  35. package/lib/server/bidi/bidiBrowser.js +56 -12
  36. package/lib/server/bidi/bidiChromium.js +8 -12
  37. package/lib/server/bidi/bidiConnection.js +1 -0
  38. package/lib/server/bidi/bidiDeserializer.js +116 -0
  39. package/lib/server/bidi/bidiExecutionContext.js +75 -29
  40. package/lib/server/bidi/bidiFirefox.js +6 -8
  41. package/lib/server/bidi/bidiNetworkManager.js +1 -1
  42. package/lib/server/bidi/bidiPage.js +39 -28
  43. package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
  44. package/lib/server/browserContext.js +34 -26
  45. package/lib/server/browserType.js +12 -4
  46. package/lib/server/chromium/chromium.js +14 -20
  47. package/lib/server/chromium/chromiumSwitches.js +2 -2
  48. package/lib/server/chromium/crBrowser.js +22 -12
  49. package/lib/server/chromium/crConnection.js +0 -5
  50. package/lib/server/chromium/crCoverage.js +13 -1
  51. package/lib/server/chromium/crDevTools.js +0 -2
  52. package/lib/server/chromium/crNetworkManager.js +92 -12
  53. package/lib/server/chromium/crPage.js +62 -116
  54. package/lib/server/codegen/javascript.js +6 -29
  55. package/lib/server/deviceDescriptorsSource.json +56 -56
  56. package/lib/server/dispatchers/browserContextDispatcher.js +3 -2
  57. package/lib/server/dispatchers/dispatcher.js +6 -13
  58. package/lib/server/dispatchers/frameDispatcher.js +1 -1
  59. package/lib/server/dispatchers/jsHandleDispatcher.js +2 -2
  60. package/lib/server/dispatchers/pageAgentDispatcher.js +96 -0
  61. package/lib/server/dispatchers/pageDispatcher.js +4 -0
  62. package/lib/server/dom.js +12 -3
  63. package/lib/server/electron/electron.js +5 -2
  64. package/lib/server/firefox/ffBrowser.js +10 -20
  65. package/lib/server/firefox/ffConnection.js +0 -5
  66. package/lib/server/firefox/ffNetworkManager.js +2 -2
  67. package/lib/server/firefox/ffPage.js +15 -18
  68. package/lib/server/firefox/firefox.js +6 -8
  69. package/lib/server/frameSelectors.js +16 -4
  70. package/lib/server/frames.js +251 -86
  71. package/lib/server/instrumentation.js +3 -0
  72. package/lib/server/javascript.js +8 -4
  73. package/lib/server/launchApp.js +2 -1
  74. package/lib/server/network.js +50 -12
  75. package/lib/server/page.js +61 -91
  76. package/lib/server/progress.js +26 -6
  77. package/lib/server/recorder/recorderApp.js +79 -100
  78. package/lib/server/registry/browserFetcher.js +6 -4
  79. package/lib/server/registry/index.js +172 -149
  80. package/lib/server/registry/oopDownloadBrowserMain.js +3 -0
  81. package/lib/server/screencast.js +190 -0
  82. package/lib/server/screenshotter.js +6 -0
  83. package/lib/server/trace/recorder/snapshotter.js +17 -8
  84. package/lib/server/trace/recorder/snapshotterInjected.js +30 -72
  85. package/lib/server/trace/recorder/tracing.js +29 -21
  86. package/lib/server/trace/viewer/traceParser.js +72 -0
  87. package/lib/server/trace/viewer/traceViewer.js +21 -17
  88. package/lib/server/utils/expectUtils.js +87 -2
  89. package/lib/server/utils/hostPlatform.js +15 -0
  90. package/lib/server/utils/httpServer.js +5 -20
  91. package/lib/server/utils/network.js +37 -28
  92. package/lib/server/utils/nodePlatform.js +6 -0
  93. package/lib/server/{chromium/videoRecorder.js → videoRecorder.js} +22 -13
  94. package/lib/server/webkit/webkit.js +4 -6
  95. package/lib/server/webkit/wkBrowser.js +2 -6
  96. package/lib/server/webkit/wkConnection.js +1 -6
  97. package/lib/server/webkit/wkInterceptableRequest.js +29 -1
  98. package/lib/server/webkit/wkPage.js +75 -46
  99. package/lib/utils/isomorphic/ariaSnapshot.js +60 -2
  100. package/lib/utils/isomorphic/lruCache.js +51 -0
  101. package/lib/utils/isomorphic/protocolMetainfo.js +9 -1
  102. package/lib/utils/isomorphic/stringUtils.js +49 -0
  103. package/lib/utils/isomorphic/trace/entries.js +16 -0
  104. package/lib/utils/isomorphic/trace/snapshotRenderer.js +499 -0
  105. package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
  106. package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
  107. package/lib/utils/isomorphic/trace/traceLoader.js +131 -0
  108. package/lib/utils/isomorphic/trace/traceModel.js +365 -0
  109. package/lib/utils/isomorphic/trace/traceModernizer.js +400 -0
  110. package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
  111. package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
  112. package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
  113. package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
  114. package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
  115. package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
  116. package/lib/utils/isomorphic/yaml.js +84 -0
  117. package/lib/utils.js +2 -0
  118. package/lib/utilsBundle.js +2 -5
  119. package/lib/utilsBundleImpl/index.js +165 -165
  120. package/lib/vite/htmlReport/index.html +21 -21
  121. package/lib/vite/recorder/assets/codeMirrorModule-CFUTFUO7.js +32 -0
  122. package/lib/vite/{traceViewer/codeMirrorModule.C3UTv-Ge.css → recorder/assets/codeMirrorModule-DYBRYzYX.css} +1 -1
  123. package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
  124. package/lib/vite/recorder/assets/index-CVkBxsGf.js +193 -0
  125. package/lib/vite/recorder/index.html +2 -2
  126. package/lib/vite/traceViewer/assets/codeMirrorModule-BVA4h_ZY.js +32 -0
  127. package/lib/vite/traceViewer/assets/defaultSettingsView-CjfmcdOz.js +266 -0
  128. package/lib/vite/{recorder/assets/codeMirrorModule-C3UTv-Ge.css → traceViewer/codeMirrorModule.DYBRYzYX.css} +1 -1
  129. package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +1 -0
  130. package/lib/vite/traceViewer/index.BVu7tZDe.css +1 -0
  131. package/lib/vite/traceViewer/index.BtyWtaE-.js +2 -0
  132. package/lib/vite/traceViewer/index.html +4 -4
  133. package/lib/vite/traceViewer/sw.bundle.js +5 -3
  134. package/lib/vite/traceViewer/uiMode.fyrXARf2.js +5 -0
  135. package/lib/vite/traceViewer/uiMode.html +3 -3
  136. package/package.json +2 -1
  137. package/types/protocol.d.ts +738 -159
  138. package/types/types.d.ts +25 -38
  139. package/lib/server/bidi/third_party/bidiDeserializer.js +0 -98
  140. package/lib/server/trace/test/inMemorySnapshotter.js +0 -87
  141. package/lib/vite/recorder/assets/codeMirrorModule-CBbSe-ZI.js +0 -25
  142. package/lib/vite/recorder/assets/index-CpZVd2nA.js +0 -193
  143. package/lib/vite/traceViewer/assets/codeMirrorModule-DHz0wP2C.js +0 -25
  144. package/lib/vite/traceViewer/assets/defaultSettingsView-WsZP88O6.js +0 -266
  145. package/lib/vite/traceViewer/defaultSettingsView.ConWv5KN.css +0 -1
  146. package/lib/vite/traceViewer/index.C4Y3Aw8n.css +0 -1
  147. package/lib/vite/traceViewer/index.C8xAeo93.js +0 -2
  148. package/lib/vite/traceViewer/uiMode.BltraIJB.js +0 -5
@@ -0,0 +1,96 @@
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 pageAgentDispatcher_exports = {};
20
+ __export(pageAgentDispatcher_exports, {
21
+ PageAgentDispatcher: () => PageAgentDispatcher
22
+ });
23
+ module.exports = __toCommonJS(pageAgentDispatcher_exports);
24
+ var import_dispatcher = require("./dispatcher");
25
+ var import_pageAgent = require("../agent/pageAgent");
26
+ var import_instrumentation = require("../instrumentation");
27
+ var import_context = require("../agent/context");
28
+ class PageAgentDispatcher extends import_dispatcher.Dispatcher {
29
+ constructor(scope, options) {
30
+ super(scope, new import_instrumentation.SdkObject(scope._object, "pageAgent"), "PageAgent", { page: scope });
31
+ this._type_PageAgent = true;
32
+ this._type_EventTarget = true;
33
+ this._usage = { turns: 0, inputTokens: 0, outputTokens: 0 };
34
+ this._page = scope._object;
35
+ this._context = new import_context.Context(this._page, options, this._eventSupport());
36
+ }
37
+ async perform(params, progress) {
38
+ try {
39
+ await (0, import_pageAgent.pageAgentPerform)(progress, this._context, params.task, params);
40
+ } finally {
41
+ this._context.pushHistory({ type: "perform", description: params.task });
42
+ }
43
+ return { usage: this._usage };
44
+ }
45
+ async expect(params, progress) {
46
+ try {
47
+ await (0, import_pageAgent.pageAgentExpect)(progress, this._context, params.expectation, params);
48
+ } finally {
49
+ this._context.pushHistory({ type: "expect", description: params.expectation });
50
+ }
51
+ return { usage: this._usage };
52
+ }
53
+ async extract(params, progress) {
54
+ const result = await (0, import_pageAgent.pageAgentExtract)(progress, this._context, params.query, params.schema, params);
55
+ return { result, usage: this._usage };
56
+ }
57
+ async usage(params, progress) {
58
+ return { usage: this._usage };
59
+ }
60
+ async dispose(params, progress) {
61
+ progress.metadata.potentiallyClosesScope = true;
62
+ void this.stopPendingOperations(new Error("The agent is disposed"));
63
+ this._dispose();
64
+ }
65
+ _eventSupport() {
66
+ const self = this;
67
+ return {
68
+ onBeforeTurn(params) {
69
+ const userMessage = params.conversation.messages.find((m) => m.role === "user");
70
+ self._dispatchEvent("turn", { role: "user", message: userMessage?.content ?? "" });
71
+ },
72
+ onAfterTurn(params) {
73
+ const usage = { inputTokens: params.totalUsage.input, outputTokens: params.totalUsage.output };
74
+ const intent = params.assistantMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
75
+ self._dispatchEvent("turn", { role: "assistant", message: intent, usage });
76
+ if (!params.assistantMessage.content.filter((c) => c.type === "tool_call").length)
77
+ self._dispatchEvent("turn", { role: "assistant", message: `no tool calls`, usage });
78
+ self._usage = { turns: self._usage.turns + 1, inputTokens: self._usage.inputTokens + usage.inputTokens, outputTokens: self._usage.outputTokens + usage.outputTokens };
79
+ },
80
+ onBeforeToolCall(params) {
81
+ self._dispatchEvent("turn", { role: "assistant", message: `call tool "${params.toolCall.name}"` });
82
+ },
83
+ onAfterToolCall(params) {
84
+ const suffix = params.toolCall.result?.isError ? "failed" : "succeeded";
85
+ self._dispatchEvent("turn", { role: "user", message: `tool "${params.toolCall.name}" ${suffix}` });
86
+ },
87
+ onToolCallError(params) {
88
+ self._dispatchEvent("turn", { role: "user", message: `tool "${params.toolCall.name}" failed: ${params.error.message}` });
89
+ }
90
+ };
91
+ }
92
+ }
93
+ // Annotate the CommonJS export names for ESM import in node:
94
+ 0 && (module.exports = {
95
+ PageAgentDispatcher
96
+ });
@@ -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_pageAgentDispatcher = require("./pageAgentDispatcher");
39
40
  class PageDispatcher extends import_dispatcher.Dispatcher {
40
41
  constructor(parentScope, page) {
41
42
  const mainFrame = import_frameDispatcher.FrameDispatcher.from(parentScope, page.mainFrame());
@@ -288,6 +289,9 @@ class PageDispatcher extends import_dispatcher.Dispatcher {
288
289
  const coverage = this._page.coverage;
289
290
  return await coverage.stopCSSCoverage();
290
291
  }
292
+ async agent(params, progress) {
293
+ return { agent: new import_pageAgentDispatcher.PageAgentDispatcher(this, params) };
294
+ }
291
295
  _onFrameAttached(frame) {
292
296
  this._dispatchEvent("frameAttached", { frame: import_frameDispatcher.FrameDispatcher.from(this.parentScope(), frame) });
293
297
  }
package/lib/server/dom.js CHANGED
@@ -255,6 +255,7 @@ class ElementHandle extends js.JSHandle {
255
255
  async _retryAction(progress, actionName, action, options) {
256
256
  let retry = 0;
257
257
  const waitTime = [0, 20, 100, 100, 500];
258
+ const noAutoWaiting = options.__testHookNoAutoWaiting ?? options.noAutoWaiting;
258
259
  while (true) {
259
260
  if (retry) {
260
261
  progress.log(`retrying ${actionName} action${options.trial ? " (trial run)" : ""}`);
@@ -268,35 +269,43 @@ class ElementHandle extends js.JSHandle {
268
269
  } else {
269
270
  progress.log(`attempting ${actionName} action${options.trial ? " (trial run)" : ""}`);
270
271
  }
271
- if (!options.skipActionPreChecks && !options.force)
272
+ if (!options.skipActionPreChecks && !options.force && !noAutoWaiting)
272
273
  await this._frame._page.performActionPreChecks(progress);
273
274
  const result = await action(retry);
274
275
  ++retry;
275
276
  if (result === "error:notvisible") {
276
- if (options.force)
277
+ if (options.force || noAutoWaiting)
277
278
  throw new NonRecoverableDOMError("Element is not visible");
278
279
  progress.log(" element is not visible");
279
280
  continue;
280
281
  }
281
282
  if (result === "error:notinviewport") {
282
- if (options.force)
283
+ if (options.force || noAutoWaiting)
283
284
  throw new NonRecoverableDOMError("Element is outside of the viewport");
284
285
  progress.log(" element is outside of the viewport");
285
286
  continue;
286
287
  }
287
288
  if (result === "error:optionsnotfound") {
289
+ if (noAutoWaiting)
290
+ throw new NonRecoverableDOMError("Did not find some options");
288
291
  progress.log(" did not find some options");
289
292
  continue;
290
293
  }
291
294
  if (result === "error:optionnotenabled") {
295
+ if (noAutoWaiting)
296
+ throw new NonRecoverableDOMError("Option being selected is not enabled");
292
297
  progress.log(" option being selected is not enabled");
293
298
  continue;
294
299
  }
295
300
  if (typeof result === "object" && "hitTargetDescription" in result) {
301
+ if (noAutoWaiting)
302
+ throw new NonRecoverableDOMError(`${result.hitTargetDescription} intercepts pointer events`);
296
303
  progress.log(` ${result.hitTargetDescription} intercepts pointer events`);
297
304
  continue;
298
305
  }
299
306
  if (typeof result === "object" && "missingState" in result) {
307
+ if (noAutoWaiting)
308
+ throw new NonRecoverableDOMError(`Element is not ${result.missingState}`);
300
309
  progress.log(` element is not ${result.missingState}`);
301
310
  continue;
302
311
  }
@@ -158,8 +158,8 @@ class Electron extends import_instrumentation.SdkObject {
158
158
  let shell = false;
159
159
  if (process.platform === "win32") {
160
160
  shell = true;
161
- command = `"${command}"`;
162
- electronArguments = electronArguments.map((arg) => `"${arg}"`);
161
+ command = [command, ...electronArguments].map((arg) => `"${escapeDoubleQuotes(arg)}"`).join(" ");
162
+ electronArguments = [];
163
163
  }
164
164
  delete env.NODE_OPTIONS;
165
165
  const { launchedProcess, gracefullyClose, kill } = await (0, import_processLauncher.launchProcess)({
@@ -263,6 +263,9 @@ async function waitForLine(progress, process2, regex) {
263
263
  import_eventsHelper.eventsHelper.removeEventListeners(listeners);
264
264
  }
265
265
  }
266
+ function escapeDoubleQuotes(str) {
267
+ return str.replace(/"/g, '\\"');
268
+ }
266
269
  // Annotate the CommonJS export names for ESM import in node:
267
270
  0 && (module.exports = {
268
271
  Electron,
@@ -54,7 +54,6 @@ class FFBrowser extends import_browser.Browser {
54
54
  this.session.on("Browser.detachedFromTarget", this._onDetachedFromTarget.bind(this));
55
55
  this.session.on("Browser.downloadCreated", this._onDownloadCreated.bind(this));
56
56
  this.session.on("Browser.downloadFinished", this._onDownloadFinished.bind(this));
57
- this.session.on("Browser.videoRecordingFinished", this._onVideoRecordingFinished.bind(this));
58
57
  }
59
58
  static async connect(parent, transport, options) {
60
59
  const connection = new import_ffConnection.FFConnection(transport, options.protocolLogger, options.browserLogsCollector);
@@ -141,12 +140,9 @@ class FFBrowser extends import_browser.Browser {
141
140
  const error = payload.canceled ? "canceled" : payload.error;
142
141
  this._downloadFinished(payload.uuid, error);
143
142
  }
144
- _onVideoRecordingFinished(payload) {
145
- this._takeVideo(payload.screencastId)?.reportFinished();
146
- }
147
143
  _onDisconnect() {
148
144
  for (const video of this._idToVideo.values())
149
- video.artifact.reportFinished(new import_errors.TargetClosedError());
145
+ video.artifact.reportFinished(new import_errors.TargetClosedError(this.closeReason()));
150
146
  this._idToVideo.clear();
151
147
  for (const ffPage of this._ffPages.values())
152
148
  ffPage.didClose();
@@ -199,15 +195,13 @@ class FFBrowserContext extends import_browserContext.BrowserContext {
199
195
  promises.push(this.doUpdateOffline());
200
196
  promises.push(this.doUpdateDefaultEmulatedMedia());
201
197
  if (this._options.recordVideo) {
202
- promises.push(this._ensureVideosPath().then(() => {
203
- return this._browser.session.send("Browser.setVideoRecordingOptions", {
204
- // validateBrowserContextOptions ensures correct video size.
205
- options: {
206
- ...this._options.recordVideo.size,
207
- dir: this._options.recordVideo.dir
208
- },
209
- browserContextId: this._browserContextId
210
- });
198
+ promises.push(this._browser.session.send("Browser.setScreencastOptions", {
199
+ // validateBrowserContextOptions ensures correct video size.
200
+ options: {
201
+ ...this._options.recordVideo.size,
202
+ quality: 90
203
+ },
204
+ browserContextId: this._browserContextId
211
205
  }));
212
206
  }
213
207
  const proxy = this._options.proxyOverride || this._options.proxy;
@@ -379,12 +373,8 @@ class FFBrowserContext extends import_browserContext.BrowserContext {
379
373
  }
380
374
  async doClose(reason) {
381
375
  if (!this._browserContextId) {
382
- if (this._options.recordVideo) {
383
- await this._browser.session.send("Browser.setVideoRecordingOptions", {
384
- options: void 0,
385
- browserContextId: this._browserContextId
386
- });
387
- }
376
+ if (this._options.recordVideo)
377
+ await Promise.all(this._ffPages().map((ffPage) => ffPage._page.screencast.stopVideoRecording()));
388
378
  await this._browser.close({ reason });
389
379
  } else {
390
380
  await this._browser.session.send("Browser.removeBrowserContext", { browserContextId: this._browserContextId });
@@ -90,11 +90,6 @@ class FFSession extends import_events.EventEmitter {
90
90
  this._connection = connection;
91
91
  this._sessionId = sessionId;
92
92
  this._rawSend = rawSend;
93
- this.on = super.on;
94
- this.addListener = super.addListener;
95
- this.off = super.removeListener;
96
- this.removeListener = super.removeListener;
97
- this.once = super.once;
98
93
  }
99
94
  markAsCrashed() {
100
95
  this._crashed = true;
@@ -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"
@@ -41,9 +41,9 @@ var import_ffConnection = require("./ffConnection");
41
41
  var import_ffExecutionContext = require("./ffExecutionContext");
42
42
  var import_ffInput = require("./ffInput");
43
43
  var import_ffNetworkManager = require("./ffNetworkManager");
44
- var import_debugLogger = require("../utils/debugLogger");
45
44
  var import_stackTrace = require("../../utils/isomorphic/stackTrace");
46
45
  var import_errors = require("../errors");
46
+ var import_debugLogger = require("../utils/debugLogger");
47
47
  const UTILITY_WORLD_NAME = "__playwright_utility_world__";
48
48
  class FFPage {
49
49
  constructor(session, browserContext, opener) {
@@ -83,13 +83,16 @@ class FFPage {
83
83
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.workerDestroyed", this._onWorkerDestroyed.bind(this)),
84
84
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.dispatchMessageFromWorker", this._onDispatchMessageFromWorker.bind(this)),
85
85
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.crashed", this._onCrashed.bind(this)),
86
- import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.videoRecordingStarted", this._onVideoRecordingStarted.bind(this)),
87
86
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketCreated", this._onWebSocketCreated.bind(this)),
88
87
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketClosed", this._onWebSocketClosed.bind(this)),
89
88
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketFrameReceived", this._onWebSocketFrameReceived.bind(this)),
90
89
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketFrameSent", this._onWebSocketFrameSent.bind(this)),
91
90
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.screencastFrame", this._onScreencastFrame.bind(this))
92
91
  ];
92
+ const screencast = this._page.screencast;
93
+ const videoOptions = screencast.launchVideoRecorder();
94
+ if (videoOptions)
95
+ screencast.startVideoRecording(videoOptions).catch((e) => import_debugLogger.debugLogger.log("error", e));
93
96
  this._session.once("Page.ready", () => {
94
97
  if (this._reportedAsNew)
95
98
  return;
@@ -272,11 +275,8 @@ class FFPage {
272
275
  this._session.markAsCrashed();
273
276
  this._page._didCrash();
274
277
  }
275
- _onVideoRecordingStarted(event) {
276
- this._browserContext._browser._videoStarted(this._browserContext, event.screencastId, event.file, this._page.waitForInitializedOrError());
277
- }
278
278
  didClose() {
279
- this._markAsError(new import_errors.TargetClosedError());
279
+ this._markAsError(new import_errors.TargetClosedError(this._page.closeReason()));
280
280
  this._session.dispose();
281
281
  import_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
282
282
  this._networkManager.dispose();
@@ -417,24 +417,21 @@ 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
+ await this._session.send("Page.startScreencast", options);
422
+ }
423
+ async stopScreencast() {
424
+ await this._session.sendMayFail("Page.stopScreencast");
427
425
  }
428
426
  _onScreencastFrame(event) {
429
- if (!this._screencastId)
430
- return;
431
- const screencastId = this._screencastId;
432
- this._page.throttleScreencastFrameAck(() => {
433
- this._session.send("Page.screencastFrameAck", { screencastId }).catch((e) => import_debugLogger.debugLogger.log("error", e));
427
+ this._page.screencast.throttleFrameAck(() => {
428
+ this._session.sendMayFail("Page.screencastFrameAck");
434
429
  });
435
430
  const buffer = Buffer.from(event.data, "base64");
436
431
  this._page.emit(import_page2.Page.Events.ScreencastFrame, {
437
432
  buffer,
433
+ frameSwapWallTime: event.timestamp * 1e3,
434
+ // timestamp is in seconds, we need to convert to milliseconds.
438
435
  width: event.deviceWidth,
439
436
  height: event.deviceHeight
440
437
  });
@@ -56,15 +56,13 @@ class Firefox extends import_browserType.BrowserType {
56
56
  connectToTransport(transport, options) {
57
57
  return import_ffBrowser.FFBrowser.connect(this.attribution.playwright, transport, options);
58
58
  }
59
- doRewriteStartupLog(error) {
60
- if (!error.logs)
61
- return error;
62
- if (error.logs.includes(`as root in a regular user's session is not supported.`))
63
- error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
59
+ doRewriteStartupLog(logs) {
60
+ if (logs.includes(`as root in a regular user's session is not supported.`))
61
+ logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
64
62
  Workaround: Set the HOME=/root environment variable${process.env.GITHUB_ACTION ? " in your GitHub Actions workflow file" : ""} when running Playwright.`, 1);
65
- if (error.logs.includes("no DISPLAY environment variable specified"))
66
- error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
67
- return error;
63
+ if (logs.includes("no DISPLAY environment variable specified"))
64
+ logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
65
+ return logs;
68
66
  }
69
67
  amendEnvironment(env) {
70
68
  if (!import_path.default.isAbsolute(import_os.default.homedir()))
@@ -51,7 +51,9 @@ class FrameSelectors {
51
51
  if (!resolved)
52
52
  throw new Error(`Failed to find frame for selector "${selector}"`);
53
53
  return await resolved.injected.evaluateHandle((injected, { info, scope: scope2 }) => {
54
- return injected.querySelectorAll(info.parsed, scope2 || document);
54
+ const elements = injected.querySelectorAll(info.parsed, scope2 || document);
55
+ injected.checkDeprecatedSelectorUsage(info.parsed, elements);
56
+ return elements;
55
57
  }, { info: resolved.info, scope: resolved.scope });
56
58
  }
57
59
  async queryCount(selector, options) {
@@ -60,7 +62,9 @@ class FrameSelectors {
60
62
  throw new Error(`Failed to find frame for selector "${selector}"`);
61
63
  await options.__testHookBeforeQuery?.();
62
64
  return await resolved.injected.evaluate((injected, { info }) => {
63
- return injected.querySelectorAll(info.parsed, document).length;
65
+ const elements = injected.querySelectorAll(info.parsed, document);
66
+ injected.checkDeprecatedSelectorUsage(info.parsed, elements);
67
+ return elements.length;
64
68
  }, { info: resolved.info });
65
69
  }
66
70
  async queryAll(selector, scope) {
@@ -68,7 +72,9 @@ class FrameSelectors {
68
72
  if (!resolved)
69
73
  return [];
70
74
  const arrayHandle = await resolved.injected.evaluateHandle((injected, { info, scope: scope2 }) => {
71
- return injected.querySelectorAll(info.parsed, scope2 || document);
75
+ const elements = injected.querySelectorAll(info.parsed, scope2 || document);
76
+ injected.checkDeprecatedSelectorUsage(info.parsed, elements);
77
+ return elements;
72
78
  }, { info: resolved.info, scope: resolved.scope });
73
79
  const properties = await arrayHandle.getProperties();
74
80
  arrayHandle.dispose();
@@ -158,6 +164,7 @@ class FrameSelectors {
158
164
  if (!resolved)
159
165
  return;
160
166
  const context = await resolved.frame._context(options?.mainWorld ? "main" : resolved.info.world);
167
+ if (!context) throw new Error("Frame was detached");
161
168
  const injected = await context.injectedScript();
162
169
  return { injected, info: resolved.info, frame: resolved.frame, scope: resolved.scope };
163
170
  }
@@ -287,7 +294,7 @@ class FrameSelectors {
287
294
  }
288
295
  for (const child of queryingElement.children || []) {
289
296
  const childrenNodeIndex = queryingElement.children.indexOf(child);
290
- const childIndex = this._findElementPositionInDomTree(element, child, documentScope, currentIndex + childrenNodeIndex.toString());
297
+ const childIndex = this._findElementPositionInDomTree(element, child, documentScope, currentIndex + "." + childrenNodeIndex.toString());
291
298
  if (childIndex !== null) return childIndex;
292
299
  }
293
300
  if (queryingElement.shadowRoots && Array.isArray(queryingElement.shadowRoots)) {
@@ -297,6 +304,11 @@ class FrameSelectors {
297
304
  const childIndex = this._findElementPositionInDomTree(element, shadowRootHandle, documentScope, currentIndex);
298
305
  if (childIndex !== null) return childIndex;
299
306
  }
307
+ for (const shadowChild of shadowRoot.children || []) {
308
+ const shadowChildIndex = (shadowRoot.children || []).indexOf(shadowChild);
309
+ const childIndex = this._findElementPositionInDomTree(element, shadowChild, documentScope, currentIndex + "." + shadowChildIndex.toString());
310
+ if (childIndex !== null) return childIndex;
311
+ }
300
312
  }
301
313
  }
302
314
  return null;