chrome-devtools-frontend 1.0.1697595 → 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 (124) hide show
  1. package/.agents/skills/version-control/SKILL.md +21 -9
  2. package/.stylelintignore +2 -0
  3. package/front_end/core/common/VersionController.ts +5 -1
  4. package/front_end/core/platform/HostRuntime.ts +12 -0
  5. package/front_end/core/platform/api/HostRuntime.ts +13 -0
  6. package/front_end/core/platform/browser/HostRuntime.ts +34 -0
  7. package/front_end/core/platform/node/HostRuntime.ts +40 -0
  8. package/front_end/core/sdk/AnimationModel.ts +21 -99
  9. package/front_end/core/sdk/CSSModel.ts +4 -2
  10. package/front_end/core/sdk/CSSPropertyParser.ts +4 -4
  11. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +4 -44
  12. package/front_end/core/sdk/Connections.ts +6 -1
  13. package/front_end/core/sdk/ConsoleModel.ts +1 -12
  14. package/front_end/core/sdk/DOMModel.ts +3 -51
  15. package/front_end/core/sdk/DebuggerModel.ts +9 -8
  16. package/front_end/core/sdk/NetworkRequest.ts +1 -1
  17. package/front_end/core/sdk/PageFunctions.ts +187 -0
  18. package/front_end/core/sdk/Resource.ts +1 -1
  19. package/front_end/core/sdk/RuntimeModel.ts +1 -20
  20. package/front_end/core/sdk/Script.ts +21 -0
  21. package/front_end/core/sdk/SourceMap.ts +15 -2
  22. package/front_end/core/sdk/SourceMapCache.ts +13 -10
  23. package/front_end/core/sdk/SourceMapManager.ts +11 -9
  24. package/front_end/core/sdk/SourceMapScopeChainEntry.ts +59 -17
  25. package/front_end/core/sdk/SourceMapScopesInfo.ts +8 -2
  26. package/front_end/entrypoints/heap_snapshot_worker/ContextAnalyzer.ts +635 -0
  27. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +26 -12
  28. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +16 -2
  29. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.ts +4 -4
  30. package/front_end/entrypoints/heap_snapshot_worker/heap_snapshot_worker.ts +2 -0
  31. package/front_end/entrypoints/shell/shell.ts +1 -1
  32. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  33. package/front_end/generated/protocol.ts +8 -2
  34. package/front_end/models/ai_assistance/DOMHelpers.ts +95 -0
  35. package/front_end/models/ai_assistance/EvaluateAction.ts +5 -42
  36. package/front_end/models/ai_assistance/ExtensionScope.ts +2 -31
  37. package/front_end/models/ai_assistance/agents/AiAgent.ts +2 -1
  38. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +27 -2
  39. package/front_end/models/ai_assistance/ai_assistance.ts +6 -4
  40. package/front_end/models/ai_assistance/contexts/DOMNodeContext.ts +10 -7
  41. package/front_end/models/ai_assistance/contexts/FileContext.ts +2 -10
  42. package/front_end/models/ai_assistance/skills/performance.md +4 -3
  43. package/front_end/models/ai_assistance/tools/GetSourceContent.ts +3 -2
  44. package/front_end/models/ai_assistance/tools/{GetFunctionCode.ts → GetTraceFunctionCode.ts} +26 -13
  45. package/front_end/models/ai_assistance/tools/{GetResourceContent.ts → GetTraceResourceContent.ts} +31 -11
  46. package/front_end/models/ai_assistance/tools/ListSources.ts +21 -14
  47. package/front_end/models/ai_assistance/tools/Tool.ts +2 -2
  48. package/front_end/models/ai_assistance/tools/ToolRegistry.ts +6 -6
  49. package/front_end/models/bindings/CompilerScriptMapping.ts +3 -10
  50. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +48 -17
  51. package/front_end/models/bindings/ResourceScriptMapping.ts +2 -2
  52. package/front_end/models/bindings/StylesSourceMapping.ts +1 -1
  53. package/front_end/models/comment_manager/CD4ABridge.ts +55 -12
  54. package/front_end/models/comment_manager/CommentManager.ts +46 -91
  55. package/front_end/models/comment_manager/CommentThread.ts +145 -0
  56. package/front_end/models/comment_manager/comment_manager.ts +2 -0
  57. package/front_end/models/elements/DOMChanges.ts +238 -0
  58. package/front_end/models/elements/elements.ts +2 -0
  59. package/front_end/models/emulation/DeviceModeModel.ts +53 -0
  60. package/front_end/models/extensions/ExtensionAPI.ts +8 -6
  61. package/front_end/models/extensions/ExtensionEndpoint.ts +11 -8
  62. package/front_end/models/extensions/HostUrlPattern.ts +4 -3
  63. package/front_end/models/extensions/LanguageExtensionEndpoint.ts +3 -2
  64. package/front_end/models/extensions/RecorderExtensionEndpoint.ts +2 -1
  65. package/front_end/models/formatter/FormatterWorkerPool.ts +4 -6
  66. package/front_end/models/heap_snapshot/HeapSnapshotModel.ts +55 -0
  67. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +18 -14
  68. package/front_end/models/issues_manager/IssuesManager.ts +5 -0
  69. package/front_end/models/issues_manager/WebInstallIssue.ts +63 -0
  70. package/front_end/models/issues_manager/descriptions/webInstallManifestMissingId.md +3 -0
  71. package/front_end/models/issues_manager/descriptions/webInstallManifestMissingNameOrShortName.md +3 -0
  72. package/front_end/models/issues_manager/descriptions/webInstallManifestParsingOrNetworkError.md +3 -0
  73. package/front_end/models/issues_manager/descriptions/webInstallNoManifest.md +3 -0
  74. package/front_end/models/issues_manager/descriptions/webInstallStartUrlInvalid.md +3 -0
  75. package/front_end/models/issues_manager/issues_manager.ts +2 -0
  76. package/front_end/models/workspace/UISourceCode.ts +20 -0
  77. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +7 -7
  78. package/front_end/panels/ai_assistance/components/AIv2MarkdownRenderer.ts +4 -10
  79. package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +25 -5
  80. package/front_end/panels/browser_debugger/ObjectEventListenersSidebarPane.ts +2 -3
  81. package/front_end/panels/common/CommentThreadWidget.ts +221 -0
  82. package/front_end/{ui/comments → panels/common}/CommentsOverlayWidget.ts +117 -28
  83. package/front_end/{ui/comments → panels/common}/CommentsStatusBarPill.ts +5 -5
  84. package/front_end/panels/common/ExtensionServer.ts +2 -1
  85. package/front_end/panels/common/commentThreadWidget.css +173 -0
  86. package/front_end/{ui/comments → panels/common}/commentsOverlay.css +8 -1
  87. package/front_end/{ui/comments/comments-meta.ts → panels/common/common-meta.ts} +11 -11
  88. package/front_end/panels/common/common.ts +3 -0
  89. package/front_end/panels/elements/AdoptedStyleSheetTreeElement.ts +3 -3
  90. package/front_end/panels/elements/ElementsPanel.ts +5 -1
  91. package/front_end/panels/elements/ElementsTreeElement.ts +102 -21
  92. package/front_end/panels/elements/ElementsTreeOutline.ts +326 -91
  93. package/front_end/panels/elements/EventListenersWidget.ts +0 -1
  94. package/front_end/panels/elements/PropertiesWidget.ts +11 -10
  95. package/front_end/panels/elements/PropertyRenderer.ts +29 -25
  96. package/front_end/panels/elements/StylePropertyTreeElement.ts +6 -6
  97. package/front_end/panels/elements/elementsTreeOutline.css +7 -1
  98. package/front_end/panels/emulation/DeviceModeToolbar.ts +2 -3
  99. package/front_end/panels/event_listeners/EventListenersView.ts +235 -302
  100. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +6 -7
  101. package/front_end/panels/linear_memory_inspector/components/linearMemoryInspector.css +5 -1
  102. package/front_end/panels/linear_memory_inspector/linear_memory_inspector-meta.ts +1 -1
  103. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +10 -2
  104. package/front_end/panels/network/NetworkConfigView.ts +141 -116
  105. package/front_end/panels/network/NetworkPanel.ts +7 -4
  106. package/front_end/panels/network/RequestHeadersView.ts +1 -1
  107. package/front_end/panels/network/forward/BackendLinking.ts +5 -2
  108. package/front_end/panels/recorder/stepView.css +1 -0
  109. package/front_end/panels/security/SecurityPanel.ts +5 -5
  110. package/front_end/panels/security/SecurityPanelSidebar.ts +2 -11
  111. package/front_end/panels/settings/BackendLinkingSettingsTab.ts +7 -2
  112. package/front_end/panels/sources/DebuggerPlugin.ts +1 -1
  113. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +11 -16
  114. package/front_end/panels/sources/sources-meta.ts +1 -1
  115. package/front_end/panels/timeline/TimelineTreeView.ts +11 -1
  116. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +0 -3
  117. package/front_end/third_party/chromium/README.chromium +1 -1
  118. package/front_end/ui/comments/CommentOverlayManager.ts +89 -42
  119. package/front_end/ui/comments/comments.ts +0 -4
  120. package/front_end/ui/legacy/Treeoutline.ts +4 -0
  121. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +15 -8
  122. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +4 -0
  123. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  124. package/package.json +5 -5
