chrome-devtools-frontend 1.0.995629 → 1.0.997048

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 (119) hide show
  1. package/AUTHORS +1 -0
  2. package/front_end/core/i18n/locales/af.json +96 -42
  3. package/front_end/core/i18n/locales/am.json +97 -43
  4. package/front_end/core/i18n/locales/ar.json +95 -41
  5. package/front_end/core/i18n/locales/as.json +95 -41
  6. package/front_end/core/i18n/locales/az.json +96 -42
  7. package/front_end/core/i18n/locales/be.json +124 -70
  8. package/front_end/core/i18n/locales/bg.json +96 -42
  9. package/front_end/core/i18n/locales/bn.json +95 -41
  10. package/front_end/core/i18n/locales/bs.json +95 -41
  11. package/front_end/core/i18n/locales/ca.json +96 -42
  12. package/front_end/core/i18n/locales/cs.json +95 -41
  13. package/front_end/core/i18n/locales/cy.json +95 -41
  14. package/front_end/core/i18n/locales/da.json +97 -43
  15. package/front_end/core/i18n/locales/de.json +96 -42
  16. package/front_end/core/i18n/locales/el.json +95 -41
  17. package/front_end/core/i18n/locales/en-GB.json +95 -41
  18. package/front_end/core/i18n/locales/en-US.json +32 -5
  19. package/front_end/core/i18n/locales/en-XL.json +32 -5
  20. package/front_end/core/i18n/locales/es-419.json +95 -41
  21. package/front_end/core/i18n/locales/es.json +101 -47
  22. package/front_end/core/i18n/locales/et.json +95 -41
  23. package/front_end/core/i18n/locales/eu.json +100 -46
  24. package/front_end/core/i18n/locales/fa.json +104 -50
  25. package/front_end/core/i18n/locales/fi.json +95 -41
  26. package/front_end/core/i18n/locales/fil.json +95 -41
  27. package/front_end/core/i18n/locales/fr-CA.json +96 -42
  28. package/front_end/core/i18n/locales/fr.json +95 -41
  29. package/front_end/core/i18n/locales/gl.json +104 -50
  30. package/front_end/core/i18n/locales/gu.json +95 -41
  31. package/front_end/core/i18n/locales/he.json +95 -41
  32. package/front_end/core/i18n/locales/hi.json +98 -44
  33. package/front_end/core/i18n/locales/hr.json +96 -42
  34. package/front_end/core/i18n/locales/hu.json +96 -42
  35. package/front_end/core/i18n/locales/hy.json +95 -41
  36. package/front_end/core/i18n/locales/id.json +97 -43
  37. package/front_end/core/i18n/locales/is.json +95 -41
  38. package/front_end/core/i18n/locales/it.json +96 -42
  39. package/front_end/core/i18n/locales/ja.json +95 -41
  40. package/front_end/core/i18n/locales/ka.json +95 -41
  41. package/front_end/core/i18n/locales/kk.json +98 -44
  42. package/front_end/core/i18n/locales/km.json +95 -41
  43. package/front_end/core/i18n/locales/kn.json +96 -42
  44. package/front_end/core/i18n/locales/ko.json +96 -42
  45. package/front_end/core/i18n/locales/ky.json +97 -43
  46. package/front_end/core/i18n/locales/lo.json +96 -42
  47. package/front_end/core/i18n/locales/lt.json +95 -41
  48. package/front_end/core/i18n/locales/lv.json +95 -41
  49. package/front_end/core/i18n/locales/mk.json +98 -44
  50. package/front_end/core/i18n/locales/ml.json +96 -42
  51. package/front_end/core/i18n/locales/mn.json +96 -42
  52. package/front_end/core/i18n/locales/mr.json +95 -41
  53. package/front_end/core/i18n/locales/ms.json +95 -41
  54. package/front_end/core/i18n/locales/my.json +95 -41
  55. package/front_end/core/i18n/locales/ne.json +100 -46
  56. package/front_end/core/i18n/locales/nl.json +99 -45
  57. package/front_end/core/i18n/locales/no.json +95 -41
  58. package/front_end/core/i18n/locales/or.json +98 -44
  59. package/front_end/core/i18n/locales/pa.json +95 -41
  60. package/front_end/core/i18n/locales/pl.json +95 -41
  61. package/front_end/core/i18n/locales/pt-PT.json +95 -41
  62. package/front_end/core/i18n/locales/pt.json +98 -44
  63. package/front_end/core/i18n/locales/ro.json +96 -42
  64. package/front_end/core/i18n/locales/ru.json +115 -61
  65. package/front_end/core/i18n/locales/si.json +96 -42
  66. package/front_end/core/i18n/locales/sk.json +95 -41
  67. package/front_end/core/i18n/locales/sl.json +95 -41
  68. package/front_end/core/i18n/locales/sq.json +96 -42
  69. package/front_end/core/i18n/locales/sr-Latn.json +96 -42
  70. package/front_end/core/i18n/locales/sr.json +96 -42
  71. package/front_end/core/i18n/locales/sv.json +96 -42
  72. package/front_end/core/i18n/locales/sw.json +97 -43
  73. package/front_end/core/i18n/locales/ta.json +96 -42
  74. package/front_end/core/i18n/locales/te.json +108 -54
  75. package/front_end/core/i18n/locales/th.json +95 -41
  76. package/front_end/core/i18n/locales/tr.json +95 -41
  77. package/front_end/core/i18n/locales/uk.json +95 -41
  78. package/front_end/core/i18n/locales/ur.json +95 -41
  79. package/front_end/core/i18n/locales/uz.json +95 -41
  80. package/front_end/core/i18n/locales/vi.json +104 -50
  81. package/front_end/core/i18n/locales/zh-HK.json +96 -42
  82. package/front_end/core/i18n/locales/zh-TW.json +97 -43
  83. package/front_end/core/i18n/locales/zh.json +99 -45
  84. package/front_end/core/i18n/locales/zu.json +95 -41
  85. package/front_end/core/root/Runtime.ts +5 -0
  86. package/front_end/core/sdk/CSSMatchedStyles.ts +158 -33
  87. package/front_end/core/sdk/CSSMetadata.ts +1 -8
  88. package/front_end/core/sdk/DebuggerModel.ts +1 -1
  89. package/front_end/generated/InspectorBackendCommands.js +33 -2
  90. package/front_end/generated/protocol.ts +42 -7
  91. package/front_end/models/bindings/BreakpointManager.ts +12 -3
  92. package/front_end/models/issues_manager/DeprecationIssue.ts +3 -3
  93. package/front_end/panels/changes/ChangesView.ts +25 -10
  94. package/front_end/panels/elements/ElementsPanel.ts +7 -6
  95. package/front_end/panels/elements/StylesSidebarPane.ts +55 -21
  96. package/front_end/panels/elements/components/adornerSettingsPane.css +5 -0
  97. package/front_end/panels/elements/stylesSectionTree.css +5 -4
  98. package/front_end/panels/elements/stylesSidebarPane.css +1 -1
  99. package/front_end/panels/lighthouse/LighthouseController.ts +38 -7
  100. package/front_end/panels/lighthouse/LighthousePanel.ts +1 -1
  101. package/front_end/panels/lighthouse/LighthouseStartView.ts +15 -7
  102. package/front_end/panels/lighthouse/LighthouseStartViewFR.ts +77 -21
  103. package/front_end/panels/lighthouse/RadioSetting.ts +12 -6
  104. package/front_end/panels/lighthouse/lighthouseStartView.css +49 -2
  105. package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +1 -0
  106. package/front_end/panels/security/SecurityPanel.ts +2 -2
  107. package/front_end/panels/sources/DebuggerPlugin.ts +6 -2
  108. package/front_end/panels/sources/SourcesPanel.ts +22 -6
  109. package/front_end/panels/sources/sources-legacy.ts +1 -1
  110. package/front_end/panels/sources/sources-meta.ts +61 -7
  111. package/front_end/ui/components/diff_view/diffView.css +2 -0
  112. package/front_end/ui/components/tree_outline/TreeOutline.ts +18 -7
  113. package/front_end/ui/legacy/SplitWidget.ts +17 -7
  114. package/front_end/ui/legacy/Toolbar.ts +5 -0
  115. package/front_end/ui/legacy/softDropDownButton.css +4 -0
  116. package/package.json +2 -1
  117. package/scripts/eslint_rules/lib/inline_type_imports.js +158 -0
  118. package/scripts/eslint_rules/tests/inline_type_imports_test.js +106 -0
  119. package/scripts/javascript_natives/index.js +1 -2
