chrome-devtools-frontend 1.0.1689415 → 1.0.1690116
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/eslint.config.mjs +8 -2
- package/front_end/core/common/Object.ts +10 -4
- package/front_end/core/i18n/collect-ui-strings.js +5 -5
- package/front_end/core/i18n/generate-locales-js.js +1 -1
- package/front_end/core/i18n/i18n.ts +6 -0
- package/front_end/core/root/Runtime.ts +0 -5
- package/front_end/core/sdk/CSSMetadata.ts +3 -5
- package/front_end/core/sdk/DOMModel.ts +46 -11
- package/front_end/core/sdk/EmulationModel.ts +18 -0
- package/front_end/core/sdk/SDKSettings.ts +9 -0
- package/front_end/core/sdk/Script.ts +0 -1
- package/front_end/core/sdk/SecurityOrigin.ts +135 -25
- package/front_end/core/sdk/Target.ts +1 -5
- package/front_end/models/ai_assistance/AiUtils.ts +0 -10
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +6 -10
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +0 -1
- package/front_end/models/ai_assistance/injected.ts +0 -2
- package/front_end/models/javascript_metadata/NativeFunctions.ts +1 -1
- package/front_end/models/trace/insights/CLSCulprits.ts +1 -2
- package/front_end/models/trace/insights/Cache.ts +1 -3
- package/front_end/models/trace/insights/CharacterSet.ts +1 -3
- package/front_end/models/trace/insights/DOMSize.ts +1 -3
- package/front_end/models/trace/insights/DocumentLatency.ts +1 -3
- package/front_end/models/trace/insights/DuplicatedJavaScript.ts +1 -3
- package/front_end/models/trace/insights/FontDisplay.ts +1 -2
- package/front_end/models/trace/insights/ForcedReflow.ts +1 -2
- package/front_end/models/trace/insights/INPBreakdown.ts +1 -3
- package/front_end/models/trace/insights/ImageDelivery.ts +1 -3
- package/front_end/models/trace/insights/LCPBreakdown.ts +1 -3
- package/front_end/models/trace/insights/LCPDiscovery.ts +1 -3
- package/front_end/models/trace/insights/LegacyJavaScript.ts +1 -3
- package/front_end/models/trace/insights/ModernHTTP.ts +1 -2
- package/front_end/models/trace/insights/NetworkDependencyTree.ts +1 -2
- package/front_end/models/trace/insights/RenderBlocking.ts +1 -3
- package/front_end/models/trace/insights/SlowCSSSelector.ts +1 -3
- package/front_end/models/trace/insights/ThirdParties.ts +1 -3
- package/front_end/models/trace/insights/Viewport.ts +1 -2
- package/front_end/panels/accessibility/ARIAAttributesView.ts +1 -1
- package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +3 -3
- package/front_end/panels/accessibility/AccessibilityNodeView.ts +1 -2
- package/front_end/panels/accessibility/AccessibilityStrings.ts +7 -3
- package/front_end/panels/ai_assistance/components/AIv2MarkdownRenderer.ts +2 -2
- package/front_end/panels/ai_assistance/components/AccessibilityAgentMarkdownRenderer.ts +1 -3
- package/front_end/panels/animation/AnimationGroupPreviewUI.ts +1 -1
- package/front_end/panels/animation/AnimationTimeline.ts +1 -1
- package/front_end/panels/animation/AnimationUI.ts +1 -1
- package/front_end/panels/application/AppManifestView.ts +6 -2
- package/front_end/panels/application/ApplicationPanelSidebar.ts +2 -4
- package/front_end/panels/application/BounceTrackingMitigationsTreeElement.ts +1 -1
- package/front_end/panels/application/FrameDetailsView.ts +1 -1
- package/front_end/panels/application/IndexedDBViews.ts +3 -2
- package/front_end/panels/application/ReportingApiTreeElement.ts +1 -1
- package/front_end/panels/application/ReportingApiView.ts +2 -2
- package/front_end/panels/application/ServiceWorkerUpdateCycleView.ts +1 -1
- package/front_end/panels/application/ServiceWorkersView.ts +1 -1
- package/front_end/panels/application/StorageBucketsTreeElement.ts +1 -1
- package/front_end/panels/application/StorageItemsToolbar.ts +6 -2
- package/front_end/panels/application/StorageView.ts +9 -8
- package/front_end/panels/application/TrustTokensTreeElement.ts +1 -1
- package/front_end/panels/application/WebMCPView.ts +2 -1
- package/front_end/panels/application/components/BounceTrackingMitigationsView.ts +1 -1
- package/front_end/panels/application/components/CrashReportContextGrid.ts +1 -1
- package/front_end/panels/application/components/EndpointsGrid.ts +1 -1
- package/front_end/panels/application/components/ReportsGrid.ts +1 -1
- package/front_end/panels/application/components/TrustTokensView.ts +1 -1
- package/front_end/panels/application/preloading/components/MismatchedPreloadingGrid.ts +1 -1
- package/front_end/panels/application/preloading/components/PreloadingGrid.ts +1 -1
- package/front_end/panels/application/preloading/components/RuleSetGrid.ts +7 -2
- package/front_end/panels/application/serviceWorkerUpdateCycleView.css +2 -0
- package/front_end/panels/autofill/AutofillView.ts +2 -2
- package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +2 -3
- package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +1 -1
- package/front_end/panels/changes/ChangesSidebar.ts +56 -15
- package/front_end/panels/changes/ChangesView.ts +1 -1
- package/front_end/panels/console/ConsolePrompt.ts +6 -2
- package/front_end/panels/console/ConsoleSidebar.ts +6 -2
- package/front_end/panels/elements/ElementsTreeElement.ts +12 -0
- package/front_end/panels/elements/ElementsTreeOutline.ts +400 -128
- package/front_end/panels/elements/PropertyRenderer.ts +22 -15
- package/front_end/panels/elements/StandaloneStylesContainer.ts +6 -2
- package/front_end/panels/elements/StylePropertyTreeElement.ts +75 -26
- package/front_end/panels/elements/StylesSidebarPane.ts +6 -2
- package/front_end/panels/elements/elementsTreeOutline.css +4 -0
- package/front_end/panels/emulation/DeviceModeView.ts +6 -1
- package/front_end/panels/emulation/InspectedPagePlaceholder.ts +6 -2
- package/front_end/panels/layer_viewer/LayerDetailsView.ts +6 -2
- package/front_end/panels/layer_viewer/LayerTreeOutline.ts +7 -2
- package/front_end/panels/layer_viewer/Layers3DView.ts +8 -1
- package/front_end/panels/layer_viewer/PaintProfilerView.ts +6 -2
- package/front_end/panels/lighthouse/lighthousePanel.css +5 -5
- package/front_end/panels/lighthouse/lighthouseStartView.css +13 -13
- package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +6 -2
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +6 -2
- package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +6 -2
- package/front_end/panels/mobile_throttling/ThrottlingManager.ts +25 -54
- package/front_end/panels/network/NetworkLogView.ts +8 -3
- package/front_end/panels/network/components/RequestHeadersView.css +5 -0
- package/front_end/panels/network/networkLogView.css +4 -0
- package/front_end/panels/network/requestInitiatorViewTree.css +2 -0
- package/front_end/panels/performance_monitor/performanceMonitor.css +3 -3
- package/front_end/panels/profiler/HeapDetachedElementsView.ts +7 -2
- package/front_end/panels/profiler/HeapProfileView.ts +7 -2
- package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +8 -4
- package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +8 -4
- package/front_end/panels/profiler/HeapSnapshotView.ts +15 -6
- package/front_end/panels/profiler/HeapTimelineOverview.ts +6 -2
- package/front_end/panels/profiler/ProfileFlameChartDataProvider.ts +12 -5
- package/front_end/panels/profiler/ProfileLauncherView.ts +6 -2
- package/front_end/panels/profiler/profilesPanel.css +8 -9
- package/front_end/panels/profiler/profilesSidebarTree.css +13 -13
- package/front_end/panels/protocol_monitor/JSONEditor.css +2 -2
- package/front_end/panels/protocol_monitor/JSONEditor.ts +6 -1
- package/front_end/panels/protocol_monitor/protocolMonitor.css +2 -2
- package/front_end/panels/sources/SourcesView.ts +7 -2
- package/front_end/panels/sources/TabbedEditorContainer.ts +6 -2
- package/front_end/panels/sources/UISourceCodeFrame.ts +10 -3
- package/front_end/panels/timeline/AnimationsTrackAppender.ts +1 -1
- package/front_end/panels/timeline/AnnotationHelpers.ts +9 -9
- package/front_end/panels/timeline/CountersGraph.ts +8 -8
- package/front_end/panels/timeline/EventsTimelineTreeView.ts +3 -3
- package/front_end/panels/timeline/ExtensionTrackAppender.ts +1 -1
- package/front_end/panels/timeline/GPUTrackAppender.ts +1 -1
- package/front_end/panels/timeline/InteractionsTrackAppender.ts +1 -1
- package/front_end/panels/timeline/IsolateSelector.ts +2 -2
- package/front_end/panels/timeline/LayoutShiftsTrackAppender.ts +3 -3
- package/front_end/panels/timeline/NetworkTrackAppender.ts +1 -1
- package/front_end/panels/timeline/StatusDialog.ts +5 -6
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +4 -4
- package/front_end/panels/timeline/ThreadAppender.ts +12 -14
- package/front_end/panels/timeline/TimelineController.ts +5 -8
- package/front_end/panels/timeline/TimelineDetailsView.ts +13 -9
- package/front_end/panels/timeline/TimelineEventOverview.ts +4 -4
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +17 -17
- package/front_end/panels/timeline/TimelineFlameChartView.ts +8 -3
- package/front_end/panels/timeline/TimelineHistoryManager.ts +8 -8
- package/front_end/panels/timeline/TimelineLoader.ts +1 -1
- package/front_end/panels/timeline/TimelineMiniMap.ts +7 -2
- package/front_end/panels/timeline/TimelinePanel.ts +57 -59
- package/front_end/panels/timeline/TimelineSelectorStatsView.ts +27 -27
- package/front_end/panels/timeline/TimelineTreeView.ts +46 -44
- package/front_end/panels/timeline/TimelineUIUtils.ts +142 -116
- package/front_end/panels/timeline/TimingsTrackAppender.ts +1 -1
- package/front_end/panels/timeline/TrackConfigBanner.ts +4 -4
- package/front_end/panels/timeline/UIDevtoolsUtils.ts +15 -15
- package/front_end/panels/timeline/components/insights/Table.ts +1 -1
- package/front_end/panels/timeline/enable-easter-egg.js +1 -1
- package/front_end/panels/timeline/timeline-meta.ts +30 -30
- package/front_end/panels/timeline/timelineFlameChartView.css +10 -10
- package/front_end/panels/timeline/timelineFlamechartPopover.css +5 -5
- package/front_end/panels/timeline/timelineHistoryManager.css +7 -7
- package/front_end/panels/timeline/timelinePaintProfiler.css +2 -2
- package/front_end/panels/timeline/utils/IgnoreList.ts +4 -4
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/comments/CommentAnchorResolver.ts +12 -3
- package/front_end/ui/comments/CommentOverlayManager.ts +9 -1
- package/front_end/ui/components/buttons/Button.docs.ts +1 -1
- package/front_end/ui/components/buttons/button.css +21 -0
- package/front_end/ui/components/report_view/ReportView.docs.ts +1 -1
- package/front_end/ui/components/snackbars/Snackbars.docs.ts +1 -1
- package/front_end/ui/components/spinners/Spinner.ts +1 -1
- package/front_end/ui/components/spinners/Spinners.docs.ts +1 -1
- package/front_end/ui/components/suggestion_input/SuggestionInput.ts +1 -2
- package/front_end/ui/components/switch/Switch.docs.ts +1 -1
- package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +10 -8
- package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +2 -1
- package/front_end/ui/components/text_editor/ExecutionPositionHighlighter.ts +2 -2
- package/front_end/ui/components/text_editor/TextEditor.ts +19 -0
- package/front_end/ui/components/text_editor/config.ts +109 -96
- package/front_end/ui/components/text_editor/cursor_tooltip.ts +1 -1
- package/front_end/ui/components/text_editor/theme.ts +1 -1
- package/front_end/ui/components/tooltips/Tooltip.docs.ts +1 -1
- package/front_end/ui/components/tooltips/Tooltip.ts +1 -1
- package/front_end/ui/components/tree_outline/TreeOutlineUtils.ts +4 -1
- package/front_end/ui/kit/cards/Card.ts +1 -1
- package/front_end/ui/kit/icons/Icon.ts +1 -1
- package/front_end/ui/kit/link/Link.docs.ts +1 -1
- package/front_end/ui/kit/link/Link.ts +1 -1
- package/front_end/ui/legacy/ContextMenu.docs.ts +1 -1
- package/front_end/ui/legacy/Dialog.ts +10 -2
- package/front_end/ui/legacy/FilterBar.ts +6 -1
- package/front_end/ui/legacy/RadioButton.docs.ts +1 -1
- package/front_end/ui/legacy/SelectMenu.docs.ts +1 -1
- package/front_end/ui/legacy/Slider.docs.ts +1 -1
- package/front_end/ui/legacy/SplitWidget.ts +5 -1
- package/front_end/ui/legacy/TabbedPane.ts +5 -1
- package/front_end/ui/legacy/components/color_picker/Spectrum.ts +6 -1
- package/front_end/ui/legacy/components/data_grid/ViewportDataGrid.ts +6 -2
- package/front_end/ui/legacy/components/inline_editor/BezierEditor.ts +6 -1
- package/front_end/ui/legacy/components/inline_editor/CSSShadowEditor.ts +6 -2
- package/front_end/ui/legacy/components/object_ui/objectPropertiesSection.css +2 -0
- package/front_end/ui/legacy/components/perf_ui/FilmStripView.ts +6 -1
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +6 -2
- package/front_end/ui/legacy/components/perf_ui/TimelineOverviewPane.ts +8 -4
- package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +8 -3
- package/front_end/ui/legacy/components/quick_open/QuickOpen.ts +6 -1
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +7 -2
- package/package.json +2 -2
|
@@ -40,6 +40,7 @@ import * as i18n from '../../core/i18n/i18n.js';
|
|
|
40
40
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
41
41
|
import * as Badges from '../../models/badges/badges.js';
|
|
42
42
|
import * as Elements from '../../models/elements/elements.js';
|
|
43
|
+
import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
43
44
|
import * as CodeHighlighter from '../../ui/components/code_highlighter/code_highlighter.js';
|
|
44
45
|
import * as Highlighting from '../../ui/components/highlighting/highlighting.js';
|
|
45
46
|
import * as IssueCounter from '../../ui/components/issue_counter/issue_counter.js';
|
|
@@ -179,11 +180,13 @@ interface ViewInput {
|
|
|
179
180
|
onToggleAdoptedStyleSheetExpanded?: (sheet: SDK.DOMModel.AdoptedStyleSheet, expanded: boolean) => void;
|
|
180
181
|
selectedAdoptedStyleSheet?: SDK.DOMModel.AdoptedStyleSheet|null;
|
|
181
182
|
onSelectAdoptedStyleSheet?: (sheet: SDK.DOMModel.AdoptedStyleSheet) => void;
|
|
183
|
+
expandedChildrenLimit?: (node: SDK.DOMModel.DOMNode) => number;
|
|
184
|
+
onExpandAllChildren?: (node: SDK.DOMModel.DOMNode) => void;
|
|
185
|
+
updateRecordForNode?: (node: SDK.DOMModel.DOMNode) => Elements.ElementUpdateRecord.ElementUpdateRecord | null;
|
|
182
186
|
}
|
|
183
187
|
|
|
184
188
|
interface ViewOutput {
|
|
185
189
|
elementsTreeOutline?: ElementsTreeOutline;
|
|
186
|
-
imagePreviewPopover?: ImagePreviewPopover;
|
|
187
190
|
highlightedTreeElement: ElementsTreeElement|null;
|
|
188
191
|
searchMatchTreeElement?: ElementsTreeElement|null;
|
|
189
192
|
searchMatchQuery?: string;
|
|
@@ -230,84 +233,6 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
230
233
|
elementsTreeOutline.elementInternal.addEventListener('clipboard-paste', (event: Event) => {
|
|
231
234
|
input.onPaste?.(event);
|
|
232
235
|
}, false);
|
|
233
|
-
output.imagePreviewPopover = new ImagePreviewPopover(
|
|
234
|
-
elementsTreeOutline.contentElement,
|
|
235
|
-
event => {
|
|
236
|
-
let link: (Element|null) = (event.target as Element | null);
|
|
237
|
-
while (link && !ImagePreviewPopover.getImageURL(link)) {
|
|
238
|
-
link = link.parentElementOrShadowHost();
|
|
239
|
-
}
|
|
240
|
-
return link;
|
|
241
|
-
},
|
|
242
|
-
async link => {
|
|
243
|
-
const listItem = UI.UIUtils.enclosingNodeOrSelfWithNodeName(link, 'li');
|
|
244
|
-
if (!listItem) {
|
|
245
|
-
return undefined;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const treeElement =
|
|
249
|
-
(UI.TreeOutline.TreeElement.getTreeElementBylistItemNode(listItem) as ElementsTreeElement | undefined);
|
|
250
|
-
return await UIComponentUtils.ImagePreview.loadPrecomputedFeatures(treeElement?.node());
|
|
251
|
-
});
|
|
252
|
-
// TODO(changhaohan): refactor the popover to use tooltip component.
|
|
253
|
-
const popupHelper = new UI.PopoverHelper.PopoverHelper(elementsTreeOutline.elementInternal, event => {
|
|
254
|
-
const hoveredNode = event.composedPath()[0];
|
|
255
|
-
if (!(hoveredNode instanceof Element) || !hoveredNode.matches('.violating-element')) {
|
|
256
|
-
return null;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const listItem = UI.UIUtils.enclosingNodeOrSelfWithNodeName(hoveredNode, 'li');
|
|
260
|
-
if (!listItem) {
|
|
261
|
-
return null;
|
|
262
|
-
}
|
|
263
|
-
const treeElement =
|
|
264
|
-
UI.TreeOutline.TreeElement.getTreeElementBylistItemNode(listItem) as ElementsTreeElement | undefined;
|
|
265
|
-
const node = treeElement?.node();
|
|
266
|
-
if (!node) {
|
|
267
|
-
return null;
|
|
268
|
-
}
|
|
269
|
-
let issues = treeElement?.widget?.issues ?? [];
|
|
270
|
-
if (hoveredNode.classList.contains('webkit-html-attribute-name')) {
|
|
271
|
-
const attrName = hoveredNode.textContent;
|
|
272
|
-
issues = issues.filter(issue => getElementIssueDetails(issue)?.attribute === attrName);
|
|
273
|
-
} else if (hoveredNode.classList.contains('webkit-html-tag-name')) {
|
|
274
|
-
issues = issues.filter(issue => {
|
|
275
|
-
const details = getElementIssueDetails(issue);
|
|
276
|
-
return Boolean(details && !details.attribute);
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
if (issues.length === 0) {
|
|
280
|
-
return null;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
return {
|
|
284
|
-
box: hoveredNode.boxInWindow(),
|
|
285
|
-
show: async (popover: UI.GlassPane.GlassPane) => {
|
|
286
|
-
popover.setIgnoreLeftMargin(true);
|
|
287
|
-
// clang-format off
|
|
288
|
-
render(html`
|
|
289
|
-
<div class="squiggles-content">
|
|
290
|
-
${issues.map(issue => {
|
|
291
|
-
const elementIssueDetails = getElementIssueDetails(issue);
|
|
292
|
-
if (!elementIssueDetails) {
|
|
293
|
-
return nothing;
|
|
294
|
-
}
|
|
295
|
-
const issueKindIconName = IssueCounter.IssueCounter.getIssueKindIconName(issue.getKind());
|
|
296
|
-
const openIssueEvent = (): Promise<void> => Common.Revealer.reveal(issue);
|
|
297
|
-
return html`
|
|
298
|
-
<div class="squiggles-content-item">
|
|
299
|
-
<devtools-icon .name=${issueKindIconName} @click=${openIssueEvent}></devtools-icon>
|
|
300
|
-
<devtools-link class="link" @click=${openIssueEvent}>${i18nString(UIStrings.viewIssue)}</devtools-link>
|
|
301
|
-
<span>${elementIssueDetails.tooltip}</span>
|
|
302
|
-
</div>`;
|
|
303
|
-
})}
|
|
304
|
-
</div>`, popover.contentElement);
|
|
305
|
-
// clang-format on
|
|
306
|
-
return true;
|
|
307
|
-
},
|
|
308
|
-
};
|
|
309
|
-
}, 'elements.issue');
|
|
310
|
-
popupHelper.setTimeout(300);
|
|
311
236
|
target.appendChild(elementsTreeOutline.element);
|
|
312
237
|
}
|
|
313
238
|
|
|
@@ -333,9 +258,6 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
333
258
|
}
|
|
334
259
|
if (input.visible !== undefined) {
|
|
335
260
|
output.elementsTreeOutline.setVisible(input.visible);
|
|
336
|
-
if (!input.visible) {
|
|
337
|
-
output.imagePreviewPopover?.hide();
|
|
338
|
-
}
|
|
339
261
|
}
|
|
340
262
|
output.elementsTreeOutline.maxRowsShown = input.maxRowsShown;
|
|
341
263
|
output.elementsTreeOutline.setWordWrap(input.wrap);
|
|
@@ -556,11 +478,14 @@ function computeLeftIndent(depth: number, isExpandable: boolean): number {
|
|
|
556
478
|
}
|
|
557
479
|
|
|
558
480
|
export const DECLARATIVE_VIEW: View = (input: ViewInput, _output: ViewOutput, target: HTMLElement): void => {
|
|
481
|
+
let allRootNodes: SDK.DOMModel.DOMNode[] = [];
|
|
559
482
|
let rootNodes: SDK.DOMModel.DOMNode[] = [];
|
|
560
483
|
const rootDOMNode = input.rootDOMNode;
|
|
561
484
|
if (rootDOMNode) {
|
|
562
485
|
if (input.omitRootDOMNode) {
|
|
563
|
-
|
|
486
|
+
allRootNodes = getVisibleChildren(rootDOMNode, input.showComments ?? true);
|
|
487
|
+
const rootLimit = input.expandedChildrenLimit ? input.expandedChildrenLimit(rootDOMNode) : InitialChildrenLimit;
|
|
488
|
+
rootNodes = allRootNodes.slice(0, rootLimit);
|
|
564
489
|
} else {
|
|
565
490
|
rootNodes = [rootDOMNode];
|
|
566
491
|
}
|
|
@@ -762,15 +687,14 @@ export const DECLARATIVE_VIEW: View = (input: ViewInput, _output: ViewOutput, ta
|
|
|
762
687
|
(input.expandRoot &&
|
|
763
688
|
(node === input.rootDOMNode || (input.omitRootDOMNode && node.parentNode === input.rootDOMNode)))));
|
|
764
689
|
const hasChildren = nodeHasVisibleChildren(node, input.rootDOMNode, input.maxTreeDepth, input.omitRootDOMNode);
|
|
765
|
-
const
|
|
690
|
+
const allVisibleChildren = hasChildren ? getVisibleChildren(node, input.showComments ?? true) : [];
|
|
691
|
+
const limit = input.expandedChildrenLimit ? input.expandedChildrenLimit(node) : InitialChildrenLimit;
|
|
692
|
+
const children = allVisibleChildren.slice(0, limit);
|
|
693
|
+
const remainingChildrenCount = allVisibleChildren.length - children.length;
|
|
766
694
|
const tagName = node.nodeName().toLowerCase();
|
|
767
695
|
const needsClosingTag = node.nodeType() === Node.ELEMENT_NODE && !ForbiddenClosingTagElements.has(tagName) &&
|
|
768
696
|
!node.pseudoType() && (hasChildren || !ElementsTreeWidget.canShowInlineText(node));
|
|
769
697
|
|
|
770
|
-
// TODO: Move tree node pagination ("Show all nodes" button and expandedChildrenLimit) to a declarative tree slice model.
|
|
771
|
-
// TODO: Move ImagePreviewPopover and issue tooltip helpers into declarative Lit directives or tooltip components.
|
|
772
|
-
// TODO: Move DOMModel event subscription and reactive state synchronization (updateRecords, DOM update animations) directly into DOMTreeWidget.
|
|
773
|
-
|
|
774
698
|
const on = Lit.Directive.directive(Lit.CustomDirectives.InterceptBindingDirective);
|
|
775
699
|
|
|
776
700
|
const onSelect = (): void => {
|
|
@@ -893,12 +817,29 @@ export const DECLARATIVE_VIEW: View = (input: ViewInput, _output: ViewOutput, ta
|
|
|
893
817
|
input.onContextMenu?.(node, event, widget);
|
|
894
818
|
}
|
|
895
819
|
},
|
|
820
|
+
updateRecord: input.updateRecordForNode?.(node) ?? null,
|
|
896
821
|
})}
|
|
897
822
|
${hasChildren ? html`
|
|
898
823
|
<ul role="group">
|
|
899
824
|
${UI.TreeOutline.ifExpanded(html`
|
|
900
825
|
${node.adoptedStyleSheetsForNode.length > 0 ? renderAdoptedStyleSheets(node, depth + 1) : nothing}
|
|
901
826
|
${children.map(child => renderNode(child, depth + 1))}
|
|
827
|
+
${remainingChildrenCount > 0 ? html`
|
|
828
|
+
<li role="treeitem"
|
|
829
|
+
class="elements-tree-expand-all"
|
|
830
|
+
style="--indent: ${computeLeftIndent(depth + 1, false)}px"
|
|
831
|
+
jslog=${VisualLogging.treeItem('show-all-nodes').parent('elementsTreeOutline')}>
|
|
832
|
+
<devtools-button
|
|
833
|
+
.variant=${Buttons.Button.Variant.OUTLINED}
|
|
834
|
+
title=${i18nString(UIStrings.showAllNodesDMore, {PH1: remainingChildrenCount})}
|
|
835
|
+
@click=${on((event: Event) => {
|
|
836
|
+
event.stopPropagation();
|
|
837
|
+
input.onExpandAllChildren?.(node);
|
|
838
|
+
})}>
|
|
839
|
+
${i18nString(UIStrings.showAllNodesDMore, {PH1: remainingChildrenCount})}
|
|
840
|
+
</devtools-button>
|
|
841
|
+
</li>
|
|
842
|
+
` : nothing}
|
|
902
843
|
${node instanceof SDK.DOMModel.DOMDocument ? renderTopLayerContainer(node, depth + 1) : nothing}
|
|
903
844
|
${needsClosingTag ? html`
|
|
904
845
|
<li role="treeitem"
|
|
@@ -924,6 +865,7 @@ export const DECLARATIVE_VIEW: View = (input: ViewInput, _output: ViewOutput, ta
|
|
|
924
865
|
input.onContextMenu?.(node, event, widget);
|
|
925
866
|
}
|
|
926
867
|
},
|
|
868
|
+
updateRecord: input.updateRecordForNode?.(node) ?? null,
|
|
927
869
|
})}
|
|
928
870
|
</li>
|
|
929
871
|
` : nothing}
|
|
@@ -957,7 +899,30 @@ export const DECLARATIVE_VIEW: View = (input: ViewInput, _output: ViewOutput, ta
|
|
|
957
899
|
<style>${CodeHighlighter.codeHighlighterStyles}</style>
|
|
958
900
|
<ul role="tree">
|
|
959
901
|
${rootNodes.map(node => renderNode(node))}
|
|
960
|
-
${input.omitRootDOMNode && input.rootDOMNode
|
|
902
|
+
${input.omitRootDOMNode && input.rootDOMNode ? (() => {
|
|
903
|
+
const remaining = allRootNodes.length - rootNodes.length;
|
|
904
|
+
if (remaining <= 0) {
|
|
905
|
+
return nothing;
|
|
906
|
+
}
|
|
907
|
+
const root = input.rootDOMNode;
|
|
908
|
+
return html`
|
|
909
|
+
<li role="treeitem"
|
|
910
|
+
class="elements-tree-expand-all"
|
|
911
|
+
style="--indent: ${computeLeftIndent(0, false)}px"
|
|
912
|
+
jslog=${VisualLogging.treeItem('show-all-nodes').parent('elementsTreeOutline')}>
|
|
913
|
+
<devtools-button
|
|
914
|
+
.variant=${Buttons.Button.Variant.OUTLINED}
|
|
915
|
+
title=${i18nString(UIStrings.showAllNodesDMore, {PH1: remaining})}
|
|
916
|
+
@click=${on((event: Event) => {
|
|
917
|
+
event.stopPropagation();
|
|
918
|
+
input.onExpandAllChildren?.(root);
|
|
919
|
+
})}>
|
|
920
|
+
${i18nString(UIStrings.showAllNodesDMore, {PH1: remaining})}
|
|
921
|
+
</devtools-button>
|
|
922
|
+
</li>
|
|
923
|
+
`;
|
|
924
|
+
})() : nothing}
|
|
925
|
+
${input.omitRootDOMNode && input.rootDOMNode instanceof SDK.DOMModel.DOMDocument ? renderTopLayerContainer(input.rootDOMNode, 0) : nothing}
|
|
961
926
|
</ul>
|
|
962
927
|
`}>
|
|
963
928
|
</devtools-tree>
|
|
@@ -966,6 +931,24 @@ export const DECLARATIVE_VIEW: View = (input: ViewInput, _output: ViewOutput, ta
|
|
|
966
931
|
/* clang-format on */
|
|
967
932
|
};
|
|
968
933
|
|
|
934
|
+
function getElementsTreeWidgetAndNode(element: Element): {node?: SDK.DOMModel.DOMNode, widget?: ElementsTreeWidget} {
|
|
935
|
+
let current: Element|null = element;
|
|
936
|
+
while (current) {
|
|
937
|
+
if (current.tagName === 'LI') {
|
|
938
|
+
const treeElement = UI.TreeOutline.TreeElement.getTreeElementBylistItemNode(current);
|
|
939
|
+
if (treeElement instanceof ElementsTreeElement) {
|
|
940
|
+
return {node: treeElement.node(), widget: treeElement.widget};
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
const widget = UI.Widget.Widget.get(current);
|
|
944
|
+
if (widget instanceof ElementsTreeWidget) {
|
|
945
|
+
return {node: widget.node, widget};
|
|
946
|
+
}
|
|
947
|
+
current = current.parentElementOrShadowHost();
|
|
948
|
+
}
|
|
949
|
+
return {};
|
|
950
|
+
}
|
|
951
|
+
|
|
969
952
|
/**
|
|
970
953
|
* The main goal of this presenter is to wrap ElementsTreeOutline until
|
|
971
954
|
* ElementsTreeOutline can be fully integrated into DOMTreeWidget.
|
|
@@ -1022,6 +1005,7 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1022
1005
|
#rootDOMNode: SDK.DOMModel.DOMNode|null = null;
|
|
1023
1006
|
#selectedDOMNode: SDK.DOMModel.DOMNode|null = null;
|
|
1024
1007
|
#expandedNodes = new Set<SDK.DOMModel.DOMNode>();
|
|
1008
|
+
#expandedChildrenLimitByNode = new WeakMap<SDK.DOMModel.DOMNode, number>();
|
|
1025
1009
|
|
|
1026
1010
|
// FIXME: this is not declarative because ElementsTreeOutline can
|
|
1027
1011
|
// change root node internally.
|
|
@@ -1119,6 +1103,10 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1119
1103
|
#adoptedStyleSheetExpanded = new WeakMap<SDK.DOMModel.AdoptedStyleSheet, boolean>();
|
|
1120
1104
|
#selectedAdoptedStyleSheet: SDK.DOMModel.AdoptedStyleSheet|null = null;
|
|
1121
1105
|
|
|
1106
|
+
// TODO: Move #imagePreviewPopover and #issuePopoverHelper to the view once declarative versions exist.
|
|
1107
|
+
#imagePreviewPopover?: ImagePreviewPopover;
|
|
1108
|
+
#issuePopoverHelper?: UI.PopoverHelper.PopoverHelper;
|
|
1109
|
+
|
|
1122
1110
|
#view: View;
|
|
1123
1111
|
#viewOutput: ViewOutput = {
|
|
1124
1112
|
highlightedTreeElement: null,
|
|
@@ -1145,6 +1133,92 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1145
1133
|
SDK.OverlayModel.OverlayModel, SDK.OverlayModel.Events.INSPECT_MODE_WILL_BE_TOGGLED,
|
|
1146
1134
|
this.#clearHighlightedNode, this, {scoped: true});
|
|
1147
1135
|
}
|
|
1136
|
+
this.#setupPopovers();
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
// TODO: Move imagePreviewPopover and issuePopoverHelper to the view once declarative versions exist.
|
|
1140
|
+
#setupPopovers(): void {
|
|
1141
|
+
this.#imagePreviewPopover = new ImagePreviewPopover(
|
|
1142
|
+
this.contentElement,
|
|
1143
|
+
event => {
|
|
1144
|
+
let link: (Element|null) = (event.composedPath()[0] as Element | null);
|
|
1145
|
+
while (link && link !== this.contentElement && !ImagePreviewPopover.getImageURL(link)) {
|
|
1146
|
+
link = link.parentElementOrShadowHost();
|
|
1147
|
+
}
|
|
1148
|
+
return (link && link !== this.contentElement) ? link : null;
|
|
1149
|
+
},
|
|
1150
|
+
async link => {
|
|
1151
|
+
const {node} = getElementsTreeWidgetAndNode(link);
|
|
1152
|
+
return await UIComponentUtils.ImagePreview.loadPrecomputedFeatures(node);
|
|
1153
|
+
});
|
|
1154
|
+
|
|
1155
|
+
this.#issuePopoverHelper = new UI.PopoverHelper.PopoverHelper(this.contentElement, event => {
|
|
1156
|
+
const hoveredNode = event.composedPath()[0];
|
|
1157
|
+
if (!(hoveredNode instanceof Element) || !hoveredNode.matches('.violating-element')) {
|
|
1158
|
+
return null;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
const {node, widget} = getElementsTreeWidgetAndNode(hoveredNode);
|
|
1162
|
+
if (!node) {
|
|
1163
|
+
return null;
|
|
1164
|
+
}
|
|
1165
|
+
let issues = widget?.issues ?? [];
|
|
1166
|
+
if (hoveredNode.classList.contains('webkit-html-attribute-name')) {
|
|
1167
|
+
const attrName = hoveredNode.textContent;
|
|
1168
|
+
issues = issues.filter(issue => getElementIssueDetails(issue)?.attribute === attrName);
|
|
1169
|
+
} else if (hoveredNode.classList.contains('webkit-html-tag-name')) {
|
|
1170
|
+
issues = issues.filter(issue => {
|
|
1171
|
+
const details = getElementIssueDetails(issue);
|
|
1172
|
+
return Boolean(details && !details.attribute);
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
if (issues.length === 0) {
|
|
1176
|
+
return null;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
return {
|
|
1180
|
+
box: hoveredNode.boxInWindow(),
|
|
1181
|
+
show: async (popover: UI.GlassPane.GlassPane) => {
|
|
1182
|
+
popover.setIgnoreLeftMargin(true);
|
|
1183
|
+
// clang-format off
|
|
1184
|
+
render(html`
|
|
1185
|
+
<div class="squiggles-content">
|
|
1186
|
+
${issues.map(issue => {
|
|
1187
|
+
const elementIssueDetails = getElementIssueDetails(issue);
|
|
1188
|
+
if (!elementIssueDetails) {
|
|
1189
|
+
return nothing;
|
|
1190
|
+
}
|
|
1191
|
+
const issueKindIconName = IssueCounter.IssueCounter.getIssueKindIconName(issue.getKind());
|
|
1192
|
+
const openIssueEvent = (): Promise<void> => Common.Revealer.reveal(issue);
|
|
1193
|
+
return html`
|
|
1194
|
+
<div class="squiggles-content-item">
|
|
1195
|
+
<devtools-icon .name=${issueKindIconName} @click=${openIssueEvent}></devtools-icon>
|
|
1196
|
+
<devtools-link class="link" @click=${openIssueEvent}>${i18nString(UIStrings.viewIssue)}</devtools-link>
|
|
1197
|
+
<span>${elementIssueDetails.tooltip}</span>
|
|
1198
|
+
</div>`;
|
|
1199
|
+
})}
|
|
1200
|
+
</div>`, popover.contentElement);
|
|
1201
|
+
// clang-format on
|
|
1202
|
+
return true;
|
|
1203
|
+
},
|
|
1204
|
+
};
|
|
1205
|
+
}, 'elements.issue');
|
|
1206
|
+
this.#issuePopoverHelper.setTimeout(300);
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
#updateRecords = new Map<SDK.DOMModel.DOMNode, Elements.ElementUpdateRecord.ElementUpdateRecord>();
|
|
1210
|
+
|
|
1211
|
+
updateRecordsForTest(): Map<SDK.DOMModel.DOMNode, Elements.ElementUpdateRecord.ElementUpdateRecord> {
|
|
1212
|
+
return this.#updateRecords;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
#addUpdateRecord(node: SDK.DOMModel.DOMNode): Elements.ElementUpdateRecord.ElementUpdateRecord {
|
|
1216
|
+
let record = this.#updateRecords.get(node);
|
|
1217
|
+
if (!record) {
|
|
1218
|
+
record = new Elements.ElementUpdateRecord.ElementUpdateRecord();
|
|
1219
|
+
this.#updateRecords.set(node, record);
|
|
1220
|
+
}
|
|
1221
|
+
return record;
|
|
1148
1222
|
}
|
|
1149
1223
|
|
|
1150
1224
|
#onDocumentUpdated(event: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMModel>): void {
|
|
@@ -1153,6 +1227,7 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1153
1227
|
this.#selectedDOMNode = null;
|
|
1154
1228
|
this.#expandedNodes.clear();
|
|
1155
1229
|
this.#currentHighlightedNode = null;
|
|
1230
|
+
this.#updateRecords.clear();
|
|
1156
1231
|
}
|
|
1157
1232
|
if (domModel.existingDocument()) {
|
|
1158
1233
|
this.rootDOMNode = domModel.existingDocument();
|
|
@@ -1160,8 +1235,123 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1160
1235
|
this.onDocumentUpdated(domModel);
|
|
1161
1236
|
}
|
|
1162
1237
|
|
|
1163
|
-
#
|
|
1164
|
-
|
|
1238
|
+
#updateModifiedNodesTimeout?: number;
|
|
1239
|
+
|
|
1240
|
+
#updateModifiedNodesSoon(): void {
|
|
1241
|
+
if (!this.#updateRecords.size) {
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
if (this.#updateModifiedNodesTimeout) {
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
this.#updateModifiedNodesTimeout = window.setTimeout(this.updateModifiedNodes.bind(this), 50);
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
#onNodeInserted(event: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMNode>): void {
|
|
1251
|
+
const node = event.data;
|
|
1252
|
+
if (node.parentNode) {
|
|
1253
|
+
this.#addUpdateRecord(node.parentNode).nodeInserted(node);
|
|
1254
|
+
}
|
|
1255
|
+
this.#updateModifiedNodesSoon();
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
#onNodeRemoved(
|
|
1259
|
+
event: Common.EventTarget.EventTargetEvent<{node: SDK.DOMModel.DOMNode, parent: SDK.DOMModel.DOMNode}>): void {
|
|
1260
|
+
const {node, parent} = event.data;
|
|
1261
|
+
this.resetClipboardIfNeeded(node);
|
|
1262
|
+
if (parent) {
|
|
1263
|
+
this.#addUpdateRecord(parent).nodeRemoved(node);
|
|
1264
|
+
}
|
|
1265
|
+
this.#updateModifiedNodesSoon();
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
#onAttrModified(event: Common.EventTarget.EventTargetEvent<{node: SDK.DOMModel.DOMNode, name: string}>): void {
|
|
1269
|
+
const {node, name} = event.data;
|
|
1270
|
+
this.#addUpdateRecord(node).attributeModified(name);
|
|
1271
|
+
this.#updateModifiedNodesSoon();
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
#onAttrRemoved(event: Common.EventTarget.EventTargetEvent<{node: SDK.DOMModel.DOMNode, name: string}>): void {
|
|
1275
|
+
const {node, name} = event.data;
|
|
1276
|
+
this.#addUpdateRecord(node).attributeRemoved(name);
|
|
1277
|
+
this.#updateModifiedNodesSoon();
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
#onCharacterDataModified(event: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMNode>): void {
|
|
1281
|
+
const node = event.data;
|
|
1282
|
+
this.#addUpdateRecord(node).charDataModified();
|
|
1283
|
+
if (node.parentNode && node.parentNode.firstChild === node.parentNode.lastChild) {
|
|
1284
|
+
this.#addUpdateRecord(node.parentNode).childrenModified();
|
|
1285
|
+
}
|
|
1286
|
+
this.#updateModifiedNodesSoon();
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
#onChildNodeCountUpdated(event: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMNode>): void {
|
|
1290
|
+
const node = event.data;
|
|
1291
|
+
this.#addUpdateRecord(node).childrenModified();
|
|
1292
|
+
this.#updateModifiedNodesSoon();
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
#onAdoptedStyleSheetsModified(event: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMNode>): void {
|
|
1296
|
+
const node = event.data;
|
|
1297
|
+
this.#addUpdateRecord(node).childrenModified();
|
|
1298
|
+
this.#updateModifiedNodesSoon();
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
#onDistributedNodesChanged(event: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMNode>): void {
|
|
1302
|
+
const node = event.data;
|
|
1303
|
+
this.#addUpdateRecord(node).childrenModified();
|
|
1304
|
+
this.#updateModifiedNodesSoon();
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
#onDocumentURLChanged(event: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMDocument>): void {
|
|
1308
|
+
this.#addUpdateRecord(event.data).charDataModified();
|
|
1309
|
+
this.#updateModifiedNodesSoon();
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
#onMarkersChanged(): void {
|
|
1313
|
+
this.#updateModifiedNodesSoon();
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
updateModifiedNodes(): void {
|
|
1317
|
+
if (this.#view === DECLARATIVE_VIEW) {
|
|
1318
|
+
this.performUpdate();
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
this.#viewOutput.elementsTreeOutline?.updateModifiedNodes();
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
#wireDOMModel(domModel: SDK.DOMModel.DOMModel): void {
|
|
1325
|
+
domModel.addEventListener(SDK.DOMModel.Events.DocumentUpdated, this.#onDocumentUpdated, this);
|
|
1326
|
+
domModel.addEventListener(SDK.DOMModel.Events.NodeInserted, this.#onNodeInserted, this);
|
|
1327
|
+
domModel.addEventListener(SDK.DOMModel.Events.NodeRemoved, this.#onNodeRemoved, this);
|
|
1328
|
+
domModel.addEventListener(SDK.DOMModel.Events.AttrModified, this.#onAttrModified, this);
|
|
1329
|
+
domModel.addEventListener(SDK.DOMModel.Events.AttrRemoved, this.#onAttrRemoved, this);
|
|
1330
|
+
domModel.addEventListener(SDK.DOMModel.Events.CharacterDataModified, this.#onCharacterDataModified, this);
|
|
1331
|
+
domModel.addEventListener(SDK.DOMModel.Events.ChildNodeCountUpdated, this.#onChildNodeCountUpdated, this);
|
|
1332
|
+
domModel.addEventListener(SDK.DOMModel.Events.MarkersChanged, this.#onMarkersChanged, this);
|
|
1333
|
+
domModel.addEventListener(SDK.DOMModel.Events.AdoptedStyleSheetsModified, this.#onAdoptedStyleSheetsModified, this);
|
|
1334
|
+
domModel.addEventListener(SDK.DOMModel.Events.TopLayerElementsChanged, this.#onTopLayerElementsChanged, this);
|
|
1335
|
+
domModel.addEventListener(SDK.DOMModel.Events.DistributedNodesChanged, this.#onDistributedNodesChanged, this);
|
|
1336
|
+
domModel.addEventListener(SDK.DOMModel.Events.DocumentURLChanged, this.#onDocumentURLChanged, this);
|
|
1337
|
+
domModel.addEventListener(SDK.DOMModel.Events.AffectedByStartingStylesFlagUpdated, this.requestUpdate, this);
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
#unwireDOMModel(domModel: SDK.DOMModel.DOMModel): void {
|
|
1341
|
+
domModel.removeEventListener(SDK.DOMModel.Events.DocumentUpdated, this.#onDocumentUpdated, this);
|
|
1342
|
+
domModel.removeEventListener(SDK.DOMModel.Events.NodeInserted, this.#onNodeInserted, this);
|
|
1343
|
+
domModel.removeEventListener(SDK.DOMModel.Events.NodeRemoved, this.#onNodeRemoved, this);
|
|
1344
|
+
domModel.removeEventListener(SDK.DOMModel.Events.AttrModified, this.#onAttrModified, this);
|
|
1345
|
+
domModel.removeEventListener(SDK.DOMModel.Events.AttrRemoved, this.#onAttrRemoved, this);
|
|
1346
|
+
domModel.removeEventListener(SDK.DOMModel.Events.CharacterDataModified, this.#onCharacterDataModified, this);
|
|
1347
|
+
domModel.removeEventListener(SDK.DOMModel.Events.ChildNodeCountUpdated, this.#onChildNodeCountUpdated, this);
|
|
1348
|
+
domModel.removeEventListener(SDK.DOMModel.Events.MarkersChanged, this.#onMarkersChanged, this);
|
|
1349
|
+
domModel.removeEventListener(SDK.DOMModel.Events.AdoptedStyleSheetsModified, this.#onAdoptedStyleSheetsModified,
|
|
1350
|
+
this);
|
|
1351
|
+
domModel.removeEventListener(SDK.DOMModel.Events.TopLayerElementsChanged, this.#onTopLayerElementsChanged, this);
|
|
1352
|
+
domModel.removeEventListener(SDK.DOMModel.Events.DistributedNodesChanged, this.#onDistributedNodesChanged, this);
|
|
1353
|
+
domModel.removeEventListener(SDK.DOMModel.Events.DocumentURLChanged, this.#onDocumentURLChanged, this);
|
|
1354
|
+
domModel.removeEventListener(SDK.DOMModel.Events.AffectedByStartingStylesFlagUpdated, this.requestUpdate, this);
|
|
1165
1355
|
}
|
|
1166
1356
|
|
|
1167
1357
|
#onShowHTMLCommentsChange(): void {
|
|
@@ -1192,30 +1382,48 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1192
1382
|
}
|
|
1193
1383
|
|
|
1194
1384
|
selectDOMNode(node: SDK.DOMModel.DOMNode|SDK.DOMModel.AdoptedStyleSheet|null, focus?: boolean): void {
|
|
1385
|
+
this.#imagePreviewPopover?.hide();
|
|
1386
|
+
this.#issuePopoverHelper?.hidePopover();
|
|
1195
1387
|
if (node instanceof SDK.DOMModel.AdoptedStyleSheet) {
|
|
1196
1388
|
this.highlightAdoptedStyleSheet(node);
|
|
1197
1389
|
return;
|
|
1198
1390
|
}
|
|
1199
1391
|
this.#selectedAdoptedStyleSheet = null;
|
|
1200
1392
|
if (this.#view === DECLARATIVE_VIEW) {
|
|
1201
|
-
|
|
1202
|
-
return;
|
|
1203
|
-
}
|
|
1393
|
+
const isSameNode = this.#selectedDOMNode === node;
|
|
1204
1394
|
this.#selectedDOMNode = node;
|
|
1205
1395
|
if (node) {
|
|
1396
|
+
const ancestors: SDK.DOMModel.DOMNode[] = [];
|
|
1206
1397
|
for (let current: (SDK.DOMModel.DOMNode|null) = node.parentNode; current; current = current.parentNode) {
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1398
|
+
ancestors.unshift(current);
|
|
1399
|
+
}
|
|
1400
|
+
for (let i = 0; i < ancestors.length; ++i) {
|
|
1401
|
+
const ancestor = ancestors[i];
|
|
1402
|
+
const child = ancestors[i + 1] || node;
|
|
1403
|
+
this.#expandedNodes.add(ancestor);
|
|
1404
|
+
const visibleChildren = getVisibleChildren(ancestor, this.#showComments);
|
|
1405
|
+
const childIndex = visibleChildren.indexOf(child);
|
|
1406
|
+
if (childIndex !== -1 && childIndex >= this.expandedChildrenLimit(ancestor)) {
|
|
1407
|
+
this.setExpandedChildrenLimit(ancestor, childIndex + 1);
|
|
1408
|
+
}
|
|
1409
|
+
if (!ancestor.children() && ancestor.childNodeCount()) {
|
|
1410
|
+
void ancestor.getChildNodes(() => {
|
|
1411
|
+
const visibleChildren = getVisibleChildren(ancestor, this.#showComments);
|
|
1412
|
+
const childIndex = visibleChildren.indexOf(child);
|
|
1413
|
+
if (childIndex !== -1 && childIndex >= this.expandedChildrenLimit(ancestor)) {
|
|
1414
|
+
this.setExpandedChildrenLimit(ancestor, childIndex + 1);
|
|
1415
|
+
}
|
|
1210
1416
|
this.performUpdate();
|
|
1211
1417
|
});
|
|
1212
1418
|
}
|
|
1213
1419
|
}
|
|
1214
1420
|
}
|
|
1215
1421
|
this.#clearHighlightedNode();
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1422
|
+
if (!isSameNode) {
|
|
1423
|
+
this.onSelectedNodeChanged(
|
|
1424
|
+
{data: {node, focus: Boolean(focus)}} as
|
|
1425
|
+
Common.EventTarget.EventTargetEvent<{node: SDK.DOMModel.DOMNode | null, focus: boolean}>);
|
|
1426
|
+
}
|
|
1219
1427
|
this.performUpdate();
|
|
1220
1428
|
return;
|
|
1221
1429
|
}
|
|
@@ -1281,6 +1489,30 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1281
1489
|
return Boolean(this.#viewOutput.elementsTreeOutline?.findTreeElement(node)?.expanded);
|
|
1282
1490
|
}
|
|
1283
1491
|
|
|
1492
|
+
expandedChildrenLimit(node: SDK.DOMModel.DOMNode): number {
|
|
1493
|
+
return this.#expandedChildrenLimitByNode.get(node) ?? InitialChildrenLimit;
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
setExpandedChildrenLimit(node: SDK.DOMModel.DOMNode, limit: number): void {
|
|
1497
|
+
if (this.expandedChildrenLimit(node) === limit) {
|
|
1498
|
+
return;
|
|
1499
|
+
}
|
|
1500
|
+
this.#expandedChildrenLimitByNode.set(node, limit);
|
|
1501
|
+
if (this.#viewOutput.elementsTreeOutline) {
|
|
1502
|
+
const treeElement = this.#viewOutput.elementsTreeOutline.findTreeElement(node);
|
|
1503
|
+
if (treeElement && treeElement.expandedChildrenLimit() !== limit) {
|
|
1504
|
+
this.#viewOutput.elementsTreeOutline.setExpandedChildrenLimit(treeElement, limit);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
this.performUpdate();
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
expandAllChildren(node: SDK.DOMModel.DOMNode): void {
|
|
1511
|
+
const currentLimit = this.expandedChildrenLimit(node);
|
|
1512
|
+
const visibleChildren = getVisibleChildren(node, this.#showComments);
|
|
1513
|
+
this.setExpandedChildrenLimit(node, Math.max(visibleChildren.length, currentLimit + InitialChildrenLimit));
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1284
1516
|
async expandRecursively(node: SDK.DOMModel.DOMNode, maxDepth = Number.MAX_VALUE): Promise<void> {
|
|
1285
1517
|
if (this.#view === DECLARATIVE_VIEW) {
|
|
1286
1518
|
await node.getSubtree(100, true);
|
|
@@ -1405,7 +1637,12 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1405
1637
|
}
|
|
1406
1638
|
|
|
1407
1639
|
override performUpdate(): void {
|
|
1640
|
+
if (this.#updateModifiedNodesTimeout) {
|
|
1641
|
+
clearTimeout(this.#updateModifiedNodesTimeout);
|
|
1642
|
+
this.#updateModifiedNodesTimeout = undefined;
|
|
1643
|
+
}
|
|
1408
1644
|
const firstRender = !this.#viewOutput.elementsTreeOutline;
|
|
1645
|
+
const updatedNodes = this.#view === DECLARATIVE_VIEW ? [...this.#updateRecords.keys()] : [];
|
|
1409
1646
|
this.#view({
|
|
1410
1647
|
domTreeWidget: this,
|
|
1411
1648
|
rootDOMNode: this.#rootDOMNode,
|
|
@@ -1548,8 +1785,17 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1548
1785
|
this.selectDOMNode(null);
|
|
1549
1786
|
this.performUpdate();
|
|
1550
1787
|
},
|
|
1788
|
+
expandedChildrenLimit: (node: SDK.DOMModel.DOMNode) => this.expandedChildrenLimit(node),
|
|
1789
|
+
onExpandAllChildren: (node: SDK.DOMModel.DOMNode) => this.expandAllChildren(node),
|
|
1790
|
+
updateRecordForNode: (node: SDK.DOMModel.DOMNode) => this.#updateRecords.get(node) ?? null,
|
|
1551
1791
|
},
|
|
1552
1792
|
this.#viewOutput, this.contentElement);
|
|
1793
|
+
if (this.#view === DECLARATIVE_VIEW) {
|
|
1794
|
+
this.#updateRecords.clear();
|
|
1795
|
+
if (updatedNodes.length > 0) {
|
|
1796
|
+
this.onElementsTreeUpdated({data: updatedNodes} as Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMNode[]>);
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1553
1799
|
if (this.#viewOutput.elementsTreeOutline) {
|
|
1554
1800
|
this.#viewOutput.elementsTreeOutline.domTreeWidget = this;
|
|
1555
1801
|
}
|
|
@@ -1564,16 +1810,7 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1564
1810
|
if (this.#view === DECLARATIVE_VIEW) {
|
|
1565
1811
|
if (!this.#wiredDOMModels.has(domModel)) {
|
|
1566
1812
|
this.#wiredDOMModels.add(domModel);
|
|
1567
|
-
|
|
1568
|
-
domModel.addEventListener(SDK.DOMModel.Events.NodeInserted, this.#onDOMNodeChanged, this);
|
|
1569
|
-
domModel.addEventListener(SDK.DOMModel.Events.NodeRemoved, this.#onDOMNodeChanged, this);
|
|
1570
|
-
domModel.addEventListener(SDK.DOMModel.Events.AttrModified, this.#onDOMNodeChanged, this);
|
|
1571
|
-
domModel.addEventListener(SDK.DOMModel.Events.AttrRemoved, this.#onDOMNodeChanged, this);
|
|
1572
|
-
domModel.addEventListener(SDK.DOMModel.Events.CharacterDataModified, this.#onDOMNodeChanged, this);
|
|
1573
|
-
domModel.addEventListener(SDK.DOMModel.Events.ChildNodeCountUpdated, this.#onDOMNodeChanged, this);
|
|
1574
|
-
domModel.addEventListener(SDK.DOMModel.Events.MarkersChanged, this.#onDOMNodeChanged, this);
|
|
1575
|
-
domModel.addEventListener(SDK.DOMModel.Events.AdoptedStyleSheetsModified, this.#onDOMNodeChanged, this);
|
|
1576
|
-
domModel.addEventListener(SDK.DOMModel.Events.TopLayerElementsChanged, this.#onTopLayerElementsChanged, this);
|
|
1813
|
+
this.#wireDOMModel(domModel);
|
|
1577
1814
|
}
|
|
1578
1815
|
if (this.isShowing() && !domModel.parentModel() &&
|
|
1579
1816
|
(!this.rootDOMNode || this.rootDOMNode.domModel() !== domModel)) {
|
|
@@ -1604,17 +1841,7 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1604
1841
|
if (this.#view === DECLARATIVE_VIEW) {
|
|
1605
1842
|
if (this.#wiredDOMModels.has(domModel)) {
|
|
1606
1843
|
this.#wiredDOMModels.delete(domModel);
|
|
1607
|
-
|
|
1608
|
-
domModel.removeEventListener(SDK.DOMModel.Events.NodeInserted, this.#onDOMNodeChanged, this);
|
|
1609
|
-
domModel.removeEventListener(SDK.DOMModel.Events.NodeRemoved, this.#onDOMNodeChanged, this);
|
|
1610
|
-
domModel.removeEventListener(SDK.DOMModel.Events.AttrModified, this.#onDOMNodeChanged, this);
|
|
1611
|
-
domModel.removeEventListener(SDK.DOMModel.Events.AttrRemoved, this.#onDOMNodeChanged, this);
|
|
1612
|
-
domModel.removeEventListener(SDK.DOMModel.Events.CharacterDataModified, this.#onDOMNodeChanged, this);
|
|
1613
|
-
domModel.removeEventListener(SDK.DOMModel.Events.ChildNodeCountUpdated, this.#onDOMNodeChanged, this);
|
|
1614
|
-
domModel.removeEventListener(SDK.DOMModel.Events.MarkersChanged, this.#onDOMNodeChanged, this);
|
|
1615
|
-
domModel.removeEventListener(SDK.DOMModel.Events.AdoptedStyleSheetsModified, this.#onDOMNodeChanged, this);
|
|
1616
|
-
domModel.removeEventListener(SDK.DOMModel.Events.TopLayerElementsChanged, this.#onTopLayerElementsChanged,
|
|
1617
|
-
this);
|
|
1844
|
+
this.#unwireDOMModel(domModel);
|
|
1618
1845
|
}
|
|
1619
1846
|
this.performUpdate();
|
|
1620
1847
|
return;
|
|
@@ -1698,8 +1925,10 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1698
1925
|
}
|
|
1699
1926
|
|
|
1700
1927
|
runPendingUpdates(): void {
|
|
1701
|
-
this
|
|
1702
|
-
this
|
|
1928
|
+
this.updateModifiedNodes();
|
|
1929
|
+
if (this.#view !== DECLARATIVE_VIEW) {
|
|
1930
|
+
this.performUpdate();
|
|
1931
|
+
}
|
|
1703
1932
|
}
|
|
1704
1933
|
|
|
1705
1934
|
override onResize(): void {
|
|
@@ -1711,6 +1940,15 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
1711
1940
|
|
|
1712
1941
|
override willHide(): void {
|
|
1713
1942
|
super.willHide();
|
|
1943
|
+
this.#imagePreviewPopover?.hide();
|
|
1944
|
+
this.#issuePopoverHelper?.hidePopover();
|
|
1945
|
+
if (this.#updateModifiedNodesTimeout) {
|
|
1946
|
+
clearTimeout(this.#updateModifiedNodesTimeout);
|
|
1947
|
+
this.#updateModifiedNodesTimeout = undefined;
|
|
1948
|
+
}
|
|
1949
|
+
if (this.#view === DECLARATIVE_VIEW) {
|
|
1950
|
+
this.#updateRecords.clear();
|
|
1951
|
+
}
|
|
1714
1952
|
if (this.#multilineEditing) {
|
|
1715
1953
|
this.#multilineEditing.cancel();
|
|
1716
1954
|
}
|
|
@@ -2316,7 +2554,13 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
2316
2554
|
override wasHidden(): void {
|
|
2317
2555
|
super.wasHidden();
|
|
2318
2556
|
this.#visible = false;
|
|
2319
|
-
this.#
|
|
2557
|
+
if (this.#updateModifiedNodesTimeout) {
|
|
2558
|
+
clearTimeout(this.#updateModifiedNodesTimeout);
|
|
2559
|
+
this.#updateModifiedNodesTimeout = undefined;
|
|
2560
|
+
}
|
|
2561
|
+
if (this.#view === DECLARATIVE_VIEW) {
|
|
2562
|
+
this.#updateRecords.clear();
|
|
2563
|
+
}
|
|
2320
2564
|
this.performUpdate();
|
|
2321
2565
|
}
|
|
2322
2566
|
|
|
@@ -2324,10 +2568,28 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
2324
2568
|
super.detach(overrideHideOnDetach);
|
|
2325
2569
|
this.#visible = false;
|
|
2326
2570
|
this.#showHTMLCommentsSetting.removeChangeListener(this.#onShowHTMLCommentsChange, this);
|
|
2327
|
-
this.#
|
|
2571
|
+
if (this.#updateModifiedNodesTimeout) {
|
|
2572
|
+
clearTimeout(this.#updateModifiedNodesTimeout);
|
|
2573
|
+
this.#updateModifiedNodesTimeout = undefined;
|
|
2574
|
+
}
|
|
2575
|
+
if (this.#view === DECLARATIVE_VIEW) {
|
|
2576
|
+
this.#updateRecords.clear();
|
|
2577
|
+
}
|
|
2328
2578
|
this.performUpdate();
|
|
2329
2579
|
}
|
|
2330
2580
|
|
|
2581
|
+
hideImagePreview(): void {
|
|
2582
|
+
this.#imagePreviewPopover?.hide();
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
imagePreviewPopoverForTest(): ImagePreviewPopover|undefined {
|
|
2586
|
+
return this.#imagePreviewPopover;
|
|
2587
|
+
}
|
|
2588
|
+
|
|
2589
|
+
issuePopoverHelperForTest(): UI.PopoverHelper.PopoverHelper|undefined {
|
|
2590
|
+
return this.#issuePopoverHelper;
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2331
2593
|
override show(parentElement: Element, insertBefore?: Node|null, suppressOrphanWidgetError = false): void {
|
|
2332
2594
|
this.performUpdate();
|
|
2333
2595
|
const domModels = SDK.TargetManager.TargetManager.instance().models(SDK.DOMModel.DOMModel, {scoped: true});
|
|
@@ -2355,9 +2617,13 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
2355
2617
|
}
|
|
2356
2618
|
}
|
|
2357
2619
|
|
|
2358
|
-
|
|
2359
|
-
Common.ObjectWrapper.
|
|
2360
|
-
|
|
2620
|
+
const ElementsTreeOutlineBase:
|
|
2621
|
+
Common.ObjectWrapper.EventMixin<ElementsTreeOutline.EventTypes, typeof UI.TreeOutline.TreeOutline> =
|
|
2622
|
+
Common.ObjectWrapper.eventMixin(
|
|
2623
|
+
UI.TreeOutline.TreeOutline,
|
|
2624
|
+
);
|
|
2625
|
+
|
|
2626
|
+
export class ElementsTreeOutline extends ElementsTreeOutlineBase {
|
|
2361
2627
|
treeElementByNode: WeakMap<SDK.DOMModel.DOMNode, ElementsTreeElement>;
|
|
2362
2628
|
private readonly shadowRoot: ShadowRoot;
|
|
2363
2629
|
readonly elementInternal: HTMLElement;
|
|
@@ -3232,6 +3498,9 @@ export class ElementsTreeOutline extends
|
|
|
3232
3498
|
return new AdoptedStyleSheetSetTreeElement(node);
|
|
3233
3499
|
}
|
|
3234
3500
|
const treeElement = new ElementsTreeElement(node, isClosingTag);
|
|
3501
|
+
if (this.domTreeWidget) {
|
|
3502
|
+
treeElement.setExpandedChildrenLimit(this.domTreeWidget.expandedChildrenLimit(node));
|
|
3503
|
+
}
|
|
3235
3504
|
treeElement.setExpandable(!isClosingTag && this.hasVisibleChildren(node));
|
|
3236
3505
|
if (node.nodeType() === Node.ELEMENT_NODE && node.parentNode && node.parentNode.nodeType() === Node.DOCUMENT_NODE &&
|
|
3237
3506
|
!node.parentNode.parentNode) {
|
|
@@ -3373,6 +3642,9 @@ export class ElementsTreeOutline extends
|
|
|
3373
3642
|
}
|
|
3374
3643
|
|
|
3375
3644
|
treeElement.setExpandedChildrenLimit(expandedChildrenLimit);
|
|
3645
|
+
if (this.domTreeWidget && this.domTreeWidget.expandedChildrenLimit(treeElement.node()) !== expandedChildrenLimit) {
|
|
3646
|
+
this.domTreeWidget.setExpandedChildrenLimit(treeElement.node(), expandedChildrenLimit);
|
|
3647
|
+
}
|
|
3376
3648
|
if (treeElement.treeOutline && !this.treeElementsBeingUpdated.has(treeElement)) {
|
|
3377
3649
|
this.updateModifiedParentNode(treeElement.node());
|
|
3378
3650
|
}
|