chrome-devtools-frontend 1.0.1698733 → 1.0.1700561

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 (164) hide show
  1. package/.agents/skills/devtools-verification/SKILL.md +19 -0
  2. package/.agents/skills/{repro-flaky-tests → fix-tests}/SKILL.md +2 -2
  3. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +2 -2
  4. package/front_end/core/sdk/DOMModel.ts +3 -5
  5. package/front_end/core/sdk/NetworkManager.ts +2 -2
  6. package/front_end/core/sdk/OverlayModel.ts +11 -12
  7. package/front_end/core/sdk/ServiceWorkerCacheModel.ts +3 -0
  8. package/front_end/core/sdk/SourceMapScopeChainEntry.ts +84 -32
  9. package/front_end/core/sdk/StorageBucketsModel.ts +2 -0
  10. package/front_end/entrypoints/main/GlobalAiButton.ts +2 -6
  11. package/front_end/entrypoints/main/MainImpl.ts +8 -1
  12. package/front_end/generated/InspectorBackendCommands.ts +12 -2
  13. package/front_end/generated/SupportedCSSProperties.ts +14 -0
  14. package/front_end/generated/protocol-mapping.d.ts +48 -1
  15. package/front_end/generated/protocol-proxy-api.d.ts +37 -1
  16. package/front_end/generated/protocol.ts +131 -0
  17. package/front_end/models/bindings/NetworkProject.ts +30 -0
  18. package/front_end/models/bindings/ResourceScriptMapping.ts +62 -0
  19. package/front_end/models/change_tracker/ChangeTracker.ts +1 -1
  20. package/front_end/models/comment_manager/CD4ABridge.ts +2 -2
  21. package/front_end/models/comment_manager/CommentManager.ts +18 -0
  22. package/front_end/models/emulation/DeviceModeModel.ts +1 -1
  23. package/front_end/models/extensions/ExtensionAPI.ts +4 -2
  24. package/front_end/models/issues_manager/CookieIssue.ts +0 -15
  25. package/front_end/models/persistence/NetworkPersistenceManager.ts +29 -4
  26. package/front_end/models/source_map_scopes/NamesResolver.ts +34 -4
  27. package/front_end/models/source_map_scopes/ScopeChainModel.ts +31 -7
  28. package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +281 -3
  29. package/front_end/panels/accessibility/accessibilityAnnouncementRecordingView.css +85 -0
  30. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +1 -2
  31. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +5 -8
  32. package/front_end/panels/animation/AnimationTimeline.ts +1 -1
  33. package/front_end/panels/application/AppManifestView.ts +128 -134
  34. package/front_end/panels/application/CrashReportContextView.ts +6 -6
  35. package/front_end/panels/application/DeviceBoundSessionsTreeElement.ts +17 -17
  36. package/front_end/panels/application/DeviceBoundSessionsView.ts +136 -137
  37. package/front_end/panels/application/IndexedDBModel.ts +3 -0
  38. package/front_end/panels/application/IndexedDBViews.ts +1 -1
  39. package/front_end/panels/application/KeyValueStorageItemsView.ts +1 -0
  40. package/front_end/panels/application/OriginTrialTreeView.ts +18 -23
  41. package/front_end/panels/application/ReportingApiTreeElement.ts +3 -3
  42. package/front_end/panels/application/ReportingApiView.ts +6 -14
  43. package/front_end/panels/application/application-meta.ts +7 -7
  44. package/front_end/panels/application/components/AdsView.ts +63 -1
  45. package/front_end/panels/application/components/adsView.css +11 -1
  46. package/front_end/panels/common/CommentThreadWidget.ts +20 -22
  47. package/front_end/panels/common/CommentsOverlayWidget.ts +115 -9
  48. package/front_end/panels/common/CommentsStatusBarPill.ts +13 -1
  49. package/front_end/panels/common/ExtensionServer.ts +43 -34
  50. package/front_end/panels/common/GeminiRebrandPromoDialog.ts +1 -1
  51. package/front_end/panels/common/commentThreadWidget.css +6 -0
  52. package/front_end/panels/common/common-meta.ts +4 -1
  53. package/front_end/panels/elements/CSSRuleValidator.ts +1 -1
  54. package/front_end/panels/elements/ElementsPanel.ts +4 -4
  55. package/front_end/panels/elements/ElementsTreeElement.ts +9 -2
  56. package/front_end/panels/elements/ElementsTreeOutline.ts +25 -33
  57. package/front_end/panels/elements/elementsTreeOutline.css +8 -4
  58. package/front_end/panels/event_listeners/EventListenersView.ts +9 -4
  59. package/front_end/panels/issues/IssuesPane.ts +34 -22
  60. package/front_end/panels/lighthouse/LighthouseController.ts +1 -1
  61. package/front_end/panels/mobile_throttling/NetworkPanelIndicator.ts +1 -1
  62. package/front_end/panels/mobile_throttling/ThrottlingManager.ts +1 -1
  63. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +1 -1
  64. package/front_end/panels/network/RequestPayloadView.ts +17 -15
  65. package/front_end/panels/recorder/RecordingView.ts +32 -53
  66. package/front_end/panels/recorder/StepView.ts +19 -4
  67. package/front_end/panels/recorder/TimelineSection.ts +1 -1
  68. package/front_end/panels/recorder/controlButton.css +6 -0
  69. package/front_end/panels/recorder/recordingView.css +11 -2
  70. package/front_end/panels/settings/BackendLinkingSettingsTab.ts +2 -1
  71. package/front_end/panels/settings/EditFileSystemView.ts +1 -1
  72. package/front_end/panels/sources/CallStackSidebarPane.ts +1 -1
  73. package/front_end/panels/sources/DebuggerPlugin.ts +137 -56
  74. package/front_end/panels/sources/ScopeChainSidebarPane.ts +17 -15
  75. package/front_end/panels/timeline/components/DetailsView.ts +3 -3
  76. package/front_end/panels/timeline/components/IgnoreListSetting.ts +0 -2
  77. package/front_end/panels/timeline/components/LiveMetricsView.ts +59 -64
  78. package/front_end/panels/timeline/components/OriginMap.ts +1 -1
  79. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +2 -3
  80. package/front_end/panels/timeline/components/liveMetricsView.css +1 -0
  81. package/front_end/third_party/chromium/README.chromium +1 -1
  82. package/front_end/third_party/lighthouse/README.chromium +2 -2
  83. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1580 -1524
  84. package/front_end/third_party/lighthouse/locales/ar-XB.json +111 -72
  85. package/front_end/third_party/lighthouse/locales/ar.json +113 -74
  86. package/front_end/third_party/lighthouse/locales/bg.json +112 -73
  87. package/front_end/third_party/lighthouse/locales/ca.json +112 -73
  88. package/front_end/third_party/lighthouse/locales/cs.json +112 -73
  89. package/front_end/third_party/lighthouse/locales/da.json +112 -73
  90. package/front_end/third_party/lighthouse/locales/de.json +112 -73
  91. package/front_end/third_party/lighthouse/locales/el.json +112 -73
  92. package/front_end/third_party/lighthouse/locales/en-GB.json +111 -72
  93. package/front_end/third_party/lighthouse/locales/en-US.json +102 -66
  94. package/front_end/third_party/lighthouse/locales/en-XA.json +111 -72
  95. package/front_end/third_party/lighthouse/locales/en-XL.json +102 -66
  96. package/front_end/third_party/lighthouse/locales/es-419.json +112 -73
  97. package/front_end/third_party/lighthouse/locales/es.json +112 -73
  98. package/front_end/third_party/lighthouse/locales/fi.json +112 -73
  99. package/front_end/third_party/lighthouse/locales/fil.json +112 -73
  100. package/front_end/third_party/lighthouse/locales/fr.json +112 -73
  101. package/front_end/third_party/lighthouse/locales/he.json +112 -73
  102. package/front_end/third_party/lighthouse/locales/hi.json +112 -73
  103. package/front_end/third_party/lighthouse/locales/hr.json +112 -73
  104. package/front_end/third_party/lighthouse/locales/hu.json +112 -73
  105. package/front_end/third_party/lighthouse/locales/id.json +112 -73
  106. package/front_end/third_party/lighthouse/locales/it.json +113 -74
  107. package/front_end/third_party/lighthouse/locales/ja.json +112 -73
  108. package/front_end/third_party/lighthouse/locales/ko.json +112 -73
  109. package/front_end/third_party/lighthouse/locales/lt.json +112 -73
  110. package/front_end/third_party/lighthouse/locales/lv.json +112 -73
  111. package/front_end/third_party/lighthouse/locales/nl.json +112 -73
  112. package/front_end/third_party/lighthouse/locales/no.json +112 -73
  113. package/front_end/third_party/lighthouse/locales/pl.json +112 -73
  114. package/front_end/third_party/lighthouse/locales/pt-PT.json +112 -73
  115. package/front_end/third_party/lighthouse/locales/pt.json +112 -73
  116. package/front_end/third_party/lighthouse/locales/ro.json +112 -73
  117. package/front_end/third_party/lighthouse/locales/ru.json +112 -73
  118. package/front_end/third_party/lighthouse/locales/sk.json +112 -73
  119. package/front_end/third_party/lighthouse/locales/sl.json +112 -73
  120. package/front_end/third_party/lighthouse/locales/sr-Latn.json +112 -73
  121. package/front_end/third_party/lighthouse/locales/sr.json +112 -73
  122. package/front_end/third_party/lighthouse/locales/sv.json +124 -85
  123. package/front_end/third_party/lighthouse/locales/ta.json +112 -73
  124. package/front_end/third_party/lighthouse/locales/te.json +112 -73
  125. package/front_end/third_party/lighthouse/locales/th.json +112 -73
  126. package/front_end/third_party/lighthouse/locales/tr.json +113 -74
  127. package/front_end/third_party/lighthouse/locales/uk.json +112 -73
  128. package/front_end/third_party/lighthouse/locales/vi.json +112 -73
  129. package/front_end/third_party/lighthouse/locales/zh-HK.json +112 -73
  130. package/front_end/third_party/lighthouse/locales/zh-TW.json +113 -74
  131. package/front_end/third_party/lighthouse/locales/zh.json +113 -74
  132. package/front_end/third_party/lighthouse/report/bundle.d.ts +4 -4
  133. package/front_end/third_party/lighthouse/report/bundle.js +10 -3
  134. package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +2 -2
  135. package/front_end/third_party/lit/lit.ts +3 -0
  136. package/front_end/third_party/lit/package.json +3 -0
  137. package/front_end/third_party/lit/rebuild.sh +3 -2
  138. package/front_end/ui/comments/CommentAnchorResolver.ts +8 -2
  139. package/front_end/ui/comments/CommentOverlayManager.ts +2 -1
  140. package/front_end/ui/components/buttons/Button.ts +19 -1
  141. package/front_end/ui/legacy/ContextMenu.ts +16 -1
  142. package/front_end/ui/legacy/InspectorView.ts +4 -3
  143. package/front_end/ui/legacy/PlusButton.ts +5 -6
  144. package/front_end/ui/legacy/TabbedPane.ts +121 -80
  145. package/front_end/ui/legacy/Treeoutline.ts +37 -6
  146. package/front_end/ui/legacy/UIUtils.ts +7 -0
  147. package/front_end/ui/legacy/Widget.ts +33 -0
  148. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +3 -0
  149. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +14 -4
  150. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +157 -171
  151. package/front_end/ui/lit/lit.ts +1 -1
  152. package/front_end/ui/visual_logging/KnownContextValues.ts +7 -0
  153. package/inspector_overlay/highlight_anchor.ts +197 -0
  154. package/inspector_overlay/tool_highlight.ts +8 -0
  155. package/package.json +1 -1
  156. package/.agents/skills/devtools-ci/SKILL.md +0 -65
  157. package/.agents/skills/evaluate-ai-css-completion/SKILL.md +0 -143
  158. package/.agents/skills/evaluate-ai-css-completion/scripts/evaluate.js +0 -104
  159. package/.agents/skills/fixing-skipped-tests/SKILL.md +0 -32
  160. package/.agents/skills/gerrit-cli/SKILL.md +0 -74
  161. package/.agents/skills/gerrit-cli/references/commands.md +0 -169
  162. package/.agents/skills/gerrit-cli/references/workflows.md +0 -63
  163. package/.agents/skills/gerrit-cli/scripts/import_upstream.py +0 -85
  164. package/front_end/models/issues_manager/descriptions/cookieExcludeBlockedWithinRelatedWebsiteSet.md +0 -4
