chrome-devtools-frontend 1.0.941208 → 1.0.943182

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 (289) hide show
  1. package/WATCHLISTS +1 -1
  2. package/config/gni/all_devtools_files.gni +0 -64
  3. package/config/gni/devtools_grd_files.gni +54 -19
  4. package/config/gni/devtools_image_files.gni +1 -3
  5. package/front_end/.eslintrc.js +11 -1
  6. package/front_end/Images/src/{feedback_thin_16x16_icon.svg → survey_feedback_icon.svg} +1 -1
  7. package/front_end/Tests.js +1 -32
  8. package/front_end/core/common/Color.ts +5 -0
  9. package/front_end/core/i18n/locales/en-US.json +17 -29
  10. package/front_end/core/i18n/locales/en-XL.json +17 -29
  11. package/front_end/core/sdk/CPUProfilerModel.ts +7 -9
  12. package/front_end/core/sdk/ConsoleModel.ts +27 -33
  13. package/front_end/core/sdk/DebuggerModel.ts +4 -14
  14. package/front_end/core/sdk/sdk-meta.ts +17 -3
  15. package/front_end/entrypoints/device_mode_emulation_frame/device_mode_emulation_frame.ts +1 -1
  16. package/front_end/entrypoints/devtools_app/devtools_app.js +1 -1
  17. package/front_end/entrypoints/devtools_app/devtools_app.json +1 -12
  18. package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +1 -1
  19. package/front_end/entrypoints/heap_snapshot_worker/heap_snapshot_worker-entrypoint.ts +1 -1
  20. package/front_end/entrypoints/inspector/inspector.js +1 -1
  21. package/front_end/entrypoints/inspector/inspector.json +1 -3
  22. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +2 -3
  23. package/front_end/entrypoints/js_app/js_app.js +1 -1
  24. package/front_end/entrypoints/js_app/js_app.json +1 -3
  25. package/front_end/entrypoints/main/MainImpl.ts +26 -0
  26. package/front_end/entrypoints/main/main-meta.ts +1 -2
  27. package/front_end/entrypoints/ndb_app/ndb_app.js +1 -1
  28. package/front_end/entrypoints/node_app/node_app-meta.ts +0 -2
  29. package/front_end/entrypoints/node_app/node_app.js +1 -1
  30. package/front_end/entrypoints/node_app/node_app.json +1 -3
  31. package/front_end/entrypoints/node_main/node_main-meta.ts +0 -1
  32. package/front_end/entrypoints/shell/shell.js +0 -11
  33. package/front_end/entrypoints/shell/shell.json +1 -5
  34. package/front_end/entrypoints/wasmparser_worker/wasmparser_worker-entrypoint.ts +1 -1
  35. package/front_end/entrypoints/worker_app/worker_app.js +1 -1
  36. package/front_end/entrypoints/worker_app/worker_app.json +1 -7
  37. package/front_end/generated/InspectorBackendCommands.js +19 -0
  38. package/front_end/generated/protocol-mapping.d.ts +31 -1
  39. package/front_end/generated/protocol-proxy-api.d.ts +34 -2
  40. package/front_end/generated/protocol.d.ts +81 -6
  41. package/front_end/legacy_test_runner/bindings_test_runner/IsolatedFilesystemTestRunner.js +2 -2
  42. package/front_end/legacy_test_runner/console_test_runner/console_test_runner.js +5 -1
  43. package/front_end/legacy_test_runner/legacy_test_runner.ts +10 -1
  44. package/front_end/legacy_test_runner/test_runner/TestRunner.js +3 -1
  45. package/front_end/models/formatter/SourceFormatter.ts +0 -10
  46. package/front_end/models/persistence/persistence-meta.ts +0 -1
  47. package/front_end/models/workspace/UISourceCode.ts +9 -42
  48. package/front_end/panels/accessibility/accessibility-meta.ts +0 -1
  49. package/front_end/panels/animation/AnimationTimeline.ts +3 -3
  50. package/front_end/panels/animation/animation-meta.ts +0 -1
  51. package/front_end/panels/application/ApplicationPanelSidebar.ts +3 -3
  52. package/front_end/panels/application/BackForwardCacheStrings.ts +3 -1
  53. package/front_end/panels/application/application-meta.ts +0 -4
  54. package/front_end/panels/application/components/EndpointsGrid.ts +1 -1
  55. package/front_end/panels/application/components/ReportsGrid.ts +1 -1
  56. package/front_end/panels/application/components/stackTraceRow.css +8 -0
  57. package/front_end/panels/browser_debugger/browser_debugger-meta.ts +1 -2
  58. package/front_end/panels/changes/changes-meta.ts +0 -1
  59. package/front_end/panels/console/ConsolePinPane.ts +23 -32
  60. package/front_end/panels/console/ConsoleViewMessage.ts +8 -1
  61. package/front_end/panels/console/console-meta.ts +0 -1
  62. package/front_end/panels/console_counters/console_counters-meta.ts +0 -1
  63. package/front_end/panels/coverage/CoverageDecorationManager.ts +4 -5
  64. package/front_end/panels/coverage/CoverageView.ts +2 -105
  65. package/front_end/panels/coverage/coverage-meta.ts +0 -1
  66. package/front_end/panels/css_overview/components/CSSOverviewStartView.ts +11 -56
  67. package/front_end/panels/css_overview/components/cssOverviewStartView.css +1 -8
  68. package/front_end/panels/css_overview/css_overview-meta.ts +0 -1
  69. package/front_end/panels/developer_resources/developer_resources-meta.ts +0 -1
  70. package/front_end/panels/elements/ElementsTreeElement.ts +4 -9
  71. package/front_end/panels/elements/components/StylePropertyEditor.ts +2 -0
  72. package/front_end/panels/elements/components/adornerSettingsPane.css +0 -4
  73. package/front_end/panels/elements/elements-meta.ts +0 -1
  74. package/front_end/panels/emulation/DeviceModeToolbar.ts +3 -1
  75. package/front_end/panels/emulation/DeviceModeView.ts +2 -1
  76. package/front_end/panels/emulation/InspectedPagePlaceholder.ts +3 -1
  77. package/front_end/panels/emulation/MediaQueryInspector.ts +3 -1
  78. package/front_end/panels/emulation/emulation-meta.ts +2 -5
  79. package/front_end/panels/help/help-meta.ts +0 -1
  80. package/front_end/panels/input/input-meta.ts +0 -1
  81. package/front_end/panels/issues/issues-meta.ts +0 -3
  82. package/front_end/panels/js_profiler/js_profiler-meta.ts +0 -4
  83. package/front_end/panels/layers/layers-meta.ts +0 -4
  84. package/front_end/panels/lighthouse/LighthousePanel.ts +2 -4
  85. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +1 -4
  86. package/front_end/panels/lighthouse/lighthouse-meta.ts +0 -1
  87. package/front_end/panels/lighthouse/lighthouseStartView.css +4 -0
  88. package/front_end/panels/lighthouse/module.json +0 -6
  89. package/front_end/panels/media/media-meta.ts +0 -4
  90. package/front_end/panels/mobile_throttling/mobile_throttling-meta.ts +0 -1
  91. package/front_end/panels/network/ResourceWebSocketFrameView.ts +2 -1
  92. package/front_end/panels/network/network-meta.ts +1 -5
  93. package/front_end/panels/performance_monitor/performance_monitor-meta.ts +0 -1
  94. package/front_end/panels/profiler/CPUProfileView.ts +10 -3
  95. package/front_end/panels/profiler/profiler-meta.ts +0 -3
  96. package/front_end/panels/protocol_monitor/protocol_monitor-meta.ts +0 -1
  97. package/front_end/panels/screencast/screencast-meta.ts +0 -4
  98. package/front_end/panels/security/security-meta.ts +0 -4
  99. package/front_end/panels/sensors/sensors-meta.ts +0 -1
  100. package/front_end/panels/settings/emulation/emulation-meta.ts +0 -1
  101. package/front_end/panels/settings/settings-meta.ts +0 -1
  102. package/front_end/panels/sources/BreakpointEditDialog.ts +16 -30
  103. package/front_end/panels/sources/CSSPlugin.ts +310 -331
  104. package/front_end/panels/sources/CallStackSidebarPane.ts +28 -34
  105. package/front_end/panels/sources/CoveragePlugin.ts +121 -6
  106. package/front_end/panels/sources/DebuggerPlugin.ts +1166 -1243
  107. package/front_end/panels/sources/EditingLocationHistoryManager.ts +71 -101
  108. package/front_end/panels/sources/GoToLineQuickOpen.ts +4 -3
  109. package/front_end/panels/sources/InplaceFormatterEditorAction.ts +3 -3
  110. package/front_end/panels/sources/JavaScriptCompilerPlugin.ts +26 -23
  111. package/front_end/panels/sources/Plugin.ts +20 -4
  112. package/front_end/panels/sources/ProfilePlugin.ts +185 -0
  113. package/front_end/panels/sources/ScriptFormatterEditorAction.ts +3 -3
  114. package/front_end/panels/sources/ScriptOriginPlugin.ts +0 -10
  115. package/front_end/panels/sources/SnippetsPlugin.ts +1 -10
  116. package/front_end/panels/sources/SourcesPanel.ts +6 -5
  117. package/front_end/panels/sources/SourcesView.ts +10 -8
  118. package/front_end/panels/sources/TabbedEditorContainer.ts +31 -27
  119. package/front_end/panels/sources/UISourceCodeFrame.ts +335 -470
  120. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +3 -2
  121. package/front_end/panels/sources/sources-legacy.ts +0 -6
  122. package/front_end/panels/sources/sources-meta.ts +2 -6
  123. package/front_end/panels/sources/sources.ts +0 -2
  124. package/front_end/panels/timeline/timeline-meta.ts +2 -9
  125. package/front_end/panels/web_audio/web_audio-meta.ts +0 -1
  126. package/front_end/panels/webauthn/webauthn-meta.ts +0 -1
  127. package/front_end/third_party/codemirror.next/bundle.ts +9 -13
  128. package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
  129. package/front_end/third_party/codemirror.next/chunk/javascript.js +2 -2
  130. package/front_end/third_party/codemirror.next/chunk/markdown.js +2 -6
  131. package/front_end/third_party/codemirror.next/chunk/php.js +2 -6
  132. package/front_end/third_party/codemirror.next/chunk/python.js +1 -1
  133. package/front_end/third_party/codemirror.next/chunk/wast.js +1 -1
  134. package/front_end/third_party/codemirror.next/chunk/xml.js +2 -2
  135. package/front_end/third_party/codemirror.next/codemirror.next.d.ts +279 -198
  136. package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
  137. package/front_end/third_party/codemirror.next/package.json +13 -11
  138. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1128 -1158
  139. package/front_end/third_party/lighthouse/locales/ar-XB.json +211 -79
  140. package/front_end/third_party/lighthouse/locales/ar.json +213 -81
  141. package/front_end/third_party/lighthouse/locales/bg.json +211 -79
  142. package/front_end/third_party/lighthouse/locales/ca.json +212 -80
  143. package/front_end/third_party/lighthouse/locales/cs.json +211 -79
  144. package/front_end/third_party/lighthouse/locales/da.json +211 -79
  145. package/front_end/third_party/lighthouse/locales/de.json +211 -79
  146. package/front_end/third_party/lighthouse/locales/el.json +213 -81
  147. package/front_end/third_party/lighthouse/locales/en-GB.json +211 -79
  148. package/front_end/third_party/lighthouse/locales/en-US.json +186 -75
  149. package/front_end/third_party/lighthouse/locales/en-XA.json +211 -79
  150. package/front_end/third_party/lighthouse/locales/en-XL.json +186 -75
  151. package/front_end/third_party/lighthouse/locales/es-419.json +211 -79
  152. package/front_end/third_party/lighthouse/locales/es.json +212 -80
  153. package/front_end/third_party/lighthouse/locales/fi.json +211 -79
  154. package/front_end/third_party/lighthouse/locales/fil.json +211 -79
  155. package/front_end/third_party/lighthouse/locales/fr.json +211 -79
  156. package/front_end/third_party/lighthouse/locales/he.json +212 -80
  157. package/front_end/third_party/lighthouse/locales/hi.json +214 -82
  158. package/front_end/third_party/lighthouse/locales/hr.json +211 -79
  159. package/front_end/third_party/lighthouse/locales/hu.json +211 -79
  160. package/front_end/third_party/lighthouse/locales/id.json +211 -79
  161. package/front_end/third_party/lighthouse/locales/it.json +211 -79
  162. package/front_end/third_party/lighthouse/locales/ja.json +211 -79
  163. package/front_end/third_party/lighthouse/locales/ko.json +211 -79
  164. package/front_end/third_party/lighthouse/locales/lt.json +211 -79
  165. package/front_end/third_party/lighthouse/locales/lv.json +214 -82
  166. package/front_end/third_party/lighthouse/locales/nl.json +211 -79
  167. package/front_end/third_party/lighthouse/locales/no.json +211 -79
  168. package/front_end/third_party/lighthouse/locales/pl.json +211 -79
  169. package/front_end/third_party/lighthouse/locales/pt-PT.json +211 -79
  170. package/front_end/third_party/lighthouse/locales/pt.json +211 -79
  171. package/front_end/third_party/lighthouse/locales/ro.json +212 -80
  172. package/front_end/third_party/lighthouse/locales/ru.json +211 -79
  173. package/front_end/third_party/lighthouse/locales/sk.json +211 -79
  174. package/front_end/third_party/lighthouse/locales/sl.json +211 -79
  175. package/front_end/third_party/lighthouse/locales/sr-Latn.json +211 -79
  176. package/front_end/third_party/lighthouse/locales/sr.json +211 -79
  177. package/front_end/third_party/lighthouse/locales/sv.json +211 -79
  178. package/front_end/third_party/lighthouse/locales/ta.json +218 -86
  179. package/front_end/third_party/lighthouse/locales/te.json +251 -119
  180. package/front_end/third_party/lighthouse/locales/th.json +211 -79
  181. package/front_end/third_party/lighthouse/locales/tr.json +211 -79
  182. package/front_end/third_party/lighthouse/locales/uk.json +212 -80
  183. package/front_end/third_party/lighthouse/locales/vi.json +211 -79
  184. package/front_end/third_party/lighthouse/locales/zh-HK.json +211 -79
  185. package/front_end/third_party/lighthouse/locales/zh-TW.json +211 -79
  186. package/front_end/third_party/lighthouse/locales/zh.json +211 -79
  187. package/front_end/third_party/lighthouse/report/bundle.d.ts +72 -34
  188. package/front_end/third_party/lighthouse/report/bundle.js +698 -492
  189. package/front_end/third_party/lighthouse/report-assets/report-generator.js +1 -2
  190. package/front_end/third_party/lighthouse/report-assets/report.js +40 -35
  191. package/front_end/third_party/lighthouse/report-assets/standalone-template.html +2 -4
  192. package/front_end/ui/components/code_highlighter/CodeHighlighter.ts +60 -68
  193. package/front_end/ui/components/data_grid/dataGrid.css +12 -10
  194. package/front_end/ui/components/docs/component_docs.ts +14 -0
  195. package/front_end/ui/components/docs/create_breadcrumbs.ts +1 -1
  196. package/front_end/ui/components/docs/css_overview/start_view.html +25 -0
  197. package/front_end/ui/components/docs/css_overview/start_view.ts +14 -0
  198. package/front_end/ui/components/docs/icon_button/basic.ts +3 -3
  199. package/front_end/ui/components/docs/toggle_dark_mode.ts +1 -0
  200. package/front_end/ui/components/docs/toggle_fonts.ts +2 -0
  201. package/front_end/ui/components/helpers/get-stylesheet.ts +0 -15
  202. package/front_end/ui/components/linear_memory_inspector/linear_memory_inspector-meta.ts +1 -2
  203. package/front_end/ui/components/markdown_view/MarkdownImagesMap.ts +1 -1
  204. package/front_end/ui/components/survey_link/SurveyLink.ts +1 -1
  205. package/front_end/ui/components/text_editor/TextEditor.ts +79 -36
  206. package/front_end/ui/components/text_editor/config.ts +42 -26
  207. package/front_end/ui/components/text_editor/javascript.ts +2 -3
  208. package/front_end/ui/components/text_editor/position.ts +17 -0
  209. package/front_end/ui/components/text_editor/text_editor.ts +1 -0
  210. package/front_end/ui/components/text_editor/theme.ts +5 -1
  211. package/front_end/ui/components/tree_outline/TreeOutline.ts +63 -8
  212. package/front_end/ui/components/tree_outline/TreeOutlineUtils.ts +8 -6
  213. package/front_end/ui/legacy/Dialog.ts +3 -1
  214. package/front_end/ui/legacy/DropTarget.ts +2 -1
  215. package/front_end/ui/legacy/EmptyWidget.ts +2 -1
  216. package/front_end/ui/legacy/FilterBar.ts +2 -1
  217. package/front_end/ui/legacy/GlassPane.ts +4 -2
  218. package/front_end/ui/legacy/Infobar.ts +5 -8
  219. package/front_end/ui/legacy/InspectorView.ts +6 -1
  220. package/front_end/ui/legacy/ListWidget.ts +2 -1
  221. package/front_end/ui/legacy/PopoverHelper.ts +2 -1
  222. package/front_end/ui/legacy/ProgressIndicator.ts +2 -1
  223. package/front_end/ui/legacy/RemoteDebuggingTerminatedScreen.ts +2 -1
  224. package/front_end/ui/legacy/ReportView.ts +2 -1
  225. package/front_end/ui/legacy/RootView.ts +2 -1
  226. package/front_end/ui/legacy/SearchableView.ts +2 -1
  227. package/front_end/ui/legacy/ShortcutRegistry.ts +11 -7
  228. package/front_end/ui/legacy/SoftContextMenu.ts +3 -2
  229. package/front_end/ui/legacy/SoftDropDown.ts +4 -2
  230. package/front_end/ui/legacy/SplitWidget.ts +2 -1
  231. package/front_end/ui/legacy/SuggestBox.ts +2 -1
  232. package/front_end/ui/legacy/TabbedPane.ts +2 -1
  233. package/front_end/ui/legacy/TargetCrashedScreen.ts +2 -1
  234. package/front_end/ui/legacy/TextPrompt.ts +2 -1
  235. package/front_end/ui/legacy/Toolbar.ts +3 -2
  236. package/front_end/ui/legacy/Treeoutline.ts +4 -3
  237. package/front_end/ui/legacy/UIUtils.ts +17 -14
  238. package/front_end/ui/legacy/ViewManager.ts +2 -1
  239. package/front_end/ui/legacy/components/inline_editor/CSSAngle.ts +1 -2
  240. package/front_end/ui/legacy/components/inline_editor/cssAngle.css +4 -0
  241. package/front_end/ui/legacy/components/object_ui/JavaScriptREPL.ts +2 -2
  242. package/front_end/ui/legacy/components/object_ui/object_ui-meta.ts +0 -4
  243. package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +35 -131
  244. package/front_end/ui/legacy/components/perf_ui/perf_ui-meta.ts +0 -3
  245. package/front_end/ui/legacy/components/quick_open/filteredListWidget.css +2 -2
  246. package/front_end/ui/legacy/components/quick_open/quick_open-meta.ts +2 -3
  247. package/front_end/ui/legacy/components/source_frame/BinaryResourceViewFactory.ts +3 -6
  248. package/front_end/ui/legacy/components/source_frame/FontView.ts +4 -1
  249. package/front_end/ui/legacy/components/source_frame/ImageView.ts +4 -1
  250. package/front_end/ui/legacy/components/source_frame/JSONView.ts +4 -1
  251. package/front_end/ui/legacy/components/source_frame/ResourceSourceFrame.ts +21 -15
  252. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +501 -252
  253. package/front_end/ui/legacy/components/source_frame/XMLView.ts +7 -2
  254. package/front_end/ui/legacy/components/source_frame/source_frame-legacy.ts +0 -11
  255. package/front_end/ui/legacy/components/source_frame/source_frame.ts +0 -2
  256. package/front_end/ui/legacy/components/text_editor/CodeMirrorTextEditor.ts +2 -0
  257. package/front_end/ui/legacy/components/text_editor/cmdevtools.css +3 -1
  258. package/front_end/ui/legacy/components/text_editor/module.json +0 -3
  259. package/front_end/ui/legacy/components/utils/Linkifier.ts +7 -15
  260. package/front_end/ui/legacy/radioButton.css +1 -13
  261. package/front_end/ui/legacy/textButton.css +5 -4
  262. package/front_end/ui/legacy/themeColors.css +36 -0
  263. package/front_end/ui/legacy/theme_support/theme_support_impl.ts +7 -9
  264. package/front_end/ui/legacy/utils/create-shadow-root-with-core-styles.ts +2 -2
  265. package/front_end/ui/legacy/utils/inject-core-styles.ts +7 -4
  266. package/package.json +1 -1
  267. package/scripts/check_gn.js +0 -35
  268. package/scripts/eslint_rules/lib/es_modules_import.js +15 -8
  269. package/scripts/eslint_rules/tests/es_modules_import_test.js +8 -0
  270. package/front_end/Images/radioDot-dark-theme.png +0 -0
  271. package/front_end/Images/radioDot.png +0 -0
  272. package/front_end/emulated_devices/module.json +0 -6
  273. package/front_end/panels/application/module.json +0 -6
  274. package/front_end/panels/emulation/module.json +0 -11
  275. package/front_end/panels/issues/module.json +0 -6
  276. package/front_end/panels/js_profiler/module.json +0 -5
  277. package/front_end/panels/layer_viewer/module.json +0 -5
  278. package/front_end/panels/layers/module.json +0 -5
  279. package/front_end/panels/media/module.json +0 -5
  280. package/front_end/panels/network/module.json +0 -5
  281. package/front_end/panels/profiler/module.json +0 -5
  282. package/front_end/panels/screencast/module.json +0 -6
  283. package/front_end/panels/security/module.json +0 -5
  284. package/front_end/panels/timeline/module.json +0 -7
  285. package/front_end/third_party/lighthouse/report-assets/report.css +0 -1774
  286. package/front_end/ui/legacy/components/source_frame/SourcesTextEditor.ts +0 -1030
  287. package/front_end/ui/legacy/components/source_frame/messagesPopover.css +0 -32
  288. package/front_end/ui/legacy/components/source_frame/module.json +0 -14
  289. package/front_end/ui/legacy/module.json +0 -41
