patchright-core 1.57.0 → 1.59.0

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 (307) hide show
  1. package/ThirdPartyNotices.txt +2688 -297
  2. package/browsers.json +23 -22
  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 +48 -413
  8. package/lib/client/android.js +4 -4
  9. package/lib/client/api.js +3 -0
  10. package/lib/client/browser.js +11 -5
  11. package/lib/client/browserContext.js +20 -23
  12. package/lib/client/browserType.js +23 -54
  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 -0
  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 -1
  25. package/lib/client/events.js +3 -0
  26. package/lib/client/fetch.js +2 -4
  27. package/lib/client/frame.js +9 -13
  28. package/lib/client/harRouter.js +13 -1
  29. package/lib/client/jsHandle.js +4 -8
  30. package/lib/client/locator.js +13 -36
  31. package/lib/client/network.js +14 -11
  32. package/lib/client/page.js +44 -50
  33. package/lib/client/screencast.js +88 -0
  34. package/lib/client/selectors.js +3 -1
  35. package/lib/client/tracing.js +11 -5
  36. package/lib/client/video.js +13 -20
  37. package/lib/client/worker.js +6 -6
  38. package/lib/generated/bindingsControllerSource.js +1 -1
  39. package/lib/generated/clockSource.js +1 -1
  40. package/lib/generated/injectedScriptSource.js +1 -1
  41. package/lib/generated/pollingRecorderSource.js +1 -1
  42. package/lib/generated/storageScriptSource.js +1 -1
  43. package/lib/generated/utilityScriptSource.js +1 -1
  44. package/lib/mcpBundle.js +78 -0
  45. package/lib/mcpBundleImpl.js +91 -0
  46. package/lib/protocol/serializers.js +5 -0
  47. package/lib/protocol/validator.js +228 -58
  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 +14 -10
  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/artifact.js +1 -1
  56. package/lib/server/bidi/bidiBrowser.js +80 -14
  57. package/lib/server/bidi/bidiChromium.js +23 -14
  58. package/lib/server/bidi/bidiConnection.js +1 -0
  59. package/lib/server/bidi/bidiDeserializer.js +116 -0
  60. package/lib/server/bidi/bidiExecutionContext.js +75 -29
  61. package/lib/server/bidi/bidiFirefox.js +6 -8
  62. package/lib/server/bidi/bidiNetworkManager.js +40 -12
  63. package/lib/server/bidi/bidiPage.js +67 -40
  64. package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
  65. package/lib/server/bidi/third_party/firefoxPrefs.js +3 -1
  66. package/lib/server/browser.js +84 -21
  67. package/lib/server/browserContext.js +137 -77
  68. package/lib/server/browserType.js +26 -16
  69. package/lib/server/chromium/chromium.js +28 -31
  70. package/lib/server/chromium/chromiumSwitches.js +16 -4
  71. package/lib/server/chromium/crBrowser.js +40 -27
  72. package/lib/server/chromium/crConnection.js +0 -5
  73. package/lib/server/chromium/crDevTools.js +1 -2
  74. package/lib/server/chromium/crNetworkManager.js +54 -229
  75. package/lib/server/chromium/crPage.js +74 -260
  76. package/lib/server/chromium/crServiceWorker.js +7 -14
  77. package/lib/server/clock.js +33 -41
  78. package/lib/server/codegen/javascript.js +6 -29
  79. package/lib/server/console.js +5 -1
  80. package/lib/server/debugController.js +12 -6
  81. package/lib/server/debugger.js +40 -47
  82. package/lib/server/deviceDescriptorsSource.json +137 -137
  83. package/lib/server/dispatchers/browserContextDispatcher.js +30 -30
  84. package/lib/server/dispatchers/browserDispatcher.js +11 -5
  85. package/lib/server/dispatchers/browserTypeDispatcher.js +7 -0
  86. package/lib/server/dispatchers/cdpSessionDispatcher.js +4 -1
  87. package/lib/server/dispatchers/debuggerDispatcher.js +84 -0
  88. package/lib/server/dispatchers/dispatcher.js +7 -14
  89. package/lib/server/dispatchers/disposableDispatcher.js +39 -0
  90. package/lib/server/dispatchers/electronDispatcher.js +2 -1
  91. package/lib/server/dispatchers/frameDispatcher.js +7 -7
  92. package/lib/server/dispatchers/localUtilsDispatcher.js +37 -1
  93. package/lib/server/dispatchers/networkDispatchers.js +6 -5
  94. package/lib/server/dispatchers/pageDispatcher.js +101 -34
  95. package/lib/server/dispatchers/webSocketRouteDispatcher.js +4 -5
  96. package/lib/server/disposable.js +41 -0
  97. package/lib/server/dom.js +56 -29
  98. package/lib/server/download.js +3 -2
  99. package/lib/server/electron/electron.js +17 -9
  100. package/lib/server/firefox/ffBrowser.js +9 -29
  101. package/lib/server/firefox/ffConnection.js +0 -5
  102. package/lib/server/firefox/ffInput.js +21 -5
  103. package/lib/server/firefox/ffNetworkManager.js +4 -4
  104. package/lib/server/firefox/ffPage.js +27 -33
  105. package/lib/server/firefox/firefox.js +6 -8
  106. package/lib/server/frameSelectors.js +14 -169
  107. package/lib/server/frames.js +263 -551
  108. package/lib/server/har/harRecorder.js +2 -2
  109. package/lib/server/har/harTracer.js +5 -4
  110. package/lib/server/input.js +49 -4
  111. package/lib/server/instrumentation.js +8 -0
  112. package/lib/server/javascript.js +6 -22
  113. package/lib/server/launchApp.js +0 -1
  114. package/lib/server/localUtils.js +6 -6
  115. package/lib/server/network.js +59 -20
  116. package/lib/server/overlay.js +138 -0
  117. package/lib/server/page.js +179 -157
  118. package/lib/server/progress.js +32 -6
  119. package/lib/server/recorder/recorderApp.js +84 -104
  120. package/lib/server/recorder.js +76 -40
  121. package/lib/server/registry/browserFetcher.js +6 -4
  122. package/lib/server/registry/index.js +222 -226
  123. package/lib/server/registry/nativeDeps.js +1 -0
  124. package/lib/server/registry/oopDownloadBrowserMain.js +3 -0
  125. package/lib/server/screencast.js +137 -0
  126. package/lib/server/trace/recorder/snapshotter.js +2 -2
  127. package/lib/server/trace/recorder/snapshotterInjected.js +21 -1
  128. package/lib/server/trace/recorder/tracing.js +98 -47
  129. package/lib/server/trace/viewer/traceViewer.js +24 -21
  130. package/lib/server/usKeyboardLayout.js +7 -0
  131. package/lib/server/utils/comparators.js +1 -1
  132. package/lib/server/utils/disposable.js +32 -0
  133. package/lib/server/utils/eventsHelper.js +3 -1
  134. package/lib/server/utils/expectUtils.js +87 -2
  135. package/lib/server/utils/fileUtils.js +16 -2
  136. package/lib/server/utils/happyEyeballs.js +15 -12
  137. package/lib/server/utils/httpServer.js +10 -23
  138. package/lib/server/utils/network.js +39 -29
  139. package/lib/server/utils/processLauncher.js +8 -6
  140. package/lib/server/utils/zipFile.js +2 -2
  141. package/lib/server/videoRecorder.js +194 -0
  142. package/lib/server/webkit/webkit.js +4 -6
  143. package/lib/server/webkit/wkBrowser.js +1 -10
  144. package/lib/server/webkit/wkConnection.js +1 -6
  145. package/lib/server/webkit/wkInterceptableRequest.js +29 -1
  146. package/lib/server/webkit/wkPage.js +88 -57
  147. package/lib/server/webkit/wkWorkers.js +2 -1
  148. package/lib/serverRegistry.js +156 -0
  149. package/lib/tools/backend/browserBackend.js +79 -0
  150. package/lib/tools/backend/common.js +63 -0
  151. package/lib/tools/backend/config.js +41 -0
  152. package/lib/tools/backend/console.js +66 -0
  153. package/lib/tools/backend/context.js +296 -0
  154. package/lib/tools/backend/cookies.js +152 -0
  155. package/lib/tools/backend/devtools.js +69 -0
  156. package/lib/tools/backend/dialogs.js +59 -0
  157. package/lib/tools/backend/evaluate.js +64 -0
  158. package/lib/tools/backend/files.js +60 -0
  159. package/lib/tools/backend/form.js +64 -0
  160. package/lib/tools/backend/keyboard.js +155 -0
  161. package/lib/tools/backend/logFile.js +95 -0
  162. package/lib/tools/backend/mouse.js +168 -0
  163. package/lib/tools/backend/navigate.js +106 -0
  164. package/lib/tools/backend/network.js +135 -0
  165. package/lib/tools/backend/pdf.js +48 -0
  166. package/lib/tools/backend/response.js +305 -0
  167. package/lib/tools/backend/route.js +140 -0
  168. package/lib/tools/backend/runCode.js +77 -0
  169. package/lib/tools/backend/screenshot.js +88 -0
  170. package/lib/tools/backend/sessionLog.js +74 -0
  171. package/lib/tools/backend/snapshot.js +208 -0
  172. package/lib/tools/backend/storage.js +68 -0
  173. package/lib/tools/backend/tab.js +445 -0
  174. package/lib/tools/backend/tabs.js +67 -0
  175. package/lib/tools/backend/tool.js +47 -0
  176. package/lib/tools/backend/tools.js +102 -0
  177. package/lib/tools/backend/tracing.js +78 -0
  178. package/lib/tools/backend/utils.js +83 -0
  179. package/lib/tools/backend/verify.js +151 -0
  180. package/lib/tools/backend/video.js +98 -0
  181. package/lib/tools/backend/wait.js +63 -0
  182. package/lib/tools/backend/webstorage.js +223 -0
  183. package/lib/tools/cli-client/cli.js +6 -0
  184. package/lib/tools/cli-client/help.json +399 -0
  185. package/lib/tools/cli-client/minimist.js +128 -0
  186. package/lib/tools/cli-client/program.js +350 -0
  187. package/lib/tools/cli-client/registry.js +176 -0
  188. package/lib/tools/cli-client/session.js +289 -0
  189. package/lib/tools/cli-client/skill/SKILL.md +328 -0
  190. package/lib/tools/cli-client/skill/references/element-attributes.md +23 -0
  191. package/lib/tools/cli-client/skill/references/playwright-tests.md +39 -0
  192. package/lib/tools/cli-client/skill/references/request-mocking.md +87 -0
  193. package/lib/tools/cli-client/skill/references/running-code.md +231 -0
  194. package/lib/tools/cli-client/skill/references/session-management.md +169 -0
  195. package/lib/tools/cli-client/skill/references/storage-state.md +275 -0
  196. package/lib/tools/cli-client/skill/references/test-generation.md +88 -0
  197. package/lib/tools/cli-client/skill/references/tracing.md +139 -0
  198. package/lib/tools/cli-client/skill/references/video-recording.md +143 -0
  199. package/lib/tools/cli-daemon/command.js +73 -0
  200. package/lib/tools/cli-daemon/commands.js +956 -0
  201. package/lib/tools/cli-daemon/daemon.js +157 -0
  202. package/lib/tools/cli-daemon/helpGenerator.js +177 -0
  203. package/lib/tools/cli-daemon/program.js +129 -0
  204. package/lib/tools/dashboard/appIcon.png +0 -0
  205. package/lib/tools/dashboard/dashboardApp.js +284 -0
  206. package/lib/tools/dashboard/dashboardController.js +296 -0
  207. package/lib/tools/exports.js +60 -0
  208. package/lib/tools/mcp/browserFactory.js +233 -0
  209. package/lib/tools/mcp/cdpRelay.js +352 -0
  210. package/lib/tools/mcp/cli-stub.js +7 -0
  211. package/lib/tools/mcp/config.d.js +16 -0
  212. package/lib/tools/mcp/config.js +446 -0
  213. package/lib/tools/mcp/configIni.js +189 -0
  214. package/lib/tools/mcp/extensionContextFactory.js +55 -0
  215. package/lib/tools/mcp/index.js +62 -0
  216. package/lib/tools/mcp/log.js +35 -0
  217. package/lib/tools/mcp/program.js +107 -0
  218. package/lib/tools/mcp/protocol.js +28 -0
  219. package/lib/tools/mcp/watchdog.js +44 -0
  220. package/lib/tools/trace/SKILL.md +171 -0
  221. package/lib/tools/trace/installSkill.js +48 -0
  222. package/lib/tools/trace/traceActions.js +142 -0
  223. package/lib/tools/trace/traceAttachments.js +69 -0
  224. package/lib/tools/trace/traceCli.js +87 -0
  225. package/lib/tools/trace/traceConsole.js +97 -0
  226. package/lib/tools/trace/traceErrors.js +55 -0
  227. package/lib/tools/trace/traceOpen.js +69 -0
  228. package/lib/tools/trace/traceParser.js +96 -0
  229. package/lib/tools/trace/traceRequests.js +182 -0
  230. package/lib/tools/trace/traceScreenshot.js +68 -0
  231. package/lib/tools/trace/traceSnapshot.js +149 -0
  232. package/lib/tools/trace/traceUtils.js +153 -0
  233. package/lib/tools/utils/connect.js +32 -0
  234. package/lib/tools/utils/mcp/http.js +152 -0
  235. package/lib/tools/utils/mcp/server.js +230 -0
  236. package/lib/tools/utils/mcp/tool.js +47 -0
  237. package/lib/tools/utils/socketConnection.js +108 -0
  238. package/lib/utils/isomorphic/ariaSnapshot.js +60 -2
  239. package/lib/utils/isomorphic/formatUtils.js +64 -0
  240. package/lib/utils/isomorphic/jsonSchema.js +89 -0
  241. package/lib/utils/isomorphic/lruCache.js +51 -0
  242. package/lib/utils/isomorphic/mimeType.js +7 -2
  243. package/lib/utils/isomorphic/protocolFormatter.js +2 -2
  244. package/lib/utils/isomorphic/protocolMetainfo.js +127 -98
  245. package/lib/utils/isomorphic/stringUtils.js +49 -0
  246. package/lib/utils/isomorphic/timeoutRunner.js +3 -3
  247. package/lib/utils/isomorphic/trace/entries.js +16 -0
  248. package/lib/utils/isomorphic/trace/snapshotRenderer.js +492 -0
  249. package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
  250. package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
  251. package/lib/utils/isomorphic/trace/traceLoader.js +132 -0
  252. package/lib/utils/isomorphic/trace/traceModel.js +366 -0
  253. package/lib/utils/isomorphic/trace/traceModernizer.js +401 -0
  254. package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
  255. package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
  256. package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
  257. package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
  258. package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
  259. package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
  260. package/lib/utils/isomorphic/urlMatch.js +54 -1
  261. package/lib/utils/isomorphic/utilityScriptSerializers.js +11 -0
  262. package/lib/utils/isomorphic/yaml.js +84 -0
  263. package/lib/utils.js +8 -2
  264. package/lib/utilsBundle.js +5 -26
  265. package/lib/utilsBundleImpl/index.js +172 -173
  266. package/lib/vite/dashboard/assets/index-BAOybkp8.js +50 -0
  267. package/lib/vite/dashboard/assets/index-CZAYOG76.css +1 -0
  268. package/lib/vite/dashboard/index.html +28 -0
  269. package/lib/vite/htmlReport/index.html +2 -70
  270. package/lib/vite/htmlReport/report.css +1 -0
  271. package/lib/vite/htmlReport/report.js +72 -0
  272. package/lib/vite/recorder/assets/codeMirrorModule-C8KMvO9L.js +32 -0
  273. package/lib/vite/recorder/assets/{codeMirrorModule-C3UTv-Ge.css → codeMirrorModule-DYBRYzYX.css} +1 -1
  274. package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
  275. package/lib/vite/recorder/assets/index-CqAYX1I3.js +193 -0
  276. package/lib/vite/recorder/index.html +2 -2
  277. package/lib/vite/traceViewer/assets/codeMirrorModule-DS0FLvoc.js +32 -0
  278. package/lib/vite/traceViewer/assets/defaultSettingsView-GTWI-W_B.js +262 -0
  279. package/lib/vite/traceViewer/{codeMirrorModule.C3UTv-Ge.css → codeMirrorModule.DYBRYzYX.css} +1 -1
  280. package/lib/vite/traceViewer/defaultSettingsView.B4dS75f0.css +1 -0
  281. package/lib/vite/traceViewer/index.CzXZzn5A.css +1 -0
  282. package/lib/vite/traceViewer/index.Dtstcb7U.js +2 -0
  283. package/lib/vite/traceViewer/index.html +4 -4
  284. package/lib/vite/traceViewer/sw.bundle.js +5 -3
  285. package/lib/vite/traceViewer/uiMode.Vipi55dB.js +6 -0
  286. package/lib/vite/traceViewer/uiMode.html +3 -3
  287. package/lib/zipBundleImpl.js +2 -2
  288. package/lib/zodBundle.js +39 -0
  289. package/lib/zodBundleImpl.js +40 -0
  290. package/package.json +7 -1
  291. package/types/protocol.d.ts +1696 -221
  292. package/types/types.d.ts +879 -112
  293. package/lib/server/bidi/third_party/bidiDeserializer.js +0 -98
  294. package/lib/server/chromium/videoRecorder.js +0 -115
  295. package/lib/server/pageBinding.js +0 -87
  296. package/lib/server/trace/test/inMemorySnapshotter.js +0 -87
  297. package/lib/utils/isomorphic/oldUtilityScriptSerializers.js +0 -248
  298. package/lib/vite/recorder/assets/codeMirrorModule-CBbSe-ZI.js +0 -25
  299. package/lib/vite/recorder/assets/index-CpZVd2nA.js +0 -193
  300. package/lib/vite/traceViewer/assets/codeMirrorModule-DHz0wP2C.js +0 -25
  301. package/lib/vite/traceViewer/assets/defaultSettingsView-WsZP88O6.js +0 -266
  302. package/lib/vite/traceViewer/defaultSettingsView.ConWv5KN.css +0 -1
  303. package/lib/vite/traceViewer/index.C4Y3Aw8n.css +0 -1
  304. package/lib/vite/traceViewer/index.C8xAeo93.js +0 -2
  305. package/lib/vite/traceViewer/uiMode.BltraIJB.js +0 -5
  306. /package/lib/{server/utils → utils/isomorphic}/imageUtils.js +0 -0
  307. /package/lib/utils/isomorphic/{traceUtils.js → trace/traceUtils.js} +0 -0
