patchright-core 1.57.0 → 1.58.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/ThirdPartyNotices.txt +3223 -308
  2. package/browsers.json +21 -22
  3. package/lib/cli/program.js +4 -5
  4. package/lib/client/api.js +3 -0
  5. package/lib/client/browser.js +3 -5
  6. package/lib/client/browserContext.js +40 -4
  7. package/lib/client/browserType.js +4 -3
  8. package/lib/client/connection.js +4 -0
  9. package/lib/client/elementHandle.js +3 -0
  10. package/lib/client/events.js +3 -0
  11. package/lib/client/fetch.js +3 -4
  12. package/lib/client/frame.js +10 -1
  13. package/lib/client/locator.js +8 -0
  14. package/lib/client/network.js +5 -1
  15. package/lib/client/page.js +29 -1
  16. package/lib/client/pageAgent.js +64 -0
  17. package/lib/client/platform.js +3 -0
  18. package/lib/client/tracing.js +1 -1
  19. package/lib/generated/injectedScriptSource.js +1 -1
  20. package/lib/generated/pollingRecorderSource.js +1 -1
  21. package/lib/mcpBundle.js +84 -0
  22. package/lib/mcpBundleImpl/index.js +147 -0
  23. package/lib/protocol/serializers.js +5 -0
  24. package/lib/protocol/validator.js +88 -4
  25. package/lib/remote/playwrightServer.js +1 -2
  26. package/lib/server/agent/actionRunner.js +335 -0
  27. package/lib/server/agent/actions.js +128 -0
  28. package/lib/server/agent/codegen.js +111 -0
  29. package/lib/server/agent/context.js +150 -0
  30. package/lib/server/agent/expectTools.js +156 -0
  31. package/lib/server/agent/pageAgent.js +204 -0
  32. package/lib/server/agent/performTools.js +262 -0
  33. package/lib/server/agent/tool.js +109 -0
  34. package/lib/server/artifact.js +1 -1
  35. package/lib/server/bidi/bidiBrowser.js +56 -12
  36. package/lib/server/bidi/bidiChromium.js +8 -12
  37. package/lib/server/bidi/bidiConnection.js +1 -0
  38. package/lib/server/bidi/bidiDeserializer.js +116 -0
  39. package/lib/server/bidi/bidiExecutionContext.js +75 -29
  40. package/lib/server/bidi/bidiFirefox.js +6 -8
  41. package/lib/server/bidi/bidiNetworkManager.js +1 -1
  42. package/lib/server/bidi/bidiPage.js +39 -28
  43. package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
  44. package/lib/server/browserContext.js +34 -26
  45. package/lib/server/browserType.js +12 -4
  46. package/lib/server/chromium/chromium.js +14 -20
  47. package/lib/server/chromium/chromiumSwitches.js +2 -2
  48. package/lib/server/chromium/crBrowser.js +22 -12
  49. package/lib/server/chromium/crConnection.js +0 -5
  50. package/lib/server/chromium/crCoverage.js +13 -1
  51. package/lib/server/chromium/crDevTools.js +0 -2
  52. package/lib/server/chromium/crNetworkManager.js +92 -12
  53. package/lib/server/chromium/crPage.js +62 -116
  54. package/lib/server/codegen/javascript.js +6 -29
  55. package/lib/server/deviceDescriptorsSource.json +56 -56
  56. package/lib/server/dispatchers/browserContextDispatcher.js +3 -2
  57. package/lib/server/dispatchers/dispatcher.js +6 -13
  58. package/lib/server/dispatchers/frameDispatcher.js +1 -1
  59. package/lib/server/dispatchers/jsHandleDispatcher.js +2 -2
  60. package/lib/server/dispatchers/pageAgentDispatcher.js +96 -0
  61. package/lib/server/dispatchers/pageDispatcher.js +4 -0
  62. package/lib/server/dom.js +12 -3
  63. package/lib/server/electron/electron.js +5 -2
  64. package/lib/server/firefox/ffBrowser.js +10 -20
  65. package/lib/server/firefox/ffConnection.js +0 -5
  66. package/lib/server/firefox/ffNetworkManager.js +2 -2
  67. package/lib/server/firefox/ffPage.js +15 -18
  68. package/lib/server/firefox/firefox.js +6 -8
  69. package/lib/server/frameSelectors.js +16 -4
  70. package/lib/server/frames.js +251 -86
  71. package/lib/server/instrumentation.js +3 -0
  72. package/lib/server/javascript.js +8 -4
  73. package/lib/server/launchApp.js +2 -1
  74. package/lib/server/network.js +50 -12
  75. package/lib/server/page.js +61 -91
  76. package/lib/server/progress.js +26 -6
  77. package/lib/server/recorder/recorderApp.js +79 -100
  78. package/lib/server/registry/browserFetcher.js +6 -4
  79. package/lib/server/registry/index.js +172 -149
  80. package/lib/server/registry/oopDownloadBrowserMain.js +3 -0
  81. package/lib/server/screencast.js +190 -0
  82. package/lib/server/screenshotter.js +6 -0
  83. package/lib/server/trace/recorder/snapshotter.js +17 -8
  84. package/lib/server/trace/recorder/snapshotterInjected.js +30 -72
  85. package/lib/server/trace/recorder/tracing.js +29 -21
  86. package/lib/server/trace/viewer/traceParser.js +72 -0
  87. package/lib/server/trace/viewer/traceViewer.js +21 -17
  88. package/lib/server/utils/expectUtils.js +87 -2
  89. package/lib/server/utils/hostPlatform.js +15 -0
  90. package/lib/server/utils/httpServer.js +5 -20
  91. package/lib/server/utils/network.js +37 -28
  92. package/lib/server/utils/nodePlatform.js +6 -0
  93. package/lib/server/{chromium/videoRecorder.js → videoRecorder.js} +22 -13
  94. package/lib/server/webkit/webkit.js +4 -6
  95. package/lib/server/webkit/wkBrowser.js +2 -6
  96. package/lib/server/webkit/wkConnection.js +1 -6
  97. package/lib/server/webkit/wkInterceptableRequest.js +29 -1
  98. package/lib/server/webkit/wkPage.js +75 -46
  99. package/lib/utils/isomorphic/ariaSnapshot.js +60 -2
  100. package/lib/utils/isomorphic/lruCache.js +51 -0
  101. package/lib/utils/isomorphic/protocolMetainfo.js +9 -1
  102. package/lib/utils/isomorphic/stringUtils.js +49 -0
  103. package/lib/utils/isomorphic/trace/entries.js +16 -0
  104. package/lib/utils/isomorphic/trace/snapshotRenderer.js +499 -0
  105. package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
  106. package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
  107. package/lib/utils/isomorphic/trace/traceLoader.js +131 -0
  108. package/lib/utils/isomorphic/trace/traceModel.js +365 -0
  109. package/lib/utils/isomorphic/trace/traceModernizer.js +400 -0
  110. package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
  111. package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
  112. package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
  113. package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
  114. package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
  115. package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
  116. package/lib/utils/isomorphic/yaml.js +84 -0
  117. package/lib/utils.js +2 -0
  118. package/lib/utilsBundle.js +2 -5
  119. package/lib/utilsBundleImpl/index.js +165 -165
  120. package/lib/vite/htmlReport/index.html +21 -21
  121. package/lib/vite/recorder/assets/codeMirrorModule-CFUTFUO7.js +32 -0
  122. package/lib/vite/{traceViewer/codeMirrorModule.C3UTv-Ge.css → recorder/assets/codeMirrorModule-DYBRYzYX.css} +1 -1
  123. package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
  124. package/lib/vite/recorder/assets/index-CVkBxsGf.js +193 -0
  125. package/lib/vite/recorder/index.html +2 -2
  126. package/lib/vite/traceViewer/assets/codeMirrorModule-BVA4h_ZY.js +32 -0
  127. package/lib/vite/traceViewer/assets/defaultSettingsView-CjfmcdOz.js +266 -0
  128. package/lib/vite/{recorder/assets/codeMirrorModule-C3UTv-Ge.css → traceViewer/codeMirrorModule.DYBRYzYX.css} +1 -1
  129. package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +1 -0
  130. package/lib/vite/traceViewer/index.BVu7tZDe.css +1 -0
  131. package/lib/vite/traceViewer/index.BtyWtaE-.js +2 -0
  132. package/lib/vite/traceViewer/index.html +4 -4
  133. package/lib/vite/traceViewer/sw.bundle.js +5 -3
  134. package/lib/vite/traceViewer/uiMode.fyrXARf2.js +5 -0
  135. package/lib/vite/traceViewer/uiMode.html +3 -3
  136. package/package.json +2 -1
  137. package/types/protocol.d.ts +738 -159
  138. package/types/types.d.ts +25 -38
  139. package/lib/server/bidi/third_party/bidiDeserializer.js +0 -98
  140. package/lib/server/trace/test/inMemorySnapshotter.js +0 -87
  141. package/lib/vite/recorder/assets/codeMirrorModule-CBbSe-ZI.js +0 -25
  142. package/lib/vite/recorder/assets/index-CpZVd2nA.js +0 -193
  143. package/lib/vite/traceViewer/assets/codeMirrorModule-DHz0wP2C.js +0 -25
  144. package/lib/vite/traceViewer/assets/defaultSettingsView-WsZP88O6.js +0 -266
  145. package/lib/vite/traceViewer/defaultSettingsView.ConWv5KN.css +0 -1
  146. package/lib/vite/traceViewer/index.C4Y3Aw8n.css +0 -1
  147. package/lib/vite/traceViewer/index.C8xAeo93.js +0 -2
  148. package/lib/vite/traceViewer/uiMode.BltraIJB.js +0 -5
