chrome-devtools-frontend 1.0.1543082 → 1.0.1544076

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 (149) hide show
  1. package/AUTHORS +2 -0
  2. package/front_end/core/common/Gzip.ts +4 -4
  3. package/front_end/core/common/common.ts +0 -2
  4. package/front_end/core/host/AidaClient.ts +10 -7
  5. package/front_end/core/host/DispatchHttpRequestClient.ts +18 -3
  6. package/front_end/core/root/DevToolsContext.ts +60 -0
  7. package/front_end/core/root/Runtime.ts +8 -7
  8. package/front_end/core/root/root.ts +6 -1
  9. package/front_end/core/sdk/CPUThrottlingManager.ts +0 -4
  10. package/front_end/core/sdk/CSSMatchedStyles.ts +7 -9
  11. package/front_end/core/sdk/CSSModel.ts +1 -1
  12. package/front_end/core/sdk/CSSRule.ts +18 -6
  13. package/front_end/core/sdk/ChildTargetManager.ts +2 -2
  14. package/front_end/core/sdk/TargetManager.ts +5 -6
  15. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +2 -0
  16. package/front_end/entrypoints/inspector_main/InspectorMain.ts +1 -13
  17. package/front_end/entrypoints/main/MainImpl.ts +2 -20
  18. package/front_end/foundation/Universe.ts +24 -1
  19. package/front_end/models/ai_assistance/agents/AiAgent.ts +10 -8
  20. package/front_end/models/ai_assistance/agents/PatchAgent.ts +7 -1
  21. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +0 -5
  22. package/front_end/models/ai_assistance/agents/StylingAgent.ts +4 -8
  23. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +1 -1
  24. package/front_end/models/ai_code_generation/AiCodeGeneration.ts +5 -3
  25. package/front_end/models/bindings/CSSWorkspaceBinding.ts +8 -7
  26. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +19 -15
  27. package/front_end/models/bindings/ResourceMapping.ts +57 -15
  28. package/front_end/models/live-metrics/LiveMetrics.ts +12 -20
  29. package/front_end/models/trace/handlers/SamplesHandler.ts +64 -6
  30. package/front_end/models/trace/types/TraceEvents.ts +16 -0
  31. package/front_end/models/workspace/IgnoreListManager.ts +10 -9
  32. package/front_end/models/workspace/WorkspaceImpl.ts +5 -10
  33. package/front_end/panels/accessibility/AccessibilityNodeView.ts +6 -2
  34. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +1 -1
  35. package/front_end/panels/ai_assistance/components/ChatView.ts +2 -4
  36. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +2 -1
  37. package/front_end/panels/animation/AnimationTimeline.ts +6 -6
  38. package/front_end/panels/application/ApplicationPanelSidebar.ts +0 -1
  39. package/front_end/panels/application/OpenedWindowDetailsView.ts +0 -2
  40. package/front_end/panels/application/ServiceWorkersView.ts +0 -2
  41. package/front_end/panels/application/StorageView.ts +0 -1
  42. package/front_end/panels/application/components/FrameDetailsView.ts +468 -447
  43. package/front_end/panels/application/components/ReportsGrid.ts +7 -2
  44. package/front_end/panels/application/components/SharedStorageAccessGrid.ts +5 -3
  45. package/front_end/panels/application/components/TrustTokensView.ts +7 -1
  46. package/front_end/panels/application/preloading/PreloadingView.ts +10 -4
  47. package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +7 -11
  48. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +15 -3
  49. package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +12 -13
  50. package/front_end/panels/{elements → common}/DOMLinkifier.ts +6 -6
  51. package/front_end/panels/common/common.ts +1 -0
  52. package/front_end/panels/console/ConsoleView.ts +9 -7
  53. package/front_end/panels/console/ConsoleViewMessage.ts +23 -13
  54. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +2 -1
  55. package/front_end/panels/elements/ElementsTreeElement.ts +3 -1
  56. package/front_end/panels/elements/StylePropertiesSection.ts +52 -15
  57. package/front_end/panels/elements/StylePropertyTreeElement.ts +8 -3
  58. package/front_end/panels/elements/StylesSidebarPane.ts +24 -14
  59. package/front_end/panels/elements/elements-meta.ts +11 -2
  60. package/front_end/panels/elements/elements.ts +0 -3
  61. package/front_end/panels/explain/components/ConsoleInsight.ts +333 -318
  62. package/front_end/panels/issues/AffectedResourcesView.ts +2 -1
  63. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +2 -1
  64. package/front_end/panels/network/NetworkLogView.ts +1 -1
  65. package/front_end/panels/recorder/RecorderController.ts +7 -1
  66. package/front_end/panels/settings/SettingsScreen.ts +3 -6
  67. package/front_end/panels/settings/components/SyncSection.ts +218 -226
  68. package/front_end/panels/settings/components/syncSection.css +81 -80
  69. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +42 -294
  70. package/front_end/panels/sources/DebuggerPausedMessage.ts +3 -3
  71. package/front_end/panels/sources/DebuggerPlugin.ts +3 -1
  72. package/front_end/panels/sources/ResourceOriginPlugin.ts +7 -3
  73. package/front_end/panels/sources/SourcesPanel.ts +5 -1
  74. package/front_end/panels/timeline/TimelinePanel.ts +0 -21
  75. package/front_end/panels/timeline/TimelineUIUtils.ts +3 -2
  76. package/front_end/panels/timeline/components/LiveMetricsView.ts +7 -4
  77. package/front_end/panels/timeline/components/insights/NodeLink.ts +3 -2
  78. package/front_end/third_party/puppeteer/README.chromium +2 -2
  79. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.d.ts +1 -0
  80. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
  81. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.js +4 -1
  82. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.js.map +1 -1
  83. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkEventManager.d.ts +1 -0
  84. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkEventManager.d.ts.map +1 -1
  85. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkEventManager.js +8 -0
  86. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkEventManager.js.map +1 -1
  87. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  88. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js +22 -0
  89. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js.map +1 -1
  90. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  91. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  92. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  93. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
  94. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  95. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  96. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  97. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +34 -6
  98. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.d.ts +1 -0
  99. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
  100. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.js +4 -1
  101. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.js.map +1 -1
  102. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkEventManager.d.ts +1 -0
  103. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkEventManager.d.ts.map +1 -1
  104. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkEventManager.js +8 -0
  105. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkEventManager.js.map +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  107. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js +22 -0
  108. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js.map +1 -1
  109. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  110. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  111. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  113. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  114. package/front_end/third_party/puppeteer/package/package.json +2 -2
  115. package/front_end/third_party/puppeteer/package/src/cdp/HTTPRequest.ts +5 -1
  116. package/front_end/third_party/puppeteer/package/src/cdp/NetworkEventManager.ts +16 -1
  117. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +28 -0
  118. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  119. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  120. package/front_end/ui/components/docs/component_docs.ts +0 -4
  121. package/front_end/ui/components/report_view/ReportView.ts +4 -1
  122. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +8 -5
  123. package/front_end/ui/i18n/i18n.ts +16 -0
  124. package/front_end/ui/legacy/ReportView.ts +0 -5
  125. package/front_end/ui/legacy/TextPrompt.ts +65 -19
  126. package/front_end/ui/legacy/UIUtils.ts +1 -1
  127. package/front_end/ui/legacy/Widget.ts +56 -25
  128. package/front_end/ui/legacy/XLink.ts +0 -2
  129. package/front_end/ui/legacy/components/object_ui/JavaScriptREPL.ts +8 -4
  130. package/front_end/ui/legacy/components/object_ui/ObjectPopoverHelper.ts +3 -1
  131. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +239 -284
  132. package/front_end/ui/legacy/components/object_ui/RemoteObjectPreviewFormatter.ts +114 -184
  133. package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -1
  134. package/front_end/ui/legacy/inspectorCommon.css +0 -4
  135. package/front_end/ui/{components/docs/theme_colors/basic.ts → legacy/theme_support/ThemeColors.docs.ts} +33 -23
  136. package/mcp/mcp.ts +1 -0
  137. package/package.json +1 -1
  138. package/front_end/core/common/QueryParamHandler.ts +0 -7
  139. package/front_end/ui/components/docs/input/basic.html +0 -31
  140. package/front_end/ui/components/docs/input/basic.ts +0 -12
  141. package/front_end/ui/components/docs/report/basic.html +0 -27
  142. package/front_end/ui/components/docs/report/basic.ts +0 -48
  143. package/front_end/ui/components/docs/theme_colors/basic.html +0 -56
  144. package/front_end/ui/components/docs/toggle_dark_mode.ts +0 -36
  145. package/front_end/ui/components/docs/toggle_fonts.ts +0 -74
  146. package/front_end/ui/components/docs/user_agent_client_hints/basic.html +0 -25
  147. package/front_end/ui/components/docs/user_agent_client_hints/basic.ts +0 -26
  148. package/front_end/ui/components/expandable_list/ExpandableList.docs.ts +0 -30
  149. /package/front_end/panels/{elements → common}/domLinkifier.css +0 -0
