chrome-devtools-mcp-for-extension 0.19.2 → 0.20.0

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 (153) hide show
  1. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Color.js +13 -9
  2. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ColorConverter.js +9 -7
  3. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Console.js +1 -8
  4. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Debouncer.js +2 -2
  5. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Gzip.js +9 -7
  6. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/MapWithDefault.js +5 -3
  7. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ParsedURL.js +10 -20
  8. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ResourceType.js +0 -11
  9. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ReturnToPanel.js +6 -4
  10. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Revealer.js +5 -0
  11. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/SegmentedRange.js +1 -2
  12. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Settings.js +110 -99
  13. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/StringOutputStream.js +1 -4
  14. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Throttler.js +2 -2
  15. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/common.js +1 -4
  16. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/AidaClient.js +21 -2
  17. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/DispatchHttpRequestClient.js +66 -0
  18. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/GdpClient.js +102 -86
  19. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHost.js +32 -450
  20. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHostAPI.js +32 -29
  21. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHostStub.js +430 -0
  22. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/Platform.js +5 -3
  23. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/ResourceLoader.js +10 -22
  24. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/UserMetrics.js +26 -15
  25. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/host.js +2 -1
  26. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/ArrayUtilities.js +2 -2
  27. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/HostRuntime.js +19 -0
  28. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/StringUtilities.js +34 -32
  29. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/api/HostRuntime.js +4 -0
  30. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/api/api.js +5 -0
  31. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/browser/HostRuntime.js +63 -0
  32. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/browser/browser.js +5 -0
  33. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/node/HostRuntime.js +72 -0
  34. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/node/node.js +5 -0
  35. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/platform.js +2 -2
  36. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/CDPConnection.js +17 -0
  37. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/ConnectionTransport.js +12 -0
  38. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/DevToolsCDPConnection.js +138 -0
  39. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/InspectorBackend.js +49 -312
  40. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/protocol_client.js +4 -9
  41. package/build/node_modules/chrome-devtools-frontend/front_end/core/root/DevToolsContext.js +54 -0
  42. package/build/node_modules/chrome-devtools-frontend/front_end/core/root/root.js +2 -1
  43. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/AnimationModel.js +2 -3
  44. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CPUThrottlingManager.js +0 -3
  45. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMatchedStyles.js +51 -17
  46. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMetadata.js +21 -7
  47. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSModel.js +11 -5
  48. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSProperty.js +4 -7
  49. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParser.js +11 -9
  50. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParserMatchers.js +34 -24
  51. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSRule.js +52 -10
  52. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSStartingStyle.js +21 -0
  53. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSStyleDeclaration.js +4 -4
  54. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ChildTargetManager.js +39 -35
  55. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Connections.js +10 -47
  56. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ConsoleModel.js +1 -1
  57. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Cookie.js +1 -1
  58. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DOMModel.js +29 -4
  59. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DebuggerModel.js +5 -20
  60. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/EnhancedTracesParser.js +17 -3
  61. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/EventBreakpointsModel.js +4 -2
  62. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/HttpReasonPhraseStrings.js +4 -2
  63. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/IOModel.js +1 -4
  64. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkManager.js +428 -121
  65. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkRequest.js +8 -22
  66. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/PageResourceLoader.js +44 -34
  67. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/PreloadingModel.js +64 -19
  68. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RehydratingConnection.js +139 -12
  69. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RemoteObject.js +5 -2
  70. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ResourceTreeModel.js +3 -2
  71. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ScopeTreeCache.js +36 -0
  72. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ScreenCaptureModel.js +20 -18
  73. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Script.js +26 -1
  74. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ServerSentEventsProtocol.js +3 -0
  75. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMap.js +54 -14
  76. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapCache.js +16 -0
  77. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapManager.js +19 -7
  78. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapScopesInfo.js +240 -8
  79. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Target.js +12 -17
  80. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/TargetManager.js +38 -29
  81. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/TraceObject.js +11 -8
  82. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/sdk-meta.js +80 -31
  83. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/sdk.js +4 -2
  84. package/build/node_modules/chrome-devtools-frontend/front_end/generated/ARIAProperties.js +1301 -174
  85. package/build/node_modules/chrome-devtools-frontend/front_end/generated/Deprecation.js +67 -22
  86. package/build/node_modules/chrome-devtools-frontend/front_end/generated/InspectorBackendCommands.js +62 -91
  87. package/build/node_modules/chrome-devtools-frontend/front_end/generated/SupportedCSSProperties.js +188 -100
  88. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.js +30 -3
  89. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.js +50 -34
  90. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.js +152 -101
  91. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AICallTree.js +11 -6
  92. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIContext.js +25 -26
  93. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIQueries.js +46 -2
  94. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CSSWorkspaceBinding.js +10 -8
  95. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CompilerScriptMapping.js +82 -3
  96. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/DebuggerWorkspaceBinding.js +33 -15
  97. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/ResourceMapping.js +105 -14
  98. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/ResourceScriptMapping.js +38 -0
  99. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/SASSSourceMapping.js +5 -4
  100. package/build/node_modules/chrome-devtools-frontend/front_end/models/cpu_profile/CPUProfileDataModel.js +9 -7
  101. package/build/node_modules/chrome-devtools-frontend/front_end/models/cpu_profile/ProfileTreeModel.js +6 -7
  102. package/build/node_modules/chrome-devtools-frontend/front_end/models/crux-manager/CrUXManager.js +6 -4
  103. package/build/node_modules/chrome-devtools-frontend/front_end/models/formatter/FormatterWorkerPool.js +16 -2
  104. package/build/node_modules/chrome-devtools-frontend/front_end/models/network_time_calculator/RequestTimeRanges.js +6 -4
  105. package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/FunctionCodeResolver.js +192 -0
  106. package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/NamesResolver.js +12 -16
  107. package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/source_map_scopes.js +2 -2
  108. package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/StackTraceModel.js +1 -1
  109. package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/Trie.js +8 -0
  110. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/LanternComputationData.js +1 -0
  111. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/ModelImpl.js +6 -3
  112. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/Processor.js +4 -4
  113. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/Styles.js +1 -1
  114. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/extras/TraceTree.js +11 -4
  115. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/FramesHandler.js +7 -5
  116. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/LayoutShiftsHandler.js +8 -4
  117. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/MetaHandler.js +4 -1
  118. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/NetworkRequestsHandler.js +29 -3
  119. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/SamplesHandler.js +59 -6
  120. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/ScriptsHandler.js +26 -1
  121. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/UserTimingsHandler.js +1 -1
  122. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/helpers.js +1 -1
  123. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/helpers/Timing.js +4 -2
  124. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/helpers/Trace.js +18 -4
  125. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/CLSCulprits.js +2 -1
  126. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/Cache.js +2 -1
  127. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DOMSize.js +2 -1
  128. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DocumentLatency.js +12 -11
  129. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DuplicatedJavaScript.js +2 -1
  130. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/FontDisplay.js +2 -1
  131. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ForcedReflow.js +3 -2
  132. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/INPBreakdown.js +14 -2
  133. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ImageDelivery.js +2 -1
  134. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LCPBreakdown.js +13 -2
  135. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LCPDiscovery.js +2 -1
  136. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LegacyJavaScript.js +4 -2
  137. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ModernHTTP.js +2 -1
  138. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/NetworkDependencyTree.js +4 -3
  139. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/RenderBlocking.js +2 -1
  140. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/SlowCSSSelector.js +2 -1
  141. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ThirdParties.js +2 -1
  142. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/Viewport.js +2 -1
  143. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/types/TraceEvents.js +9 -3
  144. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace_source_maps_resolver/SourceMapsResolver.js +25 -2
  145. package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/IgnoreListManager.js +41 -48
  146. package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/UISourceCode.js +38 -0
  147. package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/WorkspaceImpl.js +5 -8
  148. package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/workspace-meta.js +34 -0
  149. package/build/src/McpContext.js +8 -1
  150. package/build/src/tools/bookmarks.js +0 -1
  151. package/build/src/tools/gemini-web.js +17 -25
  152. package/build/src/tools/snapshot.js +9 -2
  153. package/package.json +3 -3
