chrome-devtools-frontend 1.0.1672557 → 1.0.1675430
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.
- package/.agents/skills/devtools-ux-writing-refactor/SKILL.md +26 -9
- package/front_end/core/common/ParsedURL.ts +5 -1
- package/front_end/core/common/SettingRegistration.ts +30 -34
- package/front_end/core/common/Settings.ts +4 -64
- package/front_end/core/host/UserMetrics.ts +127 -117
- package/front_end/core/protocol_client/PuppeteerDevToolsConnection.ts +42 -9
- package/front_end/core/root/Runtime.ts +14 -0
- package/front_end/core/sdk/NetworkManager.ts +0 -35
- package/front_end/core/sdk/SourceMap.ts +1 -19
- package/front_end/core/sdk/SourceMapManager.ts +75 -48
- package/front_end/core/sdk/SourceMapScopesInfo.ts +0 -62
- package/front_end/core/sdk/TargetManager.ts +18 -0
- package/front_end/devtools_compatibility.js +1 -1
- package/front_end/entrypoints/main/MainImpl.ts +1 -0
- package/front_end/foundation/Universe.ts +44 -29
- package/front_end/generated/InspectorBackendCommands.ts +4 -3
- package/front_end/generated/SupportedCSSProperties.ts +16 -1
- package/front_end/generated/protocol-mapping.d.ts +8 -0
- package/front_end/generated/protocol-proxy-api.d.ts +6 -0
- package/front_end/generated/protocol.ts +16 -2
- package/front_end/models/ai_assistance/AiSetting.ts +66 -3
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +15 -5
- package/front_end/models/bindings/CompilerScriptMapping.ts +1 -1
- package/front_end/models/emulation/DeviceModeModel.ts +82 -102
- package/front_end/models/emulation/EmulatedDevices.ts +18 -66
- package/front_end/models/javascript_metadata/NativeFunctions.js +4 -4
- package/front_end/models/persistence/AutomaticFileSystemManager.ts +2 -2
- package/front_end/models/persistence/IsolatedFileSystemManager.ts +20 -29
- package/front_end/models/trace/ModelImpl.ts +5 -0
- package/front_end/models/trace/Processor.ts +5 -0
- package/front_end/models/trace/handlers/LayoutShiftsHandler.ts +7 -1
- package/front_end/models/trace/handlers/MetaHandler.ts +8 -4
- package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +11 -0
- package/front_end/models/workspace/FileManager.ts +13 -6
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +11 -10
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +3 -45
- package/front_end/panels/application/BackgroundServiceView.ts +42 -40
- package/front_end/panels/application/KeyValueStorageItemsView.ts +1 -0
- package/front_end/panels/application/WebMCPView.ts +13 -5
- package/front_end/panels/application/components/AdsView.ts +24 -1
- package/front_end/panels/application/components/adsView.css +27 -21
- package/front_end/panels/autofill/AutofillView.ts +12 -12
- package/front_end/panels/autofill/autofill-meta.ts +2 -2
- package/front_end/panels/common/ExtensionServer.ts +7 -1
- package/front_end/panels/common/common.ts +0 -1
- package/front_end/panels/console/ConsoleInsightTeaser.ts +7 -6
- package/front_end/panels/console/ConsoleViewMessage.ts +1 -1
- package/front_end/panels/elements/ClassesPaneWidget.ts +2 -2
- package/front_end/panels/elements/ElementsTreeElement.ts +602 -327
- package/front_end/panels/elements/ElementsTreeOutline.ts +1 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +1 -1
- package/front_end/panels/elements/components/AdornerManager.ts +1 -0
- package/front_end/panels/emulation/AdvancedApp.ts +3 -3
- package/front_end/panels/emulation/DeviceModeToolbar.ts +2 -11
- package/front_end/panels/emulation/DeviceModeView.ts +234 -75
- package/front_end/panels/emulation/InspectedPagePlaceholder.ts +1 -1
- package/front_end/panels/emulation/deviceModeView.css +4 -21
- package/front_end/panels/emulation/emulation-meta.ts +4 -30
- package/front_end/panels/emulation/emulation.ts +0 -3
- package/front_end/panels/explain/components/ConsoleInsight.ts +11 -7
- package/front_end/panels/js_timeline/js_timeline-meta.ts +8 -8
- package/front_end/panels/layer_viewer/LayerDetailsView.ts +30 -30
- package/front_end/panels/layer_viewer/LayerTreeOutline.ts +6 -6
- package/front_end/panels/layer_viewer/LayerViewHost.ts +1 -1
- package/front_end/panels/layer_viewer/Layers3DView.ts +11 -11
- package/front_end/panels/layer_viewer/PaintProfilerView.ts +8 -8
- package/front_end/panels/layer_viewer/TransformController.ts +3 -3
- package/front_end/panels/layer_viewer/layer_viewer-meta.ts +11 -11
- package/front_end/panels/layers/LayersPanel.ts +2 -2
- package/front_end/panels/layers/layers-meta.ts +2 -2
- package/front_end/panels/lighthouse/LighthouseController.ts +3 -7
- package/front_end/panels/mobile_throttling/CPUThrottlingSelector.ts +313 -0
- package/front_end/panels/mobile_throttling/NetworkPanelIndicator.ts +0 -10
- package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +21 -10
- package/front_end/panels/mobile_throttling/ThrottlingManager.ts +1 -58
- package/front_end/panels/mobile_throttling/mobile_throttling.ts +2 -9
- package/front_end/panels/network/NetworkConfigView.ts +1 -71
- package/front_end/panels/network/networkConfigView.css +1 -2
- package/front_end/panels/profiler/HeapDetachedElementsDataGrid.ts +3 -3
- package/front_end/panels/profiler/HeapDetachedElementsView.ts +5 -5
- package/front_end/panels/profiler/HeapProfileView.ts +32 -32
- package/front_end/panels/profiler/HeapProfilerPanel.ts +2 -2
- package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +33 -37
- package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +26 -27
- package/front_end/panels/profiler/HeapSnapshotView.ts +48 -48
- package/front_end/panels/profiler/IsolateSelector.ts +10 -10
- package/front_end/panels/profiler/ModuleUIStrings.ts +25 -25
- package/front_end/panels/profiler/ProfileLauncherView.ts +6 -6
- package/front_end/panels/profiler/ProfilesPanel.ts +6 -6
- package/front_end/panels/profiler/WritableProfileHeader.ts +6 -6
- package/front_end/panels/profiler/profiler-meta.ts +7 -7
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +7 -0
- package/front_end/panels/recorder/RecorderPanel.ts +1 -1
- package/front_end/panels/settings/AISettingsTab.ts +27 -23
- package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +1 -2
- package/front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts +12 -17
- package/front_end/panels/timeline/TimelinePanel.ts +20 -35
- package/front_end/panels/timeline/components/LiveMetricsView.ts +27 -6
- package/front_end/panels/timeline/components/NetworkTrackWidget.ts +1 -1
- package/front_end/panels/timeline/components/components.ts +0 -4
- package/front_end/panels/timeline/components/liveMetricsView.css +7 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/CONTRIBUTING.md +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/LICENSE +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/README.md +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/builder.d.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/builder.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/safe_builder.d.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/safe_builder.d.ts.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/decode/decode.d.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/decode/decode.d.ts.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/encode/encode.d.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/encode/encode.d.ts.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/mod.d.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/mod.d.ts.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/scopes.d.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/scopes.d.ts.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/deno.json +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/package.json +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.js +2 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.ts +2 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/codec.js +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/codec.js.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/codec.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.js +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.js.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/mod.js +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/mod.js.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/mod.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/scopes.js +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/scopes.js.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/scopes.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/util.js +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/util.js.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/util.ts +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/vlq.js +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/vlq.js.map +0 -0
- package/front_end/third_party/source-map-scopes-codec/package/src/vlq.ts +0 -0
- package/front_end/ui/comments/CommentAnchorResolver.ts +132 -0
- package/front_end/ui/comments/comments.ts +9 -0
- package/front_end/ui/components/dialogs/ShortcutDialog.ts +2 -0
- package/front_end/ui/components/settings/SettingCheckbox.ts +4 -12
- package/front_end/ui/components/settings/settingCheckbox.css +0 -7
- package/front_end/ui/legacy/Treeoutline.ts +14 -14
- package/front_end/ui/legacy/UIUtils.ts +2 -47
- package/front_end/ui/legacy/Widget.ts +10 -2
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +40 -0
- package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +1 -1
- package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -0
- package/front_end/ui/lit/Directives.ts +80 -0
- package/front_end/ui/lit/lit.ts +1 -0
- package/front_end/ui/lit/render.ts +8 -0
- package/front_end/ui/settings/SettingUIRegistration.ts +4 -0
- package/front_end/ui/visual_logging/Debugging.ts +1 -5
- package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
- package/front_end/ui/visual_logging/LoggingConfig.ts +21 -0
- package/front_end/ui/visual_logging/visual_logging.ts +9 -0
- package/mcp/mcp.ts +1 -0
- package/package.json +1 -1
- package/front_end/panels/common/ThrottlingUtils.ts +0 -51
- package/front_end/panels/emulation/DeviceModeWrapper.ts +0 -248
- package/front_end/panels/mobile_throttling/MobileThrottlingSelector.ts +0 -92
- package/front_end/panels/timeline/components/CPUThrottlingSelector.ts +0 -235
- package/front_end/panels/timeline/components/NetworkThrottlingSelector.ts +0 -245
- package/front_end/panels/timeline/components/cpuThrottlingSelector.css +0 -30
- package/front_end/panels/timeline/components/networkThrottlingSelector.css +0 -24
|
File without changes
|
package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js.map
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// Copyright 2026 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
|
+
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
6
|
+
|
|
7
|
+
export interface CommentAnchorSignature {
|
|
8
|
+
/** Visual logging tree path, e.g. "Panel: elements > Pane: styles > TreeOutline > TreeItem: color" */
|
|
9
|
+
vePath: string;
|
|
10
|
+
/** Normalized text content of the target node */
|
|
11
|
+
textSignature: string;
|
|
12
|
+
/** Text content of the parent container VE node for sibling disambiguation */
|
|
13
|
+
parentTextSignature?: string;
|
|
14
|
+
/** 0-indexed position among siblings sharing the same visual logging path and text signature */
|
|
15
|
+
siblingIndex?: number;
|
|
16
|
+
/** Optional backend RequestId for Network panel elements (`data-network-request-id`) */
|
|
17
|
+
networkRequestId?: string;
|
|
18
|
+
/** Optional backend NodeId for Elements panel DOM nodes (`data-backend-node-id`) */
|
|
19
|
+
backendNodeId?: number;
|
|
20
|
+
/** Optional 1-indexed line number for CodeMirror text editors */
|
|
21
|
+
editorLineNumber?: number;
|
|
22
|
+
/** Optional file path of the document displayed in the CodeMirror editor */
|
|
23
|
+
editorFilePath?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface CommentThread {
|
|
27
|
+
id: string;
|
|
28
|
+
anchor: CommentAnchorSignature;
|
|
29
|
+
comments: Array<{
|
|
30
|
+
author: 'DEVELOPER' | 'AGENT',
|
|
31
|
+
text: string,
|
|
32
|
+
timestamp: number,
|
|
33
|
+
}>;
|
|
34
|
+
status: 'ACTIVE'|'RESOLVED';
|
|
35
|
+
changes?: Array<Record<string, unknown>>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const IGNORED_MINOR_CONTROLS = new Set<number>([
|
|
39
|
+
VisualLogging.VisualElements.Action,
|
|
40
|
+
VisualLogging.VisualElements.Toggle,
|
|
41
|
+
VisualLogging.VisualElements.Close,
|
|
42
|
+
VisualLogging.VisualElements.Expand,
|
|
43
|
+
VisualLogging.VisualElements.ToggleSubpane,
|
|
44
|
+
VisualLogging.VisualElements.Toolbar,
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
export function closestAcrossShadow(element: Element, selector: string): Element|null {
|
|
48
|
+
let current: Element|null = element;
|
|
49
|
+
while (current) {
|
|
50
|
+
if (current.matches(selector)) {
|
|
51
|
+
return current;
|
|
52
|
+
}
|
|
53
|
+
current = current.parentElementOrShadowHost();
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function isNonEmptyItem(element: Element): boolean {
|
|
59
|
+
return element.deepTextContent().trim().length > 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function isTabTitle(element: Element): boolean {
|
|
63
|
+
let current: Element|null = element;
|
|
64
|
+
while (current) {
|
|
65
|
+
if (VisualLogging.needsLogging(current)) {
|
|
66
|
+
try {
|
|
67
|
+
const config = VisualLogging.getLoggingConfig(current);
|
|
68
|
+
if (config.ve === VisualLogging.VisualElements.PanelTabHeader) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
// Ignore
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const role = current.getAttribute('role');
|
|
76
|
+
if (role === 'tab') {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
if (current.classList.contains('tab-element') || current.classList.contains('tab-header')) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
current = current.parentElementOrShadowHost();
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function resolveCommentAnchorElement(element: Element): Element|null {
|
|
88
|
+
if (isTabTitle(element)) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
let target: Element|null = element;
|
|
92
|
+
let fallbackCandidate: Element|null = null;
|
|
93
|
+
|
|
94
|
+
while (target) {
|
|
95
|
+
const hasDomainId = target.hasAttribute('data-network-request-id') || target.hasAttribute('data-backend-node-id');
|
|
96
|
+
|
|
97
|
+
if (hasDomainId) {
|
|
98
|
+
return isNonEmptyItem(target) ? target : null;
|
|
99
|
+
}
|
|
100
|
+
if (VisualLogging.needsLogging(target)) {
|
|
101
|
+
try {
|
|
102
|
+
const config = VisualLogging.getLoggingConfig(target);
|
|
103
|
+
if (config.ve === VisualLogging.VisualElements.TableRow ||
|
|
104
|
+
config.ve === VisualLogging.VisualElements.TreeItem) {
|
|
105
|
+
return isNonEmptyItem(target) ? target : null;
|
|
106
|
+
}
|
|
107
|
+
if (!fallbackCandidate && !IGNORED_MINOR_CONTROLS.has(config.ve)) {
|
|
108
|
+
fallbackCandidate = target;
|
|
109
|
+
}
|
|
110
|
+
} catch {
|
|
111
|
+
// Ignore
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
target = target.parentElementOrShadowHost();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (fallbackCandidate && isNonEmptyItem(fallbackCandidate)) {
|
|
118
|
+
return fallbackCandidate;
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function isElementVisible(element: Element): boolean {
|
|
124
|
+
if (!element.isConnected) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
if (!element.checkVisibility({checkOpacity: true, checkVisibilityCSS: true, contentVisibilityAuto: true})) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
const rect = element.getBoundingClientRect();
|
|
131
|
+
return rect.width > 0 && rect.height > 0;
|
|
132
|
+
}
|
|
@@ -13,6 +13,7 @@ import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
|
|
|
13
13
|
import {html, nothing, render, type TemplateResult} from '../../../ui/lit/lit.js';
|
|
14
14
|
|
|
15
15
|
import type {ButtonDialogData} from './ButtonDialog.js';
|
|
16
|
+
import {DialogHorizontalAlignment} from './Dialog.js';
|
|
16
17
|
import shortcutDialogStyles from './shortcutDialog.css.js';
|
|
17
18
|
|
|
18
19
|
const UIStrings = {
|
|
@@ -116,6 +117,7 @@ export class ShortcutDialog extends HTMLElement {
|
|
|
116
117
|
variant: Buttons.Button.Variant.TOOLBAR,
|
|
117
118
|
iconName: 'help',
|
|
118
119
|
iconTitle: i18nString(UIStrings.showShortcutTitle),
|
|
120
|
+
horizontalAlignment: DialogHorizontalAlignment.AUTO,
|
|
119
121
|
} as ButtonDialogData}>
|
|
120
122
|
<ul class="keybinds-list">
|
|
121
123
|
${(this.#prependedElement) ? html`${this.#prependedElement}` : nothing}
|
|
@@ -17,7 +17,7 @@ import * as Input from '../input/input.js';
|
|
|
17
17
|
|
|
18
18
|
import settingCheckboxStyles from './settingCheckbox.css.js';
|
|
19
19
|
|
|
20
|
-
const {html
|
|
20
|
+
const {html} = Lit;
|
|
21
21
|
|
|
22
22
|
const UIStrings = {
|
|
23
23
|
/**
|
|
@@ -123,7 +123,7 @@ export class SettingCheckbox extends HTMLElement {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
get checked(): boolean {
|
|
126
|
-
if (!this.#setting
|
|
126
|
+
if (!this.#setting) {
|
|
127
127
|
return false;
|
|
128
128
|
}
|
|
129
129
|
|
|
@@ -141,14 +141,6 @@ export class SettingCheckbox extends HTMLElement {
|
|
|
141
141
|
|
|
142
142
|
const icon = this.icon();
|
|
143
143
|
const title = learnMore?.tooltip?.() ?? '';
|
|
144
|
-
const disabledReasons = this.#setting.disabledReasons();
|
|
145
|
-
const reason = disabledReasons.length ?
|
|
146
|
-
html`
|
|
147
|
-
<devtools-button class="disabled-reason" .iconName=${'info'} .variant=${Buttons.Button.Variant.ICON} .size=${
|
|
148
|
-
Buttons.Button.Size.SMALL} title=${ifDefined(disabledReasons.join('\n'))} @click=${
|
|
149
|
-
onclick}></devtools-button>
|
|
150
|
-
` :
|
|
151
|
-
Lit.nothing;
|
|
152
144
|
Lit.render(html`
|
|
153
145
|
<style>${Input.checkboxStyles}</style>
|
|
154
146
|
<style>${settingCheckboxStyles}</style>
|
|
@@ -157,12 +149,12 @@ export class SettingCheckbox extends HTMLElement {
|
|
|
157
149
|
<input
|
|
158
150
|
type="checkbox"
|
|
159
151
|
.checked=${this.checked}
|
|
160
|
-
?disabled=${this.#disabled
|
|
152
|
+
?disabled=${this.#disabled}
|
|
161
153
|
@change=${this.#checkboxChanged}
|
|
162
154
|
jslog=${VisualLogging.toggle().track({change: true}).context(this.#setting.name)}
|
|
163
155
|
aria-label=${titleText}
|
|
164
156
|
/>
|
|
165
|
-
${this.#textOverride || titleText}
|
|
157
|
+
${this.#textOverride || titleText}
|
|
166
158
|
</label>
|
|
167
159
|
${icon}
|
|
168
160
|
</p>`,
|
|
@@ -58,7 +58,6 @@ import {
|
|
|
58
58
|
deepElementFromPoint,
|
|
59
59
|
enclosingNodeOrSelfWithNodeNameInArray,
|
|
60
60
|
HTMLElementWithLightDOMTemplate,
|
|
61
|
-
InterceptBindingDirective,
|
|
62
61
|
isEditing,
|
|
63
62
|
} from './UIUtils.js';
|
|
64
63
|
|
|
@@ -1658,7 +1657,7 @@ class TreeViewTreeElement extends TreeElement {
|
|
|
1658
1657
|
}
|
|
1659
1658
|
|
|
1660
1659
|
refresh(): void {
|
|
1661
|
-
const expandable = Boolean(this.configElement.querySelector('ul[role="group"]'));
|
|
1660
|
+
const expandable = Boolean(this.configElement.querySelector(':scope > ul[role="group"]'));
|
|
1662
1661
|
this.setExpandable(expandable);
|
|
1663
1662
|
|
|
1664
1663
|
this.titleElement.textContent = '';
|
|
@@ -1677,7 +1676,9 @@ class TreeViewTreeElement extends TreeElement {
|
|
|
1677
1676
|
this.listItemElement.classList.add(className);
|
|
1678
1677
|
this.#clonedClasses.add(className);
|
|
1679
1678
|
}
|
|
1680
|
-
|
|
1679
|
+
const childUl = this.configElement.querySelector(':scope > ul[role="group"]');
|
|
1680
|
+
const templateElements = childUl ? [this.configElement, childUl] : [this.configElement];
|
|
1681
|
+
Lit.CustomDirectives.InterceptBindingDirective.setEventListeners(templateElements, this.listItemElement);
|
|
1681
1682
|
|
|
1682
1683
|
for (const child of this.configElement.childNodes) {
|
|
1683
1684
|
if (child instanceof HTMLUListElement && child.role === 'group') {
|
|
@@ -1697,9 +1698,9 @@ class TreeViewTreeElement extends TreeElement {
|
|
|
1697
1698
|
}
|
|
1698
1699
|
|
|
1699
1700
|
remove(): void {
|
|
1700
|
-
removeNode(
|
|
1701
|
-
|
|
1702
|
-
|
|
1701
|
+
removeNode(this,
|
|
1702
|
+
Boolean(this.parent &&
|
|
1703
|
+
(this.parent as TreeViewTreeElement).configElement?.querySelector(':scope > ul[role="group"]')));
|
|
1703
1704
|
TreeViewTreeElement.#elementToTreeElement.delete(this.configElement);
|
|
1704
1705
|
}
|
|
1705
1706
|
}
|
|
@@ -1804,10 +1805,10 @@ function removeNode(node: TreeElement, preserveParentExpandable = false): void {
|
|
|
1804
1805
|
* This section is only relevant if NOT using the `template`.
|
|
1805
1806
|
*
|
|
1806
1807
|
* Since config elements are cloned into the shadow DOM, it's not possible to directly attach event listeners to the
|
|
1807
|
-
* children of config elements. Instead, the `
|
|
1808
|
+
* children of config elements. Instead, the `Lit.CustomDirectives.InterceptBindingDirective` directive needs to be used as a
|
|
1808
1809
|
* wrapper:
|
|
1809
1810
|
* ```
|
|
1810
|
-
* const on = Lit.Directive.directive(
|
|
1811
|
+
* const on = Lit.Directive.directive(Lit.CustomDirectives.InterceptBindingDirective);
|
|
1811
1812
|
*
|
|
1812
1813
|
* html`<li role="treeitem">
|
|
1813
1814
|
* <button @click=${on(clickHandler)}>click me</button>
|
|
@@ -1933,7 +1934,7 @@ export class TreeViewElement extends HTMLElementWithLightDOMTemplate {
|
|
|
1933
1934
|
let treeElement;
|
|
1934
1935
|
if (node instanceof HTMLLIElement) {
|
|
1935
1936
|
treeElement = new TreeViewTreeElement(this.#treeOutline, node);
|
|
1936
|
-
const expandable = Boolean(node.querySelector('ul[role="group"]'));
|
|
1937
|
+
const expandable = Boolean(node.querySelector(':scope > ul[role="group"]'));
|
|
1937
1938
|
treeElement.setExpandable(expandable);
|
|
1938
1939
|
treeElement.updateExpansionFromAttribute();
|
|
1939
1940
|
} else {
|
|
@@ -1965,11 +1966,10 @@ export class TreeViewElement extends HTMLElementWithLightDOMTemplate {
|
|
|
1965
1966
|
if (node instanceof HTMLLIElement) {
|
|
1966
1967
|
TreeViewTreeElement.get(node)?.remove();
|
|
1967
1968
|
} else if (node.treeElement) {
|
|
1968
|
-
removeNode(
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
(node.treeElement.parent as TreeViewTreeElement).configElement?.querySelector('ul[role="group"]')));
|
|
1969
|
+
removeNode(node.treeElement,
|
|
1970
|
+
Boolean(node.treeElement.parent &&
|
|
1971
|
+
(node.treeElement.parent as TreeViewTreeElement)
|
|
1972
|
+
.configElement?.querySelector(':scope > ul[role="group"]')));
|
|
1973
1973
|
}
|
|
1974
1974
|
}
|
|
1975
1975
|
}
|
|
@@ -2026,51 +2026,6 @@ export function bindToAction(actionName: string): ReturnType<typeof Directives.r
|
|
|
2026
2026
|
});
|
|
2027
2027
|
}
|
|
2028
2028
|
|
|
2029
|
-
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
2030
|
-
type BindingEventListener = (arg: any) => any;
|
|
2031
|
-
export class InterceptBindingDirective extends Lit.Directive.Directive {
|
|
2032
|
-
static readonly #interceptedBindings = new WeakMap<Element, Map<string, BindingEventListener>>();
|
|
2033
|
-
static readonly #attachedBindings = new WeakMap<Element, Map<string, BindingEventListener>>();
|
|
2034
|
-
|
|
2035
|
-
override update(part: Lit.Directive.Part, [listener]: [BindingEventListener]): unknown {
|
|
2036
|
-
if (part.type !== Lit.Directive.PartType.EVENT) {
|
|
2037
|
-
return listener;
|
|
2038
|
-
}
|
|
2039
|
-
let eventListeners = InterceptBindingDirective.#interceptedBindings.get(part.element);
|
|
2040
|
-
if (!eventListeners) {
|
|
2041
|
-
eventListeners = new Map();
|
|
2042
|
-
InterceptBindingDirective.#interceptedBindings.set(part.element, eventListeners);
|
|
2043
|
-
}
|
|
2044
|
-
eventListeners.set(part.name, listener);
|
|
2045
|
-
|
|
2046
|
-
return this.render(listener);
|
|
2047
|
-
}
|
|
2048
|
-
|
|
2049
|
-
/* eslint-disable-next-line @typescript-eslint/no-unsafe-function-type */
|
|
2050
|
-
render(listener: Function): Function {
|
|
2051
|
-
return listener;
|
|
2052
|
-
}
|
|
2053
|
-
|
|
2054
|
-
static setEventListeners(templateElement: Element, renderedElement: Element): void {
|
|
2055
|
-
const attachedListeners = InterceptBindingDirective.#attachedBindings.get(renderedElement);
|
|
2056
|
-
if (attachedListeners) {
|
|
2057
|
-
for (const [name, listener] of attachedListeners) {
|
|
2058
|
-
renderedElement.removeEventListener(name, listener);
|
|
2059
|
-
}
|
|
2060
|
-
}
|
|
2061
|
-
|
|
2062
|
-
const newListeners = InterceptBindingDirective.#interceptedBindings.get(templateElement);
|
|
2063
|
-
if (newListeners?.size) {
|
|
2064
|
-
for (const [name, listener] of newListeners) {
|
|
2065
|
-
renderedElement.addEventListener(name, listener);
|
|
2066
|
-
}
|
|
2067
|
-
InterceptBindingDirective.#attachedBindings.set(renderedElement, new Map(newListeners));
|
|
2068
|
-
} else {
|
|
2069
|
-
InterceptBindingDirective.#attachedBindings.delete(renderedElement);
|
|
2070
|
-
}
|
|
2071
|
-
}
|
|
2072
|
-
}
|
|
2073
|
-
|
|
2074
2029
|
export const cloneCustomElement = <T extends HTMLElement>(element: T, deep?: boolean): T => {
|
|
2075
2030
|
const clone = document.createElement(element.localName) as T;
|
|
2076
2031
|
for (const attribute of element.attributes) {
|
|
@@ -2099,13 +2054,13 @@ export class HTMLElementWithLightDOMTemplate extends HTMLElement {
|
|
|
2099
2054
|
clone.appendChild(HTMLElementWithLightDOMTemplate.cloneNode(child));
|
|
2100
2055
|
}
|
|
2101
2056
|
if (node instanceof Element && clone instanceof Element) {
|
|
2102
|
-
InterceptBindingDirective.setEventListeners(node, clone);
|
|
2057
|
+
Lit.CustomDirectives.InterceptBindingDirective.setEventListeners(node, clone);
|
|
2103
2058
|
}
|
|
2104
2059
|
return clone;
|
|
2105
2060
|
}
|
|
2106
2061
|
|
|
2107
2062
|
private static patchLitTemplate(template: Lit.LitTemplate): void {
|
|
2108
|
-
const interceptingWrapper = Lit.Directive.directive(InterceptBindingDirective);
|
|
2063
|
+
const interceptingWrapper = Lit.Directive.directive(Lit.CustomDirectives.InterceptBindingDirective);
|
|
2109
2064
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2110
2065
|
const patchingWrapper = <Args extends any[], R>(fn: (...args: Args) => R): ((...args: Args) => R) => {
|
|
2111
2066
|
return function(this: unknown, ...args: Args): R {
|
|
@@ -1144,8 +1144,12 @@ export class Widget<ContentTypeT extends HTMLElement|DocumentFragment = HTMLElem
|
|
|
1144
1144
|
}
|
|
1145
1145
|
|
|
1146
1146
|
setMinimumAndPreferredSizes(width: number, height: number, preferredWidth: number, preferredHeight: number): void {
|
|
1147
|
-
|
|
1147
|
+
const newConstraints =
|
|
1148
1148
|
new Geometry.Constraints(new Geometry.Size(width, height), new Geometry.Size(preferredWidth, preferredHeight));
|
|
1149
|
+
if (this.#constraints?.isEqual(newConstraints)) {
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
this.#constraints = newConstraints;
|
|
1149
1153
|
this.invalidateConstraints();
|
|
1150
1154
|
}
|
|
1151
1155
|
|
|
@@ -1154,7 +1158,11 @@ export class Widget<ContentTypeT extends HTMLElement|DocumentFragment = HTMLElem
|
|
|
1154
1158
|
}
|
|
1155
1159
|
|
|
1156
1160
|
set minimumSize(size: Geometry.Size) {
|
|
1157
|
-
|
|
1161
|
+
const newConstraints = new Geometry.Constraints(size);
|
|
1162
|
+
if (this.#constraints?.isEqual(newConstraints)) {
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
this.#constraints = newConstraints;
|
|
1158
1166
|
this.invalidateConstraints();
|
|
1159
1167
|
}
|
|
1160
1168
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
/* eslint-disable @devtools/no-imperative-dom-api */
|
|
5
5
|
|
|
6
|
+
import type * as Common from '../../../../core/common/common.js';
|
|
6
7
|
import type * as Platform from '../../../../core/platform/platform.js';
|
|
7
8
|
import type * as TextUtils from '../../../../core/text_utils/text_utils.js';
|
|
8
9
|
import * as Lit from '../../../lit/lit.js';
|
|
@@ -79,6 +80,39 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
|
|
|
79
80
|
#hiddenColumns = new Set<string>();
|
|
80
81
|
#usedCreationNode: DataGridElementNode|null = null;
|
|
81
82
|
#sortingChangedScheduled = false;
|
|
83
|
+
#columnsVisibilitySetting?: Common.Settings.Setting<Record<string, {visible: boolean}>>;
|
|
84
|
+
|
|
85
|
+
set columnsVisibilitySetting(setting: Common.Settings.Setting<Record<string, {visible: boolean}>>) {
|
|
86
|
+
this.#columnsVisibilitySetting = setting;
|
|
87
|
+
this.#applyColumnVisibilitySetting();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get columnsVisibilitySetting(): Common.Settings.Setting<Record<string, {visible: boolean}>>|undefined {
|
|
91
|
+
return this.#columnsVisibilitySetting;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#applyColumnVisibilitySetting(): void {
|
|
95
|
+
if (!this.#columnsVisibilitySetting) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const settingValue = this.#columnsVisibilitySetting.get();
|
|
99
|
+
let changed = false;
|
|
100
|
+
for (const column of this.#columns) {
|
|
101
|
+
if (this.#hideableColumns.has(column.id) && settingValue[column.id]?.visible === false) {
|
|
102
|
+
if (!this.#hiddenColumns.has(column.id)) {
|
|
103
|
+
this.#hiddenColumns.add(column.id);
|
|
104
|
+
changed = true;
|
|
105
|
+
}
|
|
106
|
+
} else if (this.#hiddenColumns.has(column.id)) {
|
|
107
|
+
this.#hiddenColumns.delete(column.id);
|
|
108
|
+
changed = true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (changed) {
|
|
112
|
+
const visibleColumns = new Set(this.#columns.map(({id}) => id).filter(id => !this.#hiddenColumns.has(id)));
|
|
113
|
+
this.#dataGrid.setColumnsVisibility(visibleColumns);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
82
116
|
|
|
83
117
|
constructor() {
|
|
84
118
|
super();
|
|
@@ -133,6 +167,11 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
|
|
|
133
167
|
}
|
|
134
168
|
this.#dataGrid.setColumnsVisibility(
|
|
135
169
|
new Set(this.#columns.map(({id}) => id).filter(column => !this.#hiddenColumns.has(column))));
|
|
170
|
+
if (this.#columnsVisibilitySetting) {
|
|
171
|
+
const settingValue = this.#columnsVisibilitySetting.get();
|
|
172
|
+
settingValue[column.id] = {visible: !this.#hiddenColumns.has(column.id)};
|
|
173
|
+
this.#columnsVisibilitySetting.set(settingValue);
|
|
174
|
+
}
|
|
136
175
|
}, {checked: !this.#hiddenColumns.has(column.id)});
|
|
137
176
|
}
|
|
138
177
|
}
|
|
@@ -320,6 +359,7 @@ export class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate
|
|
|
320
359
|
const visibleColumns = new Set(this.#columns.map(({id}) => id).filter(id => !this.#hiddenColumns.has(id)));
|
|
321
360
|
this.#dataGrid.setColumnsVisibility(visibleColumns);
|
|
322
361
|
this.#dataGrid.setEditCallback(hasEditableColumn ? this.#editCallback.bind(this) : undefined, INTERNAL_TOKEN);
|
|
362
|
+
this.#applyColumnVisibilitySetting();
|
|
323
363
|
}
|
|
324
364
|
|
|
325
365
|
#needUpdateColumns(mutationList: MutationRecord[]): boolean {
|
|
@@ -80,7 +80,7 @@ export function renderSettingSelect(setting: Common.Settings.Setting<unknown>, s
|
|
|
80
80
|
<select
|
|
81
81
|
id=${controlId}
|
|
82
82
|
aria-label=${name}
|
|
83
|
-
.disabled=${disabled
|
|
83
|
+
.disabled=${Boolean(disabled)}
|
|
84
84
|
@change=${onSelectChange}
|
|
85
85
|
jslog=${VisualLogging.dropDown().track({change: true}).context(setting.name)}
|
|
86
86
|
>
|
|
@@ -709,6 +709,7 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
|
|
|
709
709
|
if (text instanceof HTMLElement) {
|
|
710
710
|
link.appendChild(text);
|
|
711
711
|
} else if (bypassURLTrimming) {
|
|
712
|
+
link.removeChildren();
|
|
712
713
|
link.classList.add('devtools-link-styled-trim');
|
|
713
714
|
Linkifier.appendTextWithoutHashes(link, text);
|
|
714
715
|
} else {
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Copyright 2026 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
|
+
import * as Lit from '../../third_party/lit/lit.js';
|
|
6
|
+
|
|
7
|
+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
8
|
+
export type BindingEventListener = (arg: any) => any;
|
|
9
|
+
|
|
10
|
+
export class InterceptBindingDirective extends Lit.Directive.Directive {
|
|
11
|
+
static readonly #interceptedBindings = new WeakMap<Element, Map<string, BindingEventListener>>();
|
|
12
|
+
static readonly #attachedBindings = new WeakMap<Element, Map<string, Set<BindingEventListener>>>();
|
|
13
|
+
|
|
14
|
+
override update(part: Lit.Directive.Part, [listener]: [BindingEventListener]): unknown {
|
|
15
|
+
if (part.type !== Lit.Directive.PartType.EVENT) {
|
|
16
|
+
return listener;
|
|
17
|
+
}
|
|
18
|
+
let eventListeners = InterceptBindingDirective.#interceptedBindings.get(part.element);
|
|
19
|
+
if (!eventListeners) {
|
|
20
|
+
eventListeners = new Map();
|
|
21
|
+
InterceptBindingDirective.#interceptedBindings.set(part.element, eventListeners);
|
|
22
|
+
}
|
|
23
|
+
eventListeners.set(part.name, listener);
|
|
24
|
+
|
|
25
|
+
return this.render(listener);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-function-type */
|
|
29
|
+
render(listener: Function): Function {
|
|
30
|
+
return listener;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static setEventListeners(templateElements: Element|Iterable<Element>, renderedElement: Element): void {
|
|
34
|
+
const attachedListeners = InterceptBindingDirective.#attachedBindings.get(renderedElement);
|
|
35
|
+
if (attachedListeners) {
|
|
36
|
+
for (const [name, listeners] of attachedListeners) {
|
|
37
|
+
for (const listener of listeners) {
|
|
38
|
+
renderedElement.removeEventListener(name, listener);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const elements = templateElements instanceof Element ? [templateElements] : templateElements;
|
|
44
|
+
const newAttachedListeners = new Map<string, Set<BindingEventListener>>();
|
|
45
|
+
for (const templateElement of elements) {
|
|
46
|
+
const newListeners = InterceptBindingDirective.#interceptedBindings.get(templateElement);
|
|
47
|
+
if (newListeners) {
|
|
48
|
+
for (const [name, listener] of newListeners) {
|
|
49
|
+
renderedElement.addEventListener(name, listener);
|
|
50
|
+
let listenersSet = newAttachedListeners.get(name);
|
|
51
|
+
if (!listenersSet) {
|
|
52
|
+
listenersSet = new Set();
|
|
53
|
+
newAttachedListeners.set(name, listenersSet);
|
|
54
|
+
}
|
|
55
|
+
listenersSet.add(listener);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (newAttachedListeners.size) {
|
|
61
|
+
InterceptBindingDirective.#attachedBindings.set(renderedElement, newAttachedListeners);
|
|
62
|
+
} else {
|
|
63
|
+
InterceptBindingDirective.#attachedBindings.delete(renderedElement);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static registerListeners(element: Element, listeners?: Record<string, EventListenerOrEventListenerObject>): void {
|
|
68
|
+
if (!listeners) {
|
|
69
|
+
InterceptBindingDirective.#interceptedBindings.delete(element);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const map = new Map<string, BindingEventListener>();
|
|
73
|
+
for (const [name, listener] of Object.entries(listeners)) {
|
|
74
|
+
map.set(name,
|
|
75
|
+
typeof listener === 'function' ? listener as BindingEventListener :
|
|
76
|
+
listener.handleEvent.bind(listener) as BindingEventListener);
|
|
77
|
+
}
|
|
78
|
+
InterceptBindingDirective.#interceptedBindings.set(element, map);
|
|
79
|
+
}
|
|
80
|
+
}
|