patchright-core 1.52.4 → 1.55.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 (218) hide show
  1. package/ThirdPartyNotices.txt +65 -123
  2. package/bin/reinstall_chrome_beta_mac.sh +1 -1
  3. package/bin/reinstall_chrome_stable_mac.sh +1 -1
  4. package/bin/reinstall_msedge_beta_mac.sh +1 -1
  5. package/bin/reinstall_msedge_dev_mac.sh +1 -1
  6. package/bin/reinstall_msedge_stable_mac.sh +1 -1
  7. package/browsers.json +14 -14
  8. package/index.js +1 -1
  9. package/lib/androidServerImpl.js +4 -2
  10. package/lib/browserServerImpl.js +47 -12
  11. package/lib/cli/program.js +116 -50
  12. package/lib/cli/programWithTestStub.js +1 -1
  13. package/lib/client/android.js +30 -34
  14. package/lib/client/browser.js +54 -17
  15. package/lib/client/browserContext.js +67 -71
  16. package/lib/client/browserType.js +25 -34
  17. package/lib/client/channelOwner.js +20 -24
  18. package/lib/client/connection.js +6 -10
  19. package/lib/client/electron.js +8 -3
  20. package/lib/client/elementHandle.js +18 -21
  21. package/lib/client/fetch.js +5 -3
  22. package/lib/client/frame.js +57 -35
  23. package/lib/client/input.js +3 -1
  24. package/lib/client/jsHandle.js +4 -0
  25. package/lib/client/localUtils.js +0 -1
  26. package/lib/client/locator.js +32 -28
  27. package/lib/client/network.js +5 -12
  28. package/lib/client/page.js +32 -32
  29. package/lib/client/playwright.js +6 -16
  30. package/lib/client/selectors.js +18 -38
  31. package/lib/client/timeoutSettings.js +12 -8
  32. package/lib/client/tracing.js +24 -20
  33. package/lib/client/waiter.js +2 -2
  34. package/lib/client/webSocket.js +4 -22
  35. package/lib/generated/bindingsControllerSource.js +28 -0
  36. package/lib/generated/clockSource.js +1 -1
  37. package/lib/generated/injectedScriptSource.js +1 -1
  38. package/lib/generated/pollingRecorderSource.js +1 -1
  39. package/lib/generated/storageScriptSource.js +28 -0
  40. package/lib/generated/utilityScriptSource.js +1 -1
  41. package/lib/generated/webSocketMockSource.js +12 -50
  42. package/lib/inProcessFactory.js +9 -6
  43. package/lib/outofprocess.js +0 -2
  44. package/lib/protocol/validator.js +423 -346
  45. package/lib/protocol/validatorPrimitives.js +18 -4
  46. package/lib/remote/playwrightConnection.js +29 -166
  47. package/lib/remote/playwrightServer.js +233 -35
  48. package/lib/server/android/android.js +97 -83
  49. package/lib/server/android/backendAdb.js +0 -2
  50. package/lib/server/bidi/bidiBrowser.js +139 -73
  51. package/lib/server/bidi/bidiChromium.js +23 -22
  52. package/lib/server/bidi/bidiExecutionContext.js +2 -1
  53. package/lib/server/bidi/bidiFirefox.js +17 -14
  54. package/lib/server/bidi/bidiInput.js +22 -22
  55. package/lib/server/bidi/bidiNetworkManager.js +8 -11
  56. package/lib/server/bidi/bidiPage.js +42 -86
  57. package/lib/server/bidi/third_party/bidiProtocol.js +5 -133
  58. package/lib/server/bidi/third_party/bidiProtocolCore.js +179 -0
  59. package/lib/server/{dispatchers/selectorsDispatcher.js → bidi/third_party/bidiProtocolPermissions.js} +20 -18
  60. package/lib/server/browser.js +30 -21
  61. package/lib/server/browserContext.js +203 -165
  62. package/lib/server/browserType.js +109 -107
  63. package/lib/server/chromium/chromium.js +84 -69
  64. package/lib/server/chromium/chromiumSwitches.js +13 -20
  65. package/lib/server/chromium/crBrowser.js +74 -40
  66. package/lib/server/chromium/crConnection.js +8 -9
  67. package/lib/server/chromium/crCoverage.js +11 -8
  68. package/lib/server/chromium/crDragDrop.js +25 -20
  69. package/lib/server/chromium/crExecutionContext.js +2 -1
  70. package/lib/server/chromium/crInput.js +32 -29
  71. package/lib/server/chromium/crNetworkManager.js +45 -33
  72. package/lib/server/chromium/crPage.js +98 -73
  73. package/lib/server/chromium/crServiceWorker.js +13 -18
  74. package/lib/server/chromium/videoRecorder.js +10 -18
  75. package/lib/server/clock.js +51 -39
  76. package/lib/server/codegen/csharp.js +10 -5
  77. package/lib/server/codegen/java.js +1 -1
  78. package/lib/server/codegen/javascript.js +1 -1
  79. package/lib/server/codegen/jsonl.js +2 -1
  80. package/lib/server/codegen/language.js +22 -1
  81. package/lib/server/codegen/languages.js +4 -4
  82. package/lib/server/codegen/python.js +1 -1
  83. package/lib/server/cookieStore.js +3 -1
  84. package/lib/server/debugController.js +105 -71
  85. package/lib/server/debugger.js +6 -23
  86. package/lib/server/deviceDescriptorsSource.json +237 -127
  87. package/lib/server/dialog.js +50 -6
  88. package/lib/server/dispatchers/androidDispatcher.js +77 -62
  89. package/lib/server/dispatchers/artifactDispatcher.js +18 -18
  90. package/lib/server/dispatchers/browserContextDispatcher.js +141 -91
  91. package/lib/server/dispatchers/browserDispatcher.js +55 -88
  92. package/lib/server/dispatchers/browserTypeDispatcher.js +18 -9
  93. package/lib/server/dispatchers/cdpSessionDispatcher.js +4 -4
  94. package/lib/server/dispatchers/debugControllerDispatcher.js +12 -21
  95. package/lib/server/dispatchers/dialogDispatcher.js +4 -4
  96. package/lib/server/dispatchers/dispatcher.js +78 -53
  97. package/lib/server/dispatchers/electronDispatcher.js +19 -20
  98. package/lib/server/dispatchers/elementHandlerDispatcher.js +83 -93
  99. package/lib/server/dispatchers/frameDispatcher.js +99 -102
  100. package/lib/server/dispatchers/jsHandleDispatcher.js +21 -16
  101. package/lib/server/dispatchers/jsonPipeDispatcher.js +4 -4
  102. package/lib/server/dispatchers/localUtilsDispatcher.js +53 -59
  103. package/lib/server/dispatchers/networkDispatchers.js +41 -35
  104. package/lib/server/dispatchers/pageDispatcher.js +156 -107
  105. package/lib/server/dispatchers/playwrightDispatcher.js +37 -25
  106. package/lib/server/dispatchers/streamDispatcher.js +15 -8
  107. package/lib/server/dispatchers/tracingDispatcher.js +22 -13
  108. package/lib/server/dispatchers/webSocketRouteDispatcher.js +46 -35
  109. package/lib/server/dispatchers/writableStreamDispatcher.js +16 -10
  110. package/lib/server/dom.js +198 -266
  111. package/lib/server/download.js +3 -3
  112. package/lib/server/electron/electron.js +96 -103
  113. package/lib/server/electron/loader.js +1 -1
  114. package/lib/server/fetch.js +22 -41
  115. package/lib/server/fileUploadUtils.js +1 -1
  116. package/lib/server/firefox/ffBrowser.js +79 -55
  117. package/lib/server/firefox/ffExecutionContext.js +2 -1
  118. package/lib/server/firefox/ffInput.js +23 -23
  119. package/lib/server/firefox/ffNetworkManager.js +8 -6
  120. package/lib/server/firefox/ffPage.js +39 -36
  121. package/lib/server/firefox/firefox.js +9 -10
  122. package/lib/server/frameSelectors.js +65 -22
  123. package/lib/server/frames.js +516 -544
  124. package/lib/server/har/harRecorder.js +1 -1
  125. package/lib/server/har/harTracer.js +4 -2
  126. package/lib/server/helper.js +3 -7
  127. package/lib/server/index.js +0 -3
  128. package/lib/server/input.js +47 -54
  129. package/lib/server/instrumentation.js +8 -14
  130. package/lib/server/javascript.js +9 -17
  131. package/lib/server/launchApp.js +48 -30
  132. package/lib/server/localUtils.js +45 -38
  133. package/lib/server/network.js +44 -10
  134. package/lib/server/page.js +233 -178
  135. package/lib/server/pageBinding.js +6 -7
  136. package/lib/server/playwright.js +4 -14
  137. package/lib/server/progress.js +57 -49
  138. package/lib/server/recorder/recorderApp.js +298 -95
  139. package/lib/server/recorder/recorderRunner.js +23 -24
  140. package/lib/server/recorder/recorderSignalProcessor.js +83 -0
  141. package/lib/server/recorder/recorderUtils.js +67 -10
  142. package/lib/server/recorder.js +284 -146
  143. package/lib/server/registry/index.js +83 -48
  144. package/lib/server/registry/nativeDeps.js +175 -0
  145. package/lib/server/registry/oopDownloadBrowserMain.js +1 -1
  146. package/lib/server/screenshotter.js +84 -83
  147. package/lib/server/selectors.js +12 -12
  148. package/lib/server/socksClientCertificatesInterceptor.js +198 -136
  149. package/lib/server/trace/recorder/snapshotter.js +12 -19
  150. package/lib/server/trace/recorder/tracing.js +36 -27
  151. package/lib/server/trace/viewer/traceViewer.js +11 -20
  152. package/lib/server/transport.js +20 -22
  153. package/lib/server/utils/comparators.js +2 -2
  154. package/lib/server/utils/debug.js +3 -8
  155. package/lib/server/utils/debugLogger.js +8 -0
  156. package/lib/server/utils/hostPlatform.js +3 -1
  157. package/lib/server/utils/network.js +35 -25
  158. package/lib/server/utils/nodePlatform.js +1 -1
  159. package/lib/server/utils/processLauncher.js +4 -1
  160. package/lib/server/utils/wsServer.js +11 -17
  161. package/lib/server/webkit/webkit.js +5 -2
  162. package/lib/server/webkit/wkBrowser.js +51 -28
  163. package/lib/server/webkit/wkExecutionContext.js +2 -1
  164. package/lib/server/webkit/wkInput.js +25 -25
  165. package/lib/server/webkit/wkInterceptableRequest.js +1 -1
  166. package/lib/server/webkit/wkPage.js +80 -59
  167. package/lib/server/webkit/wkProvisionalPage.js +1 -1
  168. package/lib/server/webkit/wkWorkers.js +7 -7
  169. package/lib/utils/isomorphic/ariaSnapshot.js +13 -7
  170. package/lib/utils/isomorphic/cssParser.js +1 -2
  171. package/lib/utils/isomorphic/locatorGenerators.js +18 -0
  172. package/lib/utils/isomorphic/manualPromise.js +1 -2
  173. package/lib/utils/isomorphic/mimeType.js +1 -2
  174. package/lib/utils/isomorphic/multimap.js +1 -2
  175. package/lib/utils/isomorphic/oldUtilityScriptSerializers.js +248 -0
  176. package/lib/utils/isomorphic/protocolFormatter.js +78 -0
  177. package/lib/utils/isomorphic/protocolMetainfo.js +318 -0
  178. package/lib/utils/isomorphic/selectorParser.js +3 -4
  179. package/lib/utils/isomorphic/stringUtils.js +3 -24
  180. package/lib/utils/isomorphic/time.js +9 -4
  181. package/lib/utils/isomorphic/timeoutRunner.js +3 -4
  182. package/lib/utils/isomorphic/traceUtils.js +2 -3
  183. package/lib/utils/isomorphic/urlMatch.js +21 -7
  184. package/lib/utils/isomorphic/utilityScriptSerializers.js +208 -205
  185. package/lib/utils.js +8 -2
  186. package/lib/utilsBundleImpl/index.js +160 -150
  187. package/lib/vite/htmlReport/index.html +17 -17
  188. package/lib/vite/recorder/assets/{codeMirrorModule-CXVeovup.js → codeMirrorModule-DzQ0k89p.js} +1 -1
  189. package/lib/vite/recorder/assets/{index-eHBmevrY.css → index-CI4HQ-Zb.css} +1 -1
  190. package/lib/vite/recorder/assets/index-D7C7daHH.js +184 -0
  191. package/lib/vite/recorder/index.html +3 -3
  192. package/lib/vite/traceViewer/assets/{codeMirrorModule-_GLjJL-7.js → codeMirrorModule-Di48jgWx.js} +1 -1
  193. package/lib/vite/traceViewer/assets/defaultSettingsView-szBn8781.js +256 -0
  194. package/lib/vite/traceViewer/defaultSettingsView.DVJHpiGt.css +1 -0
  195. package/lib/vite/traceViewer/index.BFsek2M6.css +1 -0
  196. package/lib/vite/traceViewer/index.DQvXoPLL.js +2 -0
  197. package/lib/vite/traceViewer/index.html +6 -6
  198. package/lib/vite/traceViewer/sw.bundle.js +3 -3
  199. package/lib/vite/traceViewer/uiMode.dBV3oN9h.js +5 -0
  200. package/lib/vite/traceViewer/uiMode.html +4 -4
  201. package/lib/zipBundleImpl.js +4 -4
  202. package/package.json +1 -1
  203. package/types/protocol.d.ts +712 -107
  204. package/types/types.d.ts +148 -37
  205. package/lib/generated/consoleApiSource.js +0 -28
  206. package/lib/protocol/debug.js +0 -211
  207. package/lib/server/recorder/contextRecorder.js +0 -286
  208. package/lib/server/recorder/recorderCollection.js +0 -116
  209. package/lib/server/recorder/recorderFrontend.js +0 -16
  210. package/lib/server/storageScript.js +0 -154
  211. package/lib/server/timeoutSettings.js +0 -89
  212. package/lib/utils/isomorphic/builtins.js +0 -86
  213. package/lib/vite/recorder/assets/index-BsWQsSGl.js +0 -184
  214. package/lib/vite/traceViewer/assets/defaultSettingsView-DtCQiGHe.js +0 -265
  215. package/lib/vite/traceViewer/defaultSettingsView.QdHITyLI.css +0 -1
  216. package/lib/vite/traceViewer/index.CFOW-Ezb.css +0 -1
  217. package/lib/vite/traceViewer/index.cFZzK9RN.js +0 -2
  218. package/lib/vite/traceViewer/uiMode.XVPIqBeS.js +0 -5