@@ -50,7 +50,15 @@ export class CPUProfileDataModel extends ProfileTreeModel {
50
50
  * for CPU profiles coming from traces.
51
51
  */
52
52
  traceIds;
53
+ /**
54
+ * Each item in the `lines` array contains the script line executing
55
+ * when the sample in that array position was taken.
56
+ */
53
57
  lines;
58
+ /**
59
+ * Same as `lines` above, but with the script column.
60
+ */
61
+ columns;
54
62
  totalHitCount;
55
63
  profileHead;
56
64
  /**
@@ -84,14 +92,8 @@ export class CPUProfileDataModel extends ProfileTreeModel {
84
92
  }
85
93
  this.traceIds = profile.traceIds;
86
94
  this.samples = profile.samples;
87
- // Lines are available only in profiles coming from tracing.
88
- // Elements in the lines array have a 1 to 1 correspondence with
89
- // samples, by array position. They can be 1 or 0 and indicate if
90
- // there is line data for a given sample, i.e. if a given sample
91
- // needs to be included to calculate the line level execution time
92
- // data, which we show in the sources panel after recording a
93
- // profile.
94
95
  this.lines = profile.lines;
96
+ this.columns = profile.columns;
95
97
  this.totalHitCount = 0;
96
98
  this.profileHead = this.translateProfileTree(profile.nodes);
97
99
  this.initialize(this.profileHead);
@@ -9,7 +9,7 @@ export class ProfileNode {
9
9
  id;
10
10
  parent;
11
11
  children;
12
- functionName;
12
+ originalFunctionName = null;
13
13
  depth;
14
14
  deoptReason;
15
15
  constructor(callFrame) {
@@ -18,7 +18,6 @@ export class ProfileNode {
18
18
  this.self = 0;
19
19
  this.total = 0;
20
20
  this.id = 0;
21
- this.functionName = callFrame.functionName;
22
21
  this.parent = null;
23
22
  this.children = [];
24
23
  }
@@ -34,11 +33,11 @@ export class ProfileNode {
34
33
  get columnNumber() {
35
34
  return this.callFrame.columnNumber;
36
35
  }
37
- setFunctionName(name) {
38
- if (name === null) {
39
- return;
40
- }
41
- this.functionName = name;
36
+ get functionName() {
37
+ return this.originalFunctionName ?? this.callFrame.functionName;
38
+ }
39
+ setOriginalFunctionName(name) {
40
+ this.originalFunctionName = name;
42
41
  }
43
42
  }
44
43
  export class ProfileTreeModel {
@@ -19,7 +19,7 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
19
19
  const CRUX_API_KEY = 'AIzaSyCCSOx25vrb5z0tbedCB3_JRzzbVW6Uwgw';
20
20
  const DEFAULT_ENDPOINT = `https://chromeuxreport.googleapis.com/v1/records:queryRecord?key=${CRUX_API_KEY}`;
21
21
  let cruxManagerInstance;
22
- // TODO: Potentially support `TABLET`. Tablet field data will always be `null` until then.
22
+ /** TODO: Potentially support `TABLET`. Tablet field data will always be `null` until then. **/
23
23
  export const DEVICE_SCOPE_LIST = ['ALL', 'DESKTOP', 'PHONE'];
24
24
  const pageScopeList = ['origin', 'url'];
25
25
  const metrics = [
@@ -92,9 +92,11 @@ export class CrUXManager extends Common.ObjectWrapper.ObjectWrapper {
92
92
  'url-PHONE': null,
93
93
  'url-TABLET': null,
94
94
  warnings: [],
95
+ normalizedUrl: '',
95
96
  };
96
97
  try {
97
98
  const normalizedUrl = this.#normalizeUrl(pageUrl);
99
+ pageResult.normalizedUrl = normalizedUrl.href;
98
100
  const promises = [];
99
101
  for (const pageScope of pageScopeList) {
100
102
  for (const deviceScope of DEVICE_SCOPE_LIST) {
@@ -143,10 +145,10 @@ export class CrUXManager extends Common.ObjectWrapper.ObjectWrapper {
143
145
  */
144
146
  async #getFieldDataForCurrentPage() {
145
147
  const currentUrl = this.#mainDocumentUrl || await this.#getInspectedURL();
146
- const urlForCrux = this.#configSetting.get().overrideEnabled ? this.#configSetting.get().override || '' :
148
+ const normalizedUrl = this.#configSetting.get().overrideEnabled ? this.#configSetting.get().override || '' :
147
149
  this.#getMappedUrl(currentUrl);
148
- const result = await this.getFieldDataForPage(urlForCrux);
149
- if (currentUrl !== urlForCrux) {
150
+ const result = await this.getFieldDataForPage(normalizedUrl);
151
+ if (currentUrl !== normalizedUrl) {
150
152
  result.warnings.push(i18nString(UIStrings.fieldOverrideWarning));
151
153
  }
152
154
  return result;
@@ -1,7 +1,7 @@
1
1
  // Copyright 2016 The Chromium Authors
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
- import * as Common from '../../core/common/common.js';
4
+ import * as Platform from '../../core/platform/platform.js';
5
5
  let formatterWorkerPoolInstance;
6
6
  export class FormatterWorkerPool {
7
7
  taskQueue;
@@ -16,8 +16,22 @@ export class FormatterWorkerPool {
16
16
  }
17
17
  return formatterWorkerPoolInstance;
18
18
  }
19
+ dispose() {
20
+ for (const task of this.taskQueue) {
21
+ console.error('rejecting task');
22
+ task.errorCallback(new Event('Worker terminated'));
23
+ }
24
+ for (const [worker, task] of this.workerTasks.entries()) {
25
+ task?.errorCallback(new Event('Worker terminated'));
26
+ worker.terminate(/* immediately=*/ true);
27
+ }
28
+ }
29
+ static removeInstance() {
30
+ formatterWorkerPoolInstance?.dispose();
31
+ formatterWorkerPoolInstance = undefined;
32
+ }
19
33
  createWorker() {
20
- const worker = Common.Worker.WorkerWrapper.fromURL(new URL('../../entrypoints/formatter_worker/formatter_worker-entrypoint.js', import.meta.url));
34
+ const worker = Platform.HostRuntime.HOST_RUNTIME.createWorker(new URL('../../entrypoints/formatter_worker/formatter_worker-entrypoint.js', import.meta.url).toString());
21
35
  worker.onmessage = this.onWorkerMessage.bind(this, worker);
22
36
  worker.onerror = this.onWorkerError.bind(this, worker);
23
37
  return worker;
@@ -36,10 +36,12 @@ export function calculateRequestTimeRanges(request, navigationStart) {
36
36
  addRange(name, startTime + (start / 1000), startTime + (end / 1000));
37
37
  }
38
38
  }
39
- // In some situations, argument `start` may come before `startTime` (`timing.requestStart`). This is especially true
40
- // in cases such as SW static routing API where fields like `workerRouterEvaluationStart` or `workerCacheLookupStart`
41
- // is set before setting `timing.requestStart`. If the `start` and `end` is known to be a valid value (i.e. not default
42
- // invalid value -1 or undefined), we allow adding the range.
39
+ /**
40
+ * In some situations, argument `start` may come before `startTime` (`timing.requestStart`). This is especially true
41
+ * in cases such as SW static routing API where fields like `workerRouterEvaluationStart` or `workerCacheLookupStart`
42
+ * is set before setting `timing.requestStart`. If the `start` and `end` is known to be a valid value (i.e. not default
43
+ * invalid value -1 or undefined), we allow adding the range.
44
+ **/
43
45
  function addMaybeNegativeOffsetRange(name, start, end) {
44
46
  addRange(name, startTime + (start / 1000), startTime + (end / 1000));
45
47
  }
@@ -0,0 +1,192 @@
1
+ // Copyright 2025 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
+ import * as SDK from '../../core/sdk/sdk.js';
5
+ import * as Bindings from '../bindings/bindings.js';
6
+ import * as Formatter from '../formatter/formatter.js';
7
+ import * as TextUtils from '../text_utils/text_utils.js';
8
+ import * as Workspace from '../workspace/workspace.js';
9
+ const inputCache = new WeakMap();
10
+ async function prepareInput(uiSourceCode, content) {
11
+ const formattedContent = await format(uiSourceCode, content);
12
+ const text = new TextUtils.Text.Text(formattedContent ? formattedContent.formattedContent : content);
13
+ let performanceData = uiSourceCode.getDecorationData("performance" /* Workspace.UISourceCode.DecoratorType.PERFORMANCE */);
14
+ // Map profile data to the formatted view of the text.
15
+ if (formattedContent && performanceData) {
16
+ performanceData = Workspace.UISourceCode.createMappedProfileData(performanceData, (line, column) => {
17
+ return formattedContent.formattedMapping.originalToFormatted(line, column);
18
+ });
19
+ }
20
+ return { text, formattedContent, performanceData };
21
+ }
22
+ /** Formatting and parsing line endings for Text is expensive, so cache it. */
23
+ async function prepareInputAndCache(uiSourceCode, content) {
24
+ let cachedPromise = inputCache.get(uiSourceCode);
25
+ if (cachedPromise) {
26
+ return await cachedPromise;
27
+ }
28
+ cachedPromise = prepareInput(uiSourceCode, content);
29
+ inputCache.set(uiSourceCode, cachedPromise);
30
+ return await cachedPromise;
31
+ }
32
+ function extractPerformanceDataByLine(textRange, performanceData) {
33
+ const { startLine, startColumn, endLine, endColumn } = textRange;
34
+ const byLine = new Array(endLine - startLine + 1).fill(0);
35
+ for (let line = startLine; line <= endLine; line++) {
36
+ const lineData = performanceData.get(line + 1);
37
+ if (!lineData) {
38
+ continue;
39
+ }
40
+ // Fast-path for when the entire line's data is relevant.
41
+ if (line !== startLine && line !== endLine) {
42
+ byLine[line - startLine] = lineData.values().reduce((acc, cur) => acc + cur);
43
+ continue;
44
+ }
45
+ const column0 = line === startLine ? startColumn + 1 : 0;
46
+ const column1 = line === endLine ? endColumn + 1 : Number.POSITIVE_INFINITY;
47
+ let totalData = 0;
48
+ for (const [column, data] of lineData) {
49
+ if (column >= column0 && column <= column1) {
50
+ totalData += data;
51
+ }
52
+ }
53
+ byLine[line - startLine] = totalData;
54
+ }
55
+ return byLine.map(data => Math.round(data * 10) / 10);
56
+ }
57
+ function createFunctionCode(inputData, functionBounds, options) {
58
+ let { startLine, startColumn, endLine, endColumn } = functionBounds.range;
59
+ if (inputData.formattedContent) {
60
+ const startMapped = inputData.formattedContent.formattedMapping.originalToFormatted(startLine, startColumn);
61
+ startLine = startMapped[0];
62
+ startColumn = startMapped[1];
63
+ const endMapped = inputData.formattedContent.formattedMapping.originalToFormatted(endLine, endColumn);
64
+ endLine = endMapped[0];
65
+ endColumn = endMapped[1];
66
+ }
67
+ const text = inputData.text;
68
+ const content = text.value();
69
+ // Define two ranges - the first is just the function bounds, the second includes
70
+ // that plus some surrounding context as dictated by the options.
71
+ const range = new TextUtils.TextRange.TextRange(startLine, startColumn, endLine, endColumn);
72
+ const functionStartOffset = text.offsetFromPosition(startLine, startColumn);
73
+ const functionEndOffset = text.offsetFromPosition(endLine, endColumn);
74
+ let contextStartOffset = 0;
75
+ if (options?.contextLength !== undefined) {
76
+ const contextLength = options.contextLength;
77
+ contextStartOffset = Math.max(contextStartOffset, functionStartOffset - contextLength);
78
+ }
79
+ if (options?.contextLineLength !== undefined) {
80
+ const contextLineLength = options.contextLineLength;
81
+ const position = text.offsetFromPosition(Math.max(startLine - contextLineLength, 0), 0);
82
+ contextStartOffset = Math.max(contextStartOffset, position);
83
+ }
84
+ let contextEndOffset = content.length;
85
+ if (options?.contextLength !== undefined) {
86
+ const contextLength = options.contextLength;
87
+ contextEndOffset = Math.min(contextEndOffset, functionEndOffset + contextLength);
88
+ }
89
+ if (options?.contextLineLength !== undefined) {
90
+ const contextLineLength = options.contextLineLength;
91
+ const position = text.offsetFromPosition(Math.min(endLine + contextLineLength, text.lineCount() - 1), Number.POSITIVE_INFINITY);
92
+ contextEndOffset = Math.min(contextEndOffset, position);
93
+ }
94
+ const contextStart = text.positionFromOffset(contextStartOffset);
95
+ const contextEnd = text.positionFromOffset(contextEndOffset);
96
+ const rangeWithContext = new TextUtils.TextRange.TextRange(contextStart.lineNumber, contextStart.columnNumber, contextEnd.lineNumber, contextEnd.columnNumber);
97
+ // Grab substrings for the function range, and for the context range.
98
+ const code = content.substring(functionStartOffset, functionEndOffset);
99
+ const before = content.substring(contextStartOffset, functionStartOffset);
100
+ const after = content.substring(functionEndOffset, contextEndOffset);
101
+ let codeWithContext;
102
+ if (options?.appendProfileData && inputData.performanceData) {
103
+ const performanceDataByLine = extractPerformanceDataByLine(range, inputData.performanceData);
104
+ const lines = performanceDataByLine.map((data, i) => {
105
+ let line = text.lineAt(startLine + i);
106
+ const isLastLine = i === performanceDataByLine.length - 1;
107
+ if (i === 0) {
108
+ if (isLastLine) {
109
+ line = line.substring(startColumn, endColumn);
110
+ }
111
+ else {
112
+ line = line.substring(startColumn);
113
+ }
114
+ }
115
+ else if (isLastLine) {
116
+ line = line.substring(0, endColumn);
117
+ }
118
+ if (isLastLine) {
119
+ // Don't ever annotate the last line - it could make the rest of the code on
120
+ // that line get commented out.
121
+ data = 0;
122
+ }
123
+ return data ? `${line} // ${data} ms` : line;
124
+ });
125
+ const annotatedCode = lines.join('\n');
126
+ codeWithContext = before + `<FUNCTION_START>${annotatedCode}<FUNCTION_END>` + after;
127
+ }
128
+ else {
129
+ codeWithContext = before + `<FUNCTION_START>${code}<FUNCTION_END>` + after;
130
+ }
131
+ return {
132
+ functionBounds,
133
+ text,
134
+ code,
135
+ range,
136
+ codeWithContext,
137
+ rangeWithContext,
138
+ };
139
+ }
140
+ /**
141
+ * The input location may be a source mapped location or a raw location.
142
+ */
143
+ export async function getFunctionCodeFromLocation(target, url, line, column, options) {
144
+ const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
145
+ if (!debuggerModel) {
146
+ throw new Error('missing debugger model');
147
+ }
148
+ let uiSourceCode;
149
+ const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance();
150
+ const projects = debuggerWorkspaceBinding.workspace.projectsForType(Workspace.Workspace.projectTypes.Network);
151
+ for (const project of projects) {
152
+ uiSourceCode = project.uiSourceCodeForURL(url);
153
+ if (uiSourceCode) {
154
+ break;
155
+ }
156
+ }
157
+ if (!uiSourceCode) {
158
+ return null;
159
+ }
160
+ const rawLocations = await debuggerWorkspaceBinding.uiLocationToRawLocations(uiSourceCode, line, column);
161
+ const rawLocation = rawLocations.at(-1);
162
+ if (!rawLocation) {
163
+ return null;
164
+ }
165
+ return await getFunctionCodeFromRawLocation(rawLocation, options);
166
+ }
167
+ async function format(uiSourceCode, content) {
168
+ const contentType = uiSourceCode.contentType();
169
+ const shouldFormat = !contentType.isFromSourceMap() && (contentType.isDocument() || contentType.isScript()) &&
170
+ TextUtils.TextUtils.isMinified(content);
171
+ if (!shouldFormat) {
172
+ return null;
173
+ }
174
+ return await Formatter.ScriptFormatter.formatScriptContent(contentType.canonicalMimeType(), content, '\t');
175
+ }
176
+ /**
177
+ * Returns a {@link FunctionCode} for the given raw location.
178
+ */
179
+ export async function getFunctionCodeFromRawLocation(rawLocation, options) {
180
+ const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance();
181
+ const functionBounds = await debuggerWorkspaceBinding.functionBoundsAtRawLocation(rawLocation);
182
+ if (!functionBounds) {
183
+ return null;
184
+ }
185
+ await functionBounds.uiSourceCode.requestContentData();
186
+ const content = functionBounds.uiSourceCode.content();
187
+ if (!content) {
188
+ return null;
189
+ }
190
+ const inputData = await prepareInputAndCache(functionBounds.uiSourceCode, content);
191
+ return createFunctionCode(inputData, functionBounds, options);
192
+ }
@@ -2,11 +2,11 @@
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
  import * as Common from '../../core/common/common.js';
5
+ import * as Root from '../../core/root/root.js';
5
6
  import * as SDK from '../../core/sdk/sdk.js';
6
7
  import * as Bindings from '../bindings/bindings.js';
7
8
  import * as Formatter from '../formatter/formatter.js';
8
9
  import * as TextUtils from '../text_utils/text_utils.js';
9
- import { scopeTreeForScript } from './ScopeTreeCache.js';
10
10
  const scopeToCachedIdentifiersMap = new WeakMap();
11
11
  const cachedMapByCallFrame = new WeakMap();
12
12
  export async function getTextFor(contentProvider) {
@@ -31,15 +31,7 @@ const computeScopeTree = async function (script) {
31
31
  if (!script.sourceMapURL) {
32
32
  return null;
33
33
  }
34
- const text = await getTextFor(script);
35
- if (!text) {
36
- return null;
37
- }
38
- const scopeTree = await scopeTreeForScript(script);
39
- if (!scopeTree) {
40
- return null;
41
- }
42
- return { scopeTree, text };
34
+ return await SDK.ScopeTreeCache.scopeTreeForScript(script);
43
35
  };
44
36
  /**
45
37
  * @returns the scope chain from outer-most to inner-most scope where the inner-most
@@ -182,7 +174,7 @@ const resolveScope = async (script, scopeChain) => {
182
174
  return;
183
175
  }
184
176
  }
185
- // If there is no entry with the name field, try to infer the name from the source positions.
177
+ /** If there is no entry with the name field, try to infer the name from the source positions. **/
186
178
  async function resolvePosition() {
187
179
  if (!sourceMap) {
188
180
  return;
@@ -309,7 +301,9 @@ export const resolveScopeChain = async function (callFrame) {
309
301
  if (scopeChain) {
310
302
  return scopeChain;
311
303
  }
312
- scopeChain = callFrame.script.sourceMap()?.resolveScopeChain(callFrame);
304
+ scopeChain = Root.Runtime.experiments.isEnabled("use-source-map-scopes" /* Root.Runtime.ExperimentName.USE_SOURCE_MAP_SCOPES */) ?
305
+ callFrame.script.sourceMap()?.resolveScopeChain(callFrame) :
306
+ null;
313
307
  if (scopeChain) {
314
308
  return scopeChain;
315
309
  }
@@ -556,10 +550,12 @@ export class RemoteObject extends SDK.RemoteObject.RemoteObject {
556
550
  return this.object.isNode();
557
551
  }
558
552
  }
559
- // Resolve the frame's function name using the name associated with the opening
560
- // paren that starts the scope. If there is no name associated with the scope
561
- // start or if the function scope does not start with a left paren (e.g., arrow
562
- // function with one parameter), the resolution returns null.
553
+ /**
554
+ * Resolve the frame's function name using the name associated with the opening
555
+ * paren that starts the scope. If there is no name associated with the scope
556
+ * start or if the function scope does not start with a left paren (e.g., arrow
557
+ * function with one parameter), the resolution returns null.
558
+ **/
563
559
  async function getFunctionNameFromScopeStart(script, lineNumber, columnNumber) {
564
560
  // To reduce the overhead of resolving function names,
565
561
  // we check for source maps first and immediately leave
@@ -1,7 +1,7 @@
1
1
  // Copyright 2022 The Chromium Authors
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
+ import * as FunctionCodeResolver from './FunctionCodeResolver.js';
4
5
  import * as NamesResolver from './NamesResolver.js';
5
6
  import * as ScopeChainModel from './ScopeChainModel.js';
6
- import * as ScopeTreeCache from './ScopeTreeCache.js';
7
- export { NamesResolver, ScopeChainModel, ScopeTreeCache, };
7
+ export { FunctionCodeResolver, NamesResolver, ScopeChainModel, };
@@ -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
  import * as SDK from '../../core/sdk/sdk.js';
5
- // eslint-disable-next-line rulesdir/es-modules-import
5
+ // eslint-disable-next-line @devtools/es-modules-import
6
6
  import * as StackTrace from './stack_trace.js';
7
7
  import { AsyncFragmentImpl, FragmentImpl, FrameImpl, StackTraceImpl } from './StackTraceImpl.js';
8
8
  import { Trie } from './Trie.js';
@@ -1,6 +1,14 @@
1
1
  // Copyright 2025 The Chromium Authors
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
+ /**
5
+ * @returns whether the frame is a V8 builtin frame e.g. Array.map. Builtin frames
6
+ * have neither source position nor script or URL. They only have a name.
7
+ */
8
+ export function isBuiltinFrame(rawFrame) {
9
+ return rawFrame.lineNumber === -1 && rawFrame.columnNumber === -1 && !Boolean(rawFrame.scriptId) &&
10
+ !Boolean(rawFrame.url);
11
+ }
4
12
  export class FrameNode {
5
13
  parent;
6
14
  children = [];
@@ -167,6 +167,7 @@ function createLanternRequest(parsedTrace, workerThreads, request) {
167
167
  priority: request.args.data.priority,
168
168
  frameId: request.args.data.frame,
169
169
  fromWorker,
170
+ serverResponseTime: request.args.data.lrServerResponseTime ?? undefined,
170
171
  // Set later.
171
172
  redirects: undefined,
172
173
  redirectSource: undefined,
@@ -70,8 +70,11 @@ export class Model extends EventTarget {
70
70
  * });
71
71
  * void this.traceModel.parse(events);
72
72
  **/
73
- async parse(traceEvents, config) {
74
- const metadata = config?.metadata || {};
73
+ async parse(traceEvents, config = {}) {
74
+ if (config.showAllEvents === undefined) {
75
+ config.showAllEvents = this.#config.showAllEvents;
76
+ }
77
+ const metadata = config.metadata || {};
75
78
  // During parsing, periodically update any listeners on each processors'
76
79
  // progress (if they have any updates).
77
80
  const onTraceUpdate = (event) => {
@@ -84,7 +87,7 @@ export class Model extends EventTarget {
84
87
  try {
85
88
  // Wait for all outstanding promises before finishing the async execution,
86
89
  // but perform all tasks in parallel.
87
- await this.#processor.parse(traceEvents, config ?? {});
90
+ await this.#processor.parse(traceEvents, config);
88
91
  if (!this.#processor.data) {
89
92
  throw new Error('processor did not parse trace');
90
93
  }
@@ -351,9 +351,12 @@ export class TraceProcessor extends EventTarget {
351
351
  }
352
352
  #computeInsightSet(data, context) {
353
353
  const logger = context.options.logger;
354
+ if (!this.#insights) {
355
+ this.#insights = new Map();
356
+ }
354
357
  let id, urlString, navigation;
355
358
  if (context.navigation) {
356
- id = context.navigationId;
359
+ id = `NAVIGATION_${this.#insights.size}`;
357
360
  urlString = data.Meta.finalDisplayUrlByNavigationId.get(context.navigationId) ?? data.Meta.mainFrameURL;
358
361
  navigation = context.navigation;
359
362
  }
@@ -421,9 +424,6 @@ export class TraceProcessor extends EventTarget {
421
424
  bounds: context.bounds,
422
425
  model: insightSetModel,
423
426
  };
424
- if (!this.#insights) {
425
- this.#insights = new Map();
426
- }
427
427
  this.#insights.set(insightSet.id, insightSet);
428
428
  this.sortInsightSet(insightSet, context.options.metadata ?? null);
429
429
  }
@@ -428,7 +428,7 @@ const UIStrings = {
428
428
  /**
429
429
  * @description Event category in the Performance panel for time spent to perform Garbage Collection for C++: https://chromium.googlesource.com/v8/v8/+/main/include/cppgc/README.md
430
430
  */
431
- cppGc: 'CPP GC',
431
+ cppGc: 'C++ GC',
432
432
  /**
433
433
  * @description Event category in the Performance panel for time spent to perform encryption
434
434
  */
@@ -326,6 +326,7 @@ export class BottomUpRootNode extends Node {
326
326
  const root = this;
327
327
  const startTime = this.startTime;
328
328
  const endTime = this.endTime;
329
+ const idStack = [];
329
330
  const nodeById = new Map();
330
331
  const selfTimeStack = [endTime - startTime];
331
332
  const firstNodeStack = [];
@@ -383,6 +384,11 @@ export class BottomUpRootNode extends Node {
383
384
  if (forceGroupIdCallback && eventGroupIdCallback) {
384
385
  id = `${id}-${eventGroupIdCallback(e)}`;
385
386
  }
387
+ idStack.push(id);
388
+ // For an event 'X' that contains another event 'X' (resolving to the same node
389
+ // id), we need to measure `totalTime` from the start of the outermost 'X' to
390
+ // its corresponding end. This logic ensures we don't double-count the duration
391
+ // of the inner event.
386
392
  const noNodeOnStack = !totalTimeById.has(id);
387
393
  if (noNodeOnStack) {
388
394
  totalTimeById.set(id, duration);
@@ -390,9 +396,9 @@ export class BottomUpRootNode extends Node {
390
396
  firstNodeStack.push(noNodeOnStack);
391
397
  }
392
398
  function onEndEvent(event) {
393
- let id = generateEventID(event);
394
- if (forceGroupIdCallback && eventGroupIdCallback) {
395
- id = `${id}-${eventGroupIdCallback(event)}`;
399
+ const id = idStack.pop();
400
+ if (!id) {
401
+ return;
396
402
  }
397
403
  let node = nodeById.get(id);
398
404
  if (!node) {
@@ -407,6 +413,7 @@ export class BottomUpRootNode extends Node {
407
413
  node.totalTime += totalTimeById.get(id) || 0;
408
414
  totalTimeById.delete(id);
409
415
  }
416
+ // TODO: this may be wrong. See the skipped test in TraceTree.test.ts.
410
417
  if (firstNodeStack.length) {
411
418
  node.setHasChildren(true);
412
419
  }
@@ -573,7 +580,7 @@ export function eventStackFrame(event) {
573
580
  }
574
581
  return { ...topFrame, scriptId: String(topFrame.scriptId) };
575
582
  }
576
- // TODO(paulirish): rename to generateNodeId
583
+ /** TODO(paulirish): rename to generateNodeId **/
577
584
  export function generateEventID(event) {
578
585
  if (Types.Events.isProfileCall(event)) {
579
586
  const name = SamplesIntegrator.isNativeRuntimeFrame(event.callFrame) ?
@@ -410,7 +410,7 @@ export class PendingFrame {
410
410
  this.triggerTime = triggerTime;
411
411
  }
412
412
  }
413
- // The parameters of an impl-side BeginFrame.
413
+ /** The parameters of an impl-side BeginFrame. **/
414
414
  class BeginFrameInfo {
415
415
  seqId;
416
416
  startTime;
@@ -423,10 +423,12 @@ class BeginFrameInfo {
423
423
  this.isPartial = isPartial;
424
424
  }
425
425
  }
426
- // A queue of BeginFrames pending visualization.
427
- // BeginFrames are added into this queue as they occur; later when their
428
- // corresponding DrawFrames occur (or lack thereof), the BeginFrames are removed
429
- // from the queue and their timestamps are used for visualization.
426
+ /**
427
+ * A queue of BeginFrames pending visualization.
428
+ * BeginFrames are added into this queue as they occur; later when their
429
+ * corresponding DrawFrames occur (or lack thereof), the BeginFrames are removed
430
+ * from the queue and their timestamps are used for visualization.
431
+ **/
430
432
  export class TimelineFrameBeginFrameQueue {
431
433
  queueFrames = [];
432
434
  // Maps frameSeqId to BeginFrameInfo.
@@ -6,11 +6,15 @@ import * as Helpers from '../helpers/helpers.js';
6
6
  import * as Types from '../types/types.js';
7
7
  import { data as metaHandlerData } from './MetaHandler.js';
8
8
  import { data as screenshotsHandlerData } from './ScreenshotsHandler.js';
9
- // This represents the maximum #time we will allow a cluster to go before we
10
- // reset it.
9
+ /**
10
+ * This represents the maximum #time we will allow a cluster to go before we
11
+ * reset it.
12
+ **/
11
13
  export const MAX_CLUSTER_DURATION = Helpers.Timing.milliToMicro(Types.Timing.Milli(5000));
12
- // This represents the maximum #time we will allow between layout shift events
13
- // before considering it to be the start of a new cluster.
14
+ /**
15
+ * This represents the maximum #time we will allow between layout shift events
16
+ * before considering it to be the start of a new cluster.
17
+ **/
14
18
  export const MAX_SHIFT_TIME_DELTA = Helpers.Timing.milliToMicro(Types.Timing.Milli(1000));
15
19
  // Layout shifts are reported globally to the developer, irrespective of which
16
20
  // frame they originated in. However, each process does have its own individual
@@ -4,6 +4,7 @@
4
4
  import * as Platform from '../../../core/platform/platform.js';
5
5
  import * as Helpers from '../helpers/helpers.js';
6
6
  import * as Types from '../types/types.js';
7
+ let config;
7
8
  // We track the renderer processes we see in each frame on the way through the trace.
8
9
  let rendererProcessesByFrameId = new Map();
9
10
  // We will often want to key data by Frame IDs, and commonly we'll care most
@@ -299,7 +300,8 @@ export function handleEvent(event) {
299
300
  return;
300
301
  }
301
302
  }
302
- export async function finalize() {
303
+ export async function finalize(options) {
304
+ config = { showAllEvents: Boolean(options?.showAllEvents) };
303
305
  // We try to set the minimum time by finding the event with the smallest
304
306
  // timestamp. However, if we also got a timestamp from the
305
307
  // TracingStartedInBrowser event, we should always use that.
@@ -378,6 +380,7 @@ export async function finalize() {
378
380
  }
379
381
  export function data() {
380
382
  return {
383
+ config,
381
384
  traceBounds,
382
385
  browserProcessId,
383
386
  browserThreadId,