chrome-devtools-frontend 1.0.1656897 → 1.0.1657855

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 (113) hide show
  1. package/.agents/skills/devtools-ux-writing-refactor/SKILL.md +125 -0
  2. package/.agents/skills/repro-flaky-tests/SKILL.md +53 -0
  3. package/AUTHORS +2 -0
  4. package/docs/get_the_code.md +6 -6
  5. package/front_end/Images/src/ads.svg +1 -0
  6. package/front_end/Tests.js +1 -1
  7. package/front_end/core/common/ResourceType.ts +19 -19
  8. package/front_end/core/common/Revealer.ts +15 -15
  9. package/front_end/core/common/SettingRegistration.ts +19 -19
  10. package/front_end/core/common/Settings.ts +0 -8
  11. package/front_end/core/host/Platform.ts +4 -0
  12. package/front_end/core/sdk/CSSMetadata.ts +121 -16
  13. package/front_end/core/sdk/CSSModel.ts +3 -0
  14. package/front_end/core/sdk/DOMModel.ts +37 -8
  15. package/front_end/core/sdk/DebuggerModel.ts +5 -4
  16. package/front_end/core/sdk/EmulationModel.ts +6 -4
  17. package/front_end/core/sdk/NetworkManager.ts +22 -17
  18. package/front_end/core/sdk/RuntimeModel.ts +1 -1
  19. package/front_end/core/sdk/TargetManager.ts +10 -0
  20. package/front_end/design_system_tokens.css +6 -0
  21. package/front_end/entrypoints/devtools_app/devtools_app.ts +1 -1
  22. package/front_end/entrypoints/formatter_worker/CSSFormatter.ts +13 -4
  23. package/front_end/entrypoints/formatter_worker/FormatterWorker.ts +23 -4
  24. package/front_end/entrypoints/formatter_worker/HTMLFormatter.ts +7 -6
  25. package/front_end/entrypoints/inspector_main/InspectorMain.ts +1 -11
  26. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +1 -1
  27. package/front_end/entrypoints/main/GlobalAiButton.ts +29 -35
  28. package/front_end/entrypoints/main/MainImpl.ts +7 -34
  29. package/front_end/entrypoints/main/main-meta.ts +9 -9
  30. package/front_end/entrypoints/node_app/app/NodeConnectionsPanel.ts +7 -8
  31. package/front_end/entrypoints/node_app/app/NodeMain.ts +3 -3
  32. package/front_end/entrypoints/node_app/node_app.ts +7 -7
  33. package/front_end/foundation/Universe.ts +60 -1
  34. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  35. package/front_end/generated/protocol.ts +4 -0
  36. package/front_end/models/ai_assistance/AiUtils.ts +6 -6
  37. package/front_end/models/bindings/CSSWorkspaceBinding.ts +8 -5
  38. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +13 -15
  39. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +6 -3
  40. package/front_end/models/bindings/FileUtils.ts +11 -12
  41. package/front_end/models/emulation/DeviceModeModel.ts +56 -37
  42. package/front_end/models/emulation/EmulatedDevices.ts +3 -3
  43. package/front_end/models/live-metrics/LiveMetrics.ts +47 -23
  44. package/front_end/models/project_settings/ProjectSettingsModel.ts +2 -37
  45. package/front_end/models/workspace/FileManager.ts +9 -6
  46. package/front_end/models/workspace_diff/WorkspaceDiff.ts +23 -12
  47. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +2 -1
  48. package/front_end/panels/application/ApplicationPanelSidebar.ts +9 -1
  49. package/front_end/panels/application/BackgroundServiceView.ts +2 -1
  50. package/front_end/panels/application/IndexedDBViews.ts +52 -23
  51. package/front_end/panels/application/ServiceWorkersView.ts +9 -20
  52. package/front_end/panels/application/components/AdsView.ts +1 -1
  53. package/front_end/panels/application/components/StorageMetadataView.ts +7 -2
  54. package/front_end/panels/application/resourcesSidebar.css +5 -0
  55. package/front_end/panels/common/BadgeNotification.ts +1 -1
  56. package/front_end/panels/console/ConsoleContextSelector.ts +3 -3
  57. package/front_end/panels/console/ConsoleInsightTeaser.ts +2 -1
  58. package/front_end/panels/console/ConsolePinPane.ts +10 -10
  59. package/front_end/panels/console/ConsolePrompt.ts +4 -4
  60. package/front_end/panels/console/ConsoleSidebar.ts +7 -7
  61. package/front_end/panels/console/ConsoleView.ts +44 -43
  62. package/front_end/panels/console/ConsoleViewMessage.ts +40 -40
  63. package/front_end/panels/console/console-meta.ts +34 -34
  64. package/front_end/panels/coverage/CoverageView.ts +1 -1
  65. package/front_end/panels/developer_resources/DeveloperResourcesListView.ts +19 -20
  66. package/front_end/panels/developer_resources/DeveloperResourcesView.ts +6 -8
  67. package/front_end/panels/developer_resources/developer_resources-meta.ts +2 -2
  68. package/front_end/panels/elements/ElementsTreeElement.ts +253 -144
  69. package/front_end/panels/elements/ElementsTreeOutline.ts +3 -2
  70. package/front_end/panels/elements/components/AdornerManager.ts +1 -0
  71. package/front_end/panels/emulation/DeviceModeToolbar.ts +19 -19
  72. package/front_end/panels/explain/components/ConsoleInsight.ts +2 -1
  73. package/front_end/panels/media/EventDisplayTable.ts +2 -2
  74. package/front_end/panels/media/EventTimelineView.ts +4 -4
  75. package/front_end/panels/media/MainView.ts +4 -4
  76. package/front_end/panels/media/PlayerDetailView.ts +5 -5
  77. package/front_end/panels/media/PlayerListView.ts +1 -1
  78. package/front_end/panels/media/PlayerMessagesView.ts +12 -12
  79. package/front_end/panels/media/PlayerPropertiesView.ts +17 -17
  80. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +13 -12
  81. package/front_end/panels/mobile_throttling/ThrottlingManager.ts +8 -7
  82. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +6 -7
  83. package/front_end/panels/mobile_throttling/mobile_throttling-meta.ts +3 -2
  84. package/front_end/panels/network/NetworkLogView.ts +2 -1
  85. package/front_end/panels/network/NetworkWaterfallColumn.ts +1 -3
  86. package/front_end/panels/network/RequestConditionsDrawer.ts +2 -2
  87. package/front_end/panels/network/networkPanel.css +1 -0
  88. package/front_end/panels/network/networkTimingTable.css +1 -1
  89. package/front_end/panels/profiler/HeapSnapshotView.ts +2 -1
  90. package/front_end/panels/profiler/ProfileView.ts +2 -1
  91. package/front_end/panels/protocol_monitor/JSONEditor.ts +10 -10
  92. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +28 -32
  93. package/front_end/panels/protocol_monitor/protocol_monitor-meta.ts +1 -1
  94. package/front_end/panels/recorder/RecorderController.ts +1 -0
  95. package/front_end/panels/recorder/RecorderEvents.ts +8 -0
  96. package/front_end/panels/settings/components/SyncSection.ts +2 -1
  97. package/front_end/panels/timeline/AppenderUtils.ts +12 -4
  98. package/front_end/panels/timeline/ThreadAppender.ts +3 -3
  99. package/front_end/panels/timeline/TimelinePanel.ts +5 -5
  100. package/front_end/panels/timeline/timelineFlameChartView.css +2 -1
  101. package/front_end/panels/webauthn/WebauthnPane.ts +10 -10
  102. package/front_end/third_party/chromium/README.chromium +1 -1
  103. package/front_end/third_party/chromium/ahem/ahem.js +792 -0
  104. package/front_end/tsconfig.json +7 -1
  105. package/front_end/ui/components/dialogs/shortcutDialog.css +15 -12
  106. package/front_end/ui/legacy/ActionRegistration.ts +1 -1
  107. package/front_end/ui/legacy/InspectorView.ts +1 -1
  108. package/front_end/ui/legacy/Treeoutline.ts +15 -0
  109. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +109 -23
  110. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +5 -0
  111. package/front_end/ui/legacy/theme_support/ThemeSupport.ts +2 -2
  112. package/front_end/ui/visual_logging/KnownContextValues.ts +4 -0
  113. package/package.json +1 -1
