chrome-devtools-frontend 1.0.976172 → 1.0.977567
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/config/gni/devtools_grd_files.gni +6 -1
- package/config/gni/devtools_image_files.gni +2 -0
- package/front_end/Images/src/minus_icon.svg +3 -0
- package/front_end/Images/src/plus_icon.svg +3 -0
- package/front_end/core/host/UserMetrics.ts +23 -23
- package/front_end/core/i18n/locales/af.json +5 -5
- package/front_end/core/i18n/locales/am.json +5 -5
- package/front_end/core/i18n/locales/ar.json +5 -5
- package/front_end/core/i18n/locales/as.json +5 -5
- package/front_end/core/i18n/locales/az.json +5 -5
- package/front_end/core/i18n/locales/be.json +5 -5
- package/front_end/core/i18n/locales/bg.json +5 -5
- package/front_end/core/i18n/locales/bn.json +5 -5
- package/front_end/core/i18n/locales/bs.json +5 -5
- package/front_end/core/i18n/locales/ca.json +5 -5
- package/front_end/core/i18n/locales/cs.json +5 -5
- package/front_end/core/i18n/locales/cy.json +5 -5
- package/front_end/core/i18n/locales/da.json +5 -5
- package/front_end/core/i18n/locales/de.json +5 -5
- package/front_end/core/i18n/locales/el.json +5 -5
- package/front_end/core/i18n/locales/en-GB.json +5 -5
- package/front_end/core/i18n/locales/en-US.json +24 -15
- package/front_end/core/i18n/locales/en-XL.json +24 -15
- package/front_end/core/i18n/locales/es-419.json +5 -5
- package/front_end/core/i18n/locales/es.json +5 -5
- package/front_end/core/i18n/locales/et.json +5 -5
- package/front_end/core/i18n/locales/eu.json +5 -5
- package/front_end/core/i18n/locales/fa.json +5 -5
- package/front_end/core/i18n/locales/fi.json +5 -5
- package/front_end/core/i18n/locales/fil.json +5 -5
- package/front_end/core/i18n/locales/fr-CA.json +5 -5
- package/front_end/core/i18n/locales/fr.json +5 -5
- package/front_end/core/i18n/locales/gl.json +5 -5
- package/front_end/core/i18n/locales/gu.json +5 -5
- package/front_end/core/i18n/locales/he.json +5 -5
- package/front_end/core/i18n/locales/hi.json +5 -5
- package/front_end/core/i18n/locales/hr.json +5 -5
- package/front_end/core/i18n/locales/hu.json +5 -5
- package/front_end/core/i18n/locales/hy.json +5 -5
- package/front_end/core/i18n/locales/id.json +5 -5
- package/front_end/core/i18n/locales/is.json +5 -5
- package/front_end/core/i18n/locales/it.json +5 -5
- package/front_end/core/i18n/locales/ja.json +5 -5
- package/front_end/core/i18n/locales/ka.json +5 -5
- package/front_end/core/i18n/locales/kk.json +5 -5
- package/front_end/core/i18n/locales/km.json +5 -5
- package/front_end/core/i18n/locales/kn.json +5 -5
- package/front_end/core/i18n/locales/ko.json +5 -5
- package/front_end/core/i18n/locales/ky.json +5 -5
- package/front_end/core/i18n/locales/lo.json +5 -5
- package/front_end/core/i18n/locales/lt.json +5 -5
- package/front_end/core/i18n/locales/lv.json +5 -5
- package/front_end/core/i18n/locales/mk.json +5 -5
- package/front_end/core/i18n/locales/ml.json +5 -5
- package/front_end/core/i18n/locales/mn.json +5 -5
- package/front_end/core/i18n/locales/mr.json +5 -5
- package/front_end/core/i18n/locales/ms.json +5 -5
- package/front_end/core/i18n/locales/my.json +5 -5
- package/front_end/core/i18n/locales/ne.json +5 -5
- package/front_end/core/i18n/locales/nl.json +5 -5
- package/front_end/core/i18n/locales/no.json +5 -5
- package/front_end/core/i18n/locales/or.json +5 -5
- package/front_end/core/i18n/locales/pa.json +5 -5
- package/front_end/core/i18n/locales/pl.json +5 -5
- package/front_end/core/i18n/locales/pt-PT.json +5 -5
- package/front_end/core/i18n/locales/pt.json +5 -5
- package/front_end/core/i18n/locales/ro.json +5 -5
- package/front_end/core/i18n/locales/ru.json +5 -5
- package/front_end/core/i18n/locales/si.json +5 -5
- package/front_end/core/i18n/locales/sk.json +5 -5
- package/front_end/core/i18n/locales/sl.json +5 -5
- package/front_end/core/i18n/locales/sq.json +5 -5
- package/front_end/core/i18n/locales/sr-Latn.json +5 -5
- package/front_end/core/i18n/locales/sr.json +5 -5
- package/front_end/core/i18n/locales/sv.json +5 -5
- package/front_end/core/i18n/locales/sw.json +5 -5
- package/front_end/core/i18n/locales/ta.json +5 -5
- package/front_end/core/i18n/locales/te.json +5 -5
- package/front_end/core/i18n/locales/th.json +5 -5
- package/front_end/core/i18n/locales/tr.json +5 -5
- package/front_end/core/i18n/locales/uk.json +5 -5
- package/front_end/core/i18n/locales/ur.json +5 -5
- package/front_end/core/i18n/locales/uz.json +5 -5
- package/front_end/core/i18n/locales/vi.json +5 -5
- package/front_end/core/i18n/locales/zh-HK.json +5 -5
- package/front_end/core/i18n/locales/zh-TW.json +5 -5
- package/front_end/core/i18n/locales/zh.json +5 -5
- package/front_end/core/i18n/locales/zu.json +5 -5
- package/front_end/core/sdk/CSSContainerQuery.ts +1 -1
- package/front_end/core/sdk/CSSModel.ts +13 -9
- package/front_end/generated/InspectorBackendCommands.js +6 -5
- package/front_end/generated/protocol.ts +10 -9
- package/front_end/models/issues_manager/{SameSiteCookieIssue.ts → CookieIssue.ts} +75 -79
- package/front_end/models/issues_manager/Issue.ts +1 -1
- package/front_end/models/issues_manager/IssuesManager.ts +3 -9
- package/front_end/models/issues_manager/NavigatorUserAgentIssue.ts +1 -1
- package/front_end/models/issues_manager/issues_manager.ts +2 -2
- package/front_end/models/persistence/NetworkPersistenceManager.ts +1 -1
- package/front_end/panels/application/components/BackForwardCacheView.ts +23 -1
- package/front_end/panels/elements/ClassesPaneWidget.ts +1 -1
- package/front_end/panels/elements/ComputedStyleModel.ts +1 -1
- package/front_end/panels/elements/ElementsTreeElement.ts +1 -1
- package/front_end/panels/elements/LayersWidget.ts +4 -3
- package/front_end/panels/elements/MetricsSidebarPane.ts +2 -2
- package/front_end/panels/elements/PlatformFontsWidget.ts +1 -1
- package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +10 -8
- package/front_end/panels/emulation/MediaQueryInspector.ts +1 -1
- package/front_end/panels/issues/IssueView.ts +1 -1
- package/front_end/panels/issues/IssuesPane.ts +1 -1
- package/front_end/panels/network/NetworkLogView.ts +1 -1
- package/front_end/panels/sources/CSSPlugin.ts +77 -22
- package/front_end/panels/sources/SourcesView.ts +23 -10
- package/front_end/panels/sources/components/HeadersView.css +32 -0
- package/front_end/panels/sources/components/HeadersView.ts +89 -0
- package/front_end/panels/sources/components/components.ts +9 -0
- package/front_end/panels/timeline/TimelineController.ts +17 -5
- package/front_end/ui/components/expandable_list/expandableList.css +10 -0
- package/front_end/ui/components/text_editor/javascript.ts +46 -1
- package/package.json +1 -1
@@ -84,8 +84,9 @@ export class LayersWidget extends UI.Widget.Widget {
|
|
84
84
|
const makeTreeNode = (parentId: string) =>
|
85
85
|
(layer: Protocol.CSS.CSSLayerData): TreeOutline.TreeOutlineUtils.TreeNode<string> => {
|
86
86
|
const subLayers = layer.subLayers;
|
87
|
-
const
|
88
|
-
const
|
87
|
+
const name = SDK.CSSModel.CSSModel.readableLayerName(layer.name);
|
88
|
+
const treeNodeData = layer.order + ': ' + name;
|
89
|
+
const id = parentId ? parentId + '.' + name : name;
|
89
90
|
if (!subLayers) {
|
90
91
|
return {treeNodeData, id};
|
91
92
|
}
|
@@ -96,7 +97,7 @@ export class LayersWidget extends UI.Widget.Widget {
|
|
96
97
|
Promise.resolve(subLayers.sort((layer1, layer2) => layer1.order - layer2.order).map(makeTreeNode(id))),
|
97
98
|
};
|
98
99
|
};
|
99
|
-
const rootLayer = await this.cssModel.
|
100
|
+
const rootLayer = await this.cssModel.getRootLayer(node.id);
|
100
101
|
this.layerTreeComponent.data = {
|
101
102
|
defaultRenderer: TreeOutline.TreeOutline.defaultRenderer,
|
102
103
|
tree: [makeTreeNode('')(rootLayer)],
|
@@ -88,8 +88,8 @@ export class MetricsSidebarPane extends ElementsSidebarPane {
|
|
88
88
|
}
|
89
89
|
|
90
90
|
const promises = [
|
91
|
-
cssModel.
|
92
|
-
cssModel.
|
91
|
+
cssModel.getComputedStyle(node.id).then(callback.bind(this)),
|
92
|
+
cssModel.getInlineStyles(node.id).then(inlineStyleResult => {
|
93
93
|
if (inlineStyleResult && this.node() === node) {
|
94
94
|
this.inlineStyle = inlineStyleResult.inlineStyle;
|
95
95
|
}
|
@@ -88,7 +88,7 @@ export class PlatformFontsWidget extends UI.ThrottledWidget.ThrottledWidget {
|
|
88
88
|
return Promise.resolve();
|
89
89
|
}
|
90
90
|
|
91
|
-
return cssModel.
|
91
|
+
return cssModel.getPlatformFonts(node.id).then(this.refreshUI.bind(this, node));
|
92
92
|
}
|
93
93
|
|
94
94
|
private refreshUI(node: SDK.DOMModel.DOMNode, platformFonts: Protocol.CSS.PlatformFontUsage[]|null): void {
|
@@ -278,7 +278,7 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
278
278
|
const cssModel = this.parentPaneInternal.cssModel();
|
279
279
|
const node = this.node();
|
280
280
|
if (cssModel && node && typeof node.id !== 'undefined') {
|
281
|
-
const contrastInfo = new ColorPicker.ContrastInfo.ContrastInfo(await cssModel.
|
281
|
+
const contrastInfo = new ColorPicker.ContrastInfo.ContrastInfo(await cssModel.getBackgroundColors(node.id));
|
282
282
|
swatchIcon.setContrastInfo(contrastInfo);
|
283
283
|
}
|
284
284
|
}
|
@@ -875,7 +875,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
875
875
|
if (parentRule instanceof SDK.CSSRule.CSSStyleRule) {
|
876
876
|
const layers = parentRule.layers;
|
877
877
|
if ((layers.length || lastLayers) && lastLayers !== layers) {
|
878
|
-
const block = SectionBlock.createLayerBlock(
|
878
|
+
const block = SectionBlock.createLayerBlock(parentRule);
|
879
879
|
blocks.push(block);
|
880
880
|
sawLayers = true;
|
881
881
|
lastLayers = layers;
|
@@ -1430,18 +1430,21 @@ export class SectionBlock {
|
|
1430
1430
|
return new SectionBlock(separatorElement);
|
1431
1431
|
}
|
1432
1432
|
|
1433
|
-
static createLayerBlock(
|
1433
|
+
static createLayerBlock(rule: SDK.CSSRule.CSSStyleRule): SectionBlock {
|
1434
1434
|
const separatorElement = document.createElement('div');
|
1435
1435
|
separatorElement.className = 'sidebar-separator layer-separator';
|
1436
1436
|
UI.UIUtils.createTextChild(separatorElement.createChild('div'), i18nString(UIStrings.layer));
|
1437
|
-
|
1438
|
-
|
1437
|
+
const layers = rule.layers;
|
1438
|
+
if (!layers.length && rule.origin === Protocol.CSS.StyleSheetOrigin.UserAgent) {
|
1439
|
+
const name = rule.origin === Protocol.CSS.StyleSheetOrigin.UserAgent ? '\xa0user\xa0agent\xa0stylesheet' :
|
1440
|
+
'\xa0implicit\xa0outer\xa0layer';
|
1441
|
+
UI.UIUtils.createTextChild(separatorElement.createChild('div'), name);
|
1439
1442
|
return new SectionBlock(separatorElement);
|
1440
1443
|
}
|
1441
1444
|
const layerLink = separatorElement.createChild('button') as HTMLButtonElement;
|
1442
1445
|
layerLink.className = 'link';
|
1443
1446
|
layerLink.title = i18nString(UIStrings.clickToRevealLayer);
|
1444
|
-
const name = layers.map(layer => layer.text
|
1447
|
+
const name = layers.map(layer => SDK.CSSModel.CSSModel.readableLayerName(layer.text)).join('.');
|
1445
1448
|
layerLink.textContent = name;
|
1446
1449
|
layerLink.onclick = (): Promise<void> => LayersWidget.LayersWidget.instance().revealLayer(name);
|
1447
1450
|
return new SectionBlock(separatorElement);
|
@@ -3192,13 +3195,12 @@ export class CSSPropertyPrompt extends UI.TextPrompt.TextPrompt {
|
|
3192
3195
|
if (!node || this.selectedNodeComputedStyles) {
|
3193
3196
|
return;
|
3194
3197
|
}
|
3195
|
-
this.selectedNodeComputedStyles = await node.domModel().cssModel().
|
3198
|
+
this.selectedNodeComputedStyles = await node.domModel().cssModel().getComputedStyle(node.id);
|
3196
3199
|
const parentNode = node.parentNode;
|
3197
3200
|
if (parentNode) {
|
3198
|
-
this.parentNodeComputedStyles = await parentNode.domModel().cssModel().
|
3201
|
+
this.parentNodeComputedStyles = await parentNode.domModel().cssModel().getComputedStyle(parentNode.id);
|
3199
3202
|
}
|
3200
3203
|
};
|
3201
|
-
|
3202
3204
|
for (const result of results) {
|
3203
3205
|
await ensureComputedStyles();
|
3204
3206
|
// Using parent node's computed styles does not work in all cases. For example:
|
@@ -165,7 +165,7 @@ export class MediaQueryInspector extends UI.Widget.Widget implements
|
|
165
165
|
return Promise.resolve();
|
166
166
|
}
|
167
167
|
|
168
|
-
return this.cssModel.
|
168
|
+
return this.cssModel.getMediaQueries().then(this.rebuildMediaQueries.bind(this));
|
169
169
|
}
|
170
170
|
|
171
171
|
private squashAdjacentEqual(models: MediaQueryUIModel[]): MediaQueryUIModel[] {
|
@@ -131,7 +131,7 @@ class AffectedRequestsView extends AffectedResourcesView {
|
|
131
131
|
const issueTypeToNetworkHeaderMap =
|
132
132
|
new Map<IssuesManager.Issue.IssueCategory, NetworkForward.UIRequestLocation.UIRequestTabs>([
|
133
133
|
[
|
134
|
-
IssuesManager.Issue.IssueCategory.
|
134
|
+
IssuesManager.Issue.IssueCategory.Cookie,
|
135
135
|
NetworkForward.UIRequestLocation.UIRequestTabs.Cookies,
|
136
136
|
],
|
137
137
|
[
|
@@ -127,7 +127,7 @@ class IssueCategoryView extends UI.TreeOutline.TreeElement {
|
|
127
127
|
return i18nString(UIStrings.crossOriginEmbedderPolicy);
|
128
128
|
case IssuesManager.Issue.IssueCategory.MixedContent:
|
129
129
|
return i18nString(UIStrings.mixedContent);
|
130
|
-
case IssuesManager.Issue.IssueCategory.
|
130
|
+
case IssuesManager.Issue.IssueCategory.Cookie:
|
131
131
|
return i18nString(UIStrings.samesiteCookie);
|
132
132
|
case IssuesManager.Issue.IssueCategory.HeavyAd:
|
133
133
|
return i18nString(UIStrings.heavyAds);
|
@@ -1716,7 +1716,7 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
1716
1716
|
return false;
|
1717
1717
|
}
|
1718
1718
|
if (this.onlyIssuesFilterUI.checked() &&
|
1719
|
-
!IssuesManager.RelatedIssue.hasIssueOfCategory(request, IssuesManager.Issue.IssueCategory.
|
1719
|
+
!IssuesManager.RelatedIssue.hasIssueOfCategory(request, IssuesManager.Issue.IssueCategory.Cookie)) {
|
1720
1720
|
return false;
|
1721
1721
|
}
|
1722
1722
|
if (this.onlyBlockedRequestsUI.checked() && !request.wasBlocked() && !request.corsErrorStatus()) {
|
@@ -4,13 +4,17 @@
|
|
4
4
|
|
5
5
|
import * as Common from '../../core/common/common.js';
|
6
6
|
import * as i18n from '../../core/i18n/i18n.js';
|
7
|
+
import * as Platform from '../../core/platform/platform.js';
|
7
8
|
import * as SDK from '../../core/sdk/sdk.js';
|
9
|
+
import type * as Protocol from '../../generated/protocol.js';
|
8
10
|
import type * as Workspace from '../../models/workspace/workspace.js';
|
9
11
|
import * as ColorPicker from '../../ui/legacy/components/color_picker/color_picker.js';
|
10
12
|
import * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';
|
11
13
|
import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
|
14
|
+
import type * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
|
12
15
|
import * as UI from '../../ui/legacy/legacy.js';
|
13
16
|
|
17
|
+
import {assertNotNullOrUndefined} from '../../core/platform/platform.js';
|
14
18
|
import {Plugin} from './Plugin.js';
|
15
19
|
|
16
20
|
// Plugin to add CSS completion, shortcuts, and color/curve swatches
|
@@ -29,17 +33,6 @@ const UIStrings = {
|
|
29
33
|
const str_ = i18n.i18n.registerUIStrings('panels/sources/CSSPlugin.ts', UIStrings);
|
30
34
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
31
35
|
|
32
|
-
export function completion(): CodeMirror.Extension {
|
33
|
-
const {cssCompletionSource} = CodeMirror.css;
|
34
|
-
return CodeMirror.autocompletion({
|
35
|
-
override:
|
36
|
-
[async(cx: CodeMirror.CompletionContext):
|
37
|
-
Promise<CodeMirror.CompletionResult|null> => {
|
38
|
-
return (await specificCssCompletion(cx)) || cssCompletionSource(cx);
|
39
|
-
}],
|
40
|
-
});
|
41
|
-
}
|
42
|
-
|
43
36
|
const dontCompleteIn = new Set(['ColorLiteral', 'NumberLiteral', 'StringLiteral', 'Comment', 'Important']);
|
44
37
|
|
45
38
|
function findPropertyAt(node: CodeMirror.SyntaxNode, pos: number): CodeMirror.SyntaxNode|null {
|
@@ -57,18 +50,43 @@ function findPropertyAt(node: CodeMirror.SyntaxNode, pos: number): CodeMirror.Sy
|
|
57
50
|
return null;
|
58
51
|
}
|
59
52
|
|
60
|
-
function
|
53
|
+
function getCurrentStyleSheet(
|
54
|
+
url: Platform.DevToolsPath.UrlString, cssModel: SDK.CSSModel.CSSModel): Protocol.CSS.StyleSheetId {
|
55
|
+
const currentStyleSheet = cssModel.getStyleSheetIdsForURL(url);
|
56
|
+
if (currentStyleSheet.length === 0) {
|
57
|
+
Platform.DCHECK(() => currentStyleSheet.length !== 0, 'Can\'t find style sheet ID for current URL');
|
58
|
+
}
|
59
|
+
|
60
|
+
return currentStyleSheet[0];
|
61
|
+
}
|
62
|
+
|
63
|
+
async function specificCssCompletion(
|
64
|
+
cx: CodeMirror.CompletionContext, uiSourceCode: Workspace.UISourceCode.UISourceCode,
|
65
|
+
cssModel: SDK.CSSModel.CSSModel|undefined): Promise<CodeMirror.CompletionResult|null> {
|
61
66
|
const node = CodeMirror.syntaxTree(cx.state).resolveInner(cx.pos, -1);
|
67
|
+
if (node.name === 'ClassName') {
|
68
|
+
// Should never happen, but let's code defensively here
|
69
|
+
assertNotNullOrUndefined(cssModel);
|
70
|
+
|
71
|
+
const currentStyleSheet = getCurrentStyleSheet(uiSourceCode.url(), cssModel);
|
72
|
+
const existingClassNames = await cssModel.getClassNames(currentStyleSheet);
|
73
|
+
|
74
|
+
return {
|
75
|
+
from: node.from,
|
76
|
+
options: existingClassNames.map(value => ({type: 'constant', label: value})),
|
77
|
+
};
|
78
|
+
}
|
62
79
|
const property = findPropertyAt(node, cx.pos);
|
63
|
-
if (
|
64
|
-
|
80
|
+
if (property) {
|
81
|
+
const propertyValues =
|
82
|
+
SDK.CSSMetadata.cssMetadata().getPropertyValues(cx.state.sliceDoc(property.from, property.to));
|
83
|
+
return {
|
84
|
+
from: node.name === 'ValueName' ? node.from : cx.pos,
|
85
|
+
options: propertyValues.map(value => ({type: 'constant', label: value})),
|
86
|
+
span: /^[\w\P{ASCII}\-]+$/u,
|
87
|
+
};
|
65
88
|
}
|
66
|
-
|
67
|
-
return {
|
68
|
-
from: node.name === 'ValueName' ? node.from : cx.pos,
|
69
|
-
options: propertyValues.map(value => ({type: 'constant', label: value})),
|
70
|
-
span: /^[\w\P{ASCII}\-]+$/u,
|
71
|
-
};
|
89
|
+
return null;
|
72
90
|
}
|
73
91
|
|
74
92
|
function findColorsAndCurves(
|
@@ -380,12 +398,49 @@ export function cssBindings(): CodeMirror.Extension {
|
|
380
398
|
});
|
381
399
|
}
|
382
400
|
|
383
|
-
export class CSSPlugin extends Plugin {
|
401
|
+
export class CSSPlugin extends Plugin implements SDK.TargetManager.SDKModelObserver<SDK.CSSModel.CSSModel> {
|
402
|
+
#cssModel?: SDK.CSSModel.CSSModel;
|
403
|
+
|
404
|
+
constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode, _transformer?: SourceFrame.SourceFrame.Transformer) {
|
405
|
+
super(uiSourceCode, _transformer);
|
406
|
+
SDK.TargetManager.TargetManager.instance().observeModels(SDK.CSSModel.CSSModel, this);
|
407
|
+
}
|
408
|
+
|
384
409
|
static accepts(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean {
|
385
410
|
return uiSourceCode.contentType().isStyleSheet();
|
386
411
|
}
|
387
412
|
|
413
|
+
modelAdded(cssModel: SDK.CSSModel.CSSModel): void {
|
414
|
+
if (this.#cssModel) {
|
415
|
+
return;
|
416
|
+
}
|
417
|
+
this.#cssModel = cssModel;
|
418
|
+
}
|
419
|
+
modelRemoved(cssModel: SDK.CSSModel.CSSModel): void {
|
420
|
+
if (this.#cssModel === cssModel) {
|
421
|
+
this.#cssModel = undefined;
|
422
|
+
}
|
423
|
+
}
|
424
|
+
|
388
425
|
editorExtension(): CodeMirror.Extension {
|
389
|
-
return [cssBindings(),
|
426
|
+
return [cssBindings(), this.#cssCompletion(), cssSwatches()];
|
427
|
+
}
|
428
|
+
|
429
|
+
#cssCompletion(): CodeMirror.Extension {
|
430
|
+
const {cssCompletionSource} = CodeMirror.css;
|
431
|
+
|
432
|
+
// CodeMirror binds the function below to the state object.
|
433
|
+
// Therefore, we can't access `this` and retrieve the following properties.
|
434
|
+
// Instead, retrieve them up front to bind them to the correct closure.
|
435
|
+
const uiSourceCode = this.uiSourceCode;
|
436
|
+
const cssModel = this.#cssModel;
|
437
|
+
|
438
|
+
return CodeMirror.autocompletion({
|
439
|
+
override:
|
440
|
+
[async(cx: CodeMirror.CompletionContext):
|
441
|
+
Promise<CodeMirror.CompletionResult|null> => {
|
442
|
+
return (await specificCssCompletion(cx, uiSourceCode, cssModel)) || cssCompletionSource(cx);
|
443
|
+
}],
|
444
|
+
});
|
390
445
|
}
|
391
446
|
}
|
@@ -12,6 +12,7 @@ import * as QuickOpen from '../../ui/legacy/components/quick_open/quick_open.js'
|
|
12
12
|
import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
|
13
13
|
import * as UI from '../../ui/legacy/legacy.js';
|
14
14
|
|
15
|
+
import * as Components from './components/components.js';
|
15
16
|
import {EditingLocationHistoryManager} from './EditingLocationHistoryManager.js';
|
16
17
|
import sourcesViewStyles from './sourcesView.css.js';
|
17
18
|
|
@@ -377,6 +378,10 @@ export class SourcesView extends Common.ObjectWrapper.eventMixin<EventTypes, typ
|
|
377
378
|
sourceView = new SourceFrame.ImageView.ImageView(uiSourceCode.mimeType(), uiSourceCode);
|
378
379
|
} else if (contentType === Common.ResourceType.resourceTypes.Font) {
|
379
380
|
sourceView = new SourceFrame.FontView.FontView(uiSourceCode.mimeType(), uiSourceCode);
|
381
|
+
} else if (
|
382
|
+
uiSourceCode.name() === HEADER_OVERRIDES_FILENAME &&
|
383
|
+
Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.HEADER_OVERRIDES)) {
|
384
|
+
sourceView = new Components.HeadersView.HeadersView(uiSourceCode);
|
380
385
|
} else {
|
381
386
|
sourceFrame = new UISourceCodeFrame(uiSourceCode);
|
382
387
|
}
|
@@ -399,10 +404,18 @@ export class SourcesView extends Common.ObjectWrapper.eventMixin<EventTypes, typ
|
|
399
404
|
if (widget instanceof SourceFrame.FontView.FontView) {
|
400
405
|
return SourceViewType.FontView;
|
401
406
|
}
|
407
|
+
if (widget instanceof Components.HeadersView.HeadersView) {
|
408
|
+
return SourceViewType.HeadersView;
|
409
|
+
}
|
402
410
|
return SourceViewType.SourceView;
|
403
411
|
}
|
404
412
|
|
405
|
-
#
|
413
|
+
#sourceViewTypeForUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode): SourceViewType {
|
414
|
+
if (uiSourceCode.name() === HEADER_OVERRIDES_FILENAME &&
|
415
|
+
Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.HEADER_OVERRIDES)) {
|
416
|
+
return SourceViewType.HeadersView;
|
417
|
+
}
|
418
|
+
const contentType = uiSourceCode.contentType();
|
406
419
|
switch (contentType) {
|
407
420
|
case Common.ResourceType.resourceTypes.Image:
|
408
421
|
return SourceViewType.ImageView;
|
@@ -417,8 +430,7 @@ export class SourcesView extends Common.ObjectWrapper.eventMixin<EventTypes, typ
|
|
417
430
|
const uiSourceCode = event.data;
|
418
431
|
const widget = this.sourceViewByUISourceCode.get(uiSourceCode);
|
419
432
|
if (widget) {
|
420
|
-
|
421
|
-
if (this.#sourceViewTypeForWidget(widget) !== this.#sourceViewTypeForContentType(contentType)) {
|
433
|
+
if (this.#sourceViewTypeForWidget(widget) !== this.#sourceViewTypeForUISourceCode(uiSourceCode)) {
|
422
434
|
// Remove the exisiting editor tab and create a new one of the correct type.
|
423
435
|
this.removeUISourceCodes([uiSourceCode]);
|
424
436
|
this.showSourceLocation(uiSourceCode);
|
@@ -602,20 +614,18 @@ export class SourcesView extends Common.ObjectWrapper.eventMixin<EventTypes, typ
|
|
602
614
|
}
|
603
615
|
|
604
616
|
save(): void {
|
605
|
-
this.
|
617
|
+
this.saveSourceView(this.visibleView());
|
606
618
|
}
|
607
619
|
|
608
620
|
saveAll(): void {
|
609
621
|
const sourceFrames = this.editorContainer.fileViews();
|
610
|
-
sourceFrames.forEach(this.
|
622
|
+
sourceFrames.forEach(this.saveSourceView.bind(this));
|
611
623
|
}
|
612
624
|
|
613
|
-
private
|
614
|
-
if (
|
615
|
-
|
625
|
+
private saveSourceView(sourceView: UI.Widget.Widget|null): void {
|
626
|
+
if (sourceView instanceof UISourceCodeFrame || sourceView instanceof Components.HeadersView.HeadersView) {
|
627
|
+
sourceView.commitEditing();
|
616
628
|
}
|
617
|
-
const uiSourceCodeFrame = (sourceFrame as UISourceCodeFrame);
|
618
|
-
uiSourceCodeFrame.commitEditing();
|
619
629
|
}
|
620
630
|
|
621
631
|
toggleBreakpointsActiveState(active: boolean): void {
|
@@ -764,9 +774,12 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
|
|
764
774
|
}
|
765
775
|
}
|
766
776
|
|
777
|
+
const HEADER_OVERRIDES_FILENAME = '.headers';
|
778
|
+
|
767
779
|
// eslint-disable-next-line rulesdir/const_enum
|
768
780
|
enum SourceViewType {
|
769
781
|
ImageView = 'ImageView',
|
770
782
|
FontView = 'FontView',
|
783
|
+
HeadersView = 'HeadersView',
|
771
784
|
SourceView = 'SourceView',
|
772
785
|
}
|
@@ -0,0 +1,32 @@
|
|
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-grow: 1;
|
9
|
+
}
|
10
|
+
|
11
|
+
.center-wrapper {
|
12
|
+
height: 100%;
|
13
|
+
display: flex;
|
14
|
+
justify-content: center;
|
15
|
+
align-items: center;
|
16
|
+
}
|
17
|
+
|
18
|
+
.centered {
|
19
|
+
margin: 1em;
|
20
|
+
max-width: 300px;
|
21
|
+
text-align: center;
|
22
|
+
}
|
23
|
+
|
24
|
+
.error-header {
|
25
|
+
font-weight: bold;
|
26
|
+
margin-bottom: 1em;
|
27
|
+
}
|
28
|
+
|
29
|
+
.error-body {
|
30
|
+
line-height: 1.5em;
|
31
|
+
color: var(--color-text-secondary);
|
32
|
+
}
|
@@ -0,0 +1,89 @@
|
|
1
|
+
// Copyright 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 Persistence from '../../../models/persistence/persistence.js';
|
7
|
+
import type * as Workspace from '../../../models/workspace/workspace.js';
|
8
|
+
import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
|
9
|
+
import * as UI from '../../../ui/legacy/legacy.js';
|
10
|
+
import * as LitHtml from '../../../ui/lit-html/lit-html.js';
|
11
|
+
|
12
|
+
import HeadersViewStyles from './HeadersView.css.js';
|
13
|
+
|
14
|
+
const UIStrings = {
|
15
|
+
/**
|
16
|
+
*@description Error message for files which cannot not be parsed.
|
17
|
+
*@example {.headers} PH1
|
18
|
+
*/
|
19
|
+
errorWhenParsing: 'Error when parsing \'\'{PH1}\'\'.',
|
20
|
+
/**
|
21
|
+
*@description Explainer for files which cannot be parsed.
|
22
|
+
*@example {.headers} PH1
|
23
|
+
*/
|
24
|
+
parsingErrorExplainer:
|
25
|
+
'This is most likely due to a syntax error in \'\'{PH1}\'\'. Try opening this file in an external editor to fix the error or delete the file and re-create the override.',
|
26
|
+
};
|
27
|
+
const str_ = i18n.i18n.registerUIStrings('panels/sources/components/HeadersView.ts', UIStrings);
|
28
|
+
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
29
|
+
|
30
|
+
export class HeadersView extends UI.View.SimpleView {
|
31
|
+
readonly #headersViewComponent = new HeadersViewComponent();
|
32
|
+
#uiSourceCode: Workspace.UISourceCode.UISourceCode;
|
33
|
+
|
34
|
+
constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode) {
|
35
|
+
super('HeadersView');
|
36
|
+
this.#uiSourceCode = uiSourceCode;
|
37
|
+
this.element.appendChild(this.#headersViewComponent);
|
38
|
+
this.#headersViewComponent.data = {
|
39
|
+
uiSourceCode: this.#uiSourceCode,
|
40
|
+
};
|
41
|
+
}
|
42
|
+
|
43
|
+
commitEditing(): void {
|
44
|
+
this.#uiSourceCode.commitWorkingCopy();
|
45
|
+
Persistence.NetworkPersistenceManager.NetworkPersistenceManager.instance().updateInterceptionPatterns();
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
export interface HeadersViewComponentData {
|
50
|
+
uiSourceCode: Workspace.UISourceCode.UISourceCode;
|
51
|
+
}
|
52
|
+
|
53
|
+
export class HeadersViewComponent extends HTMLElement {
|
54
|
+
static readonly litTagName = LitHtml.literal`devtools-sources-headers-view`;
|
55
|
+
readonly #shadow = this.attachShadow({mode: 'open'});
|
56
|
+
#uiSourceCode: Workspace.UISourceCode.UISourceCode|null = null;
|
57
|
+
|
58
|
+
connectedCallback(): void {
|
59
|
+
this.#shadow.adoptedStyleSheets = [HeadersViewStyles];
|
60
|
+
}
|
61
|
+
|
62
|
+
set data(data: HeadersViewComponentData) {
|
63
|
+
this.#uiSourceCode = data.uiSourceCode;
|
64
|
+
this.#render();
|
65
|
+
}
|
66
|
+
|
67
|
+
#render(): void {
|
68
|
+
const fileName = this.#uiSourceCode?.name() || '.headers';
|
69
|
+
// clang-format off
|
70
|
+
LitHtml.render(LitHtml.html`
|
71
|
+
<div class="center-wrapper">
|
72
|
+
<div class="centered">
|
73
|
+
<div class="error-header">${i18nString(UIStrings.errorWhenParsing, {PH1: fileName})}</div>
|
74
|
+
<div class="error-body">${i18nString(UIStrings.parsingErrorExplainer, {PH1: fileName})}</div>
|
75
|
+
</div>
|
76
|
+
</div>
|
77
|
+
`, this.#shadow, {host: this});
|
78
|
+
// clang-format on
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
ComponentHelpers.CustomElements.defineComponent('devtools-sources-headers-view', HeadersViewComponent);
|
83
|
+
|
84
|
+
declare global {
|
85
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
86
|
+
interface HTMLElementTagNameMap {
|
87
|
+
'devtools-sources-headers-view': HeadersViewComponent;
|
88
|
+
}
|
89
|
+
}
|
@@ -80,18 +80,31 @@ export class TimelineController implements SDK.TargetManager.SDKModelObserver<SD
|
|
80
80
|
function disabledByDefault(category: string): string {
|
81
81
|
return 'disabled-by-default-' + category;
|
82
82
|
}
|
83
|
+
|
84
|
+
// The following categories are also used in other tools, but this panel
|
85
|
+
// offers the possibility of turning them off (see below).
|
86
|
+
// 'disabled-by-default-devtools.screenshot'
|
87
|
+
// └ default: on, option: captureFilmStrip
|
88
|
+
// 'disabled-by-default-devtools.timeline.invalidationTracking'
|
89
|
+
// └ default: off, experiment: timelineInvalidationTracking
|
90
|
+
// 'disabled-by-default-v8.cpu_profiler'
|
91
|
+
// └ default: on, option: enableJSSampling
|
83
92
|
const categoriesArray = [
|
84
93
|
'-*',
|
94
|
+
TimelineModel.TimelineModel.TimelineModelImpl.Category.Console,
|
95
|
+
TimelineModel.TimelineModel.TimelineModelImpl.Category.UserTiming,
|
85
96
|
'devtools.timeline',
|
86
97
|
disabledByDefault('devtools.timeline'),
|
87
98
|
disabledByDefault('devtools.timeline.frame'),
|
88
|
-
'
|
99
|
+
disabledByDefault('devtools.timeline.stack'),
|
89
100
|
disabledByDefault('v8.compile'),
|
90
|
-
|
91
|
-
TimelineModel.TimelineModel.TimelineModelImpl.Category.
|
101
|
+
disabledByDefault('v8.cpu_profiler.hires'),
|
102
|
+
TimelineModel.TimelineModel.TimelineModelImpl.Category.LatencyInfo,
|
92
103
|
TimelineModel.TimelineModel.TimelineModelImpl.Category.Loading,
|
104
|
+
disabledByDefault('lighthouse'),
|
105
|
+
'v8.execute',
|
106
|
+
'v8',
|
93
107
|
];
|
94
|
-
categoriesArray.push(TimelineModel.TimelineModel.TimelineModelImpl.Category.LatencyInfo);
|
95
108
|
|
96
109
|
if (Root.Runtime.experiments.isEnabled('timelineV8RuntimeCallStats') && options.enableJSSampling) {
|
97
110
|
categoriesArray.push(disabledByDefault('v8.runtime_stats_sampling'));
|
@@ -99,7 +112,6 @@ export class TimelineController implements SDK.TargetManager.SDKModelObserver<SD
|
|
99
112
|
if (!Root.Runtime.Runtime.queryParam('timelineTracingJSProfileDisabled') && options.enableJSSampling) {
|
100
113
|
categoriesArray.push(disabledByDefault('v8.cpu_profiler'));
|
101
114
|
}
|
102
|
-
categoriesArray.push(disabledByDefault('devtools.timeline.stack'));
|
103
115
|
if (Root.Runtime.experiments.isEnabled('timelineInvalidationTracking')) {
|
104
116
|
categoriesArray.push(disabledByDefault('devtools.timeline.invalidationTracking'));
|
105
117
|
}
|
@@ -4,6 +4,10 @@
|
|
4
4
|
* found in the LICENSE file.
|
5
5
|
*/
|
6
6
|
|
7
|
+
:host {
|
8
|
+
overflow: hidden;
|
9
|
+
}
|
10
|
+
|
7
11
|
div {
|
8
12
|
line-height: 1.7em;
|
9
13
|
}
|
@@ -53,3 +57,9 @@ button.link {
|
|
53
57
|
font-family: inherit;
|
54
58
|
font-size: inherit;
|
55
59
|
}
|
60
|
+
|
61
|
+
.text-ellipsis {
|
62
|
+
overflow: hidden;
|
63
|
+
text-overflow: ellipsis;
|
64
|
+
white-space: nowrap;
|
65
|
+
}
|
@@ -101,11 +101,11 @@ const dontCompleteIn = new Set([
|
|
101
101
|
'TypeName',
|
102
102
|
]);
|
103
103
|
|
104
|
-
// FIXME Implement Map property completion?
|
105
104
|
export const enum QueryType {
|
106
105
|
Expression = 0,
|
107
106
|
PropertyName = 1,
|
108
107
|
PropertyExpression = 2,
|
108
|
+
PotentiallyRetrievingFromMap = 3,
|
109
109
|
}
|
110
110
|
|
111
111
|
export function getQueryType(tree: CodeMirror.Tree, pos: number, doc: CodeMirror.Text): {
|
@@ -149,6 +149,22 @@ export function getQueryType(tree: CodeMirror.Tree, pos: number, doc: CodeMirror
|
|
149
149
|
return {type: QueryType.PropertyName, relatedNode: node};
|
150
150
|
}
|
151
151
|
}
|
152
|
+
if (node.name === '(') {
|
153
|
+
// map.get(<auto-complete>
|
154
|
+
if (parent.name === 'ArgList' && parent.parent.name === 'CallExpression') {
|
155
|
+
// map.get
|
156
|
+
const callReceiver = parent.parent.firstChild;
|
157
|
+
if (callReceiver.name === 'MemberExpression') {
|
158
|
+
// get
|
159
|
+
const propertyExpression = callReceiver.lastChild;
|
160
|
+
if (doc.sliceString(propertyExpression.from, propertyExpression.to) === 'get') {
|
161
|
+
// map
|
162
|
+
const potentiallyMapObject = callReceiver.firstChild;
|
163
|
+
return {type: QueryType.PotentiallyRetrievingFromMap, relatedNode: potentiallyMapObject};
|
164
|
+
}
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
152
168
|
return {type: QueryType.Expression};
|
153
169
|
}
|
154
170
|
|
@@ -184,6 +200,12 @@ export async function javascriptCompletionSource(cx: CodeMirror.CompletionContex
|
|
184
200
|
}
|
185
201
|
result = await completeProperties(
|
186
202
|
cx.state.sliceDoc(objectExpr.from, objectExpr.to), quote, cx.state.sliceDoc(cx.pos, cx.pos + 1) === ']');
|
203
|
+
} else if (query.type === QueryType.PotentiallyRetrievingFromMap) {
|
204
|
+
const potentialMapObject = query.relatedNode;
|
205
|
+
if (!potentialMapObject) {
|
206
|
+
return null;
|
207
|
+
}
|
208
|
+
result = await maybeCompleteKeysFromMap(cx.state.sliceDoc(potentialMapObject.from, potentialMapObject.to));
|
187
209
|
} else {
|
188
210
|
return null;
|
189
211
|
}
|
@@ -272,6 +294,29 @@ class PropertyCache {
|
|
272
294
|
}
|
273
295
|
}
|
274
296
|
|
297
|
+
async function maybeCompleteKeysFromMap(objectVariable: string): Promise<CompletionSet> {
|
298
|
+
const result = new CompletionSet();
|
299
|
+
const context = getExecutionContext();
|
300
|
+
if (!context) {
|
301
|
+
return result;
|
302
|
+
}
|
303
|
+
const maybeRetrieveKeys =
|
304
|
+
await evaluateExpression(context, `[...Map.prototype.keys.call(${objectVariable})]`, 'completion');
|
305
|
+
if (!maybeRetrieveKeys) {
|
306
|
+
return result;
|
307
|
+
}
|
308
|
+
const properties = SDK.RemoteObject.RemoteArray.objectAsArray(maybeRetrieveKeys);
|
309
|
+
const numProperties = properties.length();
|
310
|
+
for (let i = 0; i < numProperties; i++) {
|
311
|
+
result.add({
|
312
|
+
label: `"${(await properties.at(i)).value}")`,
|
313
|
+
type: 'constant',
|
314
|
+
boost: i * -1,
|
315
|
+
});
|
316
|
+
}
|
317
|
+
return result;
|
318
|
+
}
|
319
|
+
|
275
320
|
async function completeProperties(
|
276
321
|
expression: string,
|
277
322
|
quoted?: string,
|
package/package.json
CHANGED