@@ -138,7 +138,7 @@ const UIStrings = {
138
138
  * @description Error message that is displayed in UI when a file needed for debugging information for a call frame is missing.
139
139
  * @example {src/myapp.debug.wasm.dwp} PH1
140
140
  */
141
- debugFileNotFound: 'Failed to load debug file "{PH1}".',
141
+ debugFileNotFound: 'Failed to load debug file "{PH1}"',
142
142
  /**
143
143
  * @description Error message that is displayed when no debug info could be loaded.
144
144
  * @example {app.wasm} PH1
@@ -666,6 +666,23 @@ export class DebuggerPlugin extends Plugin {
666
666
  return {
667
667
  box,
668
668
  show: async (popover: UI.GlassPane.GlassPane) => {
669
+ const scopeMappings = await this.#getScopeMappings(selectedCallFrame);
670
+ const scopedVariable = findVariableInScopeMappings(evaluationText, highlightRange.from, scopeMappings);
671
+ if (scopedVariable.found) {
672
+ if (!scopedVariable.value) {
673
+ return false;
674
+ }
675
+ objectPopoverHelper =
676
+ await ObjectUI.ObjectPopoverHelper.ObjectPopoverHelper.buildObjectPopover(scopedVariable.value, popover);
677
+ const potentiallyUpdatedCallFrame =
678
+ UI.Context.Context.instance().flavor(StackTrace.StackTrace.DebuggableFrameFlavor);
679
+ if (!objectPopoverHelper || debuggableFrame !== potentiallyUpdatedCallFrame) {
680
+ objectPopoverHelper?.dispose();
681
+ return false;
682
+ }
683
+ return true;
684
+ }
685
+
669
686
  let resolvedText = '';
670
687
  if (selectedCallFrame.script.isJavaScript()) {
671
688
  const nameMap = await SourceMapScopes.NamesResolver.allVariablesInCallFrame(
@@ -950,6 +967,23 @@ export class DebuggerPlugin extends Plugin {
950
967
  return offset ?? null;
951
968
  }
952
969
 
970
+ #cachedScopeMappings?: {callFrame: SDK.DebuggerModel.CallFrame, promise: Promise<ScopeMapping[]>};
971
+
972
+ #getScopeMappings(callFrame: SDK.DebuggerModel.CallFrame,
973
+ resolvedScopeChain?: SDK.DebuggerModel.ScopeChainEntry[]): Promise<ScopeMapping[]> {
974
+ if (this.#cachedScopeMappings?.callFrame !== callFrame) {
975
+ const url = this.uiSourceCode.url();
976
+ this.#cachedScopeMappings = {
977
+ callFrame,
978
+ promise: computeScopeMappings(
979
+ callFrame, location => this.#rawLocationToEditorOffset(location, url),
980
+ (line, col) => this.editor?.toOffset(this.transformer.uiLocationToEditorLocation(line, col)) ?? null,
981
+ resolvedScopeChain),
982
+ };
983
+ }
984
+ return this.#cachedScopeMappings.promise;
985
+ }
986
+
953
987
  private async computeValueDecorations(): Promise<CodeMirror.DecorationSet|null> {
954
988
  if (!this.editor) {
955
989
  return null;
@@ -968,13 +1002,22 @@ export class DebuggerPlugin extends Plugin {
968
1002
  const callFrame = debuggableFrame.sdkFrame;
969
1003
  const url = this.uiSourceCode.url();
970
1004
 
971
- const rawLocationToEditorOffset: (location: SDK.DebuggerModel.Location|null) => Promise<number|null> = location =>
972
- this.#rawLocationToEditorOffset(location, url);
973
-
974
- const functionOffsetPromise = this.#rawLocationToEditorOffset(callFrame.functionLocation(), url);
1005
+ const uiPositionToEditorOffset = (lineNumber: number, columnNumber: number): number|null =>
1006
+ this.editor?.toOffset(this.transformer.uiLocationToEditorLocation(lineNumber, columnNumber)) ?? null;
1007
+ const scopeChain = await SourceMapScopes.ScopeChainModel.ScopeChainModel.resolveScopeChain(
1008
+ callFrame, Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance());
1009
+ const localOriginalScope = scopeChain
1010
+ .find((s): s is SDK.SourceMapScopeChainEntry.SourceMapScopeChainEntry =>
1011
+ s instanceof SDK.SourceMapScopeChainEntry.SourceMapScopeChainEntry &&
1012
+ s.type() === Protocol.Debugger.ScopeType.Local)
1013
+ ?.originalScope();
1014
+
1015
+ const functionOffsetPromise = localOriginalScope ?
1016
+ Promise.resolve(uiPositionToEditorOffset(localOriginalScope.start.line, localOriginalScope.start.column)) :
1017
+ this.#rawLocationToEditorOffset(callFrame.functionLocation(), url);
975
1018
  const executionOffsetPromise = this.#rawLocationToEditorOffset(callFrame.location(), url);
976
1019
  const [functionOffset, executionOffset] = await Promise.all([functionOffsetPromise, executionOffsetPromise]);
977
- if (!functionOffset || !executionOffset || !this.editor) {
1020
+ if (functionOffset === null || !executionOffset || !this.editor) {
978
1021
  return null;
979
1022
  }
980
1023
 
@@ -991,12 +1034,13 @@ export class DebuggerPlugin extends Plugin {
991
1034
  CodeMirror.ensureSyntaxTree(this.editor.state, executionOffset, 16);
992
1035
  }
993
1036
 
994
- const variableNames = getVariableNamesByLine(this.editor.state, functionOffset, executionOffset, executionOffset);
1037
+ const variableNames = getVariableNamesByLine(this.editor.state, functionOffset, executionOffset, executionOffset,
1038
+ Boolean(localOriginalScope));
995
1039
  if (variableNames.length === 0) {
996
1040
  return null;
997
1041
  }
998
1042
 
999
- const scopeMappings = await computeScopeMappings(callFrame, rawLocationToEditorOffset);
1043
+ const scopeMappings = await this.#getScopeMappings(callFrame, scopeChain);
1000
1044
  // After the `await` the DebuggerPlugin could have been disposed. Re-check `this.editor`.
1001
1045
  if (!this.editor || scopeMappings.length === 0) {
1002
1046
  return null;
@@ -1986,8 +2030,19 @@ class ValueDecoration extends CodeMirror.WidgetType {
1986
2030
 
1987
2031
  const valueDecorations = defineStatefulDecoration();
1988
2032
 
1989
- function isVariableIdentifier(tokenType: string): boolean {
1990
- return tokenType === 'VariableName' || tokenType === 'VariableDefinition';
2033
+ function isVariableIdentifierNode(node: {name: string, from: number, to: number}, doc: CodeMirror.Text): boolean {
2034
+ switch (node.name) {
2035
+ case 'VariableName':
2036
+ case 'VariableDefinition':
2037
+ case 'Identifier':
2038
+ case 'Definition':
2039
+ case 'variableName':
2040
+ case 'variableName.definition':
2041
+ return (node.from === 0 || doc.sliceString(node.from - 1, node.from) !== '.') &&
2042
+ doc.sliceString(node.to, node.to + 1) !== '(';
2043
+ default:
2044
+ return false;
2045
+ }
1991
2046
  }
1992
2047
 
1993
2048
  function isVariableDefinition(tokenType: string): boolean {
@@ -2007,9 +2062,9 @@ class SiblingScopeVariables {
2007
2062
  variables: Array<{line: number, from: number, id: string}> = [];
2008
2063
  }
2009
2064
 
2010
- export function getVariableNamesByLine(
2011
- editorState: CodeMirror.EditorState, fromPos: number, toPos: number,
2012
- currentPos: number): Array<{line: number, from: number, id: string}> {
2065
+ export function getVariableNamesByLine(editorState: CodeMirror.EditorState, fromPos: number, toPos: number,
2066
+ currentPos: number,
2067
+ useOriginalScopes = false): Array<{line: number, from: number, id: string}> {
2013
2068
  const fromLine = editorState.doc.lineAt(fromPos);
2014
2069
  fromPos = Math.min(fromLine.to, fromPos);
2015
2070
  toPos = editorState.doc.lineAt(toPos).from;
@@ -2020,7 +2075,7 @@ export function getVariableNamesByLine(
2020
2075
  * We will exclude variables that are defined (and used in those scopes (since we are currently outside of their lifetime).
2021
2076
  **/
2022
2077
  function isSiblingScopeNode(node: {name: string, from: number, to: number}): boolean {
2023
- return isScopeNode(node.name) && (node.to < currentPos || currentPos < node.from);
2078
+ return !useOriginalScopes && isScopeNode(node.name) && (node.to < currentPos || currentPos < node.from);
2024
2079
  }
2025
2080
 
2026
2081
  const names: Array<{line: number, from: number, id: string}> = [];
@@ -2050,7 +2105,7 @@ export function getVariableNamesByLine(
2050
2105
  return;
2051
2106
  }
2052
2107
 
2053
- const varName = isVariableIdentifier(node.name) && editorState.sliceDoc(node.from, node.to);
2108
+ const varName = isVariableIdentifierNode(node, editorState.doc) && editorState.sliceDoc(node.from, node.to);
2054
2109
  if (!varName) {
2055
2110
  return;
2056
2111
  }
@@ -2083,49 +2138,92 @@ export function getVariableNamesByLine(
2083
2138
  return names;
2084
2139
  }
2085
2140
 
2141
+ export interface ScopeMapping {
2142
+ scopeStart: number;
2143
+ scopeEnd: number;
2144
+ variableMap: Map<string, SDK.RemoteObject.RemoteObject|null>;
2145
+ }
2146
+
2086
2147
  export async function computeScopeMappings(
2087
2148
  callFrame: SDK.DebuggerModel.CallFrame,
2088
- rawLocationToEditorOffset: (l: SDK.DebuggerModel.Location|null) => Promise<number|null>):
2089
- Promise<Array<{scopeStart: number, scopeEnd: number, variableMap: Map<string, SDK.RemoteObject.RemoteObject>}>> {
2090
- const scopeMappings:
2091
- Array<{scopeStart: number, scopeEnd: number, variableMap: Map<string, SDK.RemoteObject.RemoteObject>}> = [];
2092
- for (const scope of callFrame.scopeChain()) {
2093
- const scopeStart = await rawLocationToEditorOffset(scope.range()?.start ?? null);
2094
- if (!scopeStart) {
2095
- break;
2149
+ rawLocationToEditorOffset: (l: SDK.DebuggerModel.Location|null) => Promise<number|null>,
2150
+ uiPositionToEditorOffset?: (line: number, column: number) => number | null,
2151
+ resolvedScopeChain?: SDK.DebuggerModel.ScopeChainEntry[]): Promise<ScopeMapping[]> {
2152
+ const scopeMappings: ScopeMapping[] = [];
2153
+ const scopeChain = resolvedScopeChain ??
2154
+ await SourceMapScopes.ScopeChainModel.ScopeChainModel.resolveScopeChain(
2155
+ callFrame, Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance());
2156
+ const activeScopes =
2157
+ new Set(scopeChain.filter(s => s instanceof SDK.SourceMapScopeChainEntry.SourceMapScopeChainEntry)
2158
+ .map(s => s.originalScope()));
2159
+ const addInactiveChildren =
2160
+ (children: ReturnType<SDK.SourceMapScopeChainEntry.SourceMapScopeChainEntry['originalScope']>['children']):
2161
+ void => {
2162
+ for (const child of children) {
2163
+ if (!activeScopes.has(child)) {
2164
+ const scopeStart = uiPositionToEditorOffset?.(child.start.line, child.start.column) ?? null;
2165
+ const scopeEnd = uiPositionToEditorOffset?.(child.end.line, child.end.column) ?? null;
2166
+ if (scopeStart !== null && scopeEnd !== null && child.variables.length > 0) {
2167
+ scopeMappings.push({scopeStart, scopeEnd, variableMap: new Map(child.variables.map(v => [v, null]))});
2168
+ }
2169
+ addInactiveChildren(child.children);
2170
+ }
2171
+ }
2172
+ };
2173
+
2174
+ for (const scope of scopeChain) {
2175
+ let scopeStart: number|null = null;
2176
+ let scopeEnd: number|null = null;
2177
+ if (scope instanceof SDK.SourceMapScopeChainEntry.SourceMapScopeChainEntry) {
2178
+ const orig = scope.originalScope();
2179
+ scopeStart = uiPositionToEditorOffset?.(orig.start.line, orig.start.column) ?? null;
2180
+ scopeEnd = uiPositionToEditorOffset?.(orig.end.line, orig.end.column) ?? null;
2181
+ addInactiveChildren(orig.children);
2182
+ } else {
2183
+ scopeStart = await rawLocationToEditorOffset(scope.range()?.start ?? null);
2184
+ scopeEnd = await rawLocationToEditorOffset(scope.range()?.end ?? null);
2096
2185
  }
2097
- const scopeEnd = await rawLocationToEditorOffset(scope.range()?.end ?? null);
2098
- if (!scopeEnd) {
2186
+ if (scopeStart === null || scopeEnd === null) {
2099
2187
  break;
2100
2188
  }
2101
2189
 
2102
- const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance();
2103
- const {properties} = await SourceMapScopes.NamesResolver.resolveScopeInObject(scope, debuggerWorkspaceBinding)
2104
- .getAllProperties(false, false);
2190
+ const {properties} = await scope.object().getAllProperties(false, true);
2105
2191
  if (!properties || properties.length > MAX_PROPERTIES_IN_SCOPE_FOR_VALUE_DECORATIONS) {
2106
2192
  break;
2107
2193
  }
2108
- const variableMap = new Map<string, SDK.RemoteObject.RemoteObject>(
2109
- properties.map(p => [p.name, p.value] as [string, SDK.RemoteObject.RemoteObject]));
2194
+ const variableMap =
2195
+ new Map<string, SDK.RemoteObject.RemoteObject|null>(properties.map(p => [p.name, p.value ?? null]));
2110
2196
 
2111
2197
  scopeMappings.push({scopeStart, scopeEnd, variableMap});
2112
2198
 
2113
2199
  // Let us only get mappings for block scopes until we see a surrounding function (local) scope.
2114
- if (scope.type() === Protocol.Debugger.ScopeType.Local) {
2200
+ if (scope.type() === Protocol.Debugger.ScopeType.Local &&
2201
+ !(scope instanceof SDK.SourceMapScopeChainEntry.SourceMapScopeChainEntry)) {
2115
2202
  break;
2116
2203
  }
2117
2204
  }
2118
2205
  return scopeMappings;
2119
2206
  }
2120
2207
 
2121
- export function getVariableValuesByLine(
2122
- scopeMappings:
2123
- Array<{scopeStart: number, scopeEnd: number, variableMap: Map<string, SDK.RemoteObject.RemoteObject>}>,
2124
- variableNames: Array<{line: number, from: number, id: string}>):
2208
+ export function findVariableInScopeMappings(name: string, pos: number, scopeMappings: ScopeMapping[]):
2209
+ {found: boolean, value: SDK.RemoteObject.RemoteObject|null} {
2210
+ for (const scope of scopeMappings) {
2211
+ if (pos < scope.scopeStart || pos >= scope.scopeEnd) {
2212
+ continue;
2213
+ }
2214
+ if (scope.variableMap.has(name)) {
2215
+ return {found: true, value: scope.variableMap.get(name) ?? null};
2216
+ }
2217
+ }
2218
+ return {found: false, value: null};
2219
+ }
2220
+
2221
+ export function getVariableValuesByLine(scopeMappings: ScopeMapping[],
2222
+ variableNames: Array<{line: number, from: number, id: string}>):
2125
2223
  Map<number, Map<string, SDK.RemoteObject.RemoteObject>>|null {
2126
2224
  const namesPerLine = new Map<number, Map<string, SDK.RemoteObject.RemoteObject>>();
2127
2225
  for (const {line, from, id} of variableNames) {
2128
- const varValue = findVariableInChain(id, from, scopeMappings);
2226
+ const varValue = findVariableInScopeMappings(id, from, scopeMappings).value;
2129
2227
  if (!varValue) {
2130
2228
  continue;
2131
2229
  }
@@ -2137,24 +2235,6 @@ export function getVariableValuesByLine(
2137
2235
  names.set(id, varValue);
2138
2236
  }
2139
2237
  return namesPerLine;
2140
-
2141
- function findVariableInChain(
2142
- name: string,
2143
- pos: number,
2144
- scopeMappings:
2145
- Array<{scopeStart: number, scopeEnd: number, variableMap: Map<string, SDK.RemoteObject.RemoteObject>}>,
2146
- ): SDK.RemoteObject.RemoteObject|null {
2147
- for (const scope of scopeMappings) {
2148
- if (pos < scope.scopeStart || pos >= scope.scopeEnd) {
2149
- continue;
2150
- }
2151
- const value = scope.variableMap.get(name);
2152
- if (value) {
2153
- return value;
2154
- }
2155
- }
2156
- return null;
2157
- }
2158
2238
  }
2159
2239
 
2160
2240
  // Pop-over
@@ -2229,8 +2309,9 @@ export function computePopoverHighlightRange(state: CodeMirror.EditorState, mime
2229
2309
 
2230
2310
  default: {
2231
2311
  // In other languages, just assume a token consisting entirely
2232
- // of identifier-like characters is an identifier.
2233
- if (node.to - node.from > 50 || /[^\w_\-$]/.test(state.sliceDoc(node.from, node.to))) {
2312
+ // of identifier-like characters is an identifier, unless it is a member access.
2313
+ if (node.to - node.from > 50 || /[^\w_\-$]/.test(state.sliceDoc(node.from, node.to)) ||
2314
+ state.sliceDoc(node.from - 1, node.from) === '.' || state.sliceDoc(node.from - 2, node.from) === '->') {
2234
2315
  return null;
2235
2316
  }
2236
2317
  return {from: node.from, to: node.to, containsSideEffects: false};
@@ -244,21 +244,23 @@ export class ScopeChainSidebarPane extends UI.Widget.VBox implements UI.ContextF
244
244
  ObjectUI.ObjectPropertiesSection.populateObjectTreeContextMenu(
245
245
  contextMenu,
246
246
  objectTree,
247
- async () => {
248
- await objectTree.expandRecursively(ObjectUI.ObjectPropertiesSection.EXPANDABLE_MAX_DEPTH);
249
- this.requestUpdate();
250
- },
251
- () => {
252
- objectTree.collapseRecursively();
253
- this.requestUpdate();
254
- },
255
- () => {
256
- objectTree.sortPropertiesAlphabetically = !objectTree.sortPropertiesAlphabetically;
257
- this.requestUpdate();
258
- },
259
- () => {
260
- objectTree.includeNullOrUndefinedValues = !objectTree.includeNullOrUndefinedValues;
261
- this.requestUpdate();
247
+ {
248
+ expandRecursively: async () => {
249
+ await objectTree.expandRecursively(ObjectUI.ObjectPropertiesSection.EXPANDABLE_MAX_DEPTH);
250
+ this.requestUpdate();
251
+ },
252
+ collapseChildren: () => {
253
+ objectTree.collapseRecursively();
254
+ this.requestUpdate();
255
+ },
256
+ sortPropertiesAlphabetically: node => {
257
+ node.sortPropertiesAlphabetically = !node.sortPropertiesAlphabetically;
258
+ this.requestUpdate();
259
+ },
260
+ onShowAllToggled: node => {
261
+ node.includeNullOrUndefinedValues = !node.includeNullOrUndefinedValues;
262
+ this.requestUpdate();
263
+ },
262
264
  },
263
265
  );
264
266
  },
@@ -25,7 +25,7 @@ const UIStrings = {
25
25
  * @description Warning message indicating that an event is likely a performance bottleneck in the Performance panel.
26
26
  * @example {Forced reflow} PH1
27
27
  */
28
- sIsALikelyPerformanceBottleneck: '{PH1} is a likely performance bottleneck.',
28
+ sIsALikelyPerformanceBottleneck: '{PH1} is a likely performance bottleneck',
29
29
  /**
30
30
  * @description Warning message in the Performance panel for an idle callback function that took longer to execute than its predefined deadline.
31
31
  * @example {10ms} PH1
@@ -36,7 +36,7 @@ const UIStrings = {
36
36
  * @example {Task} PH1
37
37
  * @example {10ms} PH2
38
38
  */
39
- sTookS: '{PH1} took {PH2}.',
39
+ sTookS: '{PH1} took {PH2}',
40
40
  /**
41
41
  * @description Label in the Performance panel for a task that took a long time.
42
42
  */
@@ -49,7 +49,7 @@ const UIStrings = {
49
49
  * @description Warning message in the Performance panel indicating that an interaction caused poor responsiveness.
50
50
  * @example {Long interaction} PH1
51
51
  */
52
- sIsLikelyPoorPageResponsiveness: '{PH1} indicates poor page responsiveness.',
52
+ sIsLikelyPoorPageResponsiveness: '{PH1} indicates poor page responsiveness',
53
53
  /**
54
54
  * @description Label for the WebSocket sub-protocol in the event details view of the Performance panel.
55
55
  */
@@ -2,8 +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 '../../../ui/components/menus/menus.js';
6
-
7
5
  import * as Common from '../../../core/common/common.js';
8
6
  import * as i18n from '../../../core/i18n/i18n.js';
9
7
  import * as Platform from '../../../core/platform/platform.js';
@@ -5,12 +5,11 @@
5
5
  import '../../../ui/components/settings/settings.js';
6
6
  import '../../../ui/kit/kit.js';
7
7
  import './FieldSettingsDialog.js';
8
- import '../../../ui/components/menus/menus.js';
9
8
  import './MetricCard.js';
10
9
 
11
10
  import * as Common from '../../../core/common/common.js';
12
11
  import * as i18n from '../../../core/i18n/i18n.js';
13
- import type * as Platform from '../../../core/platform/platform.js';
12
+ import * as Platform from '../../../core/platform/platform.js';
14
13
  import * as Root from '../../../core/root/root.js';
15
14
  import * as SDK from '../../../core/sdk/sdk.js';
16
15
  import * as CrUXManager from '../../../models/crux-manager/crux-manager.js';
@@ -19,7 +18,6 @@ import * as LiveMetrics from '../../../models/live-metrics/live-metrics.js';
19
18
  import type * as Spec from '../../../models/live-metrics/web-vitals-injected/spec/spec.js';
20
19
  import * as Trace from '../../../models/trace/trace.js';
21
20
  import * as Buttons from '../../../ui/components/buttons/buttons.js';
22
- import type * as Menus from '../../../ui/components/menus/menus.js';
23
21
  import type * as Settings from '../../../ui/components/settings/settings.js';
24
22
  import * as uiI18n from '../../../ui/i18n/i18n.js';
25
23
  import * as UI from '../../../ui/legacy/legacy.js';
@@ -99,14 +97,12 @@ const UIStrings = {
99
97
  notEnoughData: 'Not enough data',
100
98
  /**
101
99
  * @description Label for real user network conditions in the live metrics view of the Performance panel.
102
- * @example {75th percentile is similar to Slow 4G throttling} PH1
103
100
  */
104
- network: 'Network: {PH1}',
101
+ network: 'Network:',
105
102
  /**
106
103
  * @description Label for a select dropdown to choose the device form factor in the Performance panel.
107
- * @example {Mobile} PH1
108
104
  */
109
- device: 'Device: {PH1}',
105
+ device: 'Device:',
110
106
  /**
111
107
  * @description Label for an option to select all device form factors in the Performance panel.
112
108
  */
@@ -303,10 +299,6 @@ const UIStrings = {
303
299
  * @description Description text for recording a performance timeline of a connected Node process in the Performance panel.
304
300
  */
305
301
  nodeClickToRecord: 'Record a performance timeline of the connected Node process',
306
- /**
307
- * @description Label for the network throttling dropdown in the live metrics view of the Performance panel.
308
- */
309
- networkThrottling: 'Network:',
310
302
  /**
311
303
  * @description Tooltip text explaining why the user should adjust throttling settings in the Performance panel.
312
304
  */
@@ -326,8 +318,8 @@ export interface ViewInput {
326
318
  toggleRecordAction: UI.ActionRegistration.Action;
327
319
  recordReloadAction: UI.ActionRegistration.Action;
328
320
  cruxManager: CrUXManager.CrUXManager;
329
- handlePageScopeSelected: (event: Menus.SelectMenu.SelectMenuItemSelectedEvent) => void;
330
- handleDeviceOptionSelected: (event: Menus.SelectMenu.SelectMenuItemSelectedEvent) => void;
321
+ handlePageScopeSelected: (pageScope: CrUXManager.PageScope) => void;
322
+ handleDeviceOptionSelected: (deviceOption: DeviceOption) => void;
331
323
  revealLayoutShiftCluster: (clusterIds: Set<LiveMetrics.LayoutShift['uniqueLayoutShiftId']>) => void;
332
324
  revealInteraction: (interaction: LiveMetrics.Interaction) => void;
333
325
  logExtraInteractionDetails: (interaction: LiveMetrics.Interaction) => void;
@@ -636,8 +628,8 @@ function renderRecordingSettings(input: ViewInput): Lit.LitTemplate {
636
628
  <div class="device-toolbar-description">${Insights.Helpers.md(i18nString(UIStrings.useDeviceToolbar))}</div>
637
629
  ${fieldEnabled ? html`
638
630
  <ul class="environment-recs-list">
639
- <li>${uiI18n.getFormatLocalizedStringTemplate(str_, UIStrings.device, {PH1: html`<span class="environment-rec">${deviceRec}</span>`})}</li>
640
- <li>${uiI18n.getFormatLocalizedStringTemplate(str_, UIStrings.network, {PH1: html`<span class="environment-rec">${networkRec}</span>`})}</li>
631
+ <li>${i18nString(UIStrings.device)} <span class="environment-rec">${deviceRec}</span></li>
632
+ <li>${i18nString(UIStrings.network)} <span class="environment-rec">${networkRec}</span></li>
641
633
  </ul>
642
634
  ` : nothing}
643
635
  <div class="environment-option">
@@ -649,7 +641,7 @@ function renderRecordingSettings(input: ViewInput): Lit.LitTemplate {
649
641
  </div>
650
642
  <div class="environment-option">
651
643
  <label class="environment-option-label">
652
- ${i18nString(UIStrings.networkThrottling)}
644
+ ${i18nString(UIStrings.network)}
653
645
  <select
654
646
  ${widget(MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelect, {
655
647
  bindToGlobalConditions: true,
@@ -685,35 +677,38 @@ function renderPageScopeSetting(input: ViewInput): Lit.LitTemplate {
685
677
  // If there is no data at all we should force users to switch pages or reconfigure CrUX.
686
678
  const shouldDisable = !input.cruxManager.pageResult?.['url-ALL'] && !input.cruxManager.pageResult?.['origin-ALL'];
687
679
 
688
- /* eslint-disable @devtools/no-deprecated-component-usages */
689
680
  return html`
690
- <devtools-select-menu
681
+ <select
691
682
  id="page-scope-select"
692
683
  class="field-data-option"
693
- @selectmenuselected=${input.handlePageScopeSelected}
694
- .showDivider=${true}
695
- .showArrow=${true}
696
- .sideButton=${false}
697
- .showSelectedItem=${true}
698
- .buttonTitle=${buttonTitle}
699
- .disabled=${shouldDisable}
684
+ @change=${
685
+ (e: Event) => input.handlePageScopeSelected((e.target as HTMLSelectElement).value as CrUXManager.PageScope)}
686
+ ?disabled=${shouldDisable}
700
687
  title=${accessibleTitle}
688
+ aria-label=${accessibleTitle}
689
+ .value=${live(input.cruxManager.fieldPageScope)}
690
+ jslog=${VisualLogging.dropDown('page-scope').track({
691
+ change: true,
692
+ })}
701
693
  >
702
- <devtools-menu-item
703
- .value=${'url'}
704
- .selected=${input.cruxManager.fieldPageScope === 'url'}
694
+ <option
695
+ value="url"
696
+ jslog=${VisualLogging.item('url').track({
697
+ click: true,
698
+ })}
705
699
  >
706
700
  ${urlLabel}
707
- </devtools-menu-item>
708
- <devtools-menu-item
709
- .value=${'origin'}
710
- .selected=${input.cruxManager.fieldPageScope === 'origin'}
701
+ </option>
702
+ <option
703
+ value="origin"
704
+ jslog=${VisualLogging.item('origin').track({
705
+ click: true,
706
+ })}
711
707
  >
712
708
  ${originLabel}
713
- </devtools-menu-item>
714
- </devtools-select-menu>
709
+ </option>
710
+ </select>
715
711
  `;
716
- /* eslint-enable @devtools/no-deprecated-component-usages */
717
712
  }
718
713
 
719
714
  function renderDeviceScopeSetting(input: ViewInput): Lit.LitTemplate {
@@ -726,35 +721,35 @@ function renderDeviceScopeSetting(input: ViewInput): Lit.LitTemplate {
726
721
  const shouldDisable = !input.cruxManager.getFieldResponse(input.cruxManager.fieldPageScope, 'ALL');
727
722
 
728
723
  const currentDeviceLabel = getLabelForDeviceOption(input.cruxManager, input.cruxManager.fieldDeviceOption);
724
+ const accessibleTitle = i18nString(UIStrings.showFieldDataForDevice, {PH1: currentDeviceLabel});
729
725
 
730
726
  // clang-format off
731
- /* eslint-disable @devtools/no-deprecated-component-usages */
732
727
  return html`
733
- <devtools-select-menu
734
- id="device-scope-select"
735
- class="field-data-option"
736
- @selectmenuselected=${input.handleDeviceOptionSelected}
737
- .showDivider=${true}
738
- .showArrow=${true}
739
- .sideButton=${false}
740
- .showSelectedItem=${true}
741
- .buttonTitle=${i18nString(UIStrings.device, {PH1: currentDeviceLabel})}
742
- .disabled=${shouldDisable}
743
- title=${i18nString(UIStrings.showFieldDataForDevice, {PH1: currentDeviceLabel})}
744
- >
745
- ${DEVICE_OPTION_LIST.map(deviceOption => {
746
- return html`
747
- <devtools-menu-item
748
- .value=${deviceOption}
749
- .selected=${input.cruxManager.fieldDeviceOption === deviceOption}
750
- >
751
- ${getLabelForDeviceOption(input.cruxManager, deviceOption)}
752
- </devtools-menu-item>
753
- `;
754
- })}
755
- </devtools-select-menu>
728
+ <label class="field-data-option">
729
+ ${i18nString(UIStrings.device)}
730
+ <select
731
+ id="device-scope-select"
732
+ @change=${(e: Event) => input.handleDeviceOptionSelected((e.target as HTMLSelectElement).value as DeviceOption)}
733
+ ?disabled=${shouldDisable}
734
+ title=${accessibleTitle}
735
+ aria-label=${accessibleTitle}
736
+ .value=${live(input.cruxManager.fieldDeviceOption)}
737
+ jslog=${VisualLogging.dropDown('device-scope').track({change: true})}
738
+ >
739
+ ${DEVICE_OPTION_LIST.map(deviceOption => {
740
+ return html`
741
+ <option
742
+ value=${deviceOption}
743
+ ?selected=${input.cruxManager.fieldDeviceOption === deviceOption}
744
+ jslog=${VisualLogging.item(Platform.StringUtilities.toKebabCase(deviceOption)).track({click: true})}
745
+ >
746
+ ${getLabelForDeviceOption(input.cruxManager, deviceOption)}
747
+ </option>
748
+ `;
749
+ })}
750
+ </select>
751
+ </label>
756
752
  `;
757
- /* eslint-enable @devtools/no-deprecated-component-usages */
758
753
  // clang-format on
759
754
  }
760
755
 
@@ -1229,8 +1224,8 @@ export class LiveMetricsView extends UI.Widget.Widget {
1229
1224
  EmulationModel.DeviceModeModel.Events.UPDATED, this.#onEmulationChanged, this);
1230
1225
  }
1231
1226
 
1232
- #onPageScopeMenuItemSelected(event: Menus.SelectMenu.SelectMenuItemSelectedEvent): void {
1233
- if (event.itemValue === 'url') {
1227
+ #onPageScopeMenuItemSelected(pageScope: CrUXManager.PageScope): void {
1228
+ if (pageScope === 'url') {
1234
1229
  this.#cruxManager.fieldPageScope = 'url';
1235
1230
  } else {
1236
1231
  this.#cruxManager.fieldPageScope = 'origin';
@@ -1238,8 +1233,8 @@ export class LiveMetricsView extends UI.Widget.Widget {
1238
1233
  this.requestUpdate();
1239
1234
  }
1240
1235
 
1241
- #onDeviceOptionMenuItemSelected(event: Menus.SelectMenu.SelectMenuItemSelectedEvent): void {
1242
- this.#cruxManager.fieldDeviceOption = event.itemValue as DeviceOption;
1236
+ #onDeviceOptionMenuItemSelected(deviceOption: DeviceOption): void {
1237
+ this.#cruxManager.fieldDeviceOption = deviceOption;
1243
1238
  this.requestUpdate();
1244
1239
  }
1245
1240
 
@@ -115,7 +115,7 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
115
115
  }
116
116
  // clang-format off
117
117
  Lit.render(html`
118
- <devtools-data-grid striped inline
118
+ <devtools-data-grid striped inline deletable
119
119
  @click=${(e: Event) => { e.stopPropagation(); }}
120
120
  @create=${input.onCreate}>
121
121
  <table>
@@ -57,7 +57,7 @@ const UIStrings = {
57
57
  * @description Accessible label for the button to expand an insight to view details in the Performance panel sidebar.
58
58
  * @example {LCP breakdown} PH1
59
59
  */
60
- viewDetails: 'View details for {PH1} insight.',
60
+ viewDetails: 'View details for {PH1} insight',
61
61
  } as const;
62
62
 
63
63
  const str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/BaseInsightComponent.ts', UIStrings);
@@ -108,8 +108,7 @@ const DEFAULT_VIEW: View = (input, _output, target) => {
108
108
 
109
109
  let ariaLabel = `${i18nString(UIStrings.viewDetails, {PH1: model.title})}`;
110
110
  if (estimatedSavingsAriaLabel) {
111
- // space prefix is deliberate to add a gap after the view details text
112
- ariaLabel += ` ${estimatedSavingsAriaLabel}`;
111
+ ariaLabel += `. ${estimatedSavingsAriaLabel}`;
113
112
  }
114
113
 
115
114
  function renderInsightContent(): Lit.LitTemplate {
@@ -269,6 +269,7 @@
269
269
  }
270
270
 
271
271
  .field-data-option {
272
+ display: block;
272
273
  margin: var(--sys-size-5) 0;
273
274
  max-width: 100%;
274
275
  }
@@ -1,7 +1,7 @@
1
1
  Name: Dependencies sourced from the upstream `chromium` repository
2
2
  URL: Internal
3
3
  Version: N/A
4
- Revision: 87625275b7c30150efc10c7dbf7c86982459704f
4
+ Revision: 9d63ca908583451379cc48bc4e3cc2e5c7041395
5
5
  Update Mechanism: Manual (https://crbug.com/428069060)
6
6
  License: BSD-3-Clause
7
7
  License File: LICENSE