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
@@ -114,13 +114,8 @@ export class ListNetworkRequestsTool implements
114
114
  };
115
115
  }
116
116
  return {
117
- result: JSON.stringify([]),
118
- widgets: [{
119
- name: 'NETWORK_REQUESTS_LIST',
120
- data: {
121
- requests: [],
122
- },
123
- }],
117
+ error:
118
+ 'No network requests have been recorded. DevTools only records requests made while DevTools is open and network recording is enabled (and the log has not been cleared). Ask the user to ensure network recording is enabled, reload the page or repeat the action that triggers the request, and try again.',
124
119
  };
125
120
  }
126
121
 
@@ -45,9 +45,9 @@ export class RunLighthouseTool implements
45
45
  },
46
46
  categoryId: {
47
47
  type: Host.AidaClient.ParametersTypes.STRING,
48
- // The experimental 'agentic-browsing' category is intentionally omitted from the prompt description so the agent does not invoke it unprompted. It is also excluded when 'all' is provided.
48
+ // The experimental 'agentic-browsing' category is listed separately from the standard categories and restricted to explicit user requests so the agent does not invoke it unprompted. It is also excluded when 'all' is provided (see `LighthouseController.getCategoryIDs`).
49
49
  description:
50
- 'Lighthouse category. Use "all" to run all categories, or specify a category: "accessibility", "performance", "best-practices", "seo".',
50
+ 'Lighthouse category. Use "all" to run all categories, or specify a category: "accessibility", "performance", "best-practices", "seo". Use "agentic-browsing" only when the user explicitly asks for an agentic browsing audit (how well AI agents can navigate and use the page, including WebMCP). "all" does not include "agentic-browsing". Run "agentic-browsing" in "navigation" mode, because its WebMCP audits only run in "navigation" mode.',
51
51
  nullable: false,
52
52
  },
53
53
  mode: {
@@ -113,6 +113,10 @@ export class CD4ABridge extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
113
113
  details.push(`- Editor: ${editorInfo}`);
114
114
  }
115
115
 
116
+ for (const line of thread.anchor.agentContext ?? []) {
117
+ details.push(`- ${line}`);
118
+ }
119
+
116
120
  if (details.length === 0) {
117
121
  return rawText;
118
122
  }
@@ -48,11 +48,6 @@ export class CommentManager extends Common.ObjectWrapper.ObjectWrapper<EventType
48
48
  #commentMode = false;
49
49
  #agentAttached = false;
50
50
 
51
- constructor() {
52
- super();
53
- CommentThread.resetIndex();
54
- }
55
-
56
51
  #onThreadChanged(): void {
57
52
  this.dispatchEventToListeners(Events.COMMENT_THREADS_CHANGED, this.getCommentThreads());
58
53
  }
@@ -174,7 +169,6 @@ export class CommentManager extends Common.ObjectWrapper.ObjectWrapper<EventType
174
169
  thread.removeEventListener(CommentThreadEvents.CHANGED, this.#onThreadChanged, this);
175
170
  }
176
171
  this.#commentThreads.clear();
177
- CommentThread.resetIndex();
178
172
  this.dispatchEventToListeners(Events.COMMENT_THREADS_CHANGED, []);
179
173
  }
180
174
  }
