chrome-devtools-frontend 1.0.1545096 → 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 (124) hide show
  1. package/docs/styleguide/ux/styles.md +1 -1
  2. package/eslint.config.mjs +1 -1
  3. package/front_end/Images/src/arrow-down.svg +8 -1
  4. package/front_end/Images/src/arrow-up.svg +8 -1
  5. package/front_end/core/host/AidaClient.ts +1 -1
  6. package/front_end/core/host/InspectorFrontendHostAPI.ts +0 -1
  7. package/front_end/core/host/UserMetrics.ts +0 -5
  8. package/front_end/core/platform/HostRuntime.ts +18 -0
  9. package/front_end/core/platform/KeyboardUtilities.ts +2 -2
  10. package/front_end/core/platform/StringUtilities.ts +1 -1
  11. package/front_end/core/platform/api/HostRuntime.ts +20 -0
  12. package/front_end/core/platform/api/api.ts +7 -0
  13. package/front_end/core/platform/browser/HostRuntime.ts +14 -0
  14. package/front_end/core/platform/browser/browser.ts +7 -0
  15. package/front_end/core/platform/node/HostRuntime.ts +13 -0
  16. package/front_end/core/platform/node/node.ts +7 -0
  17. package/front_end/core/platform/platform.ts +2 -2
  18. package/front_end/core/sdk/SourceMapScopesInfo.ts +141 -23
  19. package/front_end/core/sdk/Target.ts +5 -14
  20. package/front_end/core/sdk/TargetManager.ts +26 -4
  21. package/front_end/core/sdk/sdk-meta.ts +62 -0
  22. package/front_end/devtools_compatibility.js +0 -1
  23. package/front_end/entrypoints/main/MainImpl.ts +2 -2
  24. package/front_end/foundation/Universe.ts +2 -2
  25. package/front_end/generated/Deprecation.ts +7 -0
  26. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  27. package/front_end/generated/SupportedCSSProperties.js +4 -2
  28. package/front_end/generated/protocol.ts +3 -2
  29. package/front_end/models/ai_assistance/AiConversation.ts +188 -0
  30. package/front_end/models/ai_assistance/AiHistoryStorage.ts +1 -172
  31. package/front_end/models/ai_assistance/ConversationHandler.ts +5 -5
  32. package/front_end/models/ai_assistance/agents/AiAgent.ts +1 -3
  33. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +6 -2
  34. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +1 -1
  35. package/front_end/models/ai_assistance/agents/StylingAgent.ts +3 -9
  36. package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
  37. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +313 -313
  38. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +8 -6
  39. package/front_end/models/ai_assistance/performance/AICallTree.snapshot.txt +33 -33
  40. package/front_end/models/ai_assistance/performance/AICallTree.ts +9 -3
  41. package/front_end/models/bindings/CSSWorkspaceBinding.ts +5 -3
  42. package/front_end/models/bindings/SASSSourceMapping.ts +6 -4
  43. package/front_end/models/cpu_profile/CPUProfileDataModel.ts +10 -7
  44. package/front_end/models/crux-manager/CrUXManager.ts +7 -4
  45. package/front_end/models/issues_manager/GenericIssue.ts +12 -9
  46. package/front_end/models/javascript_metadata/NativeFunctions.js +4 -0
  47. package/front_end/models/trace/handlers/SamplesHandler.ts +3 -0
  48. package/front_end/models/trace/helpers/Trace.ts +13 -0
  49. package/front_end/models/trace/types/TraceEvents.ts +2 -1
  50. package/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +29 -0
  51. package/front_end/models/workspace/IgnoreListManager.ts +1 -2
  52. package/front_end/models/workspace/UISourceCode.ts +50 -0
  53. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +9 -9
  54. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +8 -0
  55. package/front_end/panels/ai_assistance/components/ChatView.ts +2 -2
  56. package/front_end/panels/animation/AnimationTimeline.ts +0 -8
  57. package/front_end/panels/application/FrameDetailsView.ts +8 -8
  58. package/front_end/panels/application/components/StackTrace.ts +84 -85
  59. package/front_end/panels/common/AiCodeGenerationTeaser.ts +80 -0
  60. package/front_end/panels/common/common.ts +2 -1
  61. package/front_end/panels/console/ConsolePrompt.ts +3 -1
  62. package/front_end/panels/console/ConsoleViewport.ts +1 -2
  63. package/front_end/panels/elements/ElementIssueUtils.ts +2 -2
  64. package/front_end/panels/elements/StylePropertyTreeElement.ts +23 -19
  65. package/front_end/panels/elements/StylesSidebarPane.ts +1 -1
  66. package/front_end/panels/elements/cssValueTraceView.css +1 -1
  67. package/front_end/panels/elements/elements-meta.ts +1 -0
  68. package/front_end/panels/explain/components/ConsoleInsight.ts +44 -57
  69. package/front_end/panels/explain/components/consoleInsight.css +46 -1
  70. package/front_end/panels/layer_viewer/LayerTreeOutline.ts +1 -2
  71. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +19 -0
  72. package/front_end/panels/network/RequestConditionsDrawer.ts +54 -24
  73. package/front_end/panels/network/networkLogView.css +11 -0
  74. package/front_end/panels/network/networkTimingTable.css +8 -6
  75. package/front_end/panels/network/requestConditionsDrawer.css +10 -1
  76. package/front_end/panels/profiler/ProfilesPanel.ts +1 -2
  77. package/front_end/panels/settings/KeybindsSettingsTab.ts +20 -21
  78. package/front_end/panels/sources/CoveragePlugin.ts +5 -5
  79. package/front_end/panels/sources/Plugin.ts +1 -1
  80. package/front_end/panels/sources/ProfilePlugin.ts +22 -14
  81. package/front_end/panels/sources/UISourceCodeFrame.ts +2 -1
  82. package/front_end/panels/sources/sources-meta.ts +0 -62
  83. package/front_end/panels/timeline/README.md +1 -9
  84. package/front_end/panels/timeline/ThreadAppender.ts +0 -7
  85. package/front_end/panels/timeline/TimelinePanel.ts +1 -1
  86. package/front_end/panels/timeline/TimelineUIUtils.ts +2 -0
  87. package/front_end/panels/timeline/components/ExportTraceOptions.ts +15 -1
  88. package/front_end/panels/timeline/components/LiveMetricsView.ts +37 -1
  89. package/front_end/panels/timeline/components/exportTraceOptions.css +11 -2
  90. package/front_end/third_party/chromium/README.chromium +1 -1
  91. package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +1 -0
  92. package/front_end/ui/legacy/ARIAUtils.ts +2 -2
  93. package/front_end/ui/legacy/ActionRegistration.ts +11 -0
  94. package/front_end/ui/legacy/SoftDropDown.ts +2 -2
  95. package/front_end/ui/legacy/TextPrompt.ts +3 -2
  96. package/front_end/ui/legacy/Treeoutline.ts +2 -1
  97. package/front_end/ui/legacy/UIUtils.ts +11 -10
  98. package/front_end/ui/legacy/Widget.ts +3 -2
  99. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +2 -2
  100. package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +62 -39
  101. package/front_end/ui/legacy/components/perf_ui/OverviewGrid.ts +1 -1
  102. package/front_end/ui/legacy/components/perf_ui/TimelineGrid.ts +2 -2
  103. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +2 -7
  104. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +1 -2
  105. package/front_end/ui/legacy/inspectorCommon.css +2 -2
  106. package/front_end/ui/legacy/legacy.ts +2 -0
  107. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  108. package/package.json +1 -1
  109. package/front_end/panels/explain/components/consoleInsightSourcesList.css +0 -51
  110. package/front_end/ui/components/docs/README.md +0 -6
  111. package/front_end/ui/components/docs/building-ui-documentation/ComponentEvents.md +0 -54
  112. package/front_end/ui/components/docs/building-ui-documentation/ComponentPerformance.md +0 -136
  113. package/front_end/ui/components/docs/building-ui-documentation/CreatingComponents.md +0 -242
  114. package/front_end/ui/components/docs/building-ui-documentation/README.md +0 -23
  115. package/front_end/ui/components/docs/building-ui-documentation/StylingComponents.md +0 -66
  116. package/front_end/ui/components/docs/building-ui-documentation/TestingComponents.md +0 -111
  117. package/front_end/ui/components/docs/component_docs.ts +0 -24
  118. package/front_end/ui/components/docs/component_docs_styles.css +0 -53
  119. package/front_end/ui/components/docs/create_breadcrumbs.ts +0 -44
  120. package/front_end/ui/components/docs/slider/basic.html +0 -20
  121. package/front_end/ui/components/docs/switch/basic.html +0 -20
  122. /package/front_end/models/issues_manager/descriptions/{genericFormAriaLabelledByToNonExistingId.md → genericFormAriaLabelledByToNonExistingIdError.md} +0 -0
  123. /package/front_end/models/issues_manager/descriptions/{genericFormLabelHasNeitherForNorNestedInput.md → genericFormLabelHasNeitherForNorNestedInputError.md} +0 -0
  124. /package/front_end/{core/platform → ui/legacy}/DOMUtilities.ts +0 -0
