chrome-devtools-frontend 1.0.1543472 → 1.0.1545096

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 (166) hide show
  1. package/AUTHORS +1 -0
  2. package/config/typescript/tsconfig.eslint.json +1 -0
  3. package/front_end/core/common/ParsedURL.ts +1 -1
  4. package/front_end/core/common/common.ts +0 -2
  5. package/front_end/core/host/AidaClient.ts +10 -7
  6. package/front_end/core/host/DispatchHttpRequestClient.ts +18 -3
  7. package/front_end/core/protocol_client/CDPConnection.ts +3 -3
  8. package/front_end/core/protocol_client/DevToolsCDPConnection.ts +2 -1
  9. package/front_end/core/root/Runtime.ts +8 -7
  10. package/front_end/core/sdk/CPUThrottlingManager.ts +0 -4
  11. package/front_end/core/sdk/CSSMatchedStyles.ts +7 -9
  12. package/front_end/core/sdk/CSSMetadata.ts +17 -5
  13. package/front_end/core/sdk/CSSModel.ts +1 -1
  14. package/front_end/core/sdk/CSSRule.ts +18 -6
  15. package/front_end/core/sdk/ChildTargetManager.ts +2 -2
  16. package/front_end/core/sdk/NetworkManager.ts +6 -8
  17. package/front_end/core/sdk/NetworkRequest.ts +4 -0
  18. package/front_end/core/sdk/SDKModel.ts +4 -2
  19. package/front_end/core/sdk/TargetManager.ts +14 -15
  20. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +2 -0
  21. package/front_end/entrypoints/main/MainImpl.ts +0 -16
  22. package/front_end/foundation/Universe.ts +12 -1
  23. package/front_end/generated/Deprecation.ts +4 -0
  24. package/front_end/generated/InspectorBackendCommands.ts +2 -5
  25. package/front_end/generated/SupportedCSSProperties.js +0 -23
  26. package/front_end/generated/protocol-mapping.d.ts +0 -15
  27. package/front_end/generated/protocol-proxy-api.d.ts +0 -11
  28. package/front_end/generated/protocol.ts +2 -34
  29. package/front_end/models/ai_assistance/agents/AiAgent.ts +10 -8
  30. package/front_end/models/ai_assistance/agents/PatchAgent.ts +7 -1
  31. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +0 -5
  32. package/front_end/models/ai_assistance/agents/StylingAgent.ts +4 -8
  33. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +1 -1
  34. package/front_end/models/ai_code_generation/AiCodeGeneration.ts +5 -3
  35. package/front_end/models/bindings/CSSWorkspaceBinding.ts +8 -7
  36. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +9 -8
  37. package/front_end/models/bindings/ResourceMapping.ts +57 -15
  38. package/front_end/models/live-metrics/LiveMetrics.ts +12 -20
  39. package/front_end/panels/accessibility/AccessibilityNodeView.ts +6 -2
  40. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +3 -2
  41. package/front_end/panels/ai_assistance/components/ChatView.ts +2 -4
  42. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +2 -1
  43. package/front_end/panels/ai_assistance/components/UserActionRow.ts +2 -1
  44. package/front_end/panels/animation/AnimationTimeline.ts +6 -6
  45. package/front_end/panels/application/ApplicationPanelSidebar.ts +6 -7
  46. package/front_end/panels/application/{components/FrameDetailsView.ts → FrameDetailsView.ts} +134 -165
  47. package/front_end/panels/application/{components/OriginTrialTreeView.ts → OriginTrialTreeView.ts} +9 -9
  48. package/front_end/panels/application/application.ts +4 -0
  49. package/front_end/panels/application/components/ReportsGrid.ts +7 -2
  50. package/front_end/panels/application/components/SharedStorageAccessGrid.ts +5 -3
  51. package/front_end/panels/application/components/StackTrace.ts +5 -3
  52. package/front_end/panels/application/components/TrustTokensView.ts +7 -1
  53. package/front_end/panels/application/components/components.ts +2 -4
  54. package/front_end/panels/application/{components/frameDetailsReportView.css → frameDetailsReportView.css} +5 -1
  55. package/front_end/panels/application/preloading/PreloadingView.ts +10 -4
  56. package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +7 -11
  57. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +15 -3
  58. package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +12 -13
  59. package/front_end/panels/common/BadgeNotification.ts +2 -1
  60. package/front_end/panels/{elements → common}/DOMLinkifier.ts +13 -8
  61. package/front_end/panels/common/GdpSignUpDialog.ts +2 -1
  62. package/front_end/panels/common/common.ts +1 -0
  63. package/front_end/panels/console/ConsoleViewMessage.ts +4 -4
  64. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +2 -1
  65. package/front_end/panels/elements/ElementStatePaneWidget.ts +2 -1
  66. package/front_end/panels/elements/ElementsTreeElement.ts +3 -1
  67. package/front_end/panels/elements/StylePropertiesSection.ts +52 -15
  68. package/front_end/panels/elements/StylePropertyTreeElement.ts +8 -3
  69. package/front_end/panels/elements/StylesSidebarPane.ts +24 -14
  70. package/front_end/panels/elements/elements-meta.ts +0 -13
  71. package/front_end/panels/elements/elements.ts +0 -3
  72. package/front_end/panels/explain/components/ConsoleInsight.ts +31 -20
  73. package/front_end/panels/issues/AffectedResourcesView.ts +2 -1
  74. package/front_end/panels/lighthouse/LighthouseProtocolService.ts +3 -6
  75. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +2 -1
  76. package/front_end/panels/network/NetworkLogView.ts +1 -1
  77. package/front_end/panels/recorder/RecorderController.ts +7 -1
  78. package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +2 -1
  79. package/front_end/panels/settings/SettingsScreen.ts +3 -2
  80. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +42 -294
  81. package/front_end/panels/sources/DebuggerPausedMessage.ts +3 -3
  82. package/front_end/panels/sources/SourcesPanel.ts +5 -1
  83. package/front_end/panels/timeline/TimelineUIUtils.ts +3 -2
  84. package/front_end/panels/timeline/components/LiveMetricsView.ts +18 -6
  85. package/front_end/panels/timeline/components/MetricCard.ts +2 -2
  86. package/front_end/panels/timeline/components/insights/NodeLink.ts +4 -4
  87. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +2 -1
  88. package/front_end/panels/timeline/timeline-meta.ts +0 -10
  89. package/front_end/panels/timeline/timeline.ts +0 -2
  90. package/front_end/panels/whats_new/ReleaseNoteView.ts +2 -1
  91. package/front_end/panels/whats_new/WhatsNewImpl.ts +3 -2
  92. package/front_end/third_party/chromium/README.chromium +1 -1
  93. package/front_end/third_party/puppeteer/README.chromium +2 -2
  94. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.d.ts +1 -0
  95. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
  96. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.js +4 -1
  97. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.js.map +1 -1
  98. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkEventManager.d.ts +1 -0
  99. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkEventManager.d.ts.map +1 -1
  100. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkEventManager.js +8 -0
  101. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkEventManager.js.map +1 -1
  102. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  103. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js +22 -0
  104. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js.map +1 -1
  105. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  107. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  108. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
  109. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  110. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  111. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +34 -6
  113. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.d.ts +1 -0
  114. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
  115. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.js +4 -1
  116. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.js.map +1 -1
  117. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkEventManager.d.ts +1 -0
  118. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkEventManager.d.ts.map +1 -1
  119. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkEventManager.js +8 -0
  120. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkEventManager.js.map +1 -1
  121. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  122. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js +22 -0
  123. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js.map +1 -1
  124. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  125. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  126. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
  127. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  129. package/front_end/third_party/puppeteer/package/package.json +2 -2
  130. package/front_end/third_party/puppeteer/package/src/cdp/HTTPRequest.ts +5 -1
  131. package/front_end/third_party/puppeteer/package/src/cdp/NetworkEventManager.ts +16 -1
  132. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +28 -0
  133. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  134. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  135. package/front_end/tsconfig.json +1 -0
  136. package/front_end/ui/components/buttons/Button.docs.ts +6 -5
  137. package/front_end/ui/components/snackbars/Snackbars.docs.ts +1 -1
  138. package/front_end/ui/components/spinners/Spinners.docs.ts +1 -1
  139. package/front_end/ui/components/survey_link/SurveyLink.docs.ts +2 -1
  140. package/front_end/ui/components/switch/Switch.docs.ts +1 -1
  141. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +8 -5
  142. package/front_end/ui/components/tooltips/Tooltip.docs.ts +3 -3
  143. package/front_end/ui/helpers/OpenInNewTab.ts +87 -0
  144. package/front_end/ui/helpers/helpers.ts +5 -0
  145. package/front_end/ui/i18n/i18n.ts +16 -0
  146. package/front_end/ui/legacy/ContextMenu.docs.ts +12 -11
  147. package/front_end/ui/legacy/RadioButton.docs.ts +1 -1
  148. package/front_end/ui/legacy/SelectMenu.docs.ts +1 -1
  149. package/front_end/ui/legacy/Slider.docs.ts +1 -1
  150. package/front_end/ui/legacy/UIUtils.ts +1 -34
  151. package/front_end/ui/legacy/Widget.ts +56 -25
  152. package/front_end/ui/legacy/XLink.ts +4 -6
  153. package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +2 -1
  154. package/front_end/ui/legacy/components/object_ui/ObjectPopoverHelper.ts +3 -1
  155. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +294 -336
  156. package/front_end/ui/legacy/components/utils/Linkifier.ts +2 -1
  157. package/front_end/ui/legacy/inspectorCommon.css +0 -4
  158. package/mcp/mcp.ts +1 -0
  159. package/mcp/tsconfig.json +16 -0
  160. package/package.json +2 -2
  161. package/front_end/core/common/Linkifier.ts +0 -55
  162. package/front_end/panels/timeline/CLSLinkifier.ts +0 -58
  163. package/front_end/ui/components/expandable_list/ExpandableList.docs.ts +0 -30
  164. /package/front_end/panels/application/{components/originTrialTokenRows.css → originTrialTokenRows.css} +0 -0
  165. /package/front_end/panels/application/{components/originTrialTreeView.css → originTrialTreeView.css} +0 -0
  166. /package/front_end/panels/{elements → common}/domLinkifier.css +0 -0
