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
@@ -25,9 +25,23 @@ export interface Chunk {
25
25
 
26
26
  export type ChunkCallback = (arg0: Chunk) => void;
27
27
 
28
- export function createTokenizer(mimeType: string): (
29
- arg0: string, arg1: (arg0: string, arg1: string|null, arg2: number, arg3: number) => (Object | undefined | void)) =>
30
- void {
28
+ export type TokenizerCallback = (value: string, style: string|null, start: number, end: number) =>
29
+ Object|undefined|void;
30
+
31
+ /**
32
+ * A tokenizer function returned by {@link createTokenizer}.
33
+ *
34
+ * @param line The string content to tokenize.
35
+ * @param callback A callback function invoked for each token parsed.
36
+ * @param startOffset An optional offset pointing to where tokenization should start within
37
+ * the line, avoiding the need to allocate substrings when tokenizing a block inside a larger file.
38
+ */
39
+ export type Tokenizer = (line: string, callback: TokenizerCallback, startOffset?: number) => void;
40
+
41
+ /**
42
+ * Creates a tokenizer for the specified MIME type.
43
+ */
44
+ export function createTokenizer(mimeType: string): Tokenizer {
31
45
  const mode = CodeMirror.getMode({indentUnit: 2}, mimeType);
32
46
  const state = CodeMirror.startState(mode);
33
47
 
@@ -40,8 +54,13 @@ export function createTokenizer(mimeType: string): (
40
54
  }
41
55
 
42
56
  return (line: string,
43
- callback: (arg0: string, arg1: string|null, arg2: number, arg3: number) => void|Object|undefined) => {
57
+ callback: (arg0: string, arg1: string|null, arg2: number, arg3: number) => void|Object|undefined,
58
+ startOffset = 0) => {
44
59
  const stream = new CodeMirror.StringStream(line);
60
+ if (startOffset) {
61
+ stream.pos = startOffset;
62
+ stream.start = startOffset;
63
+ }
45
64
  while (!stream.eol()) {
46
65
  const style = mode.token(stream, state);
47
66
  const value = stream.current();
@@ -252,7 +252,7 @@ export class HTMLModel {
252
252
 
253
253
  #build(text: string): void {
254
254
  const tokenizer = createTokenizer('text/html');
255
- let baseOffset = 0, lastOffset = 0;
255
+ let lastOffset = 0;
256
256
  let pendingToken: Token|null = null;
257
257
 
258
258
  const pushToken = (token: Token): Object|undefined => {
@@ -274,8 +274,6 @@ export class HTMLModel {
274
274
  tokenStart: number,
275
275
  tokenEnd: number,
276
276
  ): Object|undefined => {
277
- tokenStart += baseOffset;
278
- tokenEnd += baseOffset;
279
277
  lastOffset = tokenEnd;
280
278
 
281
279
  const tokenType = type ? new Set<string>(type.split(' ')) : new Set<string>();
@@ -321,8 +319,7 @@ export class HTMLModel {
321
319
  };
322
320
 
323
321
  while (true) {
324
- baseOffset = lastOffset;
325
- tokenizer(text.substring(lastOffset), processToken);
322
+ tokenizer(text, processToken, lastOffset);
326
323
  if (pendingToken) {
327
324
  pushToken(pendingToken);
328
325
  pendingToken = null;
@@ -341,7 +338,11 @@ export class HTMLModel {
341
338
  lastOffset = text.length;
342
339
  break;
343
340
  }
344
- if (text.substring(lastOffset + 2).toLowerCase().startsWith(element.name)) {
341
+ // Check if the tag at lastOffset matches the current element name (e.g. </script>).
342
+ // Slice only the length of the tag name to avoid allocating a large substring
343
+ // of the remainder of the document.
344
+ const sliced = text.slice(lastOffset + 2, lastOffset + 2 + element.name.length);
345
+ if (sliced.toLowerCase() === element.name) {
345
346
  break;
346
347
  }
347
348
  lastOffset += 2;
@@ -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,
@@ -38,13 +38,12 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
38
38
  const DELAY_BEFORE_PROMOTION_COLLAPSE_IN_MS = 5000;
39
39
  const PROMOTION_END_DATE = new Date('2026-09-30');
40
40
 
41
- function getClickCountSetting(): Common.Settings.Setting<number> {
42
- return Common.Settings.Settings.instance().createSetting<number>(
43
- 'global-ai-button-click-count', 0, Common.Settings.SettingStorageType.SYNCED);
41
+ function getClickCountSetting(settings: Common.Settings.Settings): Common.Settings.Setting<number> {
42
+ return settings.createSetting<number>('global-ai-button-click-count', 0, Common.Settings.SettingStorageType.SYNCED);
44
43
  }
45
44
 
46
- function incrementClickCountSetting(): void {
47
- const setting = getClickCountSetting();
45
+ function incrementClickCountSetting(settings: Common.Settings.Settings): void {
46
+ const setting = getClickCountSetting(settings);
48
47
  setting.set(setting.get() + 1);
49
48
  }
50
49
 
@@ -89,10 +88,19 @@ export class GlobalAiButton extends UI.Widget.Widget {
89
88
  #buttonState: GlobalAiButtonState = GlobalAiButtonState.DEFAULT;
90
89
  #mouseOnMainToolbar = false;
91
90
  #returnToDefaultStateTimeout?: number;
92
-
93
- constructor(element?: HTMLElement, view?: View) {
91
+ readonly #settings: Common.Settings.Settings;
92
+ readonly #inspectorView: UI.InspectorView.InspectorView;
93
+ readonly #viewManager: UI.ViewManager.ViewManager;
94
+
95
+ constructor(element?: HTMLElement, view?: View,
96
+ settings: Common.Settings.Settings = Common.Settings.Settings.instance(),
97
+ inspectorView: UI.InspectorView.InspectorView = UI.InspectorView.InspectorView.instance(),
98
+ viewManager: UI.ViewManager.ViewManager = UI.ViewManager.ViewManager.instance()) {
94
99
  super(element);
95
100
  this.#view = view ?? DEFAULT_VIEW;
101
+ this.#settings = settings;
102
+ this.#inspectorView = inspectorView;
103
+ this.#viewManager = viewManager;
96
104
  this.requestUpdate();
97
105
 
98
106
  if (this.#shouldTriggerPromotion()) {
@@ -118,17 +126,13 @@ export class GlobalAiButton extends UI.Widget.Widget {
118
126
  };
119
127
 
120
128
  #addHoverEventListeners(): void {
121
- UI.InspectorView.InspectorView.instance().tabbedPane.headerElement().addEventListener(
122
- 'mouseenter', this.#handleMainToolbarMouseEnter);
123
- UI.InspectorView.InspectorView.instance().tabbedPane.headerElement().addEventListener(
124
- 'mouseleave', this.#handleMainToolbarMouseLeave);
129
+ this.#inspectorView.tabbedPane.headerElement().addEventListener('mouseenter', this.#handleMainToolbarMouseEnter);
130
+ this.#inspectorView.tabbedPane.headerElement().addEventListener('mouseleave', this.#handleMainToolbarMouseLeave);
125
131
  }
126
132
 
127
133
  #removeHoverEventListeners(): void {
128
- UI.InspectorView.InspectorView.instance().tabbedPane.headerElement().removeEventListener(
129
- 'mouseenter', this.#handleMainToolbarMouseEnter);
130
- UI.InspectorView.InspectorView.instance().tabbedPane.headerElement().removeEventListener(
131
- 'mouseleave', this.#handleMainToolbarMouseLeave);
134
+ this.#inspectorView.tabbedPane.headerElement().removeEventListener('mouseenter', this.#handleMainToolbarMouseEnter);
135
+ this.#inspectorView.tabbedPane.headerElement().removeEventListener('mouseleave', this.#handleMainToolbarMouseLeave);
132
136
  }
133
137
 
134
138
  // We only want to enable promotion when:
@@ -138,7 +142,7 @@ export class GlobalAiButton extends UI.Widget.Widget {
138
142
  #shouldTriggerPromotion(): boolean {
139
143
  const isFlagEnabled = Boolean(Root.Runtime.hostConfig.devToolsGlobalAiButton?.promotionEnabled);
140
144
  const isBeforeEndDate = (new Date()) < PROMOTION_END_DATE;
141
- return isFlagEnabled && isBeforeEndDate && getClickCountSetting().get() < 2;
145
+ return isFlagEnabled && isBeforeEndDate && getClickCountSetting(this.#settings).get() < 2;
142
146
  }
143
147
 
144
148
  #triggerPromotion(): void {
@@ -173,23 +177,21 @@ export class GlobalAiButton extends UI.Widget.Widget {
173
177
  }
174
178
 
175
179
  #onClick(): void {
176
- UI.ViewManager.ViewManager.instance().showViewInLocation('freestyler', 'drawer-view');
177
- incrementClickCountSetting();
180
+ this.#viewManager.showViewInLocation('freestyler', 'drawer-view');
181
+ incrementClickCountSetting(this.#settings);
178
182
 
179
- const hasExplicitUserPreference =
180
- UI.InspectorView.InspectorView.instance().isUserExplicitlyUpdatedDrawerOrientation();
183
+ const hasExplicitUserPreference = this.#inspectorView.isUserExplicitlyUpdatedDrawerOrientation();
181
184
  const isVerticalDrawerFeatureEnabled =
182
185
  Boolean(Root.Runtime.hostConfig.devToolsFlexibleLayout?.verticalDrawerEnabled);
183
186
  if (isVerticalDrawerFeatureEnabled && !hasExplicitUserPreference) {
184
187
  // This mimics what we're doing while showing the drawer via `ESC`.
185
188
  // There is a bug where opening the sidebar directly for the first time,
186
189
  // and triggering a drawer rotation without calling `showDrawer({focus: true})` makes the drawer disappear.
187
- UI.InspectorView.InspectorView.instance().showDrawer({
190
+ this.#inspectorView.showDrawer({
188
191
  focus: true,
189
192
  hasTargetDrawer: false,
190
193
  });
191
- UI.InspectorView.InspectorView.instance().toggleDrawerOrientation(
192
- {force: UI.InspectorView.DrawerOrientation.VERTICAL});
194
+ this.#inspectorView.toggleDrawerOrientation({force: UI.InspectorView.DrawerOrientation.VERTICAL});
193
195
  }
194
196
  }
195
197
 
@@ -203,14 +205,15 @@ export class GlobalAiButton extends UI.Widget.Widget {
203
205
  }
204
206
  }
205
207
 
206
- let globalAiButtonToolbarProviderInstance: GlobalAiButtonToolbarProvider;
207
208
  export class GlobalAiButtonToolbarProvider implements UI.Toolbar.Provider {
208
209
  #toolbarItem: UI.Toolbar.ToolbarItemWithCompactLayout;
209
210
  #widgetElement: UI.Widget.WidgetElement<GlobalAiButton>;
210
211
 
211
- private constructor() {
212
+ constructor(settings: Common.Settings.Settings = Common.Settings.Settings.instance(),
213
+ inspectorView: UI.InspectorView.InspectorView = UI.InspectorView.InspectorView.instance(),
214
+ viewManager: UI.ViewManager.ViewManager = UI.ViewManager.ViewManager.instance()) {
212
215
  this.#widgetElement = document.createElement('devtools-widget') as UI.Widget.WidgetElement<GlobalAiButton>;
213
- new GlobalAiButton(this.#widgetElement);
216
+ new GlobalAiButton(this.#widgetElement, undefined, settings, inspectorView, viewManager);
214
217
 
215
218
  this.#toolbarItem = new UI.Toolbar.ToolbarItemWithCompactLayout(this.#widgetElement);
216
219
  this.#toolbarItem.setVisible(false);
@@ -219,13 +222,4 @@ export class GlobalAiButtonToolbarProvider implements UI.Toolbar.Provider {
219
222
  item(): UI.Toolbar.ToolbarItem|null {
220
223
  return this.#toolbarItem;
221
224
  }
222
-
223
- static instance(opts: {forceNew: boolean|null} = {forceNew: null}): GlobalAiButtonToolbarProvider {
224
- const {forceNew} = opts;
225
- if (!globalAiButtonToolbarProviderInstance || forceNew) {
226
- globalAiButtonToolbarProviderInstance = new GlobalAiButtonToolbarProvider();
227
- }
228
-
229
- return globalAiButtonToolbarProviderInstance;
230
- }
231
225
  }
@@ -47,7 +47,6 @@ import * as Badges from '../../models/badges/badges.js';
47
47
  import * as Bindings from '../../models/bindings/bindings.js';
48
48
  import * as CrUXManager from '../../models/crux-manager/crux-manager.js';
49
49
  import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
50
- import * as LiveMetrics from '../../models/live-metrics/live-metrics.js';
51
50
  import * as Persistence from '../../models/persistence/persistence.js';
52
51
  import * as Workspace from '../../models/workspace/workspace.js';
53
52
  import * as PanelCommon from '../../panels/common/common.js';
@@ -158,9 +157,11 @@ export class MainImpl {
158
157
  #readyForTestPromise = Promise.withResolvers<void>();
159
158
  #veStartPromise!: Promise<void>;
160
159
  #universe!: Foundation.Universe.Universe;
160
+ #supportsEmulation = false;
161
161
 
162
- constructor() {
162
+ constructor(opts?: {supportsEmulation: boolean}) {
163
163
  MainImpl.instanceForTest = this;
164
+ this.#supportsEmulation = opts?.supportsEmulation ?? false;
164
165
  void this.#loaded();
165
166
  }
166
167
 
@@ -209,6 +210,7 @@ export class MainImpl {
209
210
  },
210
211
  hostConfig: Root.Runtime.hostConfig,
211
212
  inspectorFrontendHost: Host.InspectorFrontendHost.InspectorFrontendHostInstance,
213
+ supportsEmulation: this.#supportsEmulation,
212
214
  };
213
215
  this.#universe = new Foundation.Universe.Universe(creationOptions);
214
216
  Root.DevToolsContext.setGlobalInstance(this.#universe.context as Root.DevToolsContext.WritableDevToolsContext);
@@ -469,15 +471,12 @@ export class MainImpl {
469
471
  isolatedFileSystemManager.addPlatformFileSystem(
470
472
  'snippet://' as Platform.DevToolsPath.UrlString, new Snippets.ScriptSnippetFileSystem.SnippetFileSystem());
471
473
 
472
- const persistenceImpl = Persistence.Persistence.PersistenceImpl.instance();
473
- const linkDecorator = new PanelCommon.PersistenceUtils.LinkDecorator(persistenceImpl);
474
+ const linkDecorator = new PanelCommon.PersistenceUtils.LinkDecorator(this.#universe.persistence);
474
475
  Components.Linkifier.Linkifier.setLinkDecorator(linkDecorator);
475
- Persistence.NetworkPersistenceManager.NetworkPersistenceManager.instance(
476
- {forceNew: true, workspace: Workspace.Workspace.WorkspaceImpl.instance()});
477
476
 
478
477
  new ExecutionContextSelector(targetManager, UI.Context.Context.instance());
479
478
 
480
- LiveMetrics.LiveMetrics.instance();
479
+ void this.#universe.liveMetrics.enable();
481
480
  CrUXManager.CrUXManager.instance();
482
481
 
483
482
  const builtInAi = AiAssistanceModel.BuiltInAi.BuiltInAi.instance();
@@ -761,8 +760,6 @@ export class SearchActionDelegate implements UI.ActionRegistration.ActionDelegat
761
760
  return false;
762
761
  }
763
762
  }
764
- let mainMenuItemInstance: MainMenuItem;
765
-
766
763
  export class MainMenuItem implements UI.Toolbar.Provider {
767
764
  readonly #item: UI.Toolbar.ToolbarMenuButton;
768
765
  constructor() {
@@ -773,17 +770,6 @@ export class MainMenuItem implements UI.Toolbar.Provider {
773
770
  this.#item.setTitle(i18nString(UIStrings.customizeAndControlDevtools));
774
771
  }
775
772
 
776
- static instance(opts: {
777
- forceNew: boolean|null,
778
- } = {forceNew: null}): MainMenuItem {
779
- const {forceNew} = opts;
780
- if (!mainMenuItemInstance || forceNew) {
781
- mainMenuItemInstance = new MainMenuItem();
782
- }
783
-
784
- return mainMenuItemInstance;
785
- }
786
-
787
773
  item(): UI.Toolbar.ToolbarItem|null {
788
774
  return this.#item;
789
775
  }
@@ -945,25 +931,12 @@ export class MainMenuItem implements UI.Toolbar.Provider {
945
931
  }
946
932
  }
947
933
 
948
- let settingsButtonProviderInstance: SettingsButtonProvider;
949
-
950
934
  export class SettingsButtonProvider implements UI.Toolbar.Provider {
951
935
  readonly #settingsButton: UI.Toolbar.ToolbarButton;
952
- private constructor() {
936
+ constructor() {
953
937
  this.#settingsButton = UI.Toolbar.Toolbar.createActionButton('settings.show');
954
938
  }
955
939
 
956
- static instance(opts: {
957
- forceNew: boolean|null,
958
- } = {forceNew: null}): SettingsButtonProvider {
959
- const {forceNew} = opts;
960
- if (!settingsButtonProviderInstance || forceNew) {
961
- settingsButtonProviderInstance = new SettingsButtonProvider();
962
- }
963
-
964
- return settingsButtonProviderInstance;
965
- }
966
-
967
940
  item(): UI.Toolbar.ToolbarItem|null {
968
941
  return this.#settingsButton;
969
942
  }
@@ -911,29 +911,29 @@ UI.Toolbar.registerToolbarItem({
911
911
  const isPolicyRestricted = config?.aidaAvailability?.blockedByEnterprisePolicy === true;
912
912
  return Boolean(isFlagEnabled && !isGeoRestricted && !isPolicyRestricted);
913
913
  },
914
- async loadItem() {
914
+ loadItem: Common.Lazy.lazy(async () => {
915
915
  const Main = await loadMainModule();
916
- return Main.GlobalAiButton.GlobalAiButtonToolbarProvider.instance();
917
- },
916
+ return new Main.GlobalAiButton.GlobalAiButtonToolbarProvider();
917
+ }) as () => Promise<UI.Toolbar.Provider>,
918
918
  order: 98,
919
919
  location: UI.Toolbar.ToolbarItemLocation.MAIN_TOOLBAR_RIGHT,
920
920
  });
921
921
 
922
922
  UI.Toolbar.registerToolbarItem({
923
- async loadItem() {
923
+ loadItem: Common.Lazy.lazy(async () => {
924
924
  const Main = await loadMainModule();
925
- return Main.MainImpl.SettingsButtonProvider.instance();
926
- },
925
+ return new Main.MainImpl.SettingsButtonProvider();
926
+ }) as () => Promise<UI.Toolbar.Provider>,
927
927
  order: 99,
928
928
  location: UI.Toolbar.ToolbarItemLocation.MAIN_TOOLBAR_RIGHT,
929
929
  });
930
930
 
931
931
  UI.Toolbar.registerToolbarItem({
932
932
  condition: () => !Root.Runtime.Runtime.isTraceApp(),
933
- async loadItem() {
933
+ loadItem: Common.Lazy.lazy(async () => {
934
934
  const Main = await loadMainModule();
935
- return Main.MainImpl.MainMenuItem.instance();
936
- },
935
+ return new Main.MainImpl.MainMenuItem();
936
+ }) as () => Promise<UI.Toolbar.Provider>,
937
937
  order: 100,
938
938
  location: UI.Toolbar.ToolbarItemLocation.MAIN_TOOLBAR_RIGHT,
939
939
  });
@@ -15,25 +15,25 @@ import nodeConnectionsPanelStyles from './nodeConnectionsPanel.css.js';
15
15
 
16
16
  const UIStrings = {
17
17
  /**
18
- * @description Text in Node Connections Panel of the Sources panel when debugging a Node.js app
18
+ * @description Text in Node connections panel of the Sources panel when debugging a Node.js app.
19
19
  */
20
20
  nodejsDebuggingGuide: 'Node.js debugging guide',
21
21
  /**
22
- * @description Text in Node Connections Panel of the Sources panel when debugging a Node.js app
22
+ * @description Text in Node connections panel of the Sources panel when debugging a Node.js app.
23
23
  * @example {Node.js debugging guide} PH1
24
24
  */
25
25
  specifyNetworkEndpointAnd:
26
26
  'Specify network endpoint and DevTools will connect to it automatically. Read {PH1} to learn more.',
27
27
  /**
28
- * @description Placeholder text content in Node Connections Panel of the Sources panel when debugging a Node.js app
28
+ * @description Placeholder text content in Node connections panel of the Sources panel when debugging a Node.js app.
29
29
  */
30
30
  noConnectionsSpecified: 'No connections specified',
31
31
  /**
32
- * @description Text of add network target button in Node Connections Panel of the Sources panel when debugging a Node.js app
32
+ * @description Text of add network target button in Node connections panel of the Sources panel when debugging a Node.js app.
33
33
  */
34
34
  addConnection: 'Add connection',
35
35
  /**
36
- * @description Text in Node Connections Panel of the Sources panel when debugging a Node.js app
36
+ * @description Text in Node connections panel of the Sources panel when debugging a Node.js app.
37
37
  */
38
38
  networkAddressEgLocalhost: 'Network address (e.g. localhost:9229)',
39
39
  } as const;
@@ -95,9 +95,8 @@ export class NodeConnectionsView extends UI.Widget.VBox implements UI.ListWidget
95
95
  this.element.classList.add('network-discovery-view');
96
96
 
97
97
  const networkDiscoveryFooter = this.element.createChild('div', 'network-discovery-footer');
98
- const documentationLink = Link.create(
99
- 'https://nodejs.org/en/docs/inspector/', i18nString(UIStrings.nodejsDebuggingGuide), undefined,
100
- 'node-js-debugging');
98
+ const documentationLink = Link.create('https://nodejs.org/learn/getting-started/debugging',
99
+ i18nString(UIStrings.nodejsDebuggingGuide), undefined, 'node-js-debugging');
101
100
  networkDiscoveryFooter.appendChild(
102
101
  uiI18n.getFormatLocalizedString(str_, UIStrings.specifyNetworkEndpointAnd, {PH1: documentationLink}));
103
102
 
@@ -14,16 +14,16 @@ import * as Components from '../../../ui/legacy/components/utils/utils.js';
14
14
 
15
15
  const UIStrings = {
16
16
  /**
17
- * @description Text that refers to the main target
17
+ * @description Text that refers to the main target.
18
18
  */
19
19
  main: 'Main',
20
20
  /**
21
- * @description Text in Node Main of the Sources panel when debugging a Node.js app
21
+ * @description Text in Node main of the Sources panel when debugging a Node.js app.
22
22
  * @example {example.com} PH1
23
23
  */
24
24
  nodejsS: 'Node.js: {PH1}',
25
25
  /**
26
- * @description Text in DevTools window title when debugging a Node.js app
26
+ * @description Text in DevTools window title when debugging a Node.js app.
27
27
  * @example {example.com} PH1
28
28
  */
29
29
  NodejsTitleS: 'DevTools - Node.js: {PH1}',
@@ -21,31 +21,31 @@ const {NodeMainImpl} = App.NodeMain;
21
21
 
22
22
  const UIStrings = {
23
23
  /**
24
- * @description Text that refers to the network connection
24
+ * @description Text that refers to the network connection.
25
25
  */
26
26
  connection: 'Connection',
27
27
  /**
28
- * @description A tag of Node.js Connection Panel that can be searched in the command menu
28
+ * @description A tag of Node.js connection panel that can be searched in the command menu.
29
29
  */
30
30
  node: 'node',
31
31
  /**
32
- * @description Command for showing the Connection tool
32
+ * @description Command for showing the Connection tool.
33
33
  */
34
34
  showConnection: 'Show Connection',
35
35
  /**
36
- * @description Title of the 'Node' tool in the Network Navigator View, which is part of the Sources tool
36
+ * @description Title of the 'Node' tool in the Network navigator view, which is part of the Sources tool.
37
37
  */
38
38
  networkTitle: 'Node',
39
39
  /**
40
- * @description Command for showing the 'Node' tool in the Network Navigator View, which is part of the Sources tool
40
+ * @description Command for showing the 'Node' tool in the Network navigator view, which is part of the Sources tool.
41
41
  */
42
42
  showNode: 'Show Node',
43
43
  /**
44
- * @description Text in Application Panel Sidebar of the Application panel
44
+ * @description Text in Application panel sidebar of the Application panel.
45
45
  */
46
46
  application: 'Application',
47
47
  /**
48
- * @description Command for showing the 'Application' tool
48
+ * @description Command for showing the Application tool.
49
49
  */
50
50
  showApplication: 'Show Application',
51
51
  } as const;
@@ -10,17 +10,21 @@ import * as AutofillManager from '../models/autofill_manager/autofill_manager.js
10
10
  import * as Bindings from '../models/bindings/bindings.js';
11
11
  import * as Breakpoints from '../models/breakpoints/breakpoints.js';
12
12
  import * as CrUXManager from '../models/crux-manager/crux-manager.js';
13
+ import * as Emulation from '../models/emulation/emulation.js';
13
14
  import * as JavaScriptMetadata from '../models/javascript_metadata/javascript_metadata.js';
15
+ import * as LiveMetrics from '../models/live-metrics/live-metrics.js';
14
16
  import * as Logs from '../models/logs/logs.js';
15
17
  import * as Persistence from '../models/persistence/persistence.js';
16
18
  import * as ProjectSettings from '../models/project_settings/project_settings.js';
17
19
  import * as Workspace from '../models/workspace/workspace.js';
20
+ import * as WorkspaceDiff from '../models/workspace_diff/workspace_diff.js';
18
21
 
19
22
  export interface CreationOptions {
20
23
  settingsCreationOptions: Omit<Common.Settings.SettingsCreationOptions, 'console'>;
21
24
  overrideAutoStartModels?: Set<SDK.SDKModel.SDKModelConstructor>;
22
25
  hostConfig: Root.Runtime.HostConfig;
23
26
  inspectorFrontendHost: Host.InspectorFrontendHostAPI.InspectorFrontendHostAPI;
27
+ supportsEmulation: boolean;
24
28
  }
25
29
 
26
30
  export class Universe {
@@ -29,6 +33,7 @@ export class Universe {
29
33
  // directly on the `Universe`.
30
34
  readonly context: Root.DevToolsContext.DevToolsContext;
31
35
  readonly autofillManager: AutofillManager.AutofillManager.AutofillManager;
36
+ readonly supportsEmulation: boolean;
32
37
 
33
38
  constructor(options: CreationOptions) {
34
39
  const context = new Root.DevToolsContext.WritableDevToolsContext();
@@ -60,6 +65,14 @@ export class Universe {
60
65
  const multitargetNetworkManager = new SDK.NetworkManager.MultitargetNetworkManager(targetManager);
61
66
  context.set(SDK.NetworkManager.MultitargetNetworkManager, multitargetNetworkManager);
62
67
 
68
+ this.supportsEmulation = options.supportsEmulation;
69
+ let deviceModeModel = null;
70
+ if (options.supportsEmulation) {
71
+ deviceModeModel =
72
+ new Emulation.DeviceModeModel.DeviceModeModel(targetManager, settings, multitargetNetworkManager);
73
+ context.set(Emulation.DeviceModeModel.DeviceModeModel, deviceModeModel);
74
+ }
75
+
63
76
  const pageResourceLoader =
64
77
  new SDK.PageResourceLoader.PageResourceLoader(targetManager, settings, multitargetNetworkManager, null);
65
78
  context.set(SDK.PageResourceLoader.PageResourceLoader, pageResourceLoader);
@@ -84,6 +97,14 @@ export class Universe {
84
97
  const cruxManager = new CrUXManager.CrUXManager(targetManager, settings);
85
98
  context.set(CrUXManager.CrUXManager, cruxManager);
86
99
 
100
+ const isolateManager = new SDK.IsolateManager.IsolateManager(targetManager);
101
+ context.set(SDK.IsolateManager.IsolateManager, isolateManager);
102
+ const eventBreakpointsManager = new SDK.EventBreakpointsModel.EventBreakpointsManager(targetManager);
103
+ context.set(SDK.EventBreakpointsModel.EventBreakpointsManager, eventBreakpointsManager);
104
+
105
+ const domModelUndoStack = new SDK.DOMModel.DOMModelUndoStack();
106
+ context.set(SDK.DOMModel.DOMModelUndoStack, domModelUndoStack);
107
+
87
108
  const workspace = new Workspace.Workspace.WorkspaceImpl();
88
109
  context.set(Workspace.Workspace.WorkspaceImpl, workspace);
89
110
 
@@ -127,6 +148,13 @@ export class Universe {
127
148
  );
128
149
  context.set(Persistence.NetworkPersistenceManager.NetworkPersistenceManager, networkPersistenceManager);
129
150
 
151
+ const workspaceDiff = new WorkspaceDiff.WorkspaceDiff.WorkspaceDiffImpl(
152
+ workspace,
153
+ persistence,
154
+ networkPersistenceManager,
155
+ );
156
+ context.set(WorkspaceDiff.WorkspaceDiff.WorkspaceDiffImpl, workspaceDiff);
157
+
130
158
  const networkLog = new Logs.NetworkLog.NetworkLog(targetManager, settings);
131
159
  context.set(Logs.NetworkLog.NetworkLog, networkLog);
132
160
 
@@ -136,6 +164,9 @@ export class Universe {
136
164
  const javaScriptMetadata = new JavaScriptMetadata.JavaScriptMetadata.JavaScriptMetadataImpl();
137
165
  context.set(JavaScriptMetadata.JavaScriptMetadata.JavaScriptMetadataImpl, javaScriptMetadata);
138
166
 
167
+ const liveMetrics = new LiveMetrics.LiveMetrics(targetManager, deviceModeModel);
168
+ context.set(LiveMetrics.LiveMetrics, liveMetrics);
169
+
139
170
  this.autofillManager = new AutofillManager.AutofillManager.AutofillManager(targetManager, frameManager);
140
171
  }
141
172
 
@@ -155,23 +186,43 @@ export class Universe {
155
186
  get cpuThrottlingManager(): SDK.CPUThrottlingManager.CPUThrottlingManager {
156
187
  return this.context.get(SDK.CPUThrottlingManager.CPUThrottlingManager);
157
188
  }
158
-
159
189
  get cruxManager(): CrUXManager.CrUXManager {
160
190
  return this.context.get(CrUXManager.CrUXManager);
161
191
  }
162
192
 
193
+ // The DeviceModeModel may not be present, as emulation is only present for the `devtools_app` entrypoint, but not for the others.
194
+ get deviceModeModel(): Emulation.DeviceModeModel.DeviceModeModel|null {
195
+ return this.supportsEmulation ? this.context.get(Emulation.DeviceModeModel.DeviceModeModel) : null;
196
+ }
197
+
163
198
  get domDebuggerManager(): SDK.DOMDebuggerModel.DOMDebuggerManager {
164
199
  return this.context.get(SDK.DOMDebuggerModel.DOMDebuggerManager);
165
200
  }
166
201
 
202
+ get domModelUndoStack(): SDK.DOMModel.DOMModelUndoStack {
203
+ return this.context.get(SDK.DOMModel.DOMModelUndoStack);
204
+ }
205
+
206
+ get eventBreakpointsManager(): SDK.EventBreakpointsModel.EventBreakpointsManager {
207
+ return this.context.get(SDK.EventBreakpointsModel.EventBreakpointsManager);
208
+ }
209
+
167
210
  get isolatedFileSystemManager(): Persistence.IsolatedFileSystemManager.IsolatedFileSystemManager {
168
211
  return this.context.get(Persistence.IsolatedFileSystemManager.IsolatedFileSystemManager);
169
212
  }
170
213
 
214
+ get isolateManager(): SDK.IsolateManager.IsolateManager {
215
+ return this.context.get(SDK.IsolateManager.IsolateManager);
216
+ }
217
+
171
218
  get networkPersistenceManager(): Persistence.NetworkPersistenceManager.NetworkPersistenceManager {
172
219
  return this.context.get(Persistence.NetworkPersistenceManager.NetworkPersistenceManager);
173
220
  }
174
221
 
222
+ get liveMetrics(): LiveMetrics.LiveMetrics {
223
+ return this.context.get(LiveMetrics.LiveMetrics);
224
+ }
225
+
175
226
  get pageResourceLoader(): SDK.PageResourceLoader.PageResourceLoader {
176
227
  return this.context.get(SDK.PageResourceLoader.PageResourceLoader);
177
228
  }
@@ -191,4 +242,12 @@ export class Universe {
191
242
  get targetManager(): SDK.TargetManager.TargetManager {
192
243
  return this.context.get(SDK.TargetManager.TargetManager);
193
244
  }
245
+
246
+ get workspace(): Workspace.Workspace.WorkspaceImpl {
247
+ return this.context.get(Workspace.Workspace.WorkspaceImpl);
248
+ }
249
+
250
+ get workspaceDiff(): WorkspaceDiff.WorkspaceDiff.WorkspaceDiffImpl {
251
+ return this.context.get(WorkspaceDiff.WorkspaceDiff.WorkspaceDiffImpl);
252
+ }
194
253
  }
@@ -511,7 +511,7 @@ inspectorBackend.registerCommand("DeviceOrientation.setDeviceOrientationOverride
511
511
 
512
512
  // DigitalCredentials.
513
513
  inspectorBackend.registerEnum("DigitalCredentials.VirtualWalletAction", {Respond: "respond", Decline: "decline", Wait: "wait", Clear: "clear"});
514
- inspectorBackend.registerCommand("DigitalCredentials.setVirtualWalletBehavior", [{"name": "action", "type": "string", "optional": false, "description": "The action of the virtual wallet.", "typeRef": "DigitalCredentials.VirtualWalletAction"}, {"name": "protocol", "type": "string", "optional": true, "description": "The protocol identifier (e.g. \\\"openid4vp\\\"). Required when |action| is \\\"respond\\\", forbidden otherwise.", "typeRef": null}, {"name": "response", "type": "object", "optional": true, "description": "The response data object returned by the wallet. Required when |action| is \\\"respond\\\", forbidden otherwise.", "typeRef": null}], [], "Sets the behavior of the virtual wallet for digital credential requests issued from this frame.");
514
+ inspectorBackend.registerCommand("DigitalCredentials.setVirtualWalletBehavior", [{"name": "action", "type": "string", "optional": false, "description": "The action of the virtual wallet.", "typeRef": "DigitalCredentials.VirtualWalletAction"}, {"name": "protocol", "type": "string", "optional": true, "description": "The protocol identifier (e.g. \\\"openid4vp\\\"). Required when |action| is \\\"respond\\\", forbidden otherwise.", "typeRef": null}, {"name": "response", "type": "object", "optional": true, "description": "The response data object returned by the wallet. Required when |action| is \\\"respond\\\", forbidden otherwise.", "typeRef": null}, {"name": "frameId", "type": "string", "optional": true, "description": "The frame to scope the virtual wallet behavior to.", "typeRef": "Page.FrameId"}], [], "Sets the behavior of the virtual wallet for digital credential requests issued from this frame.");
515
515
 
516
516
  // Emulation.
517
517
  inspectorBackend.registerEnum("Emulation.ScreenOrientationType", {PortraitPrimary: "portraitPrimary", PortraitSecondary: "portraitSecondary", LandscapePrimary: "landscapePrimary", LandscapeSecondary: "landscapeSecondary"});