patchright-core 1.56.1 → 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 (180) hide show
  1. package/ThirdPartyNotices.txt +3134 -560
  2. package/bin/install_webkit_wsl.ps1 +1 -3
  3. package/browsers.json +21 -22
  4. package/lib/cli/program.js +16 -60
  5. package/lib/client/api.js +3 -3
  6. package/lib/client/browser.js +3 -5
  7. package/lib/client/browserContext.js +62 -8
  8. package/lib/client/browserType.js +4 -3
  9. package/lib/client/connection.js +4 -0
  10. package/lib/client/consoleMessage.js +5 -1
  11. package/lib/client/electron.js +1 -1
  12. package/lib/client/elementHandle.js +3 -0
  13. package/lib/client/events.js +5 -1
  14. package/lib/client/fetch.js +3 -4
  15. package/lib/client/frame.js +10 -1
  16. package/lib/client/locator.js +12 -1
  17. package/lib/client/network.js +5 -1
  18. package/lib/client/page.js +31 -6
  19. package/lib/client/pageAgent.js +64 -0
  20. package/lib/client/platform.js +3 -0
  21. package/lib/client/playwright.js +1 -5
  22. package/lib/client/tracing.js +7 -5
  23. package/lib/client/worker.js +22 -0
  24. package/lib/generated/clockSource.js +1 -1
  25. package/lib/generated/injectedScriptSource.js +1 -1
  26. package/lib/generated/pollingRecorderSource.js +1 -1
  27. package/lib/inProcessFactory.js +0 -2
  28. package/lib/mcpBundle.js +84 -0
  29. package/lib/mcpBundleImpl/index.js +147 -0
  30. package/lib/protocol/serializers.js +5 -0
  31. package/lib/protocol/validator.js +112 -50
  32. package/lib/remote/playwrightServer.js +1 -2
  33. package/lib/server/agent/actionRunner.js +335 -0
  34. package/lib/server/agent/actions.js +128 -0
  35. package/lib/server/agent/codegen.js +111 -0
  36. package/lib/server/agent/context.js +150 -0
  37. package/lib/server/agent/expectTools.js +156 -0
  38. package/lib/server/agent/pageAgent.js +204 -0
  39. package/lib/server/agent/performTools.js +262 -0
  40. package/lib/server/agent/tool.js +109 -0
  41. package/lib/server/android/android.js +1 -1
  42. package/lib/server/artifact.js +1 -1
  43. package/lib/server/bidi/bidiBrowser.js +81 -22
  44. package/lib/server/bidi/bidiChromium.js +9 -13
  45. package/lib/server/bidi/bidiConnection.js +1 -0
  46. package/lib/server/bidi/bidiDeserializer.js +116 -0
  47. package/lib/server/bidi/bidiExecutionContext.js +75 -29
  48. package/lib/server/bidi/bidiFirefox.js +7 -9
  49. package/lib/server/bidi/bidiNetworkManager.js +1 -1
  50. package/lib/server/bidi/bidiPage.js +61 -30
  51. package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
  52. package/lib/server/browserContext.js +43 -36
  53. package/lib/server/browserType.js +12 -4
  54. package/lib/server/chromium/chromium.js +26 -21
  55. package/lib/server/chromium/chromiumSwitches.js +12 -3
  56. package/lib/server/chromium/crBrowser.js +30 -12
  57. package/lib/server/chromium/crConnection.js +0 -5
  58. package/lib/server/chromium/crCoverage.js +13 -1
  59. package/lib/server/chromium/crDevTools.js +0 -2
  60. package/lib/server/chromium/crNetworkManager.js +107 -18
  61. package/lib/server/chromium/crPage.js +68 -124
  62. package/lib/server/chromium/crServiceWorker.js +14 -1
  63. package/lib/server/codegen/javascript.js +6 -29
  64. package/lib/server/console.js +5 -1
  65. package/lib/server/deviceDescriptorsSource.json +56 -56
  66. package/lib/server/dispatchers/browserContextDispatcher.js +26 -8
  67. package/lib/server/dispatchers/dispatcher.js +6 -13
  68. package/lib/server/dispatchers/frameDispatcher.js +1 -1
  69. package/lib/server/dispatchers/jsHandleDispatcher.js +2 -2
  70. package/lib/server/dispatchers/pageAgentDispatcher.js +96 -0
  71. package/lib/server/dispatchers/pageDispatcher.js +14 -22
  72. package/lib/server/dispatchers/playwrightDispatcher.js +0 -4
  73. package/lib/server/dom.js +12 -3
  74. package/lib/server/electron/electron.js +6 -3
  75. package/lib/server/firefox/ffBrowser.js +10 -20
  76. package/lib/server/firefox/ffConnection.js +0 -5
  77. package/lib/server/firefox/ffNetworkManager.js +2 -2
  78. package/lib/server/firefox/ffPage.js +18 -24
  79. package/lib/server/firefox/firefox.js +18 -9
  80. package/lib/server/frameSelectors.js +18 -8
  81. package/lib/server/frames.js +257 -87
  82. package/lib/server/input.js +7 -3
  83. package/lib/server/instrumentation.js +3 -0
  84. package/lib/server/javascript.js +8 -4
  85. package/lib/server/launchApp.js +2 -1
  86. package/lib/server/localUtils.js +4 -8
  87. package/lib/server/network.js +50 -12
  88. package/lib/server/page.js +112 -126
  89. package/lib/server/playwright.js +2 -4
  90. package/lib/server/progress.js +26 -6
  91. package/lib/server/recorder/recorderApp.js +80 -101
  92. package/lib/server/recorder.js +3 -2
  93. package/lib/server/registry/browserFetcher.js +6 -4
  94. package/lib/server/registry/index.js +278 -189
  95. package/lib/server/registry/oopDownloadBrowserMain.js +9 -2
  96. package/lib/server/screencast.js +190 -0
  97. package/lib/server/screenshotter.js +6 -0
  98. package/lib/server/socksClientCertificatesInterceptor.js +1 -1
  99. package/lib/server/trace/recorder/snapshotter.js +17 -8
  100. package/lib/server/trace/recorder/snapshotterInjected.js +30 -72
  101. package/lib/server/trace/recorder/tracing.js +31 -21
  102. package/lib/server/trace/viewer/traceParser.js +72 -0
  103. package/lib/server/trace/viewer/traceViewer.js +45 -40
  104. package/lib/server/utils/comparators.js +3 -25
  105. package/lib/server/utils/expectUtils.js +87 -2
  106. package/lib/server/utils/hostPlatform.js +30 -3
  107. package/lib/server/utils/httpServer.js +5 -20
  108. package/lib/server/utils/imageUtils.js +141 -0
  109. package/lib/server/utils/network.js +55 -40
  110. package/lib/server/utils/nodePlatform.js +6 -0
  111. package/lib/server/{chromium/videoRecorder.js → videoRecorder.js} +35 -24
  112. package/lib/server/webkit/webkit.js +5 -16
  113. package/lib/server/webkit/wkBrowser.js +2 -6
  114. package/lib/server/webkit/wkConnection.js +1 -6
  115. package/lib/server/webkit/wkInterceptableRequest.js +29 -1
  116. package/lib/server/webkit/wkPage.js +76 -51
  117. package/lib/server/webkit/wkWorkers.js +2 -1
  118. package/lib/utils/isomorphic/ariaSnapshot.js +63 -0
  119. package/lib/utils/isomorphic/locatorGenerators.js +24 -8
  120. package/lib/utils/isomorphic/lruCache.js +51 -0
  121. package/lib/utils/isomorphic/mimeType.js +1 -1
  122. package/lib/utils/isomorphic/protocolFormatter.js +3 -0
  123. package/lib/utils/isomorphic/protocolMetainfo.js +11 -2
  124. package/lib/utils/isomorphic/stringUtils.js +49 -0
  125. package/lib/utils/isomorphic/trace/entries.js +16 -0
  126. package/lib/utils/isomorphic/trace/snapshotRenderer.js +499 -0
  127. package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
  128. package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
  129. package/lib/utils/isomorphic/trace/traceLoader.js +131 -0
  130. package/lib/utils/isomorphic/trace/traceModel.js +365 -0
  131. package/lib/utils/isomorphic/trace/traceModernizer.js +400 -0
  132. package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
  133. package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
  134. package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
  135. package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
  136. package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
  137. package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
  138. package/lib/utils/isomorphic/urlMatch.js +19 -5
  139. package/lib/utils/isomorphic/yaml.js +84 -0
  140. package/lib/utils.js +4 -0
  141. package/lib/utilsBundle.js +1 -1
  142. package/lib/utilsBundleImpl/index.js +124 -124
  143. package/lib/vite/htmlReport/index.html +21 -21
  144. package/lib/vite/recorder/assets/codeMirrorModule-CFUTFUO7.js +32 -0
  145. package/lib/vite/recorder/assets/{codeMirrorModule-C3UTv-Ge.css → codeMirrorModule-DYBRYzYX.css} +1 -1
  146. package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
  147. package/lib/vite/recorder/assets/index-CVkBxsGf.js +193 -0
  148. package/lib/vite/recorder/index.html +2 -2
  149. package/lib/vite/traceViewer/assets/codeMirrorModule-BVA4h_ZY.js +32 -0
  150. package/lib/vite/traceViewer/assets/defaultSettingsView-CjfmcdOz.js +266 -0
  151. package/lib/vite/traceViewer/{codeMirrorModule.C3UTv-Ge.css → codeMirrorModule.DYBRYzYX.css} +1 -1
  152. package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +1 -0
  153. package/lib/vite/traceViewer/index.BVu7tZDe.css +1 -0
  154. package/lib/vite/traceViewer/index.BtyWtaE-.js +2 -0
  155. package/lib/vite/traceViewer/index.html +6 -6
  156. package/lib/vite/traceViewer/manifest.webmanifest +16 -0
  157. package/lib/vite/traceViewer/snapshot.html +3 -3
  158. package/lib/vite/traceViewer/sw.bundle.js +5 -3
  159. package/lib/vite/traceViewer/uiMode.fyrXARf2.js +5 -0
  160. package/lib/vite/traceViewer/uiMode.html +3 -3
  161. package/package.json +2 -1
  162. package/types/protocol.d.ts +939 -245
  163. package/types/types.d.ts +143 -153
  164. package/lib/client/accessibility.js +0 -49
  165. package/lib/server/accessibility.js +0 -69
  166. package/lib/server/bidi/third_party/bidiDeserializer.js +0 -98
  167. package/lib/server/chromium/crAccessibility.js +0 -263
  168. package/lib/server/firefox/ffAccessibility.js +0 -238
  169. package/lib/server/trace/test/inMemorySnapshotter.js +0 -87
  170. package/lib/server/webkit/wkAccessibility.js +0 -237
  171. package/lib/server/webkit/wsl/webkit-wsl-transport-client.js +0 -74
  172. package/lib/server/webkit/wsl/webkit-wsl-transport-server.js +0 -113
  173. package/lib/vite/recorder/assets/codeMirrorModule-RJCXzfmE.js +0 -24
  174. package/lib/vite/recorder/assets/index-Y-X2TGJv.js +0 -193
  175. package/lib/vite/traceViewer/assets/codeMirrorModule-rbQPefq7.js +0 -24
  176. package/lib/vite/traceViewer/assets/defaultSettingsView-CLbol9XR.js +0 -265
  177. package/lib/vite/traceViewer/defaultSettingsView.TQ8_7ybu.css +0 -1
  178. package/lib/vite/traceViewer/index.I8N9v4jT.css +0 -1
  179. package/lib/vite/traceViewer/index.zIVi6mN9.js +0 -2
  180. package/lib/vite/traceViewer/uiMode.B_CpmIpF.js +0 -5
