chrome-devtools-frontend 1.0.1651641 → 1.0.1654411

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 (96) hide show
  1. package/.agents/skills/fixing-skipped-tests/SKILL.md +32 -0
  2. package/.agents/skills/migrate-chromium-test/SKILL.md +144 -0
  3. package/docs/get_the_code.md +1 -2
  4. package/docs/ui_engineering.md +3 -1
  5. package/eslint.config.mjs +0 -5
  6. package/front_end/core/sdk/CPUThrottlingManager.ts +13 -8
  7. package/front_end/core/sdk/CSSMetadata.ts +23 -0
  8. package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +8 -4
  9. package/front_end/core/sdk/DOMModel.ts +4 -0
  10. package/front_end/core/sdk/EmulationModel.ts +4 -0
  11. package/front_end/core/sdk/ResourceTreeModel.ts +3 -2
  12. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +459 -74
  13. package/front_end/entrypoints/main/MainImpl.ts +0 -6
  14. package/front_end/foundation/Universe.ts +18 -0
  15. package/front_end/generated/InspectorBackendCommands.ts +7 -6
  16. package/front_end/generated/SupportedCSSProperties.js +208 -34
  17. package/front_end/generated/protocol.ts +64 -7
  18. package/front_end/models/ai_assistance/AiAgent2.ts +3 -3
  19. package/front_end/models/ai_assistance/AiConversation.ts +2 -1
  20. package/front_end/models/ai_assistance/README.md +5 -4
  21. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +1 -1
  22. package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +2 -2
  23. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +11 -164
  24. package/front_end/models/ai_assistance/ai_assistance.ts +6 -2
  25. package/front_end/models/ai_assistance/contexts/PerformanceTraceContext.ts +295 -0
  26. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +10 -10
  27. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +12 -11
  28. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +6 -6
  29. package/front_end/models/ai_assistance/skills/accessibility.md +4 -2
  30. package/front_end/models/ai_assistance/tools/GetElementAccessibilityDetails.ts +142 -0
  31. package/front_end/models/ai_assistance/tools/GetStyles.ts +1 -1
  32. package/front_end/models/ai_assistance/tools/README.md +22 -2
  33. package/front_end/models/ai_assistance/tools/{ResolveLighthousePath.ts → ResolveDevtoolsNodePath.ts} +18 -17
  34. package/front_end/models/ai_assistance/tools/Tool.ts +7 -2
  35. package/front_end/models/ai_assistance/tools/ToolRegistry.ts +10 -8
  36. package/front_end/models/autofill_manager/AutofillManager.ts +7 -15
  37. package/front_end/models/bindings/NetworkProject.ts +4 -8
  38. package/front_end/models/breakpoints/BreakpointManager.ts +9 -9
  39. package/front_end/models/emulation/DeviceModeModel.ts +24 -0
  40. package/front_end/models/emulation/EmulatedDevices.ts +108 -0
  41. package/front_end/models/heap_snapshot/HeapSnapshotModel.ts +36 -0
  42. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +8 -0
  43. package/front_end/models/issues_manager/IssuesManager.ts +10 -6
  44. package/front_end/models/javascript_metadata/JavaScriptMetadata.ts +4 -5
  45. package/front_end/models/live-metrics/LiveMetrics.ts +6 -6
  46. package/front_end/models/live-metrics/web-vitals-injected/spec/spec.ts +5 -5
  47. package/front_end/models/live-metrics/web-vitals-injected/web-vitals-injected.ts +3 -3
  48. package/front_end/models/logs/LogManager.ts +25 -10
  49. package/front_end/models/logs/NetworkLog.ts +24 -19
  50. package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +14 -5
  51. package/front_end/models/persistence/IsolatedFileSystem.ts +9 -11
  52. package/front_end/models/persistence/IsolatedFileSystemManager.ts +5 -3
  53. package/front_end/models/persistence/NetworkPersistenceManager.ts +73 -44
  54. package/front_end/models/persistence/PersistenceImpl.ts +4 -5
  55. package/front_end/models/trace/EntityMapper.ts +1 -1
  56. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +9 -9
  57. package/front_end/panels/ai_assistance/ExportConversation.ts +4 -1
  58. package/front_end/panels/ai_assistance/components/ChatInput.ts +2 -2
  59. package/front_end/panels/application/IndexedDBViews.ts +38 -36
  60. package/front_end/panels/application/components/AdsView.ts +4 -0
  61. package/front_end/panels/autofill/AutofillView.ts +1 -1
  62. package/front_end/panels/autofill/autofill-meta.ts +3 -2
  63. package/front_end/panels/elements/AccessibilityTreeUtils.ts +26 -15
  64. package/front_end/panels/elements/AccessibilityTreeView.ts +12 -9
  65. package/front_end/panels/elements/ElementsTreeOutline.ts +5 -0
  66. package/front_end/panels/layer_viewer/LayerTreeOutline.ts +118 -68
  67. package/front_end/panels/layer_viewer/Layers3DView.ts +1 -1
  68. package/front_end/panels/layer_viewer/layerTreeOutline.css +20 -13
  69. package/front_end/panels/layers/LayersPanel.ts +1 -1
  70. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +64 -17
  71. package/front_end/panels/mobile_throttling/throttlingSettingsTab.css +5 -0
  72. package/front_end/panels/network/LinkPreloadGenerator.ts +101 -0
  73. package/front_end/panels/network/NetworkLogView.ts +28 -0
  74. package/front_end/panels/network/network.ts +2 -0
  75. package/front_end/panels/profiler/HeapSnapshotView.ts +121 -33
  76. package/front_end/panels/profiler/ModuleUIStrings.ts +4 -0
  77. package/front_end/panels/sources/ScopeChainSidebarPane.ts +0 -12
  78. package/front_end/panels/timeline/TimelineHistoryManager.ts +38 -37
  79. package/front_end/panels/timeline/TimelinePanel.ts +32 -8
  80. package/front_end/panels/timeline/components/CPUThrottlingSelector.ts +7 -6
  81. package/front_end/panels/timeline/components/LiveMetricsView.ts +38 -38
  82. package/front_end/panels/timeline/components/MetricCard.ts +18 -18
  83. package/front_end/panels/timeline/components/liveMetricsView.css +6 -6
  84. package/front_end/panels/timeline/components/metricCard.css +4 -4
  85. package/front_end/panels/whats_new/ReleaseNoteText.ts +3 -3
  86. package/front_end/panels/whats_new/resources/WNDT.md +1 -1
  87. package/front_end/third_party/chromium/README.chromium +1 -1
  88. package/front_end/ui/legacy/InspectorDrawerView.ts +7 -5
  89. package/front_end/ui/legacy/ListWidget.ts +12 -0
  90. package/front_end/ui/legacy/SplitWidget.ts +12 -11
  91. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +23 -19
  92. package/front_end/ui/legacy/components/object_ui/CustomPreviewComponent.ts +8 -1
  93. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +110 -17
  94. package/front_end/ui/legacy/treeoutline.css +1 -1
  95. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  96. package/package.json +4 -3
