chrome-devtools-frontend 1.0.1721762 → 1.0.1726686

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 (273) hide show
  1. package/.agents/skills/review-ui-widgets/SKILL.md +7 -7
  2. package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +12 -0
  3. package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +3 -3
  4. package/.agents/skills/ui-widgets/SKILL.md +2 -1
  5. package/docs/cookbook/dependencies.md +57 -11
  6. package/docs/get_the_code.md +15 -0
  7. package/front_end/core/i18n/collect-ui-strings.js +58 -12
  8. package/front_end/core/i18n/i18nImpl.ts +1 -1
  9. package/front_end/core/root/Runtime.ts +1 -1
  10. package/front_end/core/sdk/ResourceTreeModel.ts +16 -0
  11. package/front_end/core/sdk/WebAuthnModel.ts +17 -10
  12. package/front_end/entrypoints/js_app/js_app.ts +2 -5
  13. package/front_end/entrypoints/node_app/node_app.ts +2 -3
  14. package/front_end/generated/InspectorBackendCommands.ts +3 -3
  15. package/front_end/generated/protocol.ts +17 -0
  16. package/front_end/models/ai_assistance/skills/lighthouse.md +2 -1
  17. package/front_end/models/ai_assistance/skills/network.md +1 -0
  18. package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +26 -2
  19. package/front_end/models/ai_assistance/tools/GetLighthouseAudits.ts +1 -1
  20. package/front_end/models/ai_assistance/tools/ListNetworkRequests.ts +2 -7
  21. package/front_end/models/ai_assistance/tools/RunLighthouse.ts +2 -2
  22. package/front_end/models/comment_manager/CD4ABridge.ts +4 -0
  23. package/front_end/models/comment_manager/CommentManager.ts +0 -6
  24. package/front_end/models/comment_manager/CommentThread.ts +39 -19
  25. package/front_end/models/elements/StyleChanges.ts +66 -0
  26. package/front_end/models/trace/EventsSerializer.ts +2 -7
  27. package/front_end/models/trace/ModelImpl.ts +0 -2
  28. package/front_end/models/trace/handlers/FlowsHandler.ts +37 -29
  29. package/front_end/models/trace/handlers/NetworkRequestsHandler.ts +13 -6
  30. package/front_end/models/trace/helpers/SyntheticEvents.ts +10 -37
  31. package/front_end/models/trace/insights/RenderBlocking.ts +3 -1
  32. package/front_end/models/trace/lantern/simulation/Simulator.ts +4 -0
  33. package/front_end/models/trace/lantern/types/Lantern.ts +1 -0
  34. package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +92 -0
  35. package/front_end/panels/accessibility/SourceOrderView.ts +1 -1
  36. package/front_end/panels/accessibility/accessibilityAnnouncementRecordingListView.css +3 -1
  37. package/front_end/panels/accessibility/accessibilityAnnouncementRecordingView.css +12 -1
  38. package/front_end/panels/application/ApplicationPanelSidebar.ts +90 -0
  39. package/front_end/panels/application/StorageView.ts +348 -254
  40. package/front_end/panels/application/SubAppsView.ts +159 -0
  41. package/front_end/panels/application/application.ts +2 -0
  42. package/front_end/panels/application/preloading/PreloadingView.ts +360 -336
  43. package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +3 -3
  44. package/front_end/panels/application/preloading/components/PreloadingGrid.ts +6 -3
  45. package/front_end/panels/application/preloading/components/RuleSetGrid.ts +17 -17
  46. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +2 -2
  47. package/front_end/panels/application/preloading/preloadingView.css +12 -4
  48. package/front_end/panels/application/preloading/preloadingViewDropDown.css +1 -1
  49. package/front_end/panels/application/storageView.css +16 -21
  50. package/front_end/panels/application/subAppsView.css +21 -0
  51. package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +2 -2
  52. package/front_end/panels/browser_debugger/browser_debugger-meta.ts +6 -8
  53. package/front_end/panels/comments/CommentsPane.ts +26 -9
  54. package/front_end/panels/comments/commentsPane.css +25 -6
  55. package/front_end/panels/common/CommentThreadWidget.ts +2 -2
  56. package/front_end/panels/common/CommentsOverlayWidget.ts +94 -35
  57. package/front_end/panels/common/commentThreadWidget.css +17 -0
  58. package/front_end/panels/common/commentsOverlay.css +5 -10
  59. package/front_end/panels/common/common-meta.ts +11 -1
  60. package/front_end/panels/elements/ClassesPaneWidget.ts +133 -89
  61. package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +7 -33
  62. package/front_end/panels/elements/DOMTreeElementWidget.ts +3 -1
  63. package/front_end/panels/elements/DOMTreeWidget.ts +19 -3
  64. package/front_end/panels/elements/ElementStatePaneWidget.ts +11 -1
  65. package/front_end/panels/elements/PropertyRenderer.ts +3 -2
  66. package/front_end/panels/elements/StyleEditorWidget.ts +87 -39
  67. package/front_end/panels/elements/StylePropertiesSection.ts +32 -5
  68. package/front_end/panels/elements/StylePropertyTreeElement.ts +227 -162
  69. package/front_end/panels/elements/StylesSidebarPane.ts +1 -0
  70. package/front_end/panels/event_listeners/EventListenersView.ts +11 -8
  71. package/front_end/panels/layer_viewer/Layers3DView.ts +21 -37
  72. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterSettings.ts +1 -1
  73. package/front_end/panels/network/NetworkConfigView.ts +12 -10
  74. package/front_end/panels/network/NetworkDataGridNode.ts +3 -1
  75. package/front_end/panels/network/RequestConditionsDrawer.ts +1 -1
  76. package/front_end/panels/network/RequestPayloadView.ts +12 -5
  77. package/front_end/panels/network/networkConfigView.css +8 -8
  78. package/front_end/panels/profiler/HeapProfileView.ts +28 -6
  79. package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +7 -3
  80. package/front_end/panels/protocol_monitor/JSONEditor.ts +0 -1
  81. package/front_end/panels/recorder/RecorderPanel.ts +2 -2
  82. package/front_end/panels/screencast/ScreencastView.ts +3 -6
  83. package/front_end/panels/security/SecurityPanelSidebar.ts +0 -31
  84. package/front_end/panels/settings/SettingsScreen.ts +1 -1
  85. package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +9 -16
  86. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +358 -345
  87. package/front_end/panels/settings/emulation/components/userAgentClientHintsForm.css +136 -121
  88. package/front_end/panels/sources/NavigatorView.ts +105 -45
  89. package/front_end/panels/sources/ScopeChainSidebarPane.ts +8 -5
  90. package/front_end/panels/sources/SourcesNavigator.ts +421 -213
  91. package/front_end/panels/sources/SourcesPanel.ts +9 -5
  92. package/front_end/panels/sources/TabbedEditorContainer.ts +41 -18
  93. package/front_end/panels/sources/UISourceCodeFrame.ts +1 -1
  94. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +10 -5
  95. package/front_end/panels/sources/sources-meta.ts +4 -15
  96. package/front_end/panels/sources/sourcesNavigator.css +5 -0
  97. package/front_end/panels/timeline/ModificationsManager.ts +0 -2
  98. package/front_end/panels/timeline/README.md +2 -0
  99. package/front_end/panels/timeline/TimelineCommentContext.ts +171 -0
  100. package/front_end/panels/timeline/TimelineCommentController.ts +168 -30
  101. package/front_end/panels/timeline/TimelinePanel.ts +4 -0
  102. package/front_end/panels/timeline/components/IgnoreListSetting.ts +1 -1
  103. package/front_end/panels/timeline/timeline.ts +2 -0
  104. package/front_end/panels/timeline/utils/Treemap.ts +8 -0
  105. package/front_end/panels/webauthn/WebauthnPane.ts +15 -13
  106. package/front_end/third_party/chromium/README.chromium +1 -1
  107. package/front_end/third_party/puppeteer/README.chromium +2 -2
  108. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +113 -3
  109. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +21311 -20981
  110. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts +36 -0
  111. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts.map +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js +22 -0
  113. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js.map +1 -1
  114. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.d.ts.map +1 -1
  115. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js +20 -18
  116. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js.map +1 -1
  117. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.d.ts +20 -1
  118. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.d.ts.map +1 -1
  119. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js +2 -2
  120. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js.map +1 -1
  121. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts +40 -1
  122. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts.map +1 -1
  123. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js +3 -1
  124. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js.map +1 -1
  125. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.d.ts +2 -0
  126. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.d.ts.map +1 -1
  127. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.js +41 -5
  128. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.js.map +1 -1
  129. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.d.ts +2 -1
  130. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
  131. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.js +23 -2
  132. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.js.map +1 -1
  133. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Input.js +1 -1
  134. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts +3 -2
  135. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts.map +1 -1
  136. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js +13 -1
  137. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js.map +1 -1
  138. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Request.d.ts +1 -0
  139. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Request.d.ts.map +1 -1
  140. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Request.js +18 -11
  141. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Request.js.map +1 -1
  142. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.d.ts +2 -1
  143. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.d.ts.map +1 -1
  144. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js +8 -1
  145. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js.map +1 -1
  146. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts +2 -1
  147. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts.map +1 -1
  148. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js +24 -12
  149. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js.map +1 -1
  150. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.d.ts +1 -1
  151. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.d.ts.map +1 -1
  152. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.js +13 -7
  153. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.js.map +1 -1
  154. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.d.ts.map +1 -1
  155. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js +5 -1
  156. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js.map +1 -1
  157. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.d.ts +22 -1
  158. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
  159. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js +75 -9
  160. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js.map +1 -1
  161. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkEventManager.d.ts +18 -4
  162. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkEventManager.d.ts.map +1 -1
  163. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkEventManager.js +8 -4
  164. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkEventManager.js.map +1 -1
  165. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  166. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js +65 -26
  167. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js.map +1 -1
  168. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts +3 -2
  169. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts.map +1 -1
  170. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.js +19 -0
  171. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.js.map +1 -1
  172. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ScreenRecording.d.ts.map +1 -1
  173. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ScreenRecording.js +4 -3
  174. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ScreenRecording.js.map +1 -1
  175. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.d.ts +1 -0
  176. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.d.ts.map +1 -1
  177. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js +4 -0
  178. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js.map +1 -1
  179. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.d.ts +2 -0
  180. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.d.ts.map +1 -1
  181. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js +95 -8
  182. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js.map +1 -1
  183. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.d.ts +0 -8
  184. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.d.ts.map +1 -1
  185. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js +8 -24
  186. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js.map +1 -1
  187. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.d.ts +1 -0
  188. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.d.ts.map +1 -1
  189. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.js +5 -4
  190. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.js.map +1 -1
  191. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts +9 -0
  192. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts.map +1 -1
  193. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/WaitTask.d.ts.map +1 -1
  194. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/WaitTask.js +10 -0
  195. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/WaitTask.js.map +1 -1
  196. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts +10 -0
  197. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts.map +1 -1
  198. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js +30 -5
  199. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js.map +1 -1
  200. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts +1 -1
  201. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts.map +1 -1
  202. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js +1 -1
  203. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js.map +1 -1
  204. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/Poller.d.ts +2 -0
  205. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/Poller.d.ts.map +1 -1
  206. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/Poller.js +33 -3
  207. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/Poller.js.map +1 -1
  208. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  209. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js +1 -2
  210. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js.map +1 -1
  211. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.d.ts +4 -0
  212. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.d.ts.map +1 -1
  213. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.js +1 -0
  214. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.js.map +1 -1
  215. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
  216. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
  217. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js.map +1 -1
  218. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/encoding.d.ts +2 -2
  219. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/encoding.d.ts.map +1 -1
  220. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
  221. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
  222. package/front_end/third_party/puppeteer/package/lib/types.d.ts +113 -3
  223. package/front_end/third_party/puppeteer/package/package.json +4 -4
  224. package/front_end/third_party/puppeteer/package/src/api/Browser.ts +42 -0
  225. package/front_end/third_party/puppeteer/package/src/api/BrowserContext.ts +25 -22
  226. package/front_end/third_party/puppeteer/package/src/api/HTTPRequest.ts +22 -2
  227. package/front_end/third_party/puppeteer/package/src/api/Page.ts +45 -2
  228. package/front_end/third_party/puppeteer/package/src/api/locators/locators.ts +79 -32
  229. package/front_end/third_party/puppeteer/package/src/bidi/HTTPRequest.ts +32 -12
  230. package/front_end/third_party/puppeteer/package/src/bidi/Input.ts +1 -1
  231. package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +18 -2
  232. package/front_end/third_party/puppeteer/package/src/bidi/core/Request.ts +21 -13
  233. package/front_end/third_party/puppeteer/package/src/cdp/Accessibility.ts +12 -2
  234. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +37 -16
  235. package/front_end/third_party/puppeteer/package/src/cdp/EmulationManager.ts +14 -11
  236. package/front_end/third_party/puppeteer/package/src/cdp/Frame.ts +7 -1
  237. package/front_end/third_party/puppeteer/package/src/cdp/HTTPRequest.ts +101 -14
  238. package/front_end/third_party/puppeteer/package/src/cdp/NetworkEventManager.ts +26 -6
  239. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +111 -29
  240. package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +37 -1
  241. package/front_end/third_party/puppeteer/package/src/cdp/ScreenRecording.ts +5 -4
  242. package/front_end/third_party/puppeteer/package/src/cdp/Target.ts +5 -0
  243. package/front_end/third_party/puppeteer/package/src/cdp/TargetManager.ts +122 -7
  244. package/front_end/third_party/puppeteer/package/src/common/BrowserConnector.ts +13 -33
  245. package/front_end/third_party/puppeteer/package/src/common/BrowserWebSocketTransport.ts +10 -5
  246. package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +10 -0
  247. package/front_end/third_party/puppeteer/package/src/common/WaitTask.ts +12 -0
  248. package/front_end/third_party/puppeteer/package/src/common/util.ts +39 -5
  249. package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
  250. package/front_end/third_party/puppeteer/package/src/injected/Poller.ts +35 -3
  251. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +4 -2
  252. package/front_end/third_party/puppeteer/package/src/node/NodeWebSocketTransport.ts +5 -0
  253. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  254. package/front_end/third_party/puppeteer/package/src/util/encoding.ts +2 -2
  255. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  256. package/front_end/ui/comments/CommentAnchorResolver.ts +3 -0
  257. package/front_end/ui/comments/CommentOverlayManager.ts +2 -4
  258. package/front_end/ui/components/lists/List.ts +14 -1
  259. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +1 -1
  260. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +23 -14
  261. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +3 -0
  262. package/front_end/ui/helpers/OpenInNewTab.ts +8 -0
  263. package/front_end/ui/legacy/LinkContextMenuProvider.ts +1 -1
  264. package/front_end/ui/legacy/ListWidget.ts +14 -18
  265. package/front_end/ui/legacy/TabbedPane.ts +46 -3
  266. package/front_end/ui/legacy/Toolbar.ts +0 -1
  267. package/front_end/ui/legacy/Treeoutline.ts +10 -3
  268. package/front_end/ui/legacy/UIUtils.ts +5 -2
  269. package/front_end/ui/legacy/components/inline_editor/Swatches.ts +19 -6
  270. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +20 -11
  271. package/front_end/ui/legacy/components/source_frame/XMLView.ts +27 -7
  272. package/front_end/ui/visual_logging/KnownContextValues.ts +5 -0
  273. package/package.json +1 -1