@@ -53,6 +53,7 @@ class RecorderApp {
53
53
  this._recorderSources = [];
54
54
  this._page = page;
55
55
  this._recorder = recorder;
56
+ this._frontend = createRecorderFrontend(page);
56
57
  this.wsEndpointForTest = wsEndpointForTest;
57
58
  this._languageGeneratorOptions = {
58
59
  browserName: params.browserName,
@@ -64,6 +65,10 @@ class RecorderApp {
64
65
  this._throttledOutputFile = params.outputFile ? new import_throttledFile.ThrottledFile(params.outputFile) : null;
65
66
  this._primaryGeneratorId = process.env.TEST_INSPECTOR_LANGUAGE || params.language || determinePrimaryGeneratorId(params.sdkLanguage);
66
67
  this._selectedGeneratorId = this._primaryGeneratorId;
68
+ for (const languageGenerator of (0, import_languages.languageSet)()) {
69
+ if (languageGenerator.id === this._primaryGeneratorId)
70
+ this._recorder.setLanguage(languageGenerator.highlighter);
71
+ }
67
72
  }
68
73
  async _init(inspectedContext) {
69
74
  await (0, import_launchApp.syncLocalStorageWithSettings)(this._page, "recorder");
@@ -89,7 +94,7 @@ class RecorderApp {
89
94
  });
90
95
  });
