chrome-devtools-mcp 0.8.1 → 0.9.0

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 (87) hide show
  1. package/README.md +58 -3
  2. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Gzip.js +8 -6
  3. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Settings.js +1 -1
  4. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Worker.js +10 -2
  5. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/UserMetrics.js +2 -1
  6. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/ArrayUtilities.js +1 -1
  7. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/ConnectionTransport.js +12 -0
  8. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/InspectorBackend.js +15 -27
  9. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/protocol_client.js +2 -8
  10. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMatchedStyles.js +42 -7
  11. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSRule.js +34 -6
  12. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ChildTargetManager.js +3 -0
  13. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Connections.js +2 -2
  14. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DOMModel.js +3 -0
  15. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DebuggerModel.js +2 -1
  16. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkManager.js +336 -40
  17. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/PreloadingModel.js +56 -13
  18. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RehydratingConnection.js +32 -7
  19. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ResourceTreeModel.js +1 -1
  20. package/build/node_modules/chrome-devtools-frontend/front_end/{models/source_map_scopes → core/sdk}/ScopeTreeCache.js +9 -5
  21. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMap.js +48 -11
  22. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapManager.js +8 -2
  23. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapScopesInfo.js +131 -8
  24. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/TargetManager.js +0 -21
  25. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/TraceObject.js +9 -6
  26. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/sdk.js +2 -1
  27. package/build/node_modules/chrome-devtools-frontend/front_end/generated/ARIAProperties.js +1301 -174
  28. package/build/node_modules/chrome-devtools-frontend/front_end/generated/Deprecation.js +7 -0
  29. package/build/node_modules/chrome-devtools-frontend/front_end/generated/InspectorBackendCommands.js +8 -6
  30. package/build/node_modules/chrome-devtools-frontend/front_end/generated/SupportedCSSProperties.js +16 -19
  31. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.js +50 -34
  32. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AICallTree.js +2 -3
  33. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CompilerScriptMapping.js +45 -2
  34. package/build/node_modules/chrome-devtools-frontend/front_end/models/formatter/FormatterWorkerPool.js +14 -0
  35. package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/NamesResolver.js +5 -11
  36. package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/source_map_scopes.js +1 -2
  37. package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/Trie.js +8 -0
  38. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/ModelImpl.js +6 -3
  39. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/extras/TraceTree.js +10 -3
  40. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/MetaHandler.js +4 -1
  41. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/UserTimingsHandler.js +1 -1
  42. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/CLSCulprits.js +2 -1
  43. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/Cache.js +2 -1
  44. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DOMSize.js +2 -1
  45. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DocumentLatency.js +2 -1
  46. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DuplicatedJavaScript.js +2 -1
  47. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/FontDisplay.js +2 -1
  48. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ForcedReflow.js +3 -2
  49. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/INPBreakdown.js +2 -1
  50. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ImageDelivery.js +2 -1
  51. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LCPBreakdown.js +2 -1
  52. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LCPDiscovery.js +2 -1
  53. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LegacyJavaScript.js +2 -1
  54. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ModernHTTP.js +2 -1
  55. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/NetworkDependencyTree.js +2 -1
  56. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/RenderBlocking.js +2 -1
  57. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/SlowCSSSelector.js +2 -1
  58. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ThirdParties.js +2 -1
  59. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/Viewport.js +2 -1
  60. package/build/src/DevToolsConnectionAdapter.js +32 -0
  61. package/build/src/McpContext.js +70 -31
  62. package/build/src/McpResponse.js +145 -44
  63. package/build/src/PageCollector.js +110 -26
  64. package/build/src/WaitForHelper.js +5 -0
  65. package/build/src/browser.js +16 -4
  66. package/build/src/cli.js +82 -6
  67. package/build/src/formatters/consoleFormatter.js +29 -62
  68. package/build/src/formatters/networkFormatter.js +5 -6
  69. package/build/src/formatters/snapshotFormatter.js +10 -5
  70. package/build/src/logger.js +1 -1
  71. package/build/src/main.js +18 -5
  72. package/build/src/polyfill.js +2 -2
  73. package/build/src/third_party/THIRD_PARTY_NOTICES +1393 -0
  74. package/build/src/third_party/index.js +76159 -0
  75. package/build/src/tools/ToolDefinition.js +2 -2
  76. package/build/src/tools/categories.js +17 -9
  77. package/build/src/tools/console.js +71 -6
  78. package/build/src/tools/emulation.js +6 -7
  79. package/build/src/tools/input.js +21 -21
  80. package/build/src/tools/network.js +18 -10
  81. package/build/src/tools/pages.js +19 -19
  82. package/build/src/tools/performance.js +8 -8
  83. package/build/src/tools/screenshot.js +8 -8
  84. package/build/src/tools/script.js +29 -15
  85. package/build/src/tools/snapshot.js +15 -20
  86. package/build/src/utils/types.js +6 -0
  87. package/package.json +16 -13
