chrome-devtools-frontend 1.0.1697998 → 1.0.1698733

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 (102) hide show
  1. package/.agents/skills/version-control/SKILL.md +21 -9
  2. package/front_end/core/platform/HostRuntime.ts +12 -0
  3. package/front_end/core/platform/api/HostRuntime.ts +13 -0
  4. package/front_end/core/platform/browser/HostRuntime.ts +34 -0
  5. package/front_end/core/platform/node/HostRuntime.ts +40 -0
  6. package/front_end/core/sdk/AnimationModel.ts +12 -98
  7. package/front_end/core/sdk/CSSModel.ts +4 -2
  8. package/front_end/core/sdk/CSSPropertyParser.ts +4 -4
  9. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +4 -44
  10. package/front_end/core/sdk/Connections.ts +6 -1
  11. package/front_end/core/sdk/ConsoleModel.ts +1 -12
  12. package/front_end/core/sdk/DOMModel.ts +3 -51
  13. package/front_end/core/sdk/DebuggerModel.ts +9 -8
  14. package/front_end/core/sdk/NetworkRequest.ts +1 -1
  15. package/front_end/core/sdk/PageFunctions.ts +187 -0
  16. package/front_end/core/sdk/Resource.ts +1 -1
  17. package/front_end/core/sdk/RuntimeModel.ts +1 -20
  18. package/front_end/core/sdk/Script.ts +21 -0
  19. package/front_end/core/sdk/SourceMap.ts +15 -2
  20. package/front_end/core/sdk/SourceMapCache.ts +13 -10
  21. package/front_end/core/sdk/SourceMapManager.ts +11 -9
  22. package/front_end/core/sdk/SourceMapScopeChainEntry.ts +59 -17
  23. package/front_end/core/sdk/SourceMapScopesInfo.ts +8 -2
  24. package/front_end/entrypoints/heap_snapshot_worker/ContextAnalyzer.ts +635 -0
  25. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +26 -12
  26. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +16 -2
  27. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.ts +4 -4
  28. package/front_end/entrypoints/heap_snapshot_worker/heap_snapshot_worker.ts +2 -0
  29. package/front_end/entrypoints/shell/shell.ts +1 -1
  30. package/front_end/models/ai_assistance/DOMHelpers.ts +95 -0
  31. package/front_end/models/ai_assistance/EvaluateAction.ts +5 -42
  32. package/front_end/models/ai_assistance/ExtensionScope.ts +2 -31
  33. package/front_end/models/ai_assistance/agents/AiAgent.ts +2 -1
  34. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +3 -4
  35. package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
  36. package/front_end/models/ai_assistance/contexts/DOMNodeContext.ts +10 -7
  37. package/front_end/models/ai_assistance/contexts/FileContext.ts +2 -10
  38. package/front_end/models/ai_assistance/tools/GetSourceContent.ts +3 -2
  39. package/front_end/models/ai_assistance/tools/ListSources.ts +21 -14
  40. package/front_end/models/bindings/CompilerScriptMapping.ts +3 -10
  41. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +48 -17
  42. package/front_end/models/bindings/ResourceScriptMapping.ts +2 -2
  43. package/front_end/models/bindings/StylesSourceMapping.ts +1 -1
  44. package/front_end/models/comment_manager/CD4ABridge.ts +55 -12
  45. package/front_end/models/comment_manager/CommentManager.ts +46 -91
  46. package/front_end/models/comment_manager/CommentThread.ts +145 -0
  47. package/front_end/models/comment_manager/comment_manager.ts +2 -0
  48. package/front_end/models/emulation/DeviceModeModel.ts +53 -0
  49. package/front_end/models/extensions/ExtensionAPI.ts +8 -6
  50. package/front_end/models/extensions/ExtensionEndpoint.ts +11 -8
  51. package/front_end/models/extensions/HostUrlPattern.ts +4 -3
  52. package/front_end/models/extensions/LanguageExtensionEndpoint.ts +3 -2
  53. package/front_end/models/extensions/RecorderExtensionEndpoint.ts +2 -1
  54. package/front_end/models/formatter/FormatterWorkerPool.ts +4 -6
  55. package/front_end/models/heap_snapshot/HeapSnapshotModel.ts +55 -0
  56. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +18 -14
  57. package/front_end/models/issues_manager/IssuesManager.ts +5 -0
  58. package/front_end/models/issues_manager/WebInstallIssue.ts +63 -0
  59. package/front_end/models/issues_manager/descriptions/webInstallManifestMissingId.md +3 -0
  60. package/front_end/models/issues_manager/descriptions/webInstallManifestMissingNameOrShortName.md +3 -0
  61. package/front_end/models/issues_manager/descriptions/webInstallManifestParsingOrNetworkError.md +3 -0
  62. package/front_end/models/issues_manager/descriptions/webInstallNoManifest.md +3 -0
  63. package/front_end/models/issues_manager/descriptions/webInstallStartUrlInvalid.md +3 -0
  64. package/front_end/models/issues_manager/issues_manager.ts +2 -0
  65. package/front_end/models/workspace/UISourceCode.ts +20 -0
  66. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +4 -6
  67. package/front_end/panels/ai_assistance/components/AIv2MarkdownRenderer.ts +4 -10
  68. package/front_end/{ui/comments → panels/common}/CommentThreadWidget.ts +4 -4
  69. package/front_end/{ui/comments → panels/common}/CommentsOverlayWidget.ts +39 -62
  70. package/front_end/{ui/comments → panels/common}/CommentsStatusBarPill.ts +5 -5
  71. package/front_end/panels/common/ExtensionServer.ts +2 -1
  72. package/front_end/{ui/comments → panels/common}/commentsOverlay.css +2 -1
  73. package/front_end/{ui/comments/comments-meta.ts → panels/common/common-meta.ts} +11 -11
  74. package/front_end/panels/common/common.ts +3 -0
  75. package/front_end/panels/elements/AdoptedStyleSheetTreeElement.ts +3 -3
  76. package/front_end/panels/elements/ElementsPanel.ts +5 -1
  77. package/front_end/panels/elements/ElementsTreeElement.ts +4 -1
  78. package/front_end/panels/elements/ElementsTreeOutline.ts +58 -51
  79. package/front_end/panels/elements/PropertiesWidget.ts +11 -10
  80. package/front_end/panels/elements/PropertyRenderer.ts +29 -25
  81. package/front_end/panels/elements/StylePropertyTreeElement.ts +6 -6
  82. package/front_end/panels/elements/elementsTreeOutline.css +7 -1
  83. package/front_end/panels/emulation/DeviceModeToolbar.ts +2 -3
  84. package/front_end/panels/event_listeners/EventListenersView.ts +33 -44
  85. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +6 -7
  86. package/front_end/panels/linear_memory_inspector/components/linearMemoryInspector.css +5 -1
  87. package/front_end/panels/linear_memory_inspector/linear_memory_inspector-meta.ts +1 -1
  88. package/front_end/panels/recorder/stepView.css +1 -0
  89. package/front_end/panels/security/SecurityPanel.ts +5 -5
  90. package/front_end/panels/security/SecurityPanelSidebar.ts +2 -11
  91. package/front_end/panels/sources/DebuggerPlugin.ts +1 -1
  92. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +11 -16
  93. package/front_end/panels/sources/sources-meta.ts +1 -1
  94. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +0 -3
  95. package/front_end/third_party/chromium/README.chromium +1 -1
  96. package/front_end/ui/comments/CommentOverlayManager.ts +28 -110
  97. package/front_end/ui/comments/comments.ts +0 -6
  98. package/front_end/ui/legacy/Treeoutline.ts +4 -0
  99. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +14 -7
  100. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  101. package/package.json +1 -1
  102. /package/front_end/{ui/comments → panels/common}/commentThreadWidget.css +0 -0
