chrome-devtools-frontend 1.0.1643855 → 1.0.1646286

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.
Files changed (95) hide show
  1. package/.agents/skills/devtools-source-maps/SKILL.md +124 -0
  2. package/docs/README.md +1 -0
  3. package/docs/using_source_maps.md +159 -0
  4. package/front_end/core/host/AidaClientTypes.ts +2 -0
  5. package/front_end/core/host/UserMetrics.ts +5 -3
  6. package/front_end/core/root/Runtime.ts +10 -0
  7. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +2 -3
  8. package/front_end/core/sdk/DebuggerModel.ts +7 -9
  9. package/front_end/core/sdk/NetworkRequest.ts +0 -25
  10. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +37 -0
  11. package/front_end/generated/InspectorBackendCommands.ts +2 -2
  12. package/front_end/generated/SupportedCSSProperties.js +79 -2
  13. package/front_end/generated/protocol.ts +0 -5
  14. package/front_end/models/ai_assistance/AiAgent2.ts +52 -15
  15. package/front_end/models/ai_assistance/AiConversation.ts +4 -2
  16. package/front_end/models/ai_assistance/AiOrigins.ts +63 -2
  17. package/front_end/models/ai_assistance/README.md +20 -8
  18. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +2 -2
  19. package/front_end/models/ai_assistance/agents/FileAgent.ts +9 -42
  20. package/front_end/models/ai_assistance/agents/NetworkAgent.snapshot.txt +2 -2
  21. package/front_end/models/ai_assistance/agents/NetworkAgent.ts +9 -133
  22. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +25 -2
  23. package/front_end/models/ai_assistance/agents/README.md +64 -0
  24. package/front_end/models/ai_assistance/agents/StylingAgent.ts +26 -3
  25. package/front_end/models/ai_assistance/ai_assistance.ts +4 -0
  26. package/front_end/models/ai_assistance/contexts/FileContext.ts +45 -0
  27. package/front_end/models/ai_assistance/contexts/RequestContext.snapshot.txt +48 -0
  28. package/front_end/models/ai_assistance/contexts/RequestContext.ts +116 -0
  29. package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +2 -1
  30. package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +9 -12
  31. package/front_end/models/ai_assistance/tools/GetStyles.ts +19 -12
  32. package/front_end/models/ai_assistance/tools/README.md +45 -0
  33. package/front_end/models/ai_assistance/tools/Tool.ts +74 -11
  34. package/front_end/models/ai_assistance/tools/ToolRegistry.ts +21 -5
  35. package/front_end/models/heap_snapshot/HeapSnapshotModel.ts +18 -2
  36. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +4 -0
  37. package/front_end/models/stack_trace/DetailedErrorStackParser.ts +17 -4
  38. package/front_end/models/stack_trace/StackTraceModel.ts +34 -1
  39. package/front_end/models/trace/Styles.ts +29 -7
  40. package/front_end/models/trace/handlers/NetworkRequestsHandler.ts +15 -11
  41. package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +33 -4
  42. package/front_end/models/trace/helpers/Timing.ts +10 -0
  43. package/front_end/models/trace/types/TraceEvents.ts +22 -2
  44. package/front_end/models/web_mcp/WebMCPModel.ts +8 -48
  45. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +21 -15
  46. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +16 -0
  47. package/front_end/panels/ai_assistance/components/ChatInput.ts +4 -4
  48. package/front_end/panels/application/ApplicationPanelSidebar.ts +69 -0
  49. package/front_end/panels/application/ServiceWorkersView.ts +2 -2
  50. package/front_end/panels/application/WebMCPView.ts +40 -71
  51. package/front_end/panels/application/components/AdsView.ts +31 -28
  52. package/front_end/panels/application/components/BackForwardCacheView.ts +1 -2
  53. package/front_end/panels/application/components/adsView.css +6 -0
  54. package/front_end/panels/common/ExtensionServer.ts +5 -0
  55. package/front_end/panels/console/ConsoleView.ts +6 -1
  56. package/front_end/panels/console/ConsoleViewMessage.ts +46 -213
  57. package/front_end/panels/console/SymbolizedErrorWidget.ts +4 -1
  58. package/front_end/panels/elements/AdoptedStyleSheetTreeElement.ts +0 -1
  59. package/front_end/panels/elements/ElementsTreeElement.ts +0 -2
  60. package/front_end/panels/elements/PropertyRenderer.ts +0 -1
  61. package/front_end/panels/elements/StylesSidebarPane.ts +9 -2
  62. package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
  63. package/front_end/panels/issues/AffectedSourcesView.ts +1 -1
  64. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +0 -1
  65. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +10 -0
  66. package/front_end/panels/network/NetworkDataGridNode.ts +1 -2
  67. package/front_end/panels/network/NetworkLogView.ts +34 -7
  68. package/front_end/panels/profiler/HeapProfileView.ts +0 -1
  69. package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +0 -1
  70. package/front_end/panels/profiler/HeapSnapshotView.ts +1 -1
  71. package/front_end/panels/profiler/IsolateSelector.ts +4 -2
  72. package/front_end/panels/profiler/ProfileLauncherView.ts +194 -126
  73. package/front_end/panels/profiler/ProfilesPanel.ts +1 -3
  74. package/front_end/panels/settings/components/SyncSection.ts +1 -1
  75. package/front_end/panels/timeline/TimelineFlameChartView.ts +5 -4
  76. package/front_end/panels/timeline/TimelinePanel.ts +7 -0
  77. package/front_end/panels/timeline/TimelineUIUtils.ts +13 -14
  78. package/front_end/panels/timeline/TimingsTrackAppender.ts +7 -5
  79. package/front_end/panels/timeline/components/LayoutShiftDetails.ts +0 -1
  80. package/front_end/panels/timeline/components/NetworkRequestDetails.ts +0 -2
  81. package/front_end/panels/timeline/components/insights/ForcedReflow.ts +0 -1
  82. package/front_end/panels/timeline/components/insights/NodeLink.ts +0 -1
  83. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +2 -0
  84. package/front_end/third_party/chromium/README.chromium +1 -1
  85. package/front_end/ui/helpers/OpenInNewTab.ts +3 -3
  86. package/front_end/ui/kit/link/Link.ts +16 -2
  87. package/front_end/ui/legacy/InspectorDrawerView.ts +14 -5
  88. package/front_end/ui/legacy/InspectorView.ts +4 -1
  89. package/front_end/ui/legacy/PlusButton.ts +6 -1
  90. package/front_end/ui/legacy/Widget.ts +19 -1
  91. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +95 -31
  92. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +0 -1
  93. package/front_end/ui/legacy/components/utils/Linkifier.ts +2 -16
  94. package/front_end/ui/visual_logging/KnownContextValues.ts +6 -0
  95. package/package.json +1 -1
