@smoothdeploy/playwright-core 1.57.1 → 1.58.1-beta-1770452953000

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.

Potentially problematic release.


This version of @smoothdeploy/playwright-core might be problematic. Click here for more details.

Files changed (155) 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 +35 -0
  7. package/lib/client/browserType.js +4 -3
  8. package/lib/client/channelOwner.js +4 -3
  9. package/lib/client/clientInstrumentation.js +10 -0
  10. package/lib/client/connection.js +4 -0
  11. package/lib/client/elementHandle.js +3 -0
  12. package/lib/client/events.js +3 -0
  13. package/lib/client/fetch.js +3 -4
  14. package/lib/client/frame.js +1 -0
  15. package/lib/client/page.js +28 -1
  16. package/lib/client/pageAgent.js +64 -0
  17. package/lib/client/platform.js +3 -0
  18. package/lib/generated/injectedScriptSource.js +1 -1
  19. package/lib/generated/pollingRecorderSource.js +1 -1
  20. package/lib/mcpBundle.js +84 -0
  21. package/lib/mcpBundleImpl/index.js +147 -0
  22. package/lib/protocol/serializers.js +5 -0
  23. package/lib/protocol/validator.js +92 -3
  24. package/lib/remote/playwrightServer.js +1 -2
  25. package/lib/server/agent/actionRunner.js +335 -0
  26. package/lib/server/agent/actions.js +128 -0
  27. package/lib/server/agent/codegen.js +111 -0
  28. package/lib/server/agent/context.js +150 -0
  29. package/lib/server/agent/expectTools.js +156 -0
  30. package/lib/server/agent/pageAgent.js +204 -0
  31. package/lib/server/agent/performTools.js +262 -0
  32. package/lib/server/agent/tool.js +109 -0
  33. package/lib/server/artifact.js +1 -1
  34. package/lib/server/bidi/bidiBrowser.js +56 -12
  35. package/lib/server/bidi/bidiChromium.js +6 -11
  36. package/lib/server/bidi/bidiConnection.js +1 -0
  37. package/lib/server/bidi/bidiDeserializer.js +116 -0
  38. package/lib/server/bidi/bidiExecutionContext.js +75 -29
  39. package/lib/server/bidi/bidiFirefox.js +6 -8
  40. package/lib/server/bidi/bidiNetworkManager.js +1 -1
  41. package/lib/server/bidi/bidiPage.js +39 -28
  42. package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
  43. package/lib/server/browserContext.js +32 -25
  44. package/lib/server/browserType.js +12 -4
  45. package/lib/server/chromium/chromium.js +14 -21
  46. package/lib/server/chromium/chromiumSwitches.js +2 -2
  47. package/lib/server/chromium/crBrowser.js +22 -12
  48. package/lib/server/chromium/crConnection.js +0 -5
  49. package/lib/server/chromium/crDevTools.js +0 -2
  50. package/lib/server/chromium/crNetworkManager.js +43 -2
  51. package/lib/server/chromium/crPage.js +19 -87
  52. package/lib/server/codegen/javascript.js +6 -29
  53. package/lib/server/deviceDescriptorsSource.json +56 -56
  54. package/lib/server/dispatchers/browserContextDispatcher.js +3 -0
  55. package/lib/server/dispatchers/dispatcher.js +6 -13
  56. package/lib/server/dispatchers/frameDispatcher.js +1 -1
  57. package/lib/server/dispatchers/pageAgentDispatcher.js +96 -0
  58. package/lib/server/dispatchers/pageDispatcher.js +4 -0
  59. package/lib/server/dom.js +12 -3
  60. package/lib/server/electron/electron.js +5 -2
  61. package/lib/server/firefox/ffBrowser.js +10 -20
  62. package/lib/server/firefox/ffConnection.js +0 -5
  63. package/lib/server/firefox/ffNetworkManager.js +2 -2
  64. package/lib/server/firefox/ffPage.js +15 -18
  65. package/lib/server/firefox/firefox.js +6 -8
  66. package/lib/server/frameSelectors.js +9 -3
  67. package/lib/server/frames.js +49 -33
  68. package/lib/server/instrumentation.js +3 -0
  69. package/lib/server/network.js +50 -12
  70. package/lib/server/page.js +33 -89
  71. package/lib/server/progress.js +26 -6
  72. package/lib/server/recorder/recorderApp.js +79 -100
  73. package/lib/server/recorder.js +55 -0
  74. package/lib/server/registry/browserFetcher.js +6 -4
  75. package/lib/server/registry/index.js +172 -149
  76. package/lib/server/registry/oopDownloadBrowserMain.js +3 -0
  77. package/lib/server/screencast.js +190 -0
  78. package/lib/server/screenshotCompositor.js +153 -0
  79. package/lib/server/trace/recorder/snapshotterInjected.js +21 -1
  80. package/lib/server/trace/recorder/tracing.js +21 -21
  81. package/lib/server/trace/viewer/traceParser.js +72 -0
  82. package/lib/server/trace/viewer/traceViewer.js +17 -13
  83. package/lib/server/utils/expectUtils.js +87 -2
  84. package/lib/server/utils/httpServer.js +4 -19
  85. package/lib/server/utils/network.js +37 -28
  86. package/lib/server/utils/nodePlatform.js +6 -0
  87. package/lib/server/videoRecorder.js +124 -0
  88. package/lib/server/webkit/webkit.js +4 -6
  89. package/lib/server/webkit/wkBrowser.js +2 -6
  90. package/lib/server/webkit/wkConnection.js +1 -6
  91. package/lib/server/webkit/wkInterceptableRequest.js +29 -1
  92. package/lib/server/webkit/wkPage.js +75 -46
  93. package/lib/utils/isomorphic/ariaSnapshot.js +60 -2
  94. package/lib/utils/isomorphic/lruCache.js +51 -0
  95. package/lib/utils/isomorphic/protocolMetainfo.js +9 -1
  96. package/lib/utils/isomorphic/stringUtils.js +49 -0
  97. package/lib/utils/isomorphic/trace/entries.js +16 -0
  98. package/lib/utils/isomorphic/trace/snapshotRenderer.js +499 -0
  99. package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
  100. package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
  101. package/lib/utils/isomorphic/trace/traceLoader.js +131 -0
  102. package/lib/utils/isomorphic/trace/traceModel.js +365 -0
  103. package/lib/utils/isomorphic/trace/traceModernizer.js +400 -0
  104. package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
  105. package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
  106. package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
  107. package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
  108. package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
  109. package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
  110. package/lib/utils/isomorphic/yaml.js +84 -0
  111. package/lib/utils.js +2 -0
  112. package/lib/utilsBundle.js +2 -5
  113. package/lib/utilsBundleImpl/index.js +165 -165
  114. package/lib/vite/htmlReport/index.html +21 -21
  115. package/lib/vite/recorder/assets/{codeMirrorModule-C3UTv-Ge.css → codeMirrorModule-DYBRYzYX.css} +1 -1
  116. package/lib/vite/recorder/assets/codeMirrorModule-DadYNm1I.js +32 -0
  117. package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
  118. package/lib/vite/recorder/assets/index-BhTWtUlo.js +193 -0
  119. package/lib/vite/recorder/index.html +2 -2
  120. package/lib/vite/traceViewer/assets/codeMirrorModule-8UJPCtp4.js +16884 -0
  121. package/lib/vite/{recorder/assets/codeMirrorModule-BoWUGj0J.js → traceViewer/assets/codeMirrorModule-BNr6yhVP.js} +1 -1
  122. package/lib/vite/traceViewer/assets/codeMirrorModule-Dimjuz94.js +32 -0
  123. package/lib/vite/traceViewer/assets/codeMirrorModule-DkmsYcws.js +32 -0
  124. package/lib/vite/traceViewer/assets/codeMirrorModule-DySgctgr.js +16884 -0
  125. package/lib/vite/traceViewer/assets/defaultSettingsView-B1vuWQsF.js +266 -0
  126. package/lib/vite/traceViewer/assets/defaultSettingsView-CtEsdeVH.js +266 -0
  127. package/lib/vite/traceViewer/assets/defaultSettingsView-D4fm31R-.js +34087 -0
  128. package/lib/vite/traceViewer/assets/defaultSettingsView-JtyB0yzL.js +34087 -0
  129. package/lib/vite/traceViewer/assets/defaultSettingsView-tEZf-LNj.js +266 -0
  130. package/lib/vite/traceViewer/assets/xtermModule-DDw6eROI.js +6168 -0
  131. package/lib/vite/traceViewer/codeMirrorModule.DYBRYzYX.css +1 -0
  132. package/lib/vite/traceViewer/codeMirrorModule.DuST8d_k.css +344 -0
  133. package/lib/vite/traceViewer/defaultSettingsView.5FCqBwKs.css +3986 -0
  134. package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +1 -0
  135. package/lib/vite/traceViewer/index.BQs8gGhY.js +249 -0
  136. package/lib/vite/traceViewer/index.BVu7tZDe.css +1 -0
  137. package/lib/vite/traceViewer/index.BoLn624r.js +2 -0
  138. package/lib/vite/traceViewer/index.Bq_EaK8x.js +249 -0
  139. package/lib/vite/traceViewer/index.C8YVh4B5.js +2 -0
  140. package/lib/vite/traceViewer/index.Cr7-GRf8.js +2 -0
  141. package/lib/vite/traceViewer/index.G-7UhDxt.css +164 -0
  142. package/lib/vite/traceViewer/index.html +4 -4
  143. package/lib/vite/traceViewer/sw.bundle.js +5 -3
  144. package/lib/vite/traceViewer/uiMode.-Kflt2XM.css +1440 -0
  145. package/lib/vite/traceViewer/uiMode.BTRKnokb.js +5 -0
  146. package/lib/vite/traceViewer/uiMode.CEZ5RVHh.js +5 -0
  147. package/lib/vite/traceViewer/uiMode.CIWF23si.js +1829 -0
  148. package/lib/vite/traceViewer/uiMode.Wi-DvIEY.js +1829 -0
  149. package/lib/vite/traceViewer/uiMode.html +3 -3
  150. package/lib/vite/traceViewer/uiMode.zEH1ejvz.js +5 -0
  151. package/lib/vite/traceViewer/xtermModule.BKlWQB97.css +218 -0
  152. package/package.json +3 -1
  153. package/types/protocol.d.ts +738 -159
  154. package/types/types.d.ts +25 -38
  155. package/lib/vite/recorder/assets/index-DJqDAOZp.js +0 -193
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var pageAgentDispatcher_exports = {};
20
+ __export(pageAgentDispatcher_exports, {
21
+ PageAgentDispatcher: () => PageAgentDispatcher
22
+ });
23
+ module.exports = __toCommonJS(pageAgentDispatcher_exports);
24
+ var import_dispatcher = require("./dispatcher");
25
+ var import_pageAgent = require("../agent/pageAgent");
26
+ var import_instrumentation = require("../instrumentation");
27
+ var import_context = require("../agent/context");
28
+ class PageAgentDispatcher extends import_dispatcher.Dispatcher {
29
+ constructor(scope, options) {
30
+ super(scope, new import_instrumentation.SdkObject(scope._object, "pageAgent"), "PageAgent", { page: scope });
31
+ this._type_PageAgent = true;
32
+ this._type_EventTarget = true;
33
+ this._usage = { turns: 0, inputTokens: 0, outputTokens: 0 };
34
+ this._page = scope._object;
35
+ this._context = new import_context.Context(this._page, options, this._eventSupport());
36
+ }
37
+ async perform(params, progress) {
38
+ try {
39
+ await (0, import_pageAgent.pageAgentPerform)(progress, this._context, params.task, params);
40
+ } finally {
41
+ this._context.pushHistory({ type: "perform", description: params.task });
42
+ }
43
+ return { usage: this._usage };
44
+ }
45
+ async expect(params, progress) {
46
+ try {
47
+ await (0, import_pageAgent.pageAgentExpect)(progress, this._context, params.expectation, params);
48
+ } finally {
49
+ this._context.pushHistory({ type: "expect", description: params.expectation });
50
+ }
51
+ return { usage: this._usage };
52
+ }
53
+ async extract(params, progress) {
54
+ const result = await (0, import_pageAgent.pageAgentExtract)(progress, this._context, params.query, params.schema, params);
55
+ return { result, usage: this._usage };
56
+ }
57
+ async usage(params, progress) {
58
+ return { usage: this._usage };
59
+ }
60
+ async dispose(params, progress) {
61
+ progress.metadata.potentiallyClosesScope = true;
62
+ void this.stopPendingOperations(new Error("The agent is disposed"));
63
+ this._dispose();
64
+ }
65
+ _eventSupport() {
66
+ const self = this;
67
+ return {
68
+ onBeforeTurn(params) {
69
+ const userMessage = params.conversation.messages.find((m) => m.role === "user");
70
+ self._dispatchEvent("turn", { role: "user", message: userMessage?.content ?? "" });
71
+ },
72
+ onAfterTurn(params) {
73
+ const usage = { inputTokens: params.totalUsage.input, outputTokens: params.totalUsage.output };
74
+ const intent = params.assistantMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
75
+ self._dispatchEvent("turn", { role: "assistant", message: intent, usage });
76
+ if (!params.assistantMessage.content.filter((c) => c.type === "tool_call").length)
77
+ self._dispatchEvent("turn", { role: "assistant", message: `no tool calls`, usage });
78
+ self._usage = { turns: self._usage.turns + 1, inputTokens: self._usage.inputTokens + usage.inputTokens, outputTokens: self._usage.outputTokens + usage.outputTokens };
79
+ },
80
+ onBeforeToolCall(params) {
81
+ self._dispatchEvent("turn", { role: "assistant", message: `call tool "${params.toolCall.name}"` });
82
+ },
83
+ onAfterToolCall(params) {
84
+ const suffix = params.toolCall.result?.isError ? "failed" : "succeeded";
85
+ self._dispatchEvent("turn", { role: "user", message: `tool "${params.toolCall.name}" ${suffix}` });
86
+ },
87
+ onToolCallError(params) {
88
+ self._dispatchEvent("turn", { role: "user", message: `tool "${params.toolCall.name}" failed: ${params.error.message}` });
89
+ }
90
+ };
91
+ }
92
+ }
93
+ // Annotate the CommonJS export names for ESM import in node:
94
+ 0 && (module.exports = {
95
+ PageAgentDispatcher
96
+ });
@@ -36,6 +36,7 @@ var import_networkDispatchers3 = require("./networkDispatchers");
36
36
  var import_webSocketRouteDispatcher = require("./webSocketRouteDispatcher");