@@ -2,7 +2,7 @@
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 * as SDK from '../../../core/sdk/sdk.js';
5
+ import type * as SDK from '../../../core/sdk/sdk.js';
6
6
  import type * as Bindings from '../../bindings/bindings.js';
7
7
  import type * as Workspace from '../../workspace/workspace.js';
8
8
  import {type ContextDetail, ConversationContext} from '../agents/AiAgent.js';
@@ -20,20 +20,12 @@ export class FileContext extends ConversationContext<Workspace.UISourceCode.UISo
20
20
  this.#debuggerWorkspaceBinding = debuggerWorkspaceBinding;
21
21
  }
22
22
 
23
- /**
24
- * Resolves the security origin of a given UISourceCode.
25
- * Prefers the project security origin, falling back to the origin of the file URL.
26
- */
27
- static originForUISourceCode(file: Workspace.UISourceCode.UISourceCode): SDK.SecurityOrigin.SecurityOrigin {
28
- return file.project()?.securityOrigin?.() ?? SDK.SecurityOrigin.SecurityOrigin.create(file.url());
29
- }
30
-
31
23
  /**
32
24
  * Returns the security origin of the project containing the file, falling
33
25
  * back to the origin derived from the file URL.
34
26
  */
35
27
  override getOrigin(): SDK.SecurityOrigin.SecurityOrigin {
36
- return FileContext.originForUISourceCode(this.#file);
28
+ return this.#file.securityOrigin();
37
29
  }
38
30
 
39
31
  override getItem(): Workspace.UISourceCode.UISourceCode {
@@ -8,8 +8,8 @@ allowed-tools:
8
8
  - getTraceMainThreadSummary
9
9
  - getTraceNetworkSummary
10
10
  - getDetailedCallTree
11
- - getFunctionCode
12
- - getResourceContent
11
+ - getTraceFunctionCode
12
+ - getTraceResourceContent
13
13
  - getInsightDetails
14
14
  ---
15
15
  You are an expert web performance assistant integrated into Chrome DevTools.
@@ -29,7 +29,8 @@ Your goal is to provide actionable advice about web page performance by analyzin
29
29
  3. **Call Tree, Event & Source Inspection**:
30
30
  - Use `getDetailedCallTree` to retrieve bottom-up execution trees for expensive main thread tasks.
31
31
  - Use `getTraceEventByKey` to inspect timing and payload data for individual events.
32
- - Use `getFunctionCode` or `getResourceContent` to inspect the source code and identify root causes.
32
+ - Use `getTraceFunctionCode` to inspect a specific function identified in the call tree, including line-by-line CPU profile execution costs.
33
+ - Use `getTraceResourceContent` to inspect the full text of a script or resource captured within the trace by URL.
33
34
 
34
35
  4. **UI Selection & Trace Recording**:
35
36
  - Use `selectTraceEventByKey` to reveal and select an event in the Performance Flamechart if requested.
@@ -65,12 +65,13 @@ export class GetSourceContentTool implements
65
65
  args: GetSourceContentArgs,
66
66
  context: BaseToolCapability&OriginLockCapability,
67
67
  ): Promise<DataHandlerResult<{content: string}>> {
68
- const originResult = resolveOriginFromLock(context.getOriginLock());
68
+ const originLock = context.getOriginLock();
69
+ const originResult = resolveOriginFromLock(originLock);
69
70
  if ('error' in originResult) {
70
71
  return originResult;
71
72
  }
72
73
 
73
- const file = ListSourcesTool.getSourceById(args.id, originResult.origin);
74
+ const file = ListSourcesTool.getSourceById(args.id, originLock);
74
75
 
75
76
  if (!file) {
76
77
  return {
@@ -21,54 +21,67 @@ const UIStringsNotTranslate = {
21
21
 
22
22
  const lockedString = i18n.i18n.lockedString;
23
23
 
24
- export interface GetFunctionCodeArgs extends ToolArgs {
24
+ /**
25
+ * Arguments for {@link GetTraceFunctionCodeTool}.
26
+ */
27
+ export interface GetTraceFunctionCodeArgs extends ToolArgs {
28
+ /** The URL of the script containing the function recorded in the performance trace. */
25
29
  scriptUrl: string;
30
+ /** The line number where the function is defined (0-based, as reported in the call tree). */
26
31
  line: number;
32
+ /** The column number where the function is defined (0-based, as reported in the call tree). */
27
33
  column: number;
28
34
  }
29
35
 
30
- export class GetFunctionCodeTool implements
31
- DataTool<GetFunctionCodeArgs, string, BaseToolCapability&PerformanceTraceCapability> {
32
- readonly name: ToolName = ToolName.GET_FUNCTION_CODE;
36
+ /**
37
+ * Retrieves function code and line-by-line CPU profile execution costs from the performance trace.
38
+ *
39
+ * Preconditions:
40
+ * - Requires an active, freshly recorded trace session (fails on imported traces).
41
+ * - Requires resource access via the performance trace context.
42
+ */
43
+ export class GetTraceFunctionCodeTool implements
44
+ DataTool<GetTraceFunctionCodeArgs, string, BaseToolCapability&PerformanceTraceCapability> {
45
+ readonly name: ToolName = ToolName.GET_TRACE_FUNCTION_CODE;
33
46
  readonly description: string =
34
- 'Retrieves the code for a function defined at the given location. The result is annotated with the runtime performance of each line of code.';
47
+ 'Retrieves the code for a function recorded in the performance trace at the specified location, annotated with line-by-line CPU runtime profiling execution costs. Do not call this tool unless a performance trace recording is actively loaded.';
35
48
 
36
- readonly parameters: Host.AidaClient.FunctionObjectParam<keyof GetFunctionCodeArgs> = {
49
+ readonly parameters: Host.AidaClient.FunctionObjectParam<keyof GetTraceFunctionCodeArgs> = {
37
50
  type: Host.AidaClient.ParametersTypes.OBJECT,
38
- description: 'Arguments for looking up function code.',
51
+ description: 'Arguments for looking up function code from the performance trace profile.',
39
52
  nullable: false,
40
53
  properties: {
41
54
  scriptUrl: {
42
55
  type: Host.AidaClient.ParametersTypes.STRING,
43
- description: 'The url of the function.',
56
+ description: 'The URL of the script containing the function recorded in the performance trace.',
44
57
  nullable: false,
45
58
  },
46
59
  line: {
47
60
  type: Host.AidaClient.ParametersTypes.INTEGER,
48
- description: 'The line number where the function is defined.',
61
+ description: 'The line number where the function is defined (0-based, as reported in the call tree).',
49
62
  nullable: false,
50
63
  },
51
64
  column: {
52
65
  type: Host.AidaClient.ParametersTypes.INTEGER,
53
- description: 'The column number where the function is defined.',
66
+ description: 'The column number where the function is defined (0-based, as reported in the call tree).',
54
67
  nullable: false,
55
68
  },
56
69
  },
57
70
  required: ['scriptUrl', 'line', 'column'],
58
71
  };
59
72
 
60
- displayInfoFromArgs(params: GetFunctionCodeArgs): {
73
+ displayInfoFromArgs(params: GetTraceFunctionCodeArgs): {
61
74
  title: string,
62
75
  action: string,
63
76
  } {
64
77
  return {
65
78
  title: lockedString(UIStringsNotTranslate.lookingUpFunctionCode),
66
- action: `getFunctionCode('${params.scriptUrl}', ${params.line}, ${params.column})`,
79
+ action: `getTraceFunctionCode('${params.scriptUrl}', ${params.line}, ${params.column})`,
67
80
  };
68
81
  }
69
82
 
70
83
  async handler(
71
- params: GetFunctionCodeArgs,
84
+ params: GetTraceFunctionCodeArgs,
72
85
  capabilities: BaseToolCapability&PerformanceTraceCapability,
73
86
  ): Promise<DataHandlerResult<string>> {
74
87
  const performanceTraceContext = capabilities.getPerformanceTraceContext();
@@ -25,42 +25,57 @@ const UIStringsNotTranslate = {
25
25
 
26
26
  const lockedString = i18n.i18n.lockedString;
27
27
 
28
- export interface GetResourceContentArgs extends ToolArgs {
28
+ /**
29
+ * Arguments for {@link GetTraceResourceContentTool}.
30
+ */
31
+ export interface GetTraceResourceContentArgs extends ToolArgs {
32
+ /** The URL of the resource captured in the performance trace to retrieve. */
29
33
  url: string;
30
34
  }
31
35
 
32
- export class GetResourceContentTool implements DataTool<
33
- GetResourceContentArgs, {content: string}, BaseToolCapability&TargetCapability&PerformanceTraceCapability> {
34
- readonly name: ToolName = ToolName.GET_RESOURCE_CONTENT;
36
+ /**
37
+ * Retrieves text content for a resource or script captured in the performance trace.
38
+ *
39
+ * Precedence:
40
+ * 1. Checks trace metadata (`parsedTrace.data.Scripts`) for scripts captured during recording.
41
+ * 2. Falls back to querying the live page target's `ResourceTreeModel`.
42
+ *
43
+ * Preconditions:
44
+ * - Requires an active, freshly recorded trace session (fails on imported traces).
45
+ * - Fails if resource is binary/non-text, cross-origin, or a `file://` URL.
46
+ */
47
+ export class GetTraceResourceContentTool implements DataTool<
48
+ GetTraceResourceContentArgs, {content: string}, BaseToolCapability&TargetCapability&PerformanceTraceCapability> {
49
+ readonly name: ToolName = ToolName.GET_TRACE_RESOURCE_CONTENT;
35
50
  readonly description: string =
36
- 'Retrieves the content of the resource with the given url. Only use this for text resource types.';
51
+ 'Retrieves the text content of a script or resource captured within the recorded performance trace by URL. Only use this for text resource types. Do not call this tool on imported traces or for general workspace files (use listSources and getSourceContent instead).';
37
52
 
38
- readonly parameters: Host.AidaClient.FunctionObjectParam<keyof GetResourceContentArgs> = {
53
+ readonly parameters: Host.AidaClient.FunctionObjectParam<keyof GetTraceResourceContentArgs> = {
39
54
  type: Host.AidaClient.ParametersTypes.OBJECT,
40
- description: 'Arguments for looking up resource content.',
55
+ description: 'Arguments for looking up resource content from the performance trace.',
41
56
  nullable: false,
42
57
  properties: {
43
58
  url: {
44
59
  type: Host.AidaClient.ParametersTypes.STRING,
45
- description: 'The url for the resource.',
60
+ description: 'The URL of the resource captured in the performance trace to retrieve.',
46
61
  nullable: false,
47
62
  },
48
63
  },
49
64
  required: ['url'],
50
65
  };
51
66
 
52
- displayInfoFromArgs(params: GetResourceContentArgs): {
67
+ displayInfoFromArgs(params: GetTraceResourceContentArgs): {
53
68
  title: string,
54
69
  action: string,
55
70
  } {
56
71
  return {
57
72
  title: lockedString(UIStringsNotTranslate.lookingAtResourceContent),
58
- action: `getResourceContent('${params.url}')`,
73
+ action: `getTraceResourceContent('${params.url}')`,
59
74
  };
60
75
  }
61
76
 
62
77
  async handler(
63
- params: GetResourceContentArgs,
78
+ params: GetTraceResourceContentArgs,
64
79
  capabilities: BaseToolCapability&TargetCapability&PerformanceTraceCapability,
65
80
  ): Promise<DataHandlerResult<{content: string}>> {
66
81
  const performanceTraceContext = capabilities.getPerformanceTraceContext();
@@ -72,6 +87,10 @@ export class GetResourceContentTool implements DataTool<
72
87
  return {error: 'Cannot use this tool on an imported file.'};
73
88
  }
74
89
 
90
+ if (!params.url) {
91
+ return {error: 'Missing arg: url'};
92
+ }
93
+
75
94
  if (!performanceTraceContext.canAccessResource(params.url)) {
76
95
  return {error: 'Resource not found'};
77
96
  }
@@ -82,6 +101,7 @@ export class GetResourceContentTool implements DataTool<
82
101
  let content: string;
83
102
 
84
103
  const url = params.url as Platform.DevToolsPath.UrlString;
104
+ // Check trace metadata for scripts captured during recording before falling back to live page resources.
85
105
  const script = parsedTrace.data.Scripts?.scripts.find(script => script.url === params.url);
86
106
  if (script?.content !== undefined) {
87
107
  content = script.content;
@@ -4,9 +4,7 @@
4
4
 
5
5
  import * as Host from '../../../core/host/host.js';
6
6
  import * as i18n from '../../../core/i18n/i18n.js';
7
- import type * as SDK from '../../../core/sdk/sdk.js';
8
7
  import * as Workspace from '../../workspace/workspace.js';
9
- import {FileContext} from '../contexts/FileContext.js';
10
8
 
11
9
  import {
12
10
  type BaseToolCapability,
@@ -50,23 +48,30 @@ export class ListSourcesTool implements
50
48
  }
51
49
 
52
50
  static getUISourceCodes(
53
- establishedOrigin: SDK.SecurityOrigin.SecurityOrigin,
51
+ originLock: OriginLockState,
54
52
  // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
55
53
  workspace: Workspace.Workspace.WorkspaceImpl = Workspace.Workspace.WorkspaceImpl.instance(),
56
54
  ): Workspace.UISourceCode.UISourceCode[] {
57
- if (establishedOrigin.isOpaque()) {
55
+ if (originLock.status !== 'ESTABLISHED_ORIGIN' || originLock.origin.isOpaque()) {
58
56
  return [];
59
57
  }
60
58
 
61
- const projects =
62
- workspace.projects().filter(project => project.type() === Workspace.Workspace.projectTypes.Network);
63
59
  const uiSourceCodes = new Map<string, Workspace.UISourceCode.UISourceCode>();
64
60
 
65
- for (const project of projects) {
61
+ for (const project of workspace.projectsForType(Workspace.Workspace.projectTypes.Network)) {
62
+ const projectOrigin = project.securityOrigin?.();
63
+ if (projectOrigin && !isOriginAllowedByLock(originLock, projectOrigin)) {
64
+ continue;
65
+ }
66
+
66
67
  for (const uiSourceCode of project.uiSourceCodes()) {
67
68
  if (uiSourceCode.isIgnoreListed()) {
68
69
  continue;
69
70
  }
71
+ if (!projectOrigin && !isOriginAllowedByLock(originLock, uiSourceCode.securityOrigin())) {
72
+ continue;
73
+ }
74
+
70
75
  const url = uiSourceCode.url();
71
76
  if (!uiSourceCodes.get(url) || uiSourceCode.contentType().isFromSourceMap()) {
72
77
  uiSourceCodes.set(url, uiSourceCode);
@@ -77,18 +82,19 @@ export class ListSourcesTool implements
77
82
  }
78
83
  }
79
84
 
80
- const originLock: OriginLockState = {status: 'ESTABLISHED_ORIGIN', origin: establishedOrigin};
81
- return [...uiSourceCodes.values()].filter(
82
- file => isOriginAllowedByLock(originLock, FileContext.originForUISourceCode(file)));
85
+ return Array.from(uiSourceCodes.values());
83
86
  }
84
87
 
85
88
  static getSourceById(
86
89
  id: number,
87
- establishedOrigin: SDK.SecurityOrigin.SecurityOrigin,
90
+ originLock: OriginLockState,
88
91
  // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
89
92
  workspace: Workspace.Workspace.WorkspaceImpl = Workspace.Workspace.WorkspaceImpl.instance(),
90
93
  ): Workspace.UISourceCode.UISourceCode|undefined {
91
- return ListSourcesTool.getUISourceCodes(establishedOrigin, workspace)
94
+ if (!Number.isInteger(id) || id <= 0) {
95
+ return undefined;
96
+ }
97
+ return ListSourcesTool.getUISourceCodes(originLock, workspace)
92
98
  .find(file => ListSourcesTool.uiSourceCodeId.get(file) === id);
93
99
  }
94
100
 
@@ -114,12 +120,13 @@ export class ListSourcesTool implements
114
120
  _params: Record<string, never>,
115
121
  context: BaseToolCapability&OriginLockCapability,
116
122
  ): Promise<DataHandlerResult<{files: SourceSummary[]}>> {
117
- const originResult = resolveOriginFromLock(context.getOriginLock());
123
+ const originLock = context.getOriginLock();
124
+ const originResult = resolveOriginFromLock(originLock);
118
125
  if ('error' in originResult) {
119
126
  return originResult;
120
127
  }
121
128
 
122
- const files = ListSourcesTool.getUISourceCodes(originResult.origin);
129
+ const files = ListSourcesTool.getUISourceCodes(originLock);
123
130
 
124
131
  return {
125
132
  result: {
@@ -258,8 +258,8 @@ export const enum ToolName {
258
258
  GET_TRACE_NETWORK_SUMMARY = 'getTraceNetworkSummary',
259
259
  RUN_LIGHTHOUSE = 'runLighthouse',
260
260
  GET_DETAILED_CALL_TREE = 'getDetailedCallTree',
261
- GET_FUNCTION_CODE = 'getFunctionCode',
262
- GET_RESOURCE_CONTENT = 'getResourceContent',
261
+ GET_TRACE_FUNCTION_CODE = 'getTraceFunctionCode',
262
+ GET_TRACE_RESOURCE_CONTENT = 'getTraceResourceContent',
263
263
  GET_INSIGHT_DETAILS = 'getInsightDetails',
264
264
  GET_STORAGE_BREAKDOWN = 'getStorageBreakdown',
265
265
  }
@@ -6,18 +6,18 @@ import {ExecuteJavaScriptTool} from './ExecuteJavaScript.js';
6
6
  import {GetCookieValuesTool} from './GetCookieValues.js';
7
7
  import {GetDetailedCallTreeTool} from './GetDetailedCallTree.js';
8
8
  import {GetElementAccessibilityDetailsTool} from './GetElementAccessibilityDetails.js';
9
- import {GetFunctionCodeTool} from './GetFunctionCode.js';
10
9
  import {GetInsightDetailsTool} from './GetInsightDetails.js';
11
10
  import {GetLighthouseAuditsTool} from './GetLighthouseAudits.js';
12
11
  import {GetNetworkRequestDetailsTool} from './GetNetworkRequestDetails.js';
13
- import {GetResourceContentTool} from './GetResourceContent.js';
14
12
  import {GetSourceContentTool} from './GetSourceContent.js';
15
13
  import {GetStorageBreakdownTool} from './GetStorageBreakdown.js';
16
14
  import {GetStorageValuesTool} from './GetStorageValues.js';
17
15
  import {GetStylesTool} from './GetStyles.js';
18
16
  import {GetTraceEventByKeyTool} from './GetTraceEventByKey.js';
17
+ import {GetTraceFunctionCodeTool} from './GetTraceFunctionCode.js';
19
18
  import {GetTraceMainThreadSummaryTool} from './GetTraceMainThreadSummary.js';
20
19
  import {GetTraceNetworkSummaryTool} from './GetTraceNetworkSummary.js';
20
+ import {GetTraceResourceContentTool} from './GetTraceResourceContent.js';
21
21
  import {ListCookiesTool} from './ListCookies.js';
22
22
  import {ListNetworkRequestsTool} from './ListNetworkRequests.js';
23
23
  import {ListPageOriginsTool} from './ListPageOrigins.js';
@@ -51,8 +51,8 @@ export interface BaseToolsRegistryMap {
51
51
  [ToolName.GET_TRACE_NETWORK_SUMMARY]: GetTraceNetworkSummaryTool;
52
52
  [ToolName.RUN_LIGHTHOUSE]: RunLighthouseTool;
53
53
  [ToolName.GET_DETAILED_CALL_TREE]: GetDetailedCallTreeTool;
54
- [ToolName.GET_FUNCTION_CODE]: GetFunctionCodeTool;
55
- [ToolName.GET_RESOURCE_CONTENT]: GetResourceContentTool;
54
+ [ToolName.GET_TRACE_FUNCTION_CODE]: GetTraceFunctionCodeTool;
55
+ [ToolName.GET_TRACE_RESOURCE_CONTENT]: GetTraceResourceContentTool;
56
56
  [ToolName.GET_INSIGHT_DETAILS]: GetInsightDetailsTool;
57
57
  [ToolName.GET_STORAGE_BREAKDOWN]: GetStorageBreakdownTool;
58
58
  }
@@ -86,8 +86,8 @@ export const TOOLS: BaseToolsRegistryMap = {
86
86
  [ToolName.GET_TRACE_NETWORK_SUMMARY]: new GetTraceNetworkSummaryTool(),
87
87
  [ToolName.RUN_LIGHTHOUSE]: new RunLighthouseTool(),
88
88
  [ToolName.GET_DETAILED_CALL_TREE]: new GetDetailedCallTreeTool(),
89
- [ToolName.GET_FUNCTION_CODE]: new GetFunctionCodeTool(),
90
- [ToolName.GET_RESOURCE_CONTENT]: new GetResourceContentTool(),
89
+ [ToolName.GET_TRACE_FUNCTION_CODE]: new GetTraceFunctionCodeTool(),
90
+ [ToolName.GET_TRACE_RESOURCE_CONTENT]: new GetTraceResourceContentTool(),
91
91
  [ToolName.GET_INSIGHT_DETAILS]: new GetInsightDetailsTool(),
92
92
  [ToolName.GET_STORAGE_BREAKDOWN]: new GetStorageBreakdownTool(),
93
93
  };
@@ -458,16 +458,9 @@ export class CompilerScriptMapping implements DebuggerSourceMapping {
458
458
  this.removeStubUISourceCode(script);
459
459
 
460
460
  const target = script.target();
461
- const embedderName = script.embedderName();
462
- let securityOrigin: SDK.SecurityOrigin.SecurityOrigin|undefined;
463
- if (embedderName) {
464
- const extractedOrigin = Common.ParsedURL.ParsedURL.extractOrigin(embedderName);
465
- if (extractedOrigin && extractedOrigin !== 'null') {
466
- securityOrigin = SDK.SecurityOrigin.SecurityOrigin.create(extractedOrigin);
467
- }
468
- }
469
- const parsedOrigin = securityOrigin ? `:${securityOrigin.siteId()}` : '';
470
- const projectId = `jsSourceMaps:${script.isContentScript() ? 'extensions' : ''}:${target.id()}${parsedOrigin}`;
461
+ const securityOrigin = script.securityOrigin();
462
+ const originPart = securityOrigin.isOpaque() ? '' : `:${securityOrigin.siteId()}`;
463
+ const projectId = `jsSourceMaps:${script.isContentScript() ? 'extensions' : ''}:${target.id()}${originPart}`;
471
464
  let project = this.#projects.get(projectId);
472
465
  if (!project) {
473
466
  const projectType = script.isContentScript() ? Workspace.Workspace.projectTypes.ContentScripts :
@@ -593,11 +593,11 @@ export class DebuggerLanguagePluginManager implements
593
593
  return {rawModuleId, plugin: null};
594
594
  }
595
595
 
596
- uiSourceCodeForURL(debuggerModel: SDK.DebuggerModel.DebuggerModel, url: Platform.DevToolsPath.UrlString):
597
- Workspace.UISourceCode.UISourceCode|null {
596
+ uiSourceCodeForURL(debuggerModel: SDK.DebuggerModel.DebuggerModel, url: Platform.DevToolsPath.UrlString,
597
+ script?: SDK.Script.Script): Workspace.UISourceCode.UISourceCode|null {
598
598
  const modelData = this.#debuggerModelToData.get(debuggerModel);
599
599
  if (modelData) {
600
- return modelData.getProject().uiSourceCodeForURL(url);
600
+ return modelData.uiSourceCodeForURL(url, script);
601
601
  }
602
602
  return null;
603
603
  }
@@ -625,7 +625,7 @@ export class DebuggerLanguagePluginManager implements
625
625
  const sourceLocations = await plugin.rawLocationToSourceLocation(pluginLocation);
626
626
  for (const sourceLocation of sourceLocations) {
627
627
  const uiSourceCode = this.uiSourceCodeForURL(
628
- script.debuggerModel, sourceLocation.sourceFileURL as Platform.DevToolsPath.UrlString);
628
+ script.debuggerModel, sourceLocation.sourceFileURL as Platform.DevToolsPath.UrlString, script);
629
629
  if (!uiSourceCode) {
630
630
  continue;
631
631
  }
@@ -1097,23 +1097,41 @@ export class DebuggerLanguagePluginManager implements
1097
1097
  }
1098
1098
 
1099
1099
  class ModelData {
1100
- project: ContentProviderBasedProject;
1100
+ readonly #debuggerModel: SDK.DebuggerModel.DebuggerModel;
1101
+ readonly #workspace: Workspace.Workspace.WorkspaceImpl;
1102
+ readonly #projects = new Map<string, ContentProviderBasedProject>();
1101
1103
  readonly uiSourceCodeToScripts: Map<Workspace.UISourceCode.UISourceCode, SDK.Script.Script[]>;
1102
1104
  constructor(debuggerModel: SDK.DebuggerModel.DebuggerModel, workspace: Workspace.Workspace.WorkspaceImpl) {
1103
- this.project =
1104
- new ContentProviderBasedProject(workspace, 'language_plugins::' + debuggerModel.target().id(),
1105
- Workspace.Workspace.projectTypes.Network, '', false /* isServiceProject */);
1106
- NetworkProject.setTargetForProject(this.project, debuggerModel.target());
1107
-
1105
+ this.#debuggerModel = debuggerModel;
1106
+ this.#workspace = workspace;
1108
1107
  this.uiSourceCodeToScripts = new Map();
1109
1108
  }
1110
1109
 
1110
+ #projectIdForScript(script: SDK.Script.Script): string {
1111
+ const securityOrigin = script.securityOrigin();
1112
+ const originPart = securityOrigin.isOpaque() ? '' : `:${securityOrigin.siteId()}`;
1113
+ return `language_plugins::${this.#debuggerModel.target().id()}${originPart}`;
1114
+ }
1115
+
1116
+ #projectForScript(script: SDK.Script.Script): ContentProviderBasedProject {
1117
+ const projectId = this.#projectIdForScript(script);
1118
+ let project = this.#projects.get(projectId);
1119
+ if (!project) {
1120
+ project = new ContentProviderBasedProject(this.#workspace, projectId, Workspace.Workspace.projectTypes.Network,
1121
+ '', false /* isServiceProject */, script.securityOrigin());
1122
+ NetworkProject.setTargetForProject(project, this.#debuggerModel.target());
1123
+ this.#projects.set(projectId, project);
1124
+ }
1125
+ return project;
1126
+ }
1127
+
1111
1128
  addSourceFiles(script: SDK.Script.Script, urls: Platform.DevToolsPath.UrlString[]): void {
1129
+ const project = this.#projectForScript(script);
1112
1130
  const initiator = script.createPageResourceLoadInitiator();
1113
1131
  for (const url of urls) {
1114
- let uiSourceCode = this.project.uiSourceCodeForURL(url);
1132
+ let uiSourceCode = project.uiSourceCodeForURL(url);
1115
1133
  if (!uiSourceCode) {
1116
- uiSourceCode = this.project.createUISourceCode(url, Common.ResourceType.resourceTypes.SourceMapScript);
1134
+ uiSourceCode = project.createUISourceCode(url, Common.ResourceType.resourceTypes.SourceMapScript);
1117
1135
  NetworkProject.setInitialFrameAttribution(uiSourceCode, script.frameId);
1118
1136
 
1119
1137
  // Bind the uiSourceCode to the script first before we add the
@@ -1129,7 +1147,7 @@ class ModelData {
1129
1147
  url, Common.ResourceType.resourceTypes.SourceMapScript, initiator,
1130
1148
  script.target().targetManager().getPageResourceLoader());
1131
1149
  const mimeType = Common.ResourceType.ResourceType.mimeFromURL(url) || 'text/javascript';
1132
- this.project.addUISourceCodeWithProvider(uiSourceCode, contentProvider, null, mimeType);
1150
+ project.addUISourceCodeWithProvider(uiSourceCode, contentProvider, null, mimeType);
1133
1151
  } else {
1134
1152
  // The same uiSourceCode can be provided by different scripts,
1135
1153
  // but we don't expect that to happen frequently.
@@ -1146,7 +1164,7 @@ class ModelData {
1146
1164
  scripts = scripts.filter(s => s !== script);
1147
1165
  if (scripts.length === 0) {
1148
1166
  this.uiSourceCodeToScripts.delete(uiSourceCode);
1149
- this.project.removeUISourceCode(uiSourceCode.url());
1167
+ uiSourceCode.project().removeUISourceCode(uiSourceCode.url());
1150
1168
  } else {
1151
1169
  this.uiSourceCodeToScripts.set(uiSourceCode, scripts);
1152
1170
  }
@@ -1154,11 +1172,24 @@ class ModelData {
1154
1172
  }
1155
1173
 
1156
1174
  dispose(): void {
1157
- this.project.dispose();
1175
+ for (const project of this.#projects.values()) {
1176
+ project.dispose();
1177
+ }
1178
+ this.#projects.clear();
1158
1179
  }
1159
1180
 
1160
- getProject(): ContentProviderBasedProject {
1161
- return this.project;
1181
+ uiSourceCodeForURL(url: Platform.DevToolsPath.UrlString,
1182
+ script?: SDK.Script.Script): Workspace.UISourceCode.UISourceCode|null {
1183
+ if (script) {
1184
+ return this.#projects.get(this.#projectIdForScript(script))?.uiSourceCodeForURL(url) ?? null;
1185
+ }
1186
+ for (const project of this.#projects.values()) {
1187
+ const uiSourceCode = project.uiSourceCodeForURL(url);
1188
+ if (uiSourceCode) {
1189
+ return uiSourceCode;
1190
+ }
1191
+ }
1192
+ return null;
1162
1193
  }
1163
1194
  }
1164
1195
 
@@ -312,11 +312,11 @@ export class ResourceScriptFile {
312
312
  this.script = this.uiSourceCode.contentType().isScript() ? script : null;
313
313
  }
314
314
 
315
- addSourceMapURL(sourceMapURL: Platform.DevToolsPath.UrlString): void {
315
+ addSourceMapURL(sourceMapURL: Platform.DevToolsPath.UrlString, provenance: SDK.SourceMap.SourceMapProvenance): void {
316
316
  if (!this.script) {
317
317
  return;
318
318
  }
319
- this.script.debuggerModel.setSourceMapURL(this.script, sourceMapURL);
319
+ this.script.debuggerModel.setSourceMapURL(this.script, sourceMapURL, provenance);
320
320
  }
321
321
 
322
322
  addDebugInfoURL(debugInfoURL: Platform.DevToolsPath.UrlString): void {
@@ -310,7 +310,7 @@ export class StyleFile implements TextUtils.ContentProvider.ContentProvider {
310
310
  const sourceMapManager = this.#cssModel.sourceMapManager();
311
311
  this.headers.forEach(header => {
312
312
  sourceMapManager.detachSourceMap(header);
313
- sourceMapManager.attachSourceMap(header, sourceUrl, sourceMapUrl);
313
+ sourceMapManager.attachSourceMap(header, sourceUrl, sourceMapUrl, SDK.SourceMap.SourceMapProvenance.USER);
314
314
  });
315
315
  }
316
316
  }
@@ -14,13 +14,12 @@ export interface CommentThread {
14
14
  id: string;
15
15
  text: string;
16
16
  networkRequestId?: string;
17
- backendNodeId?: number;
18
- editor?: CommentManager.EditorAnchorSignature;
17
+ node?: CommentManager.DOMNodeAnchorSignature;
19
18
  }
20
19
 
21
20
  export interface RevealTarget {
22
21
  networkRequestId?: string;
23
- backendNodeId?: number;
22
+ node?: CommentManager.DOMNodeAnchorSignature;
24
23
  }
25
24
 
26
25
  export const enum Events {
@@ -69,21 +68,65 @@ export class CD4ABridge extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
69
68
  Common.EventTarget.removeEventListeners(this.#eventListeners);
70
69
  }
71
70
 
71
+ #getDOMNode(nodeSignature: CommentManager.DOMNodeAnchorSignature): SDK.DOMModel.DOMNode|undefined {
72
+ if (!this.#targetManager) {
73
+ return undefined;
74
+ }
75
+ const target = this.#targetManager.targetById(nodeSignature.targetId) ?? this.#targetManager.primaryPageTarget();
76
+ const domModel = target?.model(SDK.DOMModel.DOMModel);
77
+ if (!domModel) {
78
+ return undefined;
79
+ }
80
+ for (const node of domModel.idToDOMNode.values()) {
81
+ if (node.backendNodeId() === nodeSignature.backendNodeId) {
82
+ return node;
83
+ }
84
+ }
85
+ return undefined;
86
+ }
87
+
88
+ #formatCommentText(thread: CommentManager.CommentThread): string {
89
+ const rawText = thread.comments[0]?.text ?? '';
90
+ const details: string[] = [];
91
+
92
+ if (thread.anchor.textSignature) {
93
+ details.push(`- DevTools element: ${thread.anchor.textSignature}`);
94
+ }
95
+
96
+ if (thread.anchor.node) {
97
+ const domNode = this.#getDOMNode(thread.anchor.node);
98
+ const simpleSelector = domNode?.simpleSelector();
99
+ if (simpleSelector) {
100
+ details.push(`- DOM node selector: ${simpleSelector}`);
101
+ }
102
+ }
103
+
104
+ if (thread.anchor.editor) {
105
+ const editorInfo = thread.anchor.editor.filePath ?
106
+ `${thread.anchor.editor.filePath}:${thread.anchor.editor.lineNumber}` :
107
+ `line ${thread.anchor.editor.lineNumber}`;
108
+ details.push(`- Editor: ${editorInfo}`);
109
+ }
110
+
111
+ if (details.length === 0) {
112
+ return rawText;
113
+ }
114
+
115
+ return rawText ? `${rawText}\n\n${details.join('\n')}` : details.join('\n');
116
+ }
117
+
72
118
  getCommentThreads(): CommentThread[] {
73
119
  const threads = this.#commentManager.takeComments();
74
120
  return threads.map(thread => {
75
121
  const threadPayload: CommentThread = {
76
122
  id: thread.id,
77
- text: thread.comments[0]?.text ?? '',
123
+ text: this.#formatCommentText(thread),
78
124
  };
79
125
  if (thread.anchor.networkRequestId) {
80
126
  threadPayload.networkRequestId = thread.anchor.networkRequestId;
81
127
  }
82
128
  if (thread.anchor.node) {
83
- threadPayload.backendNodeId = thread.anchor.node.backendNodeId;
84
- }
85
- if (thread.anchor.editor) {
86
- threadPayload.editor = thread.anchor.editor;
129
+ threadPayload.node = {...thread.anchor.node};
87
130
  }
88
131
  return threadPayload;
89
132
  });
@@ -112,11 +155,11 @@ export class CD4ABridge extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
112
155
  }
113
156
  }
114
157
 
115
- if (target?.backendNodeId !== undefined && this.#targetManager) {
116
- const primaryTarget = this.#targetManager.primaryPageTarget();
117
- const domModel = primaryTarget?.model(SDK.DOMModel.DOMModel);
158
+ if (target?.node && this.#targetManager) {
159
+ const sdkTarget = this.#targetManager.targetById(target.node.targetId) ?? this.#targetManager.primaryPageTarget();
160
+ const domModel = sdkTarget?.model(SDK.DOMModel.DOMModel);
118
161
  if (domModel) {
119
- const cdpNodeId = target.backendNodeId as Protocol.DOM.BackendNodeId;
162
+ const cdpNodeId = target.node.backendNodeId as Protocol.DOM.BackendNodeId;
120
163
  const nodeMap = await domModel.pushNodesByBackendIdsToFrontend(new Set([cdpNodeId]));
121
164
  const node = nodeMap?.get(cdpNodeId);
122
165
  if (node) {