chrome-devtools-frontend 1.0.1539972 → 1.0.1541169
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 +167 -151
- package/front_end/core/common/Revealer.ts +5 -0
- package/front_end/core/host/InspectorFrontendHost.ts +10 -10
- package/front_end/core/sdk/NetworkManager.ts +16 -11
- package/front_end/core/sdk/sdk-meta.ts +0 -35
- package/front_end/entrypoints/shell/shell.ts +1 -0
- package/front_end/entrypoints/trace_app/trace_app.ts +1 -0
- package/front_end/generated/InspectorBackendCommands.ts +6 -3
- package/front_end/generated/SupportedCSSProperties.js +13 -0
- package/front_end/generated/protocol.ts +58 -2
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +121 -56
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +104 -62
- package/front_end/models/ai_assistance/performance/AIQueries.ts +56 -2
- package/front_end/{panels/issues → models/issues_manager}/IssueAggregator.ts +83 -65
- package/front_end/models/issues_manager/issues_manager.ts +2 -0
- package/front_end/models/trace/Processor.ts +5 -4
- package/front_end/models/trace/insights/types.ts +1 -1
- package/front_end/models/trace/types/TraceEvents.ts +1 -1
- package/front_end/models/workspace/IgnoreListManager.ts +41 -47
- package/front_end/models/workspace/workspace-meta.ts +40 -0
- package/front_end/panels/animation/AnimationTimeline.ts +4 -4
- package/front_end/panels/animation/AnimationUI.ts +28 -34
- package/front_end/panels/elements/ElementsTreeElement.ts +37 -9
- package/front_end/panels/elements/LayoutPane.ts +2 -2
- package/front_end/panels/elements/components/AdornerManager.ts +9 -9
- package/front_end/panels/elements/layoutPane.css +5 -9
- package/front_end/panels/event_listeners/EventListenersView.ts +1 -1
- package/front_end/panels/explain/components/ConsoleInsight.ts +498 -449
- package/front_end/panels/issues/AffectedResourcesView.ts +3 -4
- package/front_end/panels/issues/CorsIssueDetailsView.ts +1 -2
- package/front_end/panels/issues/IssueView.ts +1 -1
- package/front_end/panels/issues/IssuesPane.ts +12 -15
- package/front_end/panels/issues/issues.ts +0 -2
- package/front_end/panels/network/NetworkDataGridNode.ts +2 -1
- package/front_end/panels/network/RequestConditionsDrawer.ts +149 -46
- package/front_end/panels/network/RequestTimingView.ts +13 -8
- package/front_end/panels/network/network-meta.ts +11 -0
- package/front_end/panels/settings/emulation/components/userAgentClientHintsForm.css +1 -1
- package/front_end/panels/sources/DebuggerPlugin.ts +1 -1
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +1 -1
- package/front_end/panels/sources/breakpointsView.css +1 -1
- package/front_end/panels/sources/sourcesPanel.css +2 -2
- package/front_end/panels/timeline/TimelineFlameChartView.ts +3 -3
- package/front_end/panels/timeline/TimelinePanel.ts +3 -3
- package/front_end/panels/timeline/components/LayoutShiftDetails.ts +16 -10
- package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +2 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/markdown_view/MarkdownView.ts +1 -0
- package/front_end/ui/components/snackbars/Snackbars.docs.ts +46 -0
- package/front_end/ui/{components/docs/context_menu/basic.ts → legacy/ContextMenu.docs.ts} +58 -25
- package/front_end/ui/legacy/UIUtils.ts +2 -1
- package/front_end/ui/legacy/components/inline_editor/BezierEditor.ts +1 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +105 -92
- package/front_end/ui/legacy/components/perf_ui/TimelineOverviewPane.ts +3 -3
- package/front_end/ui/legacy/components/perf_ui/pieChart.css +1 -1
- package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -1
- package/front_end/ui/legacy/inspectorCommon.css +3 -2
- package/mcp/mcp.ts +15 -1
- package/package.json +2 -1
- package/front_end/ui/components/docs/context_menu/basic.html +0 -45
- package/front_end/ui/components/docs/linkifier/simple-url.html +0 -25
- package/front_end/ui/components/docs/linkifier/simple-url.ts +0 -25
- package/front_end/ui/components/docs/panel_feedback/basic.html +0 -25
- package/front_end/ui/components/docs/panel_feedback/basic.ts +0 -21
- package/front_end/ui/components/docs/panel_feedback/button.html +0 -25
- package/front_end/ui/components/docs/panel_feedback/button.ts +0 -19
- package/front_end/ui/components/docs/panel_introduction_steps/basic.html +0 -25
- package/front_end/ui/components/docs/panel_introduction_steps/basic.ts +0 -28
- package/front_end/ui/components/docs/perf_piechart/basic-with-legend.html +0 -20
- package/front_end/ui/components/docs/perf_piechart/basic-with-legend.ts +0 -20
- package/front_end/ui/components/docs/perf_piechart/basic-without-legend.html +0 -20
- package/front_end/ui/components/docs/perf_piechart/basic-without-legend.ts +0 -18
- package/front_end/ui/components/docs/snackbars/basic.html +0 -17
- package/front_end/ui/components/docs/snackbars/basic.ts +0 -50
|
@@ -190,15 +190,22 @@ export const DEFAULT_VIEW: (input: ViewInput, output: object, target: HTMLElemen
|
|
|
190
190
|
// clang-format on
|
|
191
191
|
};
|
|
192
192
|
|
|
193
|
+
function findInsightSet(insightSets: Trace.Insights.Types.TraceInsightSets|null, navigationId: string|undefined):
|
|
194
|
+
Trace.Insights.Types.InsightSet|undefined {
|
|
195
|
+
return insightSets?.values().find(
|
|
196
|
+
insightSet =>
|
|
197
|
+
navigationId ? navigationId === insightSet.navigation?.args.data?.navigationId : !insightSet.navigation);
|
|
198
|
+
}
|
|
199
|
+
|
|
193
200
|
function renderLayoutShiftDetails(
|
|
194
|
-
layoutShift: Trace.Types.Events.SyntheticLayoutShift,
|
|
201
|
+
layoutShift: Trace.Types.Events.SyntheticLayoutShift, insightSets: Trace.Insights.Types.TraceInsightSets|null,
|
|
195
202
|
parsedTrace: Trace.TraceModel.ParsedTrace, isFreshRecording: boolean,
|
|
196
203
|
onEventClick: (e: Trace.Types.Events.Event) => void): Lit.LitTemplate {
|
|
197
|
-
if (!
|
|
204
|
+
if (!insightSets) {
|
|
198
205
|
return Lit.nothing;
|
|
199
206
|
}
|
|
200
|
-
|
|
201
|
-
const clsInsight =
|
|
207
|
+
|
|
208
|
+
const clsInsight = findInsightSet(insightSets, layoutShift.args.data?.navigationId)?.model.CLSCulprits;
|
|
202
209
|
if (!clsInsight || clsInsight instanceof Error) {
|
|
203
210
|
return Lit.nothing;
|
|
204
211
|
}
|
|
@@ -242,14 +249,13 @@ function renderLayoutShiftDetails(
|
|
|
242
249
|
}
|
|
243
250
|
|
|
244
251
|
function renderLayoutShiftClusterDetails(
|
|
245
|
-
cluster: Trace.Types.Events.SyntheticLayoutShiftCluster,
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (!traceInsightsSets) {
|
|
252
|
+
cluster: Trace.Types.Events.SyntheticLayoutShiftCluster, insightSets: Trace.Insights.Types.TraceInsightSets|null,
|
|
253
|
+
parsedTrace: Trace.TraceModel.ParsedTrace, onEventClick: (e: Trace.Types.Events.Event) => void): Lit.LitTemplate {
|
|
254
|
+
if (!insightSets) {
|
|
249
255
|
return Lit.nothing;
|
|
250
256
|
}
|
|
251
|
-
|
|
252
|
-
const clsInsight =
|
|
257
|
+
|
|
258
|
+
const clsInsight = findInsightSet(insightSets, cluster.navigationId)?.model.CLSCulprits;
|
|
253
259
|
if (!clsInsight || clsInsight instanceof Error) {
|
|
254
260
|
return Lit.nothing;
|
|
255
261
|
}
|
|
@@ -437,6 +437,7 @@ export class SidebarSingleInsightSet extends HTMLElement {
|
|
|
437
437
|
|
|
438
438
|
const agentFocus = AIAssistance.AIContext.AgentFocus.fromInsight(this.#data.parsedTrace, model);
|
|
439
439
|
// clang-format off
|
|
440
|
+
/* eslint-disable lit/binding-positions,lit/no-invalid-html */
|
|
440
441
|
return html`<div>
|
|
441
442
|
<${componentClass.litTagName}
|
|
442
443
|
.selected=${this.#data.activeInsight?.model === model}
|
|
@@ -452,6 +453,7 @@ export class SidebarSingleInsightSet extends HTMLElement {
|
|
|
452
453
|
.fieldMetrics=${fieldMetrics}>
|
|
453
454
|
</${componentClass.litTagName}>
|
|
454
455
|
</div>`;
|
|
456
|
+
/* eslint-enable lit/binding-positions,lit/no-invalid-html */
|
|
455
457
|
// clang-format on
|
|
456
458
|
};
|
|
457
459
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Name: Dependencies sourced from the upstream `chromium` repository
|
|
2
2
|
URL: https://chromium.googlesource.com/chromium/src
|
|
3
3
|
Version: N/A
|
|
4
|
-
Revision:
|
|
4
|
+
Revision: 33096dd334d53eb095e196b5663cc1921f646cae
|
|
5
5
|
Update Mechanism: Manual (https://crbug.com/428069060)
|
|
6
6
|
License: BSD-3-Clause
|
|
7
7
|
License File: LICENSE
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Copyright 2025 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
import {Snackbar} from './snackbars.js';
|
|
6
|
+
|
|
7
|
+
export async function render(container: HTMLElement) {
|
|
8
|
+
const onActionClick = (): void => {
|
|
9
|
+
// eslint-disable-next-line no-console
|
|
10
|
+
console.log('Action button clicked!');
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const showButton1 = document.createElement('button');
|
|
14
|
+
showButton1.textContent = 'Show Long Action Snackbar';
|
|
15
|
+
showButton1.addEventListener('click', () => {
|
|
16
|
+
Snackbar.Snackbar.show(
|
|
17
|
+
{
|
|
18
|
+
message: 'This is a snackbar demonstrating a long action and closable state.',
|
|
19
|
+
closable: true,
|
|
20
|
+
actionProperties: {
|
|
21
|
+
label: 'This is a long action button',
|
|
22
|
+
title: 'Click here to perform the designated action',
|
|
23
|
+
onClick: onActionClick,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
container);
|
|
27
|
+
});
|
|
28
|
+
container.appendChild(showButton1);
|
|
29
|
+
|
|
30
|
+
const showButton2 = document.createElement('button');
|
|
31
|
+
showButton2.textContent = 'Show Action Snackbar';
|
|
32
|
+
showButton2.addEventListener('click', () => {
|
|
33
|
+
Snackbar.Snackbar.show(
|
|
34
|
+
{
|
|
35
|
+
message: 'This is a snackbar demonstrating an action and closable state.',
|
|
36
|
+
closable: true,
|
|
37
|
+
actionProperties: {
|
|
38
|
+
label: 'Action',
|
|
39
|
+
title: 'Click here to perform the designated action',
|
|
40
|
+
onClick: onActionClick,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
container);
|
|
44
|
+
});
|
|
45
|
+
container.appendChild(showButton2);
|
|
46
|
+
}
|
|
@@ -2,23 +2,44 @@
|
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
|
-
import * as
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import * as ComponentHelpers from '../../helpers/helpers.js';
|
|
5
|
+
import * as Lit from '../lit/lit.js';
|
|
6
|
+
|
|
7
|
+
import {ContextMenu} from './legacy.js';
|
|
9
8
|
|
|
10
9
|
const {html} = Lit;
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
export async function render(container: HTMLElement) {
|
|
12
|
+
const style = document.createElement('style');
|
|
13
|
+
style.textContent = `
|
|
14
|
+
#container > div {
|
|
15
|
+
width: var(--sys-size-34);
|
|
16
|
+
padding: var(--sys-size-11);
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
flex-wrap: wrap;
|
|
20
|
+
gap: var(--sys-size-5);
|
|
21
|
+
background-color: var(--sys-color-neutral-container);
|
|
22
|
+
border-radius: var(--sys-shape-corner-medium);
|
|
23
|
+
text-align: center;
|
|
24
|
+
|
|
25
|
+
p {
|
|
26
|
+
vertical-align: middle;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
container.appendChild(style);
|
|
31
|
+
|
|
32
|
+
const menuButtonSection = document.createElement('div');
|
|
33
|
+
const menuButtonHeader = document.createElement('header');
|
|
34
|
+
menuButtonHeader.textContent = 'DevTools menu button (lit-html)';
|
|
35
|
+
container.appendChild(menuButtonHeader);
|
|
36
|
+
container.appendChild(menuButtonSection);
|
|
14
37
|
|
|
15
|
-
{
|
|
16
|
-
const menuButtonSection = document.querySelector('#menu-button') as HTMLElement;
|
|
17
38
|
Lit.render(
|
|
18
39
|
html`
|
|
19
40
|
<devtools-menu-button
|
|
20
41
|
icon-name="bin"
|
|
21
|
-
.populateMenuCall=${(menu:
|
|
42
|
+
.populateMenuCall=${(menu: ContextMenu.ContextMenu) => {
|
|
22
43
|
menu.defaultSection().appendItem('Item', () => {
|
|
23
44
|
alert('Item clicked');
|
|
24
45
|
}, {jslogContext: 'item'});
|
|
@@ -27,15 +48,19 @@ await FrontendHelpers.initializeGlobalVars();
|
|
|
27
48
|
></devtools-menu-button>
|
|
28
49
|
`,
|
|
29
50
|
menuButtonSection);
|
|
30
|
-
}
|
|
31
51
|
|
|
32
|
-
|
|
52
|
+
const simpleItemsSection = document.createElement('div');
|
|
53
|
+
simpleItemsSection.innerHTML = '<p>Right-click here</p>';
|
|
54
|
+
const simpleItemsHeader = document.createElement('header');
|
|
55
|
+
simpleItemsHeader.textContent = 'Various simple menu items (imperative API)';
|
|
56
|
+
container.appendChild(simpleItemsHeader);
|
|
57
|
+
container.appendChild(simpleItemsSection);
|
|
58
|
+
|
|
33
59
|
let checked = true;
|
|
34
|
-
|
|
35
|
-
simpleItemMenuSection?.addEventListener('contextmenu', onSimpleMenu.bind(this));
|
|
60
|
+
simpleItemsSection.addEventListener('contextmenu', onSimpleMenu);
|
|
36
61
|
|
|
37
62
|
function onSimpleMenu(event: Event) {
|
|
38
|
-
const simpleMenu = new
|
|
63
|
+
const simpleMenu = new ContextMenu.ContextMenu(event);
|
|
39
64
|
|
|
40
65
|
// Regular item
|
|
41
66
|
simpleMenu.defaultSection().appendItem('Regular item', () => {
|
|
@@ -63,14 +88,18 @@ await FrontendHelpers.initializeGlobalVars();
|
|
|
63
88
|
|
|
64
89
|
void simpleMenu.show();
|
|
65
90
|
}
|
|
66
|
-
}
|
|
67
91
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
92
|
+
const customSection = document.createElement('div');
|
|
93
|
+
customSection.innerHTML = '<p>Right-click here</p>';
|
|
94
|
+
const customSectionHeader = document.createElement('header');
|
|
95
|
+
customSectionHeader.textContent = 'Custom sections (imperative API)';
|
|
96
|
+
container.appendChild(customSectionHeader);
|
|
97
|
+
container.appendChild(customSection);
|
|
98
|
+
|
|
99
|
+
customSection.addEventListener('contextmenu', onCustomSectionMenu);
|
|
71
100
|
|
|
72
101
|
function onCustomSectionMenu(event: Event) {
|
|
73
|
-
const customSectionMenu = new
|
|
102
|
+
const customSectionMenu = new ContextMenu.ContextMenu(event);
|
|
74
103
|
|
|
75
104
|
// First custom section
|
|
76
105
|
const customSection = customSectionMenu.section('Custom section');
|
|
@@ -83,14 +112,18 @@ await FrontendHelpers.initializeGlobalVars();
|
|
|
83
112
|
|
|
84
113
|
void customSectionMenu.show();
|
|
85
114
|
}
|
|
86
|
-
}
|
|
87
115
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
116
|
+
const subMenuSection = document.createElement('div');
|
|
117
|
+
subMenuSection.innerHTML = '<p>Right-click here</p>';
|
|
118
|
+
const subMenuHeader = document.createElement('header');
|
|
119
|
+
subMenuHeader.textContent = 'Sub menu (imperative API)';
|
|
120
|
+
container.appendChild(subMenuHeader);
|
|
121
|
+
container.appendChild(subMenuSection);
|
|
91
122
|
|
|
92
|
-
|
|
93
|
-
|
|
123
|
+
subMenuSection.addEventListener('contextmenu', onSubMenu);
|
|
124
|
+
|
|
125
|
+
function onSubMenu(event: Event) {
|
|
126
|
+
const subMenuMenu = new ContextMenu.ContextMenu(event);
|
|
94
127
|
|
|
95
128
|
const subMenu =
|
|
96
129
|
subMenuMenu.defaultSection().appendSubMenuItem('Item to open sub menu', /* disabled */ false, 'my-sub-menu');
|
|
@@ -1820,7 +1820,8 @@ export const isScrolledToBottom = (element: Element): boolean => {
|
|
|
1820
1820
|
return Math.abs(element.scrollTop + element.clientHeight - element.scrollHeight) <= 2;
|
|
1821
1821
|
};
|
|
1822
1822
|
|
|
1823
|
-
export function createSVGChild
|
|
1823
|
+
export function createSVGChild<K extends keyof SVGElementTagNameMap>(
|
|
1824
|
+
element: Element, childType: K, className?: string): SVGElementTagNameMap[K] {
|
|
1824
1825
|
const child = element.ownerDocument.createElementNS('http://www.w3.org/2000/svg', childType);
|
|
1825
1826
|
if (className) {
|
|
1826
1827
|
child.setAttribute('class', className);
|
|
@@ -147,7 +147,7 @@ export class BezierEditor extends Common.ObjectWrapper.eventMixin<EventTypes, ty
|
|
|
147
147
|
return category;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
private createPresetModifyIcon(parentElement: Element, className: string, drawPath: string):
|
|
150
|
+
private createPresetModifyIcon(parentElement: Element, className: string, drawPath: string): SVGElement {
|
|
151
151
|
const icon = UI.UIUtils.createSVGChild(parentElement, 'svg', 'bezier-preset-modify ' + className);
|
|
152
152
|
icon.setAttribute('width', '20');
|
|
153
153
|
icon.setAttribute('height', '20');
|
|
@@ -39,6 +39,7 @@ import * as TextUtils from '../../../../models/text_utils/text_utils.js';
|
|
|
39
39
|
import * as uiI18n from '../../../../ui/i18n/i18n.js';
|
|
40
40
|
import * as IconButton from '../../../components/icon_button/icon_button.js';
|
|
41
41
|
import * as TextEditor from '../../../components/text_editor/text_editor.js';
|
|
42
|
+
import {Directives, html, render} from '../../../lit/lit.js';
|
|
42
43
|
import * as VisualLogging from '../../../visual_logging/visual_logging.js';
|
|
43
44
|
import * as UI from '../../legacy.js';
|
|
44
45
|
import type * as Components from '../utils/utils.js';
|
|
@@ -49,6 +50,7 @@ import objectPropertiesSectionStyles from './objectPropertiesSection.css.js';
|
|
|
49
50
|
import objectValueStyles from './objectValue.css.js';
|
|
50
51
|
import {createSpansForNodeTitle, RemoteObjectPreviewFormatter} from './RemoteObjectPreviewFormatter.js';
|
|
51
52
|
|
|
53
|
+
const {ifDefined} = Directives;
|
|
52
54
|
const UIStrings = {
|
|
53
55
|
/**
|
|
54
56
|
* @description Text in Object Properties Section
|
|
@@ -397,7 +399,7 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
|
|
|
397
399
|
const shadowRoot = UI.UIUtils.createShadowRootWithCoreStyles(titleElement, {cssFile: objectValueStyles});
|
|
398
400
|
const propertyValue =
|
|
399
401
|
ObjectPropertiesSection.createPropertyValue(object, /* wasThrown */ false, /* showPreview */ true);
|
|
400
|
-
shadowRoot.appendChild(propertyValue
|
|
402
|
+
shadowRoot.appendChild(propertyValue);
|
|
401
403
|
const objectPropertiesSection = new ObjectPropertiesSection(object, titleElement, linkifier);
|
|
402
404
|
objectPropertiesSection.editable = false;
|
|
403
405
|
if (skipProto) {
|
|
@@ -477,7 +479,7 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
|
|
|
477
479
|
}
|
|
478
480
|
|
|
479
481
|
static valueElementForFunctionDescription(description?: string, includePreview?: boolean, defaultName?: string):
|
|
480
|
-
|
|
482
|
+
HTMLElement {
|
|
481
483
|
const valueElement = document.createElement('span');
|
|
482
484
|
valueElement.classList.add('object-value-function');
|
|
483
485
|
description = description || '';
|
|
@@ -560,12 +562,11 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
|
|
|
560
562
|
|
|
561
563
|
static createPropertyValueWithCustomSupport(
|
|
562
564
|
value: SDK.RemoteObject.RemoteObject, wasThrown: boolean, showPreview: boolean,
|
|
563
|
-
linkifier?: Components.Linkifier.Linkifier, isSyntheticProperty?: boolean,
|
|
564
|
-
variableName?: string): ObjectPropertyValue {
|
|
565
|
+
linkifier?: Components.Linkifier.Linkifier, isSyntheticProperty?: boolean, variableName?: string): HTMLElement {
|
|
565
566
|
if (value.customPreview()) {
|
|
566
567
|
const result = (new CustomPreviewComponent(value)).element;
|
|
567
568
|
result.classList.add('object-properties-section-custom-section');
|
|
568
|
-
return
|
|
569
|
+
return result;
|
|
569
570
|
}
|
|
570
571
|
return ObjectPropertiesSection.createPropertyValue(
|
|
571
572
|
value, wasThrown, showPreview, linkifier, isSyntheticProperty, variableName);
|
|
@@ -600,9 +601,8 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
|
|
|
600
601
|
|
|
601
602
|
static createPropertyValue(
|
|
602
603
|
value: SDK.RemoteObject.RemoteObject, wasThrown: boolean, showPreview: boolean,
|
|
603
|
-
linkifier?: Components.Linkifier.Linkifier, isSyntheticProperty = false,
|
|
604
|
-
|
|
605
|
-
let propertyValue;
|
|
604
|
+
linkifier?: Components.Linkifier.Linkifier, isSyntheticProperty = false, variableName?: string): HTMLElement {
|
|
605
|
+
let propertyValue: HTMLElement;
|
|
606
606
|
const type = value.type;
|
|
607
607
|
const subtype = value.subtype;
|
|
608
608
|
const description = value.description || '';
|
|
@@ -611,31 +611,31 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
|
|
|
611
611
|
const rawLocation = value.debuggerModel().createRawLocationByScriptId(
|
|
612
612
|
value.value.scriptId, value.value.lineNumber, value.value.columnNumber);
|
|
613
613
|
if (rawLocation && linkifier) {
|
|
614
|
-
return
|
|
614
|
+
return linkifier.linkifyRawLocation(rawLocation, Platform.DevToolsPath.EmptyUrlString);
|
|
615
615
|
}
|
|
616
|
-
propertyValue =
|
|
616
|
+
propertyValue = createUnknownInternalLocationElement();
|
|
617
617
|
} else if (type === 'string' && typeof description === 'string') {
|
|
618
618
|
propertyValue = createStringElement();
|
|
619
619
|
} else if (type === 'object' && subtype === 'trustedtype') {
|
|
620
620
|
propertyValue = createTrustedTypeElement();
|
|
621
621
|
} else if (type === 'function') {
|
|
622
|
-
propertyValue =
|
|
622
|
+
propertyValue = ObjectPropertiesSection.valueElementForFunctionDescription(description);
|
|
623
623
|
} else if (type === 'object' && subtype === 'node' && description) {
|
|
624
|
-
propertyValue =
|
|
624
|
+
propertyValue = createNodeElement();
|
|
625
625
|
} else {
|
|
626
626
|
const valueElement = document.createElement('span');
|
|
627
627
|
valueElement.classList.add('object-value-' + (subtype || type));
|
|
628
628
|
if (value.preview && showPreview) {
|
|
629
629
|
const previewFormatter = new RemoteObjectPreviewFormatter();
|
|
630
630
|
previewFormatter.appendObjectPreview(valueElement, value.preview, false /* isEntry */);
|
|
631
|
-
propertyValue =
|
|
632
|
-
UI.Tooltip.Tooltip.install(propertyValue
|
|
631
|
+
propertyValue = valueElement;
|
|
632
|
+
UI.Tooltip.Tooltip.install(propertyValue as HTMLElement, description || '');
|
|
633
633
|
} else if (description.length > maxRenderableStringLength) {
|
|
634
|
-
propertyValue = new ExpandableTextPropertyValue(valueElement, description, EXPANDABLE_MAX_LENGTH);
|
|
634
|
+
propertyValue = new ExpandableTextPropertyValue(valueElement, description, EXPANDABLE_MAX_LENGTH).element;
|
|
635
635
|
} else {
|
|
636
|
-
propertyValue =
|
|
637
|
-
propertyValue.
|
|
638
|
-
UI.Tooltip.Tooltip.install(propertyValue
|
|
636
|
+
propertyValue = valueElement;
|
|
637
|
+
propertyValue.textContent = description;
|
|
638
|
+
UI.Tooltip.Tooltip.install(propertyValue as HTMLElement, description);
|
|
639
639
|
}
|
|
640
640
|
if (!isSyntheticProperty) {
|
|
641
641
|
this.appendMemoryIcon(valueElement, value, variableName);
|
|
@@ -646,54 +646,53 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
|
|
|
646
646
|
const wrapperElement = document.createElement('span');
|
|
647
647
|
wrapperElement.classList.add('error');
|
|
648
648
|
wrapperElement.classList.add('value');
|
|
649
|
-
wrapperElement.appendChild(
|
|
650
|
-
|
|
651
|
-
propertyValue.element = wrapperElement;
|
|
649
|
+
wrapperElement.appendChild(uiI18n.getFormatLocalizedString(str_, UIStrings.exceptionS, {PH1: propertyValue}));
|
|
650
|
+
propertyValue = wrapperElement;
|
|
652
651
|
}
|
|
653
|
-
propertyValue.
|
|
652
|
+
propertyValue.classList.add('value');
|
|
654
653
|
return propertyValue;
|
|
655
654
|
|
|
656
|
-
function createUnknownInternalLocationElement():
|
|
655
|
+
function createUnknownInternalLocationElement(): HTMLElement {
|
|
657
656
|
const valueElement = document.createElement('span');
|
|
658
657
|
valueElement.textContent = '<' + i18nString(UIStrings.unknown) + '>';
|
|
659
658
|
UI.Tooltip.Tooltip.install(valueElement, description || '');
|
|
660
659
|
return valueElement;
|
|
661
660
|
}
|
|
662
661
|
|
|
663
|
-
function createStringElement():
|
|
662
|
+
function createStringElement(): HTMLElement {
|
|
664
663
|
const valueElement = document.createElement('span');
|
|
665
664
|
valueElement.classList.add('object-value-string');
|
|
666
665
|
const text = JSON.stringify(description);
|
|
667
|
-
let propertyValue;
|
|
666
|
+
let propertyValue: HTMLElement;
|
|
668
667
|
if (description.length > maxRenderableStringLength) {
|
|
669
|
-
propertyValue = new ExpandableTextPropertyValue(valueElement, text, EXPANDABLE_MAX_LENGTH);
|
|
668
|
+
propertyValue = new ExpandableTextPropertyValue(valueElement, text, EXPANDABLE_MAX_LENGTH).element;
|
|
670
669
|
} else {
|
|
671
670
|
UI.UIUtils.createTextChild(valueElement, text);
|
|
672
|
-
propertyValue =
|
|
671
|
+
propertyValue = valueElement;
|
|
673
672
|
UI.Tooltip.Tooltip.install(valueElement, description);
|
|
674
673
|
}
|
|
675
674
|
return propertyValue;
|
|
676
675
|
}
|
|
677
676
|
|
|
678
|
-
function createTrustedTypeElement():
|
|
677
|
+
function createTrustedTypeElement(): HTMLElement {
|
|
679
678
|
const valueElement = document.createElement('span');
|
|
680
679
|
valueElement.classList.add('object-value-trustedtype');
|
|
681
680
|
const text = `${className} "${description}"`;
|
|
682
681
|
let propertyValue;
|
|
683
682
|
if (text.length > maxRenderableStringLength) {
|
|
684
|
-
propertyValue = new ExpandableTextPropertyValue(valueElement, text, EXPANDABLE_MAX_LENGTH);
|
|
683
|
+
propertyValue = new ExpandableTextPropertyValue(valueElement, text, EXPANDABLE_MAX_LENGTH).element;
|
|
685
684
|
} else {
|
|
686
685
|
const contentString = createStringElement();
|
|
687
686
|
UI.UIUtils.createTextChild(valueElement, `${className} `);
|
|
688
|
-
valueElement.appendChild(contentString
|
|
689
|
-
propertyValue =
|
|
687
|
+
valueElement.appendChild(contentString);
|
|
688
|
+
propertyValue = valueElement;
|
|
690
689
|
UI.Tooltip.Tooltip.install(valueElement, text);
|
|
691
690
|
}
|
|
692
691
|
|
|
693
692
|
return propertyValue;
|
|
694
693
|
}
|
|
695
694
|
|
|
696
|
-
function createNodeElement():
|
|
695
|
+
function createNodeElement(): HTMLElement {
|
|
697
696
|
const valueElement = document.createElement('span');
|
|
698
697
|
valueElement.classList.add('object-value-node');
|
|
699
698
|
createSpansForNodeTitle(valueElement, (description));
|
|
@@ -896,7 +895,7 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
896
895
|
readOnly!: boolean;
|
|
897
896
|
private prompt!: ObjectPropertyPrompt|undefined;
|
|
898
897
|
private editableDiv!: HTMLElement;
|
|
899
|
-
propertyValue?:
|
|
898
|
+
propertyValue?: HTMLElement;
|
|
900
899
|
expandedValueElement?: Element|null;
|
|
901
900
|
constructor(property: ObjectTreeNode, linkifier?: Components.Linkifier.Linkifier) {
|
|
902
901
|
// Pass an empty title, the title gets made later in onattach.
|
|
@@ -1202,7 +1201,7 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1202
1201
|
this.propertyValue = ObjectPropertiesSection.createPropertyValueWithCustomSupport(
|
|
1203
1202
|
this.property.object, this.property.property.wasThrown, showPreview, this.linkifier,
|
|
1204
1203
|
this.property.property.synthetic, this.path() /* variableName */);
|
|
1205
|
-
this.valueElement =
|
|
1204
|
+
this.valueElement = this.propertyValue;
|
|
1206
1205
|
} else if (this.property.property.getter) {
|
|
1207
1206
|
this.valueElement = document.createElement('span');
|
|
1208
1207
|
const element = this.valueElement.createChild('span');
|
|
@@ -1285,7 +1284,7 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1285
1284
|
}
|
|
1286
1285
|
}
|
|
1287
1286
|
|
|
1288
|
-
|
|
1287
|
+
getContextMenu(event: Event): UI.ContextMenu.ContextMenu {
|
|
1289
1288
|
const contextMenu = new UI.ContextMenu.ContextMenu(event);
|
|
1290
1289
|
contextMenu.appendApplicableItems(this);
|
|
1291
1290
|
if (this.property.property.symbol) {
|
|
@@ -1318,9 +1317,11 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1318
1317
|
i18nString(UIStrings.collapseChildren), this.collapseChildren.bind(this),
|
|
1319
1318
|
{jslogContext: 'collapse-children'});
|
|
1320
1319
|
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1320
|
+
return contextMenu;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
private contextMenuFired(event: Event): void {
|
|
1324
|
+
const contextMenu = this.getContextMenu(event);
|
|
1324
1325
|
void contextMenu.show();
|
|
1325
1326
|
}
|
|
1326
1327
|
|
|
@@ -1773,74 +1774,86 @@ export class Renderer implements UI.UIUtils.Renderer {
|
|
|
1773
1774
|
}
|
|
1774
1775
|
}
|
|
1775
1776
|
|
|
1776
|
-
export class
|
|
1777
|
-
element: Element;
|
|
1778
|
-
constructor(element: Element) {
|
|
1779
|
-
this.element = element;
|
|
1780
|
-
}
|
|
1781
|
-
|
|
1782
|
-
appendApplicableItems(_event: Event, _contextMenu: UI.ContextMenu.ContextMenu, _object: Object): void {
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
|
|
1786
|
-
export class ExpandableTextPropertyValue extends ObjectPropertyValue {
|
|
1777
|
+
export class ExpandableTextPropertyValue {
|
|
1787
1778
|
private readonly text: string;
|
|
1788
1779
|
private readonly maxLength: number;
|
|
1789
|
-
private expandElement: Element|null;
|
|
1790
1780
|
private readonly maxDisplayableTextLength: number;
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1781
|
+
readonly #byteCount: number;
|
|
1782
|
+
#expanded = false;
|
|
1783
|
+
#element: HTMLElement;
|
|
1784
|
+
|
|
1785
|
+
constructor(element: HTMLElement, text: string, maxLength: number) {
|
|
1786
|
+
this.#element = element;
|
|
1797
1787
|
this.text = text;
|
|
1798
1788
|
this.maxLength = maxLength;
|
|
1799
|
-
container.textContent = text.slice(0, maxLength);
|
|
1800
|
-
UI.Tooltip.Tooltip.install(container as HTMLElement, `${text.slice(0, maxLength)}…`);
|
|
1801
|
-
|
|
1802
|
-
this.expandElement = container.createChild('button');
|
|
1803
1789
|
this.maxDisplayableTextLength = 10000000;
|
|
1790
|
+
this.#byteCount = Platform.StringUtilities.countWtf8Bytes(text);
|
|
1791
|
+
this.#render();
|
|
1792
|
+
}
|
|
1804
1793
|
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
if (this.text.length < this.maxDisplayableTextLength) {
|
|
1808
|
-
this.expandElementText = i18nString(UIStrings.showMoreS, {PH1: totalBytesText});
|
|
1809
|
-
this.expandElement.setAttribute('data-text', this.expandElementText);
|
|
1810
|
-
this.expandElement.setAttribute('jslog', `${VisualLogging.action('expand').track({click: true})}`);
|
|
1811
|
-
this.expandElement.classList.add('expandable-inline-button');
|
|
1812
|
-
this.expandElement.addEventListener('click', this.expandText.bind(this));
|
|
1813
|
-
} else {
|
|
1814
|
-
this.expandElement.setAttribute('data-text', i18nString(UIStrings.longTextWasTruncatedS, {PH1: totalBytesText}));
|
|
1815
|
-
this.expandElement.classList.add('undisplayable-text');
|
|
1816
|
-
}
|
|
1817
|
-
|
|
1818
|
-
this.copyButtonText = i18nString(UIStrings.copy);
|
|
1819
|
-
const copyButton = container.createChild('button', 'expandable-inline-button');
|
|
1820
|
-
copyButton.setAttribute('data-text', this.copyButtonText);
|
|
1821
|
-
copyButton.setAttribute('jslog', `${VisualLogging.action('copy').track({click: true})}`);
|
|
1822
|
-
copyButton.addEventListener('click', this.copyText.bind(this));
|
|
1794
|
+
get element(): HTMLElement {
|
|
1795
|
+
return this.#element;
|
|
1823
1796
|
}
|
|
1824
1797
|
|
|
1825
|
-
|
|
1826
|
-
|
|
1798
|
+
#render(): void {
|
|
1799
|
+
const totalBytesText = i18n.ByteUtilities.bytesToString(this.#byteCount);
|
|
1800
|
+
const onContextMenu = (e: Event): void => {
|
|
1801
|
+
const {target} = e;
|
|
1802
|
+
if (!(target instanceof Element)) {
|
|
1803
|
+
return;
|
|
1804
|
+
}
|
|
1805
|
+
const listItem = target.closest('li');
|
|
1806
|
+
const element = listItem && UI.TreeOutline.TreeElement.getTreeElementBylistItemNode(listItem);
|
|
1807
|
+
if (!(element instanceof ObjectPropertyTreeElement)) {
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
const contextMenu = element.getContextMenu(e);
|
|
1811
|
+
if (this.text.length < this.maxDisplayableTextLength && !this.#expanded) {
|
|
1812
|
+
contextMenu.clipboardSection().appendItem(
|
|
1813
|
+
i18nString(UIStrings.showMoreS, {PH1: totalBytesText}), this.expandText.bind(this),
|
|
1814
|
+
{jslogContext: 'show-more'});
|
|
1815
|
+
}
|
|
1827
1816
|
contextMenu.clipboardSection().appendItem(
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1817
|
+
i18nString(UIStrings.copy), this.copyText.bind(this), {jslogContext: 'copy'});
|
|
1818
|
+
void contextMenu.show();
|
|
1819
|
+
e.consume(true);
|
|
1820
|
+
};
|
|
1821
|
+
|
|
1822
|
+
const croppedText = this.text.slice(0, this.maxLength);
|
|
1823
|
+
|
|
1824
|
+
// eslint-disable-next-line @devtools/no-lit-render-outside-of-view
|
|
1825
|
+
render(
|
|
1826
|
+
// clang-format off
|
|
1827
|
+
html`<span title=${croppedText + '…'} @contextmenu=${onContextMenu}>
|
|
1828
|
+
${this.#expanded ? this.text : croppedText}
|
|
1829
|
+
<button
|
|
1830
|
+
?hidden=${this.#expanded}
|
|
1831
|
+
@click=${this.#canExpand ? this.expandText.bind(this) : undefined}
|
|
1832
|
+
jslog=${ifDefined(this.#canExpand ? VisualLogging.action('expand').track({click: true}) : undefined)}
|
|
1833
|
+
class=${this.#canExpand ? 'expandable-inline-button' : 'undisplayable-text'}
|
|
1834
|
+
data-text=${this.#canExpand ? i18nString(UIStrings.showMoreS, {PH1: totalBytesText}) :
|
|
1835
|
+
i18nString(UIStrings.longTextWasTruncatedS, {PH1: totalBytesText})}
|
|
1836
|
+
></button>
|
|
1837
|
+
<button
|
|
1838
|
+
class=expandable-inline-button
|
|
1839
|
+
@click=${this.copyText.bind(this)}
|
|
1840
|
+
data-text=${i18nString(UIStrings.copy)}
|
|
1841
|
+
jslog=${VisualLogging.action('copy').track({click: true})}
|
|
1842
|
+
></button>
|
|
1843
|
+
</span>`,
|
|
1844
|
+
// clang-format on
|
|
1845
|
+
this.#element);
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
get #canExpand(): boolean {
|
|
1849
|
+
return this.text.length < this.maxDisplayableTextLength;
|
|
1831
1850
|
}
|
|
1832
1851
|
|
|
1833
1852
|
private expandText(): void {
|
|
1834
|
-
if (!this
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
if (this.expandElement.parentElement) {
|
|
1839
|
-
this.expandElement.parentElement.insertBefore(
|
|
1840
|
-
document.createTextNode(this.text.slice(this.maxLength)), this.expandElement);
|
|
1853
|
+
if (!this.#expanded) {
|
|
1854
|
+
this.#expanded = true;
|
|
1855
|
+
this.#render();
|
|
1841
1856
|
}
|
|
1842
|
-
this.expandElement.remove();
|
|
1843
|
-
this.expandElement = null;
|
|
1844
1857
|
}
|
|
1845
1858
|
|
|
1846
1859
|
private copyText(): void {
|
|
@@ -337,7 +337,7 @@ export class TimelineOverviewPane extends Common.ObjectWrapper.eventMixin<EventT
|
|
|
337
337
|
#initializeDimHighlightSVG(): void {
|
|
338
338
|
// Set up the desaturation mask
|
|
339
339
|
const defs = UI.UIUtils.createSVGChild(this.#dimHighlightSVG, 'defs');
|
|
340
|
-
const mask = UI.UIUtils.createSVGChild(defs, 'mask')
|
|
340
|
+
const mask = UI.UIUtils.createSVGChild(defs, 'mask');
|
|
341
341
|
mask.id = 'dim-highlight-cutouts';
|
|
342
342
|
/* Within the mask...
|
|
343
343
|
- black fill = punch, fully transparently, through to the next thing. these are the cutouts to the color.
|
|
@@ -357,7 +357,7 @@ export class TimelineOverviewPane extends Common.ObjectWrapper.eventMixin<EventT
|
|
|
357
357
|
// `mask` element.
|
|
358
358
|
// The `mixBlendMode` is set to 'saturation', so this rectangle will completely desaturate the area it covers
|
|
359
359
|
// within the mask.
|
|
360
|
-
const desaturateRect = UI.UIUtils.createSVGChild(this.#dimHighlightSVG, 'rect', 'background')
|
|
360
|
+
const desaturateRect = UI.UIUtils.createSVGChild(this.#dimHighlightSVG, 'rect', 'background');
|
|
361
361
|
desaturateRect.setAttribute('width', '100%');
|
|
362
362
|
desaturateRect.setAttribute('height', '100%');
|
|
363
363
|
desaturateRect.setAttribute('fill', ThemeSupport.ThemeSupport.instance().getComputedValue('--color-background'));
|
|
@@ -374,7 +374,7 @@ export class TimelineOverviewPane extends Common.ObjectWrapper.eventMixin<EventT
|
|
|
374
374
|
|
|
375
375
|
// This polygon is for the bracket beyond the not desaturated area.
|
|
376
376
|
const bracketColor = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-state-on-header-hover');
|
|
377
|
-
const bracket = UI.UIUtils.createSVGChild(this.#dimHighlightSVG, 'polygon')
|
|
377
|
+
const bracket = UI.UIUtils.createSVGChild(this.#dimHighlightSVG, 'polygon');
|
|
378
378
|
bracket.setAttribute('fill', bracketColor);
|
|
379
379
|
|
|
380
380
|
ThemeSupport.ThemeSupport.instance().addEventListener(ThemeSupport.ThemeChangeEvent.eventName, () => {
|