chrome-devtools-frontend 1.0.1570343 → 1.0.1571573

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 (72) hide show
  1. package/agents/prompts/README.md +18 -0
  2. package/agents/prompts/devtools-imports.md +47 -0
  3. package/agents/prompts/verification.md +27 -0
  4. package/docs/contributing/infrastructure.md +22 -0
  5. package/front_end/core/host/AidaClient.ts +1 -1
  6. package/front_end/core/host/UserMetrics.ts +1 -1
  7. package/front_end/core/root/Runtime.ts +54 -34
  8. package/front_end/core/sdk/CSSProperty.ts +1 -1
  9. package/front_end/core/sdk/CookieModel.ts +1 -1
  10. package/front_end/core/sdk/DOMModel.ts +1 -1
  11. package/front_end/core/sdk/DebuggerModel.ts +2 -21
  12. package/front_end/core/sdk/OverlayModel.ts +3 -2
  13. package/front_end/core/sdk/SourceMap.ts +0 -9
  14. package/front_end/core/sdk/SourceMapScopesInfo.ts +0 -24
  15. package/front_end/entrypoints/main/MainImpl.ts +43 -18
  16. package/front_end/generated/SupportedCSSProperties.js +2 -6
  17. package/front_end/models/ai_assistance/BuiltInAi.ts +5 -4
  18. package/front_end/models/issues_manager/ContrastCheckTrigger.ts +2 -2
  19. package/front_end/models/javascript_metadata/NativeFunctions.js +8 -0
  20. package/front_end/models/trace/ModelImpl.ts +0 -4
  21. package/front_end/panels/accessibility/AccessibilitySidebarView.ts +1 -1
  22. package/front_end/panels/ai_assistance/PatchWidget.ts +10 -15
  23. package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +5 -4
  24. package/front_end/panels/ai_assistance/components/ChatMessage.ts +3 -2
  25. package/front_end/panels/application/FrameDetailsView.ts +2 -1
  26. package/front_end/panels/application/components/ReportsGrid.ts +2 -1
  27. package/front_end/panels/common/AiCodeCompletionSummaryToolbar.ts +3 -5
  28. package/front_end/panels/common/AiCodeCompletionTeaser.ts +5 -5
  29. package/front_end/panels/console/ConsoleInsightTeaser.ts +10 -11
  30. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +2 -2
  31. package/front_end/panels/css_overview/CSSOverviewModel.ts +1 -1
  32. package/front_end/panels/elements/ComputedStyleModel.ts +11 -13
  33. package/front_end/panels/elements/ComputedStyleWidget.ts +3 -3
  34. package/front_end/panels/elements/ElementsPanel.ts +5 -2
  35. package/front_end/panels/elements/ElementsSidebarPane.ts +1 -1
  36. package/front_end/panels/elements/PlatformFontsWidget.ts +1 -1
  37. package/front_end/panels/elements/StylePropertiesSection.ts +1 -1
  38. package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
  39. package/front_end/panels/emulation/DeviceModeWrapper.ts +101 -62
  40. package/front_end/panels/explain/components/ConsoleInsight.ts +27 -23
  41. package/front_end/panels/explain/components/consoleInsight.css +1 -1
  42. package/front_end/panels/network/RequestConditionsDrawer.ts +0 -1
  43. package/front_end/panels/network/RequestTimingView.ts +4 -3
  44. package/front_end/panels/network/components/RequestHeadersView.css +2 -2
  45. package/front_end/panels/network/components/RequestHeadersView.ts +7 -6
  46. package/front_end/panels/profiler/HeapProfileView.ts +3 -3
  47. package/front_end/panels/profiler/HeapSnapshotView.ts +2 -2
  48. package/front_end/panels/recorder/RecorderController.ts +6 -7
  49. package/front_end/panels/recorder/recorderController.css +1 -1
  50. package/front_end/panels/security/CookieControlsView.ts +2 -2
  51. package/front_end/panels/security/CookieReportView.ts +7 -7
  52. package/front_end/panels/settings/AISettingsTab.ts +5 -5
  53. package/front_end/panels/settings/components/SyncSection.ts +4 -3
  54. package/front_end/panels/sources/CallStackSidebarPane.ts +4 -1
  55. package/front_end/panels/sources/NavigatorView.ts +1 -1
  56. package/front_end/panels/sources/SourcesPanel.ts +3 -1
  57. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +1 -1
  58. package/front_end/panels/timeline/ThreadAppender.ts +1 -1
  59. package/front_end/panels/timeline/TimelineController.ts +4 -3
  60. package/front_end/panels/timeline/TimelinePanel.ts +4 -3
  61. package/front_end/panels/whats_new/ReleaseNoteView.ts +4 -3
  62. package/front_end/third_party/chromium/README.chromium +1 -1
  63. package/front_end/ui/components/markdown_view/CodeBlock.ts +3 -6
  64. package/front_end/ui/components/markdown_view/MarkdownLink.ts +3 -4
  65. package/front_end/ui/components/panel_feedback/PanelFeedback.ts +3 -4
  66. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +9 -6
  67. package/front_end/ui/components/panel_feedback/panelFeedback.css +2 -2
  68. package/front_end/ui/kit/link/Link.ts +1 -14
  69. package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +1 -1
  70. package/front_end/ui/legacy/components/color_picker/ContrastOverlay.ts +5 -4
  71. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -1
  72. package/package.json +1 -1
