patchright-core 1.58.2 → 1.59.1

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 (285) 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 +22 -61
  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/clientHelper.js +2 -1
  16. package/lib/client/clock.js +0 -1
  17. package/lib/client/{webSocket.js → connect.js} +57 -7
  18. package/lib/client/connection.js +8 -4
  19. package/lib/client/consoleMessage.js +3 -0
  20. package/lib/client/debugger.js +57 -0
  21. package/lib/client/dialog.js +8 -1
  22. package/lib/client/disposable.js +76 -0
  23. package/lib/client/electron.js +1 -0
  24. package/lib/client/elementHandle.js +1 -4
  25. package/lib/client/events.js +3 -3
  26. package/lib/client/fetch.js +0 -1
  27. package/lib/client/frame.js +10 -23
  28. package/lib/client/harRouter.js +13 -1
  29. package/lib/client/jsHandle.js +4 -8
  30. package/lib/client/locator.js +13 -44
  31. package/lib/client/network.js +15 -16
  32. package/lib/client/page.js +41 -75
  33. package/lib/client/platform.js +0 -3
  34. package/lib/client/screencast.js +88 -0
  35. package/lib/client/selectors.js +3 -1
  36. package/lib/client/tracing.js +11 -5
  37. package/lib/client/video.js +13 -20
  38. package/lib/client/worker.js +6 -6
  39. package/lib/generated/bindingsControllerSource.js +1 -1
  40. package/lib/generated/clockSource.js +1 -1
  41. package/lib/generated/injectedScriptSource.js +1 -1
  42. package/lib/generated/pollingRecorderSource.js +1 -1
  43. package/lib/generated/storageScriptSource.js +1 -1
  44. package/lib/generated/utilityScriptSource.js +1 -1
  45. package/lib/mcpBundle.js +0 -6
  46. package/lib/mcpBundleImpl.js +91 -0
  47. package/lib/protocol/validator.js +224 -138
  48. package/lib/protocol/validatorPrimitives.js +1 -1
  49. package/lib/remote/playwrightConnection.js +10 -8
  50. package/lib/remote/playwrightPipeServer.js +100 -0
  51. package/lib/remote/playwrightServer.js +13 -8
  52. package/lib/remote/playwrightWebSocketServer.js +73 -0
  53. package/lib/remote/serverTransport.js +96 -0
  54. package/lib/server/android/android.js +2 -2
  55. package/lib/server/bidi/bidiBrowser.js +30 -8
  56. package/lib/server/bidi/bidiChromium.js +18 -5
  57. package/lib/server/bidi/bidiNetworkManager.js +39 -11
  58. package/lib/server/bidi/bidiPage.js +31 -15
  59. package/lib/server/bidi/third_party/firefoxPrefs.js +3 -1
  60. package/lib/server/browser.js +84 -21
  61. package/lib/server/browserContext.js +110 -58
  62. package/lib/server/browserType.js +14 -12
  63. package/lib/server/chromium/chromium.js +15 -12
  64. package/lib/server/chromium/chromiumSwitches.js +14 -2
  65. package/lib/server/chromium/crBrowser.js +20 -17
  66. package/lib/server/chromium/crCoverage.js +1 -13
  67. package/lib/server/chromium/crDevTools.js +1 -0
  68. package/lib/server/chromium/crNetworkManager.js +12 -267
  69. package/lib/server/chromium/crPage.js +67 -199
  70. package/lib/server/chromium/crServiceWorker.js +7 -14
  71. package/lib/server/clock.js +33 -41
  72. package/lib/server/console.js +5 -1
  73. package/lib/server/debugController.js +12 -6
  74. package/lib/server/debugger.js +40 -47
  75. package/lib/server/deviceDescriptorsSource.json +137 -137
  76. package/lib/server/dispatchers/browserContextDispatcher.js +29 -30
  77. package/lib/server/dispatchers/browserDispatcher.js +11 -5
  78. package/lib/server/dispatchers/browserTypeDispatcher.js +7 -0
  79. package/lib/server/dispatchers/cdpSessionDispatcher.js +4 -1
  80. package/lib/server/dispatchers/debuggerDispatcher.js +84 -0
  81. package/lib/server/dispatchers/dispatcher.js +1 -1
  82. package/lib/server/dispatchers/disposableDispatcher.js +39 -0
  83. package/lib/server/dispatchers/electronDispatcher.js +2 -1
  84. package/lib/server/dispatchers/frameDispatcher.js +6 -6
  85. package/lib/server/dispatchers/jsHandleDispatcher.js +2 -2
  86. package/lib/server/dispatchers/localUtilsDispatcher.js +37 -1
  87. package/lib/server/dispatchers/networkDispatchers.js +6 -5
  88. package/lib/server/dispatchers/pageDispatcher.js +101 -38
  89. package/lib/server/dispatchers/webSocketRouteDispatcher.js +4 -5
  90. package/lib/server/disposable.js +41 -0
  91. package/lib/server/dom.js +44 -26
  92. package/lib/server/download.js +3 -2
  93. package/lib/server/electron/electron.js +12 -7
  94. package/lib/server/firefox/ffBrowser.js +9 -19
  95. package/lib/server/firefox/ffInput.js +21 -5
  96. package/lib/server/firefox/ffNetworkManager.js +2 -2
  97. package/lib/server/firefox/ffPage.js +24 -27
  98. package/lib/server/frameSelectors.js +5 -172
  99. package/lib/server/frames.js +234 -687
  100. package/lib/server/har/harRecorder.js +2 -2
  101. package/lib/server/har/harTracer.js +5 -4
  102. package/lib/server/input.js +49 -4
  103. package/lib/server/instrumentation.js +5 -0
  104. package/lib/server/javascript.js +6 -26
  105. package/lib/server/launchApp.js +1 -3
  106. package/lib/server/localUtils.js +6 -6
  107. package/lib/server/network.js +9 -8
  108. package/lib/server/overlay.js +138 -0
  109. package/lib/server/page.js +157 -105
  110. package/lib/server/progress.js +6 -0
  111. package/lib/server/recorder/recorderApp.js +9 -8
  112. package/lib/server/recorder.js +76 -40
  113. package/lib/server/registry/index.js +55 -82
  114. package/lib/server/registry/nativeDeps.js +1 -0
  115. package/lib/server/screencast.js +90 -143
  116. package/lib/server/screenshotter.js +0 -6
  117. package/lib/server/trace/recorder/snapshotter.js +8 -17
  118. package/lib/server/trace/recorder/snapshotterInjected.js +82 -20
  119. package/lib/server/trace/recorder/tracing.js +87 -44
  120. package/lib/server/trace/viewer/traceViewer.js +3 -4
  121. package/lib/server/usKeyboardLayout.js +7 -0
  122. package/lib/server/utils/comparators.js +1 -1
  123. package/lib/server/utils/disposable.js +32 -0
  124. package/lib/server/utils/eventsHelper.js +3 -1
  125. package/lib/server/utils/fileUtils.js +16 -2
  126. package/lib/server/utils/happyEyeballs.js +15 -12
  127. package/lib/server/utils/hostPlatform.js +0 -15
  128. package/lib/server/utils/httpServer.js +5 -3
  129. package/lib/server/utils/network.js +2 -1
  130. package/lib/server/utils/nodePlatform.js +0 -6
  131. package/lib/server/utils/processLauncher.js +6 -5
  132. package/lib/server/utils/zipFile.js +2 -2
  133. package/lib/server/videoRecorder.js +82 -12
  134. package/lib/server/webkit/wkBrowser.js +1 -6
  135. package/lib/server/webkit/wkPage.js +27 -25
  136. package/lib/server/webkit/wkWorkers.js +2 -1
  137. package/lib/serverRegistry.js +156 -0
  138. package/lib/tools/backend/browserBackend.js +79 -0
  139. package/lib/tools/backend/common.js +63 -0
  140. package/lib/tools/backend/config.js +41 -0
  141. package/lib/tools/backend/console.js +66 -0
  142. package/lib/tools/backend/context.js +296 -0
  143. package/lib/tools/backend/cookies.js +152 -0
  144. package/lib/tools/backend/devtools.js +69 -0
  145. package/lib/tools/backend/dialogs.js +59 -0
  146. package/lib/tools/backend/evaluate.js +64 -0
  147. package/lib/tools/backend/files.js +60 -0
  148. package/lib/tools/backend/form.js +64 -0
  149. package/lib/tools/backend/keyboard.js +155 -0
  150. package/lib/tools/backend/logFile.js +95 -0
  151. package/lib/tools/backend/mouse.js +168 -0
  152. package/lib/tools/backend/navigate.js +106 -0
  153. package/lib/tools/backend/network.js +135 -0
  154. package/lib/tools/backend/pdf.js +48 -0
  155. package/lib/tools/backend/response.js +305 -0
  156. package/lib/tools/backend/route.js +140 -0
  157. package/lib/tools/backend/runCode.js +77 -0
  158. package/lib/tools/backend/screenshot.js +88 -0
  159. package/lib/tools/backend/sessionLog.js +74 -0
  160. package/lib/tools/backend/snapshot.js +208 -0
  161. package/lib/tools/backend/storage.js +68 -0
  162. package/lib/tools/backend/tab.js +445 -0
  163. package/lib/tools/backend/tabs.js +67 -0
  164. package/lib/tools/backend/tool.js +47 -0
  165. package/lib/tools/backend/tools.js +102 -0
  166. package/lib/tools/backend/tracing.js +78 -0
  167. package/lib/tools/backend/utils.js +83 -0
  168. package/lib/tools/backend/verify.js +151 -0
  169. package/lib/tools/backend/video.js +98 -0
  170. package/lib/tools/backend/wait.js +63 -0
  171. package/lib/tools/backend/webstorage.js +223 -0
  172. package/lib/tools/cli-client/cli.js +6 -0
  173. package/lib/tools/cli-client/help.json +399 -0
  174. package/lib/tools/cli-client/minimist.js +128 -0
  175. package/lib/tools/cli-client/program.js +350 -0
  176. package/lib/tools/cli-client/registry.js +176 -0
  177. package/lib/tools/cli-client/session.js +289 -0
  178. package/lib/tools/cli-client/skill/SKILL.md +328 -0
  179. package/lib/tools/cli-client/skill/references/element-attributes.md +23 -0
  180. package/lib/tools/cli-client/skill/references/playwright-tests.md +39 -0
  181. package/lib/tools/cli-client/skill/references/request-mocking.md +87 -0
  182. package/lib/tools/cli-client/skill/references/running-code.md +231 -0
  183. package/lib/tools/cli-client/skill/references/session-management.md +169 -0
  184. package/lib/tools/cli-client/skill/references/storage-state.md +275 -0
  185. package/lib/tools/cli-client/skill/references/test-generation.md +88 -0
  186. package/lib/tools/cli-client/skill/references/tracing.md +139 -0
  187. package/lib/tools/cli-client/skill/references/video-recording.md +143 -0
  188. package/lib/tools/cli-daemon/command.js +73 -0
  189. package/lib/tools/cli-daemon/commands.js +956 -0
  190. package/lib/tools/cli-daemon/daemon.js +157 -0
  191. package/lib/tools/cli-daemon/helpGenerator.js +177 -0
  192. package/lib/tools/cli-daemon/program.js +129 -0
  193. package/lib/tools/dashboard/appIcon.png +0 -0
  194. package/lib/tools/dashboard/dashboardApp.js +284 -0
  195. package/lib/tools/dashboard/dashboardController.js +296 -0
  196. package/lib/tools/exports.js +60 -0
  197. package/lib/tools/mcp/browserFactory.js +233 -0
  198. package/lib/tools/mcp/cdpRelay.js +352 -0
  199. package/lib/tools/mcp/cli-stub.js +7 -0
  200. package/lib/tools/mcp/config.d.js +16 -0
  201. package/lib/tools/mcp/config.js +446 -0
  202. package/lib/tools/mcp/configIni.js +189 -0
  203. package/lib/tools/mcp/extensionContextFactory.js +55 -0
  204. package/lib/tools/mcp/index.js +62 -0
  205. package/lib/tools/mcp/log.js +35 -0
  206. package/lib/tools/mcp/program.js +107 -0
  207. package/lib/tools/mcp/protocol.js +28 -0
  208. package/lib/tools/mcp/watchdog.js +44 -0
  209. package/lib/tools/trace/SKILL.md +171 -0
  210. package/lib/{server/trace/viewer/traceParser.js → tools/trace/installSkill.js} +15 -39
  211. package/lib/tools/trace/traceActions.js +142 -0
  212. package/lib/tools/trace/traceAttachments.js +69 -0
  213. package/lib/tools/trace/traceCli.js +87 -0
  214. package/lib/tools/trace/traceConsole.js +97 -0
  215. package/lib/tools/trace/traceErrors.js +55 -0
  216. package/lib/tools/trace/traceOpen.js +69 -0
  217. package/lib/tools/trace/traceParser.js +96 -0
  218. package/lib/tools/trace/traceRequests.js +182 -0
  219. package/lib/tools/trace/traceScreenshot.js +68 -0
  220. package/lib/tools/trace/traceSnapshot.js +149 -0
  221. package/lib/tools/trace/traceUtils.js +153 -0
  222. package/lib/tools/utils/connect.js +32 -0
  223. package/lib/tools/utils/mcp/http.js +152 -0
  224. package/lib/tools/utils/mcp/server.js +230 -0
  225. package/lib/tools/utils/mcp/tool.js +47 -0
  226. package/lib/tools/utils/socketConnection.js +108 -0
  227. package/lib/utils/isomorphic/formatUtils.js +64 -0
  228. package/lib/utils/isomorphic/jsonSchema.js +89 -0
  229. package/lib/utils/isomorphic/mimeType.js +7 -2
  230. package/lib/utils/isomorphic/protocolFormatter.js +2 -2
  231. package/lib/utils/isomorphic/protocolMetainfo.js +127 -106
  232. package/lib/utils/isomorphic/stringUtils.js +3 -3
  233. package/lib/utils/isomorphic/timeoutRunner.js +3 -3
  234. package/lib/utils/isomorphic/trace/snapshotRenderer.js +35 -42
  235. package/lib/utils/isomorphic/trace/traceLoader.js +15 -14
  236. package/lib/utils/isomorphic/trace/traceModel.js +3 -2
  237. package/lib/utils/isomorphic/trace/traceModernizer.js +1 -0
  238. package/lib/utils/isomorphic/urlMatch.js +54 -1
  239. package/lib/utils/isomorphic/utilityScriptSerializers.js +11 -0
  240. package/lib/utils.js +6 -2
  241. package/lib/utilsBundle.js +3 -21
  242. package/lib/utilsBundleImpl/index.js +132 -133
  243. package/lib/vite/dashboard/assets/index-BAOybkp8.js +50 -0
  244. package/lib/vite/dashboard/assets/index-CZAYOG76.css +1 -0
  245. package/lib/vite/dashboard/index.html +28 -0
  246. package/lib/vite/htmlReport/index.html +2 -70
  247. package/lib/vite/htmlReport/report.css +1 -0
  248. package/lib/vite/htmlReport/report.js +72 -0
  249. package/lib/vite/recorder/assets/{codeMirrorModule-CFUTFUO7.js → codeMirrorModule-C8KMvO9L.js} +20 -20
  250. package/lib/vite/recorder/assets/index-CqAYX1I3.js +193 -0
  251. package/lib/vite/recorder/index.html +1 -1
  252. package/lib/vite/traceViewer/assets/{codeMirrorModule-BVA4h_ZY.js → codeMirrorModule-DS0FLvoc.js} +20 -20
  253. package/lib/vite/traceViewer/assets/defaultSettingsView-GTWI-W_B.js +262 -0
  254. package/lib/vite/traceViewer/defaultSettingsView.B4dS75f0.css +1 -0
  255. package/lib/vite/traceViewer/{index.BtyWtaE-.js → index.C5466mMT.js} +1 -1
  256. package/lib/vite/traceViewer/{index.BVu7tZDe.css → index.CzXZzn5A.css} +1 -1
  257. package/lib/vite/traceViewer/index.html +4 -4
  258. package/lib/vite/traceViewer/sw.bundle.js +4 -4
  259. package/lib/vite/traceViewer/uiMode.Vipi55dB.js +6 -0
  260. package/lib/vite/traceViewer/uiMode.html +3 -3
  261. package/lib/zipBundleImpl.js +2 -2
  262. package/lib/zodBundle.js +39 -0
  263. package/lib/zodBundleImpl.js +40 -0
  264. package/package.json +6 -1
  265. package/types/protocol.d.ts +947 -51
  266. package/types/types.d.ts +854 -74
  267. package/lib/client/pageAgent.js +0 -64
  268. package/lib/mcpBundleImpl/index.js +0 -147
  269. package/lib/server/agent/actionRunner.js +0 -335
  270. package/lib/server/agent/actions.js +0 -128
  271. package/lib/server/agent/codegen.js +0 -111
  272. package/lib/server/agent/context.js +0 -150
  273. package/lib/server/agent/expectTools.js +0 -156
  274. package/lib/server/agent/pageAgent.js +0 -204
  275. package/lib/server/agent/performTools.js +0 -262
  276. package/lib/server/agent/tool.js +0 -109
  277. package/lib/server/dispatchers/pageAgentDispatcher.js +0 -96
  278. package/lib/server/pageBinding.js +0 -87
  279. package/lib/utils/isomorphic/oldUtilityScriptSerializers.js +0 -248
  280. package/lib/vite/recorder/assets/index-CVkBxsGf.js +0 -193
  281. package/lib/vite/traceViewer/assets/defaultSettingsView-CjfmcdOz.js +0 -266
  282. package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +0 -1
  283. package/lib/vite/traceViewer/uiMode.fyrXARf2.js +0 -5
  284. /package/lib/{server/utils → utils/isomorphic}/imageUtils.js +0 -0
  285. /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,24 @@ 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, `navigator.serviceWorker.register = async () => { };`);