@@ -368,7 +368,7 @@ export class DataGridImpl<T> extends Common.ObjectWrapper.ObjectWrapper<EventTyp
368
368
 
369
369
  announceSelectedGridNode(): void {
370
370
  // Only alert if the datagrid has focus
371
- if (this.element === Platform.DOMUtilities.deepActiveElement(this.element.ownerDocument) &&
371
+ if (this.element === UI.DOMUtilities.deepActiveElement(this.element.ownerDocument) &&
372
372
  this.selectedNode?.existingElement()) {
373
373
  // Update the expand/collapse state for the current selected node
374
374
  let expandText;
@@ -1237,7 +1237,7 @@ export class DataGridImpl<T> extends Common.ObjectWrapper.ObjectWrapper<EventTyp
1237
1237
  nextSelectedNode.select();
1238
1238
  }
1239
1239
 
1240
- const activeElement = (Platform.DOMUtilities.deepActiveElement(this.element.ownerDocument) as HTMLElement | null);
1240
+ const activeElement = (UI.DOMUtilities.deepActiveElement(this.element.ownerDocument) as HTMLElement | null);
1241
1241
  if (handled && this.element !== activeElement && !this.element.contains(activeElement)) {
1242
1242
  // crbug.com/1005449, crbug.com/1329956
1243
1243
  // navigational or delete keys pressed but current DataGrid panel has lost focus;
@@ -8,7 +8,6 @@ import type * as Protocol from '../../../../generated/protocol.js';
8
8
  import * as Bindings from '../../../../models/bindings/bindings.js';
9
9
  import type * as CPUProfile from '../../../../models/cpu_profile/cpu_profile.js';
10
10
  import * as Workspace from '../../../../models/workspace/workspace.js';
11
- import * as SourceFrame from '../source_frame/source_frame.js';
12
11
 
13
12
  let performanceInstance: Performance;
14
13
 
@@ -16,7 +15,7 @@ export class Performance {
16
15
  private readonly helper: Helper;
17
16
 
18
17
  private constructor() {
19
- this.helper = new Helper(SourceFrame.SourceFrame.DecoratorType.PERFORMANCE);
18
+ this.helper = new Helper(Workspace.UISourceCode.DecoratorType.PERFORMANCE);
20
19
  }
21
20
 
22
21
  static instance(opts: {
@@ -50,7 +49,8 @@ export class Performance {
50
49
  const lineInfo = node.positionTicks[j];
51
50
  const line = lineInfo.line;
52
51
  const time = lineInfo.ticks * sampleDuration;
53
- this.helper.addLineData(target, node.url, line, time);
52
+ // Since no column number is provided by legacy profile, default to 1 (beginning of line).
53
+ this.helper.addLocationData(target, node.url, {line, column: 1}, time);
54
54
  }
55
55
  }
56
56
  }
@@ -62,13 +62,14 @@ export class Performance {
62
62
  this.helper.scheduleUpdate();
63
63
  return;
64
64
  }
65
- if (!profile.samples) {
65
+ if (!profile.samples || !profile.columns) {
66
66
  return;
67
67
  }
68
68
 
69
69
  for (let i = 1; i < profile.samples.length; ++i) {
70
70
  const line = profile.lines[i];
71
- if (!line) {
71
+ const column = profile.columns?.[i];
72
+ if (!line || !column) {
72
73
  continue;
73
74
  }
74
75
  const node = profile.nodeByIndex(i);
@@ -80,7 +81,7 @@ export class Performance {
80
81
  continue;
81
82
  }
82
83
  const time = profile.timestamps[i] - profile.timestamps[i - 1];
83
- this.helper.addLineData(target, scriptIdOrUrl, line, time);
84
+ this.helper.addLocationData(target, scriptIdOrUrl, {line, column}, time);
84
85
  }
85
86
  this.helper.scheduleUpdate();
86
87
  }
@@ -91,7 +92,7 @@ let memoryInstance: Memory;
91
92
  export class Memory {
92
93
  private readonly helper: Helper;
93
94
  private constructor() {
94
- this.helper = new Helper(SourceFrame.SourceFrame.DecoratorType.MEMORY);
95
+ this.helper = new Helper(Workspace.UISourceCode.DecoratorType.MEMORY);
95
96
  }
96
97
 
97
98
  static instance(opts: {
@@ -124,43 +125,55 @@ export class Memory {
124
125
  return;
125
126
  }
126
127
  const line = node.callFrame.lineNumber + 1;
127
- helper.addLineData(target, script, line, node.selfSize);
128
+ // Since no column number is provided by the heap profile, default to 1 (beginning of line).
129
+ helper.addLocationData(target, script, {line, column: 1}, node.selfSize);
128
130
  }
129
131
  }
130
132
  }
131
133
 
132
134
  export class Helper {
133
- private readonly type: string;
135
+ private readonly type: Workspace.UISourceCode.DecoratorType;
134
136
  private readonly locationPool = new Bindings.LiveLocation.LiveLocationPool();
135
137
  private updateTimer: number|null = null;
136
- private lineData =
137
- new Map<SDK.Target.Target|null, Map<Platform.DevToolsPath.UrlString|number, Map<number, number>>>();
138
-
139
- constructor(type: string) {
138
+ /**
139
+ * Given a location in a script (with line and column numbers being 1-based) stores
140
+ * the time spent at that location in a performance profile.
141
+ */
142
+ private locationData =
143
+ new Map<SDK.Target.Target|null, Map<Platform.DevToolsPath.UrlString|number, Map<number, Map<number, number>>>>();
144
+ constructor(type: Workspace.UISourceCode.DecoratorType) {
140
145
  this.type = type;
141
146
  this.reset();
142
147
  }
143
148
 
144
149
  reset(): void {
145
150
  // The second map uses string keys for script URLs and numbers for scriptId.
146
- this.lineData = new Map();
151
+ this.locationData = new Map();
147
152
  this.scheduleUpdate();
148
153
  }
149
154
 
150
- addLineData(
151
- target: SDK.Target.Target|null, scriptIdOrUrl: Platform.DevToolsPath.UrlString|number, line: number,
152
- data: number): void {
153
- let targetData = this.lineData.get(target);
155
+ /**
156
+ * Stores the time taken running a given script location (line and column)
157
+ */
158
+ addLocationData(
159
+ target: SDK.Target.Target|null, scriptIdOrUrl: Platform.DevToolsPath.UrlString|number,
160
+ {line, column}: {line: number, column: number}, data: number): void {
161
+ let targetData = this.locationData.get(target);
154
162
  if (!targetData) {
155
163
  targetData = new Map();
156
- this.lineData.set(target, targetData);
164
+ this.locationData.set(target, targetData);
157
165
  }
158
166
  let scriptData = targetData.get(scriptIdOrUrl);
159
167
  if (!scriptData) {
160
168
  scriptData = new Map();
161
169
  targetData.set(scriptIdOrUrl, scriptData);
162
170
  }
163
- scriptData.set(line, (scriptData.get(line) || 0) + data);
171
+ let lineData = scriptData.get(line);
172
+ if (!lineData) {
173
+ lineData = new Map();
174
+ scriptData.set(line, lineData);
175
+ }
176
+ lineData.set(column, (lineData.get(column) || 0) + data);
164
177
  }
165
178
 
166
179
  scheduleUpdate(): void {
@@ -176,10 +189,9 @@ export class Helper {
176
189
  private async doUpdate(): Promise<void> {
177
190
  this.locationPool.disposeAll();
178
191
  // Map from sources to line->value profile maps.
179
- const decorationsBySource = new Map<Workspace.UISourceCode.UISourceCode, Map<number, number>>();
192
+ const decorationsBySource = new Map<Workspace.UISourceCode.UISourceCode, Map<number, Map<number, number>>>();
180
193
  const pending: Array<Promise<void>> = [];
181
-
182
- for (const [target, scriptToLineMap] of this.lineData) {
194
+ for (const [target, scriptToLineMap] of this.locationData) {
183
195
  const debuggerModel = target ? target.model(SDK.DebuggerModel.DebuggerModel) : null;
184
196
  for (const [scriptIdOrUrl, lineToDataMap] of scriptToLineMap) {
185
197
  // debuggerModel is null when the profile is loaded from file.
@@ -187,23 +199,34 @@ export class Helper {
187
199
  const workspace = Workspace.Workspace.WorkspaceImpl.instance();
188
200
  if (debuggerModel) {
189
201
  const workspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance();
190
- for (const lineToData of lineToDataMap) {
191
- const line = lineToData[0] - 1;
192
- const data = lineToData[1];
193
- const rawLocation = typeof scriptIdOrUrl === 'string' ?
194
- debuggerModel.createRawLocationByURL(scriptIdOrUrl, line, 0) :
195
- debuggerModel.createRawLocationByScriptId(String(scriptIdOrUrl) as Protocol.Runtime.ScriptId, line, 0);
196
- if (rawLocation) {
197
- pending.push(workspaceBinding.rawLocationToUILocation(rawLocation).then(uiLocation => {
198
- if (uiLocation) {
199
- let lineMap = decorationsBySource.get(uiLocation.uiSourceCode);
200
- if (!lineMap) {
201
- lineMap = new Map<number, number>();
202
- decorationsBySource.set(uiLocation.uiSourceCode, lineMap);
203
- }
204
- lineMap.set(uiLocation.lineNumber + 1, data);
202
+ for (const [lineNumber, lineData] of lineToDataMap) {
203
+ // lineData contains profiling data by column.
204
+ for (const [columnNumber, data] of lineData) {
205
+ const zeroBasedLine = lineNumber - 1;
206
+ const zeroBasedColumn = columnNumber - 1;
207
+ if (target) {
208
+ const rawLocation = typeof scriptIdOrUrl === 'string' ?
209
+ debuggerModel.createRawLocationByURL(scriptIdOrUrl, zeroBasedLine, zeroBasedColumn || 0) :
210
+ debuggerModel.createRawLocationByScriptId(
211
+ String(scriptIdOrUrl) as Protocol.Runtime.ScriptId, zeroBasedLine, zeroBasedColumn || 0);
212
+ if (rawLocation) {
213
+ pending.push(workspaceBinding.rawLocationToUILocation(rawLocation).then(uiLocation => {
214
+ if (uiLocation) {
215
+ let lineMap = decorationsBySource.get(uiLocation.uiSourceCode);
216
+ if (!lineMap) {
217
+ lineMap = new Map<number, Map<number, number>>();
218
+ decorationsBySource.set(uiLocation.uiSourceCode, lineMap);
219
+ }
220
+ let columnMap = lineMap.get(lineNumber);
221
+ if (!columnMap) {
222
+ columnMap = new Map<number, number>();
223
+ lineMap.set(lineNumber, columnMap);
224
+ }
225
+ columnMap.set((zeroBasedColumn || 0) + 1, data);
226
+ }
227
+ }));
205
228
  }
206
- }));
229
+ }
207
230
  }
208
231
  }
209
232
  } else if (typeof scriptIdOrUrl === 'string') {
@@ -176,7 +176,7 @@ export class Window extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
176
176
 
177
177
  this.parentElement.addEventListener('wheel', this.onMouseWheel.bind(this), true);
178
178
  this.parentElement.addEventListener('dblclick', this.resizeWindowMaximum.bind(this), true);
179
- Platform.DOMUtilities.appendStyle(this.parentElement, overviewGridStyles);
179
+ UI.DOMUtilities.appendStyle(this.parentElement, overviewGridStyles);
180
180
 
181
181
  this.leftResizeElement = parentElement.createChild('div', 'overview-grid-window-resizer');
182
182
  UI.UIUtils.installDragHandle(
@@ -33,8 +33,8 @@
33
33
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
34
  */
35
35
 
36
- import * as Platform from '../../../../core/platform/platform.js';
37
36
  import type * as NetworkTimeCalculator from '../../../../models/network_time_calculator/network_time_calculator.js';
37
+ import * as UI from '../../legacy.js';
38
38
  import * as ThemeSupport from '../../theme_support/theme_support.js';
39
39
 
40
40
  import {DEFAULT_FONT_SIZE, getFontFamilyForCanvas} from './Font.js';
@@ -51,7 +51,7 @@ export class TimelineGrid {
51
51
 
52
52
  constructor() {
53
53
  this.element = document.createElement('div');
54
- Platform.DOMUtilities.appendStyle(this.element, timelineGridStyles);
54
+ UI.DOMUtilities.appendStyle(this.element, timelineGridStyles);
55
55
 
56
56
  this.#dividersElement = this.element.createChild('div', 'resources-dividers');
57
57
 
@@ -121,7 +121,7 @@ export class SourceFrameImpl extends Common.ObjectWrapper.eventMixin<EventTypes,
121
121
  private readonly lazyContent: () => Promise<TextUtils.ContentData.ContentDataOrError>;
122
122
  private prettyInternal: boolean;
123
123
  private rawContent: string|CodeMirror.Text|null;
124
- private formattedMap: Formatter.ScriptFormatter.FormatterSourceMapping|null;
124
+ protected formattedMap: Formatter.ScriptFormatter.FormatterSourceMapping|null;
125
125
  private readonly prettyToggle: UI.Toolbar.ToolbarToggle;
126
126
  private shouldAutoPrettyPrint: boolean;
127
127
  private readonly progressToolbarItem: UI.Toolbar.ToolbarItem;
@@ -400,6 +400,7 @@ export class SourceFrameImpl extends Common.ObjectWrapper.eventMixin<EventTypes,
400
400
  newSelection = textEditor.createSelection(
401
401
  {lineNumber: start[0], columnNumber: start[1]}, {lineNumber: end[0], columnNumber: end[1]});
402
402
  } else {
403
+ this.formattedMap = null;
403
404
  await this.setContent(this.rawContent || '');
404
405
  this.baseDoc = textEditor.state.doc;
405
406
  const start = this.prettyToRawLocation(startPos.lineNumber, startPos.columnNumber);
@@ -1051,12 +1052,6 @@ export interface Transformer {
1051
1052
  };
1052
1053
  }
1053
1054
 
1054
- export const enum DecoratorType {
1055
- PERFORMANCE = 'performance',
1056
- MEMORY = 'memory',
1057
- COVERAGE = 'coverage',
1058
- }
1059
-
1060
1055
  const config = {
1061
1056
  editable: new CodeMirror.Compartment(),
1062
1057
  language: new CodeMirror.Compartment(),
@@ -36,7 +36,6 @@
36
36
 
37
37
  import * as Common from '../../../../core/common/common.js';
38
38
  import * as i18n from '../../../../core/i18n/i18n.js';
39
- import * as Platform from '../../../../core/platform/platform.js';
40
39
  import * as SDK from '../../../../core/sdk/sdk.js';
41
40
  import type * as Protocol from '../../../../generated/protocol.js';
42
41
  import * as StackTrace from '../../../../models/stack_trace/stack_trace.js';
@@ -325,7 +324,7 @@ export class StackTracePreviewContent extends UI.Widget.Widget {
325
324
  this.element.classList.toggle('width-constrained', this.#options.widthConstrained ?? false);
326
325
  this.element.style.display = 'inline-block';
327
326
 
328
- Platform.DOMUtilities.appendStyle(this.element.shadowRoot as ShadowRoot, jsUtilsStyles);
327
+ UI.DOMUtilities.appendStyle(this.element.shadowRoot as ShadowRoot, jsUtilsStyles);
329
328
 
330
329
  this.#table = this.contentElement.createChild('table', 'stack-preview-container');
331
330
  this.#table.classList.toggle('width-constrained', this.#options.widthConstrained ?? false);
@@ -141,7 +141,7 @@ iframe.widget {
141
141
  display: none !important; /* stylelint-disable-line declaration-no-important */
142
142
  }
143
143
 
144
- .highlighted-search-result,::highlight(highlighted-search-result) {
144
+ .highlighted-search-result,:host::highlight(highlighted-search-result) {
145
145
  border-radius: 1px;
146
146
  background-color: var(--sys-color-yellow-container);
147
147
  outline: 1px solid var(--sys-color-yellow-container);
@@ -326,7 +326,7 @@ input[type='range']:disabled::-webkit-slider-thumb {
326
326
  }
327
327
  }
328
328
 
329
- .highlighted-search-result.current-search-result,::highlight(current-search-result) {
329
+ .highlighted-search-result.current-search-result,:host::highlight(current-search-result) {
330
330
  /* Note: this value is used in light & dark mode */
331
331
  --override-current-search-result-background-color: rgb(255 127 0 / 80%);
332
332
 
@@ -10,6 +10,7 @@ import * as ContextFlavorListener from './ContextFlavorListener.js';
10
10
  import * as ContextMenu from './ContextMenu.js';
11
11
  import * as Dialog from './Dialog.js';
12
12
  import * as DockController from './DockController.js';
13
+ import * as DOMUtilities from './DOMUtilities.js';
13
14
  import * as DropTarget from './DropTarget.js';
14
15
  import * as EmptyWidget from './EmptyWidget.js';
15
16
  import * as FilterBar from './FilterBar.js';
@@ -61,6 +62,7 @@ export {
61
62
  ContextMenu,
62
63
  Dialog,
63
64
  DockController,
65
+ DOMUtilities,
64
66
  DropTarget,
65
67
  EmptyWidget,
66
68
  FilterBar,
@@ -3218,6 +3218,7 @@ export const knownContextValues = new Set([
3218
3218
  'save-image',
3219
3219
  'save-name',
3220
3220
  'save-player-info',
3221
+ 'save-trace-explanation',
3221
3222
  'scale',
3222
3223
  'scheme',
3223
3224
  'sci',
package/package.json CHANGED
@@ -103,5 +103,5 @@
103
103
  "flat-cache": "6.1.12"
104
104
  }
105
105
  },
106
- "version": "1.0.1545096"
106
+ "version": "1.0.1547147"
107
107
  }
@@ -1,51 +0,0 @@
1
- /*
2
- * Copyright 2023 The Chromium Authors
3
- * Use of this source code is governed by a BSD-style license that can be
4
- * found in the LICENSE file.
5
- */
6
-
7
- * {
8
- padding: 0;
9
- margin: 0;
10
- box-sizing: border-box;
11
- }
12
-
13
- :host {
14
- display: block;
15
- }
16
-
17
- ul {
18
- color: var(--sys-color-primary);
19
- font-size: 12px;
20
- font-style: normal;
21
- font-weight: 400;
22
- line-height: 18px;
23
- margin-top: 8px;
24
- padding-left: var(--sys-size-6);
25
- }
26
-
27
- li {
28
- list-style-type: none;
29
- }
30
-
31
- ul .link {
32
- color: var(--sys-color-primary);
33
- display: inline-flex !important; /* stylelint-disable-line declaration-no-important */
34
- align-items: center;
35
- gap: 4px;
36
- text-decoration-line: underline;
37
- }
38
-
39
- devtools-icon {
40
- height: 16px;
41
- width: 16px;
42
- margin-right: var(--sys-size-1);
43
- }
44
-
45
- devtools-icon[name="open-externally"] {
46
- color: var(--icon-link);
47
- }
48
-
49
- .source-disclaimer {
50
- color: var(--sys-color-on-surface-subtle);
51
- }
@@ -1,6 +0,0 @@
1
- # Component Docs
2
-
3
- This is the home of all the component server examples in the DevTools Frontend.
4
- For information on how to add your own and how to run the server, please see the
5
- [component server `README.md`](../../../../scripts/component_server/README.md).
6
-
@@ -1,54 +0,0 @@
1
- # Listening to and dispatching events
2
-
3
- Within your component it is likely that you will need to listen to user events, or dispatch custom events to enable other components to be notified of some event or user action.
4
-
5
- ## Listening to events
6
-
7
- To bind event listeners, we can use Lit-Html's event binding syntax in our template. Take the event you want to listen to, and prefix it with a `@`:
8
-
9
- ```ts
10
- LitHtml.render(LitHtml.html`
11
- <button @click=${this.#onButtonClick}>Click me!</button>
12
- `, this.#shadow, {host: this});
13
- ```
14
-
15
- Event listeners are defined as private class methods that will be called with an `Event`:
16
-
17
- ```ts
18
- #onButtonClick(event: Event): void {
19
- // ...
20
- }
21
- ```
22
-
23
- You do not need to worry about the event listener not being bound to the component's scope - Lit-Html takes care of this when we pass `{host: this}` into the `LitHtml.render` call. This tells Lit to bind event listeners on our behalf. In DevTools we have an ESLint rule which ensures that we use this option, so you cannot forget it!
24
-
25
- ## Dispatching events
26
-
27
- Sometimes you may need to dispatch an event from your component that another element higher in the DOM tree can listen to.
28
-
29
- The first step is to define the custom event. You do this by extending the built in `Event` class:
30
-
31
- ```ts
32
- export class AddBreakpointEvent extends Event {
33
- static readonly eventName = 'addbreakpoint';
34
-
35
- constructor(public index: number) {
36
- super(AddBreakpointEvent.eventName, {bubbles: true, composed: true});
37
- }
38
- }
39
- ```
40
-
41
- Custom events must have a `static readonly eventName` property (this is also enforced by an ESLint rule). We try to mimic the conventions of built in DOM events - event names should be lowercase and contain no spaces or dashes.
42
-
43
- They must also define a `constructor` which takes in any data that you want to be available on this event. This is how you can attach information to the events you dispatch for listeners to have access to. By declaring a `public node: DOMNode` above, we are declaring that this event must be initialised with a `node`, and that listeners will be able to access it via `event.node`.
44
-
45
- Within the constructor, we call `super` with our custom event name. We then pass two options in which are recommended (but not required if you know you do not need them):
46
-
47
- 1. `bubbles`: setting this to `true` means that when this event is emitted it will bubble up through the DOM tree. You usually want this because it is how built in browser events behave and it means that any listeners can be anywhere "above" the element that is dispatching the event and still be able to listen for it.
48
- 2. `composed`: this setting declares if the event will propogate through the shadow boundary and into the standard DOM. Setting this to `false` means that all event listeners must be within the shadow DOM to be able to listen to the event.
49
-
50
- MDN has some useful articles on these concepts if you want to learn more:
51
-
52
- 1. [Introduction to Events: Event bubbling](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling)
53
- 2. [Event: composed property](https://developer.mozilla.org/en-US/docs/Web/API/Event/composed)
54
- 3. [Using shadow DOM](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM)
@@ -1,136 +0,0 @@
1
- # Performance of Components
2
-
3
- Because we call the `#render()` method of a component frequently whenever any data changes, it is possible to create very inefficient component render calls that can lead to a poor experience for users.
4
-
5
- If the `#render()` method is expensive to run, and the component's data frequently changes, we will deliver a janky experience to users. This document lists some common causes of issues and ways to mitigate or avoid them. Most of these come from real world instances on DevTools; please feel free to add any that you come across!
6
-
7
- ## Manually creating component instances
8
-
9
- When you re-render a component, Lit is smart and does the minimal amount of work. For example, given a `#render()` method that looks like this:
10
-
11
- ```
12
- return html`<devtools-foo .name=${name}></devtools-foo>`
13
- ```
14
-
15
- Lit knows that the only dynamic part of that template is the `name` property, and as such on each re-render it only updates that part (and only if it has changed). It will not recreate `devtools-foo`.
16
-
17
- > You can read more about this in the [Lit templates documentation](https://lit.dev/docs/templates/overview/).
18
-
19
- However, if we change the `#render()` method to:
20
-
21
- ```
22
- const foo = new DevToolsFoo();
23
- foo.name = name;
24
- return html`${foo}`
25
- ```
26
-
27
- Now, we wil recreate `foo` on each re-render. This is not only wasted effort, but can mess with the user's experience if they had focused the node, only to have it destroyed and recreated.
28
-
29
- You should always let Lit manage instances of components. If you cannot do this, you should ensure some layer of caching to make sure instnaces are re-used whenver possible. However, **be careful!** It is very hard to implement a reliable cache for elements, and should be done only as a last resort.
30
-
31
- ## Integrating DevTools widgets & Lit and causing re-renders
32
-
33
- This issue is similar to the one above; often we can hit performance issues when using Lit to render a DevTools widget that we want to use. In a perfect world we would always re-build these widgets into Lit components, but that is often a huge undertaking and one that is not justifiable. The design of the widgets system is that they are only expected to be created once, and not re-evaluated. They expect to have their `update()` method called to trigger an update.
34
-
35
- In this instance, you will need to:
36
-
37
- 1. Manage the instance(s) of the widget, and ensure that we are not destroying and recreating the widget on each render.
38
- 2. Ensure the `update()` method of the widget is called when the relevant data changes (or on each `#render()` call).
39
-
40
- For example, this is likely to cause issues:
41
-
42
- ```ts
43
- // within #render()
44
- const someWidget = new SomeWidget();
45
- return html`<div>${someWidget.element}</div>`
46
- ```
47
-
48
- Because the widget will be created on each render. Instead, store the widget and `update()` it:
49
-
50
- ```ts
51
- // within the component
52
- #widgetInstance = new SomeWidget();
53
-
54
- // within #render()
55
- this.#widgetInstance.update();
56
- return html`<div>${this.#widgetInstance.element}</div>`;
57
- ```
58
-
59
- ## Swap from `set data` to individual properties
60
-
61
- When introducing lit-html into the DevTools codebase we made the decision to prefer:
62
-
63
- ```ts
64
- set data(data: FooData) {
65
- this.#x = data.x;
66
- this.#y = data.y;
67
- // And so on
68
- }
69
- ```
70
-
71
- Rather than:
72
-
73
- ```ts
74
- set x(x: number) {
75
- this.#x = x;
76
- }
77
-
78
- set y(y: number) {
79
- this.#y = y;
80
- }
81
- ```
82
-
83
- We did this to avoid having to immediately implement batched rendering.
84
-
85
- However, this decision came with a performance penalty. Lit will only trigger a re-render of a component if one of its properties changes. But when we pass in a new object on each render, we are effectively triggering a re-render every time. Normally this impact isn't noticable, and most components don't re-render with the frequency required to cause performance issues. When a component that takes an object via `set data()` is frequently re-rendered, that causes a non-negligible amount of garbage collection to tidy up the one-use objects we create.
86
-
87
- Therefore, if a component is re-rendered often and you are seeing issues, you can switch it to:
88
-
89
- ```
90
- <devtools-foo .x=${x} .y=${y}></devtools-foo>
91
- ```
92
-
93
- If you take this approach, ensure each property setter uses the render scheduler to batch updates. Otherwise we trigger N renders, one per property, rather than 1.
94
-
95
- ```ts
96
- set x(x: number) {
97
- this.#x = x;
98
- void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
99
- }
100
- ```
101
-
102
- ## Passing callback functions that are recreated on each render
103
-
104
- A general theme of performance in frontend is to avoid re-renders whenever possible. When a property passed into a component changes, that will trigger a re-render (as in our components we schedule renders in any setters). One pattern that can cause many re-renders is passing functions into components.
105
-
106
- For example, imagine this `#render()` method:
107
-
108
- ```ts
109
- const onClick = function(event: Event) {
110
- // do something
111
- }
112
-
113
- return html`<devtools-foo .onClick=${onClick}></devtools-foo>`
114
- ```
115
-
116
- And within `devtools-foo`, we have:
117
-
118
- ```
119
- set onClick(func: (event: Event) => void) {
120
- if (this.#onClick === func) {
121
- return;
122
- }
123
- this.#onClick = func;
124
- void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
125
- }
126
- ```
127
-
128
- On each `#render()` call, `onClick` is recreated, so it is considered to be a new function, and thus we trigger a re-render. We could fix this by making `onClick` stable, and not re-creating it on each render, but a better way is to lean into the browser and use events.
129
-
130
- In this example, we would update `devtools-foo` to dispatch an event when the user performs an action. We could then update our `#render()` method to:
131
-
132
- ```ts
133
- return html`<devtools-foo @click=${this.#onClick}></devtools-foo>`
134
- ```
135
-
136
- Lit will manage this event listener and ensure that it is not needlessly unbound and rebound. Now, we don't cause `devtools-foo` to re-render when really nothing is changing.