chrome-devtools-frontend 1.0.1530564 → 1.0.1532228

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 (59) hide show
  1. package/AUTHORS +2 -0
  2. package/front_end/core/protocol_client/InspectorBackend.ts +15 -6
  3. package/front_end/core/protocol_client/protocol_client.ts +0 -10
  4. package/front_end/core/sdk/NetworkManager.ts +155 -41
  5. package/front_end/core/sdk/SourceMap.ts +6 -1
  6. package/front_end/core/sdk/SourceMapScopesInfo.ts +73 -7
  7. package/front_end/generated/ARIAProperties.js +1301 -174
  8. package/front_end/generated/Deprecation.ts +7 -0
  9. package/front_end/generated/InspectorBackendCommands.js +1 -0
  10. package/front_end/generated/protocol-mapping.d.ts +4 -0
  11. package/front_end/generated/protocol-proxy-api.d.ts +5 -0
  12. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +1 -1
  13. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +1 -1
  14. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatterBounds.snapshot.txt +4 -0
  15. package/front_end/models/bindings/CompilerScriptMapping.ts +16 -14
  16. package/front_end/models/issues_manager/AttributionReportingIssue.ts +4 -3
  17. package/front_end/models/issues_manager/BounceTrackingIssue.ts +4 -3
  18. package/front_end/models/issues_manager/ClientHintIssue.ts +4 -3
  19. package/front_end/models/issues_manager/ContentSecurityPolicyIssue.ts +4 -3
  20. package/front_end/models/issues_manager/CookieDeprecationMetadataIssue.ts +5 -3
  21. package/front_end/models/issues_manager/CookieIssue.ts +4 -4
  22. package/front_end/models/issues_manager/CorsIssue.ts +3 -3
  23. package/front_end/models/issues_manager/CrossOriginEmbedderPolicyIssue.ts +2 -1
  24. package/front_end/models/issues_manager/DeprecationIssue.ts +4 -3
  25. package/front_end/models/issues_manager/ElementAccessibilityIssue.ts +4 -3
  26. package/front_end/models/issues_manager/FederatedAuthRequestIssue.ts +4 -3
  27. package/front_end/models/issues_manager/GenericIssue.ts +3 -3
  28. package/front_end/models/issues_manager/HeavyAdIssue.ts +3 -3
  29. package/front_end/models/issues_manager/IssuesManager.ts +3 -3
  30. package/front_end/models/issues_manager/LowTextContrastIssue.ts +5 -3
  31. package/front_end/models/issues_manager/MixedContentIssue.ts +4 -3
  32. package/front_end/models/issues_manager/PartitioningBlobURLIssue.ts +5 -3
  33. package/front_end/models/issues_manager/PropertyRuleIssue.ts +4 -3
  34. package/front_end/models/issues_manager/QuirksModeIssue.ts +4 -3
  35. package/front_end/models/issues_manager/SRIMessageSignatureIssue.ts +5 -3
  36. package/front_end/models/issues_manager/SharedArrayBufferIssue.ts +5 -3
  37. package/front_end/models/issues_manager/SharedDictionaryIssue.ts +5 -3
  38. package/front_end/models/issues_manager/StylesheetLoadingIssue.ts +5 -3
  39. package/front_end/models/issues_manager/UnencodedDigestIssue.ts +5 -3
  40. package/front_end/models/issues_manager/UserReidentificationIssue.ts +4 -3
  41. package/front_end/models/javascript_metadata/NativeFunctions.js +8 -2
  42. package/front_end/models/trace/insights/ForcedReflow.ts +1 -1
  43. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +17 -4
  44. package/front_end/panels/console/ConsoleInsightTeaser.ts +111 -60
  45. package/front_end/panels/console/ConsoleSidebar.ts +3 -3
  46. package/front_end/panels/network/NetworkLogView.ts +135 -33
  47. package/front_end/panels/network/{BlockedURLsPane.ts → RequestConditionsDrawer.ts} +64 -23
  48. package/front_end/panels/network/network-meta.ts +33 -9
  49. package/front_end/panels/network/network.ts +3 -3
  50. package/front_end/panels/network/{blockedURLsPane.css → requestConditionsDrawer.css} +5 -0
  51. package/front_end/panels/recorder/components/stepView.css +2 -2
  52. package/front_end/panels/sources/SourcesSearchScope.ts +5 -0
  53. package/front_end/panels/sources/sources-meta.ts +1 -0
  54. package/front_end/panels/timeline/components/insights/ForcedReflow.ts +2 -2
  55. package/front_end/third_party/chromium/README.chromium +1 -1
  56. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +31 -5
  57. package/front_end/ui/legacy/components/utils/TargetDetachedDialog.ts +3 -0
  58. package/front_end/ui/visual_logging/KnownContextValues.ts +5 -0
  59. package/package.json +1 -1