@@ -22,7 +22,10 @@ export interface DOMNodeAnchorSignature {
22
22
  export interface TimelineAnchorSignature {
23
23
  /** Identifier of the trace to scope comments to a specific recording */
24
24
  traceId: string;
25
- /** Serializable key from Trace.EventsSerializer (e.g. 'r-123', 'p-1-2-3-4', 's-5') */
25
+ /**
26
+ * Serializable key from Trace.EventsSerializer (e.g. 'r-123', 'p-1-2-3-4', 's-5'), or
27
+ * 'fc-<chartLocation>-<entryIndex>' for flame chart entries that EventsSerializer cannot key.
28
+ */
26
29
  traceEventKey: string;
27
30
  /** Primary event title or category name */
28
31
  entryName: string;
@@ -51,6 +54,22 @@ export interface CommentAnchorSignature {
51
54
  editor?: EditorAnchorSignature;
52
55
  /** Optional timeline flamechart anchor coordinates for Performance panel trace entries */
53
56
  timeline?: TimelineAnchorSignature;
57
+ /**
58
+ * Optional formatted lines that give the AI agent context about the
59
+ * anchored target beyond the VE path and text signature, for example the
60
+ * timing and warnings of a Performance panel trace entry. CD4ABridge
61
+ * appends each line to the comment text that it sends to the agent.
62
+ *
63
+ * These lines are only context for the agent. They are not used to
64
+ * re-match the anchor to its target; the other fields of this signature
65
+ * do that.
66
+ *
67
+ * Currently only the Performance panel sets this field. Before adding
68
+ * context here, consider whether it belongs in a new field on this
69
+ * signature instead. This field is only for text that is already
70
+ * formatted for the agent, not for data that other code needs to read.
71
+ */
72
+ agentContext?: string[];
54
73
  }
55
74
 
56
75
  export interface Comment {
@@ -77,17 +96,11 @@ export interface CommentThreadOptions {
77
96
  }
78
97
 
79
98
  export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
80
- static #nextIndex = 1;
81
-
82
- static resetIndex(): void {
83
- CommentThread.#nextIndex = 1;
84
- }
85
-
86
99
  readonly id: string = crypto.randomUUID();
87
100
  readonly anchor: CommentAnchorSignature;
88
101
  /** True for comments generated from the change tracker. */
89
102
  readonly isGeneratedComment: boolean;
90
- #savedIndex?: number;
103
+ #isOrphaned = false;
91
104
  comments: Comment[];
92
105
  status: CommentThreadStatus = 'DRAFT';
93
106
  transmitted: boolean = false;
@@ -99,8 +112,16 @@ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes
99
112
  this.isGeneratedComment = Boolean(options.isGeneratedComment);
100
113
  }
101
114
 
102
- get index(): number {
103
- return this.#savedIndex ?? CommentThread.#nextIndex;
115
+ get isOrphaned(): boolean {
116
+ return this.#isOrphaned;
117
+ }
118
+
119
+ setOrphaned(isOrphaned: boolean): void {
120
+ if (this.#isOrphaned === isOrphaned) {
121
+ return;
122
+ }
123
+ this.#isOrphaned = isOrphaned;
124
+ this.dispatchEventToListeners(Events.CHANGED);
104
125
  }
105
126
 
106
127
  /**
@@ -137,9 +158,6 @@ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes
137
158
  let changed = this.#saveText(text, author);
138
159
  if (this.status === 'DRAFT') {
139
160
  this.#recordCommentCreated();
140
- if (this.#savedIndex === undefined) {
141
- this.#savedIndex = CommentThread.#nextIndex++;
142
- }
143
161
  this.status = 'ACTIVE';
144
162
  changed = true;
145
163
  }
@@ -167,9 +185,6 @@ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes
167
185
  this.#recordCommentCreated();
168
186
  }
169
187
  if (this.status === 'DRAFT' || this.status === 'ACTIVE') {
170
- if (this.#savedIndex === undefined) {
171
- this.#savedIndex = CommentThread.#nextIndex++;
172
- }
173
188
  this.status = 'SENT_TO_AGENT';
174
189
  changed = true;
175
190
  }
@@ -186,10 +201,15 @@ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes
186
201
  timestamp: Date.now(),
187
202
  });
188
203
  }
189
- if (this.#savedIndex === undefined) {
190
- this.#savedIndex = CommentThread.#nextIndex++;
191
- }
192
204
  this.status = 'RESOLVED';
193
205
  this.dispatchEventToListeners(Events.CHANGED);
194
206
  }
195
207
  }
208
+
209
+ export class RevealableThread {
210
+ constructor(
211
+ readonly thread: CommentThread,
212
+ readonly position?: {left: number, top: number},
213
+ ) {
214
+ }
215
+ }
@@ -95,3 +95,69 @@ export function trackStylePropertyToggle(
95
95
  }
96
96
  tracker.trackChange(describeStylePropertyToggle(toggle), buildAnchor(STYLES_PANE_VE_PATH, node));
97
97
  }
98
+
99
+ export function trackStyleRuleAdded(
100
+ tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
101
+ node: SDK.DOMModel.DOMNode,
102
+ selector: string,
103
+ ): void {
104
+ if (!tracker?.isTracking) {
105
+ return;
106
+ }
107
+ const trimmedSelector = Platform.StringUtilities.collapseWhitespace(selector.trim());
108
+ if (!trimmedSelector) {
109
+ return;
110
+ }
111
+ tracker.trackChange(
112
+ `Added style rule "${trimValue(trimmedSelector)}"`,
113
+ buildAnchor(STYLES_PANE_VE_PATH, node),
114
+ );
115
+ }
116
+
117
+ function trackRuleHeaderChange(
118
+ tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
119
+ node: SDK.DOMModel.DOMNode,
120
+ headerDescription: string,
121
+ oldText: string,
122
+ newText: string,
123
+ ): void {
124
+ if (!tracker?.isTracking) {
125
+ return;
126
+ }
127
+ const trimmedOld = Platform.StringUtilities.collapseWhitespace(oldText.trim());
128
+ const trimmedNew = Platform.StringUtilities.collapseWhitespace(newText.trim());
129
+ if (!trimmedOld || !trimmedNew || trimmedOld === trimmedNew) {
130
+ return;
131
+ }
132
+ tracker.trackChange(
133
+ `Changed ${headerDescription} from "${trimValue(trimmedOld)}" to "${trimValue(trimmedNew)}"`,
134
+ buildAnchor(STYLES_PANE_VE_PATH, node),
135
+ );
136
+ }
137
+
138
+ export function trackStyleSelectorChange(
139
+ tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
140
+ node: SDK.DOMModel.DOMNode,
141
+ oldSelector: string,
142
+ newSelector: string,
143
+ ): void {
144
+ trackRuleHeaderChange(tracker, node, 'style rule selector', oldSelector, newSelector);
145
+ }
146
+
147
+ export function trackPropertyRuleNameChange(
148
+ tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
149
+ node: SDK.DOMModel.DOMNode,
150
+ oldName: string,
151
+ newName: string,
152
+ ): void {
153
+ trackRuleHeaderChange(tracker, node, '@property rule name', oldName, newName);
154
+ }
155
+
156
+ export function trackKeyframeKeyChange(
157
+ tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
158
+ node: SDK.DOMModel.DOMNode,
159
+ oldKey: string,
160
+ newKey: string,
161
+ ): void {
162
+ trackRuleHeaderChange(tracker, node, 'keyframe key', oldKey, newKey);
163
+ }
@@ -84,13 +84,8 @@ export class EventsSerializer {
84
84
  }
85
85
 
86
86
  if (EventsSerializer.isSyntheticEventKey(eventValues)) {
87
- const syntheticEvents = Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getSyntheticTraces();
88
- const syntheticEvent = syntheticEvents.at(eventValues.rawIndex);
89
- if (!syntheticEvent) {
90
- throw new Error(`Unknown trace event. Attempted to get a synthetic event from an unknown raw event index: ${
91
- eventValues.rawIndex}`);
92
- }
93
- return syntheticEvent;
87
+ return Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().syntheticEventForRawEventIndex(
88
+ eventValues.rawIndex);
94
89
  }
95
90
 
96
91
  if (EventsSerializer.isRawEventKey(eventValues)) {
@@ -110,8 +110,6 @@ export class Model extends EventTarget {
110
110
  }
111
111
  const file = this.#storeAndCreateParsedTraceFile(
112
112
  syntheticEventsManager, traceEvents, metadata, this.#processor.data, this.#processor.insights);
113
- // Reclaim memory used by the temporary event-to-index lookup map now that trace parsing is complete.
114
- syntheticEventsManager.clearRegistrationIndex();
115
113
  // We only push the file onto this.#traces here once we know it's valid
116
114
  // and there's been no errors in the parsing.
117
115
  this.#traces.push(file);
@@ -14,7 +14,7 @@ import * as Types from '../types/types.js';
14
14
  // included, while the amount of `step` phase events can be >= 0.
15
15
 
16
16
  // A flow phase event is assigned to a trace event when their cat, tid,
17
- // pid and ts are equal (see @flowPhaseBindingTokenForEvent ).
17
+ // pid and ts are equal (see findBinding()).
18
18
 
19
19
  // It's possible for a single event to belong to multiple flows. In that
20
20
  // case, it will have multiple corresponding flow phase events (one
@@ -26,24 +26,27 @@ import * as Types from '../types/types.js';
26
26
  // there are any corresponding flow phase events at all).
27
27
  let flowDataByGroupToken = new Map<string, number>();
28
28
 
29
- interface EventFlowData {
29
+ /**
30
+ * The flows bound to one flow binding tuple (timestamp, process id,
31
+ * thread id and category).
32
+ */
33
+ interface FlowBinding {
34
+ ts: Types.Timing.Micro;
35
+ pid: Types.Events.ProcessID;
36
+ tid: Types.Events.ThreadID;
37
+ cat: string;
30
38
  flows: Set<number>;
31
39
  bindingParsed: boolean;
32
40
  }
33
- type FlowBindingTuple =
34
- Map<Types.Timing.Micro, Map<Types.Events.ProcessID, Map<Types.Events.ThreadID, Map<string, EventFlowData>>>>;
35
-
36
- // Given a trace event's flow binding tuple (timestamp, process id,
37
- // thread id and category) we determine if there is any flow data bound
38
- // to it by using this map's content. It's built when processing flow
39
- // events in a trace.
40
- // An alternative to having a map of four levels is having single map
41
- // from a string token built from concatenating the binding data to the
42
- // corresponding flow data. However, this token would be calculated for
43
- // every event in a trace, resulting in a lot of memory overhead and
44
- // major GC triggering. So we are trading off readability for
45
- // performance.
46
- let boundFlowData: FlowBindingTuple = new Map();
41
+
42
+ // Trace timestamps are microseconds and too large to be small integers
43
+ // in V8, so a Map keyed by the timestamp hashes a heap number on every
44
+ // lookup. Every non-flow event in a trace is looked up here, so this
45
+ // map is keyed by the low 30 bits of the timestamp instead, which are
46
+ // always a small integer. Bindings that share a key are told apart by
47
+ // comparing the full flow binding tuple.
48
+ const TS_KEY_MASK = 0x3fffffff;
49
+ let boundFlowData = new Map<number, FlowBinding[]>();
47
50
 
48
51
  let flowsById = new Map<number, Map<Types.Timing.Micro, Types.Events.Event>>();
49
52
  let flowEvents: Types.Events.FlowEvent[] = [];
@@ -67,8 +70,17 @@ export function handleEvent(event: Types.Events.Event): void {
67
70
  nonFlowEvents.push(event);
68
71
  }
69
72
 
73
+ function findBinding(bindings: FlowBinding[], event: Types.Events.Event): FlowBinding|undefined {
74
+ return bindings.find(binding => binding.ts === event.ts && binding.pid === event.pid && binding.tid === event.tid &&
75
+ binding.cat === event.cat);
76
+ }
77
+
70
78
  function processNonFlowEvent(event: Types.Events.Event): void {
71
- const flowDataForEvent = boundFlowData.get(event.ts)?.get(event.pid)?.get(event.tid)?.get(event.cat);
79
+ const bindings = boundFlowData.get(event.ts & TS_KEY_MASK);
80
+ if (!bindings) {
81
+ return;
82
+ }
83
+ const flowDataForEvent = findBinding(bindings, event);
72
84
  if (!flowDataForEvent) {
73
85
  return;
74
86
  }
@@ -95,9 +107,8 @@ function processFlowEvent(flowPhaseEvent: Types.Events.FlowEvent): void {
95
107
  const flowGroup = flowGroupTokenForFlowPhaseEvent(flowPhaseEvent);
96
108
  switch (flowPhaseEvent.ph) {
97
109
  case (Types.Events.Phase.FLOW_START): {
98
- const flowMetadata = {flowId: flowPhaseEvent.id, times: new Map([[flowPhaseEvent.ts, undefined]])};
99
110
  flowDataByGroupToken.set(flowGroup, flowPhaseEvent.id);
100
- addFlowIdToEventBinding(flowPhaseEvent, flowMetadata.flowId);
111
+ addFlowIdToEventBinding(flowPhaseEvent, flowPhaseEvent.id);
101
112
  return;
102
113
  }
103
114
  case (Types.Events.Phase.FLOW_STEP): {
@@ -125,22 +136,19 @@ function processFlowEvent(flowPhaseEvent: Types.Events.FlowEvent): void {
125
136
  }
126
137
  }
127
138
 
128
- type MapValueType<T extends Map<unknown, unknown>> = NonNullable<ReturnType<T['get']>>;
129
139
  /**
130
140
  * A single trace event can belong to multiple flows. This method
131
141
  * tracks which flows (flowId) an event belongs to given its flow
132
142
  * binding tuple (made of its ts, pid, tid and cat).
133
143
  */
134
144
  function addFlowIdToEventBinding(event: Types.Events.Event, flowId: number): void {
135
- const flowsByPid = Platform.MapUtilities.getWithDefault<Types.Timing.Micro, MapValueType<typeof boundFlowData>>(
136
- boundFlowData, event.ts, () => new Map());
137
- const flowsByTid = Platform.MapUtilities.getWithDefault<Types.Events.ProcessID, MapValueType<typeof flowsByPid>>(
138
- flowsByPid, event.pid, () => new Map());
139
- const flowsByCat = Platform.MapUtilities.getWithDefault<Types.Events.ThreadID, MapValueType<typeof flowsByTid>>(
140
- flowsByTid, event.tid, () => new Map());
141
- const flowData =
142
- Platform.MapUtilities.getWithDefault(flowsByCat, event.cat, () => ({flows: new Set(), bindingParsed: false}));
143
- flowData.flows.add(flowId);
145
+ const bindings = Platform.MapUtilities.getWithDefault(boundFlowData, event.ts & TS_KEY_MASK, () => []);
146
+ let binding = findBinding(bindings, event);
147
+ if (!binding) {
148
+ binding = {ts: event.ts, pid: event.pid, tid: event.tid, cat: event.cat, flows: new Set(), bindingParsed: false};
149
+ bindings.push(binding);
150
+ }
151
+ binding.flows.add(flowId);
144
152
  }
145
153
 
146
154
  /**
@@ -283,14 +283,21 @@ export async function finalize(): Promise<void> {
283
283
  */
284
284
  // @ts-expect-error
285
285
  const isLightrider = globalThis.isLightrider;
286
- if (isLightrider && request.resourceFinish && request.receiveResponse?.args.data.headers) {
287
- const lrSizeHeader = request.receiveResponse.args.data.headers.find(h => h.name === 'X-TotalFetchedSize');
288
- if (lrSizeHeader) {
289
- const size = parseFloat(lrSizeHeader.value);
290
- if (!isNaN(size)) {
291
- request.resourceFinish.args.data.encodedDataLength = size;
286
+ if (isLightrider && request.receiveResponse?.args.data.headers) {
287
+ if (request.resourceFinish) {
288
+ const lrSizeHeader = request.receiveResponse.args.data.headers.find(h => h.name === 'X-TotalFetchedSize');
289
+ if (lrSizeHeader) {
290
+ const size = parseFloat(lrSizeHeader.value);
291
+ if (!isNaN(size)) {
292
+ request.resourceFinish.args.data.encodedDataLength = size;
293
+ }
292
294
  }
293
295
  }
296
+
297
+ const isH2 = request.receiveResponse.args.data.headers.some(h => h.name === 'X-ProtocolIsH2');
298
+ if (isH2) {
299
+ request.receiveResponse.args.data.protocol = 'h2';
300
+ }
294
301
  }
295
302
 
296
303
  // If a ResourceFinish event with an encoded data length is received,
@@ -8,12 +8,14 @@ let activeManager: SyntheticEventsManager|null = null;
8
8
 
9
9
  export class SyntheticEventsManager {
10
10
  /**
11
- * All synthetic entries created in a trace from
12
- * corresponding trace events.
13
- * (ProfileCalls and layout shift clusters are excluded
14
- * because they are not based on a real trace event.)
11
+ * All synthetic entries created in a trace, keyed by the raw trace event
12
+ * they are based on. (ProfileCalls and layout shift clusters are excluded
13
+ * because they are not based on a real trace event.) Keying by the raw
14
+ * event rather than by its index in the raw events array means
15
+ * registration does not need to look up the index, which would require a
16
+ * map of every raw event in the trace.
15
17
  */
16
- #syntheticTraces: Types.Events.SyntheticBased[] = [];
18
+ #syntheticEventByRawEvent = new WeakMap<Types.Events.Event, Types.Events.SyntheticBased>();
17
19
  /**
18
20
  * All raw entries from a trace.
19
21
  */
@@ -56,55 +58,26 @@ export class SyntheticEventsManager {
56
58
  this.#rawTraceEvents = rawEvents;
57
59
  }
58
60
 
59
- #rawEventIndexes: Map<Types.Events.Event, number>|null = null;
60
-
61
- #getRawEventIndex(event: Types.Events.Event): number {
62
- if (!this.#rawEventIndexes) {
63
- this.#rawEventIndexes = new Map();
64
- for (let i = 0; i < this.#rawTraceEvents.length; i++) {
65
- this.#rawEventIndexes.set(this.#rawTraceEvents[i], i);
66
- }
67
- }
68
- return this.#rawEventIndexes.get(event) ?? -1;
69
- }
70
-
71
- /**
72
- * Clears the transient raw event index map.
73
- * During trace parsing, this map provides O(1) lookups for registering synthetic events.
74
- * Once parsing is complete, queries look up synthetic events exclusively by index in
75
- * `#syntheticTraces`, so this map is discarded to reclaim memory.
76
- */
77
- clearRegistrationIndex(): void {
78
- this.#rawEventIndexes = null;
79
- }
80
-
81
61
  /**
82
62
  * Registers and returns a branded synthetic event. Synthetic events need to
83
63
  * be created with this method to ensure they are registered and made
84
64
  * available to load events using serialized keys.
85
65
  */
86
66
  #registerSyntheticEvent<T extends Types.Events.SyntheticBased>(syntheticEvent: Omit<T, '_tag'>): T {
87
- const rawIndex = this.#getRawEventIndex(syntheticEvent.rawSourceEvent);
88
- if (rawIndex < 0) {
89
- throw new Error('Attempted to register a synthetic event paired to an unknown raw event.');
90
- }
91
67
  const eventAsSynthetic = syntheticEvent as T;
92
- this.#syntheticTraces[rawIndex] = eventAsSynthetic;
68
+ this.#syntheticEventByRawEvent.set(syntheticEvent.rawSourceEvent, eventAsSynthetic);
93
69
  return eventAsSynthetic;
94
70
  }
95
71
 
96
72
  syntheticEventForRawEventIndex(rawEventIndex: number): Types.Events.SyntheticBased {
97
- const syntheticEvent = this.#syntheticTraces.at(rawEventIndex);
73
+ const rawEvent = this.#rawTraceEvents.at(rawEventIndex);
74
+ const syntheticEvent = rawEvent && this.#syntheticEventByRawEvent.get(rawEvent);
98
75
  if (!syntheticEvent) {
99
76
  throw new Error(`Attempted to get a synthetic event from an unknown raw event index: ${rawEventIndex}`);
100
77
  }
101
78
  return syntheticEvent;
102
79
  }
103
80
 
104
- getSyntheticTraces(): Types.Events.SyntheticBased[] {
105
- return this.#syntheticTraces;
106
- }
107
-
108
81
  getRawTraceEvents(): readonly Types.Events.Event[] {
109
82
  return this.#rawTraceEvents;
110
83
  }
@@ -82,18 +82,20 @@ function getNodesAndTimingByRequestId(nodeTimings: Lantern.Simulation.Result['no
82
82
 
83
83
  let duration = nodeTiming.duration;
84
84
  let startTime = nodeTiming.startTime;
85
+ let queuedTime = nodeTiming.queuedTime;
85
86
  for (const redirect of node.request.redirects ?? []) {
86
87
  const redirectTiming = timingByNodeId.get(redirect.requestId);
87
88
  if (redirectTiming) {
88
89
  duration += redirectTiming.duration;
89
90
  startTime = Math.min(startTime, redirectTiming.startTime);
91
+ queuedTime = Math.min(queuedTime, redirectTiming.queuedTime);
90
92
  }
91
93
  }
92
94
 
93
95
  const backendRequestId = node.request.rawRequest?.args.data.requestId ?? node.request.requestId;
94
96
  requestIdToNode.set(backendRequestId, {
95
97
  node,
96
- nodeTiming: {startTime, endTime: nodeTiming.endTime, duration},
98
+ nodeTiming: {startTime, endTime: nodeTiming.endTime, queuedTime, duration},
97
99
  });
98
100
  }
99
101
 
@@ -262,6 +262,9 @@ class Simulator<T = Lantern.AnyNetworkObject> {
262
262
  if (!connection) {
263
263
  return;
264
264
  }
265
+ if (this.nodeTimings.getQueued(node).queuedTime === totalElapsedTime) {
266
+ connection.setH2OverflowBytesDownloaded(0);
267
+ }
265
268
  }
266
269
 
267
270
  this.markNodeAsInProgress(node, totalElapsedTime);
@@ -430,6 +433,7 @@ class Simulator<T = Lantern.AnyNetworkObject> {
430
433
  {
431
434
  startTime: timing.startTime,
432
435
  endTime: timing.endTime,
436
+ queuedTime: timing.queuedTime,
433
437
  duration: timing.endTime - timing.startTime,
434
438
  },
435
439
  ];
@@ -233,6 +233,7 @@ export namespace Simulation {
233
233
  export interface NodeTiming {
234
234
  startTime: number;
235
235
  endTime: number;
236
+ queuedTime: number;
236
237
  duration: number;
237
238
  }
238
239
  }
@@ -89,11 +89,86 @@ const UIStrings = {
89
89
  * @description Fallback reason shown when an unknown error occurs while blocking recording.
90
90
  */
91
91
  unknownError: 'Unknown error',
92
+ /**
93
+ * @description Accessible label for the grabber handle used to vertically resize the announcements pane.
94
+ */
95
+ resizeAnnouncementsPane: 'Resize announcements pane',
92
96
  } as const;
93
97
  const str_ = i18n.i18n.registerUIStrings('panels/accessibility/AccessibilityAnnouncementRecordingView.ts', UIStrings);
94
98
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
95
99
 
96
100
  export const BINDING_NAME = '__announcementsRecorderBinding';
101
+ const MIN_MAIN_PANE_HEIGHT = 150;
102
+ const KEYBOARD_RESIZE_STEP = 10;
103
+ let isDragging = false;
104
+ let resizeStartY = 0;
105
+ let resizeStartHeight = MIN_MAIN_PANE_HEIGHT;
106
+
107
+ function onResizerPointerDown(event: PointerEvent): void {
108
+ if (event.button !== 0) {
109
+ return;
110
+ }
111
+ const resizerEl = event.currentTarget as HTMLElement | null;
112
+ const mainPane = resizerEl?.parentElement?.querySelector<HTMLElement>('.announcements-main-pane');
113
+ if (!resizerEl || !mainPane) {
114
+ return;
115
+ }
116
+ isDragging = true;
117
+ resizeStartY = event.clientY;
118
+ resizeStartHeight = mainPane.getBoundingClientRect().height;
119
+ try {
120
+ resizerEl.setPointerCapture(event.pointerId);
121
+ } catch {
122
+ // Pointer capture may fail on synthetic events in unit tests.
123
+ }
124
+ event.preventDefault();
125
+ }
126
+
127
+ function onResizerPointerMove(event: PointerEvent): void {
128
+ const resizerEl = event.currentTarget as HTMLElement | null;
129
+ if (!resizerEl || !isDragging) {
130
+ return;
131
+ }
132
+ const mainPane = resizerEl.parentElement?.querySelector<HTMLElement>('.announcements-main-pane');
133
+ if (!mainPane) {
134
+ return;
135
+ }
136
+ const delta = event.clientY - resizeStartY;
137
+ const newHeight = Math.max(MIN_MAIN_PANE_HEIGHT, resizeStartHeight + delta);
138
+ mainPane.style.height = `${newHeight}px`;
139
+ mainPane.style.flex = 'none';
140
+ }
141
+
142
+ function onResizerPointerUp(event: PointerEvent): void {
143
+ isDragging = false;
144
+ const resizerEl = event.currentTarget as HTMLElement | null;
145
+ if (resizerEl) {
146
+ try {
147
+ if (resizerEl.hasPointerCapture(event.pointerId)) {
148
+ resizerEl.releasePointerCapture(event.pointerId);
149
+ }
150
+ } catch {
151
+ // Ignored for synthetic events in unit tests.
152
+ }
153
+ }
154
+ }
155
+
156
+ function onResizerKeyDown(event: KeyboardEvent): void {
157
+ if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
158
+ return;
159
+ }
160
+ const resizerEl = event.currentTarget as HTMLElement | null;
161
+ const mainPane = resizerEl?.parentElement?.querySelector<HTMLElement>('.announcements-main-pane');
162
+ if (!mainPane) {
163
+ return;
164
+ }
165
+ event.preventDefault();
166
+ const delta = event.key === 'ArrowDown' ? KEYBOARD_RESIZE_STEP : -KEYBOARD_RESIZE_STEP;
167
+ const currentHeight = mainPane.getBoundingClientRect().height;
168
+ const newHeight = Math.max(MIN_MAIN_PANE_HEIGHT, currentHeight + delta);
169
+ mainPane.style.height = `${newHeight}px`;
170
+ mainPane.style.flex = 'none';
171
+ }
97
172
 
98
173
  export enum AnnouncementApi {
99
174
  ARIA_LIVE = 'aria-live',
@@ -218,6 +293,23 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
218
293
  @reveal-in-a11y-tree=${(e: CustomEvent<A11yAnnouncement>) => input.onRevealInA11yTree(e.detail)}>
219
294
  </devtools-widget>
220
295
  </div>
296
+ <div
297
+ class="announcements-resizer"
298
+ role="separator"
299
+ aria-orientation="horizontal"
300
+ aria-label=${i18nString(UIStrings.resizeAnnouncementsPane)}
301
+ title=${i18nString(UIStrings.resizeAnnouncementsPane)}
302
+ tabindex="0"
303
+ jslog=${VisualLogging.resizer('accessibility-announcements.resizer').track({
304
+ drag: true,
305
+ keydown: 'ArrowUp|ArrowDown',
306
+ })}
307
+ @pointerdown=${onResizerPointerDown}
308
+ @pointermove=${onResizerPointerMove}
309
+ @pointerup=${onResizerPointerUp}
310
+ @lostpointercapture=${onResizerPointerUp}
311
+ @keydown=${onResizerKeyDown}>
312
+ </div>
221
313
  </div>`,
222
314
  target);
223
315
  // clang-format on
@@ -72,7 +72,7 @@ const DEFAULT_VIEW: View = (input, _output, target) => {
72
72
  }
73
73
  <devtools-checkbox class="source-order-checkbox"
74
74
  jslog=${VisualLogging.toggle().track({click: true})}
75
- ?checked=${input.showSourceOrder}
75
+ .checked=${Boolean(input.showSourceOrder)}
76
76
  @change=${onShowSourceOrderChanged}>
77
77
  ${i18nString(UIStrings.showSourceOrder)}
78
78
  </devtools-checkbox>