chrome-devtools-frontend 1.0.1709383 → 1.0.1713292

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 (165) hide show
  1. package/.agents/skills/code-review/SKILL.md +16 -12
  2. package/AUTHORS +2 -0
  3. package/DIR_METADATA +36 -0
  4. package/front_end/core/common/ParsedURL.ts +20 -19
  5. package/front_end/core/sdk/CSSStyleSheetHeader.ts +2 -2
  6. package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +1 -1
  7. package/front_end/core/sdk/DOMModel.ts +6 -4
  8. package/front_end/core/sdk/NetworkRequest.ts +11 -11
  9. package/front_end/core/sdk/PageFunctions.ts +1 -1
  10. package/front_end/core/sdk/ResourceTreeModel.ts +17 -1
  11. package/front_end/core/sdk/SourceMap.ts +6 -0
  12. package/front_end/core/sdk/SourceMapScopesInfo.ts +25 -0
  13. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +7 -7
  14. package/front_end/generated/InspectorBackendCommands.ts +2 -1
  15. package/front_end/generated/protocol-mapping.d.ts +7 -0
  16. package/front_end/generated/protocol-proxy-api.d.ts +5 -0
  17. package/front_end/generated/protocol.ts +18 -0
  18. package/front_end/models/ai_assistance/agents/AiAgent.ts +7 -4
  19. package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -0
  20. package/front_end/models/ai_assistance/contexts/LighthouseContext.snapshot.txt +6 -1
  21. package/front_end/models/ai_assistance/contexts/LighthouseContext.ts +3 -2
  22. package/front_end/models/ai_assistance/data_formatters/LighthouseFormatter.snapshot.txt +11 -0
  23. package/front_end/models/ai_assistance/data_formatters/LighthouseFormatter.ts +47 -19
  24. package/front_end/models/ai_assistance/skills/accessibility.md +1 -0
  25. package/front_end/models/ai_assistance/skills/lighthouse.md +1 -0
  26. package/front_end/models/ai_assistance/skills/styling.md +1 -0
  27. package/front_end/models/ai_assistance/tools/ListSources.ts +11 -5
  28. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +5 -1
  29. package/front_end/models/bindings/SourceMapStepping.ts +103 -4
  30. package/front_end/models/bindings/StylesSourceMapping.ts +3 -0
  31. package/front_end/models/emulation/DeviceModeModel.ts +9 -4
  32. package/front_end/models/har/HARFormat.ts +2 -7
  33. package/front_end/models/issues_manager/Issue.ts +1 -1
  34. package/front_end/models/javascript_metadata/NativeFunctions.ts +66 -54
  35. package/front_end/models/persistence/Automapping.ts +8 -3
  36. package/front_end/models/trace/Processor.ts +9 -3
  37. package/front_end/models/trace/extras/TraceTree.ts +1 -1
  38. package/front_end/models/trace/insights/CLSCulprits.ts +1 -1
  39. package/front_end/models/trace/lantern/graph/PageDependencyGraph.ts +1 -1
  40. package/front_end/models/trace/lantern/metrics/TotalBlockingTime.ts +1 -1
  41. package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingListView.ts +40 -8
  42. package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +108 -2
  43. package/front_end/panels/accessibility/AccessibilityNodeView.ts +2 -2
  44. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +1 -1
  45. package/front_end/panels/ai_assistance/components/DisabledWidget.ts +1 -1
  46. package/front_end/panels/ai_assistance/components/OptInChangeDialog.ts +1 -1
  47. package/front_end/panels/application/BounceTrackingMitigationsTreeElement.ts +1 -1
  48. package/front_end/panels/application/CookieItemsView.ts +10 -10
  49. package/front_end/panels/application/DOMStorageItemsView.ts +7 -8
  50. package/front_end/panels/application/ExtensionStorageItemsView.ts +4 -5
  51. package/front_end/panels/application/IndexedDBViews.ts +29 -31
  52. package/front_end/panels/application/KeyValueStorageItemsView.ts +5 -5
  53. package/front_end/panels/application/ServiceWorkerCacheTreeElement.ts +6 -6
  54. package/front_end/panels/application/ServiceWorkerCacheViews.ts +17 -17
  55. package/front_end/panels/application/ServiceWorkerUpdateCycleView.ts +3 -2
  56. package/front_end/panels/application/StorageBucketsTreeElement.ts +3 -10
  57. package/front_end/panels/application/StorageItemsToolbar.ts +6 -6
  58. package/front_end/panels/application/StorageView.ts +36 -34
  59. package/front_end/panels/application/TrustTokensTreeElement.ts +1 -2
  60. package/front_end/panels/application/WebMCPView.ts +6 -2
  61. package/front_end/panels/application/components/AdsView.ts +28 -29
  62. package/front_end/panels/application/components/BackForwardCacheStrings.ts +188 -204
  63. package/front_end/panels/application/components/BackForwardCacheView.ts +33 -45
  64. package/front_end/panels/application/components/BounceTrackingMitigationsView.ts +10 -12
  65. package/front_end/panels/application/components/CrashReportContextGrid.ts +4 -4
  66. package/front_end/panels/application/components/EndpointsGrid.ts +3 -5
  67. package/front_end/panels/application/components/PermissionsPolicySection.ts +12 -15
  68. package/front_end/panels/application/components/ProtocolHandlersView.ts +9 -9
  69. package/front_end/panels/application/components/ReportsGrid.ts +7 -12
  70. package/front_end/panels/application/components/StorageMetadataView.ts +22 -24
  71. package/front_end/panels/application/components/TrustTokensView.ts +8 -10
  72. package/front_end/panels/application/preloading/components/PreloadingString.ts +28 -29
  73. package/front_end/panels/application/serviceWorkerUpdateCycleView.css +1 -1
  74. package/front_end/panels/comments/CommentsPane.ts +14 -7
  75. package/front_end/panels/comments/commentsPane.css +6 -20
  76. package/front_end/panels/common/CPUThrottlingOption.ts +1 -1
  77. package/front_end/panels/common/CommentThreadWidget.ts +0 -17
  78. package/front_end/panels/common/CommentsOverlayWidget.ts +0 -4
  79. package/front_end/panels/common/ExtensionServer.ts +52 -50
  80. package/front_end/panels/common/commentThreadWidget.css +0 -4
  81. package/front_end/panels/console/ConsoleInsightTeaser.ts +1 -1
  82. package/front_end/panels/console/ConsoleViewMessage.ts +1 -0
  83. package/front_end/panels/console/ConsoleViewport.ts +35 -4
  84. package/front_end/panels/coverage/CoverageListView.ts +2 -2
  85. package/front_end/panels/coverage/CoverageView.ts +2 -2
  86. package/front_end/panels/elements/CSSRuleValidator.ts +1 -1
  87. package/front_end/panels/elements/DOMPath.ts +7 -1
  88. package/front_end/panels/elements/DOMTreeWidget.ts +19 -22
  89. package/front_end/panels/elements/ElementsPanel.ts +3 -3
  90. package/front_end/panels/elements/StylePropertyTreeElement.ts +2 -2
  91. package/front_end/panels/elements/StylePropertyUtils.ts +11 -3
  92. package/front_end/panels/elements/components/CSSVariableValueView.ts +1 -1
  93. package/front_end/panels/elements/elements-meta.ts +3 -3
  94. package/front_end/panels/emulation/DeviceModeView.ts +1 -1
  95. package/front_end/panels/explain/components/ConsoleInsight.ts +1 -1
  96. package/front_end/panels/issues/AffectedSharedArrayBufferIssueDetailsView.ts +2 -3
  97. package/front_end/panels/layer_viewer/Layers3DView.ts +7 -8
  98. package/front_end/panels/layer_viewer/layer_viewer-meta.ts +1 -5
  99. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +1 -1
  100. package/front_end/panels/network/FetchHeaderCommenting.ts +1 -1
  101. package/front_end/panels/network/NetworkDataGridNode.ts +5 -2
  102. package/front_end/panels/network/NetworkLogView.ts +8 -13
  103. package/front_end/panels/network/RequestConditionsDrawer.ts +2 -2
  104. package/front_end/panels/network/RequestCookiesView.ts +1 -1
  105. package/front_end/panels/network/RequestDeviceBoundSessionsView.ts +3 -3
  106. package/front_end/panels/network/components/RequestHeaderSection.ts +1 -1
  107. package/front_end/panels/network/components/ResponseHeaderSection.ts +1 -1
  108. package/front_end/panels/recorder/RecordingView.ts +1 -1
  109. package/front_end/panels/security/SecurityPanel.ts +27 -20
  110. package/front_end/panels/sensors/LocationsSettingsTab.ts +4 -9
  111. package/front_end/panels/sensors/SensorsView.ts +2 -2
  112. package/front_end/panels/sensors/sensors-meta.ts +0 -83
  113. package/front_end/panels/settings/AISettingsTab.ts +5 -5
  114. package/front_end/panels/settings/BackendLinkingSettingsTab.ts +1 -1
  115. package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +4 -4
  116. package/front_end/panels/sources/BreakpointEditDialog.ts +1 -1
  117. package/front_end/panels/sources/DebuggerPlugin.ts +3 -3
  118. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +4 -1
  119. package/front_end/panels/sources/NavigatorView.ts +9 -6
  120. package/front_end/panels/sources/PersistenceActions.ts +1 -1
  121. package/front_end/panels/sources/SourcesPanel.ts +26 -9
  122. package/front_end/panels/sources/SourcesSearchScope.ts +4 -1
  123. package/front_end/panels/sources/SourcesView.ts +79 -86
  124. package/front_end/panels/sources/UISourceCodeFrame.ts +69 -64
  125. package/front_end/panels/sources/sources-meta.ts +26 -63
  126. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +4 -1
  127. package/front_end/panels/timeline/CountersGraph.ts +32 -13
  128. package/front_end/panels/timeline/ModificationsManager.ts +3 -1
  129. package/front_end/panels/timeline/ThreadAppender.ts +4 -1
  130. package/front_end/panels/timeline/TimelineController.ts +9 -2
  131. package/front_end/panels/timeline/TimelineDetailsView.ts +4 -1
  132. package/front_end/panels/timeline/TimelineEventOverview.ts +3 -5
  133. package/front_end/panels/timeline/TimelineFlameChartView.ts +1 -4
  134. package/front_end/panels/timeline/TimelinePanel.ts +39 -21
  135. package/front_end/panels/timeline/TimelineTreeView.ts +0 -6
  136. package/front_end/panels/timeline/TimelineUIUtils.ts +6 -4
  137. package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +3 -1
  138. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +3 -1
  139. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +4 -4
  140. package/front_end/panels/timeline/overlays/components/TimeRangeOverlay.ts +147 -97
  141. package/front_end/panels/timeline/timeline-meta.ts +33 -105
  142. package/front_end/third_party/chromium/README.chromium +1 -1
  143. package/front_end/ui/components/lists/list.css +1 -2
  144. package/front_end/ui/components/suggestion_input/SuggestionInput.ts +9 -5
  145. package/front_end/ui/components/text_editor/AiCodeCompletionDisclaimer.ts +3 -3
  146. package/front_end/ui/components/text_editor/AiCodeCompletionTeaser.ts +1 -1
  147. package/front_end/ui/components/text_editor/AiCodeGenerationTeaser.ts +3 -3
  148. package/front_end/ui/components/text_editor/AiCodeGenerationUpgradeDialog.ts +1 -1
  149. package/front_end/ui/components/text_editor/TextEditor.ts +18 -6
  150. package/front_end/ui/components/text_editor/config.ts +3 -3
  151. package/front_end/ui/legacy/TabbedPane.ts +17 -1
  152. package/front_end/ui/legacy/TextPrompt.ts +80 -19
  153. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +1 -0
  154. package/front_end/ui/legacy/components/perf_ui/ChartViewport.ts +4 -1
  155. package/front_end/ui/legacy/components/perf_ui/perf_ui-meta.ts +2 -5
  156. package/front_end/ui/legacy/components/source_frame/ImageView.ts +11 -4
  157. package/front_end/ui/legacy/components/utils/Linkifier.ts +29 -17
  158. package/front_end/ui/legacy/listWidget.css +1 -6
  159. package/front_end/ui/settings/EmulationSettings.ts +91 -0
  160. package/front_end/ui/settings/LayerViewerSettings.ts +14 -0
  161. package/front_end/ui/settings/SourcesSettings.ts +58 -0
  162. package/front_end/ui/settings/TimelineSettings.ts +131 -0
  163. package/front_end/ui/settings/settings.ts +4 -0
  164. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
  165. package/package.json +1 -1