@@ -0,0 +1,87 @@
1
+ // Copyright 2021 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ /*
6
+ * Copyright (C) 2011 Google Inc. All rights reserved.
7
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
8
+ * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
9
+ * Copyright (C) 2009 Joseph Pecoraro
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without
12
+ * modification, are permitted provided that the following conditions
13
+ * are met:
14
+ *
15
+ * 1. Redistributions of source code must retain the above copyright
16
+ * notice, this list of conditions and the following disclaimer.
17
+ * 2. Redistributions in binary form must reproduce the above copyright
18
+ * notice, this list of conditions and the following disclaimer in the
19
+ * documentation and/or other materials provided with the distribution.
20
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
21
+ * its contributors may be used to endorse or promote products derived
22
+ * from this software without specific prior written permission.
23
+ *
24
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
25
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
28
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+ */
35
+
36
+ import * as Common from '../../core/common/common.js';
37
+ import * as Host from '../../core/host/host.js';
38
+ import * as Platform from '../../core/platform/platform.js';
39
+ import * as Root from '../../core/root/root.js';
40
+ import * as SDK from '../../core/sdk/sdk.js';
41
+
42
+ /**
43
+ * Opens the given `url` in a new Chrome tab.
44
+ *
45
+ * If the `url` is a Google owned documentation page (currently that includes
46
+ * `web.dev`, `developers.google.com`, and `developer.chrome.com`), the `url`
47
+ * will also be checked for UTM parameters:
48
+ *
49
+ * - If no `utm_source` search parameter is present, this method will add a new
50
+ * search parameter `utm_source=devtools` to `url`.
51
+ * - If no `utm_campaign` search parameter is present, and DevTools is running
52
+ * within a branded build, this method will add `utm_campaign=<channel>` to
53
+ * the search parameters, with `<channel>` being the release channel of
54
+ * Chrome ("stable", "beta", "dev", or "canary").
55
+ *
56
+ * @param url the URL to open in a new tab.
57
+ * @throws TypeError if `url` is not a valid URL.
58
+ * @see https://en.wikipedia.org/wiki/UTM_parameters
59
+ */
60
+ export function openInNewTab(url: URL|string): void {
61
+ url = new URL(`${url}`);
62
+ // Navigating to a chrome:// link via a normal anchor doesn't work, so we "navigate"
63
+ // there using CDP.
64
+ if (Common.ParsedURL.schemeIs(url, 'chrome:')) {
65
+ const rootTarget = SDK.TargetManager.TargetManager.instance().rootTarget();
66
+ if (rootTarget === null) {
67
+ return;
68
+ }
69
+
70
+ void rootTarget.targetAgent().invoke_createTarget({url: url.toString()}).then(result => {
71
+ if (result.getError()) {
72
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(Platform.DevToolsPath.urlString`${url}`);
73
+ }
74
+ });
75
+ } else {
76
+ if (['developer.chrome.com', 'developers.google.com', 'web.dev'].includes(url.hostname)) {
77
+ if (!url.searchParams.has('utm_source')) {
78
+ url.searchParams.append('utm_source', 'devtools');
79
+ }
80
+ const {channel} = Root.Runtime.hostConfig;
81
+ if (!url.searchParams.has('utm_campaign') && typeof channel === 'string') {
82
+ url.searchParams.append('utm_campaign', channel);
83
+ }
84
+ }
85
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(Platform.DevToolsPath.urlString`${url}`);
86
+ }
87
+ }
@@ -0,0 +1,5 @@
1
+ // Copyright 2025 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ export {openInNewTab} from './OpenInNewTab.js';
@@ -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
+ }
@@ -8,10 +8,11 @@ import {ContextMenu} from './legacy.js';
8
8
 
