chrome-devtools-frontend 1.0.1603822 → 1.0.1605219

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 (89) hide show
  1. package/AUTHORS +1 -0
  2. package/front_end/Tests.js +23 -7
  3. package/front_end/core/host/AidaClient.ts +153 -525
  4. package/front_end/core/host/AidaClientTypes.ts +470 -0
  5. package/front_end/core/host/AidaGcaTranslation.ts +231 -122
  6. package/front_end/core/host/GcaClient.ts +112 -0
  7. package/front_end/core/host/GcaTypes.ts +107 -155
  8. package/front_end/core/host/UserMetrics.ts +0 -1
  9. package/front_end/core/host/host.ts +2 -0
  10. package/front_end/core/protocol_client/DevToolsCDPConnection.ts +1 -1
  11. package/front_end/core/root/ExperimentNames.ts +0 -1
  12. package/front_end/core/root/Runtime.ts +5 -0
  13. package/front_end/core/sdk/AutofillModel.ts +3 -2
  14. package/front_end/core/sdk/CSSModel.ts +3 -4
  15. package/front_end/core/sdk/CSSProperty.ts +1 -1
  16. package/front_end/core/sdk/ConsoleModel.ts +15 -13
  17. package/front_end/core/sdk/CookieModel.ts +5 -4
  18. package/front_end/core/sdk/DOMDebuggerModel.ts +20 -14
  19. package/front_end/core/sdk/DOMModel.ts +24 -22
  20. package/front_end/core/sdk/DebuggerModel.ts +21 -36
  21. package/front_end/core/sdk/EmulationModel.ts +21 -23
  22. package/front_end/core/sdk/EventBreakpointsModel.ts +16 -6
  23. package/front_end/core/sdk/HeapProfilerModel.ts +4 -7
  24. package/front_end/core/sdk/IsolateManager.ts +12 -7
  25. package/front_end/core/sdk/NetworkManager.ts +35 -28
  26. package/front_end/core/sdk/OverlayModel.ts +10 -10
  27. package/front_end/core/sdk/PreloadingModel.ts +3 -4
  28. package/front_end/core/sdk/ServiceWorkerManager.ts +2 -3
  29. package/front_end/core/sdk/SourceMapScopesInfo.ts +93 -63
  30. package/front_end/entrypoints/formatter_worker/FormatterWorker.ts +1 -3
  31. package/front_end/entrypoints/heap_snapshot_worker/AllocationProfile.ts +22 -48
  32. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +1 -1
  33. package/front_end/entrypoints/main/MainImpl.ts +0 -4
  34. package/front_end/generated/InspectorBackendCommands.ts +4 -0
  35. package/front_end/generated/SupportedCSSProperties.js +68 -2
  36. package/front_end/generated/protocol-mapping.d.ts +7 -0
  37. package/front_end/generated/protocol-proxy-api.d.ts +14 -0
  38. package/front_end/generated/protocol.ts +22 -0
  39. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +31 -17
  40. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +1 -1
  41. package/front_end/models/bindings/TempFile.ts +1 -4
  42. package/front_end/models/emulation/DeviceModeModel.ts +21 -26
  43. package/front_end/models/extensions/ExtensionAPI.ts +1 -1
  44. package/front_end/models/heap_snapshot_model/HeapSnapshotModel.ts +34 -47
  45. package/front_end/models/javascript_metadata/NativeFunctions.js +6 -6
  46. package/front_end/models/trace/insights/LCPDiscovery.ts +14 -6
  47. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +85 -31
  48. package/front_end/panels/ai_assistance/components/ChatMessage.ts +50 -40
  49. package/front_end/panels/ai_assistance/components/ChatView.ts +3 -2
  50. package/front_end/panels/ai_assistance/components/WalkthroughView.ts +35 -7
  51. package/front_end/panels/ai_assistance/components/chatMessage.css +5 -1
  52. package/front_end/panels/application/ApplicationPanelSidebar.ts +6 -0
  53. package/front_end/panels/application/IndexedDBViews.ts +0 -9
  54. package/front_end/panels/application/WebMCPTreeElement.ts +35 -0
  55. package/front_end/panels/application/WebMCPView.ts +118 -0
  56. package/front_end/panels/application/application.ts +4 -0
  57. package/front_end/panels/application/webMCPView.css +65 -0
  58. package/front_end/panels/common/aiCodeCompletionSummaryToolbar.css +1 -1
  59. package/front_end/panels/console/consoleView.css +4 -0
  60. package/front_end/panels/elements/ElementsTreeElement.ts +91 -13
  61. package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +23 -2
  62. package/front_end/panels/elements/StylesSidebarPane.ts +85 -20
  63. package/front_end/panels/elements/elementsPanel.css +14 -0
  64. package/front_end/panels/elements/elementsTreeOutline.css +18 -0
  65. package/front_end/panels/network/NetworkLogViewColumns.ts +3 -3
  66. package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +15 -19
  67. package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +4 -2
  68. package/front_end/panels/profiler/HeapSnapshotProxy.ts +12 -16
  69. package/front_end/panels/profiler/HeapSnapshotView.ts +3 -10
  70. package/front_end/panels/profiler/ProfilesPanel.ts +5 -7
  71. package/front_end/panels/recorder/components/recordingView.css +0 -6
  72. package/front_end/panels/sensors/SensorsView.ts +28 -61
  73. package/front_end/panels/timeline/EventsTimelineTreeView.ts +2 -2
  74. package/front_end/panels/timeline/ThirdPartyTreeView.ts +35 -36
  75. package/front_end/panels/timeline/TimelineDetailsView.ts +47 -41
  76. package/front_end/panels/timeline/TimelinePanel.ts +1 -3
  77. package/front_end/panels/timeline/TimelineTreeView.ts +13 -13
  78. package/front_end/panels/timeline/components/LiveMetricsView.ts +852 -824
  79. package/front_end/panels/timeline/components/liveMetricsView.css +4 -0
  80. package/front_end/panels/timeline/thirdPartyTreeView.css +2 -2
  81. package/front_end/third_party/chromium/README.chromium +1 -1
  82. package/front_end/ui/components/buttons/button.css +2 -2
  83. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +0 -11
  84. package/front_end/ui/legacy/InspectorDrawerView.ts +206 -0
  85. package/front_end/ui/legacy/InspectorView.ts +41 -91
  86. package/front_end/ui/legacy/ViewManager.ts +14 -5
  87. package/front_end/ui/legacy/inspectorDrawerTabbedPane.css +5 -0
  88. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -1
  89. package/package.json +1 -1
