chrome-devtools-frontend 1.0.1699061 → 1.0.1701636
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/front_end/core/root/Runtime.ts +5 -0
- package/front_end/core/sdk/CSSPropertyParserMatchers.ts +16 -11
- package/front_end/core/sdk/NetworkManager.ts +7 -0
- package/front_end/core/sdk/SecurityOrigin.ts +1 -0
- package/front_end/core/sdk/ServiceWorkerCacheModel.ts +3 -0
- package/front_end/core/sdk/SourceMap.ts +12 -1
- package/front_end/core/sdk/SourceMapCache.ts +12 -0
- package/front_end/core/sdk/SourceMapManager.ts +17 -8
- package/front_end/core/sdk/SourceMapScopeChainEntry.ts +2 -19
- package/front_end/core/sdk/SourceMapScopesInfo.ts +21 -0
- package/front_end/core/sdk/StorageBucketsModel.ts +2 -0
- package/front_end/entrypoints/formatter_worker/ScopeParser.ts +7 -3
- package/front_end/entrypoints/formatter_worker/Substitute.ts +90 -26
- package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +1 -1
- package/front_end/entrypoints/main/ExecutionContextSelector.ts +17 -4
- package/front_end/entrypoints/main/GlobalAiButton.ts +2 -6
- package/front_end/entrypoints/main/MainImpl.ts +8 -1
- package/front_end/generated/InspectorBackendCommands.ts +13 -5
- package/front_end/generated/SupportedCSSProperties.ts +14 -0
- package/front_end/generated/protocol-mapping.d.ts +48 -9
- package/front_end/generated/protocol-proxy-api.d.ts +37 -7
- package/front_end/generated/protocol.ts +135 -22
- package/front_end/models/ai_assistance/debug.ts +10 -2
- package/front_end/models/bindings/NetworkProject.ts +30 -0
- package/front_end/models/bindings/ResourceScriptMapping.ts +62 -0
- package/front_end/models/change_tracker/ChangeTracker.ts +1 -1
- package/front_end/models/comment_manager/CD4ABridge.ts +4 -4
- package/front_end/models/comment_manager/CommentManager.ts +21 -0
- package/front_end/models/extensions/ExtensionAPI.ts +4 -2
- package/front_end/models/formatter/FormatterWorkerPool.ts +2 -2
- package/front_end/models/issues_manager/CookieIssue.ts +0 -2
- package/front_end/models/javascript_metadata/NativeFunctions.ts +7 -2
- package/front_end/models/persistence/NetworkPersistenceManager.ts +29 -4
- package/front_end/models/source_map_scopes/NamesResolver.ts +65 -40
- package/front_end/models/source_map_scopes/ScopeChainModel.ts +21 -1
- package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +70 -1
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +5 -8
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +1 -1
- package/front_end/panels/application/AppManifestView.ts +128 -134
- package/front_end/panels/application/CrashReportContextView.ts +5 -5
- package/front_end/panels/application/DeviceBoundSessionsTreeElement.ts +17 -17
- package/front_end/panels/application/DeviceBoundSessionsView.ts +136 -137
- package/front_end/panels/application/IndexedDBModel.ts +3 -0
- package/front_end/panels/application/OriginTrialTreeView.ts +18 -23
- package/front_end/panels/application/ReportingApiTreeElement.ts +3 -3
- package/front_end/panels/application/ReportingApiView.ts +6 -14
- package/front_end/panels/application/application-meta.ts +7 -7
- package/front_end/panels/common/CommentThreadWidget.ts +19 -6
- package/front_end/panels/common/CommentsOverlayWidget.ts +143 -10
- package/front_end/panels/common/CommentsStatusBarPill.ts +13 -1
- package/front_end/panels/common/ExtensionServer.ts +61 -42
- package/front_end/panels/common/GeminiRebrandPromoDialog.ts +1 -1
- package/front_end/panels/common/commentThreadWidget.css +18 -0
- package/front_end/panels/common/common-meta.ts +4 -1
- package/front_end/panels/console/ConsolePrompt.ts +1 -1
- package/front_end/panels/console/ConsoleViewMessage.ts +1 -1
- package/front_end/panels/elements/ClassesPaneWidget.ts +2 -1
- package/front_end/panels/elements/DOMTreeContextMenu.ts +1 -1
- package/front_end/panels/elements/{ElementsTreeOutline.ts → DOMTreeWidget.ts} +45 -31
- package/front_end/panels/elements/ElementsPanel.ts +1 -1
- package/front_end/panels/elements/ElementsTreeElement.ts +3 -1
- package/front_end/panels/elements/ShortcutTreeElement.ts +1 -1
- package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +4 -6
- package/front_end/panels/elements/TopLayerContainer.ts +1 -1
- package/front_end/panels/elements/elements.ts +4 -3
- package/front_end/panels/elements/elementsTreeOutline.css +4 -0
- package/front_end/panels/event_listeners/EventListenersView.ts +9 -4
- package/front_end/panels/issues/IssuesPane.ts +34 -22
- package/front_end/panels/network/RequestPayloadView.ts +17 -15
- package/front_end/panels/profiler/HeapDetachedElementsDataGrid.ts +1 -1
- package/front_end/panels/profiler/HeapProfileView.ts +8 -6
- package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +8 -1
- package/front_end/panels/profiler/HeapSnapshotView.ts +6 -4
- package/front_end/panels/recorder/RecordingView.ts +32 -53
- package/front_end/panels/recorder/controlButton.css +6 -0
- package/front_end/panels/recorder/recordingView.css +11 -2
- package/front_end/panels/security/SecurityPanel.ts +87 -99
- package/front_end/panels/sensors/SensorsView.ts +87 -0
- package/front_end/panels/sensors/sensors-meta.ts +69 -1
- package/front_end/panels/settings/keybindsSettingsTab.css +1 -1
- package/front_end/panels/sources/DebuggerPlugin.ts +136 -55
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +17 -15
- package/front_end/panels/timeline/components/IgnoreListSetting.ts +0 -2
- package/front_end/panels/timeline/components/LiveMetricsView.ts +59 -64
- package/front_end/panels/timeline/components/liveMetricsView.css +1 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/lighthouse/README.chromium +2 -2
- package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1580 -1524
- package/front_end/third_party/lighthouse/locales/ar-XB.json +111 -72
- package/front_end/third_party/lighthouse/locales/ar.json +113 -74
- package/front_end/third_party/lighthouse/locales/bg.json +112 -73
- package/front_end/third_party/lighthouse/locales/ca.json +112 -73
- package/front_end/third_party/lighthouse/locales/cs.json +112 -73
- package/front_end/third_party/lighthouse/locales/da.json +112 -73
- package/front_end/third_party/lighthouse/locales/de.json +112 -73
- package/front_end/third_party/lighthouse/locales/el.json +112 -73
- package/front_end/third_party/lighthouse/locales/en-GB.json +111 -72
- package/front_end/third_party/lighthouse/locales/en-US.json +102 -66
- package/front_end/third_party/lighthouse/locales/en-XA.json +111 -72
- package/front_end/third_party/lighthouse/locales/en-XL.json +102 -66
- package/front_end/third_party/lighthouse/locales/es-419.json +112 -73
- package/front_end/third_party/lighthouse/locales/es.json +112 -73
- package/front_end/third_party/lighthouse/locales/fi.json +112 -73
- package/front_end/third_party/lighthouse/locales/fil.json +112 -73
- package/front_end/third_party/lighthouse/locales/fr.json +112 -73
- package/front_end/third_party/lighthouse/locales/he.json +112 -73
- package/front_end/third_party/lighthouse/locales/hi.json +112 -73
- package/front_end/third_party/lighthouse/locales/hr.json +112 -73
- package/front_end/third_party/lighthouse/locales/hu.json +112 -73
- package/front_end/third_party/lighthouse/locales/id.json +112 -73
- package/front_end/third_party/lighthouse/locales/it.json +113 -74
- package/front_end/third_party/lighthouse/locales/ja.json +112 -73
- package/front_end/third_party/lighthouse/locales/ko.json +112 -73
- package/front_end/third_party/lighthouse/locales/lt.json +112 -73
- package/front_end/third_party/lighthouse/locales/lv.json +112 -73
- package/front_end/third_party/lighthouse/locales/nl.json +112 -73
- package/front_end/third_party/lighthouse/locales/no.json +112 -73
- package/front_end/third_party/lighthouse/locales/pl.json +112 -73
- package/front_end/third_party/lighthouse/locales/pt-PT.json +112 -73
- package/front_end/third_party/lighthouse/locales/pt.json +112 -73
- package/front_end/third_party/lighthouse/locales/ro.json +112 -73
- package/front_end/third_party/lighthouse/locales/ru.json +112 -73
- package/front_end/third_party/lighthouse/locales/sk.json +112 -73
- package/front_end/third_party/lighthouse/locales/sl.json +112 -73
- package/front_end/third_party/lighthouse/locales/sr-Latn.json +112 -73
- package/front_end/third_party/lighthouse/locales/sr.json +112 -73
- package/front_end/third_party/lighthouse/locales/sv.json +124 -85
- package/front_end/third_party/lighthouse/locales/ta.json +112 -73
- package/front_end/third_party/lighthouse/locales/te.json +112 -73
- package/front_end/third_party/lighthouse/locales/th.json +112 -73
- package/front_end/third_party/lighthouse/locales/tr.json +113 -74
- package/front_end/third_party/lighthouse/locales/uk.json +112 -73
- package/front_end/third_party/lighthouse/locales/vi.json +112 -73
- package/front_end/third_party/lighthouse/locales/zh-HK.json +112 -73
- package/front_end/third_party/lighthouse/locales/zh-TW.json +113 -74
- package/front_end/third_party/lighthouse/locales/zh.json +113 -74
- package/front_end/third_party/lighthouse/report/bundle.d.ts +4 -4
- package/front_end/third_party/lighthouse/report/bundle.js +10 -3
- package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +2 -2
- package/front_end/third_party/lit/lit.ts +3 -0
- package/front_end/third_party/lit/package.json +3 -0
- package/front_end/third_party/lit/rebuild.sh +3 -2
- package/front_end/ui/comments/CommentAnchorResolver.ts +8 -2
- package/front_end/ui/comments/CommentOverlayManager.ts +2 -1
- package/front_end/ui/legacy/InspectorView.ts +4 -3
- package/front_end/ui/legacy/TabbedPane.ts +121 -80
- package/front_end/ui/legacy/Treeoutline.ts +37 -7
- package/front_end/ui/legacy/UIUtils.ts +7 -0
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +1 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +135 -146
- package/front_end/ui/legacy/treeoutline.css +2 -2
- package/front_end/ui/lit/lit.ts +1 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +11 -0
- package/inspector_overlay/highlight_anchor.ts +197 -0
- package/inspector_overlay/tool_highlight.ts +8 -0
- package/package.json +1 -1
|
@@ -9,4 +9,7 @@ import * as Directive from './lib/directive.js';
|
|
|
9
9
|
import * as Decorators from './lib/decorators.js';
|
|
10
10
|
import * as StaticHtml from './lib/static-html.js';
|
|
11
11
|
|
|
12
|
+
// Required for lit-analyzer
|
|
13
|
+
export type {DirectiveResult} from './lib/directive.js';
|
|
14
|
+
|
|
12
15
|
export {AsyncDirective, Directives, Directive, Decorators, StaticHtml};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
set -e
|
|
1
2
|
npm install
|
|
2
|
-
../../../
|
|
3
|
-
|
|
3
|
+
vpython3 ../../../third_party/typescript/typescript.py --ignoreConfig --skipLibCheck -d -t esnext -m esnext --moduleResolution bundler src/*
|
|
4
|
+
node_modules/rollup/dist/bin/rollup -c
|
|
4
5
|
rm -rf node_modules src/*.js src/*.d.ts
|
|
5
6
|
# Because there's a bug in clang causing it to reformat import lists even where formatting is disabled, run it right away
|
|
6
7
|
git cl format --js
|
|
@@ -29,6 +29,12 @@ const DISALLOWED_COMMENT_TARGETS = new Set<number>([
|
|
|
29
29
|
VisualLogging.VisualElements.Toolbar,
|
|
30
30
|
]);
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* The comment thread UI itself is never a valid comment target: anything inside it (including the
|
|
34
|
+
* DOM node link in its header) must stay inert while comment mode is on.
|
|
35
|
+
*/
|
|
36
|
+
export const COMMENT_THREAD_UI_SELECTOR = '.comment-thread-widget';
|
|
37
|
+
|
|
32
38
|
/**
|
|
33
39
|
* Finds the closest ancestor (or the element itself) matching a CSS selector,
|
|
34
40
|
* traversing across Shadow DOM boundaries (shadow root boundaries to shadow hosts).
|
|
@@ -268,7 +274,7 @@ function resolveCodeMirrorLineInfo(element: Element): CodeMirrorLineInfo|null {
|
|
|
268
274
|
* Resolves an arbitrary clicked or targeted DOM element to its appropriate semantic comment anchor element.
|
|
269
275
|
*
|
|
270
276
|
* Traversal hierarchy:
|
|
271
|
-
* 1. Checks if the element is part of a tab title (returns null if so).
|
|
277
|
+
* 1. Checks if the element is part of a tab title or of the comment thread UI (returns null if so).
|
|
272
278
|
* 2. Escalates CodeMirror line/gutter elements to .cm-editor (only if the clicked line is non-empty).
|
|
273
279
|
* 3. Checks for domain IDs (`data-network-request-id` or `data-backend-node-id`) across shadow boundaries,
|
|
274
280
|
* returning the owning domain element.
|
|
@@ -281,7 +287,7 @@ function resolveCodeMirrorLineInfo(element: Element): CodeMirrorLineInfo|null {
|
|
|
281
287
|
*/
|
|
282
288
|
export function resolveCommentAnchorElement(
|
|
283
289
|
element: Element, options?: {clientX: number, clientY: number, forHover?: boolean}): Element|null {
|
|
284
|
-
if (isTabTitle(element)) {
|
|
290
|
+
if (isTabTitle(element) || closestAcrossShadow(element, COMMENT_THREAD_UI_SELECTOR)) {
|
|
285
291
|
return null;
|
|
286
292
|
}
|
|
287
293
|
const customResolver = getCustomAnchorResolverForElement(element);
|
|
@@ -7,6 +7,7 @@ import * as CommentManager from '../../models/comment_manager/comment_manager.js
|
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
closestAcrossShadow,
|
|
10
|
+
COMMENT_THREAD_UI_SELECTOR,
|
|
10
11
|
type CommentAnchorSignature,
|
|
11
12
|
type CommentThread,
|
|
12
13
|
computeVisibleRect,
|
|
@@ -238,7 +239,7 @@ export class CommentOverlayManager extends Common.ObjectWrapper.ObjectWrapper<Ev
|
|
|
238
239
|
}
|
|
239
240
|
|
|
240
241
|
handleElementClick(element: Element, options?: {clientX: number, clientY: number}): boolean {
|
|
241
|
-
if (!this.isCommentMode() || closestAcrossShadow(element,
|
|
242
|
+
if (!this.isCommentMode() || closestAcrossShadow(element, COMMENT_THREAD_UI_SELECTOR)) {
|
|
242
243
|
return false;
|
|
243
244
|
}
|
|
244
245
|
this.clearDraftThreads();
|
|
@@ -853,15 +853,16 @@ export class InspectorView extends VBox implements ViewLocationResolver {
|
|
|
853
853
|
}
|
|
854
854
|
}
|
|
855
855
|
|
|
856
|
-
renderStatusBar(): void {
|
|
856
|
+
renderStatusBar(visible = true): void {
|
|
857
857
|
if (!this.#statusBarContainer) {
|
|
858
858
|
this.#statusBarContainer = document.createElement('div');
|
|
859
859
|
this.#statusBarContainer.style.display = 'contents';
|
|
860
860
|
this.element.appendChild(this.#statusBarContainer);
|
|
861
861
|
}
|
|
862
862
|
// eslint-disable-next-line @devtools/no-lit-render-outside-of-view
|
|
863
|
-
Lit.render(
|
|
864
|
-
|
|
863
|
+
Lit.render(
|
|
864
|
+
visible ? html`<devtools-widget class="flex-none" ${widget(StatusBarWidget)}></devtools-widget>` : Lit.nothing,
|
|
865
|
+
this.#statusBarContainer);
|
|
865
866
|
}
|
|
866
867
|
|
|
867
868
|
private createInfoBarDiv(): void {
|
|
@@ -77,6 +77,8 @@ export interface TabInfo {
|
|
|
77
77
|
jslogContext?: string;
|
|
78
78
|
enabled?: boolean;
|
|
79
79
|
selected?: boolean;
|
|
80
|
+
icon?: Element|null;
|
|
81
|
+
suffix?: Element|null;
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
const TabbedPaneBase: Common.ObjectWrapper.EventMixin<EventTypes, typeof VBox> = Common.ObjectWrapper.eventMixin(
|
|
@@ -120,6 +122,8 @@ export class TabbedPane extends TabbedPaneBase {
|
|
|
120
122
|
this.registerRequiredCSS(tabbedPaneStyles);
|
|
121
123
|
this.element.classList.add('tabbed-pane');
|
|
122
124
|
this.contentElement.classList.add('tabbed-pane-shadow');
|
|
125
|
+
this.element.classList.add('flex-auto', 'vbox');
|
|
126
|
+
this.contentElement.classList.add('flex-auto', 'vbox');
|
|
123
127
|
this.contentElement.tabIndex = -1;
|
|
124
128
|
this.setDefaultFocusedElement(this.contentElement);
|
|
125
129
|
this.#headerElement = this.contentElement.createChild('div', 'tabbed-pane-header');
|
|
@@ -565,47 +569,6 @@ export class TabbedPane extends TabbedPaneBase {
|
|
|
565
569
|
}));
|
|
566
570
|
}
|
|
567
571
|
|
|
568
|
-
set tabs(tabs: TabInfo[]) {
|
|
569
|
-
const newIds = new Set(tabs.map(tab => tab.id));
|
|
570
|
-
for (const id of this.tabsById.keys()) {
|
|
571
|
-
if (!newIds.has(id)) {
|
|
572
|
-
this.#closeTab(id);
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
let index = 0;
|
|
576
|
-
for (const tab of tabs) {
|
|
577
|
-
const existingTab = this.tabsById.get(tab.id);
|
|
578
|
-
if (existingTab) {
|
|
579
|
-
this.changeTabView(tab.id, tab.view);
|
|
580
|
-
this.changeTabTitle(tab.id, tab.title, tab.tabTooltip);
|
|
581
|
-
if (tab.jslogContext !== undefined) {
|
|
582
|
-
existingTab.jslogContext = tab.jslogContext;
|
|
583
|
-
}
|
|
584
|
-
if (tab.isCloseable !== undefined) {
|
|
585
|
-
existingTab.closeable = tab.isCloseable;
|
|
586
|
-
}
|
|
587
|
-
if (tab.previewFeature !== undefined) {
|
|
588
|
-
existingTab.previewFeature = tab.previewFeature;
|
|
589
|
-
}
|
|
590
|
-
const currentIndex = this.#tabs.indexOf(existingTab);
|
|
591
|
-
if (currentIndex !== index) {
|
|
592
|
-
this.insertBefore(existingTab, index);
|
|
593
|
-
}
|
|
594
|
-
} else {
|
|
595
|
-
this.appendTab(
|
|
596
|
-
tab.id, tab.title, tab.view, tab.tabTooltip, /* userGesture=*/ false, tab.isCloseable, tab.previewFeature,
|
|
597
|
-
index, tab.jslogContext);
|
|
598
|
-
}
|
|
599
|
-
if (tab.enabled !== undefined) {
|
|
600
|
-
this.setTabEnabled(tab.id, tab.enabled);
|
|
601
|
-
}
|
|
602
|
-
if (tab.selected) {
|
|
603
|
-
this.selectTab(tab.id);
|
|
604
|
-
}
|
|
605
|
-
++index;
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
|
|
609
572
|
override onResize(): void {
|
|
610
573
|
if (this.currentDevicePixelRatio !== window.devicePixelRatio) {
|
|
611
574
|
// Force recalculation of all tab widths on a DPI change
|
|
@@ -1694,42 +1657,72 @@ export class TabbedPaneElement extends WidgetElement<TabbedPane> {
|
|
|
1694
1657
|
this.#automaticReorder = automatic;
|
|
1695
1658
|
this.getWidget()?.setAllowTabReorder(this.#allowTabReorder, this.#automaticReorder);
|
|
1696
1659
|
}
|
|
1660
|
+
|
|
1661
|
+
get tabs(): TabInfo[] {
|
|
1662
|
+
const widget = Widget.getOrCreateWidget(this) as TabbedPane;
|
|
1663
|
+
if (widget) {
|
|
1664
|
+
this.#updateTabs(widget);
|
|
1665
|
+
return widget.tabs;
|
|
1666
|
+
}
|
|
1667
|
+
return [];
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
#delegate?: TabbedPaneTabDelegate;
|
|
1671
|
+
set tabDelegate(delegate: TabbedPaneTabDelegate) {
|
|
1672
|
+
this.#delegate = delegate;
|
|
1673
|
+
this.getWidget()?.setTabDelegate(delegate);
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
#placeholderElement?: Element;
|
|
1677
|
+
#managedTabIds = new Set<string>();
|
|
1678
|
+
set placeholder(element: Element) {
|
|
1679
|
+
this.#placeholderElement = element;
|
|
1680
|
+
this.getWidget()?.setPlaceholderElement(element);
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1697
1683
|
readonly #tabObserver = new MutationObserver(() => this.#updateTabs());
|
|
1698
1684
|
|
|
1699
1685
|
constructor() {
|
|
1700
1686
|
super();
|
|
1701
1687
|
|
|
1702
|
-
registerWidgetConfig(
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1688
|
+
registerWidgetConfig(
|
|
1689
|
+
this, widgetConfig(element => {
|
|
1690
|
+
const widget = new TabbedPane(element as TabbedPaneElement);
|
|
1691
|
+
widget.setCloseableTabs(this.#closeableTabs);
|
|
1692
|
+
widget.setAllowTabReorder(this.#allowTabReorder, this.#automaticReorder);
|
|
1693
|
+
if (this.#delegate) {
|
|
1694
|
+
widget.setTabDelegate(this.#delegate);
|
|
1695
|
+
}
|
|
1696
|
+
const slot = widget.contentElement.querySelector('slot:not([name])');
|
|
1697
|
+
if (slot) {
|
|
1698
|
+
slot.addEventListener('slotchange', () => this.#syncTabs());
|
|
1699
|
+
}
|
|
1700
|
+
widget.addEventListener(Events.TabSelected, event => {
|
|
1701
|
+
const nodes = this.#getTabNodes(widget);
|
|
1702
|
+
for (const child of nodes) {
|
|
1703
|
+
if (child.id === widget.selectedTabId) {
|
|
1704
|
+
child.setAttribute('selected', '');
|
|
1705
|
+
} else {
|
|
1706
|
+
child.removeAttribute('selected');
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
this.dispatchEvent(new CustomEvent(
|
|
1710
|
+
'select', {detail: {tabId: widget.selectedTabId, isUserGesture: event.data?.isUserGesture}}));
|
|
1711
|
+
});
|
|
1712
|
+
widget.addEventListener(Events.TabClosed, event => {
|
|
1713
|
+
this.dispatchEvent(
|
|
1714
|
+
new CustomEvent('close', {detail: {tabId: event.data.tabId, isUserGesture: event.data.isUserGesture}}));
|
|
1715
|
+
});
|
|
1716
|
+
widget.addEventListener(Events.TabOrderChanged, event => {
|
|
1717
|
+
this.dispatchEvent(
|
|
1718
|
+
new CustomEvent('taborderchanged', {detail: {tabId: event.data.tabId, tabIds: widget.tabIds()}}));
|
|
1719
|
+
});
|
|
1720
|
+
if (this.#placeholderElement) {
|
|
1721
|
+
widget.setPlaceholderElement(this.#placeholderElement);
|
|
1722
|
+
}
|
|
1723
|
+
this.#syncTabs(widget);
|
|
1724
|
+
return widget;
|
|
1725
|
+
}));
|
|
1733
1726
|
}
|
|
1734
1727
|
|
|
1735
1728
|
override disconnectedCallback(): void {
|
|
@@ -1747,8 +1740,7 @@ export class TabbedPaneElement extends WidgetElement<TabbedPane> {
|
|
|
1747
1740
|
|
|
1748
1741
|
#updateObserver(widget: TabbedPane): void {
|
|
1749
1742
|
this.#tabObserver.disconnect();
|
|
1750
|
-
const
|
|
1751
|
-
const nodes = slot ? slot.assignedElements() : [];
|
|
1743
|
+
const nodes = this.#getTabNodes(widget);
|
|
1752
1744
|
for (const child of nodes) {
|
|
1753
1745
|
this.#tabObserver.observe(child, {
|
|
1754
1746
|
attributes: true,
|
|
@@ -1757,13 +1749,18 @@ export class TabbedPaneElement extends WidgetElement<TabbedPane> {
|
|
|
1757
1749
|
}
|
|
1758
1750
|
}
|
|
1759
1751
|
|
|
1752
|
+
#getTabNodes(widget: TabbedPane): Element[] {
|
|
1753
|
+
return Array.from(widget.element.children)
|
|
1754
|
+
.filter(c => c.id !== '' && !c.hasAttribute('slot') && !c.classList.contains('tabbed-pane-header') &&
|
|
1755
|
+
!c.classList.contains('tabbed-pane-content'));
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1760
1758
|
#updateTabs(widget = this.getWidget()): void {
|
|
1761
1759
|
if (!widget) {
|
|
1762
1760
|
return;
|
|
1763
1761
|
}
|
|
1764
1762
|
const tabs: TabInfo[] = [];
|
|
1765
|
-
const
|
|
1766
|
-
const nodes = slot ? slot.assignedElements() : [];
|
|
1763
|
+
const nodes = this.#getTabNodes(widget);
|
|
1767
1764
|
for (const child of nodes) {
|
|
1768
1765
|
const id = child.id;
|
|
1769
1766
|
const title = child.getAttribute('title') || '';
|
|
@@ -1772,13 +1769,12 @@ export class TabbedPaneElement extends WidgetElement<TabbedPane> {
|
|
|
1772
1769
|
const enabled = !child.hasAttribute('disabled');
|
|
1773
1770
|
const isCloseable =
|
|
1774
1771
|
child.hasAttribute('closeable') ? true : (child.hasAttribute('uncloseable') ? false : undefined);
|
|
1772
|
+
const icon = child.querySelector('[slot="icon"]') ?? undefined;
|
|
1773
|
+
const suffix = child.querySelector('[slot="suffix"]') ?? undefined;
|
|
1775
1774
|
const view = Widget.getOrCreateWidget(child as HTMLElement);
|
|
1776
1775
|
view.setHideOnDetach();
|
|
1777
1776
|
if (widget.selectedTabId !== id) {
|
|
1778
|
-
view.hideWidget();
|
|
1779
1777
|
child.classList.add('hidden');
|
|
1780
|
-
} else {
|
|
1781
|
-
view.showWidget();
|
|
1782
1778
|
}
|
|
1783
1779
|
tabs.push({
|
|
1784
1780
|
id,
|
|
@@ -1788,10 +1784,55 @@ export class TabbedPaneElement extends WidgetElement<TabbedPane> {
|
|
|
1788
1784
|
selected,
|
|
1789
1785
|
enabled,
|
|
1790
1786
|
isCloseable,
|
|
1787
|
+
icon,
|
|
1788
|
+
suffix,
|
|
1791
1789
|
});
|
|
1792
1790
|
}
|
|
1793
1791
|
|
|
1794
|
-
|
|
1792
|
+
const newIds = new Set(tabs.map(tab => tab.id));
|
|
1793
|
+
for (const id of this.#managedTabIds) {
|
|
1794
|
+
if (!newIds.has(id)) {
|
|
1795
|
+
widget.closeTab(id);
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
this.#managedTabIds = newIds;
|
|
1799
|
+
let index = 0;
|
|
1800
|
+
for (const tab of tabs) {
|
|
1801
|
+
const existingTab = widget.tabsById.get(tab.id);
|
|
1802
|
+
if (existingTab) {
|
|
1803
|
+
widget.changeTabView(tab.id, tab.view);
|
|
1804
|
+
widget.changeTabTitle(tab.id, tab.title, tab.tabTooltip);
|
|
1805
|
+
if (tab.jslogContext !== undefined) {
|
|
1806
|
+
existingTab.jslogContext = tab.jslogContext;
|
|
1807
|
+
}
|
|
1808
|
+
if (tab.isCloseable !== undefined) {
|
|
1809
|
+
existingTab.closeable = tab.isCloseable;
|
|
1810
|
+
}
|
|
1811
|
+
if (tab.previewFeature !== undefined) {
|
|
1812
|
+
existingTab.previewFeature = tab.previewFeature;
|
|
1813
|
+
}
|
|
1814
|
+
const currentIndex = widget.tabIndex(tab.id);
|
|
1815
|
+
if (currentIndex !== index) {
|
|
1816
|
+
widget.insertBefore(existingTab, index);
|
|
1817
|
+
}
|
|
1818
|
+
} else {
|
|
1819
|
+
widget.appendTab(tab.id, tab.title, tab.view, tab.tabTooltip, /* userGesture=*/ false, tab.isCloseable,
|
|
1820
|
+
tab.previewFeature, index, tab.jslogContext);
|
|
1821
|
+
}
|
|
1822
|
+
if (tab.icon !== undefined) {
|
|
1823
|
+
widget.setTabIcon(tab.id, tab.icon as unknown as Icon);
|
|
1824
|
+
}
|
|
1825
|
+
if (tab.suffix !== undefined) {
|
|
1826
|
+
widget.setSuffixElement(tab.id, tab.suffix as unknown as HTMLElement);
|
|
1827
|
+
}
|
|
1828
|
+
if (tab.enabled !== undefined) {
|
|
1829
|
+
widget.setTabEnabled(tab.id, tab.enabled);
|
|
1830
|
+
}
|
|
1831
|
+
if (tab.selected) {
|
|
1832
|
+
widget.selectTab(tab.id);
|
|
1833
|
+
}
|
|
1834
|
+
++index;
|
|
1835
|
+
}
|
|
1795
1836
|
}
|
|
1796
1837
|
}
|
|
1797
1838
|
|
|
@@ -60,6 +60,7 @@ import {
|
|
|
60
60
|
HTMLElementWithLightDOMTemplate,
|
|
61
61
|
isEditing,
|
|
62
62
|
} from './UIUtils.js';
|
|
63
|
+
import {Widget} from './Widget.js';
|
|
63
64
|
|
|
64
65
|
const UIStrings = {
|
|
65
66
|
/**
|
|
@@ -1304,9 +1305,9 @@ export class TreeElement {
|
|
|
1304
1305
|
}
|
|
1305
1306
|
}
|
|
1306
1307
|
|
|
1307
|
-
revealAndSelect(omitFocus?: boolean): void {
|
|
1308
|
+
revealAndSelect(omitFocus?: boolean, selectedByUser?: boolean): void {
|
|
1308
1309
|
this.reveal(true);
|
|
1309
|
-
this.select(omitFocus);
|
|
1310
|
+
this.select(omitFocus, selectedByUser ?? false);
|
|
1310
1311
|
}
|
|
1311
1312
|
|
|
1312
1313
|
deselect(): void {
|
|
@@ -1653,11 +1654,18 @@ class TreeViewTreeElement extends TreeElement {
|
|
|
1653
1654
|
}
|
|
1654
1655
|
this.#refreshScheduled = true;
|
|
1655
1656
|
queueMicrotask(() => {
|
|
1656
|
-
this.#refreshScheduled
|
|
1657
|
-
|
|
1657
|
+
if (this.#refreshScheduled) {
|
|
1658
|
+
this.refresh();
|
|
1659
|
+
}
|
|
1658
1660
|
});
|
|
1659
1661
|
}
|
|
1660
1662
|
|
|
1663
|
+
flushPendingRefreshForTesting(): void {
|
|
1664
|
+
if (this.#refreshScheduled) {
|
|
1665
|
+
this.refresh();
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1661
1669
|
updateAttributes(): void {
|
|
1662
1670
|
const expandable = Boolean(this.configElement.querySelector(':scope > ul[role="group"]'));
|
|
1663
1671
|
this.setExpandable(expandable);
|
|
@@ -1668,7 +1676,8 @@ class TreeViewTreeElement extends TreeElement {
|
|
|
1668
1676
|
this.#clonedClasses.clear();
|
|
1669
1677
|
for (let i = 0; i < this.configElement.attributes.length; ++i) {
|
|
1670
1678
|
const attribute = this.configElement.attributes.item(i);
|
|
1671
|
-
if (attribute && attribute.name !== 'role' &&
|
|
1679
|
+
if (attribute && attribute.name !== 'role' &&
|
|
1680
|
+
(TreeViewTreeElement.CLONED_ATTRIBUTES.has(attribute.name) || attribute.name.startsWith('data-'))) {
|
|
1672
1681
|
this.listItemElement.setAttribute(attribute.name, attribute.value);
|
|
1673
1682
|
this.#clonedAttributes.add(attribute.name);
|
|
1674
1683
|
}
|
|
@@ -1684,6 +1693,7 @@ class TreeViewTreeElement extends TreeElement {
|
|
|
1684
1693
|
}
|
|
1685
1694
|
|
|
1686
1695
|
refresh(): void {
|
|
1696
|
+
this.#refreshScheduled = false;
|
|
1687
1697
|
const hadFocus = this.listItemElement.hasFocus();
|
|
1688
1698
|
this.titleElement.textContent = '';
|
|
1689
1699
|
this.updateAttributes();
|
|
@@ -1726,7 +1736,7 @@ class TreeViewTreeElement extends TreeElement {
|
|
|
1726
1736
|
return super.onenter();
|
|
1727
1737
|
}
|
|
1728
1738
|
|
|
1729
|
-
|
|
1739
|
+
removeFromTree(): void {
|
|
1730
1740
|
removeNode(this,
|
|
1731
1741
|
Boolean(this.parent &&
|
|
1732
1742
|
(this.parent as TreeViewTreeElement).configElement?.querySelector(':scope > ul[role="group"]')));
|
|
@@ -1892,6 +1902,26 @@ export class TreeViewElement extends HTMLElementWithLightDOMTemplate {
|
|
|
1892
1902
|
return this.#treeOutline;
|
|
1893
1903
|
}
|
|
1894
1904
|
|
|
1905
|
+
flushPendingUpdatesForTesting(): void {
|
|
1906
|
+
this.flushPendingMutationsForTesting();
|
|
1907
|
+
const stack: TreeElement[] = [...this.#treeOutline.rootElement().children()];
|
|
1908
|
+
while (stack.length > 0) {
|
|
1909
|
+
const item = stack.pop();
|
|
1910
|
+
if (!item) {
|
|
1911
|
+
continue;
|
|
1912
|
+
}
|
|
1913
|
+
if (item instanceof TreeViewTreeElement) {
|
|
1914
|
+
item.flushPendingRefreshForTesting();
|
|
1915
|
+
}
|
|
1916
|
+
if (item.children()) {
|
|
1917
|
+
stack.push(...item.children());
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
for (const widgetEl of this.#treeOutline.shadowRoot.querySelectorAll('devtools-widget')) {
|
|
1921
|
+
void Widget.get(widgetEl)?.performUpdate();
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1895
1925
|
override focus(): void {
|
|
1896
1926
|
if (!this.#treeOutline.selectedTreeElement && this.#treeOutline.firstChild()) {
|
|
1897
1927
|
this.#treeOutline.firstChild()?.select(/* omitFocus */ true, /* selectedByUser */ false);
|
|
@@ -2030,7 +2060,7 @@ export class TreeViewElement extends HTMLElementWithLightDOMTemplate {
|
|
|
2030
2060
|
protected override removeNodes(nodes: NodeList|Node[]): void {
|
|
2031
2061
|
for (const node of getTreeNodes(nodes)) {
|
|
2032
2062
|
if (node instanceof HTMLLIElement) {
|
|
2033
|
-
TreeViewTreeElement.get(node)?.
|
|
2063
|
+
TreeViewTreeElement.get(node)?.removeFromTree();
|
|
2034
2064
|
} else if (node.treeElement) {
|
|
2035
2065
|
removeNode(node.treeElement,
|
|
2036
2066
|
Boolean(node.treeElement.parent &&
|
|
@@ -2196,6 +2196,13 @@ export class HTMLElementWithLightDOMTemplate extends HTMLElement {
|
|
|
2196
2196
|
render(template, this.#contentTemplate.content);
|
|
2197
2197
|
}
|
|
2198
2198
|
|
|
2199
|
+
flushPendingMutationsForTesting(): void {
|
|
2200
|
+
const records = this.#mutationObserver.takeRecords();
|
|
2201
|
+
if (records.length > 0) {
|
|
2202
|
+
this.#onChange(records);
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2199
2206
|
#onChange(mutationList: MutationRecord[]): void {
|
|
2200
2207
|
this.onChange(mutationList);
|
|
2201
2208
|
const addedNodes = new Set<Node>();
|
|
@@ -646,7 +646,7 @@ function nodeMixin<TBase extends Constructor<DataGridNode<any>>>(base: TBase) {
|
|
|
646
646
|
|
|
647
647
|
override createElement(): HTMLElement {
|
|
648
648
|
const element = super.createElement();
|
|
649
|
-
element.addEventListener('click', this.#onRowMouseEvent.bind(this));
|
|
649
|
+
element.addEventListener('click', this.#onRowMouseEvent.bind(this), {capture: true});
|
|
650
650
|
element.addEventListener('mouseenter', this.#onRowMouseEvent.bind(this));
|
|
651
651
|
element.addEventListener('mouseleave', this.#onRowMouseEvent.bind(this));
|
|
652
652
|
if (this.#configElement.hasAttribute('style')) {
|