@@ -216,6 +216,10 @@ export const UIStrings = {
216
216
  * @description A deprecation warning shown in the DevTools Issues tab. The placeholder is always the noun 'SharedArrayBuffer' which refers to a JavaScript construct. 'Extensions' refers to Chrome extensions. The warning is shown when Chrome Extensions attempt to use 'SharedArrayBuffer's under insecure circumstances.
217
217
  */
218
218
  V8SharedArrayBufferConstructedInExtensionWithoutIsolation: "Extensions should opt into cross-origin isolation to continue using `SharedArrayBuffer`. See https://developer.chrome.com/docs/extensions/mv3/cross-origin-isolation/.",
219
+ /**
220
+ * @description This warning occurs when the deprecated `BluetoothRemoteGATTCharacteristic.writeValue()` method is used. Developers should use `writeValueWithResponse()` or `writeValueWithoutResponse()` instead.
221
+ */
222
+ WebBluetoothRemoteCharacteristicWriteValue: "`BluetoothRemoteGATTCharacteristic.writeValue()` is deprecated. Use `writeValueWithResponse()` or `writeValueWithoutResponse()` instead.",
219
223
  /**
220
224
  * @description Warning displayed to developers that they are using `XMLHttpRequest` API in a way that they expect an unsupported character encoding `UTF-16` could be used in the server reply.
221
225
  */
@@ -333,6 +337,9 @@ export const DEPRECATIONS_METADATA = {
333
337
  "V8SharedArrayBufferConstructedInExtensionWithoutIsolation": {
334
338
  "milestone": 96
335
339
  },
340
+ "WebBluetoothRemoteCharacteristicWriteValue": {
341
+ "chromeStatusFeature": 5088568590598144
342
+ },
336
343
  "XHRJSONEncodingDetection": {
337
344
  "milestone": 93
338
345
  }
@@ -204,7 +204,7 @@ export function registerCommands(inspectorBackend) {
204
204
  inspectorBackend.registerEvent("Browser.downloadWillBegin", ["frameId", "guid", "url", "suggestedFilename"]);
205
205
  inspectorBackend.registerEnum("Browser.DownloadProgressEventState", { InProgress: "inProgress", Completed: "completed", Canceled: "canceled" });
206
206
  inspectorBackend.registerEvent("Browser.downloadProgress", ["guid", "totalBytes", "receivedBytes", "state", "filePath"]);
207
- inspectorBackend.registerCommand("Browser.setPermission", [{ "name": "permission", "type": "object", "optional": false, "description": "Descriptor of permission to override.", "typeRef": "Browser.PermissionDescriptor" }, { "name": "setting", "type": "string", "optional": false, "description": "Setting of the permission.", "typeRef": "Browser.PermissionSetting" }, { "name": "origin", "type": "string", "optional": true, "description": "Requesting origin the permission applies to, all origins if not specified.", "typeRef": null }, { "name": "embeddingOrigin", "type": "string", "optional": true, "description": "Embedding origin the permission applies to. It is ignored unless the requesting origin is present and valid. If the requesting origin is provided but the embedding origin isn't, the requesting origin is used as the embedding origin.", "typeRef": null }, { "name": "browserContextId", "type": "string", "optional": true, "description": "Context to override. When omitted, default browser context is used.", "typeRef": "Browser.BrowserContextID" }], [], "Set permission settings for given requesting and embedding origins.");
207
+ inspectorBackend.registerCommand("Browser.setPermission", [{ "name": "permission", "type": "object", "optional": false, "description": "Descriptor of permission to override.", "typeRef": "Browser.PermissionDescriptor" }, { "name": "setting", "type": "string", "optional": false, "description": "Setting of the permission.", "typeRef": "Browser.PermissionSetting" }, { "name": "origin", "type": "string", "optional": true, "description": "Embedding origin the permission applies to, all origins if not specified.", "typeRef": null }, { "name": "embeddedOrigin", "type": "string", "optional": true, "description": "Embedded origin the permission applies to. It is ignored unless the embedding origin is present and valid. If the embedding origin is provided but the embedded origin isn't, the embedding origin is used as the embedded origin.", "typeRef": null }, { "name": "browserContextId", "type": "string", "optional": true, "description": "Context to override. When omitted, default browser context is used.", "typeRef": "Browser.BrowserContextID" }], [], "Set permission settings for given embedding and embedded origins.");
208
208
  inspectorBackend.registerCommand("Browser.grantPermissions", [{ "name": "permissions", "type": "array", "optional": false, "description": "", "typeRef": "Browser.PermissionType" }, { "name": "origin", "type": "string", "optional": true, "description": "Origin the permission applies to, all origins if not specified.", "typeRef": null }, { "name": "browserContextId", "type": "string", "optional": true, "description": "BrowserContext to override permissions. When omitted, default browser context is used.", "typeRef": "Browser.BrowserContextID" }], [], "Grant specific permissions to the given origin and reject all others. Deprecated. Use setPermission instead.");
209
209
  inspectorBackend.registerCommand("Browser.resetPermissions", [{ "name": "browserContextId", "type": "string", "optional": true, "description": "BrowserContext to reset permissions. When omitted, default browser context is used.", "typeRef": "Browser.BrowserContextID" }], [], "Reset all permission management for all origins.");
210
210
  inspectorBackend.registerEnum("Browser.SetDownloadBehaviorRequestBehavior", { Deny: "deny", Allow: "allow", AllowAndName: "allowAndName", Default: "default" });
@@ -666,6 +666,7 @@ export function registerCommands(inspectorBackend) {
666
666
  inspectorBackend.registerEvent("Inspector.detached", ["reason"]);
667
667
  inspectorBackend.registerEvent("Inspector.targetCrashed", []);
668
668
  inspectorBackend.registerEvent("Inspector.targetReloadedAfterCrash", []);
669
+ inspectorBackend.registerEvent("Inspector.workerScriptLoaded", []);
669
670
  inspectorBackend.registerCommand("Inspector.disable", [], [], "Disables inspector domain notifications.");
670
671
  inspectorBackend.registerCommand("Inspector.enable", [], [], "Enables inspector domain notifications.");
671
672
  // LayerTree.
@@ -749,7 +750,7 @@ export function registerCommands(inspectorBackend) {
749
750
  inspectorBackend.registerEnum("Network.TrustTokenOperationType", { Issuance: "Issuance", Redemption: "Redemption", Signing: "Signing" });
750
751
  inspectorBackend.registerEnum("Network.AlternateProtocolUsage", { AlternativeJobWonWithoutRace: "alternativeJobWonWithoutRace", AlternativeJobWonRace: "alternativeJobWonRace", MainJobWonRace: "mainJobWonRace", MappingMissing: "mappingMissing", Broken: "broken", DnsAlpnH3JobWonWithoutRace: "dnsAlpnH3JobWonWithoutRace", DnsAlpnH3JobWonRace: "dnsAlpnH3JobWonRace", UnspecifiedReason: "unspecifiedReason" });
751
752
  inspectorBackend.registerEnum("Network.ServiceWorkerRouterSource", { Network: "network", Cache: "cache", FetchEvent: "fetch-event", RaceNetworkAndFetchHandler: "race-network-and-fetch-handler", RaceNetworkAndCache: "race-network-and-cache" });
752
- inspectorBackend.registerEnum("Network.InitiatorType", { Parser: "parser", Script: "script", Preload: "preload", SignedExchange: "SignedExchange", Preflight: "preflight", Other: "other" });
753
+ inspectorBackend.registerEnum("Network.InitiatorType", { Parser: "parser", Script: "script", Preload: "preload", SignedExchange: "SignedExchange", Preflight: "preflight", FedCM: "FedCM", Other: "other" });
753
754
  inspectorBackend.registerEnum("Network.SetCookieBlockedReason", { SecureOnly: "SecureOnly", SameSiteStrict: "SameSiteStrict", SameSiteLax: "SameSiteLax", SameSiteUnspecifiedTreatedAsLax: "SameSiteUnspecifiedTreatedAsLax", SameSiteNoneInsecure: "SameSiteNoneInsecure", UserPreferences: "UserPreferences", ThirdPartyPhaseout: "ThirdPartyPhaseout", ThirdPartyBlockedInFirstPartySet: "ThirdPartyBlockedInFirstPartySet", SyntaxError: "SyntaxError", SchemeNotSupported: "SchemeNotSupported", OverwriteSecure: "OverwriteSecure", InvalidDomain: "InvalidDomain", InvalidPrefix: "InvalidPrefix", UnknownError: "UnknownError", SchemefulSameSiteStrict: "SchemefulSameSiteStrict", SchemefulSameSiteLax: "SchemefulSameSiteLax", SchemefulSameSiteUnspecifiedTreatedAsLax: "SchemefulSameSiteUnspecifiedTreatedAsLax", SamePartyFromCrossPartyContext: "SamePartyFromCrossPartyContext", SamePartyConflictsWithOtherAttributes: "SamePartyConflictsWithOtherAttributes", NameValuePairExceedsMaxSize: "NameValuePairExceedsMaxSize", DisallowedCharacter: "DisallowedCharacter", NoCookieContent: "NoCookieContent" });
754
755
  inspectorBackend.registerEnum("Network.CookieBlockedReason", { SecureOnly: "SecureOnly", NotOnPath: "NotOnPath", DomainMismatch: "DomainMismatch", SameSiteStrict: "SameSiteStrict", SameSiteLax: "SameSiteLax", SameSiteUnspecifiedTreatedAsLax: "SameSiteUnspecifiedTreatedAsLax", SameSiteNoneInsecure: "SameSiteNoneInsecure", UserPreferences: "UserPreferences", ThirdPartyPhaseout: "ThirdPartyPhaseout", ThirdPartyBlockedInFirstPartySet: "ThirdPartyBlockedInFirstPartySet", UnknownError: "UnknownError", SchemefulSameSiteStrict: "SchemefulSameSiteStrict", SchemefulSameSiteLax: "SchemefulSameSiteLax", SchemefulSameSiteUnspecifiedTreatedAsLax: "SchemefulSameSiteUnspecifiedTreatedAsLax", SamePartyFromCrossPartyContext: "SamePartyFromCrossPartyContext", NameValuePairExceedsMaxSize: "NameValuePairExceedsMaxSize", PortMismatch: "PortMismatch", SchemeMismatch: "SchemeMismatch", AnonymousContext: "AnonymousContext" });
755
756
  inspectorBackend.registerEnum("Network.CookieExemptionReason", { None: "None", UserSetting: "UserSetting", TPCDMetadata: "TPCDMetadata", TPCDDeprecationTrial: "TPCDDeprecationTrial", TopLevelTPCDDeprecationTrial: "TopLevelTPCDDeprecationTrial", TPCDHeuristics: "TPCDHeuristics", EnterprisePolicy: "EnterprisePolicy", StorageAccess: "StorageAccess", TopLevelStorageAccess: "TopLevelStorageAccess", Scheme: "Scheme", SameSiteNoneCookiesInSandbox: "SameSiteNoneCookiesInSandbox" });
@@ -823,7 +824,7 @@ export function registerCommands(inspectorBackend) {
823
824
  inspectorBackend.registerCommand("Network.deleteCookies", [{ "name": "name", "type": "string", "optional": false, "description": "Name of the cookies to remove.", "typeRef": null }, { "name": "url", "type": "string", "optional": true, "description": "If specified, deletes all the cookies with the given name where domain and path match provided URL.", "typeRef": null }, { "name": "domain", "type": "string", "optional": true, "description": "If specified, deletes only cookies with the exact domain.", "typeRef": null }, { "name": "path", "type": "string", "optional": true, "description": "If specified, deletes only cookies with the exact path.", "typeRef": null }, { "name": "partitionKey", "type": "object", "optional": true, "description": "If specified, deletes only cookies with the the given name and partitionKey where all partition key attributes match the cookie partition key attribute.", "typeRef": "Network.CookiePartitionKey" }], [], "Deletes browser cookies with matching name and url or domain/path/partitionKey pair.");
824
825
  inspectorBackend.registerCommand("Network.disable", [], [], "Disables network tracking, prevents network events from being sent to the client.");
825
826
  inspectorBackend.registerCommand("Network.emulateNetworkConditions", [{ "name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null }, { "name": "latency", "type": "number", "optional": false, "description": "Minimum latency from request sent to response headers received (ms).", "typeRef": null }, { "name": "downloadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.", "typeRef": null }, { "name": "uploadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.", "typeRef": null }, { "name": "connectionType", "type": "string", "optional": true, "description": "Connection type if known.", "typeRef": "Network.ConnectionType" }, { "name": "packetLoss", "type": "number", "optional": true, "description": "WebRTC packet loss (percent, 0-100). 0 disables packet loss emulation, 100 drops all the packets.", "typeRef": null }, { "name": "packetQueueLength", "type": "number", "optional": true, "description": "WebRTC packet queue length (packet). 0 removes any queue length limitations.", "typeRef": null }, { "name": "packetReordering", "type": "boolean", "optional": true, "description": "WebRTC packetReordering feature.", "typeRef": null }], [], "Activates emulation of network conditions. This command is deprecated in favor of the emulateNetworkConditionsByRule and overrideNetworkState commands, which can be used together to the same effect.");
826
- inspectorBackend.registerCommand("Network.emulateNetworkConditionsByRule", [{ "name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null }, { "name": "matchedNetworkConditions", "type": "array", "optional": false, "description": "Configure conditions for matching requests. If multiple entries match a request, the first entry wins. Global conditions can be configured by leaving the urlPattern for the conditions empty. These global conditions are also applied for throttling of p2p connections.", "typeRef": "Network.NetworkConditions" }], ["ruleIds"], "Activates emulation of network conditions for individual requests using URL match patterns.");
827
+ inspectorBackend.registerCommand("Network.emulateNetworkConditionsByRule", [{ "name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null }, { "name": "matchedNetworkConditions", "type": "array", "optional": false, "description": "Configure conditions for matching requests. If multiple entries match a request, the first entry wins. Global conditions can be configured by leaving the urlPattern for the conditions empty. These global conditions are also applied for throttling of p2p connections.", "typeRef": "Network.NetworkConditions" }], ["ruleIds"], "Activates emulation of network conditions for individual requests using URL match patterns. Unlike the deprecated Network.emulateNetworkConditions this method does not affect `navigator` state. Use Network.overrideNetworkState to explicitly modify `navigator` behavior.");
827
828
  inspectorBackend.registerCommand("Network.overrideNetworkState", [{ "name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null }, { "name": "latency", "type": "number", "optional": false, "description": "Minimum latency from request sent to response headers received (ms).", "typeRef": null }, { "name": "downloadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.", "typeRef": null }, { "name": "uploadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.", "typeRef": null }, { "name": "connectionType", "type": "string", "optional": true, "description": "Connection type if known.", "typeRef": "Network.ConnectionType" }], [], "Override the state of navigator.onLine and navigator.connection.");
828
829
  inspectorBackend.registerCommand("Network.enable", [{ "name": "maxTotalBufferSize", "type": "number", "optional": true, "description": "Buffer size in bytes to use when preserving network payloads (XHRs, etc).", "typeRef": null }, { "name": "maxResourceBufferSize", "type": "number", "optional": true, "description": "Per-resource buffer size in bytes to use when preserving network payloads (XHRs, etc).", "typeRef": null }, { "name": "maxPostDataSize", "type": "number", "optional": true, "description": "Longest post body size (in bytes) that would be included in requestWillBeSent notification", "typeRef": null }, { "name": "reportDirectSocketTraffic", "type": "boolean", "optional": true, "description": "Whether DirectSocket chunk send/receive events should be reported.", "typeRef": null }, { "name": "enableDurableMessages", "type": "boolean", "optional": true, "description": "Enable storing response bodies outside of renderer, so that these survive a cross-process navigation. Requires maxTotalBufferSize to be set. Currently defaults to false.", "typeRef": null }], [], "Enables network tracking, network events will now be delivered to the client.");
829
830
  inspectorBackend.registerCommand("Network.getAllCookies", [], ["cookies"], "Returns all browser cookies. Depending on the backend support, will return detailed cookie information in the `cookies` field. Deprecated. Use Storage.getCookies instead.");
@@ -835,7 +836,7 @@ export function registerCommands(inspectorBackend) {
835
836
  inspectorBackend.registerCommand("Network.takeResponseBodyForInterceptionAsStream", [{ "name": "interceptionId", "type": "string", "optional": false, "description": "", "typeRef": "Network.InterceptionId" }], ["stream"], "Returns a handle to the stream representing the response body. Note that after this command, the intercepted request can't be continued as is -- you either need to cancel it or to provide the response body. The stream only supports sequential read, IO.read will fail if the position is specified.");
836
837
  inspectorBackend.registerCommand("Network.replayXHR", [{ "name": "requestId", "type": "string", "optional": false, "description": "Identifier of XHR to replay.", "typeRef": "Network.RequestId" }], [], "This method sends a new XMLHttpRequest which is identical to the original one. The following parameters should be identical: method, url, async, request body, extra headers, withCredentials attribute, user, password.");
837
838
  inspectorBackend.registerCommand("Network.searchInResponseBody", [{ "name": "requestId", "type": "string", "optional": false, "description": "Identifier of the network response to search.", "typeRef": "Network.RequestId" }, { "name": "query", "type": "string", "optional": false, "description": "String to search for.", "typeRef": null }, { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive.", "typeRef": null }, { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex.", "typeRef": null }], ["result"], "Searches for given string in response content.");
838
- inspectorBackend.registerCommand("Network.setBlockedURLs", [{ "name": "urlPatterns", "type": "array", "optional": true, "description": "URL patterns to block. Patterns use the URLPattern constructor string syntax (https://urlpattern.spec.whatwg.org/). Example: `*://*:*/*.css`.", "typeRef": "string" }, { "name": "urls", "type": "array", "optional": true, "description": "URL patterns to block. Wildcards ('*') are allowed.", "typeRef": "string" }], [], "Blocks URLs from loading.");
839
+ inspectorBackend.registerCommand("Network.setBlockedURLs", [{ "name": "urlPatterns", "type": "array", "optional": true, "description": "Patterns to match in the order in which they are given. These patterns also take precedence over any wildcard patterns defined in `urls`.", "typeRef": "Network.BlockPattern" }, { "name": "urls", "type": "array", "optional": true, "description": "URL patterns to block. Wildcards ('*') are allowed.", "typeRef": "string" }], [], "Blocks URLs from loading.");
839
840
  inspectorBackend.registerCommand("Network.setBypassServiceWorker", [{ "name": "bypass", "type": "boolean", "optional": false, "description": "Bypass service worker and load from network.", "typeRef": null }], [], "Toggles ignoring of service worker for each request.");
840
841
  inspectorBackend.registerCommand("Network.setCacheDisabled", [{ "name": "cacheDisabled", "type": "boolean", "optional": false, "description": "Cache disabled state.", "typeRef": null }], [], "Toggles ignoring cache for each request. If `true`, cache will not be used.");
841
842
  inspectorBackend.registerCommand("Network.setCookie", [{ "name": "name", "type": "string", "optional": false, "description": "Cookie name.", "typeRef": null }, { "name": "value", "type": "string", "optional": false, "description": "Cookie value.", "typeRef": null }, { "name": "url", "type": "string", "optional": true, "description": "The request-URI to associate with the setting of the cookie. This value can affect the default domain, path, source port, and source scheme values of the created cookie.", "typeRef": null }, { "name": "domain", "type": "string", "optional": true, "description": "Cookie domain.", "typeRef": null }, { "name": "path", "type": "string", "optional": true, "description": "Cookie path.", "typeRef": null }, { "name": "secure", "type": "boolean", "optional": true, "description": "True if cookie is secure.", "typeRef": null }, { "name": "httpOnly", "type": "boolean", "optional": true, "description": "True if cookie is http-only.", "typeRef": null }, { "name": "sameSite", "type": "string", "optional": true, "description": "Cookie SameSite type.", "typeRef": "Network.CookieSameSite" }, { "name": "expires", "type": "number", "optional": true, "description": "Cookie expiration date, session cookie if not set", "typeRef": "Network.TimeSinceEpoch" }, { "name": "priority", "type": "string", "optional": true, "description": "Cookie Priority type.", "typeRef": "Network.CookiePriority" }, { "name": "sameParty", "type": "boolean", "optional": true, "description": "True if cookie is SameParty.", "typeRef": null }, { "name": "sourceScheme", "type": "string", "optional": true, "description": "Cookie source scheme type.", "typeRef": "Network.CookieSourceScheme" }, { "name": "sourcePort", "type": "number", "optional": true, "description": "Cookie source port. Valid values are {-1, [1, 65535]}, -1 indicates an unspecified port. An unspecified port value allows protocol clients to emulate legacy cookie scope for the port. This is a temporary ability and it will be removed in the future.", "typeRef": null }, { "name": "partitionKey", "type": "object", "optional": true, "description": "Cookie partition key. If not set, the cookie will be set as not partitioned.", "typeRef": "Network.CookiePartitionKey" }], ["success"], "Sets a cookie with the given cookie data; may overwrite equivalent cookies if they exist.");
@@ -876,7 +877,8 @@ export function registerCommands(inspectorBackend) {
876
877
  inspectorBackend.registerType("Network.SignedExchangeHeader", [{ "name": "requestUrl", "type": "string", "optional": false, "description": "Signed exchange request URL.", "typeRef": null }, { "name": "responseCode", "type": "number", "optional": false, "description": "Signed exchange response code.", "typeRef": null }, { "name": "responseHeaders", "type": "object", "optional": false, "description": "Signed exchange response headers.", "typeRef": "Network.Headers" }, { "name": "signatures", "type": "array", "optional": false, "description": "Signed exchange response signature.", "typeRef": "Network.SignedExchangeSignature" }, { "name": "headerIntegrity", "type": "string", "optional": false, "description": "Signed exchange header integrity hash in the form of `sha256-<base64-hash-value>`.", "typeRef": null }]);
877
878
  inspectorBackend.registerType("Network.SignedExchangeError", [{ "name": "message", "type": "string", "optional": false, "description": "Error message.", "typeRef": null }, { "name": "signatureIndex", "type": "number", "optional": true, "description": "The index of the signature which caused the error.", "typeRef": null }, { "name": "errorField", "type": "string", "optional": true, "description": "The field which caused the error.", "typeRef": "Network.SignedExchangeErrorField" }]);
878
879
  inspectorBackend.registerType("Network.SignedExchangeInfo", [{ "name": "outerResponse", "type": "object", "optional": false, "description": "The outer response of signed HTTP exchange which was received from network.", "typeRef": "Network.Response" }, { "name": "hasExtraInfo", "type": "boolean", "optional": false, "description": "Whether network response for the signed exchange was accompanied by extra headers.", "typeRef": null }, { "name": "header", "type": "object", "optional": true, "description": "Information about the signed exchange header.", "typeRef": "Network.SignedExchangeHeader" }, { "name": "securityDetails", "type": "object", "optional": true, "description": "Security details for the signed exchange header.", "typeRef": "Network.SecurityDetails" }, { "name": "errors", "type": "array", "optional": true, "description": "Errors occurred while handling the signed exchange.", "typeRef": "Network.SignedExchangeError" }]);
879
- inspectorBackend.registerType("Network.NetworkConditions", [{ "name": "urlPattern", "type": "string", "optional": false, "description": "Only matching requests will be affected by these conditions. Patterns use the URLPattern constructor string syntax (https://urlpattern.spec.whatwg.org/). If the pattern is empty, all requests are matched (including p2p connections).", "typeRef": null }, { "name": "latency", "type": "number", "optional": false, "description": "Minimum latency from request sent to response headers received (ms).", "typeRef": null }, { "name": "downloadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.", "typeRef": null }, { "name": "uploadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.", "typeRef": null }, { "name": "connectionType", "type": "string", "optional": true, "description": "Connection type if known.", "typeRef": "Network.ConnectionType" }, { "name": "packetLoss", "type": "number", "optional": true, "description": "WebRTC packet loss (percent, 0-100). 0 disables packet loss emulation, 100 drops all the packets.", "typeRef": null }, { "name": "packetQueueLength", "type": "number", "optional": true, "description": "WebRTC packet queue length (packet). 0 removes any queue length limitations.", "typeRef": null }, { "name": "packetReordering", "type": "boolean", "optional": true, "description": "WebRTC packetReordering feature.", "typeRef": null }]);
880
+ inspectorBackend.registerType("Network.NetworkConditions", [{ "name": "urlPattern", "type": "string", "optional": false, "description": "Only matching requests will be affected by these conditions. Patterns use the URLPattern constructor string syntax (https://urlpattern.spec.whatwg.org/) and must be absolute. If the pattern is empty, all requests are matched (including p2p connections).", "typeRef": null }, { "name": "latency", "type": "number", "optional": false, "description": "Minimum latency from request sent to response headers received (ms).", "typeRef": null }, { "name": "downloadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.", "typeRef": null }, { "name": "uploadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.", "typeRef": null }, { "name": "connectionType", "type": "string", "optional": true, "description": "Connection type if known.", "typeRef": "Network.ConnectionType" }, { "name": "packetLoss", "type": "number", "optional": true, "description": "WebRTC packet loss (percent, 0-100). 0 disables packet loss emulation, 100 drops all the packets.", "typeRef": null }, { "name": "packetQueueLength", "type": "number", "optional": true, "description": "WebRTC packet queue length (packet). 0 removes any queue length limitations.", "typeRef": null }, { "name": "packetReordering", "type": "boolean", "optional": true, "description": "WebRTC packetReordering feature.", "typeRef": null }]);
881
+ inspectorBackend.registerType("Network.BlockPattern", [{ "name": "urlPattern", "type": "string", "optional": false, "description": "URL pattern to match. Patterns use the URLPattern constructor string syntax (https://urlpattern.spec.whatwg.org/) and must be absolute. Example: `*://*:*/*.css`.", "typeRef": null }, { "name": "block", "type": "boolean", "optional": false, "description": "Whether or not to block the pattern. If false, a matching request will not be blocked even if it matches a later `BlockPattern`.", "typeRef": null }]);
880
882
  inspectorBackend.registerType("Network.DirectTCPSocketOptions", [{ "name": "noDelay", "type": "boolean", "optional": false, "description": "TCP_NODELAY option", "typeRef": null }, { "name": "keepAliveDelay", "type": "number", "optional": true, "description": "Expected to be unsigned integer.", "typeRef": null }, { "name": "sendBufferSize", "type": "number", "optional": true, "description": "Expected to be unsigned integer.", "typeRef": null }, { "name": "receiveBufferSize", "type": "number", "optional": true, "description": "Expected to be unsigned integer.", "typeRef": null }, { "name": "dnsQueryType", "type": "string", "optional": true, "description": "", "typeRef": "Network.DirectSocketDnsQueryType" }]);
881
883
  inspectorBackend.registerType("Network.DirectUDPSocketOptions", [{ "name": "remoteAddr", "type": "string", "optional": true, "description": "", "typeRef": null }, { "name": "remotePort", "type": "number", "optional": true, "description": "Unsigned int 16.", "typeRef": null }, { "name": "localAddr", "type": "string", "optional": true, "description": "", "typeRef": null }, { "name": "localPort", "type": "number", "optional": true, "description": "Unsigned int 16.", "typeRef": null }, { "name": "dnsQueryType", "type": "string", "optional": true, "description": "", "typeRef": "Network.DirectSocketDnsQueryType" }, { "name": "sendBufferSize", "type": "number", "optional": true, "description": "Expected to be unsigned integer.", "typeRef": null }, { "name": "receiveBufferSize", "type": "number", "optional": true, "description": "Expected to be unsigned integer.", "typeRef": null }]);
882
884
  inspectorBackend.registerType("Network.DirectUDPMessage", [{ "name": "data", "type": "string", "optional": false, "description": "", "typeRef": null }, { "name": "remoteAddr", "type": "string", "optional": true, "description": "Null for connected mode.", "typeRef": null }, { "name": "remotePort", "type": "number", "optional": true, "description": "Null for connected mode. Expected to be unsigned integer.", "typeRef": null }]);
@@ -1135,7 +1137,7 @@ export function registerCommands(inspectorBackend) {
1135
1137
  inspectorBackend.registerType("PerformanceTimeline.TimelineEvent", [{ "name": "frameId", "type": "string", "optional": false, "description": "Identifies the frame that this event is related to. Empty for non-frame targets.", "typeRef": "Page.FrameId" }, { "name": "type", "type": "string", "optional": false, "description": "The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype This determines which of the optional \\\"details\\\" fields is present.", "typeRef": null }, { "name": "name", "type": "string", "optional": false, "description": "Name may be empty depending on the type.", "typeRef": null }, { "name": "time", "type": "number", "optional": false, "description": "Time in seconds since Epoch, monotonically increasing within document lifetime.", "typeRef": "Network.TimeSinceEpoch" }, { "name": "duration", "type": "number", "optional": true, "description": "Event duration, if applicable.", "typeRef": null }, { "name": "lcpDetails", "type": "object", "optional": true, "description": "", "typeRef": "PerformanceTimeline.LargestContentfulPaint" }, { "name": "layoutShiftDetails", "type": "object", "optional": true, "description": "", "typeRef": "PerformanceTimeline.LayoutShift" }]);
1136
1138
  // Preload.
1137
1139
  inspectorBackend.registerEnum("Preload.RuleSetErrorType", { SourceIsNotJsonObject: "SourceIsNotJsonObject", InvalidRulesSkipped: "InvalidRulesSkipped", InvalidRulesetLevelTag: "InvalidRulesetLevelTag" });
1138
- inspectorBackend.registerEnum("Preload.SpeculationAction", { Prefetch: "Prefetch", Prerender: "Prerender" });
1140
+ inspectorBackend.registerEnum("Preload.SpeculationAction", { Prefetch: "Prefetch", Prerender: "Prerender", PrerenderUntilScript: "PrerenderUntilScript" });
1139
1141
  inspectorBackend.registerEnum("Preload.SpeculationTargetHint", { Blank: "Blank", Self: "Self" });
1140
1142
  inspectorBackend.registerEnum("Preload.PrerenderFinalStatus", { Activated: "Activated", Destroyed: "Destroyed", LowEndDevice: "LowEndDevice", InvalidSchemeRedirect: "InvalidSchemeRedirect", InvalidSchemeNavigation: "InvalidSchemeNavigation", NavigationRequestBlockedByCsp: "NavigationRequestBlockedByCsp", MojoBinderPolicy: "MojoBinderPolicy", RendererProcessCrashed: "RendererProcessCrashed", RendererProcessKilled: "RendererProcessKilled", Download: "Download", TriggerDestroyed: "TriggerDestroyed", NavigationNotCommitted: "NavigationNotCommitted", NavigationBadHttpStatus: "NavigationBadHttpStatus", ClientCertRequested: "ClientCertRequested", NavigationRequestNetworkError: "NavigationRequestNetworkError", CancelAllHostsForTesting: "CancelAllHostsForTesting", DidFailLoad: "DidFailLoad", Stop: "Stop", SslCertificateError: "SslCertificateError", LoginAuthRequested: "LoginAuthRequested", UaChangeRequiresReload: "UaChangeRequiresReload", BlockedByClient: "BlockedByClient", AudioOutputDeviceRequested: "AudioOutputDeviceRequested", MixedContent: "MixedContent", TriggerBackgrounded: "TriggerBackgrounded", MemoryLimitExceeded: "MemoryLimitExceeded", DataSaverEnabled: "DataSaverEnabled", TriggerUrlHasEffectiveUrl: "TriggerUrlHasEffectiveUrl", ActivatedBeforeStarted: "ActivatedBeforeStarted", InactivePageRestriction: "InactivePageRestriction", StartFailed: "StartFailed", TimeoutBackgrounded: "TimeoutBackgrounded", CrossSiteRedirectInInitialNavigation: "CrossSiteRedirectInInitialNavigation", CrossSiteNavigationInInitialNavigation: "CrossSiteNavigationInInitialNavigation", SameSiteCrossOriginRedirectNotOptInInInitialNavigation: "SameSiteCrossOriginRedirectNotOptInInInitialNavigation", SameSiteCrossOriginNavigationNotOptInInInitialNavigation: "SameSiteCrossOriginNavigationNotOptInInInitialNavigation", ActivationNavigationParameterMismatch: "ActivationNavigationParameterMismatch", ActivatedInBackground: "ActivatedInBackground", EmbedderHostDisallowed: "EmbedderHostDisallowed", ActivationNavigationDestroyedBeforeSuccess: "ActivationNavigationDestroyedBeforeSuccess", TabClosedByUserGesture: "TabClosedByUserGesture", TabClosedWithoutUserGesture: "TabClosedWithoutUserGesture", PrimaryMainFrameRendererProcessCrashed: "PrimaryMainFrameRendererProcessCrashed", PrimaryMainFrameRendererProcessKilled: "PrimaryMainFrameRendererProcessKilled", ActivationFramePolicyNotCompatible: "ActivationFramePolicyNotCompatible", PreloadingDisabled: "PreloadingDisabled", BatterySaverEnabled: "BatterySaverEnabled", ActivatedDuringMainFrameNavigation: "ActivatedDuringMainFrameNavigation", PreloadingUnsupportedByWebContents: "PreloadingUnsupportedByWebContents", CrossSiteRedirectInMainFrameNavigation: "CrossSiteRedirectInMainFrameNavigation", CrossSiteNavigationInMainFrameNavigation: "CrossSiteNavigationInMainFrameNavigation", SameSiteCrossOriginRedirectNotOptInInMainFrameNavigation: "SameSiteCrossOriginRedirectNotOptInInMainFrameNavigation", SameSiteCrossOriginNavigationNotOptInInMainFrameNavigation: "SameSiteCrossOriginNavigationNotOptInInMainFrameNavigation", MemoryPressureOnTrigger: "MemoryPressureOnTrigger", MemoryPressureAfterTriggered: "MemoryPressureAfterTriggered", PrerenderingDisabledByDevTools: "PrerenderingDisabledByDevTools", SpeculationRuleRemoved: "SpeculationRuleRemoved", ActivatedWithAuxiliaryBrowsingContexts: "ActivatedWithAuxiliaryBrowsingContexts", MaxNumOfRunningEagerPrerendersExceeded: "MaxNumOfRunningEagerPrerendersExceeded", MaxNumOfRunningNonEagerPrerendersExceeded: "MaxNumOfRunningNonEagerPrerendersExceeded", MaxNumOfRunningEmbedderPrerendersExceeded: "MaxNumOfRunningEmbedderPrerendersExceeded", PrerenderingUrlHasEffectiveUrl: "PrerenderingUrlHasEffectiveUrl", RedirectedPrerenderingUrlHasEffectiveUrl: "RedirectedPrerenderingUrlHasEffectiveUrl", ActivationUrlHasEffectiveUrl: "ActivationUrlHasEffectiveUrl", JavaScriptInterfaceAdded: "JavaScriptInterfaceAdded", JavaScriptInterfaceRemoved: "JavaScriptInterfaceRemoved", AllPrerenderingCanceled: "AllPrerenderingCanceled", WindowClosed: "WindowClosed", SlowNetwork: "SlowNetwork", OtherPrerenderedPageActivated: "OtherPrerenderedPageActivated", V8OptimizerDisabled: "V8OptimizerDisabled", PrerenderFailedDuringPrefetch: "PrerenderFailedDuringPrefetch", BrowsingDataRemoved: "BrowsingDataRemoved", PrerenderHostReused: "PrerenderHostReused" });
1141
1143
  inspectorBackend.registerEnum("Preload.PreloadingStatus", { Pending: "Pending", Running: "Running", Ready: "Ready", Success: "Success", Failure: "Failure", NotSupported: "NotSupported" });
@@ -732,7 +732,6 @@ export const generatedProperties = [
732
732
  "text-wrap-mode",
733
733
  "text-wrap-style",
734
734
  "timeline-scope",
735
- "timeline-trigger-behavior",
736
735
  "timeline-trigger-exit-range-end",
737
736
  "timeline-trigger-exit-range-start",
738
737
  "timeline-trigger-name",
@@ -3759,6 +3758,13 @@ export const generatedProperties = [
3759
3758
  ],
3760
3759
  "name": "rule"
3761
3760
  },
3761
+ {
3762
+ "longhands": [
3763
+ "row-rule-break",
3764
+ "column-rule-break"
3765
+ ],
3766
+ "name": "rule-break"
3767
+ },
3762
3768
  {
3763
3769
  "longhands": [
3764
3770
  "column-rule-color",
@@ -3766,6 +3772,13 @@ export const generatedProperties = [
3766
3772
  ],
3767
3773
  "name": "rule-color"
3768
3774
  },
3775
+ {
3776
+ "longhands": [
3777
+ "row-rule-outset",
3778
+ "column-rule-outset"
3779
+ ],
3780
+ "name": "rule-outset"
3781
+ },
3769
3782
  {
3770
3783
  "longhands": [
3771
3784
  "column-rule-style",
@@ -4375,6 +4388,7 @@ export const generatedProperties = [
4375
4388
  "capitalize",
4376
4389
  "uppercase",
4377
4390
  "lowercase",
4391
+ "full-width",
4378
4392
  "none",
4379
4393
  "math-auto"
4380
4394
  ],
@@ -4431,7 +4445,6 @@ export const generatedProperties = [
4431
4445
  "longhands": [
4432
4446
  "timeline-trigger-name",
4433
4447
  "timeline-trigger-source",
4434
- "timeline-trigger-behavior",
4435
4448
  "timeline-trigger-range-start",
4436
4449
  "timeline-trigger-range-end",
4437
4450
  "timeline-trigger-exit-range-start",
@@ -4439,15 +4452,6 @@ export const generatedProperties = [
4439
4452
  ],
4440
4453
  "name": "timeline-trigger"
4441
4454
  },
4442
- {
4443
- "keywords": [
4444
- "once",
4445
- "repeat",
4446
- "alternate",
4447
- "state"
4448
- ],
4449
- "name": "timeline-trigger-behavior"
4450
- },
4451
4455
  {
4452
4456
  "name": "timeline-trigger-exit-range-end"
4453
4457
  },
@@ -6813,6 +6817,7 @@ export const generatedPropertyValues = {
6813
6817
  "capitalize",
6814
6818
  "uppercase",
6815
6819
  "lowercase",
6820
+ "full-width",
6816
6821
  "none",
6817
6822
  "math-auto"
6818
6823
  ]
@@ -6845,14 +6850,6 @@ export const generatedPropertyValues = {
6845
6850
  "stable"
6846
6851
  ]
6847
6852
  },
6848
- "timeline-trigger-behavior": {
6849
- "values": [
6850
- "once",
6851
- "repeat",
6852
- "alternate",
6853
- "state"
6854
- ]
6855
- },
6856
6853
  "timeline-trigger-source": {
6857
6854
  "values": [
6858
6855
  "none",
@@ -239,7 +239,9 @@ export class PerformanceInsightFormatter {
239
239
  const rootCauseText = potentialRootCauses.length ? `- Potential root causes:\n ${potentialRootCauses.join('\n')}` :
240
240
  '- No potential root causes identified';
241
241
  const startTime = Trace.Helpers.Timing.microToMilli(Trace.Types.Timing.Micro(shift.ts - baseTime));
242
- return `### Layout shift ${index + 1}:
242
+ const impactedNodeNames = shift.rawSourceEvent.args.data?.impacted_nodes?.map(n => n.debug_name).filter(name => name !== undefined) ?? [];
243
+ const impactedNodeText = impactedNodeNames.length ? `\n- Impacted elements:\n - ${impactedNodeNames.join('\n - ')}\n` : '';
244
+ return `### Layout shift ${index + 1}:${impactedNodeText}
243
245
  - Start time: ${millis(startTime)}
244
246
  - Score: ${shift.args.data?.weighted_score_delta.toFixed(4)}
245
247
  ${rootCauseText}`;
@@ -432,7 +434,7 @@ Duplication grouped by Node modules: ${filesFormatted}`;
432
434
  output += 'No top-level functions causing forced reflows were identified.\n';
433
435
  }
434
436
  if (insight.aggregatedBottomUpData.length > 0) {
435
- output += '\n' + Trace.Insights.Models.ForcedReflow.UIStrings.relatedStackTrace + ' (including total time):\n';
437
+ output += '\n' + Trace.Insights.Models.ForcedReflow.UIStrings.reflowCallFrames + ' (including total time):\n';
436
438
  for (const data of insight.aggregatedBottomUpData) {
437
439
  output += `\n - ${this.#formatMicro(data.totalTime)} in ${callFrameToString(data.bottomUpData)}`;
438
440
  }
@@ -845,55 +847,69 @@ ${this.#links()}`;
845
847
  .join(', ');
846
848
  }
847
849
  #links() {
850
+ const links = [];
851
+ if (this.#insight.docs) {
852
+ links.push(this.#insight.docs);
853
+ }
848
854
  switch (this.#insight.insightKey) {
849
855
  case 'CLSCulprits':
850
- return `- https://web.dev/articles/cls
851
- - https://web.dev/articles/optimize-cls`;
856
+ links.push('https://web.dev/articles/cls');
857
+ links.push('https://web.dev/articles/optimize-cls');
858
+ break;
852
859
  case 'DocumentLatency':
853
- return '- https://web.dev/articles/optimize-ttfb';
860
+ links.push('https://web.dev/articles/optimize-ttfb');
861
+ break;
854
862
  case 'DOMSize':
855
- return '- https://developer.chrome.com/docs/lighthouse/performance/dom-size/';
856
- case 'DuplicatedJavaScript':
857
- return '';
863
+ links.push('https://developer.chrome.com/docs/lighthouse/performance/dom-size/');
864
+ break;
858
865
  case 'FontDisplay':
859
- return `- https://web.dev/articles/preload-optional-fonts
860
- - https://fonts.google.com/knowledge/glossary/foit
861
- - https://developer.chrome.com/blog/font-fallbacks`;
866
+ links.push('https://web.dev/articles/preload-optional-fonts');
867
+ links.push('https://fonts.google.com/knowledge/glossary/foit');
868
+ links.push('https://developer.chrome.com/blog/font-fallbacks');
869
+ break;
862
870
  case 'ForcedReflow':
863
- return '- https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing#avoid-forced-synchronous-layouts';
871
+ links.push('https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing#avoid-forced-synchronous-layouts');
872
+ break;
864
873
  case 'ImageDelivery':
865
- return '- https://developer.chrome.com/docs/lighthouse/performance/uses-optimized-images/';
874
+ links.push('https://developer.chrome.com/docs/lighthouse/performance/uses-optimized-images/');
875
+ break;
866
876
  case 'INPBreakdown':
867
- return `- https://web.dev/articles/inp
868
- - https://web.dev/explore/how-to-optimize-inp
869
- - https://web.dev/articles/optimize-long-tasks
870
- - https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing`;
871
- case 'LCPDiscovery':
872
- return `- https://web.dev/articles/lcp
873
- - https://web.dev/articles/optimize-lcp`;
877
+ links.push('https://web.dev/articles/inp');
878
+ links.push('https://web.dev/explore/how-to-optimize-inp');
879
+ links.push('https://web.dev/articles/optimize-long-tasks');
880
+ links.push('https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing');
881
+ break;
874
882
  case 'LCPBreakdown':
875
- return `- https://web.dev/articles/lcp
876
- - https://web.dev/articles/optimize-lcp`;
877
- case 'NetworkDependencyTree':
878
- return `- https://web.dev/learn/performance/understanding-the-critical-path
879
- - https://developer.chrome.com/docs/lighthouse/performance/uses-rel-preconnect/`;
883
+ case 'LCPDiscovery':
880
884
  case 'RenderBlocking':
881
- return `- https://web.dev/articles/lcp
882
- - https://web.dev/articles/optimize-lcp`;
885
+ links.push('https://web.dev/articles/lcp');
886
+ links.push('https://web.dev/articles/optimize-lcp');
887
+ break;
888
+ case 'NetworkDependencyTree':
889
+ links.push('https://web.dev/learn/performance/understanding-the-critical-path');
890
+ links.push('https://developer.chrome.com/docs/lighthouse/performance/uses-rel-preconnect/');
891
+ break;
883
892
  case 'SlowCSSSelector':
884
- return '- https://developer.chrome.com/docs/devtools/performance/selector-stats';
893
+ links.push('https://developer.chrome.com/docs/devtools/performance/selector-stats');
894
+ break;
885
895
  case 'ThirdParties':
886
- return '- https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/';
896
+ links.push('https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/');
897
+ break;
887
898
  case 'Viewport':
888
- return '- https://developer.chrome.com/blog/300ms-tap-delay-gone-away/';
899
+ links.push('https://developer.chrome.com/blog/300ms-tap-delay-gone-away/');
900
+ break;
889
901
  case 'Cache':
890
- return '- https://web.dev/uses-long-cache-ttl/';
902
+ links.push('https://web.dev/uses-long-cache-ttl/');
903
+ break;
891
904
  case 'ModernHTTP':
892
- return '- https://developer.chrome.com/docs/lighthouse/best-practices/uses-http2';
905
+ links.push('https://developer.chrome.com/docs/lighthouse/best-practices/uses-http2');
906
+ break;
893
907
  case 'LegacyJavaScript':
894
- return `- https://web.dev/articles/baseline-and-polyfills
895
- - https://philipwalton.com/articles/the-state-of-es5-on-the-web/`;
908
+ links.push('https://web.dev/articles/baseline-and-polyfills');
909
+ links.push('https://philipwalton.com/articles/the-state-of-es5-on-the-web/');
910
+ break;
896
911
  }
912
+ return links.map(link => '- ' + link).join('\n');
897
913
  }
898
914
  #description() {
899
915
  switch (this.#insight.insightKey) {
@@ -1,7 +1,6 @@
1
1
  // Copyright 2024 The Chromium Authors
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
- import * as Root from '../../../core/root/root.js';
5
4
  import * as Trace from '../../../models/trace/trace.js';
6
5
  import * as SourceMapsResolver from '../../../models/trace_source_maps_resolver/trace_source_maps_resolver.js';
7
6
  /** Iterates from a node down through its descendents. If the callback returns true, the loop stops. */
@@ -122,7 +121,7 @@ export class AICallTree {
122
121
  if (!data.Renderer.entryToNode.has(selectedEvent) && !data.Samples.entryToNode.has(selectedEvent)) {
123
122
  return null;
124
123
  }
125
- const allEventsEnabled = Root.Runtime.experiments.isEnabled('timeline-show-all-events');
124
+ const showAllEvents = parsedTrace.data.Meta.config.showAllEvents;
126
125
  const { startTime, endTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(selectedEvent);
127
126
  const selectedEventBounds = Trace.Helpers.Timing.traceWindowFromMicroSeconds(Trace.Helpers.Timing.milliToMicro(startTime), Trace.Helpers.Timing.milliToMicro(endTime));
128
127
  let threadEvents = data.Renderer.processes.get(selectedEvent.pid)?.threads.get(selectedEvent.tid)?.entries;
@@ -139,7 +138,7 @@ export class AICallTree {
139
138
  // If the "Show all events" experiment is on, we don't filter out any
140
139
  // events here, otherwise the generated call tree will not match what the
141
140
  // user is seeing.
142
- if (!allEventsEnabled) {
141
+ if (!showAllEvents) {
143
142
  filters.push(new Trace.Extras.TraceFilter.VisibleEventsFilter(Trace.Styles.visibleTypes()));
144
143
  }
145
144
  // Build a tree bounded by the selected event's timestamps, and our other filters applied
@@ -4,6 +4,8 @@
4
4
  import * as Common from '../../core/common/common.js';
5
5
  import * as Platform from '../../core/platform/platform.js';
6
6
  import * as SDK from '../../core/sdk/sdk.js';
7
+ // eslint-disable-next-line rulesdir/es-modules-import
8
+ import * as StackTraceImpl from '../stack_trace/stack_trace_impl.js';
7
9
  import * as TextUtils from '../text_utils/text_utils.js';
8
10
  import * as Workspace from '../workspace/workspace.js';
9
11
  import { ContentProviderBasedProject } from './ContentProviderBasedProject.js';
@@ -37,9 +39,11 @@ export class CompilerScriptMapping {
37
39
  #projects = new Map();
38
40
  #sourceMapToProject = new Map();
39
41
  #uiSourceCodeToSourceMaps = new Platform.MapUtilities.Multimap();
42
+ #debuggerModel;
40
43
  constructor(debuggerModel, workspace, debuggerWorkspaceBinding) {
41
44
  this.#sourceMapManager = debuggerModel.sourceMapManager();
42
45
  this.#debuggerWorkspaceBinding = debuggerWorkspaceBinding;
46
+ this.#debuggerModel = debuggerModel;
43
47
  this.#stubProject = new ContentProviderBasedProject(workspace, 'jsSourceMaps:stub:' + debuggerModel.target().id(), Workspace.Workspace.projectTypes.Service, '', true /* isServiceProject */);
44
48
  this.#eventListeners = [
45
49
  this.#sourceMapManager.addEventListener(SDK.SourceMapManager.Events.SourceMapWillAttach, this.sourceMapWillAttach, this),
@@ -214,8 +218,47 @@ export class CompilerScriptMapping {
214
218
  }
215
219
  return ranges;
216
220
  }
217
- translateRawFramesStep(_rawFrames, _translatedFrames) {
218
- // TODO(crbug.com/433162438): Implement source map stack trace translation.
221
+ translateRawFramesStep(rawFrames, translatedFrames) {
222
+ const frame = rawFrames[0];
223
+ if (StackTraceImpl.Trie.isBuiltinFrame(frame)) {
224
+ return false;
225
+ }
226
+ const sourceMapWithScopeInfoForFrame = (rawFrame) => {
227
+ const script = this.#debuggerModel.scriptForId(rawFrame.scriptId ?? '');
228
+ if (!script || this.#stubUISourceCodes.has(script)) {
229
+ // Use fallback while source map is being loaded.
230
+ return null;
231
+ }
232
+ const sourceMap = script.sourceMap();
233
+ return sourceMap?.hasScopeInfo() ? { sourceMap, script } : null;
234
+ };
235
+ const sourceMapAndScript = sourceMapWithScopeInfoForFrame(frame);
236
+ if (!sourceMapAndScript) {
237
+ return false;
238
+ }
239
+ const { sourceMap, script } = sourceMapAndScript;
240
+ const { lineNumber, columnNumber } = script.relativeLocationToRawLocation(frame);
241
+ if (!sourceMap.isOutlinedFrame(lineNumber, columnNumber)) {
242
+ const frames = sourceMap.translateCallSite(lineNumber, columnNumber);
243
+ if (!frames.length) {
244
+ return false;
245
+ }
246
+ rawFrames.shift();
247
+ const result = [];
248
+ translatedFrames.push(result);
249
+ const project = this.#sourceMapToProject.get(sourceMap);
250
+ for (const frame of frames) {
251
+ // Switch out url for UISourceCode where we have it.
252
+ const uiSourceCode = frame.url ? project?.uiSourceCodeForURL(frame.url) : undefined;
253
+ result.push({
254
+ ...frame,
255
+ url: uiSourceCode ? undefined : frame.url,
256
+ uiSourceCode: uiSourceCode ?? undefined,
257
+ });
258
+ }
259
+ return true;
260
+ }
261
+ // TODO(crbug.com/433162438): Consolidate outlined frames.
219
262
  return false;
220
263
  }
221
264
  /**
@@ -16,6 +16,20 @@ export class FormatterWorkerPool {
16
16
  }
17
17
  return formatterWorkerPoolInstance;
18
18
  }
19
+ dispose() {
20
+ for (const task of this.taskQueue) {
21
+ console.error('rejecting task');
22
+ task.errorCallback(new Event('Worker terminated'));
23
+ }
24
+ for (const [worker, task] of this.workerTasks.entries()) {
25
+ task?.errorCallback(new Event('Worker terminated'));
26
+ worker.terminate(/* immediately=*/ true);
27
+ }
28
+ }
29
+ static removeInstance() {
30
+ formatterWorkerPoolInstance?.dispose();
31
+ formatterWorkerPoolInstance = undefined;
32
+ }
19
33
  createWorker() {
20
34
  const worker = Common.Worker.WorkerWrapper.fromURL(new URL('../../entrypoints/formatter_worker/formatter_worker-entrypoint.js', import.meta.url));
21
35
  worker.onmessage = this.onWorkerMessage.bind(this, worker);
@@ -2,11 +2,11 @@
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
  import * as Common from '../../core/common/common.js';
5
+ import * as Root from '../../core/root/root.js';
5
6
  import * as SDK from '../../core/sdk/sdk.js';
6
7
  import * as Bindings from '../bindings/bindings.js';
7
8
  import * as Formatter from '../formatter/formatter.js';
8
9
  import * as TextUtils from '../text_utils/text_utils.js';
9
- import { scopeTreeForScript } from './ScopeTreeCache.js';
10
10
  const scopeToCachedIdentifiersMap = new WeakMap();
11
11
  const cachedMapByCallFrame = new WeakMap();
12
12
  export async function getTextFor(contentProvider) {
@@ -31,15 +31,7 @@ const computeScopeTree = async function (script) {
31
31
  if (!script.sourceMapURL) {
32
32
  return null;
33
33
  }
34
- const text = await getTextFor(script);
35
- if (!text) {
36
- return null;
37
- }
38
- const scopeTree = await scopeTreeForScript(script);
39
- if (!scopeTree) {
40
- return null;
41
- }
42
- return { scopeTree, text };
34
+ return await SDK.ScopeTreeCache.scopeTreeForScript(script);
43
35
  };
44
36
  /**
45
37
  * @returns the scope chain from outer-most to inner-most scope where the inner-most
@@ -309,7 +301,9 @@ export const resolveScopeChain = async function (callFrame) {
309
301
  if (scopeChain) {
310
302
  return scopeChain;
311
303
  }
312
- scopeChain = callFrame.script.sourceMap()?.resolveScopeChain(callFrame);
304
+ scopeChain = Root.Runtime.experiments.isEnabled("use-source-map-scopes" /* Root.Runtime.ExperimentName.USE_SOURCE_MAP_SCOPES */) ?
305
+ callFrame.script.sourceMap()?.resolveScopeChain(callFrame) :
306
+ null;
313
307
  if (scopeChain) {
314
308
  return scopeChain;
315
309
  }
@@ -3,5 +3,4 @@
3
3
  // found in the LICENSE file.
4
4
  import * as NamesResolver from './NamesResolver.js';
5
5
  import * as ScopeChainModel from './ScopeChainModel.js';
6
- import * as ScopeTreeCache from './ScopeTreeCache.js';
7
- export { NamesResolver, ScopeChainModel, ScopeTreeCache, };
6
+ export { NamesResolver, ScopeChainModel, };
@@ -1,6 +1,14 @@
1
1
  // Copyright 2025 The Chromium Authors
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
+ /**
5
+ * @returns whether the frame is a V8 builtin frame e.g. Array.map. Builtin frames
6
+ * have neither source position nor script or URL. They only have a name.
7
+ */
8
+ export function isBuiltinFrame(rawFrame) {
9
+ return rawFrame.lineNumber === -1 && rawFrame.columnNumber === -1 && !Boolean(rawFrame.scriptId) &&
10
+ !Boolean(rawFrame.url);
11
+ }
4
12
  export class FrameNode {
5
13
  parent;
6
14
  children = [];
@@ -70,8 +70,11 @@ export class Model extends EventTarget {
70
70
  * });
71
71
  * void this.traceModel.parse(events);
72
72
  **/
73
- async parse(traceEvents, config) {
74
- const metadata = config?.metadata || {};
73
+ async parse(traceEvents, config = {}) {
74
+ if (config.showAllEvents === undefined) {
75
+ config.showAllEvents = this.#config.showAllEvents;
76
+ }
77
+ const metadata = config.metadata || {};
75
78
  // During parsing, periodically update any listeners on each processors'
76
79
  // progress (if they have any updates).
77
80
  const onTraceUpdate = (event) => {
@@ -84,7 +87,7 @@ export class Model extends EventTarget {
84
87
  try {
85
88
  // Wait for all outstanding promises before finishing the async execution,
86
89
  // but perform all tasks in parallel.
87
- await this.#processor.parse(traceEvents, config ?? {});
90
+ await this.#processor.parse(traceEvents, config);
88
91
  if (!this.#processor.data) {
89
92
  throw new Error('processor did not parse trace');
90
93
  }