@@ -36,17 +36,37 @@ export class LighthouseFormatter {
36
36
  }
37
37
 
38
38
  /**
39
- * Formats a Lighthouse report for an AI Agent. If categoryId is 'all', includes
40
- * the overall summary followed by each category's audits. Otherwise, returns audits
41
- * for the specified category.
39
+ * Returns the title and score of every failing audit (score < 90), grouped by category.
40
+ * Descriptions and details tables are left out to keep the prompt small. Each category
41
+ * heading includes its category ID so the agent can request the full audit details.
42
+ */
43
+ failingAuditsSummary(report: LHModel.ReporterTypes.ReportJSON): string {
44
+ const lines: string[] = [];
45
+ lines.push('## Failing audits');
46
+ for (const [categoryId, category] of Object.entries(report.categories)) {
47
+ lines.push('');
48
+ lines.push(`### ${category.title} (categoryId: "${categoryId}")`);
49
+ const failingAudits = this.#findFailingAudits(report, category);
50
+ if (failingAudits.length === 0) {
51
+ lines.push('- No failing audits.');
52
+ continue;
53
+ }
54
+ for (const audit of failingAudits) {
55
+ lines.push(`- ${audit.title}: ${this.#formatScore(audit.score)}`);
56
+ }
57
+ }
58
+ return lines.join('\n');
59
+ }
60
+
61
+ /**
62
+ * Formats a Lighthouse report for an AI Agent. If categoryId is 'all', returns
63
+ * each category's audits. Otherwise, returns audits for the specified category.
64
+ * The output does not include the report summary, because the conversation
65
+ * context already sends it.
42
66
  */
