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
@@ -177,6 +177,9 @@ class FrameManager {
177
177
  } else {
178
178
  frame._currentDocument = { documentId, request: void 0 };
179
179
  }
180
+ frame._iframeWorld = void 0;
181
+ frame._mainWorld = void 0;
182
+ frame._isolatedWorld = void 0;
180
183
  frame._onClearLifecycle();
181
184
  const navigationEvent = { url, name, newDocument: frame._currentDocument, isPublic: true };
182
185
  this._fireInternalFrameNavigation(frame, navigationEvent);
@@ -352,6 +355,11 @@ class FrameManager {
352
355
  frame.emit(Frame.Events.InternalNavigation, event);
353
356
  }
354
357
  }
358
+ const FrameEvent = {
359
+ InternalNavigation: "internalnavigation",
360
+ AddLifecycle: "addlifecycle",
361
+ RemoveLifecycle: "removelifecycle"
362
+ };
355
363
  class Frame extends import_instrumentation.SdkObject {
356
364
  constructor(page, id, parentFrame) {
357
365
  super(page, "frame");
@@ -384,11 +392,7 @@ class Frame extends import_instrumentation.SdkObject {
384
392
  this._startNetworkIdleTimer();
385
393
  }
386
394
  static {
387
- this.Events = {
388
- InternalNavigation: "internalnavigation",
389
- AddLifecycle: "addlifecycle",
390
- RemoveLifecycle: "removelifecycle"
391
- };
395
+ this.Events = FrameEvent;
392
396
  }
393
397
  isDetached() {
394
398
  return this._detachedScope.isClosed();
@@ -403,9 +407,6 @@ class Frame extends import_instrumentation.SdkObject {
403
407
  this._page.mainFrame()._recalculateNetworkIdle();
404
408
  }
405
409
  _onClearLifecycle() {
406
- this._isolatedWorld = void 0;
407
- this._mainWorld = void 0;
408
- this._iframeWorld = void 0;
409
410
  for (const event of this._firedLifecycleEvents)
410
411
  this.emit(Frame.Events.RemoveLifecycle, event);
411
412
  this._firedLifecycleEvents.clear();
@@ -456,7 +457,11 @@ class Frame extends import_instrumentation.SdkObject {
456
457
  });
457
458
  }
458
459
  nonStallingEvaluateInExistingContext(expression, world) {
459
- return this.raceAgainstEvaluationStallingEvents(() => {
460
+ return this.raceAgainstEvaluationStallingEvents(async () => {
461
+ try {
462
+ await this._context(world);
463
+ } catch {
464
+ }
460
465
  const context = this._contextData.get(world)?.context;
461
466
  if (!context)
462
467
  throw new Error("Frame does not yet have the execution context");
@@ -574,7 +579,7 @@ class Frame extends import_instrumentation.SdkObject {
574
579
  const request = navigationEvent.newDocument ? navigationEvent.newDocument.request : void 0;
575
580
  return request ? progress.race(request._finalRequest().response()) : null;
576
581
  }
577
- async _waitForLoadState(progress, state) {
582
+ async waitForLoadState(progress, state) {
578
583
  const waitUntil = verifyLifecycle("state", state);
579
584
  if (!this._firedLifecycleEvents.has(waitUntil))
580
585
  await import_helper.helper.waitForEvent(progress, this, Frame.Events.AddLifecycle, (e) => e === waitUntil).promise;
@@ -595,7 +600,7 @@ class Frame extends import_instrumentation.SdkObject {
595
600
  var executionContextId = iframeExecutionContextId;
596
601
  var crContext = new import_crExecutionContext.CRExecutionContext(client, { id: executionContextId }, this._id);
597
602
  this._iframeWorld = new import_dom.FrameExecutionContext(crContext, this, world);
598
- this._page.delegate._mainFrameSession._onExecutionContextCreated({
603
+ this._page.delegate._sessionForFrame(this)._onExecutionContextCreated({
599
604
  id: executionContextId,
600
605
  origin: world,
601
606
  name: world,
@@ -607,13 +612,14 @@ class Frame extends import_instrumentation.SdkObject {
607
612
  serializationOptions: { serialization: "idOnly" }
608
613
  });
609
614
  if (!globalThis2) {
615
+ if (this.isDetached()) throw new Error("Frame was detached");
610
616
  return;
611
617
  }
612
618
  var globalThisObjId = globalThis2["result"]["objectId"];
613
619
  var executionContextId = parseInt(globalThisObjId.split(".")[1], 10);
614
620
  var crContext = new import_crExecutionContext.CRExecutionContext(client, { id: executionContextId }, this._id);
615
621
  this._mainWorld = new import_dom.FrameExecutionContext(crContext, this, world);
616
- this._page.delegate._mainFrameSession._onExecutionContextCreated({
622
+ this._page.delegate._sessionForFrame(this)._onExecutionContextCreated({
617
623
  id: executionContextId,
618
624
  origin: world,
619
625
  name: world,
@@ -629,12 +635,13 @@ class Frame extends import_instrumentation.SdkObject {
629
635
  worldName: world
630
636
  });
631
637
  if (!result) {
638
+ if (this.isDetached()) throw new Error("Frame was detached");
632
639
  return;
633
640
  }
634
641
  var executionContextId = result.executionContextId;
635
642
  var crContext = new import_crExecutionContext.CRExecutionContext(client, { id: executionContextId }, this._id);
636
643
  this._isolatedWorld = new import_dom.FrameExecutionContext(crContext, this, world);
637
- this._page.delegate._mainFrameSession._onExecutionContextCreated({
644
+ this._page.delegate._sessionForFrame(this)._onExecutionContextCreated({
638
645
  id: executionContextId,
639
646
  origin: world,
640
647
  name: world,
@@ -643,7 +650,7 @@ class Frame extends import_instrumentation.SdkObject {
643
650
  }
644
651
  if (world != "main") {
645
652
  return this._isolatedWorld;
646
- } else if (this != this._page.mainFrame() && iframeExecutionContextId) {
653
+ } else if (this != this._page.mainFrame() && this._iframeWorld) {
647
654
  return this._iframeWorld;
648
655
  } else {
649
656
  return this._mainWorld;
@@ -659,13 +666,13 @@ class Frame extends import_instrumentation.SdkObject {
659
666
  return this._context("utility");
660
667
  }
661
668
  async evaluateExpression(expression, options = {}, arg) {
662
- const context = await this._context(options.world ?? "main");
663
- const value = await context.evaluateExpression(expression, options, arg);
669
+ const context = await this._detachedScope.race(this._context(options.world ?? "main"));
670
+ const value = await this._detachedScope.race(context.evaluateExpression(expression, options, arg));
664
671
  return value;
665
672
  }
666
673
  async evaluateExpressionHandle(expression, options = {}, arg) {
667
- const context = await this._context(options.world ?? "utility");
668
- const value = await context.evaluateExpressionHandle(expression, options, arg);
674
+ const context = await this._detachedScope.race(this._context(options.world ?? "utility"));
675
+ const value = await this._detachedScope.race(context.evaluateExpressionHandle(expression, options, arg));
669
676
  return value;
670
677
  }
671
678
  async querySelector(selector, options) {
@@ -687,7 +694,15 @@ class Frame extends import_instrumentation.SdkObject {
687
694
  throw new Error(`state: expected one of (attached|detached|visible|hidden)`);
688
695
  if (performActionPreChecksAndLog)
689
696
  progress.log(`waiting for ${this._asLocator(selector)}${state === "attached" ? "" : " to be " + state}`);
690
- const promise = this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, async (handle) => {
697
+ const promise = this._retryWithProgressIfNotConnected(progress, selector, { ...options, performActionPreChecks: true, __patchrightWaitForSelector: true, __patchrightInitialScope: scope }, async (handle) => {
698
+ if (scope) {
699
+ const scopeIsConnected = await scope.evaluateInUtility(([injected, node]) => node.isConnected, {}).catch(() => false);
700
+ if (scopeIsConnected !== true) {
701
+ if (state === "hidden" || state === "detached")
702
+ return null;
703
+ throw new dom.NonRecoverableDOMError("Element is not attached to the DOM");
704
+ }
705
+ }
691
706
  const attached = !!handle;
692
707
  var visible = false;
693
708
  if (attached) {
@@ -718,17 +733,55 @@ class Frame extends import_instrumentation.SdkObject {
718
733
  return "internal:continuepolling";
719
734
  }
720
735
  }, "returnOnNotResolved");
721
- return scope ? scope._context._raceAgainstContextDestroyed(promise) : promise;
736
+ const resultPromise = scope ? scope._context._raceAgainstContextDestroyed(promise) : promise;
737
+ return resultPromise.catch((e) => {
738
+ if (this.isDetached() && e?.message?.includes("Execution context was destroyed"))
739
+ throw new Error("Frame was detached");
740
+ throw e;
741
+ });
722
742
  }
723
743
  async dispatchEvent(progress, selector, type, eventInit = {}, options, scope) {
724
- await this._callOnElementOnceMatches(progress, selector, (injectedScript, element, data) => {
744
+ const eventInitHandles = [];
745
+ const visited = /* @__PURE__ */ new WeakSet();
746
+ const collectHandles = (value) => {
747
+ if (!value || typeof value !== "object")
748
+ return;
749
+ if (value instanceof js.JSHandle) {
750
+ eventInitHandles.push(value);
751
+ return;
752
+ }
753
+ if (visited.has(value))
754
+ return;
755
+ visited.add(value);
756
+ if (Array.isArray(value)) {
757
+ for (const item of value)
758
+ collectHandles(item);
759
+ return;
760
+ }
761
+ for (const propertyValue of Object.values(value))
762
+ collectHandles(propertyValue);
763
+ };
764
+ collectHandles(eventInit);
765
+ const allHandlesFromSameFrame = eventInitHandles.length > 0 && eventInitHandles.every((handle) => handle._context?.frame === eventInitHandles[0]?._context?.frame);
766
+ const handlesFrame = eventInitHandles[0]?._context?.frame;
767
+ const canRetryInSecondaryContext = allHandlesFromSameFrame && (handlesFrame !== this || !selector.includes("internal:control=enter-frame"));
768
+ const callback = (injectedScript, element, data) => {
725
769
  injectedScript.dispatchEvent(element, data.type, data.eventInit);
726
- }, { type, eventInit }, { mainWorld: true, ...options }, scope);
770
+ };
771
+ try {
772
+ await this._callOnElementOnceMatches(progress, selector, callback, { type, eventInit }, { mainWorld: true, ...options }, scope);
773
+ } catch (e) {
774
+ if ("JSHandles can be evaluated only in the context they were created!" === e.message && canRetryInSecondaryContext) {
775
+ await this._callOnElementOnceMatches(progress, selector, callback, { type, eventInit }, { ...options }, scope);
776
+ return;
777
+ }
778
+ throw e;
779
+ }
727
780
  }
728
781
  async evalOnSelector(selector, strict, expression, isFunction, arg, scope) {
729
782
  const handle = await this.selectors.query(selector, { strict }, scope);
730
783
  if (!handle)
731
- throw new Error("Failed to find element matching selector " + selector);
784
+ throw new Error('Failed to find element matching selector "' + selector + '"');
732
785
  const result = await handle.evaluateExpression(expression, { isFunction }, arg, true);
733
786
  handle.dispose();
734
787
  return result;
@@ -759,7 +812,7 @@ class Frame extends import_instrumentation.SdkObject {
759
812
  metadata,
760
813
  race: (promise) => Promise.race(Array.isArray(promise) ? promise : [promise])
761
814
  };
762
- return await this._retryWithoutProgress(progress, selector, null, false, async (result) => {
815
+ return await this._retryWithoutProgress(progress, selector, { strict: null, performActionPreChecks: false }, async (result) => {
763
816
  if (!result || !result[0]) return [];
764
817
  return result[1];
765
818
  }, "returnAll", null);
@@ -771,7 +824,7 @@ class Frame extends import_instrumentation.SdkObject {
771
824
  metadata,
772
825
  race: (promise) => Promise.race(Array.isArray(promise) ? promise : [promise])
773
826
  };
774
- return await this._retryWithoutProgress(progress, selector, null, false, async (result) => {
827
+ return await this._retryWithoutProgress(progress, selector, { strict: null, performActionPreChecks: false }, async (result) => {
775
828
  if (!result) return 0;
776
829
  const handle = result[0];
777
830
  const handles = result[1];
@@ -801,9 +854,9 @@ class Frame extends import_instrumentation.SdkObject {
801
854
  progress.log(`setting frame content, waiting until "${waitUntil}"`);
802
855
  const lifecyclePromise = new Promise((resolve, reject) => {
803
856
  this._onClearLifecycle();
804
- this._waitForLoadState(progress, waitUntil).then(resolve).catch(reject);
857
+ this.waitForLoadState(progress, waitUntil).then(resolve).catch(reject);
805
858
  });
806
- const setContentPromise = this._page.delegate._mainFrameSession._client.send("Page.setDocumentContent", {
859
+ const setContentPromise = this._page.delegate._sessionForFrame(this)._client.send("Page.setDocumentContent", {
807
860
  frameId: this._id,
808
861
  html
809
862
  });
@@ -968,26 +1021,27 @@ class Frame extends import_instrumentation.SdkObject {
968
1021
  return true;
969
1022
  return false;
970
1023
  }
971
- async _retryWithProgressIfNotConnected(progress, selector, strict, performActionPreChecks, action, returnAction) {
972
- progress.log("waiting for " + this._asLocator(selector));
1024
+ async _retryWithProgressIfNotConnected(progress, selector, options, action, returnAction) {
1025
+ if (!options?.__patchrightSkipRetryLogWaiting)
1026
+ progress.log("waiting for " + this._asLocator(selector));
973
1027
  return this.retryWithProgressAndTimeouts(progress, [0, 20, 50, 100, 100, 500], async (continuePolling) => {
974
- return this._retryWithoutProgress(progress, selector, strict, performActionPreChecks, action, returnAction, continuePolling);
1028
+ return this._retryWithoutProgress(progress, selector, options, action, returnAction, continuePolling);
975
1029
  });
976
1030
  }
977
1031
  async rafrafTimeoutScreenshotElementWithProgress(progress, selector, timeout, options) {
978
- return await this._retryWithProgressIfNotConnected(progress, selector, true, true, async (handle) => {
1032
+ return await this._retryWithProgressIfNotConnected(progress, selector, { strict: true, performActionPreChecks: true }, async (handle) => {
979
1033
  await handle._frame.rafrafTimeout(progress, timeout);
980
1034
  return await this._page.screenshotter.screenshotElement(progress, handle, options);
981
1035
  });
982
1036
  }
983
1037
  async click(progress, selector, options) {
984
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._click(progress, { ...options, waitAfter: !options.noWaitAfter })));
1038
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._click(progress, { ...options, waitAfter: !options.noWaitAfter })));
985
1039
  }
986
1040
  async dblclick(progress, selector, options) {
987
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._dblclick(progress, options)));
1041
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._dblclick(progress, options)));
988
1042
  }
989
1043
  async dragAndDrop(progress, source, target, options) {
990
- dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options.strict, !options.force, async (handle) => {
1044
+ dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options, async (handle) => {
991
1045
  return handle._retryPointerAction(progress, "move and down", false, async (point) => {
992
1046
  await this._page.mouse.move(progress, point.x, point.y);
993
1047
  await this._page.mouse.down(progress);
@@ -997,7 +1051,7 @@ class Frame extends import_instrumentation.SdkObject {
997
1051
  position: options.sourcePosition
998
1052
  });
999
1053
  }));
1000
- dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options.strict, false, async (handle) => {
1054
+ dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, { ...options, performActionPreChecks: false }, async (handle) => {
1001
1055
  return handle._retryPointerAction(progress, "move and up", false, async (point) => {
1002
1056
  await this._page.mouse.move(progress, point.x, point.y, { steps: options.steps });
1003
1057
  await this._page.mouse.up(progress);
@@ -1011,16 +1065,16 @@ class Frame extends import_instrumentation.SdkObject {
1011
1065
  async tap(progress, selector, options) {
1012
1066
  if (!this._page.browserContext._options.hasTouch)
1013
1067
  throw new Error("The page does not support tap. Use hasTouch context option to enable touch support.");
1014
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._tap(progress, options)));
1068
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._tap(progress, options)));
1015
1069
  }
1016
1070
  async fill(progress, selector, value, options) {
1017
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._fill(progress, value, options)));
1071
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._fill(progress, value, options)));
1018
1072
  }
1019
1073
  async focus(progress, selector, options) {
1020
- dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._focus(progress)));
1074
+ dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._focus(progress)));
1021
1075
  }
1022
1076
  async blur(progress, selector, options) {
1023
- dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._blur(progress)));
1077
+ dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._blur(progress)));
1024
1078
  }
1025
1079
  async resolveSelector(progress, selector, options = {}) {
1026
1080
  const element = await progress.race(this.selectors.query(selector, options));
@@ -1131,7 +1185,7 @@ class Frame extends import_instrumentation.SdkObject {
1131
1185
  }, { scope });
1132
1186
  }
1133
1187
  } else {
1134
- return await this._retryWithoutProgress(progress2, selector, options.strict, false, async (handle) => {
1188
+ return await this._retryWithoutProgress(progress2, selector, { ...options, performActionPreChecks: false }, async (handle) => {
1135
1189
  if (!handle) return false;
1136
1190
  if (handle.parentNode.constructor.name == "ElementHandle") {
1137
1191
  return await handle.parentNode.evaluateInUtility(([injected, node, { handle: handle2 }]) => {
@@ -1173,35 +1227,35 @@ class Frame extends import_instrumentation.SdkObject {
1173
1227
  return this._elementState(progress, selector, "checked", options, scope);
1174
1228
  }
1175
1229
  async hover(progress, selector, options) {
1176
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._hover(progress, options)));
1230
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._hover(progress, options)));
1177
1231
  }
1178
1232
  async selectOption(progress, selector, elements, values, options) {
1179
- return await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._selectOption(progress, elements, values, options));
1233
+ return await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._selectOption(progress, elements, values, options));
1180
1234
  }
1181
1235
  async setInputFiles(progress, selector, params) {
1182
1236
  const inputFileItems = await (0, import_fileUploadUtils.prepareFilesForUpload)(this, params);
1183
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params.strict, true, (handle) => handle._setInputFiles(progress, inputFileItems)));
1237
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params, (handle) => handle._setInputFiles(progress, inputFileItems)));
1184
1238
  }
1185
1239
  async type(progress, selector, text, options) {
1186
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._type(progress, text, options)));
1240
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._type(progress, text, options)));
1187
1241
  }
1188
1242
  async press(progress, selector, key, options) {
1189
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._press(progress, key, options)));
1243
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._press(progress, key, options)));
1190
1244
  }
1191
1245
  async check(progress, selector, options) {
1192
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._setChecked(progress, true, options)));
1246
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._setChecked(progress, true, options)));
1193
1247
  }
1194
1248
  async uncheck(progress, selector, options) {
1195
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._setChecked(progress, false, options)));
1249
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._setChecked(progress, false, options)));
1196
1250
  }
