chrome-devtools-frontend 1.0.1030070 → 1.0.1031400
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 +3 -0
- package/config/gni/devtools_image_files.gni +2 -0
- package/docs/workflows.md +1 -1
- package/front_end/Images/src/file-sync_icon.svg +62 -0
- package/front_end/Images/src/file_icon.svg +52 -0
- package/front_end/Tests.js +0 -28
- package/front_end/core/host/UserMetrics.ts +2 -1
- package/front_end/core/i18n/locales/en-US.json +18 -9
- package/front_end/core/i18n/locales/en-XL.json +18 -9
- package/front_end/core/platform/string-utilities.ts +2 -5
- package/front_end/core/root/Runtime.ts +1 -0
- package/front_end/core/sdk/CSSStyleSheetHeader.ts +0 -4
- package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +0 -4
- package/front_end/core/sdk/NetworkRequest.ts +0 -4
- package/front_end/core/sdk/Resource.ts +0 -5
- package/front_end/core/sdk/Script.ts +71 -76
- package/front_end/core/sdk/Target.ts +4 -0
- package/front_end/entrypoints/inspector_main/InspectorMain.ts +4 -1
- package/front_end/entrypoints/main/MainImpl.ts +4 -0
- package/front_end/generated/InspectorBackendCommands.js +10 -8
- package/front_end/generated/protocol-mapping.d.ts +16 -2
- package/front_end/generated/protocol-proxy-api.d.ts +11 -1
- package/front_end/generated/protocol.ts +75 -1
- package/front_end/models/bindings/CompilerScriptMapping.ts +6 -3
- package/front_end/models/bindings/ContentProviderBasedProject.ts +2 -3
- package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +1 -4
- package/front_end/models/bindings/IgnoreListManager.ts +10 -8
- package/front_end/models/bindings/ResourceMapping.ts +0 -4
- package/front_end/models/bindings/StylesSourceMapping.ts +0 -5
- package/front_end/models/extensions/ExtensionServer.ts +2 -3
- package/front_end/models/issues_manager/AttributionReportingIssue.ts +8 -0
- package/front_end/models/issues_manager/DeprecationIssue.ts +5 -1
- package/front_end/models/issues_manager/descriptions/arTooManyConcurrentRequests.md +5 -0
- package/front_end/models/javascript_metadata/NativeFunctions.js +6 -2
- package/front_end/models/persistence/NetworkPersistenceManager.ts +4 -6
- package/front_end/models/persistence/PersistenceActions.ts +5 -4
- package/front_end/models/text_utils/CodeMirrorUtils.ts +17 -4
- package/front_end/models/text_utils/ContentProvider.ts +0 -1
- package/front_end/models/text_utils/StaticContentProvider.ts +0 -4
- package/front_end/models/workspace/UISourceCode.ts +10 -5
- package/front_end/panels/application/components/StackTrace.ts +2 -2
- package/front_end/panels/elements/CSSRuleValidator.ts +382 -63
- package/front_end/panels/elements/CSSRuleValidatorHelper.ts +34 -0
- package/front_end/panels/elements/ElementsTreeOutline.ts +23 -7
- package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
- package/front_end/panels/elements/TopLayerContainer.ts +17 -28
- package/front_end/panels/elements/components/CSSHintDetailsView.ts +23 -20
- package/front_end/panels/elements/components/cssHintDetailsView.css +8 -2
- package/front_end/panels/elements/stylesSectionTree.css +1 -1
- package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +12 -0
- package/front_end/panels/network/components/RequestHeadersView.css +41 -8
- package/front_end/panels/network/components/RequestHeadersView.ts +102 -12
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +1 -0
- package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +7 -0
- package/front_end/panels/sources/NavigatorView.ts +22 -0
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +3 -3
- package/front_end/third_party/codemirror.next/bundle.ts +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/cpp.js +1 -2
- package/front_end/third_party/codemirror.next/chunk/java.js +1 -2
- package/front_end/third_party/codemirror.next/chunk/json.js +1 -2
- package/front_end/third_party/codemirror.next/chunk/markdown.js +1 -2
- package/front_end/third_party/codemirror.next/chunk/php.js +1 -2
- package/front_end/third_party/codemirror.next/chunk/python.js +1 -2
- package/front_end/third_party/codemirror.next/chunk/wast.js +1 -2
- package/front_end/third_party/codemirror.next/chunk/xml.js +1 -2
- package/front_end/third_party/codemirror.next/codemirror.next.d.ts +1247 -116
- package/front_end/third_party/codemirror.next/codemirror.next.js +1 -2
- package/front_end/ui/components/data_grid/DataGrid.ts +15 -10
- package/front_end/ui/components/data_grid/DataGridController.ts +7 -0
- package/front_end/ui/components/docs/building-ui-documentation/StylingComponents.md +64 -0
- package/front_end/ui/components/linear_memory_inspector/LinearMemoryInspector.ts +2 -3
- package/front_end/ui/components/linear_memory_inspector/LinearMemoryInspectorController.ts +97 -17
- package/front_end/ui/components/linear_memory_inspector/LinearMemoryInspectorPane.ts +1 -1
- package/front_end/ui/components/linear_memory_inspector/LinearMemoryViewerUtils.ts +4 -0
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +9 -7
- package/front_end/ui/legacy/components/source_frame/ImageView.ts +10 -11
- package/front_end/ui/legacy/components/source_frame/PreviewFactory.ts +1 -1
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +49 -0
- package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +18 -17
- package/package.json +6 -5
@@ -1,2 +1 @@
|
|
1
|
-
export{
|
2
|
-
|
1
|
+
export{aw as Annotation,ax as AnnotationType,ay as ChangeDesc,az as ChangeSet,aA as Compartment,W as CompletionContext,aO as Decoration,m as EditorSelection,aB as EditorState,aQ as EditorView,aC as Facet,aS as GutterMarker,ao as HighlightStyle,L as LRParser,k as Language,e as LanguageSupport,aD as Line,aE as MapMode,aX as MatchDecorator,g as NodeProp,h as NodeSet,N as NodeType,P as Parser,n as Prec,aF as Range,aG as RangeSet,aH as RangeSetBuilder,aI as SelectionRange,aJ as StateEffect,aK as StateEffectType,aL as StateField,ar as StreamLanguage,as as StringStream,b7 as StyleModule,T as Tag,aM as Text,aN as Transaction,j as Tree,b5 as TreeCursor,b2 as ViewPlugin,b3 as ViewUpdate,b4 as WidgetType,O as acceptCompletion,Q as autocompletion,aj as bracketMatching,y as clojure,R as closeBrackets,S as closeBracketsKeymap,U as closeCompletion,ak as codeFolding,z as coffeescript,V as completeAnyWord,A as cpp,ag as css,J as cssStreamParser,X as currentCompletions,$ as cursorMatchingBracket,a0 as cursorSubwordBackward,a1 as cursorSubwordForward,aP as drawSelection,al as ensureSyntaxTree,am as foldGutter,an as foldKeymap,aR as gutter,aT as gutters,au as highlightSelectionMatches,aU as highlightSpecialChars,b6 as highlightTree,a2 as history,a3 as historyKeymap,ah as html,Y as ifNotIn,a4 as indentLess,a5 as indentMore,ap as indentOnInput,aq as indentUnit,a6 as insertNewlineAndIndent,B as java,ai as javascript,D as json,o as keymap,aV as lineNumberMarkers,aW as lineNumbers,F as markdown,G as php,aY as placeholder,H as python,a7 as redo,a8 as redoSelection,aZ as repositionTooltips,a_ as scrollPastEnd,a9 as selectMatchingBracket,av as selectNextOccurrence,aa as selectSubwordBackward,ab as selectSubwordForward,Z as selectedCompletion,I as shell,a$ as showPanel,b0 as showTooltip,ac as standardKeymap,_ as startCompletion,at as syntaxHighlighting,l as syntaxTree,t as tags,ad as toggleComment,b1 as tooltips,ae as undo,af as undoSelection,K as wast,M as xml}from"./chunk/codemirror.js";
|
@@ -58,6 +58,7 @@ export interface DataGridData {
|
|
58
58
|
activeSort: SortState|null;
|
59
59
|
contextMenus?: DataGridContextMenusConfiguration;
|
60
60
|
label?: string;
|
61
|
+
paddingRowsCount?: number;
|
61
62
|
}
|
62
63
|
|
63
64
|
const enum UserScrollState {
|
@@ -69,7 +70,6 @@ const enum UserScrollState {
|
|
69
70
|
const KEYS_TREATED_AS_CLICKS = new Set([' ', 'Enter']);
|
70
71
|
|
71
72
|
const ROW_HEIGHT_PIXELS = 18;
|
72
|
-
const PADDING_ROWS_COUNT = 10;
|
73
73
|
|
74
74
|
export class DataGrid extends HTMLElement {
|
75
75
|
static readonly litTagName = LitHtml.literal`devtools-data-grid`;
|
@@ -82,6 +82,7 @@ export class DataGrid extends HTMLElement {
|
|
82
82
|
#userScrollState: UserScrollState = UserScrollState.NOT_SCROLLED;
|
83
83
|
#contextMenus?: DataGridContextMenusConfiguration = undefined;
|
84
84
|
#label?: string = undefined;
|
85
|
+
#paddingRowsCount = 10;
|
85
86
|
#currentResize: {
|
86
87
|
rightCellCol: HTMLTableColElement,
|
87
88
|
leftCellCol: HTMLTableColElement,
|
@@ -139,6 +140,7 @@ export class DataGrid extends HTMLElement {
|
|
139
140
|
activeSort: this.#sortState,
|
140
141
|
contextMenus: this.#contextMenus,
|
141
142
|
label: this.#label,
|
143
|
+
paddingRowsCount: this.#paddingRowsCount,
|
142
144
|
};
|
143
145
|
}
|
144
146
|
|
@@ -171,6 +173,10 @@ export class DataGrid extends HTMLElement {
|
|
171
173
|
this.#cellToFocusIfUserTabsIn = calculateFirstFocusableCell({columns: this.#columns, rows: this.#rows});
|
172
174
|
}
|
173
175
|
|
176
|
+
if (data.paddingRowsCount !== undefined) {
|
177
|
+
this.#paddingRowsCount = data.paddingRowsCount;
|
178
|
+
}
|
179
|
+
|
174
180
|
if (this.#hasRenderedAtLeastOnce && this.#userHasCellFocused()) {
|
175
181
|
const [selectedColIndex, selectedRowIndex] = this.#tabbableCell();
|
176
182
|
const columnOutOfBounds = selectedColIndex > this.#columns.length;
|
@@ -220,15 +226,14 @@ export class DataGrid extends HTMLElement {
|
|
220
226
|
return;
|
221
227
|
}
|
222
228
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
229
|
+
const wrapper = this.#shadow.querySelector('.wrapping-container');
|
230
|
+
if (!wrapper) {
|
231
|
+
return;
|
232
|
+
}
|
233
|
+
|
234
|
+
void coordinator.scroll(() => {
|
228
235
|
const scrollHeight = wrapper.scrollHeight;
|
229
|
-
|
230
|
-
wrapper.scrollTo(0, scrollHeight);
|
231
|
-
});
|
236
|
+
wrapper.scrollTo(0, scrollHeight);
|
232
237
|
});
|
233
238
|
}
|
234
239
|
|
@@ -643,7 +648,7 @@ export class DataGrid extends HTMLElement {
|
|
643
648
|
scrollTop = wrapper.scrollTop;
|
644
649
|
clientHeight = wrapper.clientHeight;
|
645
650
|
}
|
646
|
-
const padding = ROW_HEIGHT_PIXELS *
|
651
|
+
const padding = ROW_HEIGHT_PIXELS * this.#paddingRowsCount;
|
647
652
|
let topVisibleRow = Math.floor((scrollTop - padding) / ROW_HEIGHT_PIXELS);
|
648
653
|
let bottomVisibleRow = Math.ceil((scrollTop + clientHeight + padding) / ROW_HEIGHT_PIXELS);
|
649
654
|
|
@@ -31,6 +31,7 @@ export interface DataGridControllerData {
|
|
31
31
|
initialSort?: SortState;
|
32
32
|
contextMenus?: DataGridContextMenusConfiguration;
|
33
33
|
label?: string;
|
34
|
+
paddingRowsCount?: number;
|
34
35
|
}
|
35
36
|
|
36
37
|
export class DataGridController extends HTMLElement {
|
@@ -55,6 +56,8 @@ export class DataGridController extends HTMLElement {
|
|
55
56
|
#sortState: Readonly<SortState>|null = null;
|
56
57
|
#filters: readonly TextUtils.TextUtils.ParsedFilter[] = [];
|
57
58
|
|
59
|
+
#paddingRowsCount?: number;
|
60
|
+
|
58
61
|
connectedCallback(): void {
|
59
62
|
this.#shadow.adoptedStyleSheets = [dataGridControllerStyles];
|
60
63
|
}
|
@@ -66,6 +69,7 @@ export class DataGridController extends HTMLElement {
|
|
66
69
|
filters: this.#filters,
|
67
70
|
contextMenus: this.#contextMenus,
|
68
71
|
label: this.#label,
|
72
|
+
paddingRowsCount: this.#paddingRowsCount,
|
69
73
|
};
|
70
74
|
}
|
71
75
|
|
@@ -88,6 +92,8 @@ export class DataGridController extends HTMLElement {
|
|
88
92
|
this.#sortRows(this.#sortState);
|
89
93
|
}
|
90
94
|
|
95
|
+
this.#paddingRowsCount = data.paddingRowsCount;
|
96
|
+
|
91
97
|
this.#render();
|
92
98
|
}
|
93
99
|
|
@@ -222,6 +228,7 @@ export class DataGridController extends HTMLElement {
|
|
222
228
|
activeSort: this.#sortState,
|
223
229
|
contextMenus: this.#contextMenus,
|
224
230
|
label: this.#label,
|
231
|
+
paddingRowsCount: this.#paddingRowsCount,
|
225
232
|
} as DataGridData}
|
226
233
|
@columnheaderclick=${this.#onColumnHeaderClick}
|
227
234
|
@contextmenucolumnsortclick=${this.#onContextMenuColumnSortClick}
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Styling Components
|
2
|
+
|
3
|
+
Components are styled by a CSS file that is co-located next to the TypeScript source file. The only difference in file name is the extension and that for CSS files, the first letter is lowercase:
|
4
|
+
|
5
|
+
```
|
6
|
+
- ElementsBreadcrumbs.ts
|
7
|
+
- elementsBreadcrumbs.css
|
8
|
+
```
|
9
|
+
|
10
|
+
To import this file you use a regular `import` statement, and import the filename with `.js` appended:
|
11
|
+
|
12
|
+
```ts
|
13
|
+
import elementsBreadcrumbsStyles from './elementsBreadcrumbs.css.js';
|
14
|
+
```
|
15
|
+
|
16
|
+
As part of the build tool step, each CSS file is converted into a JS file that exports a `CSSStyleSheet` instance. This is done by Rollup in [`generate_css_js_files`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/scripts/build/generate_css_js_files.js;l=1;drc=28af9fbe783d82aa64bfa5f9b9509572dc2b3efe).
|
17
|
+
|
18
|
+
## `BUILD.gn` changes
|
19
|
+
|
20
|
+
Use the `generate_css` action (`scripts/build/ninja/generate_css.gni`) to declare stylesheets:
|
21
|
+
|
22
|
+
```gn
|
23
|
+
import("scripts/build/ninja/generate_css.gni") // Edit path correctly: this must be relative
|
24
|
+
|
25
|
+
generate_css("css_files") {
|
26
|
+
sources = [ "elementsBreadcrumbs.css"]
|
27
|
+
}
|
28
|
+
```
|
29
|
+
|
30
|
+
And then add `:css_files` as a dependency to the `devtools_entrypoint`:
|
31
|
+
|
32
|
+
```gn
|
33
|
+
devtools_entrypoint("bundle") {
|
34
|
+
deps = [ ":css_files" , "..."]
|
35
|
+
}
|
36
|
+
```
|
37
|
+
|
38
|
+
## Adopting the stylesheet
|
39
|
+
|
40
|
+
Importing the stylesheet is not enough to have it apply to the component's ShadowDOM, it must be adopted. The `connectedCallback` method is the best place for this:
|
41
|
+
|
42
|
+
```ts
|
43
|
+
connectedCallback() {
|
44
|
+
this.#shadow.adoptedStyleSheets = [elementsBreadcrumbs];
|
45
|
+
}
|
46
|
+
```
|
47
|
+
|
48
|
+
## Tips for writing CSS.
|
49
|
+
|
50
|
+
Use `:host` to style the component itself. By default elements are `display: inline`. Often it can be useful to set `display: block`.
|
51
|
+
|
52
|
+
Remember to use theme colors (`var(--color-text-primary)`) when styling elements to ensure consistency across DevTools.
|
53
|
+
|
54
|
+
If you want your component to have its colors configurable by users, consider defining `--override` variables. In your component's CSS, you would have something like:
|
55
|
+
|
56
|
+
```css
|
57
|
+
:host {
|
58
|
+
color: var(--override-custom-color, var(--color-text-primary));
|
59
|
+
}
|
60
|
+
```
|
61
|
+
|
62
|
+
This allows someone to define that `--override-custom-color` variable, but also ensures if it isn't defined that the default `color-text-primary` will be used. **Be careful with this!** We try to ensure consistent colors across DevTools; so most of the time you shouldn't allow configurable colors and should use the correct theme variables.
|
63
|
+
|
64
|
+
|
@@ -160,12 +160,11 @@ export class LinearMemoryInspector extends HTMLElement {
|
|
160
160
|
throw new Error('Memory offset has to be greater or equal to zero.');
|
161
161
|
}
|
162
162
|
|
163
|
-
if (data.highlightInfo
|
163
|
+
if (data.highlightInfo) {
|
164
164
|
if (data.highlightInfo.size < 0) {
|
165
165
|
throw new Error('Object size has to be greater than or equal to zero');
|
166
166
|
}
|
167
|
-
if (data.highlightInfo.startAddress
|
168
|
-
data.highlightInfo.startAddress < 0) {
|
167
|
+
if (data.highlightInfo.startAddress < 0 || data.highlightInfo.startAddress >= data.outerMemoryLength) {
|
169
168
|
throw new Error('Object start address is out of bounds.');
|
170
169
|
}
|
171
170
|
}
|
@@ -164,6 +164,21 @@ export class LinearMemoryInspectorController extends SDK.TargetManager.SDKModelO
|
|
164
164
|
return await memoryWrapper.getRange(start, chunkEnd);
|
165
165
|
}
|
166
166
|
|
167
|
+
async evaluateExpression(callFrame: SDK.DebuggerModel.CallFrame, expressionName: string):
|
168
|
+
Promise<SDK.RemoteObject.RemoteObject|undefined> {
|
169
|
+
const result = await callFrame.evaluate({expression: expressionName});
|
170
|
+
if ('error' in result) {
|
171
|
+
console.error(`Tried to evaluate the expression '${expressionName}' but got an error: ${result.error}`);
|
172
|
+
return undefined;
|
173
|
+
}
|
174
|
+
if ('exceptionDetails' in result && result?.exceptionDetails?.text) {
|
175
|
+
console.error(
|
176
|
+
`Tried to evaluate the expression '${expressionName}' but got an exception: ${result.exceptionDetails.text}`);
|
177
|
+
return undefined;
|
178
|
+
}
|
179
|
+
return result.object;
|
180
|
+
}
|
181
|
+
|
167
182
|
saveSettings(data: Settings): void {
|
168
183
|
const valueTypes = Array.from(data.valueTypes);
|
169
184
|
const modes = [...data.modes];
|
@@ -233,14 +248,15 @@ export class LinearMemoryInspectorController extends SDK.TargetManager.SDKModelO
|
|
233
248
|
// This function returns the size of the source language value represented
|
234
249
|
// by the ValueNode. If the value is a pointer, the function returns the size of
|
235
250
|
// the pointed-to value. If the pointed-to value is also a pointer, it returns
|
236
|
-
// the size of the pointer (usually 4 bytes)
|
251
|
+
// the size of the pointer (usually 4 bytes). This is the convention taken
|
252
|
+
// by the DWARF extension.
|
237
253
|
// > double x = 42.0;
|
238
254
|
// > double *ptr = &x;
|
239
255
|
// > double **dblptr = &ptr;
|
240
256
|
//
|
241
257
|
// retrieveObjectSize(ptr_ValueNode) -> 8, the size of a double
|
242
258
|
// retrieveObjectSize(dblptr_ValueNode) -> 4, the size of a pointer
|
243
|
-
static
|
259
|
+
static extractObjectSize(obj: Bindings.DebuggerLanguagePlugins.ValueNode): number {
|
244
260
|
let typeInfo = obj.sourceType.typeInfo;
|
245
261
|
const pointerMembers = typeInfo.members.filter(member => member.name === '*');
|
246
262
|
if (pointerMembers.length === 1) {
|
@@ -257,7 +273,34 @@ export class LinearMemoryInspectorController extends SDK.TargetManager.SDKModelO
|
|
257
273
|
return typeInfo.size;
|
258
274
|
}
|
259
275
|
|
260
|
-
|
276
|
+
// The object type description corresponds to the type of the highlighted memory
|
277
|
+
// that the user sees in the memory inspector. For pointers, we highlight the pointed to object.
|
278
|
+
//
|
279
|
+
// Example: The variable `x` has the type `int *`. Assume that `x` points to the value 3.
|
280
|
+
// -> The memory inspector will jump to the address where 3 is stored.
|
281
|
+
// -> The memory inspector will highlight the bytes that represent the 3.
|
282
|
+
// -> The object type description of what we show will thus be `int` and not `int *`.
|
283
|
+
static extractObjectTypeDescription(obj: Bindings.DebuggerLanguagePlugins.ValueNode): string {
|
284
|
+
const objType = obj.description;
|
285
|
+
if (!objType) {
|
286
|
+
return '';
|
287
|
+
}
|
288
|
+
const lastChar = objType.charAt(objType.length - 1);
|
289
|
+
const secondToLastChar = objType.charAt(objType.length - 2);
|
290
|
+
const isPointerType = lastChar === '*' || lastChar === '&';
|
291
|
+
const isOneLevelPointer = secondToLastChar === ' ';
|
292
|
+
if (!isPointerType) {
|
293
|
+
return objType;
|
294
|
+
}
|
295
|
+
if (isOneLevelPointer) {
|
296
|
+
// For example, 'int *'and 'int &' become 'int'.
|
297
|
+
return objType.slice(0, objType.length - 2);
|
298
|
+
}
|
299
|
+
// For example, 'int **' becomes 'int *'.
|
300
|
+
return objType.slice(0, objType.length - 1);
|
301
|
+
}
|
302
|
+
|
303
|
+
async openInspectorView(obj: SDK.RemoteObject.RemoteObject, address?: number, expression?: string): Promise<void> {
|
261
304
|
const response = await LinearMemoryInspectorController.retrieveDWARFMemoryObjectAndAddress(obj);
|
262
305
|
let memoryObj = obj;
|
263
306
|
let memoryAddress = address;
|
@@ -288,8 +331,8 @@ export class LinearMemoryInspectorController extends SDK.TargetManager.SDKModelO
|
|
288
331
|
}
|
289
332
|
const memoryProperty = internalProperties?.find(({name}) => name === '[[WebAssemblyMemory]]');
|
290
333
|
const memory = memoryProperty?.value;
|
291
|
-
const highlightInfo = LinearMemoryInspectorController.extractHighlightInfo(obj,
|
292
|
-
if (highlightInfo
|
334
|
+
const highlightInfo = LinearMemoryInspectorController.extractHighlightInfo(obj, expression);
|
335
|
+
if (highlightInfo) {
|
293
336
|
this.#setHighlightInfo(id, highlightInfo);
|
294
337
|
} else {
|
295
338
|
this.#resetHighlightInfo(id);
|
@@ -308,17 +351,21 @@ export class LinearMemoryInspectorController extends SDK.TargetManager.SDKModelO
|
|
308
351
|
void UI.ViewManager.ViewManager.instance().showView('linear-memory-inspector');
|
309
352
|
}
|
310
353
|
|
311
|
-
static extractHighlightInfo(obj: SDK.RemoteObject.RemoteObject,
|
354
|
+
static extractHighlightInfo(obj: SDK.RemoteObject.RemoteObject, expression?: string): HighlightInfo|undefined {
|
355
|
+
if (!(obj instanceof Bindings.DebuggerLanguagePlugins.ValueNode)) {
|
356
|
+
return undefined;
|
357
|
+
}
|
358
|
+
|
312
359
|
let highlightInfo;
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
}
|
320
|
-
|
321
|
-
|
360
|
+
try {
|
361
|
+
highlightInfo = {
|
362
|
+
startAddress: obj.inspectableAddress || 0,
|
363
|
+
size: LinearMemoryInspectorController.extractObjectSize(obj),
|
364
|
+
name: expression,
|
365
|
+
type: LinearMemoryInspectorController.extractObjectTypeDescription(obj),
|
366
|
+
};
|
367
|
+
} catch (err) {
|
368
|
+
highlightInfo = undefined;
|
322
369
|
}
|
323
370
|
return highlightInfo;
|
324
371
|
}
|
@@ -337,8 +384,16 @@ export class LinearMemoryInspectorController extends SDK.TargetManager.SDKModelO
|
|
337
384
|
const debuggerModel = event.data;
|
338
385
|
for (const [bufferId, remoteObject] of this.#bufferIdToRemoteObject) {
|
339
386
|
if (debuggerModel.runtimeModel() === remoteObject.runtimeModel()) {
|
340
|
-
|
341
|
-
|
387
|
+
const topCallFrame = debuggerModel.debuggerPausedDetails()?.callFrames[0];
|
388
|
+
if (topCallFrame) {
|
389
|
+
void this
|
390
|
+
.updateHighlightedMemory(bufferId, topCallFrame)
|
391
|
+
// Need to call refreshView in the callback to trigger re-render.
|
392
|
+
.then(() => this.#paneInstance.refreshView(bufferId));
|
393
|
+
} else {
|
394
|
+
this.#resetHighlightInfo(bufferId);
|
395
|
+
this.#paneInstance.refreshView(bufferId);
|
396
|
+
}
|
342
397
|
}
|
343
398
|
}
|
344
399
|
}
|
@@ -355,4 +410,29 @@ export class LinearMemoryInspectorController extends SDK.TargetManager.SDKModelO
|
|
355
410
|
this.#bufferIdToRemoteObject.delete(bufferId);
|
356
411
|
this.#resetHighlightInfo(bufferId);
|
357
412
|
}
|
413
|
+
|
414
|
+
async updateHighlightedMemory(bufferId: string, callFrame: SDK.DebuggerModel.CallFrame): Promise<void> {
|
415
|
+
const oldHighlightInfo = this.getHighlightInfo(bufferId);
|
416
|
+
const expressionName = oldHighlightInfo?.name;
|
417
|
+
if (!oldHighlightInfo || !expressionName) {
|
418
|
+
this.#resetHighlightInfo(bufferId);
|
419
|
+
return;
|
420
|
+
}
|
421
|
+
const obj = await this.evaluateExpression(callFrame, expressionName);
|
422
|
+
if (!obj) {
|
423
|
+
this.#resetHighlightInfo(bufferId);
|
424
|
+
return;
|
425
|
+
}
|
426
|
+
|
427
|
+
const newHighlightInfo = LinearMemoryInspectorController.extractHighlightInfo(obj, expressionName);
|
428
|
+
if (!newHighlightInfo || !this.#pointToSameMemoryObject(newHighlightInfo, oldHighlightInfo)) {
|
429
|
+
this.#resetHighlightInfo(bufferId);
|
430
|
+
} else {
|
431
|
+
this.#setHighlightInfo(bufferId, newHighlightInfo);
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
435
|
+
#pointToSameMemoryObject(highlightInfoA: HighlightInfo, highlightInfoB: HighlightInfo): boolean {
|
436
|
+
return highlightInfoA.type === highlightInfoB.type && highlightInfoA.startAddress === highlightInfoB.startAddress;
|
437
|
+
}
|
358
438
|
}
|
@@ -226,7 +226,7 @@ class LinearMemoryInspectorView extends UI.Widget.VBox {
|
|
226
226
|
const highlightInfo = LinearMemoryInspectorController.instance().getHighlightInfo(this.#tabId);
|
227
227
|
if (highlightInfo !== undefined) {
|
228
228
|
if (highlightInfo.startAddress < 0 || highlightInfo.startAddress >= this.#memoryWrapper.length()) {
|
229
|
-
throw new Error('
|
229
|
+
throw new Error('HighlightInfo start address is out of bounds.');
|
230
230
|
}
|
231
231
|
if (highlightInfo.size <= 0) {
|
232
232
|
throw new Error('Highlight size must be a positive number.');
|
@@ -386,16 +386,17 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
|
|
386
386
|
|
387
387
|
static createPropertyValueWithCustomSupport(
|
388
388
|
value: SDK.RemoteObject.RemoteObject, wasThrown: boolean, showPreview: boolean, parentElement?: Element,
|
389
|
-
linkifier?: Components.Linkifier.Linkifier): ObjectPropertyValue {
|
389
|
+
linkifier?: Components.Linkifier.Linkifier, variableName?: string): ObjectPropertyValue {
|
390
390
|
if (value.customPreview()) {
|
391
391
|
const result = (new CustomPreviewComponent(value)).element;
|
392
392
|
result.classList.add('object-properties-section-custom-section');
|
393
393
|
return new ObjectPropertyValue(result);
|
394
394
|
}
|
395
|
-
return ObjectPropertiesSection.createPropertyValue(
|
395
|
+
return ObjectPropertiesSection.createPropertyValue(
|
396
|
+
value, wasThrown, showPreview, parentElement, linkifier, variableName);
|
396
397
|
}
|
397
398
|
|
398
|
-
static appendMemoryIcon(element: Element, obj: SDK.RemoteObject.RemoteObject): void {
|
399
|
+
static appendMemoryIcon(element: Element, obj: SDK.RemoteObject.RemoteObject, variableName?: string): void {
|
399
400
|
// We show the memory icon only on ArrayBuffer, WebAssembly.Memory and DWARF memory instances.
|
400
401
|
// TypedArrays DataViews are also supported, but showing the icon next to their
|
401
402
|
// previews is quite a significant visual overhead, and users can easily get to
|
@@ -418,7 +419,7 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
|
|
418
419
|
const controller =
|
419
420
|
LinearMemoryInspector.LinearMemoryInspectorController.LinearMemoryInspectorController.instance();
|
420
421
|
Host.userMetrics.linearMemoryInspectorRevealedFrom(Host.UserMetrics.LinearMemoryInspectorRevealedFrom.MemoryIcon);
|
421
|
-
void controller.openInspectorView(obj);
|
422
|
+
void controller.openInspectorView(obj, undefined /* address */, variableName);
|
422
423
|
};
|
423
424
|
|
424
425
|
UI.Tooltip.Tooltip.install(memoryIcon, 'Reveal in Memory Inspector panel');
|
@@ -428,7 +429,7 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
|
|
428
429
|
|
429
430
|
static createPropertyValue(
|
430
431
|
value: SDK.RemoteObject.RemoteObject, wasThrown: boolean, showPreview: boolean, parentElement?: Element,
|
431
|
-
linkifier?: Components.Linkifier.Linkifier): ObjectPropertyValue {
|
432
|
+
linkifier?: Components.Linkifier.Linkifier, variableName?: string): ObjectPropertyValue {
|
432
433
|
let propertyValue;
|
433
434
|
const type = value.type;
|
434
435
|
const subtype = value.subtype;
|
@@ -464,7 +465,7 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
|
|
464
465
|
propertyValue.element.textContent = description;
|
465
466
|
UI.Tooltip.Tooltip.install(propertyValue.element as HTMLElement, description);
|
466
467
|
}
|
467
|
-
this.appendMemoryIcon(valueElement, value);
|
468
|
+
this.appendMemoryIcon(valueElement, value, variableName);
|
468
469
|
}
|
469
470
|
|
470
471
|
if (wasThrown) {
|
@@ -1090,7 +1091,8 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
1090
1091
|
} else if (this.property.value) {
|
1091
1092
|
const showPreview = this.property.name !== '[[Prototype]]';
|
1092
1093
|
this.propertyValue = ObjectPropertiesSection.createPropertyValueWithCustomSupport(
|
1093
|
-
this.property.value, this.property.wasThrown, showPreview, this.listItemElement, this.linkifier
|
1094
|
+
this.property.value, this.property.wasThrown, showPreview, this.listItemElement, this.linkifier,
|
1095
|
+
this.path() /* variableName */);
|
1094
1096
|
this.valueElement = (this.propertyValue.element as HTMLElement);
|
1095
1097
|
} else if (this.property.getter) {
|
1096
1098
|
this.valueElement = document.createElement('span');
|
@@ -95,7 +95,7 @@ export class ImageView extends UI.View.SimpleView {
|
|
95
95
|
private readonly mimeTypeLabel: UI.Toolbar.ToolbarText;
|
96
96
|
private readonly container: HTMLElement;
|
97
97
|
private imagePreviewElement: HTMLImageElement;
|
98
|
-
private cachedContent?:
|
98
|
+
private cachedContent?: TextUtils.ContentProvider.DeferredContent;
|
99
99
|
constructor(mimeType: string, contentProvider: TextUtils.ContentProvider.ContentProvider) {
|
100
100
|
super(i18nString(UIStrings.image));
|
101
101
|
this.registerRequiredCSS(imageViewStyles);
|
@@ -153,20 +153,21 @@ export class ImageView extends UI.View.SimpleView {
|
|
153
153
|
}
|
154
154
|
|
155
155
|
private async updateContentIfNeeded(): Promise<void> {
|
156
|
-
const
|
157
|
-
if (this.cachedContent === content) {
|
156
|
+
const content = await this.contentProvider.requestContent();
|
157
|
+
if (this.cachedContent?.content === content.content) {
|
158
158
|
return;
|
159
159
|
}
|
160
160
|
|
161
|
-
const contentEncoded = await this.contentProvider.contentEncoded();
|
162
161
|
this.cachedContent = content;
|
163
|
-
const imageSrc =
|
162
|
+
const imageSrc =
|
163
|
+
TextUtils.ContentProvider.contentAsDataURL(content.content, this.mimeType, content.isEncoded) || this.url;
|
164
164
|
const loadPromise = new Promise(x => {
|
165
165
|
this.imagePreviewElement.onload = x;
|
166
166
|
});
|
167
167
|
this.imagePreviewElement.src = imageSrc;
|
168
168
|
this.imagePreviewElement.alt = i18nString(UIStrings.imageFromS, {PH1: this.url});
|
169
|
-
const size = content && !
|
169
|
+
const size = content.content && !content.isEncoded ? content.content.length :
|
170
|
+
Platform.StringUtilities.base64ToSize(content.content);
|
170
171
|
this.sizeLabel.setText(Platform.NumberUtilities.bytesToString(size));
|
171
172
|
await loadPromise;
|
172
173
|
this.dimensionsLabel.setText(i18nString(
|
@@ -203,13 +204,11 @@ export class ImageView extends UI.View.SimpleView {
|
|
203
204
|
}
|
204
205
|
|
205
206
|
private async saveImage(): Promise<void> {
|
206
|
-
|
207
|
-
if (!this.cachedContent) {
|
207
|
+
if (!this.cachedContent || !this.cachedContent.content) {
|
208
208
|
return;
|
209
209
|
}
|
210
|
-
const
|
211
|
-
|
212
|
-
TextUtils.ContentProvider.contentAsDataURL(cachedContent, this.mimeType, contentEncoded, '', false);
|
210
|
+
const imageDataURL = TextUtils.ContentProvider.contentAsDataURL(
|
211
|
+
this.cachedContent.content, this.mimeType, this.cachedContent.isEncoded, '', false);
|
213
212
|
|
214
213
|
if (!imageDataURL) {
|
215
214
|
return;
|
@@ -460,6 +460,55 @@ export class SourceFrameImpl extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
460
460
|
}
|
461
461
|
}
|
462
462
|
|
463
|
+
// If the input is wasm but v8-based wasm disassembly failed, fall back to wasmparser for backwards compatibility.
|
464
|
+
if (content && this.contentType === 'application/wasm' && !this.wasmDisassemblyInternal) {
|
465
|
+
const worker = Common.Worker.WorkerWrapper.fromURL(
|
466
|
+
new URL('../../../../entrypoints/wasmparser_worker/wasmparser_worker-entrypoint.js', import.meta.url));
|
467
|
+
const promise = new Promise<{
|
468
|
+
lines: string[],
|
469
|
+
offsets: number[],
|
470
|
+
functionBodyOffsets: {
|
471
|
+
start: number,
|
472
|
+
end: number,
|
473
|
+
}[],
|
474
|
+
}>((resolve, reject) => {
|
475
|
+
worker.onmessage =
|
476
|
+
// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
|
477
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
478
|
+
({data}: MessageEvent<any>): void => {
|
479
|
+
if ('event' in data) {
|
480
|
+
switch (data.event) {
|
481
|
+
case 'progress':
|
482
|
+
progressIndicator.setWorked(data.params.percentage);
|
483
|
+
break;
|
484
|
+
}
|
485
|
+
} else if ('method' in data) {
|
486
|
+
switch (data.method) {
|
487
|
+
case 'disassemble':
|
488
|
+
if ('error' in data) {
|
489
|
+
reject(data.error);
|
490
|
+
} else if ('result' in data) {
|
491
|
+
resolve(data.result);
|
492
|
+
}
|
493
|
+
break;
|
494
|
+
}
|
495
|
+
}
|
496
|
+
};
|
497
|
+
worker.onerror = reject;
|
498
|
+
});
|
499
|
+
worker.postMessage({method: 'disassemble', params: {content}});
|
500
|
+
try {
|
501
|
+
const {lines, offsets, functionBodyOffsets} = await promise;
|
502
|
+
this.rawContent = content = CodeMirror.Text.of(lines);
|
503
|
+
this.wasmDisassemblyInternal =
|
504
|
+
new Common.WasmDisassembly.WasmDisassembly(lines, offsets, functionBodyOffsets);
|
505
|
+
} catch (e) {
|
506
|
+
this.rawContent = content = error = e.message;
|
507
|
+
} finally {
|
508
|
+
worker.terminate();
|
509
|
+
}
|
510
|
+
}
|
511
|
+
|
463
512
|
progressIndicator.setWorked(100);
|
464
513
|
progressIndicator.done();
|
465
514
|
|