37
37
  var import_instrumentation = require("../instrumentation");
38
38
  var import_urlMatch = require("../../utils/isomorphic/urlMatch");
39
+ var import_pageAgentDispatcher = require("./pageAgentDispatcher");
39
40
  class PageDispatcher extends import_dispatcher.Dispatcher {
40
41
  constructor(parentScope, page) {
41
42
  const mainFrame = import_frameDispatcher.FrameDispatcher.from(parentScope, page.mainFrame());
@@ -288,6 +289,9 @@ class PageDispatcher extends import_dispatcher.Dispatcher {
288
289
  const coverage = this._page.coverage;
289
290
  return await coverage.stopCSSCoverage();
290
291
  }
292
+ async agent(params, progress) {
293
+ return { agent: new import_pageAgentDispatcher.PageAgentDispatcher(this, params) };
294
+ }
291
295
  _onFrameAttached(frame) {
292
296
  this._dispatchEvent("frameAttached", { frame: import_frameDispatcher.FrameDispatcher.from(this.parentScope(), frame) });
293
297
  }
package/lib/server/dom.js CHANGED
@@ -255,6 +255,7 @@ class ElementHandle extends js.JSHandle {
255
255
  async _retryAction(progress, actionName, action, options) {
256
256
  let retry = 0;
257
257
  const waitTime = [0, 20, 100, 100, 500];
258
+ const noAutoWaiting = options.__testHookNoAutoWaiting ?? options.noAutoWaiting;
258
259
  while (true) {
259
260
  if (retry) {
260
261
  progress.log(`retrying ${actionName} action${options.trial ? " (trial run)" : ""}`);
@@ -268,35 +269,43 @@ class ElementHandle extends js.JSHandle {
268
269
  } else {
269
270
  progress.log(`attempting ${actionName} action${options.trial ? " (trial run)" : ""}`);
270
271
  }
271
- if (!options.skipActionPreChecks && !options.force)
272
+ if (!options.skipActionPreChecks && !options.force && !noAutoWaiting)
272
273
  await this._frame._page.performActionPreChecks(progress);
273
274
  const result = await action(retry);
274
275
  ++retry;
275
276
  if (result === "error:notvisible") {
276
- if (options.force)
277
+ if (options.force || noAutoWaiting)
277
278
  throw new NonRecoverableDOMError("Element is not visible");
278
279
  progress.log(" element is not visible");
279
280
  continue;
280
281
  }
281
282
  if (result === "error:notinviewport") {
282
- if (options.force)
283
+ if (options.force || noAutoWaiting)
283
284
  throw new NonRecoverableDOMError("Element is outside of the viewport");
284
285
  progress.log(" element is outside of the viewport");
285
286
  continue;
286
287
  }
287
288
  if (result === "error:optionsnotfound") {
289
+ if (noAutoWaiting)
290
+ throw new NonRecoverableDOMError("Did not find some options");
288
291
  progress.log(" did not find some options");
289
292
  continue;
290
293
  }
291
294
  if (result === "error:optionnotenabled") {
295
+ if (noAutoWaiting)
296
+ throw new NonRecoverableDOMError("Option being selected is not enabled");
292
297
  progress.log(" option being selected is not enabled");
293
298
  continue;
294
299
  }
295
300
  if (typeof result === "object" && "hitTargetDescription" in result) {
301
+ if (noAutoWaiting)
302
+ throw new NonRecoverableDOMError(`${result.hitTargetDescription} intercepts pointer events`);
296
303
  progress.log(` ${result.hitTargetDescription} intercepts pointer events`);
297
304
  continue;
298
305
  }
299
306
  if (typeof result === "object" && "missingState" in result) {
307
+ if (noAutoWaiting)
308
+ throw new NonRecoverableDOMError(`Element is not ${result.missingState}`);
300
309
  progress.log(` element is not ${result.missingState}`);
301
310
  continue;
302
311
  }
@@ -158,8 +158,8 @@ class Electron extends import_instrumentation.SdkObject {
158
158
  let shell = false;
159
159
  if (process.platform === "win32") {
160
160
  shell = true;
161
- command = `"${command}"`;
162
- electronArguments = electronArguments.map((arg) => `"${arg}"`);
161
+ command = [command, ...electronArguments].map((arg) => `"${escapeDoubleQuotes(arg)}"`).join(" ");
162
+ electronArguments = [];
163
163
  }
164
164
  delete env.NODE_OPTIONS;
165
165
  const { launchedProcess, gracefullyClose, kill } = await (0, import_processLauncher.launchProcess)({
@@ -263,6 +263,9 @@ async function waitForLine(progress, process2, regex) {
263
263
  import_eventsHelper.eventsHelper.removeEventListeners(listeners);
264
264
  }
265
265
  }
266
+ function escapeDoubleQuotes(str) {
267
+ return str.replace(/"/g, '\\"');
268
+ }
266
269
  // Annotate the CommonJS export names for ESM import in node:
267
270
  0 && (module.exports = {
268
271
  Electron,
@@ -54,7 +54,6 @@ class FFBrowser extends import_browser.Browser {
54
54
  this.session.on("Browser.detachedFromTarget", this._onDetachedFromTarget.bind(this));
55
55
  this.session.on("Browser.downloadCreated", this._onDownloadCreated.bind(this));
56
56
  this.session.on("Browser.downloadFinished", this._onDownloadFinished.bind(this));
57
- this.session.on("Browser.videoRecordingFinished", this._onVideoRecordingFinished.bind(this));
58
57
  }
59
58
  static async connect(parent, transport, options) {
60
59
  const connection = new import_ffConnection.FFConnection(transport, options.protocolLogger, options.browserLogsCollector);
@@ -141,12 +140,9 @@ class FFBrowser extends import_browser.Browser {
141
140
  const error = payload.canceled ? "canceled" : payload.error;
142
141
  this._downloadFinished(payload.uuid, error);
143
142
  }
144
- _onVideoRecordingFinished(payload) {
145
- this._takeVideo(payload.screencastId)?.reportFinished();
146
- }
147
143
  _onDisconnect() {
148
144
  for (const video of this._idToVideo.values())
149
- video.artifact.reportFinished(new import_errors.TargetClosedError());
145
+ video.artifact.reportFinished(new import_errors.TargetClosedError(this.closeReason()));
150
146
  this._idToVideo.clear();
151
147
  for (const ffPage of this._ffPages.values())
152
148
  ffPage.didClose();
@@ -199,15 +195,13 @@ class FFBrowserContext extends import_browserContext.BrowserContext {
199
195
  promises.push(this.doUpdateOffline());
200
196
  promises.push(this.doUpdateDefaultEmulatedMedia());
201
197
  if (this._options.recordVideo) {
202
- promises.push(this._ensureVideosPath().then(() => {
203
- return this._browser.session.send("Browser.setVideoRecordingOptions", {
204
- // validateBrowserContextOptions ensures correct video size.
205
- options: {
206
- ...this._options.recordVideo.size,
207
- dir: this._options.recordVideo.dir
208
- },
209
- browserContextId: this._browserContextId
210
- });
198
+ promises.push(this._browser.session.send("Browser.setScreencastOptions", {
199
+ // validateBrowserContextOptions ensures correct video size.
200
+ options: {
201
+ ...this._options.recordVideo.size,
202
+ quality: 90
203
+ },
204
+ browserContextId: this._browserContextId
211
205
  }));
212
206
  }
213
207
  const proxy = this._options.proxyOverride || this._options.proxy;
@@ -379,12 +373,8 @@ class FFBrowserContext extends import_browserContext.BrowserContext {
379
373
  }
380
374
  async doClose(reason) {
381
375
  if (!this._browserContextId) {
382
- if (this._options.recordVideo) {
383
- await this._browser.session.send("Browser.setVideoRecordingOptions", {
384
- options: void 0,
385
- browserContextId: this._browserContextId
386
- });
387
- }
376
+ if (this._options.recordVideo)
377
+ await Promise.all(this._ffPages().map((ffPage) => ffPage._page.screencast.stopVideoRecording()));
388
378
  await this._browser.close({ reason });
389
379
  } else {
390
380
  await this._browser.session.send("Browser.removeBrowserContext", { browserContextId: this._browserContextId });
@@ -90,11 +90,6 @@ class FFSession extends import_events.EventEmitter {
90
90
  this._connection = connection;
91
91
  this._sessionId = sessionId;
92
92
  this._rawSend = rawSend;
93
- this.on = super.on;
94
- this.addListener = super.addListener;
95
- this.off = super.removeListener;
96
- this.removeListener = super.removeListener;
97
- this.once = super.once;
98
93
  }
99
94
  markAsCrashed() {
100
95
  this._crashed = true;
@@ -170,9 +170,9 @@ const causeToResourceType = {
170
170
  TYPE_FONT: "font",
171
171
  TYPE_MEDIA: "media",
172
172
  TYPE_WEBSOCKET: "websocket",
173
- TYPE_CSP_REPORT: "other",
173
+ TYPE_CSP_REPORT: "cspreport",
174
174
  TYPE_XSLT: "other",
175
- TYPE_BEACON: "other",
175
+ TYPE_BEACON: "beacon",
176
176
  TYPE_FETCH: "fetch",
177
177
  TYPE_IMAGESET: "image",
178
178
  TYPE_WEB_MANIFEST: "manifest"
@@ -41,9 +41,9 @@ var import_ffConnection = require("./ffConnection");
41
41
  var import_ffExecutionContext = require("./ffExecutionContext");
42
42
  var import_ffInput = require("./ffInput");
43
43
  var import_ffNetworkManager = require("./ffNetworkManager");
44
- var import_debugLogger = require("../utils/debugLogger");
45
44
  var import_stackTrace = require("../../utils/isomorphic/stackTrace");
46
45
  var import_errors = require("../errors");
46
+ var import_debugLogger = require("../utils/debugLogger");
47
47
  const UTILITY_WORLD_NAME = "__playwright_utility_world__";
48
48
  class FFPage {
49
49
  constructor(session, browserContext, opener) {
@@ -83,13 +83,16 @@ class FFPage {
83
83
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.workerDestroyed", this._onWorkerDestroyed.bind(this)),
84
84
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.dispatchMessageFromWorker", this._onDispatchMessageFromWorker.bind(this)),
85
85
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.crashed", this._onCrashed.bind(this)),
86
- import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.videoRecordingStarted", this._onVideoRecordingStarted.bind(this)),
87
86
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketCreated", this._onWebSocketCreated.bind(this)),
88
87
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketClosed", this._onWebSocketClosed.bind(this)),
89
88
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketFrameReceived", this._onWebSocketFrameReceived.bind(this)),
90
89
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketFrameSent", this._onWebSocketFrameSent.bind(this)),
91
90
  import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.screencastFrame", this._onScreencastFrame.bind(this))
92
91
  ];
92
+ const screencast = this._page.screencast;
93
+ const videoOptions = screencast.launchVideoRecorder();
94
+ if (videoOptions)
95
+ screencast.startVideoRecording(videoOptions).catch((e) => import_debugLogger.debugLogger.log("error", e));
93
96
  this._session.once("Page.ready", () => {
94
97
  if (this._reportedAsNew)
95
98
  return;
@@ -272,11 +275,8 @@ class FFPage {
272
275
  this._session.markAsCrashed();
273
276
  this._page._didCrash();
274
277
  }
275
- _onVideoRecordingStarted(event) {
276
- this._browserContext._browser._videoStarted(this._browserContext, event.screencastId, event.file, this._page.waitForInitializedOrError());
277
- }
278
278
  didClose() {
279
- this._markAsError(new import_errors.TargetClosedError());
279
+ this._markAsError(new import_errors.TargetClosedError(this._page.closeReason()));
280
280
  this._session.dispose();
281
281
  import_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
282
282
  this._networkManager.dispose();
@@ -417,24 +417,21 @@ class FFPage {
417
417
  throw e;
418
418
  });
419
419
  }
420
- async setScreencastOptions(options) {
421
- if (options) {
422
- const { screencastId } = await this._session.send("Page.startScreencast", options);
423
- this._screencastId = screencastId;
424
- } else {
425
- await this._session.send("Page.stopScreencast");
426
- }
420
+ async startScreencast(options) {
421
+ await this._session.send("Page.startScreencast", options);
422
+ }
423
+ async stopScreencast() {
424
+ await this._session.sendMayFail("Page.stopScreencast");
427
425
  }
428
426
  _onScreencastFrame(event) {
429
- if (!this._screencastId)
430
- return;
431
- const screencastId = this._screencastId;
432
- this._page.throttleScreencastFrameAck(() => {
433
- this._session.send("Page.screencastFrameAck", { screencastId }).catch((e) => import_debugLogger.debugLogger.log("error", e));
427
+ this._page.screencast.throttleFrameAck(() => {
428
+ this._session.sendMayFail("Page.screencastFrameAck");
434
429
  });
435
430
  const buffer = Buffer.from(event.data, "base64");
436
431
  this._page.emit(import_page2.Page.Events.ScreencastFrame, {
437
432
  buffer,
433
+ frameSwapWallTime: event.timestamp * 1e3,
434
+ // timestamp is in seconds, we need to convert to milliseconds.
438
435
  width: event.deviceWidth,
439
436
  height: event.deviceHeight
440
437
  });
@@ -56,15 +56,13 @@ class Firefox extends import_browserType.BrowserType {
56
56
  connectToTransport(transport, options) {
57
57
  return import_ffBrowser.FFBrowser.connect(this.attribution.playwright, transport, options);
58
58
  }
59
- doRewriteStartupLog(error) {
60
- if (!error.logs)
61
- return error;
62
- if (error.logs.includes(`as root in a regular user's session is not supported.`))
63
- error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
59
+ doRewriteStartupLog(logs) {
60
+ if (logs.includes(`as root in a regular user's session is not supported.`))
61
+ logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
64
62
  Workaround: Set the HOME=/root environment variable${process.env.GITHUB_ACTION ? " in your GitHub Actions workflow file" : ""} when running Playwright.`, 1);
65
- if (error.logs.includes("no DISPLAY environment variable specified"))
66
- error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
67
- return error;
63
+ if (logs.includes("no DISPLAY environment variable specified"))
64
+ logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
65
+ return logs;
68
66
  }
69
67
  amendEnvironment(env) {
70
68
  if (!import_path.default.isAbsolute(import_os.default.homedir()))
@@ -50,7 +50,9 @@ class FrameSelectors {
50
50
  if (!resolved)
51
51
  throw new Error(`Failed to find frame for selector "${selector}"`);
52
52
  return await resolved.injected.evaluateHandle((injected, { info, scope: scope2 }) => {
53
- return injected.querySelectorAll(info.parsed, scope2 || document);
53
+ const elements = injected.querySelectorAll(info.parsed, scope2 || document);
54
+ injected.checkDeprecatedSelectorUsage(info.parsed, elements);
55
+ return elements;
54
56
  }, { info: resolved.info, scope: resolved.scope });
55
57
  }
56
58
  async queryCount(selector, options) {
@@ -59,7 +61,9 @@ class FrameSelectors {
59
61
  throw new Error(`Failed to find frame for selector "${selector}"`);
60
62
  await options.__testHookBeforeQuery?.();
61
63
  return await resolved.injected.evaluate((injected, { info }) => {
62
- return injected.querySelectorAll(info.parsed, document).length;
64
+ const elements = injected.querySelectorAll(info.parsed, document);
65
+ injected.checkDeprecatedSelectorUsage(info.parsed, elements);
66
+ return elements.length;
63
67
  }, { info: resolved.info });
64
68
  }
65
69
  async queryAll(selector, scope) {
@@ -67,7 +71,9 @@ class FrameSelectors {
67
71
  if (!resolved)
68
72
  return [];
69
73
  const arrayHandle = await resolved.injected.evaluateHandle((injected, { info, scope: scope2 }) => {
70
- return injected.querySelectorAll(info.parsed, scope2 || document);
74
+ const elements = injected.querySelectorAll(info.parsed, scope2 || document);
75
+ injected.checkDeprecatedSelectorUsage(info.parsed, elements);
76
+ return elements;
71
77
  }, { info: resolved.info, scope: resolved.scope });
72
78
  const properties = await arrayHandle.getProperties();
73
79
  arrayHandle.dispose();
@@ -350,6 +350,11 @@ class FrameManager {
350
350
  frame.emit(Frame.Events.InternalNavigation, event);
351
351
  }
352
352
  }
353
+ const FrameEvent = {
354
+ InternalNavigation: "internalnavigation",
355
+ AddLifecycle: "addlifecycle",
356
+ RemoveLifecycle: "removelifecycle"
357
+ };
353
358
  class Frame extends import_instrumentation.SdkObject {
354
359
  constructor(page, id, parentFrame) {
355
360
  super(page, "frame");
@@ -382,11 +387,7 @@ class Frame extends import_instrumentation.SdkObject {
382
387
  this._startNetworkIdleTimer();
383
388
  }
384
389
  static {
385
- this.Events = {
386
- InternalNavigation: "internalnavigation",
387
- AddLifecycle: "addlifecycle",
388
- RemoveLifecycle: "removelifecycle"
389
- };
390
+ this.Events = FrameEvent;
390
391
  }
391
392
  isDetached() {
392
393
  return this._detachedScope.isClosed();
@@ -569,7 +570,7 @@ class Frame extends import_instrumentation.SdkObject {
569
570
  const request = navigationEvent.newDocument ? navigationEvent.newDocument.request : void 0;
570
571
  return request ? progress.race(request._finalRequest().response()) : null;
571
572
  }
572
- async _waitForLoadState(progress, state) {
573
+ async waitForLoadState(progress, state) {
573
574
  const waitUntil = verifyLifecycle("state", state);
574
575
  if (!this._firedLifecycleEvents.has(waitUntil))
575
576
  await import_helper.helper.waitForEvent(progress, this, Frame.Events.AddLifecycle, (e) => e === waitUntil).promise;
@@ -640,6 +641,7 @@ class Frame extends import_instrumentation.SdkObject {
640
641
  } else if (element2) {
641
642
  log2 = ` locator resolved to ${visible2 ? "visible" : "hidden"} ${injected.previewNode(element2)}`;
642
643
  }
644
+ injected.checkDeprecatedSelectorUsage(info.parsed, elements);
643
645
  return { log: log2, element: element2, visible: visible2, attached: !!element2 };
644
646
  }, { info: resolved.info, root: resolved.frame === this ? scope : void 0 }));
645
647
  const { log, visible, attached } = await progress.race(result.evaluate((r) => ({ log: r.log, visible: r.visible, attached: r.attached })));
@@ -735,7 +737,7 @@ class Frame extends import_instrumentation.SdkObject {
735
737
  this._onClearLifecycle();
736
738
  tagPromise.resolve();
737
739
  });
738
- const lifecyclePromise = progress.race(tagPromise).then(() => this._waitForLoadState(progress, waitUntil));
740
+ const lifecyclePromise = progress.race(tagPromise).then(() => this.waitForLoadState(progress, waitUntil));
739
741
  const contentPromise = progress.race(context.evaluate(({ html: html2, tag: tag2 }) => {
740
742
  document.open();
741
743
  console.debug(tag2);
@@ -905,14 +907,19 @@ class Frame extends import_instrumentation.SdkObject {
905
907
  return true;
906
908
  return false;
907
909
  }
908
- async _retryWithProgressIfNotConnected(progress, selector, strict, performActionPreChecks, action) {
910
+ async _retryWithProgressIfNotConnected(progress, selector, options, action) {
909
911
  progress.log(`waiting for ${this._asLocator(selector)}`);
912
+ const noAutoWaiting = options.__testHookNoAutoWaiting ?? options.noAutoWaiting;
913
+ const performActionPreChecks = (options.performActionPreChecks ?? !options.force) && !noAutoWaiting;
910
914
  return this.retryWithProgressAndTimeouts(progress, [0, 20, 50, 100, 100, 500], async (continuePolling) => {
911
915
  if (performActionPreChecks)
912
916
  await this._page.performActionPreChecks(progress);
913
- const resolved = await progress.race(this.selectors.resolveInjectedForSelector(selector, { strict }));
914
- if (!resolved)
917
+ const resolved = await progress.race(this.selectors.resolveInjectedForSelector(selector, { strict: options.strict }));
918
+ if (!resolved) {
919
+ if (noAutoWaiting)
920
+ throw new dom.NonRecoverableDOMError("Element(s) not found");
915
921
  return continuePolling;
922
+ }
916
923
  const result = await progress.race(resolved.injected.evaluateHandle((injected, { info, callId }) => {
917
924
  const elements = injected.querySelectorAll(info.parsed, document);
918
925
  if (callId)
@@ -926,12 +933,15 @@ class Frame extends import_instrumentation.SdkObject {
926
933
  } else if (element2) {
927
934
  log2 = ` locator resolved to ${injected.previewNode(element2)}`;
928
935
  }
936
+ injected.checkDeprecatedSelectorUsage(info.parsed, elements);
929
937
  return { log: log2, success: !!element2, element: element2 };
930
938
  }, { info: resolved.info, callId: progress.metadata.id }));
931
939
  const { log, success } = await progress.race(result.evaluate((r) => ({ log: r.log, success: r.success })));
932
940
  if (log)
933
941
  progress.log(log);
934
942
  if (!success) {
943
+ if (noAutoWaiting)
944
+ throw new dom.NonRecoverableDOMError("Element(s) not found");
935
945
  result.dispose();
936
946
  return continuePolling;
937
947
  }
@@ -940,6 +950,8 @@ class Frame extends import_instrumentation.SdkObject {
940
950
  try {
941
951
  const result2 = await action(element);
942
952
  if (result2 === "error:notconnected") {
953
+ if (noAutoWaiting)
954
+ throw new dom.NonRecoverableDOMError("Element is not attached to the DOM");
943
955
  progress.log("element was detached from the DOM, retrying");
944
956
  return continuePolling;
945
957
  }
@@ -950,19 +962,19 @@ class Frame extends import_instrumentation.SdkObject {
950
962
  });
951
963
  }
952
964
  async rafrafTimeoutScreenshotElementWithProgress(progress, selector, timeout, options) {
953
- return await this._retryWithProgressIfNotConnected(progress, selector, true, true, async (handle) => {
965
+ return await this._retryWithProgressIfNotConnected(progress, selector, { strict: true, performActionPreChecks: true }, async (handle) => {
954
966
  await handle._frame.rafrafTimeout(progress, timeout);
955
967
  return await this._page.screenshotter.screenshotElement(progress, handle, options);
956
968
  });
957
969
  }
958
970
  async click(progress, selector, options) {
959
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._click(progress, { ...options, waitAfter: !options.noWaitAfter })));
971
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._click(progress, { ...options, waitAfter: !options.noWaitAfter })));
960
972
  }
961
973
  async dblclick(progress, selector, options) {
962
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._dblclick(progress, options)));
974
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._dblclick(progress, options)));
963
975
  }
964
976
  async dragAndDrop(progress, source, target, options) {
965
- dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options.strict, !options.force, async (handle) => {
977
+ dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options, async (handle) => {
966
978
  return handle._retryPointerAction(progress, "move and down", false, async (point) => {
967
979
  await this._page.mouse.move(progress, point.x, point.y);
968
980
  await this._page.mouse.down(progress);
@@ -972,7 +984,7 @@ class Frame extends import_instrumentation.SdkObject {
972
984
  position: options.sourcePosition
973
985
  });
974
986
  }));
975
- dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options.strict, false, async (handle) => {
987
+ dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, { ...options, performActionPreChecks: false }, async (handle) => {
976
988
  return handle._retryPointerAction(progress, "move and up", false, async (point) => {
977
989
  await this._page.mouse.move(progress, point.x, point.y, { steps: options.steps });
978
990
  await this._page.mouse.up(progress);
@@ -986,16 +998,16 @@ class Frame extends import_instrumentation.SdkObject {
986
998
  async tap(progress, selector, options) {
987
999
  if (!this._page.browserContext._options.hasTouch)
988
1000
  throw new Error("The page does not support tap. Use hasTouch context option to enable touch support.");
989
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._tap(progress, options)));
1001
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._tap(progress, options)));
990
1002
  }
991
1003
  async fill(progress, selector, value, options) {
992
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._fill(progress, value, options)));
1004
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._fill(progress, value, options)));
993
1005
  }
994
1006
  async focus(progress, selector, options) {
995
- dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._focus(progress)));
1007
+ dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._focus(progress)));
996
1008
  }
997
1009
  async blur(progress, selector, options) {
998
- dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._blur(progress)));
1010
+ dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._blur(progress)));
999
1011
  }
1000
1012
  async resolveSelector(progress, selector, options = {}) {
1001
1013
  const element = await progress.race(this.selectors.query(selector, options));
@@ -1109,35 +1121,35 @@ class Frame extends import_instrumentation.SdkObject {
1109
1121
  return this._elementState(progress, selector, "checked", options, scope);
1110
1122
  }
1111
1123
  async hover(progress, selector, options) {
1112
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._hover(progress, options)));
1124
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._hover(progress, options)));
1113
1125
  }
1114
1126
  async selectOption(progress, selector, elements, values, options) {
1115
- return await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._selectOption(progress, elements, values, options));
1127
+ return await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._selectOption(progress, elements, values, options));
1116
1128
  }
1117
1129
  async setInputFiles(progress, selector, params) {
1118
1130
  const inputFileItems = await (0, import_fileUploadUtils.prepareFilesForUpload)(this, params);
1119
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params.strict, true, (handle) => handle._setInputFiles(progress, inputFileItems)));
1131
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params, (handle) => handle._setInputFiles(progress, inputFileItems)));
1120
1132
  }
1121
1133
  async type(progress, selector, text, options) {
1122
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._type(progress, text, options)));
1134
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._type(progress, text, options)));
1123
1135
  }
1124
1136
  async press(progress, selector, key, options) {
1125
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._press(progress, key, options)));
1137
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._press(progress, key, options)));
1126
1138
  }
1127
1139
  async check(progress, selector, options) {
1128
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._setChecked(progress, true, options)));
1140
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._setChecked(progress, true, options)));
1129
1141
  }
1130
1142
  async uncheck(progress, selector, options) {
1131
- return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._setChecked(progress, false, options)));
1143
+ return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._setChecked(progress, false, options)));
1132
1144
  }
1133
1145
  async waitForTimeout(progress, timeout) {
1134
1146
  return progress.wait(timeout);
1135
1147
  }
1136
1148
  async ariaSnapshot(progress, selector) {
1137
- return await this._retryWithProgressIfNotConnected(progress, selector, true, true, (handle) => progress.race(handle.ariaSnapshot()));
1149
+ return await this._retryWithProgressIfNotConnected(progress, selector, { strict: true, performActionPreChecks: true }, (handle) => progress.race(handle.ariaSnapshot()));
1138
1150
  }
1139
- async expect(progress, selector, options, timeout) {
1140
- progress.log(`${(0, import_utils.renderTitleForCall)(progress.metadata)}${timeout ? ` with timeout ${timeout}ms` : ""}`);
1151
+ async expect(progress, selector, options) {
1152
+ progress.log(`${(0, import_utils.renderTitleForCall)(progress.metadata)}${options.timeoutForLogs ? ` with timeout ${options.timeoutForLogs}ms` : ""}`);
1141
1153
  const lastIntermediateResult = { isSet: false };
1142
1154
  const fixupMetadataError = (result) => {
1143
1155
  if (result.matches === options.isNot)
@@ -1146,17 +1158,19 @@ class Frame extends import_instrumentation.SdkObject {
1146
1158
  try {
1147
1159
  if (selector)
1148
1160
  progress.log(`waiting for ${this._asLocator(selector)}`);
1149
- await this._page.performActionPreChecks(progress);
1161
+ if (!options.noAutoWaiting)
1162
+ await this._page.performActionPreChecks(progress);
1150
1163
  try {
1151
1164
  const resultOneShot = await this._expectInternal(progress, selector, options, lastIntermediateResult, true);
1152
- if (resultOneShot.matches !== options.isNot)
1165
+ if (options.noAutoWaiting || resultOneShot.matches !== options.isNot)
1153
1166
  return resultOneShot;
1154
1167
  } catch (e) {
1155
- if (this.isNonRetriableError(e))
1168
+ if (options.noAutoWaiting || this.isNonRetriableError(e))
1156
1169
  throw e;
1157
1170
  }
1158
1171
  const result = await this.retryWithProgressAndTimeouts(progress, [100, 250, 500, 1e3], async (continuePolling) => {
1159
- await this._page.performActionPreChecks(progress);
1172
+ if (!options.noAutoWaiting)
1173
+ await this._page.performActionPreChecks(progress);
1160
1174
  const { matches, received } = await this._expectInternal(progress, selector, options, lastIntermediateResult, false);
1161
1175
  if (matches === options.isNot) {
1162
1176
  return continuePolling;
@@ -1200,6 +1214,8 @@ class Frame extends import_instrumentation.SdkObject {
1200
1214
  throw injected2.strictModeViolationError(info2.parsed, elements);
1201
1215
  else if (elements.length)
1202
1216
  log2 = ` locator resolved to ${injected2.previewNode(elements[0])}`;
1217
+ if (info2)
1218
+ injected2.checkDeprecatedSelectorUsage(info2.parsed, elements);
1203
1219
  return { log: log2, ...await injected2.expect(elements[0], options2, elements) };
1204
1220
  }, { info, options, callId: progress.metadata.id }));
1205
1221
  if (log)
@@ -33,6 +33,9 @@ class SdkObject extends import_events.EventEmitter {
33
33
  this.attribution = { ...parent.attribution };
34
34
  this.instrumentation = parent.instrumentation;
35
35
  }
36
+ closeReason() {
37
+ return this.attribution.page?._closeReason || this.attribution.context?._closeReason || this.attribution.browser?._closeReason;
38
+ }
36
39
  }
37
40
  function createRootSdkObject() {
38
41
  const fakeParent = { attribution: {}, instrumentation: createInstrumentation() };