chrome-devtools-frontend 1.0.1539972 → 1.0.1541552

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 (106) hide show
  1. package/eslint.config.mjs +167 -151
  2. package/front_end/Tests.js +5 -1
  3. package/front_end/core/common/Revealer.ts +5 -0
  4. package/front_end/core/common/Settings.ts +106 -95
  5. package/front_end/core/host/InspectorFrontendHost.ts +10 -10
  6. package/front_end/core/sdk/NetworkManager.ts +16 -11
  7. package/front_end/core/sdk/sdk-meta.ts +0 -35
  8. package/front_end/entrypoints/main/MainImpl.ts +15 -7
  9. package/front_end/entrypoints/shell/shell.ts +1 -0
  10. package/front_end/entrypoints/trace_app/trace_app.ts +1 -0
  11. package/front_end/foundation/README.md +10 -0
  12. package/front_end/foundation/Universe.ts +29 -0
  13. package/front_end/foundation/foundation.ts +7 -0
  14. package/front_end/generated/InspectorBackendCommands.ts +6 -3
  15. package/front_end/generated/SupportedCSSProperties.js +13 -0
  16. package/front_end/generated/protocol.ts +58 -2
  17. package/front_end/models/ai_assistance/BuiltInAi.ts +2 -1
  18. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +44 -34
  19. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +121 -56
  20. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +104 -62
  21. package/front_end/models/ai_assistance/performance/AIQueries.ts +56 -2
  22. package/front_end/{panels/issues → models/issues_manager}/IssueAggregator.ts +83 -65
  23. package/front_end/models/issues_manager/issues_manager.ts +2 -0
  24. package/front_end/models/trace/Processor.ts +5 -4
  25. package/front_end/models/trace/insights/types.ts +1 -1
  26. package/front_end/models/trace/types/TraceEvents.ts +1 -1
  27. package/front_end/models/workspace/IgnoreListManager.ts +41 -47
  28. package/front_end/models/workspace/workspace-meta.ts +40 -0
  29. package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +1 -1
  30. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +1 -1
  31. package/front_end/panels/animation/AnimationTimeline.ts +4 -4
  32. package/front_end/panels/animation/AnimationUI.ts +28 -34
  33. package/front_end/panels/elements/ElementsTreeElement.ts +37 -9
  34. package/front_end/panels/elements/LayoutPane.ts +2 -2
  35. package/front_end/panels/elements/components/AdornerManager.ts +9 -9
  36. package/front_end/panels/elements/layoutPane.css +5 -9
  37. package/front_end/panels/event_listeners/EventListenersView.ts +1 -1
  38. package/front_end/panels/explain/components/ConsoleInsight.ts +498 -449
  39. package/front_end/panels/issues/AffectedResourcesView.ts +3 -4
  40. package/front_end/panels/issues/CorsIssueDetailsView.ts +1 -2
  41. package/front_end/panels/issues/IssueView.ts +1 -1
  42. package/front_end/panels/issues/IssuesPane.ts +12 -15
  43. package/front_end/panels/issues/issues.ts +0 -2
  44. package/front_end/panels/network/NetworkDataGridNode.ts +2 -1
  45. package/front_end/panels/network/RequestConditionsDrawer.ts +149 -46
  46. package/front_end/panels/network/RequestTimingView.ts +13 -8
  47. package/front_end/panels/network/network-meta.ts +11 -0
  48. package/front_end/panels/settings/emulation/components/userAgentClientHintsForm.css +1 -1
  49. package/front_end/panels/sources/DebuggerPlugin.ts +1 -1
  50. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +1 -1
  51. package/front_end/panels/sources/breakpointsView.css +1 -1
  52. package/front_end/panels/sources/sourcesPanel.css +2 -2
  53. package/front_end/panels/timeline/TimelineFlameChartView.ts +3 -3
  54. package/front_end/panels/timeline/TimelinePanel.ts +3 -3
  55. package/front_end/panels/timeline/components/LayoutShiftDetails.ts +16 -10
  56. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +2 -0
  57. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +4 -1
  58. package/front_end/third_party/chromium/README.chromium +1 -1
  59. package/front_end/third_party/puppeteer/README.chromium +2 -2
  60. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  61. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js +3 -1
  62. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js.map +1 -1
  63. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +2 -2
  64. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +2 -2
  65. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  66. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  67. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +4 -4
  68. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  69. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js +3 -1
  70. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js.map +1 -1
  71. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +2 -2
  72. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +2 -2
  73. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  74. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  75. package/front_end/third_party/puppeteer/package/package.json +1 -1
  76. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +3 -1
  77. package/front_end/third_party/puppeteer/package/src/revisions.ts +2 -2
  78. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  79. package/front_end/ui/components/markdown_view/MarkdownView.ts +6 -6
  80. package/front_end/ui/components/snackbars/Snackbars.docs.ts +46 -0
  81. package/front_end/ui/{components/docs/context_menu/basic.ts → legacy/ContextMenu.docs.ts} +58 -25
  82. package/front_end/ui/legacy/UIUtils.ts +2 -1
  83. package/front_end/ui/legacy/components/inline_editor/BezierEditor.ts +1 -1
  84. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +148 -125
  85. package/front_end/ui/legacy/components/perf_ui/TimelineOverviewPane.ts +3 -3
  86. package/front_end/ui/legacy/components/perf_ui/pieChart.css +1 -1
  87. package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -1
  88. package/front_end/ui/legacy/inspectorCommon.css +3 -2
  89. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  90. package/mcp/mcp.ts +16 -0
  91. package/package.json +2 -1
  92. package/front_end/ui/components/docs/context_menu/basic.html +0 -45
  93. package/front_end/ui/components/docs/linkifier/simple-url.html +0 -25
  94. package/front_end/ui/components/docs/linkifier/simple-url.ts +0 -25
  95. package/front_end/ui/components/docs/panel_feedback/basic.html +0 -25
  96. package/front_end/ui/components/docs/panel_feedback/basic.ts +0 -21
  97. package/front_end/ui/components/docs/panel_feedback/button.html +0 -25
  98. package/front_end/ui/components/docs/panel_feedback/button.ts +0 -19
  99. package/front_end/ui/components/docs/panel_introduction_steps/basic.html +0 -25
  100. package/front_end/ui/components/docs/panel_introduction_steps/basic.ts +0 -28
  101. package/front_end/ui/components/docs/perf_piechart/basic-with-legend.html +0 -20
  102. package/front_end/ui/components/docs/perf_piechart/basic-with-legend.ts +0 -20
  103. package/front_end/ui/components/docs/perf_piechart/basic-without-legend.html +0 -20
  104. package/front_end/ui/components/docs/perf_piechart/basic-without-legend.ts +0 -18
  105. package/front_end/ui/components/docs/snackbars/basic.html +0 -17
  106. package/front_end/ui/components/docs/snackbars/basic.ts +0 -50