91
96
  });
92
- await this._page.exposeBinding(progress, "dispatch", false, (_, data) => this._handleUIEvent(data));
97
+ await this._createDispatcher(progress);
93
98
  this._page.once("close", () => {
94
99
  this._recorder.close();
95
100
  this._page.browserContext.close({ reason: "Recorder window closed" }).catch(() => {
@@ -100,59 +105,56 @@ class RecorderApp {
100
105
  });
101
106
  const url = this._recorder.url();
102
107
  if (url)
103
- this._onPageNavigated(url);
104
- this._onModeChanged(this._recorder.mode());
105
- this._onPausedStateChanged(this._recorder.paused());
108
+ this._frontend.pageNavigated({ url });
109
+ this._frontend.modeChanged({ mode: this._recorder.mode() });
110
+ this._frontend.pauseStateChanged({ paused: this._recorder.paused() });
106
111
  this._updateActions("reveal");
107
112
  this._onUserSourcesChanged(this._recorder.userSources(), this._recorder.pausedSourceId());
108
- this._onCallLogsUpdated(this._recorder.callLog());
113
+ this._frontend.callLogsUpdated({ callLogs: this._recorder.callLog() });
109
114
  this._wireListeners(this._recorder);
110
115
  }
111
- _handleUIEvent(data) {
112
- if (data.event === "clear") {
113
- this._actions = [];
114
- this._updateActions("reveal");
115
- this._recorder.clear();
116
- return;
117
- }
118
- if (data.event === "fileChanged") {
119
- const source = [...this._recorderSources, ...this._userSources].find((s) => s.id === data.params.fileId);
120
- if (source) {
121
- if (source.isRecorded)
122
- this._selectedGeneratorId = source.id;
123
- this._recorder.setLanguage(source.language);
116
+ async _createDispatcher(progress) {
117
+ const dispatcher = {
118
+ clear: async () => {
119
+ this._actions = [];
120
+ this._updateActions("reveal");
121
+ this._recorder.clear();
122
+ },
123
+ fileChanged: async (params) => {
124
+ const source = [...this._recorderSources, ...this._userSources].find((s) => s.id === params.fileId);
125
+ if (source) {
126
+ if (source.isRecorded)
127
+ this._selectedGeneratorId = source.id;
128
+ await this._recorder.setLanguage(source.language);
129
+ }
130
+ },
131
+ setAutoExpect: async (params) => {
132
+ this._languageGeneratorOptions.generateAutoExpect = params.autoExpect;
133
+ this._updateActions();
134
+ },
135
+ setMode: async (params) => {
136
+ await this._recorder.setMode(params.mode);
137
+ },
138
+ resume: async () => {
139
+ this._recorder.resume();
140
+ },
141
+ pause: async () => {
142
+ this._recorder.pause();
143
+ },
144
+ step: async () => {
145
+ this._recorder.step();
146
+ },
147
+ highlightRequested: async (params) => {
148
+ if (params.selector)
149
+ await this._recorder.setHighlightedSelector(params.selector);
150
+ if (params.ariaTemplate)
151
+ await this._recorder.setHighlightedAriaTemplate(params.ariaTemplate);
124
152
  }
125
- return;
126
- }
127
- if (data.event === "setAutoExpect") {
128
- this._languageGeneratorOptions.generateAutoExpect = data.params.autoExpect;
129
- this._updateActions();
130
- return;
131
- }
132
- if (data.event === "setMode") {
133
- this._recorder.setMode(data.params.mode);
134
- return;
135
- }
136
- if (data.event === "resume") {
137
- this._recorder.resume();
138
- return;
139
- }
140
- if (data.event === "pause") {
141
- this._recorder.pause();
142
- return;
143
- }
144
- if (data.event === "step") {
145
- this._recorder.step();
146
- return;
147
- }
148
- if (data.event === "highlightRequested") {
149
- if (data.params.selector)
150
- this._recorder.setHighlightedSelector(data.params.selector);
151
- if (data.params.ariaTemplate)
152
- this._recorder.setHighlightedAriaTemplate(data.params.ariaTemplate);
153
- return;
154
- }
155
- throw new Error(`Unknown event: ${data.event}`);
153
+ };
154
+ await this._page.exposeBinding(progress, "sendCommand", false, async (_, data) => {
155
+ const { method, params } = data;
156
+ return await dispatcher[method].call(dispatcher, params);
157
+ });
156
158
  }
157
159
  static async show(context, params) {
158
160
  if (process.env.PW_CODEGEN_NO_INSPECTOR)
@@ -179,6 +181,7 @@ class RecorderApp {
179
181
  return;
180
182
  inspectedContext[recorderAppSymbol] = true;
181
183
  const sdkLanguage = inspectedContext._browser.sdkLanguage();
184
+ const isChromium = inspectedContext._browser.options.browserType === "chromium";
182
185
  const headed = !!inspectedContext._browser.options.headful;
183
186
  const recorderPlaywright = require("../playwright").createPlaywright({ sdkLanguage: "javascript", isInternalPlaywright: true });
184
187
  const { context: appContext, page } = await (0, import_launchApp2.launchApp)(recorderPlaywright.chromium, {
@@ -190,9 +193,9 @@ class RecorderApp {
190
193
  headless: !!process.env.PWTEST_CLI_HEADLESS || (0, import_debug.isUnderTest)() && !headed,
191
194
  cdpPort: (0, import_debug.isUnderTest)() ? 0 : void 0,
192
195
  handleSIGINT: params.handleSIGINT,
193
- executablePath: inspectedContext._browser.options.isChromium ? inspectedContext._browser.options.customExecutablePath : void 0,
196
+ executablePath: isChromium ? inspectedContext._browser.options.customExecutablePath : void 0,
194
197
  // Use the same channel as the inspected context to guarantee that the browser is installed.
195
- channel: inspectedContext._browser.options.isChromium ? inspectedContext._browser.options.channel : void 0
198
+ channel: isChromium ? inspectedContext._browser.options.channel : void 0
196
199
  }
197
200
  });
198
201
  const controller = new import_progress.ProgressController();
@@ -204,8 +207,8 @@ class RecorderApp {
204
207
  sdkLanguage: inspectedContext._browser.sdkLanguage(),
205
208
  wsEndpointForTest: inspectedContext._browser.options.wsEndpoint,
206
209
  headed: !!inspectedContext._browser.options.headful,
207
- executablePath: inspectedContext._browser.options.isChromium ? inspectedContext._browser.options.customExecutablePath : void 0,
208
- channel: inspectedContext._browser.options.isChromium ? inspectedContext._browser.options.channel : void 0,
210
+ executablePath: isChromium ? inspectedContext._browser.options.customExecutablePath : void 0,
211
+ channel: isChromium ? inspectedContext._browser.options.channel : void 0,
209
212
  ...params
210
213
  };
211
214
  const recorderApp = new RecorderApp(recorder, appParams, page, appContext._browser.options.wsEndpoint);
@@ -220,25 +223,29 @@ class RecorderApp {
220
223
  this._onSignalAdded(signal);
221
224
  });
222
225
  recorder.on(import_recorder.RecorderEvent.PageNavigated, (url) => {
223
- this._onPageNavigated(url);
226
+ this._frontend.pageNavigated({ url });
224
227
  });
225
228
  recorder.on(import_recorder.RecorderEvent.ContextClosed, () => {
226
- this._onContextClosed();
229
+ this._throttledOutputFile?.flush();
230
+ this._page.browserContext.close({ reason: "Recorder window closed" }).catch(() => {
231
+ });
227
232
  });
228
233
  recorder.on(import_recorder.RecorderEvent.ModeChanged, (mode) => {
229
- this._onModeChanged(mode);
234
+ this._frontend.modeChanged({ mode });
230
235
  });
231
236
  recorder.on(import_recorder.RecorderEvent.PausedStateChanged, (paused) => {
232
- this._onPausedStateChanged(paused);
237
+ this._frontend.pauseStateChanged({ paused });
233
238
  });
234
239
  recorder.on(import_recorder.RecorderEvent.UserSourcesChanged, (sources, pausedSourceId) => {
235
240
  this._onUserSourcesChanged(sources, pausedSourceId);
236
241
  });
237
242
  recorder.on(import_recorder.RecorderEvent.ElementPicked, (elementInfo, userGesture) => {
238
- this._onElementPicked(elementInfo, userGesture);
243
+ if (userGesture)
244
+ this._page.bringToFront();
245
+ this._frontend.elementPicked({ elementInfo, userGesture });
239
246
  });
240
247
  recorder.on(import_recorder.RecorderEvent.CallLogsUpdated, (callLogs) => {
241
- this._onCallLogsUpdated(callLogs);
248
+ this._frontend.callLogsUpdated({ callLogs });
242
249
  });
243
250
  }
244
251
  _onActionAdded(action) {
@@ -251,29 +258,6 @@ class RecorderApp {
251
258
  lastAction.action.signals.push(signal.signal);
252
259
  this._updateActions();
253
260
  }
254
- _onPageNavigated(url) {
255
- this._page.mainFrame().evaluateExpression((({ url: url2 }) => {
256
- window.playwrightSetPageURL(url2);
257
- }).toString(), { isFunction: true }, { url }).catch(() => {
258
- });
259
- }
260
- _onContextClosed() {
261
- this._throttledOutputFile?.flush();
262
- this._page.browserContext.close({ reason: "Recorder window closed" }).catch(() => {
263
- });
264
- }
265
- _onModeChanged(mode) {
266
- this._page.mainFrame().evaluateExpression(((mode2) => {
267
- window.playwrightSetMode(mode2);
268
- }).toString(), { isFunction: true }, mode).catch(() => {
269
- });
270
- }
271
- _onPausedStateChanged(paused) {
272
- this._page.mainFrame().evaluateExpression(((paused2) => {
273
- window.playwrightSetPaused(paused2);
274
- }).toString(), { isFunction: true }, paused).catch(() => {
275
- });
276
- }
277
261
  _onUserSourcesChanged(sources, pausedSourceId) {
278
262
  if (!sources.length && !this._userSources.length)
279
263
  return;
@@ -281,34 +265,14 @@ class RecorderApp {
281
265
  this._pushAllSources();
282
266
  this._revealSource(pausedSourceId);
283
267
  }
284
- _onElementPicked(elementInfo, userGesture) {
285
- if (userGesture)
286
- this._page.bringToFront();
287
- this._page.mainFrame().evaluateExpression(((param) => {
288
- window.playwrightElementPicked(param.elementInfo, param.userGesture);
289
- }).toString(), { isFunction: true }, { elementInfo, userGesture }).catch(() => {
290
- });
291
- }
292
- _onCallLogsUpdated(callLogs) {
293
- this._page.mainFrame().evaluateExpression(((callLogs2) => {
294
- window.playwrightUpdateLogs(callLogs2);
295
- }).toString(), { isFunction: true }, callLogs).catch(() => {
296
- });
297
- }
298
268
  _pushAllSources() {
299
269
  const sources = [...this._userSources, ...this._recorderSources];
300
- this._page.mainFrame().evaluateExpression((({ sources: sources2 }) => {
301
- window.playwrightSetSources(sources2);
302
- }).toString(), { isFunction: true }, { sources }).catch(() => {
303
- });
270
+ this._frontend.sourcesUpdated({ sources });
304
271
  }
305
272
  _revealSource(sourceId) {
306
273
  if (!sourceId)
307
274
  return;
308
- this._page.mainFrame().evaluateExpression((({ sourceId: sourceId2 }) => {
309
- window.playwrightSelectSource(sourceId2);
310
- }).toString(), { isFunction: true }, { sourceId }).catch(() => {
311
- });
275
+ this._frontend.sourceRevealRequested({ sourceId });
312
276
  }
313
277
  _updateActions(reveal) {
314
278
  const recorderSources = [];
@@ -372,6 +336,8 @@ class ProgrammaticRecorderApp {
372
336
  });
373
337
  recorder.on(import_recorder.RecorderEvent.SignalAdded, (signal) => {
374
338
  const page = findPageByGuid(inspectedContext, signal.frame.pageGuid);
339
+ if (!page)
340
+ return;
375
341
  inspectedContext.emit(import_browserContext.BrowserContext.Events.RecorderEvent, { event: "signalAdded", data: signal, page, code: "" });
376
342
  });
377
343
  }
@@ -379,6 +345,20 @@ class ProgrammaticRecorderApp {
379
345
  function findPageByGuid(context, guid) {
380
346
  return context.pages().find((p) => p.guid === guid);
381
347
  }
348
+ function createRecorderFrontend(page) {
349
+ return new Proxy({}, {
350
+ get: (_target, prop) => {
351
+ if (typeof prop !== "string")
352
+ return void 0;
353
+ return (params) => {
354
+ page.mainFrame().evaluateExpression(((event) => {
355
+ window.dispatch(event);
356
+ }).toString(), { isFunction: true }, { method: prop, params }).catch(() => {
357
+ });
358
+ };
359
+ }
360
+ });
361
+ }
382
362
  const recorderAppSymbol = Symbol("recorderApp");
383
363
  // Annotate the CommonJS export names for ESM import in node:
384
364
  0 && (module.exports = {
@@ -41,6 +41,7 @@ var import_recorderUtils = require("./recorder/recorderUtils");
41
41
  var import_locatorParser = require("../utils/isomorphic/locatorParser");
42
42
  var import_selectorParser = require("../utils/isomorphic/selectorParser");
43
43
  var import_progress = require("./progress");
44
+ var import_manualPromise = require("../utils/isomorphic/manualPromise");
44
45
  var import_recorderSignalProcessor = require("./recorder/recorderSignalProcessor");
45
46
  var rawRecorderSource = __toESM(require("./../generated/pollingRecorderSource"));
46
47
  var import_utils2 = require("./../utils");
@@ -144,8 +145,11 @@ class Recorder extends import_events.default {
144
145
  }
145
146
  }
146
147
  }
148
+ let mode = this._mode;
149
+ if (this._pickLocatorPage && source.page !== this._pickLocatorPage)
150
+ mode = "none";
147
151
  const uiState = {
148
- mode: this._mode,
152
+ mode,
149
153
  actionPoint,
150
154
  actionSelector,
151
155
  ariaTemplate: this._highlightedElement.ariaTemplate,
@@ -162,7 +166,7 @@ class Recorder extends import_events.default {
162
166
  await this._context.exposeBinding(progress, "__pw_recorderSetMode", false, async ({ frame }, mode) => {
163
167
  if (frame.parentFrame())
164
168
  return;
165
- this.setMode(mode);
169
+ await this.setMode(mode);
166
170
  });
167
171
  await this._context.exposeBinding(progress, "__pw_recorderSetOverlayState", false, async ({ frame }, state) => {
168
172
  if (frame.parentFrame())
@@ -170,7 +174,7 @@ class Recorder extends import_events.default {
170
174
  this._overlayState = state;
171
175
  });
172
176
  await this._context.exposeBinding(progress, "__pw_resume", false, () => {
173
- this._debugger.resume(false);
177
+ this._debugger.resume();
174
178
  });
175
179
  this._context.on(import_browserContext.BrowserContext.Events.Page, (page) => this._onPage(page));
176
180
  for (const page of this._context.pages())
@@ -191,17 +195,16 @@ class Recorder extends import_events.default {
191
195
  false,
192
196
  (source, action) => this._recordAction(source.frame, action)
193
197
  );
194
- await this._context.extendInjectedScript(rawRecorderSource.source, { recorderMode: this._recorderMode });
198
+ await this._context.extendInjectedScript(rawRecorderSource.source, { recorderMode: this._recorderMode, hideToolbar: !!this._params.hideToolbar });
195
199
  });
196
200
  if (this._debugger.isPaused())
197
201
  this._pausedStateChanged();
198
202
  this._debugger.on(import_debugger.Debugger.Events.PausedStateChanged, () => this._pausedStateChanged());
199
203
  }
200
204
  _pausedStateChanged() {
201
- for (const { metadata, sdkObject } of this._debugger.pausedDetails()) {
202
- if (!this._currentCallsMetadata.has(metadata))
203
- this.onBeforeCall(sdkObject, metadata);
204
- }
205
+ const pausedDetails = this._debugger.pausedDetails();
206
+ if (pausedDetails && !this._currentCallsMetadata.has(pausedDetails.metadata))
207
+ this.onBeforeCall(pausedDetails.sdkObject, pausedDetails.metadata);
205
208
  this.emit(RecorderEvent.PausedStateChanged, this._debugger.isPaused());
206
209
  this._updateUserSources();
207
210
  this.updateCallLog([...this._currentCallsMetadata.keys()]);
@@ -209,7 +212,7 @@ class Recorder extends import_events.default {
209
212
  mode() {
210
213
  return this._mode;
211
214
  }
212
- setMode(mode) {
215
+ async setMode(mode) {
213
216
  if (this._mode === mode)
214
217
  return;
215
218
  this._highlightedElement = {};
@@ -217,54 +220,91 @@ class Recorder extends import_events.default {
217
220
  this.emit(RecorderEvent.ModeChanged, this._mode);
218
221
  this._setEnabled(this._isRecording());
219
222
  this._debugger.setMuted(this._isRecording());
220
- if (this._mode !== "none" && this._mode !== "standby" && this._context.pages().length === 1)
221
- this._context.pages()[0].bringToFront().catch(() => {
223
+ if (this._mode !== "none" && this._mode !== "standby") {
224
+ let pageToFocus = this._pickLocatorPage;
225
+ if (!pageToFocus && this._context.pages().length === 1)
226
+ pageToFocus = this._context.pages()[0];
227
+ pageToFocus?.bringToFront().catch(() => {
222
228
  });
223
- this._refreshOverlay();
229
+ }
230
+ await this._refreshOverlay();
231
+ }
232
+ async pickLocator(progress, page) {
233
+ if (this._mode !== "none")
234
+ await this.setMode("none");
235
+ const selectorPromise = new import_manualPromise.ManualPromise();
236
+ let recorderChangedState = false;
237
+ const onElementPicked = (elementInfo) => {
238
+ selectorPromise.resolve(elementInfo.selector);
239
+ };
240
+ const onModeChanged = () => {
241
+ if (this._mode === "inspecting")
242
+ return;
243
+ recorderChangedState = true;
244
+ selectorPromise.reject(new Error("Locator picking was cancelled"));
245
+ };
246
+ const listeners = [
247
+ import_utils2.eventsHelper.addEventListener(this, RecorderEvent.ElementPicked, onElementPicked),
248
+ import_utils2.eventsHelper.addEventListener(this, RecorderEvent.ModeChanged, onModeChanged)
249
+ ];
250
+ try {
251
+ const doPickLocator = async () => {
252
+ selectorPromise.catch(() => {
253
+ });
254
+ this._pickLocatorPage = page;
255
+ await this.setMode("inspecting");
256
+ return await selectorPromise;
257
+ };
258
+ return await progress.race(doPickLocator());
259
+ } finally {
260
+ import_utils2.eventsHelper.removeEventListeners(listeners);
261
+ this._pickLocatorPage = void 0;
262
+ if (!recorderChangedState)
263
+ await this.setMode("none");
264
+ }
224
265
  }
225
266
  url() {
226
267
  const page = this._context.pages()[0];
227
268
  return page?.mainFrame().url();
228
269
  }
229
- setHighlightedSelector(selector) {
270
+ async setHighlightedSelector(selector) {
230
271
  this._highlightedElement = { selector: (0, import_locatorParser.locatorOrSelectorAsSelector)(this._currentLanguage, selector, this._context.selectors().testIdAttributeName()) };
231
- this._refreshOverlay();
272
+ await this._refreshOverlay();
232
273
  }
233
- setHighlightedAriaTemplate(ariaTemplate) {
274
+ async setHighlightedAriaTemplate(ariaTemplate) {
234
275
  this._highlightedElement = { ariaTemplate };
235
- this._refreshOverlay();
276
+ await this._refreshOverlay();
236
277
  }
237
278
  step() {
238
- this._debugger.resume(true);
279
+ this._debugger.setPauseAt({ next: true });
280
+ this._debugger.resume();
239
281
  }
240
- setLanguage(language) {
282
+ async setLanguage(language) {
241
283
  this._currentLanguage = language;
242
- this._refreshOverlay();
284
+ await this._refreshOverlay();
243
285
  }
244
286
  resume() {
245
- this._debugger.resume(false);
287
+ this._debugger.resume();
246
288
  }
247
289
  pause() {
248
- this._debugger.pauseOnNextStatement();
290
+ this._debugger.setPauseAt({ next: true });
249
291
  }
250
292
  paused() {
251
293
  return this._debugger.isPaused();
252
294
  }
253
295
  close() {
254
- this._debugger.resume(false);
296
+ this._debugger.resume();
255
297
  }
256
- hideHighlightedSelector() {
298
+ async hideHighlightedSelector() {
257
299
  this._highlightedElement = {};
258
- this._refreshOverlay();
300
+ await this._refreshOverlay();
259
301
  }
260
302
  pausedSourceId() {
261
- for (const { metadata } of this._debugger.pausedDetails()) {
262
- if (!metadata.location)
263
- continue;
264
- const source = this._userSources.get(metadata.location.file);
265
- if (!source)
266
- continue;
267
- return source.id;
303
+ const pausedDetails = this._debugger.pausedDetails();
304
+ if (pausedDetails?.metadata.location) {
305
+ const source = this._userSources.get(pausedDetails.metadata.location.file);
306
+ if (source)
307
+ return source.id;
268
308
  }
269
309
  }
270
310
  userSources() {
@@ -290,12 +330,10 @@ class Recorder extends import_events.default {
290
330
  return "";
291
331
  }
292
332
  }
293
- _refreshOverlay() {
294
- for (const page of this._context.pages()) {
295
- for (const frame of page.frames())
296
- frame.evaluateExpression("window.__pw_refreshOverlay()").catch(() => {
297
- });
298
- }
333
+ async _refreshOverlay() {
334
+ await Promise.all(this._context.pages().map(
335
+ (page) => page.safeNonStallingEvaluateInAllFrames("window.__pw_refreshOverlay()", "main")
336
+ ));
299
337
  }
300
338
  async onBeforeCall(sdkObject, metadata) {
301
339
  if (this._omitCallTracking || this._isRecording())
@@ -338,8 +376,6 @@ class Recorder extends import_events.default {
338
376
  }
339
377
  this.emit(RecorderEvent.UserSourcesChanged, this.userSources(), this.pausedSourceId());
340
378
  }
341
- async onBeforeInputAction(sdkObject, metadata) {
342
- }
343
379
  async onCallLog(sdkObject, metadata, logName, message) {
344
380
  this.updateCallLog([metadata]);
345
381
  }
@@ -388,7 +424,7 @@ class Recorder extends import_events.default {
388
424
  this._filePrimaryURLChanged();
389
425
  });
390
426
  frame.on(import_frames.Frame.Events.InternalNavigation, (event) => {
391
- if (event.isPublic) {
427
+ if (event.isPublic && !event.error) {
392
428
  this._onFrameNavigated(frame, page);
393
429
  this._filePrimaryURLChanged();
394
430
  }
@@ -42,10 +42,13 @@ var import_userAgent = require("../utils/userAgent");
42
42
  var import_utilsBundle = require("../../utilsBundle");
43
43
  var import_fileUtils = require("../utils/fileUtils");
44
44
  var import__ = require(".");
45
- async function downloadBrowserWithProgressBar(title, browserDirectory, executablePath, downloadURLs, downloadFileName, downloadSocketTimeout) {
45
+ async function downloadBrowserWithProgressBar(title, browserDirectory, executablePath, downloadURLs, downloadFileName, downloadSocketTimeout, force) {
46
46
  if (await (0, import_fileUtils.existsAsync)((0, import__.browserDirectoryToMarkerFilePath)(browserDirectory))) {
47
47
  import_debugLogger.debugLogger.log("install", `${title} is already downloaded.`);
48
- return false;
48
+ if (force)
49
+ import_debugLogger.debugLogger.log("install", `force-downloading ${title}.`);
50
+ else
51
+ return;
49
52
  }
50
53
  const uniqueTempDir = await import_fs.default.promises.mkdtemp(import_path.default.join(import_os.default.tmpdir(), "playwright-download-"));
51
54
  const zipPath = import_path.default.join(uniqueTempDir, downloadFileName);
@@ -63,7 +66,7 @@ async function downloadBrowserWithProgressBar(title, browserDirectory, executabl
63
66
  if (await (0, import_fileUtils.existsAsync)(zipPath))
64
67
  await import_fs.default.promises.unlink(zipPath);
65
68
  if (await (0, import_fileUtils.existsAsync)(browserDirectory))
66
- await import_fs.default.promises.rmdir(browserDirectory, { recursive: true });
69
+ await (0, import_fileUtils.removeFolders)([browserDirectory]);
67
70
  const errorMessage = error?.message || "";
68
71
  import_debugLogger.debugLogger.log("install", `attempt #${attempt} - ERROR: ${errorMessage}`);
69
72
  if (attempt >= retryCount)
@@ -77,7 +80,6 @@ async function downloadBrowserWithProgressBar(title, browserDirectory, executabl
77
80
  await (0, import_fileUtils.removeFolders)([uniqueTempDir]);
78
81
  }
79
82
  logPolitely(`${title} downloaded to ${browserDirectory}`);
80
- return true;
81
83
  }
82
84
  function downloadBrowserWithProgressBarOutOfProcess(title, browserDirectory, url, zipPath, executablePath, socketTimeout) {
83
85
  const cp = childProcess.fork(import_path.default.join(__dirname, "oopDownloadBrowserMain.js"));