chrome-devtools-frontend 1.0.1568864 → 1.0.1569477

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 (35) hide show
  1. package/front_end/core/common/ParsedURL.ts +3 -0
  2. package/front_end/core/host/AidaClient.ts +1 -0
  3. package/front_end/core/root/Runtime.ts +4 -8
  4. package/front_end/entrypoints/main/MainImpl.ts +17 -20
  5. package/front_end/generated/SupportedCSSProperties.js +14 -14
  6. package/front_end/models/ai_assistance/agents/PatchAgent.ts +4 -1
  7. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +12 -0
  8. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +12 -2
  9. package/front_end/models/ai_assistance/agents/StylingAgent.ts +4 -1
  10. package/front_end/models/stack_trace/StackTraceImpl.ts +12 -2
  11. package/front_end/models/stack_trace/StackTraceModel.ts +9 -1
  12. package/front_end/models/trace/Styles.ts +11 -8
  13. package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +3 -2
  14. package/front_end/models/trace/types/TraceEvents.ts +19 -10
  15. package/front_end/panels/common/AiCodeGenerationTeaser.ts +1 -1
  16. package/front_end/panels/elements/ElementsPanel.ts +6 -3
  17. package/front_end/panels/elements/ElementsSidebarPane.ts +5 -2
  18. package/front_end/panels/elements/MetricsSidebarPane.ts +192 -177
  19. package/front_end/panels/elements/StylesSidebarPane.ts +1 -1
  20. package/front_end/panels/elements/metricsSidebarPane.css +3 -11
  21. package/front_end/panels/settings/SettingsScreen.ts +8 -38
  22. package/front_end/panels/settings/settingsScreen.css +0 -4
  23. package/front_end/panels/sources/BreakpointEditDialog.ts +203 -138
  24. package/front_end/panels/sources/DebuggerPlugin.ts +15 -7
  25. package/front_end/panels/timeline/TimelineUIUtils.ts +9 -3
  26. package/front_end/panels/timeline/TimingsTrackAppender.ts +1 -0
  27. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +3 -1
  28. package/front_end/panels/timeline/timelineFlameChartView.css +1 -0
  29. package/front_end/third_party/chromium/README.chromium +1 -1
  30. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +23 -1
  31. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +16 -4
  32. package/front_end/ui/kit/link/Link.ts +14 -8
  33. package/front_end/ui/kit/link/link.css +1 -1
  34. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
  35. package/package.json +1 -1
@@ -320,6 +320,9 @@ export class ParsedURL {
320
320
  }
321
321
 
322
322
  static extractName(url: string): string {
323
+ if (url.endsWith('/')) {
324
+ url = url.slice(0, -1);
325
+ }
323
326
  let index = url.lastIndexOf('/');
324
327
  const pathAndQuery = index !== -1 ? url.substr(index + 1) : url;
325
328
  index = pathAndQuery.indexOf('?');
@@ -79,6 +79,7 @@ export interface FunctionObjectParam<T extends string|number|symbol = string> ex
79
79
  type: ParametersTypes.OBJECT;
80
80
  // TODO: this can be also be ObjectParams
81
81
  properties: Record<T, FunctionPrimitiveParams|FunctionArrayParam>;
82
+ required: string[];
82
83
  }
83
84
 