@@ -58,7 +58,7 @@ export const AIDA_REQUEST_DEBOUNCE_TIMEOUT_MS = 200;
58
58
  const MAX_PREFIX_SUFFIX_LENGTH = 20_000;
59
59
 
60
60
  export class AiCodeCompletionProvider {
61
- #aidaClient?: Host.AidaClient.AidaClient;
61
+ #aidaClient: Host.AidaClient.AidaClient = new Host.AidaClient.AidaClient();
62
62
  #aiCodeCompletion?: AiCodeCompletion.AiCodeCompletion.AiCodeCompletion;
63
63
  #aiCodeCompletionSetting = Common.Settings.Settings.instance().createSetting('ai-code-completion-enabled', false);
64
64
  #aiCodeCompletionTeaserDismissedSetting =
@@ -71,7 +71,7 @@ export class AiCodeCompletionProvider {
71
71
 
72
72
  #boundOnUpdateAiCodeCompletionState = this.#updateAiCodeCompletionState.bind(this);
73
73
 
74
- constructor(aiCodeCompletionConfig: AiCodeCompletionConfig) {
74
+ private constructor(aiCodeCompletionConfig: AiCodeCompletionConfig) {
75
75
  const devtoolsLocale = i18n.DevToolsLocale.DevToolsLocale.instance();
76
76
  if (!AiCodeCompletion.AiCodeCompletion.AiCodeCompletion.isAiCodeCompletionEnabled(devtoolsLocale.locale)) {
77
77
  throw new Error('AI code completion feature is not enabled.');
@@ -79,6 +79,10 @@ export class AiCodeCompletionProvider {
79
79
  this.#aiCodeCompletionConfig = aiCodeCompletionConfig;
80
80
  }
81
81
 
82
+ static createInstance(aiCodeCompletionConfig: AiCodeCompletionConfig): AiCodeCompletionProvider {
83
+ return new AiCodeCompletionProvider(aiCodeCompletionConfig);
84
+ }
85
+
82
86
  extension(): CodeMirror.Extension[] {
83
87
  return [
84
88
  CodeMirror.EditorView.updateListener.of(update => this.#triggerAiCodeCompletion(update)),
@@ -118,13 +122,12 @@ export class AiCodeCompletionProvider {
118
122
  this.#aiCodeCompletion?.clearCachedRequest();
119
123
  }
120
124
 
125
+ // TODO(b/445394511): Update setup and cleanup method so that config callbacks are not
126
+ // called twice.
121
127
  #setupAiCodeCompletion(): void {
122
128
  if (!this.#editor || !this.#aiCodeCompletionConfig) {
123
129
  return;
124
130
  }
125
- if (!this.#aidaClient) {
126
- this.#aidaClient = new Host.AidaClient.AidaClient();
127
- }
128
131
  if (!this.#aiCodeCompletion) {
129
132
  this.#aiCodeCompletion = new AiCodeCompletion.AiCodeCompletion.AiCodeCompletion(
130
133
  {aidaClient: this.#aidaClient}, this.#aiCodeCompletionConfig.panel, undefined,
@@ -6,7 +6,9 @@
6
6
 
7
7
  import * as I18n from '../../core/i18n/i18n.js';
8
8
  import type * as ThirdPartyI18n from '../../third_party/i18n/i18n.js';
9
+ import {Directives, html, type LitTemplate, nothing} from '../lit/lit.js';
9
10
 
11
+ const {repeat} = Directives;
10
12
  /**
11
13
  * Returns a span element that may contains other DOM element as placeholders
12
14
  */
@@ -29,3 +31,17 @@ export function getFormatLocalizedString(
29
31
  }
30
32
  return element;
31
33
  }
34
+
35
+ export function getFormatLocalizedStringTemplate(
36
+ registeredStrings: ThirdPartyI18n.LocalizedStringSet.RegisteredFileStrings, stringId: string,
37
+ placeholders: Record<string, Object>): LitTemplate {
38
+ const formatter = registeredStrings.getLocalizedStringSetFor(I18n.DevToolsLocale.DevToolsLocale.instance().locale)
39
+ .getMessageFormatterFor(stringId);
40
+
41
+ return html`<span>${
42
+ repeat(
43
+ formatter.getAst(),
44
+ icuElement => icuElement.type === /* argumentElement */ 1 ? (placeholders[icuElement.value] ?? nothing) :
45
+ 'value' in icuElement ? String(icuElement.value) :
46
+ nothing)}</span>`;
47
+ }
@@ -13,11 +13,6 @@ import reportViewStyles from './reportView.css.js';
13
13
  import type {Toolbar} from './Toolbar.js';
14
14
  import {Tooltip} from './Tooltip.js';
15
15
  import {VBox} from './Widget.js';
16
-
17
- /**
18
- * @deprecated Please consider using the web component version of this widget
19
- * (`ui/components/report_view/ReportView.ts`) for new code.
20
- */
21
16
  export class ReportView extends VBox {
22
17
  private readonly contentBox: HTMLElement;
23
18
  private headerElement: HTMLElement;
@@ -57,50 +57,87 @@ import {cloneCustomElement, ElementFocusRestorer} from './UIUtils.js';
57
57
  *
58
58
  * @property completionTimeout Sets the delay for showing the autocomplete suggestion box.
59
59
  * @event commit Editing is done and the result was accepted.
60
- * @event expand Editing was canceled.
60
+ * @event cancel Editing was canceled.
61
61
  * @event beforeautocomplete This is sent before the autocomplete suggestion box is triggered and before the <datalist>
62
62
  * is read.
63
63
  * @attribute editing Setting/removing this attribute starts/stops editing.
64
64
  * @attribute completions Sets the `id` of the <datalist> containing the autocomplete options.
65
+ * @attribute placeholder Sets a placeholder that's shown in place of the text contents when editing if the text is too
66
+ * large.
65
67
  */
66
68
  export class TextPromptElement extends HTMLElement {
67
- static readonly observedAttributes = ['editing', 'completions'];
69
+ static readonly observedAttributes = ['editing', 'completions', 'placeholder'];
68
70
  readonly #shadow = this.attachShadow({mode: 'open'});
69
71
  readonly #entrypoint = this.#shadow.createChild('span');
70
72
  readonly #slot = this.#entrypoint.createChild('slot');
71
73
  readonly #textPrompt = new TextPrompt();
72
74
  #completionTimeout: number|null = null;
75
+ #completionObserver = new MutationObserver(this.#onMutate.bind(this));
73
76
 
74
77
  constructor() {
75
78
  super();
76
79
  this.#textPrompt.initialize(this.#willAutoComplete.bind(this));
77
80
  }
78
81
 
82
+ #onMutate(changes: MutationRecord[]): void {
83
+ const listId = this.getAttribute('completions');
84
+ if (!listId) {
85
+ return;
86
+ }
87
+ const checkIfNodeIsInCompletionList = (node: Node): boolean => {
88
+ if (node instanceof HTMLDataListElement) {
89
+ return node.id === listId;
90
+ }
91
+ if (node instanceof HTMLOptionElement) {
92
+ return Boolean(node.parentElement && checkIfNodeIsInCompletionList(node.parentElement));
93
+ }
94
+ return false;
95
+ };
96
+ const affectsCompletionList = (change: MutationRecord): boolean =>
97
+ change.addedNodes.values().some(checkIfNodeIsInCompletionList) ||
98
+ change.removedNodes.values().some(checkIfNodeIsInCompletionList) ||
99
+ checkIfNodeIsInCompletionList(change.target);
100
+
101
+ if (changes.some(affectsCompletionList)) {
102
+ this.#updateCompletions();
103
+ }
104
+ }
105
+
79
106
  attributeChangedCallback(name: string, oldValue: string|null, newValue: string|null): void {
80
- if (oldValue === newValue || !this.isConnected) {
107
+ if (oldValue === newValue) {
81
108
  return;
82
109
  }
83
110
 
84
111
  switch (name) {
85
112
  case 'editing':
86
- if (newValue !== null && newValue !== 'false' && oldValue === null) {
87
- this.#startEditing();
88
- } else {
89
- this.#stopEditing();
113
+ if (this.isConnected) {
114
+ if (newValue !== null && newValue !== 'false' && oldValue === null) {
115
+ this.#startEditing();
116
+ } else {
117
+ this.#stopEditing();
118
+ }
90
119
  }
91
120
  break;
92
121
  case 'completions':
93
- if (this.#textPrompt.isSuggestBoxVisible()) {
94
- void this.#textPrompt.complete(/* force=*/ true);
122
+ if (this.getAttribute('completions')) {
123
+ this.#completionObserver.observe(this, {childList: true, subtree: true});
124
+ this.#updateCompletions();
125
+ } else {
126
+ this.#textPrompt.clearAutocomplete();
127
+ this.#completionObserver.disconnect();
95
128
  }
96
129
  break;
97
130
  }
98
131
  }
99
132
 
100
- async #willAutoComplete(expression?: string, filter?: string, force?: boolean): Promise<Suggestion[]> {
101
- if (!force) {
102
- this.dispatchEvent(new TextPromptElement.BeforeAutoCompleteEvent({expression, filter}));
133
+ #updateCompletions(): void {
134
+ if (this.isConnected) {
135
+ void this.#textPrompt.complete(/* force=*/ true);
103
136
  }
137
+ }
138
+
139
+ async #willAutoComplete(expression: string, filter: string, force: boolean): Promise<Suggestion[]> {
140
+ this.dispatchEvent(new TextPromptElement.BeforeAutoCompleteEvent({expression, filter, force}));
104
141
 
105
142
  const listId = this.getAttribute('completions');
106
143
  if (!listId) {
@@ -112,16 +149,20 @@ export class TextPromptElement extends HTMLElement {
112
149
  return [];
113
150
  }
114
151
 
115
- filter = filter?.toLowerCase();
116
152
  return datalist.values()
117
- .filter(option => option.textContent.startsWith(filter ?? ''))
153
+ .filter(option => option.textContent.startsWith(filter.toLowerCase()))
118
154
  .map(option => ({text: option.textContent}))
119
155
  .toArray();
120
156
  }
121
157
 
122
158
  #startEditing(): void {
159
+ const truncatedTextPlaceholder = this.getAttribute('placeholder');
123
160
  const placeholder = this.#entrypoint.createChild('span');
124
- placeholder.textContent = this.#slot.deepInnerText();
161
+ if (truncatedTextPlaceholder === null) {
162
+ placeholder.textContent = this.#slot.deepInnerText();
163
+ } else {
164
+ placeholder.setTextContentTruncatedIfNeeded(this.#slot.deepInnerText(), truncatedTextPlaceholder);
165
+ }
125
166
  this.#slot.remove();
126
167
 
127
168
  const proxy = this.#textPrompt.attachAndStartEditing(placeholder, e => this.#done(e, /* commit=*/ true));
@@ -189,8 +230,8 @@ export namespace TextPromptElement {
189
230
  super('cancel');
190
231
  }
191
232
  }
192
- export class BeforeAutoCompleteEvent extends CustomEvent<{expression?: string, filter?: string}> {
193
- constructor(detail: {expression?: string, filter?: string}) {
233
+ export class BeforeAutoCompleteEvent extends CustomEvent<{expression: string, filter: string, force: boolean}> {
234
+ constructor(detail: {expression: string, filter: string, force: boolean}) {
194
235
  super('beforeautocomplete', {detail});
195
236
  }
196
237
  }
@@ -215,7 +256,12 @@ export class TextPrompt extends Common.ObjectWrapper.ObjectWrapper<EventTypes> i
215
256
  private completionRequestId: number;
216
257
  private ghostTextElement: HTMLSpanElement;
217
258
  private leftParenthesesIndices: number[];
218
- private loadCompletions!: (this: null, arg1: string, arg2: string, arg3?: boolean|undefined) => Promise<Suggestion[]>;
259
+ private loadCompletions!: (
260
+ this: null,
261
+ arg1: string,
262
+ arg2: string,
263
+ arg3: boolean,
264
+ ) => Promise<Suggestion[]>;
219
265
  private completionStopCharacters!: string;
220
266
  private usesSuggestionBuilder!: boolean;
221
267
  #element?: Element;
@@ -251,7 +297,7 @@ export class TextPrompt extends Common.ObjectWrapper.ObjectWrapper<EventTypes> i
251
297
  }
252
298
 
253
299
  initialize(
254
- completions: (this: null, expression: string, filter: string, force?: boolean|undefined) => Promise<Suggestion[]>,
300
+ completions: (this: null, expression: string, filter: string, force: boolean) => Promise<Suggestion[]>,
255
301
  stopCharacters?: string, usesSuggestionBuilder?: boolean): void {
256
302
  this.loadCompletions = completions;
257
303
  this.completionStopCharacters = stopCharacters || ' =:[({;,!+-*/&|^<>.';
@@ -1923,7 +1923,7 @@ function updateWidgetfocusWidgetForNode(node: Node|null): void {
1923
1923
  break;
1924
1924
  }
1925
1925
 
1926
- parentWidget.defaultFocusedChild = widget;
1926
+ parentWidget.setDefaultFocusedChild(widget);
1927
1927
  widget = parentWidget;
1928
1928
  }
1929
1929
  }
@@ -330,7 +330,6 @@ export interface WidgetOptions {
330
330
  export class Widget {
331
331
  readonly element: HTMLElement;
332
332
  contentElement: HTMLElement;
333
- defaultFocusedChild: Widget|null = null;
334
333
  #shadowRoot: typeof Element.prototype.shadowRoot;
335
334
  #visible = false;
336
335
  #isRoot = false;
@@ -632,6 +631,10 @@ export class Widget {
632
631
  originalAppendChild.call(parentElement, this.element);
633
632
  }
634
633
  }
634
+ const focusedElementsCount = this.#parentWidget?.getDefaultFocusedElements?.()?.length ?? 0;
635
+ if (this.element.hasAttribute('autofocus') && focusedElementsCount > 1) {
636
+ this.element.removeAttribute('autofocus');
637
+ }
635
638
 
636
639
  if (!wasVisible && this.parentIsShowing()) {
637
640
  this.processWasShown();
@@ -707,9 +710,6 @@ export class Widget {
707
710
  const childIndex = this.#parentWidget.#children.indexOf(this);
708
711
  assert(childIndex >= 0, 'Attempt to remove non-child widget');
709
712
  this.#parentWidget.#children.splice(childIndex, 1);
710
- if (this.#parentWidget.defaultFocusedChild === this) {
711
- this.#parentWidget.defaultFocusedChild = null;
712
- }
713
713
  this.#parentWidget.childWasDetached(this);
714
714
  this.#parentWidget = null;
715
715
  } else {
@@ -801,22 +801,48 @@ export class Widget {
801
801
 
802
802
  setDefaultFocusedChild(child: Widget): void {
803
803
  assert(child.#parentWidget === this, 'Attempt to set non-child widget as default focused.');
804
- this.defaultFocusedChild = child;
804
+
805
+ const defaultFocusedElement = this.getDefaultFocusedElement();
806
+ if (defaultFocusedElement) {
807
+ defaultFocusedElement.removeAttribute('autofocus');
808
+ }
809
+ child.element.setAttribute('autofocus', '');
805
810
  }
806
811
 
807
- getDefaultFocusedElement(): HTMLElement|null {
808
- const autofocusElement = this.contentElement.hasAttribute('autofocus') ?
809
- this.contentElement :
810
- this.contentElement.querySelector<HTMLElement>('[autofocus]');
811
- let widgetElement: Element|null = autofocusElement;
812
- while (widgetElement) {
813
- const widget = Widget.get(widgetElement);
814
- if (widget) {
815
- return widget === this ? autofocusElement : null;
812
+ getDefaultFocusedElements(): HTMLElement[] {
813
+ const autofocusElements = [...this.contentElement.querySelectorAll<HTMLElement>('[autofocus]')];
814
+ if (this.contentElement !== this.element) {
815
+ if (this.contentElement.hasAttribute('autofocus')) {
816
+ autofocusElements.push(this.contentElement);
817
+ }
818
+ if (autofocusElements.length === 0) {
819
+ autofocusElements.push(...this.element.querySelectorAll<HTMLElement>('[autofocus]'));
820
+ }
821
+ }
822
+ return autofocusElements.filter(autofocusElement => {
823
+ let widgetElement: Element|null = autofocusElement;
824
+ while (widgetElement) {
825
+ const widget = Widget.get(widgetElement);
826
+ if (widget) {
827
+ if (widgetElement === autofocusElement && widget.#parentWidget === this && widget.#visible) {
828
+ return true;
829
+ }
830
+ return widget === this;
831
+ }
832
+ widgetElement = widgetElement.parentElementOrShadowHost();
816
833
  }
817
- widgetElement = widgetElement.parentElementOrShadowHost();
834
+ return false;
835
+ });
836
+ }
837
+
838
+ getDefaultFocusedElement(): HTMLElement|null {
839
+ const elements = this.getDefaultFocusedElements();
840
+ if (elements.length > 1) {
841
+ console.error(
842
+ 'Multiple autofocus elements found', this.constructor.name,
843
+ ...elements.map(e => Platform.StringUtilities.trimMiddle(e.outerHTML, 250)));
818
844
  }
819
- return null;
845
+ return elements[0] || null;
820
846
  }
821
847
 
822
848
  focus(): void {
@@ -825,20 +851,25 @@ export class Widget {
825
851
  }
826
852
  const autofocusElement = this.getDefaultFocusedElement();
827
853
  if (autofocusElement) {
828
- autofocusElement.focus();
854
+ const widget = Widget.get(autofocusElement);
855
+ if (widget && widget !== this) {
856
+ widget.focus();
857
+ } else {
858
+ autofocusElement.focus();
859
+ }
829
860
  return;
830
861
  }
831
862
 
832
- if (this.defaultFocusedChild && this.defaultFocusedChild.#visible) {
833
- this.defaultFocusedChild.focus();
834
- } else {
835
- for (const child of this.#children) {
836
- if (child.#visible) {
837
- child.focus();
838
- return;
839
- }
863
+ for (const child of this.#children) {
864
+ if (child.#visible) {
865
+ child.focus();
866
+ return;
840
867
  }
841
868
  }
869
+
870
+ if (this.element === this.contentElement && this.element.hasAttribute('autofocus')) {
871
+ this.element.focus();
872
+ }
842
873
  }
843
874
 
844
875
  hasFocus(): boolean {
@@ -56,7 +56,6 @@ export class XLink extends XElement {
56
56
  if (this.#href) {
57
57
  openInNewTab(this.#href);
58
58
  }
59
- this.dispatchEvent(new Event('x-link-invoke'));
60
59
  };
61
60
  this.onKeyDown = (event: KeyboardEvent) => {
62
61
  if (Platform.KeyboardUtilities.isEnterOrSpaceKey(event)) {
@@ -65,7 +64,6 @@ export class XLink extends XElement {
65
64
  openInNewTab(this.#href);
66
65
  }
67
66
  }
68
- this.dispatchEvent(new Event('x-link-invoke'));
69
67
  };
70
68
  }
71
69
 
@@ -7,6 +7,7 @@ import * as SDK from '../../../../core/sdk/sdk.js';
7
7
  import * as Formatter from '../../../../models/formatter/formatter.js';
8
8
  import * as SourceMapScopes from '../../../../models/source_map_scopes/source_map_scopes.js';
9
9
  import * as Acorn from '../../../../third_party/acorn/acorn.js';
10
+ import {render} from '../../../lit/lit.js';
10
11
  import * as UI from '../../legacy.js';
11
12
 
12
13
  import {RemoteObjectPreviewFormatter} from './RemoteObjectPreviewFormatter.js';
@@ -103,11 +104,14 @@ export class JavaScriptREPL {
103
104
  const formatter = new RemoteObjectPreviewFormatter();
104
105
  const {preview, type, subtype, className, description} = result.object;
105
106
  if (preview && type === 'object' && subtype !== 'node' && subtype !== 'trustedtype') {
106
- formatter.appendObjectPreview(fragment, preview, false /* isEntry */);
107
+ /* eslint-disable-next-line @devtools/no-lit-render-outside-of-view */
108
+ render(formatter.renderObjectPreview(preview), fragment);
107
109
  } else {
108
- const nonObjectPreview = formatter.renderPropertyPreview(
109
- type, subtype, className, Platform.StringUtilities.trimEndWithMaxLength(description || '', 400));
110
- fragment.appendChild(nonObjectPreview);
110
+ /* eslint-disable-next-line @devtools/no-lit-render-outside-of-view */
111
+ render(
112
+ formatter.renderPropertyPreview(
113
+ type, subtype, className, Platform.StringUtilities.trimEndWithMaxLength(description || '', 400)),
114
+ fragment);
111
115
  }
112
116
  return fragment;
113
117
  }
@@ -8,6 +8,7 @@ import * as i18n from '../../../../core/i18n/i18n.js';
8
8
  import * as Platform from '../../../../core/platform/platform.js';
9
9
  import * as SDK from '../../../../core/sdk/sdk.js';
10
10
  import * as Geometry from '../../../../models/geometry/geometry.js';
11
+ import {render} from '../../../lit/lit.js';
11
12
  import * as UI from '../../legacy.js';
12
13
  import * as Components from '../utils/utils.js';
13
14
 
@@ -65,7 +66,8 @@ export class ObjectPopoverHelper {
65
66
  const titleElement = popoverContentElement.createChild('div', 'object-popover-title');
66
67
  if (result.type === 'function') {
67
68
  titleElement.classList.add('source-code');
68
- titleElement.appendChild(ObjectPropertiesSection.valueElementForFunctionDescription(result.description));
69
+ // eslint-disable-next-line @devtools/no-lit-render-outside-of-view
70
+ render(ObjectPropertiesSection.valueElementForFunctionDescription(result.description), titleElement);
69
71
  } else {
70
72
  titleElement.classList.add('monospace');
71
73
  titleElement.createChild('span').textContent = description;