@@ -182,9 +182,9 @@ class Mouse {
182
182
  await this._raw.up(progress, this._x, this._y, button, this._buttons, this._keyboard._modifiers(), clickCount);
183
183
  }
184
184
  async click(progress, x, y, options = {}) {
185
- const { delay = null, clickCount = 1 } = options;
185
+ const { delay = null, clickCount = 1, steps } = options;
186
186
  if (delay) {
187
- this.move(progress, x, y, { forClick: true });
187
+ await this.move(progress, x, y, { forClick: true, steps });
188
188
  for (let cc = 1; cc <= clickCount; ++cc) {
189
189
  await this.down(progress, { ...options, clickCount: cc });
190
190
  await progress.wait(delay);
@@ -194,7 +194,11 @@ class Mouse {
194
194
  }
195
195
  } else {
196
196
  const promises = [];
197
- promises.push(this.move(progress, x, y, { forClick: true }));
197
+ const movePromise = this.move(progress, x, y, { forClick: true, steps });
198
+ if (steps !== void 0 && steps > 1)
199
+ await movePromise;
200
+ else
201
+ promises.push(movePromise);
198
202
  for (let cc = 1; cc <= clickCount; ++cc) {
199
203
  promises.push(this.down(progress, { ...options, clickCount: cc }));
200
204
  promises.push(this.up(progress, { ...options, clickCount: cc }));
@@ -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() };
@@ -118,10 +118,12 @@ class JSHandle extends import_instrumentation.SdkObject {
118
118
  if (context.constructor.name === "FrameExecutionContext") {
119
119
  const frame = context.frame;
120
120
  if (frame) {
121
- if (isolatedContext) context = await frame._utilityContext();
122
- else if (!isolatedContext) context = await frame._mainContext();
121
+ if (isolatedContext === true) context = await frame._utilityContext();
122
+ else if (isolatedContext === false) context = await frame._mainContext();
123
123
  }
124
124
  }
125
+ if (context !== this._context && context.adoptIfNeeded(this) === null)
126
+ context = this._context;
125
127
  const value = await evaluateExpression(context, expression, { ...options, returnByValue: true }, this, arg);
126
128
  await context.doSlowMo();
127
129
  return value;
@@ -131,10 +133,12 @@ class JSHandle extends import_instrumentation.SdkObject {
131
133
  if (context.constructor.name === "FrameExecutionContext") {
132
134
  const frame = this._context.frame;
133
135
  if (frame) {
134
- if (isolatedContext) context = await frame._utilityContext();
135
- else if (!isolatedContext) context = await frame._mainContext();
136
+ if (isolatedContext === true) context = await frame._utilityContext();
137
+ else if (isolatedContext === false) context = await frame._mainContext();
136
138
  }
137
139
  }
140
+ if (context !== this._context && context.adoptIfNeeded(this) === null)
141
+ context = this._context;
138
142
  const value = await evaluateExpression(context, expression, { ...options, returnByValue: false }, this, arg);
139
143
  await context.doSlowMo();
140
144
  return value;
@@ -114,7 +114,8 @@ async function syncLocalStorageWithSettings(page, appName) {
114
114
  return;
115
115
  Object.entries(settings2).map(([k, v]) => localStorage[k] = v);
116
116
  window.saveSettings = () => {
117
- window._saveSerializedSettings(JSON.stringify({ ...localStorage }));
117
+ if (typeof window._saveSerializedSettings === "function")
118
+ window._saveSerializedSettings(JSON.stringify({ ...localStorage }));
118
119
  };
119
120
  })})(${settings});
120
121
  `
@@ -65,12 +65,8 @@ async function zip(progress, stackSessions, params) {
65
65
  const stackSession = params.stacksId ? stackSessions.get(params.stacksId) : void 0;
66
66
  if (stackSession?.callStacks.length) {
67
67
  await progress.race(stackSession.writer);
68
- if (process.env.PW_LIVE_TRACE_STACKS) {
69
- zipFile.addFile(stackSession.file, "trace.stacks");
70
- } else {
71
- const buffer = Buffer.from(JSON.stringify((0, import_traceUtils.serializeClientSideCallMetadata)(stackSession.callStacks)));
72
- zipFile.addBuffer(buffer, "trace.stacks");
73
- }
68
+ const buffer = Buffer.from(JSON.stringify((0, import_traceUtils.serializeClientSideCallMetadata)(stackSession.callStacks)));
69
+ zipFile.addBuffer(buffer, "trace.stacks");
74
70
  }
75
71
  if (params.includeSources) {
76
72
  const sourceFiles = /* @__PURE__ */ new Set();
@@ -188,7 +184,7 @@ async function tracingStarted(progress, stackSessions, params) {
188
184
  if (!params.tracesDir)
189
185
  tmpDir = await progress.race(import_fs.default.promises.mkdtemp(import_path.default.join(import_os.default.tmpdir(), "playwright-tracing-")));
190
186
  const traceStacksFile = import_path.default.join(params.tracesDir || tmpDir, params.traceName + ".stacks");
191
- stackSessions.set(traceStacksFile, { callStacks: [], file: traceStacksFile, writer: Promise.resolve(), tmpDir });
187
+ stackSessions.set(traceStacksFile, { callStacks: [], file: traceStacksFile, writer: Promise.resolve(), tmpDir, live: params.live });
192
188
  return { stacksId: traceStacksFile };
193
189
  }
194
190
  async function traceDiscarded(progress, stackSessions, params) {
@@ -197,7 +193,7 @@ async function traceDiscarded(progress, stackSessions, params) {
197
193
  function addStackToTracingNoReply(stackSessions, params) {
198
194
  for (const session of stackSessions.values()) {
199
195
  session.callStacks.push(params.callData);
200
- if (process.env.PW_LIVE_TRACE_STACKS) {
196
+ if (session.live) {
201
197
  session.writer = session.writer.then(() => {
202
198
  const buffer = Buffer.from(JSON.stringify((0, import_traceUtils.serializeClientSideCallMetadata)(session.callStacks)));
203
199
  return import_fs.default.promises.writeFile(session.file, buffer);
@@ -22,6 +22,7 @@ __export(network_exports, {
22
22
  Response: () => Response,
23
23
  Route: () => Route,
24
24
  WebSocket: () => WebSocket,
25
+ applyHeadersOverrides: () => applyHeadersOverrides,
25
26
  filterCookies: () => filterCookies,
26
27
  isLocalHostname: () => isLocalHostname,
27
28
  kMaxCookieExpiresDateInSeconds: () => kMaxCookieExpiresDateInSeconds,
@@ -61,6 +62,48 @@ function filterCookies(cookies, urls) {
61
62
  function isLocalHostname(hostname) {
62
63
  return hostname === "localhost" || hostname.endsWith(".localhost");
63
64
  }
65
+ const FORBIDDEN_HEADER_NAMES = /* @__PURE__ */ new Set([
66
+ "accept-charset",
67
+ "accept-encoding",
68
+ "access-control-request-headers",
69
+ "access-control-request-method",
70
+ "connection",
71
+ "content-length",
72
+ "cookie",
73
+ "date",
74
+ "dnt",
75
+ "expect",
76
+ "host",
77
+ "keep-alive",
78
+ "origin",
79
+ "referer",
80
+ "set-cookie",
81
+ "te",
82
+ "trailer",
83
+ "transfer-encoding",
84
+ "upgrade",
85
+ "via"
86
+ ]);
87
+ const FORBIDDEN_METHODS = /* @__PURE__ */ new Set(["CONNECT", "TRACE", "TRACK"]);
88
+ function isForbiddenHeader(name, value) {
89
+ const lowerName = name.toLowerCase();
90
+ if (FORBIDDEN_HEADER_NAMES.has(lowerName))
91
+ return true;
92
+ if (lowerName.startsWith("proxy-"))
93
+ return true;
94
+ if (lowerName.startsWith("sec-"))
95
+ return true;
96
+ if (lowerName === "x-http-method" || lowerName === "x-http-method-override" || lowerName === "x-method-override") {
97
+ if (value && FORBIDDEN_METHODS.has(value.toUpperCase()))
98
+ return true;
99
+ }
100
+ return false;
101
+ }
102
+ function applyHeadersOverrides(original, overrides) {
103
+ const forbiddenHeaders = original.filter((header) => isForbiddenHeader(header.name, header.value));
104
+ const allowedHeaders = overrides.filter((header) => !isForbiddenHeader(header.name, header.value));
105
+ return mergeHeaders([allowedHeaders, forbiddenHeaders]);
106
+ }
64
107
  const kMaxCookieExpiresDateInSeconds = 253402300799;
65
108
  function rewriteCookies(cookies) {
66
109
  return cookies.map((c) => {
@@ -99,7 +142,6 @@ class Request extends import_instrumentation.SdkObject {
99
142
  this._response = null;
100
143
  this._redirectedTo = null;
101
144
  this._failureText = null;
102
- this._headersMap = /* @__PURE__ */ new Map();
103
145
  this._frame = null;
104
146
  this._serviceWorker = null;
105
147
  this._rawRequestHeadersPromise = new import_manualPromise.ManualPromise();
@@ -118,7 +160,6 @@ class Request extends import_instrumentation.SdkObject {
118
160
  this._method = method;
119
161
  this._postData = postData;
120
162
  this._headers = headers;
121
- this._updateHeadersMap();
122
163
  this._isFavicon = url.endsWith("/favicon.ico") || !!redirectedFrom?._isFavicon;
123
164
  }
124
165
  static {
@@ -132,13 +173,8 @@ class Request extends import_instrumentation.SdkObject {
132
173
  }
133
174
  _applyOverrides(overrides) {
134
175
  this._overrides = { ...this._overrides, ...overrides };
135
- this._updateHeadersMap();
136
176
  return this._overrides;
137
177
  }
138
- _updateHeadersMap() {
139
- for (const { name, value } of this.headers())
140
- this._headersMap.set(name.toLowerCase(), value);
141
- }
142
178
  overrides() {
143
179
  return this._overrides;
144
180
  }
@@ -158,7 +194,8 @@ class Request extends import_instrumentation.SdkObject {
158
194
  return this._overrides?.headers || this._headers;
159
195
  }
160
196
  headerValue(name) {
161
- return this._headersMap.get(name);
197
+ const lowerCaseName = name.toLowerCase();
198
+ return this.headers().find((h) => h.name.toLowerCase() === lowerCaseName)?.value;
162
199
  }
163
200
  // "null" means no raw headers available - we'll use provisional headers as raw headers.
164
201
  setRawRequestHeaders(headers) {
@@ -309,10 +346,7 @@ class Route extends import_instrumentation.SdkObject {
309
346
  throw new Error("New URL must have same protocol as overridden URL");
310
347
  }
311
348
  if (overrides.headers) {
312
- overrides.headers = overrides.headers?.filter((header) => {
313
- const headerName = header.name.toLowerCase();
314
- return headerName !== "cookie" && headerName !== "host";
315
- });
349
+ overrides.headers = applyHeadersOverrides(this._request._headers, overrides.headers);
316
350
  }
317
351
  overrides = this._request._applyOverrides(overrides);
318
352
  const nextHandler = this._futureHandlers.shift();
@@ -436,6 +470,9 @@ class Response extends import_instrumentation.SdkObject {
436
470
  request() {
437
471
  return this._request;
438
472
  }
473
+ finished() {
474
+ return this._finishedPromise;
475
+ }
439
476
  frame() {
440
477
  return this._request.frame();
441
478
  }
@@ -617,6 +654,7 @@ function mergeHeaders(headers) {
617
654
  Response,
618
655
  Route,
619
656
  WebSocket,
657
+ applyHeadersOverrides,
620
658
  filterCookies,
621
659
  isLocalHostname,
622
660
  kMaxCookieExpiresDateInSeconds,
@@ -31,11 +31,11 @@ __export(page_exports, {
31
31
  InitScript: () => InitScript,
32
32
  Page: () => Page,
33
33
  PageBinding: () => PageBinding,
34
- Worker: () => Worker
34
+ Worker: () => Worker,
35
+ WorkerEvent: () => WorkerEvent
35
36
  });
36
37
  module.exports = __toCommonJS(page_exports);
37
38
  var import_pageBinding = require("./pageBinding");
38
- var accessibility = __toESM(require("./accessibility"));
39
39
  var import_browserContext = require("./browserContext");
40
40
  var import_console = require("./console");
41
41
  var import_errors = require("./errors");
@@ -54,6 +54,22 @@ var import_selectorParser = require("../utils/isomorphic/selectorParser");
54
54
  var import_manualPromise = require("../utils/isomorphic/manualPromise");
55
55
  var import_utilityScriptSerializers = require("../utils/isomorphic/utilityScriptSerializers");
56
56
  var import_callLog = require("./callLog");
57
+ var import_screencast = require("./screencast");
58
+ const PageEvent = {
59
+ Close: "close",
60
+ Crash: "crash",
61
+ Download: "download",
62
+ EmulatedSizeChanged: "emulatedsizechanged",
63
+ FileChooser: "filechooser",
64
+ FrameAttached: "frameattached",
65
+ FrameDetached: "framedetached",
66
+ InternalFrameNavigatedToNewDocument: "internalframenavigatedtonewdocument",
67
+ LocatorHandlerTriggered: "locatorhandlertriggered",
68
+ ScreencastFrame: "screencastframe",
69
+ Video: "video",
70
+ WebSocket: "websocket",
71
+ Worker: "worker"
72
+ };
57
73
  class Page extends import_instrumentation.SdkObject {
58
74
  constructor(delegate, browserContext) {
59
75
  super(browserContext, "page");
@@ -75,40 +91,22 @@ class Page extends import_instrumentation.SdkObject {
75
91
  this._lastLocatorHandlerUid = 0;
76
92
  this._locatorHandlerRunningCounter = 0;
77
93
  this._networkRequests = [];
78
- // Aiming at 25 fps by default - each frame is 40ms, but we give some slack with 35ms.
79
- // When throttling for tracing, 200ms between frames, except for 10 frames around the action.
80
- this._frameThrottler = new FrameThrottler(10, 35, 200);
81
- this.lastSnapshotFrameIds = [];
82
94
  this.attribution.page = this;
83
95
  this.delegate = delegate;
84
96
  this.browserContext = browserContext;
85
- this.accessibility = new accessibility.Accessibility(delegate.getAccessibilityTree.bind(delegate));
86
97
  this.keyboard = new input.Keyboard(delegate.rawKeyboard, this);
87
98
  this.mouse = new input.Mouse(delegate.rawMouse, this);
88
99
  this.touchscreen = new input.Touchscreen(delegate.rawTouchscreen, this);
89
100
  this.screenshotter = new import_screenshotter.Screenshotter(this);
90
101
  this.frameManager = new frames.FrameManager(this);
102
+ this.screencast = new import_screencast.Screencast(this);
91
103
  if (delegate.pdf)
92
104
  this.pdf = delegate.pdf.bind(delegate);
93
105
  this.coverage = delegate.coverage ? delegate.coverage() : null;
94
106
  this.isStorageStatePage = browserContext.isCreatingStorageStatePage();
95
107
  }
96
108
  static {
97
- this.Events = {
98
- Close: "close",
99
- Crash: "crash",
100
- Download: "download",
101
- EmulatedSizeChanged: "emulatedsizechanged",
102
- FileChooser: "filechooser",
103
- FrameAttached: "frameattached",
104
- FrameDetached: "framedetached",
105
- InternalFrameNavigatedToNewDocument: "internalframenavigatedtonewdocument",
106
- LocatorHandlerTriggered: "locatorhandlertriggered",
107
- ScreencastFrame: "screencastframe",
108
- Video: "video",
109
- WebSocket: "websocket",
110
- Worker: "worker"
111
- };
109
+ this.Events = PageEvent;
112
110
  }
113
111
  async reportAsNew(opener, error) {
114
112
  if (opener) {
@@ -161,17 +159,17 @@ class Page extends import_instrumentation.SdkObject {
161
159
  }
162
160
  _didClose() {
163
161
  this.frameManager.dispose();
164
- this._frameThrottler.dispose();
162
+ this.screencast.stopFrameThrottler();
165
163
  (0, import_utils.assert)(this._closedState !== "closed", "Page closed twice");
166
164
  this._closedState = "closed";
167
165
  this.emit(Page.Events.Close);
168
166
  this._closedPromise.resolve();
169
167
  this.instrumentation.onPageClose(this);
170
- this.openScope.close(new import_errors.TargetClosedError());
168
+ this.openScope.close(new import_errors.TargetClosedError(this.closeReason()));
171
169
  }
172
170
  _didCrash() {
173
171
  this.frameManager.dispose();
174
- this._frameThrottler.dispose();
172
+ this.screencast.stopFrameThrottler();
175
173
  this.emit(Page.Events.Crash);
176
174
  this._crashed = true;
177
175
  this.instrumentation.onPageClose(this);
@@ -243,8 +241,8 @@ class Page extends import_instrumentation.SdkObject {
243
241
  return;
244
242
  await PageBinding.dispatch(this, payload, context);
245
243
  }
246
- addConsoleMessage(type, args, location, text) {
247
- const message = new import_console.ConsoleMessage(this, type, text, args, location);
244
+ addConsoleMessage(worker, type, args, location, text) {
245
+ const message = new import_console.ConsoleMessage(this, worker, type, text, args, location);
248
246
  const intercepted = this.frameManager.interceptConsoleMessage(message);
249
247
  if (intercepted) {
250
248
  args.forEach((arg) => arg.dispose());
@@ -341,6 +339,8 @@ class Page extends import_instrumentation.SdkObject {
341
339
  await this._performWaitForNavigationCheck(progress);
342
340
  }
343
341
  async _performWaitForNavigationCheck(progress) {
342
+ if (process.env.PLAYWRIGHT_SKIP_NAVIGATION_CHECK)
343
+ return;
344
344
  const mainFrame = this.frameManager.mainFrame();
345
345
  if (!mainFrame || !mainFrame.pendingDocument())
346
346
  return;
@@ -568,10 +568,11 @@ class Page extends import_instrumentation.SdkObject {
568
568
  if (this._closedState === "closed")
569
569
  return;
570
570
  if (options.reason)
571
- this.closeReason = options.reason;
571
+ this._closeReason = options.reason;
572
572
  const runBeforeUnload = !!options.runBeforeUnload;
573
573
  if (this._closedState !== "closing") {
574
- this._closedState = "closing";
574
+ if (!runBeforeUnload)
575
+ this._closedState = "closing";
575
576
  await this.delegate.closePage(runBeforeUnload).catch((e) => import_debugLogger.debugLogger.log("error", e));
576
577
  }
577
578
  if (!runBeforeUnload)
@@ -624,16 +625,6 @@ class Page extends import_instrumentation.SdkObject {
624
625
  getBinding(name) {
625
626
  return this._pageBindings.get(name) || this.browserContext._pageBindings.get(name);
626
627
  }
627
- setScreencastOptions(options) {
628
- this.delegate.setScreencastOptions(options).catch((e) => import_debugLogger.debugLogger.log("error", e));
629
- this._frameThrottler.setThrottlingEnabled(!!options);
630
- }
631
- throttleScreencastFrameAck(ack) {
632
- this._frameThrottler.ack(ack);
633
- }
634
- temporarilyDisableTracingScreencastThrottling() {
635
- this._frameThrottler.recharge();
636
- }
637
628
  async safeNonStallingEvaluateInAllFrames(expression, world, options = {}) {
638
629
  await Promise.all(this.frames().map(async (frame) => {
639
630
  try {
@@ -648,35 +639,40 @@ class Page extends import_instrumentation.SdkObject {
648
639
  await Promise.all(this.frames().map((frame) => frame.hideHighlight().catch(() => {
649
640
  })));
650
641
  }
651
- async snapshotForAI(progress) {
652
- this.lastSnapshotFrameIds = [];
653
- const snapshot = await snapshotFrameForAI(progress, this.mainFrame(), 0, this.lastSnapshotFrameIds);
654
- return snapshot.join("\n");
642
+ async snapshotForAI(progress, options = {}) {
643
+ const snapshot = await snapshotFrameForAI(progress, this.mainFrame(), options);
644
+ return { full: snapshot.full.join("\n"), incremental: snapshot.incremental?.join("\n") };
655
645
  }
656
646
  allBindings() {
657
647
  return [...this.browserContext._pageBindings.values(), ...this._pageBindings.values()];
658
648
  }
659
649
  }
650
+ const WorkerEvent = {
651
+ Close: "close"
652
+ };
660
653
  class Worker extends import_instrumentation.SdkObject {
661
654
  constructor(parent, url) {
662
655
  super(parent, "worker");
656
+ this._executionContextPromise = new import_manualPromise.ManualPromise();
657
+ this._workerScriptLoaded = false;
663
658
  this.existingExecutionContext = null;
664
659
  this.openScope = new import_utils.LongStandingScope();
665
660
  this.url = url;
666
- this._executionContextCallback = () => {
667
- };
668
- this._executionContextPromise = new Promise((x) => this._executionContextCallback = x);
669
661
  }
670
662
  static {
671
- this.Events = {
672
- Close: "close"
673
- };
663
+ this.Events = WorkerEvent;
674
664
  }
675
665
  createExecutionContext(delegate) {
676
666
  this.existingExecutionContext = new js.ExecutionContext(this, delegate, "worker");
677
- this._executionContextCallback(this.existingExecutionContext);
667
+ if (this._workerScriptLoaded)
668
+ this._executionContextPromise.resolve(this.existingExecutionContext);
678
669
  return this.existingExecutionContext;
679
670
  }
671
+ workerScriptLoaded() {
672
+ this._workerScriptLoaded = true;
673
+ if (this.existingExecutionContext)
674
+ this._executionContextPromise.resolve(this.existingExecutionContext);
675
+ }
680
676
  didClose() {
681
677
  if (this.existingExecutionContext)
682
678
  this.existingExecutionContext.contextDestroyed("Worker was closed");
@@ -715,6 +711,32 @@ class PageBinding {
715
711
  }
716
712
  static async dispatch(page, payload, context) {
717
713
  const { name, seq, serializedArgs } = JSON.parse(payload);
714
+ const deliver = async (deliverPayload) => {
715
+ let deliveryError;
716
+ try {
717
+ await context.evaluate(import_pageBinding.deliverBindingResult, deliverPayload);
718
+ return;
719
+ } catch (e) {
720
+ deliveryError = e;
721
+ }
722
+ const frame = context.frame;
723
+ if (!frame) {
724
+ import_debugLogger.debugLogger.log("error", deliveryError);
725
+ return;
726
+ }
727
+ const mainContext = await frame._mainContext().catch(() => null);
728
+ const utilityContext = await frame._utilityContext().catch(() => null);
729
+ for (const ctx of [mainContext, utilityContext]) {
730
+ if (!ctx || ctx === context)
731
+ continue;
732
+ try {
733
+ await ctx.evaluate(import_pageBinding.deliverBindingResult, deliverPayload);
734
+ return;
735
+ } catch {
736
+ }
737
+ }
738
+ import_debugLogger.debugLogger.log("error", deliveryError);
739
+ };
718
740
  try {
719
741
  (0, import_utils.assert)(context.world);
720
742
  const binding = page.getBinding(name);
@@ -730,9 +752,9 @@ class PageBinding {
730
752
  const args = serializedArgs.map((a) => (0, import_utilityScriptSerializers.parseEvaluationResultValue)(a));
731
753
  result = await binding.playwrightFunction({ frame: context.frame, page, context: page._browserContext }, ...args);
732
754
  }
733
- context.evaluate(import_pageBinding.deliverBindingResult, { name, seq, result }).catch((e) => import_debugLogger.debugLogger.log("error", e));
755
+ await deliver({ name, seq, result });
734
756
  } catch (error) {
735
- context.evaluate(import_pageBinding.deliverBindingResult, { name, seq, error }).catch((e) => import_debugLogger.debugLogger.log("error", e));
757
+ await deliver({ name, seq, error });
736
758
  }
737
759
  }
738
760
  }
@@ -741,66 +763,17 @@ class InitScript {
741
763
  this.source = `(() => { ${source} })();`;
742
764
  }
743
765
  }
744
- class FrameThrottler {
745
- constructor(nonThrottledFrames, defaultInterval, throttlingInterval) {
746
- this._acks = [];
747
- this._throttlingEnabled = false;
748
- this._nonThrottledFrames = nonThrottledFrames;
749
- this._budget = nonThrottledFrames;
750
- this._defaultInterval = defaultInterval;
751
- this._throttlingInterval = throttlingInterval;
752
- this._tick();
753
- }
754
- dispose() {
755
- if (this._timeoutId) {
756
- clearTimeout(this._timeoutId);
757
- this._timeoutId = void 0;
758
- }
759
- }
760
- setThrottlingEnabled(enabled) {
761
- this._throttlingEnabled = enabled;
762
- }
763
- recharge() {
764
- for (const ack of this._acks)
765
- ack();
766
- this._acks = [];
767
- this._budget = this._nonThrottledFrames;
768
- if (this._timeoutId) {
769
- clearTimeout(this._timeoutId);
770
- this._tick();
771
- }
772
- }
773
- ack(ack) {
774
- if (!this._timeoutId) {
775
- ack();
776
- return;
777
- }
778
- this._acks.push(ack);
779
- }
780
- _tick() {
781
- const ack = this._acks.shift();
782
- if (ack) {
783
- --this._budget;
784
- ack();
785
- }
786
- if (this._throttlingEnabled && this._budget <= 0) {
787
- this._timeoutId = setTimeout(() => this._tick(), this._throttlingInterval);
788
- } else {
789
- this._timeoutId = setTimeout(() => this._tick(), this._defaultInterval);
790
- }
791
- }
792
- }
793
- async function snapshotFrameForAI(progress, frame, frameOrdinal, frameIds) {
766
+ async function snapshotFrameForAI(progress, frame, options = {}) {
794
767
  const snapshot = await frame.retryWithProgressAndTimeouts(progress, [1e3, 2e3, 4e3, 8e3], async (continuePolling) => {
795
768
  try {
796
769
  const context = await progress.race(frame._utilityContext());
797
770
  const injectedScript = await progress.race(context.injectedScript());
798
- const snapshotOrRetry = await progress.race(injectedScript.evaluate((injected, refPrefix) => {
771
+ const snapshotOrRetry = await progress.race(injectedScript.evaluate((injected, options2) => {
799
772
  const node = injected.document.body;
800
773
  if (!node)
801
774
  return true;
802
- return injected.ariaSnapshot(node, { mode: "ai", refPrefix });
803
- }, frameOrdinal ? "f" + frameOrdinal : ""));
775
+ return injected.incrementalAriaSnapshot(node, { mode: "ai", ...options2 });
776
+ }, { refPrefix: frame.seq ? "f" + frame.seq : "", track: options.track, doNotRenderActive: options.doNotRenderActive }));
804
777
  if (snapshotOrRetry === true)
805
778
  return continuePolling;
806
779
  return snapshotOrRetry;
@@ -810,33 +783,45 @@ async function snapshotFrameForAI(progress, frame, frameOrdinal, frameIds) {
810
783
  return continuePolling;
811
784
  }
812
785
  });
813
- const lines = snapshot.split("\n");
814
- const result = [];
815
- for (const line of lines) {
786
+ const childSnapshotPromises = snapshot.iframeRefs.map((ref) => snapshotFrameRefForAI(progress, frame, ref, options));
787
+ const childSnapshots = await Promise.all(childSnapshotPromises);
788
+ const full = [];
789
+ let incremental;
790
+ if (snapshot.incremental !== void 0) {
791
+ incremental = snapshot.incremental.split("\n");
792
+ for (let i = 0; i < snapshot.iframeRefs.length; i++) {
793
+ const childSnapshot = childSnapshots[i];
794
+ if (childSnapshot.incremental)
795
+ incremental.push(...childSnapshot.incremental);
796
+ else if (childSnapshot.full.length)
797
+ incremental.push("- <changed> iframe [ref=" + snapshot.iframeRefs[i] + "]:", ...childSnapshot.full.map((l) => " " + l));
798
+ }
799
+ }
800
+ for (const line of snapshot.full.split("\n")) {
816
801
  const match = line.match(/^(\s*)- iframe (?:\[active\] )?\[ref=([^\]]*)\]/);
817
802
  if (!match) {
818
- result.push(line);
803
+ full.push(line);
819
804
  continue;
820
805
  }
821
806
  const leadingSpace = match[1];
822
807
  const ref = match[2];
823
- const frameSelector = `aria-ref=${ref} >> internal:control=enter-frame`;
824
- const frameBodySelector = `${frameSelector} >> body`;
825
- const child = await progress.race(frame.selectors.resolveFrameForSelector(frameBodySelector, { strict: true }));
826
- if (!child) {
827
- result.push(line);
828
- continue;
829
- }
830
- const frameOrdinal2 = frameIds.length + 1;
831
- frameIds.push(child.frame._id);
832
- try {
833
- const childSnapshot = await snapshotFrameForAI(progress, child.frame, frameOrdinal2, frameIds);
834
- result.push(line + ":", ...childSnapshot.map((l) => leadingSpace + " " + l));
835
- } catch {
836
- result.push(line);
837
- }
808
+ const childSnapshot = childSnapshots[snapshot.iframeRefs.indexOf(ref)] ?? { full: [] };
809
+ full.push(childSnapshot.full.length ? line + ":" : line);
810
+ full.push(...childSnapshot.full.map((l) => leadingSpace + " " + l));
811
+ }
812
+ return { full, incremental };
813
+ }
814
+ async function snapshotFrameRefForAI(progress, parentFrame, frameRef, options) {
815
+ const frameSelector = `aria-ref=${frameRef} >> internal:control=enter-frame`;
816
+ const frameBodySelector = `${frameSelector} >> body`;
817
+ const child = await progress.race(parentFrame.selectors.resolveFrameForSelector(frameBodySelector, { strict: true }));
818
+ if (!child)
819
+ return { full: [] };
820
+ try {
821
+ return await snapshotFrameForAI(progress, child.frame, options);
822
+ } catch {
823
+ return { full: [] };
838
824
  }
839
- return result;
840
825
  }
841
826
  function ensureArrayLimit(array, limit) {
842
827
  if (array.length > limit)
@@ -848,5 +833,6 @@ function ensureArrayLimit(array, limit) {
848
833
  InitScript,
849
834
  Page,
850
835
  PageBinding,
851
- Worker
836
+ Worker,
837
+ WorkerEvent
852
838
  });
@@ -45,10 +45,8 @@ class Playwright extends import_instrumentation.SdkObject {
45
45
  onPageOpen: (page) => this._allPages.add(page),
46
46
  onPageClose: (page) => this._allPages.delete(page)
47
47
  }, null);
48
- this.chromium = new import_chromium.Chromium(this);
49
- this._bidiChromium = new import_bidiChromium.BidiChromium(this);
50
- this._bidiFirefox = new import_bidiFirefox.BidiFirefox(this);
51
- this.firefox = new import_firefox.Firefox(this);
48
+ this.chromium = new import_chromium.Chromium(this, new import_bidiChromium.BidiChromium(this));
49
+ this.firefox = new import_firefox.Firefox(this, new import_bidiFirefox.BidiFirefox(this));
52
50
  this.webkit = new import_webkit.WebKit(this);
53
51
  this.electron = new import_electron.Electron(this);
54
52
  this.android = new import_android.Android(this, new import_backendAdb.AdbBackend());