chrome-devtools-frontend 1.0.1656291 → 1.0.1657110

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 (63) hide show
  1. package/AUTHORS +2 -0
  2. package/docs/get_the_code.md +6 -6
  3. package/front_end/Tests.js +1 -1
  4. package/front_end/core/common/Settings.ts +0 -8
  5. package/front_end/core/host/Platform.ts +4 -0
  6. package/front_end/core/sdk/CSSMetadata.ts +11 -0
  7. package/front_end/core/sdk/CSSModel.ts +3 -0
  8. package/front_end/core/sdk/DOMModel.ts +44 -13
  9. package/front_end/core/sdk/DebuggerModel.ts +5 -4
  10. package/front_end/core/sdk/EmulationModel.ts +6 -4
  11. package/front_end/core/sdk/NetworkManager.ts +21 -14
  12. package/front_end/core/sdk/RuntimeModel.ts +1 -1
  13. package/front_end/core/sdk/SourceMapCache.ts +2 -4
  14. package/front_end/core/sdk/SourceMapManager.ts +8 -7
  15. package/front_end/core/sdk/TargetManager.ts +10 -0
  16. package/front_end/design_system_tokens.css +6 -0
  17. package/front_end/entrypoints/inspector_main/InspectorMain.ts +1 -11
  18. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +1 -1
  19. package/front_end/entrypoints/main/GlobalAiButton.ts +29 -35
  20. package/front_end/entrypoints/main/MainImpl.ts +1 -1
  21. package/front_end/entrypoints/main/SimpleApp.ts +0 -13
  22. package/front_end/entrypoints/main/main-meta.ts +2 -2
  23. package/front_end/entrypoints/node_app/app/NodeConnectionsPanel.ts +2 -3
  24. package/front_end/foundation/Universe.ts +44 -0
  25. package/front_end/generated/InspectorBackendCommands.ts +2 -2
  26. package/front_end/generated/protocol.ts +5 -5
  27. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +2 -1
  28. package/front_end/models/crux-manager/CrUXManager.ts +16 -11
  29. package/front_end/models/emulation/DeviceModeModel.ts +43 -24
  30. package/front_end/models/live-metrics/LiveMetrics.ts +47 -23
  31. package/front_end/models/project_settings/ProjectSettingsModel.ts +2 -37
  32. package/front_end/models/workspace/FileManager.ts +9 -6
  33. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +2 -1
  34. package/front_end/panels/application/ServiceWorkersView.ts +177 -163
  35. package/front_end/panels/application/components/StorageMetadataView.ts +7 -2
  36. package/front_end/panels/application/serviceWorkersView.css +8 -0
  37. package/front_end/panels/common/BadgeNotification.ts +1 -1
  38. package/front_end/panels/console/ConsoleInsightTeaser.ts +2 -1
  39. package/front_end/panels/elements/ElementsPanel.ts +35 -28
  40. package/front_end/panels/elements/ElementsTreeElement.ts +208 -143
  41. package/front_end/panels/elements/ElementsTreeOutline.ts +3 -2
  42. package/front_end/panels/elements/components/AdornerManager.ts +1 -0
  43. package/front_end/panels/elements/elements-meta.ts +3 -2
  44. package/front_end/panels/emulation/DeviceModeToolbar.ts +19 -19
  45. package/front_end/panels/explain/components/ConsoleInsight.ts +2 -1
  46. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +13 -12
  47. package/front_end/panels/mobile_throttling/ThrottlingManager.ts +8 -7
  48. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +6 -7
  49. package/front_end/panels/mobile_throttling/mobile_throttling-meta.ts +3 -2
  50. package/front_end/panels/settings/components/SyncSection.ts +2 -1
  51. package/front_end/panels/timeline/AppenderUtils.ts +12 -4
  52. package/front_end/panels/timeline/ThreadAppender.ts +3 -3
  53. package/front_end/panels/timeline/TimelinePanel.ts +5 -5
  54. package/front_end/panels/timeline/timelineFlameChartView.css +2 -1
  55. package/front_end/third_party/chromium/README.chromium +1 -1
  56. package/front_end/third_party/chromium/ahem/ahem.js +792 -0
  57. package/front_end/tsconfig.json +7 -1
  58. package/front_end/ui/legacy/ActionRegistration.ts +1 -1
  59. package/front_end/ui/legacy/InspectorView.ts +1 -1
  60. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +109 -23
  61. package/front_end/ui/legacy/theme_support/ThemeSupport.ts +2 -2
  62. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
  63. package/package.json +1 -1