9
9
  const {html} = Lit;
10
10
 
11
- export async function render(container: HTMLElement) {
11
+ export function render(container: HTMLElement) {
12
+ const menuDocs = container.createChild('div', 'menu-docs');
12
13
  const style = document.createElement('style');
13
14
  style.textContent = `
14
- #container > div {
15
+ .menu-docs > div {
15
16
  width: var(--sys-size-34);
16
17
  padding: var(--sys-size-11);
17
18
  display: flex;
@@ -27,13 +28,13 @@ export async function render(container: HTMLElement) {
27
28
  }
28
29
  }
29
30
  `;
30
- container.appendChild(style);
31
+ menuDocs.appendChild(style);
31
32
 
32
33
  const menuButtonSection = document.createElement('div');
33
34
  const menuButtonHeader = document.createElement('header');
34
35
  menuButtonHeader.textContent = 'DevTools menu button (lit-html)';
35
- container.appendChild(menuButtonHeader);
36
- container.appendChild(menuButtonSection);
36
+ menuDocs.appendChild(menuButtonHeader);
37
+ menuDocs.appendChild(menuButtonSection);
37
38
 
38
39
  Lit.render(
39
40
  html`
@@ -53,8 +54,8 @@ export async function render(container: HTMLElement) {
53
54
  simpleItemsSection.innerHTML = '<p>Right-click here</p>';
54
55
  const simpleItemsHeader = document.createElement('header');
55
56
  simpleItemsHeader.textContent = 'Various simple menu items (imperative API)';
56
- container.appendChild(simpleItemsHeader);
57
- container.appendChild(simpleItemsSection);
57
+ menuDocs.appendChild(simpleItemsHeader);
58
+ menuDocs.appendChild(simpleItemsSection);
58
59
 
59
60
  let checked = true;
60
61
  simpleItemsSection.addEventListener('contextmenu', onSimpleMenu);
@@ -93,8 +94,8 @@ export async function render(container: HTMLElement) {
93
94
  customSection.innerHTML = '<p>Right-click here</p>';
94
95
  const customSectionHeader = document.createElement('header');
95
96
  customSectionHeader.textContent = 'Custom sections (imperative API)';
96
- container.appendChild(customSectionHeader);
97
- container.appendChild(customSection);
97
+ menuDocs.appendChild(customSectionHeader);
98
+ menuDocs.appendChild(customSection);
98
99
 
99
100
  customSection.addEventListener('contextmenu', onCustomSectionMenu);
100
101
 
@@ -117,8 +118,8 @@ export async function render(container: HTMLElement) {
117
118
  subMenuSection.innerHTML = '<p>Right-click here</p>';
118
119
  const subMenuHeader = document.createElement('header');
119
120
  subMenuHeader.textContent = 'Sub menu (imperative API)';
120
- container.appendChild(subMenuHeader);
121
- container.appendChild(subMenuSection);
121
+ menuDocs.appendChild(subMenuHeader);
122
+ menuDocs.appendChild(subMenuSection);
122
123
 
123
124
  subMenuSection.addEventListener('contextmenu', onSubMenu);
124
125
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  import {UIUtils} from './legacy.js';
6
6
 
7
- export async function render(container: HTMLElement) {
7
+ export function render(container: HTMLElement) {
8
8
  const styleElement = document.createElement('style');
9
9
  styleElement.textContent = 'fieldset { label { display: block; } }';
10
10
  container.appendChild(styleElement);
@@ -9,7 +9,7 @@ import {UIUtils} from './legacy.js';
9
9
 
10
10
  const {html} = Lit;
11
11
 
12
- export async function render(container: HTMLElement) {
12
+ export function render(container: HTMLElement) {
13
13
  function createDivWithP(text: string): HTMLDivElement {
14
14
  const div = document.createElement('div');
15
15
  div.style.paddingLeft = '25px';
@@ -4,7 +4,7 @@
4
4
 
5
5
  import {UIUtils} from './legacy.js';
6
6
 
7
- export async function render(container: HTMLElement) {
7
+ export function render(container: HTMLElement) {
8
8
  function sliderExample({min, max, tabIndex, disabled}: {
9
9
  min: number,
10
10
  max: number,
@@ -40,7 +40,6 @@ import * as Common from '../../core/common/common.js';
40
40
  import * as Host from '../../core/host/host.js';
41
41
  import * as i18n from '../../core/i18n/i18n.js';
42
42
  import * as Platform from '../../core/platform/platform.js';
43
- import * as Root from '../../core/root/root.js';
44
43
  import * as Geometry from '../../models/geometry/geometry.js';
45
44
  import * as TextUtils from '../../models/text_utils/text_utils.js';
46
45
  import * as Buttons from '../components/buttons/buttons.js';
@@ -1923,7 +1922,7 @@ function updateWidgetfocusWidgetForNode(node: Node|null): void {
1923
1922
  break;
1924
1923
  }
1925
1924
 
1926
- parentWidget.defaultFocusedChild = widget;
1925
+ parentWidget.setDefaultFocusedChild(widget);
1927
1926
  widget = parentWidget;
1928
1927
  }
1929
1928
  }
@@ -1989,38 +1988,6 @@ export function measuredScrollbarWidth(document?: Document|null): number {
1989
1988
  return cachedMeasuredScrollbarWidth;
1990
1989
  }
1991
1990
 
1992
- /**
1993
- * Opens the given `url` in a new Chrome tab.
1994
- *
1995
- * If the `url` is a Google owned documentation page (currently that includes
1996
- * `web.dev`, `developers.google.com`, and `developer.chrome.com`), the `url`
1997
- * will also be checked for UTM parameters:
1998
- *
1999
- * - If no `utm_source` search parameter is present, this method will add a new
2000
- * search parameter `utm_source=devtools` to `url`.
2001
- * - If no `utm_campaign` search parameter is present, and DevTools is running
2002
- * within a branded build, this method will add `utm_campaign=<channel>` to
2003
- * the search parameters, with `<channel>` being the release channel of
2004
- * Chrome ("stable", "beta", "dev", or "canary").
2005
- *
2006
- * @param url the URL to open in a new tab.
2007
- * @throws TypeError if `url` is not a valid URL.
2008
- * @see https://en.wikipedia.org/wiki/UTM_parameters
2009
- */
2010
- export function openInNewTab(url: URL|string): void {
2011
- url = new URL(`${url}`);
2012
- if (['developer.chrome.com', 'developers.google.com', 'web.dev'].includes(url.hostname)) {
2013
- if (!url.searchParams.has('utm_source')) {
2014
- url.searchParams.append('utm_source', 'devtools');
2015
- }
2016
- const {channel} = Root.Runtime.hostConfig;
2017
- if (!url.searchParams.has('utm_campaign') && typeof channel === 'string') {
2018
- url.searchParams.append('utm_campaign', channel);
2019
- }
2020
- }
2021
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(Platform.DevToolsPath.urlString`${url}`);
2022
- }
2023
-
2024
1991
  export interface PromotionDisplayState {
2025
1992
  displayCount: number;
2026
1993
  firstRegistered: number;
@@ -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 {
@@ -4,6 +4,7 @@
4
4
 
5
5
  import * as Host from '../../core/host/host.js';
6
6
  import * as Platform from '../../core/platform/platform.js';
7
+ import * as UIHelpers from '../helpers/helpers.js';
7
8
  import * as VisualLogging from '../visual_logging/visual_logging.js';
8
9
 
9
10
  import * as ARIAUtils from './ARIAUtils.js';
@@ -13,7 +14,6 @@ import {Tooltip} from './Tooltip.js';
13
14
  import {
14
15
  copyLinkAddressLabel,
15
16
  MaxLengthForDisplayedURLs,
16
- openInNewTab,
17
17
  openLinkExternallyLabel,
18
18
  } from './UIUtils.js';
19
19
  import {XElement} from './XElement.js';
@@ -54,18 +54,16 @@ export class XLink extends XElement {
54
54
  this.onClick = (event: Event) => {
55
55
  event.consume(true);
56
56
  if (this.#href) {
57
- openInNewTab(this.#href);
57
+ UIHelpers.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)) {
63
62
  event.consume(true);
64
63
  if (this.#href) {
65
- openInNewTab(this.#href);
64
+ UIHelpers.openInNewTab(this.#href);
66
65
  }
67
66
  }
68
- this.dispatchEvent(new Event('x-link-invoke'));
69
67
  };
70
68
  }
71
69
 
@@ -142,7 +140,7 @@ export class ContextMenuProvider implements Provider<Node> {
142
140
  const node: XLink = targetNode;
143
141
  contextMenu.revealSection().appendItem(openLinkExternallyLabel(), () => {
144
142
  if (node.href) {
145
- openInNewTab(node.href);
143
+ UIHelpers.openInNewTab(node.href);
146
144
  }
147
145
  }, {jslogContext: 'open-in-new-tab'});
148
146
  contextMenu.revealSection().appendItem(copyLinkAddressLabel(), () => {
@@ -11,6 +11,7 @@ import * as i18n from '../../../../core/i18n/i18n.js';
11
11
  import * as Platform from '../../../../core/platform/platform.js';
12
12
  import * as Root from '../../../../core/root/root.js';
13
13
  import * as IconButton from '../../../../ui/components/icon_button/icon_button.js';
14
+ import * as UIHelpers from '../../../helpers/helpers.js';
14
15
  import * as UI from '../../legacy.js';
15
16
 
16
17
  import {type ContrastInfo, Events as ContrastInfoEvents} from './ContrastInfo.js';
@@ -363,7 +364,7 @@ export class ContrastDetails extends Common.ObjectWrapper.ObjectWrapper<EventTyp
363
364
  }
364
365
 
365
366
  private static showHelp(): void {
366
- UI.UIUtils.openInNewTab('https://web.dev/color-and-contrast-accessibility/');
367
+ UIHelpers.openInNewTab('https://web.dev/color-and-contrast-accessibility/');
367
368
  }
368
369
 
369
370
  setVisible(visible: boolean): void {
@@ -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;