chrome-devtools-frontend 1.0.954163 → 1.0.954716
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 +1 -0
- package/front_end/core/common/Settings.ts +10 -0
- package/front_end/core/i18n/locales/en-US.json +6 -18
- package/front_end/core/i18n/locales/en-XL.json +6 -18
- package/front_end/core/platform/string-utilities.ts +0 -180
- package/front_end/core/sdk/EmulationModel.ts +18 -19
- package/front_end/core/sdk/sdk-meta.ts +2 -39
- package/front_end/entrypoints/inspector_main/RenderingOptions.ts +13 -9
- package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +6 -0
- package/front_end/panels/application/components/BackForwardCacheView.ts +6 -4
- package/front_end/panels/console/ConsoleFormat.ts +197 -0
- package/front_end/panels/console/ConsoleViewMessage.ts +54 -155
- package/front_end/panels/console/console.ts +3 -0
- package/front_end/panels/console/consoleView.css +4 -0
- package/front_end/panels/elements/ElementsTreeElement.ts +1 -1
- package/front_end/panels/elements/elementsTreeOutline.css +5 -9
- package/front_end/panels/emulation/components/DeviceSizeInputElement.ts +5 -1
- package/front_end/panels/profiler/HeapTimelineOverview.ts +1 -1
- package/front_end/panels/sources/SourcesPanel.ts +1 -1
- package/front_end/ui/components/settings/SettingCheckbox.ts +3 -2
- package/front_end/ui/legacy/SettingsUI.ts +1 -0
- package/front_end/ui/legacy/Treeoutline.ts +4 -0
- package/front_end/ui/legacy/components/object_ui/objectValue.css +1 -1
- package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +4 -0
- package/front_end/ui/legacy/components/quick_open/QuickOpen.ts +2 -2
- package/package.json +1 -1
|
@@ -845,6 +845,7 @@ grd_files_debug_sources = [
|
|
|
845
845
|
"front_end/panels/changes/changesView.css.js",
|
|
846
846
|
"front_end/panels/console/ConsoleContextSelector.js",
|
|
847
847
|
"front_end/panels/console/ConsoleFilter.js",
|
|
848
|
+
"front_end/panels/console/ConsoleFormat.js",
|
|
848
849
|
"front_end/panels/console/ConsolePanel.js",
|
|
849
850
|
"front_end/panels/console/ConsolePinPane.js",
|
|
850
851
|
"front_end/panels/console/ConsolePrompt.js",
|
|
@@ -290,6 +290,7 @@ export class Setting<V> {
|
|
|
290
290
|
// TODO(crbug.com/1172300) Type cannot be inferred without changes to consumers. See above.
|
|
291
291
|
#serializer: Serializer<unknown, V> = JSON;
|
|
292
292
|
#hadUserAction?: boolean;
|
|
293
|
+
#disabled?: boolean;
|
|
293
294
|
|
|
294
295
|
constructor(
|
|
295
296
|
readonly name: string, readonly defaultValue: V, private readonly eventSupport: ObjectWrapper<GenericEvents>,
|
|
@@ -333,6 +334,15 @@ export class Setting<V> {
|
|
|
333
334
|
this.#requiresUserAction = requiresUserAction;
|
|
334
335
|
}
|
|
335
336
|
|
|
337
|
+
disabled(): boolean {
|
|
338
|
+
return this.#disabled || false;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
setDisabled(disabled: boolean): void {
|
|
342
|
+
this.#disabled = disabled;
|
|
343
|
+
this.eventSupport.dispatchEventToListeners(this.name);
|
|
344
|
+
}
|
|
345
|
+
|
|
336
346
|
get(): V {
|
|
337
347
|
if (this.#requiresUserAction && !this.#hadUserAction) {
|
|
338
348
|
return this.defaultValue;
|
|
@@ -581,12 +581,6 @@
|
|
|
581
581
|
"core/sdk/sdk-meta.ts | disableCache": {
|
|
582
582
|
"message": "Disable cache (while DevTools is open)"
|
|
583
583
|
},
|
|
584
|
-
"core/sdk/sdk-meta.ts | disabledDarkMode": {
|
|
585
|
-
"message": "Disable"
|
|
586
|
-
},
|
|
587
|
-
"core/sdk/sdk-meta.ts | disableEmulateAutoDarkMode": {
|
|
588
|
-
"message": "Disable auto dark mode"
|
|
589
|
-
},
|
|
590
584
|
"core/sdk/sdk-meta.ts | disableJavascript": {
|
|
591
585
|
"message": "Disable JavaScript"
|
|
592
586
|
},
|
|
@@ -617,9 +611,6 @@
|
|
|
617
611
|
"core/sdk/sdk-meta.ts | doNotEmulateCssMediaType": {
|
|
618
612
|
"message": "Do not emulate CSS media type"
|
|
619
613
|
},
|
|
620
|
-
"core/sdk/sdk-meta.ts | doNotEmulateDarkMode": {
|
|
621
|
-
"message": "Do not emulate auto dark mode"
|
|
622
|
-
},
|
|
623
614
|
"core/sdk/sdk-meta.ts | doNotExtendGridLines": {
|
|
624
615
|
"message": "Do not extend grid lines"
|
|
625
616
|
},
|
|
@@ -689,12 +680,6 @@
|
|
|
689
680
|
"core/sdk/sdk-meta.ts | enableCustomFormatters": {
|
|
690
681
|
"message": "Enable custom formatters"
|
|
691
682
|
},
|
|
692
|
-
"core/sdk/sdk-meta.ts | enabledDarkMode": {
|
|
693
|
-
"message": "Enable"
|
|
694
|
-
},
|
|
695
|
-
"core/sdk/sdk-meta.ts | enableEmulateAutoDarkMode": {
|
|
696
|
-
"message": "Enable auto dark mode"
|
|
697
|
-
},
|
|
698
683
|
"core/sdk/sdk-meta.ts | enableJavascript": {
|
|
699
684
|
"message": "Enable JavaScript"
|
|
700
685
|
},
|
|
@@ -947,11 +932,14 @@
|
|
|
947
932
|
"entrypoints/inspector_main/RenderingOptions.ts | emulateAFocusedPage": {
|
|
948
933
|
"message": "Emulate a focused page"
|
|
949
934
|
},
|
|
935
|
+
"entrypoints/inspector_main/RenderingOptions.ts | emulateAutoDarkMode": {
|
|
936
|
+
"message": "Enable automatic dark mode"
|
|
937
|
+
},
|
|
950
938
|
"entrypoints/inspector_main/RenderingOptions.ts | emulatesAFocusedPage": {
|
|
951
939
|
"message": "Emulates a focused page."
|
|
952
940
|
},
|
|
953
941
|
"entrypoints/inspector_main/RenderingOptions.ts | emulatesAutoDarkMode": {
|
|
954
|
-
"message": "Enables automatic dark mode
|
|
942
|
+
"message": "Enables automatic dark mode and sets prefers-color-scheme to dark."
|
|
955
943
|
},
|
|
956
944
|
"entrypoints/inspector_main/RenderingOptions.ts | forcesCssColorgamutMediaFeature": {
|
|
957
945
|
"message": "Forces CSS color-gamut media feature"
|
|
@@ -11924,8 +11912,8 @@
|
|
|
11924
11912
|
"ui/legacy/components/quick_open/QuickInput.ts | pressEnterToConfirmOrEscapeTo": {
|
|
11925
11913
|
"message": "{PH1} (Press 'Enter' to confirm or 'Escape' to cancel.)"
|
|
11926
11914
|
},
|
|
11927
|
-
"ui/legacy/components/quick_open/QuickOpen.ts |
|
|
11928
|
-
"message": "
|
|
11915
|
+
"ui/legacy/components/quick_open/QuickOpen.ts | typeToSeeAvailableCommands": {
|
|
11916
|
+
"message": "Type '?' to see available commands"
|
|
11929
11917
|
},
|
|
11930
11918
|
"ui/legacy/components/source_frame/FontView.ts | font": {
|
|
11931
11919
|
"message": "Font"
|
|
@@ -581,12 +581,6 @@
|
|
|
581
581
|
"core/sdk/sdk-meta.ts | disableCache": {
|
|
582
582
|
"message": "D̂íŝáb̂ĺê ćâćĥé (ŵh́îĺê D́êv́T̂óôĺŝ íŝ óp̂én̂)"
|
|
583
583
|
},
|
|
584
|
-
"core/sdk/sdk-meta.ts | disabledDarkMode": {
|
|
585
|
-
"message": "D̂íŝáb̂ĺê"
|
|
586
|
-
},
|
|
587
|
-
"core/sdk/sdk-meta.ts | disableEmulateAutoDarkMode": {
|
|
588
|
-
"message": "D̂íŝáb̂ĺê áût́ô d́âŕk̂ ḿôd́ê"
|
|
589
|
-
},
|
|
590
584
|
"core/sdk/sdk-meta.ts | disableJavascript": {
|
|
591
585
|
"message": "D̂íŝáb̂ĺê J́âv́âŚĉŕîṕt̂"
|
|
592
586
|
},
|
|
@@ -617,9 +611,6 @@
|
|
|
617
611
|
"core/sdk/sdk-meta.ts | doNotEmulateCssMediaType": {
|
|
618
612
|
"message": "D̂ó n̂ót̂ ém̂úl̂át̂é ĈŚŜ ḿêd́îá t̂ýp̂é"
|
|
619
613
|
},
|
|
620
|
-
"core/sdk/sdk-meta.ts | doNotEmulateDarkMode": {
|
|
621
|
-
"message": "D̂ó n̂ót̂ ém̂úl̂át̂é âút̂ó d̂ár̂ḱ m̂ód̂é"
|
|
622
|
-
},
|
|
623
614
|
"core/sdk/sdk-meta.ts | doNotExtendGridLines": {
|
|
624
615
|
"message": "D̂ó n̂ót̂ éx̂t́êńd̂ ǵr̂íd̂ ĺîńêś"
|
|
625
616
|
},
|
|
@@ -689,12 +680,6 @@
|
|
|
689
680
|
"core/sdk/sdk-meta.ts | enableCustomFormatters": {
|
|
690
681
|
"message": "Êńâb́l̂é ĉúŝt́ôḿ f̂ór̂ḿât́t̂ér̂ś"
|
|
691
682
|
},
|
|
692
|
-
"core/sdk/sdk-meta.ts | enabledDarkMode": {
|
|
693
|
-
"message": "Êńâb́l̂é"
|
|
694
|
-
},
|
|
695
|
-
"core/sdk/sdk-meta.ts | enableEmulateAutoDarkMode": {
|
|
696
|
-
"message": "Êńâb́l̂é âút̂ó d̂ár̂ḱ m̂ód̂é"
|
|
697
|
-
},
|
|
698
683
|
"core/sdk/sdk-meta.ts | enableJavascript": {
|
|
699
684
|
"message": "Êńâb́l̂é Ĵáv̂áŜćr̂íp̂t́"
|
|
700
685
|
},
|
|
@@ -947,11 +932,14 @@
|
|
|
947
932
|
"entrypoints/inspector_main/RenderingOptions.ts | emulateAFocusedPage": {
|
|
948
933
|
"message": "Êḿûĺât́ê á f̂óĉúŝéd̂ ṕâǵê"
|
|
949
934
|
},
|
|
935
|
+
"entrypoints/inspector_main/RenderingOptions.ts | emulateAutoDarkMode": {
|
|
936
|
+
"message": "Êńâb́l̂é âút̂óm̂át̂íĉ d́âŕk̂ ḿôd́ê"
|
|
937
|
+
},
|
|
950
938
|
"entrypoints/inspector_main/RenderingOptions.ts | emulatesAFocusedPage": {
|
|
951
939
|
"message": "Êḿûĺât́êś â f́ôćûśêd́ p̂áĝé."
|
|
952
940
|
},
|
|
953
941
|
"entrypoints/inspector_main/RenderingOptions.ts | emulatesAutoDarkMode": {
|
|
954
|
-
"message": "Êńâb́l̂éŝ áût́ôḿât́îć d̂ár̂ḱ m̂ód̂é
|
|
942
|
+
"message": "Êńâb́l̂éŝ áût́ôḿât́îć d̂ár̂ḱ m̂ód̂é âńd̂ śêt́ŝ prefers-color-scheme t́ô dark."
|
|
955
943
|
},
|
|
956
944
|
"entrypoints/inspector_main/RenderingOptions.ts | forcesCssColorgamutMediaFeature": {
|
|
957
945
|
"message": "F̂ór̂ćêś ĈŚŜ color-gamut ḿêd́îá f̂éât́ûŕê"
|
|
@@ -11924,8 +11912,8 @@
|
|
|
11924
11912
|
"ui/legacy/components/quick_open/QuickInput.ts | pressEnterToConfirmOrEscapeTo": {
|
|
11925
11913
|
"message": "{PH1} (P̂ŕêśŝ 'Én̂t́êŕ' t̂ó ĉón̂f́îŕm̂ ór̂ 'Éŝćâṕê' t́ô ćâńĉél̂.)"
|
|
11926
11914
|
},
|
|
11927
|
-
"ui/legacy/components/quick_open/QuickOpen.ts |
|
|
11928
|
-
"message": "
|
|
11915
|
+
"ui/legacy/components/quick_open/QuickOpen.ts | typeToSeeAvailableCommands": {
|
|
11916
|
+
"message": "T̂ýp̂é '?' t̂ó ŝéê áv̂áîĺâb́l̂é ĉóm̂ḿâńd̂ś"
|
|
11929
11917
|
},
|
|
11930
11918
|
"ui/legacy/components/source_frame/FontView.ts | font": {
|
|
11931
11919
|
"message": "F̂ón̂t́"
|
|
@@ -26,186 +26,6 @@ export const escapeCharacters = (inputString: string, charsToEscape: string): st
|
|
|
26
26
|
return result;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
export const enum FormatterType {
|
|
30
|
-
STRING = 'string',
|
|
31
|
-
SPECIFIER = 'specifier',
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface FormatterToken {
|
|
35
|
-
type: FormatterType;
|
|
36
|
-
value?: string|{description: string};
|
|
37
|
-
specifier?: string;
|
|
38
|
-
precision?: number;
|
|
39
|
-
substitutionIndex?: number;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const tokenizeFormatString = function(
|
|
43
|
-
formatString: string, formatters: Record<string, Function>): FormatterToken[] {
|
|
44
|
-
const tokens: FormatterToken[] = [];
|
|
45
|
-
|
|
46
|
-
function addStringToken(str: string): void {
|
|
47
|
-
if (!str) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
if (tokens.length && tokens[tokens.length - 1].type === FormatterType.STRING) {
|
|
51
|
-
tokens[tokens.length - 1].value += str;
|
|
52
|
-
} else {
|
|
53
|
-
tokens.push({
|
|
54
|
-
type: FormatterType.STRING,
|
|
55
|
-
value: str,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function addSpecifierToken(specifier: string, precision: number, substitutionIndex: number): void {
|
|
61
|
-
tokens.push({type: FormatterType.SPECIFIER, specifier, precision, substitutionIndex, value: undefined});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function addAnsiColor(code: number): void {
|
|
65
|
-
type ColorType = 'color'|'colorLight'|'bgColor'|'bgColorLight';
|
|
66
|
-
|
|
67
|
-
const types: Record<number, ColorType> = {3: 'color', 9: 'colorLight', 4: 'bgColor', 10: 'bgColorLight'};
|
|
68
|
-
const colorCodes = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'lightGray', '', 'default'];
|
|
69
|
-
const colorCodesLight =
|
|
70
|
-
['darkGray', 'lightRed', 'lightGreen', 'lightYellow', 'lightBlue', 'lightMagenta', 'lightCyan', 'white', ''];
|
|
71
|
-
const colors: Record<ColorType, string[]> =
|
|
72
|
-
{color: colorCodes, colorLight: colorCodesLight, bgColor: colorCodes, bgColorLight: colorCodesLight};
|
|
73
|
-
const type = types[Math.floor(code / 10)] as ColorType;
|
|
74
|
-
if (!type) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const color = colors[type][code % 10];
|
|
78
|
-
if (!color) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
tokens.push({
|
|
82
|
-
type: FormatterType.SPECIFIER,
|
|
83
|
-
specifier: 'c',
|
|
84
|
-
value: {description: (type.startsWith('bg') ? 'background : ' : 'color: ') + color},
|
|
85
|
-
precision: undefined,
|
|
86
|
-
substitutionIndex: undefined,
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
let textStart = 0;
|
|
91
|
-
let substitutionIndex = 0;
|
|
92
|
-
const re =
|
|
93
|
-
new RegExp(`%%|%(?:(\\d+)\\$)?(?:\\.(\\d*))?([${Object.keys(formatters).join('')}])|\\u001b\\[(\\d+)m`, 'g');
|
|
94
|
-
for (let match = re.exec(formatString); match !== null; match = re.exec(formatString)) {
|
|
95
|
-
const matchStart = match.index;
|
|
96
|
-
if (matchStart > textStart) {
|
|
97
|
-
addStringToken(formatString.substring(textStart, matchStart));
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (match[0] === '%%') {
|
|
101
|
-
addStringToken('%');
|
|
102
|
-
} else if (match[0].startsWith('%')) {
|
|
103
|
-
const [, substitionString, precisionString, specifierString] = match;
|
|
104
|
-
if (substitionString && Number(substitionString) > 0) {
|
|
105
|
-
substitutionIndex = Number(substitionString) - 1;
|
|
106
|
-
}
|
|
107
|
-
const precision = precisionString ? Number(precisionString) : -1;
|
|
108
|
-
addSpecifierToken(specifierString, precision, substitutionIndex);
|
|
109
|
-
++substitutionIndex;
|
|
110
|
-
} else {
|
|
111
|
-
const code = Number(match[4]);
|
|
112
|
-
addAnsiColor(code);
|
|
113
|
-
}
|
|
114
|
-
textStart = matchStart + match[0].length;
|
|
115
|
-
}
|
|
116
|
-
addStringToken(formatString.substring(textStart));
|
|
117
|
-
return tokens;
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
export type FormatterFunction<T> = (input: string|{description: string}|undefined|T, token: FormatterToken) => unknown;
|
|
121
|
-
|
|
122
|
-
export const format = function<T, U>(
|
|
123
|
-
formatString: string, substitutions: ArrayLike<U>|null, formatters: Record<string, FormatterFunction<U>>,
|
|
124
|
-
initialValue: T, append: (initialValue: T, newString: string) => T, tokenizedFormat?: FormatterToken[]): {
|
|
125
|
-
formattedResult: T,
|
|
126
|
-
unusedSubstitutions: ArrayLike<U>|null,
|
|
127
|
-
} {
|
|
128
|
-
if (!formatString || ((!substitutions || !substitutions.length) && formatString.search(/\u001b\[(\d+)m/) === -1)) {
|
|
129
|
-
return {formattedResult: append(initialValue, formatString), unusedSubstitutions: substitutions};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function prettyFunctionName(): string {
|
|
133
|
-
return 'String.format("' + formatString + '", "' + Array.prototype.join.call(substitutions, '", "') + '")';
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function warn(msg: string): void {
|
|
137
|
-
console.warn(prettyFunctionName() + ': ' + msg);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function error(msg: string): void {
|
|
141
|
-
console.error(prettyFunctionName() + ': ' + msg);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
let result = initialValue;
|
|
145
|
-
const tokens = tokenizedFormat || tokenizeFormatString(formatString, formatters);
|
|
146
|
-
const usedSubstitutionIndexes: Record<number, boolean> = {};
|
|
147
|
-
const actualSubstitutions: ArrayLike<U> = substitutions || [];
|
|
148
|
-
|
|
149
|
-
for (const token of tokens) {
|
|
150
|
-
if (token.type === FormatterType.STRING) {
|
|
151
|
-
result = append(result, token.value as string);
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (token.type !== FormatterType.SPECIFIER) {
|
|
156
|
-
error('Unknown token type "' + token.type + '" found.');
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (!token.value && token.substitutionIndex !== undefined &&
|
|
161
|
-
token.substitutionIndex >= actualSubstitutions.length) {
|
|
162
|
-
// If there are not enough substitutions for the current substitutionIndex
|
|
163
|
-
// just output the format specifier literally and move on.
|
|
164
|
-
error(
|
|
165
|
-
'not enough substitution arguments. Had ' + actualSubstitutions.length + ' but needed ' +
|
|
166
|
-
(token.substitutionIndex + 1) + ', so substitution was skipped.');
|
|
167
|
-
result = append(
|
|
168
|
-
result,
|
|
169
|
-
'%' + ((token.precision !== undefined && token.precision > -1) ? token.precision : '') + token.specifier);
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (!token.value && token.substitutionIndex !== undefined) {
|
|
174
|
-
usedSubstitutionIndexes[token.substitutionIndex] = true;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (token.specifier === undefined || !(token.specifier in formatters)) {
|
|
178
|
-
// Encountered an unsupported format character, treat as a string.
|
|
179
|
-
warn('unsupported format character \u201C' + token.specifier + '\u201D. Treating as a string.');
|
|
180
|
-
const stringToAppend = (token.value || token.substitutionIndex === undefined) ?
|
|
181
|
-
'' :
|
|
182
|
-
String(actualSubstitutions[token.substitutionIndex]);
|
|
183
|
-
result = append(result, stringToAppend);
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const formatter = formatters[token.specifier];
|
|
188
|
-
const valueToFormat = token.value ||
|
|
189
|
-
(token.substitutionIndex !== undefined ? actualSubstitutions[token.substitutionIndex] : undefined);
|
|
190
|
-
const stringToAppend = formatter(valueToFormat, token);
|
|
191
|
-
|
|
192
|
-
result = append(
|
|
193
|
-
result,
|
|
194
|
-
stringToAppend as string,
|
|
195
|
-
);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const unusedSubstitutions = [];
|
|
199
|
-
for (let i = 0; i < actualSubstitutions.length; ++i) {
|
|
200
|
-
if (i in usedSubstitutionIndexes) {
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
unusedSubstitutions.push(actualSubstitutions[i]);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return {formattedResult: result, unusedSubstitutions: unusedSubstitutions};
|
|
207
|
-
};
|
|
208
|
-
|
|
209
29
|
const toHexadecimal = (charCode: number, padToLength: number): string => {
|
|
210
30
|
return charCode.toString(16).toUpperCase().padStart(padToLength, '0');
|
|
211
31
|
};
|
|
@@ -126,9 +126,16 @@ export class EmulationModel extends SDKModel<void> {
|
|
|
126
126
|
this.updateCssMedia();
|
|
127
127
|
|
|
128
128
|
const autoDarkModeSetting = Common.Settings.Settings.instance().moduleSetting('emulateAutoDarkMode');
|
|
129
|
-
autoDarkModeSetting.addChangeListener(() =>
|
|
129
|
+
autoDarkModeSetting.addChangeListener(() => {
|
|
130
|
+
const enabled = autoDarkModeSetting.get();
|
|
131
|
+
mediaFeaturePrefersColorSchemeSetting.setDisabled(enabled);
|
|
132
|
+
mediaFeaturePrefersColorSchemeSetting.set(enabled ? 'dark' : '');
|
|
133
|
+
this.emulateAutoDarkMode(enabled);
|
|
134
|
+
});
|
|
130
135
|
if (autoDarkModeSetting.get()) {
|
|
131
|
-
|
|
136
|
+
mediaFeaturePrefersColorSchemeSetting.setDisabled(true);
|
|
137
|
+
mediaFeaturePrefersColorSchemeSetting.set('dark');
|
|
138
|
+
this.emulateAutoDarkMode(true);
|
|
132
139
|
}
|
|
133
140
|
|
|
134
141
|
const visionDeficiencySetting = Common.Settings.Settings.instance().moduleSetting('emulatedVisionDeficiency');
|
|
@@ -277,22 +284,14 @@ export class EmulationModel extends SDKModel<void> {
|
|
|
277
284
|
}
|
|
278
285
|
}
|
|
279
286
|
|
|
280
|
-
private
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
case 'enabled':
|
|
285
|
-
return true;
|
|
286
|
-
case 'disabled':
|
|
287
|
-
return false;
|
|
288
|
-
default:
|
|
289
|
-
throw Error('unrecognized auto dark mode setting');
|
|
287
|
+
private async emulateAutoDarkMode(enabled: boolean): Promise<void> {
|
|
288
|
+
if (enabled) {
|
|
289
|
+
this.#mediaConfiguration.set('prefers-color-scheme', 'dark');
|
|
290
|
+
await this.updateCssMedia();
|
|
290
291
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const enabled = EmulationModel.parseAutoDarkModeSetting(setting);
|
|
295
|
-
await this.#emulationAgent.invoke_setAutoDarkModeOverride({enabled});
|
|
292
|
+
// We never send `enabled: false` since that would explicitly disable
|
|
293
|
+
// autodark mode. We either enable it or clear any existing override.
|
|
294
|
+
await this.#emulationAgent.invoke_setAutoDarkModeOverride({enabled: enabled || undefined});
|
|
296
295
|
}
|
|
297
296
|
|
|
298
297
|
private async emulateVisionDeficiency(type: Protocol.Emulation.SetEmulatedVisionDeficiencyRequestType):
|
|
@@ -360,7 +359,7 @@ export class EmulationModel extends SDKModel<void> {
|
|
|
360
359
|
{enabled: configuration.enabled, configuration: configuration.configuration});
|
|
361
360
|
}
|
|
362
361
|
|
|
363
|
-
private updateCssMedia(): void {
|
|
362
|
+
private async updateCssMedia(): Promise<void> {
|
|
364
363
|
// See the note above, where this.#mediaConfiguration is defined.
|
|
365
364
|
const type = this.#mediaConfiguration.get('type') ?? '';
|
|
366
365
|
const features = [
|
|
@@ -389,7 +388,7 @@ export class EmulationModel extends SDKModel<void> {
|
|
|
389
388
|
value: this.#mediaConfiguration.get('prefers-reduced-motion') ?? '',
|
|
390
389
|
},
|
|
391
390
|
];
|
|
392
|
-
this.emulateCSSMedia(type, features);
|
|
391
|
+
return this.emulateCSSMedia(type, features);
|
|
393
392
|
}
|
|
394
393
|
}
|
|
395
394
|
|
|
@@ -314,26 +314,6 @@ const UIStrings = {
|
|
|
314
314
|
* emulates that the webpage is in auto dark mode.
|
|
315
315
|
*/
|
|
316
316
|
emulateAutoDarkMode: 'Emulate auto dark mode',
|
|
317
|
-
/**
|
|
318
|
-
* @description Title of a setting for enabling auto dark mode.
|
|
319
|
-
*/
|
|
320
|
-
enableEmulateAutoDarkMode: 'Enable auto dark mode',
|
|
321
|
-
/**
|
|
322
|
-
* @description Text to emulate enabled auto dark mode.
|
|
323
|
-
*/
|
|
324
|
-
enabledDarkMode: 'Enable',
|
|
325
|
-
/**
|
|
326
|
-
* @description Title of a setting for disabling auto dark mode.
|
|
327
|
-
*/
|
|
328
|
-
disableEmulateAutoDarkMode: 'Disable auto dark mode',
|
|
329
|
-
/**
|
|
330
|
-
* @description Text to emulate disabled auto dark mode.
|
|
331
|
-
*/
|
|
332
|
-
disabledDarkMode: 'Disable',
|
|
333
|
-
/**
|
|
334
|
-
* @description Title of a setting for disabling dark mode emulation.
|
|
335
|
-
*/
|
|
336
|
-
doNotEmulateDarkMode: 'Do not emulate auto dark mode',
|
|
337
317
|
};
|
|
338
318
|
const str_ = i18n.i18n.registerUIStrings('core/sdk/sdk-meta.ts', UIStrings);
|
|
339
319
|
const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
|
|
@@ -1049,24 +1029,7 @@ Common.Settings.registerSettingExtension({
|
|
|
1049
1029
|
category: Common.Settings.SettingCategory.RENDERING,
|
|
1050
1030
|
title: i18nLazyString(UIStrings.emulateAutoDarkMode),
|
|
1051
1031
|
settingName: 'emulateAutoDarkMode',
|
|
1052
|
-
settingType: Common.Settings.SettingType.
|
|
1032
|
+
settingType: Common.Settings.SettingType.BOOLEAN,
|
|
1053
1033
|
storageType: Common.Settings.SettingStorageType.Session,
|
|
1054
|
-
defaultValue:
|
|
1055
|
-
options: [
|
|
1056
|
-
{
|
|
1057
|
-
title: i18nLazyString(UIStrings.doNotEmulateDarkMode),
|
|
1058
|
-
text: i18nLazyString(UIStrings.noEmulation),
|
|
1059
|
-
value: 'default',
|
|
1060
|
-
},
|
|
1061
|
-
{
|
|
1062
|
-
title: i18nLazyString(UIStrings.enableEmulateAutoDarkMode),
|
|
1063
|
-
text: i18nLazyString(UIStrings.enabledDarkMode),
|
|
1064
|
-
value: 'enabled',
|
|
1065
|
-
},
|
|
1066
|
-
{
|
|
1067
|
-
title: i18nLazyString(UIStrings.disableEmulateAutoDarkMode),
|
|
1068
|
-
text: i18nLazyString(UIStrings.disabledDarkMode),
|
|
1069
|
-
value: 'disabled',
|
|
1070
|
-
},
|
|
1071
|
-
],
|
|
1034
|
+
defaultValue: false,
|
|
1072
1035
|
});
|
|
@@ -124,9 +124,13 @@ const UIStrings = {
|
|
|
124
124
|
*/
|
|
125
125
|
emulatesAFocusedPage: 'Emulates a focused page.',
|
|
126
126
|
/**
|
|
127
|
-
* @description
|
|
127
|
+
* @description The name of a checkbox setting in the Rendering tool. This setting enables auto dark mode emulation.
|
|
128
|
+
*/
|
|
129
|
+
emulateAutoDarkMode: 'Enable automatic dark mode',
|
|
130
|
+
/**
|
|
131
|
+
* @description Explanation text for the 'Emulate automatic dark mode' setting in the Rendering tool.
|
|
128
132
|
*/
|
|
129
|
-
emulatesAutoDarkMode: 'Enables automatic dark mode
|
|
133
|
+
emulatesAutoDarkMode: 'Enables automatic dark mode and sets `prefers-color-scheme` to `dark`.',
|
|
130
134
|
/**
|
|
131
135
|
* @description Explanation text for the 'Emulate CSS media type' setting in the Rendering tool.
|
|
132
136
|
* This setting overrides the CSS media type on the page:
|
|
@@ -245,14 +249,18 @@ export class RenderingOptionsView extends UI.Widget.VBox {
|
|
|
245
249
|
this.#appendCheckbox(
|
|
246
250
|
i18nString(UIStrings.emulateAFocusedPage), i18nString(UIStrings.emulatesAFocusedPage),
|
|
247
251
|
Common.Settings.Settings.instance().moduleSetting('emulatePageFocus'));
|
|
252
|
+
this.#appendCheckbox(
|
|
253
|
+
i18nString(UIStrings.emulateAutoDarkMode), i18nString(UIStrings.emulatesAutoDarkMode),
|
|
254
|
+
Common.Settings.Settings.instance().moduleSetting('emulateAutoDarkMode'));
|
|
255
|
+
|
|
248
256
|
this.contentElement.createChild('div').classList.add('panel-section-separator');
|
|
249
257
|
|
|
250
|
-
this.#appendSelect(
|
|
251
|
-
i18nString(UIStrings.forcesMediaTypeForTestingPrint),
|
|
252
|
-
Common.Settings.Settings.instance().moduleSetting('emulatedCSSMedia'));
|
|
253
258
|
this.#appendSelect(
|
|
254
259
|
i18nString(UIStrings.forcesCssPreferscolorschemeMedia),
|
|
255
260
|
Common.Settings.Settings.instance().moduleSetting('emulatedCSSMediaFeaturePrefersColorScheme'));
|
|
261
|
+
this.#appendSelect(
|
|
262
|
+
i18nString(UIStrings.forcesMediaTypeForTestingPrint),
|
|
263
|
+
Common.Settings.Settings.instance().moduleSetting('emulatedCSSMedia'));
|
|
256
264
|
this.#appendSelect(
|
|
257
265
|
i18nString(UIStrings.forcesCssForcedColors),
|
|
258
266
|
Common.Settings.Settings.instance().moduleSetting('emulatedCSSMediaFeatureForcedColors'));
|
|
@@ -279,10 +287,6 @@ export class RenderingOptionsView extends UI.Widget.VBox {
|
|
|
279
287
|
Common.Settings.Settings.instance().moduleSetting('emulatedVisionDeficiency'));
|
|
280
288
|
|
|
281
289
|
this.contentElement.createChild('div').classList.add('panel-section-separator');
|
|
282
|
-
this.#appendSelect(
|
|
283
|
-
i18nString(UIStrings.emulatesAutoDarkMode),
|
|
284
|
-
Common.Settings.Settings.instance().moduleSetting('emulateAutoDarkMode'));
|
|
285
|
-
this.contentElement.createChild('div').classList.add('panel-section-separator');
|
|
286
290
|
|
|
287
291
|
this.#appendCheckbox(
|
|
288
292
|
i18nString(UIStrings.disableAvifImageFormat), i18nString(UIStrings.requiresAPageReloadToApplyAnd),
|
|
@@ -120,6 +120,12 @@ export class DebuggerWorkspaceBinding implements SDK.TargetManager.SDKModelObser
|
|
|
120
120
|
if (!compilerMapping) {
|
|
121
121
|
return [];
|
|
122
122
|
}
|
|
123
|
+
if (mode === SDK.DebuggerModel.StepMode.StepOut) {
|
|
124
|
+
// We should actually return the source range for the entire function
|
|
125
|
+
// to skip over. Since we don't have that, we return an empty range
|
|
126
|
+
// instead, to signal that we should perform a regular step-out.
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
123
129
|
ranges = compilerMapping.getLocationRangesForSameSourceLocation(rawLocation);
|
|
124
130
|
ranges = ranges.filter(range => contained(rawLocation, range));
|
|
125
131
|
return ranges;
|
|
@@ -238,7 +238,9 @@ export class BackForwardCacheView extends HTMLElement {
|
|
|
238
238
|
`;
|
|
239
239
|
// clang-format on
|
|
240
240
|
}
|
|
241
|
-
const
|
|
241
|
+
const isTestRunning = (this.#screenStatus === ScreenStatusType.Running);
|
|
242
|
+
// Prevent running BFCache test on the DevTools window itself via DevTools on DevTools
|
|
243
|
+
const isTestingForbidden = this.#frame.url.startsWith('devtools://');
|
|
242
244
|
// clang-format off
|
|
243
245
|
return LitHtml.html`
|
|
244
246
|
${this.#renderBackForwardCacheStatus(this.#frame.backForwardCacheDetails.restoredFromCache)}
|
|
@@ -252,11 +254,11 @@ export class BackForwardCacheView extends HTMLElement {
|
|
|
252
254
|
</div>
|
|
253
255
|
<${ReportView.ReportView.ReportSection.litTagName}>
|
|
254
256
|
<${Buttons.Button.Button.litTagName}
|
|
255
|
-
.disabled=${
|
|
256
|
-
.spinner=${
|
|
257
|
+
.disabled=${isTestRunning || isTestingForbidden}
|
|
258
|
+
.spinner=${isTestRunning}
|
|
257
259
|
.variant=${Buttons.Button.Variant.PRIMARY}
|
|
258
260
|
@click=${this.#navigateAwayAndBack}>
|
|
259
|
-
${
|
|
261
|
+
${isTestRunning ? LitHtml.html`
|
|
260
262
|
${i18nString(UIStrings.runningTest)}`:`
|
|
261
263
|
${i18nString(UIStrings.runTest)}
|
|
262
264
|
`}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// Copyright 2021 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 type * as SDK from '../../core/sdk/sdk.js';
|
|
6
|
+
|
|
7
|
+
// VGA color palette
|
|
8
|
+
const ANSI_COLORS = ['#000000', '#AA0000', '#00AA00', '#AA5500', '#0000AA', '#AA00AA', '#00AAAA', '#AAAAAA'];
|
|
9
|
+
const ANSI_BRIGHT_COLORS = ['#555555', '#FF5555', '#55FF55', '#FFFF55', '#5555FF', '#FF55FF', '#55FFFF', '#FFFFFF'];
|
|
10
|
+
|
|
11
|
+
export type FormatToken = {
|
|
12
|
+
type: 'generic'|'optimal',
|
|
13
|
+
value: SDK.RemoteObject.RemoteObject,
|
|
14
|
+
}|{
|
|
15
|
+
type: 'string' | 'style',
|
|
16
|
+
value: string,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* This is the front-end part of the Formatter function specified in the
|
|
21
|
+
* Console Standard (https://console.spec.whatwg.org/#formatter). Here we
|
|
22
|
+
* assume that all type conversions have already happened in V8 before and
|
|
23
|
+
* are only concerned with performing the actual substitutions and dealing
|
|
24
|
+
* with generic and optimal object formatting as well as styling.
|
|
25
|
+
*
|
|
26
|
+
* @param fmt the format string.
|
|
27
|
+
* @param args the substitution arguments for `fmt`.
|
|
28
|
+
* @returns a list of `FormatToken`s as well as the unused arguments.
|
|
29
|
+
*/
|
|
30
|
+
export const format = (fmt: string, args: SDK.RemoteObject.RemoteObject[]): {
|
|
31
|
+
tokens: FormatToken[],
|
|
32
|
+
args: SDK.RemoteObject.RemoteObject[],
|
|
33
|
+
} => {
|
|
34
|
+
const tokens: FormatToken[] = [];
|
|
35
|
+
|
|
36
|
+
// Current maintained style for ANSI color codes.
|
|
37
|
+
const currentStyle = new Map<string, string>();
|
|
38
|
+
function addTextDecoration(value: string): void {
|
|
39
|
+
const textDecoration = currentStyle.get('text-decoration') ?? '';
|
|
40
|
+
if (!textDecoration.includes(value)) {
|
|
41
|
+
currentStyle.set('text-decoration', `${textDecoration} ${value}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function removeTextDecoration(value: string): void {
|
|
45
|
+
const textDecoration = currentStyle.get('text-decoration')?.replace(` ${value}`, '');
|
|
46
|
+
if (textDecoration) {
|
|
47
|
+
currentStyle.set('text-decoration', textDecoration);
|
|
48
|
+
} else {
|
|
49
|
+
currentStyle.delete('text-decoration');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function addStringToken(value: string): void {
|
|
54
|
+
if (!value) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (tokens.length && tokens[tokens.length - 1].type === 'string') {
|
|
58
|
+
tokens[tokens.length - 1].value += value;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
tokens.push({type: 'string', value});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let argIndex = 0;
|
|
65
|
+
const re = /%([%_Oocsdfi])|\x1B\[([\d;]*)m/;
|
|
66
|
+
for (let match = re.exec(fmt); match !== null; match = re.exec(fmt)) {
|
|
67
|
+
addStringToken(match.input.substring(0, match.index));
|
|
68
|
+
let substitution: number|string|undefined = undefined;
|
|
69
|
+
const specifier = match[1];
|
|
70
|
+
switch (specifier) {
|
|
71
|
+
case '%':
|
|
72
|
+
addStringToken('%');
|
|
73
|
+
substitution = '';
|
|
74
|
+
break;
|
|
75
|
+
case 's':
|
|
76
|
+
if (argIndex < args.length) {
|
|
77
|
+
const {description} = args[argIndex++];
|
|
78
|
+
substitution = description ?? '';
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
case 'c':
|
|
82
|
+
if (argIndex < args.length) {
|
|
83
|
+
const type = 'style';
|
|
84
|
+
const value = args[argIndex++].description ?? '';
|
|
85
|
+
tokens.push({type, value});
|
|
86
|
+
substitution = '';
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
case 'o':
|
|
90
|
+
case 'O':
|
|
91
|
+
if (argIndex < args.length) {
|
|
92
|
+
const type = specifier === 'O' ? 'generic' : 'optimal';
|
|
93
|
+
const value = args[argIndex++];
|
|
94
|
+
tokens.push({type, value});
|
|
95
|
+
substitution = '';
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
case '_':
|
|
99
|
+
if (argIndex < args.length) {
|
|
100
|
+
argIndex++;
|
|
101
|
+
substitution = '';
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
case 'd':
|
|
105
|
+
case 'f':
|
|
106
|
+
case 'i':
|
|
107
|
+
if (argIndex < args.length) {
|
|
108
|
+
const {value} = args[argIndex++];
|
|
109
|
+
substitution = typeof value !== 'number' ? NaN : value;
|
|
110
|
+
if (specifier !== 'f') {
|
|
111
|
+
substitution = Math.floor(substitution);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
case undefined: {
|
|
116
|
+
const codes = (match[2] || '0').split(';').map(code => code ? parseInt(code, 10) : 0);
|
|
117
|
+
while (codes.length) {
|
|
118
|
+
const code = codes.shift() as number;
|
|
119
|
+
switch (code) {
|
|
120
|
+
case 0:
|
|
121
|
+
currentStyle.clear();
|
|
122
|
+
break;
|
|
123
|
+
case 1:
|
|
124
|
+
currentStyle.set('font-weight', 'bold');
|
|
125
|
+
break;
|
|
126
|
+
case 2:
|
|
127
|
+
currentStyle.set('font-weight', 'lighter');
|
|
128
|
+
break;
|
|
129
|
+
case 3:
|
|
130
|
+
currentStyle.set('font-style', 'italic');
|
|
131
|
+
break;
|
|
132
|
+
case 4:
|
|
133
|
+
addTextDecoration('underline');
|
|
134
|
+
break;
|
|
135
|
+
case 9:
|
|
136
|
+
addTextDecoration('line-through');
|
|
137
|
+
break;
|
|
138
|
+
case 22:
|
|
139
|
+
currentStyle.delete('font-weight');
|
|
140
|
+
break;
|
|
141
|
+
case 23:
|
|
142
|
+
currentStyle.delete('font-style');
|
|
143
|
+
break;
|
|
144
|
+
case 24:
|
|
145
|
+
removeTextDecoration('underline');
|
|
146
|
+
break;
|
|
147
|
+
case 29:
|
|
148
|
+
removeTextDecoration('line-through');
|
|
149
|
+
break;
|
|
150
|
+
case 38:
|
|
151
|
+
case 48:
|
|
152
|
+
if (codes.shift() === 2) {
|
|
153
|
+
const r = codes.shift() ?? 0, g = codes.shift() ?? 0, b = codes.shift() ?? 0;
|
|
154
|
+
currentStyle.set(code === 38 ? 'color' : 'background', `rgb(${r},${g},${b})`);
|
|
155
|
+
}
|
|
156
|
+
break;
|
|
157
|
+
case 39:
|
|
158
|
+
case 49:
|
|
159
|
+
currentStyle.delete(code === 39 ? 'color' : 'background');
|
|
160
|
+
break;
|
|
161
|
+
case 53:
|
|
162
|
+
addTextDecoration('overline');
|
|
163
|
+
break;
|
|
164
|
+
case 55:
|
|
165
|
+
removeTextDecoration('overline');
|
|
166
|
+
break;
|
|
167
|
+
default: {
|
|
168
|
+
const color = ANSI_COLORS[code - 30] ?? ANSI_BRIGHT_COLORS[code - 90];
|
|
169
|
+
if (color !== undefined) {
|
|
170
|
+
currentStyle.set('color', color);
|
|
171
|
+
} else {
|
|
172
|
+
const background = ANSI_COLORS[code - 40] ?? ANSI_BRIGHT_COLORS[code - 100];
|
|
173
|
+
if (background !== undefined) {
|
|
174
|
+
currentStyle.set('background', background);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const value = [...currentStyle.entries()].map(([key, val]) => `${key}:${val.trimStart()}`).join(';');
|
|
182
|
+
const type = 'style';
|
|
183
|
+
tokens.push({type, value});
|
|
184
|
+
substitution = '';
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (substitution === undefined) {
|
|
189
|
+
// If there's no substitution, emit the original specifier / sequence verbatim.
|
|
190
|
+
addStringToken(match[0]);
|
|
191
|
+
substitution = '';
|
|
192
|
+
}
|
|
193
|
+
fmt = substitution + match.input.substring(match.index + match[0].length);
|
|
194
|
+
}
|
|
195
|
+
addStringToken(fmt);
|
|
196
|
+
return {tokens, args: args.slice(argIndex)};
|
|
197
|
+
};
|
|
@@ -53,6 +53,7 @@ import * as UI from '../../ui/legacy/legacy.js';
|
|
|
53
53
|
import objectValueStyles from '../../ui/legacy/components/object_ui/objectValue.css.js';
|
|
54
54
|
import type {Chrome} from '../../../extension-api/ExtensionAPI.js'; // eslint-disable-line rulesdir/es_modules_import
|
|
55
55
|
|
|
56
|
+
import {format} from './ConsoleFormat.js';
|
|
56
57
|
import type {ConsoleViewportElement} from './ConsoleViewport.js';
|
|
57
58
|
import consoleViewStyles from './consoleView.css.js';
|
|
58
59
|
|
|
@@ -586,9 +587,8 @@ export class ConsoleViewMessage implements ConsoleViewportElement {
|
|
|
586
587
|
|
|
587
588
|
// Multiple parameters with the first being a format string. Save unused substitutions.
|
|
588
589
|
if (shouldFormatMessage) {
|
|
589
|
-
|
|
590
|
+
parameters = this.formatWithSubstitutionString(
|
|
590
591
|
(parameters[0].description as string), parameters.slice(1), formattedResult);
|
|
591
|
-
parameters = Array.from(result.unusedSubstitutions || []);
|
|
592
592
|
if (parameters.length) {
|
|
593
593
|
UI.UIUtils.createTextChild(formattedResult, ' ');
|
|
594
594
|
}
|
|
@@ -866,165 +866,64 @@ export class ConsoleViewMessage implements ConsoleViewportElement {
|
|
|
866
866
|
}
|
|
867
867
|
|
|
868
868
|
private formatWithSubstitutionString(
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
}
|
|
879
|
-
return stringFormatter(obj);
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
function stringFormatter(obj?: string|SDK.RemoteObject.RemoteObject): string|undefined {
|
|
883
|
-
if (obj === undefined) {
|
|
884
|
-
return undefined;
|
|
885
|
-
}
|
|
886
|
-
if (typeof obj === 'string') {
|
|
887
|
-
return obj;
|
|
888
|
-
}
|
|
889
|
-
return obj.description;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
function floatFormatter(obj?: string|SDK.RemoteObject.RemoteObject): number|string|undefined {
|
|
893
|
-
if (obj instanceof SDK.RemoteObject.RemoteObject) {
|
|
894
|
-
if (typeof obj.value !== 'number') {
|
|
895
|
-
return 'NaN';
|
|
896
|
-
}
|
|
897
|
-
return obj.value;
|
|
898
|
-
}
|
|
899
|
-
return undefined;
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
function integerFormatter(obj?: string|SDK.RemoteObject.RemoteObject): string|number|undefined {
|
|
903
|
-
if (obj instanceof SDK.RemoteObject.RemoteObject) {
|
|
904
|
-
if (obj.type === 'bigint') {
|
|
905
|
-
return obj.description;
|
|
906
|
-
}
|
|
907
|
-
if (typeof obj.value !== 'number') {
|
|
908
|
-
return 'NaN';
|
|
869
|
+
formatString: string, parameters: SDK.RemoteObject.RemoteObject[],
|
|
870
|
+
formattedResult: HTMLElement): SDK.RemoteObject.RemoteObject[] {
|
|
871
|
+
const currentStyle = new Map();
|
|
872
|
+
const {tokens, args} = format(formatString, parameters);
|
|
873
|
+
for (const token of tokens) {
|
|
874
|
+
switch (token.type) {
|
|
875
|
+
case 'generic': {
|
|
876
|
+
formattedResult.append(this.formatParameter(token.value, true /* force */, false /* includePreview */));
|
|
877
|
+
break;
|
|
909
878
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
function bypassFormatter(obj?: string|SDK.RemoteObject.RemoteObject): Node|string {
|
|
916
|
-
return (obj instanceof Node) ? obj : '';
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
let currentStyle: Map<string, {value: string, priority: string}>|null = null;
|
|
920
|
-
function styleFormatter(obj?: string|SDK.RemoteObject.RemoteObject): void {
|
|
921
|
-
currentStyle = new Map();
|
|
922
|
-
const buffer = document.createElement('span');
|
|
923
|
-
if (obj === undefined) {
|
|
924
|
-
return;
|
|
925
|
-
}
|
|
926
|
-
if (typeof obj === 'string' || !obj.description) {
|
|
927
|
-
return;
|
|
928
|
-
}
|
|
929
|
-
buffer.setAttribute('style', obj.description);
|
|
930
|
-
for (const property of buffer.style) {
|
|
931
|
-
if (isAllowedProperty(property)) {
|
|
932
|
-
const info = {
|
|
933
|
-
value: buffer.style.getPropertyValue(property),
|
|
934
|
-
priority: buffer.style.getPropertyPriority(property),
|
|
935
|
-
};
|
|
936
|
-
currentStyle.set(property, info);
|
|
879
|
+
case 'optimal': {
|
|
880
|
+
formattedResult.append(this.formatParameter(token.value, false /* force */, true /* includePreview */));
|
|
881
|
+
break;
|
|
937
882
|
}
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
for (const prefix of prefixes) {
|
|
960
|
-
if (property.startsWith(prefix)) {
|
|
961
|
-
return true;
|
|
883
|
+
case 'string': {
|
|
884
|
+
if (currentStyle.size === 0) {
|
|
885
|
+
formattedResult.append(this.linkifyStringAsFragment(token.value));
|
|
886
|
+
} else {
|
|
887
|
+
const lines = token.value.split('\n');
|
|
888
|
+
for (let i = 0; i < lines.length; i++) {
|
|
889
|
+
if (i > 0) {
|
|
890
|
+
formattedResult.append(document.createElement('br'));
|
|
891
|
+
}
|
|
892
|
+
const wrapper = document.createElement('span');
|
|
893
|
+
wrapper.style.setProperty('contain', 'paint');
|
|
894
|
+
wrapper.style.setProperty('display', 'inline-block');
|
|
895
|
+
wrapper.style.setProperty('max-width', '100%');
|
|
896
|
+
wrapper.appendChild(this.linkifyStringAsFragment(lines[i]));
|
|
897
|
+
for (const [property, {value, priority}] of currentStyle) {
|
|
898
|
+
wrapper.style.setProperty(property, value, priority);
|
|
899
|
+
}
|
|
900
|
+
formattedResult.append(wrapper);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
break;
|
|
962
904
|
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
// Support %O to force object formatting, instead of the type-based %o formatting.
|
|
982
|
-
formatters.O = parameterFormatter.bind(this, true /* force */, false /* includePreview */);
|
|
983
|
-
|
|
984
|
-
formatters._ = bypassFormatter;
|
|
985
|
-
|
|
986
|
-
function append(this: ConsoleViewMessage, a: HTMLElement, b?: string|Node): HTMLElement {
|
|
987
|
-
if (b instanceof Node) {
|
|
988
|
-
a.appendChild(b);
|
|
989
|
-
return a;
|
|
990
|
-
}
|
|
991
|
-
if (typeof b === 'undefined') {
|
|
992
|
-
return a;
|
|
993
|
-
}
|
|
994
|
-
if (!currentStyle) {
|
|
995
|
-
a.appendChild(this.linkifyStringAsFragment(String(b)));
|
|
996
|
-
return a;
|
|
997
|
-
}
|
|
998
|
-
const lines = String(b).split('\n');
|
|
999
|
-
for (let i = 0; i < lines.length; i++) {
|
|
1000
|
-
const line = lines[i];
|
|
1001
|
-
const lineFragment = this.linkifyStringAsFragment(line);
|
|
1002
|
-
const wrapper = document.createElement('span');
|
|
1003
|
-
wrapper.style.setProperty('contain', 'paint');
|
|
1004
|
-
wrapper.style.setProperty('display', 'inline-block');
|
|
1005
|
-
wrapper.style.setProperty('max-width', '100%');
|
|
1006
|
-
wrapper.appendChild(lineFragment);
|
|
1007
|
-
applyCurrentStyle(wrapper);
|
|
1008
|
-
|
|
1009
|
-
a.appendChild(wrapper);
|
|
1010
|
-
if (i < lines.length - 1) {
|
|
1011
|
-
a.appendChild(document.createElement('br'));
|
|
905
|
+
case 'style': {
|
|
906
|
+
// Make sure that allowed properties do not interfere with link visibility.
|
|
907
|
+
const ALLOWED_PROPERTY_PREFIXES =
|
|
908
|
+
['background', 'border', 'color', 'font', 'line', 'margin', 'padding', 'text'];
|
|
909
|
+
currentStyle.clear();
|
|
910
|
+
const buffer = document.createElement('span');
|
|
911
|
+
buffer.setAttribute('style', token.value);
|
|
912
|
+
for (const property of buffer.style) {
|
|
913
|
+
if (!ALLOWED_PROPERTY_PREFIXES.some(
|
|
914
|
+
prefix => property.startsWith(prefix) || property.startsWith(`-webkit-${prefix}`))) {
|
|
915
|
+
continue;
|
|
916
|
+
}
|
|
917
|
+
currentStyle.set(property, {
|
|
918
|
+
value: buffer.style.getPropertyValue(property),
|
|
919
|
+
priority: buffer.style.getPropertyPriority(property),
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
break;
|
|
1012
923
|
}
|
|
1013
924
|
}
|
|
1014
|
-
return a;
|
|
1015
925
|
}
|
|
1016
|
-
|
|
1017
|
-
function applyCurrentStyle(element: HTMLElement): void {
|
|
1018
|
-
if (!currentStyle) {
|
|
1019
|
-
return;
|
|
1020
|
-
}
|
|
1021
|
-
for (const [property, {value, priority}] of currentStyle.entries()) {
|
|
1022
|
-
element.style.setProperty((property as string), value, priority);
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
// Platform.StringUtilities.format does treat formattedResult like a Builder, result is an object.
|
|
1027
|
-
return Platform.StringUtilities.format(format, parameters, formatters, formattedResult, append.bind(this));
|
|
926
|
+
return args;
|
|
1028
927
|
}
|
|
1029
928
|
|
|
1030
929
|
matchesFilterRegex(regexObject: RegExp): boolean {
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import './ConsoleContextSelector.js';
|
|
6
6
|
import './ConsoleFilter.js';
|
|
7
|
+
import './ConsoleFormat.js';
|
|
7
8
|
import './ConsolePinPane.js';
|
|
8
9
|
import './ConsoleSidebar.js';
|
|
9
10
|
import './ConsoleViewport.js';
|
|
@@ -14,6 +15,7 @@ import './ConsolePanel.js';
|
|
|
14
15
|
|
|
15
16
|
import * as ConsoleContextSelector from './ConsoleContextSelector.js';
|
|
16
17
|
import * as ConsoleFilter from './ConsoleFilter.js';
|
|
18
|
+
import * as ConsoleFormat from './ConsoleFormat.js';
|
|
17
19
|
import * as ConsolePanel from './ConsolePanel.js';
|
|
18
20
|
import * as ConsolePinPane from './ConsolePinPane.js';
|
|
19
21
|
import * as ConsolePrompt from './ConsolePrompt.js';
|
|
@@ -25,6 +27,7 @@ import * as ConsoleViewport from './ConsoleViewport.js';
|
|
|
25
27
|
export {
|
|
26
28
|
ConsoleContextSelector,
|
|
27
29
|
ConsoleFilter,
|
|
30
|
+
ConsoleFormat,
|
|
28
31
|
ConsolePanel,
|
|
29
32
|
ConsolePinPane,
|
|
30
33
|
ConsolePrompt,
|
|
@@ -375,6 +375,10 @@
|
|
|
375
375
|
flex-shrink: 0;
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
+
.console-message-text .object-value-node {
|
|
379
|
+
display: inline-block;
|
|
380
|
+
}
|
|
381
|
+
|
|
378
382
|
.console-message-text .object-value-string,
|
|
379
383
|
.console-message-text .object-value-regexp,
|
|
380
384
|
.console-message-text .object-value-symbol {
|
|
@@ -1334,7 +1334,7 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1334
1334
|
}
|
|
1335
1335
|
|
|
1336
1336
|
/** Keep it in sync with elementsTreeOutline.css **/
|
|
1337
|
-
return 12 * (depth - 2) + (this.isExpandable() ? 1 : 12);
|
|
1337
|
+
return 12 * (depth - 2) + (this.isExpandable() && this.isCollapsible() ? 1 : 12);
|
|
1338
1338
|
}
|
|
1339
1339
|
|
|
1340
1340
|
updateDecorations(): void {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
.elements-disclosure li {
|
|
37
|
-
/** Keep margin-left & padding-left in sync with ElementsTreeElements.
|
|
37
|
+
/** Keep margin-left & padding-left in sync with ElementsTreeElements.updateDecorations **/
|
|
38
38
|
padding: 1px 0 0 14px;
|
|
39
39
|
margin-left: -2px;
|
|
40
40
|
word-break: normal;
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
min-width: 200px;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
.elements-disclosure li.parent {
|
|
48
|
-
/** Keep it in sync with ElementsTreeElements.
|
|
47
|
+
.elements-disclosure li.parent:not(.always-parent) {
|
|
48
|
+
/** Keep it in sync with ElementsTreeElements.updateDecorations **/
|
|
49
49
|
margin-left: -13px;
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
opacity: 60%;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
.elements-disclosure li.parent::before {
|
|
65
|
+
.elements-disclosure li.parent:not(.always-parent)::before {
|
|
66
66
|
box-sizing: border-box;
|
|
67
67
|
user-select: none;
|
|
68
68
|
-webkit-mask-image: var(--image-file-treeoutlineTriangles);
|
|
@@ -79,10 +79,6 @@
|
|
|
79
79
|
-webkit-mask-position: -16px 0;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
.elements-disclosure li.always-parent::before {
|
|
83
|
-
visibility: hidden;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
82
|
.elements-disclosure li .selection {
|
|
87
83
|
display: none;
|
|
88
84
|
z-index: -1;
|
|
@@ -126,7 +122,7 @@
|
|
|
126
122
|
|
|
127
123
|
.elements-disclosure ol {
|
|
128
124
|
list-style-type: none;
|
|
129
|
-
/** Keep it in sync with ElementsTreeElements.
|
|
125
|
+
/** Keep it in sync with ElementsTreeElements.updateDecorations **/
|
|
130
126
|
padding-inline-start: 12px;
|
|
131
127
|
margin: 0;
|
|
132
128
|
}
|
|
@@ -104,13 +104,17 @@ export class SizeInputElement extends HTMLElement {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
#handleModifierKeys(event: Event): void {
|
|
107
|
-
|
|
107
|
+
let modifiedValue = UILegacy.UIUtils.modifiedFloatNumber(getInputValue(event), event);
|
|
108
108
|
if (modifiedValue === null) {
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
modifiedValue = Math.min(modifiedValue, EmulationModel.DeviceModeModel.MaxDeviceSize);
|
|
113
|
+
modifiedValue = Math.max(modifiedValue, EmulationModel.DeviceModeModel.MinDeviceSize);
|
|
114
|
+
|
|
112
115
|
event.preventDefault();
|
|
113
116
|
(event.target as HTMLInputElement).value = String(modifiedValue);
|
|
117
|
+
this.dispatchEvent(new SizeChangedEvent(modifiedValue));
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
120
|
|
|
@@ -242,7 +242,7 @@ export class HeapTimelineOverview extends Common.ObjectWrapper.eventMixin<EventT
|
|
|
242
242
|
const maxIndex =
|
|
243
243
|
Platform.ArrayUtilities.upperBound(timestamps, timeRight, Platform.ArrayUtilities.DEFAULT_COMPARATOR);
|
|
244
244
|
let size = 0;
|
|
245
|
-
for (let i = minIndex; i
|
|
245
|
+
for (let i = minIndex; i < maxIndex; ++i) {
|
|
246
246
|
size += sizes[i];
|
|
247
247
|
}
|
|
248
248
|
const minId = minIndex > 0 ? ids[minIndex - 1] : 0;
|
|
@@ -293,7 +293,7 @@ export class SourcesPanel extends UI.Panel.Panel implements UI.ContextMenu.Provi
|
|
|
293
293
|
Extensions.ExtensionServer.ExtensionServer.instance().addEventListener(
|
|
294
294
|
Extensions.ExtensionServer.Events.SidebarPaneAdded, this.extensionSidebarPaneAdded, this);
|
|
295
295
|
SDK.TargetManager.TargetManager.instance().observeTargets(this);
|
|
296
|
-
this.lastModificationTime =
|
|
296
|
+
this.lastModificationTime = -Infinity;
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
static instance(opts: {
|
|
@@ -56,8 +56,9 @@ export class SettingCheckbox extends HTMLElement {
|
|
|
56
56
|
LitHtml.html`
|
|
57
57
|
<p>
|
|
58
58
|
<label>
|
|
59
|
-
<input type="checkbox" ?checked=${this.#setting.get()} ?disabled=${
|
|
60
|
-
this.#
|
|
59
|
+
<input type="checkbox" ?checked=${this.#setting.get()} ?disabled=${
|
|
60
|
+
this.#disabled || this.#setting.disabled()} @change=${this.#checkboxChanged} aria-label=${
|
|
61
|
+
this.#setting.title()} /> ${this.#setting.title()}
|
|
61
62
|
</label>
|
|
62
63
|
</p>`,
|
|
63
64
|
this.#shadow, {host: this});
|
|
@@ -510,6 +510,10 @@ export class FilteredListWidget extends Common.ObjectWrapper.eventMixin<EventTyp
|
|
|
510
510
|
this.onEnter(keyboardEvent);
|
|
511
511
|
return;
|
|
512
512
|
case Platform.KeyboardUtilities.TAB_KEY:
|
|
513
|
+
if (keyboardEvent.shiftKey) {
|
|
514
|
+
handled = this.list.selectPreviousItem(true, false);
|
|
515
|
+
break;
|
|
516
|
+
}
|
|
513
517
|
handled = this.tabKeyPressed();
|
|
514
518
|
break;
|
|
515
519
|
case Platform.KeyboardUtilities.ArrowKey.UP:
|
|
@@ -12,7 +12,7 @@ const UIStrings = {
|
|
|
12
12
|
/**
|
|
13
13
|
* @description Text of the hint shows under Quick Open input box
|
|
14
14
|
*/
|
|
15
|
-
|
|
15
|
+
typeToSeeAvailableCommands: 'Type \'?\' to see available commands',
|
|
16
16
|
};
|
|
17
17
|
const str_ = i18n.i18n.registerUIStrings('ui/legacy/components/quick_open/QuickOpen.ts', UIStrings);
|
|
18
18
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
@@ -43,7 +43,7 @@ export class QuickOpenImpl {
|
|
|
43
43
|
const quickOpen = new this();
|
|
44
44
|
const filteredListWidget = new FilteredListWidget(null, history, quickOpen.queryChanged.bind(quickOpen));
|
|
45
45
|
quickOpen.filteredListWidget = filteredListWidget;
|
|
46
|
-
filteredListWidget.setHintElement(i18nString(UIStrings.
|
|
46
|
+
filteredListWidget.setHintElement(i18nString(UIStrings.typeToSeeAvailableCommands));
|
|
47
47
|
filteredListWidget.showAsDialog();
|
|
48
48
|
filteredListWidget.setQuery(query);
|
|
49
49
|
}
|
package/package.json
CHANGED