131
+ await this.addInitScript(`
132
+ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { console.warn('Service Worker registration blocked by Playwright'); };
133
+ `);
128
134
  if (this._options.permissions)
129
135
  await this.grantPermissions(this._options.permissions);
130
136
  }
@@ -140,10 +146,6 @@ class BrowserContext extends import_instrumentation.SdkObject {
140
146
  module.exports = { default: () => installConsoleApi };
141
147
  `);
142
148
  }
143
- async _ensureVideosPath() {
144
- if (this._options.recordVideo)
145
- await (0, import_fileUtils.mkdirIfNeeded)(import_path.default.join(this._options.recordVideo.dir, "dummy"));
146
- }
147
149
  canResetForReuse() {
148
150
  if (this._closedStatus !== "open")
149
151
  return false;
@@ -237,7 +239,7 @@ class BrowserContext extends import_instrumentation.SdkObject {
237
239
  async exposePlaywrightBindingIfNeeded() {
238
240
  this._playwrightBindingExposed ??= (async () => {
239
241
  await this.doExposePlaywrightBinding();
240
- this.bindingsInitScript = import_page2.PageBinding.createInitScript();
242
+ this.bindingsInitScript = import_page2.PageBinding.createInitScript(this);
241
243
  this.initScripts.push(this.bindingsInitScript);
242
244
  await this.doAddInitScript(this.bindingsInitScript);
243
245
  await this.safeNonStallingEvaluateInAllFrames(this.bindingsInitScript.source, "main");
@@ -254,16 +256,26 @@ class BrowserContext extends import_instrumentation.SdkObject {
254
256
  if (page.getBinding(name))
255
257
  throw new Error(`Function "${name}" has been already registered in one of the pages`);
256
258
  }
257
- const binding = new import_page2.PageBinding(name, playwrightBinding, needsHandle);
259
+ await progress.race(this.exposePlaywrightBindingIfNeeded());
260
+ const binding = new import_page2.PageBinding(this, name, playwrightBinding, needsHandle);
258
261
  binding.forClient = forClient;
259
262
  this._pageBindings.set(name, binding);
260
- await this.doExposeBinding(binding);
261
- }
262
- async removeExposedBindings(bindings) {
263
- for (const key of this._pageBindings.keys()) {
264
- if (!key.startsWith("__pw")) this._pageBindings.delete(key);
263
+ try {
264
+ await progress.race(this.doAddInitScript(binding.initScript));
265
+ await progress.race(this.safeNonStallingEvaluateInAllFrames(binding.initScript.source, "main"));
266
+ return binding;
267
+ } catch (error) {
268
+ this._pageBindings.delete(name);
269
+ throw error;
265
270
  }
266
- await this.doRemoveExposedBindings();
271
+ }
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} };`;
278
+ await this.safeNonStallingEvaluateInAllFrames(cleanup, "main");
267
279
  }