@@ -33,23 +33,38 @@ import * as Platform from '../../core/platform/platform.js';
33
33
  import * as Root from '../../core/root/root.js';
34
34
  import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
35
35
  import * as Persistence from '../../models/persistence/persistence.js';
36
- import * as TextUtils from '../../models/text_utils/text_utils.js';
36
+ import type * as TextUtils from '../../models/text_utils/text_utils.js';
37
37
  import * as Workspace from '../../models/workspace/workspace.js';
38
+ import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
38
39
  import * as IconButton from '../../ui/components/icon_button/icon_button.js';
39
40
  import * as IssueCounter from '../../ui/components/issue_counter/issue_counter.js';
40
41
  import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
41
- import type * as TextEditor from '../../ui/legacy/components/text_editor/text_editor.js';
42
42
  import * as UI from '../../ui/legacy/legacy.js';
43
43
 
44
44
  import {CoveragePlugin} from './CoveragePlugin.js';
45
45
  import {CSSPlugin} from './CSSPlugin.js';
46
46
  import {DebuggerPlugin} from './DebuggerPlugin.js';
47
+ import {MemoryProfilePlugin, PerformanceProfilePlugin} from './ProfilePlugin.js';
47
48
  import {JavaScriptCompilerPlugin} from './JavaScriptCompilerPlugin.js';
