chrome-devtools-frontend 1.0.1605219 → 1.0.1606789
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/Images/src/dots-circle.svg +10 -0
- package/front_end/core/host/UserMetrics.ts +0 -1
- package/front_end/core/platform/api/HostRuntime.ts +9 -6
- package/front_end/core/platform/browser/HostRuntime.ts +2 -2
- package/front_end/core/platform/node/HostRuntime.ts +7 -7
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/core/root/ExperimentNames.ts +0 -1
- package/front_end/core/sdk/CrashReportContextModel.ts +28 -0
- package/front_end/core/sdk/sdk.ts +2 -2
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.ts +3 -3
- package/front_end/entrypoints/heap_snapshot_worker/heap_snapshot_worker-entrypoint.ts +5 -4
- package/front_end/entrypoints/main/MainImpl.ts +0 -101
- package/front_end/models/ai_assistance/ChangeManager.ts +6 -6
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +112 -5
- package/front_end/models/ai_assistance/agents/AiAgent.ts +9 -25
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +6 -3
- package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +10 -9
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +313 -0
- package/front_end/models/ai_assistance/agents/FileAgent.ts +15 -1
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +15 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +19 -8
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +35 -278
- package/front_end/models/ai_assistance/ai_assistance.ts +0 -2
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -5
- package/front_end/models/web_mcp/WebMCPModel.ts +187 -0
- package/front_end/models/web_mcp/web_mcp.ts +9 -0
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +8 -1
- package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
- package/front_end/panels/ai_assistance/components/AccessibilityAgentMarkdownRenderer.ts +88 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +149 -49
- package/front_end/panels/ai_assistance/components/ChatView.ts +11 -15
- package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +13 -4
- package/front_end/panels/ai_assistance/components/chatMessage.css +53 -1
- package/front_end/panels/ai_assistance/components/chatView.css +0 -10
- package/front_end/panels/ai_assistance/components/exportForAgentsDialog.css +13 -0
- package/front_end/panels/application/WebMCPView.ts +471 -25
- package/front_end/panels/application/webMCPView.css +53 -2
- package/front_end/panels/elements/ElementsTreeElement.ts +1 -1
- package/front_end/panels/elements/ElementsTreeOutline.ts +87 -0
- package/front_end/panels/elements/StylePropertiesSection.ts +0 -4
- package/front_end/panels/elements/elements.ts +3 -0
- package/front_end/panels/elements/elementsTreeOutline.css +21 -0
- package/front_end/panels/elements/stylePropertiesTreeOutline.css +7 -0
- package/front_end/panels/lighthouse/LighthousePanel.ts +7 -1
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +25 -2
- package/front_end/panels/profiler/HeapDetachedElementsView.ts +0 -4
- package/front_end/panels/profiler/HeapProfileView.ts +0 -4
- package/front_end/panels/profiler/HeapProfilerPanel.ts +4 -13
- package/front_end/panels/profiler/HeapSnapshotProxy.ts +2 -6
- package/front_end/panels/profiler/HeapSnapshotView.ts +19 -32
- package/front_end/panels/profiler/ProfileHeader.ts +1 -15
- package/front_end/panels/profiler/ProfileTypeRegistry.ts +4 -12
- package/front_end/panels/profiler/ProfileView.ts +1 -6
- package/front_end/panels/profiler/ProfilesPanel.ts +60 -7
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +27 -22
- package/front_end/panels/timeline/EventsTimelineTreeView.ts +1 -1
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +2 -2
- package/front_end/panels/timeline/TimelinePanel.ts +11 -153
- package/front_end/panels/timeline/TimelineTreeView.ts +147 -48
- package/front_end/panels/timeline/TimelineUIUtils.ts +2 -1
- package/front_end/panels/timeline/components/CWVMetrics.ts +18 -2
- package/front_end/panels/timeline/timeline-meta.ts +11 -0
- package/front_end/panels/timeline/utils/Helpers.ts +5 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/markdown_view/CodeBlock.ts +47 -1
- package/front_end/ui/components/markdown_view/codeBlock.css +8 -0
- package/front_end/ui/legacy/FilterBar.ts +2 -0
- package/front_end/ui/legacy/SplitWidget.ts +33 -27
- package/front_end/ui/legacy/TabbedPane.ts +123 -3
- package/front_end/ui/legacy/Widget.ts +95 -48
- package/front_end/ui/legacy/components/source_frame/JSONView.ts +1 -1
- package/front_end/ui/legacy/components/utils/jsUtils.css +2 -0
- package/front_end/ui/legacy/infobar.css +1 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +6 -1
- package/package.json +1 -1
- package/front_end/core/sdk/WebMCPModel.ts +0 -104
- package/front_end/models/ai_assistance/ConversationHandler.ts +0 -325
|
@@ -23,6 +23,14 @@
|
|
|
23
23
|
flex: auto;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
devtools-data-grid {
|
|
27
|
+
flex: auto;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
devtools-data-grid td {
|
|
31
|
+
vertical-align: middle;
|
|
32
|
+
}
|
|
33
|
+
|
|
26
34
|
.section-title {
|
|
27
35
|
background-color: var(--sys-color-surface1);
|
|
28
36
|
padding: 0 5px;
|
|
@@ -33,9 +41,17 @@
|
|
|
33
41
|
color: var(--sys-color-on-surface);
|
|
34
42
|
}
|
|
35
43
|
|
|
44
|
+
.status-cell {
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
gap: 4px;
|
|
48
|
+
}
|
|
49
|
+
|
|
36
50
|
devtools-list {
|
|
37
51
|
flex: 1 1 auto;
|
|
38
|
-
margin:
|
|
52
|
+
margin: 0;
|
|
53
|
+
padding: var(--sys-size-4);
|
|
54
|
+
box-sizing: border-box;
|
|
39
55
|
}
|
|
40
56
|
|
|
41
57
|
.tool-item {
|
|
@@ -44,22 +60,57 @@
|
|
|
44
60
|
padding: 8px 0;
|
|
45
61
|
gap: 4px;
|
|
46
62
|
width: 100%;
|
|
63
|
+
min-width: 0;
|
|
47
64
|
border-bottom: 1px solid var(--sys-color-divider);
|
|
48
65
|
}
|
|
49
66
|
|
|
50
67
|
.tool-name-container {
|
|
51
68
|
display: flex;
|
|
52
69
|
justify-content: space-between;
|
|
53
|
-
align-items:
|
|
70
|
+
align-items: flex-start;
|
|
71
|
+
gap: 8px;
|
|
54
72
|
}
|
|
55
73
|
|
|
56
74
|
.tool-name.source-code {
|
|
57
75
|
color: var(--sys-color-token-string);
|
|
76
|
+
white-space: nowrap;
|
|
77
|
+
overflow: hidden;
|
|
78
|
+
text-overflow: ellipsis;
|
|
79
|
+
min-width: 0;
|
|
80
|
+
flex: 1;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* stylelint-disable-next-line selector-type-no-unknown */
|
|
84
|
+
.tool-name-container icon-button {
|
|
85
|
+
flex-shrink: 0;
|
|
86
|
+
height: 0;
|
|
87
|
+
overflow: visible;
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
58
90
|
}
|
|
59
91
|
|
|
60
92
|
.tool-description {
|
|
61
93
|
color: var(--sys-color-on-surface);
|
|
62
94
|
}
|
|
63
95
|
|
|
96
|
+
tr.status-error {
|
|
97
|
+
color: var(--sys-color-error);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
devtools-toolbar-input {
|
|
101
|
+
flex-grow: 1;
|
|
102
|
+
flex-shrink: 1;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
tr.status-cancelled {
|
|
106
|
+
color: var(--sys-color-on-surface-light);
|
|
107
|
+
}
|
|
64
108
|
|
|
109
|
+
.toolbar-text.status-error-text {
|
|
110
|
+
color: var(--sys-color-error);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.toolbar-text.status-cancelled-text {
|
|
114
|
+
color: var(--sys-color-on-surface-light);
|
|
115
|
+
}
|
|
65
116
|
}
|
|
@@ -878,7 +878,7 @@ function maybeRenderAdAdorner(input: ViewInput): Lit.TemplateResult|typeof nothi
|
|
|
878
878
|
// clang-format off
|
|
879
879
|
return html`
|
|
880
880
|
<devtools-adorner
|
|
881
|
-
aria-
|
|
881
|
+
aria-details=${input.adTooltipId}
|
|
882
882
|
aria-label=${i18nString(UIStrings.thisElementWasIdentifiedAsAnAd)}
|
|
883
883
|
.name=${ElementsComponents.AdornerManager.RegisteredAdorners.AD}
|
|
884
884
|
jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.AD)}
|
|
@@ -72,6 +72,11 @@ const UIStrings = {
|
|
|
72
72
|
* @example {3} PH1
|
|
73
73
|
*/
|
|
74
74
|
showAllNodesDMore: 'Show all nodes ({PH1} more)',
|
|
75
|
+
/**
|
|
76
|
+
* @description Text for a button to show all truncated lines in the tree.
|
|
77
|
+
* @example {5} PH1
|
|
78
|
+
*/
|
|
79
|
+
showAllLines: 'Show all ({PH1} lines)',
|
|
75
80
|
/**
|
|
76
81
|
* @description Text for popover that directs to Issues panel
|
|
77
82
|
*/
|
|
@@ -98,6 +103,7 @@ interface ViewInput {
|
|
|
98
103
|
expandRoot?: boolean;
|
|
99
104
|
visibleWidth?: number;
|
|
100
105
|
visible?: boolean;
|
|
106
|
+
maxRowsShown?: number;
|
|
101
107
|
wrap: boolean;
|
|
102
108
|
showSelectionOnKeyboardFocus: boolean;
|
|
103
109
|
preventTabOrder: boolean;
|
|
@@ -134,6 +140,12 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
134
140
|
ElementsTreeOutline.Events.ElementsTreeUpdated, input.onElementsTreeUpdated, this);
|
|
135
141
|
output.elementsTreeOutline.addEventListener(UI.TreeOutline.Events.ElementExpanded, input.onElementExpanded, this);
|
|
136
142
|
output.elementsTreeOutline.addEventListener(UI.TreeOutline.Events.ElementCollapsed, input.onElementCollapsed, this);
|
|
143
|
+
output.elementsTreeOutline.addEventListener(ElementsTreeOutline.Events.ShowAllRows, () => {
|
|
144
|
+
if (output.elementsTreeOutline?.maxRowsShown) {
|
|
145
|
+
// Set max to undefined to show all rows
|
|
146
|
+
output.elementsTreeOutline.maxRowsShown = undefined;
|
|
147
|
+
}
|
|
148
|
+
}, this);
|
|
137
149
|
target.appendChild(output.elementsTreeOutline.element);
|
|
138
150
|
}
|
|
139
151
|
|
|
@@ -150,6 +162,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
150
162
|
if (input.visible !== undefined) {
|
|
151
163
|
output.elementsTreeOutline.setVisible(input.visible);
|
|
152
164
|
}
|
|
165
|
+
output.elementsTreeOutline.maxRowsShown = input.maxRowsShown;
|
|
153
166
|
output.elementsTreeOutline.setWordWrap(input.wrap);
|
|
154
167
|
output.elementsTreeOutline.setShowSelectionOnKeyboardFocus(input.showSelectionOnKeyboardFocus, input.preventTabOrder);
|
|
155
168
|
if (input.deindentSingleNode) {
|
|
@@ -234,6 +247,17 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
234
247
|
#visible = false;
|
|
235
248
|
#visibleWidth?: number;
|
|
236
249
|
#wrap = false;
|
|
250
|
+
#maxRows?: number;
|
|
251
|
+
|
|
252
|
+
// If maxRows is undefined, all rows are shown. If it is set to a number, only that many rows are shown.
|
|
253
|
+
set maxRows(maxRows: number|undefined) {
|
|
254
|
+
this.#maxRows = maxRows;
|
|
255
|
+
this.requestUpdate();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
get maxRows(): number|undefined {
|
|
259
|
+
return this.#maxRows;
|
|
260
|
+
}
|
|
237
261
|
|
|
238
262
|
set visibleWidth(width: number) {
|
|
239
263
|
this.#visibleWidth = width;
|
|
@@ -402,6 +426,7 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
402
426
|
}
|
|
403
427
|
|
|
404
428
|
override performUpdate(): void {
|
|
429
|
+
const firstRender = !this.#viewOutput.elementsTreeOutline;
|
|
405
430
|
this.#view(
|
|
406
431
|
{
|
|
407
432
|
omitRootDOMNode: this.omitRootDOMNode,
|
|
@@ -416,6 +441,7 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
416
441
|
visibleWidth: this.#visibleWidth,
|
|
417
442
|
visible: this.#visible,
|
|
418
443
|
wrap: this.#wrap,
|
|
444
|
+
maxRowsShown: this.#maxRows,
|
|
419
445
|
showSelectionOnKeyboardFocus: this.showSelectionOnKeyboardFocus,
|
|
420
446
|
preventTabOrder: this.preventTabOrder,
|
|
421
447
|
deindentSingleNode: this.deindentSingleNode,
|
|
@@ -437,6 +463,11 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
|
437
463
|
},
|
|
438
464
|
},
|
|
439
465
|
this.#viewOutput, this.contentElement);
|
|
466
|
+
if (firstRender && this.#viewOutput.elementsTreeOutline) {
|
|
467
|
+
this.#viewOutput.elementsTreeOutline.addEventListener(ElementsTreeOutline.Events.ShowAllRows, () => {
|
|
468
|
+
this.maxRows = undefined;
|
|
469
|
+
});
|
|
470
|
+
}
|
|
440
471
|
}
|
|
441
472
|
|
|
442
473
|
modelAdded(domModel: SDK.DOMModel.DOMModel): void {
|
|
@@ -597,6 +628,8 @@ export class ElementsTreeOutline extends
|
|
|
597
628
|
showAIButton: boolean;
|
|
598
629
|
disableEdits: boolean;
|
|
599
630
|
expandRoot: boolean;
|
|
631
|
+
#maxRowsShown?: number;
|
|
632
|
+
#showAllButton?: HTMLElement;
|
|
600
633
|
|
|
601
634
|
constructor(
|
|
602
635
|
omitRootDOMNode?: boolean, selectEnabled?: boolean, hideGutter?: boolean, maxTreeDepth?: number,
|
|
@@ -1030,6 +1063,58 @@ export class ElementsTreeOutline extends
|
|
|
1030
1063
|
}
|
|
1031
1064
|
}
|
|
1032
1065
|
|
|
1066
|
+
set maxRowsShown(maxRows: number|undefined) {
|
|
1067
|
+
this.#maxRowsShown = maxRows;
|
|
1068
|
+
this.#updateShowAllButton();
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
#updateShowAllButton(): void {
|
|
1072
|
+
const container = this.shadowRoot.querySelector('.elements-disclosure') as HTMLElement;
|
|
1073
|
+
if (!container) {
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
if (!this.#maxRowsShown) {
|
|
1077
|
+
this.#showAllButton?.classList.add('hidden');
|
|
1078
|
+
container.style.removeProperty('--max-rows');
|
|
1079
|
+
container.classList.remove('elements-tree-truncated');
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
container.style.setProperty('--max-rows', String(this.#maxRowsShown));
|
|
1084
|
+
container.classList.add('elements-tree-truncated');
|
|
1085
|
+
|
|
1086
|
+
// We use a microtask to wait for rendering so all node lines are rendered.
|
|
1087
|
+
window.requestAnimationFrame(() => {
|
|
1088
|
+
// The container has a max-height (based on --max-rows). If the total content height
|
|
1089
|
+
// (scrollHeight) is greater than the visible height (clientHeight), it means
|
|
1090
|
+
// some rows are hidden due to truncation, and we should show the "Show all" button.
|
|
1091
|
+
const isOverflowing = container.scrollHeight > container.clientHeight;
|
|
1092
|
+
if (!isOverflowing) {
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
if (!this.#showAllButton) {
|
|
1096
|
+
this.#showAllButton = UI.UIUtils.createTextButton('', () => {
|
|
1097
|
+
this.dispatchEventToListeners(ElementsTreeOutline.Events.ShowAllRows);
|
|
1098
|
+
this.dispatchEventToListeners(UI.TreeOutline.Events.ElementExpanded, this.rootElement());
|
|
1099
|
+
}, {
|
|
1100
|
+
jslogContext: 'show-all-nodes',
|
|
1101
|
+
});
|
|
1102
|
+
this.#showAllButton.classList.add('elements-tree-show-all');
|
|
1103
|
+
this.shadowRoot.appendChild(this.#showAllButton);
|
|
1104
|
+
}
|
|
1105
|
+
this.#showAllButton.classList.remove('hidden');
|
|
1106
|
+
const computedStyle = window.getComputedStyle(container);
|
|
1107
|
+
const lineHeight = parseFloat(computedStyle.lineHeight) || 16;
|
|
1108
|
+
const truncatedLines = Math.round((container.scrollHeight - container.clientHeight) / lineHeight);
|
|
1109
|
+
|
|
1110
|
+
if (truncatedLines > 0) {
|
|
1111
|
+
this.#showAllButton.textContent = i18nString(UIStrings.showAllLines, {PH1: truncatedLines});
|
|
1112
|
+
} else {
|
|
1113
|
+
this.#showAllButton?.classList.add('hidden');
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1033
1118
|
highlightAdoptedStyleSheet(adoptedStyleSheet: SDK.DOMModel.AdoptedStyleSheet): void {
|
|
1034
1119
|
const parentDOMNode =
|
|
1035
1120
|
!this.includeRootDOMNode && adoptedStyleSheet.parent === this.rootDOMNode && this.rootDOMNode ?
|
|
@@ -2219,12 +2304,14 @@ export namespace ElementsTreeOutline {
|
|
|
2219
2304
|
/* eslint-disable @typescript-eslint/naming-convention -- Used by web_tests. */
|
|
2220
2305
|
SelectedNodeChanged = 'SelectedNodeChanged',
|
|
2221
2306
|
ElementsTreeUpdated = 'ElementsTreeUpdated',
|
|
2307
|
+
ShowAllRows = 'ShowAllRows',
|
|
2222
2308
|
/* eslint-enable @typescript-eslint/naming-convention */
|
|
2223
2309
|
}
|
|
2224
2310
|
|
|
2225
2311
|
export interface EventTypes {
|
|
2226
2312
|
[Events.SelectedNodeChanged]: {node: SDK.DOMModel.DOMNode|null, focus: boolean};
|
|
2227
2313
|
[Events.ElementsTreeUpdated]: SDK.DOMModel.DOMNode[];
|
|
2314
|
+
[Events.ShowAllRows]: void;
|
|
2228
2315
|
}
|
|
2229
2316
|
}
|
|
2230
2317
|
|
|
@@ -1075,10 +1075,6 @@ export class StylePropertiesSection {
|
|
|
1075
1075
|
|
|
1076
1076
|
protected createContainerQueryElement(containerQuery: SDK.CSSContainerQuery.CSSContainerQuery):
|
|
1077
1077
|
ElementsComponents.CSSQuery.CSSQuery|undefined {
|
|
1078
|
-
if (!containerQuery.text) {
|
|
1079
|
-
return;
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
1078
|
let onQueryTextClick;
|
|
1083
1079
|
if (containerQuery.styleSheetId) {
|
|
1084
1080
|
onQueryTextClick = this.handleQueryRuleClick.bind(this, containerQuery);
|
|
@@ -10,6 +10,7 @@ import './ElementsTreeElement.js';
|
|
|
10
10
|
import './AdoptedStyleSheetTreeElement.js';
|
|
11
11
|
import './TopLayerContainer.js';
|
|
12
12
|
import './ElementsTreeOutline.js';
|
|
13
|
+
import './ImagePreviewPopover.js';
|
|
13
14
|
import './EventListenersWidget.js';
|
|
14
15
|
import './MarkerDecorator.js';
|
|
15
16
|
import './MetricsSidebarPane.js';
|
|
@@ -45,6 +46,7 @@ import * as ElementsTreeElement from './ElementsTreeElement.js';
|
|
|
45
46
|
import * as ElementsTreeOutline from './ElementsTreeOutline.js';
|
|
46
47
|
import * as ElementsTreeOutlineRenderer from './ElementsTreeOutlineRenderer.js';
|
|
47
48
|
import * as EventListenersWidget from './EventListenersWidget.js';
|
|
49
|
+
import * as ImagePreviewPopover from './ImagePreviewPopover.js';
|
|
48
50
|
import * as InspectElementModeController from './InspectElementModeController.js';
|
|
49
51
|
import * as LayersWidget from './LayersWidget.js';
|
|
50
52
|
import * as LayoutPane from './LayoutPane.js';
|
|
@@ -82,6 +84,7 @@ export {
|
|
|
82
84
|
ElementsTreeOutline,
|
|
83
85
|
ElementsTreeOutlineRenderer,
|
|
84
86
|
EventListenersWidget,
|
|
87
|
+
ImagePreviewPopover,
|
|
85
88
|
InspectElementModeController,
|
|
86
89
|
LayersWidget,
|
|
87
90
|
LayoutPane,
|
|
@@ -402,3 +402,24 @@ li.hovered:not(.always-parent) + ol.children:not(.shadow-root) {
|
|
|
402
402
|
.ad-provenance-tooltip-content {
|
|
403
403
|
padding-left: 16px;
|
|
404
404
|
}
|
|
405
|
+
|
|
406
|
+
.elements-disclosure.elements-tree-truncated {
|
|
407
|
+
/* 1.36 is the line-height, 15px is the min-height */
|
|
408
|
+
max-height: calc(var(--max-rows) * 1.36em + 5px);
|
|
409
|
+
overflow: hidden;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
.elements-tree-show-all {
|
|
413
|
+
border: none;
|
|
414
|
+
color: var(--sys-color-primary);
|
|
415
|
+
cursor: pointer;
|
|
416
|
+
display: block;
|
|
417
|
+
font-size: 12px;
|
|
418
|
+
padding: 4px 12px;
|
|
419
|
+
text-align: center;
|
|
420
|
+
width: 100%;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.elements-tree-show-all.hidden {
|
|
424
|
+
display: none;
|
|
425
|
+
}
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
padding-left: 22px;
|
|
22
22
|
white-space: normal;
|
|
23
23
|
text-overflow: ellipsis;
|
|
24
|
+
overflow-wrap: break-word;
|
|
24
25
|
cursor: auto;
|
|
25
26
|
display: block;
|
|
26
27
|
|
|
@@ -74,6 +75,12 @@
|
|
|
74
75
|
overflow-wrap: break-word !important; /* stylelint-disable-line declaration-no-important */
|
|
75
76
|
white-space: normal !important; /* stylelint-disable-line declaration-no-important */
|
|
76
77
|
padding-left: 0;
|
|
78
|
+
|
|
79
|
+
/* Constrain the TextPrompt proxy span (display: inline-block) so that
|
|
80
|
+
long values wrap instead of overflowing the section. */
|
|
81
|
+
> span:has(> .text-prompt-root) {
|
|
82
|
+
max-width: 100%;
|
|
83
|
+
}
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
.info {
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
type PageWarningsChangedEvent
|
|
20
20
|
} from './LighthouseController.js';
|
|
21
21
|
import lighthousePanelStyles from './lighthousePanel.css.js';
|
|
22
|
-
import {ProtocolService} from './LighthouseProtocolService.js';
|
|
22
|
+
import {CancelledError, ProtocolService} from './LighthouseProtocolService.js';
|
|
23
23
|
import {LighthouseReportRenderer} from './LighthouseReportRenderer.js';
|
|
24
24
|
import {Item, ReportSelector} from './LighthouseReportSelector.js';
|
|
25
25
|
import {StartView} from './LighthouseStartView.js';
|
|
@@ -176,6 +176,12 @@ export class LighthousePanel extends UI.Panel.Panel {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
private handleError(err: unknown): void {
|
|
179
|
+
if (err instanceof CancelledError) {
|
|
180
|
+
// If the error was an explicit choice to cancel, we don't want to render
|
|
181
|
+
// the bug report view.
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
179
185
|
if (err instanceof Error) {
|
|
180
186
|
this.statusView.renderBugReport(err);
|
|
181
187
|
}
|
|
@@ -58,6 +58,12 @@ export interface LighthouseRun {
|
|
|
58
58
|
isAIControlled?: boolean;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
export class CancelledError extends Error {
|
|
62
|
+
constructor() {
|
|
63
|
+
super('Lighthouse run cancelled');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
61
67
|
/**
|
|
62
68
|
* ProtocolService manages a connection between the frontend (Lighthouse panel) and the Lighthouse worker.
|
|
63
69
|
*/
|
|
@@ -71,6 +77,14 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
|
|
|
71
77
|
private configForTesting?: object;
|
|
72
78
|
private connection?: ProtocolClient.CDPConnection.CDPConnection;
|
|
73
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Tracks pending requests to the Lighthouse worker.
|
|
82
|
+
* Key: The message ID sent to the worker.
|
|
83
|
+
* Value: The rejection function for the corresponding promise.
|
|
84
|
+
* This is used to gracefully cancel hanging promises if the ProtocolService is detached before the worker replies.
|
|
85
|
+
*/
|
|
86
|
+
readonly #pendingRequests = new Map<number, (reason: Error) => void>();
|
|
87
|
+
|
|
74
88
|
async attach(): Promise<void> {
|
|
75
89
|
await SDK.TargetManager.TargetManager.instance().suspendAllTargets();
|
|
76
90
|
const mainTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
@@ -174,6 +188,10 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
|
|
|
174
188
|
}
|
|
175
189
|
|
|
176
190
|
async detach(): Promise<void> {
|
|
191
|
+
for (const reject of this.#pendingRequests.values()) {
|
|
192
|
+
reject(new CancelledError());
|
|
193
|
+
}
|
|
194
|
+
this.#pendingRequests.clear();
|
|
177
195
|
const oldLighthouseWorker = this.lighthouseWorkerPromise;
|
|
178
196
|
const oldRootTarget = this.rootTarget;
|
|
179
197
|
|
|
@@ -245,7 +263,7 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
|
|
|
245
263
|
return this.lighthouseWorkerPromise;
|
|
246
264
|
}
|
|
247
265
|
|
|
248
|
-
|
|
266
|
+
async ensureWorkerExists(): Promise<Worker> {
|
|
249
267
|
let worker: Worker;
|
|
250
268
|
if (!this.lighthouseWorkerPromise) {
|
|
251
269
|
worker = await this.initWorker();
|
|
@@ -293,16 +311,21 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
|
|
|
293
311
|
Promise<LighthouseModel.ReporterTypes.RunnerResult> {
|
|
294
312
|
const worker = await this.ensureWorkerExists();
|
|
295
313
|
const messageId = lastId++;
|
|
296
|
-
const messageResult = new Promise<LighthouseModel.ReporterTypes.RunnerResult>(resolve => {
|
|
314
|
+
const messageResult = new Promise<LighthouseModel.ReporterTypes.RunnerResult>((resolve, reject) => {
|
|
297
315
|
const workerListener = (event: MessageEvent): void => {
|
|
298
316
|
const lighthouseMessage = event.data;
|
|
299
317
|
|
|
300
318
|
if (lighthouseMessage.id === messageId) {
|
|
301
319
|
worker.removeEventListener('message', workerListener);
|
|
320
|
+
this.#pendingRequests.delete(messageId);
|
|
302
321
|
resolve(lighthouseMessage.result);
|
|
303
322
|
}
|
|
304
323
|
};
|
|
305
324
|
worker.addEventListener('message', workerListener);
|
|
325
|
+
this.#pendingRequests.set(messageId, (err: Error) => {
|
|
326
|
+
worker.removeEventListener('message', workerListener);
|
|
327
|
+
reject(err);
|
|
328
|
+
});
|
|
306
329
|
});
|
|
307
330
|
worker.postMessage({id: messageId, action, args: {...args, id: messageId}});
|
|
308
331
|
|
|
@@ -182,10 +182,6 @@ export class DetachedElementsProfileHeader extends WritableProfileHeader {
|
|
|
182
182
|
this.#heapProfilerModel = heapProfilerModel;
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
override createView(dataDisplayDelegate: DataDisplayDelegate): DetachedElementsProfileView {
|
|
186
|
-
return new DetachedElementsProfileView(dataDisplayDelegate, this);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
185
|
heapProfilerModel(): SDK.HeapProfilerModel.HeapProfilerModel|null {
|
|
190
186
|
return this.#heapProfilerModel;
|
|
191
187
|
}
|
|
@@ -487,10 +487,6 @@ export class SamplingHeapProfileHeader extends WritableProfileHeader {
|
|
|
487
487
|
};
|
|
488
488
|
}
|
|
489
489
|
|
|
490
|
-
override createView(): HeapProfileView {
|
|
491
|
-
return new HeapProfileView(this);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
490
|
protocolProfile(): Protocol.HeapProfiler.SamplingHeapProfile {
|
|
495
491
|
return this.protocolProfileInternal;
|
|
496
492
|
}
|
|
@@ -8,9 +8,7 @@ import type * as SDK from '../../core/sdk/sdk.js';
|
|
|
8
8
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
9
9
|
|
|
10
10
|
import type {HeapSnapshotView} from './HeapSnapshotView.js';
|
|
11
|
-
import type {ProfileType} from './ProfileHeader.js';
|
|
12
11
|
import {ProfilesPanel} from './ProfilesPanel.js';
|
|
13
|
-
import {instance} from './ProfileTypeRegistry.js';
|
|
14
12
|
|
|
15
13
|
const UIStrings = {
|
|
16
14
|
/**
|
|
@@ -20,18 +18,12 @@ const UIStrings = {
|
|
|
20
18
|
} as const;
|
|
21
19
|
const str_ = i18n.i18n.registerUIStrings('panels/profiler/HeapProfilerPanel.ts', UIStrings);
|
|
22
20
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
21
|
+
|
|
23
22
|
let heapProfilerPanelInstance: HeapProfilerPanel;
|
|
24
23
|
export class HeapProfilerPanel extends ProfilesPanel implements UI.ContextMenu.Provider<SDK.RemoteObject.RemoteObject>,
|
|
25
24
|
UI.ActionRegistration.ActionDelegate {
|
|
26
25
|
constructor() {
|
|
27
|
-
|
|
28
|
-
const profileTypes = [
|
|
29
|
-
registry.heapSnapshotProfileType,
|
|
30
|
-
registry.trackingHeapSnapshotProfileType,
|
|
31
|
-
registry.samplingHeapProfileType,
|
|
32
|
-
registry.detachedElementProfileType,
|
|
33
|
-
];
|
|
34
|
-
super('heap-profiler', profileTypes as ProfileType[], 'profiler.heap-toggle-recording');
|
|
26
|
+
super('heap-profiler', 'profiler.heap-toggle-recording');
|
|
35
27
|
}
|
|
36
28
|
|
|
37
29
|
static instance(): HeapProfilerPanel {
|
|
@@ -52,7 +44,7 @@ export class HeapProfilerPanel extends ProfilesPanel implements UI.ContextMenu.P
|
|
|
52
44
|
}
|
|
53
45
|
const objectId = object.objectId;
|
|
54
46
|
|
|
55
|
-
const heapProfiles =
|
|
47
|
+
const heapProfiles = ProfilesPanel.registry.heapSnapshotProfileType.getProfiles();
|
|
56
48
|
if (!heapProfiles.length) {
|
|
57
49
|
return;
|
|
58
50
|
}
|
|
@@ -97,8 +89,7 @@ export class HeapProfilerPanel extends ProfilesPanel implements UI.ContextMenu.P
|
|
|
97
89
|
}
|
|
98
90
|
|
|
99
91
|
override showObject(snapshotObjectId: string, perspectiveName: string): void {
|
|
100
|
-
const
|
|
101
|
-
const heapProfiles = registry.heapSnapshotProfileType.getProfiles();
|
|
92
|
+
const heapProfiles = ProfilesPanel.registry.heapSnapshotProfileType.getProfiles();
|
|
102
93
|
for (let i = 0; i < heapProfiles.length; i++) {
|
|
103
94
|
const profile = heapProfiles[i];
|
|
104
95
|
// FIXME: allow to choose snapshot if there are several options.
|
|
@@ -23,9 +23,7 @@ export class HeapSnapshotWorkerProxy extends Common.ObjectWrapper.ObjectWrapper<
|
|
|
23
23
|
readonly eventHandler: (arg0: string, arg1: string) => void;
|
|
24
24
|
nextObjectId = 1;
|
|
25
25
|
nextCallId = 1;
|
|
26
|
-
|
|
27
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
-
callbacks = new Map<number, (arg0: any) => void>();
|
|
26
|
+
callbacks = new Map<number, (...args: any[]) => void>();
|
|
29
27
|
readonly previousCallbacks = new Set<number>();
|
|
30
28
|
readonly worker: PlatformApi.HostRuntime.Worker;
|
|
31
29
|
interval?: number;
|
|
@@ -53,9 +51,7 @@ export class HeapSnapshotWorkerProxy extends Common.ObjectWrapper.ObjectWrapper<
|
|
|
53
51
|
|
|
54
52
|
dispose(): void {
|
|
55
53
|
this.worker.terminate();
|
|
56
|
-
|
|
57
|
-
clearInterval(this.interval);
|
|
58
|
-
}
|
|
54
|
+
clearInterval(this.interval);
|
|
59
55
|
}
|
|
60
56
|
|
|
61
57
|
disposeObject(objectId: number): void {
|