package/AUTHORS CHANGED
@@ -24,6 +24,7 @@ Anna Agoha <annaagoha@gmail.com>
24
24
  Anthony Xie <anthonyxie64@gmail.com>
25
25
  Axel Chong <haxatron1@gmail.com>
26
26
  Anton Bershanskyi <bershanskyi@gmail.com>
27
+ Aviv Keller <me@aviv.sh>
27
28
  Biboswan Roy <biboswan98@gmail.com>
28
29
  Boris Verkhovskiy <boris.verk@gmail.com>
29
30
  Carl Espe <carl@cpespe.com>
@@ -62,6 +63,7 @@ Juba Borgohain <chromiumjuba@gmail.com>
62
63
  Julian Geppert <spctstr@gmail.com>
63
64
  Junseo Yoo <joon.yoo181@berkeley.edu>
64
65
  Kanishk Ranjan <kanishkranjan17@gmail.com>
66
+ Karim El Harim <karimelharim@gmail.com>
65
67
  Karntino Areros <karntino.c.areros@gmail.com>
66
68
  Kohei Ueno <kohei.ueno119@gmail.com>
67
69
  Krishnal Ciccolella <ciccolella.krishnal@gmail.com>
@@ -53,10 +53,10 @@ a build time cost. If you want an even fast fast build, you might want to opt
53
53
  out of bundling by setting `devtools_bundle` to `false`
54
54
 
55
55
  ```bash
56
- gn gen out/fast-build --args="devtools_skip_typecheck=true devtools_bundle=false"
56
+ gn gen out/Fast --args="devtools_skip_typecheck=true devtools_bundle=false"
57
57
  ```
58
58
 
59
- and use `npm run build -- -t fast-build` to build this target.
59
+ and use `npm run build -- -t Fast` to build this target.
60
60
 
61
61
  ### Rebuilding automatically
62
62
 
@@ -111,10 +111,10 @@ The `.env.template` file lists all supported variables. Copy it to `.env` to get
111
111
  cp .env.template .env
112
112
  ```
113
113
 
114
- As mentioned earlier, you might create a fast build target. Instead of always typing `npm run build -- -t fast-build`, to remove the flag repetition you simple run `npm run build` you can set the following variable in your `.env` file:
114
+ As mentioned earlier, you might create a fast build target. Instead of always typing `npm run build -- -t Fast`, to remove the flag repetition you simple run `npm run build` you can set the following variable in your `.env` file:
115
115
 
116
116
  ```shell
117
- DEVTOOLS_TARGET=fast-build
117
+ DEVTOOLS_TARGET=Fast
118
118
  ```
119
119
 
120
120
  Another example - by default running `npm start` auto-opens DevTools for new Tabs.
@@ -468,8 +468,8 @@ In the `custom_deps` section, insert this line:
468
468
  "src/third_party/devtools-frontend/src": None,
469
469
  ```
470
470
 
471
- For the integrated checkout, create a single gclient project that automatically gclient sync's all dependencies for both
472
- repositories. After checking out chromium, modify the .gclient file for `chromium/src` to add the DevTools project:
471
+ For the integrated checkout, create a single gclient project that automatically `gclient sync`s all dependencies for both
472
+ repositories. After checking out chromium, modify the `.gclient` file for `chromium/src` to add the DevTools project:
473
473
 