48
49
  import type {Plugin} from './Plugin.js';
49
50
  import {ScriptOriginPlugin} from './ScriptOriginPlugin.js';
50
51
  import {SnippetsPlugin} from './SnippetsPlugin.js';
51
52
  import {SourcesPanel} from './SourcesPanel.js';
52
53
 
54
+ function sourceFramePlugins(): (typeof Plugin)[] {
55
+ // The order of these plugins matters for toolbar items
56
+ return [
57
+ CSSPlugin,
58
+ DebuggerPlugin,
59
+ JavaScriptCompilerPlugin,
60
+ SnippetsPlugin,
61
+ ScriptOriginPlugin,
62
+ CoveragePlugin,
63
+ MemoryProfilePlugin,
64
+ PerformanceProfilePlugin,
65
+ ];
66
+ }
67
+
53
68
  export class UISourceCodeFrame extends
54
69
  Common.ObjectWrapper.eventMixin<EventTypes, typeof SourceFrame.SourceFrame.SourceFrameImpl>(
55
70
  SourceFrame.SourceFrame.SourceFrameImpl) {
@@ -57,13 +72,12 @@ export class UISourceCodeFrame extends
57
72
  private muteSourceCodeEvents: boolean;
58
73
  private isSettingContent: boolean;
59
74
  private persistenceBinding: Persistence.Persistence.PersistenceBinding|null;
60
- private readonly rowMessageBuckets: Map<number, RowMessageBucket>;
61
- private readonly typeDecorationsPending: Set<string>;
62
75
  private uiSourceCodeEventListeners: Common.EventTarget.EventDescriptor[];
63
76
  private messageAndDecorationListeners: Common.EventTarget.EventDescriptor[];
64
77
  private readonly boundOnBindingChanged: () => void;
78
+ private plugins: Plugin[] = [];
79
+ private pluginsLoaded = false;
65
80
  private readonly errorPopoverHelper: UI.PopoverHelper.PopoverHelper;
66
- private plugins: Plugin[];
67
81
 
68
82
  constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode) {
69
83
  super(workingCopy);
@@ -74,31 +88,21 @@ export class UISourceCodeFrame extends
74
88
 
75
89
  this.persistenceBinding = Persistence.Persistence.PersistenceImpl.instance().binding(uiSourceCode);
76
90
 
77
- this.rowMessageBuckets = new Map();
78
- this.typeDecorationsPending = new Set();
79
-
80
91
  this.uiSourceCodeEventListeners = [];
81
92
  this.messageAndDecorationListeners = [];
82
93
 
83
94
  this.boundOnBindingChanged = this.onBindingChanged.bind(this);
84
95
 
85
- this.textEditor.addEventListener(
86
- SourceFrame.SourcesTextEditor.Events.EditorBlurred,
87
- () => UI.Context.Context.instance().setFlavor(UISourceCodeFrame, null));
88
- this.textEditor.addEventListener(
89
- SourceFrame.SourcesTextEditor.Events.EditorFocused,
90
- () => UI.Context.Context.instance().setFlavor(UISourceCodeFrame, this));
91
96
  Common.Settings.Settings.instance()
92
97
  .moduleSetting('persistenceNetworkOverridesEnabled')
93
98
  .addChangeListener(this.onNetworkPersistenceChanged, this);
94
99
 
95
- this.errorPopoverHelper = new UI.PopoverHelper.PopoverHelper(this.element, this.getErrorPopoverContent.bind(this));
100
+ this.errorPopoverHelper =
101
+ new UI.PopoverHelper.PopoverHelper(this.textEditor.editor.contentDOM, this.getErrorPopoverContent.bind(this));
96
102
  this.errorPopoverHelper.setHasPadding(true);
97
103
 
98
104
  this.errorPopoverHelper.setTimeout(100, 100);
99
105
 
100
- this.plugins = [];
101
-
102
106
  this.initializeUISourceCode();
103
107
 
104
108
  function workingCopy(): Promise<TextUtils.ContentProvider.DeferredContent> {
@@ -109,6 +113,24 @@ export class UISourceCodeFrame extends
109
113
  }
110
114
  }
111
115
 