@@ -0,0 +1,18 @@
1
+ This directory contains a series of prompts that can be added to your root `GEMINI.md` file, which is not committed to version control.
2
+
3
+ More context for Googlers: go/chrome-devtools:ai-agents-use
4
+
5
+ ## Getting started
6
+
7
+ 1. Create `//GEMINI.md` in the root of the `devtools-frontend` repository.
8
+ 2. Include the relevant prompts with `@`:
9
+
10
+ ```
11
+ @agents/prompts/verification.md
12
+ ```
13
+
14
+ The `/memory show` command in Gemini CL can be used to verify that the files have been included correctly.
15
+
16
+ ## Contributing
17
+
18
+ Contributions to existing prompts or to add new ones are encouraged; CLs are very welcome.
@@ -0,0 +1,47 @@
1
+ # Imports
2
+
3
+ This codebase follows a special convention for importing code that must be followed to avoid build errors.
4
+
5
+ In DevTools each folder of code is considered a *module*:
6
+
7
+ - `front_end/models/trace` is the *trace module*.
8
+ - `front_end/panels/timeline` is the *timeline module*.
9
+
10
+ Within each module there are multiple TypeScript files. *The file that is named the same as the folder name is called the entrypoint*.
11
+
12
+ - `front_end/models/trace/trace.ts` is the *trace module's entrypoint*
13
+ - `front_end/models/trace/ModelImpl.ts` is part of the implementation of the trace module.
14
+
15
+ ## Importing from another module
16
+
17
+ When you want to reuse code from other modules, *you must import that module via its entrypoint*. Imagine we are in `front_end/panels/timeline/TimelinePanel.ts`. This import is GOOD:
18
+
19
+ ```
20
+ import * as Trace from '../models/trace/trace.js'; // import the entrypoint
21
+ ```
22
+
23
+ This import is BAD because we import a file that is NOT the entrypoint:
24
+
25
+ ```
26
+ import * as ModelImpl from '../models/trace/ModelImpl.js' // NEVER ALLOWED
27
+ ```
28
+
29
+ Additionally, you **must import using the `import * as` syntax**.
30
+
31
+ ```
32
+ import {ModelImpl, X, Y} from '../models/trace/trace.js'; // BAD
33
+ ```
34
+
35
+ ```
36
+ import * as Trace from '../models/trace/trace.js'; // GOOD
37
+ ```
38
+
39
+ ## Importing from within the same module
40
+
41
+ If you are within the same module, it is OK to import from files directly rather than go via the entrypoint. You can also import specifically what you need.
42
+
43
+ For example, if you are editing `front_end/models/trace/ModelImpl.ts` this would be acceptable:
44
+
45
+ ```
46
+ import {Foo} from './Foo.js'; // allowed because Foo.ts is in the same directory.
47
+ ```
@@ -0,0 +1,27 @@
1
+ # Instructions on how to verify your changes
2
+
3
+ ## Testing
4
+
5
+ - To test a file, you can run `npm run test -- <FILEPATH>` where `FILEPATH` is a path to a `*.test.ts` file, relative to the working directory.
6
+ - Test files are usually defined alongside their implementation. So if you are working on `front_end/panels/timeline/TimelinePanel.ts`, you would expect the test file to be defined in `front_end/panels/timeline/TimelinePanel.test.ts`.
7
+ - You can also test an entire directory. For example, `npm run test -- front_end/models/trace` will run all tests in that directory.
8
+
9
+ ## Building & compiling
10
+
11
+ - Check for TypeScript or dependency issues in the build system by running `autoninja -C out/Default`.
12
+
13
+ ## Fast builds
14
+
15
+ - If the `out/Fast` or `out/fast-build` directory exists, this means that a build that does not execute TypeScript is available to you which greatly decreases build time.
16
+ - To use the fast build for tests, pass the `--target=Fast` (adjust the value based on the name of the directory) argument to `npm run test`.
17
+
18
+ ## Linting
19
+
20
+ - `npm run lint` will execute ESLint and StyleLint and report any violations that must be fixed.
21
+
22
+ ## Best practices
23
+
24
+ - Run tests often to verify your changes.
25
+ - Prefer using a fast build, if it exists, to keep the feedback loop shorter.
26
+ - Periodically compile with TypeScript to check for type errors.
27
+ - Run linting at the end of your code changes.
@@ -281,6 +281,28 @@ even if it consistently failed 4 times out of 5 runs for some time. Try to
281
281
  correlate your failure with a luci-analysis report on this test and skip it
282
282
  until the flakiness gets resolved.
283
283
 