package/AUTHORS CHANGED
@@ -65,6 +65,7 @@ Marijn Haverbeke <marijnh@gmail.com>
65
65
  Max 😎 Coplan <mchcopl@gmail.com>
66
66
  Michael Brüning <michael.bruning@qt.io>
67
67
  Michael Rienstra <mrienstra@gmail.com>
68
+ Mostafa Aboalkasim <mostafa.aboalkasim.offical@gmail.com>
68
69
  Muhammad Mahad <mahadtxt@gmail.com>
69
70
  Naoto Ono <onoto1998@gmail.com>
70
71
  Paras Awasthi <awasthiparas6@gmail.com>
@@ -93,6 +94,7 @@ Tony Kostowny <tonykostowny@gmail.com>
93
94
  Toshiaki Tanaka <zokutyou2@gmail.com>
94
95
  Tushar Singh <tusharvickey1999@gmail.com>
95
96
  Varun Varada <varuncvarada@gmail.com>
97
+ Vishwa Kalubowila <vishwa.kalubowila@codimite.com>
96
98
  Vitali Zaidman <vzaidman@gmail.com>
97
99
  Will Hernandez <w.hernandez.code@gmail.com>
98
100
  Yeol Park <peary2@gmail.com>
@@ -2,6 +2,7 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
+ import * as InspectorBackendCommands from '../../generated/InspectorBackendCommands.js';
5
6
  import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';
6
7
  import type * as Protocol from '../../generated/protocol.js';
7
8
  import type * as Platform from '../platform/platform.js';