@@ -0,0 +1,145 @@
1
+ // Copyright 2026 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as Common from '../../core/common/common.js';
6
+
7
+ export interface EditorAnchorSignature {
8
+ /** 1-based line number for CodeMirror text editor anchors */
9
+ lineNumber: number;
10
+ /** File path associated with the editor */
11
+ filePath?: string;
12
+ }
13
+
14
+ export interface DOMNodeAnchorSignature {
15
+ /** Backend NodeId for DOM nodes (`data-backend-node-id`) */
16
+ backendNodeId: number;
17
+ /** Target ID associated with the DOM node (`data-target-id`) */
18
+ targetId: string;
19
+ }
20
+
21
+ export interface TimelineAnchorSignature {
22
+ /** Identifier of the trace to scope comments to a specific recording */
23
+ traceId: string;
24
+ /** Serializable key from Trace.EventsSerializer (e.g. 'r-123', 'p-1-2-3-4', 's-5') */
25
+ traceEventKey: string;
26
+ /** Primary event title or category name */
27
+ entryName: string;
28
+ /** Event start timestamp in microseconds */
29
+ startTimeMicro: number;
30
+ /** Chart location */
31
+ chartLocation: 'main'|'network';
32
+ /** Event duration in microseconds (omitted for instant markers) */
33
+ durationMicro?: number;
34
+ }
35
+
36
+ export interface CommentAnchorSignature {
37
+ /** Visual logging tree path, e.g. "Panel: elements > Pane: styles > TreeOutline > TreeItem: color" */
38
+ vePath: string;
39
+ /** Normalized text content of the target node */
40
+ textSignature: string;
41
+ /** Text content of the parent container VE node for sibling disambiguation */
42
+ parentTextSignature?: string;
43
+ /** 0-indexed position among siblings sharing the same visual logging path */
44
+ siblingIndex?: number;
45
+ /** Optional backend RequestId for Network panel elements (`data-network-request-id`) */
46
+ networkRequestId?: string;
47
+ /** Optional DOM node identifiers (`data-backend-node-id`, `data-target-id`) */
48
+ node?: DOMNodeAnchorSignature;
49
+ /** Optional editor anchor coordinates for CodeMirror text editors */
50
+ editor?: EditorAnchorSignature;
51
+ /** Optional timeline flamechart anchor coordinates for Performance panel trace entries */
52
+ timeline?: TimelineAnchorSignature;
53
+ }
54
+
55
+ export interface Comment {
56
+ author: 'DEVELOPER'|'AGENT';
57
+ text: string;
58
+ timestamp: number;
59
+ }
60
+
61
+ export interface ChangeRecord {
62
+ id: string;
63
+ description: string;
64
+ timestamp: number;
65
+ }
66
+
67
+ export type CommentThreadStatus = 'DRAFT'|'ACTIVE'|'RESOLVED';
68
+
69
+ export const enum Events {
70
+ CHANGED = 'Changed',
71
+ }
72
+
73
+ export interface EventTypes {
74
+ [Events.CHANGED]: void;
75
+ }
76
+
77
+ export interface CommentThreadOptions {
78
+ anchor: CommentAnchorSignature;
79
+ comments?: Comment[];
80
+ changes?: ChangeRecord[];
81
+ }
82
+
83
+ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
84
+ static #nextIndex = 1;
85
+
86
+ static resetIndex(): void {
87
+ CommentThread.#nextIndex = 1;
88
+ }
89
+
90
+ readonly id: string = crypto.randomUUID();
91
+ readonly anchor: CommentAnchorSignature;
92
+ #savedIndex?: number;
93
+ comments: Comment[];
94
+ status: CommentThreadStatus = 'DRAFT';
95
+ transmitted: boolean = false;
96
+ changes?: ChangeRecord[];
97
+
98
+ constructor(options: CommentThreadOptions) {
99
+ super();
100
+ this.anchor = options.anchor;
101
+ this.comments = options.comments ?? [];
102
+ this.changes = options.changes;
103
+ }
104
+
105
+ get index(): number {
106
+ return this.#savedIndex ?? CommentThread.#nextIndex;
107
+ }
108
+
109
+ save(text?: string, author: 'DEVELOPER'|'AGENT' = 'DEVELOPER'): void {
110
+ let changed = false;
111
+ if (text && text.trim().length > 0) {
112
+ this.comments.push({
113
+ author,
114
+ text: text.trim(),
115
+ timestamp: Date.now(),
116
+ });
117
+ changed = true;
118
+ }
119
+ if (this.status === 'DRAFT') {
120
+ if (this.#savedIndex === undefined) {
121
+ this.#savedIndex = CommentThread.#nextIndex++;
122
+ }
123
+ this.status = 'ACTIVE';
124
+ changed = true;
125
+ }
126
+ if (changed) {
127
+ this.dispatchEventToListeners(Events.CHANGED);
128
+ }
129
+ }
130
+
131
+ resolve(replyText?: string): void {
132
+ if (replyText && replyText.trim().length > 0) {
133
+ this.comments.push({
134
+ author: 'AGENT',
135
+ text: replyText.trim(),
136
+ timestamp: Date.now(),
137
+ });
138
+ }
139
+ if (this.#savedIndex === undefined) {
140
+ this.#savedIndex = CommentThread.#nextIndex++;
141
+ }
142
+ this.status = 'RESOLVED';
143
+ this.dispatchEventToListeners(Events.CHANGED);
144
+ }
145
+ }
@@ -4,8 +4,10 @@
4
4
 
