chrome-devtools-frontend 1.0.1544076 → 1.0.1547147

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 (178) hide show
  1. package/config/typescript/tsconfig.eslint.json +1 -0
  2. package/docs/styleguide/ux/styles.md +1 -1
  3. package/eslint.config.mjs +1 -1
  4. package/front_end/Images/src/arrow-down.svg +8 -1
  5. package/front_end/Images/src/arrow-up.svg +8 -1
  6. package/front_end/core/common/ParsedURL.ts +1 -1
  7. package/front_end/core/common/common.ts +0 -2
  8. package/front_end/core/host/AidaClient.ts +1 -1
  9. package/front_end/core/host/InspectorFrontendHostAPI.ts +0 -1
  10. package/front_end/core/host/UserMetrics.ts +0 -5
  11. package/front_end/core/platform/HostRuntime.ts +18 -0
  12. package/front_end/core/platform/KeyboardUtilities.ts +2 -2
  13. package/front_end/core/platform/StringUtilities.ts +1 -1
  14. package/front_end/core/platform/api/HostRuntime.ts +20 -0
  15. package/front_end/core/platform/api/api.ts +7 -0
  16. package/front_end/core/platform/browser/HostRuntime.ts +14 -0
  17. package/front_end/core/platform/browser/browser.ts +7 -0
  18. package/front_end/core/platform/node/HostRuntime.ts +13 -0
  19. package/front_end/core/platform/node/node.ts +7 -0
  20. package/front_end/core/platform/platform.ts +2 -2
  21. package/front_end/core/protocol_client/CDPConnection.ts +3 -3
  22. package/front_end/core/protocol_client/DevToolsCDPConnection.ts +2 -1
  23. package/front_end/core/sdk/CSSMetadata.ts +17 -5
  24. package/front_end/core/sdk/NetworkManager.ts +6 -8
  25. package/front_end/core/sdk/NetworkRequest.ts +4 -0
  26. package/front_end/core/sdk/SDKModel.ts +4 -2
  27. package/front_end/core/sdk/SourceMapScopesInfo.ts +141 -23
  28. package/front_end/core/sdk/Target.ts +5 -14
  29. package/front_end/core/sdk/TargetManager.ts +39 -18
  30. package/front_end/core/sdk/sdk-meta.ts +62 -0
  31. package/front_end/devtools_compatibility.js +0 -1
  32. package/front_end/entrypoints/main/MainImpl.ts +2 -2
  33. package/front_end/foundation/Universe.ts +2 -2
  34. package/front_end/generated/Deprecation.ts +11 -0
  35. package/front_end/generated/InspectorBackendCommands.ts +3 -6
  36. package/front_end/generated/SupportedCSSProperties.js +4 -25
  37. package/front_end/generated/protocol-mapping.d.ts +0 -15
  38. package/front_end/generated/protocol-proxy-api.d.ts +0 -11
  39. package/front_end/generated/protocol.ts +5 -36
  40. package/front_end/models/ai_assistance/AiConversation.ts +188 -0
  41. package/front_end/models/ai_assistance/AiHistoryStorage.ts +1 -172
  42. package/front_end/models/ai_assistance/ConversationHandler.ts +5 -5
  43. package/front_end/models/ai_assistance/agents/AiAgent.ts +1 -3
  44. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +6 -2
  45. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +1 -1
  46. package/front_end/models/ai_assistance/agents/StylingAgent.ts +3 -9
  47. package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
  48. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +313 -313
  49. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +8 -6
  50. package/front_end/models/ai_assistance/performance/AICallTree.snapshot.txt +33 -33
  51. package/front_end/models/ai_assistance/performance/AICallTree.ts +9 -3
  52. package/front_end/models/bindings/CSSWorkspaceBinding.ts +5 -3
  53. package/front_end/models/bindings/SASSSourceMapping.ts +6 -4
  54. package/front_end/models/cpu_profile/CPUProfileDataModel.ts +10 -7
  55. package/front_end/models/crux-manager/CrUXManager.ts +7 -4
  56. package/front_end/models/issues_manager/GenericIssue.ts +12 -9
  57. package/front_end/models/javascript_metadata/NativeFunctions.js +4 -0
  58. package/front_end/models/trace/handlers/SamplesHandler.ts +3 -0
  59. package/front_end/models/trace/helpers/Trace.ts +13 -0
  60. package/front_end/models/trace/types/TraceEvents.ts +2 -1
  61. package/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +29 -0
  62. package/front_end/models/workspace/IgnoreListManager.ts +1 -2
  63. package/front_end/models/workspace/UISourceCode.ts +50 -0
  64. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +11 -10
  65. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +8 -0
  66. package/front_end/panels/ai_assistance/components/ChatView.ts +2 -2
  67. package/front_end/panels/ai_assistance/components/UserActionRow.ts +2 -1
  68. package/front_end/panels/animation/AnimationTimeline.ts +0 -8
  69. package/front_end/panels/application/ApplicationPanelSidebar.ts +6 -7
  70. package/front_end/panels/application/{components/FrameDetailsView.ts → FrameDetailsView.ts} +140 -171
  71. package/front_end/panels/application/{components/OriginTrialTreeView.ts → OriginTrialTreeView.ts} +9 -9
  72. package/front_end/panels/application/application.ts +4 -0
  73. package/front_end/panels/application/components/StackTrace.ts +89 -88
  74. package/front_end/panels/application/components/components.ts +2 -4
  75. package/front_end/panels/application/{components/frameDetailsReportView.css → frameDetailsReportView.css} +5 -1
  76. package/front_end/panels/common/AiCodeGenerationTeaser.ts +80 -0
  77. package/front_end/panels/common/BadgeNotification.ts +2 -1
  78. package/front_end/panels/common/DOMLinkifier.ts +7 -2
  79. package/front_end/panels/common/GdpSignUpDialog.ts +2 -1
  80. package/front_end/panels/common/common.ts +2 -1
  81. package/front_end/panels/console/ConsolePrompt.ts +3 -1
  82. package/front_end/panels/console/ConsoleViewport.ts +1 -2
  83. package/front_end/panels/elements/ElementIssueUtils.ts +2 -2
  84. package/front_end/panels/elements/ElementStatePaneWidget.ts +2 -1
  85. package/front_end/panels/elements/StylePropertiesSection.ts +1 -1
  86. package/front_end/panels/elements/StylePropertyTreeElement.ts +23 -19
  87. package/front_end/panels/elements/StylesSidebarPane.ts +1 -1
  88. package/front_end/panels/elements/cssValueTraceView.css +1 -1
  89. package/front_end/panels/elements/elements-meta.ts +1 -22
  90. package/front_end/panels/explain/components/ConsoleInsight.ts +44 -57
  91. package/front_end/panels/explain/components/consoleInsight.css +46 -1
  92. package/front_end/panels/layer_viewer/LayerTreeOutline.ts +1 -2
  93. package/front_end/panels/lighthouse/LighthouseProtocolService.ts +3 -6
  94. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +19 -0
  95. package/front_end/panels/network/RequestConditionsDrawer.ts +54 -24
  96. package/front_end/panels/network/networkLogView.css +11 -0
  97. package/front_end/panels/network/networkTimingTable.css +8 -6
  98. package/front_end/panels/network/requestConditionsDrawer.css +10 -1
  99. package/front_end/panels/profiler/ProfilesPanel.ts +1 -2
  100. package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +2 -1
  101. package/front_end/panels/settings/KeybindsSettingsTab.ts +20 -21
  102. package/front_end/panels/settings/SettingsScreen.ts +3 -2
  103. package/front_end/panels/sources/CoveragePlugin.ts +5 -5
  104. package/front_end/panels/sources/Plugin.ts +1 -1
  105. package/front_end/panels/sources/ProfilePlugin.ts +22 -14
  106. package/front_end/panels/sources/UISourceCodeFrame.ts +2 -1
  107. package/front_end/panels/sources/sources-meta.ts +0 -62
  108. package/front_end/panels/timeline/README.md +1 -9
  109. package/front_end/panels/timeline/ThreadAppender.ts +0 -7
  110. package/front_end/panels/timeline/TimelinePanel.ts +1 -1
  111. package/front_end/panels/timeline/TimelineUIUtils.ts +2 -0
  112. package/front_end/panels/timeline/components/ExportTraceOptions.ts +15 -1
  113. package/front_end/panels/timeline/components/LiveMetricsView.ts +51 -6
  114. package/front_end/panels/timeline/components/MetricCard.ts +2 -2
  115. package/front_end/panels/timeline/components/exportTraceOptions.css +11 -2
  116. package/front_end/panels/timeline/components/insights/NodeLink.ts +2 -3
  117. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +2 -1
  118. package/front_end/panels/timeline/timeline-meta.ts +0 -10
  119. package/front_end/panels/timeline/timeline.ts +0 -2
  120. package/front_end/panels/whats_new/ReleaseNoteView.ts +2 -1
  121. package/front_end/panels/whats_new/WhatsNewImpl.ts +3 -2
  122. package/front_end/third_party/chromium/README.chromium +1 -1
  123. package/front_end/tsconfig.json +1 -0
  124. package/front_end/ui/components/buttons/Button.docs.ts +6 -5
  125. package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +1 -0
  126. package/front_end/ui/components/snackbars/Snackbars.docs.ts +1 -1
  127. package/front_end/ui/components/spinners/Spinners.docs.ts +1 -1
  128. package/front_end/ui/components/survey_link/SurveyLink.docs.ts +2 -1
  129. package/front_end/ui/components/switch/Switch.docs.ts +1 -1
  130. package/front_end/ui/components/tooltips/Tooltip.docs.ts +3 -3
  131. package/front_end/ui/helpers/OpenInNewTab.ts +87 -0
  132. package/front_end/ui/helpers/helpers.ts +5 -0
  133. package/front_end/ui/legacy/ARIAUtils.ts +2 -2
  134. package/front_end/ui/legacy/ActionRegistration.ts +11 -0
  135. package/front_end/ui/legacy/ContextMenu.docs.ts +12 -11
  136. package/front_end/ui/legacy/RadioButton.docs.ts +1 -1
  137. package/front_end/ui/legacy/SelectMenu.docs.ts +1 -1
  138. package/front_end/ui/legacy/Slider.docs.ts +1 -1
  139. package/front_end/ui/legacy/SoftDropDown.ts +2 -2
  140. package/front_end/ui/legacy/TextPrompt.ts +3 -2
  141. package/front_end/ui/legacy/Treeoutline.ts +2 -1
  142. package/front_end/ui/legacy/UIUtils.ts +11 -43
  143. package/front_end/ui/legacy/Widget.ts +3 -2
  144. package/front_end/ui/legacy/XLink.ts +4 -4
  145. package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +2 -1
  146. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +2 -2
  147. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +144 -143
  148. package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +62 -39
  149. package/front_end/ui/legacy/components/perf_ui/OverviewGrid.ts +1 -1
  150. package/front_end/ui/legacy/components/perf_ui/TimelineGrid.ts +2 -2
  151. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +2 -7
  152. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +1 -2
  153. package/front_end/ui/legacy/components/utils/Linkifier.ts +2 -1
  154. package/front_end/ui/legacy/inspectorCommon.css +2 -2
  155. package/front_end/ui/legacy/legacy.ts +2 -0
  156. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  157. package/mcp/tsconfig.json +16 -0
  158. package/package.json +2 -2
  159. package/front_end/core/common/Linkifier.ts +0 -55
  160. package/front_end/panels/explain/components/consoleInsightSourcesList.css +0 -51
  161. package/front_end/panels/timeline/CLSLinkifier.ts +0 -58
  162. package/front_end/ui/components/docs/README.md +0 -6
  163. package/front_end/ui/components/docs/building-ui-documentation/ComponentEvents.md +0 -54
  164. package/front_end/ui/components/docs/building-ui-documentation/ComponentPerformance.md +0 -136
  165. package/front_end/ui/components/docs/building-ui-documentation/CreatingComponents.md +0 -242
  166. package/front_end/ui/components/docs/building-ui-documentation/README.md +0 -23
  167. package/front_end/ui/components/docs/building-ui-documentation/StylingComponents.md +0 -66
  168. package/front_end/ui/components/docs/building-ui-documentation/TestingComponents.md +0 -111
  169. package/front_end/ui/components/docs/component_docs.ts +0 -24
  170. package/front_end/ui/components/docs/component_docs_styles.css +0 -53
  171. package/front_end/ui/components/docs/create_breadcrumbs.ts +0 -44
  172. package/front_end/ui/components/docs/slider/basic.html +0 -20
  173. package/front_end/ui/components/docs/switch/basic.html +0 -20
  174. /package/front_end/models/issues_manager/descriptions/{genericFormAriaLabelledByToNonExistingId.md → genericFormAriaLabelledByToNonExistingIdError.md} +0 -0
  175. /package/front_end/models/issues_manager/descriptions/{genericFormLabelHasNeitherForNorNestedInput.md → genericFormLabelHasNeitherForNorNestedInputError.md} +0 -0
  176. /package/front_end/panels/application/{components/originTrialTokenRows.css → originTrialTokenRows.css} +0 -0
  177. /package/front_end/panels/application/{components/originTrialTreeView.css → originTrialTreeView.css} +0 -0
  178. /package/front_end/{core/platform → ui/legacy}/DOMUtilities.ts +0 -0
