chrome-devtools-frontend 1.0.1570343 → 1.0.1571573

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 (72) hide show
  1. package/agents/prompts/README.md +18 -0
  2. package/agents/prompts/devtools-imports.md +47 -0
  3. package/agents/prompts/verification.md +27 -0
  4. package/docs/contributing/infrastructure.md +22 -0
  5. package/front_end/core/host/AidaClient.ts +1 -1
  6. package/front_end/core/host/UserMetrics.ts +1 -1
  7. package/front_end/core/root/Runtime.ts +54 -34
  8. package/front_end/core/sdk/CSSProperty.ts +1 -1
  9. package/front_end/core/sdk/CookieModel.ts +1 -1
  10. package/front_end/core/sdk/DOMModel.ts +1 -1
  11. package/front_end/core/sdk/DebuggerModel.ts +2 -21
  12. package/front_end/core/sdk/OverlayModel.ts +3 -2
  13. package/front_end/core/sdk/SourceMap.ts +0 -9
  14. package/front_end/core/sdk/SourceMapScopesInfo.ts +0 -24
  15. package/front_end/entrypoints/main/MainImpl.ts +43 -18
  16. package/front_end/generated/SupportedCSSProperties.js +2 -6
  17. package/front_end/models/ai_assistance/BuiltInAi.ts +5 -4
  18. package/front_end/models/issues_manager/ContrastCheckTrigger.ts +2 -2
  19. package/front_end/models/javascript_metadata/NativeFunctions.js +8 -0
  20. package/front_end/models/trace/ModelImpl.ts +0 -4
  21. package/front_end/panels/accessibility/AccessibilitySidebarView.ts +1 -1
  22. package/front_end/panels/ai_assistance/PatchWidget.ts +10 -15
  23. package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +5 -4
  24. package/front_end/panels/ai_assistance/components/ChatMessage.ts +3 -2
  25. package/front_end/panels/application/FrameDetailsView.ts +2 -1
  26. package/front_end/panels/application/components/ReportsGrid.ts +2 -1
  27. package/front_end/panels/common/AiCodeCompletionSummaryToolbar.ts +3 -5
  28. package/front_end/panels/common/AiCodeCompletionTeaser.ts +5 -5
  29. package/front_end/panels/console/ConsoleInsightTeaser.ts +10 -11
  30. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +2 -2
  31. package/front_end/panels/css_overview/CSSOverviewModel.ts +1 -1
  32. package/front_end/panels/elements/ComputedStyleModel.ts +11 -13
  33. package/front_end/panels/elements/ComputedStyleWidget.ts +3 -3
  34. package/front_end/panels/elements/ElementsPanel.ts +5 -2
  35. package/front_end/panels/elements/ElementsSidebarPane.ts +1 -1
  36. package/front_end/panels/elements/PlatformFontsWidget.ts +1 -1
  37. package/front_end/panels/elements/StylePropertiesSection.ts +1 -1
  38. package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
  39. package/front_end/panels/emulation/DeviceModeWrapper.ts +101 -62
  40. package/front_end/panels/explain/components/ConsoleInsight.ts +27 -23
  41. package/front_end/panels/explain/components/consoleInsight.css +1 -1
  42. package/front_end/panels/network/RequestConditionsDrawer.ts +0 -1
  43. package/front_end/panels/network/RequestTimingView.ts +4 -3
  44. package/front_end/panels/network/components/RequestHeadersView.css +2 -2
  45. package/front_end/panels/network/components/RequestHeadersView.ts +7 -6
  46. package/front_end/panels/profiler/HeapProfileView.ts +3 -3
  47. package/front_end/panels/profiler/HeapSnapshotView.ts +2 -2
  48. package/front_end/panels/recorder/RecorderController.ts +6 -7
  49. package/front_end/panels/recorder/recorderController.css +1 -1
  50. package/front_end/panels/security/CookieControlsView.ts +2 -2
  51. package/front_end/panels/security/CookieReportView.ts +7 -7
  52. package/front_end/panels/settings/AISettingsTab.ts +5 -5
  53. package/front_end/panels/settings/components/SyncSection.ts +4 -3
  54. package/front_end/panels/sources/CallStackSidebarPane.ts +4 -1
  55. package/front_end/panels/sources/NavigatorView.ts +1 -1
  56. package/front_end/panels/sources/SourcesPanel.ts +3 -1
  57. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +1 -1
  58. package/front_end/panels/timeline/ThreadAppender.ts +1 -1
  59. package/front_end/panels/timeline/TimelineController.ts +4 -3
  60. package/front_end/panels/timeline/TimelinePanel.ts +4 -3
  61. package/front_end/panels/whats_new/ReleaseNoteView.ts +4 -3
  62. package/front_end/third_party/chromium/README.chromium +1 -1
  63. package/front_end/ui/components/markdown_view/CodeBlock.ts +3 -6
  64. package/front_end/ui/components/markdown_view/MarkdownLink.ts +3 -4
  65. package/front_end/ui/components/panel_feedback/PanelFeedback.ts +3 -4
  66. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +9 -6
  67. package/front_end/ui/components/panel_feedback/panelFeedback.css +2 -2
  68. package/front_end/ui/kit/link/Link.ts +1 -14
  69. package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +1 -1
  70. package/front_end/ui/legacy/components/color_picker/ContrastOverlay.ts +5 -4
  71. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -1
  72. package/package.json +1 -1