116
+ protected editorConfiguration(doc: string): CodeMirror.Extension {
117
+ return [
118
+ super.editorConfiguration(doc),
119
+ rowMessages([...this.allMessages()]),
120
+ pluginCompartment.of(this.plugins.map(plugin => plugin.editorExtension())),
121
+ ];
122
+ }
123
+
124
+ protected onFocus(): void {
125
+ super.onFocus();
126
+ UI.Context.Context.instance().setFlavor(UISourceCodeFrame, this);
127
+ }
128
+
129
+ protected onBlur(): void {
130
+ super.onBlur();
131
+ UI.Context.Context.instance().setFlavor(UISourceCodeFrame, null);
132
+ }
133
+
112
134
  private installMessageAndDecorationListeners(): void {
113
135
  if (this.persistenceBinding) {
114
136
  const networkSourceCode = this.persistenceBinding.network;
@@ -117,9 +139,7 @@ export class UISourceCodeFrame extends
117
139
  networkSourceCode.addEventListener(Workspace.UISourceCode.Events.MessageAdded, this.onMessageAdded, this),
118
140
  networkSourceCode.addEventListener(Workspace.UISourceCode.Events.MessageRemoved, this.onMessageRemoved, this),
119
141
  networkSourceCode.addEventListener(
120
- Workspace.UISourceCode.Events.LineDecorationAdded, this.onLineDecorationAdded, this),
121
- networkSourceCode.addEventListener(
122
- Workspace.UISourceCode.Events.LineDecorationRemoved, this.onLineDecorationRemoved, this),
142
+ Workspace.UISourceCode.Events.DecorationChanged, this.onDecorationChanged, this),
123
143
 
124
144
  fileSystemSourceCode.addEventListener(Workspace.UISourceCode.Events.MessageAdded, this.onMessageAdded, this),
125
145
  fileSystemSourceCode.addEventListener(
@@ -132,9 +152,7 @@ export class UISourceCodeFrame extends
132
152
  this.uiSourceCodeInternal.addEventListener(
133
153
  Workspace.UISourceCode.Events.MessageRemoved, this.onMessageRemoved, this),
134
154
  this.uiSourceCodeInternal.addEventListener(
135
- Workspace.UISourceCode.Events.LineDecorationAdded, this.onLineDecorationAdded, this),
136
- this.uiSourceCodeInternal.addEventListener(
137
- Workspace.UISourceCode.Events.LineDecorationRemoved, this.onLineDecorationRemoved, this),
155
+ Workspace.UISourceCode.Events.DecorationChanged, this.onDecorationChanged, this),
138
156
  ];
139
157
  }
140
158
  }
@@ -147,7 +165,7 @@ export class UISourceCodeFrame extends
147
165
  this.unloadUISourceCode();
148
166
  this.uiSourceCodeInternal = uiSourceCode;
149
167
  if (uiSourceCode.contentLoaded()) {
150
- if (uiSourceCode.workingCopy() !== this.textEditor.text()) {
168
+ if (uiSourceCode.workingCopy() !== this.textEditor.state.doc.toString()) {
151
169
  this.innerSetContent(uiSourceCode.workingCopy());
152
170
  }
153
171
  } else {
@@ -155,7 +173,7 @@ export class UISourceCodeFrame extends
155
173
  if (this.uiSourceCodeInternal !== uiSourceCode) {
156
174
  return;
157
175
  }
158
- if (uiSourceCode.workingCopy() !== this.textEditor.text()) {
176
+ if (uiSourceCode.workingCopy() !== this.textEditor.state.doc.toString()) {
159
177
  this.innerSetContent(uiSourceCode.workingCopy());
160
178
  }
161
179
  });
@@ -165,9 +183,6 @@ export class UISourceCodeFrame extends
165
183
 
166
184
  private unloadUISourceCode(): void {
167
185
  this.disposePlugins();
168
- for (const message of this.allMessages()) {
169
- this.removeMessageFromSource(message);
170
- }
171
186
  Common.EventTarget.removeEventListeners(this.messageAndDecorationListeners);
172
187
  Common.EventTarget.removeEventListeners(this.uiSourceCodeEventListeners);
173
188
  this.uiSourceCodeInternal.removeWorkingCopyGetter();
@@ -181,30 +196,21 @@ export class UISourceCodeFrame extends
181
196
  Workspace.UISourceCode.Events.WorkingCopyChanged, this.onWorkingCopyChanged, this),
182
197
  this.uiSourceCodeInternal.addEventListener(
183
198
  Workspace.UISourceCode.Events.WorkingCopyCommitted, this.onWorkingCopyCommitted, this),
184
- this.uiSourceCodeInternal.addEventListener(
185
- Workspace.UISourceCode.Events.TitleChanged, this.refreshHighlighterType, this),
199
+ this.uiSourceCodeInternal.addEventListener(Workspace.UISourceCode.Events.TitleChanged, this.onTitleChanged, this),
186
200
  ];
187
201
 
188
202
  Persistence.Persistence.PersistenceImpl.instance().subscribeForBindingEvent(
189
203
  this.uiSourceCodeInternal, this.boundOnBindingChanged);
190
- for (const message of this.allMessages()) {
191
- this.addMessageToSource(message);
192
- }
193
204
  this.installMessageAndDecorationListeners();
194
205
  this.updateStyle();
195
- this.decorateAllTypes();
196
- this.refreshHighlighterType();
197
206
  if (Root.Runtime.experiments.isEnabled('sourcesPrettyPrint')) {
198
207
  const supportedPrettyTypes = new Set<string>(['text/html', 'text/css', 'text/javascript']);
199
- this.setCanPrettyPrint(supportedPrettyTypes.has(this.highlighterType()), true);
208
+ this.setCanPrettyPrint(supportedPrettyTypes.has(this.contentType), true);
200
209
  }
201
- this.ensurePluginsLoaded();
202
210
  }
203
211
 