84
85
  /**
@@ -167,15 +167,13 @@ export class ExperimentsSupport {
167
167
  return result;
168
168
  }
169
169
 
170
- register(
171
- experimentName: string, experimentTitle: string, unstable?: boolean, docLink?: string,
172
- feedbackLink?: string): void {
170
+ register(experimentName: string, experimentTitle: string, docLink?: string, feedbackLink?: string): void {
173
171
  if (this.#experimentNames.has(experimentName)) {
174
172
  throw new Error(`Duplicate registration of experiment '${experimentName}'`);
175
173
  }
176
174
  this.#experimentNames.add(experimentName);
177
175
  this.#experiments.push(new Experiment(
178
- this, experimentName, experimentTitle, Boolean(unstable),
176
+ this, experimentName, experimentTitle,
179
177
  docLink as Platform.DevToolsPath.UrlString ?? Platform.DevToolsPath.EmptyUrlString,
180
178
  feedbackLink as Platform.DevToolsPath.UrlString ?? Platform.DevToolsPath.EmptyUrlString));
181
179
  }
@@ -299,16 +297,14 @@ class ExperimentStorage {
299
297
  export class Experiment {
300
298
  name: string;
301
299
  title: string;
302
- unstable: boolean;
303
300
  docLink?: Platform.DevToolsPath.UrlString;
304
301
  readonly feedbackLink?: Platform.DevToolsPath.UrlString;
305
302
  readonly #experiments: ExperimentsSupport;
306
303
  constructor(
307
- experiments: ExperimentsSupport, name: string, title: string, unstable: boolean,
308
- docLink: Platform.DevToolsPath.UrlString, feedbackLink: Platform.DevToolsPath.UrlString) {
304
+ experiments: ExperimentsSupport, name: string, title: string, docLink: Platform.DevToolsPath.UrlString,
305
+ feedbackLink: Platform.DevToolsPath.UrlString) {
309
306
  this.name = name;
310
307
  this.title = title;
311
- this.unstable = unstable;
312
308
  this.docLink = docLink;
313
309
  this.feedbackLink = feedbackLink;
314
310
  this.#experiments = experiments;
@@ -325,57 +325,53 @@ export class MainImpl {
325
325
 
326
326
  #initializeExperiments(): void {
327
327
  Root.Runtime.experiments.register('capture-node-creation-stacks', 'Capture node creation stacks');
328
- Root.Runtime.experiments.register('live-heap-profile', 'Live heap profile', true);
328
+ Root.Runtime.experiments.register('live-heap-profile', 'Live heap profile');
329
329
  Root.Runtime.experiments.register(
330
- 'protocol-monitor', 'Protocol Monitor', undefined,
330
+ 'protocol-monitor', 'Protocol Monitor',
331
331
  'https://developer.chrome.com/blog/new-in-devtools-92/#protocol-monitor');
332
- Root.Runtime.experiments.register('sampling-heap-profiler-timeline', 'Sampling heap profiler timeline', true);
332
+ Root.Runtime.experiments.register('sampling-heap-profiler-timeline', 'Sampling heap profiler timeline');
333
333
  Root.Runtime.experiments.register(
334
334
  'show-option-tp-expose-internals-in-heap-snapshot', 'Show option to expose internals in heap snapshots');
335
335
 
336
336
  // Timeline
337
+ Root.Runtime.experiments.register('timeline-invalidation-tracking', 'Performance panel: invalidation tracking');
338
+ Root.Runtime.experiments.register('timeline-show-all-events', 'Performance panel: show all events');
339
+ Root.Runtime.experiments.register('timeline-v8-runtime-call-stats', 'Performance panel: V8 runtime call stats');
337
340
  Root.Runtime.experiments.register(
338
- 'timeline-invalidation-tracking', 'Performance panel: invalidation tracking', true);
339
- Root.Runtime.experiments.register('timeline-show-all-events', 'Performance panel: show all events', true);
340
- Root.Runtime.experiments.register(
341
- 'timeline-v8-runtime-call-stats', 'Performance panel: V8 runtime call stats', true);
342
- Root.Runtime.experiments.register(
343
- Root.Runtime.ExperimentName.TIMELINE_DEBUG_MODE,
344
- 'Performance panel: Enable debug mode (trace event details, etc)', true);
341
+ Root.Runtime.ExperimentName.TIMELINE_DEBUG_MODE, 'Performance panel: debug mode (trace event details, etc)');
345
342
 
346
343
  // Debugging
347
- Root.Runtime.experiments.register('instrumentation-breakpoints', 'Enable instrumentation breakpoints', true);
348
- Root.Runtime.experiments.register('use-source-map-scopes', 'Use scope information from source maps', true);
344
+ Root.Runtime.experiments.register('instrumentation-breakpoints', 'Instrumentation breakpoints');
345
+ Root.Runtime.experiments.register('use-source-map-scopes', 'Use scope information from source maps');
349
346
 
350
347
  // Advanced Perceptual Contrast Algorithm.
351
348
  Root.Runtime.experiments.register(
352
- 'apca',
353
- 'Enable new Advanced Perceptual Contrast Algorithm (APCA) replacing previous contrast ratio and AA/AAA guidelines',
354
- undefined, 'https://developer.chrome.com/blog/new-in-devtools-89/#apca');
349
+ 'apca', 'Advanced Perceptual Contrast Algorithm (APCA) replacing previous contrast ratio and AA/AAA guidelines',
350
+ 'https://developer.chrome.com/blog/new-in-devtools-89/#apca');
355
351
 
356
352
  // Full Accessibility Tree
357
353
  Root.Runtime.experiments.register(
358
- 'full-accessibility-tree', 'Enable full accessibility tree view in the Elements panel', undefined,
354
+ 'full-accessibility-tree', 'Full accessibility tree view in the Elements panel',
359
355
  'https://developer.chrome.com/blog/new-in-devtools-90/#accessibility-tree',
360
356
  'https://g.co/devtools/a11y-tree-feedback');
361
357
 
362
358
  // Font Editor
363
359
  Root.Runtime.experiments.register(
364
- 'font-editor', 'Enable new font editor within the Styles tab', undefined,
360
+ 'font-editor', 'New font editor in the Styles tab',
365
361
  'https://developer.chrome.com/blog/new-in-devtools-89/#font');
366
362
 
367
363
  // Contrast issues reported via the Issues panel.
368
364
  Root.Runtime.experiments.register(
369
- 'contrast-issues', 'Enable automatic contrast issue reporting via the Issues panel', undefined,
365
+ 'contrast-issues', 'Automatic contrast issue reporting via the Issues panel',
370
366
  'https://developer.chrome.com/blog/new-in-devtools-90/#low-contrast');
371
367
 
372
368
  // New cookie features.
373
- Root.Runtime.experiments.register('experimental-cookie-features', 'Enable experimental cookie features');
369
+ Root.Runtime.experiments.register('experimental-cookie-features', 'Experimental cookie features');
374
370
 
375
371
  // Change grouping of sources panel to use Authored/Deployed trees
376
372
  Root.Runtime.experiments.register(
377
373
  Root.Runtime.ExperimentName.AUTHORED_DEPLOYED_GROUPING, 'Group sources into authored and deployed trees',
378
- undefined, 'https://goo.gle/authored-deployed', 'https://goo.gle/authored-deployed-feedback');
374
+ 'https://goo.gle/authored-deployed', 'https://goo.gle/authored-deployed-feedback');
379
375
 
380
376
  // Hide third party code (as determined by ignore lists or source maps)
381
377
  Root.Runtime.experiments.register(
@@ -413,6 +409,7 @@ export class MainImpl {
413
409
  }
414
410
  }
415
411
  }
412
+
416
413
  async #createAppUI(): Promise<void> {
417
414
  MainImpl.time('Main._createAppUI');
418
415
 
@@ -474,6 +474,7 @@ export const generatedProperties = [
474
474
  "float",
475
475
  "flood-color",
476
476
  "flood-opacity",
477
+ "flow-tolerance",
477
478
  "font-display",
478
479
  "font-family",
479
480
  "font-feature-settings",
@@ -532,7 +533,6 @@ export const generatedProperties = [
532
533
  "interest-delay-start",
533
534
  "interpolate-size",
534
535
  "isolation",
535
- "item-tolerance",
536
536
  "justify-content",
537
537
  "justify-items",
538
538
  "justify-self",
@@ -2308,6 +2308,13 @@ export const generatedProperties = [
2308
2308
  {
2309
2309
  "name": "flood-opacity"
2310
2310
  },
2311
+ {
2312
+ "keywords": [
2313
+ "normal",
2314
+ "infinite"
2315
+ ],
2316
+ "name": "flow-tolerance"
2317
+ },
2311
2318
  {
2312
2319
  "inherited": true,
2313
2320
  "longhands": [
@@ -2881,13 +2888,6 @@ export const generatedProperties = [
2881
2888
  ],
2882
2889
  "name": "isolation"
2883
2890
  },
2884
- {
2885
- "keywords": [
2886
- "normal",
2887
- "infinite"
2888
- ],
2889
- "name": "item-tolerance"
2890
- },
2891
2891
  {
2892
2892
  "name": "justify-content"
2893
2893
  },
@@ -5835,6 +5835,12 @@ export const generatedPropertyValues = {
5835
5835
  "currentcolor"
5836
5836
  ]
5837
5837
  },
5838
+ "flow-tolerance": {
5839
+ "values": [
5840
+ "normal",
5841
+ "infinite"
5842
+ ]
5843
+ },
5838
5844
  "font-feature-settings": {
5839
5845
  "values": [
5840
5846
  "normal"
@@ -6156,12 +6162,6 @@ export const generatedPropertyValues = {
6156
6162
  "isolate"
6157
6163
  ]
6158
6164
  },
6159
- "item-tolerance": {
6160
- "values": [
6161
- "normal",
6162
- "infinite"
6163
- ]
6164
- },
6165
6165
  "left": {
6166
6166
  "values": [
6167
6167
  "auto"
@@ -97,6 +97,7 @@ export class PatchAgent extends AiAgent<Workspace.Workspace.Project> {
97
97
  description: '',
98
98
  nullable: true,
99
99
  properties: {},
100
+ required: [],
100
101
  },
101
102
  handler: async () => {
102
103
  const files = this.#project.getFiles();
@@ -143,9 +144,10 @@ export class PatchAgent extends AiAgent<Workspace.Workspace.Project> {
143
144
  isRegex: {
144
145
  type: Host.AidaClient.ParametersTypes.BOOLEAN,
145
146
  description: 'Whether the query is a regular expression or not',
146
- nullable: true,
147
+ nullable: false,
147
148
  }
148
149
  },
150
+ required: ['query']
149
151
  },
150
152
  handler: async (args, options) => {
151
153
  return {
@@ -182,6 +184,7 @@ export class PatchAgent extends AiAgent<Workspace.Workspace.Project> {
182
184
  }
183
185
  }
184
186
  },
187
+ required: ['files']
185
188
  },
186
189
  handler: async (args, options) => {
187
190
  debugLog('updateFiles', args.files);
@@ -782,6 +782,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
782
782
  nullable: false,
783
783
  }
784
784
  },
785
+ required: ['insightSetId', 'insightName']
785
786
  },
786
787
  displayInfoFromArgs: params => {
787
788
  return {
@@ -829,6 +830,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
829
830
  nullable: false,
830
831
  }
831
832
  },
833
+ required: ['eventKey']
832
834
  },
833
835
  displayInfoFromArgs: params => {
834
836
  return {title: lockedString('Looking at trace event…'), action: `getEventByKey('${params.eventKey}')`};
@@ -886,6 +888,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
886
888
  nullable: false,
887
889
  },
888
890
  },
891
+ required: ['min', 'max']
889
892
  },
890
893
  displayInfoFromArgs: args => {
891
894
  return {
@@ -943,6 +946,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
943
946
  nullable: false,
944
947
  },
945
948
  },
949
+ required: ['min', 'max']
946
950
  },
947
951
  displayInfoFromArgs: args => {
948
952
  return {
@@ -993,6 +997,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
993
997
  nullable: false,
994
998
  },
995
999
  },
1000
+ required: ['eventKey']
996
1001
  },
997
1002
  displayInfoFromArgs: args => {
998
1003
  return {title: lockedString('Looking at call tree…'), action: `getDetailedCallTree('${args.eventKey}')`};
@@ -1046,7 +1051,9 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1046
1051
  description: 'The message the annotation should show to the user.',
1047
1052
  nullable: false,
1048
1053
  },
1054
+
1049
1055
  },
1056
+ required: ['elementId', 'annotationMessage']
1050
1057
  },
1051
1058
  handler: async params => {
1052
1059
  return await this.addElementAnnotation(params.elementId, params.annotationMessage);
@@ -1077,6 +1084,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1077
1084
  nullable: false,
1078
1085
  },
1079
1086
  },
1087
+ required: ['eventKey', 'annotationMessage']
1080
1088
  },
1081
1089
  handler: async params => {
1082
1090
  return await this.addNetworkRequestAnnotation(params.eventKey, params.annotationMessage);
@@ -1108,6 +1116,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1108
1116
  nullable: false,
1109
1117
  },
1110
1118
  },
1119
+ required: ['scriptUrl', 'line', 'column']
1111
1120
  },
1112
1121
  displayInfoFromArgs: args => {
1113
1122
  return {
@@ -1166,6 +1175,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1166
1175
  nullable: false,
1167
1176
  },
1168
1177
  },
1178
+ required: ['url']
1169
1179
  },
1170
1180
  displayInfoFromArgs: args => {
1171
1181
  return {title: lockedString('Looking at resource content…'), action: `getResourceContent('${args.url}')`};
@@ -1220,6 +1230,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1220
1230
  nullable: false,
1221
1231
  }
1222
1232
  },
1233
+ required: ['eventKey']
1223
1234
  },
1224
1235
  displayInfoFromArgs: params => {
1225
1236
  return {title: lockedString('Selecting event…'), action: `selectEventByKey('${params.eventKey}')`};
@@ -1281,6 +1292,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1281
1292
  nullable: true,
1282
1293
  },
1283
1294
  },
1295
+ required: ['type']
1284
1296
  },
1285
1297
  handler: async params => {
1286
1298
  switch (params.type) {
@@ -86,7 +86,12 @@ Content:
86
86
  "description": "A CSS style property name to retrieve. For example, 'background-color'."
87
87
  }
88
88
  }
89
- }
89
+ },
90
+ "required": [
91
+ "explanation",
92
+ "elements",
93
+ "styleProperties"
94
+ ]
90
95
  }
91
96
  },
92
97
  {
@@ -109,7 +114,12 @@ Content:
109
114
  "type": 1,
110
115
  "description": "Provide a summary of what the code does. For example, \"Checking related element styles\"."
111
116
  }
112
- }
117
+ },
118
+ "required": [
119
+ "code",
120
+ "thought",
121
+ "title"
122
+ ]
113
123
  }
114
124
  }
115
125
  ],
@@ -313,7 +313,8 @@ export class StylingAgent extends AiAgent<SDK.DOMModel.DOMNode> {
313
313
  description: 'A CSS style property name to retrieve. For example, \'background-color\'.'
314
314
  }
315
315
  },
316
- }
316
+ },
317
+ required: ['explanation', 'elements', 'styleProperties']
317
318
  },
318
319
  displayInfoFromArgs: params => {
319
320
  return {
@@ -396,6 +397,7 @@ const data = {
396
397
  description: 'Provide a summary of what the code does. For example, "Checking related element styles".',
397
398
  },
398
399
  },
400
+ required: ['code', 'thought', 'title']
399
401
  },
400
402
  displayInfoFromArgs: params => {
401
403
  return {
@@ -436,6 +438,7 @@ const data = {
436
438
  nullable: false,
437
439
  },
438
440
  },
441
+ required: ['elementId', 'annotationMessage']
439
442
  },
440
443
  handler: async params => {
441
444
  return await this.addElementAnnotation(params.elementId, params.annotationMessage);
@@ -31,7 +31,9 @@ export class StackTraceImpl<SyncFragmentT extends FragmentImpl|DebuggableFragmen
31
31
  }
32
32
 
33
33
  export class FragmentImpl implements StackTrace.StackTrace.Fragment {
34
- readonly node: FrameNode;
34
+ static readonly EMPTY_FRAGMENT = new FragmentImpl();
35
+
36
+ readonly node?: FrameNode;
35
37
  readonly stackTraces = new Set<AnyStackTraceImpl>();
36
38
 
37
39
  /**
@@ -46,11 +48,15 @@ export class FragmentImpl implements StackTrace.StackTrace.Fragment {
46
48
  return node.fragment;
47
49
  }
48
50
 
49
- private constructor(node: FrameNode) {
51
+ private constructor(node?: FrameNode) {
50
52
  this.node = node;
51
53
  }
52
54
 
53
55
  get frames(): FrameImpl[] {
56
+ if (!this.node) {
57
+ return [];
58
+ }
59
+
54
60
  const frames: FrameImpl[] = [];
55
61
 
56
62
  for (const node of this.node.getCallStack()) {
@@ -101,6 +107,10 @@ export class DebuggableFragmentImpl implements StackTrace.StackTrace.DebuggableF
101
107
  }
102
108
 
103
109
  get frames(): DebuggableFrameImpl[] {
110
+ if (!this.fragment.node) {
111
+ return [];
112
+ }
113
+
104
114
  const frames: DebuggableFrameImpl[] = [];
105
115
 
106
116
  let index = 0;
@@ -77,7 +77,7 @@ export class StackTraceModel extends SDK.SDKModel.SDKModel<unknown> {
77
77
  // is re-translated as a side-effect.
78
78
  // We just need to remember the stack traces of the skipped over fragments, so we can send the
79
79
  // UPDATED event also to them.
80
- if (fragment.node.children.length === 0) {
80
+ if (fragment.node?.children.length === 0) {
81
81
  translatePromises.push(this.#translateFragment(fragment, translateRawFrames));
82
82
  }
83
83
  stackTracesToUpdate = stackTracesToUpdate.union(fragment.stackTraces);
@@ -133,6 +133,10 @@ export class StackTraceModel extends SDK.SDKModel.SDKModel<unknown> {
133
133
  }
134
134
 
135
135
  async #createFragment(frames: RawFrame[], rawFramesToUIFrames: TranslateRawFrames): Promise<FragmentImpl> {
136
+ if (frames.length === 0) {
137
+ return FragmentImpl.EMPTY_FRAGMENT;
138
+ }
139
+
136
140
  const release = await this.#mutex.acquire();
137
141
  try {
138
142
  const node = this.#trie.insert(frames);
@@ -150,6 +154,10 @@ export class StackTraceModel extends SDK.SDKModel.SDKModel<unknown> {
150
154
  }
151
155
 
152
156
  async #translateFragment(fragment: FragmentImpl, rawFramesToUIFrames: TranslateRawFrames): Promise<void> {
157
+ if (!fragment.node) {
158
+ return;
159
+ }
160
+
153
161
  const rawFrames = fragment.node.getCallStack().map(node => node.rawFrame).toArray();
154
162
  const uiFrames = await rawFramesToUIFrames(rawFrames, this.target());
155
163
  console.assert(rawFrames.length === uiFrames.length, 'Broken rawFramesToUIFrames implementation');
@@ -311,6 +311,10 @@ const UIStrings = {
311
311
  * @description Text in Timeline UIUtils of the Performance panel
312
312
  */