474
474
  ```python
475
475
  solutions = [
@@ -761,7 +761,7 @@
761
761
  this.releaseControl();
762
762
  });
763
763
 
764
- Common.Settings.moduleSetting('active-keybind-set').set('vsCode');
764
+ Common.Settings.Settings.instance().moduleSetting('active-keybind-set').set('vsCode');
765
765
  };
766
766
 
767
767
  TestSuite.prototype.testDispatchKeyEventDoesNotCrash = function() {
@@ -715,14 +715,6 @@ export const enum SettingStorageType {
715
715
  SESSION = 'Session',
716
716
  }
717
717
 
718
- export function moduleSetting(settingName: string): Setting<unknown> {
719
- return Settings.instance().moduleSetting(settingName);
720
- }
721
-
722
- export function settingForTest(settingName: string): Setting<unknown> {
723
- return Settings.instance().settingForTest(settingName);
724
- }
725
-
726
718
  export {
727
719
  getLocalizedSettingsCategory,
728
720
  maybeRemoveSettingExtension,
@@ -65,3 +65,7 @@ export function fontFamily(): string {
65
65
  }
66
66
  return _fontFamily;
67
67
  }
68
+
69
+ export function setFontFamilyForTests(family: string): void {
70
+ _fontFamily = family;
71
+ }
@@ -1517,6 +1517,17 @@ const extraPropertyValues = new Map<string, Set<string>>([
1517
1517
  'ex alphabetic',
1518
1518
  ]),
1519
1519
  ],
1520
+ [
1521
+ 'text-wrap',
1522
+ new Set([
1523
+ 'auto',
1524
+ 'wrap',
1525
+ 'nowrap',
1526
+ 'balance',
1527
+ 'pretty',
1528
+ 'stable',
1529
+ ]),
1530
+ ],
1520
1531
  [
1521
1532
  'corner-shape',
1522
1533
  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,16 +38,17 @@ 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
- import {FrameManager} from './FrameManager.js';
44
+ import type {FrameManager} from './FrameManager.js';
44
45
  import {OverlayModel} from './OverlayModel.js';
45
46
  import {RemoteObject} from './RemoteObject.js';
46
47
  import {Events as ResourceTreeModelEvents, type ResourceTreeFrame, ResourceTreeModel} from './ResourceTreeModel.js';
47
48
  import {RuntimeModel} from './RuntimeModel.js';
48
49
  import {SDKModel} from './SDKModel.js';
49
50
  import {Capability, type Target} from './Target.js';
50
- import {TargetManager} from './TargetManager.js';
51
+ import type {TargetManager} from './TargetManager.js';
51
52
 
52
53
  /** Keep this list in sync with https://w3c.github.io/aria/#state_prop_def **/
53
54
  export const ARIA_ATTRIBUTES = new Set<string>([
@@ -129,6 +130,7 @@ export interface DOMNodeEventTypes {
129
130
 
130
131
  export class DOMNode extends Common.ObjectWrapper.ObjectWrapper<DOMNodeEventTypes> {
131
132
  #domModel: DOMModel;
133
+ readonly #frameManager: FrameManager;
132
134
  #agent: ProtocolProxyApi.DOMApi;
133
135
  ownerDocument!: DOMDocument|null;
134
136
  #isInShadowTree!: boolean;
@@ -194,6 +196,7 @@ export class DOMNode extends Common.ObjectWrapper.ObjectWrapper<DOMNodeEventType
194
196
  constructor(domModel: DOMModel) {
195
197
  super();
196
198
  this.#domModel = domModel;
199
+ this.#frameManager = domModel.target().targetManager().getFrameManager();
197
200
  this.#agent = this.#domModel.getAgent();
198
201
  }
199
202
 
@@ -313,7 +316,7 @@ export class DOMNode extends Common.ObjectWrapper.ObjectWrapper<DOMNodeEventType
313
316
  }
314
317
 
315
318
  private async requestChildDocument(frameId: Protocol.Page.FrameId, notInTarget: Target): Promise<DOMDocument|null> {
316
- const frame = await FrameManager.instance().getOrWaitForFrame(frameId, notInTarget);
319
+ const frame = await this.#frameManager.getOrWaitForFrame(frameId, notInTarget);
317
320
  const childModel = frame.resourceTreeModel()?.target().model(DOMModel);
318
321
  return await (childModel?.requestDocument() || null);
319
322
  }
@@ -341,7 +344,7 @@ export class DOMNode extends Common.ObjectWrapper.ObjectWrapper<DOMNodeEventType
341
344
  return undefined;
342
345
  }
343
346
 
344
- const frame = FrameManager.instance().getFrame(this.#frameOwnerFrameId);
347
+ const frame = this.#frameManager.getFrame(this.#frameOwnerFrameId);
345
348
  if (frame && frame.adFrameType() !== Protocol.Page.AdFrameType.None) {
346
349
  // The frame is ad-related, but provenance information is unavailable.
347
350
  return {};
@@ -1014,6 +1017,27 @@ export class DOMNode extends Common.ObjectWrapper.ObjectWrapper<DOMNodeEventType
1014
1017
  return Boolean(this.#xmlVersion);
1015
1018
  }
1016
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
+
1017
1041
  setMarker(name: string, value: unknown): void {
1018
1042
  if (value === null) {
1019
1043
  if (!this.#markers.has(name)) {
@@ -1478,7 +1502,7 @@ export class DOMModel extends SDKModel<EventTypes> {
1478
1502
  return this.target().model(OverlayModel) as OverlayModel;
1479
1503
  }
1480
1504
 
1481
- static cancelSearch(targetManager: TargetManager = TargetManager.instance()): void {
1505
+ static cancelSearch(targetManager: TargetManager): void {
1482
1506
  for (const domModel of targetManager.models(DOMModel)) {
1483
1507
  domModel.cancelSearch();
1484
1508
  }
@@ -1696,7 +1720,7 @@ export class DOMModel extends SDKModel<EventTypes> {
1696
1720
  } else {
1697
1721
  this.#document = null;
1698
1722
  }
1699
- DOMModelUndoStack.instance().dispose(this);
1723
+ this.#undoStack().dispose(this);
1700
1724
 
1701
1725
  if (!this.parentModel()) {
1702
1726
  this.dispatchEventToListeners(Events.DocumentUpdated, this);
@@ -2032,7 +2056,7 @@ export class DOMModel extends SDKModel<EventTypes> {
2032
2056
  }
2033
2057
 
2034
2058
  markUndoableState(minorChange?: boolean): void {
2035
- void DOMModelUndoStack.instance().markUndoableState(this, minorChange || false);
2059
+ void this.#undoStack().markUndoableState(this, minorChange || false);
2036
2060
  }
2037
2061
 
2038
2062
  async nodeForLocation(x: number, y: number, includeUserAgentShadowDOM: boolean): Promise<DOMNode|null> {
@@ -2069,7 +2093,16 @@ export class DOMModel extends SDKModel<EventTypes> {
2069
2093
 
2070
2094
  override dispose(): void {
2071
2095
  this.#resourceTreeModel?.removeEventListener(ResourceTreeModelEvents.DocumentOpened, this.onDocumentOpened, this);
2072
- 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();
2073
2106
  }
2074
2107
 
2075
2108
  parentModel(): DOMModel|null {
@@ -2210,8 +2243,6 @@ class DOMDispatcher implements ProtocolProxyApi.DOMDispatcher {
2210
2243
  }
2211
2244
  }
2212
2245
 
2213
- let domModelUndoStackInstance: DOMModelUndoStack|null = null;
2214
-
2215
2246
  export class DOMModelUndoStack {
2216
2247
  #stack: DOMModel[];
2217
2248
  #index: number;
@@ -2226,11 +2257,11 @@ export class DOMModelUndoStack {
2226
2257
  forceNew: boolean|null,
2227
2258
  } = {forceNew: null}): DOMModelUndoStack {
2228
2259
  const {forceNew} = opts;
2229
- if (!domModelUndoStackInstance || forceNew) {
2230
- domModelUndoStackInstance = new DOMModelUndoStack();
2260
+ if (!Root.DevToolsContext.globalInstance().has(DOMModelUndoStack) || forceNew) {
2261
+ Root.DevToolsContext.globalInstance().set(DOMModelUndoStack, new DOMModelUndoStack());
2231
2262
  }
2232
2263
 
2233
- return domModelUndoStackInstance;
2264
+ return Root.DevToolsContext.globalInstance().get(DOMModelUndoStack);
2234
2265
  }
2235
2266
 
2236
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() &&
@@ -2385,6 +2389,7 @@ export namespace MultitargetNetworkManager {
2385
2389
  }
2386
2390
 
2387
2391
  export class InterceptedRequest {
2392
+ readonly #multitargetNetworkManager: MultitargetNetworkManager;
2388
2393
  readonly #fetchAgent: ProtocolProxyApi.FetchApi;
2389
2394
  #hasResponded = false;
2390
2395
  request: Protocol.Network.Request;
@@ -2395,6 +2400,7 @@ export class InterceptedRequest {
2395
2400
  networkRequest: NetworkRequest|null;
2396
2401
 
2397
2402
  constructor(
2403
+ multitargetNetworkManager: MultitargetNetworkManager,
2398
2404
  fetchAgent: ProtocolProxyApi.FetchApi,
2399
2405
  request: Protocol.Network.Request,
2400
2406
  resourceType: Protocol.Network.ResourceType,
@@ -2403,6 +2409,7 @@ export class InterceptedRequest {
2403
2409
  responseStatusCode?: number,
2404
2410
  responseHeaders?: Protocol.Fetch.HeaderEntry[],
2405
2411
  ) {
2412
+ this.#multitargetNetworkManager = multitargetNetworkManager;
2406
2413
  this.#fetchAgent = fetchAgent;
2407
2414
  this.request = request;
2408
2415
  this.resourceType = resourceType;
@@ -2494,8 +2501,8 @@ export class InterceptedRequest {
2494
2501
  }
2495
2502
 
2496
2503
  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);
2504
+ this.#multitargetNetworkManager.dispatchEventToListeners(MultitargetNetworkManager.Events.REQUEST_FULFILLED,
2505
+ this.request.url as Platform.DevToolsPath.UrlString);
2499
2506
  }
2500
2507
 
2501
2508
  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});
@@ -8,15 +8,13 @@ import type {DebugId, SourceMapV3} from './SourceMap.js';
8
8
 
9
9
  /** A thin wrapper around the Cache API to store source map JSONs keyed on Debug IDs */
10
10
  export class SourceMapCache {
11
- static readonly #INSTANCE = new SourceMapCache('devtools-source-map-cache');
12
-
13
- static instance(): SourceMapCache {
11
+ static create(): SourceMapCache {
14
12
  if (typeof window === 'undefined') {
15
13
  // TODO(crbug.com/451502260): Move this behind a `HostRuntime` interface.
16
14
  return IN_MEMORY_INSTANCE as unknown as
17
15
  SourceMapCache; // TS doesn't like that our in-memory class doesn't have the same private fields.
18
16
  }
19
- return this.#INSTANCE;
17
+ return new SourceMapCache('devtools-source-map-cache');
20
18
  }
21
19
 
22
20
  static createForTest(name: string): SourceMapCache {
@@ -22,6 +22,7 @@ export class SourceMapManager<T extends FrameAssociated> extends Common.ObjectWr
22
22
  readonly #clientData = new Map<T, ClientData>();
23
23
  readonly #sourceMaps = new Map<SourceMap, T>();
24
24
  #attachingClient: T|null = null;
25
+ readonly #sourceMapCache = SourceMapCache.create();
25
26
 
26
27
  constructor(target: Target, factory?: SourceMapFactory<T>) {
27
28
  super();
@@ -118,7 +119,7 @@ export class SourceMapManager<T extends FrameAssociated> extends Common.ObjectWr
118
119
  // SourceMapManager in their respective constructors.
119
120
  const resourceLoader = this.#target.targetManager().context.get(PageResourceLoader);
120
121
  clientData.sourceMapPromise =
121
- loadSourceMap(resourceLoader, sourceMapURL, client.debugId(), initiator)
122
+ loadSourceMap(resourceLoader, this.#sourceMapCache, sourceMapURL, client.debugId(), initiator)
122
123
  .then(
123
124
  payload => {
124
125
  const sourceMap = this.#factory(sourceURL, sourceMapURL, payload, client);
@@ -185,14 +186,14 @@ export class SourceMapManager<T extends FrameAssociated> extends Common.ObjectWr
185
186
  }
186
187
  }
187
188
 
188
- async function loadSourceMap(
189
- resourceLoader: ResourceLoader, url: Platform.DevToolsPath.UrlString, debugId: DebugId|null,
190
- initiator: PageResourceLoadInitiator): Promise<SourceMapV3> {
189
+ async function loadSourceMap(resourceLoader: ResourceLoader, sourceMapCache: SourceMapCache,
190
+ url: Platform.DevToolsPath.UrlString, debugId: DebugId|null,
191
+ initiator: PageResourceLoadInitiator): Promise<SourceMapV3> {
191
192
  try {
192
193
  if (debugId) {
193
194
  const securityOrigin = initiator.initiatorUrl ? Common.ParsedURL.ParsedURL.extractOrigin(initiator.initiatorUrl) :
194
195
  Platform.DevToolsPath.EmptyUrlString;
195
- const cachedSourceMap = await SourceMapCache.instance().get(debugId, securityOrigin);
196
+ const cachedSourceMap = await sourceMapCache.get(debugId, securityOrigin);
196
197
  if (cachedSourceMap) {
197
198
  return cachedSourceMap;
198
199
  }
@@ -204,7 +205,7 @@ async function loadSourceMap(
204
205
  // In case something goes wrong with updating the cache, we still want to use the source map.
205
206
  const securityOrigin = initiator.initiatorUrl ? Common.ParsedURL.ParsedURL.extractOrigin(initiator.initiatorUrl) :
206
207
  Platform.DevToolsPath.EmptyUrlString;
207
- await SourceMapCache.instance().set(sourceMap.debugId as DebugId, securityOrigin, sourceMap).catch();
208
+ await sourceMapCache.set(sourceMap.debugId as DebugId, securityOrigin, sourceMap).catch();
208
209
  }
209
210
  return sourceMap;
210
211
  } catch (cause) {
@@ -216,7 +217,7 @@ export async function tryLoadSourceMap(
216
217
  resourceLoader: ResourceLoader, url: Platform.DevToolsPath.UrlString,
217
218
  initiator: PageResourceLoadInitiator): Promise<SourceMapV3|null> {
218
219
  try {
219
- return await loadSourceMap(resourceLoader, url, null, initiator);
220
+ return await loadSourceMap(resourceLoader, SourceMapCache.create(), url, null, initiator);
220
221
  } catch (cause) {
221
222
  console.error(cause);
222
223
  return null;
@@ -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;
@@ -207,12 +207,11 @@ export class NodeIndicator extends UI.Widget.Widget {
207
207
  }
208
208
  }
209
209
 
210
- let nodeIndicatorProviderInstance: NodeIndicatorProvider;
211
210
  export class NodeIndicatorProvider implements UI.Toolbar.Provider {
212
211
  #toolbarItem: UI.Toolbar.ToolbarItem;
213
212
  #widgetElement: UI.Widget.WidgetElement<NodeIndicator>;
214
213
 
215
- private constructor() {
214
+ constructor() {
216
215
  this.#widgetElement = document.createElement('devtools-widget') as UI.Widget.WidgetElement<NodeIndicator>;
217
216
  new NodeIndicator(this.#widgetElement);
218
217
 
@@ -223,15 +222,6 @@ export class NodeIndicatorProvider implements UI.Toolbar.Provider {
223
222
  item(): UI.Toolbar.ToolbarItem|null {
224
223
  return this.#toolbarItem;
225
224
  }
226
-
227
- static instance(opts: {forceNew: boolean|null} = {forceNew: null}): NodeIndicatorProvider {
228
- const {forceNew} = opts;
229
- if (!nodeIndicatorProviderInstance || forceNew) {
230
- nodeIndicatorProviderInstance = new NodeIndicatorProvider();
231
- }
232
-
233
- return nodeIndicatorProviderInstance;
234
- }
235
225
  }
236
226
 
237
227
  export class SourcesPanelIndicator {
@@ -257,7 +257,7 @@ Common.Settings.registerSettingExtension({
257
257
  UI.Toolbar.registerToolbarItem({
258
258
  async loadItem() {
259
259
  const InspectorMain = await loadInspectorMainModule();
260
- return InspectorMain.InspectorMain.NodeIndicatorProvider.instance();
260
+ return new InspectorMain.InspectorMain.NodeIndicatorProvider();
261
261
  },
262
262
  order: 2,
263
263
  location: UI.Toolbar.ToolbarItemLocation.MAIN_TOOLBAR_LEFT,