204
212
  wasShown(): void {
205
213
  super.wasShown();
206
- // We need CodeMirrorTextEditor to be initialized prior to this call as it calls |cursorPositionToCoordinates| internally. @see crbug.com/506566
207
- window.setTimeout(() => this.updateBucketDecorations(), 0);
208
214
  this.setEditable(this.canEditSourceInternal());
209
215
  for (const plugin of this.plugins) {
210
216
  plugin.wasShown();
@@ -220,15 +226,9 @@ export class UISourceCodeFrame extends
220
226
  this.uiSourceCodeInternal.removeWorkingCopyGetter();
221
227
  }
222
228
 
223
- private refreshHighlighterType(): void {
229
+ protected getContentType(): string {
224
230
  const binding = Persistence.Persistence.PersistenceImpl.instance().binding(this.uiSourceCodeInternal);
225
- const highlighterType = binding ? binding.network.mimeType() : this.uiSourceCodeInternal.mimeType();
226
- if (this.highlighterType() === highlighterType) {
227
- return;
228
- }
229
- this.disposePlugins();
230
- this.setHighlighterType(highlighterType);
231
- this.ensurePluginsLoaded();
231
+ return binding ? binding.network.mimeType() : this.uiSourceCodeInternal.mimeType();
232
232
  }
233
233
 
234
234
  canEditSourceInternal(): boolean {
@@ -275,18 +275,20 @@ export class UISourceCodeFrame extends
275
275
  this.muteSourceCodeEvents = false;
276
276
  }
277
277
 
278
- setContent(content: string|null, loadError: string|null): void {
278
+ async setContent(content: string): Promise<void> {
279
279
  this.disposePlugins();
280
- this.rowMessageBuckets.clear();
281
- super.setContent(content, loadError);
282
- for (const message of this.allMessages()) {
283
- this.addMessageToSource(message);
284
- }
285
- this.decorateAllTypes();
286
280
  this.ensurePluginsLoaded();
281
+ await super.setContent(content);
287
282
  Common.EventTarget.fireEvent('source-file-loaded', this.uiSourceCodeInternal.displayName(true));
288
283
  }
289
284
 
285
+ protected editorInitialized(): void {
286
+ super.editorInitialized();
287
+ for (const plugin of this.plugins) {
288
+ plugin.editorInitialized(this.textEditor);
289
+ }
290
+ }
291
+
290
292
  private allMessages(): Set<Workspace.UISourceCode.Message> {
291
293
  if (this.persistenceBinding) {
292
294
  const combinedSet = this.persistenceBinding.network.messages();
@@ -296,9 +298,9 @@ export class UISourceCodeFrame extends
296
298
  return this.uiSourceCodeInternal.messages();
297
299
  }
298
300
 
299
- onTextChanged(oldRange: TextUtils.TextRange.TextRange, newRange: TextUtils.TextRange.TextRange): void {
301
+ onTextChanged(): void {
300
302
  const wasPretty = this.pretty;
301
- super.onTextChanged(oldRange, newRange);
303
+ super.onTextChanged();
302
304
  this.errorPopoverHelper.hidePopover();
303
305
  if (this.isSettingContent) {
304
306
  return;
@@ -308,13 +310,12 @@ export class UISourceCodeFrame extends
308
310
  if (this.isClean()) {
309
311
  this.uiSourceCodeInternal.resetWorkingCopy();
310
312
  } else {
311
- this.uiSourceCodeInternal.setWorkingCopyGetter(this.textEditor.text.bind(this.textEditor));
313
+ this.uiSourceCodeInternal.setWorkingCopyGetter(() => this.textEditor.state.doc.toString());
312
314
  }
313
315
  this.muteSourceCodeEvents = false;
314
316
  if (wasPretty !== this.pretty) {
315
317
  this.updateStyle();
316
- this.disposePlugins();
317
- this.ensurePluginsLoaded();
318
+ this.reloadPlugins();
318
319
  }
319
320
  }
320
321
 
@@ -333,32 +334,33 @@ export class UISourceCodeFrame extends
333
334
  this.updateStyle();
334
335
  }
335
336
 
337
+ private reloadPlugins(): void {
338
+ this.disposePlugins();
339
+ this.ensurePluginsLoaded();
340
+ const editor = this.textEditor;
341
+ editor.dispatch({effects: pluginCompartment.reconfigure(this.plugins.map(plugin => plugin.editorExtension()))});
342
+ for (const plugin of this.plugins) {
343
+ plugin.editorInitialized(editor);
344
+ }
345
+ }
346
+
347
+ private onTitleChanged(): void {
348
+ this.updateLanguageMode('').then(() => this.reloadPlugins(), console.error);
349
+ }
350
+
336
351
  private ensurePluginsLoaded(): void {
337
- if (!this.loaded || this.plugins.length) {
352
+ if (this.pluginsLoaded) {
338
353
  return;
339
354
  }
355
+ this.pluginsLoaded = true;
340
356
 
341
357
  const binding = Persistence.Persistence.PersistenceImpl.instance().binding(this.uiSourceCodeInternal);
342
358
  const pluginUISourceCode = binding ? binding.network : this.uiSourceCodeInternal;
343
359
 
344
- // The order of these plugins matters for toolbar items
345
- if (DebuggerPlugin.accepts(pluginUISourceCode)) {
346
- this.plugins.push(new DebuggerPlugin(this.textEditor, pluginUISourceCode, this));
347
- }
348
- if (CSSPlugin.accepts(pluginUISourceCode)) {
349
- this.plugins.push(new CSSPlugin(this.textEditor));
350
- }
351
- if (!this.pretty && JavaScriptCompilerPlugin.accepts(pluginUISourceCode)) {
352
- this.plugins.push(new JavaScriptCompilerPlugin(this.textEditor, pluginUISourceCode));
353
- }
354
- if (SnippetsPlugin.accepts(pluginUISourceCode)) {
355
- this.plugins.push(new SnippetsPlugin(this.textEditor, pluginUISourceCode));
356
- }
357
- if (ScriptOriginPlugin.accepts(pluginUISourceCode)) {
358
- this.plugins.push(new ScriptOriginPlugin(this.textEditor, pluginUISourceCode));
359
- }
360
- if (CoveragePlugin.accepts(pluginUISourceCode)) {
361
- this.plugins.push(new CoveragePlugin(this.textEditor, pluginUISourceCode));
360
+ for (const pluginType of sourceFramePlugins()) {
361
+ if (pluginType.accepts(pluginUISourceCode)) {
362
+ this.plugins.push(new pluginType(pluginUISourceCode, this));
363
+ }
362
364
  }
363
365
 
364
366
  this.dispatchEventToListeners(Events.ToolbarItemsChanged);
@@ -368,12 +370,11 @@ export class UISourceCodeFrame extends
368
370
  }
369
371
 
370
372
  private disposePlugins(): void {
371
- this.textEditor.operation(() => {
372
- for (const plugin of this.plugins) {
373
- plugin.dispose();
374
- }
375
- });
373
+ for (const plugin of this.plugins) {
374
+ plugin.dispose();
375
+ }
376
376
  this.plugins = [];
377
+ this.pluginsLoaded = false;
377
378
  }
378
379
 
379
380
  private onBindingChanged(): void {
@@ -392,30 +393,37 @@ export class UISourceCodeFrame extends
392
393
 
393
394
  private innerSetContent(content: string): void {
394
395
  this.isSettingContent = true;
395
- const oldContent = this.textEditor.text();
396
+ const oldContent = this.textEditor.state.doc.toString();
396
397
  if (oldContent !== content) {
397
- this.setContent(content, null);
398
+ this.setContent(content);
398
399
  }
399
400
  this.isSettingContent = false;
400
401
  }
401
402
 
402
- async populateTextAreaContextMenu(
403
- contextMenu: UI.ContextMenu.ContextMenu, editorLineNumber: number, editorColumnNumber: number): Promise<void> {
404
- await super.populateTextAreaContextMenu(contextMenu, editorLineNumber, editorColumnNumber);
403
+ protected populateTextAreaContextMenu(
404
+ contextMenu: UI.ContextMenu.ContextMenu, lineNumber: number, columnNumber: number): void {
405
+ super.populateTextAreaContextMenu(contextMenu, lineNumber, columnNumber);
405
406
  contextMenu.appendApplicableItems(this.uiSourceCodeInternal);
406
- const location = this.editorLocationToUILocation(editorLineNumber, editorColumnNumber);
407
+ const location = this.editorLocationToUILocation(lineNumber, columnNumber);
407
408
  contextMenu.appendApplicableItems(
408
409
  new Workspace.UISourceCode.UILocation(this.uiSourceCodeInternal, location.lineNumber, location.columnNumber));
409
410
  contextMenu.appendApplicableItems(this);
410
411
  for (const plugin of this.plugins) {
411
- await plugin.populateTextAreaContextMenu(contextMenu, editorLineNumber, editorColumnNumber);
412
+ plugin.populateTextAreaContextMenu(contextMenu, lineNumber, columnNumber);
413
+ }
414
+ }
415
+
416
+ protected populateLineGutterContextMenu(contextMenu: UI.ContextMenu.ContextMenu, lineNumber: number): void {
417
+ super.populateLineGutterContextMenu(contextMenu, lineNumber);
418
+ for (const plugin of this.plugins) {
419
+ plugin.populateLineGutterContextMenu(contextMenu, lineNumber);
412
420
  }
413
421
  }
414
422
 
415
423
  dispose(): void {
416
424
  this.errorPopoverHelper.dispose();
417
425
  this.unloadUISourceCode();
418
- this.textEditor.dispose();
426
+ this.textEditor.editor.destroy();
419
427
  this.detach();
420
428
  Common.Settings.Settings.instance()
421
429
  .moduleSetting('persistenceNetworkOverridesEnabled')
@@ -423,108 +431,22 @@ export class UISourceCodeFrame extends
423
431
  }
424
432
 
425
433
  private onMessageAdded(event: Common.EventTarget.EventTargetEvent<Workspace.UISourceCode.Message>): void {
426
- const message = event.data;
427
- this.addMessageToSource(message);
428
- }
429
-
430
- private getClampedEditorLineNumberForMessage(message: Workspace.UISourceCode.Message): number {
431
- let {lineNumber} = this.uiLocationToEditorLocation(message.lineNumber(), message.columnNumber());
432
- if (lineNumber >= this.textEditor.linesCount) {
433
- lineNumber = this.textEditor.linesCount - 1;
434
+ const {editor} = this.textEditor, shownMessages = editor.state.field(showRowMessages, false);
435
+ if (shownMessages) {
436
+ editor.dispatch({effects: setRowMessages.of(shownMessages.messages.add(event.data))});
434
437
  }
435
- if (lineNumber < 0) {
436
- lineNumber = 0;
437
- }
438
- return lineNumber;
439
- }
440
-
441
- private addMessageToSource(message: Workspace.UISourceCode.Message): void {
442
- if (!this.loaded) {
443
- return;
444
- }
445
-
446
- const editorLineNumber = this.getClampedEditorLineNumberForMessage(message);
447
- let messageBucket = this.rowMessageBuckets.get(editorLineNumber);
448
- if (!messageBucket) {
449
- messageBucket = new RowMessageBucket(this, this.textEditor, editorLineNumber);
450
- this.rowMessageBuckets.set(editorLineNumber, messageBucket);
451
- }
452
- messageBucket.addMessage(message);
453
438
  }
454
439
 
455
440
  private onMessageRemoved(event: Common.EventTarget.EventTargetEvent<Workspace.UISourceCode.Message>): void {
456
- const message = event.data;
457
- this.removeMessageFromSource(message);
458
- }
459
-
460
- private removeMessageFromSource(message: Workspace.UISourceCode.Message): void {
461
- if (!this.loaded) {
462
- return;
463
- }
464
-
465
- const editorLineNumber = this.getClampedEditorLineNumberForMessage(message);
466
- const messageBucket = this.rowMessageBuckets.get(editorLineNumber);
467
- if (!messageBucket) {
468
- return;
469
- }
470
- messageBucket.removeMessage(message);
471
- if (!messageBucket.uniqueMessagesCount()) {
472
- messageBucket.detachFromEditor();
473
- this.rowMessageBuckets.delete(editorLineNumber);
474
- }
475
- }
476
-
477
- private getErrorPopoverContent(event: Event): UI.PopoverHelper.PopoverRequest|null {
478
- const mouseEvent = (event as MouseEvent);
479
- const eventTarget = (mouseEvent.target as HTMLElement);
480
- return RowMessageBucket.getPopover(eventTarget, mouseEvent);
481
- }
482
-
483
- private updateBucketDecorations(): void {
484
- for (const bucket of this.rowMessageBuckets.values()) {
485
- bucket.updateDecoration();
486
- }
487
- }
488
-
489
- private onLineDecorationAdded(event: Common.EventTarget.EventTargetEvent<Workspace.UISourceCode.LineMarker>): void {
490
- const marker = event.data;
491
- this.decorateTypeThrottled(marker.type());
492
- }
493
-
494
- private onLineDecorationRemoved(event: Common.EventTarget.EventTargetEvent<Workspace.UISourceCode.LineMarker>): void {
495
- const marker = event.data;
496
- this.decorateTypeThrottled(marker.type());
497
- }
498
-
499
- private decorateTypeThrottled(type: string): void {
500
- if (this.typeDecorationsPending.has(type)) {
501
- return;
441
+ const {editor} = this.textEditor, shownMessages = editor.state.field(showRowMessages, false);
442
+ if (shownMessages) {
443
+ editor.dispatch({effects: setRowMessages.of(shownMessages.messages.remove(event.data))});
502
444
  }
503
- this.typeDecorationsPending.add(type);
504
- const extension =
505
- SourceFrame.SourceFrame.getRegisteredLineDecorators().find(extension => extension.decoratorType === type);
506
- const decorator = extension && extension.lineDecorator();
507
- if (!decorator) {
508
- return;
509
- }
510
- this.typeDecorationsPending.delete(type);
511
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
512
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
513
- (this.textEditor.codeMirror() as any).operation(() => {
514
- decorator.decorate(
515
- this.persistenceBinding ? this.persistenceBinding.network : this.uiSourceCode(), this.textEditor, type);
516
- });
517
445
  }
518
446
 
519
- private decorateAllTypes(): void {
520
- if (!this.loaded) {
521
- return;
522
- }
523
- for (const extension of SourceFrame.SourceFrame.getRegisteredLineDecorators()) {
524
- const type = extension.decoratorType;
525
- if (type !== null && this.uiSourceCodeInternal.decorationsForType(type)) {
526
- this.decorateTypeThrottled(type);
527
- }
447
+ private onDecorationChanged(event: Common.EventTarget.EventTargetEvent<string>): void {
448
+ for (const plugin of this.plugins) {
449
+ plugin.decorationChanged(event.data as SourceFrame.SourceFrame.DecoratorType, this.textEditor);
528
450
  }
529
451
  }
530
452
 
@@ -543,11 +465,56 @@ export class UISourceCodeFrame extends
543
465
  return [...leftToolbarItems, new UI.Toolbar.ToolbarSeparator(true), ...rightToolbarItems];
544
466
  }
545
467
 
546
- async populateLineGutterContextMenu(contextMenu: UI.ContextMenu.ContextMenu, lineNumber: number): Promise<void> {
547
- await super.populateLineGutterContextMenu(contextMenu, lineNumber);
548
- for (const plugin of this.plugins) {
549
- await plugin.populateLineGutterContextMenu(contextMenu, lineNumber);
468
+ private getErrorPopoverContent(event: Event): UI.PopoverHelper.PopoverRequest|null {
469
+ const mouseEvent = event as MouseEvent;
470
+ const eventTarget = event.target as HTMLElement;
471
+ const anchorElement = eventTarget.enclosingNodeOrSelfWithClass('cm-messageIcon-error') ||
472
+ eventTarget.enclosingNodeOrSelfWithClass('cm-messageIcon-issue');
473
+ if (!anchorElement) {
474
+ return null;
550
475
  }
476
+
477
+ const messageField = this.textEditor.state.field(showRowMessages, false);
478
+ if (!messageField || messageField.messages.rows.length === 0) {
479
+ return null;
480
+ }
481
+ const {editor} = this.textEditor;
482
+ const position = editor.posAtCoords(mouseEvent);
483
+ if (position === null) {
484
+ return null;
485
+ }
486
+ const line = editor.state.doc.lineAt(position);
487
+ if (position !== line.to) {
488
+ return null;
489
+ }
490
+ const row = messageField.messages.rows.find(row => row[0].lineNumber() === line.number - 1);
491
+ if (!row) {
492
+ return null;
493
+ }
494
+ const issues = anchorElement.classList.contains('cm-messageIcon-issue');
495
+ const messages = row.filter(msg => (msg.level() === Workspace.UISourceCode.Message.Level.Issue) === issues);
496
+ if (!messages.length) {
497
+ return null;
498
+ }
499
+ const anchor =
500
+ anchorElement ? anchorElement.boxInWindow() : new AnchorBox(mouseEvent.clientX, mouseEvent.clientY, 1, 1);
501
+
502
+ const counts = countDuplicates(messages);
503
+ const element = document.createElement('div');
504
+ element.classList.add('text-editor-messages-description-container');
505
+ for (let i = 0; i < messages.length; i++) {
506
+ if (counts[i]) {
507
+ element.appendChild(renderMessage(messages[i], counts[i]));
508
+ }
509
+ }
510
+ return {
511
+ box: anchor,
512
+ hide(): void{},
513
+ show: (popover: UI.GlassPane.GlassPane): Promise<true> => {
514
+ popover.contentElement.append(element);
515
+ return Promise.resolve(true);
516
+ },
517
+ };
551
518
  }
552
519
  }
553
520
 
@@ -575,15 +542,13 @@ function getBubbleTypePerLevel(level: Workspace.UISourceCode.Message.Level): str
575
542
  }
576
543
  }
577
544
 
578
- function getLineClassPerLevel(level: Workspace.UISourceCode.Message.Level): string {
579
- switch (level) {
580
- case Workspace.UISourceCode.Message.Level.Error:
581
- return 'text-editor-line-with-error';
582
- case Workspace.UISourceCode.Message.Level.Warning:
583
- return 'text-editor-line-with-warning';
584
- case Workspace.UISourceCode.Message.Level.Issue:
585
- return 'text-editor-line-with-warning';
586
- }
545
+ function messageLevelComparator(a: Workspace.UISourceCode.Message, b: Workspace.UISourceCode.Message): number {
546
+ const messageLevelPriority = {
547
+ [Workspace.UISourceCode.Message.Level.Issue]: 2,
548
+ [Workspace.UISourceCode.Message.Level.Warning]: 3,
549
+ [Workspace.UISourceCode.Message.Level.Error]: 4,
550
+ };
551
+ return messageLevelPriority[a.level()] - messageLevelPriority[b.level()];
587
552
  }
588
553
 
589
554
  function getIconDataForMessage(message: Workspace.UISourceCode.Message): IconButton.Icon.IconData {
@@ -597,318 +562,218 @@ function getIconDataForMessage(message: Workspace.UISourceCode.Message): IconBut
597
562
  return getIconDataForLevel(message.level());
598
563
  }
599
564
 
600
- export class RowMessage {
601
- private message: Workspace.UISourceCode.Message;
602
- private repeatCount: number;
603
- element: HTMLDivElement;
604
- private icon: IconButton.Icon.Icon;
605
- private repeatCountElement: UI.UIUtils.DevToolsSmallBubble;
565
+ // TODO(crbug.com/1167717): Make this a const enum again
566
+ // eslint-disable-next-line rulesdir/const_enum
567
+ export enum Events {
568
+ ToolbarItemsChanged = 'ToolbarItemsChanged',
569
+ }
570
+
571
+ export type EventTypes = {
572
+ [Events.ToolbarItemsChanged]: void,
573
+ };
606
574
 
607
- constructor(message: Workspace.UISourceCode.Message) {
608
- this.message = message;
609
- this.repeatCount = 1;
610
- this.element = document.createElement('div');
611
- this.element.classList.add('text-editor-row-message');
612
- this.icon = new IconButton.Icon.Icon();
613
- this.icon.data = getIconDataForMessage(message);
614
- this.icon.classList.add('text-editor-row-message-icon');
615
- this.icon.addEventListener('click', () => this.callClickHandler());
575
+ const pluginCompartment = new CodeMirror.Compartment();
616
576
 
617
- this.element.append(this.icon);
618
- this.repeatCountElement = document.createElement('span', {is: 'dt-small-bubble'}) as UI.UIUtils.DevToolsSmallBubble;
619
- this.repeatCountElement.classList.add('text-editor-row-message-repeat-count', 'hidden');
620
- this.element.appendChild(this.repeatCountElement);
621
- this.repeatCountElement.type = getBubbleTypePerLevel(message.level());
622
- const linesContainer = this.element.createChild('div');
623
- const lines = this.message.text().split('\n');
624
- for (let i = 0; i < lines.length; ++i) {
625
- const messageLine = linesContainer.createChild('div');
626
- messageLine.textContent = lines[i];
627
- }
628
- }
577
+ // Row message management and display logic
629
578
 
630
- getMessage(): Workspace.UISourceCode.Message {
631
- return this.message;
579
+ function addMessage(rows: Workspace.UISourceCode.Message[][], message: Workspace.UISourceCode.Message):
580
+ Workspace.UISourceCode.Message[][] {
581
+ const lineNumber = message.lineNumber();
582
+ let i = 0;
583
+ for (; i < rows.length; i++) {
584
+ const diff = rows[i][0].lineNumber() - lineNumber;
585
+ if (diff === 0) {
586
+ rows[i] = rows[i].concat(message);
587
+ return rows;
588
+ }
589
+ if (diff > 0) {
590
+ break;
591
+ }
632
592
  }
593
+ rows.splice(i, 0, [message]);
594
+ return rows;
595
+ }
633
596
 
634
- callClickHandler(): void {
635
- const handler = this.message.clickHandler();
636
- if (handler) {
637
- handler();
597
+ function removeMessage(rows: Workspace.UISourceCode.Message[][], message: Workspace.UISourceCode.Message): void {
598
+ for (let i = 0; i < rows.length; i++) {
599
+ if (rows[i][0].lineNumber() === message.lineNumber()) {
600
+ const remaining = rows[i].filter(m => !m.isEqual(message));
601
+ if (remaining.length) {
602
+ rows[i] = remaining;
603
+ } else {
604
+ rows.splice(i, 1);
605
+ }
606
+ break;
638
607
  }
639
608
  }
609
+ }
640
610
 
641
- getRepeatCount(): number {
642
- return this.repeatCount;
611
+ class RowMessages {
612
+ constructor(readonly rows: Workspace.UISourceCode.Message[][]) {
643
613
  }
644
614
 
645
- setRepeatCount(repeatCount: number): void {
646
- if (this.repeatCount === repeatCount) {
647
- return;
615
+ static create(messages: Workspace.UISourceCode.Message[]): RowMessages {
616
+ const rows: Workspace.UISourceCode.Message[][] = [];
617
+ for (const message of messages) {
618
+ addMessage(rows, message);
648
619
  }
649
- this.repeatCount = repeatCount;
650
- this.updateMessageRepeatCount();
620
+ return new RowMessages(rows);
621
+ }
622
+
623
+ remove(message: Workspace.UISourceCode.Message): RowMessages {
624
+ const rows = this.rows.slice();
625
+ removeMessage(rows, message);
626
+ return new RowMessages(rows);
651
627
  }
652
628
 
653
- private updateMessageRepeatCount(): void {
654
- this.repeatCountElement.textContent = String(this.repeatCount);
655
- const showRepeatCount = this.repeatCount > 1;
656
- this.repeatCountElement.classList.toggle('hidden', !showRepeatCount);
657
- this.icon.classList.toggle('hidden', showRepeatCount);
629
+ add(message: Workspace.UISourceCode.Message): RowMessages {
630
+ return new RowMessages(addMessage(this.rows.slice(), message));
658
631
  }
659
632
  }
660
633
 
661
- const elementToMessageBucket = new WeakMap<Element, RowMessageBucket>();
662
- const bookmarkTypeRowBucket = Symbol('bookmarkTypeRowBucket');
663
-
664
- export class RowMessageBucket {
665
- private sourceFrame: UISourceCodeFrame;
666
- private textEditor: SourceFrame.SourcesTextEditor.SourcesTextEditor;
667
- private readonly lineHandle: TextEditor.CodeMirrorTextEditor.TextEditorPositionHandle;
668
- private readonly decoration: HTMLDivElement;
669
- private readonly wave: HTMLElement;
670
- private errorIcon: IconButton.Icon.Icon;
671
- private issueIcon: IconButton.Icon.Icon;
672
- private decorationStartColumn: number|null;
673
- private readonly messagesDescriptionElement: HTMLDivElement;
674
- private messages: RowMessage[];
675
- private level: Workspace.UISourceCode.Message.Level|null;
676
- private bookmark?: TextEditor.CodeMirrorTextEditor.TextEditorBookMark;
677
- private iconsElement: HTMLSpanElement;
678
-
679
- constructor(
680
- sourceFrame: UISourceCodeFrame, textEditor: SourceFrame.SourcesTextEditor.SourcesTextEditor,
681
- editorLineNumber: number) {
682
- this.sourceFrame = sourceFrame;
683
- this.textEditor = textEditor;
684
- this.lineHandle = textEditor.textEditorPositionHandle(editorLineNumber, 0);
685
- this.decoration = document.createElement('div');
686
- this.decoration.classList.add('text-editor-line-decoration');
687
- elementToMessageBucket.set(this.decoration, this);
688
- this.wave = this.decoration.createChild('div', 'text-editor-line-decoration-wave');
689
-
690
- this.errorIcon = new IconButton.Icon.Icon();
691
- this.errorIcon.data = getIconDataForLevel(Workspace.UISourceCode.Message.Level.Warning);
692
- this.errorIcon.classList.add('text-editor-line-decoration-icon-error');
693
- this.issueIcon = new IconButton.Icon.Icon();
694
- this.issueIcon.data = getIconDataForLevel(Workspace.UISourceCode.Message.Level.Issue);
695
- this.issueIcon.classList.add('text-editor-line-decoration-icon-issue');
696
- this.issueIcon.addEventListener('click', () => this.issueClickHandler());
697
-
698
- this.iconsElement = document.createElement('span');
699
- this.iconsElement.append(this.errorIcon);
700
- this.iconsElement.append(this.issueIcon);
701
- this.iconsElement.classList.add('text-editor-line-decoration-icon');
702
- elementToMessageBucket.set(this.iconsElement, this);
703
-
704
- this.decorationStartColumn = null;
705
-
706
- this.messagesDescriptionElement = document.createElement('div');
707
- this.messagesDescriptionElement.classList.add('text-editor-messages-description-container');
708
- this.messages = [];
709
-
710
- this.level = null;
711
- }
712
-
713
- private updateWavePosition(editorLineNumber: number, columnNumber: number): void {
714
- editorLineNumber = Math.min(editorLineNumber, this.textEditor.linesCount - 1);
715
- const lineText = this.textEditor.line(editorLineNumber);
716
- columnNumber = Math.min(columnNumber, lineText.length);
717
- const lineIndent = TextUtils.TextUtils.Utils.lineIndent(lineText).length;
718
- const startColumn = Math.max(columnNumber, lineIndent);
719
- if (this.decorationStartColumn === startColumn) {
720
- return;
721
- }
722
- if (this.decorationStartColumn !== null) {
723
- this.textEditor.removeDecoration(this.decoration, editorLineNumber);
724
- }
725
- this.textEditor.addDecoration(this.decoration, editorLineNumber, startColumn);
726
- this.decorationStartColumn = startColumn;
634
+ const setRowMessages = CodeMirror.StateEffect.define<RowMessages>();
635
+
636
+ const underlineMark = CodeMirror.Decoration.mark({class: 'cm-waveUnderline'});
637
+
638
+ class MessageWidget extends CodeMirror.WidgetType {
639
+ constructor(readonly messages: Workspace.UISourceCode.Message[]) {
640
+ super();
727
641
  }
728
642
 
729
- private messageDescription(levels: Set<Workspace.UISourceCode.Message.Level>): Element {
730
- this.messagesDescriptionElement.removeChildren();
731
- UI.Utils.appendStyle(this.messagesDescriptionElement, 'ui/legacy/components/source_frame/messagesPopover.css');
732
- for (const message of this.messages.filter(m => levels.has(m.getMessage().level()))) {
733
- this.messagesDescriptionElement.append(message.element);
734
- }
735
- return this.messagesDescriptionElement;
643
+ eq(other: MessageWidget): boolean {
644
+ return other.messages === this.messages;
736
645
  }
737
646
 
738
- detachFromEditor(): void {
739
- const position = this.lineHandle.resolve();
740
- if (!position) {
741
- return;
742
- }
743
- const editorLineNumber = position.lineNumber;
744
- if (this.level) {
745
- this.textEditor.toggleLineClass(editorLineNumber, getLineClassPerLevel(this.level), false);
746
- }
747
- if (this.decorationStartColumn !== null) {
748
- this.textEditor.removeDecoration(this.decoration, editorLineNumber);
749
- this.decorationStartColumn = null;
647
+ toDOM(): HTMLElement {
648
+ const wrap = document.createElement('span');
649
+ wrap.classList.add('cm-messageIcon');
650
+ const nonIssues = this.messages.filter(msg => msg.level() !== Workspace.UISourceCode.Message.Level.Issue);
651
+ if (nonIssues.length) {
652
+ const maxIssue = nonIssues.sort(messageLevelComparator)[nonIssues.length - 1];
653
+ const errorIcon = wrap.appendChild(new IconButton.Icon.Icon());
654
+ errorIcon.data = getIconDataForLevel(maxIssue.level());
655
+ errorIcon.classList.add('cm-messageIcon-error');
750
656
  }
751
- if (this.bookmark) {
752
- this.bookmark.clear();
657
+ const issue = this.messages.find(m => m.level() === Workspace.UISourceCode.Message.Level.Issue);
658
+ if (issue) {
659
+ const issueIcon = wrap.appendChild(new IconButton.Icon.Icon());
660
+ issueIcon.data = getIconDataForLevel(Workspace.UISourceCode.Message.Level.Issue);
661
+ issueIcon.classList.add('cm-messageIcon-issue');
662
+ issueIcon.addEventListener('click', () => (issue.clickHandler() || Math.min)());
753
663
  }
664
+ return wrap;
754
665
  }
755
666
 
756
- uniqueMessagesCount(): number {
757
- return this.messages.length;
667
+ ignoreEvents(): boolean {
668
+ return true;
758
669
  }
670
+ }
759
671
 
760
- private issueClickHandler(): void {
761
- const firstIssue = this.messages.find(m => m.getMessage().level() === Workspace.UISourceCode.Message.Level.Issue);
762
- if (firstIssue) {
763
- firstIssue.callClickHandler();
764
- }
672
+ class RowMessageDecorations {
673
+ constructor(readonly messages: RowMessages, readonly decorations: CodeMirror.DecorationSet) {
765
674
  }
766
675
 
767
- addMessage(message: Workspace.UISourceCode.Message): void {
768
- for (let i = 0; i < this.messages.length; ++i) {
769
- const rowMessage = this.messages[i];
770
- if (rowMessage.getMessage().isEqual(message)) {
771
- rowMessage.setRepeatCount(rowMessage.getRepeatCount() + 1);
772
- return;
676
+ static create(messages: RowMessages, doc: CodeMirror.Text): RowMessageDecorations {
677
+ const builder = new CodeMirror.RangeSetBuilder<CodeMirror.Decoration>();
678
+ for (const row of messages.rows) {
679
+ const line = doc.line(row[0].lineNumber() + 1);
680
+ const minCol = row.reduce((col, msg) => Math.min(col, msg.columnNumber() || 0), line.length);
681
+ if (minCol < line.length) {
682
+ builder.add(line.from + minCol, line.to, underlineMark);
773
683
  }
684
+ builder.add(line.to, line.to, CodeMirror.Decoration.widget({side: 1, widget: new MessageWidget(row)}));
774
685
  }
775
-
776
- const rowMessage = new RowMessage(message);
777
- this.messages.push(rowMessage);
778
- this.updateDecoration();
686
+ return new RowMessageDecorations(messages, builder.finish());
779
687
  }
780
688
 
781
- removeMessage(message: Workspace.UISourceCode.Message): void {
782
- for (let i = 0; i < this.messages.length; ++i) {
783
- const rowMessage = this.messages[i];
784
- if (!rowMessage.getMessage().isEqual(message)) {
785
- continue;
786
- }
787
- rowMessage.setRepeatCount(rowMessage.getRepeatCount() - 1);
788
- if (!rowMessage.getRepeatCount()) {
789
- this.messages.splice(i, 1);
689
+ apply(tr: CodeMirror.Transaction): RowMessageDecorations {
690
+ let result: RowMessageDecorations = this;
691
+ if (tr.docChanged) {
692
+ result = new RowMessageDecorations(this.messages, this.decorations.map(tr.changes));
693
+ }
694
+ for (const effect of tr.effects) {
695
+ if (effect.is(setRowMessages)) {
696
+ result = RowMessageDecorations.create(effect.value, tr.state.doc);
790
697
  }
791
- this.updateDecoration();
792
- return;
793
698
  }
699
+ return result;
794
700
  }
701
+ }
795
702
 
796
- updateDecoration(): void {
797
- if (!this.sourceFrame.isShowing()) {
798
- return;
799
- }
800
- if (this.bookmark) {
801
- this.bookmark.clear();
802
- }
803
- if (!this.messages.length) {
804
- return;
805
- }
806
- const position = this.lineHandle.resolve();
807
- if (!position) {
808
- return;
809
- }
810
-
811
- const editorLineNumber = position.lineNumber;
812
- let columnNumber: number = Number.MAX_VALUE;
813
- let maxMessage: Workspace.UISourceCode.Message|null = null;
814
- let maxIssueKind = IssuesManager.Issue.IssueKind.Improvement;
815
- let showIssues = false;
816
- let showErrors = false;
817
- for (let i = 0; i < this.messages.length; ++i) {
818
- const message = this.messages[i].getMessage();
819
- const {columnNumber: editorColumnNumber} =
820
- this.sourceFrame.uiLocationToEditorLocation(editorLineNumber, message.columnNumber());
821
- columnNumber = Math.min(columnNumber, editorColumnNumber);
822
- if (!maxMessage || messageLevelComparator(maxMessage, message) < 0) {
823
- maxMessage = message;
824
- }
825
- if (message instanceof IssuesManager.SourceFrameIssuesManager.IssueMessage) {
826
- maxIssueKind = IssuesManager.Issue.unionIssueKind(maxIssueKind, message.getIssueKind());
703
+ const showRowMessages = CodeMirror.StateField.define<RowMessageDecorations>({
704
+ create(state): RowMessageDecorations {
705
+ return RowMessageDecorations.create(new RowMessages([]), state.doc);
706
+ },
707
+ update(value, tr): RowMessageDecorations {
708
+ return value.apply(tr);
709
+ },
710
+ provide: field => CodeMirror.Prec.lowest(CodeMirror.EditorView.decorations.from(field, value => value.decorations)),
711
+ });
712
+
713
+ function countDuplicates(messages: Workspace.UISourceCode.Message[]): number[] {
714
+ const counts = [];
715
+ for (let i = 0; i < messages.length; i++) {
716
+ counts[i] = 0;
717
+ for (let j = 0; j <= i; j++) {
718
+ if (messages[j].isEqual(messages[i])) {
719
+ counts[j]++;
720
+ break;
827
721
  }
828
- showIssues = showIssues || message.level() === Workspace.UISourceCode.Message.Level.Issue;
829
- showErrors = showErrors || message.level() !== Workspace.UISourceCode.Message.Level.Issue;
830
- }
831
- this.updateWavePosition(editorLineNumber, columnNumber);
832
-
833
- if (!maxMessage) {
834
- return;
835
- }
836
- if (this.level) {
837
- this.textEditor.toggleLineClass(editorLineNumber, getLineClassPerLevel(this.level), false);
838
- }
839
- this.level = maxMessage.level();
840
- if (!this.level) {
841
- return;
842
- }
843
- this.textEditor.toggleLineClass(editorLineNumber, getLineClassPerLevel(this.level), true);
844
- this.errorIcon.data = getIconDataForLevel(this.level);
845
- this.issueIcon
846
- .data = {...IssueCounter.IssueCounter.getIssueKindIconData(maxIssueKind), width: '12px', height: '12px'};
847
- this.issueIcon.classList.toggle('hidden', !showIssues);
848
- this.errorIcon.classList.toggle('hidden', !showErrors);
849
- if (showIssues || showErrors) {
850
- this.bookmark = this.textEditor.addBookmark(
851
- editorLineNumber, Number.MAX_SAFE_INTEGER, this.iconsElement, bookmarkTypeRowBucket);
852
- }
853
- }
854
-
855
- private getPopoverMessages(eventTarget: HTMLElement): Element|null {
856
- let messagesOutline: Element|null = null;
857
- if (eventTarget.classList.contains('text-editor-line-decoration-icon-error')) {
858
- messagesOutline = this.messageDescription(
859
- new Set([Workspace.UISourceCode.Message.Level.Error, Workspace.UISourceCode.Message.Level.Warning]));
860
- } else if (eventTarget.classList.contains('text-editor-line-decoration-icon-issue')) {
861
- messagesOutline = this.messageDescription(new Set([Workspace.UISourceCode.Message.Level.Issue]));
862
- } else if (
863
- eventTarget.classList.contains('text-editor-line-decoration-wave') &&
864
- !eventTarget.classList.contains('text-editor-line-decoration-icon')) {
865
- messagesOutline = this.messageDescription(
866
- new Set([Workspace.UISourceCode.Message.Level.Error, Workspace.UISourceCode.Message.Level.Warning]));
867
- }
868
- return messagesOutline;
869
- }
870
-
871
- static getPopover(eventTarget: HTMLElement, mouseEvent: MouseEvent): UI.PopoverHelper.PopoverRequest|null {
872
- const enclosingNode = eventTarget.enclosingNodeOrSelfWithClass('text-editor-line-decoration') ||
873
- eventTarget.enclosingNodeOrSelfWithClass('text-editor-line-decoration-icon');
874
- const messageBucket = elementToMessageBucket.get(enclosingNode);
875
- if (!messageBucket) {
876
- return null;
877
- }
878
- const anchorElement = eventTarget.enclosingNodeOrSelfWithClass('text-editor-line-decoration-icon-error') ||
879
- eventTarget.enclosingNodeOrSelfWithClass('text-editor-line-decoration-icon-issue');
880
- const anchor =
881
- anchorElement ? anchorElement.boxInWindow() : new AnchorBox(mouseEvent.clientX, mouseEvent.clientY, 1, 1);
882
- const messagesOutline = messageBucket.getPopoverMessages(eventTarget);
883
- if (!messagesOutline) {
884
- return null;
885
722
  }
886
- return {
887
- box: anchor,
888
- hide(): void{},
889
- show: (popover: UI.GlassPane.GlassPane): Promise<true> => {
890
- popover.contentElement.append(messagesOutline);
891
- return Promise.resolve(true);
892
- },
893
- };
894
723
  }
724
+ return counts;
895
725
  }
896
726
 
897
- function messageLevelComparator(a: Workspace.UISourceCode.Message, b: Workspace.UISourceCode.Message): number {
898
- const messageLevelPriority = {
899
- [Workspace.UISourceCode.Message.Level.Issue]: 2,
900
- [Workspace.UISourceCode.Message.Level.Warning]: 3,
901
- [Workspace.UISourceCode.Message.Level.Error]: 4,
902
- };
903
- return messageLevelPriority[a.level()] - messageLevelPriority[b.level()];
727
+ function renderMessage(message: Workspace.UISourceCode.Message, count: number): HTMLElement {
728
+ const element = document.createElement('div');
729
+ element.classList.add('text-editor-row-message');
730
+
731
+ if (count === 1) {
732
+ const icon = element.appendChild(new IconButton.Icon.Icon());
733
+ icon.data = getIconDataForMessage(message);
734
+ icon.classList.add('text-editor-row-message-icon');
735
+ icon.addEventListener('click', () => (message.clickHandler() || Math.min)());
736
+ } else {
737
+ const repeatCountElement =
738
+ document.createElement('span', {is: 'dt-small-bubble'}) as UI.UIUtils.DevToolsSmallBubble;
739
+ repeatCountElement.textContent = String(count);
740
+ repeatCountElement.classList.add('text-editor-row-message-repeat-count');
741
+ element.appendChild(repeatCountElement);
742
+ repeatCountElement.type = getBubbleTypePerLevel(message.level());
743
+ }
744
+ const linesContainer = element.createChild('div');
745
+ for (const line of message.text().split('\n')) {
746
+ linesContainer.createChild('div').textContent = line;
747
+ }
748
+
749
+ return element;
904
750
  }
905
751
 
906
- // TODO(crbug.com/1167717): Make this a const enum again
907
- // eslint-disable-next-line rulesdir/const_enum
908
- export enum Events {
909
- ToolbarItemsChanged = 'ToolbarItemsChanged',
752
+ const rowMessageTheme = CodeMirror.EditorView.baseTheme({
753
+ '.cm-tooltip-message': {
754
+ padding: '4px',
755
+ },
756
+
757
+ '.cm-waveUnderline': {
758
+ backgroundImage: 'var(--image-file-errorWave)',
759
+ backgroundRepeat: 'repeat-x',
760
+ backgroundPosition: 'bottom',
761
+ paddingBottom: '1px',
762
+ },
763
+
764
+ '.cm-messageIcon': {
765
+ cursor: 'pointer',
766
+ '& > *': {
767
+ verticalAlign: 'text-bottom',
768
+ marginLeft: '2px',
769
+ },
770
+ },
771
+ });
772
+
773
+ function rowMessages(initialMessages: Workspace.UISourceCode.Message[]): CodeMirror.Extension {
774
+ return [
775
+ showRowMessages.init(
776
+ (state): RowMessageDecorations => RowMessageDecorations.create(RowMessages.create(initialMessages), state.doc)),
777
+ rowMessageTheme,
778
+ ];
910
779
  }
911
-
912
- export type EventTypes = {
913
- [Events.ToolbarItemsChanged]: void,
914
- };