313
313
  largestContentfulPaint: 'Largest Contentful Paint',
314
+ /**
315
+ * @description Text in Timeline UIUtils of the Performance panel
316
+ */
317
+ softLargestContentfulPaint: 'Soft Largest Contentful Paint',
314
318
  /**
315
319
  * @description Text for timestamps of items
316
320
  */
@@ -880,7 +884,7 @@ export function maybeInitSylesMap(): EventStylesMap {
880
884
  true,
881
885
  ),
882
886
  [Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION]: new TimelineRecordStyle(
883
- i18nString(UIStrings.largestContentfulPaint),
887
+ i18nString(UIStrings.softLargestContentfulPaint),
884
888
  defaultCategoryStyles.rendering,
885
889
  true,
886
890
  ),
@@ -1125,15 +1129,14 @@ export function markerDetailsForEvent(event: Types.Events.Event): {
1125
1129
  }
1126
1130
  if (Types.Events.isAnyLargestContentfulPaintCandidate(event)) {
1127
1131
  color = 'var(--sys-color-green)';
1128
- title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP;
1132
+ title = Types.Events.isSoftLargestContentfulPaintCandidate(event) ?
1133
+ Handlers.ModelHandlers.PageLoadMetrics.MetricName.SOFT_LCP :
1134
+ Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP;
1129
1135
  }