1197
1251
  async waitForTimeout(progress, timeout) {
1198
1252
  return progress.wait(timeout);
1199
1253
  }
1200
1254
  async ariaSnapshot(progress, selector) {
1201
- return await this._retryWithProgressIfNotConnected(progress, selector, true, true, (handle) => progress.race(handle.ariaSnapshot()));
1255
+ return await this._retryWithProgressIfNotConnected(progress, selector, { strict: true, performActionPreChecks: true }, (handle) => progress.race(handle.ariaSnapshot()));
1202
1256
  }
1203
- async expect(progress, selector, options, timeout) {
1204
- progress.log(`${(0, import_utils.renderTitleForCall)(progress.metadata)}${timeout ? ` with timeout ${timeout}ms` : ""}`);
1257
+ async expect(progress, selector, options) {
1258
+ progress.log(`${(0, import_utils.renderTitleForCall)(progress.metadata)}${options.timeoutForLogs ? ` with timeout ${options.timeoutForLogs}ms` : ""}`);
1205
1259
  const lastIntermediateResult = { isSet: false };
1206
1260
  const fixupMetadataError = (result) => {
1207
1261
  if (result.matches === options.isNot)
@@ -1210,17 +1264,19 @@ class Frame extends import_instrumentation.SdkObject {
1210
1264
  try {
1211
1265
  if (selector)
1212
1266
  progress.log(`waiting for ${this._asLocator(selector)}`);
1213
- await this._page.performActionPreChecks(progress);
1267
+ if (!options.noAutoWaiting)
1268
+ await this._page.performActionPreChecks(progress);
1214
1269
  try {
1215
1270
  const resultOneShot = await this._expectInternal(progress, selector, options, lastIntermediateResult, true);
1216
- if (resultOneShot.matches !== options.isNot)
1271
+ if (options.noAutoWaiting || resultOneShot.matches !== options.isNot)
1217
1272
  return resultOneShot;
1218
1273
  } catch (e) {
1219
- if (this.isNonRetriableError(e))
1274
+ if (options.noAutoWaiting || this.isNonRetriableError(e))
1220
1275
  throw e;
1221
1276
  }
1222
1277
  const result = await this.retryWithProgressAndTimeouts(progress, [100, 250, 500, 1e3], async (continuePolling) => {
1223
- await this._page.performActionPreChecks(progress);
1278
+ if (!options.noAutoWaiting)
1279
+ await this._page.performActionPreChecks(progress);
1224
1280
  const { matches, received } = await this._expectInternal(progress, selector, options, lastIntermediateResult, false);
1225
1281
  if (matches === options.isNot) {
1226
1282
  return continuePolling;
@@ -1250,11 +1306,17 @@ class Frame extends import_instrumentation.SdkObject {
1250
1306
  const isArray = options.expression === "to.have.count" || options.expression.endsWith(".array");
1251
1307
  var log, matches, received, missingReceived;
1252
1308
  if (selector) {
1253
- const { frame, info } = await race(this.selectors.resolveFrameForSelector(selector, { strict: true }));
1309
+ var frame, info;
1310
+ try {
1311
+ var { frame, info } = await race(this.selectors.resolveFrameForSelector(selector, { strict: true }));
1312
+ } catch (e) {
1313
+ }
1254
1314
  const action = async (result) => {
1255
1315
  if (!result) {
1256
1316
  if (options.expectedNumber === 0)
1257
1317
  return { matches: true };
1318
+ if (options.isNot && options.expectedNumber)
1319
+ return { matches: false, received: 0 };
1258
1320
  if (!options.isNot && options.expression === "to.be.hidden")
1259
1321
  return { matches: true };
1260
1322
  if (options.isNot && options.expression === "to.be.visible")
@@ -1265,6 +1327,12 @@ class Frame extends import_instrumentation.SdkObject {
1265
1327
  return { matches: false };
1266
1328
  if (options.isNot && options.expression === "to.be.in.viewport")
1267
1329
  return { matches: false };
1330
+ if (options.expression === "to.have.text.array") {
1331
+ if (options.expectedText.length === 0)
1332
+ return { matches: true, received: [] };
1333
+ if (options.isNot && options.expectedText.length !== 0)
1334
+ return { matches: false, received: [] };
1335
+ }
1268
1336
  return { matches: options.isNot, missingReceived: true };
1269
1337
  }
1270
1338
  const handle = result[0];
@@ -1280,9 +1348,9 @@ class Frame extends import_instrumentation.SdkObject {
1280
1348
  }
1281
1349
  };
1282
1350
  if (noAbort) {
1283
- var { log, matches, received, missingReceived } = await this._retryWithoutProgress(progress, selector, !isArray, false, action, "returnAll", null);
1351
+ var { log, matches, received, missingReceived } = await this._retryWithoutProgress(progress, selector, { strict: !isArray, performActionPreChecks: false }, action, "returnAll", null);
1284
1352
  } else {
1285
- var { log, matches, received, missingReceived } = await race(this._retryWithProgressIfNotConnected(progress, selector, !isArray, false, action, "returnAll"));
1353
+ var { log, matches, received, missingReceived } = await race(this._retryWithProgressIfNotConnected(progress, selector, { strict: !isArray, performActionPreChecks: false, __patchrightSkipRetryLogWaiting: true }, action, "returnAll"));
1286
1354
  }
1287
1355
  } else {
1288
1356
  const world = options.expression === "to.have.property" ? "main" : "utility";
@@ -1295,10 +1363,18 @@ class Frame extends import_instrumentation.SdkObject {
1295
1363
  if (log)
1296
1364
  progress.log(log);
1297
1365
  if (matches === options.isNot) {
1298
- lastIntermediateResult.received = missingReceived ? "<element(s) not found>" : received;
1366
+ if (missingReceived) {
1367
+ lastIntermediateResult.errorMessage = "Error: element(s) not found";
1368
+ } else {
1369
+ lastIntermediateResult.errorMessage = void 0;
1370
+ lastIntermediateResult.received = received;
1371
+ }
1299
1372
  lastIntermediateResult.isSet = true;
1300
- if (!missingReceived && !Array.isArray(received))
1301
- progress.log(` unexpected value "${renderUnexpectedValue(options.expression, received)}"`);
1373
+ if (!missingReceived) {
1374
+ const rendered = renderUnexpectedValue(options.expression, received);
1375
+ if (rendered !== void 0)
1376
+ progress.log(' unexpected value "' + rendered + '"');
1377
+ }
1302
1378
  }
1303
1379
  return { matches, received };
1304
1380
  }
@@ -1354,7 +1430,7 @@ class Frame extends import_instrumentation.SdkObject {
1354
1430
  return { result, abort: () => aborted = true };
1355
1431
  }, { expression, isFunction, polling: options.pollingInterval, arg }));
1356
1432
  try {
1357
- return await progress.race(handle.evaluateHandle((h) => h.result));
1433
+ return await progress.race(this._detachedScope.race(handle.evaluateHandle((h) => h.result)));
1358
1434
  } catch (error) {
1359
1435
  await handle.evaluate((h) => h.abort()).catch(() => {
1360
1436
  });
@@ -1400,6 +1476,12 @@ class Frame extends import_instrumentation.SdkObject {
1400
1476
  data.context.contextDestroyed("Frame was detached");
1401
1477
  data.contextPromise.resolve({ destroyedReason: "Frame was detached" });
1402
1478
  }
1479
+ if (this._mainWorld)
1480
+ this._mainWorld.contextDestroyed("Frame was detached");
1481
+ if (this._iframeWorld)
1482
+ this._iframeWorld.contextDestroyed("Frame was detached");
1483
+ if (this._isolatedWorld)
1484
+ this._isolatedWorld.contextDestroyed("Frame was detached");
1403
1485
  if (this._parentFrame)
1404
1486
  this._parentFrame._childFrames.delete(this);
1405
1487
  this._parentFrame = null;
@@ -1411,15 +1493,33 @@ class Frame extends import_instrumentation.SdkObject {
1411
1493
  if (selector === ":scope") {
1412
1494
  const scopeParentNode = scope.parentNode || scope;
1413
1495
  if (scopeParentNode.constructor.name == "ElementHandle") {
1414
- promise = scopeParentNode.evaluateInUtility(([injected, node, { callbackText: callbackText2, scope: handle2, taskData: taskData2 }]) => {
1415
- const callback = injected.eval(callbackText2);
1416
- const haha = callback(injected, handle2, taskData2);
1417
- return haha;
1418
- }, {
1419
- callbackText,
1420
- scope,
1421
- taskData
1422
- });
1496
+ if (options?.mainWorld) {
1497
+ promise = (async () => {
1498
+ const mainContext = await this._mainContext();
1499
+ const adoptedScope = await this._page.delegate.adoptElementHandle(scope, mainContext);
1500
+ try {
1501
+ return await mainContext.evaluate(([injected, node, { callbackText: callbackText2, scope: handle2, taskData: taskData2 }]) => {
1502
+ const callback = injected.eval(callbackText2);
1503
+ return callback(injected, handle2, taskData2);
1504
+ }, [
1505
+ await mainContext.injectedScript(),
1506
+ adoptedScope,
1507
+ { callbackText, scope: adoptedScope, taskData }
1508
+ ]);
1509
+ } finally {
1510
+ adoptedScope.dispose();
1511
+ }
1512
+ })();
1513
+ } else {
1514
+ promise = scopeParentNode.evaluateInUtility(([injected, node, { callbackText: callbackText2, scope: handle2, taskData: taskData2 }]) => {
1515
+ const callback = injected.eval(callbackText2);
1516
+ return callback(injected, handle2, taskData2);
1517
+ }, {
1518
+ callbackText,
1519
+ scope,
1520
+ taskData
1521
+ });
1522
+ }
1423
1523
  } else {
1424
1524
  promise = scopeParentNode.evaluate((injected, { callbackText: callbackText2, scope: handle2, taskData: taskData2 }) => {
1425
1525
  const callback = injected.eval(callbackText2);
@@ -1431,12 +1531,40 @@ class Frame extends import_instrumentation.SdkObject {
1431
1531
  });
1432
1532
  }
1433
1533
  } else {
1434
- promise = this._retryWithProgressIfNotConnected(progress, selector, options.strict, false, async (handle) => {
1534
+ promise = this._retryWithProgressIfNotConnected(progress, selector, { ...options, performActionPreChecks: false }, async (handle) => {
1435
1535
  if (handle.parentNode.constructor.name == "ElementHandle") {
1536
+ if (options?.mainWorld) {
1537
+ const mainContext = await handle._frame._mainContext();
1538
+ const adoptedHandle = await this._page.delegate.adoptElementHandle(handle, mainContext);
1539
+ try {
1540
+ return await mainContext.evaluate(([injected, node, { callbackText: callbackText2, handle: handle2, taskData: taskData2 }]) => {
1541
+ const callback = injected.eval(callbackText2);
1542
+ return callback(injected, handle2, taskData2);
1543
+ }, [
1544
+ await mainContext.injectedScript(),
1545
+ adoptedHandle,
1546
+ { callbackText, handle: adoptedHandle, taskData }
1547
+ ]);
1548
+ } finally {
1549
+ adoptedHandle.dispose();
1550
+ }
1551
+ }
1552
+ const [taskScope] = Object.values(taskData?.eventInit ?? {});
1553
+ if (taskScope) {
1554
+ const taskScopeContext = taskScope._context;
1555
+ const adoptedHandle = await handle._adoptTo(taskScopeContext);
1556
+ return await taskScopeContext.evaluate(([injected, node, { callbackText: callbackText2, adoptedHandle: handle2, taskData: taskData2 }]) => {
1557
+ const callback = injected.eval(callbackText2);
1558
+ return callback(injected, handle2, taskData2);
1559
+ }, [
1560
+ await taskScopeContext.injectedScript(),
1561
+ adoptedHandle,
1562
+ { callbackText, adoptedHandle, taskData }
1563
+ ]);
1564
+ }
1436
1565
  return await handle.parentNode.evaluateInUtility(([injected, node, { callbackText: callbackText2, handle: handle2, taskData: taskData2 }]) => {
1437
1566
  const callback = injected.eval(callbackText2);
1438
- const haha = callback(injected, handle2, taskData2);
1439
- return haha;
1567
+ return callback(injected, handle2, taskData2);
1440
1568
  }, {
1441
1569
  callbackText,
1442
1570
  handle,
@@ -1513,21 +1641,23 @@ class Frame extends import_instrumentation.SdkObject {
1513
1641
  var describedNode = await client._sendMayFail("DOM.describeNode", {
1514
1642
  backendNodeId: globalDocument.backendNodeId
1515
1643
  });
1516
- if (describedNode) {
1644
+ if (describedNode && describedNode.node.contentDocument) {
1517
1645
  var resolvedNode = await client._sendMayFail("DOM.resolveNode", {
1518
- nodeId: describedNode.node.contentDocument.nodeId
1646
+ backendNodeId: describedNode.node.contentDocument.backendNodeId
1519
1647
  });
1520
- var _executionContextId = parseInt(resolvedNode.object.objectId.split(".")[1], 10);
1521
- return _executionContextId;
1648
+ if (resolvedNode && resolvedNode.object && resolvedNode.object.objectId) {
1649
+ var _executionContextId = parseInt(resolvedNode.object.objectId.split(".")[1], 10);
1650
+ return _executionContextId;
1651
+ }
1522
1652
  }
1523
1653
  }
1524
1654
  } catch (e) {
1525
1655
  }
1526
1656
  return 0;
1527
1657
  }
1528
- async _retryWithoutProgress(progress, selector, strict, performActionPreChecks, action, returnAction, continuePolling) {
1529
- if (performActionPreChecks) await this._page.performActionPreChecks(progress);
1530
- const resolved = await this.selectors.resolveInjectedForSelector(selector, { strict });
1658
+ async _retryWithoutProgress(progress, selector, options, action, returnAction, continuePolling) {
1659
+ if (options.performActionPreChecks) await this._page.performActionPreChecks(progress);
1660
+ const resolved = await this.selectors.resolveInjectedForSelector(selector, { strict: options.strict }, options.__patchrightInitialScope);
1531
1661
  if (!resolved) {
1532
1662
  if (returnAction === "returnOnNotResolved" || returnAction === "returnAll") {
1533
1663
  const result2 = await action(null);
@@ -1550,24 +1680,51 @@ class Frame extends import_instrumentation.SdkObject {
1550
1680
  contextId: utilityContext.delegate._contextId
1551
1681
  });
1552
1682
  if (!documentNode) return continuePolling;
1553
- const documentScope = new dom.ElementHandle(utilityContext, documentNode.result.objectId);
1683
+ let documentScope = new dom.ElementHandle(utilityContext, documentNode.result.objectId);
1684
+ let initialScope = documentScope;
1685
+ if (resolved.scope) {
1686
+ const scopeBackendNodeId = resolved.scope._objectId ? (await client._sendMayFail("DOM.describeNode", { objectId: resolved.scope._objectId }))?.node?.backendNodeId : null;
1687
+ if (scopeBackendNodeId) {
1688
+ const scopeInUtility = await client._sendMayFail("DOM.resolveNode", { backendNodeId: scopeBackendNodeId, executionContextId: utilityContext.delegate._contextId });
1689
+ if (scopeInUtility?.object?.objectId)
1690
+ initialScope = new dom.ElementHandle(utilityContext, scopeInUtility.object.objectId);
1691
+ }
1692
+ }
1693
+ progress.__patchrightInitialScope = resolved.scope;
1694
+ const parsedSnapshot = options.__patchrightWaitForSelector ? JSON.parse(JSON.stringify(resolved.info.parsed)) : null;
1554
1695
  let currentScopingElements;
1555
1696
  try {
1556
- currentScopingElements = await this._customFindElementsByParsed(resolved, client, mainContext, documentScope, progress, resolved.info.parsed);
1697
+ currentScopingElements = await this._customFindElementsByParsed(resolved, client, mainContext, initialScope, progress, resolved.info.parsed);
1557
1698
  } catch (e) {
1558
- if ("JSHandles can be evaluated only in the context they were created!" === e.message) return continuePolling3;
1699
+ if ("JSHandles can be evaluated only in the context they were created!" === e.message) return continuePolling;
1700
+ if (e instanceof TypeError && e.message.includes("is not a function")) return continuePolling;
1559
1701
  await progress.race(resolved.injected.evaluateHandle((injected, { error }) => {
1560
1702
  throw error;
1561
1703
  }, { error: e }));
1562
1704
  }
1563
1705
  if (currentScopingElements.length == 0) {
1706
+ if (options.__testHookNoAutoWaiting || options.noAutoWaiting)
1707
+ throw new dom.NonRecoverableDOMError("Element(s) not found");
1708
+ if (parsedSnapshot && (returnAction === "returnOnNotResolved" || returnAction === "returnAll")) {
1709
+ const elementCount = await resolved.injected.evaluate((injected, { parsed }) => {
1710
+ return injected.querySelectorAll(parsed, document).length;
1711
+ }, { parsed: parsedSnapshot }).catch(() => 0);
1712
+ if (elementCount > 0)
1713
+ return continuePolling;
1714
+ }
1564
1715
  if (returnAction === "returnOnNotResolved" || returnAction === "returnAll") {
1565
1716
  const result2 = await action(null);
1566
- return result2 === "internal:continuepolling" ? continuePolling2 : result2;
1717
+ return result2 === "internal:continuepolling" ? continuePolling : result2;
1567
1718
  }
1568
1719
  return continuePolling;
1569
1720
  }
1570
1721
  const resultElement = currentScopingElements[0];
1722
+ await resultElement._initializePreview().catch(() => {
1723
+ });
1724
+ let visibilityQualifier = "";
1725
+ if (options && options.__patchrightWaitForSelector) {
1726
+ visibilityQualifier = await resultElement.evaluateInUtility(([injected, node]) => injected.utils.isElementVisible(node) ? "visible" : "hidden", {}).catch(() => "");
1727
+ }
1571
1728
  if (currentScopingElements.length > 1) {
1572
1729
  if (resolved.info.strict) {
1573
1730
  await progress.race(resolved.injected.evaluateHandle((injected, {
@@ -1582,7 +1739,7 @@ class Frame extends import_instrumentation.SdkObject {
1582
1739
  }
1583
1740
  progress.log(" locator resolved to " + currentScopingElements.length + " elements. Proceeding with the first one: " + resultElement.preview());
1584
1741
  } else if (resultElement) {
1585
- progress.log(" locator resolved to " + resultElement.preview());
1742
+ progress.log(" locator resolved to " + (visibilityQualifier ? visibilityQualifier + " " : "") + resultElement.preview().replace("JSHandle@", ""));
1586
1743
  }
1587
1744
  try {
1588
1745
  var result = null;
@@ -1597,6 +1754,14 @@ class Frame extends import_instrumentation.SdkObject {
1597
1754
  } else if (result === "internal:continuepolling") {
1598
1755
  return continuePolling;
1599
1756
  }
1757
+ if (parsedSnapshot && result === null && (options.state === "hidden" || options.state === "detached")) {
1758
+ const visibleCount = await resolved.injected.evaluate((injected, { parsed }) => {
1759
+ const elements = injected.querySelectorAll(parsed, document);
1760
+ return elements.filter((e) => injected.utils.isElementVisible(e)).length;
1761
+ }, { parsed: parsedSnapshot }).catch(() => 0);
1762
+ if (visibleCount > 0)
1763
+ return continuePolling;
1764
+ }
1600
1765
  return result;
1601
1766
  } finally {
1602
1767
  }
@@ -1709,7 +1874,7 @@ class Frame extends import_instrumentation.SdkObject {
1709
1874
  }
1710
1875
  }
1711
1876
  }
1712
- const getParts = (pos) => (pos || "").split("").map(Number);
1877
+ const getParts = (pos) => (pos || "").split(".").filter(Boolean).map(Number);
1713
1878
  elements.sort((a, b) => {
1714
1879
  const partA = getParts(a.nodePosition);
1715
1880
  const partB = getParts(b.nodePosition);