patchright-core 1.58.2 → 1.59.1

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 (285) hide show
  1. package/ThirdPartyNotices.txt +126 -650
  2. package/browsers.json +16 -14
  3. package/lib/bootstrap.js +77 -0
  4. package/lib/cli/browserActions.js +308 -0
  5. package/lib/cli/driver.js +3 -2
  6. package/lib/cli/installActions.js +171 -0
  7. package/lib/cli/program.js +47 -411
  8. package/lib/client/android.js +4 -4
  9. package/lib/client/api.js +3 -3
  10. package/lib/client/browser.js +8 -0
  11. package/lib/client/browserContext.js +22 -61
  12. package/lib/client/browserType.js +19 -51
  13. package/lib/client/cdpSession.js +6 -2
  14. package/lib/client/channelOwner.js +1 -1
  15. package/lib/client/clientHelper.js +2 -1
  16. package/lib/client/clock.js +0 -1
  17. package/lib/client/{webSocket.js → connect.js} +57 -7
  18. package/lib/client/connection.js +8 -4
  19. package/lib/client/consoleMessage.js +3 -0
  20. package/lib/client/debugger.js +57 -0
  21. package/lib/client/dialog.js +8 -1
  22. package/lib/client/disposable.js +76 -0
  23. package/lib/client/electron.js +1 -0
  24. package/lib/client/elementHandle.js +1 -4
  25. package/lib/client/events.js +3 -3
  26. package/lib/client/fetch.js +0 -1
  27. package/lib/client/frame.js +10 -23
  28. package/lib/client/harRouter.js +13 -1
  29. package/lib/client/jsHandle.js +4 -8
  30. package/lib/client/locator.js +13 -44
  31. package/lib/client/network.js +15 -16
  32. package/lib/client/page.js +41 -75
  33. package/lib/client/platform.js +0 -3
  34. package/lib/client/screencast.js +88 -0
  35. package/lib/client/selectors.js +3 -1
  36. package/lib/client/tracing.js +11 -5
  37. package/lib/client/video.js +13 -20
  38. package/lib/client/worker.js +6 -6
  39. package/lib/generated/bindingsControllerSource.js +1 -1
  40. package/lib/generated/clockSource.js +1 -1
  41. package/lib/generated/injectedScriptSource.js +1 -1
  42. package/lib/generated/pollingRecorderSource.js +1 -1
  43. package/lib/generated/storageScriptSource.js +1 -1
  44. package/lib/generated/utilityScriptSource.js +1 -1
  45. package/lib/mcpBundle.js +0 -6
  46. package/lib/mcpBundleImpl.js +91 -0
  47. package/lib/protocol/validator.js +224 -138
  48. package/lib/protocol/validatorPrimitives.js +1 -1
  49. package/lib/remote/playwrightConnection.js +10 -8
  50. package/lib/remote/playwrightPipeServer.js +100 -0
  51. package/lib/remote/playwrightServer.js +13 -8
  52. package/lib/remote/playwrightWebSocketServer.js +73 -0
  53. package/lib/remote/serverTransport.js +96 -0
  54. package/lib/server/android/android.js +2 -2
  55. package/lib/server/bidi/bidiBrowser.js +30 -8
  56. package/lib/server/bidi/bidiChromium.js +18 -5
  57. package/lib/server/bidi/bidiNetworkManager.js +39 -11
  58. package/lib/server/bidi/bidiPage.js +31 -15
  59. package/lib/server/bidi/third_party/firefoxPrefs.js +3 -1
  60. package/lib/server/browser.js +84 -21
  61. package/lib/server/browserContext.js +110 -58
  62. package/lib/server/browserType.js +14 -12
  63. package/lib/server/chromium/chromium.js +15 -12
  64. package/lib/server/chromium/chromiumSwitches.js +14 -2
  65. package/lib/server/chromium/crBrowser.js +20 -17
  66. package/lib/server/chromium/crCoverage.js +1 -13
  67. package/lib/server/chromium/crDevTools.js +1 -0
  68. package/lib/server/chromium/crNetworkManager.js +12 -267
  69. package/lib/server/chromium/crPage.js +67 -199
  70. package/lib/server/chromium/crServiceWorker.js +7 -14
  71. package/lib/server/clock.js +33 -41
  72. package/lib/server/console.js +5 -1
  73. package/lib/server/debugController.js +12 -6
  74. package/lib/server/debugger.js +40 -47
  75. package/lib/server/deviceDescriptorsSource.json +137 -137
  76. package/lib/server/dispatchers/browserContextDispatcher.js +29 -30
  77. package/lib/server/dispatchers/browserDispatcher.js +11 -5
  78. package/lib/server/dispatchers/browserTypeDispatcher.js +7 -0
  79. package/lib/server/dispatchers/cdpSessionDispatcher.js +4 -1
  80. package/lib/server/dispatchers/debuggerDispatcher.js +84 -0
  81. package/lib/server/dispatchers/dispatcher.js +1 -1
  82. package/lib/server/dispatchers/disposableDispatcher.js +39 -0
  83. package/lib/server/dispatchers/electronDispatcher.js +2 -1
  84. package/lib/server/dispatchers/frameDispatcher.js +6 -6
  85. package/lib/server/dispatchers/jsHandleDispatcher.js +2 -2
  86. package/lib/server/dispatchers/localUtilsDispatcher.js +37 -1
  87. package/lib/server/dispatchers/networkDispatchers.js +6 -5
  88. package/lib/server/dispatchers/pageDispatcher.js +101 -38
  89. package/lib/server/dispatchers/webSocketRouteDispatcher.js +4 -5
  90. package/lib/server/disposable.js +41 -0
  91. package/lib/server/dom.js +44 -26
  92. package/lib/server/download.js +3 -2
  93. package/lib/server/electron/electron.js +12 -7
  94. package/lib/server/firefox/ffBrowser.js +9 -19
  95. package/lib/server/firefox/ffInput.js +21 -5
  96. package/lib/server/firefox/ffNetworkManager.js +2 -2
  97. package/lib/server/firefox/ffPage.js +24 -27
  98. package/lib/server/frameSelectors.js +5 -172
  99. package/lib/server/frames.js +234 -687
  100. package/lib/server/har/harRecorder.js +2 -2
  101. package/lib/server/har/harTracer.js +5 -4
  102. package/lib/server/input.js +49 -4
  103. package/lib/server/instrumentation.js +5 -0
  104. package/lib/server/javascript.js +6 -26
  105. package/lib/server/launchApp.js +1 -3
  106. package/lib/server/localUtils.js +6 -6
  107. package/lib/server/network.js +9 -8
  108. package/lib/server/overlay.js +138 -0
  109. package/lib/server/page.js +157 -105
  110. package/lib/server/progress.js +6 -0
  111. package/lib/server/recorder/recorderApp.js +9 -8
  112. package/lib/server/recorder.js +76 -40
  113. package/lib/server/registry/index.js +55 -82
  114. package/lib/server/registry/nativeDeps.js +1 -0
  115. package/lib/server/screencast.js +90 -143
  116. package/lib/server/screenshotter.js +0 -6
  117. package/lib/server/trace/recorder/snapshotter.js +8 -17
  118. package/lib/server/trace/recorder/snapshotterInjected.js +82 -20
  119. package/lib/server/trace/recorder/tracing.js +87 -44
  120. package/lib/server/trace/viewer/traceViewer.js +3 -4
  121. package/lib/server/usKeyboardLayout.js +7 -0
  122. package/lib/server/utils/comparators.js +1 -1
  123. package/lib/server/utils/disposable.js +32 -0
  124. package/lib/server/utils/eventsHelper.js +3 -1
  125. package/lib/server/utils/fileUtils.js +16 -2
  126. package/lib/server/utils/happyEyeballs.js +15 -12
  127. package/lib/server/utils/hostPlatform.js +0 -15
  128. package/lib/server/utils/httpServer.js +5 -3
  129. package/lib/server/utils/network.js +2 -1
  130. package/lib/server/utils/nodePlatform.js +0 -6
  131. package/lib/server/utils/processLauncher.js +6 -5
  132. package/lib/server/utils/zipFile.js +2 -2
  133. package/lib/server/videoRecorder.js +82 -12
  134. package/lib/server/webkit/wkBrowser.js +1 -6
  135. package/lib/server/webkit/wkPage.js +27 -25
  136. package/lib/server/webkit/wkWorkers.js +2 -1
  137. package/lib/serverRegistry.js +156 -0
  138. package/lib/tools/backend/browserBackend.js +79 -0
  139. package/lib/tools/backend/common.js +63 -0
  140. package/lib/tools/backend/config.js +41 -0
  141. package/lib/tools/backend/console.js +66 -0
  142. package/lib/tools/backend/context.js +296 -0
  143. package/lib/tools/backend/cookies.js +152 -0
  144. package/lib/tools/backend/devtools.js +69 -0
  145. package/lib/tools/backend/dialogs.js +59 -0
  146. package/lib/tools/backend/evaluate.js +64 -0
  147. package/lib/tools/backend/files.js +60 -0
  148. package/lib/tools/backend/form.js +64 -0
  149. package/lib/tools/backend/keyboard.js +155 -0
  150. package/lib/tools/backend/logFile.js +95 -0
  151. package/lib/tools/backend/mouse.js +168 -0
  152. package/lib/tools/backend/navigate.js +106 -0
  153. package/lib/tools/backend/network.js +135 -0
  154. package/lib/tools/backend/pdf.js +48 -0
  155. package/lib/tools/backend/response.js +305 -0
  156. package/lib/tools/backend/route.js +140 -0
  157. package/lib/tools/backend/runCode.js +77 -0
  158. package/lib/tools/backend/screenshot.js +88 -0
  159. package/lib/tools/backend/sessionLog.js +74 -0
  160. package/lib/tools/backend/snapshot.js +208 -0
  161. package/lib/tools/backend/storage.js +68 -0
  162. package/lib/tools/backend/tab.js +445 -0
  163. package/lib/tools/backend/tabs.js +67 -0
  164. package/lib/tools/backend/tool.js +47 -0
  165. package/lib/tools/backend/tools.js +102 -0
  166. package/lib/tools/backend/tracing.js +78 -0
  167. package/lib/tools/backend/utils.js +83 -0
  168. package/lib/tools/backend/verify.js +151 -0
  169. package/lib/tools/backend/video.js +98 -0
  170. package/lib/tools/backend/wait.js +63 -0
  171. package/lib/tools/backend/webstorage.js +223 -0
  172. package/lib/tools/cli-client/cli.js +6 -0
  173. package/lib/tools/cli-client/help.json +399 -0
  174. package/lib/tools/cli-client/minimist.js +128 -0
  175. package/lib/tools/cli-client/program.js +350 -0
  176. package/lib/tools/cli-client/registry.js +176 -0
  177. package/lib/tools/cli-client/session.js +289 -0
  178. package/lib/tools/cli-client/skill/SKILL.md +328 -0
  179. package/lib/tools/cli-client/skill/references/element-attributes.md +23 -0
  180. package/lib/tools/cli-client/skill/references/playwright-tests.md +39 -0
  181. package/lib/tools/cli-client/skill/references/request-mocking.md +87 -0
  182. package/lib/tools/cli-client/skill/references/running-code.md +231 -0
  183. package/lib/tools/cli-client/skill/references/session-management.md +169 -0
  184. package/lib/tools/cli-client/skill/references/storage-state.md +275 -0
  185. package/lib/tools/cli-client/skill/references/test-generation.md +88 -0
  186. package/lib/tools/cli-client/skill/references/tracing.md +139 -0
  187. package/lib/tools/cli-client/skill/references/video-recording.md +143 -0
  188. package/lib/tools/cli-daemon/command.js +73 -0
  189. package/lib/tools/cli-daemon/commands.js +956 -0
  190. package/lib/tools/cli-daemon/daemon.js +157 -0
  191. package/lib/tools/cli-daemon/helpGenerator.js +177 -0
  192. package/lib/tools/cli-daemon/program.js +129 -0
  193. package/lib/tools/dashboard/appIcon.png +0 -0
  194. package/lib/tools/dashboard/dashboardApp.js +284 -0
  195. package/lib/tools/dashboard/dashboardController.js +296 -0
  196. package/lib/tools/exports.js +60 -0
  197. package/lib/tools/mcp/browserFactory.js +233 -0
  198. package/lib/tools/mcp/cdpRelay.js +352 -0
  199. package/lib/tools/mcp/cli-stub.js +7 -0
  200. package/lib/tools/mcp/config.d.js +16 -0
  201. package/lib/tools/mcp/config.js +446 -0
  202. package/lib/tools/mcp/configIni.js +189 -0
  203. package/lib/tools/mcp/extensionContextFactory.js +55 -0
  204. package/lib/tools/mcp/index.js +62 -0
  205. package/lib/tools/mcp/log.js +35 -0
  206. package/lib/tools/mcp/program.js +107 -0
  207. package/lib/tools/mcp/protocol.js +28 -0
  208. package/lib/tools/mcp/watchdog.js +44 -0
  209. package/lib/tools/trace/SKILL.md +171 -0
  210. package/lib/{server/trace/viewer/traceParser.js → tools/trace/installSkill.js} +15 -39
  211. package/lib/tools/trace/traceActions.js +142 -0
  212. package/lib/tools/trace/traceAttachments.js +69 -0
  213. package/lib/tools/trace/traceCli.js +87 -0
  214. package/lib/tools/trace/traceConsole.js +97 -0
  215. package/lib/tools/trace/traceErrors.js +55 -0
  216. package/lib/tools/trace/traceOpen.js +69 -0
  217. package/lib/tools/trace/traceParser.js +96 -0
  218. package/lib/tools/trace/traceRequests.js +182 -0
  219. package/lib/tools/trace/traceScreenshot.js +68 -0
  220. package/lib/tools/trace/traceSnapshot.js +149 -0
  221. package/lib/tools/trace/traceUtils.js +153 -0
  222. package/lib/tools/utils/connect.js +32 -0
  223. package/lib/tools/utils/mcp/http.js +152 -0
  224. package/lib/tools/utils/mcp/server.js +230 -0
  225. package/lib/tools/utils/mcp/tool.js +47 -0
  226. package/lib/tools/utils/socketConnection.js +108 -0
  227. package/lib/utils/isomorphic/formatUtils.js +64 -0
  228. package/lib/utils/isomorphic/jsonSchema.js +89 -0
  229. package/lib/utils/isomorphic/mimeType.js +7 -2
  230. package/lib/utils/isomorphic/protocolFormatter.js +2 -2
  231. package/lib/utils/isomorphic/protocolMetainfo.js +127 -106
  232. package/lib/utils/isomorphic/stringUtils.js +3 -3
  233. package/lib/utils/isomorphic/timeoutRunner.js +3 -3
  234. package/lib/utils/isomorphic/trace/snapshotRenderer.js +35 -42
  235. package/lib/utils/isomorphic/trace/traceLoader.js +15 -14
  236. package/lib/utils/isomorphic/trace/traceModel.js +3 -2
  237. package/lib/utils/isomorphic/trace/traceModernizer.js +1 -0
  238. package/lib/utils/isomorphic/urlMatch.js +54 -1
  239. package/lib/utils/isomorphic/utilityScriptSerializers.js +11 -0
  240. package/lib/utils.js +6 -2
  241. package/lib/utilsBundle.js +3 -21
  242. package/lib/utilsBundleImpl/index.js +132 -133
  243. package/lib/vite/dashboard/assets/index-BAOybkp8.js +50 -0
  244. package/lib/vite/dashboard/assets/index-CZAYOG76.css +1 -0
  245. package/lib/vite/dashboard/index.html +28 -0
  246. package/lib/vite/htmlReport/index.html +2 -70
  247. package/lib/vite/htmlReport/report.css +1 -0
  248. package/lib/vite/htmlReport/report.js +72 -0
  249. package/lib/vite/recorder/assets/{codeMirrorModule-CFUTFUO7.js → codeMirrorModule-C8KMvO9L.js} +20 -20
  250. package/lib/vite/recorder/assets/index-CqAYX1I3.js +193 -0
  251. package/lib/vite/recorder/index.html +1 -1
  252. package/lib/vite/traceViewer/assets/{codeMirrorModule-BVA4h_ZY.js → codeMirrorModule-DS0FLvoc.js} +20 -20
  253. package/lib/vite/traceViewer/assets/defaultSettingsView-GTWI-W_B.js +262 -0
  254. package/lib/vite/traceViewer/defaultSettingsView.B4dS75f0.css +1 -0
  255. package/lib/vite/traceViewer/{index.BtyWtaE-.js → index.C5466mMT.js} +1 -1
  256. package/lib/vite/traceViewer/{index.BVu7tZDe.css → index.CzXZzn5A.css} +1 -1
  257. package/lib/vite/traceViewer/index.html +4 -4
  258. package/lib/vite/traceViewer/sw.bundle.js +4 -4
  259. package/lib/vite/traceViewer/uiMode.Vipi55dB.js +6 -0
  260. package/lib/vite/traceViewer/uiMode.html +3 -3
  261. package/lib/zipBundleImpl.js +2 -2
  262. package/lib/zodBundle.js +39 -0
  263. package/lib/zodBundleImpl.js +40 -0
  264. package/package.json +6 -1
  265. package/types/protocol.d.ts +947 -51
  266. package/types/types.d.ts +854 -74
  267. package/lib/client/pageAgent.js +0 -64
  268. package/lib/mcpBundleImpl/index.js +0 -147
  269. package/lib/server/agent/actionRunner.js +0 -335
  270. package/lib/server/agent/actions.js +0 -128
  271. package/lib/server/agent/codegen.js +0 -111
  272. package/lib/server/agent/context.js +0 -150
  273. package/lib/server/agent/expectTools.js +0 -156
  274. package/lib/server/agent/pageAgent.js +0 -204
  275. package/lib/server/agent/performTools.js +0 -262
  276. package/lib/server/agent/tool.js +0 -109
  277. package/lib/server/dispatchers/pageAgentDispatcher.js +0 -96
  278. package/lib/server/pageBinding.js +0 -87
  279. package/lib/utils/isomorphic/oldUtilityScriptSerializers.js +0 -248
  280. package/lib/vite/recorder/assets/index-CVkBxsGf.js +0 -193
  281. package/lib/vite/traceViewer/assets/defaultSettingsView-CjfmcdOz.js +0 -266
  282. package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +0 -1
  283. package/lib/vite/traceViewer/uiMode.fyrXARf2.js +0 -5
  284. /package/lib/{server/utils → utils/isomorphic}/imageUtils.js +0 -0
  285. /package/lib/utils/isomorphic/{traceUtils.js → trace/traceUtils.js} +0 -0
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,171 +15,120 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
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
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
  var screencast_exports = {};
