chrome-devtools-frontend 1.0.1030946 → 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.
@@ -4842,10 +4842,10 @@
4842
4842
  "message": "Inactive property"
4843
4843
  },
4844
4844
  "panels/elements/CSSRuleValidator.ts | ruleViolatedByParentElementRuleFix": {
4845
- "message": "Please change parent element's {EXISTING_PARENT_ELEMENT_RULE} to {TARGET_PARENT_ELEMENT_RULE} to fix this issue."
4845
+ "message": "Please change the parent element's property declaration from {EXISTING_PARENT_ELEMENT_RULE} to {TARGET_PARENT_ELEMENT_RULE} to fix this issue."
4846
4846
  },
4847
4847
  "panels/elements/CSSRuleValidator.ts | ruleViolatedByParentElementRuleReason": {
4848
- "message": "Parent element has {REASON_PROPERTY_DECLARATION_CODE} rule, therefore this elements {AFFECTED_PROPERTY_DECLARATION_CODE} has no effect."
4848
+ "message": "The parent element has the {REASON_PROPERTY_DECLARATION_CODE} property and therefore, this element's property {AFFECTED_PROPERTY_DECLARATION_CODE} has no effect."
4849
4849
  },
4850
4850
  "panels/elements/CSSRuleValidator.ts | ruleViolatedBySameElementRuleChangeSuggestion": {
4851
4851
  "message": "For this property to work, please change the {EXISTING_PROPERTY_DECLARATION} rule to {TARGET_PROPERTY_DECLARATION}."
@@ -4854,7 +4854,7 @@
4854
4854
  "message": "For this property to work, please remove or change the value of {REASON_PROPERTY_DECLARATION_CODE}."
4855
4855
  },
4856
4856
  "panels/elements/CSSRuleValidator.ts | ruleViolatedBySameElementRuleReason": {
4857
- "message": "This element has the {REASON_PROPERTY_DECLARATION_CODE} property and, therefore, {AFFECTED_PROPERTY_DECLARATION_CODE} has no effect."
4857
+ "message": "This element has the {REASON_PROPERTY_DECLARATION_CODE} property and therefore, {AFFECTED_PROPERTY_DECLARATION_CODE} has no effect."
4858
4858
  },
