patchright-bun-core 1.58.2 → 1.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/ThirdPartyNotices.txt +126 -650
  2. package/browsers.json +16 -14
  3. package/lib/bootstrap.js +77 -0
  4. package/lib/cli/browserActions.js +308 -0
  5. package/lib/cli/driver.js +3 -2
  6. package/lib/cli/installActions.js +171 -0
  7. package/lib/cli/program.js +47 -411
  8. package/lib/client/android.js +4 -4
  9. package/lib/client/api.js +3 -3
  10. package/lib/client/browser.js +8 -0
  11. package/lib/client/browserContext.js +18 -37
  12. package/lib/client/browserType.js +19 -51
  13. package/lib/client/cdpSession.js +6 -2
  14. package/lib/client/channelOwner.js +1 -1
  15. package/lib/client/{webSocket.js → connect.js} +57 -7
  16. package/lib/client/connection.js +8 -4
  17. package/lib/client/consoleMessage.js +3 -0
  18. package/lib/client/debugger.js +57 -0
  19. package/lib/client/dialog.js +8 -1
  20. package/lib/client/disposable.js +76 -0
  21. package/lib/client/electron.js +1 -0
  22. package/lib/client/elementHandle.js +1 -4
  23. package/lib/client/events.js +3 -3
  24. package/lib/client/fetch.js +0 -1
  25. package/lib/client/frame.js +0 -5
  26. package/lib/client/harRouter.js +13 -1
  27. package/lib/client/jsHandle.js +0 -4
  28. package/lib/client/locator.js +5 -7
  29. package/lib/client/network.js +14 -11
  30. package/lib/client/page.js +34 -48
  31. package/lib/client/platform.js +0 -3
  32. package/lib/client/screencast.js +88 -0
  33. package/lib/client/selectors.js +3 -1
  34. package/lib/client/tracing.js +11 -4
  35. package/lib/client/video.js +13 -20
  36. package/lib/generated/bindingsControllerSource.js +1 -1
  37. package/lib/generated/clockSource.js +1 -1
  38. package/lib/generated/injectedScriptSource.js +1 -1
  39. package/lib/generated/pollingRecorderSource.js +1 -1
  40. package/lib/generated/storageScriptSource.js +1 -1
  41. package/lib/generated/utilityScriptSource.js +1 -1
  42. package/lib/mcpBundle.js +0 -6
  43. package/lib/mcpBundleImpl.js +91 -0
  44. package/lib/protocol/validator.js +216 -118
  45. package/lib/protocol/validatorPrimitives.js +1 -1
  46. package/lib/remote/playwrightConnection.js +10 -8
  47. package/lib/remote/playwrightPipeServer.js +100 -0
  48. package/lib/remote/playwrightServer.js +13 -8
  49. package/lib/remote/playwrightWebSocketServer.js +73 -0
  50. package/lib/remote/serverTransport.js +96 -0
  51. package/lib/server/android/android.js +2 -2
  52. package/lib/server/bidi/bidiBrowser.js +30 -8
  53. package/lib/server/bidi/bidiChromium.js +18 -5
  54. package/lib/server/bidi/bidiNetworkManager.js +39 -11
  55. package/lib/server/bidi/bidiPage.js +31 -15
  56. package/lib/server/bidi/third_party/firefoxPrefs.js +3 -1
  57. package/lib/server/browser.js +84 -21
  58. package/lib/server/browserContext.js +97 -58
  59. package/lib/server/browserType.js +14 -12
  60. package/lib/server/chromium/chromium.js +15 -13
  61. package/lib/server/chromium/crBrowser.js +18 -10
  62. package/lib/server/chromium/crNetworkManager.js +4 -4
  63. package/lib/server/chromium/crPage.js +26 -64
  64. package/lib/server/chromium/crServiceWorker.js +5 -4
  65. package/lib/server/clock.js +33 -33
  66. package/lib/server/console.js +5 -1
  67. package/lib/server/debugController.js +12 -6
  68. package/lib/server/debugger.js +40 -47
  69. package/lib/server/deviceDescriptorsSource.json +137 -137
  70. package/lib/server/dispatchers/browserContextDispatcher.js +27 -30
  71. package/lib/server/dispatchers/browserDispatcher.js +11 -5
  72. package/lib/server/dispatchers/browserTypeDispatcher.js +7 -0
  73. package/lib/server/dispatchers/cdpSessionDispatcher.js +4 -1
  74. package/lib/server/dispatchers/debuggerDispatcher.js +84 -0
  75. package/lib/server/dispatchers/dispatcher.js +1 -1
  76. package/lib/server/dispatchers/disposableDispatcher.js +39 -0
  77. package/lib/server/dispatchers/electronDispatcher.js +2 -1
  78. package/lib/server/dispatchers/frameDispatcher.js +3 -3
  79. package/lib/server/dispatchers/localUtilsDispatcher.js +37 -1
  80. package/lib/server/dispatchers/networkDispatchers.js +6 -5
  81. package/lib/server/dispatchers/pageDispatcher.js +101 -38
  82. package/lib/server/dispatchers/webSocketRouteDispatcher.js +4 -5
  83. package/lib/server/disposable.js +41 -0
  84. package/lib/server/dom.js +44 -26
  85. package/lib/server/download.js +3 -2
  86. package/lib/server/electron/electron.js +12 -7
  87. package/lib/server/firefox/ffBrowser.js +9 -19
  88. package/lib/server/firefox/ffInput.js +21 -5
  89. package/lib/server/firefox/ffNetworkManager.js +2 -2
  90. package/lib/server/firefox/ffPage.js +24 -27
  91. package/lib/server/frames.js +40 -11
  92. package/lib/server/har/harRecorder.js +2 -2
  93. package/lib/server/har/harTracer.js +5 -4
  94. package/lib/server/input.js +49 -4
  95. package/lib/server/instrumentation.js +5 -0
  96. package/lib/server/launchApp.js +0 -1
  97. package/lib/server/localUtils.js +6 -6
  98. package/lib/server/network.js +9 -8
  99. package/lib/server/overlay.js +138 -0
  100. package/lib/server/page.js +111 -51
  101. package/lib/server/progress.js +6 -0
  102. package/lib/server/recorder/recorderApp.js +9 -8
  103. package/lib/server/recorder.js +76 -40
  104. package/lib/server/registry/index.js +54 -81
  105. package/lib/server/registry/nativeDeps.js +1 -0
  106. package/lib/server/screencast.js +90 -143
  107. package/lib/server/trace/recorder/snapshotter.js +2 -2
  108. package/lib/server/trace/recorder/tracing.js +87 -36
  109. package/lib/server/trace/viewer/traceViewer.js +3 -4
  110. package/lib/server/usKeyboardLayout.js +7 -0
  111. package/lib/server/utils/comparators.js +1 -1
  112. package/lib/server/utils/disposable.js +32 -0
  113. package/lib/server/utils/eventsHelper.js +3 -1
  114. package/lib/server/utils/fileUtils.js +16 -2
  115. package/lib/server/utils/happyEyeballs.js +15 -12
  116. package/lib/server/utils/hostPlatform.js +0 -15
  117. package/lib/server/utils/httpServer.js +5 -3
  118. package/lib/server/utils/network.js +2 -1
  119. package/lib/server/utils/nodePlatform.js +0 -6
  120. package/lib/server/utils/processLauncher.js +8 -6
  121. package/lib/server/utils/zipFile.js +2 -2
  122. package/lib/server/videoRecorder.js +82 -12
  123. package/lib/server/webkit/wkBrowser.js +1 -6
  124. package/lib/server/webkit/wkPage.js +27 -25
  125. package/lib/server/webkit/wkWorkers.js +2 -1
  126. package/lib/serverRegistry.js +156 -0
  127. package/lib/tools/backend/browserBackend.js +79 -0
  128. package/lib/tools/backend/common.js +63 -0
  129. package/lib/tools/backend/config.js +41 -0
  130. package/lib/tools/backend/console.js +66 -0
  131. package/lib/tools/backend/context.js +296 -0
  132. package/lib/tools/backend/cookies.js +152 -0
  133. package/lib/tools/backend/devtools.js +69 -0
  134. package/lib/tools/backend/dialogs.js +59 -0
  135. package/lib/tools/backend/evaluate.js +64 -0
  136. package/lib/tools/backend/files.js +60 -0
  137. package/lib/tools/backend/form.js +64 -0
  138. package/lib/tools/backend/keyboard.js +155 -0
  139. package/lib/tools/backend/logFile.js +95 -0
  140. package/lib/tools/backend/mouse.js +168 -0
  141. package/lib/tools/backend/navigate.js +106 -0
  142. package/lib/tools/backend/network.js +135 -0
  143. package/lib/tools/backend/pdf.js +48 -0
  144. package/lib/tools/backend/response.js +305 -0
  145. package/lib/tools/backend/route.js +140 -0
  146. package/lib/tools/backend/runCode.js +77 -0
  147. package/lib/tools/backend/screenshot.js +88 -0
  148. package/lib/tools/backend/sessionLog.js +74 -0
  149. package/lib/tools/backend/snapshot.js +208 -0
  150. package/lib/tools/backend/storage.js +68 -0
  151. package/lib/tools/backend/tab.js +445 -0
  152. package/lib/tools/backend/tabs.js +67 -0
  153. package/lib/tools/backend/tool.js +47 -0
  154. package/lib/tools/backend/tools.js +102 -0
  155. package/lib/tools/backend/tracing.js +78 -0
  156. package/lib/tools/backend/utils.js +83 -0
  157. package/lib/tools/backend/verify.js +151 -0
  158. package/lib/tools/backend/video.js +98 -0
  159. package/lib/tools/backend/wait.js +63 -0
  160. package/lib/tools/backend/webstorage.js +223 -0
  161. package/lib/tools/cli-client/cli.js +6 -0
  162. package/lib/tools/cli-client/help.json +399 -0
  163. package/lib/tools/cli-client/minimist.js +128 -0
  164. package/lib/tools/cli-client/program.js +350 -0
  165. package/lib/tools/cli-client/registry.js +176 -0
  166. package/lib/tools/cli-client/session.js +289 -0
  167. package/lib/tools/cli-client/skill/SKILL.md +328 -0
  168. package/lib/tools/cli-client/skill/references/element-attributes.md +23 -0
  169. package/lib/tools/cli-client/skill/references/playwright-tests.md +39 -0
  170. package/lib/tools/cli-client/skill/references/request-mocking.md +87 -0
  171. package/lib/tools/cli-client/skill/references/running-code.md +231 -0
  172. package/lib/tools/cli-client/skill/references/session-management.md +169 -0
  173. package/lib/tools/cli-client/skill/references/storage-state.md +275 -0
  174. package/lib/tools/cli-client/skill/references/test-generation.md +88 -0
  175. package/lib/tools/cli-client/skill/references/tracing.md +139 -0
  176. package/lib/tools/cli-client/skill/references/video-recording.md +143 -0
  177. package/lib/tools/cli-daemon/command.js +73 -0
  178. package/lib/tools/cli-daemon/commands.js +956 -0
  179. package/lib/tools/cli-daemon/daemon.js +157 -0
  180. package/lib/tools/cli-daemon/helpGenerator.js +177 -0
  181. package/lib/tools/cli-daemon/program.js +129 -0
  182. package/lib/tools/dashboard/appIcon.png +0 -0
  183. package/lib/tools/dashboard/dashboardApp.js +284 -0
  184. package/lib/tools/dashboard/dashboardController.js +296 -0
  185. package/lib/tools/exports.js +60 -0
  186. package/lib/tools/mcp/browserFactory.js +233 -0
  187. package/lib/tools/mcp/cdpRelay.js +352 -0
  188. package/lib/tools/mcp/cli-stub.js +7 -0
  189. package/lib/tools/mcp/config.d.js +16 -0
  190. package/lib/tools/mcp/config.js +446 -0
  191. package/lib/tools/mcp/configIni.js +189 -0
  192. package/lib/tools/mcp/extensionContextFactory.js +55 -0
  193. package/lib/tools/mcp/index.js +62 -0
  194. package/lib/tools/mcp/log.js +35 -0
  195. package/lib/tools/mcp/program.js +107 -0
  196. package/lib/tools/mcp/protocol.js +28 -0
  197. package/lib/tools/mcp/watchdog.js +44 -0
  198. package/lib/tools/trace/SKILL.md +171 -0
  199. package/lib/{server/trace/viewer/traceParser.js → tools/trace/installSkill.js} +15 -39
  200. package/lib/tools/trace/traceActions.js +142 -0
  201. package/lib/tools/trace/traceAttachments.js +69 -0
  202. package/lib/tools/trace/traceCli.js +87 -0
  203. package/lib/tools/trace/traceConsole.js +97 -0
  204. package/lib/tools/trace/traceErrors.js +55 -0
  205. package/lib/tools/trace/traceOpen.js +69 -0
  206. package/lib/tools/trace/traceParser.js +96 -0
  207. package/lib/tools/trace/traceRequests.js +182 -0
  208. package/lib/tools/trace/traceScreenshot.js +68 -0
  209. package/lib/tools/trace/traceSnapshot.js +149 -0
  210. package/lib/tools/trace/traceUtils.js +153 -0
  211. package/lib/tools/utils/connect.js +32 -0
  212. package/lib/tools/utils/mcp/http.js +152 -0
  213. package/lib/tools/utils/mcp/server.js +230 -0
  214. package/lib/tools/utils/mcp/tool.js +47 -0
  215. package/lib/tools/utils/socketConnection.js +108 -0
  216. package/lib/utils/isomorphic/formatUtils.js +64 -0
  217. package/lib/utils/isomorphic/jsonSchema.js +89 -0
  218. package/lib/utils/isomorphic/mimeType.js +7 -2
  219. package/lib/utils/isomorphic/protocolFormatter.js +2 -2
  220. package/lib/utils/isomorphic/protocolMetainfo.js +127 -106
  221. package/lib/utils/isomorphic/stringUtils.js +3 -3
  222. package/lib/utils/isomorphic/timeoutRunner.js +3 -3
  223. package/lib/utils/isomorphic/trace/snapshotRenderer.js +35 -42
  224. package/lib/utils/isomorphic/trace/traceLoader.js +15 -14
  225. package/lib/utils/isomorphic/trace/traceModel.js +3 -2
  226. package/lib/utils/isomorphic/trace/traceModernizer.js +1 -0
  227. package/lib/utils/isomorphic/urlMatch.js +54 -1
  228. package/lib/utils/isomorphic/utilityScriptSerializers.js +11 -0
  229. package/lib/utils.js +6 -2
  230. package/lib/utilsBundle.js +3 -21
  231. package/lib/utilsBundleImpl/index.js +132 -133
  232. package/lib/vite/dashboard/assets/index-BAOybkp8.js +50 -0
  233. package/lib/vite/dashboard/assets/index-CZAYOG76.css +1 -0
  234. package/lib/vite/dashboard/index.html +28 -0
  235. package/lib/vite/htmlReport/index.html +2 -70
  236. package/lib/vite/htmlReport/report.css +1 -0
  237. package/lib/vite/htmlReport/report.js +72 -0
  238. package/lib/vite/recorder/assets/{codeMirrorModule-DadYNm1I.js → codeMirrorModule-C8KMvO9L.js} +20 -20
  239. package/lib/vite/recorder/assets/index-CqAYX1I3.js +193 -0
  240. package/lib/vite/recorder/index.html +1 -1
  241. package/lib/vite/traceViewer/assets/{codeMirrorModule-a5XoALAZ.js → codeMirrorModule-DS0FLvoc.js} +20 -20
  242. package/lib/vite/traceViewer/assets/defaultSettingsView-GTWI-W_B.js +262 -0
  243. package/lib/vite/traceViewer/defaultSettingsView.B4dS75f0.css +1 -0
  244. package/lib/vite/traceViewer/{index.BVu7tZDe.css → index.CzXZzn5A.css} +1 -1
  245. package/lib/vite/traceViewer/{index.BDwrLSGN.js → index.Dtstcb7U.js} +1 -1
  246. package/lib/vite/traceViewer/index.html +4 -4
  247. package/lib/vite/traceViewer/sw.bundle.js +4 -4
  248. package/lib/vite/traceViewer/uiMode.Vipi55dB.js +6 -0
  249. package/lib/vite/traceViewer/uiMode.html +3 -3
  250. package/lib/zipBundleImpl.js +2 -2
  251. package/lib/zodBundle.js +39 -0
  252. package/lib/zodBundleImpl.js +40 -0
  253. package/package.json +6 -1
  254. package/types/protocol.d.ts +947 -51
  255. package/types/types.d.ts +854 -74
  256. package/lib/client/pageAgent.js +0 -64
  257. package/lib/mcpBundleImpl/index.js +0 -147
  258. package/lib/server/agent/actionRunner.js +0 -335
  259. package/lib/server/agent/actions.js +0 -128
  260. package/lib/server/agent/codegen.js +0 -111
  261. package/lib/server/agent/context.js +0 -150
  262. package/lib/server/agent/expectTools.js +0 -156
  263. package/lib/server/agent/pageAgent.js +0 -204
  264. package/lib/server/agent/performTools.js +0 -262
  265. package/lib/server/agent/tool.js +0 -109
  266. package/lib/server/dispatchers/pageAgentDispatcher.js +0 -96
  267. package/lib/vite/recorder/assets/index-BhTWtUlo.js +0 -193
  268. package/lib/vite/traceViewer/assets/defaultSettingsView-CJSZINFr.js +0 -266
  269. package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +0 -1
  270. package/lib/vite/traceViewer/uiMode.CQJ9SCIQ.js +0 -5
  271. /package/lib/{server/utils → utils/isomorphic}/imageUtils.js +0 -0
  272. /package/lib/utils/isomorphic/{traceUtils.js → trace/traceUtils.js} +0 -0