@@ -271,30 +271,29 @@ export class KeybindsSettingsTab extends UI.Widget.VBox implements UI.ListContro
271
271
  }
272
272
 
273
273
  private createListItems(): KeybindsItem[] {
274
- const actions = UI.ActionRegistry.ActionRegistry.instance().actions().sort((actionA, actionB) => {
275
- if (actionA.category() < actionB.category()) {
276
- return -1;
277
- }
278
- if (actionA.category() > actionB.category()) {
279
- return 1;
280
- }
281
- if (actionA.id() < actionB.id()) {
282
- return -1;
283
- }
284
- if (actionA.id() > actionB.id()) {
285
- return 1;
286
- }
287
- return 0;
288
- });
274
+ const actions = UI.ActionRegistry.ActionRegistry.instance()
275
+ .actions()
276
+ .filter(action => action.configurableBindings())
277
+ .sort((actionA, actionB) => {
278
+ if (actionA.category() < actionB.category()) {
279
+ return -1;
280
+ }
281
+ if (actionA.category() > actionB.category()) {
282
+ return 1;
283
+ }
284
+ if (actionA.id() < actionB.id()) {
285
+ return -1;
286
+ }
287
+ if (actionA.id() > actionB.id()) {
288
+ return 1;
289
+ }
290
+ return 0;
291
+ });
289
292
 
290
293
  const items: KeybindsItem[] = [];
291
294
 
292
295
  let currentCategory: UI.ActionRegistration.ActionCategory;
293
296
  actions.forEach(action => {
294
- if (action.id() === 'elements.toggle-element-search') {
295
- return;
296
- }
297
-
298
297
  if (currentCategory !== action.category()) {
299
298
  items.push(action.category());
300
299
  }
@@ -305,7 +304,7 @@ export class KeybindsSettingsTab extends UI.Widget.VBox implements UI.ListContro
305
304
  }
306
305
 
307
306
  onEscapeKeyPressed(event: Event): void {
308
- const deepActiveElement = Platform.DOMUtilities.deepActiveElement(document);
307
+ const deepActiveElement = UI.DOMUtilities.deepActiveElement(document);
309
308
  if (this.editingRow && deepActiveElement && deepActiveElement.nodeName === 'INPUT') {
310
309
  this.editingRow.onEscapeKeyPressed(event);
311
310
  }
@@ -595,7 +594,7 @@ export class ShortcutListItem {
595
594
  }
596
595
 
597
596
  onEscapeKeyPressed(event: Event): void {
598
- const activeElement = Platform.DOMUtilities.deepActiveElement(document);
597
+ const activeElement = UI.DOMUtilities.deepActiveElement(document);
599
598
  for (const [shortcut, shortcutInput] of this.shortcutInputs.entries()) {
600
599
  if (activeElement === shortcutInput) {
601
600
  this.onShortcutInputKeyDown(shortcut, shortcutInput as HTMLInputElement, event);
@@ -14,6 +14,7 @@ import * as Root from '../../core/root/root.js';
14
14
  import * as Buttons from '../../ui/components/buttons/buttons.js';
15
15
  import type * as Cards from '../../ui/components/cards/cards.js';
16
16
  import * as IconButton from '../../ui/components/icon_button/icon_button.js';
17
+ import * as UIHelpers from '../../ui/helpers/helpers.js';
17
18
  import * as SettingsUI from '../../ui/legacy/components/settings_ui/settings_ui.js';
18
19
  import * as Components from '../../ui/legacy/components/utils/utils.js';
19
20
  import * as UI from '../../ui/legacy/legacy.js';
@@ -497,7 +498,7 @@ export class ExperimentsSettingsTab extends UI.Widget.VBox implements SettingsTa
497
498
  jslogContext: `${experiment.name}-documentation`,
498
499
  title: i18nString(UIStrings.learnMore),
499
500
  };
500
- linkButton.addEventListener('click', () => UI.UIUtils.openInNewTab(experimentLink));
501
+ linkButton.addEventListener('click', () => UIHelpers.openInNewTab(experimentLink));
501
502
  linkButton.classList.add('link-icon');
502
503
 
503
504
  p.appendChild(linkButton);
@@ -542,7 +543,7 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
542
543
  void SettingsScreen.showSettingsScreen({focusTabHeader: true} as ShowSettingsScreenOptions);
543
544
  return true;
544
545
  case 'settings.documentation':
545
- UI.UIUtils.openInNewTab('https://developer.chrome.com/docs/devtools/');
546
+ UIHelpers.openInNewTab('https://developer.chrome.com/docs/devtools/');
546
547
  return true;
547
548
  case 'settings.shortcuts':
548
549
  void SettingsScreen.showSettingsScreen({name: 'keybinds', focusTabHeader: true});
@@ -7,10 +7,10 @@ import * as i18n from '../../core/i18n/i18n.js';
7
7
  import type * as Platform from '../../core/platform/platform.js';
8
8
  import * as SDK from '../../core/sdk/sdk.js';
9
9
  import * as TextUtils from '../../models/text_utils/text_utils.js';
10
- import type * as Workspace from '../../models/workspace/workspace.js';
10
+ import * as Workspace from '../../models/workspace/workspace.js';
11
11
  import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
12
12
  import type * as TextEditor from '../../ui/components/text_editor/text_editor.js';
13
- import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
13
+ import type * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
14
14
  import * as UI from '../../ui/legacy/legacy.js';
15
15
  import * as Coverage from '../coverage/coverage.js';
16
16
 
@@ -123,7 +123,7 @@ export class CoveragePlugin extends Plugin {
123
123
  }
124
124
 
125
125
  private getCoverageManager(): Coverage.CoverageDecorationManager.CoverageDecorationManager|undefined {
126
- return this.uiSourceCode.getDecorationData(SourceFrame.SourceFrame.DecoratorType.COVERAGE);
126
+ return this.uiSourceCode.getDecorationData(Workspace.UISourceCode.DecoratorType.COVERAGE);
127
127
  }
128
128
 
129
129
  override editorInitialized(editor: TextEditor.TextEditor.TextEditor): void {
@@ -132,9 +132,9 @@ export class CoveragePlugin extends Plugin {
132
132
  }
133
133
  }
134
134
 
135
- override decorationChanged(type: SourceFrame.SourceFrame.DecoratorType, editor: TextEditor.TextEditor.TextEditor):
135
+ override decorationChanged(type: Workspace.UISourceCode.DecoratorType, editor: TextEditor.TextEditor.TextEditor):
136
136
  void {
137
- if (type === SourceFrame.SourceFrame.DecoratorType.COVERAGE) {
137
+ if (type === Workspace.UISourceCode.DecoratorType.COVERAGE) {
138
138
  this.startDecoUpdate(editor);
139
139
  }
140
140
  }
@@ -41,7 +41,7 @@ export class Plugin {
41
41
  void {
42
42
  }
43
43
 
44
- decorationChanged(_type: SourceFrame.SourceFrame.DecoratorType, _editor: TextEditor.TextEditor.TextEditor): void {
44
+ decorationChanged(_type: Workspace.UISourceCode.DecoratorType, _editor: TextEditor.TextEditor.TextEditor): void {
45
45
  }
46
46
 
47
47
  editorExtension(): CodeMirror.Extension {
@@ -5,10 +5,9 @@
5
5
 
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
7
  import * as Platform from '../../core/platform/platform.js';
8
- import type * as Workspace from '../../models/workspace/workspace.js';
8
+ import * as Workspace from '../../models/workspace/workspace.js';
9
9
  import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
10
10
  import type * as TextEditor from '../../ui/components/text_editor/text_editor.js';
11
- import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
12
11
 
13
12
  import {Plugin} from './Plugin.js';
14
13
 
@@ -90,22 +89,31 @@ class PerformanceMarker extends CodeMirror.GutterMarker {
90
89
  }
91
90
 
92
91
  function markersFromProfileData(
93
- map: Map<number, number>, state: CodeMirror.EditorState,
94
- type: SourceFrame.SourceFrame.DecoratorType): CodeMirror.RangeSet<CodeMirror.GutterMarker> {
95
- const markerType = type === SourceFrame.SourceFrame.DecoratorType.PERFORMANCE ? PerformanceMarker : MemoryMarker;
92
+ map: Map<number, number>|Map<number, Map<number, number>>, state: CodeMirror.EditorState,
93
+ type: Workspace.UISourceCode.DecoratorType): CodeMirror.RangeSet<CodeMirror.GutterMarker> {
94
+ const markerType = type === Workspace.UISourceCode.DecoratorType.PERFORMANCE ? PerformanceMarker : MemoryMarker;
96
95
  const markers: Array<CodeMirror.Range<CodeMirror.GutterMarker>> = [];
96
+ const aggregatedByLine = new Map<number, number>();
97
97
  for (const [line, value] of map) {
98
98
  if (line <= state.doc.lines) {
99
- const {from} = state.doc.line(line);
100
- markers.push(new markerType(value).range(from));
99
+ if (value instanceof Map) {
100
+ for (const [, data] of value) {
101
+ aggregatedByLine.set(line, (aggregatedByLine.get(line) || 0) + data);
102
+ }
103
+ continue;
104
+ }
105
+ aggregatedByLine.set(line, value);
101
106
  }
102
107
  }
108
+ for (const [line, value] of aggregatedByLine) {
109
+ const {from} = state.doc.line(line);
110
+ markers.push(new markerType(value).range(from));
111
+ }
103
112
  return CodeMirror.RangeSet.of(markers, true);
104
113
  }
105
114
 
106
- const makeLineLevelProfilePlugin = (type: SourceFrame.SourceFrame.DecoratorType): typeof Plugin =>
107
- class extends Plugin {
108
- updateEffect = CodeMirror.StateEffect.define<Map<number, number>>();
115
+ const makeLineLevelProfilePlugin = (type: Workspace.UISourceCode.DecoratorType): typeof Plugin => class extends Plugin {
116
+ updateEffect = CodeMirror.StateEffect.define<Map<number, number>|Map<number, Map<number, number>>>();
109
117
  field: CodeMirror.StateField<CodeMirror.RangeSet<CodeMirror.GutterMarker>>;
110
118
  gutter: CodeMirror.Extension;
111
119
  compartment: CodeMirror.Compartment = new CodeMirror.Compartment();
@@ -134,7 +142,7 @@ const makeLineLevelProfilePlugin = (type: SourceFrame.SourceFrame.DecoratorType)
134
142
  return uiSourceCode.contentType().hasScripts();
135
143
  }
136
144
 
137
- private getLineMap(): Map<number, number>|undefined {
145
+ private getLineMap(): Map<number, number>|Map<number, Map<number, number>>|undefined {
138
146
  return this.uiSourceCode.getDecorationData(type);
139
147
  }
140
148
 
@@ -144,7 +152,7 @@ const makeLineLevelProfilePlugin = (type: SourceFrame.SourceFrame.DecoratorType)
144
152
  !map ? [] : [this.field.init(state => markersFromProfileData(map, state, type)), this.gutter, theme]);
145
153
  }
146
154
 
147
- override decorationChanged(type: SourceFrame.SourceFrame.DecoratorType, editor: TextEditor.TextEditor.TextEditor):
155
+ override decorationChanged(type: Workspace.UISourceCode.DecoratorType, editor: TextEditor.TextEditor.TextEditor):
148
156
  void {
149
157
  const installed = Boolean(editor.state.field(this.field, false));
150
158
  const map = this.getLineMap();
@@ -189,6 +197,6 @@ const theme = CodeMirror.EditorView.baseTheme({
189
197
  },
190
198
  });
191
199
 
192
- export const MemoryProfilePlugin = makeLineLevelProfilePlugin(SourceFrame.SourceFrame.DecoratorType.MEMORY);
200
+ export const MemoryProfilePlugin = makeLineLevelProfilePlugin(Workspace.UISourceCode.DecoratorType.MEMORY);
193
201
 
194
- export const PerformanceProfilePlugin = makeLineLevelProfilePlugin(SourceFrame.SourceFrame.DecoratorType.PERFORMANCE);
202
+ export const PerformanceProfilePlugin = makeLineLevelProfilePlugin(Workspace.UISourceCode.DecoratorType.PERFORMANCE);
@@ -238,6 +238,7 @@ export class UISourceCodeFrame extends Common.ObjectWrapper
238
238
  }
239
239
 
240
240
  override async setContent(content: string): Promise<void> {
241
+ this.#uiSourceCode.formatChanged(this.formattedMap);
241
242
  this.disposePlugins();
242
243
  this.loadPlugins();
243
244
  await super.setContent(content);
@@ -423,7 +424,7 @@ export class UISourceCodeFrame extends Common.ObjectWrapper
423
424
 
424
425
  private onDecorationChanged(event: Common.EventTarget.EventTargetEvent<string>): void {
425
426
  for (const plugin of this.plugins) {
426
- plugin.decorationChanged(event.data as SourceFrame.SourceFrame.DecoratorType, this.textEditor);
427
+ plugin.decorationChanged(event.data as Workspace.UISourceCode.DecoratorType, this.textEditor);
427
428
  }
428
429
  }
429
430
 
@@ -232,18 +232,6 @@ const UIStrings = {
232
232
  * @description Title of a setting under the Sources category that can be invoked through the Command Menu
233
233
  */
234
234
  doNotAutomaticallyRevealFilesIn: 'Do not automatically reveal files in sidebar',
235
- /**
236
- * @description Setting under the Sources category to toggle usage of JavaScript source maps.
237
- */
238
- javaScriptSourceMaps: 'JavaScript source maps',
239
- /**
240
- * @description Title of a setting under the Sources category that can be invoked through the Command Menu
241
- */
242
- enableJavaScriptSourceMaps: 'Enable JavaScript source maps',
243
- /**
244
- * @description Title of a setting under the Sources category that can be invoked through the Command Menu
245
- */
246
- disableJavaScriptSourceMaps: 'Disable JavaScript source maps',
247
235
  /**
248
236
  * @description Title of a setting under the Sources category.
249
237
  *'tab moves focus' is the name of the setting, which means that when the user
@@ -373,18 +361,6 @@ const UIStrings = {
373
361
  * @description Title of a setting under the Sources category that can be invoked through the Command Menu
374
362
  */
375
363
  doNotDisplayVariableValuesInline: 'Do not display variable values inline while debugging',
376
- /**
377
- * @description Title of a setting under the Sources category
378
- */
379
- cssSourceMaps: 'CSS source maps',
380
- /**
381
- * @description Title of a setting under the Sources category that can be invoked through the Command Menu
382
- */
383
- enableCssSourceMaps: 'Enable CSS source maps',
384
- /**
385
- * @description Title of a setting under the Sources category that can be invoked through the Command Menu
386
- */
387
- disableCssSourceMaps: 'Disable CSS source maps',
388
364
  /**
389
365
  * @description Title of a setting under the Sources category in Settings
390
366
  */
@@ -1556,25 +1532,6 @@ Common.Settings.registerSettingExtension({
1556
1532
  ],
1557
1533
  });
1558
1534
 
1559
- Common.Settings.registerSettingExtension({
1560
- category: Common.Settings.SettingCategory.SOURCES,
1561
- storageType: Common.Settings.SettingStorageType.SYNCED,
1562
- title: i18nLazyString(UIStrings.javaScriptSourceMaps),
1563
- settingName: 'js-source-maps-enabled',
1564
- settingType: Common.Settings.SettingType.BOOLEAN,
1565
- defaultValue: true,
1566
- options: [
1567
- {
1568
- value: true,
1569
- title: i18nLazyString(UIStrings.enableJavaScriptSourceMaps),
1570
- },
1571
- {
1572
- value: false,
1573
- title: i18nLazyString(UIStrings.disableJavaScriptSourceMaps),
1574
- },
1575
- ],
1576
- });
1577
-
1578
1535
  Common.Settings.registerSettingExtension({
1579
1536
  category: Common.Settings.SettingCategory.SOURCES,
1580
1537
  storageType: Common.Settings.SettingStorageType.SYNCED,
@@ -1799,25 +1756,6 @@ Common.Settings.registerSettingExtension({
1799
1756
  ],
1800
1757
  });
1801
1758
 
1802
- Common.Settings.registerSettingExtension({
1803
- category: Common.Settings.SettingCategory.SOURCES,
1804
- storageType: Common.Settings.SettingStorageType.SYNCED,
1805
- title: i18nLazyString(UIStrings.cssSourceMaps),
1806
- settingName: 'css-source-maps-enabled',
1807
- settingType: Common.Settings.SettingType.BOOLEAN,
1808
- defaultValue: true,
1809
- options: [
1810
- {
1811
- value: true,
1812
- title: i18nLazyString(UIStrings.enableCssSourceMaps),
1813
- },
1814
- {
1815
- value: false,
1816
- title: i18nLazyString(UIStrings.disableCssSourceMaps),
1817
- },
1818
- ],
1819
- });
1820
-
1821
1759
  Common.Settings.registerSettingExtension({
1822
1760
  category: Common.Settings.SettingCategory.SOURCES,
1823
1761
  storageType: Common.Settings.SettingStorageType.SYNCED,
@@ -14,15 +14,7 @@ The first method is to run DevTools! Load up the Chrome for Testing version that
14
14
 
15
15
  DevTools, navigate to the Performance Panel and record or import a trace. There are a number of trace files saved in `devtools-frontend/test/unittests/fixtures/traces` that you can use.
16
16
 
17
- #### Option 2: the components server
18
-
19
- You can also use the DevTools component server. This server runs standalone parts of DevTools in the browser. To do this, run `npm run components-server` in the terminal, which will run a server on `localhost:8090`.
20
-
21
- You can then navigate to the Performance Panel examples using the link on the index page. This runs the real Performance Panel code in isolation, and you can additionally preload a trace by appending `?trace=name-of-trace-file-from-fixtures`. This is a nicer development cycle because you do not have to manually import a trace after each change. Note though that some parts of the experience are stubbed, so you always should test your work in proper DevTools too.
22
-
23
- These examples can also be used to create screenshot tests, which are an important tool for the Performance Panel because it is the only way to test `<canvas>` output. We define these as interaction tests (`devtools-frontend/tests/interactions/panels/performance`).
24
-
25
- #### Option 3: bundled DevTools in the browser
17
+ #### Option 2: bundled DevTools in the browser
26
18
 
27
19
  This option loads the DevTools frontend in a browser tab in Chrome, but requires a little more setup to easily load traces.
28
20
 
@@ -135,13 +135,6 @@ const UIStrings = {
135
135
  const str_ = i18n.i18n.registerUIStrings('panels/timeline/ThreadAppender.ts', UIStrings);
136
136
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
137
137
 
138
- /**
139
- * This appender is only triggered when the Renderer handler is run. At
140
- * the moment this only happens in the basic component server example.
141
- * In the future, once this appender fully supports the behaviour of the
142
- * old engine's thread/sync tracks we can always run it by enabling the
143
- * Renderer and Samples handler by default.
144
- **/
145
138
  export class ThreadAppender implements TrackAppender {
146
139
  readonly appenderName: TrackAppenderName = 'Thread';
147
140
 
@@ -946,7 +946,7 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
946
946
  }
947
947
 
948
948
  const agent = conversationHandler.createAgent(AiAssistanceModel.AiHistoryStorage.ConversationType.PERFORMANCE);
949
- const conversation = new AiAssistanceModel.AiHistoryStorage.Conversation(
949
+ const conversation = new AiAssistanceModel.AiConversation.AiConversation(
950
950
  AiAssistanceModel.AiHistoryStorage.ConversationType.PERFORMANCE,
951
951
  [],
952
952
  agent.id,
@@ -1646,6 +1646,8 @@ export class TimelineUIUtils {
1646
1646
  private static renderEventJson(event: Trace.Types.Events.Event, contentHelper: TimelineDetailsContentHelper): void {
1647
1647
  contentHelper.addSection(i18nString(UIStrings.traceEvent));
1648
1648
 
1649
+ contentHelper.appendElementRow('eventKey', new Trace.EventsSerializer.EventsSerializer().keyForEvent(event) ?? '?');
1650
+
1649
1651
  const eventWithArgsFirst = {
1650
1652
  ...{args: event.args},
1651
1653
  ...event,
@@ -14,6 +14,7 @@ import * as Dialogs from '../../../ui/components/dialogs/dialogs.js';
14
14
  import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
15
15
  import * as UI from '../../../ui/legacy/legacy.js';
16
16
  import * as Lit from '../../../ui/lit/lit.js';
17
+ import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
17
18
 
18
19
  import exportTraceOptionsStyles from './exportTraceOptions.css.js';
19
20
 
@@ -44,6 +45,10 @@ const UIStrings = {
44
45
  * @description Text for the compression option.
45
46
  */
46
47
  shouldCompress: 'Compress with gzip',
48
+ /**
49
+ * @description Text for the explanation link
50
+ */
51
+ explanation: 'Explanation',
47
52
  /**
48
53
  * @description Text for the save trace button
49
54
  */
@@ -292,7 +297,16 @@ export class ExportTraceOptions extends HTMLElement {
292
297
  'script-source-maps',
293
298
  this.#includeSourceMapsCheckbox, i18nString(UIStrings.includeSourcemap), this.#state.includeSourceMaps): ''}
294
299
  ${this.#renderCheckbox('compress-with-gzip', this.#shouldCompressCheckbox, i18nString(UIStrings.shouldCompress), this.#state.shouldCompress)}
295
- <div class='export-trace-options-row'><div class='export-trace-blank'></div><devtools-button
300
+ <div class='export-trace-options-row export-trace-options-row-last'>
301
+ <div class="export-trace-explanation">
302
+ <x-link
303
+ href="https://developer.chrome.com/docs/devtools/performance/save-trace"
304
+ class=devtools-link
305
+ jslog=${VisualLogging.link().track({click: true, keydown:'Enter|Space'}).context('save-trace-explanation')}>
306
+ ${i18nString(UIStrings.explanation)}
307
+ </x-link>
308
+ </div>
309
+ <devtools-button
296
310
  class="setup-button"
297
311
  data-export-button
298
312
  @click=${this.#onExportClick.bind(this)}
@@ -41,6 +41,7 @@ import metricValueStyles from './metricValueStyles.css.js';
41
41
  import {CLS_THRESHOLDS, INP_THRESHOLDS, renderMetricValue} from './Utils.js';
42
42
 
43
43
  const {html, nothing} = Lit;
44
+ const {widgetConfig} = UI.Widget;
44
45
 
45
46
  type DeviceOption = CrUXManager.DeviceScope|'AUTO';
46
47
 
@@ -57,6 +58,14 @@ const UIStrings = {
57
58
  * @description Title of a view that shows performance metrics from the local environment.
58
59
  */
59
60
  localMetrics: 'Local metrics',
61
+ /**
62
+ *@description Text for the link to the historical field data for the specific URL or origin that is shown. This link text appears in parenthesis after the collection period information in the field data dialog. The link opens the CrUX Vis viewer (https://cruxvis.withgoogle.com).
63
+ */
64
+ fieldDataHistoryLink: 'View history',
65
+ /**
66
+ *@description Tooltip for the CrUX Vis viewer link which shows the history of the field data for the specific URL or origin.
67
+ */
68
+ fieldDataHistoryTooltip: 'View field data history in CrUX Vis',
60
69
  /**
61
70
  * @description Accessible label for a section that logs user interactions and layout shifts. A layout shift is an event that shifts content in the layout of the page causing a jarring experience for the user.
62
71
  */
@@ -475,7 +484,10 @@ export class LiveMetricsView extends LegacyWrapper.LegacyWrapper.WrappableCompon
475
484
  ${nodeLink ? html`
476
485
  <div class="related-info" slot="extra-info">
477
486
  <span class="related-info-label">${i18nString(UIStrings.lcpElement)}</span>
478
- <span class="related-info-link">${nodeLink}</span>
487
+ <span class="related-info-link">
488
+ <devtools-widget .widgetConfig=${widgetConfig(PanelsCommon.DOMLinkifier.DOMNodeLink, {node: this.#lcpValue?.nodeRef})}>
489
+ </devtools-widget>
490
+ </span>
479
491
  </div>
480
492
  `
481
493
  : nothing}
@@ -638,7 +650,7 @@ export class LiveMetricsView extends LegacyWrapper.LegacyWrapper.WrappableCompon
638
650
  </ul>
639
651
  ` : nothing}
640
652
  <div class="environment-option">
641
- <devtools-widget .widgetConfig=${UI.Widget.widgetConfig(CPUThrottlingSelector, {recommendedOption: recs.cpuOption})}></devtools-widget>
653
+ <devtools-widget .widgetConfig=${widgetConfig(CPUThrottlingSelector, {recommendedOption: recs.cpuOption})}></devtools-widget>
642
654
  </div>
643
655
  <div class="environment-option">
644
656
  <devtools-network-throttling-selector .recommendedConditions=${recs.networkConditions}></devtools-network-throttling-selector>
@@ -836,6 +848,32 @@ export class LiveMetricsView extends LegacyWrapper.LegacyWrapper.WrappableCompon
836
848
  });
837
849
  }
838
850
 
851
+ #renderFieldDataHistoryLink(): Lit.LitTemplate {
852
+ if (!this.#cruxManager.getConfigSetting().get().enabled) {
853
+ return Lit.nothing;
854
+ }
855
+ const normalizedUrl = this.#cruxManager.pageResult?.normalizedUrl;
856
+ if (!normalizedUrl) {
857
+ return Lit.nothing;
858
+ }
859
+ const tmp = new URL('https://cruxvis.withgoogle.com/');
860
+ tmp.searchParams.set('view', 'cwvsummary');
861
+ tmp.searchParams.set('url', normalizedUrl);
862
+ // identifier must be 'origin' or 'url'.
863
+ const identifier = this.#cruxManager.fieldPageScope;
864
+ tmp.searchParams.set('identifier', identifier);
865
+ // device must be one 'PHONE', 'DESKTOP', 'TABLET', or 'ALL'.
866
+ const device = this.#cruxManager.getSelectedDeviceScope();
867
+ tmp.searchParams.set('device', device);
868
+ const cruxVis = `${tmp.origin}/#/${tmp.search}`;
869
+ return html`
870
+ (<x-link href=${cruxVis}
871
+ class="local-field-link"
872
+ title=${i18nString(UIStrings.fieldDataHistoryTooltip)}
873
+ >${i18nString(UIStrings.fieldDataHistoryLink)}</x-link>)
874
+ `;
875
+ }
876
+
839
877
  #renderCollectionPeriod(): Lit.LitTemplate {
840
878
  const range = this.#getCollectionPeriodRange();
841
879
 
@@ -847,11 +885,13 @@ export class LiveMetricsView extends LegacyWrapper.LegacyWrapper.WrappableCompon
847
885
  PH1: dateEl,
848
886
  });
849
887
 
888
+ const fieldDataHistoryLink = range ? this.#renderFieldDataHistoryLink() : Lit.nothing;
889
+
850
890
  const warnings = this.#cruxManager.pageResult?.warnings || [];
851
891
 
852
892
  return html`
853
893
  <div class="field-data-message">
854
- <div>${message}</div>
894
+ <div>${message} ${fieldDataHistoryLink}</div>
855
895
  ${warnings.map(warning => html`
856
896
  <div class="field-data-warning">${warning}</div>
857
897
  `)}
@@ -948,7 +988,6 @@ export class LiveMetricsView extends LegacyWrapper.LegacyWrapper.WrappableCompon
948
988
 
949
989
  const isP98Excluded = this.#inpValue && this.#inpValue.value < interaction.duration;
950
990
  const isInp = this.#inpValue?.interactionId === interaction.interactionId;
951
- const nodeLink = interaction.nodeRef ? PanelsCommon.DOMLinkifier.Linkifier.instance().linkify(interaction.nodeRef) : Lit.nothing;
952
991
 
953
992
  return html`
954
993
  <li id=${interaction.interactionId} class="log-item interaction" tabindex="-1">
@@ -959,7 +998,10 @@ export class LiveMetricsView extends LegacyWrapper.LegacyWrapper.WrappableCompon
959
998
  html`<span class="interaction-inp-chip" title=${i18nString(UIStrings.inpInteraction)}>INP</span>`
960
999
  : nothing}
961
1000
  </span>
962
- <span class="interaction-node">${nodeLink}</span>
1001
+ <span class="interaction-node">
1002
+ <devtools-widget .widgetConfig=${widgetConfig(PanelsCommon.DOMLinkifier.DOMNodeLink, {node: interaction.nodeRef})}>
1003
+ </devtools-widget>
1004
+ </span>
963
1005
  ${isP98Excluded ? html`<devtools-icon
964
1006
  class="interaction-info"
965
1007
  name="info"
@@ -1066,7 +1108,10 @@ export class LiveMetricsView extends LegacyWrapper.LegacyWrapper.WrappableCompon
1066
1108
  <div class="layout-shift-score">Layout shift score: ${metricValue}</div>
1067
1109
  <div class="layout-shift-nodes">
1068
1110
  ${layoutShift.affectedNodeRefs.map(node => html`
1069
- <div class="layout-shift-node">${PanelsCommon.DOMLinkifier.Linkifier.instance().linkify(node)}</div>
1111
+ <div class="layout-shift-node">
1112
+ <devtools-widget .widgetConfig=${widgetConfig(PanelsCommon.DOMLinkifier.DOMNodeLink, {node})}>
1113
+ </devtools-widget>
1114
+ </div>
1070
1115
  `)}
1071
1116
  </div>
1072
1117
  </li>
@@ -9,7 +9,7 @@ import * as CrUXManager from '../../../models/crux-manager/crux-manager.js';
9
9
  import type * as Trace from '../../../models/trace/trace.js';
10
10
  import * as Buttons from '../../../ui/components/buttons/buttons.js';
11
11
  import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
12
- import * as UI from '../../../ui/legacy/legacy.js';
12
+ import * as UIHelpers from '../../../ui/helpers/helpers.js';
13
13
  import * as Lit from '../../../ui/lit/lit.js';
14
14
 
15
15
  import metricCardStyles from './metricCard.css.js';
@@ -622,7 +622,7 @@ export class MetricCard extends HTMLElement {
622
622
  title=${this.#getHelpTooltip()}
623
623
  .iconName=${'help'}
624
624
  .variant=${Buttons.Button.Variant.ICON}
625
- @click=${() => UI.UIUtils.openInNewTab(helpLink)}
625
+ @click=${() => UIHelpers.openInNewTab(helpLink)}
626
626
  ></devtools-button>
627
627
  </h3>
628
628
  <div tabindex="0" class="metric-values-section"
@@ -19,13 +19,22 @@
19
19
  height: 24px;
20
20
  }
21
21
 
22
- .export-trace-blank {
22
+ .export-trace-explanation {
23
23
  flex: 1;
24
- min-width: var(--sys-size-25)
24
+ min-width: var(--sys-size-25);
25
25
  }
26
26
  }
27
27
 
28
+ .export-trace-options-row-last {
29
+ align-items: center;
30
+ }
31
+
28
32
  .info-tooltip-container {
29
33
  max-width: var(--sys-size-28);
30
34
  white-space: normal;
31
35
  }
36
+
37
+ x-link {
38
+ color: var(--sys-color-primary);
39
+ text-decoration-line: underline;
40
+ }
@@ -5,7 +5,6 @@
5
5
 
6
6
  // TODO: move to ui/components/node_link?
7
7
 
8
- import type * as Common from '../../../../core/common/common.js';
9
8
  import type * as Platform from '../../../../core/platform/platform.js';
10
9
  import * as SDK from '../../../../core/sdk/sdk.js';
11
10
  import type * as Protocol from '../../../../generated/protocol.js';
@@ -20,7 +19,7 @@ const {html} = Lit;
20
19
  export interface NodeLinkData {
21
20
  backendNodeId: Protocol.DOM.BackendNodeId;
22
21
  frame: string;
23
- options?: Common.Linkifier.Options;
22
+ options?: PanelsCommon.DOMLinkifier.Options;
24
23
  /**
25
24
  * URL to display if backendNodeId cannot be resolved (ie for traces loaded from disk).
26
25
  * Will be given to linkifyURL. Use this or one of the other fallback fields.
@@ -42,7 +41,7 @@ export class NodeLink extends HTMLElement {
42
41
  readonly #shadow = this.attachShadow({mode: 'open'});
43
42
  #backendNodeId?: Protocol.DOM.BackendNodeId;
44
43
  #frame?: string;
45
- #options?: Common.Linkifier.Options;
44
+ #options?: PanelsCommon.DOMLinkifier.Options;
46
45
  #fallbackUrl?: Platform.DevToolsPath.UrlString;
47
46
  #fallbackHtmlSnippet?: string;
48
47
  #fallbackText?: string;
@@ -15,6 +15,7 @@ import * as Root from '../../../../core/root/root.js';
15
15
  import * as AiAssistanceModels from '../../../../models/ai_assistance/ai_assistance.js';
16
16
  import * as Buttons from '../../../../ui/components/buttons/buttons.js';
17
17
  import * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';
18
+ import * as UIHelpers from '../../../../ui/helpers/helpers.js';
18
19
  import * as UI from '../../../../ui/legacy/legacy.js';
19
20
  import * as ThemeSupport from '../../../../ui/legacy/theme_support/theme_support.js';
20
21
  import * as Lit from '../../../../ui/lit/lit.js';
@@ -574,7 +575,7 @@ export class EntryLabelOverlay extends HTMLElement {
574
575
  },
575
576
  ],
576
577
  onLearnMoreClick: () => {
577
- UI.UIUtils.openInNewTab('https://developer.chrome.com/docs/devtools/performance/annotations#auto-annotations');
578
+ UIHelpers.openInNewTab('https://developer.chrome.com/docs/devtools/performance/annotations#auto-annotations');
578
579
  },
579
580
  learnMoreButtonText: UIStringsNotTranslate.learnMoreButton,
580
581
  });
@@ -323,16 +323,6 @@ Common.Settings.registerSettingExtension({
323
323
  defaultValue: false,
324
324
  });
325
325
 
326
- Common.Linkifier.registerLinkifier({
327
- contextTypes() {
328
- return maybeRetrieveContextTypes(Timeline => [Timeline.CLSLinkifier.CLSRect]);
329
- },
330
- async loadLinkifier() {
331
- const Timeline = await loadTimelineModule();
332
- return Timeline.CLSLinkifier.Linkifier.instance();
333
- },
334
- });
335
-
336
326
  UI.ContextMenu.registerItem({
337
327
  location: UI.ContextMenu.ItemLocation.TIMELINE_MENU_OPEN,
338
328
  actionId: 'timeline.load-from-file',