@@ -491,19 +491,19 @@ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
491
491
  * Whereas in **Non-hosted** (aka "embedded"), DevTools is embedded and fully dockable. It's the common way DevTools is run.
492
492
  *
493
493
  * **Hosted mode** == we're using the `InspectorFrontendHostStub`. impl. (@see `InspectorFrontendHostStub` class comment)
494
- * Whereas with **non-hosted** mode, native `DevToolsEmbedderMessageDispatcher` is used for CDP and more.
494
+ * Whereas with **non-hosted** mode, native `DevToolsEmbedderMessageDispatcher` is used for CDP and more. `globalThis.DevToolsAPI` is present.
495
495
  *
496
496
  * Relationships to other signals:
497
- * - Hosted-ness does not indicate whether the frontend is _connected to a valid CDP target_.
498
- * - Being _"dockable"_ (aka `canDock`) is typically aligned but technically orthogonal.
499
- * - It's unrelated to the _tab's (main frame's) URL_. Though in non-hosted, the devtools frame origin will always be `devtools://devtools`.
497
+ * - _Connection_: Hosted-ness does not indicate whether the frontend is _connected to a valid CDP target_.
498
+ * - _Dockability_: Being _"dockable"_ (aka `canDock`) is typically aligned but technically orthogonal.
499
+ * - _URL scheme_: If the main frame's URL scheme is `devtools://`, it's non-hosted.
500
500
  *
501
- * | Example case | Mode | Example devtools |
502
- * | :--------------------------------------------------- | :------------- | :---------------------------------------------------------------------------- |
503
- * | tab URL: anything. embedded DevTools w/ native CDP bindings | **NOT Hosted** | `devtools://devtools/bundled/devtools_app.html?targetType=tab&...` |
504
- * | tab URL: `devtools://…?ws=…` | **Hosted** | `devtools://devtools/bundled/devtools_app.html?ws=localhost:9228/...` |
505
- * | tab URL: `devtools://…` but no connection | **Hosted** | `devtools://devtools/bundled/devtools_app.html` |
506
- * | tab URL: `https://…` but no connection | **Hosted** | `https://chrome-devtools-frontend.appspot.com/serve_rev/@.../worker_app.html` |
501
+ * | Example case | Mode | Example devtools |
502
+ * | :------------------------------------------ | :------------- | :---------------------------------------------------------------------------- |
503
+ * | tab URL: `devtools://…` | **NOT Hosted** | `devtools://devtools/bundled/devtools_app.html?targetType=tab&...` |
504
+ * | tab URL: `devtools://…?ws=…` | **NOT Hosted** | `devtools://devtools/bundled/devtools_app.html?ws=localhost:9228/...` |
505
+ * | tab URL: `devtools://…` but no connection | **NOT Hosted** | `devtools://devtools/bundled/trace_app.html` |
506
+ * | tab URL: `https://…` but no connection | **Hosted** | `https://chrome-devtools-frontend.appspot.com/serve_rev/@.../trace_app.html` |
507
507
  * | tab URL: `http://…?ws=` (connected) | **Hosted** | `http://localhost:9222/devtools/inspector.html?ws=localhost:9222/...` |
508
508
  */
509
509
  isHostedMode(): boolean {
@@ -1812,7 +1812,7 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper<Reques
1812
1812
  }
1813
1813
 
1814
1814
  Platform.ArrayUtilities.swap(this.#conditions, index, index + 1);
1815
- this.dispatchEventToListeners(RequestConditions.Events.REQUEST_CONDITIONS_CHANGED);
1815
+ this.#conditionsChanged();
1816
1816
  }
1817
1817
 
1818
1818
  increasePriority(condition: RequestCondition): void {
@@ -1822,7 +1822,7 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper<Reques
1822
1822
  }
1823
1823
 
1824
1824
  Platform.ArrayUtilities.swap(this.#conditions, index - 1, index);
1825
- this.dispatchEventToListeners(RequestConditions.Events.REQUEST_CONDITIONS_CHANGED);
1825
+ this.#conditionsChanged();
1826
1826
  }
1827
1827
 
1828
1828
  delete(condition: RequestCondition): void {
@@ -1939,11 +1939,13 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper<Reques
1939
1939
  return this.#conditionsAppliedForTestPromise;
1940
1940
  }
1941
1941
 
1942
- conditionsForId(appliedNetworkConditionsId: string): {
1943
- conditions: Conditions,
1944
- urlPattern?: string,
1945
- }|undefined {
1946
- return this.#requestConditionsById.get(appliedNetworkConditionsId);
1942
+ conditionsForId(appliedNetworkConditionsId: string): AppliedNetworkConditions|undefined {
1943
+ const requestConditions = this.#requestConditionsById.get(appliedNetworkConditionsId);
1944
+ if (!requestConditions) {
1945
+ return undefined;
1946
+ }
1947
+ const {conditions, urlPattern} = requestConditions;
1948
+ return new AppliedNetworkConditions(conditions, appliedNetworkConditionsId, urlPattern);
1947
1949
  }
1948
1950
  }
1949
1951
 
@@ -1958,6 +1960,12 @@ export namespace RequestConditions {
1958
1960
 
1959
1961
  let multiTargetNetworkManagerInstance: MultitargetNetworkManager|null;
1960
1962
 
1963
+ export class AppliedNetworkConditions {
1964
+ constructor(
1965
+ readonly conditions: Conditions, readonly appliedNetworkConditionsId: string, readonly urlPattern?: string) {
1966
+ }
1967
+ }
1968
+
1961
1969
  export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrapper<MultitargetNetworkManager.EventTypes>
1962
1970
  implements SDKModelObserver<NetworkManager> {
1963
1971
  #userAgentOverride = '';
@@ -2327,10 +2335,7 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
2327
2335
  }, allowRemoteFilePaths));
2328
2336
  }
2329
2337
 