1130
- if (Types.Events.isNavigationStart(event)) {
1136
+ if (Types.Events.isNavigationStart(event) || Types.Events.isSoftNavigationStart(event)) {
1131
1137
  color = 'var(--color-text-primary)';
1132
- title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.NAV;
1133
- }
1134
- if (Types.Events.isSoftNavigationStart(event)) {
1135
- color = 'var(--sys-color-blue)';
1136
- title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.SOFT_NAV;
1138
+ title = Types.Events.isSoftNavigationStart(event) ? Handlers.ModelHandlers.PageLoadMetrics.MetricName.SOFT_NAV :
1139
+ Handlers.ModelHandlers.PageLoadMetrics.MetricName.NAV;
1137
1140
  }
1138
1141
  if (Types.Events.isMarkDOMContent(event)) {
1139
1142
  color = 'var(--color-text-disabled)';
@@ -460,8 +460,9 @@ export const enum MetricName {
460
460
  CLS = 'CLS',
461
461
  // Navigation
462
462
  NAV = 'Nav',
463
- // Soft Navigation (just "Nav" b/c space is limited in flame chart)
464
- SOFT_NAV = 'Nav',
463
+ // Soft Navigation and Soft Metrics
464
+ SOFT_NAV = 'Nav*',
465
+ SOFT_LCP = 'LCP*',
465
466
  // Note: INP is handled in UserInteractionsHandler
466
467
  }
467
468
 
@@ -678,7 +678,7 @@ export interface Mark extends Event {
678
678
  }
679
679
 
680
680
  export interface NavigationStart extends Mark {
681
- name: 'navigationStart';
681
+ name: Name.NAVIGATION_START;
682
682
  args: Args&{
683
683
  frame: string,
684
684
  data?: ArgsData&{
@@ -738,7 +738,7 @@ export interface FirstContentfulPaint extends Mark {
738
738
  }
739
739
 
740
740
  export interface FirstPaint extends Mark {
741
- name: 'firstPaint';
741
+ name: Name.MARK_FIRST_PAINT;
742
742
  args: Args&{
743
743
  frame: string,
744
744
  data?: ArgsData&{
@@ -761,8 +761,14 @@ const markerTypeGuards = [
761
761
  ];
762
762
 
763
763
  export const MarkerName = [
764
- 'MarkDOMContent', 'MarkLoad', 'firstPaint', 'firstContentfulPaint', 'largestContentfulPaint::Candidate',
765
- 'largestContentfulPaint::CandidateForSoftNavigation'
764
+ Name.MARK_DOM_CONTENT,
765
+ Name.MARK_LOAD,
766
+ Name.MARK_FIRST_PAINT,
767
+ Name.MARK_FCP,
768
+ Name.MARK_LCP_CANDIDATE,
769
+ Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION,
770
+ Name.NAVIGATION_START,
771
+ Name.SOFT_NAVIGATION_START,
766
772
  ] as const;
767
773
 
768
774
  export interface MarkerEvent extends Event {
@@ -968,7 +974,7 @@ export interface CommitLoad extends Instant {
968
974
  }
969
975
 
970
976
  export interface MarkDOMContent extends Instant {
971
- name: 'MarkDOMContent';
977
+ name: Name.MARK_DOM_CONTENT;
972
978
  args: Args&{
973
979
  data?: ArgsData & {
974
980
  frame: string,
@@ -980,7 +986,7 @@ export interface MarkDOMContent extends Instant {
980
986
  }
981
987
 
982
988
  export interface MarkLoad extends Instant {
983
- name: 'MarkLoad';
989
+ name: Name.MARK_LOAD;
984
990
  args: Args&{
985
991
  data?: ArgsData & {
986
992
  frame: string,
@@ -2256,12 +2262,15 @@ export function isLayoutInvalidationTracking(
2256
2262
  }
2257
2263
 
2258
2264
  export function isFirstContentfulPaint(event: Event): event is FirstContentfulPaint {
2259
- return event.name === 'firstContentfulPaint';
2265
+ return event.name === Name.MARK_FCP;
2260
2266
  }
2261
2267
 
2262
2268
  export function isAnyLargestContentfulPaintCandidate(event: Event): event is AnyLargestContentfulPaintCandidate {
2263
2269
  return event.name === Name.MARK_LCP_CANDIDATE || event.name === Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION;
2264
2270
  }
2271
+ export function isSoftLargestContentfulPaintCandidate(event: Event): event is AnyLargestContentfulPaintCandidate {
2272
+ return event.name === Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION;
2273
+ }
2265
2274
  export function isLargestImagePaintCandidate(event: Event): event is LargestImagePaintCandidate {
2266
2275
  return event.name === 'LargestImagePaint::Candidate';
2267
2276
  }
@@ -2270,15 +2279,15 @@ export function isLargestTextPaintCandidate(event: Event): event is LargestTextP
2270
2279
  }
2271
2280
 
2272
2281
  export function isMarkLoad(event: Event): event is MarkLoad {
2273
- return event.name === 'MarkLoad';
2282
+ return event.name === Name.MARK_LOAD;
2274
2283
  }
2275
2284
 
2276
2285
  export function isFirstPaint(event: Event): event is FirstPaint {
2277
- return event.name === 'firstPaint';
2286
+ return event.name === Name.MARK_FIRST_PAINT;
2278
2287
  }
2279
2288
 
2280
2289
  export function isMarkDOMContent(event: Event): event is MarkDOMContent {
2281
- return event.name === 'MarkDOMContent';
2290
+ return event.name === Name.MARK_DOM_CONTENT;
2282
2291
  }
2283
2292
 
2284
2293
  export function isInteractiveTime(event: Event): event is InteractiveTime {
@@ -70,7 +70,7 @@ const UIStringsNotTranslate = {
70
70
  } as const;
71
71
 
72
72
  const lockedString = i18n.i18n.lockedString;
73
- const PROMOTION_ID = 'ai-code-generation';
73
+ export const PROMOTION_ID = 'ai-code-generation';
74
74
 
75
75
  export enum AiCodeGenerationTeaserDisplayState {
76
76
  TRIGGER = 'trigger',
@@ -982,7 +982,6 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
982
982
 
983
983
  const showMetricsWidgetInComputedPane = (): void => {
984
984
  this.metricsWidget.show(computedStylePanesWrapper.element, this.computedStyleWidget.element);
985
- this.metricsWidget.toggleVisibility(true /* visible */);
986
985
  this.stylesWidget.removeEventListener(StylesSidebarPaneEvents.STYLES_UPDATE_COMPLETED, toggleMetricsWidget);
987
986
  };
988
987
 
@@ -993,14 +992,18 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
993
992
  } else {
994
993
  this.metricsWidget.show(matchedStylePanesWrapper.element);
995
994
  if (!this.stylesWidget.hasMatchedStyles) {
996
- this.metricsWidget.toggleVisibility(false /* invisible */);
995
+ this.metricsWidget.hideWidget();
997
996
  }
998
997
  this.stylesWidget.addEventListener(StylesSidebarPaneEvents.STYLES_UPDATE_COMPLETED, toggleMetricsWidget);
999
998
  }
1000
999
  };
1001
1000
 
1002
1001
  const toggleMetricsWidget = (event: Common.EventTarget.EventTargetEvent<StylesUpdateCompletedEvent>): void => {
1003
- this.metricsWidget.toggleVisibility(event.data.hasMatchedStyles);
1002
+ if (event.data.hasMatchedStyles) {
1003
+ this.metricsWidget.showWidget();
1004
+ } else {
1005
+ this.metricsWidget.hideWidget();
1006
+ }
1004
1007
  };
1005
1008
 
1006
1009
  const tabSelected = (event: Common.EventTarget.EventTargetEvent<UI.TabbedPane.EventData>): void => {
@@ -10,8 +10,11 @@ import {type ComputedStyleModel, type CSSModelChangedEvent, Events} from './Comp
10
10
 
11
11
  export class ElementsSidebarPane extends UI.Widget.VBox {
12
12
  protected computedStyleModelInternal: ComputedStyleModel;
13
- constructor(computedStyleModel: ComputedStyleModel, delegatesFocus?: boolean) {
14
- super({useShadowDom: true, delegatesFocus, classes: ['flex-none']});
13
+ constructor(computedStyleModel: ComputedStyleModel, options: UI.Widget.WidgetOptions = {}) {
14
+ options.useShadowDom = options.useShadowDom ?? true;
15
+ options.classes = options.classes ?? [];
16
+ options.classes.push('flex-none');
17
+ super(options);
15
18
  this.computedStyleModelInternal = computedStyleModel;
16
19
  this.computedStyleModelInternal.addEventListener(Events.CSS_MODEL_CHANGED, this.onCSSModelChanged, this);
17
20
  this.computedStyleModelInternal.addEventListener(Events.COMPUTED_STYLE_CHANGED, this.onComputedStyleChanged, this);