@@ -291,7 +291,7 @@ export class LiveMetrics extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
291
291
  const warnings: string[] = [];
292
292
  const lcpEvent: LcpValue = {
293
293
  value: webVitalsEvent.value,
294
- phases: webVitalsEvent.phases,
294
+ subparts: webVitalsEvent.subparts,
295
295
  warnings,
296
296
  };
297
297
  if (webVitalsEvent.nodeIndex !== undefined) {
@@ -323,7 +323,7 @@ export class LiveMetrics extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
323
323
  case 'INP': {
324
324
  const inpEvent: InpValue = {
325
325
  value: webVitalsEvent.value,
326
- phases: webVitalsEvent.phases,
326
+ subparts: webVitalsEvent.subparts,
327
327
  interactionId: `interaction-${webVitalsEvent.entryGroupId}-${webVitalsEvent.startTime}`,
328
328
  };
329
329
  this.#inpValue = inpEvent;
@@ -345,7 +345,7 @@ export class LiveMetrics extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
345
345
  interactionType: webVitalsEvent.interactionType,
346
346
  duration: webVitalsEvent.duration,
347
347
  eventNames: [],
348
- phases: webVitalsEvent.phases,
348
+ subparts: webVitalsEvent.subparts,
349
349
  startTime: webVitalsEvent.startTime,
350
350
  nextPaintTime: webVitalsEvent.nextPaintTime,
351
351
  longAnimationFrameTimings: webVitalsEvent.longAnimationFrameEntries,
@@ -610,12 +610,12 @@ export interface MetricValue {
610
610
  }
611
611
 
612
612
  export interface LcpValue extends MetricValue {
613
- phases: Spec.LcpPhases;
613
+ subparts: Spec.LcpSubparts;
614
614
  nodeRef?: SDK.DOMModel.DOMNode;
615
615
  }
616
616
 
617
617
  export interface InpValue extends MetricValue {
618
- phases: Spec.InpPhases;
618
+ subparts: Spec.InpSubparts;
619
619
  interactionId: InteractionId;
620
620
  }
621
621
 
@@ -636,7 +636,7 @@ export interface Interaction {
636
636
  duration: number;
637
637
  startTime: number;
638
638
  nextPaintTime: number;
639
- phases: Spec.InpPhases;
639
+ subparts: Spec.InpSubparts;
640
640
  longAnimationFrameTimings: Spec.PerformanceLongAnimationFrameTimingJSON[];
641
641
  nodeRef?: SDK.DOMModel.DOMNode;
642
642
  }
@@ -18,14 +18,14 @@ export function getUniqueLayoutShiftId(entry: LayoutShift): UniqueLayoutShiftId
18
18
  return `layout-shift-${entry.value}-${entry.startTime}`;
19
19
  }
20
20
 
21
- export interface LcpPhases {
21
+ export interface LcpSubparts {
22
22
  timeToFirstByte: Trace.Types.Timing.Milli;
23
23
  resourceLoadDelay: Trace.Types.Timing.Milli;
24
24
  resourceLoadTime: Trace.Types.Timing.Milli;
25
25
  elementRenderDelay: Trace.Types.Timing.Milli;
26
26
  }
27
27
 
28
- export interface InpPhases {
28
+ export interface InpSubparts {
29
29
  inputDelay: Trace.Types.Timing.Milli;
30
30
  processingDuration: Trace.Types.Timing.Milli;
31
31
  presentationDelay: Trace.Types.Timing.Milli;
@@ -34,7 +34,7 @@ export interface InpPhases {
34
34
  export interface LcpChangeEvent {
35
35
  name: 'LCP';
36
36
  value: Trace.Types.Timing.Milli;
37
- phases: LcpPhases;
37
+ subparts: LcpSubparts;
38
38
  startedHidden: boolean;
39
39
  nodeIndex?: number;
40
40
  }
@@ -49,7 +49,7 @@ export interface InpChangeEvent {
49
49
  name: 'INP';
50
50
  value: Trace.Types.Timing.Milli;
51
51
  interactionType: INPAttribution['interactionType'];
52
- phases: InpPhases;
52
+ subparts: InpSubparts;
53
53
  startTime: number;
54
54
  entryGroupId: InteractionEntryGroupId;
55
55
  }
@@ -95,7 +95,7 @@ export interface InteractionEntryEvent {
95
95
  startTime: number;
96
96
  nextPaintTime: number;
97
97
  duration: Trace.Types.Timing.Milli;
98
- phases: InpPhases;
98
+ subparts: InpSubparts;
99
99
  nodeIndex?: number;
100
100
  longAnimationFrameEntries: PerformanceLongAnimationFrameTimingJSON[];
101
101
  }
@@ -182,7 +182,7 @@ function initialize(): void {
182
182
  name: 'LCP',
183
183
  value: metric.value as Trace.Types.Timing.Milli,
184
184
  startedHidden: Boolean(startedHidden),
185
- phases: {
185
+ subparts: {
186
186
  timeToFirstByte: metric.attribution.timeToFirstByte as Trace.Types.Timing.Milli,
187
187
  resourceLoadDelay: metric.attribution.resourceLoadDelay as Trace.Types.Timing.Milli,
188
188
  resourceLoadTime: metric.attribution.resourceLoadDuration as Trace.Types.Timing.Milli,
@@ -213,7 +213,7 @@ function initialize(): void {
213
213
  const event: Spec.InteractionEntryEvent = {
214
214
  name: 'InteractionEntry',
215
215
  duration: interaction.value as Trace.Types.Timing.Milli,
216
- phases: {
216
+ subparts: {
217
217
  inputDelay: interaction.attribution.inputDelay as Trace.Types.Timing.Milli,
218
218
  processingDuration: interaction.attribution.processingDuration as Trace.Types.Timing.Milli,
219
219
  presentationDelay: interaction.attribution.presentationDelay as Trace.Types.Timing.Milli,
@@ -238,7 +238,7 @@ function initialize(): void {
238
238
  const event: Spec.InpChangeEvent = {
239
239
  name: 'INP',
240
240
  value: metric.value as Trace.Types.Timing.Milli,
241
- phases: {
241
+ subparts: {
242
242
  inputDelay: metric.attribution.inputDelay as Trace.Types.Timing.Milli,
243
243
  processingDuration: metric.attribution.processingDuration as Trace.Types.Timing.Milli,
244
244
  presentationDelay: metric.attribution.presentationDelay as Trace.Types.Timing.Milli,
@@ -4,6 +4,7 @@
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import type * as Platform from '../../core/platform/platform.js';
7
+ import * as Root from '../../core/root/root.js';
7
8
  import * as SDK from '../../core/sdk/sdk.js';
8
9
  import * as Protocol from '../../generated/protocol.js';
9
10
 
@@ -11,19 +12,33 @@ import {NetworkLog} from './NetworkLog.js';
11
12
 
12
13
  const modelToEventListeners = new WeakMap<SDK.LogModel.LogModel, Common.EventTarget.EventDescriptor[]>();
13
14
 
14
- let instance: LogManager|null = null;
15
-
16
15
  export class LogManager implements SDK.TargetManager.SDKModelObserver<SDK.LogModel.LogModel> {
17
- private constructor() {
18
- SDK.TargetManager.TargetManager.instance().observeModels(SDK.LogModel.LogModel, this);
16
+ readonly #targetManager: SDK.TargetManager.TargetManager;
17
+ readonly #networkLog: NetworkLog;
18
+
19
+ constructor(
20
+ targetManager: SDK.TargetManager.TargetManager,
21
+ networkLog: NetworkLog,
22
+ ) {
23
+ this.#targetManager = targetManager;
24
+ this.#networkLog = networkLog;
25
+ this.#targetManager.observeModels(SDK.LogModel.LogModel, this);
19
26
  }
20
27
 
21
28
  static instance({forceNew}: {forceNew: boolean} = {forceNew: false}): LogManager {
22
- if (!instance || forceNew) {
23
- instance = new LogManager();
29
+ if (!Root.DevToolsContext.globalInstance().has(LogManager) || forceNew) {
30
+ Root.DevToolsContext.globalInstance().set(LogManager,
31
+ new LogManager(
32
+ SDK.TargetManager.TargetManager.instance(),
33
+ NetworkLog.instance(),
34
+ ));
24
35
  }
25
36
 
26
- return instance;
37
+ return Root.DevToolsContext.globalInstance().get(LogManager);
38
+ }
39
+
40
+ static removeInstance(): void {
41
+ Root.DevToolsContext.globalInstance().delete(LogManager);
27
42
  }
28
43
 
29
44
  modelAdded(logModel: SDK.LogModel.LogModel): void {
@@ -56,7 +71,7 @@ export class LogManager implements SDK.TargetManager.SDKModelObserver<SDK.LogMod
56
71
  target.model(SDK.RuntimeModel.RuntimeModel), entry.source, entry.level, entry.text, details);
57
72
 
58
73
  if (entry.networkRequestId) {
59
- NetworkLog.instance().associateConsoleMessageWithRequest(consoleMessage, entry.networkRequestId);
74
+ this.#networkLog.associateConsoleMessageWithRequest(consoleMessage, entry.networkRequestId);
60
75
  }
61
76
 
62
77
  const consoleModel = target.model(SDK.ConsoleModel.ConsoleModel);
@@ -66,11 +81,11 @@ export class LogManager implements SDK.TargetManager.SDKModelObserver<SDK.LogMod
66
81
  // user can see messages from the worker which has been already destroyed.
67
82
  // When opening DevTools, give us some time to connect to the worker and
68
83
  // not report the message twice if the worker is still alive.
69
- if (SDK.TargetManager.TargetManager.instance().targetById(workerId)) {
84
+ if (this.#targetManager.targetById(workerId)) {
70
85
  return;
71
86
  }
72
87
  window.setTimeout(() => {
73
- if (!SDK.TargetManager.TargetManager.instance().targetById(workerId)) {
88
+ if (!this.#targetManager.targetById(workerId)) {
74
89
  consoleModel?.addMessage(consoleMessage);
75
90
  }
76
91
  }, 1000);
@@ -5,6 +5,7 @@
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
7
  import * as Platform from '../../core/platform/platform.js';
8
+ import * as Root from '../../core/root/root.js';
8
9
  import * as SDK from '../../core/sdk/sdk.js';
9
10
  import * as Protocol from '../../generated/protocol.js';
10
11
 
@@ -18,8 +19,6 @@ const UIStrings = {
18
19
  const str_ = i18n.i18n.registerUIStrings('models/logs/NetworkLog.ts', UIStrings);
19
20
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
20
21
 
21
- let networkLogInstance: NetworkLog|undefined;
22
-
23
22
  export class NetworkLog extends Common.ObjectWrapper.ObjectWrapper<EventTypes> implements
24
23
  SDK.TargetManager.SDKModelObserver<SDK.NetworkManager.NetworkManager> {
25
24
  #requests: SDK.NetworkRequest.NetworkRequest[] = [];
@@ -32,15 +31,21 @@ export class NetworkLog extends Common.ObjectWrapper.ObjectWrapper<EventTypes> i
32
31
  readonly #modelListeners = new WeakMap<SDK.NetworkManager.NetworkManager, Common.EventTarget.EventDescriptor[]>();
33
32
  readonly #initiatorData = new WeakMap<SDK.NetworkRequest.NetworkRequest, InitiatorData>();
34
33
  #isRecording = true;
34
+ readonly #targetManager: SDK.TargetManager.TargetManager;
35
+ readonly #settings: Common.Settings.Settings;
35
36
 
36
- constructor() {
37
+ constructor(
38
+ targetManager: SDK.TargetManager.TargetManager = SDK.TargetManager.TargetManager.instance(),
39
+ settings: Common.Settings.Settings = Common.Settings.Settings.instance(),
40
+ ) {
37
41
  super();
42
+ this.#targetManager = targetManager;
43
+ this.#settings = settings;
38
44
 
39
- SDK.TargetManager.TargetManager.instance().observeModels(SDK.NetworkManager.NetworkManager, this);
40
- const recordLogSetting: Common.Settings.Setting<boolean> =
41
- Common.Settings.Settings.instance().moduleSetting('network-log.record-log');
45
+ this.#targetManager.observeModels(SDK.NetworkManager.NetworkManager, this);
46
+ const recordLogSetting: Common.Settings.Setting<boolean> = this.#settings.moduleSetting('network-log.record-log');
42
47
  recordLogSetting.addChangeListener(() => {
43
- const preserveLogSetting = Common.Settings.Settings.instance().moduleSetting('network-log.preserve-log');
48
+ const preserveLogSetting = this.#settings.moduleSetting('network-log.preserve-log');
44
49
  if (!preserveLogSetting.get() && recordLogSetting.get()) {
45
50
  this.reset(true);
46
51
  }
@@ -49,14 +54,15 @@ export class NetworkLog extends Common.ObjectWrapper.ObjectWrapper<EventTypes> i
49
54
  }
50
55
 
51
56
  static instance(): NetworkLog {
52
- if (!networkLogInstance) {
53
- networkLogInstance = new NetworkLog();
57
+ if (!Root.DevToolsContext.globalInstance().has(NetworkLog)) {
58
+ Root.DevToolsContext.globalInstance().set(NetworkLog, new NetworkLog());
54
59
  }
55
- return networkLogInstance;
60
+
61
+ return Root.DevToolsContext.globalInstance().get(NetworkLog);
56
62
  }
57
63
 
58
64
  static removeInstance(): void {
59
- networkLogInstance = undefined;
65
+ Root.DevToolsContext.globalInstance().delete(NetworkLog);
60
66
  }
61
67
 
62
68
  modelAdded(networkManager: SDK.NetworkManager.NetworkManager): void {
@@ -102,11 +108,10 @@ export class NetworkLog extends Common.ObjectWrapper.ObjectWrapper<EventTypes> i
102
108
  }
103
109
  this.#isRecording = enabled;
104
110
  if (enabled) {
105
- SDK.TargetManager.TargetManager.instance().observeModels(SDK.NetworkManager.NetworkManager, this);
111
+ this.#targetManager.observeModels(SDK.NetworkManager.NetworkManager, this);
106
112
  } else {
107
- SDK.TargetManager.TargetManager.instance().unobserveModels(SDK.NetworkManager.NetworkManager, this);
108
- SDK.TargetManager.TargetManager.instance()
109
- .models(SDK.NetworkManager.NetworkManager)
113
+ this.#targetManager.unobserveModels(SDK.NetworkManager.NetworkManager, this);
114
+ this.#targetManager.models(SDK.NetworkManager.NetworkManager)
110
115
  .forEach(this.removeNetworkManagerListeners.bind(this));
111
116
  }
112
117
  }
@@ -289,7 +294,7 @@ export class NetworkLog extends Common.ObjectWrapper.ObjectWrapper<EventTypes> i
289
294
  }
290
295
 
291
296
  private willReloadPage(): void {
292
- if (!Common.Settings.Settings.instance().moduleSetting('network-log.preserve-log').get()) {
297
+ if (!this.#settings.moduleSetting('network-log.preserve-log').get()) {
293
298
  this.reset(true);
294
299
  }
295
300
  }
@@ -310,7 +315,7 @@ export class NetworkLog extends Common.ObjectWrapper.ObjectWrapper<EventTypes> i
310
315
  return;
311
316
  }
312
317
 
313
- const preserveLog = Common.Settings.Settings.instance().moduleSetting('network-log.preserve-log').get();
318
+ const preserveLog = this.#settings.moduleSetting('network-log.preserve-log').get();
314
319
 
315
320
  const oldRequests = this.#requests;
316
321
  const oldManagerRequests =
@@ -501,8 +506,8 @@ export class NetworkLog extends Common.ObjectWrapper.ObjectWrapper<EventTypes> i
501
506
  this.#requestsSet.clear();
502
507
  this.#requestsMap.clear();
503
508
  this.#unresolvedPreflightRequests.clear();
504
- const managers = new Set<SDK.NetworkManager.NetworkManager>(
505
- SDK.TargetManager.TargetManager.instance().models(SDK.NetworkManager.NetworkManager));
509
+ const managers =
510
+ new Set<SDK.NetworkManager.NetworkManager>(this.#targetManager.models(SDK.NetworkManager.NetworkManager));
506
511
  for (const manager of this.#pageLoadForManager.keys()) {
507
512
  if (!managers.has(manager)) {
508
513
  this.#pageLoadForManager.delete(manager);
@@ -141,14 +141,23 @@ export class FileSystem implements Workspace.Workspace.Project {
141
141
  return [];
142
142
  }
143
143
 
144
- async findFilesMatchingSearchRequest(
145
- _searchConfig: Workspace.SearchConfig.SearchConfig,
146
- _filesMatchingFileQuery: Workspace.UISourceCode.UISourceCode[],
147
- _progress: Common.Progress.Progress): Promise<Map<Workspace.UISourceCode.UISourceCode, SearchMatch[]|null>> {
144
+ async findFilesMatchingSearchRequest(_searchConfig: Workspace.SearchConfig.SearchConfig,
145
+ _filesMatchingFileQuery: Workspace.UISourceCode.UISourceCode[],
146
+ progress: Common.Progress.Progress):
147
+ Promise<Map<Workspace.UISourceCode.UISourceCode, SearchMatch[]|null>> {
148
+ // Defer completion to the next microtask to avoid triggering premature
149
+ // completion events in CompositeProgress setup loops.
150
+ await Promise.resolve();
151
+ progress.done = true;
148
152
  return new Map();
149
153
  }
150
154
 
151
- indexContent(_progress: Common.Progress.Progress): void {
155
+ indexContent(progress: Common.Progress.Progress): void {
156
+ // Defer completion to the next microtask to avoid triggering premature
157
+ // completion events in CompositeProgress setup loops.
158
+ queueMicrotask(() => {
159
+ progress.done = true;
160
+ });
152
161
  }
153
162
 
154
163
  uiSourceCodeForURL(_url: Platform.DevToolsPath.UrlString): Workspace.UISourceCode.UISourceCode|null {
@@ -58,29 +58,27 @@ export class IsolatedFileSystem extends PlatformFileSystem {
58
58
  readonly #initialGitFolders = new Set<Platform.DevToolsPath.EncodedPathString>();
59
59
  private readonly fileLocks = new Map<Platform.DevToolsPath.EncodedPathString, Promise<unknown>>();
60
60
 
61
- constructor(
62
- manager: IsolatedFileSystemManager, path: Platform.DevToolsPath.UrlString,
63
- embedderPath: Platform.DevToolsPath.RawPathString, domFileSystem: FileSystem, type: PlatformFileSystemType,
64
- automatic: boolean) {
61
+ constructor(manager: IsolatedFileSystemManager, path: Platform.DevToolsPath.UrlString,
62
+ embedderPath: Platform.DevToolsPath.RawPathString, domFileSystem: FileSystem,
63
+ type: PlatformFileSystemType, automatic: boolean, settings: Common.Settings.Settings) {
65
64
  super(path, type, automatic);
66
65
  this.manager = manager;
67
66
  this.#embedderPath = embedderPath;
68
67
  this.domFileSystem = domFileSystem;
69
- this.excludedFoldersSetting =
70
- Common.Settings.Settings.instance().createLocalSetting('workspace-excluded-folders', {});
68
+ this.excludedFoldersSetting = settings.createLocalSetting('workspace-excluded-folders', {});
71
69
  this.#excludedFolders = new Set(this.excludedFoldersSetting.get()[path] || []);
72
70
  }
73
71
 
74
- static async create(
75
- manager: IsolatedFileSystemManager, path: Platform.DevToolsPath.UrlString,
76
- embedderPath: Platform.DevToolsPath.RawPathString, type: PlatformFileSystemType, name: string, rootURL: string,
77
- automatic: boolean): Promise<IsolatedFileSystem|null> {
72
+ static async create(manager: IsolatedFileSystemManager, path: Platform.DevToolsPath.UrlString,
73
+ embedderPath: Platform.DevToolsPath.RawPathString, type: PlatformFileSystemType, name: string,
74
+ rootURL: string, automatic: boolean,
75
+ settings: Common.Settings.Settings): Promise<IsolatedFileSystem|null> {
78
76
  const domFileSystem = Host.InspectorFrontendHost.InspectorFrontendHostInstance.isolatedFileSystem(name, rootURL);
79
77
  if (!domFileSystem) {
80
78
  return null;
81
79
  }
82
80
 
83
- const fileSystem = new IsolatedFileSystem(manager, path, embedderPath, domFileSystem, type, automatic);
81
+ const fileSystem = new IsolatedFileSystem(manager, path, embedderPath, domFileSystem, type, automatic, settings);
84
82
  return await fileSystem.initializeFilePaths().then(() => fileSystem).catch(error => {
85
83
  console.error(error);
86
84
  return null;
@@ -33,8 +33,10 @@ export class IsolatedFileSystemManager extends Common.ObjectWrapper.ObjectWrappe
33
33
  readonly #workspaceFolderExcludePatternSetting: Common.Settings.RegExpSetting;
34
34
  private fileSystemRequestResolve: ((arg0: IsolatedFileSystem|null) => void)|null;
35
35
  private readonly fileSystemsLoadedPromise: Promise<IsolatedFileSystem[]>;
36
- private constructor() {
36
+ readonly #settings: Common.Settings.Settings;
37
+ private constructor(settings: Common.Settings.Settings = Common.Settings.Settings.instance()) {
37
38
  super();
39
+ this.#settings = settings;
38
40
 
39
41
  this.#fileSystems = new Map();
40
42
  this.callbacks = new Map();
@@ -90,7 +92,7 @@ export class IsolatedFileSystemManager extends Common.ObjectWrapper.ObjectWrappe
90
92
  defaultExcludedFolders = defaultExcludedFolders.concat(defaultLinuxExcludedFolders);
91
93
  }
92
94
  const defaultExcludedFoldersPattern = defaultExcludedFolders.join('|');
93
- this.#workspaceFolderExcludePatternSetting = Common.Settings.Settings.instance().createRegExpSetting(
95
+ this.#workspaceFolderExcludePatternSetting = this.#settings.createRegExpSetting(
94
96
  'workspace-folder-exclude-pattern', defaultExcludedFoldersPattern, Host.Platform.isWin() ? 'i' : '');
95
97
 
96
98
  this.fileSystemRequestResolve = null;
@@ -160,7 +162,7 @@ export class IsolatedFileSystemManager extends Common.ObjectWrapper.ObjectWrappe
160
162
  const fileSystemURL = Common.ParsedURL.ParsedURL.rawPathToUrlString(fileSystem.fileSystemPath);
161
163
  const promise = IsolatedFileSystem.create(
162
164
  this, fileSystemURL, embedderPath, hostFileSystemTypeToPlatformFileSystemType(fileSystem.type),
163
- fileSystem.fileSystemName, fileSystem.rootURL, fileSystem.type === 'automatic');
165
+ fileSystem.fileSystemName, fileSystem.rootURL, fileSystem.type === 'automatic', this.#settings);
164
166
  return promise.then(storeFileSystem.bind(this));
165
167
 
166
168
  function storeFileSystem(this: IsolatedFileSystemManager, fileSystem: IsolatedFileSystem|null): IsolatedFileSystem|
@@ -5,6 +5,7 @@
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import * as Host from '../../core/host/host.js';
7
7
  import * as Platform from '../../core/platform/platform.js';
8
+ import * as Root from '../../core/root/root.js';
8
9
  import * as SDK from '../../core/sdk/sdk.js';
9
10
  import * as Protocol from '../../generated/protocol.js';
10
11
  import * as Breakpoints from '../breakpoints/breakpoints.js';
@@ -15,8 +16,6 @@ import {type FileSystem, FileSystemWorkspaceBinding} from './FileSystemWorkspace
15
16
  import {IsolatedFileSystemManager} from './IsolatedFileSystemManager.js';
16
17
  import {PersistenceBinding, PersistenceImpl} from './PersistenceImpl.js';
17
18
 
18
- let networkPersistenceManagerInstance: NetworkPersistenceManager|null;
19
-
20
19
  const forbiddenUrls = ['chromewebstore.google.com', 'chrome.google.com'];
21
20
 
22
21
  export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes> implements
@@ -24,8 +23,14 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
24
23
  #bindings = new WeakMap<Workspace.UISourceCode.UISourceCode, PersistenceBinding>();
25
24
  readonly #originalResponseContentPromises = new WeakMap<Workspace.UISourceCode.UISourceCode, Promise<string|null>>();
26
25
  #savingForOverrides = new WeakSet<Workspace.UISourceCode.UISourceCode>();
27
- #enabledSetting = Common.Settings.Settings.instance().moduleSetting<boolean>('persistence-network-overrides-enabled');
26
+ readonly #enabledSetting: Common.Settings.Setting<boolean>;
28
27
  readonly #workspace: Workspace.Workspace.WorkspaceImpl;
28
+ readonly #persistence: PersistenceImpl;
29
+ readonly #breakpointManager: Breakpoints.BreakpointManager.BreakpointManager;
30
+ readonly #targetManager: SDK.TargetManager.TargetManager;
31
+ readonly #settings: Common.Settings.Settings;
32
+ readonly #isolatedFileSystemManager: IsolatedFileSystemManager;
33
+ readonly #multitargetNetworkManager: SDK.NetworkManager.MultitargetNetworkManager;
29
34
  readonly #networkUISourceCodeForEncodedPath =
30
35
  new Map<Platform.DevToolsPath.EncodedPathString, Workspace.UISourceCode.UISourceCode>();
31
36
  readonly #interceptionHandlerBound: (interceptedRequest: SDK.NetworkManager.InterceptedRequest) => Promise<void>;
@@ -39,12 +44,27 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
39
44
  readonly #eventDispatchThrottler = new Common.Throttler.Throttler(50);
40
45
  #headerOverridesForEventDispatch = new Set<Workspace.UISourceCode.UISourceCode>();
41
46
 
42
- private constructor(workspace: Workspace.Workspace.WorkspaceImpl) {
47
+ constructor(
48
+ workspace: Workspace.Workspace.WorkspaceImpl,
49
+ persistence: PersistenceImpl,
50
+ breakpointManager: Breakpoints.BreakpointManager.BreakpointManager,
51
+ targetManager: SDK.TargetManager.TargetManager,
52
+ settings: Common.Settings.Settings,
53
+ isolatedFileSystemManager: IsolatedFileSystemManager,
54
+ multitargetNetworkManager: SDK.NetworkManager.MultitargetNetworkManager,
55
+ ) {
43
56
  super();
44
57
 
45
- this.#enabledSetting.addChangeListener(this.enabledChanged, this);
46
-
47
58
  this.#workspace = workspace;
59
+ this.#persistence = persistence;
60
+ this.#breakpointManager = breakpointManager;
61
+ this.#targetManager = targetManager;
62
+ this.#settings = settings;
63
+ this.#isolatedFileSystemManager = isolatedFileSystemManager;
64
+ this.#multitargetNetworkManager = multitargetNetworkManager;
65
+
66
+ this.#enabledSetting = this.#settings.moduleSetting<boolean>('persistence-network-overrides-enabled');
67
+ this.#enabledSetting.addChangeListener(this.enabledChanged, this);
48
68
 
49
69
  this.#interceptionHandlerBound = this.interceptionHandler.bind(this);
50
70
 
@@ -55,13 +75,12 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
55
75
  void this.onProjectRemoved(event.data);
56
76
  });
57
77
 
58
- PersistenceImpl.instance().addNetworkInterceptor(this.canHandleNetworkUISourceCode.bind(this));
59
- Breakpoints.BreakpointManager.BreakpointManager.instance().addUpdateBindingsCallback(
60
- this.networkUISourceCodeAdded.bind(this));
78
+ this.#persistence.addNetworkInterceptor(this.canHandleNetworkUISourceCode.bind(this));
79
+ this.#breakpointManager.addUpdateBindingsCallback(this.networkUISourceCodeAdded.bind(this));
61
80
 
62
81
  void this.enabledChanged();
63
82
 
64
- SDK.TargetManager.TargetManager.instance().observeTargets(this);
83
+ this.#targetManager.observeTargets(this);
65
84
  }
66
85
 
67
86
  targetAdded(): void {
@@ -76,14 +95,29 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
76
95
  workspace: Workspace.Workspace.WorkspaceImpl|null,
77
96
  } = {forceNew: null, workspace: null}): NetworkPersistenceManager {
78
97
  const {forceNew, workspace} = opts;
79
- if (!networkPersistenceManagerInstance || forceNew) {
98
+ if (!Root.DevToolsContext.globalInstance().has(NetworkPersistenceManager) || forceNew) {
80
99
  if (!workspace) {
81
100
  throw new Error('Missing workspace for NetworkPersistenceManager');
82
101
  }
83
- networkPersistenceManagerInstance = new NetworkPersistenceManager(workspace);
102
+ Root.DevToolsContext.globalInstance().set(
103
+ NetworkPersistenceManager,
104
+ new NetworkPersistenceManager(
105
+ workspace,
106
+ PersistenceImpl.instance(),
107
+ Breakpoints.BreakpointManager.BreakpointManager.instance(),
108
+ SDK.TargetManager.TargetManager.instance(),
109
+ Common.Settings.Settings.instance(),
110
+ IsolatedFileSystemManager.instance(),
111
+ SDK.NetworkManager.MultitargetNetworkManager.instance(),
112
+ ),
113
+ );
84
114
  }
85
115
 
86
- return networkPersistenceManagerInstance;
116
+ return Root.DevToolsContext.globalInstance().get(NetworkPersistenceManager);
117
+ }
118
+
119
+ static removeInstance(): void {
120
+ Root.DevToolsContext.globalInstance().delete(NetworkPersistenceManager);
87
121
  }
88
122
 
89
123
  active(): boolean {
@@ -111,24 +145,20 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
111
145
  if (this.#enabled) {
112
146
  Host.userMetrics.actionTaken(Host.UserMetrics.Action.PersistenceNetworkOverridesEnabled);
113
147
  this.#eventDescriptors = [
114
- Workspace.Workspace.WorkspaceImpl.instance().addEventListener(
115
- Workspace.Workspace.Events.UISourceCodeRenamed,
116
- event => {
117
- void this.uiSourceCodeRenamedListener(event);
118
- }),
119
- Workspace.Workspace.WorkspaceImpl.instance().addEventListener(
120
- Workspace.Workspace.Events.UISourceCodeAdded,
121
- event => {
122
- void this.uiSourceCodeAdded(event);
123
- }),
124
- Workspace.Workspace.WorkspaceImpl.instance().addEventListener(
125
- Workspace.Workspace.Events.UISourceCodeRemoved,
126
- event => {
127
- void this.uiSourceCodeRemovedListener(event);
128
- }),
129
- Workspace.Workspace.WorkspaceImpl.instance().addEventListener(
130
- Workspace.Workspace.Events.WorkingCopyCommitted,
131
- event => this.onUISourceCodeWorkingCopyCommitted(event.data.uiSourceCode)),
148
+ this.#workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeRenamed,
149
+ event => {
150
+ void this.uiSourceCodeRenamedListener(event);
151
+ }),
152
+ this.#workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded,
153
+ event => {
154
+ void this.uiSourceCodeAdded(event);
155
+ }),
156
+ this.#workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeRemoved,
157
+ event => {
158
+ void this.uiSourceCodeRemovedListener(event);
159
+ }),
160
+ this.#workspace.addEventListener(Workspace.Workspace.Events.WorkingCopyCommitted,
161
+ event => this.onUISourceCodeWorkingCopyCommitted(event.data.uiSourceCode)),
132
162
  ];
133
163
  await this.updateActiveProject();
134
164
  } else {
@@ -158,8 +188,7 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
158
188
 
159
189
  private async updateActiveProject(): Promise<void> {
160
190
  const wasActive = this.#active;
161
- this.#active =
162
- Boolean(this.#enabledSetting.get() && SDK.TargetManager.TargetManager.instance().rootTarget() && this.#project);
191
+ this.#active = Boolean(this.#enabledSetting.get() && this.#targetManager.rootTarget() && this.#project);
163
192
  if (this.#active === wasActive) {
164
193
  return;
165
194
  }
@@ -178,7 +207,7 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
178
207
  [...this.#project.uiSourceCodes()].map(uiSourceCode => this.filesystemUISourceCodeRemoved(uiSourceCode)));
179
208
  this.#networkUISourceCodeForEncodedPath.clear();
180
209
  }
181
- PersistenceImpl.instance().refreshAutomapping();
210
+ this.#persistence.refreshAutomapping();
182
211
  }
183
212
 
184
213
  encodedPathFromUrl(url: Platform.DevToolsPath.UrlString, ignoreInactive?: boolean):
@@ -270,7 +299,7 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
270
299
  const folderUrlFromRequest =
271
300
  Common.ParsedURL.ParsedURL.substring(fileUrlFromRequest, 0, fileUrlFromRequest.lastIndexOf('/'));
272
301
  const headersFileUrl = Common.ParsedURL.ParsedURL.concatenate(folderUrlFromRequest, '/', HEADERS_FILENAME);
273
- return Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodeForURL(headersFileUrl);
302
+ return this.#workspace.uiSourceCodeForURL(headersFileUrl);
274
303
  }
275
304
 
276
305
  async getOrCreateHeadersUISourceCodeFromUrl(url: Platform.DevToolsPath.UrlString):
@@ -315,7 +344,7 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
315
344
  #innerUnbind(binding: PersistenceBinding): Promise<void> {
316
345
  this.#bindings.delete(binding.network);
317
346
  this.#bindings.delete(binding.fileSystem);
318
- return PersistenceImpl.instance().removeBinding(binding);
347
+ return this.#persistence.removeBinding(binding);
319
348
  }
320
349
 
321
350
  async #bind(
@@ -352,12 +381,12 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
352
381
  const binding = new PersistenceBinding(networkUISourceCode, fileSystemUISourceCode);
353
382
  this.#bindings.set(networkUISourceCode, binding);
354
383
  this.#bindings.set(fileSystemUISourceCode, binding);
355
- await PersistenceImpl.instance().addBinding(binding);
384
+ await this.#persistence.addBinding(binding);
356
385
  const uiSourceCodeOfTruth =
357
386
  this.#savingForOverrides.has(networkUISourceCode) ? networkUISourceCode : fileSystemUISourceCode;
358
387
  const contentDataOrError = await uiSourceCodeOfTruth.requestContentData();
359
388
  const {content, isEncoded} = TextUtils.ContentData.ContentData.asDeferredContent(contentDataOrError);
360
- PersistenceImpl.instance().syncContent(uiSourceCodeOfTruth, content || '', isEncoded);
389
+ this.#persistence.syncContent(uiSourceCodeOfTruth, content || '', isEncoded);
361
390
  }
362
391
 
363
392
  private onUISourceCodeWorkingCopyCommitted(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
@@ -398,7 +427,7 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
398
427
  if (this.#shouldPromptSaveForOverridesDialog(uiSourceCode)) {
399
428
  Host.userMetrics.actionTaken(Host.UserMetrics.Action.OverrideContentContextMenuSetup);
400
429
  await new Promise<void>(resolve => this.dispatchEventToListeners(Events.LOCAL_OVERRIDES_REQUESTED, resolve));
401
- await IsolatedFileSystemManager.instance().addFileSystem('overrides');
430
+ await this.#isolatedFileSystemManager.addFileSystem('overrides');
402
431
  }
403
432
 
404
433
  if (!this.project()) {
@@ -683,8 +712,8 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
683
712
  async #innerUpdateInterceptionPatterns(): Promise<void> {
684
713
  this.#headerOverridesMap.clear();
685
714
  if (!this.#active || !this.#project) {
686
- return await SDK.NetworkManager.MultitargetNetworkManager.instance().setInterceptionHandlerForPatterns(
687
- [], this.#interceptionHandlerBound);
715
+ return await this.#multitargetNetworkManager.setInterceptionHandlerForPatterns([],
716
+ this.#interceptionHandlerBound);
688
717
  }
689
718
  let patterns = new Set<string>();
690
719
  for (const uiSourceCode of this.#project.uiSourceCodes()) {
@@ -713,9 +742,9 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
713
742
  }
714
743
  }
715
744
 
716
- return await SDK.NetworkManager.MultitargetNetworkManager.instance().setInterceptionHandlerForPatterns(
717
- Array.from(patterns).map(
718
- pattern => ({urlPattern: pattern, requestStage: Protocol.Fetch.RequestStage.Response})),
745
+ return await this.#multitargetNetworkManager.setInterceptionHandlerForPatterns(
746
+ Array.from(patterns).map(pattern =>
747
+ ({urlPattern: pattern, requestStage: Protocol.Fetch.RequestStage.Response})),
719
748
  this.#interceptionHandlerBound);
720
749
  }
721
750