5
5
  import * as CD4ABridge from './CD4ABridge.js';
6
6
  import * as CommentManager from './CommentManager.js';
7
+ import * as CommentThread from './CommentThread.js';
7
8
 
8
9
  export {
9
10
  CD4ABridge,
10
11
  CommentManager,
12
+ CommentThread,
11
13
  };
@@ -107,6 +107,8 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
107
107
  #appliedUserAgentType: UA;
108
108
  readonly #scaleSetting: Common.Settings.Setting<number>;
109
109
  #scale: number;
110
+ readonly #autoAdjustScaleSetting: Common.Settings.Setting<boolean>;
111
+ readonly #deviceScaleMapSetting: Common.Settings.Setting<Record<string, {scale: number, autoAdjust: boolean}>>;
110
112
  #widthSetting: Common.Settings.Setting<number>;
111
113
  #heightSetting: Common.Settings.Setting<number>;
112
114
  #uaSetting: Common.Settings.Setting<UA>;
@@ -153,6 +155,9 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
153
155
  this.#scaleSetting.addChangeListener(this.scaleSettingChanged, this);
154
156
  this.#scale = 1;
155
157
 
158
+ this.#autoAdjustScaleSetting = this.#settings.createSetting('emulation.auto-adjust-scale', true);
159
+ this.#deviceScaleMapSetting = this.#settings.createSetting('emulation.device-scale-map', {});
160
+
156
161
  this.#widthSetting = this.#settings.createSetting('emulation.device-width', 400);
