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
@@ -4,155 +4,170 @@
4
4
  * found in the LICENSE file.
5
5
  */
6
6
 
7
- .root {
8
- color: var(--sys-color-on-surface);
9
- width: 100%;
10
- }
7
+ @scope to (devtools-widget > *) {
8
+ /* Host styles can now reach the elements of this form. For example,
9
+ * the inspector common styles set "box-sizing: border-box" on all
10
+ * elements, and ListWidget editors set margins on all inputs. Restore
11
+ * the default box sizing and input margins of the browser. */
12
+ :scope * {
13
+ box-sizing: revert;
14
+ }
11
15
 
12
- .tree-title {
13
- font-weight: 700;
14
- display: flex;
15
- align-items: center;
16
+ :scope input {
17
+ margin: revert;
18
+ }
16
19
 
17
- & > [aria-controls="form-container"] {
18
- margin-left: var(--sys-size-2);
19
- padding-right: var(--sys-size-3);
20
+ .root {
21
+ color: var(--sys-color-on-surface);
22
+ width: 100%;
23
+ }
20
24
 
21
- & > [name="triangle-right"],
22
- & > [name="triangle-down"] {
23
- vertical-align: bottom;
24
- }
25
+ .tree-title {
26
+ font-weight: 700;
27
+ display: flex;
28
+ align-items: center;
25
29
 
26
- &[aria-expanded="true"] > [name="triangle-right"] {
27
- display: none;
28
- }
30
+ & > [aria-controls="form-container"] {
31
+ margin-left: var(--sys-size-2);
32
+ padding-right: var(--sys-size-3);
33
+
34
+ & > [name="triangle-right"],
35
+ & > [name="triangle-down"] {
36
+ vertical-align: bottom;
37
+ }
29
38
 
30
- &[aria-expanded="false"] > [name="triangle-down"] {
31
- display: none;
39
+ &[aria-expanded="true"] > [name="triangle-right"] {
40
+ display: none;
41
+ }
42
+
43
+ &[aria-expanded="false"] > [name="triangle-down"] {
44
+ display: none;
45
+ }
32
46
  }
33
47
  }
34
- }
35
-
36
- .form-container {
37
- display: grid;
38
- grid-template-columns: 1fr 1fr 1fr auto;
39
- align-items: center;
40
- gap: var(--sys-size-5) 10px;
41
- padding: 0 10px;
42
- }
43
48
 
44
- .full-row {
45
- grid-column: 1 / 5;
46
- }
49
+ .form-container {
50
+ display: grid;
51
+ grid-template-columns: 1fr 1fr 1fr auto;
52
+ align-items: center;
53
+ gap: var(--sys-size-5) 10px;
54
+ padding: 0 10px;
55
+ }
47
56
 
48
- .form-factors-checkbox-group {
49
- display: grid;
50
- grid-template-columns: repeat(2, 1fr);
51
- gap: var(--sys-size-4) 10px;
52
- }
57
+ .full-row {
58
+ grid-column: 1 / 5;
59
+ }
53
60
 
54
- .form-factor-checkbox-label {
55
- display: flex;
56
- align-items: center;
57
- gap: var(--sys-size-4);
58
- white-space: nowrap;
59
- }
61
+ .form-factors-checkbox-group {
62
+ display: grid;
63
+ grid-template-columns: repeat(2, 1fr);
64
+ gap: var(--sys-size-4) 10px;
65
+ }
60
66
 
61
- hr.section-separator {
62
- grid-column: 1 / 5; /* Ensures the separator spans all columns */
63
- border: none;
64
- margin-top: var(--sys-size-1);
65
- }
67
+ .form-factor-checkbox-label {
68
+ display: flex;
69
+ align-items: center;
70
+ gap: var(--sys-size-4);
71
+ white-space: nowrap;
72
+ }
66
73
 
67
- .half-row {
68
- grid-column: span 2;
69
- }
74
+ hr.section-separator {
75
+ grid-column: 1 / 5; /* Ensures the separator spans all columns */
76
+ border: none;
77
+ margin-top: var(--sys-size-1);
78
+ }
70
79
 
71
- .mobile-checkbox-container {
72
- display: flex;
73
- }
80
+ .half-row {
81
+ grid-column: span 2;
82
+ }
74
83
 
75
- .device-model-input {
76
- grid-column: 1 / 4;
77
- }
84
+ .mobile-checkbox-container {
85
+ display: flex;
86
+ }
78
87
 
79
- .input-field {
80
- color: var(--sys-color-on-surface);
81
- padding: 3px var(--sys-size-4);
82
- border-radius: var(--sys-size-2);
83
- border: var(--sys-size-1) solid var(--sys-color-neutral-outline);
84
- background-color: var(--sys-color-cdt-base-container);
85
- font-size: inherit;
86
- height: 18px;
87
- }
88
+ .device-model-input {
89
+ grid-column: 1 / 4;
90
+ }
88
91
 
89
- .input-field::placeholder {
90
- color: var(--sys-color-on-surface-subtle);
91
- }
92
+ .input-field {
93
+ color: var(--sys-color-on-surface);
94
+ padding: 3px var(--sys-size-4);
95
+ border-radius: var(--sys-size-2);
96
+ border: var(--sys-size-1) solid var(--sys-color-neutral-outline);
97
+ background-color: var(--sys-color-cdt-base-container);
98
+ font-family: inherit;
99
+ font-size: inherit;
100
+ height: 18px;
101
+ }
92
102
 
93
- .input-field:focus {
94
- border: var(--sys-size-1) solid var(--sys-color-state-focus-ring);
95
- outline-style: none;
96
- }
103
+ .input-field::placeholder {
104
+ color: var(--sys-color-on-surface-subtle);
105
+ }
97
106
 
98
- .add-container {
99
- cursor: pointer;
100
- display: flex;
101
- align-items: center;
102
- gap: var(--sys-size-4);
103
- }
107
+ .input-field:focus {
108
+ border: var(--sys-size-1) solid var(--sys-color-state-focus-ring);
109
+ outline-style: none;
110
+ }
104
111
 
105
- .add-icon {
106
- margin-right: 5px;
107
- }
112
+ .add-container {
113
+ cursor: pointer;
114
+ display: flex;
115
+ align-items: center;
116
+ gap: var(--sys-size-4);
117
+ }
108
118
 
109
- .brand-row {
110
- display: flex;
111
- align-items: center;
112
- gap: 10px;
113
- justify-content: space-between;
114
- }
119
+ .add-icon {
120
+ margin-right: 5px;
121
+ }
115
122
 
116
- .brand-row > input {
117
- width: 100%;
118
- }
123
+ .brand-row {
124
+ display: flex;
125
+ align-items: center;
126
+ gap: 10px;
127
+ justify-content: space-between;
128
+ }
119
129
 
120
- .info-icon {
121
- margin-left: 5px;
122
- margin-right: var(--sys-size-1);
123
- height: var(--sys-size-8);
124
- width: var(--sys-size-8);
125
- }
130
+ .brand-row > input {
131
+ width: 100%;
132
+ }
126
133
 
127
- .link,
128
- .devtools-link {
129
- color: var(--sys-color-primary);
130
- text-decoration: underline;
131
- cursor: pointer;
132
- outline-offset: var(--sys-size-2);
133
- font-weight: 400;
134
- }
134
+ .info-icon {
135
+ margin-left: 5px;
136
+ margin-right: var(--sys-size-1);
137
+ height: var(--sys-size-8);
138
+ width: var(--sys-size-8);
139
+ }
135
140
 
136
- devtools-icon + .link {
137
- margin-inline-start: var(--sys-size-2);
138
- }
141
+ .link,
142
+ .devtools-link {
143
+ color: var(--sys-color-primary);
144
+ text-decoration: underline;
145
+ cursor: pointer;
146
+ outline-offset: var(--sys-size-2);
147
+ font-weight: 400;
148
+ }
139
149
 
140
- .hide-container {
141
- display: none;
142
- }
150
+ devtools-icon + .link {
151
+ margin-inline-start: var(--sys-size-2);
152
+ }
143
153
 
144
- .input-field-label-container {
145
- display: flex;
146
- flex-direction: column;
147
- gap: 10px;
148
- }
154
+ .hide-container {
155
+ display: none;
156
+ }
149
157
 
150
- @media (forced-colors: active) {
151
- .input-field {
152
- border: var(--sys-size-1) solid;
158
+ .input-field-label-container {
159
+ display: flex;
160
+ flex-direction: column;
161
+ gap: 10px;
153
162
  }
154
163
 
155
- .tree-title[aria-disabled="true"] {
156
- color: GrayText;
164
+ @media (forced-colors: active) {
165
+ .input-field {
166
+ border: var(--sys-size-1) solid;
167
+ }
168
+
169
+ .tree-title[aria-disabled="true"] {
170
+ color: GrayText;
171
+ }
157
172
  }
158
173
  }
@@ -140,6 +140,20 @@ const UIStrings = {
140
140
  * shows up for disconnected automatic workspace folders.
141
141
  */
142
142
  connectFolderToWorkspace: 'Connect to workspace',
143
+ /**
144
+ * @description A context menu item in the Sources navigator of the Sources panel.
145
+ */
146
+ run: 'Run',
147
+ /**
148
+ * @description Text to save content as a specific file type.
149
+ */
150
+ saveAs: 'Save as…',
151
+ /**
152
+ * @description An error message logged to the Console panel when the user uses
153
+ * the "Save as…" context menu in the Sources panel and the operation
154
+ * fails.
155
+ */
156
+ saveAsFailed: 'Failed to save file to disk',
143
157
  } as const;
144
158
 
145
159
  const str_ = i18n.i18n.registerUIStrings('panels/sources/NavigatorView.ts', UIStrings);
@@ -174,30 +188,22 @@ const TYPE_ORDERS = new Map([
174
188
 
175
189
  export interface ViewInput {
176
190
  treeElement: HTMLElement;
177
- placeholder: UI.Widget.Widget|null;
178
191
  showTree: boolean;
179
- onContextMenu: (event: Event) => void;
180
192
  }
181
193
 
182
194
  export type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
183
195
 
184
196
  export const DEFAULT_VIEW: View = (input, _output, target): void => {
185
- const showPlaceholder = Boolean(input.placeholder && !input.showTree);
197
+ const showPlaceholder = !input.showTree;
186
198
  // clang-format off
187
199
  render(
188
200
  html`
189
201
  <style>${navigatorViewStyles}</style>
190
202
  <slot name="header"></slot>
191
- <div class="vbox flex-auto" ?hidden=${!showPlaceholder} @contextmenu=${input.onContextMenu}>
192
- <slot name="placeholder">
193
- ${input.placeholder ? html`
194
- <devtools-widget class="vbox flex-auto" ?hidden=${!showPlaceholder}>
195
- ${input.placeholder.element}
196
- </devtools-widget>
197
- ` : Lit.nothing}
198
- </slot>
203
+ <div class="vbox flex-auto" ?hidden=${!showPlaceholder}>
204
+ <slot name="placeholder"></slot>
199
205
  </div>
200
- <div class="vbox flex-auto" ?hidden=${showPlaceholder} @contextmenu=${input.onContextMenu}>
206
+ <div class="vbox flex-auto" ?hidden=${showPlaceholder}>
201
207
  ${input.treeElement}
202
208
  </div>
203
209
  `,
@@ -205,11 +211,28 @@ export const DEFAULT_VIEW: View = (input, _output, target): void => {
205
211
  // clang-format on
206
212
  };
207
213
 
208
- export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.Observer {
214
+ export const enum Events {
215
+ UI_SOURCE_CODE_ADDED = 'ui-source-code-added',
216
+ SOURCE_SELECTED = 'source-selected',
217
+ }
218
+
219
+ export interface SourceSelectedEvent {
220
+ uiSourceCode: Workspace.UISourceCode.UISourceCode;
221
+ focusSource: boolean;
222
+ }
223
+
224
+ export interface EventTypes {
225
+ [Events.UI_SOURCE_CODE_ADDED]: Workspace.UISourceCode.UISourceCode;
226
+ [Events.SOURCE_SELECTED]: SourceSelectedEvent;
227
+ }
228
+
229
+ const NavigatorViewBase: Common.ObjectWrapper.EventMixin<EventTypes, typeof UI.Widget.VBox> =
230
+ Common.ObjectWrapper.eventMixin(UI.Widget.VBox);
231
+
232
+ export class NavigatorView extends NavigatorViewBase implements SDK.TargetManager.Observer {
209
233
  static override readonly INJECT: readonly[typeof Bindings.NetworkProject.NetworkProjectManager] =
210
234
  [Bindings.NetworkProject.NetworkProjectManager] as const;
211
235
 
212
- private placeholder: UI.Widget.Widget|null;
213
236
  scriptsTree: UI.TreeOutline.TreeOutlineInShadow;
214
237
  private readonly uiSourceCodeNodes:
215
238
  Platform.MapUtilities.Multimap<Workspace.UISourceCode.UISourceCode, NavigatorUISourceCodeTreeNode>;
@@ -223,7 +246,9 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
223
246
  private navigatorGroupByAuthoredSetting?: Common.Settings.Setting<boolean>;
224
247
  #navigatorGroupByAuthoredChangeListener?: () => void;
225
248
  #enableAuthoredGrouping = false;
226
- #workspace!: Workspace.Workspace.WorkspaceImpl;
249
+ #projectFilter?: (project: Workspace.Workspace.Project) => boolean;
250
+ #workspace = Workspace.Workspace.WorkspaceImpl.instance();
251
+ #initialized = false;
227
252
  private groupByFrame?: boolean;
228
253
  private groupByAuthored?: boolean;
229
254
  private groupByDomain?: boolean;
@@ -235,15 +260,10 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
235
260
  [networkProjectManager]: UI.Widget.WidgetDependencies<typeof NavigatorView> =
236
261
  [Bindings.NetworkProject.NetworkProjectManager.instance()],
237
262
  view: View = DEFAULT_VIEW,
238
- options?: UI.Widget.WidgetOptions,
239
263
  ) {
240
- super(element, {
241
- ...options,
242
- useShadowDom: true,
243
- });
264
+ super(element, {useShadowDom: true});
244
265
  this.#view = view;
245
266
 
246
- this.placeholder = null;
247
267
  this.scriptsTree = new UI.TreeOutline.TreeOutlineInShadow(UI.TreeOutline.TreeVariant.NAVIGATION_TREE);
248
268
  this.scriptsTree.registerRequiredCSS(navigatorTreeStyles);
249
269
 
@@ -286,12 +306,11 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
286
306
  SDK.TargetManager.Events.NAME_CHANGED, this.targetNameChanged, this);
287
307
 
288
308
  SDK.TargetManager.TargetManager.instance().observeTargets(this);
289
- this.resetWorkspace(Workspace.Workspace.WorkspaceImpl.instance());
290
- this.#workspace.uiSourceCodes().forEach(this.addUISourceCode.bind(this));
291
309
  networkProjectManager.addEventListener(Bindings.NetworkProject.Events.FRAME_ATTRIBUTION_ADDED,
292
310
  this.frameAttributionAdded, this);
293
311
  networkProjectManager.addEventListener(Bindings.NetworkProject.Events.FRAME_ATTRIBUTION_REMOVED,
294
312
  this.frameAttributionRemoved, this);
313
+ this.requestUpdate();
295
314
  }
296
315
 
297
316
  override wasShown(): void {
@@ -319,7 +338,22 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
319
338
  this.#navigatorGroupByAuthoredChangeListener = this.groupingChanged.bind(this);
320
339
  this.navigatorGroupByAuthoredSetting.addChangeListener(this.#navigatorGroupByAuthoredChangeListener);
321
340
  }
322
- if (this.#workspace && Boolean(this.groupByAuthored) !== Boolean(this.navigatorGroupByAuthoredSetting?.get())) {
341
+ if (this.#initialized && Boolean(this.groupByAuthored) !== Boolean(this.navigatorGroupByAuthoredSetting?.get())) {
342
+ this.groupingChanged();
343
+ }
344
+ this.requestUpdate();
345
+ }
346
+
347
+ get projectFilter(): ((project: Workspace.Workspace.Project) => boolean)|undefined {
348
+ return this.#projectFilter;
349
+ }
350
+
351
+ set projectFilter(projectFilter: ((project: Workspace.Workspace.Project) => boolean)|undefined) {
352
+ if (this.#projectFilter === projectFilter) {
353
+ return;
354
+ }
355
+ this.#projectFilter = projectFilter;
356
+ if (this.#initialized) {
323
357
  this.groupingChanged();
324
358
  }
325
359
  this.requestUpdate();
@@ -371,18 +405,16 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
371
405
  return Platform.StringUtilities.naturalOrderComparator(treeElement1.titleAsText(), treeElement2.titleAsText());
372
406
  }
373
407
 
374
- setPlaceholder(placeholder: UI.Widget.Widget): void {
375
- console.assert(!this.placeholder, 'A placeholder widget was already set');
376
- this.placeholder = placeholder;
377
- this.requestUpdate();
378
- }
379
-
380
408
  override performUpdate(): void {
409
+ if (!this.#initialized) {
410
+ this.#initialized = true;
411
+ this.initGrouping();
412
+ this.resetWorkspace(this.#workspace);
413
+ this.#workspace.uiSourceCodes().forEach(this.addUISourceCode.bind(this));
414
+ }
381
415
  this.#view({
382
416
  treeElement: this.scriptsTree.element,
383
- placeholder: this.placeholder,
384
417
  showTree: Boolean(this.scriptsTree.firstChild()),
385
- onContextMenu: this.handleContextMenu.bind(this),
386
418
  },
387
419
  undefined, this.contentElement);
388
420
  }
@@ -497,11 +529,10 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
497
529
  }
498
530
  }
499
531
 
500
- workspace(): Workspace.Workspace.WorkspaceImpl {
501
- return this.#workspace;
502
- }
503
-
504
532
  acceptProject(project: Workspace.Workspace.Project): boolean {
533
+ if (this.#projectFilter) {
534
+ return this.#projectFilter(project);
535
+ }
505
536
  return !project.isServiceProject();
506
537
  }
507
538
 
@@ -558,7 +589,7 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
558
589
  } else {
559
590
  this.addUISourceCodeNode(uiSourceCode, null);
560
591
  }
561
- this.uiSourceCodeAdded(uiSourceCode);
592
+ this.dispatchEventToListeners(Events.UI_SOURCE_CODE_ADDED, uiSourceCode);
562
593
  }
563
594
 
564
595
  private addUISourceCodeNode(
@@ -588,9 +619,6 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
588
619
  this.selectDefaultTreeNode();
589
620
  }
590
621
 
591
- uiSourceCodeAdded(_uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
592
- }
593
-
594
622
  private uiSourceCodeAddedCallback(event: Common.EventTarget.EventTargetEvent<Workspace.UISourceCode.UISourceCode>):
595
623
  void {
596
624
  const uiSourceCode = event.data;
@@ -912,11 +940,13 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
912
940
  }
913
941
 
914
942
  sourceSelected(uiSourceCode: Workspace.UISourceCode.UISourceCode, focusSource: boolean): void {
943
+ this.dispatchEventToListeners(Events.SOURCE_SELECTED, {uiSourceCode, focusSource});
915
944
  void Common.Revealer.reveal(uiSourceCode, !focusSource);
916
945
  }
917
946
 
918
947
  #isUISourceCodeOrAnyAncestorSelected(node: NavigatorUISourceCodeTreeNode): boolean {
919
- const selectedTreeElement = (this.scriptsTree.selectedTreeElement as NavigatorSourceTreeElement | null);
948
+ const selectedTreeElement =
949
+ (this.scriptsTree.selectedTreeElement as NavigatorSourceTreeElement | NavigatorFolderTreeElement | null);
920
950
  const selectedNode = selectedTreeElement?.node;
921
951
  let currentNode: NavigatorTreeNode|null = node;
922
952
  while (currentNode) {
@@ -924,7 +954,7 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
924
954
  return true;
925
955
  }
926
956
  currentNode = currentNode.parent;
927
- if (!(node instanceof NavigatorGroupTreeNode || node instanceof NavigatorFolderTreeElement)) {
957
+ if (!(currentNode instanceof NavigatorGroupTreeNode || currentNode instanceof NavigatorFolderTreeNode)) {
928
958
  break;
929
959
  }
930
960
  }
@@ -1022,9 +1052,6 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
1022
1052
  }
1023
1053
  }
1024
1054
 
1025
- handleContextMenu(_event: Event): void {
1026
- }
1027
-
1028
1055
  private async renameShortcut(): Promise<boolean> {
1029
1056
  const selectedTreeElement = (this.scriptsTree.selectedTreeElement as NavigatorSourceTreeElement | null);
1030
1057
  const node = selectedTreeElement?.node;
@@ -1074,6 +1101,22 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
1074
1101
 
1075
1102
  handleFileContextMenu(event: Event, node: NavigatorUISourceCodeTreeNode): void {
1076
1103
  const uiSourceCode = node.uiSourceCode();
1104
+ if (Snippets.ScriptSnippetFileSystem.isSnippetsUISourceCode(uiSourceCode)) {
1105
+ const contextMenu = new UI.ContextMenu.ContextMenu(event);
1106
+ contextMenu.headerSection().appendItem(i18nString(UIStrings.run),
1107
+ () => Snippets.ScriptSnippetFileSystem.evaluateScriptSnippet(uiSourceCode),
1108
+ {jslogContext: 'run'});
1109
+ contextMenu.editSection().appendItem(i18nString(UIStrings.rename), () => this.rename(node, false),
1110
+ {jslogContext: 'rename'});
1111
+ contextMenu.editSection().appendItem(i18nString(UIStrings.remove),
1112
+ () => uiSourceCode.project().deleteFile(uiSourceCode),
1113
+ {jslogContext: 'remove'});
1114
+ contextMenu.saveSection().appendItem(i18nString(UIStrings.saveAs), this.handleSaveAs.bind(this, uiSourceCode),
1115
+ {jslogContext: 'save-as'});
1116
+ void contextMenu.show();
1117
+ return;
1118
+ }
1119
+
1077
1120
  const contextMenu = new UI.ContextMenu.ContextMenu(event);
1078
1121
  contextMenu.appendApplicableItems(uiSourceCode);
1079
1122
 
@@ -1093,6 +1136,23 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
1093
1136
  void contextMenu.show();
1094
1137
  }
1095
1138
 
1139
+ private async handleSaveAs(uiSourceCode: Workspace.UISourceCode.UISourceCode): Promise<void> {
1140
+ uiSourceCode.commitWorkingCopy();
1141
+ const contentData = await uiSourceCode.requestContentData();
1142
+ if (TextUtils.ContentData.ContentData.isError(contentData)) {
1143
+ console.error(`Failed to retrieve content for ${uiSourceCode.url()}: ${contentData}`);
1144
+ Common.Console.Console.instance().error(i18nString(UIStrings.saveAsFailed), /* show=*/ false);
1145
+ return;
1146
+ }
1147
+ await Workspace.FileManager.FileManager.instance().save(this.addJSExtension(uiSourceCode.url()), contentData,
1148
+ /* forceSaveAs=*/ true);
1149
+ Workspace.FileManager.FileManager.instance().close(uiSourceCode.url());
1150
+ }
1151
+
1152
+ private addJSExtension(url: Platform.DevToolsPath.UrlString): Platform.DevToolsPath.UrlString {
1153
+ return Common.ParsedURL.ParsedURL.concatenate(url, '.js');
1154
+ }
1155
+
1096
1156
  private async handleDeleteFolder(node: NavigatorTreeNode): Promise<void> {
1097
1157
  const shouldRemove = await UI.UIUtils.ConfirmDialog.show(
1098
1158
  i18nString(UIStrings.actionCannotBeUndone), i18nString(UIStrings.deleteFolder), undefined,
@@ -75,7 +75,7 @@ interface ViewInput {
75
75
  scope: SDK.DebuggerModel.ScopeChainEntry,
76
76
  objectTree: ObjectUI.ObjectPropertiesSection.ObjectTree,
77
77
  }>|null;
78
- onToggle: (objectTree: ObjectUI.ObjectPropertiesSection.ObjectTree, expanded: boolean) => void;
78
+ onToggle: (objectTree: ObjectUI.ObjectPropertiesSection.ObjectTree, expanded: boolean, recursively?: boolean) => void;
79
79
  onContextMenu: (
80
80
  objectTree: ObjectUI.ObjectPropertiesSection.ObjectTree,
81
81
  contextMenu: UI.ContextMenu.ContextMenu,
@@ -100,9 +100,8 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
100
100
  class="scope-chain-sidebar-pane-section"
101
101
  aria-label=${title}
102
102
  ?open=${objectTree.expanded}
103
- @expand=${(e: Event) => {
104
- const customEvent = e as UI.TreeOutline.TreeViewElement.ExpandEvent;
105
- input.onToggle(objectTree, customEvent.detail.expanded);
103
+ @expand=${(e: UI.TreeOutline.TreeViewElement.ExpandEvent) => {
104
+ input.onToggle(objectTree, e.detail.expanded, e.detail.recursively);
106
105
  }}
107
106
  @contextmenu=${(e: Event) => {
108
107
  const contextMenu = new UI.ContextMenu.ContextMenu(e);
@@ -232,7 +231,11 @@ export class ScopeChainSidebarPane extends UI.Widget.VBox implements UI.ContextF
232
231
  linkifier: this.#linkifier,
233
232
  isPaused: Boolean(this.#scopeChainModel),
234
233
  scopeChain: this.#scopeChain,
235
- onToggle: (objectTree: ObjectUI.ObjectPropertiesSection.ObjectTree, expanded: boolean) => {
234
+ onToggle: (objectTree: ObjectUI.ObjectPropertiesSection.ObjectTree, expanded: boolean, recursively = false) => {
235
+ if (expanded && recursively) {
236
+ void objectTree.expandRecursively().then(() => this.requestUpdate());
237
+ return;
238
+ }
236
239
  objectTree.expanded = expanded;
237
240
  this.requestUpdate();
238
241
  },