@@ -78,6 +79,15 @@ export class InspectorBackend {
78
79
  readonly typeMap = new Map<QualifiedName, CommandParameter[]>();
79
80
  readonly enumMap = new Map<QualifiedName, Record<string, string>>();
80
81
 
82
+ constructor() {
83
+ // Create the global here because registering commands will involve putting
84
+ // items onto the global.
85
+ // @ts-expect-error Global namespace instantiation
86
+ globalThis.Protocol ||= {};
87
+
88
+ InspectorBackendCommands.registerCommands(this);
89
+ }
90
+
81
91
  private getOrCreateEventParameterNamesForDomain(domain: ProtocolDomainName): EventParameterNames {
82
92
  let map = this.#eventParameterNamesForDomain.get(domain);
83
93
  if (!map) {
@@ -367,9 +377,8 @@ export class SessionRouter {
367
377
  const sessionId = messageObject.sessionId || '';
368
378
  const session = this.#sessions.get(sessionId);
369
379
  if (!session) {
370
- if (!suppressUnknownMessageErrors) {
371
- InspectorBackend.reportProtocolError('Protocol Error: the message with wrong session id', messageObject);
372
- }
380
+ // In the DevTools MCP case, we may share the transport with puppeteer so we silently
381
+ // ignore unknown sessions.
373
382
  return;
374
383
  }
375
384
 
@@ -492,12 +501,12 @@ export class TargetBase {
492
501
  this.needsNodeJSPatching = needsNodeJSPatching;
493
502
  this.sessionId = sessionId;
494
503
 
495
- if ((!parentTarget && connection) || (!parentTarget && sessionId) || (connection && sessionId)) {
496
- throw new Error('Either connection or sessionId (but not both) must be supplied for a child target');
504
+ if (parentTarget && !sessionId) {
505
+ throw new Error('Specifying a parent target requires a session ID');
497
506
  }
498
507
 
499
508
  let router: SessionRouter;
500
- if (sessionId && parentTarget && parentTarget.#router) {
509
+ if (parentTarget && parentTarget.#router) {
501
510
  router = parentTarget.#router;
502
511
  } else if (connection) {
503
512
  router = new SessionRouter(connection);
@@ -2,8 +2,6 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- import * as InspectorBackendCommands from '../../generated/InspectorBackendCommands.js';
6
-
7
5
  import * as InspectorBackend from './InspectorBackend.js';
8
6
  import * as NodeURL from './NodeURL.js';
9
7
 
@@ -11,11 +9,3 @@ export {
11
9
  InspectorBackend,
12
10
  NodeURL,
13
11
  };
14
-
15
- // Create the global here because registering commands will involve putting
16
- // items onto the global.
17
- // @ts-expect-error Global namespace instantiation
18
- globalThis.Protocol = globalThis.Protocol || {};
19
-
20
- // FIXME: This instance of InspectorBackend should not be a side effect of importing this module.
21
- InspectorBackendCommands.registerCommands(InspectorBackend.inspectorBackend);
@@ -531,7 +531,7 @@ export const Fast4GConditions: Conditions = {
531
531
  targetLatency: fast4GTargetLatency,
532
532
  };
533
533
 
534
- const MAX_EAGER_POST_REQUEST_BODY_LENGTH = 64 * 1024; // bytes
534
+ const MAX_EAGER_POST_REQUEST_BODY_LENGTH = 64 * 1024; // bytes
535
535
  const MAX_RESPONSE_BODY_TOTAL_BUFFER_LENGTH = 250 * 1024 * 1024; // bytes
536
536
 
537
537
  export class FetchDispatcher implements ProtocolProxyApi.FetchDispatcher {
@@ -1566,11 +1566,12 @@ export class NetworkDispatcher implements ProtocolProxyApi.NetworkDispatcher {
1566
1566
  }
1567
1567
  }
1568
1568
 
1569
- type RequestConditionsSetting = {
1569
+ export type RequestConditionsSetting = {
1570
1570
  url: string,
1571
1571
  enabled: boolean,
1572
1572
  }|{
1573
1573
  urlPattern: URLPatternConstructorString,
1574
+ conditions: ThrottlingConditionKey,
1574
1575
  enabled: boolean,
1575
1576
  };
1576
1577
 
@@ -1648,21 +1649,40 @@ export class RequestURLPattern {
1648
1649
  export class RequestCondition extends Common.ObjectWrapper.ObjectWrapper<RequestCondition.EventTypes> {
1649
1650
  #pattern: RequestURLPattern|{wildcardURL: string, upgradedPattern?: RequestURLPattern};
1650
1651
  #enabled: boolean;
1652
+ #conditions: ThrottlingConditions;
1651
1653
 
1652
- constructor(setting: RequestConditionsSetting) {
1653
- super();
1654
+ static createFromSetting(setting: RequestConditionsSetting): RequestCondition {
1654
1655
  if ('urlPattern' in setting) {
1655
- this.#pattern = RequestURLPattern.create(setting.urlPattern) ?? {
1656
+ const pattern = RequestURLPattern.create(setting.urlPattern) ?? {
1656
1657
  wildcardURL: setting.urlPattern,
1657
1658
  upgradedPattern: RequestURLPattern.upgradeFromWildcard(setting.urlPattern) ?? undefined,
1658
1659
  };
1659
- } else {
1660
- this.#pattern = {
1661
- wildcardURL: setting.url,
1662
- upgradedPattern: RequestURLPattern.upgradeFromWildcard(setting.url) ?? undefined
1663
- };
1660
+
1661
+ const conditions = getPredefinedOrBlockingCondition(setting.conditions) ??
1662
+ customUserNetworkConditionsSetting().get().find(condition => condition.key === setting.conditions) ??
1663
+ NoThrottlingConditions;
1664
+
1665
+ return new this(pattern, setting.enabled, conditions);
1664
1666
  }
1665
- this.#enabled = setting.enabled;
1667
+
1668
+ const pattern = {
1669
+ wildcardURL: setting.url,
1670
+ upgradedPattern: RequestURLPattern.upgradeFromWildcard(setting.url) ?? undefined
1671
+ };
1672
+ return new this(pattern, setting.enabled, BlockingConditions);
1673
+ }
1674
+
1675
+ static create(pattern: RequestURLPattern, conditions: ThrottlingConditions): RequestCondition {
1676
+ return new this(pattern, /* enabled=*/ true, conditions);
1677
+ }
1678
+
1679
+ private constructor(
1680
+ pattern: RequestURLPattern|{wildcardURL: string, upgradedPattern?: RequestURLPattern}, enabled: boolean,
1681
+ conditions: ThrottlingConditions) {
1682
+ super();
1683
+ this.#pattern = pattern;
1684
+ this.#enabled = enabled;
1685
+ this.#conditions = conditions;
1666
1686
  }
1667
1687
 
1668
1688
  get constructorString(): string|undefined {
@@ -1705,10 +1725,24 @@ export class RequestCondition extends Common.ObjectWrapper.ObjectWrapper<Request
1705
1725
  this.dispatchEventToListeners(RequestCondition.Events.REQUEST_CONDITION_CHANGED);
1706
1726
  }
1707
1727
 
1728
+ get conditions(): ThrottlingConditions {
1729
+ return this.#conditions;
1730
+ }
1731
+
1732
+ set conditions(conditions: ThrottlingConditions) {
1733
+ this.#conditions = conditions;
1734
+ this.dispatchEventToListeners(RequestCondition.Events.REQUEST_CONDITION_CHANGED);
1735
+ }
1736
+
1708
1737
  toSetting(): RequestConditionsSetting {
1709
1738
  const enabled = this.enabled;
1710
- return this.#pattern instanceof RequestURLPattern ? {enabled, urlPattern: this.#pattern.constructorString} :
1711
- {enabled, url: this.#pattern.wildcardURL};
1739
+ if (this.#pattern instanceof RequestURLPattern) {
1740
+ return {enabled, urlPattern: this.#pattern.constructorString, conditions: this.#conditions.key};
1741
+ }
1742
+ if (this.#conditions !== BlockingConditions && this.#pattern.upgradedPattern) {
1743
+ return {enabled, urlPattern: this.#pattern.upgradedPattern.constructorString, conditions: this.#conditions.key};
1744
+ }
1745
+ return {enabled, url: this.#pattern.wildcardURL};
1712
1746
  }
1713
1747
 
1714
1748
  get originalOrUpgradedURLPattern(): URLPattern|undefined {
@@ -1729,20 +1763,41 @@ export namespace RequestCondition {
1729
1763
  export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper<RequestConditions.EventTypes> {
1730
1764
  readonly #setting =
1731
1765
  Common.Settings.Settings.instance().createSetting<RequestConditionsSetting[]>('network-blocked-patterns', []);
1732
- readonly #conditions: RequestCondition[];
1766
+ readonly #conditionsEnabledSetting =
1767
+ Common.Settings.Settings.instance().moduleSetting<boolean>('request-blocking-enabled');
1768
+ readonly #conditions: RequestCondition[] = [];
1733
1769
 
1734
1770
  constructor() {
1735
1771
  super();
1736
- this.#conditions = this.#setting.get().map(condition => new RequestCondition(condition));
1772
+ for (const condition of this.#setting.get()) {
1773
+ try {
1774
+ this.#conditions.push(RequestCondition.createFromSetting(condition));
1775
+ } catch (e) {
1776
+ console.error('Error loading throttling settings: ', e);
1777
+ }
1778
+ }
1737
1779
  for (const condition of this.#conditions) {
1738
1780
  condition.addEventListener(RequestCondition.Events.REQUEST_CONDITION_CHANGED, this.#conditionsChanged, this);
1739
1781
  }
1782
+ this.#conditionsEnabledSetting.addChangeListener(
1783
+ () => this.dispatchEventToListeners(RequestConditions.Events.REQUEST_CONDITIONS_CHANGED));
1740
1784
  }
1741
1785
 
1742
1786
  get count(): number {
1743
1787
  return this.#conditions.length;
1744
1788
  }
1745
1789
 
1790
+ get conditionsEnabled(): boolean {
1791
+ return this.#conditionsEnabledSetting.get();
1792
+ }
1793
+
1794
+ set conditionsEnabled(enabled: boolean) {
1795
+ if (this.#conditionsEnabledSetting.get() === enabled) {
1796
+ return;
1797
+ }
1798
+ this.#conditionsEnabledSetting.set(enabled);
1799
+ }
1800
+
1746
1801
  findCondition(pattern: string): RequestCondition|undefined {
1747
1802
  if (Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled) {
1748
1803
  return this.#conditions.find(condition => condition.constructorString === pattern);
@@ -1756,6 +1811,9 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper<Reques
1756
1811
 
1757
1812
  add(...conditions: RequestCondition[]): void {
1758
1813
  this.#conditions.push(...conditions);
1814
+ for (const condition of conditions) {
1815
+ condition.addEventListener(RequestCondition.Events.REQUEST_CONDITION_CHANGED, this.#conditionsChanged, this);
1816
+ }
1759
1817
  this.#conditionsChanged();
1760
1818
  }
1761
1819
 
@@ -1765,7 +1823,7 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper<Reques
1765
1823
  return;
1766
1824
  }
1767
1825
  condition.removeEventListener(RequestCondition.Events.REQUEST_CONDITION_CHANGED, this.#conditionsChanged, this);
1768
- this.#conditions.splice(index);
1826
+ this.#conditions.splice(index, 1);
1769
1827
  this.#conditionsChanged();
1770
1828
  }
1771
1829
 
@@ -1786,18 +1844,69 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper<Reques
1786
1844
  return this.#conditions.values();
1787
1845
  }
1788
1846
 
1789
- applyConditions(...agents: ProtocolProxyApi.NetworkApi[]): boolean {
1847
+ applyConditions(offline: boolean, globalConditions: Conditions|null, ...agents: ProtocolProxyApi.NetworkApi[]):
1848
+ boolean {
1849
+ function isNonBlockingCondition(condition: ThrottlingConditions): condition is Conditions {
1850
+ return !('block' in condition);
1851
+ }
1790
1852
  if (Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled) {
1791
- const urlPatterns = this.#conditions.filter(condition => condition.enabled && condition.constructorString)
1792
- .map(condition => ({urlPattern: condition.constructorString as string, block: true}));
1853
+ const urlPatterns: Protocol.Network.BlockPattern[] = [];
1854
+ const matchedNetworkConditions: Protocol.Network.NetworkConditions[] = [];
1855
+ if (this.conditionsEnabled) {
1856
+ for (const condition of this.#conditions) {
1857
+ const urlPattern = condition.constructorString;
1858
+ const conditions = condition.conditions;
1859
+ if (!condition.enabled || !urlPattern || conditions === NoThrottlingConditions) {
1860
+ continue;
1861
+ }
1862
+ const block = !isNonBlockingCondition(conditions);
1863
+ urlPatterns.push({urlPattern, block});
1864
+ if (!block) {
1865
+ matchedNetworkConditions.push({
1866
+ urlPattern,
1867
+ latency: conditions.latency,
1868
+ downloadThroughput: conditions.download < 0 ? 0 : conditions.download,
1869
+ uploadThroughput: conditions.upload < 0 ? 0 : conditions.upload,
1870
+ packetLoss: (conditions.packetLoss ?? 0) < 0 ? 0 : conditions.packetLoss,
1871
+ packetQueueLength: conditions.packetQueueLength,
1872
+ packetReordering: conditions.packetReordering,
1873
+ connectionType: NetworkManager.connectionType(conditions),
1874
+ });
1875
+ }
1876
+ }
1877
+
1878
+ if (globalConditions) {
1879
+ matchedNetworkConditions.push({
1880
+ urlPattern: '',
1881
+ latency: globalConditions.latency,
1882
+ downloadThroughput: globalConditions.download < 0 ? 0 : globalConditions.download,
1883
+ uploadThroughput: globalConditions.upload < 0 ? 0 : globalConditions.upload,
1884
+ packetLoss: (globalConditions.packetLoss ?? 0) < 0 ? 0 : globalConditions.packetLoss,
1885
+ packetQueueLength: globalConditions.packetQueueLength,
1886
+ packetReordering: globalConditions.packetReordering,
1887
+ connectionType: NetworkManager.connectionType(globalConditions),
1888
+ });
1889
+ }
1890
+ }
1793
1891
 
1794
1892
  for (const agent of agents) {
1795
1893
  void agent.invoke_setBlockedURLs({urlPatterns});
1894
+ void agent.invoke_emulateNetworkConditionsByRule({offline, matchedNetworkConditions});
1895
+ void agent.invoke_overrideNetworkState({
1896
+ offline,
1897
+ latency: globalConditions?.latency ?? 0,
1898
+ downloadThroughput: !globalConditions || globalConditions.download < 0 ? 0 : globalConditions.download,
1899
+ uploadThroughput: !globalConditions || globalConditions.upload < 0 ? 0 : globalConditions.upload,
1900
+ });
1796
1901
  }
1797
1902
  return urlPatterns.length > 0;
1798
1903
  }
1799
- const urls = this.#conditions.filter(condition => condition.enabled && condition.wildcardURL)
1800
- .map(condition => condition.wildcardURL as string);
1904
+
1905
+ const urls = this.conditionsEnabled ?
1906
+ this.#conditions.filter(condition => condition.enabled && condition.wildcardURL)
1907
+ .map(condition => condition.wildcardURL as string) :
1908
+ [];
1909
+
1801
1910
  for (const agent of agents) {
1802
1911
  void agent.invoke_setBlockedURLs({urls});
1803
1912
  }
@@ -1826,8 +1935,6 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
1826
1935
  readonly inflightMainResourceRequests = new Map<string, NetworkRequest>();
1827
1936
  #networkConditions: Conditions = NoThrottlingConditions;
1828
1937
  #updatingInterceptionPatternsPromise: Promise<void>|null = null;
1829
- readonly #blockingEnabledSetting =
1830
- Common.Settings.Settings.instance().moduleSetting<boolean>('request-blocking-enabled');
1831
1938
  readonly #requestConditions = new RequestConditions();
1832
1939
  readonly #urlsForRequestInterceptor:
1833
1940
  Platform.MapUtilities.Multimap<(arg0: InterceptedRequest) => Promise<void>, InterceptionPattern> =
@@ -1844,7 +1951,6 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
1844
1951
  this.updateBlockedPatterns();
1845
1952
  this.dispatchEventToListeners(MultitargetNetworkManager.Events.BLOCKED_PATTERNS_CHANGED);
1846
1953
  };
1847
- this.#blockingEnabledSetting.addChangeListener(blockedPatternChanged);
1848
1954
  this.#requestConditions.addEventListener(
1849
1955
  RequestConditions.Events.REQUEST_CONDITIONS_CHANGED, blockedPatternChanged);
1850
1956
  this.updateBlockedPatterns();
@@ -1914,7 +2020,8 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
1914
2020
  void networkAgent.invoke_setUserAgentOverride(
1915
2021
  {userAgent: this.currentUserAgent(), userAgentMetadata: this.#userAgentMetadataOverride || undefined});
1916
2022
  }
1917
- this.#requestConditions.applyConditions(networkAgent);
2023
+ this.#requestConditions.applyConditions(
2024
+ this.isOffline(), this.isThrottling() ? this.#networkConditions : null, networkAgent);
1918
2025
  if (this.isIntercepting()) {
1919
2026
  void fetchAgent.invoke_enable({patterns: this.#urlsForRequestInterceptor.valuesArray()});
1920
2027
  }
@@ -1925,7 +2032,7 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
1925
2032
  }
1926
2033
  this.#networkAgents.add(networkAgent);
1927
2034
  this.#fetchAgents.add(fetchAgent);
1928
- if (this.isThrottling()) {
2035
+ if (this.isThrottling() && !Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled) {
1929
2036
  this.updateNetworkConditions(networkAgent);
1930
2037
  }
1931
2038
  }
@@ -1953,8 +2060,13 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
1953
2060
 
1954
2061
  setNetworkConditions(conditions: Conditions): void {
1955
2062
  this.#networkConditions = conditions;
1956
- for (const agent of this.#networkAgents) {
1957
- this.updateNetworkConditions(agent);
2063
+ if (Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled) {
2064
+ this.#requestConditions.applyConditions(
2065
+ this.isOffline(), this.isThrottling() ? this.#networkConditions : null, ...this.#networkAgents);
2066
+ } else {
2067
+ for (const agent of this.#networkAgents) {
2068
+ this.updateNetworkConditions(agent);
2069
+ }
1958
2070
  }
1959
2071
  this.dispatchEventToListeners(MultitargetNetworkManager.Events.CONDITIONS_CHANGED);
1960
2072
  }
@@ -2058,12 +2170,16 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
2058
2170
  return this.#requestConditions;
2059
2171
  }
2060
2172
 
2061
- blockingEnabled(): boolean {
2062
- return this.#blockingEnabledSetting.get();
2173
+ isBlocking(): boolean {
2174
+ return this.#isBlocking && this.requestConditions.conditionsEnabled;
2063
2175
  }
2064
2176
 
2065
- isBlocking(): boolean {
2066
- return this.#isBlocking && this.blockingEnabled();
2177
+ /**
2178
+ * @deprecated Kept for layout tests
2179
+ * TODO(pfaffe) remove
2180
+ */
2181
+ private setBlockingEnabled(enabled: boolean): void {
2182
+ this.requestConditions.conditionsEnabled = enabled;
2067
2183
  }
2068
2184
 
2069
2185
  /**
@@ -2072,18 +2188,12 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
2072
2188
  */
2073
2189
  private setBlockedPatterns(patterns: Array<{url: string, enabled: boolean}>): void {
2074
2190
  this.requestConditions.clear();
2075
- this.requestConditions.add(...patterns.map(pattern => new RequestCondition(pattern)));
2076
- }
2077
-
2078
- setBlockingEnabled(enabled: boolean): void {
2079
- if (this.#blockingEnabledSetting.get() === enabled) {
2080
- return;
2081
- }
2082
- this.#blockingEnabledSetting.set(enabled);
2191
+ this.requestConditions.add(...patterns.map(pattern => RequestCondition.createFromSetting(pattern)));
2083
2192
  }
2084
2193
 
2085
2194
  private updateBlockedPatterns(): void {
2086
- this.#isBlocking = this.#requestConditions.applyConditions(...this.#networkAgents);
2195
+ this.#isBlocking = this.#requestConditions.applyConditions(
2196
+ this.isOffline(), this.isThrottling() ? this.#networkConditions : null, ...this.#networkAgents);
2087
2197
  }
2088
2198
 
2089
2199
  isIntercepting(): boolean {
@@ -2544,6 +2654,10 @@ export function getPredefinedCondition(key: ThrottlingConditionKey): Conditions|
2544
2654
  return THROTTLING_CONDITIONS_LOOKUP.get(key) ?? null;
2545
2655
  }
2546
2656
 
2657
+ export function getPredefinedOrBlockingCondition(key: ThrottlingConditionKey): ThrottlingConditions|null {
2658
+ return key === PredefinedThrottlingConditionKey.BLOCKING ? BlockingConditions : getPredefinedCondition(key);
2659
+ }
2660
+
2547
2661
  export type ThrottlingConditions = Conditions|{
2548
2662
  readonly key: ThrottlingConditionKey,
2549
2663
  block: true,
@@ -12,7 +12,7 @@ import type {CallFrame, ScopeChainEntry} from './DebuggerModel.js';
12
12
  import {scopeTreeForScript} from './ScopeTreeCache.js';
13
13
  import type {Script} from './Script.js';
14
14
  import {buildOriginalScopes, decodePastaRanges, type NamedFunctionRange} from './SourceMapFunctionRanges.js';
15
- import {SourceMapScopesInfo} from './SourceMapScopesInfo.js';
15
+ import {SourceMapScopesInfo, type TranslatedFrame} from './SourceMapScopesInfo.js';
16
16
 
17
17
  /**
18
18
  * Type of the base source map JSON object, which contains the sources and the mappings at the very least, plus
@@ -789,6 +789,11 @@ export class SourceMap {
789
789
  this.#ensureSourceMapProcessed();
790
790
  return this.#scopesInfo?.hasInlinedFrames(generatedLine, generatedColumn) ?? false;
791
791
  }
792
+
793
+ translateCallSite(generatedLine: number, generatedColumn: number): TranslatedFrame[] {
794
+ this.#ensureSourceMapProcessed();
795
+ return this.#scopesInfo?.translateCallSite(generatedLine, generatedColumn) ?? [];
796
+ }
792
797
  }
793
798
 
794
799
  const VLQ_BASE_SHIFT = 5;
@@ -113,6 +113,10 @@ export class SourceMapScopesInfo {
113
113
  */
114
114
  isOutlinedFrame(generatedLine: number, generatedColumn: number): boolean {
115
115
  const rangeChain = this.#findGeneratedRangeChain(generatedLine, generatedColumn);
116
+ return this.#isOutlinedFrame(rangeChain);
117
+ }
118
+
119
+ #isOutlinedFrame(rangeChain: ScopesCodec.GeneratedRange[]): boolean {
116
120
  for (let i = rangeChain.length - 1; i >= 0; --i) {
117
121
  if (rangeChain[i].isStackFrame) {
118
122
  return rangeChain[i].isHidden;
@@ -372,13 +376,7 @@ export class SourceMapScopesInfo {
372
376
  .at(-1);
373
377
  }
374
378
 
375
- // Walk the original scope chain outwards until we find a function.
376
- for (let originalScope = originalInnerMostScope; originalScope; originalScope = originalScope.parent) {
377
- if (originalScope.isStackFrame) {
378
- return originalScope.name ?? '';
379
- }
380
- }
381
- return null;
379
+ return this.#findFunctionNameInOriginalScopeChain(originalInnerMostScope) ?? null;
382
380
  }
383
381
 
384
382
  /**
@@ -404,6 +402,74 @@ export class SourceMapScopesInfo {
404
402
 
405
403
  return result;
406
404
  }
405
+
406
+ #findFunctionNameInOriginalScopeChain(innerOriginalScope: ScopesCodec.OriginalScope|undefined): string|null {
407
+ for (let originalScope = innerOriginalScope; originalScope; originalScope = originalScope.parent) {
408
+ if (originalScope.isStackFrame) {
409
+ return originalScope.name ?? '';
410
+ }
411
+ }
412
+ return null;
413
+ }
414
+
415
+ /**
416
+ * Returns one or more original stack frames for this single "raw frame" or call-site.
417
+ *
418
+ * @returns An empty array if no mapping at the call-site was found, or the resulting frames
419
+ * in top-to-bottom order in case of inlining.
420
+ * @throws If this range is marked "hidden". Outlining needs to be handled externally as
421
+ * outlined function segments in stack traces can span across bundles.
422
+ */
423
+ translateCallSite(generatedLine: number, generatedColumn: number): TranslatedFrame[] {
424
+ const rangeChain = this.#findGeneratedRangeChain(generatedLine, generatedColumn);
425
+ if (this.#isOutlinedFrame(rangeChain)) {
426
+ throw new Error('SourceMapScopesInfo is unable to translate an outlined function by itself');
427
+ }
428
+
429
+ const mapping = this.#sourceMap.findEntry(generatedLine, generatedColumn);
430
+ if (mapping?.sourceIndex === undefined) {
431
+ return [];
432
+ }
433
+
434
+ // The top-most frame is translated the same even if we have inlined functions.
435
+ const result: TranslatedFrame[] = [{
436
+ line: mapping.sourceLineNumber,
437
+ column: mapping.sourceColumnNumber,
438
+ name: this.findOriginalFunctionName({line: generatedLine, column: generatedColumn}) ?? undefined,
439
+ url: mapping.sourceURL,
440
+ }];
441
+
442
+ // Walk the range chain inside out until we find a generated function and for each inlined function add a frame.
443
+ for (let i = rangeChain.length - 1; i >= 0 && !rangeChain[i].isStackFrame; --i) {
444
+ const range = rangeChain[i];
445
+ if (!range.callSite) {
446
+ continue;
447
+ }
448
+
449
+ const originalScopeChain = this.#findOriginalScopeChain(range.callSite);
450
+ result.push({
451
+ line: range.callSite.line,
452
+ column: range.callSite.column,
453
+ name: this.#findFunctionNameInOriginalScopeChain(originalScopeChain.at(-1)) ?? undefined,
454
+ url: this.#sourceMap.sourceURLForSourceIndex(range.callSite.sourceIndex),
455
+ });
456
+ }
457
+
458
+ return result;
459
+ }
460
+ }
461
+
462
+ /**
463
+ * Represents a stack frame in original terms. It closely aligns with StackTrace.StackTrace.Frame,
464
+ * but since we can't import that type here we mirror it here somewhat.
465
+ *
466
+ * Equivalent to Pick<StackTrace.StackTrace.Frame, 'line'|'column'|'name'|'url'>.
467
+ */
468
+ export interface TranslatedFrame {
469
+ line: number;
470
+ column: number;
471
+ name?: string;
472
+ url?: Platform.DevToolsPath.UrlString;
407
473
  }
408
474
 
409
475
  /**