157
162
  if (this.#widthSetting.get() < MinDeviceSize) {
158
163
  this.#widthSetting.set(MinDeviceSize);
@@ -327,12 +332,44 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
327
332
 
328
333
  emulate(type: Type, device: EmulatedDevice|null, mode: Mode|null, scale?: number): void {
329
334
  const resetPageScaleFactor = this.#type !== type || this.#device !== device || this.#mode !== mode;
335
+ const deviceChanged = this.#type !== type || this.#device !== device;
336
+
337
+ if (deviceChanged) {
338
+ if (this.#type === Type.Device && this.#device) {
339
+ const map = this.#deviceScaleMapSetting.get();
340
+ map[this.#device.title] = {
341
+ scale: this.#scaleSetting.get(),
342
+ autoAdjust: this.#autoAdjustScaleSetting.get(),
343
+ };
344
+ this.#deviceScaleMapSetting.set(map);
345
+ } else if (this.#type === Type.Responsive) {
346
+ const map = this.#deviceScaleMapSetting.get();
347
+ map['Responsive'] = {
348
+ scale: this.#scaleSetting.get(),
349
+ autoAdjust: this.#autoAdjustScaleSetting.get(),
350
+ };
351
+ this.#deviceScaleMapSetting.set(map);
352
+ }
353
+ }
354
+
330
355
  this.#type = type;
331
356
 
332
357
  if (type === Type.Device && device && mode) {
333
358
  console.assert(Boolean(device) && Boolean(mode), 'Must pass device and mode for device emulation');
334
359
  this.#mode = mode;
335
360
  this.#device = device;
361
+
362
+ if (deviceChanged) {
363
+ const map = this.#deviceScaleMapSetting.get();
364
+ const savedDevice = map[device.title];
365
+ if (savedDevice) {
366
+ this.#autoAdjustScaleSetting.set(savedDevice.autoAdjust);
367
+ scale = savedDevice.autoAdjust ? undefined : savedDevice.scale;
368
+ } else {
369
+ this.#autoAdjustScaleSetting.set(scale === undefined);
370
+ }
371
+ }
372
+
336
373
  if (scale !== undefined) {
337
374
  this.#autoFitScaleOnInitialize = false;
338
375
  this.#scaleSetting.set(scale);
@@ -346,6 +383,22 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
346
383
  this.#device = null;
347
384
  this.#mode = null;
348
385
  this.#autoFitScaleOnInitialize = false;
386
+
387
+ if (deviceChanged && type === Type.Responsive) {
388
+ const map = this.#deviceScaleMapSetting.get();
389
+ const savedDevice = map['Responsive'];
390
+ if (savedDevice) {
391
+ this.#autoAdjustScaleSetting.set(savedDevice.autoAdjust);
392
+ if (!savedDevice.autoAdjust) {
393
+ this.#scaleSetting.set(savedDevice.scale);
394
+ } else {
395
+ this.#scaleSetting.set(this.calculateFitScale(this.#widthSetting.get(), this.#heightSetting.get()));
396
+ }
397
+ } else {
398
+ this.#autoAdjustScaleSetting.set(true);
399
+ this.#scaleSetting.set(1);
400
+ }
401
+ }
349
402
  }
350
403
 
351
404
  if (type !== Type.None) {
@@ -404,6 +404,8 @@ declare global {
404
404
  chrome: PublicAPI.Chrome.DevTools.Chrome;
405
405
  webInspector?: APIImpl.InspectorExtensionAPI;
406
406
  }
407
+ var injectedExtensionAPI: Window['injectedExtensionAPI'];
408
+ var buildExtensionAPIInjectedScript: Window['buildExtensionAPIInjectedScript'];
407
409
  }
408
410
 
409
411
  export interface ExtensionDescriptor {
@@ -511,7 +513,7 @@ namespace APIImpl {
511
513
  }
512
514
  }
513
515
 
514
- self.injectedExtensionAPI = function(
516
+ globalThis.injectedExtensionAPI = function(
515
517
  extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
516
518
  testHook: (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
517
519
  injectedScriptId: number, targetWindowForTest?: Window): void {
@@ -1763,22 +1765,22 @@ self.injectedExtensionAPI = function(
1763
1765
  testHook(extensionServer, coreAPI);
1764
1766
  };
1765
1767
 
1766
- self.buildExtensionAPIInjectedScript = function(
1768
+ globalThis.buildExtensionAPIInjectedScript = function(
1767
1769
  extensionInfo: {
1768
1770
  startPage: string,
1769
1771
  name: string,
1770
1772
  exposeExperimentalAPIs: boolean,
1771
1773
  },
1772
1774
  inspectedTabId: string, themeName: string, keysToForward: number[],
1773
- testHook:
1774
- ((extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown)|
1775
- undefined): string {
1775
+ testHook: ((extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) =>
1776
+ unknown)|undefined): string {
1776
1777
  const argumentsJSON =
1777
1778
  [extensionInfo, inspectedTabId || null, themeName, keysToForward].map(_ => JSON.stringify(_)).join(',');
1778
1779
  if (!testHook) {
1779
1780
  testHook = (): void => {};
1780
1781
  }
1781
1782
  return '(function(injectedScriptId){ ' +
1782
- '(' + self.injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
1783
+ '(' + globalThis.injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook +
1784
+ ', injectedScriptId);' +
1783
1785
  '})';
1784
1786
  };
@@ -2,29 +2,31 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
+ import type * as Platform from '../../core/platform/platform.js';
6
+
5
7
  interface Response {
6
8
  requestId: number;
7
9
  result: unknown;
8
10
  error: Error|null;
9
11
  }
10
12
 
11
- interface Event {
13
+ interface EventMessage {
12
14
  event: string;
13
15
  }
14
16
 
15
- type Message = MessageEvent<Response|Event>;
16
-
17
17
  export class ExtensionEndpoint {
18
- private readonly port: MessagePort;
18
+ private readonly port: Platform.HostRuntime.WorkerMessagePort;
19
19
  private nextRequestId = 0;
20
20
  private pendingRequests: Map<number, {
21
21
  resolve: (arg: unknown) => void,
22
22
  reject: (error: Error) => void,
23
23
  }>;
24
24
 
25
- constructor(port: MessagePort) {
25
+ constructor(port: Platform.HostRuntime.WorkerMessagePort) {
26
26
  this.port = port;
27
- this.port.onmessage = this.onResponse.bind(this);
27
+ this.port.addEventListener('message', (event: unknown) => this.onResponse(event as MessageEvent));
28
+ (this.port as {start?: () => void}).start?.();
29
+ (this.port as {unref?: () => void}).unref?.();
28
30
  this.pendingRequests = new Map();
29
31
  }
30
32
 
@@ -44,7 +46,8 @@ export class ExtensionEndpoint {
44
46
  this.port.close();
45
47
  }
46
48
 
47
- private onResponse({data}: Message): void {
49
+ private onResponse(event: MessageEvent): void {
50
+ const data = event.data as Response | EventMessage;
48
51
  if ('event' in data) {
49
52
  this.handleEvent(data);
50
53
  return;
@@ -63,7 +66,7 @@ export class ExtensionEndpoint {
63
66
  }
64
67
  }
65
68
 
66
- protected handleEvent(_event: Event): void {
69
+ protected handleEvent(_event: EventMessage): void {
67
70
  throw new Error('handleEvent is not implemented');
68
71
  }
69
72
  }
@@ -77,8 +77,9 @@ function parseHostAndPort(pattern: string, scheme: string): {host: string, port:
77
77
  asUrl.hostname = asUrl.hostname.substr(0, asUrl.hostname.length - 1);
78
78
  }
79
79
 
80
- // The URL constructor is happy to accept '*', but it gets replaced with %2A
81
- if (asUrl.hostname !== '%2A' && asUrl.hostname.includes('%2A')) {
80
+ // The URL constructor in Chrome replaces '*' with '%2A', whereas Node preserves '*'.
81
+ const isWildcardHost = asUrl.hostname === '%2A' || asUrl.hostname === '*';
82
+ if (!isWildcardHost && (asUrl.hostname.includes('%2A') || asUrl.hostname.includes('*'))) {
82
83
  return undefined;
83
84
  }
84
85
 
@@ -93,7 +94,7 @@ function parseHostAndPort(pattern: string, scheme: string): {host: string, port:
93
94
  return undefined;
94
95
  }
95
96
 
96
- const host = asUrl.hostname !== '%2A' ? (pattern.startsWith('*.') ? `*.${asUrl.hostname}` : asUrl.hostname) : '*';
97
+ const host = !isWildcardHost ? (pattern.startsWith('*.') ? `*.${asUrl.hostname}` : asUrl.hostname) : '*';
97
98
  return {
98
99
  host,
99
100
  port,
@@ -13,7 +13,7 @@ import {ExtensionEndpoint} from './ExtensionEndpoint.js';
13
13
  class LanguageExtensionEndpointImpl extends ExtensionEndpoint {
14
14
  private plugin: LanguageExtensionEndpoint;
15
15
  #pluginManager: Bindings.DebuggerLanguagePlugins.DebuggerLanguagePluginManager;
16
- constructor(plugin: LanguageExtensionEndpoint, port: MessagePort,
16
+ constructor(plugin: LanguageExtensionEndpoint, port: Platform.HostRuntime.WorkerMessagePort,
17
17
  pluginManager: Bindings.DebuggerLanguagePlugins.DebuggerLanguagePluginManager) {
18
18
  super(port);
19
19
  this.plugin = plugin;
@@ -46,7 +46,8 @@ export class LanguageExtensionEndpoint implements Bindings.DebuggerLanguagePlugi
46
46
  // eslint-disable-next-line @typescript-eslint/naming-convention
47
47
  symbol_types: string[],
48
48
  },
49
- port: MessagePort, pluginManager: Bindings.DebuggerLanguagePlugins.DebuggerLanguagePluginManager) {
49
+ port: Platform.HostRuntime.WorkerMessagePort,
50
+ pluginManager: Bindings.DebuggerLanguagePlugins.DebuggerLanguagePluginManager) {
50
51
  this.name = name;
51
52
  this.extensionOrigin = extensionOrigin;
52
53
  this.supportedScriptTypes = supportedScriptTypes;
@@ -15,7 +15,8 @@ export class RecorderExtensionEndpoint extends ExtensionEndpoint {
15
15
  readonly #extensionOrigin: Platform.DevToolsPath.UrlString;
16
16
  readonly #recorderPluginManager: RecorderPluginManager;
17
17
 
18
- constructor(name: string, port: MessagePort, capabilities: PrivateAPI.RecordingExtensionPluginCapability[],
18
+ constructor(name: string, port: Platform.HostRuntime.WorkerMessagePort,
19
+ capabilities: PrivateAPI.RecordingExtensionPluginCapability[],
19
20
  extensionOrigin: Platform.DevToolsPath.UrlString, recorderPluginManager: RecorderPluginManager,
20
21
  mediaType?: string) {
21
22
  super(port);
@@ -2,7 +2,6 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- import type * as PlatformApi from '../../core/platform/api/api.js';
6
5
  import * as Platform from '../../core/platform/platform.js';
7
6
  import * as FormatterActions from '../../entrypoints/formatter_actions/formatter_actions.js';
8
7
 
@@ -12,7 +11,7 @@ let formatterWorkerPoolInstance: FormatterWorkerPool|undefined;
12
11
 
13
12
  export class FormatterWorkerPool {
14
13
  private taskQueue: Task[];
15
- private workerTasks: Map<PlatformApi.HostRuntime.Worker, Task|null>;
14
+ private workerTasks: Map<Platform.HostRuntime.Worker, Task|null>;
16
15
  private entrypointURL: string;
17
16
 
18
17
  constructor(entrypointURL?: string) {
@@ -46,7 +45,7 @@ export class FormatterWorkerPool {
46
45
  formatterWorkerPoolInstance = undefined;
47
46
  }
48
47
 
49
- private createWorker(): PlatformApi.HostRuntime.Worker {
48
+ private createWorker(): Platform.HostRuntime.Worker {
50
49
  const worker = Platform.HostRuntime.HOST_RUNTIME.createWorker(this.entrypointURL);
51
50
  worker.onmessage = this.onWorkerMessage.bind(this, worker);
52
51
  worker.onerror = this.onWorkerError.bind(this, worker);
@@ -75,8 +74,7 @@ export class FormatterWorkerPool {
75
74
  }
76
75
  }
77
76
 
78
- private onWorkerMessage(worker: PlatformApi.HostRuntime.Worker, event: PlatformApi.HostRuntime.WorkerMessageEvent):
79
- void {
77
+ private onWorkerMessage(worker: Platform.HostRuntime.Worker, event: Platform.HostRuntime.WorkerMessageEvent): void {
80
78
  const task = this.workerTasks.get(worker);
81
79
  if (!task) {
82
80
  return;
@@ -91,7 +89,7 @@ export class FormatterWorkerPool {
91
89
  task.callback(event.data ? event.data : null);
92
90
  }
93
91
 
94
- private onWorkerError(worker: PlatformApi.HostRuntime.Worker, event: Event): void {
92
+ private onWorkerError(worker: Platform.HostRuntime.Worker, event: Event): void {
95
93
  console.error(event);
96
94
  const task = this.workerTasks.get(worker);
97
95
  worker.terminate();
@@ -363,6 +363,61 @@ export interface ObjectInfo {
363
363
  retainerCount: number;
364
364
  }
365
365
 
366
+ export interface ContextAnalysisResult {
367
+ /** Scopes with dead fields, sorted by their highest-ranked context. */
368
+ scopes: ScopeAnalysis[];
369
+ /** Scripts with live contexts that could not be analyzed because they lack embedded scope metadata. */
370
+ scriptsWithoutScopes: ScriptWithoutScopes[];
371
+ }
372
+
373
+ export interface ScopeAnalysis {
374
+ scopeInfoNodeIndex: number;
375
+ scopeInfoNodeId: number;
376
+ scriptNodeIndex: number;
377
+ scriptNodeId: number;
378
+ scriptName: string;
379
+ /** Source name of the scope, when available. */
380
+ scopeName?: string;
381
+ scopeStart: number;
382
+ scopeEnd: number;
383
+ /** Number of context-typed fields in each context belonging to this scope. */
384
+ contextFieldCount: number;
385
+ /** Contexts with dead fields, sorted descending by deadFieldsRetainedSizeSum. */
386
+ contexts: ContextAnalysis[];
387
+ }
388
+
389
+ export interface ContextAnalysis {
390
+ contextNodeIndex: number;
391
+ contextNodeId: number;
392
+ retainedSize: number;
393
+ /**
394
+ * The sum of the retained sizes of values in fields classified as dead.
395
+ * This is a ranking heuristic, not the number of bytes that would be
396
+ * reclaimed by clearing the fields.
397
+ */
398
+ deadFieldsRetainedSizeSum: number;
399
+ /** Fields classified as dead in this context, sorted descending by retainedSize. */
400
+ deadFields: ContextField[];
401
+ }
402
+
403
+ export interface ContextField {
404
+ name: string;
405
+ valueNodeIndex: number;
406
+ valueNodeId: number;
407
+ valueName: string;
408
+ valueType: string;
409
+ selfSize: number;
410
+ retainedSize: number;
411
+ }
412
+
413
+ export interface ScriptWithoutScopes {
414
+ scriptNodeIndex: number;
415
+ scriptNodeId: number;
416
+ scriptName: string;
417
+ /** Number of live context instances belonging to this script. */
418
+ contextCount: number;
419
+ }
420
+
366
421
  export interface HeapQueryOptions {
367
422
  className?: string;
368
423
  propertyName?: string;
@@ -3,7 +3,6 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
- import type * as PlatformApi from '../../core/platform/api/api.js';
7
6
  import * as Platform from '../../core/platform/platform.js';
8
7
 
9
8
  import type {ChildrenProvider} from './ChildrenProvider.js';
@@ -17,7 +16,7 @@ export class HeapSnapshotWorkerProxy extends Common.ObjectWrapper.ObjectWrapper<
17
16
  callbacks: Map<number, (error?: string, result?: unknown) => void> =
18
17
  new Map<number, (error?: string, result?: unknown) => void>();
19
18
  readonly previousCallbacks: Set<number> = new Set<number>();
20
- readonly worker: PlatformApi.HostRuntime.Worker;
19
+ readonly worker: Platform.HostRuntime.Worker;
21
20
  interval?: ReturnType<typeof setInterval>;
22
21
  readonly workerUrl?: string;
23
22
 
@@ -69,17 +68,18 @@ export class HeapSnapshotWorkerProxy extends Common.ObjectWrapper.ObjectWrapper<
69
68
  this.postMessage({callId, disposition: 'evaluateForTest', source: script});
70
69
  }
71
70
 
72
- callFactoryMethod<T extends Object>(
73
- callback: null, objectId: string, methodName: string, proxyConstructor: new(...arg1: any[]) => T,
74
- transfer: PlatformApi.HostRuntime.WorkerTransferable[], ...methodArguments: any[]): T;
71
+ callFactoryMethod<T extends Object>(callback: null, objectId: string, methodName: string,
72
+ proxyConstructor: new(...arg1: any[]) => T,
73
+ transfer: Platform.HostRuntime.WorkerTransferable[],
74
+ ...methodArguments: any[]): T;
75
75
  callFactoryMethod<T extends Object>(callback: ((error?: string, result?: T) => void), objectId: string,
76
76
  methodName: string, proxyConstructor: new(...arg1: any[]) => T,
77
- transfer: PlatformApi.HostRuntime.WorkerTransferable[],
77
+ transfer: Platform.HostRuntime.WorkerTransferable[],
78
78
  ...methodArguments: any[]): null;
79
79
  callFactoryMethod<T extends Object>(callback: ((error?: string, result?: T) => void)|null, objectId: string,
80
80
  methodName: string, proxyConstructor: new(...arg1: any[]) => T,
81
- transfer: PlatformApi.HostRuntime.WorkerTransferable[],
82
- ...methodArguments: any[]): T|null {
81
+ transfer: Platform.HostRuntime.WorkerTransferable[], ...methodArguments: any[]): T
82
+ |null {
83
83
  const callId = this.nextCallId++;
84
84
  const newObjectId = this.nextObjectId++;
85
85
 
@@ -154,7 +154,7 @@ export class HeapSnapshotWorkerProxy extends Common.ObjectWrapper.ObjectWrapper<
154
154
  }
155
155
  }
156
156
 
157
- setupForSecondaryInit(port: PlatformApi.HostRuntime.WorkerMessagePort): Promise<void> {
157
+ setupForSecondaryInit(port: Platform.HostRuntime.WorkerMessagePort): Promise<void> {
158
158
  const callId = this.nextCallId++;
159
159
  const done = new Promise<void>((resolve, reject) => {
160
160
  this.callbacks.set(callId, error => {
@@ -175,7 +175,7 @@ export class HeapSnapshotWorkerProxy extends Common.ObjectWrapper.ObjectWrapper<
175
175
  return done;
176
176
  }
177
177
 
178
- messageReceived(event: PlatformApi.HostRuntime.WorkerMessageEvent): void {
178
+ messageReceived(event: Platform.HostRuntime.WorkerMessageEvent): void {
179
179
  const data = event.data;
180
180
  if (data.eventName) {
181
181
  if (this.eventHandler) {
@@ -199,7 +199,7 @@ export class HeapSnapshotWorkerProxy extends Common.ObjectWrapper.ObjectWrapper<
199
199
  callback(undefined, data.result);
200
200
  }
201
201
 
202
- postMessage(message: unknown, transfer?: PlatformApi.HostRuntime.WorkerTransferable[]): void {
202
+ postMessage(message: unknown, transfer?: Platform.HostRuntime.WorkerTransferable[]): void {
203
203
  this.worker.postMessage(message, transfer);
204
204
  }
205
205
  }
@@ -231,9 +231,9 @@ export class HeapSnapshotProxyObject {
231
231
  return this.worker.callFactoryMethod(null, String(this.objectId), methodName, proxyConstructor, [], ...args);
232
232
  }
233
233
 
234
- callFactoryMethodPromise<T extends Object>(
235
- methodName: string, proxyConstructor: new(...arg1: any[]) => T,
236
- transfer: PlatformApi.HostRuntime.WorkerTransferable[], ...args: any[]): Promise<T> {
234
+ callFactoryMethodPromise<T extends Object>(methodName: string, proxyConstructor: new(...arg1: any[]) => T,
235
+ transfer: Platform.HostRuntime.WorkerTransferable[],
236
+ ...args: any[]): Promise<T> {
237
237
  return new Promise((resolve, reject) => this.worker.callFactoryMethod((error, result) => {
238
238
  if (error) {
239
239
  reject(new Error(error));
@@ -348,6 +348,10 @@ export class HeapSnapshotProxy extends HeapSnapshotProxyObject {
348
348
  return this.callMethodPromise('getObjectInfo', nodeIndex);
349
349
  }
350
350
 
351
+ analyzeContexts(): Promise<HeapSnapshotModel.ContextAnalysisResult> {
352
+ return this.callMethodPromise('analyzeContexts');
353
+ }
354
+
351
355
  createEdgesProvider(nodeIndex: number, options?: HeapSnapshotModel.HeapEdgesQueryOptions): HeapSnapshotProviderProxy {
352
356
  return this.callFactoryMethod('createEdgesProvider', HeapSnapshotProviderProxy, nodeIndex, options);
353
357
  }
@@ -38,6 +38,7 @@ import {SourceFrameIssuesManager} from './SourceFrameIssuesManager.js';
38
38
  import {SRIMessageSignatureIssue} from './SRIMessageSignatureIssue.js';
39
39
  import {StylesheetLoadingIssue} from './StylesheetLoadingIssue.js';
40
40
  import {UnencodedDigestIssue} from './UnencodedDigestIssue.js';
41
+ import {WebInstallIssue} from './WebInstallIssue.js';
41
42
 
42
43
  export {Events} from './IssuesManagerEvents.js';
43
44
 
@@ -149,6 +150,10 @@ const issueCodeHandlers =
149
150
  Protocol.Audits.InspectorIssueCode.ConnectionAllowlistIssue,
150
151
  ConnectionAllowlistIssue.fromInspectorIssue,
151
152
  ],
153
+ [
154
+ Protocol.Audits.InspectorIssueCode.WebInstallIssue,
155
+ WebInstallIssue.fromInspectorIssue,
156
+ ],
152
157
  [
153
158
  Protocol.Audits.InspectorIssueCode.PermissionElementIssue,
154
159
  PermissionElementIssue.fromInspectorIssue,