@@ -11,6 +11,7 @@ import {
11
11
  type ContinueRequestOverridesInternal,
12
12
  headersArray,
13
13
  HTTPRequest,
14
+ InterceptResolutionAction,
14
15
  type ResourceType,
15
16
  type ResponseForRequestInternal,
16
17
  STATUS_TEXTS,
@@ -25,6 +26,20 @@ import {
25
26
 
26
27
  import type {CdpHTTPResponse} from './HTTPResponse.js';
27
28
 
29
+ type InterceptResolution =
30
+ | {
31
+ action: InterceptResolutionAction.Continue;
32
+ overrides: ContinueRequestOverridesInternal;
33
+ }
34
+ | {
35
+ action: InterceptResolutionAction.Respond;
36
+ response: Partial<ResponseForRequestInternal>;
37
+ }
38
+ | {
39
+ action: InterceptResolutionAction.Abort;
40
+ errorReason: Protocol.Network.ErrorReason | null;
41
+ };
42
+
28
43
  /**
29
44
  * @internal
30
45
  */
@@ -34,6 +49,7 @@ export class CdpHTTPRequest extends HTTPRequest {
34
49
  declare _response: CdpHTTPResponse | null;
35
50
 
36
51
  #client: CDPSession;
52
+ #fetchClient: CDPSession;
37
53
  #isNavigationRequest: boolean;
38
54
 
39
55
  #url: string;
@@ -42,10 +58,13 @@ export class CdpHTTPRequest extends HTTPRequest {
42
58
  #method: string;
43
59
  #hasPostData = false;
44
60
  #postData?: string;
61
+ #postDataBytes?: Uint8Array;
62
+ #hasCompletePostData = false;
45
63
  #headers: Record<string, string> = {};
46
64
  #frame: Frame | null;
47
65
  #initiator?: Protocol.Network.Initiator;
48
66
  #logger: Logger;
67
+ #resolution: InterceptResolution | null = null;
49
68
 
50
69
  override get client(): CDPSession {
51
70
  return this.#client;
@@ -55,6 +74,17 @@ export class CdpHTTPRequest extends HTTPRequest {
55
74
  this.#client = newClient;
56
75
  }
57
76
 
77
+ /**
78
+ * @internal
79
+ */
80
+ get _fetchClient(): CDPSession {
81
+ return this.#fetchClient;
82
+ }
83
+
84
+ set _fetchClient(fetchClient: CDPSession) {
85
+ this.#fetchClient = fetchClient;
86
+ }
87
+
58
88
  constructor(
59
89
  client: CDPSession,
60
90
  frame: Frame | null,
@@ -88,10 +118,12 @@ export class CdpHTTPRequest extends HTTPRequest {
88
118
  },
89
119
  redirectChain: CdpHTTPRequest[],
90
120
  logger: Logger,
121
+ fetchClient: CDPSession = client,
91
122
  ) {
92
123
  super();
93
124
  this.#logger = logger;
94
125
  this.#client = client;
126
+ this.#fetchClient = fetchClient;
95
127
  this.id = data.requestId;
96
128
  this.#isNavigationRequest =
97
129
  data.requestId === data.loaderId && data.type === 'Document';
@@ -103,17 +135,19 @@ export class CdpHTTPRequest extends HTTPRequest {
103
135
  data.request.postDataEntries &&
104
136
  data.request.postDataEntries.length > 0
105
137
  ) {
106
- this.#postData = new TextDecoder().decode(
107
- mergeUint8Arrays(
108
- data.request.postDataEntries
109
- .map(entry => {
110
- return entry.bytes ? stringToTypedArray(entry.bytes, true) : null;
111
- })
112
- .filter((entry): entry is Uint8Array => {
113
- return entry !== null;
114
- }),
115
- ),
138
+ this.#hasCompletePostData = data.request.postDataEntries.every(entry => {
139
+ return !!entry.bytes;
140
+ });
141
+ this.#postDataBytes = mergeUint8Arrays(
142
+ data.request.postDataEntries
143
+ .map(entry => {
144
+ return entry.bytes ? stringToTypedArray(entry.bytes, true) : null;
145
+ })
146
+ .filter(entry => {
147
+ return entry !== null;
148
+ }),
116
149
  );
150
+ this.#postData = new TextDecoder().decode(this.#postDataBytes);
117
151
  } else {
118
152
  this.#postData = data.request.postData;
119
153
  }
@@ -154,11 +188,28 @@ export class CdpHTTPRequest extends HTTPRequest {
154
188
  }
155
189
 
156
190
  override async fetchPostData(): Promise<string | undefined> {
191
+ const content = await this.content();
192
+ if (content === undefined) {
193
+ return undefined;
194
+ }
195
+ return new TextDecoder().decode(content);
196
+ }
197
+
198
+ override async content(): Promise<Uint8Array | undefined> {
199
+ if (
200
+ this._interceptionId !== undefined &&
201
+ this.interception.enabled &&
202
+ !this.isInterceptResolutionHandled() &&
203
+ this.#hasCompletePostData
204
+ ) {
205
+ // Chrome may wait for the paused request to continue before returning data.
206
+ return this.#postDataBytes;
207
+ }
157
208
  try {
158
209
  const result = await this.#client.send('Network.getRequestPostData', {
159
210
  requestId: this.id,
160
211
  });
161
- return result.postData;
212
+ return stringToTypedArray(result.postData, result.base64Encoded);
162
213
  } catch (err) {
163
214
  this.#logger?.(DEBUG_PREFIXES.error)?.(err);
164
215
  return;
@@ -211,6 +262,7 @@ export class CdpHTTPRequest extends HTTPRequest {
211
262
  ): Promise<void> {
212
263
  const {url, method, postData, headers} = overrides;
213
264
  this.interception.handled = true;
265
+ this.#resolution = {action: InterceptResolutionAction.Continue, overrides};
214
266
 
215
267
  const postDataBinaryBase64 = postData
216
268
  ? stringToBase64(postData)
@@ -221,7 +273,7 @@ export class CdpHTTPRequest extends HTTPRequest {
221
273
  'HTTPRequest is missing _interceptionId needed for Fetch.continueRequest',
222
274
  );
223
275
  }
224
- await this.#client
276
+ await this.#fetchClient
225
277
  .send('Fetch.continueRequest', {
226
278
  requestId: this._interceptionId,
227
279
  url,
@@ -237,6 +289,7 @@ export class CdpHTTPRequest extends HTTPRequest {
237
289
 
238
290
  async _respond(response: Partial<ResponseForRequestInternal>): Promise<void> {
239
291
  this.interception.handled = true;
292
+ this.#resolution = {action: InterceptResolutionAction.Respond, response};
240
293
 
241
294
  let parsedBody:
242
295
  | {
@@ -251,6 +304,9 @@ export class CdpHTTPRequest extends HTTPRequest {
251
304
  const responseHeaders: Record<string, string | string[]> = {};
252
305
  if (response.headers) {
253
306
  for (const [header, value] of Object.entries(response.headers)) {
307
+ if (value === undefined) {
308
+ continue;
309
+ }
254
310
  responseHeaders[header.toLowerCase()] = Array.isArray(value)
255
311
  ? value.map(item => {
256
312
  return String(item);
@@ -271,7 +327,7 @@ export class CdpHTTPRequest extends HTTPRequest {
271
327
  'HTTPRequest is missing _interceptionId needed for Fetch.fulfillRequest',
272
328
  );
273
329
  }
274
- await this.#client
330
+ await this.#fetchClient
275
331
  .send('Fetch.fulfillRequest', {
276
332
  requestId: this._interceptionId,
277
333
  responseCode: status,
@@ -289,12 +345,13 @@ export class CdpHTTPRequest extends HTTPRequest {
289
345
  errorReason: Protocol.Network.ErrorReason | null,
290
346
  ): Promise<void> {
291
347
  this.interception.handled = true;
348
+ this.#resolution = {action: InterceptResolutionAction.Abort, errorReason};
292
349
  if (this._interceptionId === undefined) {
293
350
  throw new Error(
294
351
  'HTTPRequest is missing _interceptionId needed for Fetch.failRequest',
295
352
  );
296
353
  }
297
- await this.#client
354
+ await this.#fetchClient
298
355
  .send('Fetch.failRequest', {
299
356
  requestId: this._interceptionId,
300
357
  errorReason: errorReason || 'Failed',
@@ -303,4 +360,34 @@ export class CdpHTTPRequest extends HTTPRequest {
303
360
  return handleError(error, this.#logger);
304
361
  });
305
362
  }
363
+
364
+ /**
365
+ * The overrides sent with `Fetch.continueRequest`, or an empty object if
366
+ * the request was not continued.
367
+ *
368
+ * @internal
369
+ */
370
+ get _continueOverrides(): ContinueRequestOverridesInternal {
371
+ return this.#resolution?.action === InterceptResolutionAction.Continue
372
+ ? this.#resolution.overrides
373
+ : {};
374
+ }
375
+
376
+ /**
377
+ * Re-sends the resolution the user already chose to the current
378
+ * `_interceptionId`. Used when Chrome restarts a request under a new
379
+ * interception id.
380
+ *
381
+ * @internal
382
+ */
383
+ async _replayInterception(): Promise<void> {
384
+ switch (this.#resolution?.action) {
385
+ case InterceptResolutionAction.Continue:
386
+ return await this._continue(this.#resolution.overrides);
387
+ case InterceptResolutionAction.Respond:
388
+ return await this._respond(this.#resolution.response);
389
+ case InterceptResolutionAction.Abort:
390
+ return await this._abort(this.#resolution.errorReason);
391
+ }
392
+ }
306
393
  }
@@ -6,6 +6,8 @@
6
6
 
7
7
  import type {Protocol} from 'devtools-protocol';
8
8
 
9
+ import {CDPSession} from '../api/CDPSession.js';
10
+
9
11
  import {CdpHTTPRequest} from './HTTPRequest.js';
10
12
 
11
13
  /**
@@ -28,9 +30,23 @@ export type FetchRequestId = string;
28
30
  export interface RedirectInfo {
29
31
  event: Protocol.Network.RequestWillBeSentEvent;
30
32
  fetchRequestId?: FetchRequestId;
33
+ client: CDPSession;
34
+ fetchClient: CDPSession;
31
35
  }
32
36
  type RedirectInfoList = RedirectInfo[];
33
37
 
38
+ /**
39
+ * A stored event and the session that sent it. A worker request can get its
40
+ * Network events on the worker session and its Fetch events on the page
41
+ * session.
42
+ *
43
+ * @internal
44
+ */
45
+ export interface SessionEvent<T> {
46
+ event: T;
47
+ client: CDPSession;
48
+ }
49
+
34
50
  /**
35
51
  * @internal
36
52
  */
@@ -76,11 +92,11 @@ export class NetworkEventManager {
76
92
  */
77
93
  #requestWillBeSentMap = new Map<
78
94
  NetworkRequestId,
79
- Protocol.Network.RequestWillBeSentEvent
95
+ SessionEvent<Protocol.Network.RequestWillBeSentEvent>
80
96
  >();
81
97
  #requestPausedMap = new Map<
82
98
  NetworkRequestId,
83
- Protocol.Fetch.RequestPausedEvent
99
+ SessionEvent<Protocol.Fetch.RequestPausedEvent>
84
100
  >();
85
101
  #httpRequestsMap = new Map<NetworkRequestId, CdpHTTPRequest>();
86
102
  #requestWillBeSentExtraInfoMap = new Map<
@@ -167,13 +183,14 @@ export class NetworkEventManager {
167
183
  storeRequestWillBeSent(
168
184
  networkRequestId: NetworkRequestId,
169
185
  event: Protocol.Network.RequestWillBeSentEvent,
186
+ client: CDPSession,
170
187
  ): void {
171
- this.#requestWillBeSentMap.set(networkRequestId, event);
188
+ this.#requestWillBeSentMap.set(networkRequestId, {event, client});
172
189
  }
173
190
 
174
191
  getRequestWillBeSent(
175
192
  networkRequestId: NetworkRequestId,
176
- ): Protocol.Network.RequestWillBeSentEvent | undefined {
193
+ ): SessionEvent<Protocol.Network.RequestWillBeSentEvent> | undefined {
177
194
  return this.#requestWillBeSentMap.get(networkRequestId);
178
195
  }
179
196
 
@@ -183,7 +200,7 @@ export class NetworkEventManager {
183
200
 
184
201
  getRequestPaused(
185
202
  networkRequestId: NetworkRequestId,
186
- ): Protocol.Fetch.RequestPausedEvent | undefined {
203
+ ): SessionEvent<Protocol.Fetch.RequestPausedEvent> | undefined {
187
204
  return this.#requestPausedMap.get(networkRequestId);
188
205
  }
189
206
 
@@ -194,8 +211,9 @@ export class NetworkEventManager {
194
211
  storeRequestPaused(
195
212
  networkRequestId: NetworkRequestId,
196
213
  event: Protocol.Fetch.RequestPausedEvent,
214
+ client: CDPSession,
197
215
  ): void {
198
- this.#requestPausedMap.set(networkRequestId, event);
216
+ this.#requestPausedMap.set(networkRequestId, {event, client});
199
217
  }
200
218
 
201
219
  getRequest(networkRequestId: NetworkRequestId): CdpHTTPRequest | undefined {
@@ -237,6 +255,8 @@ export class NetworkEventManager {
237
255
  dataType: 'Map',
238
256
  value: Array.from(value.entries()), // or with spread: value: [...value]
239
257
  };
258
+ } else if (value instanceof CDPSession) {
259
+ return value.id();
240
260
  } else if (value instanceof CdpHTTPRequest) {
241
261
  return {
242
262
  dataType: 'CdpHTTPRequest',
@@ -420,17 +420,27 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
420
420
  ) {
421
421
  const {requestId: networkRequestId} = event;
422
422
 
423
- this.#networkEventManager.storeRequestWillBeSent(networkRequestId, event);
423
+ this.#networkEventManager.storeRequestWillBeSent(
424
+ networkRequestId,
425
+ event,
426
+ client,
427
+ );
424
428
 
425
429
  /**
426
430
  * CDP may have sent a Fetch.requestPaused event already. Check for it.
431
+ * It may come from another session, e.g. the page for a worker request.
427
432
  */
428
- const requestPausedEvent =
433
+ const requestPaused =
429
434
  this.#networkEventManager.getRequestPaused(networkRequestId);
430
- if (requestPausedEvent) {
431
- const {requestId: fetchRequestId} = requestPausedEvent;
435
+ if (requestPaused) {
436
+ const {event: requestPausedEvent, client: fetchClient} = requestPaused;
432
437
  this.#patchRequestEventHeaders(event, requestPausedEvent);
433
- this.#onRequest(client, event, fetchRequestId);
438
+ this.#onRequest(
439
+ client,
440
+ event,
441
+ requestPausedEvent.requestId,
442
+ fetchClient,
443
+ );
434
444
  this.#networkEventManager.forgetRequestPaused(networkRequestId);
435
445
  }
436
446
 
@@ -495,27 +505,88 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
495
505
  return;
496
506
  }
497
507
 
498
- const requestWillBeSentEvent = (() => {
499
- const requestWillBeSentEvent =
500
- this.#networkEventManager.getRequestWillBeSent(networkRequestId);
501
-
502
- // redirect requests have the same `requestId`,
503
- if (
504
- requestWillBeSentEvent &&
505
- (requestWillBeSentEvent.request.url !== event.request.url ||
506
- requestWillBeSentEvent.request.method !== event.request.method)
507
- ) {
508
- this.#networkEventManager.forgetRequestWillBeSent(networkRequestId);
508
+ const requestWillBeSent =
509
+ this.#networkEventManager.getRequestWillBeSent(networkRequestId);
510
+ if (!requestWillBeSent) {
511
+ // Chrome may restart a request and send a second Fetch.requestPaused
512
+ // for a request Puppeteer already emitted (crbug.com/1196004). Repoint
513
+ // that request instead of emitting a duplicate that never finishes.
514
+ const request = this.#networkEventManager.getRequest(networkRequestId);
515
+ if (request && this.#isRestartedRequest(request, event)) {
516
+ this.#onRequestRestarted(client, request, fetchRequestId);
509
517
  return;
510
518
  }
511
- return requestWillBeSentEvent;
512
- })();
519
+ this.#networkEventManager.storeRequestPaused(
520
+ networkRequestId,
521
+ event,
522
+ client,
523
+ );
524
+ return;
525
+ }
526
+ const {event: requestWillBeSentEvent, client: networkClient} =
527
+ requestWillBeSent;
513
528
 
514
- if (requestWillBeSentEvent) {
515
- this.#patchRequestEventHeaders(requestWillBeSentEvent, event);
516
- this.#onRequest(client, requestWillBeSentEvent, fetchRequestId);
517
- } else {
518
- this.#networkEventManager.storeRequestPaused(networkRequestId, event);
529
+ // Redirect requests have the same `requestId`. Wait for the redirect's
530
+ // own Network.requestWillBeSent.
531
+ if (
532
+ requestWillBeSentEvent.request.url !== event.request.url ||
533
+ requestWillBeSentEvent.request.method !== event.request.method
534
+ ) {
535
+ this.#networkEventManager.forgetRequestWillBeSent(networkRequestId);
536
+ this.#networkEventManager.storeRequestPaused(
537
+ networkRequestId,
538
+ event,
539
+ client,
540
+ );
541
+ return;
542
+ }
543
+
544
+ this.#patchRequestEventHeaders(requestWillBeSentEvent, event);
545
+ this.#onRequest(
546
+ networkClient,
547
+ requestWillBeSentEvent,
548
+ fetchRequestId,
549
+ client,
550
+ );
551
+ }
552
+
553
+ #isRestartedRequest(
554
+ request: CdpHTTPRequest,
555
+ event: Protocol.Fetch.RequestPausedEvent,
556
+ ): boolean {
557
+ // Only a request with no response yet can be restarted. Redirects are
558
+ // excluded by id because in a same-URL redirect, the pause can arrive
559
+ // before the response does.
560
+ if (event.redirectedRequestId || request.response()) {
561
+ return false;
562
+ }
563
+ // Chrome usually pauses the request the user continued to, but can pause
564
+ // the original if it restarts before the overrides are applied.
565
+ const overrides = request._continueOverrides;
566
+ const eventUrl = event.request.url + (event.request.urlFragment ?? '');
567
+ const urlMatches =
568
+ eventUrl === request.url() ||
569
+ eventUrl === overrides.url ||
570
+ event.request.url === overrides.url;
571
+ const methodMatches =
572
+ event.request.method === request.method() ||
573
+ event.request.method === overrides.method;
574
+ return urlMatches && methodMatches;
575
+ }
576
+
577
+ #onRequestRestarted(
578
+ client: CDPSession,
579
+ request: CdpHTTPRequest,
580
+ fetchRequestId: FetchRequestId,
581
+ ): void {
582
+ request._interceptionId = fetchRequestId;
583
+ request._fetchClient = client;
584
+ if (this.#userRequestInterceptionEnabled) {
585
+ // If the user already resolved the interception, the restarted job needs
586
+ // the same resolution or the request hangs.
587
+ void request._replayInterception().catch(err => {
588
+ this.#logger?.(DEBUG_PREFIXES.error)?.(err);
589
+ });
519
590
  }
520
591
  }
521
592
 
@@ -557,6 +628,7 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
557
628
  client: CDPSession,
558
629
  event: Protocol.Network.RequestWillBeSentEvent,
559
630
  fetchRequestId?: FetchRequestId,
631
+ fetchClient = client,
560
632
  fromMemoryCache = false,
561
633
  ): void {
562
634
  let redirectChain: CdpHTTPRequest[] = [];
@@ -577,6 +649,8 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
577
649
  this.#networkEventManager.queueRedirectInfo(event.requestId, {
578
650
  event,
579
651
  fetchRequestId,
652
+ client,
653
+ fetchClient,
580
654
  });
581
655
  return;
582
656
  }
@@ -614,6 +688,7 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
614
688
  event,
615
689
  redirectChain,
616
690
  this.#logger,
691
+ fetchClient,
617
692
  );
618
693
 
619
694
  const extraInfo = this.#networkEventManager
@@ -625,6 +700,7 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
625
700
 
626
701
  request._fromMemoryCache = fromMemoryCache;
627
702
  this.#networkEventManager.storeRequest(event.requestId, request);
703
+ this.#networkEventManager.forgetRequestWillBeSent(event.requestId);
628
704
  this.emit(NetworkManagerEvent.Request, request);
629
705
  void request.finalizeInterceptions();
630
706
  }
@@ -645,8 +721,9 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
645
721
  client: CDPSession,
646
722
  event: Protocol.Network.RequestServedFromCacheEvent,
647
723
  ): void {
648
- const requestWillBeSentEvent =
649
- this.#networkEventManager.getRequestWillBeSent(event.requestId);
724
+ const requestWillBeSent = this.#networkEventManager.getRequestWillBeSent(
725
+ event.requestId,
726
+ );
650
727
  let request = this.#networkEventManager.getRequest(event.requestId);
651
728
  // Requests served from memory cannot be intercepted.
652
729
  if (request) {
@@ -654,8 +731,8 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
654
731
  }
655
732
  // If request ended up being served from cache, we need to convert
656
733
  // requestWillBeSentEvent to a HTTP request.
657
- if (!request && requestWillBeSentEvent) {
658
- this.#onRequest(client, requestWillBeSentEvent, undefined, true);
734
+ if (!request && requestWillBeSent) {
735
+ this.#onRequest(client, requestWillBeSent.event, undefined, client, true);
659
736
  request = this.#networkEventManager.getRequest(event.requestId);
660
737
  }
661
738
  if (!request) {
@@ -760,7 +837,12 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
760
837
  );
761
838
  if (redirectInfo) {
762
839
  this.#networkEventManager.responseExtraInfo(event.requestId).push(event);
763
- this.#onRequest(client, redirectInfo.event, redirectInfo.fetchRequestId);
840
+ this.#onRequest(
841
+ redirectInfo.client,
842
+ redirectInfo.event,
843
+ redirectInfo.fetchRequestId,
844
+ redirectInfo.fetchClient,
845
+ );
764
846
  return;
765
847
  }
766
848
 
@@ -868,7 +950,7 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
868
950
  return;
869
951
  }
870
952
  this.#adoptCdpSessionIfNeeded(client, request);
871
- request._failureText = event.errorText;
953
+ request._failureText = event.errorText || event.blockedReason || null;
872
954
  const response = request.response();
873
955
  if (response) {
874
956
  response._resolveBody();
@@ -33,6 +33,7 @@ import {
33
33
  type NewDocumentScriptEvaluation,
34
34
  type ScreenshotClip,
35
35
  type ScreenshotOptions,
36
+ type TabInfo,
36
37
  type WaitTimeoutOptions,
37
38
  } from '../api/Page.js';
38
39
  import {WebWorker, WebWorkerEvent} from '../api/WebWorker.js';
@@ -447,6 +448,25 @@ export class CdpPage extends Page {
447
448
  return windowId.toString();
448
449
  }
449
450
 
451
+ override async tabInfo(): Promise<TabInfo | null> {
452
+ const {targetInfo} = await this.#tabTargetClient.send(
453
+ 'Target.getTargetInfo',
454
+ );
455
+ const data = targetInfo.embedderData as TabEmbedderData | undefined;
456
+ if (typeof data?.tabStripIndex !== 'number') {
457
+ return null;
458
+ }
459
+ const tabInfo: TabInfo = {
460
+ index: data.tabStripIndex,
461
+ active: data.tabActive ?? false,
462
+ pinned: data.tabPinned ?? false,
463
+ };
464
+ if (data.tabGroupId) {
465
+ tabInfo.groupId = data.tabGroupId;
466
+ }
467
+ return tabInfo;
468
+ }
469
+
450
470
  async #onFileChooser(
451
471
  event: Protocol.Page.FileChooserOpenedEvent,
452
472
  ): Promise<void> {
@@ -454,6 +474,10 @@ export class CdpPage extends Page {
454
474
  return;
455
475
  }
456
476
 
477
+ if (!event.backendNodeId) {
478
+ return;
479
+ }
480
+
457
481
  const frame = this.#frameManager.frame(event.frameId);
458
482
  assert(frame, 'This should never happen.');
459
483
 
@@ -553,7 +577,9 @@ export class CdpPage extends Page {
553
577
  }
554
578
  }
555
579
 
556
- override async setGeolocation(options: GeolocationOptions): Promise<void> {
580
+ override async setGeolocation(
581
+ options: GeolocationOptions | null,
582
+ ): Promise<void> {
557
583
  return await this.#emulationManager.setGeolocation(options);
558
584
  }
559
585
 
@@ -1382,6 +1408,16 @@ export class CdpPage extends Page {
1382
1408
  }
1383
1409
  }
1384
1410
 
1411
+ /**
1412
+ * Shape of `TargetInfo.embedderData` for tab targets.
1413
+ */
1414
+ interface TabEmbedderData {
1415
+ tabStripIndex?: number;
1416
+ tabActive?: boolean;
1417
+ tabPinned?: boolean;
1418
+ tabGroupId?: string;
1419
+ }
1420
+
1385
1421
  const supportedMetrics = new Set<string>([
1386
1422
  'Timestamp',
1387
1423
  'Documents',
@@ -62,15 +62,16 @@ export class CdpScreenRecording extends ScreenRecording {
62
62
  this.stopped = true;
63
63
 
64
64
  try {
65
+ if (!this.#streamHandle) {
66
+ // `_start()` did not succeed, so there is no recording to stop.
67
+ return;
68
+ }
69
+
65
70
  const {client} = this.page.mainFrame();
66
71
  await client.send('Page.stopScreenRecording').catch(err => {
67
72
  this.logger(DEBUG_PREFIXES.error)?.(err);
68
73
  });
69
74
 
70
- if (!this.#streamHandle) {
71
- throw new Error('Screen recording stream handle is missing.');
72
- }
73
-
74
75
  let eof = false;
75
76
  while (!eof) {
76
77
  const {
@@ -101,6 +101,11 @@ export class CdpTarget extends Target {
101
101
  return this.#session;
102
102
  }
103
103
 
104
+ _setSession(session: CdpCDPSession): void {
105
+ this.#session = session;
106
+ this.#session.setTarget(this);
107
+ }
108
+
104
109
  _addChildTarget(target: CdpTarget): void {
105
110
  this.#childTargets.add(target);
106
111
  }