284
+ ### Clobber a builder's cache
285
+
286
+ Builder bots utilize caching for project checkouts to speed up updates. This
287
+ cache includes the build output directory (`/out`). Occasionally, stale files
288
+ within these directories can interfere with the build process or test execution.
289
+
290
+ If you suspect a cache issue, you can clear (clobber) the cache for a specific
291
+ builder. This requires a local Chromium checkout to access the necessary utility
292
+ script.
293
+
294
+ Run the following command from the root of your Chromium checkout:
295
+
296
+ ```bash
297
+ ./tools/infra/builder-cache-clobber.py -S https://chromium-swarm.appspot.com/ --builder "Stand-alone Mac-arm64" --bucket ci --project devtools-frontend
298
+ ```
299
+
300
+ #### Note about caches on try bots:
301
+
302
+ Try bots (CQ) operate in tester/compilator pairs. When clearing caches, ensure
303
+ you target both builders in the pair. For example, if you clear the cache for
304
+ `dtf_mac_arm64_rel`, you must also clear it for `dtf_mac_arm64_compile_rel`.
305
+
284
306
  ## Luci Analysis configuration
285
307
 
286
308
  [Luci Analysis](go/luci-analysis) is a tool that helps you understand the
@@ -79,7 +79,7 @@ export interface FunctionObjectParam<T extends string|number|symbol = string> ex
79
79
  type: ParametersTypes.OBJECT;
80
80
  // TODO: this can be also be ObjectParams
81
81
  properties: Record<T, FunctionPrimitiveParams|FunctionArrayParam>;
82
- required: string[];
82
+ required: T[];
83
83
  }
84
84
 
85
85
  /**
@@ -825,7 +825,7 @@ export enum DevtoolsExperiments {
825
825
  'live-heap-profile' = 11,
826
826
  'protocol-monitor' = 13,
827
827
  'sampling-heap-profiler-timeline' = 17,
828
- 'show-option-tp-expose-internals-in-heap-snapshot' = 18,
828
+ 'show-option-to-expose-internals-in-heap-snapshot' = 18,
829
829
  'timeline-invalidation-tracking' = 26,
830
830
  'timeline-show-all-events' = 27,
831
831
  'timeline-v8-runtime-call-stats' = 28,
@@ -119,11 +119,17 @@ export class Runtime {
119
119
  if (experiment === '*') {
120
120
  return true;
121
121
  }
122
- if (experiment && experiment.startsWith('!') && experiments.isEnabled(experiment.substring(1))) {
123
- return false;
122
+ if (experiment?.startsWith('!')) {
123
+ const experimentName = experiment.substring(1) as ExperimentName;
124
+ if (experiments.isEnabled(experimentName)) {
125
+ return false;
126
+ }
124
127
  }
125
- if (experiment && !experiment.startsWith('!') && !experiments.isEnabled(experiment)) {
126
- return false;
128
+ if (experiment && !experiment.startsWith('!')) {
129
+ const experimentName = experiment as ExperimentName;
130
+ if (!experiments.isEnabled(experimentName)) {
131
+ return false;
132
+ }
127
133
  }
128
134
  const {condition} = descriptor;
129
135
  return condition ? condition(hostConfig) : true;
@@ -151,10 +157,10 @@ export interface Option {
151
157
 
152
158
  export class ExperimentsSupport {
153
159
  #experiments: Experiment[] = [];
154
- readonly #experimentNames = new Set<string>();
155
- readonly #enabledTransiently = new Set<string>();
156
- readonly #enabledByDefault = new Set<string>();
157
- readonly #serverEnabled = new Set<string>();
160
+ readonly #experimentNames = new Set<ExperimentName>();
161
+ readonly #enabledTransiently = new Set<ExperimentName>();
162
+ readonly #enabledByDefault = new Set<ExperimentName>();
163
+ readonly #serverEnabled = new Set<ExperimentName>();
158
164
  readonly #storage = new ExperimentStorage();
159
165
 
160
166
  allConfigurableExperiments(): Experiment[] {
@@ -167,7 +173,7 @@ export class ExperimentsSupport {
167
173
  return result;
168
174
  }
169
175
 
170
- register(experimentName: string, experimentTitle: string, docLink?: string, feedbackLink?: string): void {
176
+ register(experimentName: ExperimentName, experimentTitle: string, docLink?: string, feedbackLink?: string): void {
171
177
  if (this.#experimentNames.has(experimentName)) {
172
178
  throw new Error(`Duplicate registration of experiment '${experimentName}'`);
173
179
  }
@@ -178,7 +184,7 @@ export class ExperimentsSupport {
178
184
  feedbackLink as Platform.DevToolsPath.UrlString ?? Platform.DevToolsPath.EmptyUrlString));
179
185
  }
180
186
 
181
- isEnabled(experimentName: string): boolean {
187
+ isEnabled(experimentName: ExperimentName): boolean {
182
188
  this.checkExperiment(experimentName);
183
189
  // Check for explicitly disabled #experiments first - the code could call setEnable(false) on the experiment enabled
184
190
  // by default and we should respect that.
@@ -195,38 +201,39 @@ export class ExperimentsSupport {
195
201
  return Boolean(this.#storage.get(experimentName));
196
202
  }
197
203
 
198
- setEnabled(experimentName: string, enabled: boolean): void {
204
+ setEnabled(experimentName: ExperimentName, enabled: boolean): void {
199
205
  this.checkExperiment(experimentName);
200
206
  this.#storage.set(experimentName, enabled);
201
207
  }
202
208
 
203
- enableExperimentsTransiently(experimentNames: string[]): void {
209
+ enableExperimentsTransiently(experimentNames: ExperimentName[]): void {
204
210
  for (const experimentName of experimentNames) {
205
211
  this.checkExperiment(experimentName);
206
212
  this.#enabledTransiently.add(experimentName);
207
213
  }
208
214
  }
209
215
 
210
- enableExperimentsByDefault(experimentNames: string[]): void {
216
+ enableExperimentsByDefault(experimentNames: ExperimentName[]): void {
211
217
  for (const experimentName of experimentNames) {
212
218
  this.checkExperiment(experimentName);
213
219
  this.#enabledByDefault.add(experimentName);
214
220
  }
215
221
  }
216
222
 
217
- setServerEnabledExperiments(experimentNames: string[]): void {
218
- for (const experiment of experimentNames) {
219
- this.checkExperiment(experiment);
220
- this.#serverEnabled.add(experiment);
223
+ setServerEnabledExperiments(experiments: string[]): void {
224
+ for (const experiment of experiments) {
225
+ const experimentName = experiment as ExperimentName;
226
+ this.checkExperiment(experimentName);
227
+ this.#serverEnabled.add(experimentName);
221
228
  }
222
229
  }
223
230
 
224
- enableForTest(experimentName: string): void {
231
+ enableForTest(experimentName: ExperimentName): void {
225
232
  this.checkExperiment(experimentName);
226
233
  this.#enabledTransiently.add(experimentName);
227
234
  }
228
235
 
229
- disableForTest(experimentName: string): void {
236
+ disableForTest(experimentName: ExperimentName): void {
230
237
  this.checkExperiment(experimentName);
231
238
  this.#enabledTransiently.delete(experimentName);
232
239
  }
@@ -243,7 +250,7 @@ export class ExperimentsSupport {
243
250
  this.#storage.cleanUpStaleExperiments(this.#experimentNames);
244
251
  }
245
252
 
246
- private checkExperiment(experimentName: string): void {
253
+ private checkExperiment(experimentName: ExperimentName): void {
247
254
  if (!this.#experimentNames.has(experimentName)) {
248
255
  throw new Error(`Unknown experiment '${experimentName}'`);
249
256
  }
@@ -271,11 +278,11 @@ class ExperimentStorage {
271
278
  * - false: Explicitly disabled.
272
279
  * - undefined: Disabled.
273
280
  */