30
20
  __export(screencast_exports, {
31
21
  Screencast: () => Screencast
32
22
  });
33
23
  module.exports = __toCommonJS(screencast_exports);
34
- var import_path = __toESM(require("path"));
35
24
  var import_utils = require("../utils");
36
25
  var import_utils2 = require("../utils");
37
- var import_videoRecorder = require("./videoRecorder");
38
- var import_page = require("./page");
39
- var import_registry = require("./registry");
40
26
  class Screencast {
41
27
  constructor(page) {
42
- this._videoRecorder = null;
43
- this._videoId = 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._frameListener = null;
49
- this._page = page;
50
- }
51
- stopFrameThrottler() {
52
- this._frameThrottler.dispose();
53
- }
54
- setOptions(options) {
55
- this._setOptions(options).catch((e) => import_utils2.debugLogger.log("error", e));
56
- this._frameThrottler.setThrottlingEnabled(!!options);
28
+ this._clients = /* @__PURE__ */ new Set();
29
+ this.page = page;
30
+ this.page.instrumentation.addListener(this, page.browserContext);
31
+ }
32
+ async handlePageOrContextClose() {
33
+ const clients = [...this._clients];
34
+ this._clients.clear();
35
+ for (const client of clients) {
36
+ if (client.gracefulClose)
37
+ await client.gracefulClose();
38
+ }
57
39
  }
58
- throttleFrameAck(ack) {
59
- this._frameThrottler.ack(ack);
40
+ dispose() {
41
+ for (const client of this._clients)
42
+ client.dispose();
43
+ this._clients.clear();
44
+ this.page.instrumentation.removeListener(this);
60
45
  }
61
- temporarilyDisableThrottling() {
62
- this._frameThrottler.recharge();
46
+ showActions(options) {
47
+ this._actions = options;
63
48
  }
64
- launchVideoRecorder() {
65
- const recordVideo = this._page.browserContext._options.recordVideo;
66
- if (!recordVideo)
67
- return void 0;
68
- (0, import_utils.assert)(!this._videoId);
69
- this._videoId = (0, import_utils.createGuid)();
70
- const outputFile = import_path.default.join(recordVideo.dir, this._videoId + ".webm");
71
- const videoOptions = {
72
- // validateBrowserContextOptions ensures correct video size.
73
- ...recordVideo.size,
74
- outputFile
75
- };
76
- const ffmpegPath = import_registry.registry.findExecutable("ffmpeg").executablePathOrDie(this._page.browserContext._browser.sdkLanguage());
77
- this._videoRecorder = new import_videoRecorder.VideoRecorder(ffmpegPath, videoOptions);
78
- this._frameListener = import_utils.eventsHelper.addEventListener(this._page, import_page.Page.Events.ScreencastFrame, (frame) => this._videoRecorder.writeFrame(frame.buffer, frame.frameSwapWallTime / 1e3));
79
- this._page.waitForInitializedOrError().then((p) => {
80
- if (p instanceof Error)
81
- this.stopVideoRecording().catch(() => {
82
- });
83
- });
84
- return videoOptions;
49
+ hideActions() {
50
+ this._actions = void 0;
85
51
  }
86
- async startVideoRecording(options) {
87
- const videoId = this._videoId;
88
- (0, import_utils.assert)(videoId);
89
- this._page.once(import_page.Page.Events.Close, () => this.stopVideoRecording().catch(() => {
90
- }));
91
- const gotFirstFrame = new Promise((f) => this._page.once(import_page.Page.Events.ScreencastFrame, f));
92
- await this._startScreencast(this._videoRecorder, {
93
- quality: 90,
94
- width: options.width,
95
- height: options.height
96
- });
97
- gotFirstFrame.then(() => {
98
- this._page.browserContext._browser._videoStarted(this._page.browserContext, videoId, options.outputFile, this._page.waitForInitializedOrError());
99
- });
52
+ addClient(client) {
53
+ this._clients.add(client);
54
+ if (this._clients.size === 1)
55
+ this._startScreencast(client.size, client.quality);
56
+ return { size: this._size };
100
57
  }
101
- async stopVideoRecording() {
102
- if (!this._videoId)
58
+ removeClient(client) {
59
+ if (!this._clients.has(client))
103
60
  return;
104
- if (this._frameListener)
105
- import_utils.eventsHelper.removeEventListeners([this._frameListener]);
106
- this._frameListener = null;
107
- const videoId = this._videoId;
108
- this._videoId = null;
109
- const videoRecorder = this._videoRecorder;
110
- this._videoRecorder = null;
111
- await this._stopScreencast(videoRecorder);
112
- await videoRecorder.stop();
113
- const video = this._page.browserContext._browser._takeVideo(videoId);
114
- video?.reportFinished();
115
- }
116
- async _setOptions(options) {
117
- if (options)
118
- await this._startScreencast(this, options);
119
- else
120
- await this._stopScreencast(this);
121
- }
122
- async _startScreencast(client, options) {
123
- this._screencastClients.add(client);
124
- if (this._screencastClients.size === 1) {
125
- await this._page.delegate.startScreencast({
126
- width: options.width,
127
- height: options.height,
128
- quality: options.quality
129
- });
61
+ this._clients.delete(client);
62
+ if (!this._clients.size)
63
+ this._stopScreencast();
64
+ }
65
+ size() {
66
+ return this._size;
67
+ }
68
+ _startScreencast(size, quality) {
69
+ this._size = size;
70
+ if (!this._size) {
71
+ const viewport = this.page.browserContext._options.viewport || { width: 800, height: 600 };
72
+ const scale = Math.min(1, 800 / Math.max(viewport.width, viewport.height));
73
+ this._size = {
74
+ width: Math.floor(viewport.width * scale),
75
+ height: Math.floor(viewport.height * scale)
76
+ };
130
77
  }
78
+ this._size = {
79
+ width: this._size.width & ~1,
80
+ height: this._size.height & ~1
81
+ };
82
+ this.page.delegate.startScreencast({
83
+ width: this._size.width,
84
+ height: this._size.height,
85
+ quality: quality ?? 90
86
+ });
131
87
  }
132
- async _stopScreencast(client) {
133
- this._screencastClients.delete(client);
134
- if (!this._screencastClients.size)
135
- await this._page.delegate.stopScreencast();
136
- }
137
- }
138
- class FrameThrottler {
139
- constructor(nonThrottledFrames, defaultInterval, throttlingInterval) {
140
- this._acks = [];
141
- this._throttlingEnabled = false;
142
- this._nonThrottledFrames = nonThrottledFrames;
143
- this._budget = nonThrottledFrames;
144
- this._defaultInterval = defaultInterval;
145
- this._throttlingInterval = throttlingInterval;
146
- this._tick();
88
+ _stopScreencast() {
89
+ this.page.delegate.stopScreencast();
147
90
  }
148
- dispose() {
149
- if (this._timeoutId) {
150
- clearTimeout(this._timeoutId);
151
- this._timeoutId = void 0;
91
+ onScreencastFrame(frame, ack) {
92
+ const asyncResults = [];
93
+ for (const client of this._clients) {
94
+ const result = client.onFrame(frame);
95
+ if (result)
96
+ asyncResults.push(result);
152
97
  }
153
- }
154
- setThrottlingEnabled(enabled) {
155
- this._throttlingEnabled = enabled;
156
- }
157
- recharge() {
158
- for (const ack of this._acks)
159
- ack();
160
- this._acks = [];
161
- this._budget = this._nonThrottledFrames;
162
- if (this._timeoutId) {
163
- clearTimeout(this._timeoutId);
164
- this._tick();
98
+ if (ack) {
99
+ if (!asyncResults.length)
100
+ ack();
101
+ else
102
+ Promise.race(asyncResults).then(ack);
165
103
  }
166
104
  }
167
- ack(ack) {
168
- if (!this._timeoutId) {
169
- ack();
105
+ async onBeforeCall(sdkObject, metadata, parentId) {
106
+ if (!this._actions)
170
107
  return;
171
- }
172
- this._acks.push(ack);
108
+ metadata.annotate = true;
173
109
  }
174
- _tick() {
175
- const ack = this._acks.shift();
176
- if (ack) {
177
- --this._budget;
178
- ack();
179
- }
180
- if (this._throttlingEnabled && this._budget <= 0) {
181
- this._timeoutId = setTimeout(() => this._tick(), this._throttlingInterval);
182
- } else {
183
- this._timeoutId = setTimeout(() => this._tick(), this._defaultInterval);
184
- }
110
+ async onBeforeInputAction(sdkObject, metadata) {
111
+ if (!this._actions)
112
+ return;
113
+ const page = sdkObject.attribution.page;
114
+ if (!page)
115
+ return;
116
+ const actionTitle = (0, import_utils.renderTitleForCall)(metadata);
117
+ const utility = await page.mainFrame()._utilityContext();
118
+ await utility.evaluate(async (options) => {
119
+ const { injected, duration } = options;
120
+ injected.setScreencastAnnotation(options);
121
+ await new Promise((f) => injected.utils.builtins.setTimeout(f, duration));
122
+ injected.setScreencastAnnotation(null);
123
+ }, {
124
+ injected: await utility.injectedScript(),
125
+ duration: this._actions?.duration ?? 500,
126
+ point: metadata.point,
127
+ box: metadata.box,
128
+ actionTitle,
129
+ position: this._actions?.position,
130
+ fontSize: this._actions?.fontSize
131
+ }).catch((e) => import_utils2.debugLogger.log("error", e));
185
132
  }
186
133
  }
187
134
  // Annotate the CommonJS export names for ESM import in node:
@@ -213,12 +213,6 @@ class Screenshotter {
213
213
  if (disableAnimations)
214
214
  progress.log(" disabled all CSS animations");
215
215
  const syncAnimations = this._page.delegate.shouldToggleStyleSheetToSyncAnimations();
216
- await Promise.all(this._page.frames().map(async (f) => {
217
- try {
218
- await f._utilityContext();
219
- } catch {
220
- }
221
- }));
222
216
  await progress.race(this._page.safeNonStallingEvaluateInAllFrames("(" + inPagePrepareForScreenshots.toString() + `)(${JSON.stringify(screenshotStyle)}, ${hideCaret}, ${disableAnimations}, ${syncAnimations})`, "utility"));
223
217
  try {
224
218
  if (!process.env.PW_TEST_SCREENSHOT_NO_FONTS_READY) {
@@ -49,7 +49,7 @@ class Snapshotter {
49
49
  }
50
50
  async reset() {
51
51
  if (this._started)
52
- await this._context.safeNonStallingEvaluateInAllFrames(`window["${this._snapshotStreamer}"].reset()`, "utility");
52
+ await this._context.safeNonStallingEvaluateInAllFrames(`window["${this._snapshotStreamer}"].reset()`, "main");
53
53
  }
54
54
  stop() {
55
55
  this._started = false;
@@ -57,20 +57,20 @@ class Snapshotter {
57
57
  async resetForReuse() {
58
58
  if (this._initScript) {
59
59
  import_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
60
+ await this._initScript.dispose();
60
61
  this._initScript = void 0;
61
- this._initScriptSource = void 0;
62
62
  }
63
63
  }
64
64
  async _initialize() {
65
- const { javaScriptEnabled } = this._context._options;
66
- this._initScriptSource = `(${import_snapshotterInjected.frameSnapshotStreamer})("${this._snapshotStreamer}", ${javaScriptEnabled || javaScriptEnabled === void 0})`;
67
- this._initScript = true;
68
65
  for (const page of this._context.pages())
69
66
  this._onPage(page);
70
67
  this._eventListeners = [
71
68
  import_eventsHelper.eventsHelper.addEventListener(this._context, import_browserContext.BrowserContext.Events.Page, this._onPage.bind(this))
72
69
  ];
73
- await this._context.safeNonStallingEvaluateInAllFrames(this._initScriptSource, "utility");
70
+ const { javaScriptEnabled } = this._context._options;
71
+ const initScriptSource = `(${import_snapshotterInjected.frameSnapshotStreamer})("${this._snapshotStreamer}", ${javaScriptEnabled || javaScriptEnabled === void 0})`;
72
+ this._initScript = await this._context.addInitScript(initScriptSource);
73
+ await this._context.safeNonStallingEvaluateInAllFrames(initScriptSource, "main");
74
74
  }
75
75
  dispose() {
76
76
  import_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
@@ -80,7 +80,7 @@ class Snapshotter {
80
80
  frame[kNeedsResetSymbol] = false;
81
81
  const expression = `window["${this._snapshotStreamer}"].captureSnapshot(${needsReset ? "true" : "false"})`;
82
82
  try {
83
- return await frame.nonStallingEvaluateInExistingContext(expression, "utility");
83
+ return await frame.nonStallingRawEvaluateInExistingMainContext(expression);
84
84
  } catch (e) {
85
85
  frame[kNeedsResetSymbol] = true;
86
86
  import_debugLogger.debugLogger.log("error", e);
@@ -124,7 +124,6 @@ class Snapshotter {
124
124
  for (const frame of page.frames())
125
125
  this._annotateFrameHierarchy(frame);
126
126
  this._eventListeners.push(import_eventsHelper.eventsHelper.addEventListener(page, import_page.Page.Events.FrameAttached, (frame) => this._annotateFrameHierarchy(frame)));
127
- this._eventListeners.push(import_eventsHelper.eventsHelper.addEventListener(page, import_page.Page.Events.InternalFrameNavigatedToNewDocument, (frame) => this._onFrameNavigated(frame)));
128
127
  }
129
128
  async _annotateFrameHierarchy(frame) {
130
129
  try {
@@ -132,7 +131,7 @@ class Snapshotter {
132
131
  const parent = frame.parentFrame();
133
132
  if (!parent)
134
133
  return;
135
- const context = await parent._utilityContext();
134
+ const context = await parent._mainContext();
136
135
  await context?.evaluate(({ snapshotStreamer, frameElement: frameElement2, frameId }) => {
137
136
  window[snapshotStreamer].markIframe(frameElement2, frameId);
138
137
  }, { snapshotStreamer: this._snapshotStreamer, frameElement, frameId: frame.guid });
@@ -140,14 +139,6 @@ class Snapshotter {
140
139
  } catch (e) {
141
140
  }
142
141
  }
143
- async _onFrameNavigated(frame) {
144
- if (!this._initScriptSource)
145
- return;
146
- try {
147
- await frame.nonStallingEvaluateInExistingContext(this._initScriptSource, "utility");
148
- } catch (e) {
149
- }
150
- }
151
142
  }
152
143
  const kNeedsResetSymbol = Symbol("kNeedsReset");
153
144
  // Annotate the CommonJS export names for ESM import in node:
@@ -60,11 +60,28 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
60
60
  class Streamer {
61
61
  constructor() {
62
62
  this._lastSnapshotNumber = 0;
63
+ this._staleStyleSheets = /* @__PURE__ */ new Set();
63
64
  this._modifiedStyleSheets = /* @__PURE__ */ new Set();
65
+ this._readingStyleSheet = false;
66
+ const invalidateCSSGroupingRule = (rule) => {
67
+ if (rule.parentStyleSheet)
68
+ this._invalidateStyleSheet(rule.parentStyleSheet);
69
+ };
70
+ this._interceptNativeMethod(window.CSSStyleSheet.prototype, "insertRule", (sheet) => this._invalidateStyleSheet(sheet));
71
+ this._interceptNativeMethod(window.CSSStyleSheet.prototype, "deleteRule", (sheet) => this._invalidateStyleSheet(sheet));
72
+ this._interceptNativeMethod(window.CSSStyleSheet.prototype, "addRule", (sheet) => this._invalidateStyleSheet(sheet));
73
+ this._interceptNativeMethod(window.CSSStyleSheet.prototype, "removeRule", (sheet) => this._invalidateStyleSheet(sheet));
74
+ this._interceptNativeGetter(window.CSSStyleSheet.prototype, "rules", (sheet) => this._invalidateStyleSheet(sheet));
75
+ this._interceptNativeGetter(window.CSSStyleSheet.prototype, "cssRules", (sheet) => this._invalidateStyleSheet(sheet));
76
+ this._interceptNativeMethod(window.CSSStyleSheet.prototype, "replaceSync", (sheet) => this._invalidateStyleSheet(sheet));
77
+ this._interceptNativeMethod(window.CSSGroupingRule.prototype, "insertRule", invalidateCSSGroupingRule);
78
+ this._interceptNativeMethod(window.CSSGroupingRule.prototype, "deleteRule", invalidateCSSGroupingRule);
79
+ this._interceptNativeGetter(window.CSSGroupingRule.prototype, "cssRules", invalidateCSSGroupingRule);
64
80
  this._interceptNativeSetter(window.StyleSheet.prototype, "disabled", (sheet) => {
65
81
  if (sheet instanceof CSSStyleSheet)
66
82
  this._invalidateStyleSheet(sheet);
67
83
  });
84
+ this._interceptNativeAsyncMethod(window.CSSStyleSheet.prototype, "replace", (sheet) => this._invalidateStyleSheet(sheet));
68
85
  this._fakeBase = document.createElement("base");
69
86
  this._observer = new MutationObserver((list) => this._handleMutations(list));
70
87
  const observerConfig = { attributes: true, subtree: true };
@@ -105,6 +122,37 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
105
122
  delete event.composedPath()[0].__playwright_target__;
106
123
  });
107
124
  }
125
+ _interceptNativeMethod(obj, method, cb) {
126
+ const native = obj[method];
127
+ if (!native)
128
+ return;
129
+ obj[method] = function(...args) {
130
+ const result = native.call(this, ...args);
131
+ cb(this, result);
132
+ return result;
133
+ };
134
+ }
135
+ _interceptNativeAsyncMethod(obj, method, cb) {
136
+ const native = obj[method];
137
+ if (!native)
138
+ return;
139
+ obj[method] = async function(...args) {
140
+ const result = await native.call(this, ...args);
141
+ cb(this, result);
142
+ return result;
143
+ };
144
+ }
145
+ _interceptNativeGetter(obj, prop, cb) {
146
+ const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
147
+ Object.defineProperty(obj, prop, {
148
+ ...descriptor,
149
+ get: function() {
150
+ const result = descriptor.get.call(this);
151
+ cb(this, result);
152
+ return result;
153
+ }
154
+ });
155
+ }
108
156
  _interceptNativeSetter(obj, prop, cb) {
109
157
  const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
110
158
  Object.defineProperty(obj, prop, {
@@ -120,37 +168,44 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
120
168
  for (const mutation of list)
121
169
  ensureCachedData(mutation.target).attributesCached = void 0;
122
170
  }
171
+ _invalidateStyleSheet(sheet) {
172
+ if (this._readingStyleSheet)
173
+ return;
174
+ this._staleStyleSheets.add(sheet);
175
+ if (sheet.href !== null)
176
+ this._modifiedStyleSheets.add(sheet);
177
+ }
123
178
  _updateStyleElementStyleSheetTextIfNeeded(sheet, forceText) {
124
179
  const data = ensureCachedData(sheet);
125
- try {
126
- data.cssText = this._getSheetText(sheet);
127
- } catch (e) {
128
- data.cssText = "";
180
+ if (this._staleStyleSheets.has(sheet) || forceText && data.cssText === void 0) {
181
+ this._staleStyleSheets.delete(sheet);
182
+ try {
183
+ data.cssText = this._getSheetText(sheet);
184
+ } catch (e) {
185
+ data.cssText = "";
186
+ }
129
187
  }
130
188
  return data.cssText;
131
189
  }
132
190
  // Returns either content, ref, or no override.
133
191
  _updateLinkStyleSheetTextIfNeeded(sheet, snapshotNumber) {
134
192
  const data = ensureCachedData(sheet);
135
- try {
136
- const currentText = this._getSheetText(sheet);
137
- if (data.cssText === void 0) {
138
- data.cssText = currentText;
139
- return void 0;
193
+ if (this._staleStyleSheets.has(sheet)) {
194
+ this._staleStyleSheets.delete(sheet);
195
+ try {
196
+ data.cssText = this._getSheetText(sheet);
197
+ data.cssRef = snapshotNumber;
198
+ return data.cssText;
199
+ } catch (e) {
140
200
  }
141
- if (currentText === data.cssText)
142
- return data.cssRef === void 0 ? void 0 : snapshotNumber - data.cssRef;
143
- data.cssText = currentText;
144
- data.cssRef = snapshotNumber;
145
- return data.cssText;
146
- } catch (e) {
147
- return void 0;
148
201
  }
202
+ return data.cssRef === void 0 ? void 0 : snapshotNumber - data.cssRef;
149
203
  }
150
204
  markIframe(iframeElement, frameId) {
151
205
  iframeElement[kSnapshotFrameId] = frameId;
152
206
  }
153
207
  reset() {
208
+ this._staleStyleSheets.clear();
154
209
  const visitNode = (node) => {
155
210
  resetCachedData(node);
156
211
  if (node.nodeType === Node.ELEMENT_NODE) {
@@ -209,10 +264,17 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
209
264
  return document.baseURI;
210
265
  }
211
266
  _getSheetText(sheet) {
212
- const rules = [];
213
- for (const rule of sheet.cssRules)
214
- rules.push(rule.cssText);
215
- return rules.join("\n");
267
+ this._readingStyleSheet = true;
268
+ try {
269
+ if (sheet.disabled)
270
+ return "";
271
+ const rules = [];
272
+ for (const rule of sheet.cssRules)
273
+ rules.push(rule.cssText);
274
+ return rules.join("\n");
275
+ } finally {
276
+ this._readingStyleSheet = false;
277
+ }
216
278
  }
217
279
  captureSnapshot(needsReset) {
218
280
  const timestamp = performance.now();