@@ -29,6 +29,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  var browserContext_exports = {};
30
30
  __export(browserContext_exports, {
31
31
  BrowserContext: () => BrowserContext,
32
+ calculateUserAgentEmulation: () => calculateUserAgentEmulation,
32
33
  normalizeProxySettings: () => normalizeProxySettings,
33
34
  validateBrowserContextOptions: () => validateBrowserContextOptions,
34
35
  verifyClientCertificates: () => verifyClientCertificates,
@@ -36,14 +37,12 @@ __export(browserContext_exports, {
36
37
  });
37
38
  module.exports = __toCommonJS(browserContext_exports);
38
39
  var import_fs = __toESM(require("fs"));
39
- var import_path = __toESM(require("path"));
40
40
  var import_crypto = require("./utils/crypto");
41
41
  var import_debug = require("./utils/debug");
42
42
  var import_clock = require("./clock");
43
43
  var import_debugger = require("./debugger");
44
44
  var import_dialog = require("./dialog");
45
45
  var import_fetch = require("./fetch");
46
- var import_fileUtils = require("./utils/fileUtils");
47
46
  var import_stackTrace = require("../utils/isomorphic/stackTrace");
48
47
  var import_harRecorder = require("./har/harRecorder");
49
48
  var import_helper = require("./helper");
@@ -70,8 +69,9 @@ const BrowserContextEvent = {
70
69
  RequestFulfilled: "requestfulfilled",
71
70
  RequestContinued: "requestcontinued",
72
71
  BeforeClose: "beforeclose",
73
- VideoStarted: "videostarted",
74
- RecorderEvent: "recorderevent"
72
+ RecorderEvent: "recorderevent",
73
+ PageClosed: "pageclosed",
74
+ InternalFrameNavigatedToNewDocument: "internalframenavigatedtonewdocument"
75
75
  };
76
76
  class BrowserContext extends import_instrumentation.SdkObject {
77
77
  constructor(browser, options, browserContextId) {
@@ -113,18 +113,22 @@ class BrowserContext extends import_instrumentation.SdkObject {
113
113
  if (this.attribution.playwright.options.isInternalPlaywright)
114
114
  return;
115
115
  this._debugger = new import_debugger.Debugger(this);
116
- if ((0, import_debug.debugMode)() === "inspector")
116
+ const shouldEnableDebugger = !this.attribution.playwright.options.isServer && ((0, import_debug.isUnderTest)() || !!this._browser.options.headful);
117
+ if (shouldEnableDebugger) {
118
+ this._debugger.setPauseAt();
119
+ this._debugger.on(import_debugger.Debugger.Events.PausedStateChanged, () => {
120
+ if (this._debugger.isPaused())
121
+ import_recorderApp.RecorderApp.showInspectorNoReply(this);
122
+ });
123
+ }
124
+ if ((0, import_debug.debugMode)() === "inspector") {
125
+ this._debugger.setPauseAt({ next: true });
117
126
  await import_recorderApp.RecorderApp.show(this, { pauseOnNextStatement: true });
118
- if (this._debugger.isPaused())
119
- import_recorderApp.RecorderApp.showInspectorNoReply(this);
120
- this._debugger.on(import_debugger.Debugger.Events.PausedStateChanged, () => {
121
- if (this._debugger.isPaused())
122
- import_recorderApp.RecorderApp.showInspectorNoReply(this);
123
- });
127
+ }
124
128
  if ((0, import_debug.debugMode)() === "console")
125
129
  await this.exposeConsoleApi();
126
130
  if (this._options.serviceWorkers === "block")
127
- await this.addInitScript(void 0, `
131
+ await this.addInitScript(`
128
132
  if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { console.warn('Service Worker registration blocked by Playwright'); };
129
133
  `);
130
134
  if (this._options.permissions)
@@ -142,10 +146,6 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
142
146
  module.exports = { default: () => installConsoleApi };
143
147
  `);
144
148
  }
145
- async _ensureVideosPath() {
146
- if (this._options.recordVideo)
147
- await (0, import_fileUtils.mkdirIfNeeded)(import_path.default.join(this._options.recordVideo.dir, "dummy"));
148
- }
149
149
  canResetForReuse() {
150
150
  if (this._closedStatus !== "open")
151
151
  return false;
@@ -239,7 +239,7 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
239
239
  async exposePlaywrightBindingIfNeeded() {
240
240
  this._playwrightBindingExposed ??= (async () => {
241
241
  await this.doExposePlaywrightBinding();
242
- this.bindingsInitScript = import_page2.PageBinding.createInitScript();
242
+ this.bindingsInitScript = import_page2.PageBinding.createInitScript(this);
243
243
  this.initScripts.push(this.bindingsInitScript);
244
244
  await this.doAddInitScript(this.bindingsInitScript);
245
245
  await this.safeNonStallingEvaluateInAllFrames(this.bindingsInitScript.source, "main");
@@ -257,7 +257,7 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
257
257
  throw new Error(`Function "${name}" has been already registered in one of the pages`);
258
258
  }
259
259
  await progress.race(this.exposePlaywrightBindingIfNeeded());
260
- const binding = new import_page2.PageBinding(name, playwrightBinding, needsHandle);
260
+ const binding = new import_page2.PageBinding(this, name, playwrightBinding, needsHandle);
261
261
  binding.forClient = forClient;
262
262
  this._pageBindings.set(name, binding);
263
263
  try {
@@ -269,13 +269,12 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
269
269
  throw error;
270
270
  }
271
271
  }
272
- async removeExposedBindings(bindings) {
273
- bindings = bindings.filter((binding) => this._pageBindings.get(binding.name) === binding);
274
- for (const binding of bindings)
275
- this._pageBindings.delete(binding.name);
276
- await this.doRemoveInitScripts(bindings.map((binding) => binding.initScript));
277
- const cleanup = bindings.map((binding) => `{ ${binding.cleanupScript} };
278
- `).join("");
272
+ async removeExposedBinding(binding) {
273
+ if (this._pageBindings.get(binding.name) !== binding)
274
+ return;
275
+ this._pageBindings.delete(binding.name);
276
+ await this.doRemoveInitScripts([binding.initScript]);
277
+ const cleanup = `{ ${binding.cleanupScript} };`;
279
278
  await this.safeNonStallingEvaluateInAllFrames(cleanup, "main");
280
279
  }
281
280
  async grantPermissions(permissions, origin) {
@@ -362,26 +361,21 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
362
361
  if (username)
363
362
  this._options.httpCredentials = { username, password: password || "" };
364
363
  }
365
- async addInitScript(progress, source) {
366
- const initScript = new import_page.InitScript(source);
364
+ async addInitScript(source) {
365
+ const initScript = new import_page.InitScript(this, source);
367
366
  this.initScripts.push(initScript);
368
367
  try {
369
- const promise = this.doAddInitScript(initScript);
370
- if (progress)
371
- await progress.race(promise);
372
- else
373
- await promise;
368
+ await this.doAddInitScript(initScript);
374
369
  return initScript;
375
370
  } catch (error) {
376
- this.removeInitScripts([initScript]).catch(() => {
371
+ initScript.dispose().catch(() => {
377
372
  });
378
373
  throw error;
379
374
  }
380
375
  }
381
- async removeInitScripts(initScripts) {
382
- const set = new Set(initScripts);
383
- this.initScripts = this.initScripts.filter((script) => !set.has(script));
384
- await this.doRemoveInitScripts(initScripts);
376
+ async removeInitScript(initScript) {
377
+ this.initScripts = this.initScripts.filter((script) => initScript !== script);
378
+ await this.doRemoveInitScripts([initScript]);
385
379
  }
386
380
  async addRequestInterceptor(progress, handler) {
387
381
  this.requestInterceptors.push(handler);
@@ -417,16 +411,13 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
417
411
  for (const harRecorder of this._harRecorders.values())
418
412
  await harRecorder.flush();
419
413
  await this.tracing.flush();
420
- const promises = [];
421
- for (const { context, artifact } of this._browser._idToVideo.values()) {
422
- if (context === this)
423
- promises.push(artifact.finishedPromise());
424
- }
414
+ await Promise.all(this.pages().map((page) => page.screencast.handlePageOrContextClose()));
425
415
  if (this._customCloseHandler) {
426
416
  await this._customCloseHandler();
427
417
  } else {
428
418
  await this.doClose(options.reason);
429
419
  }
420
+ const promises = [];
430
421
  promises.push(this._deleteAllDownloads());
431
422
  promises.push(this._deleteAllTempDirs());
432
423
  await Promise.all(promises);
@@ -602,22 +593,6 @@ function validateBrowserContextOptions(options, browserOptions) {
602
593
  options.acceptDownloads = "internal-browser-default";
603
594
  if (!options.viewport && !options.noDefaultViewport)
604
595
  options.viewport = { width: 1280, height: 720 };
605
- if (options.recordVideo) {
606
- if (!options.recordVideo.size) {
607
- if (options.noDefaultViewport) {
608
- options.recordVideo.size = { width: 800, height: 600 };
609
- } else {
610
- const size = options.viewport;
611
- const scale = Math.min(1, 800 / Math.max(size.width, size.height));
612
- options.recordVideo.size = {
613
- width: Math.floor(size.width * scale),
614
- height: Math.floor(size.height * scale)
615
- };
616
- }
617
- }
618
- options.recordVideo.size.width &= ~1;
619
- options.recordVideo.size.height &= ~1;
620
- }
621
596
  if (options.proxy)
622
597
  options.proxy = normalizeProxySettings(options.proxy);
623
598
  verifyGeolocation(options.geolocation);
@@ -669,6 +644,69 @@ function normalizeProxySettings(proxy) {
669
644
  bypass = bypass.split(",").map((t) => t.trim()).join(",");
670
645
  return { ...proxy, server, bypass };
671
646
  }
647
+ function calculateUserAgentEmulation(options) {
648
+ const ua = options.userAgent;
649
+ if (!ua)
650
+ return { navigatorPlatform: void 0, userAgentMetadata: void 0 };
651
+ const userAgentMetadata = {
652
+ mobile: !!options.isMobile,
653
+ model: "",
654
+ architecture: "x86",
655
+ platform: "Windows",
656
+ platformVersion: ""
657
+ };
658
+ const androidMatch = ua.match(/Android (\d+(\.\d+)?(\.\d+)?)/);
659
+ const iPhoneMatch = ua.match(/iPhone OS (\d+(_\d+)?)/);
660
+ const iPadMatch = ua.match(/iPad; CPU OS (\d+(_\d+)?)/);
661
+ const macOSMatch = ua.match(/Mac OS X (\d+(_\d+)?(_\d+)?)/);
662
+ const windowsMatch = ua.match(/Windows\D+(\d+(\.\d+)?(\.\d+)?)/);
663
+ if (androidMatch) {
664
+ userAgentMetadata.platform = "Android";
665
+ userAgentMetadata.platformVersion = androidMatch[1];
666
+ userAgentMetadata.architecture = "arm";
667
+ } else if (iPhoneMatch) {
668
+ userAgentMetadata.platform = "iOS";
669
+ userAgentMetadata.platformVersion = iPhoneMatch[1].replace(/_/g, ".");
670
+ userAgentMetadata.architecture = "arm";
671
+ } else if (iPadMatch) {
672
+ userAgentMetadata.platform = "iOS";
673
+ userAgentMetadata.platformVersion = iPadMatch[1].replace(/_/g, ".");
674
+ userAgentMetadata.architecture = "arm";
675
+ } else if (macOSMatch) {
676
+ userAgentMetadata.platform = "macOS";
677
+ userAgentMetadata.platformVersion = macOSMatch[1].replace(/_/g, ".");
678
+ if (!ua.includes("Intel"))
679
+ userAgentMetadata.architecture = "arm";
680
+ } else if (windowsMatch) {
681
+ userAgentMetadata.platform = "Windows";
682
+ userAgentMetadata.platformVersion = windowsMatch[1];
683
+ } else if (ua.toLowerCase().includes("linux")) {
684
+ userAgentMetadata.platform = "Linux";
685
+ }
686
+ if (ua.includes("ARM") || ua.includes("aarch64"))
687
+ userAgentMetadata.architecture = "arm";
688
+ let navigatorPlatform;
689
+ if (!process.env.PLAYWRIGHT_NO_UA_PLATFORM) {
690
+ switch (userAgentMetadata.platform) {
691
+ case "Android":
692
+ navigatorPlatform = userAgentMetadata.architecture === "arm" ? "Linux armv8l" : "Linux x86_64";
693
+ break;
694
+ case "iOS":
695
+ navigatorPlatform = ua.includes("iPad") ? "iPad" : "iPhone";
696
+ break;
697
+ case "macOS":
698
+ navigatorPlatform = "MacIntel";
699
+ break;
700
+ case "Linux":
701
+ navigatorPlatform = userAgentMetadata.architecture === "arm" ? "Linux aarch64" : "Linux x86_64";
702
+ break;
703
+ case "Windows":
704
+ navigatorPlatform = "Win32";
705
+ break;
706
+ }
707
+ }
708
+ return { navigatorPlatform, userAgentMetadata };
709
+ }
672
710
  const paramsThatAllowContextReuse = [
673
711
  "colorScheme",
674
712
  "forcedColors",
@@ -695,6 +733,7 @@ const defaultNewContextParamValues = {
695
733
  // Annotate the CommonJS export names for ESM import in node:
696
734
  0 && (module.exports = {
697
735
  BrowserContext,
736
+ calculateUserAgentEmulation,
698
737
  normalizeProxySettings,
699
738
  validateBrowserContextOptions,
700
739
  verifyClientCertificates,
@@ -59,7 +59,7 @@ class BrowserType extends import_instrumentation.SdkObject {
59
59
  this.logName = "browser";
60
60
  }
61
61
  executablePath() {
62
- return import_registry.registry.findExecutable(this._name).executablePath(this.attribution.playwright.options.sdkLanguage) || "";
62
+ return import_registry.registry.findExecutable(this._name).executablePath() || "";
63
63
  }
64
64
  name() {
65
65
  return this._name;
@@ -115,7 +115,7 @@ class BrowserType extends import_instrumentation.SdkObject {
115
115
  await progress.race(options.__testHookBeforeCreateBrowser());
116
116
  const browserOptions = {
117
117
  name: this._name,
118
- isChromium: this._name === "chromium",
118
+ browserType: this._name,
119
119
  channel: options.channel,
120
120
  slowMo: options.slowMo,
121
121
  persistent,
@@ -129,7 +129,8 @@ class BrowserType extends import_instrumentation.SdkObject {
129
129
  protocolLogger,
130
130
  browserLogsCollector,
131
131
  wsEndpoint: transport instanceof import_transport.WebSocketTransport ? transport.wsEndpoint : void 0,
132
- originalLaunchOptions: options
132
+ originalLaunchOptions: options,
133
+ userDataDir: persistent ? userDataDir : void 0
133
134
  };
134
135
  if (persistent)
135
136
  (0, import_browserContext.validateBrowserContextOptions)(persistent, browserOptions);
@@ -152,10 +153,14 @@ class BrowserType extends import_instrumentation.SdkObject {
152
153
  args = [],
153
154
  executablePath = null
154
155
  } = options;
155
- await this._createArtifactDirs(options);
156
156
  const tempDirectories = [];
157
- const artifactsDir = await import_fs.default.promises.mkdtemp(import_path.default.join(import_os.default.tmpdir(), "playwright-artifacts-"));
158
- tempDirectories.push(artifactsDir);
157
+ let artifactsDir;
158
+ if (options.artifactsDir) {
159
+ artifactsDir = options.artifactsDir;
160
+ } else {
161
+ artifactsDir = await import_fs.default.promises.mkdtemp(import_path.default.join(import_os.default.tmpdir(), "playwright-artifacts-"));
162
+ tempDirectories.push(artifactsDir);
163
+ }
159
164
  if (userDataDir) {
160
165
  (0, import_assert.assert)(import_path.default.isAbsolute(userDataDir), "userDataDir must be an absolute path");
161
166
  if (!await (0, import_fileUtils.existsAsync)(userDataDir))
@@ -270,15 +275,12 @@ ${updatedLog}`);
270
275
  throw error;
271
276
  }
272
277
  }
273
- async _createArtifactDirs(options) {
274
- if (options.downloadsPath)
275
- await import_fs.default.promises.mkdir(options.downloadsPath, { recursive: true });
276
- if (options.tracesDir)
277
- await import_fs.default.promises.mkdir(options.tracesDir, { recursive: true });
278
- }
279
278
  async connectOverCDP(progress, endpointURL, options) {
280
279
  throw new Error("CDP connections are only supported by Chromium");
281
280
  }
281
+ async connectOverCDPTransport(progress, transport) {
282
+ throw new Error("CDP connections are only supported by Chromium");
283
+ }
282
284
  async _launchWithSeleniumHub(progress, hubUrl, options) {
283
285
  throw new Error("Connecting to SELENIUM_REMOTE_URL is only supported by Chromium");
284
286
  }
@@ -82,6 +82,12 @@ class Chromium extends import_browserType.BrowserType {
82
82
  headersMap = { "User-Agent": (0, import_userAgent.getUserAgent)() };
83
83
  else if (headersMap && !Object.keys(headersMap).some((key) => key.toLowerCase() === "user-agent"))
84
84
  headersMap["User-Agent"] = (0, import_userAgent.getUserAgent)();
85
+ const wsEndpoint = await urlToWSEndpoint(progress, endpointURL, headersMap);
86
+ const chromeTransport = await import_transport.WebSocketTransport.connect(progress, wsEndpoint, { headers: headersMap, followRedirects: true, debugLogHeader: "x-playwright-debug-log" });
87
+ const closeAndWait = async () => await chromeTransport.closeAndWait();
88
+ return this._connectOverCDPImpl(progress, chromeTransport, closeAndWait, options, onClose);
89
+ }
90
+ async _connectOverCDPImpl(progress, transport, closeAndWait, options, onClose) {
85
91
  const artifactsDir = await progress.race(import_fs.default.promises.mkdtemp(ARTIFACTS_FOLDER));
86
92
  const doCleanup = async () => {
87
93
  await (0, import_fileUtils.removeFolders)([artifactsDir]);
@@ -89,20 +95,17 @@ class Chromium extends import_browserType.BrowserType {
89
95
  onClose = void 0;
90
96
  await cb?.();
91
97
  };
92
- let chromeTransport;
93
98
  const doClose = async () => {
94
- await chromeTransport?.closeAndWait();
99
+ await closeAndWait();
95
100
  await doCleanup();
96
101
  };
97
102
  try {
98
- const wsEndpoint = await urlToWSEndpoint(progress, endpointURL, headersMap);
99
- chromeTransport = await import_transport.WebSocketTransport.connect(progress, wsEndpoint, { headers: headersMap });
100
103
  const browserProcess = { close: doClose, kill: doClose };
101
104
  const persistent = { noDefaultViewport: true };
102
105
  const browserOptions = {
103
106
  slowMo: options.slowMo,
104
107
  name: "chromium",
105
- isChromium: true,
108
+ browserType: "chromium",
106
109
  persistent,
107
110
  browserProcess,
108
111
  protocolLogger: import_helper.helper.debugProtocolLogger(),
@@ -113,7 +116,7 @@ class Chromium extends import_browserType.BrowserType {
113
116
  originalLaunchOptions: {}
114
117
  };
115
118
  (0, import_browserContext.validateBrowserContextOptions)(persistent, browserOptions);
116
- const browser = await progress.race(import_crBrowser.CRBrowser.connect(this.attribution.playwright, chromeTransport, browserOptions));
119
+ const browser = await progress.race(import_crBrowser.CRBrowser.connect(this.attribution.playwright, transport, browserOptions));
117
120
  if (!options.isLocal)
118
121
  browser._isCollocatedWithServer = false;
119
122
  browser.on(import_browser.Browser.Events.Disconnected, doCleanup);
@@ -124,6 +127,10 @@ class Chromium extends import_browserType.BrowserType {
124
127
  throw error;
125
128
  }
126
129
  }
130
+ async connectOverCDPTransport(progress, transport) {
131
+ const closeAndWait = async () => transport.close();
132
+ return this._connectOverCDPImpl(progress, transport, closeAndWait, { isLocal: true });
133
+ }
127
134
  _createDevTools() {
128
135
  const directory = import_registry.registry.findExecutable("chromium").directory;
129
136
  return directory ? new import_crDevTools.CRDevTools(import_path.default.join(directory, "devtools-preferences.json")) : void 0;
@@ -163,7 +170,6 @@ class Chromium extends import_browserType.BrowserType {
163
170
  transport.send(message);
164
171
  }
165
172
  async _launchWithSeleniumHub(progress, hubUrl, options) {
166
- await progress.race(this._createArtifactDirs(options));
167
173
  if (!hubUrl.endsWith("/"))
168
174
  hubUrl = hubUrl + "/";
169
175
  const args = this._innerDefaultArgs(options);
@@ -277,9 +283,7 @@ class Chromium extends import_browserType.BrowserType {
277
283
  if (args.find((arg) => !arg.startsWith("-")))
278
284
  throw new Error("Arguments can not specify page to be opened");
279
285
  const chromeArguments = [...(0, import_chromiumSwitches.chromiumSwitches)(options.assistantMode, options.channel)];
280
- if (import_os.default.platform() !== "darwin" || !(0, import_utils.hasGpuMac)()) {
281
- chromeArguments.push("--enable-unsafe-swiftshader");
282
- }
286
+ chromeArguments.push("--enable-unsafe-swiftshader");
283
287
  if (options.headless) {
284
288
  chromeArguments.push("--headless");
285
289
  chromeArguments.push(
@@ -299,11 +303,9 @@ class Chromium extends import_browserType.BrowserType {
299
303
  }
300
304
  chromeArguments.push(`--proxy-server=${proxy.server}`);
301
305
  const proxyBypassRules = [];
302
- if (options.socksProxyPort)
303
- proxyBypassRules.push("<-loopback>");
304
306
  if (proxy.bypass)
305
307
  proxyBypassRules.push(...proxy.bypass.split(",").map((t) => t.trim()).map((t) => t.startsWith(".") ? "*" + t : t));
306
- if (!process.env.PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK && !proxyBypassRules.includes("<-loopback>"))
308
+ if (options.socksProxyPort || (0, import_crBrowser.shouldProxyLoopback)(proxy.bypass))
307
309
  proxyBypassRules.push("<-loopback>");
308
310
  if (proxyBypassRules.length > 0)
309
311
  chromeArguments.push(`--proxy-bypass-list=${proxyBypassRules.join(";")}`);
@@ -29,7 +29,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  var crBrowser_exports = {};
30
30
  __export(crBrowser_exports, {
31
31
  CRBrowser: () => CRBrowser,
32
- CRBrowserContext: () => CRBrowserContext
32
+ CRBrowserContext: () => CRBrowserContext,
33
+ shouldProxyLoopback: () => shouldProxyLoopback
33
34
  });
34
35
  module.exports = __toCommonJS(crBrowser_exports);
35
36
  var import_path = __toESM(require("path"));
@@ -54,6 +55,7 @@ class CRBrowser extends import_browser.Browser {
54
55
  this._serviceWorkers = /* @__PURE__ */ new Map();
55
56
  this._version = "";
56
57
  this._majorVersion = 0;
58
+ this._revision = "";
57
59
  this._tracingRecording = false;
58
60
  this._userAgent = "";
59
61
  this._connection = connection;
@@ -75,6 +77,7 @@ class CRBrowser extends import_browser.Browser {
75
77
  if (options.__testHookOnConnectToBrowser)
76
78
  await options.__testHookOnConnectToBrowser();
77
79
  const version = await session.send("Browser.getVersion");
80
+ browser._revision = version.revision;
78
81
  browser._version = version.product.substring(version.product.indexOf("/") + 1);
79
82
  try {
80
83
  browser._majorVersion = +browser._version.split(".")[0];
@@ -100,10 +103,10 @@ class CRBrowser extends import_browser.Browser {
100
103
  const proxy = options.proxyOverride || options.proxy;
101
104
  let proxyBypassList = void 0;
102
105
  if (proxy) {
103
- if (process.env.PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK)
104
- proxyBypassList = proxy.bypass;
105
- else
106
+ if (shouldProxyLoopback(proxy.bypass))
106
107
  proxyBypassList = "<-loopback>" + (proxy.bypass ? `,${proxy.bypass}` : "");
108
+ else
109
+ proxyBypassList = proxy.bypass;
107
110
  }
108
111
  const { browserContextId } = await this._session.send("Target.createBrowserContext", {
109
112
  disposeOnDetach: true,
@@ -389,7 +392,8 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
389
392
  ["midi-sysex", "midiSysex"],
390
393
  ["storage-access", "storageAccess"],
391
394
  ["local-fonts", "localFonts"],
392
- ["local-network-access", ["localNetworkAccess", "localNetwork", "loopbackNetwork"]]
395
+ ["local-network-access", ["localNetworkAccess", "localNetwork", "loopbackNetwork"]],
396
+ ["screen-wake-lock", "wakeLockScreen"]
393
397
  ]);
394
398
  const grantPermissions = async (mapping) => {
395
399
  const filtered = permissions.flatMap((permission) => {
@@ -466,7 +470,6 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
466
470
  async doClose(reason) {
467
471
  await this.dialogManager.closeBeforeUnloadDialogs();
468
472
  if (!this._browserContextId) {
469
- await this.stopVideoRecording();
470
473
  await this._browser.close({ reason });
471
474
  return;
472
475
  }
@@ -479,9 +482,6 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
479
482
  this._browser._serviceWorkers.delete(targetId);
480
483
  }
481
484
  }
482
- async stopVideoRecording() {
483
- await Promise.all(this._crPages().map((crPage) => crPage._page.screencast.stopVideoRecording()));
484
- }
485
485
  onClosePersistent() {
486
486
  }
487
487
  async clearCache() {
@@ -513,8 +513,16 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
513
513
  return rootSession.attachToTarget(targetId);
514
514
  }
515
515
  }
516
+ function shouldProxyLoopback(bypass) {
517
+ if (process.env.PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK)
518
+ return false;
519
+ const hosts = (bypass || "").split(",").map((s) => s.trim());
520
+ const shouldBypassSomeLoopback = ["localhost", "127.0.0.1", "::1", "[::]", "[::1]", "<loopback>", "<-loopback>"].some((host) => hosts.includes(host));
521
+ return !shouldBypassSomeLoopback;
522
+ }
516
523
  // Annotate the CommonJS export names for ESM import in node:
517
524
  0 && (module.exports = {
518
525
  CRBrowser,
519
- CRBrowserContext
526
+ CRBrowserContext,
527
+ shouldProxyLoopback
520
528
  });
@@ -239,7 +239,7 @@ class CRNetworkManager {
239
239
  this._requestIdToRequestWillBeSentEvent.delete(requestId);
240
240
  } else {
241
241
  const existingRequest = this._requestIdToRequest.get(requestId);
242
- const alreadyContinuedParams = existingRequest?._route?._alreadyContinuedParams;
242
+ const alreadyContinuedParams = existingRequest?._originalRequestRoute?._alreadyContinuedParams;
243
243
  if (alreadyContinuedParams && !event.redirectedRequestId) {
244
244
  sessionInfo.session._sendMayFail("Fetch.continueRequest", {
245
245
  ...alreadyContinuedParams,
@@ -333,7 +333,7 @@ class CRNetworkManager {
333
333
  const response2 = await session.send("Network.getResponseBody", { requestId: request._requestId });
334
334
  if (response2.body || !expectedLength)
335
335
  return Buffer.from(response2.body, response2.base64Encoded ? "base64" : "utf8");
336
- if (request._route?._fulfilled)
336
+ if (request._originalRequestRoute?._fulfilled)
337
337
  return Buffer.from("");
338
338
  const resource = await session.send("Network.loadNetworkResource", { url: request.request.url(), frameId: this._serviceWorker ? void 0 : request.request.frame()._id, options: { disableCache: false, includeCredentials: true } });
339
339
  const chunks = [];
@@ -372,7 +372,8 @@ class CRNetworkManager {
372
372
  responseStart: -1
373
373
  };
374
374
  }
375
- const response = new network.Response(request.request, responsePayload.status, responsePayload.statusText, (0, import_utils.headersObjectToArray)(responsePayload.headers), timing, getResponseBody, !!responsePayload.fromServiceWorker, responsePayload.protocol);
375
+ const response = new network.Response(request.request, responsePayload.status, responsePayload.statusText, (0, import_utils.headersObjectToArray)(responsePayload.headers), timing, getResponseBody, !!responsePayload.fromServiceWorker);
376
+ response._setHttpVersion(responsePayload?.protocol ?? null);
376
377
  if (responsePayload?.remoteIPAddress && typeof responsePayload?.remotePort === "number") {
377
378
  response._serverAddrFinished({
378
379
  ipAddress: responsePayload.remoteIPAddress,
@@ -478,7 +479,6 @@ class InterceptableRequest {
478
479
  this._requestId = requestWillBeSentEvent.requestId;
479
480
  this._interceptionId = requestPausedEvent && requestPausedEvent.requestId;
480
481
  this._documentId = documentId;
481
- this._route = route;
482
482
  this._originalRequestRoute = route ?? redirectedFrom?._originalRequestRoute;
483
483
  const {
484
484
  headers,