@@ -1020,38 +1020,69 @@ export namespace Audits {
1020
1020
 
1021
1021
  export const enum DeprecationIssueType {
1022
1022
  AuthorizationCoveredByWildcard = 'AuthorizationCoveredByWildcard',
1023
+ BatteryStatusInsecureOrigin = 'BatteryStatusInsecureOrigin',
1024
+ CanRequestURLHTTPContainingNewline = 'CanRequestURLHTTPContainingNewline',
1025
+ ChromeLoadTimesConnectionInfo = 'ChromeLoadTimesConnectionInfo',
1026
+ ChromeLoadTimesFirstPaintAfterLoadTime = 'ChromeLoadTimesFirstPaintAfterLoadTime',
1027
+ ChromeLoadTimesWasAlternateProtocolAvailable = 'ChromeLoadTimesWasAlternateProtocolAvailable',
1023
1028
  CookieWithTruncatingChar = 'CookieWithTruncatingChar',
1024
1029
  CrossOriginAccessBasedOnDocumentDomain = 'CrossOriginAccessBasedOnDocumentDomain',
1025
1030
  CrossOriginWindowAlert = 'CrossOriginWindowAlert',
1026
1031
  CrossOriginWindowConfirm = 'CrossOriginWindowConfirm',
1032
+ CSSSelectorInternalMediaControlsOverlayCastButton = 'CSSSelectorInternalMediaControlsOverlayCastButton',
1033
+ CustomCursorIntersectsViewport = 'CustomCursorIntersectsViewport',
1027
1034
  DeprecationExample = 'DeprecationExample',
1028
1035
  DocumentDomainSettingWithoutOriginAgentClusterHeader = 'DocumentDomainSettingWithoutOriginAgentClusterHeader',
1036
+ EventPath = 'EventPath',
1029
1037
  GeolocationInsecureOrigin = 'GeolocationInsecureOrigin',
1030
1038
  GeolocationInsecureOriginDeprecatedNotRemoved = 'GeolocationInsecureOriginDeprecatedNotRemoved',
1031
1039
  GetUserMediaInsecureOrigin = 'GetUserMediaInsecureOrigin',
1040
+ HostCandidateAttributeGetter = 'HostCandidateAttributeGetter',
1041
+ InsecurePrivateNetworkSubresourceRequest = 'InsecurePrivateNetworkSubresourceRequest',
1032
1042
  LegacyConstraintGoogCpuOveruseDetection = 'LegacyConstraintGoogCpuOveruseDetection',
1033
1043
  LegacyConstraintGoogIPv6 = 'LegacyConstraintGoogIPv6',
1034
1044
  LegacyConstraintGoogScreencastMinBitrate = 'LegacyConstraintGoogScreencastMinBitrate',
1035
1045
  LegacyConstraintGoogSuspendBelowMinBitrate = 'LegacyConstraintGoogSuspendBelowMinBitrate',
1036
1046
  LocalCSSFileExtensionRejected = 'LocalCSSFileExtensionRejected',
1047
+ MediaElementAudioSourceNode = 'MediaElementAudioSourceNode',
1048
+ MediaSourceAbortRemove = 'MediaSourceAbortRemove',
1049
+ MediaSourceDurationTruncatingBuffered = 'MediaSourceDurationTruncatingBuffered',
1050
+ NoSysexWebMIDIWithoutPermission = 'NoSysexWebMIDIWithoutPermission',
1037
1051
  NotificationInsecureOrigin = 'NotificationInsecureOrigin',
1052
+ NotificationPermissionRequestedIframe = 'NotificationPermissionRequestedIframe',
1038
1053
  ObsoleteWebRtcCipherSuite = 'ObsoleteWebRtcCipherSuite',
1054
+ PaymentRequestBasicCard = 'PaymentRequestBasicCard',
1055
+ PaymentRequestShowWithoutGesture = 'PaymentRequestShowWithoutGesture',
1039
1056
  PictureSourceSrc = 'PictureSourceSrc',
1040
1057
  PrefixedCancelAnimationFrame = 'PrefixedCancelAnimationFrame',
1041
1058
  PrefixedRequestAnimationFrame = 'PrefixedRequestAnimationFrame',
1059
+ PrefixedStorageInfo = 'PrefixedStorageInfo',
1060
+ PrefixedVideoDisplayingFullscreen = 'PrefixedVideoDisplayingFullscreen',
1061
+ PrefixedVideoEnterFullscreen = 'PrefixedVideoEnterFullscreen',
1062
+ PrefixedVideoEnterFullScreen = 'PrefixedVideoEnterFullScreen',
1063
+ PrefixedVideoExitFullscreen = 'PrefixedVideoExitFullscreen',
1064
+ PrefixedVideoExitFullScreen = 'PrefixedVideoExitFullScreen',
1065
+ PrefixedVideoSupportsFullscreen = 'PrefixedVideoSupportsFullscreen',
1066
+ RangeExpand = 'RangeExpand',
1067
+ RequestedSubresourceWithEmbeddedCredentials = 'RequestedSubresourceWithEmbeddedCredentials',
1042
1068
  RTCConstraintEnableDtlsSrtpFalse = 'RTCConstraintEnableDtlsSrtpFalse',
1043
1069
  RTCConstraintEnableDtlsSrtpTrue = 'RTCConstraintEnableDtlsSrtpTrue',
1044
1070
  RTCPeerConnectionComplexPlanBSdpUsingDefaultSdpSemantics =
1045
1071
  'RTCPeerConnectionComplexPlanBSdpUsingDefaultSdpSemantics',
1046
1072
  RTCPeerConnectionLegacyCreateWithMediaConstraints = 'RTCPeerConnectionLegacyCreateWithMediaConstraints',
1073
+ RTCPeerConnectionSdpSemanticsPlanB = 'RTCPeerConnectionSdpSemanticsPlanB',
1074
+ RtcpMuxPolicyNegotiate = 'RtcpMuxPolicyNegotiate',
1047
1075
  RTPDataChannel = 'RTPDataChannel',
1076
+ SelectionAddRangeIntersect = 'SelectionAddRangeIntersect',
1048
1077
  SharedArrayBufferConstructedWithoutIsolation = 'SharedArrayBufferConstructedWithoutIsolation',
1078
+ TextToSpeech_DisallowedByAutoplay = 'TextToSpeech_DisallowedByAutoplay',
1049
1079
  Untranslated = 'Untranslated',
1050
1080
  V8SharedArrayBufferConstructedInExtensionWithoutIsolation =
1051
1081
  'V8SharedArrayBufferConstructedInExtensionWithoutIsolation',
1052
1082
  WebCodecsVideoFrameDefaultTimestamp = 'WebCodecsVideoFrameDefaultTimestamp',
1053
1083
  XHRJSONEncodingDetection = 'XHRJSONEncodingDetection',
1054
1084
  XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload = 'XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload',
1085
+ XRSupportsSession = 'XRSupportsSession',
1055
1086
  }
1056
1087
 
1057
1088
  /**
@@ -5162,6 +5193,8 @@ export namespace Emulation {
5162
5193
  architecture: string;
5163
5194
  model: string;
5164
5195
  mobile: boolean;
5196
+ bitness?: string;
5197
+ wow64?: boolean;
5165
5198
  }
5166
5199
 
5167
5200
  /**
@@ -10200,6 +10233,7 @@ export namespace Page {
10200
10233
  InterestCohort = 'interest-cohort',
10201
10234
  JoinAdInterestGroup = 'join-ad-interest-group',
10202
10235
  KeyboardMap = 'keyboard-map',
10236
+ LocalFonts = 'local-fonts',
10203
10237
  Magnetometer = 'magnetometer',
10204
10238
  Microphone = 'microphone',
10205
10239
  Midi = 'midi',
@@ -11300,15 +11334,16 @@ export namespace Page {
11300
11334
  */
11301
11335
  marginRight?: number;
11302
11336
  /**
11303
- * Paper ranges to print, e.g., '1-5, 8, 11-13'. Defaults to the empty string, which means
11304
- * print all pages.
11337
+ * Paper ranges to print, one based, e.g., '1-5, 8, 11-13'. Pages are
11338
+ * printed in the document order, not in the order specified, and no
11339
+ * more than once.
11340
+ * Defaults to empty string, which implies the entire document is printed.
11341
+ * The page numbers are quietly capped to actual page count of the
11342
+ * document, and ranges beyond the end of the document are ignored.
11343
+ * If this results in no pages to print, an error is reported.
11344
+ * It is an error to specify a range with start greater than end.
11305
11345
  */
11306
11346
  pageRanges?: string;
11307
- /**
11308
- * Whether to silently ignore invalid but successfully parsed page ranges, such as '3-2'.
11309
- * Defaults to false.
11310
- */
11311
- ignoreInvalidPageRanges?: boolean;
11312
11347
  /**
11313
11348
  * HTML template for the print header. Should be valid HTML markup with following
11314
11349
  * classes used to inject printing values into them:
@@ -100,11 +100,12 @@ export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventT
100
100
 
101
101
  modelAdded(debuggerModel: SDK.DebuggerModel.DebuggerModel): void {
102
102
  if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.INSTRUMENTATION_BREAKPOINTS)) {
103
- debuggerModel.setSynchronizeBreakpointsCallback(this.#restoreBreakpointsForScript.bind(this));
103
+ debuggerModel.setSynchronizeBreakpointsCallback(this.restoreBreakpointsForScript.bind(this));
104
104
  }
105
105
  }
106
106
 
107
- modelRemoved(): void {
107
+ modelRemoved(debuggerModel: SDK.DebuggerModel.DebuggerModel): void {
108
+ debuggerModel.setSynchronizeBreakpointsCallback(null);
108
109
  }
109
110
 
110
111
  async copyBreakpoints(fromURL: Platform.DevToolsPath.UrlString, toSourceCode: Workspace.UISourceCode.UISourceCode):
@@ -117,7 +118,7 @@ export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventT
117
118
 
118
119
  // This method explicitly awaits the source map (if necessary) and the uiSourceCodes
119
120
  // required to set all breakpoints that are related to this script.
120
- async #restoreBreakpointsForScript(script: SDK.Script.Script): Promise<void> {
121
+ async restoreBreakpointsForScript(script: SDK.Script.Script): Promise<void> {
121
122
  if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.INSTRUMENTATION_BREAKPOINTS)) {
122
123
  return;
123
124
  }
@@ -416,6 +417,10 @@ export class Breakpoint implements SDK.TargetManager.SDKModelObserver<SDK.Debugg
416
417
  modelBreakpoint.removeEventListeners();
417
418
  }
418
419
 
420
+ modelBreakpoint(debuggerModel: SDK.DebuggerModel.DebuggerModel): ModelBreakpoint|undefined {
421
+ return this.#modelBreakpoints.get(debuggerModel);
422
+ }
423
+
419
424
  addUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
420
425
  if (!this.uiSourceCodes.has(uiSourceCode)) {
421
426
  this.uiSourceCodes.add(uiSourceCode);
@@ -626,6 +631,10 @@ export class ModelBreakpoint {
626
631
  }
627
632
  }
628
633
 
634
+ get currentState(): Breakpoint.State|null {
635
+ return this.#currentState;
636
+ }
637
+
629
638
  resetLocations(): void {
630
639
  for (const uiLocation of this.#uiLocations.values()) {
631
640
  this.#breakpoint.uiLocationRemoved(uiLocation);
@@ -61,12 +61,12 @@ const UIStrings = {
61
61
  documentDomainSettingWithoutOriginAgentClusterHeader:
62
62
  'Relaxing the same-origin policy by setting `document.domain` is deprecated, and will be disabled by default. To continue using this feature, please opt-out of origin-keyed agent clusters by sending an `Origin-Agent-Cluster: ?0` header along with the HTTP response for the document and frames. See https://developer.chrome.com/blog/immutable-document-domain/ for more details.',
63
63
  /**
64
- *@description TODO(crbug.com/1318853): Description needed for translation
64
+ *@description Warning displayed to developers when the Geolocation API is used from an insecure origin (one that isn't localhost or doesn't use HTTPS) to notify them that this use is no longer supported.
65
65
  */
66
66
  geolocationInsecureOrigin:
67
67
  '`getCurrentPosition()` and `watchPosition()` no longer work on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.',
68
68
  /**
69
- *@description TODO(crbug.com/1318855): Description needed for translation
69
+ *@description Warning displayed to developers when the Geolocation API is used from an insecure origin (one that isn't localhost or doesn't use HTTPS) to notify them that this use is deprecated.
70
70
  */
71
71
  geolocationInsecureOriginDeprecatedNotRemoved:
72
72
  '`getCurrentPosition()` and `watchPosition()` are deprecated on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.',
@@ -110,7 +110,7 @@ const UIStrings = {
110
110
  obsoleteWebRtcCipherSuite:
111
111
  'Your partner is negotiating an obsolete (D)TLS version. Please check with your partner to have this fixed.',
112
112
  /**
113
- *@description TODO(crbug.com/1318868): Description needed for translation
113
+ *@description This issue indicates that a `<source>` element with a `<picture>` parent was using an `src` attribute, which is not valid and is ignored by the browser. The `srcset` attribute should be used instead.
114
114
  */
115
115
  pictureSourceSrc:
116
116
  '`<source src>` with a `<picture>` parent is invalid and therefore ignored. Please use `<source srcset>` instead.',
@@ -6,6 +6,7 @@ import * as Common from '../../core/common/common.js';
6
6
  import * as Host from '../../core/host/host.js';
7
7
  import * as i18n from '../../core/i18n/i18n.js';
8
8
  import * as Root from '../../core/root/root.js';
9
+ import type * as Formatter from '../../models/formatter/formatter.js';
9
10
  import {formatCSSChangesFromDiff} from '../../panels/utils/utils.js';
10
11
  import * as Diff from '../../third_party/diff/diff.js';
11
12
  import * as DiffView from '../../ui/components/diff_view/diff_view.js';
@@ -72,6 +73,7 @@ export class ChangesView extends UI.Widget.VBox {
72
73
  private readonly workspaceDiff: WorkspaceDiff.WorkspaceDiff.WorkspaceDiffImpl;
73
74
  readonly changesSidebar: ChangesSidebar;
74
75
  private selectedUISourceCode: Workspace.UISourceCode.UISourceCode|null;
76
+ #selectedSourceCodeFormattedMapping?: Formatter.ScriptFormatter.FormatterSourceMapping;
75
77
  private readonly diffContainer: HTMLElement;
76
78
  private readonly toolbar: UI.Toolbar.Toolbar;
77
79
  private readonly diffStats: UI.Toolbar.ToolbarText;
@@ -167,16 +169,27 @@ export class ChangesView extends UI.Widget.VBox {
167
169
  if (!this.selectedUISourceCode) {
168
170
  return;
169
171
  }
170
- for (let target: HTMLElement|null = event.target as HTMLElement; target; target = target.parentElement) {
171
- if (target.classList.contains('diff-line-content')) {
172
- const number = target.getAttribute('data-line-number');
173
- if (number) {
174
- // Unfortunately, caretRangeFromPoint is broken in shadow
175
- // roots, which makes determining the character offset more
176
- // work than justified here.
177
- void Common.Revealer.reveal(this.selectedUISourceCode.uiLocation(Number(number) - 1, 0), false);
178
- event.consume(true);
172
+
173
+ for (const target of event.composedPath()) {
174
+ if (!(target instanceof HTMLElement)) {
175
+ continue;
176
+ }
177
+ const selection = target.ownerDocument.getSelection();
178
+ if (selection?.toString()) {
179
+ // We abort source revelation when user has text selection.
180
+ break;
181
+ }
182
+ if (target.classList.contains('diff-line-content') && target.hasAttribute('data-line-number')) {
183
+ let lineNumber = Number(target.dataset.lineNumber) - 1;
184
+ // Unfortunately, caretRangeFromPoint is broken in shadow
185
+ // roots, which makes determining the character offset more
186
+ // work than justified here.
187
+ if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.PRECISE_CHANGES) &&
188
+ this.#selectedSourceCodeFormattedMapping) {
189
+ lineNumber = this.#selectedSourceCodeFormattedMapping.formattedToOriginal(lineNumber, 0)[0];
179
190
  }
191
+ void Common.Revealer.reveal(this.selectedUISourceCode.uiLocation(lineNumber, 0), false);
192
+ event.consume(true);
180
193
  break;
181
194
  } else if (target.classList.contains('diff-listing')) {
182
195
  break;
@@ -220,10 +233,12 @@ export class ChangesView extends UI.Widget.VBox {
220
233
  return;
221
234
  }
222
235
  const diffResponse = await this.workspaceDiff.requestDiff(
223
- uiSourceCode, {shouldFormatDiff: Root.Runtime.experiments.isEnabled('preciseChanges')});
236
+ uiSourceCode,
237
+ {shouldFormatDiff: Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.PRECISE_CHANGES)});
224
238
  if (this.selectedUISourceCode !== uiSourceCode) {
225
239
  return;
226
240
  }
241
+ this.#selectedSourceCodeFormattedMapping = diffResponse?.formattedCurrentMapping;
227
242
  this.renderDiffRows(diffResponse?.diff);
228
243
  }
229
244
 
@@ -878,18 +878,19 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
878
878
  return node;
879
879
  }
880
880
 
881
- async revealAndSelectNode(node: SDK.DOMModel.DOMNode, focus: boolean, omitHighlight?: boolean): Promise<void> {
881
+ async revealAndSelectNode(nodeToReveal: SDK.DOMModel.DOMNode, focus: boolean, omitHighlight?: boolean):
882
+ Promise<void> {
882
883
  this.omitDefaultSelection = true;
883
884
 
884
- node = Common.Settings.Settings.instance().moduleSetting('showUAShadowDOM').get() ?
885
- node :
886
- this.leaveUserAgentShadowDOM(node);
885
+ const node = Common.Settings.Settings.instance().moduleSetting('showUAShadowDOM').get() ?
886
+ nodeToReveal :
887
+ this.leaveUserAgentShadowDOM(nodeToReveal);
887
888
  if (!omitHighlight) {
888
889
  node.highlightForTwoSeconds();
889
890
  }
890
891
 
891
892
  if (this.accessibilityTreeView) {
892
- void this.accessibilityTreeView.revealAndSelectNode(node);
893
+ void this.accessibilityTreeView.revealAndSelectNode(nodeToReveal);
893
894
  }
894
895
 
895
896
  await UI.ViewManager.ViewManager.instance().showView('elements', false, !focus);
@@ -1029,7 +1030,7 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
1029
1030
  };
1030
1031
 
1031
1032
  this.sidebarPaneView = UI.ViewManager.ViewManager.instance().createTabbedLocation(
1032
- () => UI.ViewManager.ViewManager.instance().showView('elements'));
1033
+ () => UI.ViewManager.ViewManager.instance().showView('elements'), 'Styles-pane-sidebar', false, true);
1033
1034
  const tabbedPane = this.sidebarPaneView.tabbedPane();
1034
1035
  if (this.splitMode !== _splitMode.Vertical) {
1035
1036
  this.splitWidget.installResizer(tabbedPane.headerElement());
@@ -859,17 +859,48 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
859
859
  }
860
860
  }
861
861
 
862
- let pseudoTypes: Protocol.DOM.PseudoType[] = [];
863
- const keys = matchedStyles.pseudoTypes();
864
- if (keys.delete(Protocol.DOM.PseudoType.Before)) {
865
- pseudoTypes.push(Protocol.DOM.PseudoType.Before);
866
- }
867
- pseudoTypes = pseudoTypes.concat([...keys].sort());
868
- for (const pseudoType of pseudoTypes) {
862
+ const customHighlightPseudoRulesets: {
863
+ highlightName: string|null,
864
+ pseudoType: Protocol.DOM.PseudoType,
865
+ pseudoStyles: SDK.CSSStyleDeclaration.CSSStyleDeclaration[],
866
+ }[] = Array.from(matchedStyles.customHighlightPseudoNames()).map(highlightName => {
867
+ return {
868
+ 'highlightName': highlightName,
869
+ 'pseudoType': Protocol.DOM.PseudoType.Highlight,
870
+ 'pseudoStyles': matchedStyles.customHighlightPseudoStyles(highlightName),
871
+ };
872
+ });
873
+
874
+ const otherPseudoRulesets: {
875
+ highlightName: string|null,
876
+ pseudoType: Protocol.DOM.PseudoType,
877
+ pseudoStyles: SDK.CSSStyleDeclaration.CSSStyleDeclaration[],
878
+ }[] = [...matchedStyles.pseudoTypes()].map(pseudoType => {
879
+ return {'highlightName': null, 'pseudoType': pseudoType, 'pseudoStyles': matchedStyles.pseudoStyles(pseudoType)};
880
+ });
881
+
882
+ const pseudoRulesets = customHighlightPseudoRulesets.concat(otherPseudoRulesets).sort((a, b) => {
883
+ // We want to show the ::before pseudos first, followed by the remaining pseudos
884
+ // in alphabetical order.
885
+ if (a.pseudoType === Protocol.DOM.PseudoType.Before && b.pseudoType !== Protocol.DOM.PseudoType.Before) {
886
+ return -1;
887
+ }
888
+ if (a.pseudoType !== Protocol.DOM.PseudoType.Before && b.pseudoType === Protocol.DOM.PseudoType.Before) {
889
+ return 1;
890
+ }
891
+ if (a.pseudoType < b.pseudoType) {
892
+ return -1;
893
+ }
894
+ if (a.pseudoType > b.pseudoType) {
895
+ return 1;
896
+ }
897
+ return 0;
898
+ });
899
+
900
+ for (const pseudo of pseudoRulesets) {
869
901
  lastParentNode = null;
870
- const pseudoStyles = matchedStyles.pseudoStyles(pseudoType);
871
- for (let i = 0; i < pseudoStyles.length; ++i) {
872
- const style = pseudoStyles[i];
902
+ for (let i = 0; i < pseudo.pseudoStyles.length; ++i) {
903
+ const style = pseudo.pseudoStyles[i];
873
904
  const parentNode = matchedStyles.isInherited(style) ? matchedStyles.nodeForStyle(style) : null;
874
905
 
875
906
  // Start a new SectionBlock if this is the first rule for this pseudo type, or if this
@@ -877,10 +908,11 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
877
908
  if (i === 0 || parentNode !== lastParentNode) {
878
909
  lastLayers = null;
879
910
  if (parentNode) {
880
- const block = await SectionBlock.createInheritedPseudoTypeBlock(pseudoType, parentNode);
911
+ const block =
912
+ await SectionBlock.createInheritedPseudoTypeBlock(pseudo.pseudoType, pseudo.highlightName, parentNode);
881
913
  blocks.push(block);
882
914
  } else {
883
- const block = SectionBlock.createPseudoTypeBlock(pseudoType);
915
+ const block = SectionBlock.createPseudoTypeBlock(pseudo.pseudoType, pseudo.highlightName);
884
916
  blocks.push(block);
885
917
  }
886
918
  }
@@ -889,9 +921,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
889
921
  addLayerSeparator(style);
890
922
  const lastBlock = blocks[blocks.length - 1];
891
923
  this.idleCallbackManager.schedule(() => {
892
- const section = SDK.CSSMetadata.cssMetadata().isHighlightPseudoType(pseudoType) ?
893
- new HighlightPseudoStylePropertiesSection(this, matchedStyles, style, sectionIdx) :
894
- new StylePropertiesSection(this, matchedStyles, style, sectionIdx);
924
+ const section = new HighlightPseudoStylePropertiesSection(this, matchedStyles, style, sectionIdx);
895
925
  sectionIdx++;
896
926
  lastBlock.sections.push(section);
897
927
  });
@@ -1287,19 +1317,23 @@ export class SectionBlock {
1287
1317
  this.sections = [];
1288
1318
  }
1289
1319
 
1290
- static createPseudoTypeBlock(pseudoType: Protocol.DOM.PseudoType): SectionBlock {
1320
+ static createPseudoTypeBlock(pseudoType: Protocol.DOM.PseudoType, pseudoArgument: string|null): SectionBlock {
1291
1321
  const separatorElement = document.createElement('div');
1292
1322
  separatorElement.className = 'sidebar-separator';
1293
- separatorElement.textContent = i18nString(UIStrings.pseudoSElement, {PH1: pseudoType});
1323
+ const pseudoArgumentString = pseudoArgument ? `(${pseudoArgument})` : '';
1324
+ const pseudoTypeString = `${pseudoType}${pseudoArgumentString}`;
1325
+ separatorElement.textContent = i18nString(UIStrings.pseudoSElement, {PH1: pseudoTypeString});
1294
1326
  return new SectionBlock(separatorElement);
1295
1327
  }
1296
1328
 
1297
- static async createInheritedPseudoTypeBlock(pseudoType: Protocol.DOM.PseudoType, node: SDK.DOMModel.DOMNode):
1298
- Promise<SectionBlock> {
1329
+ static async createInheritedPseudoTypeBlock(
1330
+ pseudoType: Protocol.DOM.PseudoType, pseudoArgument: string|null,
1331
+ node: SDK.DOMModel.DOMNode): Promise<SectionBlock> {
1299
1332
  const separatorElement = document.createElement('div');
1300
1333
  separatorElement.className = 'sidebar-separator';
1301
-
1302
- UI.UIUtils.createTextChild(separatorElement, i18nString(UIStrings.inheritedFromSPseudoOf, {PH1: pseudoType}));
1334
+ const pseudoArgumentString = pseudoArgument ? `(${pseudoArgument})` : '';
1335
+ const pseudoTypeString = `${pseudoType}${pseudoArgumentString}`;
1336
+ UI.UIUtils.createTextChild(separatorElement, i18nString(UIStrings.inheritedFromSPseudoOf, {PH1: pseudoTypeString}));
1303
1337
  const link = await Common.Linkifier.Linkifier.linkify(node, {
1304
1338
  preventKeyboardFocus: true,
1305
1339
  tooltip: undefined,
@@ -57,6 +57,11 @@
57
57
  border-radius: 2px;
58
58
  }
59
59
 
60
+ .close:hover,
61
+ .close:focus {
62
+ background-color: var(--color-background-elevation-2);
63
+ }
64
+
60
65
  .close::before {
61
66
  transform: rotate(45deg);
62
67
  }
@@ -126,10 +126,15 @@ ol.expanded {
126
126
  opacity: 50%;
127
127
  }
128
128
 
129
+ .changed {
130
+ background-color: var(--color-accent-green-background);
131
+ }
132
+
129
133
  .changed::after {
130
134
  content: "";
131
135
  position: absolute;
132
136
  left: -4px;
137
+ top: 0;
133
138
  width: 2px;
134
139
  height: 100%;
135
140
  background-color: var(--color-accent-green);
@@ -139,10 +144,6 @@ ol.expanded {
139
144
  display: none;
140
145
  }
141
146
 
142
- .changed:hover {
143
- background-color: var(--color-accent-green-background);
144
- }
145
-
146
147
  .changed:hover .copy {
147
148
  position: absolute;
148
149
  right: -4px;
@@ -226,7 +226,7 @@
226
226
  .sidebar-pane-section-toolbar {
227
227
  position: absolute;
228
228
  right: 0;
229
- bottom: 0;
229
+ bottom: -5px;
230
230
  z-index: 0;
231
231
  }
232
232
 
@@ -113,17 +113,29 @@ const UIStrings = {
113
113
  */
114
114
  runLighthouseInMode: 'Run Lighthouse in navigation, timespan, or snapshot mode',
115
115
  /**
116
- * @description Label of a radio option for a Lighthouse mode that audits a page navigation.
116
+ * @description Label of a radio option for a Lighthouse mode that audits a page navigation. This should be marked as the default radio option.
117
117
  */
118
- navigation: 'Navigation',
118
+ navigation: 'Navigation (Default)',
119
+ /**
120
+ * @description Tooltip description of a radio option for a Lighthouse mode that audits a page navigation.
121
+ */
122
+ navigationTooltip: 'Navigation mode analyzes a page load, exactly like the original Lighthouse reports.',
119
123
  /**
120
124
  * @description Label of a radio option for a Lighthouse mode that audits user interactions over a period of time.
121
125
  */
122
126
  timespan: 'Timespan',
127
+ /**
128
+ * @description Tooltip description of a radio option for a Lighthouse mode that audits user interactions over a period of time.
129
+ */
130
+ timespanTooltip: 'Timespan mode analyzes an arbitrary period of time, typically containing user interactions.',
123
131
  /**
124
132
  * @description Label of a radio option for a Lighthouse mode that audits the current page state.
125
133
  */
126
134
  snapshot: 'Snapshot',
135
+ /**
136
+ * @description Tooltip description of a radio option for a Lighthouse mode that audits the current page state.
137
+ */
138
+ snapshotTooltip: 'Snapshot mode analyzes the page in a particular state, typically after user interactions.',
127
139
  /**
128
140
  *@description Text for the mobile platform, as opposed to desktop
129
141
  */
@@ -364,6 +376,9 @@ export class LighthouseController extends Common.ObjectWrapper.ObjectWrapper<Eve
364
376
  this.dispatchEventToListeners(Events.PageAuditabilityChanged, {helpText});
365
377
 
366
378
  void this.hasImportantResourcesNotCleared().then(warning => {
379
+ if (this.getFlags().mode !== 'navigation') {
380
+ warning = '';
381
+ }
367
382
  this.dispatchEventToListeners(Events.PageWarningsChanged, {warning});
368
383
  });
369
384
  }
@@ -456,11 +471,23 @@ export const RuntimeSettings: RuntimeSetting[] = [
456
471
  flags.mode = value;
457
472
  },
458
473
  options: [
459
- {label: i18nLazyString(UIStrings.navigation), value: 'navigation'},
460
- {label: i18nLazyString(UIStrings.timespan), value: 'timespan'},
461
- {label: i18nLazyString(UIStrings.snapshot), value: 'snapshot'},
474
+ {
475
+ label: i18nLazyString(UIStrings.navigation),
476
+ tooltip: i18nLazyString(UIStrings.navigationTooltip),
477
+ value: 'navigation',
478
+ },
479
+ {
480
+ label: i18nLazyString(UIStrings.timespan),
481
+ tooltip: i18nLazyString(UIStrings.timespanTooltip),
482
+ value: 'timespan',
483
+ },
484
+ {
485
+ label: i18nLazyString(UIStrings.snapshot),
486
+ tooltip: i18nLazyString(UIStrings.snapshotTooltip),
487
+ value: 'snapshot',
488
+ },
462
489
  ],
463
- learnMore: undefined,
490
+ learnMore: 'https://web.dev/lighthouse-user-flows/',
464
491
  },
465
492
  {
466
493
  // This setting is disabled, but we keep it around to show in the UI.
@@ -545,7 +572,11 @@ export interface RuntimeSetting {
545
572
  setting: Common.Settings.Setting<string|boolean>;
546
573
  description: () => Common.UIString.LocalizedString;
547
574
  setFlags: (flags: Flags, value: string|boolean) => void;
548
- options?: {label: () => Common.UIString.LocalizedString, value: string}[];
575
+ options?: {
576
+ label: () => Common.UIString.LocalizedString,
577
+ value: string,
578
+ tooltip?: () => Common.UIString.LocalizedString,
579
+ }[];
549
580
  title?: () => Common.UIString.LocalizedString;
550
581
  learnMore?: string;
551
582
  }
@@ -174,7 +174,7 @@ export class LighthousePanel extends UI.Panel.Panel {
174
174
  return;
175
175
  }
176
176
 
177
- this.startView.updateStartButton();
177
+ this.startView.updateMode();
178
178
 
179
179
  this.unauditableExplanation = evt.data.helpText;
180
180
  this.startView.setUnauditableExplanation(evt.data.helpText);
@@ -44,8 +44,8 @@ export class StartView extends UI.Widget.Widget {
44
44
  protected controller: LighthouseController;
45
45
  private readonly settingsToolbarInternal: UI.Toolbar.Toolbar;
46
46
  protected startButton!: HTMLButtonElement;
47
- private helpText?: Element;
48
- private warningText?: Element;
47
+ protected helpText?: Element;
48
+ protected warningText?: Element;
49
49
  private shouldConfirm?: boolean;
50
50
 
51
51
  constructor(controller: LighthouseController) {
@@ -66,6 +66,17 @@ export class StartView extends UI.Widget.Widget {
66
66
  throw new Error(`${settingName} is not a setting with options`);
67
67
  }
68
68
 
69
+ const labelEl = document.createElement('div');
70
+ labelEl.classList.add('lighthouse-form-section-label');
71
+ labelEl.textContent = label;
72
+
73
+ if (runtimeSetting.learnMore) {
74
+ const link =
75
+ UI.XLink.XLink.create(runtimeSetting.learnMore, i18nString(UIStrings.learnMore), 'lighthouse-learn-more');
76
+ labelEl.append(link);
77
+ }
78
+ parentElement.appendChild(labelEl);
79
+
69
80
  const control = new RadioSetting(
70
81
  runtimeSetting.options, runtimeSetting.setting as Common.Settings.Setting<string>,
71
82
  runtimeSetting.description());
@@ -91,7 +102,7 @@ export class StartView extends UI.Widget.Widget {
91
102
  }
92
103
  }
93
104
 
94
- private populateFormControls(fragment: UI.Fragment.Fragment): void {
105
+ protected populateFormControls(fragment: UI.Fragment.Fragment): void {
95
106
  // Populate the device type
96
107
  const deviceTypeFormElements = fragment.$('device-type-form-elements');
97
108
  this.populateRuntimeSettingAsRadio('lighthouse.device_type', i18nString(UIStrings.device), deviceTypeFormElements);
@@ -157,9 +168,6 @@ export class StartView extends UI.Widget.Widget {
157
168
  </div>
158
169
  </div>
159
170
  <div class="lighthouse-form-section">
160
- <div class="lighthouse-form-section-label">
161
- ${i18nString(UIStrings.device)}
162
- </div>
163
171
  <div class="lighthouse-form-elements" $="device-type-form-elements"></div>
164
172
  </div>
165
173
  </form>
@@ -173,7 +181,7 @@ export class StartView extends UI.Widget.Widget {
173
181
  this.contentElement.style.overflow = 'auto';
174
182
  }
175
183
 
176
- updateStartButton(): void {
184
+ updateMode(): void {
177
185
  // Do nothing in default case.
178
186
  }
179
187