2330
- appliedRequestConditions(requestInternal: NetworkRequest): {
2331
- conditions: Conditions,
2332
- urlPattern?: string,
2333
- }|undefined {
2338
+ appliedRequestConditions(requestInternal: NetworkRequest): AppliedNetworkConditions|undefined {
2334
2339
  if (!requestInternal.appliedNetworkConditionsId) {
2335
2340
  return undefined;
2336
2341
  }
@@ -367,41 +367,6 @@ const UIStrings = {
367
367
  const str_ = i18n.i18n.registerUIStrings('core/sdk/sdk-meta.ts', UIStrings);
368
368
  const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
369
369
 
370
- Common.Settings.registerSettingExtension({
371
- storageType: Common.Settings.SettingStorageType.SYNCED,
372
- settingName: 'skip-stack-frames-pattern',
373
- settingType: Common.Settings.SettingType.REGEX,
374
- defaultValue: '/node_modules/|^node:',
375
- });
376
-
377
- Common.Settings.registerSettingExtension({
378
- storageType: Common.Settings.SettingStorageType.SYNCED,
379
- settingName: 'skip-content-scripts',
380
- settingType: Common.Settings.SettingType.BOOLEAN,
381
- defaultValue: true,
382
- });
383
-
384
- Common.Settings.registerSettingExtension({
385
- storageType: Common.Settings.SettingStorageType.SYNCED,
386
- settingName: 'automatically-ignore-list-known-third-party-scripts',
387
- settingType: Common.Settings.SettingType.BOOLEAN,
388
- defaultValue: true,
389
- });
390
-
391
- Common.Settings.registerSettingExtension({
392
- storageType: Common.Settings.SettingStorageType.SYNCED,
393
- settingName: 'skip-anonymous-scripts',
394
- settingType: Common.Settings.SettingType.BOOLEAN,
395
- defaultValue: false,
396
- });
397
-
398
- Common.Settings.registerSettingExtension({
399
- storageType: Common.Settings.SettingStorageType.SYNCED,
400
- settingName: 'enable-ignore-listing',
401
- settingType: Common.Settings.SettingType.BOOLEAN,
402
- defaultValue: true,
403
- });
404
-
405
370
  Common.Settings.registerSettingExtension({
406
371
  category: Common.Settings.SettingCategory.CONSOLE,
407
372
  storageType: Common.Settings.SettingStorageType.SYNCED,
@@ -41,6 +41,7 @@ import * as Platform from '../../core/platform/platform.js';
41
41
  import * as ProtocolClient from '../../core/protocol_client/protocol_client.js';
42
42
  import * as Root from '../../core/root/root.js';
43
43
  import * as SDK from '../../core/sdk/sdk.js';
44
+ import * as Foundation from '../../foundation/foundation.js';
44
45
  import * as AiAssistanceModel from '../../models/ai_assistance/ai_assistance.js';
45
46
  import * as AutofillManager from '../../models/autofill_manager/autofill_manager.js';
46
47
  import * as Badges from '../../models/badges/badges.js';
@@ -165,7 +166,14 @@ export class MainImpl {
165
166
  console.timeStamp('Main._gotPreferences');
166
167
  this.#initializeGlobalsForLayoutTests();
167
168
  Object.assign(Root.Runtime.hostConfig, config);
168
- this.createSettings(prefs);
169
+
170
+ const creationOptions: Foundation.Universe.CreationOptions = {
171
+ ...this.createSettingsStorage(prefs),
172
+ logSettingAccess: VisualLogging.logSettingAccess,
173
+ runSettingsMigration: !Host.InspectorFrontendHost.isUnderTest(),
174
+ };
175
+ new Foundation.Universe.Universe(creationOptions);
176
+
169
177
  await this.requestAndRegisterLocaleData();
170
178
 
171
179
  Host.userMetrics.syncSetting(Common.Settings.Settings.instance().moduleSetting<boolean>('sync-preferences').get());
@@ -243,7 +251,11 @@ export class MainImpl {
243
251
  }
244
252
  }
245
253
 
246
- createSettings(prefs: Record<string, string>): void {
254
+ createSettingsStorage(prefs: Record<string, string>): {
255
+ syncedStorage: Common.Settings.SettingsStorage,
256
+ globalStorage: Common.Settings.SettingsStorage,
257
+ localStorage: Common.Settings.SettingsStorage,
258
+ } {
247
259
  this.#initializeExperiments();
248
260
  let storagePrefix = '';
249
261
  if (Host.Platform.isCustomDevtoolsFrontend()) {
@@ -287,12 +299,8 @@ export class MainImpl {
287
299
  // setting can't change storage buckets during a single DevTools session.
288
300
  const syncedStorage = new Common.Settings.SettingsStorage(prefs, hostSyncedStorage, storagePrefix);
289
301
  const globalStorage = new Common.Settings.SettingsStorage(prefs, hostUnsyncedStorage, storagePrefix);
290
- Common.Settings.Settings.instance(
291
- {forceNew: true, syncedStorage, globalStorage, localStorage, logSettingAccess: VisualLogging.logSettingAccess});
292
302
 
293
- if (!Host.InspectorFrontendHost.isUnderTest()) {
294
- new Common.Settings.VersionController().updateVersion();
295
- }
303
+ return {syncedStorage, globalStorage, localStorage};
296
304
  }
297
305
 
298
306
  #initializeExperiments(): void {
@@ -18,6 +18,7 @@ import '../main/main-meta.js';
18
18
  import '../../ui/legacy/components/perf_ui/perf_ui-meta.js';
19
19
  import '../../ui/legacy/components/quick_open/quick_open-meta.js';
20
20
  import '../../core/sdk/sdk-meta.js';
21
+ import '../../models/workspace/workspace-meta.js';
21
22
  import '../../ui/legacy/components/source_frame/source_frame-meta.js';
22
23
  import '../../panels/console_counters/console_counters-meta.js';
23
24
  import '../../ui/legacy/components/object_ui/object_ui-meta.js';
@@ -5,6 +5,7 @@
5
5
  import '../main/main-meta.js';
6
6
  import '../inspector_main/inspector_main-meta.js';
7
7
  import '../../core/sdk/sdk-meta.js';
8
+ import '../../models/workspace/workspace-meta.js';
8
9
  import '../../Images/Images.js';
9
10
  import '../../models/logs/logs-meta.js';
10
11
  import '../../models/persistence/persistence-meta.js';
@@ -0,0 +1,10 @@
1
+ # DevTools foundation
2
+
3
+ DevTools foundation is the core business logic of DevTools: mainly core/ and models/.
4
+ The difference between "foundation" and the rest of DevTools is
5
+ that the code is targeted not just for the browser, but also the Node.js runtime.
6
+ As such, allowed use of APIs is restricted to what is available in both runtimes.
7
+
8
+ A `DevToolsUniverse` is a concrete, encapsulated instance of "foundation" scoped
9
+ to a single root CDP target. It is valid to create multiple `DevToolsUniverse`
10
+ instances simultaneously.
@@ -0,0 +1,29 @@
1
+ // Copyright 2025 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as Common from '../core/common/common.js';
6
+
7
+ export interface CreationOptions {
8
+ // Settings things
9
+ syncedStorage: Common.Settings.SettingsStorage;
10
+ globalStorage: Common.Settings.SettingsStorage;
11
+ localStorage: Common.Settings.SettingsStorage;
12
+ logSettingAccess?: (name: string, value: number|string|boolean) => Promise<void>;
13
+ runSettingsMigration?: boolean;
14
+ }
15
+
16
+ export class Universe {
17
+ constructor(options: CreationOptions) {
18
+ // TODO(crbug.com/458180550): Store instance on a "DevToolsContext" instead.
19
+ // For now the global is fine as we don't anticipate the MCP server to change settings.
20
+ Common.Settings.Settings.instance({
21
+ forceNew: true,
22
+ syncedStorage: options.syncedStorage,
23
+ globalStorage: options.globalStorage,
24
+ localStorage: options.localStorage,
25
+ logSettingAccess: options.logSettingAccess,
26
+ runSettingsMigration: options.runSettingsMigration,
27
+ });
28
+ }
29
+ }
@@ -0,0 +1,7 @@
1
+ // Copyright 2025 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as Universe from './Universe.js';
6
+
7
+ export {Universe};
@@ -61,7 +61,7 @@ inspectorBackend.registerCommand("Animation.setPlaybackRate", [{"name": "playbac
61
61
  inspectorBackend.registerCommand("Animation.setTiming", [{"name": "animationId", "type": "string", "optional": false, "description": "Animation id.", "typeRef": null}, {"name": "duration", "type": "number", "optional": false, "description": "Duration of the animation.", "typeRef": null}, {"name": "delay", "type": "number", "optional": false, "description": "Delay of the animation.", "typeRef": null}], [], "Sets the timing of an animation node.");
62
62
  inspectorBackend.registerType("Animation.Animation", [{"name": "id", "type": "string", "optional": false, "description": "`Animation`'s id.", "typeRef": null}, {"name": "name", "type": "string", "optional": false, "description": "`Animation`'s name.", "typeRef": null}, {"name": "pausedState", "type": "boolean", "optional": false, "description": "`Animation`'s internal paused state.", "typeRef": null}, {"name": "playState", "type": "string", "optional": false, "description": "`Animation`'s play state.", "typeRef": null}, {"name": "playbackRate", "type": "number", "optional": false, "description": "`Animation`'s playback rate.", "typeRef": null}, {"name": "startTime", "type": "number", "optional": false, "description": "`Animation`'s start time. Milliseconds for time based animations and percentage [0 - 100] for scroll driven animations (i.e. when viewOrScrollTimeline exists).", "typeRef": null}, {"name": "currentTime", "type": "number", "optional": false, "description": "`Animation`'s current time.", "typeRef": null}, {"name": "type", "type": "string", "optional": false, "description": "Animation type of `Animation`.", "typeRef": null}, {"name": "source", "type": "object", "optional": true, "description": "`Animation`'s source animation node.", "typeRef": "Animation.AnimationEffect"}, {"name": "cssId", "type": "string", "optional": true, "description": "A unique ID for `Animation` representing the sources that triggered this CSS animation/transition.", "typeRef": null}, {"name": "viewOrScrollTimeline", "type": "object", "optional": true, "description": "View or scroll timeline", "typeRef": "Animation.ViewOrScrollTimeline"}]);
63
63
  inspectorBackend.registerType("Animation.ViewOrScrollTimeline", [{"name": "sourceNodeId", "type": "number", "optional": true, "description": "Scroll container node", "typeRef": "DOM.BackendNodeId"}, {"name": "startOffset", "type": "number", "optional": true, "description": "Represents the starting scroll position of the timeline as a length offset in pixels from scroll origin.", "typeRef": null}, {"name": "endOffset", "type": "number", "optional": true, "description": "Represents the ending scroll position of the timeline as a length offset in pixels from scroll origin.", "typeRef": null}, {"name": "subjectNodeId", "type": "number", "optional": true, "description": "The element whose principal box's visibility in the scrollport defined the progress of the timeline. Does not exist for animations with ScrollTimeline", "typeRef": "DOM.BackendNodeId"}, {"name": "axis", "type": "string", "optional": false, "description": "Orientation of the scroll", "typeRef": "DOM.ScrollOrientation"}]);
64
- inspectorBackend.registerType("Animation.AnimationEffect", [{"name": "delay", "type": "number", "optional": false, "description": "`AnimationEffect`'s delay.", "typeRef": null}, {"name": "endDelay", "type": "number", "optional": false, "description": "`AnimationEffect`'s end delay.", "typeRef": null}, {"name": "iterationStart", "type": "number", "optional": false, "description": "`AnimationEffect`'s iteration start.", "typeRef": null}, {"name": "iterations", "type": "number", "optional": false, "description": "`AnimationEffect`'s iterations.", "typeRef": null}, {"name": "duration", "type": "number", "optional": false, "description": "`AnimationEffect`'s iteration duration. Milliseconds for time based animations and percentage [0 - 100] for scroll driven animations (i.e. when viewOrScrollTimeline exists).", "typeRef": null}, {"name": "direction", "type": "string", "optional": false, "description": "`AnimationEffect`'s playback direction.", "typeRef": null}, {"name": "fill", "type": "string", "optional": false, "description": "`AnimationEffect`'s fill mode.", "typeRef": null}, {"name": "backendNodeId", "type": "number", "optional": true, "description": "`AnimationEffect`'s target node.", "typeRef": "DOM.BackendNodeId"}, {"name": "keyframesRule", "type": "object", "optional": true, "description": "`AnimationEffect`'s keyframes.", "typeRef": "Animation.KeyframesRule"}, {"name": "easing", "type": "string", "optional": false, "description": "`AnimationEffect`'s timing function.", "typeRef": null}]);
64
+ inspectorBackend.registerType("Animation.AnimationEffect", [{"name": "delay", "type": "number", "optional": false, "description": "`AnimationEffect`'s delay.", "typeRef": null}, {"name": "endDelay", "type": "number", "optional": false, "description": "`AnimationEffect`'s end delay.", "typeRef": null}, {"name": "iterationStart", "type": "number", "optional": false, "description": "`AnimationEffect`'s iteration start.", "typeRef": null}, {"name": "iterations", "type": "number", "optional": true, "description": "`AnimationEffect`'s iterations. Omitted if the value is infinite.", "typeRef": null}, {"name": "duration", "type": "number", "optional": false, "description": "`AnimationEffect`'s iteration duration. Milliseconds for time based animations and percentage [0 - 100] for scroll driven animations (i.e. when viewOrScrollTimeline exists).", "typeRef": null}, {"name": "direction", "type": "string", "optional": false, "description": "`AnimationEffect`'s playback direction.", "typeRef": null}, {"name": "fill", "type": "string", "optional": false, "description": "`AnimationEffect`'s fill mode.", "typeRef": null}, {"name": "backendNodeId", "type": "number", "optional": true, "description": "`AnimationEffect`'s target node.", "typeRef": "DOM.BackendNodeId"}, {"name": "keyframesRule", "type": "object", "optional": true, "description": "`AnimationEffect`'s keyframes.", "typeRef": "Animation.KeyframesRule"}, {"name": "easing", "type": "string", "optional": false, "description": "`AnimationEffect`'s timing function.", "typeRef": null}]);
65
65
  inspectorBackend.registerType("Animation.KeyframesRule", [{"name": "name", "type": "string", "optional": true, "description": "CSS keyframed animation's name.", "typeRef": null}, {"name": "keyframes", "type": "array", "optional": false, "description": "List of animation keyframes.", "typeRef": "Animation.KeyframeStyle"}]);
66
66
  inspectorBackend.registerType("Animation.KeyframeStyle", [{"name": "offset", "type": "string", "optional": false, "description": "Keyframe's time offset.", "typeRef": null}, {"name": "easing", "type": "string", "optional": false, "description": "`AnimationEffect`'s timing function.", "typeRef": null}]);
67
67
 
@@ -226,6 +226,8 @@ inspectorBackend.registerType("Browser.Histogram", [{"name": "name", "type": "st
226
226
  inspectorBackend.registerEnum("CSS.StyleSheetOrigin", {Injected: "injected", UserAgent: "user-agent", Inspector: "inspector", Regular: "regular"});
227
227
  inspectorBackend.registerEnum("CSS.CSSRuleType", {MediaRule: "MediaRule", SupportsRule: "SupportsRule", ContainerRule: "ContainerRule", LayerRule: "LayerRule", ScopeRule: "ScopeRule", StyleRule: "StyleRule", StartingStyleRule: "StartingStyleRule"});
228
228
  inspectorBackend.registerEnum("CSS.CSSMediaSource", {MediaRule: "mediaRule", ImportRule: "importRule", LinkedSheet: "linkedSheet", InlineSheet: "inlineSheet"});
229
+ inspectorBackend.registerEnum("CSS.CSSAtRuleType", {FontFace: "font-face", FontFeatureValues: "font-feature-values", FontPaletteValues: "font-palette-values"});
230
+ inspectorBackend.registerEnum("CSS.CSSAtRuleSubsection", {Swash: "swash", Annotation: "annotation", Ornaments: "ornaments", Stylistic: "stylistic", Styleset: "styleset", CharacterVariant: "character-variant"});
229
231
  inspectorBackend.registerEvent("CSS.fontsUpdated", ["font"]);
230
232
  inspectorBackend.registerEvent("CSS.mediaQueryResultChanged", []);
231
233
  inspectorBackend.registerEvent("CSS.styleSheetAdded", ["header"]);
@@ -245,7 +247,7 @@ inspectorBackend.registerCommand("CSS.resolveValues", [{"name": "values", "type"
245
247
  inspectorBackend.registerCommand("CSS.getLonghandProperties", [{"name": "shorthandName", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "value", "type": "string", "optional": false, "description": "", "typeRef": null}], ["longhandProperties"], "");
246
248
  inspectorBackend.registerCommand("CSS.getInlineStylesForNode", [{"name": "nodeId", "type": "number", "optional": false, "description": "", "typeRef": "DOM.NodeId"}], ["inlineStyle", "attributesStyle"], "Returns the styles defined inline (explicitly in the \"style\" attribute and implicitly, using DOM attributes) for a DOM node identified by `nodeId`.");
247
249
  inspectorBackend.registerCommand("CSS.getAnimatedStylesForNode", [{"name": "nodeId", "type": "number", "optional": false, "description": "", "typeRef": "DOM.NodeId"}], ["animationStyles", "transitionsStyle", "inherited"], "Returns the styles coming from animations & transitions including the animation & transition styles coming from inheritance chain.");
248
- inspectorBackend.registerCommand("CSS.getMatchedStylesForNode", [{"name": "nodeId", "type": "number", "optional": false, "description": "", "typeRef": "DOM.NodeId"}], ["inlineStyle", "attributesStyle", "matchedCSSRules", "pseudoElements", "inherited", "inheritedPseudoElements", "cssKeyframesRules", "cssPositionTryRules", "activePositionFallbackIndex", "cssPropertyRules", "cssPropertyRegistrations", "cssFontPaletteValuesRule", "parentLayoutNodeId", "cssFunctionRules"], "Returns requested styles for a DOM node identified by `nodeId`.");
250
+ inspectorBackend.registerCommand("CSS.getMatchedStylesForNode", [{"name": "nodeId", "type": "number", "optional": false, "description": "", "typeRef": "DOM.NodeId"}], ["inlineStyle", "attributesStyle", "matchedCSSRules", "pseudoElements", "inherited", "inheritedPseudoElements", "cssKeyframesRules", "cssPositionTryRules", "activePositionFallbackIndex", "cssPropertyRules", "cssPropertyRegistrations", "cssFontPaletteValuesRule", "cssAtRules", "parentLayoutNodeId", "cssFunctionRules"], "Returns requested styles for a DOM node identified by `nodeId`.");
249
251
  inspectorBackend.registerCommand("CSS.getEnvironmentVariables", [], ["environmentVariables"], "Returns the values of the default UA-defined environment variables used in env()");
250
252
  inspectorBackend.registerCommand("CSS.getMediaQueries", [], ["medias"], "Returns all media queries parsed by the rendering engine.");
251
253
  inspectorBackend.registerCommand("CSS.getPlatformFontsForNode", [{"name": "nodeId", "type": "number", "optional": false, "description": "", "typeRef": "DOM.NodeId"}], ["fonts"], "Requests information about platform fonts which we used to render child TextNodes in the given node.");
@@ -304,6 +306,7 @@ inspectorBackend.registerType("CSS.CSSPositionTryRule", [{"name": "name", "type"
304
306
  inspectorBackend.registerType("CSS.CSSKeyframesRule", [{"name": "animationName", "type": "object", "optional": false, "description": "Animation name.", "typeRef": "CSS.Value"}, {"name": "keyframes", "type": "array", "optional": false, "description": "List of keyframes.", "typeRef": "CSS.CSSKeyframeRule"}]);
305
307
  inspectorBackend.registerType("CSS.CSSPropertyRegistration", [{"name": "propertyName", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "initialValue", "type": "object", "optional": true, "description": "", "typeRef": "CSS.Value"}, {"name": "inherits", "type": "boolean", "optional": false, "description": "", "typeRef": null}, {"name": "syntax", "type": "string", "optional": false, "description": "", "typeRef": null}]);
306
308
  inspectorBackend.registerType("CSS.CSSFontPaletteValuesRule", [{"name": "styleSheetId", "type": "string", "optional": true, "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified stylesheet rules) this rule came from.", "typeRef": "CSS.StyleSheetId"}, {"name": "origin", "type": "string", "optional": false, "description": "Parent stylesheet's origin.", "typeRef": "CSS.StyleSheetOrigin"}, {"name": "fontPaletteName", "type": "object", "optional": false, "description": "Associated font palette name.", "typeRef": "CSS.Value"}, {"name": "style", "type": "object", "optional": false, "description": "Associated style declaration.", "typeRef": "CSS.CSSStyle"}]);
309
+ inspectorBackend.registerType("CSS.CSSAtRule", [{"name": "type", "type": "string", "optional": false, "description": "Type of at-rule.", "typeRef": null}, {"name": "subsection", "type": "string", "optional": true, "description": "Subsection of font-feature-values, if this is a subsection.", "typeRef": null}, {"name": "name", "type": "object", "optional": true, "description": "LINT_SKIP.ThenChange(//third_party/blink/renderer/core/inspector/inspector_style_sheet.cc:FontVariantAlternatesFeatureType,//third_party/blink/renderer/core/inspector/inspector_css_agent.cc:FontVariantAlternatesFeatureType) Associated name, if applicable.", "typeRef": "CSS.Value"}, {"name": "styleSheetId", "type": "string", "optional": true, "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified stylesheet rules) this rule came from.", "typeRef": "CSS.StyleSheetId"}, {"name": "origin", "type": "string", "optional": false, "description": "Parent stylesheet's origin.", "typeRef": "CSS.StyleSheetOrigin"}, {"name": "style", "type": "object", "optional": false, "description": "Associated style declaration.", "typeRef": "CSS.CSSStyle"}]);
307
310
  inspectorBackend.registerType("CSS.CSSPropertyRule", [{"name": "styleSheetId", "type": "string", "optional": true, "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified stylesheet rules) this rule came from.", "typeRef": "CSS.StyleSheetId"}, {"name": "origin", "type": "string", "optional": false, "description": "Parent stylesheet's origin.", "typeRef": "CSS.StyleSheetOrigin"}, {"name": "propertyName", "type": "object", "optional": false, "description": "Associated property name.", "typeRef": "CSS.Value"}, {"name": "style", "type": "object", "optional": false, "description": "Associated style declaration.", "typeRef": "CSS.CSSStyle"}]);
308
311
  inspectorBackend.registerType("CSS.CSSFunctionParameter", [{"name": "name", "type": "string", "optional": false, "description": "The parameter name.", "typeRef": null}, {"name": "type", "type": "string", "optional": false, "description": "The parameter type.", "typeRef": null}]);
309
312
  inspectorBackend.registerType("CSS.CSSFunctionConditionNode", [{"name": "media", "type": "object", "optional": true, "description": "Media query for this conditional block. Only one type of condition should be set.", "typeRef": "CSS.CSSMedia"}, {"name": "containerQueries", "type": "object", "optional": true, "description": "Container query for this conditional block. Only one type of condition should be set.", "typeRef": "CSS.CSSContainerQuery"}, {"name": "supports", "type": "object", "optional": true, "description": "@supports CSS at-rule condition. Only one type of condition should be set.", "typeRef": "CSS.CSSSupports"}, {"name": "children", "type": "array", "optional": false, "description": "Block body.", "typeRef": "CSS.CSSFunctionNode"}, {"name": "conditionText", "type": "string", "optional": false, "description": "The condition text.", "typeRef": null}]);
@@ -1351,7 +1354,7 @@ inspectorBackend.registerCommand("Target.setAutoAttach", [{"name": "autoAttach",
1351
1354
  inspectorBackend.registerCommand("Target.autoAttachRelated", [{"name": "targetId", "type": "string", "optional": false, "description": "", "typeRef": "Target.TargetID"}, {"name": "waitForDebuggerOnStart", "type": "boolean", "optional": false, "description": "Whether to pause new targets when attaching to them. Use `Runtime.runIfWaitingForDebugger` to run paused targets.", "typeRef": null}, {"name": "filter", "type": "array", "optional": true, "description": "Only targets matching filter will be attached.", "typeRef": "Target.TargetFilter"}], [], "Adds the specified target to the list of targets that will be monitored for any related target creation (such as child frames, child workers and new versions of service worker) and reported through `attachedToTarget`. The specified target is also auto-attached. This cancels the effect of any previous `setAutoAttach` and is also cancelled by subsequent `setAutoAttach`. Only available at the Browser target.");
1352
1355
  inspectorBackend.registerCommand("Target.setDiscoverTargets", [{"name": "discover", "type": "boolean", "optional": false, "description": "Whether to discover available targets.", "typeRef": null}, {"name": "filter", "type": "array", "optional": true, "description": "Only targets matching filter will be attached. If `discover` is false, `filter` must be omitted or empty.", "typeRef": "Target.TargetFilter"}], [], "Controls whether to discover available targets and notify via `targetCreated/targetInfoChanged/targetDestroyed` events.");
1353
1356
  inspectorBackend.registerCommand("Target.setRemoteLocations", [{"name": "locations", "type": "array", "optional": false, "description": "List of remote locations.", "typeRef": "Target.RemoteLocation"}], [], "Enables target discovery for the specified locations, when `setDiscoverTargets` was set to `true`.");
1354
- inspectorBackend.registerCommand("Target.openDevTools", [{"name": "targetId", "type": "string", "optional": false, "description": "This can be the page or tab target ID.", "typeRef": "Target.TargetID"}], ["targetId"], "Opens a DevTools window for the target.");
1357
+ inspectorBackend.registerCommand("Target.openDevTools", [{"name": "targetId", "type": "string", "optional": false, "description": "This can be the page or tab target ID.", "typeRef": "Target.TargetID"}, {"name": "panelId", "type": "string", "optional": true, "description": "The id of the panel we want DevTools to open initially. Currently supported panels are elements, console, network, sources and resources.", "typeRef": null}], ["targetId"], "Opens a DevTools window for the target.");
1355
1358
  inspectorBackend.registerType("Target.TargetInfo", [{"name": "targetId", "type": "string", "optional": false, "description": "", "typeRef": "Target.TargetID"}, {"name": "type", "type": "string", "optional": false, "description": "List of types: https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/devtools_agent_host_impl.cc?ss=chromium&q=f:devtools%20-f:out%20%22::kTypeTab%5B%5D%22", "typeRef": null}, {"name": "title", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "url", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "attached", "type": "boolean", "optional": false, "description": "Whether the target has an attached client.", "typeRef": null}, {"name": "openerId", "type": "string", "optional": true, "description": "Opener target Id", "typeRef": "Target.TargetID"}, {"name": "canAccessOpener", "type": "boolean", "optional": false, "description": "Whether the target has access to the originating window.", "typeRef": null}, {"name": "openerFrameId", "type": "string", "optional": true, "description": "Frame id of originating window (is only set if target has an opener).", "typeRef": "Page.FrameId"}, {"name": "parentFrameId", "type": "string", "optional": true, "description": "Id of the parent frame, only present for the \\\"iframe\\\" targets.", "typeRef": "Page.FrameId"}, {"name": "browserContextId", "type": "string", "optional": true, "description": "", "typeRef": "Browser.BrowserContextID"}, {"name": "subtype", "type": "string", "optional": true, "description": "Provides additional details for specific target types. For example, for the type of \\\"page\\\", this may be set to \\\"prerender\\\".", "typeRef": null}]);
1356
1359
  inspectorBackend.registerType("Target.FilterEntry", [{"name": "exclude", "type": "boolean", "optional": true, "description": "If set, causes exclusion of matching targets from the list.", "typeRef": null}, {"name": "type", "type": "string", "optional": true, "description": "If not present, matches any type.", "typeRef": null}]);
1357
1360
  inspectorBackend.registerType("Target.TargetFilter", [{"name": "TargetFilter", "type": "array", "optional": false, "description": "The entries in TargetFilter are matched sequentially against targets and the first entry that matches determines if the target is included or not, depending on the value of `exclude` field in the entry. If filter is not specified, the one assumed is [{type: \\\"browser\\\", exclude: true}, {type: \\\"tab\\\", exclude: true}, {}] (i.e. include everything but `browser` and `tab`).", "typeRef": "Target.FilterEntry"}]);
@@ -3845,6 +3845,19 @@ export const generatedProperties = [
3845
3845
  ],
3846
3846
  "name": "rule-color"
3847
3847
  },
3848
+ {
3849
+ "longhands": [
3850
+ "row-rule-edge-start-outset",
3851
+ "row-rule-edge-end-outset",
3852
+ "row-rule-interior-start-outset",
3853
+ "row-rule-interior-end-outset",
3854
+ "column-rule-edge-start-outset",
3855
+ "column-rule-edge-end-outset",
3856
+ "column-rule-interior-start-outset",
3857
+ "column-rule-interior-end-outset"
3858
+ ],
3859
+ "name": "rule-outset"
3860
+ },
3848
3861
  {
3849
3862
  "longhands": [
3850
3863
  "column-rule-style",
@@ -544,9 +544,9 @@ export namespace Animation {
544
544
  */
545
545
  iterationStart: number;
546
546
  /**
547
- * `AnimationEffect`'s iterations.
547
+ * `AnimationEffect`'s iterations. Omitted if the value is infinite.
548
548
  */
549
- iterations: number;
549
+ iterations?: number;
550
550
  /**
551
551
  * `AnimationEffect`'s iteration duration.
552
552
  * Milliseconds for time based animations and
@@ -3452,6 +3452,53 @@ export namespace CSS {
3452
3452
  style: CSSStyle;
3453
3453
  }
3454
3454
 
3455
+ export const enum CSSAtRuleType {
3456
+ FontFace = 'font-face',
3457
+ FontFeatureValues = 'font-feature-values',
3458
+ FontPaletteValues = 'font-palette-values',
3459
+ }
3460
+
3461
+ export const enum CSSAtRuleSubsection {
3462
+ Swash = 'swash',
3463
+ Annotation = 'annotation',
3464
+ Ornaments = 'ornaments',
3465
+ Stylistic = 'stylistic',
3466
+ Styleset = 'styleset',
3467
+ CharacterVariant = 'character-variant',
3468
+ }
3469
+
3470
+ /**
3471
+ * CSS generic @rule representation.
3472
+ */
3473
+ export interface CSSAtRule {
3474
+ /**
3475
+ * Type of at-rule.
3476
+ */
3477
+ type: CSSAtRuleType;
3478
+ /**
3479
+ * Subsection of font-feature-values, if this is a subsection.
3480
+ */
3481
+ subsection?: CSSAtRuleSubsection;
3482
+ /**
3483
+ * LINT_SKIP.ThenChange(//third_party/blink/renderer/core/inspector/inspector_style_sheet.cc:FontVariantAlternatesFeatureType,//third_party/blink/renderer/core/inspector/inspector_css_agent.cc:FontVariantAlternatesFeatureType)
3484
+ * Associated name, if applicable.
3485
+ */
3486
+ name?: Value;
3487
+ /**
3488
+ * The css style sheet identifier (absent for user agent stylesheet and user-specified
3489
+ * stylesheet rules) this rule came from.
3490
+ */
3491
+ styleSheetId?: StyleSheetId;
3492
+ /**
3493
+ * Parent stylesheet's origin.
3494
+ */
3495
+ origin: StyleSheetOrigin;
3496
+ /**
3497
+ * Associated style declaration.
3498
+ */
3499
+ style: CSSStyle;
3500
+ }
3501
+
3455
3502
  /**
3456
3503
  * CSS property at-rule representation.
3457
3504
  */
@@ -3848,6 +3895,10 @@ export namespace CSS {
3848
3895
  * A font-palette-values rule matching this node.
3849
3896
  */
3850
3897
  cssFontPaletteValuesRule?: CSSFontPaletteValuesRule;
3898
+ /**
3899
+ * A list of simple @rules matching this node or its pseudo-elements.
3900
+ */
3901
+ cssAtRules?: CSSAtRule[];
3851
3902
  /**
3852
3903
  * Id of the first parent element that does not have display: contents.
3853
3904
  */
@@ -18464,6 +18515,11 @@ export namespace Target {
18464
18515
  * This can be the page or tab target ID.
18465
18516
  */
18466
18517
  targetId: TargetID;
18518
+ /**
18519
+ * The id of the panel we want DevTools to open initially. Currently
18520
+ * supported panels are elements, console, network, sources and resources.
18521
+ */
18522
+ panelId?: string;
18467
18523
  }
18468
18524
 
18469
18525
  export interface OpenDevToolsResponse extends ProtocolResponseWithError {
@@ -44,7 +44,8 @@ export class BuiltInAi {
44
44
  }
45
45
 
46
46
  static cachedIsAvailable(): boolean {
47
- return availability === LanguageModelAvailability.AVAILABLE;
47
+ return availability === LanguageModelAvailability.AVAILABLE &&
48
+ (hasGpu || Boolean(Root.Runtime.hostConfig.devToolsAiPromptApi?.allowWithoutGpu));
48
49
  }
49
50
 
50
51
  static isGpuAvailable(): boolean {
@@ -885,50 +885,60 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
885
885
  });
886
886
 
887
887
  const isFresh = Tracing.FreshRecording.Tracker.instance().recordingIsFresh(parsedTrace);
888
- const hasScriptContents =
889
- parsedTrace.metadata.enhancedTraceVersion && parsedTrace.data.Scripts.scripts.some(s => s.content);
888
+ const isTraceApp = Root.Runtime.Runtime.isTraceApp();
890
889
 
891
- if (isFresh || hasScriptContents) {
892
- this.declareFunction<{url: string}, {content: string}>('getResourceContent', {
893
- description: 'Returns the content of the resource with the given url. Only use this for text resource types.',
894
- parameters: {
895
- type: Host.AidaClient.ParametersTypes.OBJECT,
896
- description: '',
897
- nullable: false,
898
- properties: {
899
- url: {
900
- type: Host.AidaClient.ParametersTypes.STRING,
901
- description: 'The url for the resource.',
902
- nullable: false,
903
- },
890
+ this.declareFunction<{url: string}, {content: string}>('getResourceContent', {
891
+ description:
892
+ 'Returns the content of the resource with the given url. Only use this for text resource types. This function is helpful for getting script contents in order to further analyze main thread activity and suggest code improvements. When analyzing the main thread activity, always call this function to get more detail. Always call this function when asked to provide specifics about what is happening in the code. Never ask permission to call this function, just do it.',
893
+ parameters: {
894
+ type: Host.AidaClient.ParametersTypes.OBJECT,
895
+ description: '',
896
+ nullable: false,
897
+ properties: {
898
+ url: {
899
+ type: Host.AidaClient.ParametersTypes.STRING,
900
+ description: 'The url for the resource.',
901
+ nullable: false,
904
902
  },
905
903
  },
906
- displayInfoFromArgs: args => {
907
- return {title: lockedString('Looking at resource content…'), action: `getResourceContent('${args.url}')`};
908
- },
909
- handler: async args => {
910
- debugLog('Function call: getResourceContent');
911
-
912
- const url = args.url as Platform.DevToolsPath.UrlString;
904
+ },
905
+ displayInfoFromArgs: args => {
906
+ return {title: lockedString('Looking at resource content…'), action: `getResourceContent('${args.url}')`};
907
+ },
908
+ handler: async args => {
909
+ debugLog('Function call: getResourceContent');
910
+
911
+ const url = args.url as Platform.DevToolsPath.UrlString;
912
+ let content: string|undefined;
913
+
914
+ // First check parsedTrace.data.Scripts.
915
+ // Then, check ResourceTreeModel, but only when it is valid. Don't want to
916
+ // use if viewing a loaded trace from DevTools attached to an unrelated
917
+ // page.
918
+ const script = parsedTrace.data.Scripts.scripts.find(script => script.url === url);
919
+ if (script?.content !== undefined) {
920
+ content = script.content;
921
+ } else if (isFresh || isTraceApp) {
913
922
  const resource = SDK.ResourceTreeModel.ResourceTreeModel.resourceForURL(url);
914
923
  if (!resource) {
915
- if (!resource) {
916
- return {error: 'Resource not found'};
917
- }
924
+ return {error: 'Resource not found'};
918
925
  }
919
926
 
920
- const content = await resource.requestContentData();
921
- if ('error' in content) {
922
- return {error: `Could not get resource content: ${content.error}`};
927
+ const data = await resource.requestContentData();
928
+ if ('error' in data) {
929
+ return {error: `Could not get resource content: ${data.error}`};
923
930
  }
924
931
 
925
- const key = `getResourceContent(${args.url})`;
926
- this.#cacheFunctionResult(focus, key, content.text);
927
- return {result: {content: content.text}};
928
- },
932
+ content = data.text;
933
+ } else {
934
+ return {error: 'Resource not found'};
935
+ }
929
936
 
930
- });
931
- }
937
+ const key = `getResourceContent(${args.url})`;
938
+ this.#cacheFunctionResult(focus, key, content);
939
+ return {result: {content}};
940
+ },
941
+ });
932
942
 
933
943
  if (!context.external) {
934
944
  this.declareFunction<{eventKey: string}, {success: boolean}>('selectEventByKey', {