chrome-devtools-frontend 1.0.1589336 → 1.0.1590494
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/front_end/core/common/Settings.ts +30 -1
- package/front_end/generated/Deprecation.ts +7 -0
- package/front_end/generated/InspectorBackendCommands.ts +9 -3
- package/front_end/generated/protocol-mapping.d.ts +9 -0
- package/front_end/generated/protocol-proxy-api.d.ts +7 -0
- package/front_end/generated/protocol.ts +98 -0
- package/front_end/models/javascript_metadata/NativeFunctions.js +48 -0
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +140 -32
- package/front_end/panels/ai_assistance/README.md +71 -0
- package/front_end/panels/ai_assistance/aiAssistancePanel.css +5 -0
- package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +110 -7
- package/front_end/panels/ai_assistance/components/ChatView.ts +10 -0
- package/front_end/panels/ai_assistance/components/WalkthroughView.ts +208 -0
- package/front_end/panels/ai_assistance/components/chatMessage.css +2 -2
- package/front_end/panels/ai_assistance/components/walkthroughView.css +121 -0
- package/front_end/panels/application/DeviceBoundSessionsView.ts +64 -2
- package/front_end/panels/console/ConsoleView.ts +8 -8
- package/front_end/panels/console/console-meta.ts +10 -6
- package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +14 -14
- package/front_end/panels/elements/ComputedStyleWidget.ts +27 -22
- package/front_end/panels/elements/ElementsTreeElement.ts +56 -2
- package/front_end/panels/elements/ElementsTreeOutline.ts +2 -0
- package/front_end/panels/elements/StyleEditorWidget.ts +12 -12
- package/front_end/panels/elements/StylePropertiesSection.ts +65 -64
- package/front_end/panels/elements/StylePropertyTreeElement.ts +138 -135
- package/front_end/panels/elements/StylesContainer.ts +57 -0
- package/front_end/panels/elements/StylesSidebarPane.ts +2 -1
- package/front_end/panels/layer_viewer/Layers3DView.ts +2 -2
- package/front_end/panels/network/RequestInitiatorView.ts +3 -2
- package/front_end/panels/timeline/timeline-meta.ts +4 -4
- package/front_end/panels/whats_new/ReleaseNoteText.ts +10 -16
- package/front_end/panels/whats_new/resources/WNDT.md +6 -6
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/markdown_view/MarkdownView.ts +5 -6
- package/front_end/ui/components/markdown_view/markdownView.css +6 -0
- package/front_end/ui/components/markdown_view/markdown_view.ts +0 -2
- package/front_end/ui/legacy/Treeoutline.ts +58 -10
- package/front_end/ui/legacy/Widget.ts +11 -1
- package/front_end/ui/legacy/inspectorCommon.css +2 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +11 -1
- package/package.json +1 -1
- package/front_end/ui/components/markdown_view/MarkdownLink.ts +0 -53
- package/front_end/ui/components/markdown_view/markdownLink.css +0 -11
|
@@ -93,21 +93,6 @@ const UIStrings = {
|
|
|
93
93
|
const str_ = i18n.i18n.registerUIStrings('panels/elements/ComputedStyleWidget.ts', UIStrings);
|
|
94
94
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
95
95
|
|
|
96
|
-
/**
|
|
97
|
-
* Rendering a property's name and value is expensive, and each time we do it
|
|
98
|
-
* it generates a new HTML element. If we call this directly from our Lit
|
|
99
|
-
* components, we will generate a brand new DOM element on each single render.
|
|
100
|
-
* This is very expensive and unnecessary - for the majority of re-renders a
|
|
101
|
-
* property's name and value does not change. So we cache the rest of rendering
|
|
102
|
-
* the name and value in a map, where the key used is a combination of the
|
|
103
|
-
* property's name and value. This ensures that we only re-generate this element
|
|
104
|
-
* if the node itself changes.
|
|
105
|
-
* The resulting Element nodes are inserted into the ComputedStyleProperty
|
|
106
|
-
* component via <slot>s, ensuring that Lit doesn't directly render/re-render
|
|
107
|
-
* the element.
|
|
108
|
-
*/
|
|
109
|
-
const propertyContentsCache = new Map<string, {name: Element, value: Element}>();
|
|
110
|
-
|
|
111
96
|
function matchProperty(name: string, value: string): SDK.CSSPropertyParser.BottomUpTreeMatching|null {
|
|
112
97
|
return SDK.CSSPropertyParser.matchDeclaration(name, value, [
|
|
113
98
|
new SDK.CSSPropertyParserMatchers.ColorMatcher(), new SDK.CSSPropertyParserMatchers.URLMatcher(),
|
|
@@ -116,9 +101,10 @@ function matchProperty(name: string, value: string): SDK.CSSPropertyParser.Botto
|
|
|
116
101
|
}
|
|
117
102
|
|
|
118
103
|
function renderPropertyContents(
|
|
119
|
-
node: SDK.DOMModel.DOMNode,
|
|
104
|
+
node: SDK.DOMModel.DOMNode, cache: Map<string, {name: Element, value: Element}>, propertyName: string,
|
|
105
|
+
propertyValue: string): {name: Element, value: Element} {
|
|
120
106
|
const cacheKey = propertyName + ':' + propertyValue;
|
|
121
|
-
const valueFromCache =
|
|
107
|
+
const valueFromCache = cache.get(cacheKey);
|
|
122
108
|
if (valueFromCache) {
|
|
123
109
|
return valueFromCache;
|
|
124
110
|
}
|
|
@@ -130,7 +116,7 @@ function renderPropertyContents(
|
|
|
130
116
|
[new ColorRenderer(), new URLRenderer(null, node), new StringRenderer()])
|
|
131
117
|
.valueElement;
|
|
132
118
|
value.slot = 'value';
|
|
133
|
-
|
|
119
|
+
cache.set(cacheKey, {name, value});
|
|
134
120
|
return {name, value};
|
|
135
121
|
}
|
|
136
122
|
|
|
@@ -139,10 +125,11 @@ function renderPropertyContents(
|
|
|
139
125
|
* to ensure nothing expensive runs here, or if it does it is safely cached.
|
|
140
126
|
**/
|
|
141
127
|
const createPropertyElement =
|
|
142
|
-
(node: SDK.DOMModel.DOMNode,
|
|
128
|
+
(node: SDK.DOMModel.DOMNode, cache: Map<string, {name: Element, value: Element}>, propertyName: string,
|
|
129
|
+
propertyValue: string, traceable: boolean, inherited: boolean,
|
|
143
130
|
activeProperty: SDK.CSSProperty.CSSProperty|undefined,
|
|
144
131
|
onContextMenu: ((event: Event) => void)): Lit.TemplateResult => {
|
|
145
|
-
const {name, value} = renderPropertyContents(node, propertyName, propertyValue);
|
|
132
|
+
const {name, value} = renderPropertyContents(node, cache, propertyName, propertyValue);
|
|
146
133
|
// clang-format off
|
|
147
134
|
return html`<devtools-computed-style-property
|
|
148
135
|
.traceable=${traceable}
|
|
@@ -315,6 +302,24 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
|
|
|
315
302
|
private filterRegex: RegExp|null;
|
|
316
303
|
private readonly linkifier: Components.Linkifier.Linkifier;
|
|
317
304
|
private readonly imagePreviewPopover: ImagePreviewPopover;
|
|
305
|
+
/**
|
|
306
|
+
* Rendering a property's name and value is expensive, and each time we do it
|
|
307
|
+
* it generates a new HTML element. If we call this directly from our Lit
|
|
308
|
+
* components, we will generate a brand new DOM element on each single render.
|
|
309
|
+
* This is very expensive and unnecessary - for the majority of re-renders a
|
|
310
|
+
* property's name and value does not change. So we cache the rest of rendering
|
|
311
|
+
* the name and value in a map, where the key used is a combination of the
|
|
312
|
+
* property's name and value. This ensures that we only re-generate this element
|
|
313
|
+
* if the node itself changes.
|
|
314
|
+
* The resulting Element nodes are inserted into the ComputedStyleProperty
|
|
315
|
+
* component via <slot>s, ensuring that Lit doesn't directly render/re-render
|
|
316
|
+
* the element.
|
|
317
|
+
* We have to store this cache per widget because it is possible to have
|
|
318
|
+
* multiple widgets for the same NodeId showing at once. In that case, if we
|
|
319
|
+
* reuse the same element from the cache, only one of the widgets will be
|
|
320
|
+
* populated, because an HTML node cannot be in two locations at once.
|
|
321
|
+
*/
|
|
322
|
+
#propertyElementsCache = new Map<string, {name: Element, value: Element}>();
|
|
318
323
|
|
|
319
324
|
#computedStylesTree = new TreeOutline.TreeOutline.TreeOutline<ComputedStyleData>();
|
|
320
325
|
#treeData?: TreeOutline.TreeOutline.TreeOutlineData<ComputedStyleData>;
|
|
@@ -559,8 +564,8 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
|
|
|
559
564
|
const activeProperty = trace?.find(
|
|
560
565
|
property => matchedStyles.propertyState(property) === SDK.CSSMatchedStyles.PropertyState.ACTIVE);
|
|
561
566
|
const propertyElement = createPropertyElement(
|
|
562
|
-
domNode,
|
|
563
|
-
activeProperty, event => {
|
|
567
|
+
domNode, this.#propertyElementsCache, data.propertyName, data.propertyValue,
|
|
568
|
+
propertyTraces.has(data.propertyName), data.inherited, activeProperty, event => {
|
|
564
569
|
if (activeProperty) {
|
|
565
570
|
this.handleContextMenuEvent(matchedStyles, activeProperty, event);
|
|
566
571
|
}
|
|
@@ -113,6 +113,10 @@ const UIStrings = {
|
|
|
113
113
|
* @description A context menu item in the Elements Tree Element of the Elements panel
|
|
114
114
|
*/
|
|
115
115
|
editAsHtml: 'Edit as HTML',
|
|
116
|
+
/**
|
|
117
|
+
* @description A context menu item in the Elements Tree Element of the Elements panel
|
|
118
|
+
*/
|
|
119
|
+
editData: 'Edit data',
|
|
116
120
|
/**
|
|
117
121
|
* @description Text to cut an element, cut should be used as a verb
|
|
118
122
|
*/
|
|
@@ -628,6 +632,18 @@ function renderTitle(
|
|
|
628
632
|
Platform.StringUtilities.collapseWhitespace(node.nodeNameInCorrectCase())}</span>`;
|
|
629
633
|
}
|
|
630
634
|
|
|
635
|
+
case Node.PROCESSING_INSTRUCTION_NODE: {
|
|
636
|
+
const nodeValue = node.nodeValue();
|
|
637
|
+
const maybeSpace = nodeValue ? ' ' : '';
|
|
638
|
+
return html`<span class="webkit-html-processing-instruction"><?<span
|
|
639
|
+
class="webkit-html-tag-name" jslog=${VisualLogging.value('tag-name').track({change: true, dblclick: true})}>${
|
|
640
|
+
node.nodeName()}</span>${maybeSpace}<span class="webkit-html-processing-instruction-value" jslog=${
|
|
641
|
+
VisualLogging.value('processing-instruction-value').track({
|
|
642
|
+
change: true,
|
|
643
|
+
dblclick: true,
|
|
644
|
+
})}>${nodeValue}</span>?></span>`;
|
|
645
|
+
}
|
|
646
|
+
|
|
631
647
|
default: {
|
|
632
648
|
return html`${Platform.StringUtilities.collapseWhitespace(node.nodeNameInCorrectCase())}`;
|
|
633
649
|
}
|
|
@@ -1785,11 +1801,13 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1785
1801
|
return false;
|
|
1786
1802
|
}
|
|
1787
1803
|
|
|
1788
|
-
if (this.nodeInternal.nodeType() !== Node.ELEMENT_NODE && this.nodeInternal.nodeType() !== Node.TEXT_NODE
|
|
1804
|
+
if (this.nodeInternal.nodeType() !== Node.ELEMENT_NODE && this.nodeInternal.nodeType() !== Node.TEXT_NODE &&
|
|
1805
|
+
this.nodeInternal.nodeType() !== Node.PROCESSING_INSTRUCTION_NODE) {
|
|
1789
1806
|
return false;
|
|
1790
1807
|
}
|
|
1791
1808
|
|
|
1792
|
-
const textNode = eventTarget.enclosingNodeOrSelfWithClass('webkit-html-text-node')
|
|
1809
|
+
const textNode = eventTarget.enclosingNodeOrSelfWithClass('webkit-html-text-node') ??
|
|
1810
|
+
eventTarget.enclosingNodeOrSelfWithClass('webkit-html-processing-instruction-value');
|
|
1793
1811
|
if (textNode) {
|
|
1794
1812
|
return this.startEditingTextNode(textNode);
|
|
1795
1813
|
}
|
|
@@ -2127,6 +2145,24 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
2127
2145
|
}
|
|
2128
2146
|
}
|
|
2129
2147
|
|
|
2148
|
+
async populateProcessingElementContextMenu(contextMenu: UI.ContextMenu.ContextMenu): Promise<void> {
|
|
2149
|
+
const treeOutline = this.treeOutline;
|
|
2150
|
+
if (!treeOutline) {
|
|
2151
|
+
return;
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
contextMenu.editSection().appendItem(
|
|
2155
|
+
i18nString(UIStrings.editData), this.startEditingProcessingInstructionValue.bind(this),
|
|
2156
|
+
{jslogContext: 'elements.edit-data'});
|
|
2157
|
+
contextMenu.editSection().appendItem(
|
|
2158
|
+
i18nString(UIStrings.duplicateElement), treeOutline.duplicateNode.bind(treeOutline, this.nodeInternal), {
|
|
2159
|
+
disabled: (this.nodeInternal.isInShadowTree()),
|
|
2160
|
+
jslogContext: 'elements.duplicate-element',
|
|
2161
|
+
});
|
|
2162
|
+
contextMenu.editSection().appendItem(
|
|
2163
|
+
i18nString(UIStrings.deleteElement), this.remove.bind(this), {jslogContext: 'delete-element'});
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2130
2166
|
private startEditing(): boolean|undefined {
|
|
2131
2167
|
if (!this.treeOutline || this.treeOutline.selectedDOMNode() !== this.nodeInternal) {
|
|
2132
2168
|
return;
|
|
@@ -2151,6 +2187,19 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
2151
2187
|
}
|
|
2152
2188
|
}
|
|
2153
2189
|
|
|
2190
|
+
if (this.nodeInternal.nodeType() === Node.PROCESSING_INSTRUCTION_NODE) {
|
|
2191
|
+
return this.startEditingProcessingInstructionValue();
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
return;
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
private startEditingProcessingInstructionValue(): boolean|undefined {
|
|
2198
|
+
const processingInstructionValue =
|
|
2199
|
+
this.listItemElement.getElementsByClassName('webkit-html-processing-instruction-value')[0];
|
|
2200
|
+
if (processingInstructionValue) {
|
|
2201
|
+
return this.startEditingTextNode(processingInstructionValue);
|
|
2202
|
+
}
|
|
2154
2203
|
return;
|
|
2155
2204
|
}
|
|
2156
2205
|
|
|
@@ -2586,6 +2635,11 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
2586
2635
|
}
|
|
2587
2636
|
|
|
2588
2637
|
function moveToNextAttributeIfNeeded(this: ElementsTreeElement): void {
|
|
2638
|
+
if (this.nodeInternal.nodeType() === Node.PROCESSING_INSTRUCTION_NODE) {
|
|
2639
|
+
this.startEditingProcessingInstructionValue();
|
|
2640
|
+
return;
|
|
2641
|
+
}
|
|
2642
|
+
|
|
2589
2643
|
if (moveDirection !== 'forward') {
|
|
2590
2644
|
this.addNewAttribute();
|
|
2591
2645
|
return;
|
|
@@ -1332,6 +1332,8 @@ export class ElementsTreeOutline extends
|
|
|
1332
1332
|
await treeElement.populateNodeContextMenu(contextMenu);
|
|
1333
1333
|
} else if (isPseudoElement) {
|
|
1334
1334
|
treeElement.populatePseudoElementContextMenu(contextMenu);
|
|
1335
|
+
} else if (treeElement.node().nodeType() === Node.PROCESSING_INSTRUCTION_NODE) {
|
|
1336
|
+
await treeElement.populateProcessingElementContextMenu(contextMenu);
|
|
1335
1337
|
}
|
|
1336
1338
|
|
|
1337
1339
|
ElementsPanel.instance().populateAdornerSettingsContextMenu(contextMenu);
|
|
@@ -9,7 +9,7 @@ import * as UI from '../../ui/legacy/legacy.js';
|
|
|
9
9
|
import type * as ElementsComponents from './components/components.js';
|
|
10
10
|
import type {StylePropertiesSection} from './StylePropertiesSection.js';
|
|
11
11
|
import {StylePropertyTreeElement} from './StylePropertyTreeElement.js';
|
|
12
|
-
import type {
|
|
12
|
+
import type {StylesContainer} from './StylesContainer.js';
|
|
13
13
|
|
|
14
14
|
type PropertySelectedEvent = ElementsComponents.StylePropertyEditor.PropertySelectedEvent;
|
|
15
15
|
type PropertyDeselectedEvent = ElementsComponents.StylePropertyEditor.PropertyDeselectedEvent;
|
|
@@ -29,7 +29,7 @@ interface Editor extends HTMLElement {
|
|
|
29
29
|
*/
|
|
30
30
|
export class StyleEditorWidget extends UI.Widget.VBox {
|
|
31
31
|
private editor?: Editor;
|
|
32
|
-
private
|
|
32
|
+
private stylesContainer?: StylesContainer;
|
|
33
33
|
private section?: StylePropertiesSection;
|
|
34
34
|
private editorContainer: HTMLElement;
|
|
35
35
|
|
|
@@ -69,8 +69,8 @@ export class StyleEditorWidget extends UI.Widget.VBox {
|
|
|
69
69
|
await this.render();
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
bindContext(
|
|
73
|
-
this.
|
|
72
|
+
bindContext(stylesContainer: StylesContainer, section: StylePropertiesSection): void {
|
|
73
|
+
this.stylesContainer = stylesContainer;
|
|
74
74
|
this.section = section;
|
|
75
75
|
this.editor?.addEventListener('propertyselected', this.onPropertySelected);
|
|
76
76
|
this.editor?.addEventListener('propertydeselected', this.onPropertyDeselected);
|
|
@@ -85,7 +85,7 @@ export class StyleEditorWidget extends UI.Widget.VBox {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
unbindContext(): void {
|
|
88
|
-
this.
|
|
88
|
+
this.stylesContainer = undefined;
|
|
89
89
|
this.section = undefined;
|
|
90
90
|
this.editor?.removeEventListener('propertyselected', this.onPropertySelected);
|
|
91
91
|
this.editor?.removeEventListener('propertydeselected', this.onPropertyDeselected);
|
|
@@ -98,7 +98,7 @@ export class StyleEditorWidget extends UI.Widget.VBox {
|
|
|
98
98
|
this.editor.data = {
|
|
99
99
|
authoredProperties: this.section ? getAuthoredStyles(this.section, this.editor.getEditableProperties()) :
|
|
100
100
|
new Map(),
|
|
101
|
-
computedProperties: this.
|
|
101
|
+
computedProperties: this.stylesContainer ? await fetchComputedStyles(this.stylesContainer) : new Map(),
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -118,19 +118,19 @@ export class StyleEditorWidget extends UI.Widget.VBox {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
static createTriggerButton(
|
|
121
|
-
|
|
122
|
-
triggerKey: string): HTMLElement {
|
|
121
|
+
stylesContainer: StylesContainer, section: StylePropertiesSection, editorClass: {new(): Editor},
|
|
122
|
+
buttonTitle: string, triggerKey: string): HTMLElement {
|
|
123
123
|
const triggerButton = createIcon('flex-wrap', 'styles-pane-button');
|
|
124
124
|
triggerButton.title = buttonTitle;
|
|
125
125
|
triggerButton.role = 'button';
|
|
126
126
|
|
|
127
127
|
triggerButton.onclick = async event => {
|
|
128
128
|
event.stopPropagation();
|
|
129
|
-
const popoverHelper =
|
|
129
|
+
const popoverHelper = stylesContainer.swatchPopoverHelper();
|
|
130
130
|
const widget = StyleEditorWidget.instance();
|
|
131
131
|
widget.element.classList.toggle('with-padding', true);
|
|
132
132
|
widget.setEditor(editorClass);
|
|
133
|
-
widget.bindContext(
|
|
133
|
+
widget.bindContext(stylesContainer, section);
|
|
134
134
|
widget.setTriggerKey(triggerKey);
|
|
135
135
|
await widget.render();
|
|
136
136
|
widget.focus();
|
|
@@ -168,8 +168,8 @@ function ensureTreeElementForProperty(section: StylePropertiesSection, propertyN
|
|
|
168
168
|
return newTarget;
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
async function fetchComputedStyles(
|
|
172
|
-
const computedStyleModel =
|
|
171
|
+
async function fetchComputedStyles(stylesContainer: StylesContainer): Promise<Map<string, string>> {
|
|
172
|
+
const computedStyleModel = stylesContainer.computedStyleModel();
|
|
173
173
|
const style = await computedStyleModel.fetchComputedStyle();
|
|
174
174
|
return style ? style.computedStyle : new Map();
|
|
175
175
|
}
|