@@ -57,15 +57,15 @@ import * as SDK from '../../core/sdk/sdk.js';
57
57
  * @throws TypeError if `url` is not a valid URL.
58
58
  * @see https://en.wikipedia.org/wiki/UTM_parameters
59
59
  */
60
- export function openInNewTab(url: URL|string): void {
60
+ export function openInNewTab(url: URL|string, allowPrivileged?: boolean): void {
61
61
  url = new URL(url);
62
62
  if (Common.ParsedURL.schemeIs(url, 'javascript:')) {
63
63
  return;
64
64
  }
65
65
 
66
66
  // Navigating to a chrome:// link via a normal anchor doesn't work, so we "navigate"
67
- // there using CDP.
68
- if (Common.ParsedURL.schemeIs(url, 'chrome:')) {
67
+ // there using CDP if explicitly requested.
68
+ if (allowPrivileged && Common.ParsedURL.schemeIs(url, 'chrome:')) {
69
69
  const rootTarget = SDK.TargetManager.TargetManager.instance().rootTarget();
70
70
  if (rootTarget === null) {
71
71
  return;
@@ -60,7 +60,7 @@ export class Link extends HTMLElement {
60
60
  return;
61
61
  }
62
62
 
63
- UIHelpers.openInNewTab(href);
63
+ UIHelpers.openInNewTab(href, this.allowPrivileged);
64
64
 
65
65
  event.consume();
66
66
  }
@@ -73,6 +73,18 @@ export class Link extends HTMLElement {
73
73
  this.setAttribute('href', href);
74
74
  }
75
75
 
76
+ get allowPrivileged(): boolean {
77
+ return this.hasAttribute('allow-privileged');
78
+ }
79
+
80
+ set allowPrivileged(allowPrivileged: boolean) {
81
+ if (allowPrivileged) {
82
+ this.setAttribute('allow-privileged', '');
83
+ } else {
84
+ this.removeAttribute('allow-privileged');
85
+ }
86
+ }
87
+
76
88
  get jslogContext(): string|null {
77
89
  return this.getAttribute('jslogcontext');
78
90
  }
@@ -98,7 +110,7 @@ export class Link extends HTMLElement {
98
110
  oldValue: string|null,
99
111
  newValue: string|null,
100
112
  ): void {
101
- if (oldValue !== newValue) {
113
+ if (oldValue === newValue) {
102
114
  return;
103
115
  }
104
116
  if (name === 'jslogcontext') {
@@ -145,9 +157,11 @@ export class Link extends HTMLElement {
145
157
  className?: string,
146
158
  jsLogContext?: string,
147
159
  tabindex = 0,
160
+ allowPrivileged = false,
148
161
  ): Link {
149
162
  const link = new Link();
150
163
  link.href = url as Platform.DevToolsPath.UrlString;
164
+ link.allowPrivileged = allowPrivileged;
151
165
  linkText = linkText ?? url;
152
166
  link.textContent = Platform.StringUtilities.trimMiddle(linkText, 150);
153
167
 
@@ -4,6 +4,7 @@
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
+ import * as Root from '../../core/root/root.js';
7
8
  import * as VisualLogging from '../visual_logging/visual_logging.js';
8
9
 
9
10
  import * as ARIAUtils from './ARIAUtils.js';
@@ -129,11 +130,19 @@ export class InspectorDrawerView {
129
130
  this.#isConsoleOpenInMainAndDrawer = options.isConsoleOpenInMainAndDrawer;
130
131
  this.#drawerMinimizedSetting =
131
132
  Common.Settings.Settings.instance().createLocalSetting('inspector.drawer-minimized', false);
132
- this.tabbedLocation = ViewManager.instance().createTabbedLocation(
133
- options.revealDrawer, 'drawer-view', true, true,
134
- {isLocationVisible: options.isVisible, tabbedPaneFactory: () => new DrawerTabbedPane()});
135
- this.#moreTabsButton = this.tabbedLocation.enableMoreTabsButton();
136
- this.#moreTabsButton.setTitle(i18nString(UIStrings.moreTools));
133
+ this.tabbedLocation = ViewManager.instance().createTabbedLocation(options.revealDrawer, 'drawer-view', true, true, {
134
+ isLocationVisible: options.isVisible,
135
+ tabbedPaneFactory: () => new DrawerTabbedPane(),
136
+ plusButton: {title: i18nString(UIStrings.moreTools), jslogContext: 'plus-button-drawer'},
137
+ });
138
+ // When the plus button is disabled we keep the legacy left-toolbar
139
+ // three-dot menu so users can still reach hidden / addable tools.
140
+ if (Root.Runtime.hostConfig.devToolsPlusButton?.enabled) {
141
+ this.#moreTabsButton = null;
142
+ } else {
143
+ this.#moreTabsButton = this.tabbedLocation.enableMoreTabsButton();
144
+ this.#moreTabsButton.setTitle(i18nString(UIStrings.moreTools));
145
+ }
137
146
  this.tabbedPane = this.tabbedLocation.tabbedPane() as DrawerTabbedPane;
138
147
  this.tabbedPane.element.classList.add('drawer-tabbed-pane');
139
148
  this.tabbedPane.element.setAttribute('jslog', `${VisualLogging.drawer()}`);
@@ -228,7 +228,10 @@ export class InspectorView extends VBox implements ViewLocationResolver {
228
228
  this.tabbedLocation = ViewManager.instance().createTabbedLocation(
229
229
  Host.InspectorFrontendHost.InspectorFrontendHostInstance.bringToFront.bind(
230
230
  Host.InspectorFrontendHost.InspectorFrontendHostInstance),
231
- 'panel', true, true, {defaultTab: Root.Runtime.Runtime.queryParam('panel')});
231
+ 'panel', true, true, {
232
+ defaultTab: Root.Runtime.Runtime.queryParam('panel'),
233
+ plusButton: {jslogContext: 'plus-button-panel'},
234
+ });
232
235
 
233
236
  this.tabbedPane = this.tabbedLocation.tabbedPane();
234
237
  this.tabbedPane.setMinimumSize(MIN_MAIN_PANEL_WIDTH, 0);
@@ -108,8 +108,13 @@ export class PlusButtonPresenter {
108
108
  for (const view of views()) {
109
109
  // Skip views that already have a tab. Hidden tabs are already listed
110
110
  // in the overflow section above, and visible tabs are accessible
111
- // directly in the tab strip.
111
+ // directly in the tab strip. Track their id and title so the
112
+ // cross-location loop below cannot offer a same-titled duplicate
113
+ // (e.g. drawer "Console" while the panel "Console" is already
114
+ // visible — they have different view ids).
112
115
  if (tabbedPane.hasTab(view.viewId())) {
116
+ seenIds.add(view.viewId());
117
+ seenTitles.add(view.title());
113
118
  continue;
114
119
  }
115
120
  // Transient views are not user-addable.
@@ -483,6 +483,12 @@ export type WidgetOptions<ContentTypeT extends HTMLElement|DocumentFragment = HT
483
483
  classes?: never,
484
484
  });
485
485
 
486
+ const enum UpdateState {
487
+ NORMAL = 'NORMAL', // Standard state: update can be aborted for efficiency.
488
+ INTERRUPTED = 'INTERRUPTED', // An update was physically running and got aborted; replacement must be shielded.
489
+ SHIELDED = 'SHIELDED', // Current update is a replacement for an interrupted one and cannot be aborted.
490
+ }
491
+
486
492
  export class Widget<ContentTypeT extends HTMLElement|DocumentFragment = HTMLElement> {
487
493
  readonly element: HTMLElement;
488
494
  #contentElement: ContentTypeT;
@@ -501,6 +507,7 @@ export class Widget<ContentTypeT extends HTMLElement|DocumentFragment = HTMLElem
501
507
  #externallyManaged?: boolean;
502
508
  #updateComplete = UPDATE_COMPLETE;
503
509
  #updateController?: AbortController;
510
+ #updateState = UpdateState.NORMAL;
504
511
 
505
512
  /**
506
513
  * Constructs a new `Widget` with the given `options`.
@@ -1165,12 +1172,17 @@ export class Widget<ContentTypeT extends HTMLElement|DocumentFragment = HTMLElem
1165
1172
  }
1166
1173
 
1167
1174
  addUpdateController(controller: AbortController): void {
1175
+ const wasInterrupted = this.#updateState === UpdateState.INTERRUPTED;
1168
1176
  this.#updateController?.abort();
1169
1177
  this.#updateController = controller;
1178
+ // Transition to SHIELDED if we are replacing a starved update, otherwise reset to NORMAL.
1179
+ this.#updateState = wasInterrupted ? UpdateState.SHIELDED : UpdateState.NORMAL;
1170
1180
  }
1171
1181
 
1172
1182
  cancelUpdateController(): void {
1173
1183
  this.#updateController?.abort();
1184
+ this.#updateController = undefined;
1185
+ this.#updateState = UpdateState.NORMAL;
1174
1186
  }
1175
1187
 
1176
1188
  /**
@@ -1180,7 +1192,13 @@ export class Widget<ContentTypeT extends HTMLElement|DocumentFragment = HTMLElem
1180
1192
  * frame.
1181
1193
  */
1182
1194
  requestUpdate(): void {
1183
- this.#updateController?.abort();
1195
+ // If the state is SHIELDED, we skip the abort call entirely to break the starvation loop.
1196
+ if (this.#updateState !== UpdateState.SHIELDED) {
1197
+ if (currentlyProcessed.has(this)) {
1198
+ this.#updateState = UpdateState.INTERRUPTED;
1199
+ }
1200
+ this.#updateController?.abort();
1201
+ }
1184
1202
  this.#updateComplete = enqueueWidgetUpdate(this);
1185
1203
  }
1186
1204
 
@@ -71,6 +71,10 @@ const UIStrings = {
71
71
  * @description Text to collapse children of a parent group
72
72
  */
73
73
  collapseChildren: 'Collapse children',
74
+ /**
75
+ * @description A context menu item in the Object Properties Section to choose property ordering.
76
+ */
77
+ sortPropertiesAlphabetically: 'Sort properties alphabetically',
74
78
  /**
75
79
  * @description Text in Object Properties Section
76
80
  */
@@ -155,6 +159,22 @@ export interface ObjectTreeOptions {
155
159
  readonly expansionTracker?: ObjectTreeExpansionTracker;
156
160
  }
157
161
 
162
+ let cachedSortAlphabeticallySetting: Common.Settings.Setting<boolean>|undefined;
163
+ export function sortPropertiesAlphabeticallySetting(): Common.Settings.Setting<boolean> {
164
+ if (!cachedSortAlphabeticallySetting) {
165
+ cachedSortAlphabeticallySetting =
166
+ Common.Settings.Settings.instance().createSetting('object-properties-sort-alphabetically', true);
167
+ }
168
+ return cachedSortAlphabeticallySetting;
169
+ }
170
+
171
+ // WASM properties are index-based (e.g. locals[0], globals[1]); alphabetical
172
+ // reordering would break the correspondence between displayed index and actual
173
+ // index, so WASM objects are always shown in insertion order.
174
+ export function isWasmObject(object: SDK.RemoteObject.RemoteObject|undefined): boolean {
175
+ return object?.subtype === 'webassemblymemory' || object?.subtype === 'wasmvalue';
176
+ }
177
+
158
178
  type KeyTypes = {
159
179
  [K in keyof Required<NodeChildren>]: Key<Required<NodeChildren>[K][0]>;
160
180
  };
@@ -362,13 +382,19 @@ export class ObjectTreeExpansionTracker {
362
382
 
363
383
  export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrapper<ObjectTreeNodeBase.EventTypes> {
364
384
  #children?: NodeChildren;
385
+ protected readonly options: ObjectTreeOptions;
365
386
  protected filter: {includeNullOrUndefinedValues: boolean, regex: RegExp|null}|null = null;
366
387
  protected extraProperties: ObjectTreeNode[] = [];
367
388
  #expanded = false;
368
389
 
369
- constructor(readonly parent: ObjectTreeNodeBase|undefined, protected readonly options: ObjectTreeOptions) {
390
+ constructor(readonly parent: ObjectTreeNodeBase|undefined, options: ObjectTreeOptions) {
370
391
  super();
371
392
  this.filter = parent?.filter ?? null;
393
+ this.options = {...options};
394
+ }
395
+
396
+ get isWasm(): boolean {
397
+ return isWasmObject(this.object);
372
398
  }
373
399
  get expanded(): boolean {
374
400
  return this.#expanded;
@@ -399,6 +425,22 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
399
425
  this.setFilter({includeNullOrUndefinedValues: value, regex: this.filter?.regex ?? null});
400
426
  }
401
427
 
428
+ get sortPropertiesAlphabetically(): boolean {
429
+ if (this.isWasm) {
430
+ return false;
431
+ }
432
+ return sortPropertiesAlphabeticallySetting().get();
433
+ }
434
+
435
+ set sortPropertiesAlphabetically(value: boolean) {
436
+ const setting = sortPropertiesAlphabeticallySetting();
437
+ if (this.isWasm || setting.get() === value) {
438
+ return;
439
+ }
440
+ setting.set(value);
441
+ this.removeChildren();
442
+ }
443
+
402
444
  // Performs a pre-order tree traversal over the populated children. If any children need to be populated, callers must
403
445
  // do that while walking (pre-order visitation enables that).
404
446
  * #walk(maxDepth = -1): Generator<ObjectTreeNodeBase> {
@@ -499,13 +541,12 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
499
541
 
500
542
  if (this.arrayLength > ARRAY_LOAD_THRESHOLD) {
501
543
  const ranges = await arrayRangeGroups(object, 0, this.arrayLength - 1);
502
- const arrayRanges = ranges?.ranges.map(
503
- ([fromIndex, toIndex, count]) =>
504
- new ArrayGroupTreeNode(object, {fromIndex, toIndex, count}, effectiveParent, {
505
- readOnly: this.readOnly,
506
- propertiesMode: this.propertiesMode,
507
- expansionTracker: this.options.expansionTracker
508
- }));
544
+ const arrayRanges = ranges?.ranges.map(([fromIndex, toIndex, count]) => new ArrayGroupTreeNode(
545
+ object, {fromIndex, toIndex, count}, effectiveParent, {
546
+ readOnly: this.readOnly,
547
+ propertiesMode: this.propertiesMode,
548
+ expansionTracker: this.options.expansionTracker,
549
+ }));
509
550
  if (!arrayRanges) {
510
551
  return {};
511
552
  }
@@ -517,14 +558,14 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
517
558
  const properties = objectProperties?.map(p => new ObjectTreeNode(p, effectiveParent, {
518
559
  readOnly: this.readOnly,
519
560
  propertiesMode: ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
520
- expansionTracker: this.options.expansionTracker
561
+ expansionTracker: this.options.expansionTracker,
521
562
  }));
522
563
 
523
564
  const internalProperties =
524
565
  objectInternalProperties?.map(p => new ObjectTreeNode(p, effectiveParent, {
525
566
  readOnly: this.readOnly,
526
567
  propertiesMode: ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
527
- expansionTracker: this.options.expansionTracker
568
+ expansionTracker: this.options.expansionTracker,
528
569
  }));
529
570
  return {arrayRanges, properties, internalProperties};
530
571
  }
@@ -545,17 +586,17 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
545
586
  const properties = objectProperties?.map(p => new ObjectTreeNode(p, effectiveParent, {
546
587
  readOnly: this.readOnly,
547
588
  propertiesMode: ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
548
- expansionTracker: this.options.expansionTracker
589
+ expansionTracker: this.options.expansionTracker,
549
590
  }));
550
591
  properties?.push(...this.extraProperties);
551
- properties?.sort(ObjectPropertiesSection.compareProperties);
592
+ properties?.sort((a, b) => ObjectPropertiesSection.compareProperties(a, b, this.sortPropertiesAlphabetically));
552
593
  const accessors = properties && ObjectTreeNodeBase.getGettersAndSetters(properties, this.options);
553
594
 
554
595
  const internalProperties =
555
596
  objectInternalProperties?.map(p => new ObjectTreeNode(p, effectiveParent, {
556
597
  readOnly: this.readOnly,
557
598
  propertiesMode: ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
558
- expansionTracker: this.options.expansionTracker
599
+ expansionTracker: this.options.expansionTracker,
559
600
  }));
560
601
  return {properties, internalProperties, accessors};
561
602
  }
@@ -577,7 +618,7 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
577
618
  this.extraProperties.push(...properties.map(p => new ObjectTreeNode(p, this, {
578
619
  readOnly: this.readOnly,
579
620
  propertiesMode: ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
580
- expansionTracker: this.options.expansionTracker
621
+ expansionTracker: this.options.expansionTracker,
581
622
  })));
582
623
  }
583
624
 
@@ -591,7 +632,7 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
591
632
  gettersAndSetters.push(new ObjectTreeNode(getterProperty, property.parent, {
592
633
  propertiesMode: property.propertiesMode,
593
634
  readOnly: property.readOnly,
594
- expansionTracker: options.expansionTracker
635
+ expansionTracker: options.expansionTracker,
595
636
  }));
596
637
  }
597
638
  if (property.property.setter) {
@@ -600,7 +641,7 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
600
641
  gettersAndSetters.push(new ObjectTreeNode(setterProperty, property.parent, {
601
642
  propertiesMode: property.propertiesMode,
602
643
  readOnly: property.readOnly,
603
- expansionTracker: options.expansionTracker
644
+ expansionTracker: options.expansionTracker,
604
645
  }));
605
646
  }
606
647
  }
@@ -658,7 +699,7 @@ export class ArrayGroupTreeNode extends ObjectTreeNodeBase {
658
699
  ([fromIndex, toIndex, count]) => new ArrayGroupTreeNode(this.object, {fromIndex, toIndex, count}, this, {
659
700
  readOnly: this.readOnly,
660
701
  propertiesMode: this.propertiesMode,
661
- expansionTracker: this.options.expansionTracker
702
+ expansionTracker: this.options.expansionTracker,
662
703
  }));
663
704
  return {arrayRanges};
664
705
  }
@@ -678,10 +719,10 @@ export class ArrayGroupTreeNode extends ObjectTreeNodeBase {
678
719
  const properties = allProperties.properties?.map(p => new ObjectTreeNode(p, this, {
679
720
  propertiesMode: this.propertiesMode,
680
721
  readOnly: this.readOnly,
681
- expansionTracker: this.options.expansionTracker
722
+ expansionTracker: this.options.expansionTracker,
682
723
  }));
683
724
  properties?.push(...this.extraProperties);
684
- properties?.sort(ObjectPropertiesSection.compareProperties);
725
+ properties?.sort((a, b) => ObjectPropertiesSection.compareProperties(a, b, this.sortPropertiesAlphabetically));
685
726
  const accessors = properties && ObjectTreeNodeBase.getGettersAndSetters(properties, this.options);
686
727
  return {properties, accessors};
687
728
  }
@@ -872,15 +913,16 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
872
913
  }
873
914
 
874
915
  // The RemoteObjectProperty overload is kept for web test compatibility for now.
875
- static compareProperties(
876
- propertyA: ObjectTreeNode|SDK.RemoteObject.RemoteObjectProperty,
877
- propertyB: ObjectTreeNode|SDK.RemoteObject.RemoteObjectProperty): number {
916
+ static compareProperties(propertyA: ObjectTreeNode|SDK.RemoteObject.RemoteObjectProperty,
917
+ propertyB: ObjectTreeNode|SDK.RemoteObject.RemoteObjectProperty,
918
+ sortPropertiesAlphabetically = true): number {
878
919
  if (propertyA instanceof ObjectTreeNode) {
879
920
  propertyA = propertyA.property;
880
921
  }
881
922
  if (propertyB instanceof ObjectTreeNode) {
882
923
  propertyB = propertyB.property;
883
924
  }
925
+
884
926
  if (!propertyA.synthetic && propertyB.synthetic) {
885
927
  return 1;
886
928
  }
@@ -911,15 +953,20 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
911
953
  if (propertyB.private && !propertyA.private) {
912
954
  return -1;
913
955
  }
914
- const a = propertyA.name;
915
- const b = propertyB.name;
916
- if (a.startsWith('_') && !b.startsWith('_')) {
917
- return 1;
918
- }
919
- if (b.startsWith('_') && !a.startsWith('_')) {
920
- return -1;
956
+
957
+ if (sortPropertiesAlphabetically) {
958
+ const nameA = propertyA.name;
959
+ const nameB = propertyB.name;
960
+ if (nameA.startsWith('_') && !nameB.startsWith('_')) {
961
+ return 1;
962
+ }
963
+ if (nameB.startsWith('_') && !nameA.startsWith('_')) {
964
+ return -1;
965
+ }
966
+ return Platform.StringUtilities.naturalOrderComparator(nameA, nameB);
921
967
  }
922
- return Platform.StringUtilities.naturalOrderComparator(a, b);
968
+
969
+ return 0;
923
970
  }
924
971
 
925
972
  static createNameElement(name: string|null, isPrivate?: boolean): Element {
@@ -1297,6 +1344,14 @@ export class RootElement extends UI.TreeOutline.TreeElement {
1297
1344
  {jslogContext: 'expand-recursively'});
1298
1345
  contextMenu.viewSection().appendItem(
1299
1346
  i18nString(UIStrings.collapseChildren), this.collapseChildren.bind(this), {jslogContext: 'collapse-children'});
1347
+ if (!this.object.isWasm) {
1348
+ contextMenu.viewSection().appendCheckboxItem(i18nString(UIStrings.sortPropertiesAlphabetically), () => {
1349
+ this.object.sortPropertiesAlphabetically = !this.object.sortPropertiesAlphabetically;
1350
+ }, {
1351
+ checked: this.object.sortPropertiesAlphabetically,
1352
+ jslogContext: 'sort-properties-alphabetically',
1353
+ });
1354
+ }
1300
1355
  contextMenu.viewSection().appendCheckboxItem(i18n.i18n.lockedString('Show all'), () => {
1301
1356
  this.object.includeNullOrUndefinedValues = !this.object.includeNullOrUndefinedValues;
1302
1357
  }, {checked: this.object.includeNullOrUndefinedValues, jslogContext: 'show-all'});
@@ -1650,7 +1705,8 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1650
1705
  if (arrayRanges && arrayRanges.length > 0) {
1651
1706
  empty = false;
1652
1707
  }
1653
- properties?.sort(ObjectPropertiesSection.compareProperties);
1708
+ const sortPropertiesAlphabetically = properties?.[0]?.parent?.sortPropertiesAlphabetically ?? true;
1709
+ properties?.sort((a, b) => ObjectPropertiesSection.compareProperties(a, b, sortPropertiesAlphabetically));
1654
1710
 
1655
1711
  const entriesProperty = internalProperties?.find(({property}) => property.name === '[[Entries]]');
1656
1712
  if (entriesProperty) {
@@ -1850,6 +1906,14 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1850
1906
  while (root.parent) {
1851
1907
  root = root.parent;
1852
1908
  }
1909
+ if (!root.isWasm) {
1910
+ contextMenu.viewSection().appendCheckboxItem(i18nString(UIStrings.sortPropertiesAlphabetically), () => {
1911
+ root.sortPropertiesAlphabetically = !root.sortPropertiesAlphabetically;
1912
+ }, {
1913
+ checked: root.sortPropertiesAlphabetically,
1914
+ jslogContext: 'sort-properties-alphabetically',
1915
+ });
1916
+ }
1853
1917
  contextMenu.viewSection().appendCheckboxItem(i18n.i18n.lockedString('Show all'), () => {
1854
1918
  root.includeNullOrUndefinedValues = !root.includeNullOrUndefinedValues;
1855
1919
  }, {checked: root.includeNullOrUndefinedValues, jslogContext: 'show-all'});
@@ -156,7 +156,6 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
156
156
  const link = Linkifier.linkifyStackTraceFrame(frame, {
157
157
  showColumnNumber: Boolean(input.showColumnNumber),
158
158
  tabStop: Boolean(input.tabStops),
159
- inlineFrameIndex: 0,
160
159
  revealBreakpoint: previousStackFrameWasBreakpointCondition,
161
160
  maxLength: UI.UIUtils.MaxLengthForDisplayedURLsInConsole,
162
161
  ignoreListManager: input.ignoreListManager,
@@ -237,7 +237,6 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
237
237
  showColumnNumber: Boolean(options?.showColumnNumber),
238
238
  className: options?.className,
239
239
  tabStop: options?.tabStop,
240
- inlineFrameIndex: options?.inlineFrameIndex ?? 0,
241
240
  userMetric: options?.userMetric,
242
241
  jslogContext: options?.jslogContext || 'script-location',
243
242
  omitOrigin: options?.omitOrigin,
@@ -257,10 +256,8 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
257
256
  // Prefer createRawLocationByScriptId() here, since it will always produce a correct
258
257
  // link, since the script ID is unique. Only fall back to createRawLocationByURL()
259
258
  // when all we have is an URL, which is not guaranteed to be unique.
260
- const rawLocation = scriptId ? debuggerModel.createRawLocationByScriptId(
261
- scriptId, lineNumber || 0, columnNumber, linkifyURLOptions.inlineFrameIndex) :
262
- debuggerModel.createRawLocationByURL(
263
- sourceURL, lineNumber || 0, columnNumber, linkifyURLOptions.inlineFrameIndex);
259
+ const rawLocation = scriptId ? debuggerModel.createRawLocationByScriptId(scriptId, lineNumber || 0, columnNumber) :
260
+ debuggerModel.createRawLocationByURL(sourceURL, lineNumber || 0, columnNumber);
264
261
  if (!rawLocation) {
265
262
  return fallbackAnchor;
266
263
  }
@@ -313,7 +310,6 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
313
310
  className: options?.className,
314
311
  columnNumber: options?.columnNumber,
315
312
  showColumnNumber: Boolean(options?.showColumnNumber),
316
- inlineFrameIndex: options?.inlineFrameIndex ?? 0,
317
313
  tabStop: options?.tabStop,
318
314
  userMetric: options?.userMetric,
319
315
  jslogContext: options?.jslogContext || 'script-source-url',
@@ -329,7 +325,6 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
329
325
  rawLocation.debuggerModel.target(), rawLocation.scriptId, fallbackUrl, rawLocation.lineNumber, {
330
326
  columnNumber: rawLocation.columnNumber,
331
327
  className,
332
- inlineFrameIndex: rawLocation.inlineFrameIndex,
333
328
  tabStop: options?.tabStop,
334
329
  });
335
330
  }
@@ -340,7 +335,6 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
340
335
  const linkifyOptions: LinkifyOptions = {
341
336
  ...options,
342
337
  columnNumber: callFrame.columnNumber,
343
- inlineFrameIndex: options?.inlineFrameIndex ?? 0,
344
338
  };
345
339
  return this.maybeLinkifyScriptLocation(
346
340
  target, String(callFrame.scriptId) as Protocol.Runtime.ScriptId,
@@ -355,7 +349,6 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
355
349
  showColumnNumber: Boolean(options?.showColumnNumber),
356
350
  className: options?.className,
357
351
  tabStop: options?.tabStop,
358
- inlineFrameIndex: options?.inlineFrameIndex ?? 0,
359
352
  userMetric: options?.userMetric,
360
353
  jslogContext: options?.jslogContext || 'script-location',
361
354
  omitOrigin: options?.omitOrigin,
@@ -394,7 +387,6 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
394
387
  showColumnNumber: Boolean(options?.showColumnNumber),
395
388
  className: options?.className,
396
389
  tabStop: options?.tabStop,
397
- inlineFrameIndex: options?.inlineFrameIndex ?? 0,
398
390
  userMetric: options?.userMetric,
399
391
  jslogContext: options?.jslogContext || 'script-location',
400
392
  omitOrigin: options?.omitOrigin,
@@ -424,7 +416,6 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
424
416
  lineNumber,
425
417
  columnNumber,
426
418
  showColumnNumber: false,
427
- inlineFrameIndex: 0,
428
419
  maxLength: this.maxLength,
429
420
  preventClick: true,
430
421
  jslogContext: 'script-source-url',
@@ -595,7 +586,6 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
595
586
  static renderLinkifiedUrl(url: Platform.DevToolsPath.UrlString, options?: LinkifyURLOptions): TemplateResult {
596
587
  options = options || {
597
588
  showColumnNumber: false,
598
- inlineFrameIndex: 0,
599
589
  };
600
590
 
601
591
  const text = options.text;
@@ -724,7 +714,6 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
724
714
  url: options.href || null,
725
715
  lineNumber: options.lineNumber ?? null,
726
716
  columnNumber: options.columnNumber ?? null,
727
- inlineFrameIndex: 0,
728
717
  revealable: null,
729
718
  fallback: null,
730
719
  userMetric: options.userMetric,
@@ -1174,7 +1163,6 @@ interface LinkInfo {
1174
1163
  url: Platform.DevToolsPath.UrlString|null;
1175
1164
  lineNumber: number|null;
1176
1165
  columnNumber: number|null;
1177
- inlineFrameIndex: number;
1178
1166
  revealable: Object|null;
1179
1167
  fallback: Element|null;
1180
1168
  userMetric?: Host.UserMetrics.Action;
@@ -1187,7 +1175,6 @@ export interface LinkifyURLOptions {
1187
1175
  lineNumber?: number;
1188
1176
  columnNumber?: number;
1189
1177
  showColumnNumber?: boolean;
1190
- inlineFrameIndex?: number;
1191
1178
  preventClick?: boolean;
1192
1179
  maxLength?: number;
1193
1180
  tabStop?: boolean;
@@ -1203,7 +1190,6 @@ export interface LinkifyOptions {
1203
1190
  className?: string;
1204
1191
  columnNumber?: number;
1205
1192
  showColumnNumber?: boolean;
1206
- inlineFrameIndex?: number;
1207
1193
  tabStop?: boolean;
1208
1194
  userMetric?: Host.UserMetrics.Action;
1209
1195
  jslogContext?: string;
@@ -345,6 +345,7 @@ export const knownContextValues = new Set([
345
345
  'addedSize',
346
346
  'additive-symbols',
347
347
  'adorner-settings',
348
+ 'ads',
348
349
  'af',
349
350
  'affected-cookies',
350
351
  'affected-documents',
@@ -362,6 +363,7 @@ export const knownContextValues = new Set([
362
363
  'ai-assistance-v2-opt-in-change-dialog-seen',
363
364
  'ai-assistance-v2-opt-in.got-it',
364
365
  'ai-assistance-v2-opt-in.manage-settings',
366
+ 'ai-assistance.application-panel-context',
365
367
  'ai-assistance.storage-floating-button',
366
368
  'ai-code-completion-citations',
367
369
  'ai-code-completion-citations.citation-link',
@@ -2896,6 +2898,7 @@ export const knownContextValues = new Set([
2896
2898
  'object-column',
2897
2899
  'object-fit',
2898
2900
  'object-position',
2901
+ 'object-properties-sort-alphabetically',
2899
2902
  'object-view-box',
2900
2903
  'oct',
2901
2904
  'off',
@@ -3079,6 +3082,8 @@ export const knownContextValues = new Set([
3079
3082
  'player',
3080
3083
  'playing',
3081
3084
  'plus-button',
3085
+ 'plus-button-drawer',
3086
+ 'plus-button-panel',
3082
3087
  'pointer',
3083
3088
  'pointer-32-bit',
3084
3089
  'pointer-64-bit',
@@ -3775,6 +3780,7 @@ export const knownContextValues = new Set([
3775
3780
  'socket',
3776
3781
  'some_id',
3777
3782
  'sort-by',
3783
+ 'sort-properties-alphabetically',
3778
3784
  'source-code',
3779
3785
  'source-code-widget',
3780
3786
  'source-file',
package/package.json CHANGED
@@ -92,5 +92,5 @@
92
92
  "webidl2": "24.5.0",
93
93
  "yargs": "17.7.2"
94
94
  },
95
- "version": "1.0.1643855"
95
+ "version": "1.0.1646286"
96
96
  }