4859
4859
  "panels/elements/DOMLinkifier.ts | node": {
4860
4860
  "message": "<node>"
@@ -5330,8 +5330,8 @@
5330
5330
  "panels/elements/StylesSidebarPane.ts | unknownPropertyName": {
5331
5331
  "message": "Unknown property name"
5332
5332
  },
5333
- "panels/elements/TopLayerContainer.ts | topLayer": {
5334
- "message": "top-layer"
5333
+ "panels/elements/TopLayerContainer.ts | reveal": {
5334
+ "message": "reveal"
5335
5335
  },
5336
5336
  "panels/emulation/DeviceModeToolbar.ts | addDevicePixelRatio": {
5337
5337
  "message": "Add device pixel ratio"
@@ -4842,10 +4842,10 @@
4842
4842
  "message": "Îńâćt̂ív̂é p̂ŕôṕêŕt̂ý"
4843
4843
  },
4844
4844
  "panels/elements/CSSRuleValidator.ts | ruleViolatedByParentElementRuleFix": {
4845
- "message": "P̂ĺêáŝé ĉh́âńĝé p̂ár̂én̂t́ êĺêḿêńt̂'ś {EXISTING_PARENT_ELEMENT_RULE} t̂ó {TARGET_PARENT_ELEMENT_RULE} t̂ó f̂íx̂ t́ĥíŝ íŝśûé."
4845
+ "message": "P̂ĺêáŝé ĉh́âńĝé t̂h́ê ṕâŕêńt̂ l̂ém̂én̂t́'ŝ ṕr̂óér̂t́ŷ d́ćl̂ár̂áíôń f̂ŕôḿ {EXISTING_PARENT_ELEMENT_RULE} t̂ó {TARGET_PARENT_ELEMENT_RULE} t̂ó f̂íx̂ t́ĥíŝ íŝśûé."
4846
4846
  },
4847
4847
  "panels/elements/CSSRuleValidator.ts | ruleViolatedByParentElementRuleReason": {
4848
- "message": "P̂ár̂én̂t́ êĺêḿêńt̂ ś {REASON_PROPERTY_DECLARATION_CODE} úl̂é, t̂h́êŕêf́ôŕê ĥíŝ éém̂én̂t́ {AFFECTED_PROPERTY_DECLARATION_CODE} h́â êf́f̂ét́."
4848
+ "message": "T̂h́ê ṕâŕêńt̂ l̂ém̂én̂t́ ĥáŝ t́ĥé {REASON_PROPERTY_DECLARATION_CODE} p̂ŕôṕŕt̂ń t́ĥééf̂ór̂é, t̂h́îś ĺêḿêt̂'ś p̂ŕôṕêŕt̂ý {AFFECTED_PROPERTY_DECLARATION_CODE} ĥáŝ ńô éf̂f́êćt̂."
4849
4849
  },
4850
4850
  "panels/elements/CSSRuleValidator.ts | ruleViolatedBySameElementRuleChangeSuggestion": {
4851
4851
  "message": "F̂ór̂ t́ĥíŝ ṕr̂óp̂ér̂t́ŷ t́ô ẃôŕk̂, ṕl̂éâśê ćĥán̂ǵê t́ĥé {EXISTING_PROPERTY_DECLARATION} r̂úl̂é t̂ó {TARGET_PROPERTY_DECLARATION}."
@@ -4854,7 +4854,7 @@
4854
4854
  "message": "F̂ór̂ t́ĥíŝ ṕr̂óp̂ér̂t́ŷ t́ô ẃôŕk̂, ṕl̂éâśê ŕêḿôv́ê ór̂ ćĥán̂ǵê t́ĥé v̂ál̂úê óf̂ {REASON_PROPERTY_DECLARATION_CODE}."
4855
4855
  },
4856
4856
  "panels/elements/CSSRuleValidator.ts | ruleViolatedBySameElementRuleReason": {
4857
- "message": "T̂h́îś êĺêḿêńt̂ h́âś t̂h́ê {REASON_PROPERTY_DECLARATION_CODE} ṕr̂óp̂ér̂t́ŷ án̂d́, t̂h́êŕêf́ôŕê, {AFFECTED_PROPERTY_DECLARATION_CODE} h́âś n̂ó êf́f̂éĉt́."
4857
+ "message": "T̂h́îś êĺêḿêńt̂ h́âś t̂h́ê {REASON_PROPERTY_DECLARATION_CODE} ṕr̂óp̂ér̂t́ŷ án̂d́ t̂h́êŕêf́ôŕê, {AFFECTED_PROPERTY_DECLARATION_CODE} h́âś n̂ó êf́f̂éĉt́."
4858
4858
  },
4859
4859
  "panels/elements/DOMLinkifier.ts | node": {
4860
4860
  "message": "<n̂ód̂é>"
@@ -5330,8 +5330,8 @@
5330
5330
  "panels/elements/StylesSidebarPane.ts | unknownPropertyName": {
5331
5331
  "message": "Ûńk̂ńôẃn̂ ṕr̂óp̂ér̂t́ŷ ńâḿê"
5332
5332
  },
5333
- "panels/elements/TopLayerContainer.ts | topLayer": {
5334
- "message": "t̂óp̂-ĺâýêŕ"
5333
+ "panels/elements/TopLayerContainer.ts | reveal": {
5334
+ "message": "r̂év̂éâĺ"
5335
5335
  },
5336
5336
  "panels/emulation/DeviceModeToolbar.ts | addDevicePixelRatio": {
5337
5337
  "message": "Âd́d̂ d́êv́îćê ṕîx́êĺ r̂át̂íô"
@@ -263,16 +263,13 @@ export const regexSpecialCharacters = function(): string {
263
263
  };
264
264
 
265
265
  export const filterRegex = function(query: string): RegExp {
266
- let regexString = '';
266
+ let regexString = '^(?:.*\\0)?'; // Start from beginning or after a \0
267
267
  for (let i = 0; i < query.length; ++i) {
268
268
  let c = query.charAt(i);
269
269
  if (SPECIAL_REGEX_CHARACTERS.indexOf(c) !== -1) {
270
270
  c = '\\' + c;
271
271
  }
272
- if (i) {
273
- regexString += '[^\\0' + c + ']*';
274
- }
275
- regexString += c;
272
+ regexString += '[^\\0' + c + ']*' + c;
276
273
  }
277
274
  return new RegExp(regexString, 'i');
278
275
  };
@@ -73,6 +73,9 @@ export class Target extends ProtocolClient.InspectorBackend.TargetBase {
73
73
  case Type.Browser:
74
74
  this.#capabilitiesMask = Capability.Target | Capability.IO;
75
75
  break;
76
+ case Type.Tab:
77
+ this.#capabilitiesMask = Capability.Target;
78
+ break;
76
79
  }
77
80
  this.#typeInternal = type;
78
81
  this.#parentTargetInternal = parentTarget;
@@ -227,6 +230,7 @@ export enum Type {
227
230
  Node = 'node',
228
231
  Browser = 'browser',
229
232
  AuctionWorklet = 'auction-worklet',
233
+ Tab = 'tab',
230
234
  }
231
235
 
232
236
  // TODO(crbug.com/1167717): Make this a const enum again
@@ -52,7 +52,10 @@ export class InspectorMainImpl implements Common.Runnable.Runnable {
52
52
  async run(): Promise<void> {
53
53
  let firstCall = true;
54
54
  await SDK.Connections.initMainConnection(async () => {
55
- const type = Root.Runtime.Runtime.queryParam('v8only') ? SDK.Target.Type.Node : SDK.Target.Type.Frame;
55
+ const type = Root.Runtime.Runtime.queryParam('v8only') ?
56
+ SDK.Target.Type.Node :
57
+ (Root.Runtime.Runtime.queryParam('targetType') === 'tab' ? SDK.Target.Type.Tab : SDK.Target.Type.Frame);
58
+ // TODO(crbug.com/1348385): support waiting for debugger with tab target.
56
59
  const waitForDebuggerInPage =
57
60
  type === SDK.Target.Type.Frame && Root.Runtime.Runtime.queryParam('panel') === 'sources';
58
61
  const target = SDK.TargetManager.TargetManager.instance().createTarget(
@@ -155,7 +155,7 @@ export class StackTrace extends HTMLElement {
155
155
  const expandableRows = [];
156
156
  let hiddenCallFramesCount = 0;
157
157
  for (const item of this.#stackTraceRows) {
158
- if (this.#showHidden || (!item.ignoreListHide && !item.rowCountHide)) {
158
+ if (this.#showHidden || !item.ignoreListHide) {
159
159
  if ('functionName' in item) {
160
160
  expandableRows.push(LitHtml.html`
161
161
  <${StackTraceRow.litTagName} data-stack-trace-row .data=${{
@@ -168,7 +168,7 @@ export class StackTrace extends HTMLElement {
168
168
  `);
169
169
  }
170
170
  }
171
- if (!this.#showHidden && 'functionName' in item && (item.ignoreListHide || item.rowCountHide)) {
171
+ if (!this.#showHidden && 'functionName' in item && item.ignoreListHide) {
172
172
  hiddenCallFramesCount++;
173
173
  }
174
174
  }
@@ -27,7 +27,7 @@ const UIStrings = {
27
27
  *@example {align-content} AFFECTED_PROPERTY_DECLARATION_CODE
28
28
  */
29
29
  ruleViolatedBySameElementRuleReason:
30
- 'This element has the {REASON_PROPERTY_DECLARATION_CODE} property and, therefore, {AFFECTED_PROPERTY_DECLARATION_CODE} has no effect.',
30
+ 'This element has the {REASON_PROPERTY_DECLARATION_CODE} property and therefore, {AFFECTED_PROPERTY_DECLARATION_CODE} has no effect.',
31
31
  /**
32
32
  *@description The message that is shown in the Style panel when the user hovers over a property declaration that has not effect due to some other property.
33
33
  *@example {flex-wrap: nowrap} REASON_PROPERTY_DECLARATION_CODE
@@ -47,14 +47,14 @@ const UIStrings = {
47
47
  *@example {flex} AFFECTED_PROPERTY_DECLARATION_CODE
48
48
  */
49
49
  ruleViolatedByParentElementRuleReason:
50
- 'Parent element has {REASON_PROPERTY_DECLARATION_CODE} rule, therefore this elements {AFFECTED_PROPERTY_DECLARATION_CODE} has no effect.',
50
+ 'The parent element has the {REASON_PROPERTY_DECLARATION_CODE} property and therefore, this element\'s property {AFFECTED_PROPERTY_DECLARATION_CODE} has no effect.',
51
51
  /**
52
52
  *@description The message that is shown in the Style panel when the user hovers over a property declaration that has not effect due to the properties of the parent element.
53
53
  *@example {display: block} EXISTING_PARENT_ELEMENT_RULE
54
54
  *@example {display: flex} TARGET_PARENT_ELEMENT_RULE
55
55
  */
56
56
  ruleViolatedByParentElementRuleFix:
57
- 'Please change parent element\'s {EXISTING_PARENT_ELEMENT_RULE} to {TARGET_PARENT_ELEMENT_RULE} to fix this issue.',
57
+ 'Please change the parent element\'s property declaration from {EXISTING_PARENT_ELEMENT_RULE} to {TARGET_PARENT_ELEMENT_RULE} to fix this issue.',
58
58
  };
59
59
  const str_ = i18n.i18n.registerUIStrings('panels/elements/CSSRuleValidator.ts', UIStrings);
60
60
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -103,7 +103,7 @@ export class ElementsTreeOutline extends
103
103
  private treeElementBeingDragged?: ElementsTreeElement;
104
104
  private dragOverTreeElement?: ElementsTreeElement;
105
105
  private updateModifiedNodesTimeout?: number;
106
- private topLayerContainer?: TopLayerContainer;
106
+ #topLayerContainerByParent: Map<UI.TreeOutline.TreeElement, TopLayerContainer> = new Map();
107
107
 
108
108
  constructor(omitRootDOMNode?: boolean, selectEnabled?: boolean, hideGutter?: boolean) {
109
109
  super();
@@ -453,7 +453,7 @@ export class ElementsTreeOutline extends
453
453
  }
454
454
  }
455
455
 
456
- this.createTopLayerContainer();
456
+ void this.createTopLayerContainer(this.rootElement(), this.rootDOMNode.domModel());
457
457
 
458
458
  if (selectedNode) {
459
459
  this.revealAndSelectNode(selectedNode, true);
@@ -1183,9 +1183,16 @@ export class ElementsTreeOutline extends
1183
1183
  });
1184
1184
  }
1185
1185
 
1186
- createTopLayerContainer(): void {
1187
- this.topLayerContainer = new TopLayerContainer(this);
1188
- void this.topLayerContainer.throttledUpdateTopLayerElements();
1186
+ async createTopLayerContainer(parent: UI.TreeOutline.TreeElement, domModel: SDK.DOMModel.DOMModel): Promise<void> {
1187
+ if (!parent.treeOutline || !(parent.treeOutline instanceof ElementsTreeOutline)) {
1188
+ return;
1189
+ }
1190
+ const container = new TopLayerContainer(parent.treeOutline, domModel);
1191
+ await container.throttledUpdateTopLayerElements();
1192
+ if (container.currentTopLayerElements.size > 0) {
1193
+ parent.appendChild(container);
1194
+ }
1195
+ this.#topLayerContainerByParent.set(parent, container);
1189
1196
  }
1190
1197
 
1191
1198
  private createElementTreeElement(node: SDK.DOMModel.DOMNode, isClosingTag?: boolean): ElementsTreeElement {
@@ -1342,6 +1349,9 @@ export class ElementsTreeOutline extends
1342
1349
  isClosingTag?: boolean): ElementsTreeElement {
1343
1350
  const newElement = this.createElementTreeElement(child, isClosingTag);
1344
1351
  treeElement.insertChild(newElement, index);
1352
+ if (child.nodeType() === Node.DOCUMENT_NODE) {
1353
+ void this.createTopLayerContainer(newElement, child.domModel());
1354
+ }
1345
1355
  return newElement;
1346
1356
  }
1347
1357
 
@@ -1447,8 +1457,14 @@ export class ElementsTreeOutline extends
1447
1457
  }
1448
1458
  }
1449
1459
 
1450
- private topLayerElementsChanged(): void {
1451
- void this.topLayerContainer?.throttledUpdateTopLayerElements();
1460
+ private async topLayerElementsChanged(): Promise<void> {
1461
+ for (const [parent, container] of this.#topLayerContainerByParent) {
1462
+ await container.throttledUpdateTopLayerElements();
1463
+ if (container.currentTopLayerElements.size > 0 && container.parent !== parent) {
1464
+ parent.appendChild(container);
1465
+ }
1466
+ container.hidden = container.currentTopLayerElements.size === 0;
1467
+ }
1452
1468
  }
1453
1469
 
1454
1470
  private static treeOutlineSymbol = Symbol('treeOutline');
@@ -14,23 +14,24 @@ import {type ElementsTreeElement} from './ElementsTreeElement.js';
14
14
 
15
15
  const UIStrings = {
16
16
  /**
17
- * @description Top layer is rendered closest to the user within a viewport, therefore its elements always appear on top of all other content
18
- */
19
- topLayer: 'top-layer',
17
+ *@description Link text content in Elements Tree Outline of the Elements panel. When clicked, it "reveals" the true location of an element.
18
+ */
19
+ reveal: 'reveal',
20
20
  };
21
21
 
22
22
  const str_ = i18n.i18n.registerUIStrings('panels/elements/TopLayerContainer.ts', UIStrings);
23
23
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
24
24
 
25
25
  export class TopLayerContainer extends UI.TreeOutline.TreeElement {
26
- domContainer: ElementsTreeOutline.ElementsTreeOutline;
26
+ tree: ElementsTreeOutline.ElementsTreeOutline;
27
+ domModel: SDK.DOMModel.DOMModel;
27
28
  currentTopLayerElements: Set<ElementsTreeElement>;
28
29
  topLayerUpdateThrottler: Common.Throttler.Throttler;
29
- #inserted = false;
30
30
 
31
- constructor(domContainer: ElementsTreeOutline.ElementsTreeOutline) {
31
+ constructor(tree: ElementsTreeOutline.ElementsTreeOutline, domModel: SDK.DOMModel.DOMModel) {
32
32
  super('#top-layer');
33
- this.domContainer = domContainer;
33
+ this.tree = tree;
34
+ this.domModel = domModel;
34
35
  this.currentTopLayerElements = new Set();
35
36
  this.topLayerUpdateThrottler = new Common.Throttler.Throttler(1);
36
37
  }
@@ -44,26 +45,19 @@ export class TopLayerContainer extends UI.TreeOutline.TreeElement {
44
45
  this.removeCurrentTopLayerElementsAdorners();
45
46
  this.currentTopLayerElements = new Set();
46
47
 
47
- const domModel = this.domContainer.rootDOMNode?.domModel();
48
- if (!domModel) {
49
- this.hidden = true;
50
- return;
51
- }
52
-
53
- const newTopLayerElementsIDs = await domModel.getTopLayerElements();
48
+ const newTopLayerElementsIDs = await this.domModel.getTopLayerElements();
54
49
  if (!newTopLayerElementsIDs || newTopLayerElementsIDs.length === 0) {
55
- this.hidden = true;
56
50
  return;
57
51
  }
58
52
 
59
53
  let topLayerElementIndex = 0;
60
54
  for (let i = 0; i < newTopLayerElementsIDs.length; i++) {
61
- const topLayerDOMNode = domModel.idToDOMNode.get(newTopLayerElementsIDs[i]);
55
+ const topLayerDOMNode = this.domModel.idToDOMNode.get(newTopLayerElementsIDs[i]);
62
56
  if (topLayerDOMNode && topLayerDOMNode.nodeName() !== '::backdrop') {
63
57
  const topLayerElementShortcut = new SDK.DOMModel.DOMNodeShortcut(
64
- domModel.target(), topLayerDOMNode.backendNodeId(), 0, topLayerDOMNode.nodeName());
58
+ this.domModel.target(), topLayerDOMNode.backendNodeId(), 0, topLayerDOMNode.nodeName());
65
59
  const topLayerElementRepresentation = new ElementsTreeOutline.ShortcutTreeElement(topLayerElementShortcut);
66
- const topLayerTreeElement = this.domContainer.treeElementByNode.get(topLayerDOMNode);
60
+ const topLayerTreeElement = this.tree.treeElementByNode.get(topLayerDOMNode);
67
61
  if (!topLayerTreeElement) {
68
62
  continue;
69
63
  }
@@ -73,21 +67,16 @@ export class TopLayerContainer extends UI.TreeOutline.TreeElement {
73
67
  this.currentTopLayerElements.add(topLayerTreeElement);
74
68
  this.appendChild(topLayerElementRepresentation);
75
69
  // Add the element's backdrop if previous top layer element is a backdrop.
76
- const previousTopLayerDOMNode = (i > 0) ? domModel.idToDOMNode.get(newTopLayerElementsIDs[i - 1]) : undefined;
70
+ const previousTopLayerDOMNode =
71
+ (i > 0) ? this.domModel.idToDOMNode.get(newTopLayerElementsIDs[i - 1]) : undefined;
77
72
  if (previousTopLayerDOMNode && previousTopLayerDOMNode.nodeName() === '::backdrop') {
78
73
  const backdropElementShortcut = new SDK.DOMModel.DOMNodeShortcut(
79
- domModel.target(), previousTopLayerDOMNode.backendNodeId(), 0, previousTopLayerDOMNode.nodeName());
74
+ this.domModel.target(), previousTopLayerDOMNode.backendNodeId(), 0, previousTopLayerDOMNode.nodeName());
80
75
  const backdropElementRepresentation = new ElementsTreeOutline.ShortcutTreeElement(backdropElementShortcut);
81
76
  topLayerElementRepresentation.appendChild(backdropElementRepresentation);
82
77
  }
83
78
  }
84
79
  }
85
-
86
- this.hidden = topLayerElementIndex <= 0;
87
- if (!this.hidden && !this.#inserted) {
88
- this.domContainer.appendChild(this);
89
- this.#inserted = true;
90
- }
91
80
  }
92
81
 
93
82
  private removeCurrentTopLayerElementsAdorners(): void {
@@ -118,8 +107,8 @@ export class TopLayerContainer extends UI.TreeOutline.TreeElement {
118
107
  adorner.addInteraction(onClick, {
119
108
  isToggle: false,
120
109
  shouldPropagateOnKeydown: false,
121
- ariaLabelDefault: i18nString(UIStrings.topLayer),
122
- ariaLabelActive: i18nString(UIStrings.topLayer),
110
+ ariaLabelDefault: i18nString(UIStrings.reveal),
111
+ ariaLabelActive: i18nString(UIStrings.reveal),
123
112
  });
124
113
  adorner.addEventListener('mousedown', e => e.consume(), false);
125
114
  }
@@ -4,10 +4,14 @@
4
4
  * found in the LICENSE file.
5
5
  */
6
6
 
7
+ :host {
8
+ padding: 6px;
9
+ }
10
+
7
11
  .hint-popup-wrapper {
8
- width: 400px;
9
- line-height: 1.1;
12
+ max-width: 232px;
10
13
  font-size: 12px;
14
+ line-height: 1.4;
11
15
  }
12
16
 
13
17
  code {
@@ -159,7 +159,7 @@ ol.expanded {
159
159
  position: absolute;
160
160
  top: 0;
161
161
  bottom: 0;
162
- margin: auto auto auto 5px;
162
+ margin: auto auto auto 3px;
163
163
  display: inline-block;
164
164
  cursor: pointer;
165
165
  transform: scale(0.9);
@@ -4,7 +4,9 @@
4
4
 
5
5
  import type * as Common from '../../core/common/common.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
+ import * as Bindings from '../../models/bindings/bindings.js';
7
8
  import * as Persistence from '../../models/persistence/persistence.js';
9
+ import * as Root from '../../core/root/root.js';
8
10
  import * as Workspace from '../../models/workspace/workspace.js';
9
11
  import * as QuickOpen from '../../ui/legacy/components/quick_open/quick_open.js';
10
12
  import * as UI from '../../ui/legacy/legacy.js';
@@ -62,6 +64,11 @@ export class FilteredUISourceCodeListProvider extends QuickOpen.FilteredListWidg
62
64
  if (this.uiSourceCodeUrls.has(uiSourceCode.url())) {
63
65
  return false;
64
66
  }
67
+ if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.JUST_MY_CODE) &&
68
+ Bindings.IgnoreListManager.IgnoreListManager.instance().isUserOrSourceMapIgnoreListedUISourceCode(
69
+ uiSourceCode)) {
70
+ return false;
71
+ }
65
72
  const binding = Persistence.Persistence.PersistenceImpl.instance().binding(uiSourceCode);
66
73
  return !binding || binding.fileSystem === uiSourceCode;
67
74
  }
@@ -319,14 +319,14 @@ export class OpenLinearMemoryInspector extends UI.Widget.VBox implements UI.Cont
319
319
  LinearMemoryInspector.LinearMemoryInspectorController.isMemoryObjectProperty(target.property.value)) {
320
320
  contextMenu.debugSection().appendItem(
321
321
  i18nString(UIStrings.revealInMemoryInspectorPanel),
322
- this.openMemoryInspector.bind(this, target.property.value));
322
+ this.openMemoryInspector.bind(this, target.property.name, target.property.value));
323
323
  }
324
324
  }
325
325
  }
326
326
 
327
- private async openMemoryInspector(obj: SDK.RemoteObject.RemoteObject): Promise<void> {
327
+ private async openMemoryInspector(name: string, obj: SDK.RemoteObject.RemoteObject): Promise<void> {
328
328
  const controller = LinearMemoryInspector.LinearMemoryInspectorController.LinearMemoryInspectorController.instance();
329
329
  Host.userMetrics.linearMemoryInspectorRevealedFrom(Host.UserMetrics.LinearMemoryInspectorRevealedFrom.ContextMenu);
330
- void controller.openInspectorView(obj);
330
+ void controller.openInspectorView(obj, undefined /* address */, name);
331
331
  }
332
332
  }
@@ -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 !== undefined) {
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 > data.memoryOffset + data.memory.length ||
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) to stay consistent with the DWARF extension.
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 retrieveObjectSize(obj: Bindings.DebuggerLanguagePlugins.ValueNode): number {
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
- async openInspectorView(obj: SDK.RemoteObject.RemoteObject, address?: number): Promise<void> {
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, memoryAddress);
292
- if (highlightInfo !== undefined) {
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, memoryAddress?: number): HighlightInfo|undefined {
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
- if (obj instanceof Bindings.DebuggerLanguagePlugins.ValueNode) {
314
- try {
315
- highlightInfo = {
316
- startAddress: memoryAddress || 0,
317
- size: LinearMemoryInspectorController.retrieveObjectSize(obj),
318
- };
319
- } catch (err) {
320
- highlightInfo = undefined;
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
- this.#resetHighlightInfo(bufferId);
341
- this.#paneInstance.refreshView(bufferId);
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('Highlight info start address is out of bounds.');
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.');
@@ -5,4 +5,8 @@
5
5
  export interface HighlightInfo {
6
6
  startAddress: number;
7
7
  size: number;
8
+ // If the inspector is opened from a different UI location
9
+ // than the scope view, we don't have guaranteed access to the name.
10
+ name?: string;
11
+ type: string;
8
12
  }
@@ -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(value, wasThrown, showPreview, parentElement, linkifier);
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');
@@ -94,7 +94,6 @@ export function buildStackTraceRows(
94
94
  updateCallback?: (arg0: (StackTraceRegularRow|StackTraceAsyncRow)[]) => void,
95
95
  ): (StackTraceRegularRow|StackTraceAsyncRow)[] {
96
96
  const stackTraceRows: (StackTraceRegularRow|StackTraceAsyncRow)[] = [];
97
- let regularRowCount = 0;
98
97
 
99
98
  if (updateCallback) {
100
99
  const throttler = new Common.Throttler.Throttler(100);
@@ -110,14 +109,11 @@ export function buildStackTraceRows(
110
109
  asyncRow = {
111
110
  asyncDescription: UI.UIUtils.asyncStackTraceLabel(stackTrace.description, previousCallFrames),
112
111
  ignoreListHide: false,
113
- rowCountHide: false,
114
112
  };
115
113
  stackTraceRows.push(asyncRow);
116
114
  }
117
115
  let hiddenCallFrames = 0;
118
116
  for (const stackFrame of stackTrace.callFrames) {
119
- regularRowCount++;
120
- const rowCountHide = regularRowCount > 30 && stackTrace.callFrames.length > 31;
121
117
  let ignoreListHide = false;
122
118
  const functionName = UI.UIUtils.beautifyFunctionName(stackFrame.functionName);
123
119
  const link =
@@ -125,10 +121,13 @@ export function buildStackTraceRows(
125
121
  if (link) {
126
122
  link.addEventListener('contextmenu', populateContextMenu.bind(null, link));
127
123
  // TODO(crbug.com/1183325): fix race condition with uiLocation still being null here
124
+ // Note: This has always checked whether the call frame location *in the generated
125
+ // code* is ignore-listed or not. This can change after the live location updates,
126
+ // and is handled again in the linkifier live location update callback.
128
127
  const uiLocation = Linkifier.uiLocation(link);
129
128
  if (uiLocation &&
130
- Bindings.IgnoreListManager.IgnoreListManager.instance().isUserIgnoreListedURL(
131
- uiLocation.uiSourceCode.url())) {
129
+ Bindings.IgnoreListManager.IgnoreListManager.instance().isUserOrSourceMapIgnoreListedUISourceCode(
130
+ uiLocation.uiSourceCode)) {
132
131
  ignoreListHide = true;
133
132
  }
134
133
  // Linkifier is using a workaround with the 'zero width space' (\u200b).
@@ -137,13 +136,13 @@ export function buildStackTraceRows(
137
136
  link.textContent = i18nString(UIStrings.unknownSource);
138
137
  }
139
138
  }
140
- if (rowCountHide || ignoreListHide) {
139
+ if (ignoreListHide) {
141
140
  ++hiddenCallFrames;
142
141
  }
143
- stackTraceRows.push({functionName, link, ignoreListHide, rowCountHide});
142
+ stackTraceRows.push({functionName, link, ignoreListHide});
144
143
  }
145
144
  if (asyncRow && hiddenCallFrames > 0 && hiddenCallFrames === stackTrace.callFrames.length) {
146
- stackTraceRows[1].rowCountHide ? asyncRow.rowCountHide = true : asyncRow.ignoreListHide = true;
145
+ asyncRow.ignoreListHide = true;
147
146
  }
148
147
  }
149
148
 
@@ -173,20 +172,24 @@ function updateHiddenRows(
173
172
  const row = stackTraceRows[i];
174
173
 
175
174
  if ('link' in row && row.link) {
175
+ // Note: This checks whether the call frame location *in the live location* is
176
+ // ignore-listed or not. When a source map is present, this corresponds to the
177
+ // location in the original source, not the generated source. Therefore, the
178
+ // ignore-list status might be different now from when the row was created.
176
179
  const uiLocation = Linkifier.uiLocation(row.link);
177
180
  if (uiLocation &&
178
- Bindings.IgnoreListManager.IgnoreListManager.instance().isUserIgnoreListedURL(
179
- uiLocation.uiSourceCode.url())) {
181
+ Bindings.IgnoreListManager.IgnoreListManager.instance().isUserOrSourceMapIgnoreListedUISourceCode(
182
+ uiLocation.uiSourceCode)) {
180
183
  row.ignoreListHide = true;
181
184
  }
182
- if (row.rowCountHide || row.ignoreListHide) {
185
+ if (row.ignoreListHide) {
183
186
  shouldHideSubCount++;
184
187
  }
185
188
  }
186
189
  if ('asyncDescription' in row) {
187
190
  // hide current row if all (regular) rows since the previous asyncRow are hidden
188
191
  if (shouldHideSubCount > 0 && shouldHideSubCount === indexOfAsyncRow - i - 1) {
189
- stackTraceRows[i + 1].rowCountHide ? row.rowCountHide = true : row.ignoreListHide = true;
192
+ row.ignoreListHide = true;
190
193
  }
191
194
  indexOfAsyncRow = i;
192
195
  shouldHideSubCount = 0;
@@ -238,11 +241,11 @@ function renderStackTraceTable(
238
241
  row.createChild('td').appendChild(item.link);
239
242
  links.push(item.link);
240
243
  }
241
- if (item.rowCountHide || item.ignoreListHide) {
244
+ if (item.ignoreListHide) {
242
245
  ++hiddenCallFramesCount;
243
246
  }
244
247
  }
245
- if (item.rowCountHide || item.ignoreListHide) {
248
+ if (item.ignoreListHide) {
246
249
  row.classList.add('hidden-row');
247
250
  }
248
251
  container.appendChild(row);
@@ -271,11 +274,9 @@ export interface StackTraceRegularRow {
271
274
  functionName: string;
272
275
  ignoreListHide: boolean;
273
276
  link: HTMLElement|null;
274
- rowCountHide: boolean;
275
277
  }
276
278
 
277
279
  export interface StackTraceAsyncRow {
278
280
  asyncDescription: string;
279
281
  ignoreListHide: boolean;
280
- rowCountHide: boolean;
281
282
  }
package/package.json CHANGED
@@ -56,5 +56,5 @@
56
56
  "unittest": "scripts/test/run_unittests.py --no-text-coverage",
57
57
  "watch": "vpython third_party/node/node.py --output scripts/watch_build.js"
58
58
  },
59
- "version": "1.0.1030946"
59
+ "version": "1.0.1031400"
60
60
  }