@@ -476,13 +476,24 @@ export function cssMetadata(): CSSMetadata {
476
476
 
477
477
  /**
478
478
  * The pipe character '|' indicates where text selection should be set.
479
+ *
480
+ * Spec: https://drafts.csswg.org/css-images-4/#image-values
481
+ * <image> = <url> | <image()> | <image-set()> | <cross-fade()> | <element()> | <gradient>
482
+ * <gradient> = [
483
+ * <linear-gradient()> | <repeating-linear-gradient()> |
484
+ * <radial-gradient()> | <repeating-radial-gradient()> |
485
+ * <conic-gradient()> | <repeating-conic-gradient()> ]
479
486
  */
480
487
  const imageValuePresetMap = new Map([
481
- ['linear-gradient', 'linear-gradient(|45deg, black, transparent|)'],
482
- ['radial-gradient', 'radial-gradient(|black, transparent|)'],
483
- ['repeating-linear-gradient', 'repeating-linear-gradient(|45deg, black, transparent 100px|)'],
484
- ['repeating-radial-gradient', 'repeating-radial-gradient(|black, transparent 100px|)'],
485
- ['url', 'url(||)'],
488
+ ['linear-gradient()', 'linear-gradient(|45deg, black, transparent|)'],
489
+ ['radial-gradient()', 'radial-gradient(|black, transparent|)'],
490
+ ['conic-gradient()', 'conic-gradient(|from 45deg, red, orange, yellow, green, teal, blue, purple|)'],
491
+ ['repeating-linear-gradient()', 'repeating-linear-gradient(|45deg, black, transparent 100px|)'],
492
+ ['repeating-radial-gradient()', 'repeating-radial-gradient(|black, transparent 100px|)'],
493
+ ['repeating-conic-gradient()', 'repeating-conic-gradient(|black 0deg 25%, white 0deg 50%|)'], // Checkerboard
494
+ ['url()', 'url(||)'],
495
+ ['image-set()', 'image-set(|url("") 1x, url("") 2x|)'],
496
+ ['cross-fade()', 'cross-fade(|url("") 50%, url("") 50%|)'],
486
497
  ]);
487
498
 
488
499
  const filterValuePresetMap = new Map([
@@ -505,8 +516,16 @@ const cornerShapeValuePresetMap = new Map([
505
516
  ]);
506
517
 
507
518
  const valuePresets = new Map([
508
- ['filter', filterValuePresetMap], ['backdrop-filter', filterValuePresetMap], ['background', imageValuePresetMap],
509
- ['background-image', imageValuePresetMap], ['-webkit-mask-image', imageValuePresetMap],
519
+ ['filter', filterValuePresetMap],
520
+ ['backdrop-filter', filterValuePresetMap],
521
+ ['background', imageValuePresetMap],
522
+ ['background-image', imageValuePresetMap],
523
+ ['mask-image', imageValuePresetMap],
524
+ ['-webkit-mask-image', imageValuePresetMap],
525
+ ['list-style', imageValuePresetMap],
526
+ ['list-style-image', imageValuePresetMap],
527
+ ['border-image', imageValuePresetMap],
528
+ ['border-image-source', imageValuePresetMap],
510
529
  [
511
530
  'transform',
512
531
  new Map([
@@ -866,7 +885,44 @@ const extraPropertyValues = new Map<string, Set<string>>([
866
885
  ['-webkit-text-emphasis-position', textEmphasisPosition],
867
886
  ['alignment-baseline', new Set(['before-edge', 'after-edge', 'text-before-edge', 'text-after-edge', 'hanging'])],
868
887
  ['page-break-before', new Set(['left', 'right', 'always', 'avoid'])],
869
- ['border-image', new Set(['repeat', 'stretch', 'space', 'round'])],
888
+ [
889
+ 'border-image',
890
+ new Set([
891
+ 'none', // border-image-source
892
+ 'repeat',
893
+ 'stretch',
894
+ 'space',
895
+ 'round',
896
+ 'auto', // border-image-width
897
+ 'fill', // border-image-slice
898
+ 'linear-gradient()',
899
+ 'radial-gradient()',
900
+ 'conic-gradient()',
901
+ 'repeating-linear-gradient()',
902
+ 'repeating-radial-gradient()',
903
+ 'repeating-conic-gradient()',
904
+ 'image-set()',
905
+ 'cross-fade()',
906
+ 'url()',
907
+ ]),
908
+ ],
909
+ ['border-image-width', new Set(['auto'])],
910
+ ['border-image-slice', new Set(['fill'])],
911
+ [
912
+ 'border-image-source',
913
+ new Set([
914
+ 'none',
915
+ 'linear-gradient()',
916
+ 'radial-gradient()',
917
+ 'conic-gradient()',
918
+ 'repeating-linear-gradient()',
919
+ 'repeating-radial-gradient()',
920
+ 'repeating-conic-gradient()',
921
+ 'image-set()',
922
+ 'cross-fade()',
923
+ 'url()',
924
+ ]),
925
+ ],
870
926
  [
871
927
  'text-decoration',
872
928
  new Set(['blink', 'line-through', 'overline', 'underline', 'wavy', 'double', 'solid', 'dashed', 'dotted']),
@@ -1179,16 +1235,31 @@ const extraPropertyValues = new Map<string, Set<string>>([
1179
1235
  'border-box',
1180
1236
  'content-box',
1181
1237
  'padding-box',
1182
- 'linear-gradient',
1183
- 'radial-gradient',
1184
- 'repeating-linear-gradient',
1185
- 'repeating-radial-gradient',
1186
- 'url',
1238
+ 'text', // background-clip
1239
+ 'linear-gradient()',
1240
+ 'radial-gradient()',
1241
+ 'conic-gradient()',
1242
+ 'repeating-linear-gradient()',
1243
+ 'repeating-radial-gradient()',
1244
+ 'repeating-conic-gradient()',
1245
+ 'image-set()',
1246
+ 'cross-fade()',
1247
+ 'url()',
1187
1248
  ]),
1188
1249
  ],
1189
1250
  [
1190
1251
  'background-image',
1191
- new Set(['linear-gradient', 'radial-gradient', 'repeating-linear-gradient', 'repeating-radial-gradient', 'url']),
1252
+ new Set([
1253
+ 'linear-gradient()',
1254
+ 'radial-gradient()',
1255
+ 'conic-gradient()',
1256
+ 'repeating-linear-gradient()',
1257
+ 'repeating-radial-gradient()',
1258
+ 'repeating-conic-gradient()',
1259
+ 'image-set()',
1260
+ 'cross-fade()',
1261
+ 'url()',
1262
+ ]),
1192
1263
  ],
1193
1264
  ['background-position', new Set(['top', 'bottom', 'left', 'right', 'center'])],
1194
1265
  ['background-position-x', new Set(['left', 'right', 'center'])],
@@ -1440,9 +1511,33 @@ const extraPropertyValues = new Map<string, Set<string>>([
1440
1511
  'plus-lighter',
1441
1512
  ]),
1442
1513
  ],
1514
+ [
1515
+ 'mask-image',
1516
+ new Set([
1517
+ 'linear-gradient()',
1518
+ 'radial-gradient()',
1519
+ 'conic-gradient()',
1520
+ 'repeating-linear-gradient()',
1521
+ 'repeating-radial-gradient()',
1522
+ 'repeating-conic-gradient()',
1523
+ 'image-set()',
1524
+ 'cross-fade()',
1525
+ 'url()',
1526
+ ]),
1527
+ ],
1443
1528
  [
1444
1529
  '-webkit-mask-image',
1445
- new Set(['linear-gradient', 'radial-gradient', 'repeating-linear-gradient', 'repeating-radial-gradient', 'url']),
1530
+ new Set([
1531
+ 'linear-gradient()',
1532
+ 'radial-gradient()',
1533
+ 'conic-gradient()',
1534
+ 'repeating-linear-gradient()',
1535
+ 'repeating-radial-gradient()',
1536
+ 'repeating-conic-gradient()',
1537
+ 'image-set()',
1538
+ 'cross-fade()',
1539
+ 'url()',
1540
+ ]),
1446
1541
  ],
1447
1542
  ['-webkit-mask-origin', new Set(['border', 'border-box', 'content', 'content-box', 'padding', 'padding-box'])],
1448
1543
  ['-webkit-mask-position', new Set(['top', 'bottom', 'left', 'right', 'center'])],
@@ -1479,7 +1574,6 @@ const extraPropertyValues = new Map<string, Set<string>>([
1479
1574
  ['timeline-trigger-activation-range-end', new Set(['normal'])],
1480
1575
  ['timeline-trigger-active-range-start', new Set(['normal'])],
1481
1576
  ['timeline-trigger-active-range-end', new Set(['normal'])],
1482
-
1483
1577
  ['contain-intrinsic-width', new Set(['auto none', 'auto 100px'])],
1484
1578
  ['contain-intrinsic-height', new Set(['auto none', 'auto 100px'])],
1485
1579
  ['contain-intrinsic-size', new Set(['auto none', 'auto 100px'])],
@@ -1517,6 +1611,17 @@ const extraPropertyValues = new Map<string, Set<string>>([
1517
1611
  'ex alphabetic',
1518
1612
  ]),
1519
1613
  ],
1614
+ [
1615
+ 'text-wrap',
1616
+ new Set([
1617
+ 'auto',
1618
+ 'wrap',
1619
+ 'nowrap',
1620
+ 'balance',
1621
+ 'pretty',
1622
+ 'stable',
1623
+ ]),
1624
+ ],
1520
1625
  [
1521
1626
  'corner-shape',
1522
1627
  new Set([
@@ -38,6 +38,7 @@ export interface LayoutProperties {
38
38
  isGrid: boolean;
39
39
  isSubgrid: boolean;
40
40
  isGridLanes: boolean;
41
+ isContents?: boolean;
41
42
  containerType?: string;
42
43
  hasScroll: boolean;
43
44
  }
@@ -392,6 +393,7 @@ export class CSSModel extends SDKModel<EventTypes> {
392
393
  }
393
394
 
394
395
  const display = styles.get('display');
396
+ const isContents = display === 'contents';
395
397
  const isFlex = display === 'flex' || display === 'inline-flex';
396
398
  const isGrid = display === 'grid' || display === 'inline-grid';
397
399
  const isSubgrid = (isGrid &&
@@ -408,6 +410,7 @@ export class CSSModel extends SDKModel<EventTypes> {
408
410
  isGrid,
409
411
  isSubgrid,
410
412
  isGridLanes,
413
+ isContents,
411
414
  containerType: isContainer ? containerType : undefined,
412
415
  hasScroll,
413
416
  };
@@ -38,6 +38,7 @@ import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';
38
38
  import * as Protocol from '../../generated/protocol.js';
39
39
  import * as Common from '../common/common.js';
40
40
  import * as Platform from '../platform/platform.js';
41
+ import * as Root from '../root/root.js';
41
42
 
42
43
  import {CSSModel} from './CSSModel.js';
43
44
  import type {FrameManager} from './FrameManager.js';
@@ -1016,6 +1017,27 @@ export class DOMNode extends Common.ObjectWrapper.ObjectWrapper<DOMNodeEventType
1016
1017
  return Boolean(this.#xmlVersion);
1017
1018
  }
1018
1019
 
1020
+ isCustomElement(): boolean {
1021
+ if (this.nodeType() !== Node.ELEMENT_NODE || this.isXMLNode()) {
1022
+ return false;
1023
+ }
1024
+ const localName = this.localName() || this.nodeName().toLowerCase();
1025
+ if (localName.includes('-')) {
1026
+ const builtInExclusionList = [
1027
+ 'annotation-xml',
1028
+ 'color-profile',
1029
+ 'font-face',
1030
+ 'font-face-src',
1031
+ 'font-face-uri',
1032
+ 'font-face-format',
1033
+ 'font-face-name',
1034
+ 'missing-glyph',
1035
+ ];
1036
+ return !builtInExclusionList.includes(localName);
1037
+ }
1038
+ return this.getAttribute('is') !== undefined;
1039
+ }
1040
+
1019
1041
  setMarker(name: string, value: unknown): void {
1020
1042
  if (value === null) {
1021
1043
  if (!this.#markers.has(name)) {
@@ -1698,7 +1720,7 @@ export class DOMModel extends SDKModel<EventTypes> {
1698
1720
  } else {
1699
1721
  this.#document = null;
1700
1722
  }
1701
- DOMModelUndoStack.instance().dispose(this);
1723
+ this.#undoStack().dispose(this);
1702
1724
 
1703
1725
  if (!this.parentModel()) {
1704
1726
  this.dispatchEventToListeners(Events.DocumentUpdated, this);
@@ -2034,7 +2056,7 @@ export class DOMModel extends SDKModel<EventTypes> {
2034
2056
  }
2035
2057
 
2036
2058
  markUndoableState(minorChange?: boolean): void {
2037
- void DOMModelUndoStack.instance().markUndoableState(this, minorChange || false);
2059
+ void this.#undoStack().markUndoableState(this, minorChange || false);
2038
2060
  }
2039
2061
 
2040
2062
  async nodeForLocation(x: number, y: number, includeUserAgentShadowDOM: boolean): Promise<DOMNode|null> {
@@ -2071,7 +2093,16 @@ export class DOMModel extends SDKModel<EventTypes> {
2071
2093
 
2072
2094
  override dispose(): void {
2073
2095
  this.#resourceTreeModel?.removeEventListener(ResourceTreeModelEvents.DocumentOpened, this.onDocumentOpened, this);
2074
- DOMModelUndoStack.instance().dispose(this);
2096
+ this.#undoStack().dispose(this);
2097
+ }
2098
+
2099
+ // TODO(crbug.com/493763857): Remove fallback once all unit tests use TestUniverse.
2100
+ #undoStack(): DOMModelUndoStack {
2101
+ const context = this.target().targetManager().context;
2102
+ if ('has' in context && typeof context.has === 'function' && context.has(DOMModelUndoStack)) {
2103
+ return context.get(DOMModelUndoStack);
2104
+ }
2105
+ return DOMModelUndoStack.instance();
2075
2106
  }
2076
2107
 
2077
2108
  parentModel(): DOMModel|null {
@@ -2212,8 +2243,6 @@ class DOMDispatcher implements ProtocolProxyApi.DOMDispatcher {
2212
2243
  }
2213
2244
  }
2214
2245
 
2215
- let domModelUndoStackInstance: DOMModelUndoStack|null = null;
2216
-
2217
2246
  export class DOMModelUndoStack {
2218
2247
  #stack: DOMModel[];
2219
2248
  #index: number;
@@ -2228,11 +2257,11 @@ export class DOMModelUndoStack {
2228
2257
  forceNew: boolean|null,
2229
2258
  } = {forceNew: null}): DOMModelUndoStack {
2230
2259
  const {forceNew} = opts;
2231
- if (!domModelUndoStackInstance || forceNew) {
2232
- domModelUndoStackInstance = new DOMModelUndoStack();
2260
+ if (!Root.DevToolsContext.globalInstance().has(DOMModelUndoStack) || forceNew) {
2261
+ Root.DevToolsContext.globalInstance().set(DOMModelUndoStack, new DOMModelUndoStack());
2233
2262
  }
2234
2263
 
2235
- return domModelUndoStackInstance;
2264
+ return Root.DevToolsContext.globalInstance().get(DOMModelUndoStack);
2236
2265
  }
2237
2266
 
2238
2267
  async markUndoableState(model: DOMModel, minorChange: boolean): Promise<void> {
@@ -194,7 +194,8 @@ export class DebuggerModel extends SDKModel<EventTypes> {
194
194
  }
195
195
  }
196
196
 
197
- static selectSymbolSource(debugSymbols: Protocol.Debugger.DebugSymbols[]|null): Protocol.Debugger.DebugSymbols|null {
197
+ static selectSymbolSource(debugSymbols: Protocol.Debugger.DebugSymbols[]|null,
198
+ devToolsConsole: Common.Console.Console): Protocol.Debugger.DebugSymbols|null {
198
199
  if (!debugSymbols || debugSymbols.length === 0) {
199
200
  return null;
200
201
  }
@@ -221,8 +222,7 @@ export class DebuggerModel extends SDKModel<EventTypes> {
221
222
  debugSymbolsSource !== null,
222
223
  'Unknown symbol types. Front-end and back-end should be kept in sync regarding Protocol.Debugger.DebugSymbolTypes');
223
224
  if (debugSymbolsSource && debugSymbols.length > 1) {
224
- Common.Console.Console.instance().warn(
225
- `Multiple debug symbols for script were found. Using ${debugSymbolsSource.type}`);
225
+ devToolsConsole.warn(`Multiple debug symbols for script were found. Using ${debugSymbolsSource.type}`);
226
226
  }
227
227
  return debugSymbolsSource;
228
228
  }
@@ -661,7 +661,8 @@ export class DebuggerModel extends SDKModel<EventTypes> {
661
661
  isContentScript = !executionContextAuxData['isDefault'];
662
662
  }
663
663
 
664
- const selectedDebugSymbol = DebuggerModel.selectSymbolSource(debugSymbols);
664
+ const selectedDebugSymbol =
665
+ DebuggerModel.selectSymbolSource(debugSymbols, this.target().targetManager().getConsole());
665
666
  const script = new Script(
666
667
  this, scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
667
668
  isContentScript, isLiveEdit, sourceMapURL, hasSourceURLComment, length, isModule, originStackTrace, codeOffset,
@@ -6,7 +6,7 @@ import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';
6
6
  import * as Protocol from '../../generated/protocol.js';
7
7
 
8
8
  import {CSSModel} from './CSSModel.js';
9
- import {MultitargetNetworkManager} from './NetworkManager.js';
9
+ import type {MultitargetNetworkManager} from './NetworkManager.js';
10
10
  import {Events, OverlayModel} from './OverlayModel.js';
11
11
  import {SDKModel} from './SDKModel.js';
12
12
  import {Capability, type Target} from './Target.js';
@@ -18,6 +18,7 @@ export const enum DataSaverOverride {
18
18
  }
19
19
 
20
20
  export class EmulationModel extends SDKModel<EmulationModelEventTypes> implements ProtocolProxyApi.EmulationDispatcher {
21
+ readonly #multitargetNetworkManager: MultitargetNetworkManager;
21
22
  readonly #emulationAgent: ProtocolProxyApi.EmulationApi;
22
23
  readonly #deviceOrientationAgent: ProtocolProxyApi.DeviceOrientationApi;
23
24
  #cssModel: CSSModel|null;
@@ -37,6 +38,7 @@ export class EmulationModel extends SDKModel<EmulationModelEventTypes> implement
37
38
 
38
39
  constructor(target: Target) {
39
40
  super(target);
41
+ this.#multitargetNetworkManager = target.targetManager().getNetworkManager();
40
42
  this.#emulationAgent = target.emulationAgent();
41
43
  this.#deviceOrientationAgent = target.deviceOrientationAgent();
42
44
  this.#screenOrientationLocked = false;
@@ -277,7 +279,7 @@ export class EmulationModel extends SDKModel<EmulationModelEventTypes> implement
277
279
  this.#emulationAgent.invoke_setTimezoneOverride({timezoneId: ''}),
278
280
  this.#emulationAgent.invoke_setLocaleOverride({locale: ''}),
279
281
  this.#emulationAgent.invoke_setUserAgentOverride(
280
- {userAgent: MultitargetNetworkManager.instance().currentUserAgent()}),
282
+ {userAgent: this.#multitargetNetworkManager.currentUserAgent()}),
281
283
  ]);
282
284
  } else if (location.unavailable) {
283
285
  await Promise.all([
@@ -285,7 +287,7 @@ export class EmulationModel extends SDKModel<EmulationModelEventTypes> implement
285
287
  this.#emulationAgent.invoke_setTimezoneOverride({timezoneId: ''}),
286
288
  this.#emulationAgent.invoke_setLocaleOverride({locale: ''}),
287
289
  this.#emulationAgent.invoke_setUserAgentOverride(
288
- {userAgent: MultitargetNetworkManager.instance().currentUserAgent()}),
290
+ {userAgent: this.#multitargetNetworkManager.currentUserAgent()}),
289
291
  ]);
290
292
  } else {
291
293
  function processEmulationResult(errorType: string, result: Protocol.ProtocolResponseWithError): Promise<void> {
@@ -319,7 +321,7 @@ export class EmulationModel extends SDKModel<EmulationModelEventTypes> implement
319
321
  .then(result => processEmulationResult('emulation-set-locale', result)),
320
322
  this.#emulationAgent
321
323
  .invoke_setUserAgentOverride({
322
- userAgent: MultitargetNetworkManager.instance().currentUserAgent(),
324
+ userAgent: this.#multitargetNetworkManager.currentUserAgent(),
323
325
  acceptLanguage: location.locale,
324
326
  })
325
327
  .then(result => processEmulationResult('emulation-set-user-agent', result)),
@@ -133,14 +133,13 @@ const CONNECTION_TYPES = new Map([
133
133
  * to in multiple places, and this ensures we don't have accidental typos which
134
134
  * mean extra settings get mistakenly created.
135
135
  */
136
- export function customUserNetworkConditionsSetting(
137
- settings: Common.Settings.Settings = Common.Settings.Settings.instance()): Common.Settings.Setting<Conditions[]> {
136
+ export function customUserNetworkConditionsSetting(settings: Common.Settings.Settings):
137
+ Common.Settings.Setting<Conditions[]> {
138
138
  return settings.moduleSetting<Conditions[]>('custom-network-conditions');
139
139
  }
140
140
 
141
- export function activeNetworkThrottlingKeySetting(
142
- settings: Common.Settings.Settings =
143
- Common.Settings.Settings.instance()): Common.Settings.Setting<ThrottlingConditionKey> {
141
+ export function activeNetworkThrottlingKeySetting(settings: Common.Settings.Settings):
142
+ Common.Settings.Setting<ThrottlingConditionKey> {
144
143
  return settings.createSetting('active-network-condition-key', PredefinedThrottlingConditionKey.NO_THROTTLING);
145
144
  }
146
145
 
@@ -578,10 +577,12 @@ const MAX_RESPONSE_BODY_TOTAL_BUFFER_LENGTH = 250 * 1024 * 1024; // bytes
578
577
  export class FetchDispatcher implements ProtocolProxyApi.FetchDispatcher {
579
578
  readonly #fetchAgent: ProtocolProxyApi.FetchApi;
580
579
  readonly #manager: NetworkManager;
580
+ readonly #multitargetNetworkManager;
581
581
 
582
582
  constructor(agent: ProtocolProxyApi.FetchApi, manager: NetworkManager) {
583
583
  this.#fetchAgent = agent;
584
584
  this.#manager = manager;
585
+ this.#multitargetNetworkManager = this.#manager.target().targetManager().getNetworkManager();
585
586
  }
586
587
 
587
588
  requestPaused({requestId, request, resourceType, responseStatusCode, responseHeaders, networkId}:
@@ -592,8 +593,9 @@ export class FetchDispatcher implements ProtocolProxyApi.FetchDispatcher {
592
593
  if (networkRequest?.originalResponseHeaders.length === 0 && responseHeaders) {
593
594
  networkRequest.originalResponseHeaders = responseHeaders;
594
595
  }
595
- void MultitargetNetworkManager.instance().requestIntercepted(new InterceptedRequest(
596
- this.#fetchAgent, request, resourceType, requestId, networkRequest, responseStatusCode, responseHeaders));
596
+ void this.#multitargetNetworkManager.requestIntercepted(
597
+ new InterceptedRequest(this.#multitargetNetworkManager, this.#fetchAgent, request, resourceType, requestId,
598
+ networkRequest, responseStatusCode, responseHeaders));
597
599
  }
598
600
 
599
601
  authRequired({}: Protocol.Fetch.AuthRequiredEvent): void {
@@ -602,6 +604,7 @@ export class FetchDispatcher implements ProtocolProxyApi.FetchDispatcher {
602
604
 
603
605
  export class NetworkDispatcher implements ProtocolProxyApi.NetworkDispatcher {
604
606
  readonly #manager: NetworkManager;
607
+ readonly #multitargetNetworkManager: MultitargetNetworkManager;
605
608
  readonly #requestsById = new Map<string, NetworkRequest>();
606
609
  readonly #requestsByURL = new Map<Platform.DevToolsPath.UrlString, NetworkRequest>();
607
610
  readonly #requestsByLoaderId = new Map<Protocol.Network.LoaderId, NetworkRequest>();
@@ -618,9 +621,10 @@ export class NetworkDispatcher implements ProtocolProxyApi.NetworkDispatcher {
618
621
 
619
622
  constructor(manager: NetworkManager) {
620
623
  this.#manager = manager;
624
+ this.#multitargetNetworkManager = this.#manager.target().targetManager().getNetworkManager();
621
625
 
622
- MultitargetNetworkManager.instance().addEventListener(
623
- MultitargetNetworkManager.Events.REQUEST_INTERCEPTED, this.#markAsIntercepted.bind(this));
626
+ this.#multitargetNetworkManager.addEventListener(MultitargetNetworkManager.Events.REQUEST_INTERCEPTED,
627
+ this.#markAsIntercepted.bind(this));
624
628
  }
625
629
 
626
630
  #markAsIntercepted(event: Common.EventTarget.EventTargetEvent<string>): void {
@@ -1178,7 +1182,7 @@ export class NetworkDispatcher implements ProtocolProxyApi.NetworkDispatcher {
1178
1182
  }
1179
1183
 
1180
1184
  private maybeAdoptMainResourceRequest(requestId: string): NetworkRequest|null {
1181
- const request = MultitargetNetworkManager.instance().inflightMainResourceRequests.get(requestId);
1185
+ const request = this.#multitargetNetworkManager.inflightMainResourceRequests.get(requestId);
1182
1186
  if (!request) {
1183
1187
  return null;
1184
1188
  }
@@ -1216,7 +1220,7 @@ export class NetworkDispatcher implements ProtocolProxyApi.NetworkDispatcher {
1216
1220
  // request to fetch the main worker script, the request ID is the future
1217
1221
  // worker target ID and, therefore, it is unique.
1218
1222
  if (networkRequest.loaderId === networkRequest.requestId() || networkRequest.loaderId === '') {
1219
- MultitargetNetworkManager.instance().inflightMainResourceRequests.set(networkRequest.requestId(), networkRequest);
1223
+ this.#multitargetNetworkManager.inflightMainResourceRequests.set(networkRequest.requestId(), networkRequest);
1220
1224
  }
1221
1225
 
1222
1226
  this.#manager.dispatchEventToListeners(Events.RequestStarted, {request: networkRequest, originalRequest});
@@ -1244,7 +1248,7 @@ export class NetworkDispatcher implements ProtocolProxyApi.NetworkDispatcher {
1244
1248
  }
1245
1249
  }
1246
1250
  this.#manager.dispatchEventToListeners(Events.RequestFinished, networkRequest);
1247
- MultitargetNetworkManager.instance().inflightMainResourceRequests.delete(networkRequest.requestId());
1251
+ this.#multitargetNetworkManager.inflightMainResourceRequests.delete(networkRequest.requestId());
1248
1252
 
1249
1253
  const settings = this.#manager.target().targetManager().settings;
1250
1254
  if (settings.moduleSetting('monitoring-xhr-enabled').get() &&
@@ -1712,9 +1716,7 @@ export class RequestCondition extends Common.ObjectWrapper.ObjectWrapper<Request
1712
1716
  #conditions: ThrottlingConditions;
1713
1717
  #ruleIds = new Set<string>();
1714
1718
 
1715
- static createFromSetting(
1716
- setting: RequestConditionsSetting,
1717
- settings: Common.Settings.Settings = Common.Settings.Settings.instance()): RequestCondition {
1719
+ static createFromSetting(setting: RequestConditionsSetting, settings: Common.Settings.Settings): RequestCondition {
1718
1720
  if ('urlPattern' in setting) {
1719
1721
  const pattern = RequestURLPattern.create(setting.urlPattern) ?? {
1720
1722
  wildcardURL: setting.urlPattern,
@@ -2385,6 +2387,7 @@ export namespace MultitargetNetworkManager {
2385
2387
  }
2386
2388
 
2387
2389
  export class InterceptedRequest {
2390
+ readonly #multitargetNetworkManager: MultitargetNetworkManager;
2388
2391
  readonly #fetchAgent: ProtocolProxyApi.FetchApi;
2389
2392
  #hasResponded = false;
2390
2393
  request: Protocol.Network.Request;
@@ -2395,6 +2398,7 @@ export class InterceptedRequest {
2395
2398
  networkRequest: NetworkRequest|null;
2396
2399
 
2397
2400
  constructor(
2401
+ multitargetNetworkManager: MultitargetNetworkManager,
2398
2402
  fetchAgent: ProtocolProxyApi.FetchApi,
2399
2403
  request: Protocol.Network.Request,
2400
2404
  resourceType: Protocol.Network.ResourceType,
@@ -2403,6 +2407,7 @@ export class InterceptedRequest {
2403
2407
  responseStatusCode?: number,
2404
2408
  responseHeaders?: Protocol.Fetch.HeaderEntry[],
2405
2409
  ) {
2410
+ this.#multitargetNetworkManager = multitargetNetworkManager;
2406
2411
  this.#fetchAgent = fetchAgent;
2407
2412
  this.request = request;
2408
2413
  this.resourceType = resourceType;
@@ -2494,8 +2499,8 @@ export class InterceptedRequest {
2494
2499
  }
2495
2500
 
2496
2501
  void this.#fetchAgent.invoke_fulfillRequest({requestId: this.requestId, responseCode, body, responseHeaders});
2497
- MultitargetNetworkManager.instance().dispatchEventToListeners(
2498
- MultitargetNetworkManager.Events.REQUEST_FULFILLED, this.request.url as Platform.DevToolsPath.UrlString);
2502
+ this.#multitargetNetworkManager.dispatchEventToListeners(MultitargetNetworkManager.Events.REQUEST_FULFILLED,
2503
+ this.request.url as Platform.DevToolsPath.UrlString);
2499
2504
  }
2500
2505
 
2501
2506
  continueRequestWithoutChange(): void {
@@ -337,7 +337,7 @@ export class RuntimeModel extends SDKModel<EventTypes> {
337
337
  const result = await this.queryObjects(object);
338
338
  object.release();
339
339
  if ('error' in result) {
340
- Common.Console.Console.instance().error(result.error);
340
+ this.target().targetManager().getConsole().error(result.error);
341
341
  return;
342
342
  }
343
343
  this.dispatchEventToListeners(Events.QueryObjectRequested, {objects: result.objects, executionContextId});
@@ -11,6 +11,7 @@ import type * as ProtocolClient from '../protocol_client/protocol_client.js';
11
11
  import * as Root from '../root/root.js';
12
12
 
13
13
  import {FrameManager} from './FrameManager.js';
14
+ import {MultitargetNetworkManager} from './NetworkManager.js';
14
15
  import {type RegistrationInfo, SDKModel, type SDKModelConstructor} from './SDKModel.js';
15
16
  import {Target, Type as TargetType} from './Target.js';
16
17
 
@@ -48,6 +49,15 @@ export class TargetManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes
48
49
  return this.context.get(FrameManager);
49
50
  }
50
51
 
52
+ // TODO(crbug.com/493763857): Remove fallback once all unit tests use TestUniverse.
53
+ getNetworkManager(): MultitargetNetworkManager {
54
+ if ('has' in this.context && typeof this.context.has === 'function' &&
55
+ !this.context.has(MultitargetNetworkManager)) {
56
+ return MultitargetNetworkManager.instance();
57
+ }
58
+ return this.context.get(MultitargetNetworkManager);
59
+ }
60
+
51
61
  /* eslint-disable @typescript-eslint/no-explicit-any */
52
62
  #modelListeners: Platform.MapUtilities.Multimap<string|symbol|number, {
53
63
  modelClass: SDKModelConstructor,
@@ -639,6 +639,12 @@
639
639
  }
640
640
 
641
641
  &.platform-screenshot-test {
642
+ --default-font-family: ahem;
643
+ --monospace-font-family: ahem;
644
+ --source-code-font-family: ahem;
645
+ }
646
+
647
+ &.platform-screenshot-e2e-test {
642
648
  --default-font-family: roboto;
643
649
  --monospace-font-family: roboto;
644
650
  --source-code-font-family: roboto;
@@ -33,4 +33,4 @@ import * as Main from '../main/main.js';
33
33
 
34
34
  // @ts-expect-error Exposed for legacy layout tests
35
35
  self.runtime = Root.Runtime.Runtime.instance({forceNew: true});
36
- new Main.MainImpl.MainImpl();
36
+ new Main.MainImpl.MainImpl({supportsEmulation: true});
@@ -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 * as Platform from '../../core/platform/platform.js';
6
-
7
5
  import type {FormattedContentBuilder} from './FormattedContentBuilder.js';
8
6
  import {createTokenizer} from './FormatterWorker.js';
9
7
 
@@ -19,6 +17,7 @@ export class CSSFormatter {
19
17
  #fromOffset!: number;
20
18
  #lineEndings!: number[];
21
19
  #lastLine = -1;
20
+ #currentLineIndex = 0;
22
21
  #state: {
23
22
  eatWhitespace?: boolean,
24
23
  seenProperty?: boolean,
@@ -35,6 +34,7 @@ export class CSSFormatter {
35
34
  this.#toOffset = toOffset;
36
35
  this.#state = {};
37
36
  this.#lastLine = -1;
37
+ this.#currentLineIndex = 0;
38
38
  const tokenize = createTokenizer('text/css');
39
39
  const oldEnforce = this.#builder.setEnforceSpaceBetweenWords(false);
40
40
  tokenize(text.substring(this.#fromOffset, this.#toOffset), this.#tokenCallback.bind(this));
@@ -42,9 +42,18 @@ export class CSSFormatter {
42
42
  }
43
43
 
44
44
  #tokenCallback(token: string, type: string|null, startPosition: number): void {
45
+ // startPosition is relative to the start of the CSS block.
46
+ // Convert it to an absolute document offset to match this.#lineEndings.
45
47
  startPosition += this.#fromOffset;
46
- const startLine = Platform.ArrayUtilities.lowerBound(
47
- this.#lineEndings, startPosition, Platform.ArrayUtilities.DEFAULT_COMPARATOR);
48
+
49
+ // Find the line index containing startPosition.
50
+ // Since CodeMirror processes tokens sequentially in increasing order of their offset,
51
+ // we can perform an amortized O(1) linear scan forward by tracking the current index.
52
+ while (this.#currentLineIndex < this.#lineEndings.length &&
53
+ this.#lineEndings[this.#currentLineIndex] < startPosition) {
54
+ this.#currentLineIndex++;
55
+ }
56
+ const startLine = this.#currentLineIndex;
48
57
  if (startLine !== this.#lastLine) {
49
58
  this.#state.eatWhitespace = true;
50
59
  }