43
67
  formatReport(report: LHModel.ReporterTypes.ReportJSON, categoryId: LighthouseCategoryArg): string {
44
68
  if (categoryId === 'all') {
45
- const sections: string[] = [this.summary(report)];
46
- for (const category of Object.values(report.categories)) {
47
- sections.push(this.audits(report, category));
48
- }
49
- return sections.join('\n\n');
69
+ return Object.values(report.categories).map(category => this.audits(report, category)).join('\n\n');
50
70
  }
51
71
  return this.audits(report, categoryId);
52
72
  }
@@ -69,10 +89,7 @@ export class LighthouseFormatter {
69
89
  }
70
90
  lines.push('');
71
91
 
72
- const failingAudits = category.auditRefs.filter(ref => {
73
- const audit = report.audits[ref.id];
74
- return audit && audit.score !== null && audit.score < 0.9;
75
- });
92
+ const failingAudits = this.#findFailingAudits(report, category);
76
93
 
77
94
  if (failingAudits.length === 0) {
78
95
  lines.push('All audits in this category passed (score >= 90).');
@@ -80,13 +97,8 @@ export class LighthouseFormatter {
80
97
  }
81
98
 
82
99
  lines.push('The following audits in this category have a score below 90 and may need attention:');
83
- for (const ref of failingAudits) {
84
- const audit = report.audits[ref.id];
85
- if (!audit) {
86
- continue;
87
- }
88
- const score = audit.score !== null ? Math.round(audit.score * 100) : 'n/a';
89
- let line = `- **${audit.title}**: ${score}`;
100
+ for (const audit of failingAudits) {
101
+ let line = `- **${audit.title}**: ${this.#formatScore(audit.score)}`;
90
102
  if (audit.displayValue) {
91
103
  line += ` (${audit.displayValue})`;
92
104
  }
@@ -104,6 +116,22 @@ export class LighthouseFormatter {
104
116
  return lines.join('\n');
105
117
  }
106
118
 
119
+ /**
120
+ * Returns the audits in a category that scored below 90, in the category's order.
121
+ * Audits without a score (such as informative or manual audits) cannot fail, so they
122
+ * are excluded.
123
+ */
124
+ #findFailingAudits(report: LHModel.ReporterTypes.ReportJSON, category: LHModel.ReporterTypes.CategoryJSON):
125
+ Array<LHModel.ReporterTypes.AuditResultJSON&{score: number}> {
126
+ return category.auditRefs.map(ref => report.audits[ref.id])
127
+ .filter((audit): audit is LHModel.ReporterTypes.AuditResultJSON&{score: number} =>
128
+ Boolean(audit) && audit.score !== null && audit.score < 0.9);
129
+ }
130
+
131
+ #formatScore(score: number): number {
132
+ return Math.round(score * 100);
133
+ }
134
+
107
135
  #formatDetails(details: LHModel.ReporterTypes.DetailsJSON): string {
108
136
  switch (details.type) {
109
137
  case 'table': {
@@ -19,6 +19,7 @@ You are an expert accessibility debugging assistant.
19
19
  - Use `getStyles` on the backend node ID to inspect layout, color contrast, or font properties.
20
20
 
21
21
  2. **Lighthouse Accessibility Audits (`getLighthouseAudits` & `runLighthouse`)**:
22
+ - The Lighthouse report context contains only category scores and failing audit titles. To answer questions about failing accessibility audits, you must first call `getLighthouseAudits` with `categoryId: 'accessibility'` to fetch the full details. Never reply using only the initial summary.
22
23
  - If the user asks for a Lighthouse audit or report (such as recording a report or checking accessibility scores), or if audits are needed:
23
24
  - If an active Lighthouse report context already exists and no fresh audit is requested, query it via `getLighthouseAudits` with `categoryId: 'accessibility'`.
24
25
  - If no active report exists or a fresh audit is requested, use `runLighthouse` with `categoryId: 'accessibility'`:
@@ -12,6 +12,7 @@ Your role is to evaluate websites using Lighthouse audits across performance, ac
12
12
  # Tools & Workflow
13
13
 
14
14
  1. **Lighthouse Audits (`runLighthouse` & `getLighthouseAudits`)**:
15
+ - The Lighthouse report context contains only category scores and failing audit titles. To answer questions about failing audits or how to improve a score, you must first call `getLighthouseAudits` for the relevant category to fetch the full details. Never reply using only the initial summary.
15
16
  - If an active Lighthouse report context already exists and no fresh audit is requested:
16
17
  - To inspect the entire report or multiple categories, call `getLighthouseAudits` with `categoryId: 'all'`.
17
18
  - For a specific category, call `getLighthouseAudits` with the corresponding category ID (e.g. `'performance'`, `'accessibility'`, `'best-practices'`, `'seo'`).
@@ -39,3 +39,4 @@ The user selected a DOM element in DevTools and asks a query about the element o
39
39
 
40
40
  * Meticulously investigate all potential causes for the observed behavior before concluding. Inspect parents, siblings, children, and overlapping elements where relevant.
41
41
  * After applying a style fix, ask the user to verify if the visual change resolved their issue.
42
+ * If the target element is in a cross-origin iframe, stop and ask the user to select it in the Elements panel and start a new chat with that context.
@@ -43,10 +43,13 @@ export class ListSourcesTool implements
43
43
  static lastSourceId = 0;
44
44
  static uiSourceCodeId: WeakMap<Workspace.UISourceCode.UISourceCode, number> =
45
45
  new WeakMap<Workspace.UISourceCode.UISourceCode, number>();
46
+ static idToUiSourceCode: Map<number, Workspace.UISourceCode.UISourceCode> =
47
+ new Map<number, Workspace.UISourceCode.UISourceCode>();
46
48
 
47
49
  static reset(): void {
48
50
  ListSourcesTool.lastSourceId = 0;
49
51
  ListSourcesTool.uiSourceCodeId = new WeakMap();
52
+ ListSourcesTool.idToUiSourceCode = new Map();
50
53
  }
51
54
 
52
55
  static getUISourceCodes(
@@ -78,7 +81,9 @@ export class ListSourcesTool implements
78
81
  if (!uiSourceCodes.get(url) || uiSourceCode.contentType().isFromSourceMap()) {
79
82
  uiSourceCodes.set(url, uiSourceCode);
80
83
  if (!ListSourcesTool.uiSourceCodeId.has(uiSourceCode)) {
81
- ListSourcesTool.uiSourceCodeId.set(uiSourceCode, ++ListSourcesTool.lastSourceId);
84
+ const id = ++ListSourcesTool.lastSourceId;
85
+ ListSourcesTool.uiSourceCodeId.set(uiSourceCode, id);
86
+ ListSourcesTool.idToUiSourceCode.set(id, uiSourceCode);
82
87
  }
83
88
  }
84
89
  }
@@ -90,14 +95,15 @@ export class ListSourcesTool implements
90
95
  static getSourceById(
91
96
  id: number,
92
97
  originLock: OriginLockState,
93
- // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
94
- workspace: Workspace.Workspace.WorkspaceImpl = Workspace.Workspace.WorkspaceImpl.instance(),
95
98
  ): Workspace.UISourceCode.UISourceCode|undefined {
96
99
  if (!Number.isInteger(id) || id <= 0) {
97
100
  return undefined;
98
101
  }
99
- return ListSourcesTool.getUISourceCodes(originLock, workspace)
100
- .find(file => ListSourcesTool.uiSourceCodeId.get(file) === id);
102
+ const file = ListSourcesTool.idToUiSourceCode.get(id);
103
+ if (!file || !isOriginAllowedByLock(originLock, file.securityOrigin())) {
104
+ return undefined;
105
+ }
106
+ return file;
101
107
  }
102
108
 
103
109
  readonly parameters: Host.AidaClient.FunctionObjectParam<never> = {
@@ -144,6 +144,10 @@ export class DebuggerWorkspaceBinding implements SDK.TargetManager.SDKModelObser
144
144
  }
145
145
  ranges = compilerMapping.getLocationRangesForSameSourceLocation(rawLocation);
146
146
  ranges = ranges.filter(range => contained(rawLocation, range));
147
+ if (mode === SDK.DebuggerModel.StepMode.STEP_OVER) {
148
+ // Step over functions inlined by the compiler (from encoded source map scopes).
149
+ ranges = ranges.concat(SourceMapStepping.inlinedCalleeRanges(callFrame));
150
+ }
147
151
  return ranges;
148
152
  }
149
153
 
@@ -516,7 +520,7 @@ export class DebuggerWorkspaceBinding implements SDK.TargetManager.SDKModelObser
516
520
  null :
517
521
  await this.computeAutoStep(SDK.DebuggerModel.StepMode.STEP_OVER, callFrames);
518
522
  }
519
- return null;
523
+ return await SourceMapStepping.nextAutoStep(debuggerPausedDetails, context, this.computeAutoStep.bind(this));
520
524
  }
521
525
 
522
526
  async #shouldPauseInWasm(debuggerPausedDetails: SDK.DebuggerModel.DebuggerPausedDetails,
@@ -5,11 +5,17 @@
5
5
  /**
6
6
  * @file Stepping through code with encoded source map scopes: inlined functions, outlined functions and unmapped code.
7
7
  *
8
- * Mirrors the Wasm auto-stepping: user steps get a skip list (see `DebuggerWorkspaceBinding.computeAutoStep`).
8
+ * Mirrors the Wasm auto-stepping: user steps get a skip list (see `DebuggerWorkspaceBinding.computeAutoStep`), and
9
+ * pauses that don't correspond to a "logical" step are continued automatically ({@link nextAutoStep}).
10
+ *
11
+ * Outlined code is code of an authored function that the compiler moved into a separate generated function marked as
12
+ * "hidden". A run of outlined frames on top of the stack is one logical frame together with the frame below them (the
13
+ * "owner"), see {@link logicalDepth}.
9
14
  */
10
15
 
11
16
  import * as Root from '../../core/root/root.js';
12
- import type * as SDK from '../../core/sdk/sdk.js';
17
+ import * as SDK from '../../core/sdk/sdk.js';
18
+ import * as Protocol from '../../generated/protocol.js';
13
19
 
14
20
  interface ScopedPosition {
15
21
  sourceMap: SDK.SourceMap.SourceMap;
@@ -19,14 +25,17 @@ interface ScopedPosition {
19
25
  column: number;
20
26
  }
21
27
 
22
- /** @returns the script-relative position of {@link frame}, if it's in a script with encoded source map scopes. */
28
+ /**
29
+ * @returns the script-relative position of {@link frame}, if it's in a script with encoded source map scopes.
30
+ * Scopes without any mappings are ignored: every position would count as unmapped (see {@link isUnmapped}).
31
+ */
23
32
  function scopedPosition(frame: SDK.DebuggerModel.CallFrame): ScopedPosition|null {
24
33
  if (!Root.Runtime.hostConfig.devToolsSourceMapScopesInSourcesPanel?.enabled) {
25
34
  return null;
26
35
  }
27
36
  const script = frame.script;
28
37
  const sourceMap = script.sourceMap();
29
- if (!sourceMap?.hasEncodedScopeInfo()) {
38
+ if (!sourceMap?.hasEncodedScopeInfo() || sourceMap.mappings().length === 0) {
30
39
  return null;
31
40
  }
32
41
  const {lineNumber, columnNumber} = script.rawLocationToRelativeLocation(frame.location());
@@ -42,9 +51,99 @@ function toLocationRanges({script}: ScopedPosition,
42
51
  return ranges.map(({start, end}) => ({start: toLocation(start), end: toLocation(end)}));
43
52
  }
44
53
 
54
+ export function isScopedFrame(frame: SDK.DebuggerModel.CallFrame): boolean {
55
+ return scopedPosition(frame) !== null;
56
+ }
57
+
58
+ /** @returns the number of leading frames that are outlined parts of the (logical) frame below them. */
59
+ function outlinedPrefixLength(callFrames: readonly SDK.DebuggerModel.CallFrame[]): number {
60
+ let length = 0;
61
+ for (const frame of callFrames) {
62
+ const position = scopedPosition(frame);
63
+ if (!position ||
64
+ position.sourceMap.translateRawFrame(position.line, position.column)?.kind !==
65
+ SDK.SourceMapScopesInfo.GeneratedFrameKind.OUTLINED) {
66
+ break;
67
+ }
68
+ ++length;
69
+ }
70
+ return length;
71
+ }
72
+
73
+ /**
74
+ * @returns the stack depth that doesn't count outlined frames on top of the stack. Entering or leaving an outlined
75
+ * part of a function doesn't change it, while calling a function increases it.
76
+ */
77
+ export function logicalDepth(callFrames: readonly SDK.DebuggerModel.CallFrame[]): number {
78
+ return callFrames.length - outlinedPrefixLength(callFrames);
79
+ }
80
+
81
+ /** @returns true iff {@link frame} has encoded scopes, and its position is not mapped to any source. */
82
+ export function isUnmapped(frame: SDK.DebuggerModel.CallFrame): boolean {
83
+ const position = scopedPosition(frame);
84
+ return position !== null && position.sourceMap.findEntry(position.line, position.column)?.sourceURL === undefined;
85
+ }
86
+
87
+ /** @returns true iff both frames have encoded scopes and are mapped to the same original location. */
88
+ export function isSameOriginalLocation(a: SDK.DebuggerModel.CallFrame, b: SDK.DebuggerModel.CallFrame): boolean {
89
+ const entry = (frame: SDK.DebuggerModel.CallFrame): SDK.SourceMap.SourceMapEntry|null => {
90
+ const position = scopedPosition(frame);
91
+ return position?.sourceMap.findEntry(position.line, position.column) ?? null;
92
+ };
93
+ const entryA = entry(a);
94
+ const entryB = entry(b);
95
+ return entryA?.sourceURL !== undefined && entryA.sourceURL === entryB?.sourceURL &&
96
+ entryA.sourceLineNumber === entryB.sourceLineNumber && entryA.sourceColumnNumber === entryB.sourceColumnNumber;
97
+ }
98
+
45
99
  /** @returns the body of the innermost inlined function that {@link frame} is paused in (empty if none). */
46
100
  export function inlinedFunctionRanges(frame: SDK.DebuggerModel.CallFrame): SDK.DebuggerModel.LocationRange[] {
47
101
  const position = scopedPosition(frame);
48
102
  const range = position?.sourceMap.inlinedFunctionRange(position.line, position.column);
49
103
  return position && range ? toLocationRanges(position, [range]) : [];
50
104
  }
105
+
106
+ /** @returns the bodies of the functions inlined into the logical function that {@link frame} is paused in. */
107
+ export function inlinedCalleeRanges(frame: SDK.DebuggerModel.CallFrame): SDK.DebuggerModel.LocationRange[] {
108
+ const position = scopedPosition(frame);
109
+ return position ? toLocationRanges(position, position.sourceMap.inlinedCalleeRanges(position.line, position.column)) :
110
+ [];
111
+ }
112
+
113
+ /**
114
+ * Decides whether the pause {@link details} completes the user's step {@link context}.
115
+ *
116
+ * @returns null to present the pause, or the step to issue instead.
117
+ */
118
+ export async function nextAutoStep(
119
+ details: SDK.DebuggerModel.DebuggerPausedDetails, context: SDK.DebuggerModel.StepContext|null,
120
+ computeAutoStep: SDK.DebuggerModel.ComputeAutoStepCallback): Promise<SDK.DebuggerModel.AutoStep|null> {
121
+ if (!context || details.reason !== Protocol.Debugger.PausedEventReason.Step) {
122
+ return null;
123
+ }
124
+ const frames = details.callFrames;
125
+ const start = context.callFrames;
126
+ if (frames.length === 0 || start.length === 0 || (!isScopedFrame(frames[0]) && !isScopedFrame(start[0]))) {
127
+ return null;
128
+ }
129
+
130
+ switch (context.mode) {
131
+ case SDK.DebuggerModel.StepMode.STEP_INTO:
132
+ return isUnmapped(frames[0]) ? await computeAutoStep(SDK.DebuggerModel.StepMode.STEP_INTO, frames) : null;
133
+
134
+ case SDK.DebuggerModel.StepMode.STEP_OVER: {
135
+ const startDepth = logicalDepth(start);
136
+ const depth = logicalDepth(frames);
137
+ if (isUnmapped(frames[0]) || (depth === startDepth && isSameOriginalLocation(frames[0], start[0]))) {
138
+ // Unmapped code, or still on the same original location (the skip list only covers the generated ranges that
139
+ // contain the start position): keep stepping over.
140
+ return await computeAutoStep(SDK.DebuggerModel.StepMode.STEP_OVER, frames);
141
+ }
142
+ return null;
143
+ }
144
+
145
+ case SDK.DebuggerModel.StepMode.STEP_OUT:
146
+ // Stepping into calls of the unmapped code would present a pause inside the callee, so continue as step over.
147
+ return isUnmapped(frames[0]) ? await computeAutoStep(SDK.DebuggerModel.StepMode.STEP_OVER, frames) : null;
148
+ }
149
+ }
@@ -191,6 +191,9 @@ export class StyleFile implements TextUtils.ContentProvider.ContentProvider {
191
191
 
192
192
  addHeader(header: SDK.CSSStyleSheetHeader.CSSStyleSheetHeader): void {
193
193
  this.headers.add(header);
194
+ if (header.hasSourceURL) {
195
+ NetworkProject.setSourceURLSynthesized(this.uiSourceCode);
196
+ }
194
197
  NetworkProject.addFrameAttribution(this.uiSourceCode, header.frameId);
195
198
  }
196
199
 
@@ -319,6 +319,8 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
319
319
  if (this.#type === Type.Device && this.#device && this.#mode) {
320
320
  const orientation = this.#device.orientationByName(this.#mode.orientation);
321
321
  this.#scaleSetting.set(this.calculateFitScale(orientation.width, orientation.height));
322
+ } else if (this.#type === Type.Responsive) {
323
+ this.#scaleSetting.set(this.calculateFitScale(this.#widthSetting.get(), this.#heightSetting.get()));
322
324
  }
323
325
  }
324
326
 
@@ -377,7 +379,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
377
379
  if (savedDevice) {
378
380
  this.#autoAdjustScaleSetting.set(savedDevice.autoAdjust);
379
381
  // An explicitly requested scale takes precedence over the saved one.
380
- if (scale === undefined && !savedDevice.autoAdjust) {
382
+ if (scale === undefined && !savedDevice.autoAdjust && savedDevice.scale > 0) {
381
383
  scale = savedDevice.scale;
382
384
  }
383
385
  } else {
@@ -404,10 +406,13 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
404
406
  const savedDevice = map['Responsive'];
405
407
  if (savedDevice) {
406
408
  this.#autoAdjustScaleSetting.set(savedDevice.autoAdjust);
407
- if (!savedDevice.autoAdjust) {
409
+ if (!savedDevice.autoAdjust && savedDevice.scale > 0) {
408
410
  this.#scaleSetting.set(savedDevice.scale);
411
+ } else if (this.#initialized) {
412
+ this.#updateFitScale();
409
413
  } else {
410
- this.#scaleSetting.set(this.calculateFitScale(this.#widthSetting.get(), this.#heightSetting.get()));
414
+ // Defer fit-scale calculation until setAvailableSize() initializes #preferredSize.
415
+ this.#autoFitScaleOnInitialize = true;
411
416
  }
412
417
  } else {
413
418
  this.#autoAdjustScaleSetting.set(true);
@@ -775,7 +780,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
775
780
  private calculateFitScale(screenWidth: number, screenHeight: number): number {
776
781
  let scale = Math.min(screenWidth ? this.#preferredSize.width / screenWidth : 1,
777
782
  screenHeight ? this.#preferredSize.height / screenHeight : 1);
778
- scale = Math.min(Math.floor(scale * 100), 100);
783
+ scale = Math.max(Math.min(Math.floor(scale * 100), 100), 1);
779
784
 
780
785
  let sharpScale = scale;
781
786
  while (sharpScale > scale * 0.7) {
@@ -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 * as Common from '../../core/common/common.js';
6
5
  import type * as Platform from '../../core/platform/platform.js';
7
6
  import * as SDK from '../../core/sdk/sdk.js';
8
7
  import type * as Protocol from '../../generated/protocol.js';
@@ -421,9 +420,7 @@ export class HARInitiator extends HARBase {
421
420
  super(data);
422
421
  this.type = (HARBase.optionalString(data['type']) ?? SDK.NetworkRequest.InitiatorType.OTHER) as
423
422
  Protocol.Network.InitiatorType;
424
- const url = HARBase.optionalString(data['url']);
425
- // Ignore privileged/non-web schemes in imported HARs.
426
- this.url = url && Common.ParsedURL.hasWebSafeScheme(url) ? url : undefined;
423
+ this.url = HARBase.optionalString(data['url']);
427
424
  this.lineNumber = HARBase.optionalNumber(data['lineNumber']);
428
425
  this.requestId = HARBase.optionalString(data['requestId']) as Protocol.Network.RequestId;
429
426
  if (data['stack']) {
@@ -480,9 +477,7 @@ export class HARCallFrame extends HARBase {
480
477
 
481
478
  this.functionName = HARBase.optionalString(data['functionName']) ?? '';
482
479
  this.scriptId = (HARBase.optionalString(data['scriptId']) ?? '') as Protocol.Runtime.ScriptId;
483
- const url = HARBase.optionalString(data['url']) ?? '';
484
- // Ignore privileged/non-web schemes in imported HARs.
485
- this.url = Common.ParsedURL.hasWebSafeScheme(url) ? url : '';
480
+ this.url = HARBase.optionalString(data['url']) ?? '';
486
481
  this.lineNumber = HARBase.optionalNumber(data['lineNumber']) ?? -1;
487
482
  this.columnNumber = HARBase.optionalNumber(data['columnNumber']) ?? -1;
488
483
  }
@@ -27,7 +27,7 @@ const UIStrings = {
27
27
  /**
28
28
  * @description A description for a kind of issue we display in the Issues tab.
29
29
  */
30
- pageErrorIssue: 'A page error issue: the page is not working correctly',
30
+ pageErrorIssue: 'A page error issue: the page isn’t working correctly',
31
31
  /**
32
32
  * @description A description for a kind of issue we display in the Issues tab.
33
33
  */
@@ -227,7 +227,7 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
227
227
  {
228
228
  name: "create",
229
229
  signatures: [["?options"]],
230
- receivers: ["CredentialsContainer","SemanticEmbedder"]
230
+ receivers: ["CredentialsContainer","DecisionModel","SemanticEmbedder"]
231
231
  },
232
232
  {
233
233
  name: "defineProperty",
@@ -3859,6 +3859,10 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
3859
3859
  name: "framebufferTextureMultiviewOVR",
3860
3860
  signatures: [["target","attachment","texture","level","baseViewIndex","numViews"]]
3861
3861
  },
3862
+ {
3863
+ name: "startRendering",
3864
+ signatures: [["?chunkSize"]]
3865
+ },
3862
3866
  {
3863
3867
  name: "convertToBlob",
3864
3868
  signatures: [["?options"]]
@@ -8085,6 +8089,10 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
8085
8089
  name: "decapsulateBits",
8086
8090
  signatures: [["decapsulationAlgorithm","decapsulationKey","ciphertext"]]
8087
8091
  },
8092
+ {
8093
+ name: "requestFileHandle",
8094
+ signatures: [["hash","?options"]]
8095
+ },
8088
8096
  {
8089
8097
  name: "userAgentAllowsProtocol",
8090
8098
  signatures: [["protocol"]]
@@ -8301,6 +8309,14 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
8301
8309
  name: "WorkletAnimation",
8302
8310
  signatures: [["animatorName","effects","?timeline","?options"]]
8303
8311
  },
8312
+ {
8313
+ name: "availability",
8314
+ signatures: [["?options"]]
8315
+ },
8316
+ {
8317
+ name: "decide",
8318
+ signatures: [["input","?options"]]
8319
+ },
8304
8320
  {
8305
8321
  name: "LanguageModelToolCall",
8306
8322
  signatures: [["init"]]
@@ -8313,10 +8329,6 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
8313
8329
  name: "LanguageModelToolError",
8314
8330
  signatures: [["init"]]
8315
8331
  },
8316
- {
8317
- name: "availability",
8318
- signatures: [["?options"]]
8319
- },
8320
8332
  {
8321
8333
  name: "embed",
8322
8334
  signatures: [["input","?options"]]
@@ -8395,7 +8407,7 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
8395
8407
  },
8396
8408
  {
8397
8409
  name: "createParserOptions",
8398
- signatures: [["input"]]
8410
+ signatures: [["?input","...args"]]
8399
8411
  },
8400
8412
  {
8401
8413
  name: "createPolicy",
@@ -9031,54 +9043,6 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
9031
9043
  name: "timeout",
9032
9044
  signatures: [["milliseconds"]]
9033
9045
  },
9034
- {
9035
- name: "beforeHTML",
9036
- signatures: [["html","?options"]]
9037
- },
9038
- {
9039
- name: "beforeHTMLUnsafe",
9040
- signatures: [["html","?options"]]
9041
- },
9042
- {
9043
- name: "afterHTML",
9044
- signatures: [["html","?options"]]
9045
- },
9046
- {
9047
- name: "afterHTMLUnsafe",
9048
- signatures: [["html","?options"]]
9049
- },
9050
- {
9051
- name: "replaceWithHTML",
9052
- signatures: [["html","?options"]]
9053
- },
9054
- {
9055
- name: "replaceWithHTMLUnsafe",
9056
- signatures: [["html","?options"]]
9057
- },
9058
- {
9059
- name: "streamBeforeHTML",
9060
- signatures: [["?options"]]
9061
- },
9062
- {
9063
- name: "streamBeforeHTMLUnsafe",
9064
- signatures: [["?options"]]
9065
- },
9066
- {
9067
- name: "streamAfterHTML",
9068
- signatures: [["?options"]]
9069
- },
9070
- {
9071
- name: "streamAfterHTMLUnsafe",
9072
- signatures: [["?options"]]
9073
- },
9074
- {
9075
- name: "streamReplaceWithHTML",
9076
- signatures: [["?options"]]
9077
- },
9078
- {
9079
- name: "streamReplaceWithHTMLUnsafe",
9080
- signatures: [["?options"]]
9081
- },
9082
9046
  {
9083
9047
  name: "Comment",
9084
9048
  signatures: [["?data"]]
@@ -9191,6 +9155,54 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
9191
9155
  name: "MutationObserver",
9192
9156
  signatures: [["callback"]]
9193
9157
  },
9158
+ {
9159
+ name: "beforeHTML",
9160
+ signatures: [["html","?options"]]
9161
+ },
9162
+ {
9163
+ name: "beforeHTMLUnsafe",
9164
+ signatures: [["html","?options"]]
9165
+ },
9166
+ {
9167
+ name: "afterHTML",
9168
+ signatures: [["html","?options"]]
9169
+ },
9170
+ {
9171
+ name: "afterHTMLUnsafe",
9172
+ signatures: [["html","?options"]]
9173
+ },
9174
+ {
9175
+ name: "replaceWithHTML",
9176
+ signatures: [["html","?options"]]
9177
+ },
9178
+ {
9179
+ name: "replaceWithHTMLUnsafe",
9180
+ signatures: [["html","?options"]]
9181
+ },
9182
+ {
9183
+ name: "streamBeforeHTML",
9184
+ signatures: [["?options"]]
9185
+ },
9186
+ {
9187
+ name: "streamBeforeHTMLUnsafe",
9188
+ signatures: [["?options"]]
9189
+ },
9190
+ {
9191
+ name: "streamAfterHTML",
9192
+ signatures: [["?options"]]
9193
+ },
9194
+ {
9195
+ name: "streamAfterHTMLUnsafe",
9196
+ signatures: [["?options"]]
9197
+ },
9198
+ {
9199
+ name: "streamReplaceWithHTML",
9200
+ signatures: [["?options"]]
9201
+ },
9202
+ {
9203
+ name: "streamReplaceWithHTMLUnsafe",
9204
+ signatures: [["?options"]]
9205
+ },
9194
9206
  {
9195
9207
  name: "Observable",
9196
9208
  signatures: [["callback"]]
@@ -194,7 +194,13 @@ export class Automapping {
194
194
  if (this.#sourceCodeToProcessingPromiseMap.get(networkSourceCode) !== createBindingPromise) {
195
195
  return null;
196
196
  }
197
- if (status.network.contentType().isFromSourceMap() || !status.fileSystem.contentType().isTextType()) {
197
+ const target = Bindings.NetworkProject.NetworkProject.targetForUISourceCode(status.network);
198
+ const isNodeTarget = target?.type() === SDK.Target.Type.NODE;
199
+ // Source-map-derived URLs and contents are controlled by the inspected page.
200
+ // Only trust them without content validation when debugging Node.js.
201
+ const skipContentValidation = !status.fileSystem.contentType().isTextType() ||
202
+ (status.network.contentType().isFromSourceMap() && isNodeTarget);
203
+ if (skipContentValidation) {
198
204
  return status;
199
205
  }
200
206
 
@@ -231,10 +237,9 @@ export class Automapping {
231
237
  return null;
232
238
  }
233
239
 
234
- const target = Bindings.NetworkProject.NetworkProject.targetForUISourceCode(status.network);
235
240
  let isValid = false;
236
241
  const fileContent = fileSystemContent.content;
237
- if (target && target.type() === SDK.Target.Type.NODE) {
242
+ if (isNodeTarget) {
238
243
  if (networkContent.content) {
239
244
  const rewrappedNetworkContent =
240
245
  PersistenceImpl.rewrapNodeJSContent(status.fileSystem, fileContent, networkContent.content);
@@ -202,6 +202,13 @@ export class TraceProcessor extends EventTarget {
202
202
 
203
203
  options.logger?.start('parse:handleEvent');
204
204
 
205
+ // In bundled builds each handler is a module namespace object whose exports are getters, and every handler has a
206
+ // different shape. V8 can't optimise a `handler.handleEvent` read that sees all these shapes, so reading it inside the
207
+ // loop costs a slow getter call for every event and handler.
208
+ // On a 1M-event trace that is about 30M getter calls per parse. Reading each `handleEvent` once here cut the
209
+ // handleEvent loop from ~2.9s to ~2.1s (-25%) and total parse time by ~10%, so keep this read outside the loop.
210
+ const handleEventFns = sortedHandlers.map(([, handler]) => handler.handleEvent);
211
+
205
212
  // Handle each event.
206
213
  for (let i = 0; i < traceEvents.length; ++i) {
207
214
  // Every so often we take a break just to render.
@@ -213,9 +220,8 @@ export class TraceProcessor extends EventTarget {
213
220
  await new Promise(resolve => setTimeout(resolve, 0));
214
221
  }
215
222
  const event = traceEvents[i];
216
- for (let j = 0; j < sortedHandlers.length; ++j) {
217
- const [, handler] = sortedHandlers[j];
218
- handler.handleEvent(event);
223
+ for (let j = 0; j < handleEventFns.length; ++j) {
224
+ handleEventFns[j](event);
219
225
  }
220
226
  }
221
227
 
@@ -497,7 +497,7 @@ export class BottomUpRootNode extends Node {
497
497
 
498
498
  function onEndEvent(event: Types.Events.Event): void {
499
499
  const id = idStack.pop();
500
- if (!id) {
500
+ if (id === undefined) {
501
501
  return;
502
502
  }
503
503