chrome-devtools-frontend 1.0.1034999 → 1.0.1036501
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/AUTHORS +1 -0
- package/config/gni/devtools_grd_files.gni +2 -0
- package/docs/workflows.md +4 -5
- package/front_end/core/i18n/locales/en-US.json +21 -6
- package/front_end/core/i18n/locales/en-XL.json +21 -6
- package/front_end/core/root/Runtime.ts +8 -3
- package/front_end/entrypoints/main/MainImpl.ts +6 -5
- package/front_end/generated/InspectorBackendCommands.js +2 -2
- package/front_end/generated/SupportedCSSProperties.js +8 -4
- package/front_end/generated/protocol.ts +7 -1
- package/front_end/models/persistence/NetworkPersistenceManager.ts +25 -14
- package/front_end/panels/application/components/Prerender2.ts +5 -7
- package/front_end/panels/elements/CSSRuleValidator.ts +1 -1
- package/front_end/panels/elements/StylePropertiesSection.ts +12 -0
- package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +1 -0
- package/front_end/panels/network/NetworkLogView.ts +13 -5
- package/front_end/panels/settings/SettingsScreen.ts +12 -0
- package/front_end/panels/settings/settingsScreen.css +6 -0
- package/front_end/panels/sources/NavigatorView.ts +0 -7
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +4 -3
- package/front_end/panels/sources/SourcesNavigator.ts +0 -37
- package/front_end/panels/sources/SourcesPanel.ts +34 -22
- package/front_end/panels/sources/components/BreakpointsView.ts +206 -0
- package/front_end/panels/sources/components/HeadersView.ts +8 -41
- package/front_end/panels/sources/components/breakpointsView.css +95 -0
- package/front_end/panels/sources/components/components.ts +2 -0
- package/front_end/ui/components/linear_memory_inspector/LinearMemoryHighlightChipList.ts +11 -9
- package/front_end/ui/components/linear_memory_inspector/linearMemoryHighlightChipList.css +48 -30
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +2 -2
- package/package.json +1 -1
@@ -1034,17 +1034,10 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
|
|
1034
1034
|
}
|
1035
1035
|
}
|
1036
1036
|
|
1037
|
-
/**
|
1038
|
-
* Subclasses can override to listen to grouping changes.
|
1039
|
-
*/
|
1040
|
-
onGroupingChanged(): void {
|
1041
|
-
}
|
1042
|
-
|
1043
1037
|
private groupingChanged(): void {
|
1044
1038
|
this.reset(true);
|
1045
1039
|
this.initGrouping();
|
1046
1040
|
// Reset the workspace to repopulate filesystem folders.
|
1047
|
-
this.onGroupingChanged();
|
1048
1041
|
this.resetWorkspace(Workspace.Workspace.WorkspaceImpl.instance());
|
1049
1042
|
this.workspaceInternal.uiSourceCodes().forEach(this.addUISourceCode.bind(this));
|
1050
1043
|
}
|
@@ -317,16 +317,17 @@ export class OpenLinearMemoryInspector extends UI.Widget.VBox implements UI.Cont
|
|
317
317
|
if (target instanceof ObjectUI.ObjectPropertiesSection.ObjectPropertyTreeElement) {
|
318
318
|
if (target.property && target.property.value &&
|
319
319
|
LinearMemoryInspector.LinearMemoryInspectorController.isMemoryObjectProperty(target.property.value)) {
|
320
|
+
const expression = target.path();
|
320
321
|
contextMenu.debugSection().appendItem(
|
321
322
|
i18nString(UIStrings.revealInMemoryInspectorPanel),
|
322
|
-
this.openMemoryInspector.bind(this,
|
323
|
+
this.openMemoryInspector.bind(this, expression, target.property.value));
|
323
324
|
}
|
324
325
|
}
|
325
326
|
}
|
326
327
|
|
327
|
-
private async openMemoryInspector(
|
328
|
+
private async openMemoryInspector(expression: string, obj: SDK.RemoteObject.RemoteObject): Promise<void> {
|
328
329
|
const controller = LinearMemoryInspector.LinearMemoryInspectorController.LinearMemoryInspectorController.instance();
|
329
330
|
Host.userMetrics.linearMemoryInspectorRevealedFrom(Host.UserMetrics.LinearMemoryInspectorRevealedFrom.ContextMenu);
|
330
|
-
void controller.openInspectorView(obj,
|
331
|
+
void controller.openInspectorView(obj, /* address */ undefined, expression);
|
331
332
|
}
|
332
333
|
}
|
@@ -32,11 +32,9 @@ import * as Common from '../../core/common/common.js';
|
|
32
32
|
import * as Host from '../../core/host/host.js';
|
33
33
|
import * as i18n from '../../core/i18n/i18n.js';
|
34
34
|
import * as Platform from '../../core/platform/platform.js';
|
35
|
-
import * as Root from '../../core/root/root.js';
|
36
35
|
import * as SDK from '../../core/sdk/sdk.js';
|
37
36
|
import * as Persistence from '../../models/persistence/persistence.js';
|
38
37
|
import * as Workspace from '../../models/workspace/workspace.js';
|
39
|
-
import * as Feedback from '../../ui/components/panel_feedback/panel_feedback.js';
|
40
38
|
import * as UI from '../../ui/legacy/legacy.js';
|
41
39
|
import * as Snippets from '../snippets/snippets.js';
|
42
40
|
|
@@ -102,61 +100,26 @@ const UIStrings = {
|
|
102
100
|
*@description Text to save content as a specific file type
|
103
101
|
*/
|
104
102
|
saveAs: 'Save as...',
|
105
|
-
/**
|
106
|
-
*@description Description of the new experimental Authored/Deployed view
|
107
|
-
*/
|
108
|
-
authoredDescription: 'Group files by Authored/Deployed',
|
109
103
|
};
|
110
104
|
const str_ = i18n.i18n.registerUIStrings('panels/sources/SourcesNavigator.ts', UIStrings);
|
111
105
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
112
106
|
let networkNavigatorViewInstance: NetworkNavigatorView;
|
113
107
|
|
114
108
|
export class NetworkNavigatorView extends NavigatorView {
|
115
|
-
private previewToggle: Feedback.PreviewToggle.PreviewToggle;
|
116
109
|
private constructor() {
|
117
110
|
super(true);
|
118
111
|
SDK.TargetManager.TargetManager.instance().addEventListener(
|
119
112
|
SDK.TargetManager.Events.InspectedURLChanged, this.inspectedURLChanged, this);
|
120
113
|
|
121
|
-
this.previewToggle = new Feedback.PreviewToggle.PreviewToggle();
|
122
|
-
this.onGroupingChanged();
|
123
|
-
|
124
|
-
const div = UI.Fragment.html`<div class="border-container"></div>`;
|
125
|
-
div.append(this.previewToggle);
|
126
|
-
this.contentElement.prepend(div);
|
127
|
-
|
128
114
|
// Record the sources tool load time after the file navigator has loaded.
|
129
115
|
Host.userMetrics.panelLoaded('sources', 'DevTools.Launch.Sources');
|
130
116
|
}
|
131
117
|
|
132
|
-
onGroupingChanged(): void {
|
133
|
-
// Setting the data will re-render it.
|
134
|
-
this.previewToggle.data = {
|
135
|
-
name: i18nString(UIStrings.authoredDescription),
|
136
|
-
helperText: null,
|
137
|
-
experiment: Root.Runtime.ExperimentName.AUTHORED_DEPLOYED_GROUPING,
|
138
|
-
learnMoreURL: 'https://goo.gle/authored-deployed',
|
139
|
-
feedbackURL: 'https://goo.gle/authored-deployed-feedback',
|
140
|
-
onChangeCallback: this.onAuthoredDeployedChanged,
|
141
|
-
};
|
142
|
-
}
|
143
|
-
|
144
118
|
wasShown(): void {
|
145
119
|
this.registerCSSFiles([sourcesNavigatorStyles]);
|
146
120
|
super.wasShown();
|
147
121
|
}
|
148
122
|
|
149
|
-
private onAuthoredDeployedChanged(checked: boolean): void {
|
150
|
-
Host.userMetrics.experimentChanged(Root.Runtime.ExperimentName.AUTHORED_DEPLOYED_GROUPING, checked);
|
151
|
-
// Need to signal to the NavigatorView that grouping has changed. Unfortunately,
|
152
|
-
// it can't listen to an experiment, and this class doesn't directly interact
|
153
|
-
// with it, so we will convince it a different grouping setting changed. When we switch
|
154
|
-
// from using an experiment to a setting, it will listen to that setting and we
|
155
|
-
// won't need to do this.
|
156
|
-
const groupByFolderSetting = Common.Settings.Settings.instance().moduleSetting('navigatorGroupByFolder');
|
157
|
-
groupByFolderSetting.set(groupByFolderSetting.get());
|
158
|
-
}
|
159
|
-
|
160
123
|
static instance(opts: {
|
161
124
|
forceNew: boolean|null,
|
162
125
|
} = {forceNew: null}): NetworkNavigatorView {
|
@@ -112,6 +112,10 @@ const UIStrings = {
|
|
112
112
|
*/
|
113
113
|
groupByAuthored: 'Group by Authored/Deployed',
|
114
114
|
/**
|
115
|
+
*@description Text in Sources Panel of the Sources panel
|
116
|
+
*/
|
117
|
+
hideIgnoreListed: 'Hide ignore-listed sources',
|
118
|
+
/**
|
115
119
|
*@description Text for pausing the debugger on exceptions
|
116
120
|
*/
|
117
121
|
pauseOnExceptions: 'Pause on exceptions',
|
@@ -563,36 +567,44 @@ export class SourcesPanel extends UI.Panel.Panel implements UI.ContextMenu.Provi
|
|
563
567
|
}
|
564
568
|
}
|
565
569
|
|
566
|
-
private
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
570
|
+
private addExperimentMenuItem(
|
571
|
+
menuSection: UI.ContextMenu.Section, experiment: string, menuItem: Common.UIString.LocalizedString): void {
|
572
|
+
// menu handler
|
573
|
+
function toggleExperiment(): void {
|
574
|
+
const checked = Root.Runtime.experiments.isEnabled(experiment);
|
575
|
+
Root.Runtime.experiments.setEnabled(experiment, !checked);
|
576
|
+
Host.userMetrics.experimentChanged(experiment, checked);
|
577
|
+
// Need to signal to the NavigatorView that grouping has changed. Unfortunately,
|
578
|
+
// it can't listen to an experiment, and this class doesn't directly interact
|
579
|
+
// with it, so we will convince it a different grouping setting changed. When we switch
|
580
|
+
// from using an experiment to a setting, it will listen to that setting and we
|
581
|
+
// won't need to do this.
|
582
|
+
const groupByFolderSetting = Common.Settings.Settings.instance().moduleSetting('navigatorGroupByFolder');
|
583
|
+
groupByFolderSetting.set(groupByFolderSetting.get());
|
584
|
+
}
|
579
585
|
|
580
|
-
private populateNavigatorMenu(contextMenu: UI.ContextMenu.ContextMenu): void {
|
581
|
-
const groupByFolderSetting = Common.Settings.Settings.instance().moduleSetting('navigatorGroupByFolder');
|
582
|
-
contextMenu.appendItemsAtLocation('navigatorMenu');
|
583
|
-
contextMenu.viewSection().appendCheckboxItem(
|
584
|
-
i18nString(UIStrings.groupByFolder), () => groupByFolderSetting.set(!groupByFolderSetting.get()),
|
585
|
-
groupByFolderSetting.get());
|
586
586
|
const previewIcon = new IconButton.Icon.Icon();
|
587
|
-
const experiment = Root.Runtime.ExperimentName.AUTHORED_DEPLOYED_GROUPING;
|
588
587
|
previewIcon.data = {
|
589
588
|
iconName: 'ic_preview_feature',
|
590
589
|
color: 'var(--icon-color)',
|
591
590
|
width: '14px',
|
592
591
|
};
|
592
|
+
menuSection.appendCheckboxItem(
|
593
|
+
menuItem, toggleExperiment, Root.Runtime.experiments.isEnabled(experiment), false, previewIcon);
|
594
|
+
}
|
595
|
+
|
596
|
+
private populateNavigatorMenu(contextMenu: UI.ContextMenu.ContextMenu): void {
|
597
|
+
const groupByFolderSetting = Common.Settings.Settings.instance().moduleSetting('navigatorGroupByFolder');
|
598
|
+
contextMenu.appendItemsAtLocation('navigatorMenu');
|
593
599
|
contextMenu.viewSection().appendCheckboxItem(
|
594
|
-
i18nString(UIStrings.
|
595
|
-
|
600
|
+
i18nString(UIStrings.groupByFolder), () => groupByFolderSetting.set(!groupByFolderSetting.get()),
|
601
|
+
groupByFolderSetting.get());
|
602
|
+
|
603
|
+
this.addExperimentMenuItem(
|
604
|
+
contextMenu.viewSection(), Root.Runtime.ExperimentName.AUTHORED_DEPLOYED_GROUPING,
|
605
|
+
i18nString(UIStrings.groupByAuthored));
|
606
|
+
this.addExperimentMenuItem(
|
607
|
+
contextMenu.viewSection(), Root.Runtime.ExperimentName.JUST_MY_CODE, i18nString(UIStrings.hideIgnoreListed));
|
596
608
|
}
|
597
609
|
|
598
610
|
setIgnoreExecutionLineEvents(ignoreExecutionLineEvents: boolean): void {
|
@@ -0,0 +1,206 @@
|
|
1
|
+
// Copyright (c) 2022 The Chromium Authors. All rights reserved.
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
3
|
+
// found in the LICENSE file.
|
4
|
+
|
5
|
+
import * as i18n from '../../../core/i18n/i18n.js';
|
6
|
+
import * as Platform from '../../../core/platform/platform.js';
|
7
|
+
import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
|
8
|
+
import * as IconButton from '../../../ui/components/icon_button/icon_button.js';
|
9
|
+
import * as LitHtml from '../../../ui/lit-html/lit-html.js';
|
10
|
+
|
11
|
+
import breakpointsViewStyles from './breakpointsView.css.js';
|
12
|
+
|
13
|
+
const UIStrings = {
|
14
|
+
/**
|
15
|
+
*@description Text exposed to screen readers on checked items.
|
16
|
+
*/
|
17
|
+
checked: 'checked',
|
18
|
+
/**
|
19
|
+
*@description Accessible text exposed to screen readers when the screen reader encounters an unchecked checkbox.
|
20
|
+
*/
|
21
|
+
unchecked: 'unchecked',
|
22
|
+
/**
|
23
|
+
*@description Accessible text for a breakpoint collection with a combination of checked states.
|
24
|
+
*/
|
25
|
+
indeterminate: 'mixed',
|
26
|
+
/**
|
27
|
+
*@description Accessibility label for hit breakpoints in the Sources panel.
|
28
|
+
*@example {checked} PH1
|
29
|
+
*/
|
30
|
+
breakpointHit: '{PH1} breakpoint hit',
|
31
|
+
|
32
|
+
};
|
33
|
+
const str_ = i18n.i18n.registerUIStrings('panels/sources/components/BreakpointsView.ts', UIStrings);
|
34
|
+
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
35
|
+
|
36
|
+
const MAX_SNIPPET_LENGTH = 200;
|
37
|
+
|
38
|
+
export interface BreakpointsViewData {
|
39
|
+
groups: BreakpointGroup[];
|
40
|
+
}
|
41
|
+
|
42
|
+
export interface BreakpointGroup {
|
43
|
+
name: string;
|
44
|
+
url: Platform.DevToolsPath.UrlString;
|
45
|
+
expanded: boolean;
|
46
|
+
breakpointItems: BreakpointItem[];
|
47
|
+
}
|
48
|
+
|
49
|
+
export interface BreakpointItem {
|
50
|
+
location: string;
|
51
|
+
codeSnippet: string;
|
52
|
+
isHit: boolean;
|
53
|
+
status: BreakpointStatus;
|
54
|
+
hoverText?: string;
|
55
|
+
}
|
56
|
+
|
57
|
+
export const enum BreakpointStatus {
|
58
|
+
ENABLED = 'ENABLED',
|
59
|
+
DISABLED = 'DISABLED',
|
60
|
+
INDETERMINATE = 'INDETERMINATE',
|
61
|
+
}
|
62
|
+
|
63
|
+
export class CheckboxToggledEvent extends Event {
|
64
|
+
static readonly eventName = 'checkboxtoggled';
|
65
|
+
data: {breakpointItem: BreakpointItem, checked: boolean};
|
66
|
+
|
67
|
+
constructor(breakpointItem: BreakpointItem, checked: boolean) {
|
68
|
+
super(CheckboxToggledEvent.eventName);
|
69
|
+
this.data = {breakpointItem: breakpointItem, checked};
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
export class ExpandedStateChangedEvent extends Event {
|
74
|
+
static readonly eventName = 'expandedstatechanged';
|
75
|
+
data: {url: Platform.DevToolsPath.UrlString, expanded: boolean};
|
76
|
+
|
77
|
+
constructor(url: Platform.DevToolsPath.UrlString, expanded: boolean) {
|
78
|
+
super(ExpandedStateChangedEvent.eventName);
|
79
|
+
this.data = {url, expanded};
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
export class BreakpointSelectedEvent extends Event {
|
84
|
+
static readonly eventName = 'breakpointselected';
|
85
|
+
data: {breakpointItem: BreakpointItem};
|
86
|
+
|
87
|
+
constructor(breakpointItem: BreakpointItem) {
|
88
|
+
super(BreakpointSelectedEvent.eventName);
|
89
|
+
this.data = {breakpointItem: breakpointItem};
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
export class BreakpointsView extends HTMLElement {
|
94
|
+
static readonly litTagName = LitHtml.literal`devtools-breakpoint-view`;
|
95
|
+
readonly #shadow = this.attachShadow({mode: 'open'});
|
96
|
+
readonly #boundRender = this.#render.bind(this);
|
97
|
+
|
98
|
+
#breakpointGroups: BreakpointGroup[] = [];
|
99
|
+
|
100
|
+
set data(data: BreakpointsViewData) {
|
101
|
+
this.#breakpointGroups = data.groups;
|
102
|
+
void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
|
103
|
+
}
|
104
|
+
|
105
|
+
connectedCallback(): void {
|
106
|
+
this.#shadow.adoptedStyleSheets = [breakpointsViewStyles];
|
107
|
+
void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
|
108
|
+
}
|
109
|
+
|
110
|
+
#render(): void {
|
111
|
+
const renderedGroups = this.#breakpointGroups.map((group, index) => {
|
112
|
+
const out = this.#renderBreakpointGroup(group);
|
113
|
+
if (index === this.#breakpointGroups.length - 1) {
|
114
|
+
return out;
|
115
|
+
}
|
116
|
+
return LitHtml.html`${out}<div class='divider'></div>`;
|
117
|
+
});
|
118
|
+
LitHtml.render(LitHtml.html`${renderedGroups}`, this.#shadow, {host: this});
|
119
|
+
}
|
120
|
+
|
121
|
+
#renderBreakpointGroup(group: BreakpointGroup): LitHtml.TemplateResult {
|
122
|
+
const groupClassMap = {
|
123
|
+
'expanded': group.expanded,
|
124
|
+
};
|
125
|
+
// clang-format off
|
126
|
+
return LitHtml.html`
|
127
|
+
<div data-group='true' class=${LitHtml.Directives.classMap(groupClassMap)}>
|
128
|
+
<div class='group-header' @click=${(): void => this.#onGroupExpandToggled(group)}>
|
129
|
+
<span class='triangle'></span>
|
130
|
+
${this.#renderFileIcon()}
|
131
|
+
<span class='group-header-title'>${group.name}</span>
|
132
|
+
</div>
|
133
|
+
${group.expanded? LitHtml.html`
|
134
|
+
${group.breakpointItems.map(entry => this.#renderBreakpointEntry(entry))}` : LitHtml.nothing}
|
135
|
+
</div>
|
136
|
+
`;
|
137
|
+
// clang-format on
|
138
|
+
}
|
139
|
+
|
140
|
+
#renderFileIcon(): LitHtml.TemplateResult {
|
141
|
+
return LitHtml.html`
|
142
|
+
<${IconButton.Icon.Icon.litTagName} .data=${
|
143
|
+
{iconName: 'ic_file_script', color: 'var(--color-ic-file-script)', width: '16px', height: '16px'} as
|
144
|
+
IconButton.Icon.IconWithName}></${IconButton.Icon.Icon.litTagName}>
|
145
|
+
`;
|
146
|
+
}
|
147
|
+
|
148
|
+
#renderBreakpointEntry(breakpointItem: BreakpointItem): LitHtml.TemplateResult {
|
149
|
+
const classMap = {
|
150
|
+
'breakpoint-item': true,
|
151
|
+
'hit': breakpointItem.isHit,
|
152
|
+
};
|
153
|
+
const breakpointItemDescription = this.#getBreakpointItemDescription(breakpointItem);
|
154
|
+
const codeSnippet = Platform.StringUtilities.trimEndWithMaxLength(breakpointItem.codeSnippet, MAX_SNIPPET_LENGTH);
|
155
|
+
|
156
|
+
// clang-format off
|
157
|
+
return LitHtml.html`
|
158
|
+
<div class=${LitHtml.Directives.classMap(classMap)} aria-label=${breakpointItemDescription} tabIndex=${breakpointItem.isHit ? 0 : 1}>
|
159
|
+
<label class='checkbox-label'>
|
160
|
+
<input type='checkbox' aria-label=${breakpointItem.location} ?indeterminate=${breakpointItem.status === BreakpointStatus.INDETERMINATE} ?checked=${breakpointItem.status === BreakpointStatus.ENABLED} @change=${(e: Event): void => this.#onCheckboxToggled(e, breakpointItem)}>
|
161
|
+
</label>
|
162
|
+
<span class='code-snippet' @click=${():void => {this.dispatchEvent(new BreakpointSelectedEvent(breakpointItem));}}>${codeSnippet}</span>
|
163
|
+
<span class='location'>${breakpointItem.location}</span>
|
164
|
+
</div>
|
165
|
+
`;
|
166
|
+
// clang-format on
|
167
|
+
}
|
168
|
+
|
169
|
+
#getBreakpointItemDescription(breakpointItem: BreakpointItem): Platform.UIString.LocalizedString {
|
170
|
+
let checkboxDescription;
|
171
|
+
switch (breakpointItem.status) {
|
172
|
+
case BreakpointStatus.ENABLED:
|
173
|
+
checkboxDescription = i18nString(UIStrings.checked);
|
174
|
+
break;
|
175
|
+
case BreakpointStatus.DISABLED:
|
176
|
+
checkboxDescription = i18nString(UIStrings.unchecked);
|
177
|
+
break;
|
178
|
+
case BreakpointStatus.INDETERMINATE:
|
179
|
+
checkboxDescription = i18nString(UIStrings.indeterminate);
|
180
|
+
break;
|
181
|
+
}
|
182
|
+
if (!breakpointItem.isHit) {
|
183
|
+
return checkboxDescription;
|
184
|
+
}
|
185
|
+
return i18nString(UIStrings.breakpointHit, {PH1: checkboxDescription});
|
186
|
+
}
|
187
|
+
|
188
|
+
#onGroupExpandToggled(group: BreakpointGroup): void {
|
189
|
+
group.expanded = !group.expanded;
|
190
|
+
this.dispatchEvent(new ExpandedStateChangedEvent(group.url, group.expanded));
|
191
|
+
void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
|
192
|
+
}
|
193
|
+
|
194
|
+
#onCheckboxToggled(e: Event, item: BreakpointItem): void {
|
195
|
+
const element = e.target as HTMLInputElement;
|
196
|
+
this.dispatchEvent(new CheckboxToggledEvent(item, element.checked));
|
197
|
+
}
|
198
|
+
}
|
199
|
+
|
200
|
+
ComponentHelpers.CustomElements.defineComponent('devtools-breakpoint-view', BreakpointsView);
|
201
|
+
|
202
|
+
declare global {
|
203
|
+
interface HTMLElementTagNameMap {
|
204
|
+
'devtools-breakpoint-view': BreakpointsView;
|
205
|
+
}
|
206
|
+
}
|
@@ -9,6 +9,7 @@ import * as Buttons from '../../../ui/components/buttons/buttons.js';
|
|
9
9
|
import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
|
10
10
|
import * as UI from '../../../ui/legacy/legacy.js';
|
11
11
|
import * as LitHtml from '../../../ui/lit-html/lit-html.js';
|
12
|
+
import type * as Protocol from '../../../generated/protocol.js';
|
12
13
|
|
13
14
|
import HeadersViewStyles from './HeadersView.css.js';
|
14
15
|
|
@@ -81,23 +82,8 @@ export class HeadersView extends UI.View.SimpleView {
|
|
81
82
|
parsingError = true;
|
82
83
|
}
|
83
84
|
|
84
|
-
// Header overrides are stored as the key-value pairs of a JSON object on
|
85
|
-
// disk. For the editor we want them as an array instead, so that we can
|
86
|
-
// access/add/remove entries by their index.
|
87
|
-
const arrayOfHeaderOverrideArrays: HeaderOverride[] = headerOverrides.map(headerOverride => {
|
88
|
-
return {
|
89
|
-
applyTo: headerOverride.applyTo,
|
90
|
-
headers: Object.entries(headerOverride.headers).map(([headerName, headerValue]) => {
|
91
|
-
return {
|
92
|
-
name: headerName,
|
93
|
-
value: headerValue,
|
94
|
-
};
|
95
|
-
}),
|
96
|
-
};
|
97
|
-
});
|
98
|
-
|
99
85
|
this.#headersViewComponent.data = {
|
100
|
-
headerOverrides
|
86
|
+
headerOverrides,
|
101
87
|
uiSourceCode: this.#uiSourceCode,
|
102
88
|
parsingError,
|
103
89
|
};
|
@@ -128,18 +114,8 @@ export class HeadersView extends UI.View.SimpleView {
|
|
128
114
|
}
|
129
115
|
}
|
130
116
|
|
131
|
-
type Header = {
|
132
|
-
name: string,
|
133
|
-
value: string,
|
134
|
-
};
|
135
|
-
|
136
|
-
type HeaderOverride = {
|
137
|
-
applyTo: string,
|
138
|
-
headers: Header[],
|
139
|
-
};
|
140
|
-
|
141
117
|
export interface HeadersViewComponentData {
|
142
|
-
headerOverrides: HeaderOverride[];
|
118
|
+
headerOverrides: Persistence.NetworkPersistenceManager.HeaderOverride[];
|
143
119
|
uiSourceCode: Workspace.UISourceCode.UISourceCode;
|
144
120
|
parsingError: boolean;
|
145
121
|
}
|
@@ -148,7 +124,7 @@ export class HeadersViewComponent extends HTMLElement {
|
|
148
124
|
static readonly litTagName = LitHtml.literal`devtools-sources-headers-view`;
|
149
125
|
readonly #shadow = this.attachShadow({mode: 'open'});
|
150
126
|
readonly #boundRender = this.#render.bind(this);
|
151
|
-
#headerOverrides: HeaderOverride[] = [];
|
127
|
+
#headerOverrides: Persistence.NetworkPersistenceManager.HeaderOverride[] = [];
|
152
128
|
#uiSourceCode: Workspace.UISourceCode.UISourceCode|null = null;
|
153
129
|
#parsingError = false;
|
154
130
|
#focusElement: {blockIndex: number, headerIndex?: number}|null = null;
|
@@ -213,7 +189,7 @@ export class HeadersViewComponent extends HTMLElement {
|
|
213
189
|
selection?.removeAllRanges();
|
214
190
|
}
|
215
191
|
|
216
|
-
#generateNextHeaderName(headers:
|
192
|
+
#generateNextHeaderName(headers: Protocol.Fetch.HeaderEntry[]): string {
|
217
193
|
const takenNames = new Set<string>(headers.map(header => header.name));
|
218
194
|
let idx = 1;
|
219
195
|
while (takenNames.has('headerName' + idx)) {
|
@@ -270,17 +246,7 @@ export class HeadersViewComponent extends HTMLElement {
|
|
270
246
|
}
|
271
247
|
|
272
248
|
#onHeadersChanged(): void {
|
273
|
-
|
274
|
-
// that we can access/add/remove entries by their index. On disk, they are
|
275
|
-
// stored as key-value pairs of a JSON object instead.
|
276
|
-
const arrayOfHeaderOverrideObjects: Persistence.NetworkPersistenceManager.HeaderOverride[] =
|
277
|
-
this.#headerOverrides.map(headerOverride => {
|
278
|
-
return {
|
279
|
-
applyTo: headerOverride.applyTo,
|
280
|
-
headers: headerOverride.headers.reduce((a, v) => ({...a, [v.name]: v.value}), {}),
|
281
|
-
};
|
282
|
-
});
|
283
|
-
this.#uiSourceCode?.setWorkingCopy(JSON.stringify(arrayOfHeaderOverrideObjects, null, 2));
|
249
|
+
this.#uiSourceCode?.setWorkingCopy(JSON.stringify(this.#headerOverrides, null, 2));
|
284
250
|
}
|
285
251
|
|
286
252
|
#render(): void {
|
@@ -355,7 +321,8 @@ export class HeadersViewComponent extends HTMLElement {
|
|
355
321
|
// clang-format on
|
356
322
|
}
|
357
323
|
|
358
|
-
#renderHeaderRow(header:
|
324
|
+
#renderHeaderRow(header: Protocol.Fetch.HeaderEntry, blockIndex: number, headerIndex: number):
|
325
|
+
LitHtml.TemplateResult {
|
359
326
|
// clang-format off
|
360
327
|
return LitHtml.html`
|
361
328
|
<div class="row padded" data-block-index=${blockIndex} data-header-index=${headerIndex}>
|
@@ -0,0 +1,95 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2022 The Chromium Authors. All rights reserved.
|
3
|
+
* Use of this source code is governed by a BSD-style license that can be
|
4
|
+
* found in the LICENSE file.
|
5
|
+
*/
|
6
|
+
|
7
|
+
:host {
|
8
|
+
flex: auto;
|
9
|
+
display: flex;
|
10
|
+
flex-direction: column;
|
11
|
+
}
|
12
|
+
|
13
|
+
.divider {
|
14
|
+
height: 1px;
|
15
|
+
width: inherit;
|
16
|
+
background-color: var(--color-details-hairline);
|
17
|
+
}
|
18
|
+
|
19
|
+
.code-snippet {
|
20
|
+
width: 100%;
|
21
|
+
padding-left: 6px;
|
22
|
+
font-family: var(--source-code-font-family);
|
23
|
+
font-size: var(--source-code-font-size);
|
24
|
+
color: var(--color-text-secondary);
|
25
|
+
text-overflow: ellipsis;
|
26
|
+
overflow: hidden;
|
27
|
+
white-space: nowrap;
|
28
|
+
flex-shrink: 100;
|
29
|
+
}
|
30
|
+
|
31
|
+
input {
|
32
|
+
height: 12px;
|
33
|
+
width: 12px;
|
34
|
+
flex-shrink: 0;
|
35
|
+
margin: 3px 0;
|
36
|
+
}
|
37
|
+
|
38
|
+
.triangle {
|
39
|
+
margin-left: 6px;
|
40
|
+
margin-right: 4px;
|
41
|
+
display: inline-block;
|
42
|
+
-webkit-mask-image: var(--image-file-treeoutlineTriangles);
|
43
|
+
-webkit-mask-size: 32px 24px;
|
44
|
+
-webkit-mask-position: 0 0;
|
45
|
+
background-color: var(--color-text-primary);
|
46
|
+
height: 12px;
|
47
|
+
width: 8px;
|
48
|
+
}
|
49
|
+
|
50
|
+
.group-header {
|
51
|
+
display: flex;
|
52
|
+
align-items: center;
|
53
|
+
height: 18px;
|
54
|
+
}
|
55
|
+
|
56
|
+
.expanded > .group-header > .triangle {
|
57
|
+
-webkit-mask-position: -16px 0;
|
58
|
+
}
|
59
|
+
|
60
|
+
.group-header-title {
|
61
|
+
margin-left: 4px;
|
62
|
+
font-weight: 500;
|
63
|
+
font-size: var(--source-code-font-size);
|
64
|
+
text-overflow: ellipsis;
|
65
|
+
overflow: hidden;
|
66
|
+
white-space: nowrap;
|
67
|
+
}
|
68
|
+
|
69
|
+
.breakpoint-item {
|
70
|
+
display: flex;
|
71
|
+
align-items: center;
|
72
|
+
line-height: 13px;
|
73
|
+
height: 18px;
|
74
|
+
}
|
75
|
+
|
76
|
+
.breakpoint-item:hover {
|
77
|
+
background-color: var(--color-background-elevation-1);
|
78
|
+
}
|
79
|
+
|
80
|
+
.breakpoint-item.hit {
|
81
|
+
--override-breakpoint-hit-background: rgb(255 255 194);
|
82
|
+
|
83
|
+
background-color: var(--override-breakpoint-hit-background);
|
84
|
+
}
|
85
|
+
|
86
|
+
.checkbox-label {
|
87
|
+
padding-left: 24px;
|
88
|
+
display: flex;
|
89
|
+
align-items: center;
|
90
|
+
}
|
91
|
+
|
92
|
+
.location {
|
93
|
+
line-height: 14px;
|
94
|
+
margin: 0 8px;
|
95
|
+
}
|
@@ -2,8 +2,10 @@
|
|
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 BreakpointsView from './BreakpointsView.js';
|
5
6
|
import * as HeadersView from './HeadersView.js';
|
6
7
|
|
7
8
|
export {
|
9
|
+
BreakpointsView,
|
8
10
|
HeadersView,
|
9
11
|
};
|
@@ -95,15 +95,17 @@ export class LinearMemoryHighlightChipList extends HTMLElement {
|
|
95
95
|
<span class="value">${expressionName}</span><span class="separator">: </span><span>${expressionType}</span>
|
96
96
|
</span>
|
97
97
|
</button>
|
98
|
-
<
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
98
|
+
<div class="delete-highlight-container">
|
99
|
+
<button class="delete-highlight-button" title=${
|
100
|
+
i18nString(UIStrings.deleteHighlight)} @click=${():void => this.#onDeleteHighlightClick(highlightInfo)}>
|
101
|
+
<${IconButton.Icon.Icon.litTagName} .data=${{
|
102
|
+
iconName: 'close-icon',
|
103
|
+
color: 'var(--color-text-primary)',
|
104
|
+
width: '7px',
|
105
|
+
} as IconButton.Icon.IconData}>
|
106
|
+
</${IconButton.Icon.Icon.litTagName}>
|
107
|
+
</button>
|
108
|
+
</div>
|
107
109
|
</div>
|
108
110
|
`;
|
109
111
|
// clang-format off
|