@@ -129,13 +129,15 @@ const CONNECTION_TYPES = new Map([
129
129
  * to in multiple places, and this ensures we don't have accidental typos which
130
130
  * mean extra settings get mistakenly created.
131
131
  */
132
- export function customUserNetworkConditionsSetting(): Common.Settings.Setting<Conditions[]> {
133
- return Common.Settings.Settings.instance().moduleSetting<Conditions[]>('custom-network-conditions');
132
+ export function customUserNetworkConditionsSetting(
133
+ settings: Common.Settings.Settings = Common.Settings.Settings.instance()): Common.Settings.Setting<Conditions[]> {
134
+ return settings.moduleSetting<Conditions[]>('custom-network-conditions');
134
135
  }
135
136
 
136
- export function activeNetworkThrottlingKeySetting(): Common.Settings.Setting<ThrottlingConditionKey> {
137
- return Common.Settings.Settings.instance().createSetting(
138
- 'active-network-condition-key', PredefinedThrottlingConditionKey.NO_THROTTLING);
137
+ export function activeNetworkThrottlingKeySetting(
138
+ settings: Common.Settings.Settings =
139
+ Common.Settings.Settings.instance()): Common.Settings.Setting<ThrottlingConditionKey> {
140
+ return settings.createSetting('active-network-condition-key', PredefinedThrottlingConditionKey.NO_THROTTLING);
139
141
  }
140
142
 
141
143
  export class NetworkManager extends SDKModel<EventTypes> {
@@ -144,8 +146,7 @@ export class NetworkManager extends SDKModel<EventTypes> {
144
146
  readonly #networkAgent: ProtocolProxyApi.NetworkApi;
145
147
  readonly #bypassServiceWorkerSetting: Common.Settings.Setting<boolean>;
146
148
 
147
- readonly activeNetworkThrottlingKey: Common.Settings.Setting<ThrottlingConditionKey> =
148
- activeNetworkThrottlingKeySetting();
149
+ readonly activeNetworkThrottlingKey: Common.Settings.Setting<ThrottlingConditionKey>;
149
150
 
150
151
  constructor(target: Target) {
151
152
  super(target);
@@ -154,7 +155,11 @@ export class NetworkManager extends SDKModel<EventTypes> {
154
155
  this.#networkAgent = target.networkAgent();
155
156
  target.registerNetworkDispatcher(this.dispatcher);
156
157
  target.registerFetchDispatcher(this.fetchDispatcher);
157
- if (Common.Settings.Settings.instance().moduleSetting('cache-disabled').get()) {
158
+
159
+ const settings = this.target().targetManager().settings;
160
+ this.activeNetworkThrottlingKey = activeNetworkThrottlingKeySetting(settings);
161
+
162
+ if (settings.moduleSetting('cache-disabled').get()) {
158
163
  void this.#networkAgent.invoke_setCacheDisabled({cacheDisabled: true});
159
164
  }
160
165
 
@@ -166,16 +171,13 @@ export class NetworkManager extends SDKModel<EventTypes> {
166
171
  });
167
172
  void this.#networkAgent.invoke_setAttachDebugStack({enabled: true});
168
173
 
169
- this.#bypassServiceWorkerSetting =
170
- Common.Settings.Settings.instance().createSetting('bypass-service-worker', false);
174
+ this.#bypassServiceWorkerSetting = settings.createSetting('bypass-service-worker', false);
171
175
  if (this.#bypassServiceWorkerSetting.get()) {
172
176
  this.bypassServiceWorkerChanged();
173
177
  }
174
178
  this.#bypassServiceWorkerSetting.addChangeListener(this.bypassServiceWorkerChanged, this);
175
179
 
176
- Common.Settings.Settings.instance()
177
- .moduleSetting('cache-disabled')
178
- .addChangeListener(this.cacheDisabledSettingChanged, this);
180
+ settings.moduleSetting('cache-disabled').addChangeListener(this.cacheDisabledSettingChanged, this);
179
181
  }
180
182
 
181
183
  static forRequest(request: NetworkRequest): NetworkManager|null {
@@ -372,9 +374,8 @@ export class NetworkManager extends SDKModel<EventTypes> {
372
374
  }
373
375
 
374
376
  override dispose(): void {
375
- Common.Settings.Settings.instance()
376
- .moduleSetting('cache-disabled')
377
- .removeChangeListener(this.cacheDisabledSettingChanged, this);
377
+ const settings = this.target().targetManager().settings;
378
+ settings.moduleSetting('cache-disabled').removeChangeListener(this.cacheDisabledSettingChanged, this);
378
379
  }
379
380
 
380
381
  private bypassServiceWorkerChanged(): void {
@@ -1212,7 +1213,8 @@ export class NetworkDispatcher implements ProtocolProxyApi.NetworkDispatcher {
1212
1213
  this.#manager.dispatchEventToListeners(Events.RequestFinished, networkRequest);
1213
1214
  MultitargetNetworkManager.instance().inflightMainResourceRequests.delete(networkRequest.requestId());
1214
1215
 
1215
- if (Common.Settings.Settings.instance().moduleSetting('monitoring-xhr-enabled').get() &&
1216
+ const settings = this.#manager.target().targetManager().settings;
1217
+ if (settings.moduleSetting('monitoring-xhr-enabled').get() &&
1216
1218
  networkRequest.resourceType().category() === Common.ResourceType.resourceCategories.XHR) {
1217
1219
  let message;
1218
1220
  const failedToLoad = networkRequest.failed || networkRequest.hasErrorStatusCode();
@@ -1677,7 +1679,9 @@ export class RequestCondition extends Common.ObjectWrapper.ObjectWrapper<Request
1677
1679
  #conditions: ThrottlingConditions;
1678
1680
  #ruleIds = new Set<string>();
1679
1681
 
1680
- static createFromSetting(setting: RequestConditionsSetting): RequestCondition {
1682
+ static createFromSetting(
1683
+ setting: RequestConditionsSetting,
1684
+ settings: Common.Settings.Settings = Common.Settings.Settings.instance()): RequestCondition {
1681
1685
  if ('urlPattern' in setting) {
1682
1686
  const pattern = RequestURLPattern.create(setting.urlPattern) ?? {
1683
1687
  wildcardURL: setting.urlPattern,
@@ -1685,7 +1689,7 @@ export class RequestCondition extends Common.ObjectWrapper.ObjectWrapper<Request
1685
1689
  };
1686
1690
 
1687
1691
  const conditions = getPredefinedOrBlockingCondition(setting.conditions) ??
1688
- customUserNetworkConditionsSetting().get().find(condition => condition.key === setting.conditions) ??
1692
+ customUserNetworkConditionsSetting(settings).get().find(condition => condition.key === setting.conditions) ??
1689
1693
  NoThrottlingConditions;
1690
1694
 
1691
1695
  return new this(pattern, setting.enabled, conditions);
@@ -1785,10 +1789,8 @@ export namespace RequestCondition {
1785
1789
  }
1786
1790
 
1787
1791
  export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper<RequestConditions.EventTypes> {
1788
- readonly #setting =
1789
- Common.Settings.Settings.instance().createSetting<RequestConditionsSetting[]>('network-blocked-patterns', []);
1790
- readonly #conditionsEnabledSetting =
1791
- Common.Settings.Settings.instance().moduleSetting<boolean>('request-blocking-enabled');
1792
+ readonly #setting: Common.Settings.Setting<RequestConditionsSetting[]>;
1793
+ readonly #conditionsEnabledSetting: Common.Settings.Setting<boolean>;
1792
1794
  readonly #conditions: RequestCondition[] = [];
1793
1795
  readonly #requestConditionsById = new Map<string, {
1794
1796
  conditions: Conditions,
@@ -1796,11 +1798,13 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper<Reques
1796
1798
  }>();
1797
1799
  #conditionsAppliedForTestPromise: Promise<unknown> = Promise.resolve();
1798
1800
 
1799
- constructor() {
1801
+ constructor(settings: Common.Settings.Settings) {
1800
1802
  super();
1803
+ this.#setting = settings.createSetting<RequestConditionsSetting[]>('network-blocked-patterns', []);
1804
+ this.#conditionsEnabledSetting = settings.moduleSetting<boolean>('request-blocking-enabled');
1801
1805
  for (const condition of this.#setting.get()) {
1802
1806
  try {
1803
- this.#conditions.push(RequestCondition.createFromSetting(condition));
1807
+ this.#conditions.push(RequestCondition.createFromSetting(condition, settings));
1804
1808
  } catch (e) {
1805
1809
  console.error('Error loading throttling settings: ', e);
1806
1810
  }
@@ -2003,7 +2007,7 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
2003
2007
  readonly inflightMainResourceRequests = new Map<string, NetworkRequest>();
2004
2008
  #networkConditions: Conditions = NoThrottlingConditions;
2005
2009
  #updatingInterceptionPatternsPromise: Promise<void>|null = null;
2006
- readonly #requestConditions = new RequestConditions();
2010
+ readonly #requestConditions: RequestConditions;
2007
2011
  readonly #urlsForRequestInterceptor:
2008
2012
  Platform.MapUtilities.Multimap<(arg0: InterceptedRequest) => Promise<void>, InterceptionPattern> =
2009
2013
  new Platform.MapUtilities.Multimap();
@@ -2014,6 +2018,8 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
2014
2018
  constructor(targetManager: TargetManager) {
2015
2019
  super();
2016
2020
  this.#targetManager = targetManager;
2021
+ const settings = targetManager.settings;
2022
+ this.#requestConditions = new RequestConditions(settings);
2017
2023
 
2018
2024
  // TODO(allada) Remove these and merge it with request interception.
2019
2025
  const blockedPatternChanged: () => void = () => {
@@ -2264,8 +2270,9 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
2264
2270
  }
2265
2271
 
2266
2272
  private async updateInterceptionPatterns(): Promise<void> {
2267
- if (!Common.Settings.Settings.instance().moduleSetting('cache-disabled').get()) {
2268
- Common.Settings.Settings.instance().moduleSetting('cache-disabled').set(true);
2273
+ const settings = this.#targetManager.settings;
2274
+ if (!settings.moduleSetting('cache-disabled').get()) {
2275
+ settings.moduleSetting('cache-disabled').set(true);
2269
2276
  }
2270
2277
  this.#updatingInterceptionPatternsPromise = null;
2271
2278
  const promises = ([] as Array<Promise<unknown>>);
@@ -179,28 +179,28 @@ export class OverlayModel extends SDKModel<EventTypes> implements ProtocolProxyA
179
179
  }
180
180
  }
181
181
 
182
- static hideDOMNodeHighlight(): void {
183
- for (const overlayModel of TargetManager.instance().models(OverlayModel)) {
182
+ static hideDOMNodeHighlight(targetManager: TargetManager = TargetManager.instance()): void {
183
+ for (const overlayModel of targetManager.models(OverlayModel)) {
184
184
  overlayModel.delayedHideHighlight(0);
185
185
  }
186
186
  }
187
187
 
188
- static async muteHighlight(): Promise<void[]> {
189
- return await Promise.all(TargetManager.instance().models(OverlayModel).map(model => model.suspendModel()));
188
+ static async muteHighlight(targetManager: TargetManager = TargetManager.instance()): Promise<void[]> {
189
+ return await Promise.all(targetManager.models(OverlayModel).map(model => model.suspendModel()));
190
190
  }
191
191
 
192
- static async unmuteHighlight(): Promise<void[]> {
193
- return await Promise.all(TargetManager.instance().models(OverlayModel).map(model => model.resumeModel()));
192
+ static async unmuteHighlight(targetManager: TargetManager = TargetManager.instance()): Promise<void[]> {
193
+ return await Promise.all(targetManager.models(OverlayModel).map(model => model.resumeModel()));
194
194
  }
195
195
 
196
- static highlightRect(rect: HighlightRect): void {
197
- for (const overlayModel of TargetManager.instance().models(OverlayModel)) {
196
+ static highlightRect(rect: HighlightRect, targetManager: TargetManager = TargetManager.instance()): void {
197
+ for (const overlayModel of targetManager.models(OverlayModel)) {
198
198
  void overlayModel.highlightRect(rect);
199
199
  }
200
200
  }
201
201
 
202
- static clearHighlight(): void {
203
- for (const overlayModel of TargetManager.instance().models(OverlayModel)) {
202
+ static clearHighlight(targetManager: TargetManager = TargetManager.instance()): void {
203
+ for (const overlayModel of targetManager.models(OverlayModel)) {
204
204
  void overlayModel.clearHighlight();
205
205
  }
206
206
  }
@@ -16,7 +16,6 @@ import {
16
16
  } from './ResourceTreeModel.js';
17
17
  import {SDKModel} from './SDKModel.js';
18
18
  import {Capability, type Target} from './Target.js';
19
- import {TargetManager} from './TargetManager.js';
20
19
 
21
20
  export interface WithId<I, V> {
22
21
  id: I;
@@ -48,17 +47,17 @@ export class PreloadingModel extends SDKModel<EventTypes> {
48
47
 
49
48
  const targetInfo = target.targetInfo();
50
49
  if (targetInfo?.subtype === 'prerender') {
51
- this.lastPrimaryPageModel = TargetManager.instance().primaryPageTarget()?.model(PreloadingModel) || null;
50
+ this.lastPrimaryPageModel = target.targetManager().primaryPageTarget()?.model(PreloadingModel) || null;
52
51
  }
53
52
 
54
- TargetManager.instance().addModelListener(
53
+ target.targetManager().addModelListener(
55
54
  ResourceTreeModel, ResourceTreeModelEvents.PrimaryPageChanged, this.onPrimaryPageChanged, this);
56
55
  }
57
56
 
58
57
  override dispose(): void {
59
58
  super.dispose();
60
59
 
61
- TargetManager.instance().removeModelListener(
60
+ this.target().targetManager().removeModelListener(
62
61
  ResourceTreeModel, ResourceTreeModelEvents.PrimaryPageChanged, this.onPrimaryPageChanged, this);
63
62
 
64
63
  void this.agent.invoke_disable();
@@ -11,7 +11,6 @@ import type * as Platform from '../platform/platform.js';
11
11
  import {Events as RuntimeModelEvents, type ExecutionContext, RuntimeModel} from './RuntimeModel.js';
12
12
  import {SDKModel} from './SDKModel.js';
13
13
  import {Capability, type Target, Type} from './Target.js';
14
- import {TargetManager} from './TargetManager.js';
15
14
 
16
15
  const UIStrings = {
17
16
  /**
@@ -544,7 +543,7 @@ class ServiceWorkerContextNamer {
544
543
  this.#serviceWorkerManager = serviceWorkerManager;
545
544
  serviceWorkerManager.addEventListener(Events.REGISTRATION_UPDATED, this.registrationsUpdated, this);
546
545
  serviceWorkerManager.addEventListener(Events.REGISTRATION_DELETED, this.registrationsUpdated, this);
547
- TargetManager.instance().addModelListener(
546
+ this.#target.targetManager().addModelListener(
548
547
  RuntimeModel, RuntimeModelEvents.ExecutionContextCreated, this.executionContextCreated, this);
549
548
  }
550
549
 
@@ -578,7 +577,7 @@ class ServiceWorkerContextNamer {
578
577
  }
579
578
 
580
579
  private updateAllContextLabels(): void {
581
- for (const target of TargetManager.instance().targets()) {
580
+ for (const target of this.#target.targetManager().targets()) {
582
581
  const serviceWorkerTargetId = this.serviceWorkerTargetId(target);
583
582
  if (!serviceWorkerTargetId) {
584
583
  continue;
@@ -49,70 +49,21 @@ export class SourceMapScopesInfo {
49
49
 
50
50
  // Convert the entire scopeTree. Returns a root range that encompasses everything,
51
51
  // and inserts scopes by sourceIndex into the above scopeBySourceUrl.
52
- const {range} = convertScope(scopeTree, undefined);
53
- return new SourceMapScopesInfo(sourceMap, {scopes: scopeBySourceUrl, ranges: [range]});
52
+ const stack: Array<{
53
+ node: Formatter.FormatterWorkerPool.ScopeTreeNode,
54
+ parentRange?: ScopesCodec.GeneratedRange,
55
+ parentScopeHint?: ScopesCodec.OriginalScope,
56
+ }> = [{node: scopeTree}];
54
57
 
55
- /**
56
- * Recursively finds the correct place in the tree to insert the new scope.
57
- * Maintains the invariant that children are sorted and contained by their parent.
58
- */
59
- function insertInScope(parent: ScopesCodec.OriginalScope, newScope: ScopesCodec.OriginalScope): void {
60
- // Check if the newScope fits strictly inside any of the existing children.
61
- for (const child of parent.children) {
62
- if (contains(child, newScope)) {
63
- insertInScope(child, newScope);
64
- return;
65
- }
66
- }
58
+ let rootRange: ScopesCodec.GeneratedRange|undefined = undefined;
67
59
 
68
- // When here, newScope belongs directly in parent.
69
- // However, newScope might encompass some of parent's existing children (due
70
- // to compiler transform quirks or arbitrary insertion order). We must move
71
- // those children inside newScope.
72
- const childrenToKeep: ScopesCodec.OriginalScope[] = [];
73
- for (const child of parent.children) {
74
- if (contains(newScope, child)) {
75
- // child is actually inside newScope, so re-parent it.
76
- newScope.children.push(child);
77
- child.parent = newScope;
78
- } else {
79
- childrenToKeep.push(child);
80
- }
81
- }
82
-
83
- // Find the correct index in the remaining children to insert newScope.
84
- // We look for the first child that starts after the new scope.
85
- const insertIndex = childrenToKeep.findIndex(child => compareScopes(newScope, child) < 0);
86
- if (insertIndex === -1) {
87
- // If no child starts after, it goes at the end.
88
- childrenToKeep.push(newScope);
89
- } else {
90
- childrenToKeep.splice(insertIndex, 0, newScope);
91
- }
92
-
93
- // Update parent's children to only be the ones that don't belong to newScope.
94
- parent.children = childrenToKeep;
95
- newScope.parent = parent;
96
- }
97
-
98
- function contains(outer: ScopesCodec.OriginalScope, inner: ScopesCodec.OriginalScope): boolean {
99
- return comparePositions(outer.start, inner.start) <= 0 && comparePositions(outer.end, inner.end) >= 0;
100
- }
101
-
102
- function compareScopes(a: ScopesCodec.OriginalScope, b: ScopesCodec.OriginalScope): number {
103
- return comparePositions(a.start, b.start);
104
- }
105
-
106
- function comparePositions(a: ScopesCodec.Position, b: ScopesCodec.Position): number {
107
- if (a.line !== b.line) {
108
- return a.line - b.line;
60
+ while (stack.length > 0) {
61
+ const popped = stack.pop();
62
+ if (!popped) {
63
+ break;
109
64
  }
110
- return a.column - b.column;
111
- }
65
+ const {node, parentRange, parentScopeHint} = popped;
112
66
 
113
- function convertScope(
114
- node: Formatter.FormatterWorkerPool.ScopeTreeNode,
115
- parentRange: ScopesCodec.GeneratedRange|undefined): {range: ScopesCodec.GeneratedRange} {
116
67
  const start = positionFromOffset(node.start);
117
68
  const end = positionFromOffset(node.end);
118
69
  const startEntry = sourceMap.findEntry(start.line, start.column);
@@ -156,15 +107,94 @@ export class SourceMapScopesInfo {
156
107
  children: [],
157
108
  };
158
109
 
110
+ if (!rootRange) {
111
+ rootRange = range;
112
+ }
159
113
  parentRange?.children.push(range);
114
+
115
+ let nextParentScopeHint = parentScopeHint;
160
116
  if (canMapOriginalPosition && scope) {
161
117
  const rootScope = scopeBySourceUrl[sourceIndex];
162
- insertInScope(rootScope, scope);
118
+ const startSearchFrom =
119
+ (parentScopeHint && containsOriginal(parentScopeHint, scope)) ? parentScopeHint : rootScope;
120
+ insertInScope(startSearchFrom, scope);
121
+ nextParentScopeHint = scope;
163
122
  }
164
123
 
165
- node.children.forEach(child => convertScope(child, range));
124
+ for (let i = node.children.length - 1; i >= 0; --i) {
125
+ stack.push({node: node.children[i], parentRange: range, parentScopeHint: nextParentScopeHint});
126
+ }
127
+ }
166
128
 
167
- return {range};
129
+ return new SourceMapScopesInfo(sourceMap, {scopes: scopeBySourceUrl, ranges: rootRange ? [rootRange] : []});
130
+
131
+ /**
132
+ * Finds the correct place in the tree to insert the new scope.
133
+ * Maintains the invariant that children are sorted and contained by their parent.
134
+ */
135
+ function insertInScope(rootScope: ScopesCodec.OriginalScope, newScope: ScopesCodec.OriginalScope): void {
136
+ let parent = rootScope;
137
+ // Check if the newScope fits strictly inside any of the existing children.
138
+ // We iterate to find the deepest parent to avoid Maximum Call Stack Size Exceeded
139
+ // errors on highly nested scripts.
140
+ while (true) {
141
+ let deeperParent: ScopesCodec.OriginalScope|null = null;
142
+ for (const child of parent.children) {
143
+ if (containsOriginal(child, newScope)) {
144
+ deeperParent = child;
145
+ break;
146
+ }
147
+ }
148
+ if (deeperParent) {
149
+ parent = deeperParent;
150
+ } else {
151
+ break;
152
+ }
153
+ }
154
+
155
+ // When here, newScope belongs directly in parent.
156
+ // However, newScope might encompass some of parent's existing children (due
157
+ // to compiler transform quirks or arbitrary insertion order). We must move
158
+ // those children inside newScope.
159
+ const childrenToKeep: ScopesCodec.OriginalScope[] = [];
160
+ for (const child of parent.children) {
161
+ if (containsOriginal(newScope, child)) {
162
+ // child is actually inside newScope, so re-parent it.
163
+ newScope.children.push(child);
164
+ child.parent = newScope;
165
+ } else {
166
+ childrenToKeep.push(child);
167
+ }
168
+ }
169
+
170
+ // Find the correct index in the remaining children to insert newScope.
171
+ // We look for the first child that starts after the new scope.
172
+ const insertIndex = childrenToKeep.findIndex(child => compareScopes(newScope, child) < 0);
173
+ if (insertIndex === -1) {
174
+ // If no child starts after, it goes at the end.
175
+ childrenToKeep.push(newScope);
176
+ } else {
177
+ childrenToKeep.splice(insertIndex, 0, newScope);
178
+ }
179
+
180
+ // Update parent's children to only be the ones that don't belong to newScope.
181
+ parent.children = childrenToKeep;
182
+ newScope.parent = parent;
183
+ }
184
+
185
+ function containsOriginal(outer: ScopesCodec.OriginalScope, inner: ScopesCodec.OriginalScope): boolean {
186
+ return comparePositions(outer.start, inner.start) <= 0 && comparePositions(outer.end, inner.end) >= 0;
187
+ }
188
+
189
+ function compareScopes(a: ScopesCodec.OriginalScope, b: ScopesCodec.OriginalScope): number {
190
+ return comparePositions(a.start, b.start);
191
+ }
192
+
193
+ function comparePositions(a: ScopesCodec.Position, b: ScopesCodec.Position): number {
194
+ if (a.line !== b.line) {
195
+ return a.line - b.line;
196
+ }
197
+ return a.column - b.column;
168
198
  }
169
199
 
170
200
  function positionFromOffset(offset: number): ScopesCodec.Position {
@@ -19,9 +19,7 @@ import {JSONFormatter} from './JSONFormatter.js';
19
19
  import {substituteExpression} from './Substitute.js';
20
20
 
21
21
  export interface Chunk {
22
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
23
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
- chunk: any[];
22
+ chunk: unknown[];
25
23
  isLastChunk: boolean;
26
24
  }
27
25
 
@@ -8,27 +8,16 @@ import type {LiveObjects, Profile} from './HeapSnapshot.js';
8
8
 
9
9
  export class AllocationProfile {
10
10
  readonly #strings: string[];
11
- #nextNodeId: number;
12
- #functionInfos: FunctionAllocationInfo[];
13
- #idToNode: Record<number, BottomUpAllocationNode|null>;
14
- readonly #idToTopDownNode: Record<number, TopDownAllocationNode>;
15
- #collapsedTopNodeIdToFunctionInfo: Record<number, FunctionAllocationInfo>;
16
- #traceTops: HeapSnapshotModel.HeapSnapshotModel.SerializedAllocationNode[]|null;
11
+ #nextNodeId = 1;
12
+ #functionInfos: FunctionAllocationInfo[] = [];
13
+ #idToNode: Record<number, BottomUpAllocationNode|null> = {};
14
+ readonly #idToTopDownNode: Record<number, TopDownAllocationNode> = {};
15
+ #collapsedTopNodeIdToFunctionInfo: Record<number, FunctionAllocationInfo> = {};
16
+ #traceTops: HeapSnapshotModel.HeapSnapshotModel.SerializedAllocationNode[]|null = null;
17
17
 
18
18
  constructor(profile: Profile, liveObjectStats: LiveObjects) {
19
19
  this.#strings = profile.strings;
20
20
 
21
- this.#nextNodeId = 1;
22
- this.#functionInfos = [];
23
-
24
- this.#idToNode = {};
25
-
26
- this.#idToTopDownNode = {};
27
-
28
- this.#collapsedTopNodeIdToFunctionInfo = {};
29
-
30
- this.#traceTops = null;
31
-
32
21
  this.#buildFunctionAllocationInfos(profile);
33
22
  this.#buildAllocationTree(profile, liveObjectStats);
34
23
  }
@@ -71,7 +60,7 @@ export class AllocationProfile {
71
60
  function traverseNode(
72
61
  // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
73
62
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
74
- rawNodeArray: any, nodeOffset: any, parent: TopDownAllocationNode|null): TopDownAllocationNode {
63
+ rawNodeArray: any, nodeOffset: number, parent: TopDownAllocationNode|null): TopDownAllocationNode {
75
64
  const functionInfo = functionInfos[rawNodeArray[nodeOffset + functionInfoIndexOffset]];
76
65
  const id = rawNodeArray[nodeOffset + nodeIdOffset];
77
66
  const stats = liveObjectStats[id];
@@ -188,7 +177,7 @@ export class TopDownAllocationNode {
188
177
  liveCount: number;
189
178
  liveSize: number;
190
179
  parent: TopDownAllocationNode|null;
191
- children: TopDownAllocationNode[];
180
+ children: TopDownAllocationNode[] = [];
192
181
  constructor(
193
182
  id: number, functionInfo: FunctionAllocationInfo, count: number, size: number, liveCount: number,
194
183
  liveSize: number, parent: TopDownAllocationNode|null) {
@@ -199,29 +188,20 @@ export class TopDownAllocationNode {
199
188
  this.liveCount = liveCount;
200
189
  this.liveSize = liveSize;
201
190
  this.parent = parent;
202
-
203
- this.children = [];
204
191
  }
205
192
  }
206
193
 
207
194
  export class BottomUpAllocationNode {
208
195
  functionInfo: FunctionAllocationInfo;
209
- allocationCount: number;
210
- allocationSize: number;
211
- liveCount: number;
212
- liveSize: number;
213
- traceTopIds: number[];
214
- readonly #callers: BottomUpAllocationNode[];
196
+ allocationCount = 0;
197
+ allocationSize = 0;
198
+ liveCount = 0;
199
+ liveSize = 0;
200
+ traceTopIds: number[] = [];
201
+ readonly #callers: BottomUpAllocationNode[] = [];
202
+
215
203
  constructor(functionInfo: FunctionAllocationInfo) {
216
204
  this.functionInfo = functionInfo;
217
- this.allocationCount = 0;
218
- this.allocationSize = 0;
219
- this.liveCount = 0;
220
- this.liveSize = 0;
221
-
222
- this.traceTopIds = [];
223
-
224
- this.#callers = [];
225
205
  }
226
206
 
227
207
  addCaller(traceNode: TopDownAllocationNode): BottomUpAllocationNode {
@@ -256,11 +236,11 @@ export class FunctionAllocationInfo {
256
236
  scriptId: number;
257
237
  line: number;
258
238
  column: number;
259
- totalCount: number;
260
- totalSize: number;
261
- totalLiveCount: number;
262
- totalLiveSize: number;
263
- #traceTops: TopDownAllocationNode[];
239
+ totalCount = 0;
240
+ totalSize = 0;
241
+ totalLiveCount = 0;
242
+ totalLiveSize = 0;
243
+ #traceTops: TopDownAllocationNode[] = [];
264
244
  #bottomUpTree?: BottomUpAllocationNode;
265
245
  constructor(functionName: string, scriptName: string, scriptId: number, line: number, column: number) {
266
246
  this.functionName = functionName;
@@ -268,12 +248,6 @@ export class FunctionAllocationInfo {
268
248
  this.scriptId = scriptId;
269
249
  this.line = line;
270
250
  this.column = column;
271
- this.totalCount = 0;
272
- this.totalSize = 0;
273
- this.totalLiveCount = 0;
274
- this.totalLiveSize = 0;
275
-
276
- this.#traceTops = [];
277
251
  }
278
252
 
279
253
  addTraceTopNode(node: TopDownAllocationNode): void {
@@ -294,14 +268,14 @@ export class FunctionAllocationInfo {
294
268
  if (!this.#bottomUpTree) {
295
269
  this.#buildAllocationTraceTree();
296
270
  }
297
- return this.#bottomUpTree as BottomUpAllocationNode;
271
+ return this.#bottomUpTree ?? null;
298
272
  }
299
273
 
300
274
  #buildAllocationTraceTree(): void {
301
275
  this.#bottomUpTree = new BottomUpAllocationNode(this);
302
276
 
303
277
  for (let i = 0; i < this.#traceTops.length; i++) {
304
- let node: (TopDownAllocationNode|null)|TopDownAllocationNode = this.#traceTops[i];
278
+ let node: TopDownAllocationNode|null = this.#traceTops[i];
305
279
  let bottomUpNode: BottomUpAllocationNode = this.#bottomUpTree;
306
280
  const count = node.allocationCount;
307
281
  const size = node.allocationSize;
@@ -2675,7 +2675,7 @@ export abstract class HeapSnapshot {
2675
2675
  if (snapshotDiff) {
2676
2676
  return snapshotDiff;
2677
2677
  }
2678
- snapshotDiff = ({} as Record<string, HeapSnapshotModel.HeapSnapshotModel.Diff>);
2678
+ snapshotDiff = {};
2679
2679
 
2680
2680
  const aggregates = this.getAggregatesByClassKey(true, 'allObjects');
2681
2681
  for (const classKey in baseSnapshotAggregates) {
@@ -397,10 +397,6 @@ export class MainImpl {
397
397
  Root.ExperimentNames.ExperimentName.FONT_EDITOR, 'New font editor in the Styles tab',
398
398
  'https://developer.chrome.com/blog/new-in-devtools-89/#font');
399
399
 
400
- // New cookie features.
401
- Root.Runtime.experiments.register(
402
- Root.ExperimentNames.ExperimentName.EXPERIMENTAL_COOKIE_FEATURES, 'Experimental cookie features');
403
-
404
400
  Root.Runtime.experiments.registerHostExperiment({
405
401
  name: Root.ExperimentNames.ExperimentName.DURABLE_MESSAGES,
406
402
  title: 'Durable Messages',
@@ -344,6 +344,10 @@ inspectorBackend.registerCommand("Cast.startTabMirroring", [{"name": "sinkName",
344
344
  inspectorBackend.registerCommand("Cast.stopCasting", [{"name": "sinkName", "type": "string", "optional": false, "description": "", "typeRef": null}], [], "Stops the active Cast session on the sink.");
345
345
  inspectorBackend.registerType("Cast.Sink", [{"name": "name", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "id", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "session", "type": "string", "optional": true, "description": "Text describing the current session. Present only if there is an active session on the sink.", "typeRef": null}]);
346
346
 
347
+ // CrashReportContext.
348
+ inspectorBackend.registerCommand("CrashReportContext.getEntries", [], ["entries"], "Returns all entries in the CrashReportContext across all frames in the page.");
349
+ inspectorBackend.registerType("CrashReportContext.CrashReportContextEntry", [{"name": "key", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "value", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "frameId", "type": "string", "optional": false, "description": "The ID of the frame where the key-value pair was set.", "typeRef": "Page.FrameId"}]);
350
+
347
351
  // DOM.
348
352
  inspectorBackend.registerEnum("DOM.PseudoType", {FirstLine: "first-line", FirstLetter: "first-letter", Checkmark: "checkmark", Before: "before", After: "after", ExpandIcon: "expand-icon", PickerIcon: "picker-icon", InterestHint: "interest-hint", Marker: "marker", Backdrop: "backdrop", Column: "column", Selection: "selection", SearchText: "search-text", TargetText: "target-text", SpellingError: "spelling-error", GrammarError: "grammar-error", Highlight: "highlight", FirstLineInherited: "first-line-inherited", ScrollMarker: "scroll-marker", ScrollMarkerGroup: "scroll-marker-group", ScrollButton: "scroll-button", Scrollbar: "scrollbar", ScrollbarThumb: "scrollbar-thumb", ScrollbarButton: "scrollbar-button", ScrollbarTrack: "scrollbar-track", ScrollbarTrackPiece: "scrollbar-track-piece", ScrollbarCorner: "scrollbar-corner", Resizer: "resizer", InputListButton: "input-list-button", ViewTransition: "view-transition", ViewTransitionGroup: "view-transition-group", ViewTransitionImagePair: "view-transition-image-pair", ViewTransitionGroupChildren: "view-transition-group-children", ViewTransitionOld: "view-transition-old", ViewTransitionNew: "view-transition-new", Placeholder: "placeholder", FileSelectorButton: "file-selector-button", DetailsContent: "details-content", Picker: "picker", PermissionIcon: "permission-icon", OverscrollAreaParent: "overscroll-area-parent"});
349
353
  inspectorBackend.registerEnum("DOM.ShadowRootType", {UserAgent: "user-agent", Open: "open", Closed: "closed"});