274
- get(experimentName: string): boolean|undefined {
281
+ get(experimentName: ExperimentName): boolean|undefined {
275
282
  return this.#experiments[experimentName];
276
283
  }
277
284
 
278
- set(experimentName: string, enabled: boolean): void {
285
+ set(experimentName: ExperimentName, enabled: boolean): void {
279
286
  this.#experiments[experimentName] = enabled;
280
287
  this.#syncToLocalStorage();
281
288
  }
@@ -294,14 +301,18 @@ class ExperimentStorage {
294
301
  }
295
302
  }
296
303
 
304
+ /**
305
+ * @deprecated Experiments should not be used anymore, instead use base::Feature.
306
+ * See docs/contributing/settings-experiments-features.md
307
+ */
297
308
  export class Experiment {
298
- name: string;
309
+ name: ExperimentName;
299
310
  title: string;
300
311
  docLink?: Platform.DevToolsPath.UrlString;
301
312
  readonly feedbackLink?: Platform.DevToolsPath.UrlString;
302
313
  readonly #experiments: ExperimentsSupport;
303
314
  constructor(
304
- experiments: ExperimentsSupport, name: string, title: string, docLink: Platform.DevToolsPath.UrlString,
315
+ experiments: ExperimentsSupport, name: ExperimentName, title: string, docLink: Platform.DevToolsPath.UrlString,
305
316
  feedbackLink: Platform.DevToolsPath.UrlString) {
306
317
  this.name = name;
307
318
  this.title = title;
@@ -322,18 +333,21 @@ export class Experiment {
322
333
  /** This must be constructed after the query parameters have been parsed. **/
323
334
  export const experiments = new ExperimentsSupport();
324
335
 
325
- /**
326
- * @deprecated Experiments should not be used anymore, instead use base::Feature.
327
- * See docs/contributing/settings-experiments-features.md
328
- */
329
- export const enum ExperimentName {
336
+ export enum ExperimentName {
337
+ ALL = '*',
330
338
  CAPTURE_NODE_CREATION_STACKS = 'capture-node-creation-stacks',
331
- CSS_OVERVIEW = 'css-overview',
332
339
  LIVE_HEAP_PROFILE = 'live-heap-profile',
333
- ALL = '*',
334
340
  PROTOCOL_MONITOR = 'protocol-monitor',
341
+ SAMPLING_HEAP_PROFILER_TIMELINE = 'sampling-heap-profiler-timeline',
342
+ SHOW_OPTION_TO_EXPOSE_INTERNALS_IN_HEAP_SNAPSHOT = 'show-option-to-expose-internals-in-heap-snapshot',
343
+ TIMELINE_INVALIDATION_TRACKING = 'timeline-invalidation-tracking',
344
+ TIMELINE_SHOW_ALL_EVENTS = 'timeline-show-all-events',
345
+ TIMELINE_V8_RUNTIME_CALL_STATS = 'timeline-v8-runtime-call-stats',
346
+ APCA = 'apca',
347
+ FONT_EDITOR = 'font-editor',
335
348
  FULL_ACCESSIBILITY_TREE = 'full-accessibility-tree',
336
- HEADER_OVERRIDES = 'header-overrides',
349
+ CONTRAST_ISSUES = 'contrast-issues',
350
+ EXPERIMENTAL_COOKIE_FEATURES = 'experimental-cookie-features',
337
351
  INSTRUMENTATION_BREAKPOINTS = 'instrumentation-breakpoints',
338
352
  AUTHORED_DEPLOYED_GROUPING = 'authored-deployed-grouping',
339
353
  JUST_MY_CODE = 'just-my-code',
@@ -342,8 +356,8 @@ export const enum ExperimentName {
342
356
  TIMELINE_DEBUG_MODE = 'timeline-debug-mode',
343
357
  // Adding or removing an entry from this enum?
344
358
  // You will need to update:
345
- // 1. REGISTERED_EXPERIMENTS in EnvironmentHelpers.ts (to create this experiment in the test env)
346
- // 2. DevToolsExperiments enum in host/UserMetrics.ts
359
+ // 1. DevToolsExperiments enum in host/UserMetrics.ts
360
+ // 2. Maybe REGISTERED_EXPERIMENTS in EnvironmentHelpers.ts (to create this experiment in the test env)
347
361
  }
348
362
 
349
363
  export enum GenAiEnterprisePolicyValue {
@@ -522,6 +536,11 @@ interface HostConfigAiAssistanceContextSelectionAgent {
522
536
  enabled: boolean;
523
537
  }
524
538
 
539
+ interface ConsoleInsightsTeasers {
540
+ enabled: boolean;
541
+ allowWithoutGpu: boolean;
542
+ }
543
+
525
544
  /**
526
545
  * The host configuration that we expect from the DevTools back-end.
527
546
  *
@@ -570,6 +589,7 @@ export type HostConfig = Platform.TypeScriptUtilities.RecursivePartial<{
570
589
  devToolsAiPromptApi: AiPromptApi,
571
590
  devToolsEnableDurableMessages: DevToolsEnableDurableMessages,
572
591
  devToolsAiAssistanceContextSelectionAgent: HostConfigAiAssistanceContextSelectionAgent,
592
+ devToolsConsoleInsightsTeasers: ConsoleInsightsTeasers,
573
593
  }>;
574
594
 
575
595
  /**
@@ -115,7 +115,7 @@ export class CSSProperty extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
115
115
  const matchers = matchedStyles.propertyMatchers(this.ownerStyle, computedStyles);
116
116
 
117
117
  matchers.push(new CSSWideKeywordMatcher(this, matchedStyles));
118
- if (Root.Runtime.experiments.isEnabled('font-editor')) {
118
+ if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.FONT_EDITOR)) {
119
119
  matchers.push(new FontMatcher());
120
120
  }
121
121
  return matchers;
@@ -99,7 +99,7 @@ export class CookieModel extends SDKModel<EventTypes> {
99
99
  if (cookie.expires()) {
100
100
  expires = Math.floor(Date.parse(`${cookie.expires()}`) / 1000);
101
101
  }
102
- const enabled = Root.Runtime.experiments.isEnabled('experimental-cookie-features');
102
+ const enabled = Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.EXPERIMENTAL_COOKIE_FEATURES);
103
103
  const preserveUnset = (scheme: Protocol.Network.CookieSourceScheme): Protocol.Network.CookieSourceScheme.Unset|
104
104
  undefined => scheme === Protocol.Network.CookieSourceScheme.Unset ? scheme : undefined;
105
105
  const protocolCookie = {
@@ -1319,7 +1319,7 @@ export class DOMModel extends SDKModel<EventTypes> {
1319
1319
  void this.agent.invoke_enable({});
1320
1320
  }
1321
1321
 
1322
- if (Root.Runtime.experiments.isEnabled('capture-node-creation-stacks')) {
1322
+ if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.CAPTURE_NODE_CREATION_STACKS)) {
1323
1323
  void this.agent.invoke_setNodeStackTracesEnabled({enable: true});
1324
1324
  }
1325
1325
  }
@@ -653,26 +653,6 @@ export class DebuggerModel extends SDKModel<EventTypes> {
653
653
  if (this.#expandCallFramesCallback) {
654
654
  pausedDetails.callFrames = await this.#expandCallFramesCallback.call(null, pausedDetails.callFrames);
655
655
  }
656
-
657
- if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.USE_SOURCE_MAP_SCOPES)) {
658
- return;
659
- }
660
-
661
- // TODO(crbug.com/40277685): Support attaching/detaching source maps after pausing.
662
- // Expanding call frames via source maps here is only suitable for the experiment prototype because
663
- // we block until all relevant source maps are loaded.
664
- // We should change this so the "Debugger Plugin" and "Source Map" have a bottle neck where they expand
665
- // call frames and that bottleneck should support attaching/detaching source maps while paused.
666
- const finalFrames: CallFrame[] = [];
667
- for (const frame of pausedDetails.callFrames) {
668
- const sourceMap = await this.sourceMapManager().sourceMapForClientPromise(frame.script);
669
- if (sourceMap?.hasScopeInfo()) {
670
- finalFrames.push(...sourceMap.expandCallFrame(frame));
671
- } else {
672
- finalFrames.push(frame);
673
- }
674
- }
675
- pausedDetails.callFrames = finalFrames;
676
656
  }
677
657
 
678
658
  resumedScript(): void {
@@ -707,7 +687,8 @@ export class DebuggerModel extends SDKModel<EventTypes> {
707
687
  this.registerScript(script);
708
688
  this.dispatchEventToListeners(Events.ParsedScriptSource, script);
709
689
 
710
- if (script.sourceMapURL && !hasSyntaxError) {
690
+ if ((!selectedDebugSymbol || selectedDebugSymbol.type === Protocol.Debugger.DebugSymbolsType.SourceMap) &&
691
+ script.sourceMapURL && !hasSyntaxError) {
711
692
  this.#sourceMapManager.attachSourceMap(script, script.sourceURL, script.sourceMapURL);
712
693
  }
713
694
 
@@ -534,8 +534,9 @@ export class OverlayModel extends SDKModel<EventTypes> implements ProtocolProxyA
534
534
  gridHighlightConfig: {},
535
535
  flexContainerHighlightConfig: {},
536
536
  flexItemHighlightConfig: {},
537
- contrastAlgorithm: Root.Runtime.experiments.isEnabled('apca') ? Protocol.Overlay.ContrastAlgorithm.Apca :
538
- Protocol.Overlay.ContrastAlgorithm.Aa,
537
+ contrastAlgorithm: Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.APCA) ?
538
+ Protocol.Overlay.ContrastAlgorithm.Apca :
539
+ Protocol.Overlay.ContrastAlgorithm.Aa,
539
540
  };
540
541
 
541
542
  if (mode === 'all' || mode === 'content') {
@@ -770,15 +770,6 @@ export class SourceMap {
770
770
  this.hasIgnoreListHint(sourceURL) === other.hasIgnoreListHint(sourceURL);
771
771
  }
772
772
 
773
- expandCallFrame(frame: CallFrame): CallFrame[] {
774
- this.#ensureSourceMapProcessed();
775
- if (this.#scopesInfo === null) {
776
- return [frame];
777
- }
778
-
779
- return this.#scopesInfo.expandCallFrame(frame);
780
- }
781
-
782
773
  resolveScopeChain(frame: CallFrame): ScopeChainEntry[]|null {
783
774
  this.#ensureSourceMapProcessed();
784
775
  if (this.#scopesInfo === null) {
@@ -276,30 +276,6 @@ export class SourceMapScopesInfo {
276
276
  return result;
277
277
  }
278
278
 
279
- /**
280
- * Takes a V8 provided call frame and expands any inlined frames into virtual call frames.
281
- *
282
- * For call frames where nothing was inlined, the result contains only a single element,
283
- * the provided frame but with the original name.
284
- *
285
- * For call frames where we are paused in inlined code, this function returns a list of
286
- * call frames from "inner to outer". This is the call frame at index 0
287
- * signifies the top of this stack trace fragment.
288
- *
289
- * The rest are "virtual" call frames and will have an "inlineFrameIndex" set in ascending
290
- * order, so the condition `result[index] === result[index].inlineFrameIndex` always holds.
291
- */
292
- expandCallFrame(callFrame: CallFrame): CallFrame[] {
293
- const {originalFunctionName, inlinedFunctions} =
294
- this.findInlinedFunctions(callFrame.location().lineNumber, callFrame.location().columnNumber);
295
- const result: CallFrame[] = [];
296
- for (const [index, fn] of inlinedFunctions.entries()) {
297
- result.push(callFrame.createVirtualCallFrame(index, fn.name));
298
- }
299
- result.push(callFrame.createVirtualCallFrame(result.length, originalFunctionName));
300
- return result;
301
- }
302
-
303
279
  /**
304
280
  * Given a generated position, this returns all the surrounding generated ranges from outer
305
281
  * to inner.
@@ -58,6 +58,7 @@ import * as PanelCommon from '../../panels/common/common.js';
58
58
  import * as Snippets from '../../panels/snippets/snippets.js';
59
59
  import * as Buttons from '../../ui/components/buttons/buttons.js';
60
60
  import * as Snackbar from '../../ui/components/snackbars/snackbars.js';
61
+ import * as UIHelpers from '../../ui/helpers/helpers.js';
61
62
  import * as Components from '../../ui/legacy/components/utils/utils.js';
62
63
  import * as UI from '../../ui/legacy/legacy.js';
63
64
  import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';
@@ -128,6 +129,10 @@ const UIStrings = {
128
129
  * @description Notification shown to the user whenever DevTools has finished downloading a local AI model.
129
130
  */
130
131
  aiModelDownloaded: 'AI model downloaded',
132
+ /**
133
+ * @description A title of the menu item in the main menu leading to https://github.com/ChromeDevTools/chrome-devtools-mcp.
134
+ */
135
+ getDevToolsMcp: 'Get `DevTools MCP`'
131
136
  } as const;
132
137
  const str_ = i18n.i18n.registerUIStrings('entrypoints/main/MainImpl.ts', UIStrings);
133
138
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -324,49 +329,59 @@ export class MainImpl {
324
329
  }
325
330
 
326
331
  #initializeExperiments(): void {
327
- Root.Runtime.experiments.register('capture-node-creation-stacks', 'Capture node creation stacks');
328
- Root.Runtime.experiments.register('live-heap-profile', 'Live heap profile');
329
332
  Root.Runtime.experiments.register(
330
- 'protocol-monitor', 'Protocol Monitor',
333
+ Root.Runtime.ExperimentName.CAPTURE_NODE_CREATION_STACKS, 'Capture node creation stacks');
334
+ Root.Runtime.experiments.register(Root.Runtime.ExperimentName.LIVE_HEAP_PROFILE, 'Live heap profile');
335
+ Root.Runtime.experiments.register(
336
+ Root.Runtime.ExperimentName.PROTOCOL_MONITOR, 'Protocol Monitor',
331
337
  'https://developer.chrome.com/blog/new-in-devtools-92/#protocol-monitor');
332
- Root.Runtime.experiments.register('sampling-heap-profiler-timeline', 'Sampling heap profiler timeline');
333
338
  Root.Runtime.experiments.register(
334
- 'show-option-tp-expose-internals-in-heap-snapshot', 'Show option to expose internals in heap snapshots');
339
+ Root.Runtime.ExperimentName.SAMPLING_HEAP_PROFILER_TIMELINE, 'Sampling heap profiler timeline');
340
+ Root.Runtime.experiments.register(
341
+ Root.Runtime.ExperimentName.SHOW_OPTION_TO_EXPOSE_INTERNALS_IN_HEAP_SNAPSHOT,
342
+ 'Show option to expose internals in heap snapshots');
335
343
 
336
344
  // Timeline
337
- Root.Runtime.experiments.register('timeline-invalidation-tracking', 'Performance panel: invalidation tracking');
338
- Root.Runtime.experiments.register('timeline-show-all-events', 'Performance panel: show all events');
339
- Root.Runtime.experiments.register('timeline-v8-runtime-call-stats', 'Performance panel: V8 runtime call stats');
345
+ Root.Runtime.experiments.register(
346
+ Root.Runtime.ExperimentName.TIMELINE_INVALIDATION_TRACKING, 'Performance panel: invalidation tracking');
347
+ Root.Runtime.experiments.register(
348
+ Root.Runtime.ExperimentName.TIMELINE_SHOW_ALL_EVENTS, 'Performance panel: show all events');
349
+ Root.Runtime.experiments.register(
350
+ Root.Runtime.ExperimentName.TIMELINE_V8_RUNTIME_CALL_STATS, 'Performance panel: V8 runtime call stats');
340
351
  Root.Runtime.experiments.register(
341
352
  Root.Runtime.ExperimentName.TIMELINE_DEBUG_MODE, 'Performance panel: debug mode (trace event details, etc)');
342
353
 
343
354
  // Debugging
344
- Root.Runtime.experiments.register('instrumentation-breakpoints', 'Instrumentation breakpoints');
345
- Root.Runtime.experiments.register('use-source-map-scopes', 'Use scope information from source maps');
355
+ Root.Runtime.experiments.register(
356
+ Root.Runtime.ExperimentName.INSTRUMENTATION_BREAKPOINTS, 'Instrumentation breakpoints');
357
+ Root.Runtime.experiments.register(
358
+ Root.Runtime.ExperimentName.USE_SOURCE_MAP_SCOPES, 'Use scope information from source maps');
346
359
 
347
360
  // Advanced Perceptual Contrast Algorithm.
348
361
  Root.Runtime.experiments.register(
349
- 'apca', 'Advanced Perceptual Contrast Algorithm (APCA) replacing previous contrast ratio and AA/AAA guidelines',
362
+ Root.Runtime.ExperimentName.APCA,
363
+ 'Advanced Perceptual Contrast Algorithm (APCA) replacing previous contrast ratio and AA/AAA guidelines',
350
364
  'https://developer.chrome.com/blog/new-in-devtools-89/#apca');
351
365
 
352
366
  // Full Accessibility Tree
353
367
  Root.Runtime.experiments.register(
354
- 'full-accessibility-tree', 'Full accessibility tree view in the Elements panel',
368
+ Root.Runtime.ExperimentName.FULL_ACCESSIBILITY_TREE, 'Full accessibility tree view in the Elements panel',
355
369
  'https://developer.chrome.com/blog/new-in-devtools-90/#accessibility-tree',
356
370
  'https://g.co/devtools/a11y-tree-feedback');
357
371
 
358
372
  // Font Editor
359
373
  Root.Runtime.experiments.register(
360
- 'font-editor', 'New font editor in the Styles tab',
374
+ Root.Runtime.ExperimentName.FONT_EDITOR, 'New font editor in the Styles tab',
361
375
  'https://developer.chrome.com/blog/new-in-devtools-89/#font');
362
376
 
363
377
  // Contrast issues reported via the Issues panel.
364
378
  Root.Runtime.experiments.register(
365
- 'contrast-issues', 'Automatic contrast issue reporting via the Issues panel',
379
+ Root.Runtime.ExperimentName.CONTRAST_ISSUES, 'Automatic contrast issue reporting via the Issues panel',
366
380
  'https://developer.chrome.com/blog/new-in-devtools-90/#low-contrast');
367
381
 
368
382
  // New cookie features.
369
- Root.Runtime.experiments.register('experimental-cookie-features', 'Experimental cookie features');
383
+ Root.Runtime.experiments.register(
384
+ Root.Runtime.ExperimentName.EXPERIMENTAL_COOKIE_FEATURES, 'Experimental cookie features');
370
385
 
371
386
  // Change grouping of sources panel to use Authored/Deployed trees
372
387
  Root.Runtime.experiments.register(
@@ -384,7 +399,8 @@ export class MainImpl {
384
399
 
385
400
  Root.Runtime.experiments.enableExperimentsByDefault([
386
401
  Root.Runtime.ExperimentName.FULL_ACCESSIBILITY_TREE,
387
- ...(Root.Runtime.Runtime.queryParam('isChromeForTesting') ? ['protocol-monitor'] : []),
402
+ Root.Runtime.ExperimentName.USE_SOURCE_MAP_SCOPES,
403
+ ...(Root.Runtime.Runtime.queryParam('isChromeForTesting') ? [Root.Runtime.ExperimentName.PROTOCOL_MONITOR] : []),
388
404
  ]);
389
405
 
390
406
  Root.Runtime.experiments.cleanUpStaleExperiments();
@@ -397,7 +413,7 @@ export class MainImpl {
397
413
  if (Host.InspectorFrontendHost.isUnderTest()) {
398
414
  const testParam = Root.Runtime.Runtime.queryParam('test');
399
415
  if (testParam?.includes('live-line-level-heap-profile.js')) {
400
- Root.Runtime.experiments.enableForTest('live-heap-profile');
416
+ Root.Runtime.experiments.enableForTest(Root.Runtime.ExperimentName.LIVE_HEAP_PROFILE);
401
417
  }
402
418
  }
403
419
 
@@ -667,7 +683,7 @@ export class MainImpl {
667
683
  const runnable = await lateInitializationLoader();
668
684
  return await runnable.run();
669
685
  });
670
- if (Root.Runtime.experiments.isEnabled('live-heap-profile')) {
686
+ if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.LIVE_HEAP_PROFILE)) {
671
687
  const PerfUI = await import('../../ui/legacy/components/perf_ui/perf_ui.js');
672
688
  const setting = 'memory-live-heap-profile';
673
689
  if (Common.Settings.Settings.instance().moduleSetting(setting).get()) {
@@ -942,6 +958,15 @@ export class MainMenuItem implements UI.Toolbar.Provider {
942
958
 
943
959
  contextMenu.defaultSection().appendAction('freestyler.main-menu', undefined, /* optional */ true);
944
960
 
961
+ contextMenu.defaultSection().appendItem(i18nString(UIStrings.getDevToolsMcp), () => {
962
+ UIHelpers.openInNewTab('https://github.com/ChromeDevTools/chrome-devtools-mcp');
963
+ }, {
964
+ additionalElement: UI.UIUtils.maybeCreateNewBadge('get-devtools-mcp'),
965
+ jslogContext: 'get-devtools-mcp',
966
+ });
967
+
968
+ contextMenu.defaultSection().appendSeparator();
969
+
945
970
  if (dockController.dockSide() === UI.DockController.DockState.UNDOCKED) {
946
971
  const mainTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
947
972
  if (mainTarget && mainTarget.type() === SDK.Target.Type.FRAME) {
@@ -730,14 +730,13 @@ export const generatedProperties = [
730
730
  "text-emphasis-color",
731
731
  "text-emphasis-position",
732
732
  "text-emphasis-style",
733
- "text-grow",
733
+ "text-fit",
734
734
  "text-indent",
735
735
  "text-justify",
736
736
  "text-orientation",
737
737
  "text-overflow",
738
738
  "text-rendering",
739
739
  "text-shadow",
740
- "text-shrink",
741
740
  "text-size-adjust",
742
741
  "text-spacing-trim",
743
742
  "text-transform",
@@ -4440,7 +4439,7 @@ export const generatedProperties = [
4440
4439
  "name": "text-emphasis-style"
4441
4440
  },
4442
4441
  {
4443
- "name": "text-grow"
4442
+ "name": "text-fit"
4444
4443
  },
4445
4444
  {
4446
4445
  "inherited": true,
@@ -4489,9 +4488,6 @@ export const generatedProperties = [
4489
4488
  ],
4490
4489
  "name": "text-shadow"
4491
4490
  },
4492
- {
4493
- "name": "text-shrink"
4494
- },
4495
4491
  {
4496
4492
  "inherited": true,
4497
4493
  "keywords": [