@@ -34,7 +34,6 @@ __export(browserContext_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(browserContext_exports);
36
36
  var import_artifact = require("./artifact");
37
- var import_browser = require("./browser");
38
37
  var import_cdpSession = require("./cdpSession");
39
38
  var import_channelOwner = require("./channelOwner");
40
39
  var import_clientHelper = require("./clientHelper");
@@ -64,22 +63,21 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
64
63
  this._pages = /* @__PURE__ */ new Set();
65
64
  this._routes = [];
66
65
  this._webSocketRoutes = [];
66
+ // Browser is null for browser contexts created outside of normal browser, e.g. android or electron.
67
67
  this._browser = null;
68
68
  this._bindings = /* @__PURE__ */ new Map();
69
- this._options = {};
69
+ this._forReuse = false;
70
70
  this._backgroundPages = /* @__PURE__ */ new Set();
71
71
  this._serviceWorkers = /* @__PURE__ */ new Set();
72
72
  this._harRecorders = /* @__PURE__ */ new Map();
73
- this._closeWasCalled = false;
73
+ this._closingStatus = "none";
74
74
  this._harRouters = [];
75
75
  this.routeInjecting = false;
76
+ this._options = initializer.options;
76
77
  this._timeoutSettings = new import_timeoutSettings.TimeoutSettings(this._platform);
77
- if (parent instanceof import_browser.Browser)
78
- this._browser = parent;
79
- this._browser?._contexts.add(this);
80
- this._isChromium = this._browser?._name === "chromium";
81
78
  this.tracing = import_tracing.Tracing.from(initializer.tracing);
82
79
  this.request = import_fetch.APIRequestContext.from(initializer.requestContext);
80
+ this.request._timeoutSettings = this._timeoutSettings;
83
81
  this.clock = new import_clock.Clock(this);
84
82
  this._channel.on("bindingCall", ({ binding }) => this._onBinding(import_page.BindingCall.from(binding)));
85
83
  this._channel.on("close", () => this._onClose());
@@ -130,6 +128,14 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
130
128
  this._channel.on("requestFailed", ({ request, failureText, responseEndTiming, page }) => this._onRequestFailed(network.Request.from(request), responseEndTiming, failureText, import_page.Page.fromNullable(page)));
131
129
  this._channel.on("requestFinished", (params) => this._onRequestFinished(params));
132
130
  this._channel.on("response", ({ response, page }) => this._onResponse(network.Response.from(response), import_page.Page.fromNullable(page)));
131
+ this._channel.on("recorderEvent", ({ event, data, page, code }) => {
132
+ if (event === "actionAdded")
133
+ this._onRecorderEventSink?.actionAdded?.(import_page.Page.from(page), data, code);
134
+ else if (event === "actionUpdated")
135
+ this._onRecorderEventSink?.actionUpdated?.(import_page.Page.from(page), data, code);
136
+ else if (event === "signalAdded")
137
+ this._onRecorderEventSink?.signalAdded?.(import_page.Page.from(page), data);
138
+ });
133
139
  this._closedPromise = new Promise((f) => this.once(import_events.Events.BrowserContext.Close, f));
134
140
  this._setEventToSubscriptionMapping(/* @__PURE__ */ new Map([
135
141
  [import_events.Events.BrowserContext.Console, "console"],
@@ -146,11 +152,15 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
146
152
  static fromNullable(context) {
147
153
  return context ? BrowserContext.from(context) : null;
148
154
  }
149
- _setOptions(contextOptions, browserOptions) {
150
- this._options = contextOptions;
151
- if (this._options.recordHar)
152
- this._harRecorders.set("", { path: this._options.recordHar.path, content: this._options.recordHar.content });
153
- this.tracing._tracesDir = browserOptions.tracesDir;
155
+ async _initializeHarFromOptions(recordHar) {
156
+ if (!recordHar)
157
+ return;
158
+ const defaultContent = recordHar.path.endsWith(".zip") ? "attach" : "embed";
159
+ await this._recordIntoHAR(recordHar.path, null, {
160
+ url: recordHar.urlFilter,
161
+ updateContent: recordHar.content ?? (recordHar.omitContent ? "omit" : defaultContent),
162
+ updateMode: recordHar.mode ?? "full"
163
+ });
154
164
  }
155
165
  _onPage(page) {
156
166
  this._pages.add(page);
@@ -192,7 +202,7 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
192
202
  const page = route.request()._safePage();
193
203
  const routeHandlers = this._routes.slice();
194
204
  for (const routeHandler of routeHandlers) {
195
- if (page?._closeWasCalled || this._closeWasCalled)
205
+ if (page?._closeWasCalled || this._closingStatus !== "none")
196
206
  return;
197
207
  if (!routeHandler.matches(route.request().url()))
198
208
  continue;
@@ -203,7 +213,7 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
203
213
  this._routes.splice(index, 1);
204
214
  const handled = await routeHandler.handle(route);
205
215
  if (!this._routes.length)
206
- this._wrapApiCall(() => this._updateInterceptionPatterns(), true).catch(() => {
216
+ this._updateInterceptionPatterns({ internal: true }).catch(() => {
207
217
  });
208
218
  if (handled)
209
219
  return;
@@ -229,17 +239,9 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
229
239
  }
230
240
  setDefaultNavigationTimeout(timeout) {
231
241
  this._timeoutSettings.setDefaultNavigationTimeout(timeout);
232
- this._wrapApiCall(async () => {
233
- await this._channel.setDefaultNavigationTimeoutNoReply({ timeout });
234
- }, true).catch(() => {
235
- });
236
242
  }
237
243
  setDefaultTimeout(timeout) {
238
244
  this._timeoutSettings.setDefaultTimeout(timeout);
239
- this._wrapApiCall(async () => {
240
- await this._channel.setDefaultTimeoutNoReply({ timeout });
241
- }, true).catch(() => {
242
- });
243
245
  }
244
246
  browser() {
245
247
  return this._browser;
@@ -312,21 +314,23 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
312
314
  }
313
315
  async route(url, handler, options = {}) {
314
316
  this._routes.unshift(new network.RouteHandler(this._platform, this._options.baseURL, url, handler, options.times));
315
- await this._updateInterceptionPatterns();
317
+ await this._updateInterceptionPatterns({ title: "Route requests" });
316
318
  }
317
319
  async routeWebSocket(url, handler) {
318
320
  this._webSocketRoutes.unshift(new network.WebSocketRouteHandler(this._options.baseURL, url, handler));
319
- await this._updateWebSocketInterceptionPatterns();
321
+ await this._updateWebSocketInterceptionPatterns({ title: "Route WebSockets" });
320
322
  }
321
323
  async _recordIntoHAR(har, page, options = {}) {
322
324
  const { harId } = await this._channel.harStart({
323
325
  page: page?._channel,
324
- options: prepareRecordHarOptions({
325
- path: har,
326
+ options: {
327
+ zip: har.endsWith(".zip"),
326
328
  content: options.updateContent ?? "attach",
327
- mode: options.updateMode ?? "minimal",
328
- urlFilter: options.url
329
- })
329
+ urlGlob: (0, import_rtti.isString)(options.url) ? options.url : void 0,
330
+ urlRegexSource: (0, import_rtti.isRegExp)(options.url) ? options.url.source : void 0,
331
+ urlRegexFlags: (0, import_rtti.isRegExp)(options.url) ? options.url.flags : void 0,
332
+ mode: options.updateMode ?? "minimal"
333
+ }
330
334
  });
331
335
  this._harRecorders.set(harId, { path: har, content: options.updateContent ?? "attach" });
332
336
  }
@@ -363,19 +367,19 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
363
367
  }
364
368
  async _unrouteInternal(removed, remaining, behavior) {
365
369
  this._routes = remaining;
366
- await this._updateInterceptionPatterns();
367
- if (!behavior || behavior === "default")
368
- return;
369
- const promises = removed.map((routeHandler) => routeHandler.stop(behavior));
370
- await Promise.all(promises);
370
+ if (behavior && behavior !== "default") {
371
+ const promises = removed.map((routeHandler) => routeHandler.stop(behavior));
372
+ await Promise.all(promises);
373
+ }
374
+ await this._updateInterceptionPatterns({ title: "Unroute requests" });
371
375
  }
372
- async _updateInterceptionPatterns() {
376
+ async _updateInterceptionPatterns(options) {
373
377
  const patterns = network.RouteHandler.prepareInterceptionPatterns(this._routes);
374
- await this._channel.setNetworkInterceptionPatterns({ patterns });
378
+ await this._wrapApiCall(() => this._channel.setNetworkInterceptionPatterns({ patterns }), options);
375
379
  }
376
- async _updateWebSocketInterceptionPatterns() {
380
+ async _updateWebSocketInterceptionPatterns(options) {
377
381
  const patterns = network.WebSocketRouteHandler.prepareInterceptionPatterns(this._webSocketRoutes);
378
- await this._channel.setWebSocketInterceptionPatterns({ patterns });
382
+ await this._wrapApiCall(() => this._channel.setWebSocketInterceptionPatterns({ patterns }), options);
379
383
  }
380
384
  _effectiveCloseReason() {
381
385
  return this._closeReason || this._browser?._closeReason;
@@ -414,9 +418,10 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
414
418
  return import_cdpSession.CDPSession.from(result.session);
415
419
  }
416
420
  _onClose() {
417
- if (this._browser)
418
- this._browser._contexts.delete(this);
419
- this._browserType?._contexts?.delete(this);
421
+ this._closingStatus = "closed";
422
+ this._browser?._contexts.delete(this);
423
+ this._browser?._browserType._contexts.delete(this);
424
+ this._browser?._browserType._playwright.selectors._contextsForSelectors.delete(this);
420
425
  this._disposeHarRouters();
421
426
  this.tracing._resetStackCounter();
422
427
  this.emit(import_events.Events.BrowserContext.Close, this);
@@ -425,15 +430,13 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
425
430
  await this.close();
426
431
  }
427
432
  async close(options = {}) {
428
- if (this._closeWasCalled)
433
+ if (this._closingStatus !== "none")
429
434
  return;
430
435
  this._closeReason = options.reason;
431
- this._closeWasCalled = true;
432
- await this._wrapApiCall(async () => {
433
- await this.request.dispose(options);
434
- }, true);
436
+ this._closingStatus = "closing";
437
+ await this.request.dispose(options);
438
+ await this._instrumentation.runBeforeCloseBrowserContext(this);
435
439
  await this._wrapApiCall(async () => {
436
- await this._browserType?._willCloseContext(this);
437
440
  for (const [harId, harParams] of this._harRecorders) {
438
441
  const har = await this._channel.harExport({ harId });
439
442
  const artifact = import_artifact.Artifact.from(har.artifact);
@@ -450,52 +453,46 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
450
453
  }
451
454
  await artifact.delete();
452
455
  }
453
- }, true);
456
+ }, { internal: true });
454
457
  await this._channel.close(options);
455
458
  await this._closedPromise;
456
459
  }
457
- async _enableRecorder(params) {
460
+ async _enableRecorder(params, eventSink) {
461
+ if (eventSink)
462
+ this._onRecorderEventSink = eventSink;
458
463
  await this._channel.enableRecorder(params);
459
464
  }
465
+ async _disableRecorder() {
466
+ this._onRecorderEventSink = void 0;
467
+ await this._channel.disableRecorder();
468
+ }
460
469
  async installInjectRoute() {
461
470
  if (this.routeInjecting) return;
462
471
  await this.route("**/*", async (route) => {
463
472
  try {
464
473
  if (route.request().resourceType() === "document" && route.request().url().startsWith("http")) {
465
474
  const protocol = route.request().url().split(":")[0];
466
- await route.continue({ url: protocol + "://patchright-init-script-inject.internal/" });
475
+ await route.fallback({ url: protocol + "://patchright-init-script-inject.internal/" });
467
476
  } else {
468
- await route.continue();
477
+ await route.fallback();
469
478
  }
470
479
  } catch (error) {
471
- await route.continue();
480
+ await route.fallback();
472
481
  }
473
482
  });
474
483
  }
475
484
  }
476
- async function prepareStorageState(platform, options) {
477
- if (typeof options.storageState !== "string")
478
- return options.storageState;
485
+ async function prepareStorageState(platform, storageState) {
486
+ if (typeof storageState !== "string")
487
+ return storageState;
479
488
  try {
480
- return JSON.parse(await platform.fs().promises.readFile(options.storageState, "utf8"));
489
+ return JSON.parse(await platform.fs().promises.readFile(storageState, "utf8"));
481
490
  } catch (e) {
482
- (0, import_stackTrace.rewriteErrorMessage)(e, `Error reading storage state from ${options.storageState}:
491
+ (0, import_stackTrace.rewriteErrorMessage)(e, `Error reading storage state from ${storageState}:
483
492
  ` + e.message);
484
493
  throw e;
485
494
  }
486
495
  }
487
- function prepareRecordHarOptions(options) {
488
- if (!options)
489
- return;
490
- return {
491
- path: options.path,
492
- content: options.content || (options.omitContent ? "omit" : void 0),
493
- urlGlob: (0, import_rtti.isString)(options.urlFilter) ? options.urlFilter : void 0,
494
- urlRegexSource: (0, import_rtti.isRegExp)(options.urlFilter) ? options.urlFilter.source : void 0,
495
- urlRegexFlags: (0, import_rtti.isRegExp)(options.urlFilter) ? options.urlFilter.flags : void 0,
496
- mode: options.mode
497
- };
498
- }
499
496
  async function prepareBrowserContextParams(platform, options) {
500
497
  if (options.videoSize && !options.videosPath)
501
498
  throw new Error(`"videoSize" option requires "videosPath" to be specified`);
@@ -506,9 +503,8 @@ async function prepareBrowserContextParams(platform, options) {
506
503
  viewport: options.viewport === null ? void 0 : options.viewport,
507
504
  noDefaultViewport: options.viewport === null,
508
505
  extraHTTPHeaders: options.extraHTTPHeaders ? (0, import_headers.headersObjectToArray)(options.extraHTTPHeaders) : void 0,
509
- storageState: await prepareStorageState(platform, options),
506
+ storageState: options.storageState ? await prepareStorageState(platform, options.storageState) : void 0,
510
507
  serviceWorkers: options.serviceWorkers,
511
- recordHar: prepareRecordHarOptions(options.recordHar),
512
508
  colorScheme: options.colorScheme === null ? "no-override" : options.colorScheme,
513
509
  reducedMotion: options.reducedMotion === null ? "no-override" : options.reducedMotion,
514
510
  forcedColors: options.forcedColors === null ? "no-override" : options.forcedColors,
@@ -31,6 +31,7 @@ var import_headers = require("../utils/isomorphic/headers");
31
31
  var import_time = require("../utils/isomorphic/time");
32
32
  var import_timeoutRunner = require("../utils/isomorphic/timeoutRunner");
33
33
  var import_webSocket = require("./webSocket");
34
+ var import_timeoutSettings = require("./timeoutSettings");
34
35
  class BrowserType extends import_channelOwner.ChannelOwner {
35
36
  constructor() {
36
37
  super(...arguments);
@@ -56,11 +57,12 @@ class BrowserType extends import_channelOwner.ChannelOwner {
56
57
  ...options,
57
58
  ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : void 0,
58
59
  ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
59
- env: options.env ? (0, import_clientHelper.envObjectToArray)(options.env) : void 0
60
+ env: options.env ? (0, import_clientHelper.envObjectToArray)(options.env) : void 0,
61
+ timeout: new import_timeoutSettings.TimeoutSettings(this._platform).launchTimeout(options)
60
62
  };
61
63
  return await this._wrapApiCall(async () => {
62
64
  const browser = import_browser.Browser.from((await this._channel.launch(launchOptions)).browser);
63
- this._didLaunchBrowser(browser, options, logger);
65
+ browser._connectToBrowserType(this, options, logger);
64
66
  return browser;
65
67
  });
66
68
  }
@@ -73,7 +75,11 @@ class BrowserType extends import_channelOwner.ChannelOwner {
73
75
  async launchPersistentContext(userDataDir, options = {}) {
74
76
  const logger = options.logger || this._playwright._defaultLaunchOptions?.logger;
75
77
  (0, import_assert.assert)(!options.port, "Cannot specify a port without launching as a server.");
76
- options = { ...this._playwright._defaultLaunchOptions, ...this._playwright._defaultContextOptions, ...options };
78
+ options = this._playwright.selectors._withSelectorOptions({
79
+ ...this._playwright._defaultLaunchOptions,
80
+ ...this._playwright._defaultContextOptions,
81
+ ...options
82
+ });
77
83
  const contextParams = await (0, import_browserContext.prepareBrowserContextParams)(this._platform, options);
78
84
  const persistentParams = {
79
85
  ...contextParams,
@@ -81,14 +87,19 @@ class BrowserType extends import_channelOwner.ChannelOwner {
81
87
  ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
82
88
  env: options.env ? (0, import_clientHelper.envObjectToArray)(options.env) : void 0,
83
89
  channel: options.channel,
84
- userDataDir: this._platform.path().isAbsolute(userDataDir) || !userDataDir ? userDataDir : this._platform.path().resolve(userDataDir)
90
+ userDataDir: this._platform.path().isAbsolute(userDataDir) || !userDataDir ? userDataDir : this._platform.path().resolve(userDataDir),
91
+ timeout: new import_timeoutSettings.TimeoutSettings(this._platform).launchTimeout(options)
85
92
  };
86
- return await this._wrapApiCall(async () => {
93
+ const context = await this._wrapApiCall(async () => {
87
94
  const result = await this._channel.launchPersistentContext(persistentParams);
88
- const context = import_browserContext.BrowserContext.from(result.context);
89
- await this._didCreateContext(context, contextParams, options, logger);
90
- return context;
95
+ const browser = import_browser.Browser.from(result.browser);
96
+ browser._connectToBrowserType(this, options, logger);
97
+ const context2 = import_browserContext.BrowserContext.from(result.context);
98
+ await context2._initializeHarFromOptions(options.recordHar);
99
+ return context2;
91
100
  });
101
+ await this._instrumentation.runAfterCreateBrowserContext(context);
102
+ return context;
92
103
  }
93
104
  async connect(optionsOrWsEndpoint, options) {
94
105
  if (typeof optionsOrWsEndpoint === "string")
@@ -106,7 +117,7 @@ class BrowserType extends import_channelOwner.ChannelOwner {
106
117
  headers,
107
118
  exposeNetwork: params.exposeNetwork ?? params._exposeNetwork,
108
119
  slowMo: params.slowMo,
109
- timeout: params.timeout
120
+ timeout: params.timeout || 0
110
121
  };
111
122
  if (params.__testHookRedirectPortForwarding)
112
123
  connectParams.socksProxyRedirectPortForTest = params.__testHookRedirectPortForwarding;
@@ -128,9 +139,9 @@ class BrowserType extends import_channelOwner.ChannelOwner {
128
139
  connection.close();
129
140
  throw new Error("Malformed endpoint. Did you use BrowserType.launchServer method?");
130
141
  }
131
- playwright._setSelectors(this._playwright.selectors);
142
+ playwright.selectors = this._playwright.selectors;
132
143
  browser = import_browser.Browser.from(playwright._initializer.preLaunchedBrowser);
133
- this._didLaunchBrowser(browser, {}, logger);
144
+ browser._connectToBrowserType(this, {}, logger);
134
145
  browser._shouldCloseConnectionOnClose = true;
135
146
  browser.on(import_events.Events.Browser.Disconnected, () => connection.close());
136
147
  return browser;
@@ -158,34 +169,14 @@ class BrowserType extends import_channelOwner.ChannelOwner {
158
169
  endpointURL,
159
170
  headers,
160
171
  slowMo: params.slowMo,
161
- timeout: params.timeout
172
+ timeout: new import_timeoutSettings.TimeoutSettings(this._platform).timeout(params)
162
173
  });
163
174
  const browser = import_browser.Browser.from(result.browser);
164
- this._didLaunchBrowser(browser, {}, params.logger);
175
+ browser._connectToBrowserType(this, {}, params.logger);
165
176
  if (result.defaultContext)
166
- await this._didCreateContext(import_browserContext.BrowserContext.from(result.defaultContext), {}, {}, params.logger);
177
+ await this._instrumentation.runAfterCreateBrowserContext(import_browserContext.BrowserContext.from(result.defaultContext));
167
178
  return browser;
168
179
  }
169
- _didLaunchBrowser(browser, browserOptions, logger) {
170
- browser._browserType = this;
171
- browser._options = browserOptions;
172
- browser._logger = logger;
173
- }
174
- async _didCreateContext(context, contextOptions, browserOptions, logger) {
175
- context._logger = logger;
176
- context._browserType = this;
177
- this._contexts.add(context);
178
- context._setOptions(contextOptions, browserOptions);
179
- if (this._playwright._defaultContextTimeout !== void 0)
180
- context.setDefaultTimeout(this._playwright._defaultContextTimeout);
181
- if (this._playwright._defaultContextNavigationTimeout !== void 0)
182
- context.setDefaultNavigationTimeout(this._playwright._defaultContextNavigationTimeout);
183
- await this._instrumentation.runAfterCreateBrowserContext(context);
184
- }
185
- async _willCloseContext(context) {
186
- this._contexts.delete(context);
187
- await this._instrumentation.runBeforeCloseBrowserContext(context);
188
- }
189
180
  }
190
181
  // Annotate the CommonJS export names for ESM import in node:
191
182
  0 && (module.exports = {
@@ -23,6 +23,7 @@ __export(channelOwner_exports, {
23
23
  module.exports = __toCommonJS(channelOwner_exports);
24
24
  var import_eventEmitter = require("./eventEmitter");
25
25
  var import_validator = require("../protocol/validator");
26
+ var import_protocolMetainfo = require("../utils/isomorphic/protocolMetainfo");
26
27
  var import_clientStackTrace = require("./clientStackTrace");
27
28
  var import_stackTrace = require("../utils/isomorphic/stackTrace");
28
29
  class ChannelOwner extends import_eventEmitter.EventEmitter {
@@ -31,7 +32,6 @@ class ChannelOwner extends import_eventEmitter.EventEmitter {
31
32
  super(connection._platform);
32
33
  this._objects = /* @__PURE__ */ new Map();
33
34
  this._eventToSubscriptionMapping = /* @__PURE__ */ new Map();
34
- this._isInternalType = false;
35
35
  this._wasCollected = false;
36
36
  this.setMaxListeners(0);
37
37
  this._connection = connection;
@@ -47,20 +47,14 @@ class ChannelOwner extends import_eventEmitter.EventEmitter {
47
47
  this._channel = this._createChannel(new import_eventEmitter.EventEmitter(connection._platform));
48
48
  this._initializer = initializer;
49
49
  }
50
- markAsInternalType() {
51
- this._isInternalType = true;
52
- }
53
50
  _setEventToSubscriptionMapping(mapping) {
54
51
  this._eventToSubscriptionMapping = mapping;
55
52
  }
56
53
  _updateSubscription(event, enabled) {
57
54
  const protocolEvent = this._eventToSubscriptionMapping.get(String(event));
58
- if (protocolEvent) {
59
- this._wrapApiCall(async () => {
60
- await this._channel.updateSubscription({ event: protocolEvent, enabled });
61
- }, true).catch(() => {
55
+ if (protocolEvent)
56
+ this._channel.updateSubscription({ event: protocolEvent, enabled }).catch(() => {
62
57
  });
63
- }
64
58
  }
65
59
  on(event, listener) {
66
60
  if (!this.listenerCount(event))
@@ -124,19 +118,19 @@ class ChannelOwner extends import_eventEmitter.EventEmitter {
124
118
  get: (obj, prop) => {
125
119
  if (typeof prop === "string") {
126
120
  const validator = (0, import_validator.maybeFindValidator)(this._type, prop, "Params");
121
+ const { internal } = import_protocolMetainfo.methodMetainfo.get(this._type + "." + prop) || {};
127
122
  if (validator) {
128
123
  return async (params) => {
129
124
  return await this._wrapApiCall(async (apiZone) => {
130
125
  const validatedParams = validator(params, "", this._validatorToWireContext());
131
- if (!apiZone.isInternal && !apiZone.reported) {
132
- apiZone.params = params;
126
+ if (!apiZone.internal && !apiZone.reported) {
133
127
  apiZone.reported = true;
134
- this._instrumentation.onApiCallBegin(apiZone);
128
+ this._instrumentation.onApiCallBegin(apiZone, { type: this._type, method: prop, params });
135
129
  logApiCall(this._platform, this._logger, `=> ${apiZone.apiName} started`);
136
- return await this._connection.sendMessageToServer(this, prop, validatedParams, apiZone.apiName, apiZone.frames, apiZone.stepId);
130
+ return await this._connection.sendMessageToServer(this, prop, validatedParams, apiZone);
137
131
  }
138
- return await this._connection.sendMessageToServer(this, prop, validatedParams, void 0, [], void 0);
139
- });
132
+ return await this._connection.sendMessageToServer(this, prop, validatedParams, { internal: true });
133
+ }, { internal });
140
134
  };
141
135
  }
142
136
  }
@@ -146,18 +140,16 @@ class ChannelOwner extends import_eventEmitter.EventEmitter {
146
140
  channel._object = this;
147
141
  return channel;
148
142
  }
149
- async _wrapApiCall(func, isInternal) {
143
+ async _wrapApiCall(func, options) {
150
144
  const logger = this._logger;
151
145
  const existingApiZone = this._platform.zones.current().data();
152
146
  if (existingApiZone)
153
147
  return await func(existingApiZone);
154
- if (isInternal === void 0)
155
- isInternal = this._isInternalType;
156
148
  const stackTrace = (0, import_clientStackTrace.captureLibraryStackTrace)(this._platform);
157
- const apiZone = { apiName: stackTrace.apiName, frames: stackTrace.frames, isInternal, reported: false, userData: void 0, stepId: void 0 };
149
+ const apiZone = { title: options?.title, apiName: stackTrace.apiName, frames: stackTrace.frames, internal: options?.internal ?? false, reported: false, userData: void 0, stepId: void 0 };
158
150
  try {
159
151
  const result = await this._platform.zones.current().push(apiZone).run(async () => await func(apiZone));
160
- if (!isInternal) {
152
+ if (!options?.internal) {
161
153
  logApiCall(this._platform, logger, `<= ${apiZone.apiName} succeeded`);
162
154
  this._instrumentation.onApiCallEnd(apiZone);
163
155
  }
@@ -171,17 +163,21 @@ class ChannelOwner extends import_eventEmitter.EventEmitter {
171
163
  e.stack = e.message + stackFrames;
172
164
  else
173
165
  e.stack = "";
174
- if (!isInternal) {
166
+ if (!options?.internal) {
167
+ const recoveryHandlers = [];
175
168
  apiZone.error = e;
169
+ this._instrumentation.onApiCallRecovery(apiZone, e, recoveryHandlers);
170
+ for (const handler of recoveryHandlers) {
171
+ const recoverResult = await handler();
172
+ if (recoverResult.status === "recovered")
173
+ return recoverResult.value;
174
+ }
176
175
  logApiCall(this._platform, logger, `<= ${apiZone.apiName} failed`);
177
176
  this._instrumentation.onApiCallEnd(apiZone);
178
177
  }
179
178
  throw e;
180
179
  }
181
180
  }
182
- _toImpl() {
183
- return this._connection.toImpl?.(this);
184
- }
185
181
  toJSON() {
186
182
  return {
187
183
  _type: this._type,
@@ -42,7 +42,6 @@ var import_localUtils = require("./localUtils");
42
42
  var import_network = require("./network");
43
43
  var import_page = require("./page");
44
44
  var import_playwright = require("./playwright");
45
- var import_selectors = require("./selectors");
46
45
  var import_stream = require("./stream");
47
46
  var import_tracing = require("./tracing");
48
47
  var import_worker = require("./worker");
@@ -104,7 +103,7 @@ class Connection extends import_eventEmitter.EventEmitter {
104
103
  else
105
104
  this._tracingCount--;
106
105
  }
107
- async sendMessageToServer(object, method, params, apiName, frames, stepId) {
106
+ async sendMessageToServer(object, method, params, options) {
108
107
  if (this._closedError)
109
108
  throw this._closedError;
110
109
  if (object._wasCollected)
@@ -116,13 +115,13 @@ class Connection extends import_eventEmitter.EventEmitter {
116
115
  if (this._platform.isLogEnabled("channel")) {
117
116
  this._platform.log("channel", "SEND> " + JSON.stringify(message));
118
117
  }
119
- const location = frames[0] ? { file: frames[0].file, line: frames[0].line, column: frames[0].column } : void 0;
120
- const metadata = { apiName, location, internal: !apiName, stepId };
121
- if (this._tracingCount && frames && type !== "LocalUtils")
122
- this._localUtils?.addStackToTracingNoReply({ callData: { stack: frames, id } }).catch(() => {
118
+ const location = options.frames?.[0] ? { file: options.frames[0].file, line: options.frames[0].line, column: options.frames[0].column } : void 0;
119
+ const metadata = { title: options.title, location, internal: options.internal, stepId: options.stepId };
120
+ if (this._tracingCount && options.frames && type !== "LocalUtils")
121
+ this._localUtils?.addStackToTracingNoReply({ callData: { stack: options.frames ?? [], id } }).catch(() => {
123
122
  });
124
123
  this._platform.zones.empty.run(() => this.onmessage({ ...message, metadata }));
125
- return await new Promise((resolve, reject) => this._callbacks.set(id, { resolve, reject, apiName, type, method }));
124
+ return await new Promise((resolve, reject) => this._callbacks.set(id, { resolve, reject, title: options.title, type, method }));
126
125
  }
127
126
  _validatorFromWireContext() {
128
127
  return {
@@ -277,9 +276,6 @@ class Connection extends import_eventEmitter.EventEmitter {
277
276
  case "Stream":
278
277
  result = new import_stream.Stream(parent, type, guid, initializer);
279
278
  break;
280
- case "Selectors":
281
- result = new import_selectors.SelectorsOwner(parent, type, guid, initializer);
282
- break;
283
279
  case "SocksSupport":
284
280
  result = new DummyChannelOwner(parent, type, guid, initializer);
285
281
  break;
@@ -39,13 +39,18 @@ class Electron extends import_channelOwner.ChannelOwner {
39
39
  super(parent, type, guid, initializer);
40
40
  }
41
41
  async launch(options = {}) {
42
+ options = this._playwright.selectors._withSelectorOptions(options);
42
43
  const params = {
43
44
  ...await (0, import_browserContext.prepareBrowserContextParams)(this._platform, options),
44
45
  env: (0, import_clientHelper.envObjectToArray)(options.env ? options.env : this._platform.env),
45
- tracesDir: options.tracesDir
46
+ tracesDir: options.tracesDir,
47
+ timeout: new import_timeoutSettings.TimeoutSettings(this._platform).launchTimeout(options)
46
48
  };
47
49
  const app = ElectronApplication.from((await this._channel.launch(params)).electronApplication);
48
- app._context._setOptions(params, options);
50
+ this._playwright.selectors._contextsForSelectors.add(app._context);
51
+ app.once(import_events.Events.ElectronApplication.Close, () => this._playwright.selectors._contextsForSelectors.delete(app._context));
52
+ await app._context._initializeHarFromOptions(options.recordHar);
53
+ app._context.tracing._tracesDir = options.tracesDir;
49
54
  return app;
50
55
  }
51
56
  }
@@ -70,7 +75,7 @@ class ElectronApplication extends import_channelOwner.ChannelOwner {
70
75
  return electronApplication._object;
71
76
  }
72
77
  process() {
73
- return this._toImpl().process();
78
+ return this._connection.toImpl?.(this)?.process();
74
79
  }
75
80
  _onPage(page) {
76
81
  this._windows.add(page);