@@ -47,7 +47,8 @@ export class BuiltInAi extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
47
47
  }
48
48
 
49
49
  async getLanguageModelAvailability(): Promise<LanguageModelAvailability> {
50
- if (!Root.Runtime.hostConfig.devToolsAiPromptApi?.enabled) {
50
+ if (!Root.Runtime.hostConfig.devToolsConsoleInsightsTeasers?.enabled ||
51
+ (Root.Runtime.hostConfig.devToolsAiPromptApi && !Root.Runtime.hostConfig.devToolsAiPromptApi.enabled)) {
51
52
  this.#availability = LanguageModelAvailability.DISABLED;
52
53
  return this.#availability;
53
54
  }
@@ -74,7 +75,7 @@ export class BuiltInAi extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
74
75
  }
75
76
 
76
77
  isEventuallyAvailable(): boolean {
77
- if (!this.#hasGpu && !Boolean(Root.Runtime.hostConfig.devToolsAiPromptApi?.allowWithoutGpu)) {
78
+ if (!this.#hasGpu && !Boolean(Root.Runtime.hostConfig.devToolsConsoleInsightsTeasers?.allowWithoutGpu)) {
78
79
  return false;
79
80
  }
80
81
  return this.#availability === LanguageModelAvailability.AVAILABLE ||
@@ -92,7 +93,7 @@ export class BuiltInAi extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
92
93
  }
93
94
 
94
95
  startDownloadingModel(): void {
95
- if (!Root.Runtime.hostConfig.devToolsAiPromptApi?.allowWithoutGpu && !this.#hasGpu) {
96
+ if (!Root.Runtime.hostConfig.devToolsConsoleInsightsTeasers?.allowWithoutGpu && !this.#hasGpu) {
96
97
  return;
97
98
  }
98
99
  if (this.#availability !== LanguageModelAvailability.DOWNLOADABLE) {
@@ -132,7 +133,7 @@ export class BuiltInAi extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
132
133
  }
133
134
 
134
135
  async initialize(): Promise<void> {
135
- if (!Root.Runtime.hostConfig.devToolsAiPromptApi?.allowWithoutGpu && !this.#hasGpu) {
136
+ if (!Root.Runtime.hostConfig.devToolsConsoleInsightsTeasers?.allowWithoutGpu && !this.#hasGpu) {
136
137
  return;
137
138
  }
138
139
  if (this.#availability !== LanguageModelAvailability.AVAILABLE &&
@@ -45,7 +45,7 @@ export class ContrastCheckTrigger {
45
45
  }
46
46
 
47
47
  #checkContrast(resourceTreeModel: SDK.ResourceTreeModel.ResourceTreeModel): void {
48
- if (!Root.Runtime.experiments.isEnabled('contrast-issues')) {
48
+ if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.CONTRAST_ISSUES)) {
49
49
  return;
50
50
  }
51
51
  void resourceTreeModel.target().auditsAgent().invoke_checkContrast({});
@@ -60,7 +60,7 @@ export class ContrastCheckTrigger {
60
60
 
61
61
  async #frameAdded(event: Common.EventTarget.EventTargetEvent<SDK.ResourceTreeModel.ResourceTreeFrame>):
62
62
  Promise<void> {
63
- if (!Root.Runtime.experiments.isEnabled('contrast-issues')) {
63
+ if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.CONTRAST_ISSUES)) {
64
64
  return;
65
65
  }
66
66
  const frame = event.data;
@@ -6594,6 +6594,14 @@ export const NativeFunctions = [
6594
6594
  name: "setHTML",
6595
6595
  signatures: [["html","?options"]]
6596
6596
  },
6597
+ {
6598
+ name: "streamAppendHTMLUnsafe",
6599
+ signatures: [["?options"]]
6600
+ },
6601
+ {
6602
+ name: "streamHTMLUnsafe",
6603
+ signatures: [["?options"]]
6604
+ },
6597
6605
  {
6598
6606
  name: "scrollIntoViewIfNeeded",
6599
6607
  signatures: [["?centerIfNeeded"]]
@@ -10,10 +10,6 @@ import type * as Insights from './insights/insights.js';
10
10
  import {TraceParseProgressEvent, TraceProcessor} from './Processor.js';
11
11
  import * as Types from './types/types.js';
12
12
 
13
- // Note: this model is implemented in a way that can support multiple trace
14
- // processors. Currently there is only one implemented, but you will see
15
- // references to "processors" plural because it can easily be extended in the future.
16
-
17
13
  /**
18
14
  * The Model is responsible for parsing arrays of raw trace events and storing the
19
15
  * resulting data. It can store multiple traces at once, and can return the data for
@@ -95,7 +95,7 @@ export class AccessibilitySidebarView extends UI.Widget.VBox {
95
95
  if (!accessibilityModel) {
96
96
  return;
97
97
  }
98
- if (!Root.Runtime.experiments.isEnabled('full-accessibility-tree')) {
98
+ if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.FULL_ACCESSIBILITY_TREE)) {
99
99
  accessibilityModel.clear();
100
100
  }
101
101
  await accessibilityModel.requestPartialAXTree(node);
@@ -5,6 +5,7 @@
5
5
  import '../../ui/legacy/legacy.js';
6
6
  import '../../ui/components/markdown_view/markdown_view.js';
7
7
  import '../../ui/components/spinners/spinners.js';
8
+ import '../../ui/kit/kit.js';
8
9
 
9
10
  import * as Common from '../../core/common/common.js';
10
11
  import * as Host from '../../core/host/host.js';
@@ -200,15 +201,13 @@ const DEFAULT_VIEW: View = (input, output, target) => {
200
201
  return nothing;
201
202
  }
202
203
 
203
- return html`<x-link
204
+ return html`<devtools-link
204
205
  class="link"
205
206
  title="${UIStringsNotTranslate.viewUploadedFiles} ${UIStringsNotTranslate.opensInNewTab}"
206
207
  href="data:text/plain;charset=utf-8,${encodeURIComponent(input.sources)}"
207
- jslog=${VisualLogging.link('files-used-in-patching').track({
208
- click: true
209
- })}>
208
+ .jslogContext=${'files-used-in-patching'}>
210
209
  ${UIStringsNotTranslate.viewUploadedFiles}
211
- </x-link>`;
210
+ </devtools-link>`;
212
211
  }
213
212
 
214
213
  function renderHeader(): LitTemplate {
@@ -297,12 +296,10 @@ const DEFAULT_VIEW: View = (input, output, target) => {
297
296
  return html`
298
297
  <div class="footer">
299
298
  <div class="left-side">
300
- <x-link class="link disclaimer-link" href="https://support.google.com/legal/answer/13505487" jslog=${
301
- VisualLogging.link('code-disclaimer').track({
302
- click: true,
303
- })}>
299
+ <devtools-link class="link disclaimer-link" href="https://support.google.com/legal/answer/13505487" .jslogContext=${
300
+ 'code-disclaimer'}>
304
301
  ${lockedString(UIStringsNotTranslate.codeDisclaimer)}
305
- </x-link>
302
+ </devtools-link>
306
303
  ${renderSourcesLink()}
307
304
  </div>
308
305
  <div class="save-or-discard-buttons">
@@ -575,13 +572,11 @@ export class PatchWidget extends UI.Widget.Widget {
575
572
  {
576
573
  iconName: 'warning',
577
574
  // clang-format off
578
- content: html`<x-link
575
+ content: html`<devtools-link
579
576
  href=${CODE_SNIPPET_WARNING_URL}
580
577
  class="link devtools-link"
581
- jslog=${VisualLogging.link('code-snippets-explainer.patch-widget').track({
582
- click: true
583
- })}
584
- >${lockedString(UIStringsNotTranslate.freDisclaimerTextUseWithCaution)}</x-link>`,
578
+ .jslogContext=${'code-snippets-explainer.patch-widget'}
579
+ >${lockedString(UIStringsNotTranslate.freDisclaimerTextUseWithCaution)}</devtools-link>`,
585
580
  // clang-format on
586
581
  }
587
582
  ],
@@ -2,6 +2,8 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
+ import '../../ui/kit/kit.js';
6
+
5
7
  import * as Common from '../../core/common/common.js';
6
8
  import * as Host from '../../core/host/host.js';
7
9
  import * as i18n from '../../core/i18n/i18n.js';
@@ -13,7 +15,6 @@ import * as Workspace from '../../models/workspace/workspace.js';
13
15
  import * as Buttons from '../../ui/components/buttons/buttons.js';
14
16
  import * as UI from '../../ui/legacy/legacy.js';
15
17
  import {html, nothing, render} from '../../ui/lit/lit.js';
16
- import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
17
18
 
18
19
  import selectWorkspaceDialogStyles from './selectWorkspaceDialog.css.js';
19
20
 
@@ -89,11 +90,11 @@ export const SELECT_WORKSPACE_DIALOG_DEFAULT_VIEW: View = (input, _output, targe
89
90
  <!-- Hardcoding, because there is no 'getFormatLocalizedString' equivalent for 'lockedString' -->
90
91
  <div>
91
92
  Tip: provide a
92
- <x-link
93
+ <devtools-link
93
94
  class="devtools-link"
94
95
  href="https://goo.gle/devtools-automatic-workspace-folders"
95
- jslog=${VisualLogging.link().track({click: true, keydown:'Enter|Space'}).context('automatic-workspaces-documentation')}
96
- >com.chrome.devtools.json</x-link>
96
+ .jslogContext=${'automatic-workspaces-documentation'}
97
+ >com.chrome.devtools.json</devtools-link>
97
98
  file to automatically connect your project to DevTools.
98
99
  </div>
99
100
  ` : nothing}
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import '../../../ui/components/markdown_view/markdown_view.js';
6
+ import '../../../ui/kit/kit.js';
6
7
 
7
8
  import * as Common from '../../../core/common/common.js';
8
9
  import * as Host from '../../../core/host/host.js';
@@ -576,12 +577,12 @@ function renderImageChatMessage(inlineData: Host.AidaClient.MediaBlob): Lit.LitT
576
577
  }
577
578
  const imageUrl = `data:${inlineData.mimeType};base64,${inlineData.data}`;
578
579
  // clang-format off
579
- return html`<x-link
580
+ return html`<devtools-link
580
581
  class="image-link" title=${UIStringsNotTranslate.openImageInNewTab}
581
582
  href=${imageUrl}
582
583
  >
583
584
  <img src=${imageUrl} alt=${UIStringsNotTranslate.imageInputSentToTheModel} />
584
- </x-link>`;
585
+ </devtools-link>`;
585
586
  // clang-format on
586
587
  }
587
588
 
@@ -856,7 +856,8 @@ export class FrameDetailsReportView extends UI.Widget.Widget {
856
856
 
857
857
  constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
858
858
  super(element, {useShadowDom: true});
859
- this.#protocolMonitorExperimentEnabled = Root.Runtime.experiments.isEnabled('protocol-monitor');
859
+ this.#protocolMonitorExperimentEnabled =
860
+ Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.PROTOCOL_MONITOR);
860
861
  this.#view = view;
861
862
  }
862
863
 
@@ -134,7 +134,8 @@ export class ReportsGrid extends UI.Widget.Widget {
134
134
  constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
135
135
  super(element);
136
136
  this.#view = view;
137
- this.#protocolMonitorExperimentEnabled = Root.Runtime.experiments.isEnabled('protocol-monitor');
137
+ this.#protocolMonitorExperimentEnabled =
138
+ Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.PROTOCOL_MONITOR);
138
139
  this.requestUpdate();
139
140
  }
140
141
 
@@ -4,13 +4,13 @@
4
4
 
5
5
  import '../../ui/components/spinners/spinners.js';
6
6
  import '../../ui/components/tooltips/tooltips.js';
7
+ import '../../ui/kit/kit.js';
7
8
 
8
9
  import * as Host from '../../core/host/host.js';
9
10
  import * as i18n from '../../core/i18n/i18n.js';
10
11
  import type * as AiCodeCompletion from '../../models/ai_code_completion/ai_code_completion.js';
11
12
  import * as UI from '../../ui/legacy/legacy.js';
12
13
  import {Directives, html, nothing, render} from '../../ui/lit/lit.js';
13
- import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
14
14
 
15
15
  import {AiCodeCompletionDisclaimer} from './AiCodeCompletionDisclaimer.js';
16
16
  import styles from './aiCodeCompletionSummaryToolbar.css.js';
@@ -86,12 +86,10 @@ export const DEFAULT_SUMMARY_TOOLBAR_VIEW: View = (input, _output, target) => {
86
86
  variant="rich"
87
87
  jslogContext="ai-code-completion-citations"
88
88
  ><div class="citations-tooltip-container">
89
- ${Directives.repeat(input.citations, citation => html`<x-link
89
+ ${Directives.repeat(input.citations, citation => html`<devtools-link
90
90
  tabIndex="0"
91
91
  href=${citation}
92
- jslog=${VisualLogging.link('ai-code-completion-citations.citation-link').track({
93
- click: true
94
- })}>${citation}</x-link>`)}</div></devtools-tooltip>
92
+ .jslogContext=${'ai-code-completion-citations.citation-link'}>${citation}</devtools-link>`)}</div></devtools-tooltip>
95
93
  </div>` : nothing;
96
94
 
97
95
  render(
@@ -2,6 +2,8 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
+ import '../../ui/kit/kit.js';
6
+
5
7
  import * as Common from '../../core/common/common.js';
6
8
  import * as Host from '../../core/host/host.js';
7
9
  import * as i18n from '../../core/i18n/i18n.js';
@@ -244,13 +246,11 @@ export class AiCodeCompletionTeaser extends UI.Widget.Widget {
244
246
  {
245
247
  iconName: 'warning',
246
248
  // clang-format off
247
- content: html`<x-link
249
+ content: html`<devtools-link
248
250
  href=${CODE_SNIPPET_WARNING_URL}
249
251
  class="link devtools-link"
250
- jslog=${VisualLogging.link('code-snippets-explainer.ai-code-completion-teaser').track({
251
- click: true
252
- })}
253
- >${lockedString(UIStringsNotTranslate.freDisclaimerTextUseWithCaution)}</x-link>`,
252
+ .jslogContext=${'code-snippets-explainer.ai-code-completion-teaser'}
253
+ >${lockedString(UIStringsNotTranslate.freDisclaimerTextUseWithCaution)}</devtools-link>`,
254
254
  // clang-format on
255
255
  });
256
256
  return reminderItems;
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import '../../ui/components/tooltips/tooltips.js';
6
+ import '../../ui/kit/kit.js';
6
7
 
7
8
  import * as Common from '../../core/common/common.js';
8
9
  import * as Host from '../../core/host/host.js';
@@ -167,13 +168,13 @@ function renderNoModel(input: ViewInput): Lit.TemplateResult {
167
168
  lockedString(UIStringsNotTranslate.getHelpForWarning) :
168
169
  lockedString(UIStringsNotTranslate.getHelpForError)}
169
170
  </h2>
170
- <div>You can get quick answers from <x-link
171
- .jslog=${VisualLogging.link().track({click: true, keydown: 'Enter|Space'}).context('insights-teaser-built-in-ai-documentation')}
171
+ <div>You can get quick answers from <devtools-link
172
+ .jslogContext=${'insights-teaser-built-in-ai-documentation'}
172
173
  class="link"
173
174
  href=${BUILT_IN_AI_DOCUMENTATION}
174
175
  >
175
176
  Chrome’s Built-in AI
176
- </x-link>
177
+ </devtools-link>
177
178
  , without any data leaving your device.
178
179
  </div>
179
180
  <div>${lockedString(UIStringsNotTranslate.toUseDownload)}</div>
@@ -324,12 +325,12 @@ function renderFooter(input: ViewInput): Lit.TemplateResult {
324
325
  >
325
326
  <div class="info-tooltip-text">${lockedString(UIStringsNotTranslate.infoTooltipText)}</div>
326
327
  <div class="learn-more">
327
- <x-link
328
+ <devtools-link
328
329
  class="devtools-link"
329
330
  title=${lockedString(UIStringsNotTranslate.learnMoreAboutAiSummaries)}
330
331
  href=${DATA_USAGE_URL}
331
- jslog=${VisualLogging.link().track({click: true, keydown:'Enter|Space'}).context('explain.teaser.learn-more')}
332
- >${lockedString(UIStringsNotTranslate.learnMoreAboutAiSummaries)}</x-link>
332
+ .jslogContext=${'explain.teaser.learn-more'}
333
+ >${lockedString(UIStringsNotTranslate.learnMoreAboutAiSummaries)}</devtools-link>
333
334
  </div>
334
335
  </devtools-tooltip>
335
336
  ${renderDontShowCheckbox(input)}
@@ -509,13 +510,11 @@ export class ConsoleInsightTeaser extends UI.Widget.Widget {
509
510
  {
510
511
  iconName: 'warning',
511
512
  // clang-format off
512
- content: html`<x-link
513
+ content: html`<devtools-link
513
514
  href=${CODE_SNIPPET_WARNING_URL}
514
515
  class="link devtools-link"
515
- jslog=${VisualLogging.link('explain.teaser.code-snippets-explainer').track({
516
- click: true
517
- })}
518
- >${lockedString(UIStringsNotTranslate.freDisclaimerTextUseWithCaution)}</x-link>`,
516
+ .jslogContext=${'explain.teaser.code-snippets-explainer'}
517
+ >${lockedString(UIStringsNotTranslate.freDisclaimerTextUseWithCaution)}</devtools-link>`,
519
518
  // clang-format on
520
519
  }
521
520
  ],
@@ -483,7 +483,7 @@ function renderContrastIssue(key: string, issues: ContrastIssue[]): TemplateResu
483
483
  const color = (minContrastIssue.textColor.asString(Common.Color.Format.HEXA));
484
484
  const backgroundColor = (minContrastIssue.backgroundColor.asString(Common.Color.Format.HEXA));
485
485
 
486
- const showAPCA = Root.Runtime.experiments.isEnabled('apca');
486
+ const showAPCA = Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.APCA);
487
487
 
488
488
  const title = i18nString(UIStrings.textColorSOverSBackgroundResults, {
489
489
  PH1: color,
@@ -1041,7 +1041,7 @@ function renderContrastRatio(data: PopulateNodesEventNodeTypes): TemplateResult
1041
1041
  if (!('contrastRatio' in data)) {
1042
1042
  throw new Error('Contrast ratio entry is missing a contrast ratio.');
1043
1043
  }
1044
- const showAPCA = Root.Runtime.experiments.isEnabled('apca');
1044
+ const showAPCA = Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.APCA);
1045
1045
  const contrastRatio = Platform.NumberUtilities.floor(data.contrastRatio, 2);
1046
1046
  const contrastRatioString = showAPCA ? contrastRatio + '%' : contrastRatio;
1047
1047
  const border = getBorderString(data.backgroundColor);
@@ -267,7 +267,7 @@ export class CSSOverviewModel extends SDK.SDKModel.SDKModel<void> {
267
267
  const formattedTextColor = formatColor(blendedTextColor);
268
268
  const formattedBackgroundColor = formatColor(blendedBackgroundColor.asLegacyColor());
269
269
  const key = `${formattedTextColor}_${formattedBackgroundColor}`;
270
- if (Root.Runtime.experiments.isEnabled('apca')) {
270
+ if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.APCA)) {
271
271
  const contrastRatio = contrastInfo.contrastRatioAPCA();
272
272
  const threshold = contrastInfo.contrastRatioAPCAThreshold();
273
273
  const passes = contrastRatio && threshold ? Math.abs(contrastRatio) >= threshold : false;
@@ -18,13 +18,12 @@ export class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper<Event
18
18
  private computedStylePromise?: Promise<ComputedStyle|null>;
19
19
  private currentTrackedNodeId?: number;
20
20
 
21
- constructor() {
21
+ constructor(node?: SDK.DOMModel.DOMNode|null) {
22
22
  super();
23
23
  this.#cssModel = null;
24
24
  this.eventListeners = [];
25
- this.#node = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);
25
+ this.#node = node ?? null;
26
26
 
27
- UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this.onNodeChanged, this);
28
27
  UI.Context.Context.instance().addFlavorChangeListener(
29
28
  StylesSidebarPane, this.evaluateTrackingComputedStyleUpdatesForNode, this);
30
29
  UI.Context.Context.instance().addFlavorChangeListener(
@@ -32,17 +31,23 @@ export class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper<Event
32
31
  }
33
32
 
34
33
  dispose(): void {
35
- UI.Context.Context.instance().removeFlavorChangeListener(SDK.DOMModel.DOMNode, this.onNodeChanged, this);
36
34
  UI.Context.Context.instance().removeFlavorChangeListener(
37
35
  StylesSidebarPane, this.evaluateTrackingComputedStyleUpdatesForNode, this);
38
36
  UI.Context.Context.instance().removeFlavorChangeListener(
39
37
  ComputedStyleWidget, this.evaluateTrackingComputedStyleUpdatesForNode, this);
40
38
  }
41
39
 
42
- node(): SDK.DOMModel.DOMNode|null {
40
+ get node(): SDK.DOMModel.DOMNode|null {
43
41
  return this.#node;
44
42
  }
45
43
 
44
+ set node(node: SDK.DOMModel.DOMNode|null) {
45
+ this.#node = node;
46
+ this.updateModel(this.#node ? this.#node.domModel().cssModel() : null);
47
+ this.onCSSModelChanged(null);
48
+ this.evaluateTrackingComputedStyleUpdatesForNode();
49
+ }
50
+
46
51
  cssModel(): SDK.CSSModel.CSSModel|null {
47
52
  return this.#cssModel?.isEnabled() ? this.#cssModel : null;
48
53
  }
@@ -82,13 +87,6 @@ export class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper<Event
82
87
  }
83
88
  }, 100);
84
89
 
85
- private onNodeChanged(event: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMNode|null>): void {
86
- this.#node = event.data;
87
- this.updateModel(this.#node ? this.#node.domModel().cssModel() : null);
88
- this.onCSSModelChanged(null);
89
- this.evaluateTrackingComputedStyleUpdatesForNode();
90
- }
91
-
92
90
  private updateModel(cssModel: SDK.CSSModel.CSSModel|null): void {
93
91
  if (this.#cssModel === cssModel) {
94
92
  return;
@@ -155,7 +153,7 @@ export class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper<Event
155
153
  }
156
154
 
157
155
  private elementNode(): SDK.DOMModel.DOMNode|null {
158
- const node = this.node();
156
+ const node = this.node;
159
157
  if (!node) {
160
158
  return null;
161
159
  }
@@ -319,7 +319,7 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
319
319
  return link;
320
320
  }
321
321
  return null;
322
- }, () => this.computedStyleModel.node());
322
+ }, () => this.computedStyleModel.node);
323
323
 
324
324
  const fontsWidget = new PlatformFontsWidget(this.computedStyleModel);
325
325
  fontsWidget.show(this.contentElement);
@@ -356,7 +356,7 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
356
356
  }
357
357
 
358
358
  private async fetchMatchedCascade(): Promise<SDK.CSSMatchedStyles.CSSMatchedStyles|null> {
359
- const node = this.computedStyleModel.node();
359
+ const node = this.computedStyleModel.node;
360
360
  if (!node || !this.computedStyleModel.cssModel()) {
361
361
  return null;
362
362
  }
@@ -370,7 +370,7 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
370
370
 
371
371
  function validateStyles(this: ComputedStyleWidget, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null):
372
372
  SDK.CSSMatchedStyles.CSSMatchedStyles|null {
373
- return matchedStyles && matchedStyles.node() === this.computedStyleModel.node() ? matchedStyles : null;
373
+ return matchedStyles && matchedStyles.node() === this.computedStyleModel.node ? matchedStyles : null;
374
374
  }
375
375
  }
376
376
 
@@ -263,7 +263,7 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
263
263
  this.mainContainer = document.createElement('div');
264
264
  this.domTreeContainer = document.createElement('div');
265
265
  const crumbsContainer = document.createElement('div');
266
- if (Root.Runtime.experiments.isEnabled('full-accessibility-tree')) {
266
+ if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.FULL_ACCESSIBILITY_TREE)) {
267
267
  this.initializeFullAccessibilityTreeView();
268
268
  }
269
269
  this.mainContainer.appendChild(this.domTreeContainer);
@@ -299,7 +299,10 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
299
299
 
300
300
  crumbsContainer.appendChild(this.breadcrumbs);
301
301
 
302
- const computedStyleModel = new ComputedStyleModel();
302
+ const computedStyleModel = new ComputedStyleModel(UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode));
303
+ UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, event => {
304
+ computedStyleModel.node = event.data;
305
+ });
303
306
  this.stylesWidget = new StylesSidebarPane(computedStyleModel);
304
307
  this.computedStyleWidget = new ComputedStyleWidget(computedStyleModel);
305
308
  this.metricsWidget = new MetricsSidebarPane(computedStyleModel);
@@ -21,7 +21,7 @@ export class ElementsSidebarPane extends UI.Widget.VBox {
21
21
  }
22
22
 
23
23
  node(): SDK.DOMModel.DOMNode|null {
24
- return this.computedStyleModelInternal.node();
24
+ return this.computedStyleModelInternal.node;
25
25
  }
26
26
 
27
27
  cssModel(): SDK.CSSModel.CSSModel|null {
@@ -93,7 +93,7 @@ export class PlatformFontsWidget extends UI.Widget.VBox {
93
93
 
94
94
  override async performUpdate(): Promise<void> {
95
95
  const cssModel = this.sharedModel.cssModel();
96
- const node = this.sharedModel.node();
96
+ const node = this.sharedModel.node;
97
97
  if (!node || !cssModel) {
98
98
  this.#view({platformFonts: null}, {}, this.contentElement);
99
99
  return;
@@ -257,7 +257,7 @@ export class StylePropertiesSection {
257
257
  UI.ARIAUtils.setHidden(this.newStyleRuleToolbar, true);
258
258
  }
259
259
 
260
- if (Root.Runtime.experiments.isEnabled('font-editor') && this.editable) {
260
+ if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.FONT_EDITOR) && this.editable) {
261
261
  this.fontEditorToolbar = this.#styleRuleElement.createChild('devtools-toolbar', 'sidebar-pane-section-toolbar');
262
262
  this.fontEditorSectionManager = new FontEditorSectionManager(this.parentPane.swatchPopoverHelper(), this);
263
263
  this.fontEditorButton =
@@ -2348,7 +2348,7 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
2348
2348
  this.name, this.style, this.#parentPane, this.#matchedStyles, this, this.getComputedStyles() ?? new Map()) :
2349
2349
  [];
2350
2350
 
2351
- if (Root.Runtime.experiments.isEnabled('font-editor') && this.property.parsedOk) {
2351
+ if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.FONT_EDITOR) && this.property.parsedOk) {
2352
2352
  renderers.push(new FontRenderer(this));
2353
2353
  }
2354
2354
  this.listItemElement.removeChildren();