@@ -32,9 +32,7 @@ __export(crPage_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(crPage_exports);
34
34
  var import_crypto = __toESM(require("crypto"));
35
- var import_path = __toESM(require("path"));
36
35
  var import_assert = require("../../utils/isomorphic/assert");
37
- var import_crypto2 = require("../utils/crypto");
38
36
  var import_eventsHelper = require("../utils/eventsHelper");
39
37
  var import_stackTrace = require("../../utils/isomorphic/stackTrace");
40
38
  var dialog = __toESM(require("../dialog"));
@@ -43,7 +41,6 @@ var frames = __toESM(require("../frames"));
43
41
  var import_helper = require("../helper");
44
42
  var network = __toESM(require("../network"));
45
43
  var import_page = require("../page");
46
- var import_registry = require("../registry");
47
44
  var import_crCoverage = require("./crCoverage");
48
45
  var import_crDragDrop = require("./crDragDrop");
49
46
  var import_crExecutionContext = require("./crExecutionContext");
@@ -52,7 +49,6 @@ var import_crNetworkManager = require("./crNetworkManager");
52
49
  var import_crPdf = require("./crPdf");
53
50
  var import_crProtocolHelper = require("./crProtocolHelper");
54
51
  var import_defaultFontFamilies = require("./defaultFontFamilies");
55
- var import_videoRecorder = require("./videoRecorder");
56
52
  var import_errors = require("../errors");
57
53
  var import_protocolError = require("../protocolError");
58
54
  class CRPage {
@@ -114,7 +110,7 @@ class CRPage {
114
110
  while (!this._sessions.has(frame._id)) {
115
111
  const parent = frame.parentFrame();
116
112
  if (!parent)
117
- throw new Error(`Frame has been detached.`);
113
+ throw new Error(`Frame was detached`);
118
114
  frame = parent;
119
115
  }
120
116
  return this._sessions.get(frame._id);
@@ -239,17 +235,16 @@ class CRPage {
239
235
  async scrollRectIntoViewIfNeeded(handle, rect) {
240
236
  return this._sessionForHandle(handle)._scrollRectIntoViewIfNeeded(handle, rect);
241
237
  }
242
- async setScreencastOptions(options) {
243
- if (options) {
244
- await this._mainFrameSession._startScreencast(this, {
245
- format: "jpeg",
246
- quality: options.quality,
247
- maxWidth: options.width,
248
- maxHeight: options.height
249
- });
250
- } else {
251
- await this._mainFrameSession._stopScreencast(this);
252
- }
238
+ async startScreencast(options) {
239
+ await this._mainFrameSession._client.send("Page.startScreencast", {
240
+ format: "jpeg",
241
+ quality: options.quality,
242
+ maxWidth: options.width,
243
+ maxHeight: options.height
244
+ });
245
+ }
246
+ async stopScreencast() {
247
+ await this._mainFrameSession._client._sendMayFail("Page.stopScreencast");
253
248
  }
254
249
  rafCountForStablePosition() {
255
250
  return 1;
@@ -322,9 +317,6 @@ class FrameSession {
322
317
  // Marks the oopif session that remote -> local transition has happened in the parent.
323
318
  // See Target.detachedFromTarget handler for details.
324
319
  this._swappedIn = false;
325
- this._videoRecorder = null;
326
- this._screencastId = null;
327
- this._screencastClients = /* @__PURE__ */ new Set();
328
320
  this._workerSessions = /* @__PURE__ */ new Map();
329
321
  this._initScriptIds = /* @__PURE__ */ new Map();
330
322
  this._exposedBindingNames = [];
@@ -376,38 +368,32 @@ class FrameSession {
376
368
  ]);
377
369
  }
378
370
  async _initialize(hasUIWindow) {
371
+ const pageEnablePromise = this._client.send("Page.enable");
379
372
  if (!this._page.isStorageStatePage && hasUIWindow && !this._crPage._browserContext._browser.isClank() && !this._crPage._browserContext._options.noDefaultViewport) {
380
373
  const { windowId } = await this._client.send("Browser.getWindowForTarget");
381
374
  this._windowId = windowId;
382
375
  }
383
- let screencastOptions;
384
- if (!this._page.isStorageStatePage && this._isMainFrame() && this._crPage._browserContext._options.recordVideo && hasUIWindow) {
385
- const screencastId = (0, import_crypto2.createGuid)();
386
- const outputFile = import_path.default.join(this._crPage._browserContext._options.recordVideo.dir, screencastId + ".webm");
387
- screencastOptions = {
388
- // validateBrowserContextOptions ensures correct video size.
389
- ...this._crPage._browserContext._options.recordVideo.size,
390
- outputFile
391
- };
392
- await this._crPage._browserContext._ensureVideosPath();
393
- await this._createVideoRecorder(screencastId, screencastOptions);
394
- this._crPage._page.waitForInitializedOrError().then((p) => {
395
- if (p instanceof Error)
396
- this._stopVideoRecording().catch(() => {
397
- });
398
- });
399
- }
376
+ let videoOptions;
377
+ if (!this._page.isStorageStatePage && this._isMainFrame() && hasUIWindow)
378
+ videoOptions = this._crPage._page.screencast.launchVideoRecorder();
400
379
  let lifecycleEventsEnabled;
401
380
  if (!this._isMainFrame())
402
381
  this._addRendererListeners();
382
+ let bufferedDialogEvents = this._isMainFrame() ? [] : void 0;
383
+ if (bufferedDialogEvents)
384
+ this._eventListeners.push(import_eventsHelper.eventsHelper.addEventListener(this._client, "Page.javascriptDialogOpening", (event) => bufferedDialogEvents ? bufferedDialogEvents.push(event) : void 0));
403
385
  this._addBrowserListeners();
404
386
  this._bufferedAttachedToTargetEvents = [];
405
387
  const promises = [
406
- this._client.send("Page.enable"),
388
+ pageEnablePromise,
407
389
  this._client.send("Page.getFrameTree").then(({ frameTree }) => {
408
390
  if (this._isMainFrame()) {
409
391
  this._handleFrameTree(frameTree);
410
392
  this._addRendererListeners();
393
+ const pendingDialogEvents = bufferedDialogEvents || [];
394
+ bufferedDialogEvents = void 0;
395
+ for (const event of pendingDialogEvents)
396
+ this._onDialog(event);
411
397
  }
412
398
  const attachedToTargetEvents = this._bufferedAttachedToTargetEvents || [];
413
399
  this._bufferedAttachedToTargetEvents = void 0;
@@ -422,12 +408,16 @@ class FrameSession {
422
408
  } else {
423
409
  const localFrames = this._isMainFrame() ? this._page.frames() : [this._page.frameManager.frame(this._targetId)];
424
410
  for (const frame of localFrames) {
425
- this._page.frameManager.frame(frame._id)._context("utility");
411
+ this._page.frameManager.frame(frame._id)._context("utility").catch(() => {
412
+ });
426
413
  for (const binding of this._crPage._browserContext._pageBindings.values())
427
414
  frame.evaluateExpression(binding.source).catch((e) => {
428
415
  });
429
416
  for (const source of this._crPage._browserContext.initScripts)
430
- frame.evaluateExpression(source).catch((e) => {
417
+ frame.evaluateExpression(source.source).catch((e) => {
418
+ });
419
+ for (const source of this._crPage._page.initScripts)
420
+ frame.evaluateExpression(source.source).catch((e) => {
431
421
  });
432
422
  }
433
423
  this._firstNonInitialNavigationCommittedFulfill();
@@ -446,6 +436,8 @@ class FrameSession {
446
436
  if (!this._page.isStorageStatePage) {
447
437
  if (this._crPage._browserContext.needsPlaywrightBinding())
448
438
  promises.push(this.exposePlaywrightBinding());
439
+ if (this._isMainFrame() && !this._crPage._browserContext._options.focusControl)
440
+ promises.push(this._client.send("Emulation.setFocusEmulationEnabled", { enabled: true }));
449
441
  const options = this._crPage._browserContext._options;
450
442
  if (options.bypassCSP)
451
443
  promises.push(this._client.send("Page.setBypassCSP", { enabled: true }));
@@ -471,18 +463,15 @@ class FrameSession {
471
463
  for (const binding of this._crPage._page.allBindings()) promises.push(this._initBinding(binding));
472
464
  for (const initScript of this._crPage._browserContext.initScripts) promises.push(this._evaluateOnNewDocument(initScript, "main"));
473
465
  for (const initScript of this._crPage._page.initScripts) promises.push(this._evaluateOnNewDocument(initScript, "main"));
474
- if (screencastOptions)
475
- promises.push(this._startVideoRecording(screencastOptions));
466
+ if (videoOptions)
467
+ promises.push(this._crPage._page.screencast.startVideoRecording(videoOptions));
476
468
  }
477
- if (!(this._crPage._page._pageBindings.size || this._crPage._browserContext._pageBindings.size))
478
- promises.push(this._client.send("Runtime.runIfWaitingForDebugger"));
469
+ promises.push(this._client.send("Runtime.runIfWaitingForDebugger"));
479
470
  promises.push(this._firstNonInitialNavigationCommittedPromise);
480
471
  await Promise.all(promises);
481
- if (this._crPage._page._pageBindings.size || this._crPage._browserContext._pageBindings.size)
482
- await this._client.send("Runtime.runIfWaitingForDebugger");
483
472
  }
484
473
  dispose() {
485
- this._firstNonInitialNavigationCommittedReject(new import_errors.TargetClosedError());
474
+ this._firstNonInitialNavigationCommittedReject(new import_errors.TargetClosedError(this._page.closeReason()));
486
475
  for (const childSession of this._childSessions)
487
476
  childSession.dispose();
488
477
  if (this._parentSession)
@@ -507,6 +496,10 @@ class FrameSession {
507
496
  this._page.frameManager.frameLifecycleEvent(event.frameId, "load");
508
497
  else if (event.name === "DOMContentLoaded")
509
498
  this._page.frameManager.frameLifecycleEvent(event.frameId, "domcontentloaded");
499
+ if (event.name !== "load") {
500
+ await this._client._sendMayFail("Runtime.runIfWaitingForDebugger");
501
+ return;
502
+ }
510
503
  await this._client._sendMayFail("Runtime.runIfWaitingForDebugger");
511
504
  var document = await this._client._sendMayFail("DOM.getDocument");
512
505
  if (!document) return;
@@ -559,6 +552,14 @@ class FrameSession {
559
552
  if (!initial)
560
553
  this._firstNonInitialNavigationCommittedFulfill();
561
554
  await this._client._sendMayFail("Runtime.runIfWaitingForDebugger");
555
+ if (!initial) {
556
+ try {
557
+ await this._page.frameManager.frame(this._targetId)._context("utility");
558
+ } catch {
559
+ }
560
+ ;
561
+ return;
562
+ }
562
563
  var document = await this._client._sendMayFail("DOM.getDocument");
563
564
  if (!document) return;
564
565
  var query = await this._client._sendMayFail("DOM.querySelectorAll", {
@@ -607,7 +608,7 @@ class FrameSession {
607
608
  const delegate = new import_crExecutionContext.CRExecutionContext(this._client, contextPayload);
608
609
  let worldName = contextPayload.name;
609
610
  const context = new dom.FrameExecutionContext(delegate, frame, worldName);
610
- if (worldName)
611
+ if (worldName && (worldName === "main" || worldName === "utility"))
611
612
  frame._contextCreated(worldName, context);
612
613
  this._contextIdToContext.set(contextPayload.id, context);
613
614
  for (const source of this._exposedBindingScripts) {
@@ -787,63 +788,17 @@ class FrameSession {
787
788
  }
788
789
  }
789
790
  _onScreencastFrame(payload) {
790
- this._page.throttleScreencastFrameAck(() => {
791
- this._client.send("Page.screencastFrameAck", { sessionId: payload.sessionId }).catch(() => {
792
- });
791
+ this._page.screencast.throttleFrameAck(() => {
792
+ this._client._sendMayFail("Page.screencastFrameAck", { sessionId: payload.sessionId });
793
793
  });
794
794
  const buffer = Buffer.from(payload.data, "base64");
795
795
  this._page.emit(import_page.Page.Events.ScreencastFrame, {
796
796
  buffer,
797
- frameSwapWallTime: payload.metadata.timestamp ? payload.metadata.timestamp * 1e3 : void 0,
797
+ frameSwapWallTime: payload.metadata.timestamp ? payload.metadata.timestamp * 1e3 : Date.now(),
798
798
  width: payload.metadata.deviceWidth,
799
799
  height: payload.metadata.deviceHeight
800
800
  });
801
801
  }
802
- async _createVideoRecorder(screencastId, options) {
803
- (0, import_assert.assert)(!this._screencastId);
804
- const ffmpegPath = import_registry.registry.findExecutable("ffmpeg").executablePathOrDie(this._page.browserContext._browser.sdkLanguage());
805
- this._videoRecorder = await import_videoRecorder.VideoRecorder.launch(this._crPage._page, ffmpegPath, options);
806
- this._screencastId = screencastId;
807
- }
808
- async _startVideoRecording(options) {
809
- const screencastId = this._screencastId;
810
- (0, import_assert.assert)(screencastId);
811
- this._page.once(import_page.Page.Events.Close, () => this._stopVideoRecording().catch(() => {
812
- }));
813
- const gotFirstFrame = new Promise((f) => this._client.once("Page.screencastFrame", f));
814
- await this._startScreencast(this._videoRecorder, {
815
- format: "jpeg",
816
- quality: 90,
817
- maxWidth: options.width,
818
- maxHeight: options.height
819
- });
820
- gotFirstFrame.then(() => {
821
- this._crPage._browserContext._browser._videoStarted(this._crPage._browserContext, screencastId, options.outputFile, this._crPage._page.waitForInitializedOrError());
822
- });
823
- }
824
- async _stopVideoRecording() {
825
- if (!this._screencastId)
826
- return;
827
- const screencastId = this._screencastId;
828
- this._screencastId = null;
829
- const recorder = this._videoRecorder;
830
- this._videoRecorder = null;
831
- await this._stopScreencast(recorder);
832
- await recorder.stop().catch(() => {
833
- });
834
- const video = this._crPage._browserContext._browser._takeVideo(screencastId);
835
- video?.reportFinished();
836
- }
837
- async _startScreencast(client, options = {}) {
838
- this._screencastClients.add(client);
839
- if (this._screencastClients.size === 1)
840
- await this._client.send("Page.startScreencast", options);
841
- }
842
- async _stopScreencast(client) {
843
- this._screencastClients.delete(client);
844
- if (!this._screencastClients.size)
845
- await this._client._sendMayFail("Page.stopScreencast");
846
- }
847
802
  async _updateGeolocation(initial) {
848
803
  const geolocation = this._crPage._browserContext._options.geolocation;
849
804
  if (!initial || geolocation)
@@ -1047,29 +1002,20 @@ class FrameSession {
1047
1002
  return (0, import_crExecutionContext.createHandle)(to, result.object).asElement();
1048
1003
  }
1049
1004
  async _initBinding(binding = import_page.PageBinding) {
1050
- var result = await this._client._sendMayFail("Page.createIsolatedWorld", {
1051
- frameId: this._targetId,
1052
- grantUniveralAccess: true,
1053
- worldName: "utility"
1054
- });
1055
- if (!result) return;
1056
- var isolatedContextId = result.executionContextId;
1057
- var globalThis = await this._client._sendMayFail("Runtime.evaluate", {
1058
- expression: "globalThis",
1059
- serializationOptions: { serialization: "idOnly" }
1060
- });
1061
- if (!globalThis) return;
1062
- var globalThisObjId = globalThis["result"]["objectId"];
1063
- var mainContextId = parseInt(globalThisObjId.split(".")[1], 10);
1005
+ this._exposedBindingNames.push(binding.name);
1006
+ this._exposedBindingScripts.push(binding.source);
1007
+ const contextIds = Array.from(this._contextIdToContext.keys());
1064
1008
  await Promise.all([
1065
1009
  this._client._sendMayFail("Runtime.addBinding", { name: binding.name }),
1066
- this._client._sendMayFail("Runtime.addBinding", { name: binding.name, executionContextId: mainContextId }),
1067
- this._client._sendMayFail("Runtime.addBinding", { name: binding.name, executionContextId: isolatedContextId })
1068
- // this._client._sendMayFail("Runtime.evaluate", { expression: binding.source, contextId: mainContextId, awaitPromise: true })
1010
+ ...contextIds.map((executionContextId) => this._client._sendMayFail("Runtime.addBinding", { name: binding.name, executionContextId }))
1069
1011
  ]);
1070
- this._exposedBindingNames.push(binding.name);
1071
- this._exposedBindingScripts.push(binding.source);
1072
- await this._crPage.addInitScript(binding.source);
1012
+ for (const contextId of contextIds) {
1013
+ this._client._sendMayFail("Runtime.evaluate", {
1014
+ expression: binding.source,
1015
+ contextId,
1016
+ awaitPromise: true
1017
+ });
1018
+ }
1073
1019
  }
1074
1020
  async _removeExposedBindings() {
1075
1021
  const toRetain = [];
@@ -90,7 +90,7 @@ class JavaScriptLanguageGenerator {
90
90
  case "fill":
91
91
  return `await ${subject}.${this._asLocator(action.selector)}.fill(${quote(action.text)});`;
92
92
  case "setInputFiles":
93
- return `await ${subject}.${this._asLocator(action.selector)}.setInputFiles(${formatObject(action.files.length === 1 ? action.files[0] : action.files)});`;
93
+ return `await ${subject}.${this._asLocator(action.selector)}.setInputFiles(${(0, import_utils.formatObject)(action.files.length === 1 ? action.files[0] : action.files)});`;
94
94
  case "press": {
95
95
  const modifiers = (0, import_language.toKeyboardModifiers)(action.modifiers);
96
96
  const shortcut = [...modifiers, action.key].join("+");
@@ -99,7 +99,7 @@ class JavaScriptLanguageGenerator {
99
99
  case "navigate":
100
100
  return `await ${subject}.goto(${quote(action.url)});`;
101
101
  case "select":
102
- return `await ${subject}.${this._asLocator(action.selector)}.selectOption(${formatObject(action.options.length === 1 ? action.options[0] : action.options)});`;
102
+ return `await ${subject}.${this._asLocator(action.selector)}.selectOption(${(0, import_utils.formatObject)(action.options.length === 1 ? action.options[0] : action.options)});`;
103
103
  case "assertText":
104
104
  return `${this._isTest ? "" : "// "}await expect(${subject}.${this._asLocator(action.selector)}).${action.substring ? "toContainText" : "toHaveText"}(${quote(action.text)});`;
105
105
  case "assertChecked":
@@ -151,7 +151,7 @@ ${useText ? "\ntest.use(" + useText + ");\n" : ""}
151
151
  const { ${options.browserName}${options.deviceName ? ", devices" : ""} } = require('playwright');
152
152
 
153
153
  (async () => {
154
- const browser = await ${options.browserName}.launch(${formatObjectOrVoid(options.launchOptions)});
154
+ const browser = await ${options.browserName}.launch(${(0, import_utils.formatObjectOrVoid)(options.launchOptions)});
155
155
  const context = await browser.newContext(${formatContextOptions(options.contextOptions, options.deviceName, false)});`);
156
156
  if (options.contextOptions.recordHar)
157
157
  formatter.add(` await context.routeFromHAR(${quote(options.contextOptions.recordHar.path)});`);
@@ -171,37 +171,14 @@ function formatOptions(value, hasArguments) {
171
171
  const keys = Object.keys(value).filter((key) => value[key] !== void 0);
172
172
  if (!keys.length)
173
173
  return "";
174
- return (hasArguments ? ", " : "") + formatObject(value);
175
- }
176
- function formatObject(value, indent = " ") {
177
- if (typeof value === "string")
178
- return quote(value);
179
- if (Array.isArray(value))
180
- return `[${value.map((o) => formatObject(o)).join(", ")}]`;
181
- if (typeof value === "object") {
182
- const keys = Object.keys(value).filter((key) => value[key] !== void 0).sort();
183
- if (!keys.length)
184
- return "{}";
185
- const tokens = [];
186
- for (const key of keys)
187
- tokens.push(`${key}: ${formatObject(value[key])}`);
188
- return `{
189
- ${indent}${tokens.join(`,
190
- ${indent}`)}
191
- }`;
192
- }
193
- return String(value);
194
- }
195
- function formatObjectOrVoid(value, indent = " ") {
196
- const result = formatObject(value, indent);
197
- return result === "{}" ? "" : result;
174
+ return (hasArguments ? ", " : "") + (0, import_utils.formatObject)(value);
198
175
  }
199
176
  function formatContextOptions(options, deviceName, isTest) {
200
177
  const device = deviceName && import_deviceDescriptors.deviceDescriptors[deviceName];
201
178
  options = { ...options, recordHar: void 0 };
202
179
  if (!device)
203
- return formatObjectOrVoid(options);
204
- let serializedObject = formatObjectOrVoid((0, import_language.sanitizeDeviceOptions)(device, options));
180
+ return (0, import_utils.formatObjectOrVoid)(options);
181
+ let serializedObject = (0, import_utils.formatObjectOrVoid)((0, import_language.sanitizeDeviceOptions)(device, options));
205
182
  if (!serializedObject)
206
183
  serializedObject = "{\n}";
207
184
  const lines = serializedObject.split("\n");