268
280
  async grantPermissions(permissions, origin) {
269
281
  let resolvedOrigin = "*";
@@ -349,25 +361,21 @@ class BrowserContext extends import_instrumentation.SdkObject {
349
361
  if (username)
350
362
  this._options.httpCredentials = { username, password: password || "" };
351
363
  }
352
- async addInitScript(progress, source) {
353
- const initScript = new import_page.InitScript(source);
364
+ async addInitScript(source) {
365
+ const initScript = new import_page.InitScript(this, source);
354
366
  this.initScripts.push(initScript);
355
367
  try {
356
- const promise = this.doAddInitScript(initScript);
357
- if (progress)
358
- await progress.race(promise);
359
- else
360
- await promise;
368
+ await this.doAddInitScript(initScript);
361
369
  return initScript;
362
370
  } catch (error) {
363
- this.removeInitScripts([initScript]).catch(() => {
371
+ initScript.dispose().catch(() => {
364
372
  });
365
373
  throw error;
366
374
  }
367
375
  }
368
- async removeInitScripts(initScripts) {
369
- this.initScripts.splice(0, this.initScripts.length);
370
- await this.doRemoveInitScripts();
376
+ async removeInitScript(initScript) {
377
+ this.initScripts = this.initScripts.filter((script) => initScript !== script);
378
+ await this.doRemoveInitScripts([initScript]);
371
379
  }
372
380
  async addRequestInterceptor(progress, handler) {
373
381
  this.requestInterceptors.push(handler);
@@ -403,16 +411,13 @@ class BrowserContext extends import_instrumentation.SdkObject {
403
411
  for (const harRecorder of this._harRecorders.values())
404
412
  await harRecorder.flush();
405
413
  await this.tracing.flush();
406
- const promises = [];
407
- for (const { context, artifact } of this._browser._idToVideo.values()) {
408
- if (context === this)
409
- promises.push(artifact.finishedPromise());
410
- }
414
+ await Promise.all(this.pages().map((page) => page.screencast.handlePageOrContextClose()));
411
415
  if (this._customCloseHandler) {
412
416
  await this._customCloseHandler();
413
417
  } else {
414
418
  await this.doClose(options.reason);
415
419
  }
420
+ const promises = [];
416
421
  promises.push(this._deleteAllDownloads());
417
422
  promises.push(this._deleteAllTempDirs());
418
423
  await Promise.all(promises);
@@ -588,22 +593,6 @@ function validateBrowserContextOptions(options, browserOptions) {
588
593
  options.acceptDownloads = "internal-browser-default";
589
594
  if (!options.viewport && !options.noDefaultViewport)
590
595
  options.viewport = { width: 1280, height: 720 };
591
- if (options.recordVideo) {
592
- if (!options.recordVideo.size) {
593
- if (options.noDefaultViewport) {
594
- options.recordVideo.size = { width: 800, height: 600 };
595
- } else {
596
- const size = options.viewport;
597
- const scale = Math.min(1, 800 / Math.max(size.width, size.height));
598
- options.recordVideo.size = {
599
- width: Math.floor(size.width * scale),
600
- height: Math.floor(size.height * scale)
601
- };
602
- }
603
- }
604
- options.recordVideo.size.width &= ~1;
605
- options.recordVideo.size.height &= ~1;
606
- }
607
596
  if (options.proxy)
608
597
  options.proxy = normalizeProxySettings(options.proxy);
609
598
  verifyGeolocation(options.geolocation);
@@ -655,6 +644,69 @@ function normalizeProxySettings(proxy) {
655
644
  bypass = bypass.split(",").map((t) => t.trim()).join(",");
656
645
  return { ...proxy, server, bypass };
657
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
+ }
658
710
  const paramsThatAllowContextReuse = [
659
711
  "colorScheme",
660
712
  "forcedColors",
@@ -676,12 +728,12 @@ const defaultNewContextParamValues = {
676
728
  acceptDownloads: "accept",
677
729
  strictSelectors: false,
678
730
  serviceWorkers: "allow",
679
- locale: "en-US",
680
- focusControl: false
731
+ locale: "en-US"
681
732
  };
682
733
  // Annotate the CommonJS export names for ESM import in node:
683
734
  0 && (module.exports = {
684
735
  BrowserContext,
736
+ calculateUserAgentEmulation,
685
737
  normalizeProxySettings,
686
738
  validateBrowserContextOptions,
687
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,8 +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
- }
286
+ chromeArguments.push("--enable-unsafe-swiftshader");
282
287
  if (options.headless) {
283
288
  chromeArguments.push("--headless");
284
289
  chromeArguments.push(
@@ -298,11 +303,9 @@ class Chromium extends import_browserType.BrowserType {
298
303
  }
299
304
  chromeArguments.push(`--proxy-server=${proxy.server}`);
300
305
  const proxyBypassRules = [];
301
- if (options.socksProxyPort)
302
- proxyBypassRules.push("<-loopback>");
303
306
  if (proxy.bypass)
304
307
  proxyBypassRules.push(...proxy.bypass.split(",").map((t) => t.trim()).map((t) => t.startsWith(".") ? "*" + t : t));
305
- if (!process.env.PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK && !proxyBypassRules.includes("<-loopback>"))
308
+ if (options.socksProxyPort || (0, import_crBrowser.shouldProxyLoopback)(proxy.bypass))
306
309
  proxyBypassRules.push("<-loopback>");
307
310
  if (proxyBypassRules.length > 0)
308
311
  chromeArguments.push(`--proxy-bypass-list=${proxyBypassRules.join(";")}`);
@@ -56,17 +56,27 @@ const chromiumSwitches = (assistantMode, channel, android) => [
56
56
  "--disable-background-networking",
57
57
  "--disable-background-timer-throttling",
58
58
  "--disable-backgrounding-occluded-windows",
59
+ "--disable-back-forward-cache",
59
60
  // Avoids surprises like main request not being intercepted during page.goBack().
60
61
  "--disable-breakpad",
62
+ "--disable-client-side-phishing-detection",
63
+ "--disable-component-extensions-with-background-pages",
64
+ "--disable-component-update",
61
65
  // Avoids unneeded network activity after startup.
62
66
  "--no-default-browser-check",
67
+ "--disable-default-apps",
63
68
  "--disable-dev-shm-usage",
69
+ "--disable-extensions",
64
70
  "--disable-features=" + disabledFeatures(assistantMode).join(","),
65
71
  process.env.PLAYWRIGHT_LEGACY_SCREENSHOT ? "" : "--enable-features=CDPScreenshotNewSurface",
72
+ "--allow-pre-commit-input",
66
73
  "--disable-hang-monitor",
74
+ "--disable-ipc-flooding-protection",
75
+ "--disable-popup-blocking",
67
76
  "--disable-prompt-on-repost",
68
77
  "--disable-renderer-backgrounding",
69
78
  "--force-color-profile=srgb",
79
+ "--metrics-recording-only",
70
80
  "--no-first-run",
71
81
  "--password-store=basic",
72
82
  "--use-mock-keychain",
@@ -75,16 +85,18 @@ const chromiumSwitches = (assistantMode, channel, android) => [
75
85
  "--export-tagged-pdf",
76
86
  // https://chromium-review.googlesource.com/c/chromium/src/+/4853540
77
87
  "--disable-search-engine-choice-screen",
88
+ // https://issues.chromium.org/41491762
89
+ "--unsafely-disable-devtools-self-xss-warnings",
78
90
  // Edge can potentially restart on Windows (msRelaunchNoCompatLayer) which looses its file descriptors (stdout/stderr) and CDP (3/4). Disable until fixed upstream.
79
91
  "--edge-skip-compat-layer-relaunch",
92
+ assistantMode ? "" : "--enable-automation",
80
93
  // This disables Chrome for Testing infobar that is visible in the persistent context.
81
94
  // The switch is ignored everywhere else, including Chromium/Chrome/Edge.
82
95
  "--disable-infobars",
83
96
  // Less annoying popups.
84
97
  "--disable-search-engine-choice-screen",
85
98
  // Prevents the "three dots" menu crash in IdentityManager::HasPrimaryAccount for ephemeral contexts.
86
- android ? "" : "--disable-sync",
87
- "--disable-blink-features=AutomationControlled"
99
+ android ? "" : "--disable-sync"
88
100
  ].filter(Boolean);
89
101
  // Annotate the CommonJS export names for ESM import in node:
90
102
  0 && (module.exports = {
@@ -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) => {
@@ -446,7 +450,8 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
446
450
  await page.delegate.addInitScript(initScript);
447
451
  }
448
452
  async doRemoveInitScripts(initScripts) {
449
- for (const page of this.pages()) await page.delegate.removeInitScripts();
453
+ for (const page of this.pages())
454
+ await page.delegate.removeInitScripts(initScripts);
450
455
  }
451
456
  async doUpdateRequestInterception() {
452
457
  for (const page of this.pages())
@@ -465,7 +470,6 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
465
470
  async doClose(reason) {
466
471
  await this.dialogManager.closeBeforeUnloadDialogs();
467
472
  if (!this._browserContextId) {
468
- await this.stopVideoRecording();
469
473
  await this._browser.close({ reason });
470
474
  return;
471
475
  }
@@ -478,9 +482,6 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
478
482
  this._browser._serviceWorkers.delete(targetId);
479
483
  }
480
484
  }
481
- async stopVideoRecording() {
482
- await Promise.all(this._crPages().map((crPage) => crPage._page.screencast.stopVideoRecording()));
483
- }
484
485
  onClosePersistent() {
485
486
  }
486
487
  async clearCache() {
@@ -511,15 +512,17 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
511
512
  const rootSession = await this._browser._clientRootSession();
512
513
  return rootSession.attachToTarget(targetId);
513
514
  }
514
- async doExposeBinding(binding) {
515
- for (const page of this.pages()) await page.delegate.exposeBinding(binding);
516
- }
517
- async doRemoveExposedBindings() {
518
- for (const page of this.pages()) await page.delegate.removeExposedBindings();
519
- }
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;
520
522
  }
521
523
  // Annotate the CommonJS export names for ESM import in node:
522
524
  0 && (module.exports = {
523
525
  CRBrowser,
524
- CRBrowserContext
526
+ CRBrowserContext,
527
+ shouldProxyLoopback
525
528
  });
@@ -66,7 +66,6 @@ class JSCoverage {
66
66
  this._eventListeners = [
67
67
  import_eventsHelper.eventsHelper.addEventListener(this._client, "Debugger.scriptParsed", this._onScriptParsed.bind(this)),
68
68
  import_eventsHelper.eventsHelper.addEventListener(this._client, "Runtime.executionContextsCleared", this._onExecutionContextsCleared.bind(this)),
69
- import_eventsHelper.eventsHelper.addEventListener(this._client, "Page.frameNavigated", this._onFrameNavigated.bind(this)),
70
69
  import_eventsHelper.eventsHelper.addEventListener(this._client, "Debugger.paused", this._onDebuggerPaused.bind(this))
71
70
  ];
72
71
  await Promise.all([
@@ -118,11 +117,6 @@ class JSCoverage {
118
117
  }
119
118
  return coverage;
120
119
  }
121
- _onFrameNavigated(event) {
122
- if (event.frame.parentId)
123
- return;
124
- this._onExecutionContextsCleared();
125
- }
126
120
  }
127
121
  class CSSCoverage {
128
122
  constructor(client) {
@@ -142,8 +136,7 @@ class CSSCoverage {
142
136
  this._stylesheetSources.clear();
143
137
  this._eventListeners = [
144
138
  import_eventsHelper.eventsHelper.addEventListener(this._client, "CSS.styleSheetAdded", this._onStyleSheet.bind(this)),
145
- import_eventsHelper.eventsHelper.addEventListener(this._client, "Runtime.executionContextsCleared", this._onExecutionContextsCleared.bind(this)),
146
- import_eventsHelper.eventsHelper.addEventListener(this._client, "Page.frameNavigated", this._onFrameNavigated.bind(this))
139
+ import_eventsHelper.eventsHelper.addEventListener(this._client, "Runtime.executionContextsCleared", this._onExecutionContextsCleared.bind(this))
147
140
  ];
148
141
  await Promise.all([
149
142
  this._client.send("DOM.enable"),
@@ -199,11 +192,6 @@ class CSSCoverage {
199
192
  }
200
193
  return coverage;
201
194
  }
202
- _onFrameNavigated(event) {
203
- if (event.frame.parentId)
204
- return;
205
- this._onExecutionContextsCleared();
206
- }
207
195
  }
208
196
  function convertToDisjointRanges(nestedRanges) {
209
197
  const points = [];
@@ -70,6 +70,7 @@ class CRDevTools {
70
70
  }).catch((e) => null);
71
71
  });
72
72
  Promise.all([
73
+ session.send("Runtime.enable"),
73
74
  session.send("Runtime.addBinding", { name: kBindingName }),
74
75
  session.send("Page.enable"),
75
76
  session.send("Page.addScriptToEvaluateOnNewDocument", { source: `