chrome-devtools-frontend 1.0.1650100 → 1.0.1650677

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 (290) hide show
  1. package/.agents/skills/version-control/SKILL.md +5 -1
  2. package/config/typescript/tsconfig.base.json +1 -0
  3. package/front_end/core/host/InspectorFrontendHostAPI.ts +0 -1
  4. package/front_end/core/host/UserMetrics.ts +0 -26
  5. package/front_end/core/sdk/CSSMetadata.ts +72 -0
  6. package/front_end/devtools_compatibility.js +1 -2
  7. package/front_end/foundation/Universe.ts +7 -0
  8. package/front_end/models/ai_assistance/AiAgent2.ts +11 -1
  9. package/front_end/models/ai_assistance/README.md +4 -0
  10. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +2 -0
  11. package/front_end/models/ai_assistance/agents/AiAgent.ts +3 -0
  12. package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +13 -4
  13. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +3 -7
  14. package/front_end/models/ai_assistance/ai_assistance.ts +4 -0
  15. package/front_end/models/ai_assistance/skills/Skill.ts +1 -1
  16. package/front_end/models/ai_assistance/skills/SkillRegistry.ts +2 -0
  17. package/front_end/models/ai_assistance/skills/accessibility.md +13 -0
  18. package/front_end/models/ai_assistance/tools/GetLighthouseAudits.ts +54 -0
  19. package/front_end/models/ai_assistance/tools/ResolveLighthousePath.ts +124 -0
  20. package/front_end/models/ai_assistance/tools/Tool.ts +12 -2
  21. package/front_end/models/ai_assistance/tools/ToolRegistry.ts +4 -0
  22. package/front_end/models/persistence/NetworkPersistenceManager.ts +9 -1
  23. package/front_end/panels/ai_assistance/components/ChatMessage.ts +3 -11
  24. package/front_end/panels/common/ExtensionServer.ts +70 -50
  25. package/front_end/panels/elements/ElementsPanel.ts +1 -1
  26. package/front_end/panels/js_timeline/js_timeline-meta.ts +1 -2
  27. package/front_end/panels/network/RequestConditionsDrawer.ts +236 -198
  28. package/front_end/panels/network/RequestHeadersView.ts +2 -2
  29. package/front_end/panels/network/components/RequestHeadersView.css +1 -0
  30. package/front_end/panels/network/components/ResponseHeaderSection.css +5 -1
  31. package/front_end/panels/network/requestConditionsDrawer.css +3 -0
  32. package/front_end/panels/recorder/testing/RecorderHelpers.ts +2 -0
  33. package/front_end/panels/timeline/timeline-meta.ts +1 -1
  34. package/front_end/panels/whats_new/ReleaseNoteText.ts +12 -6
  35. package/front_end/panels/whats_new/resources/WNDT.md +8 -7
  36. package/front_end/third_party/chromium/README.chromium +1 -1
  37. package/front_end/third_party/puppeteer/README.chromium +2 -2
  38. package/front_end/third_party/puppeteer/package/README.md +14 -0
  39. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +60 -24
  40. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +271 -164
  41. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts +2 -6
  42. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts.map +1 -1
  43. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js +2 -2
  44. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js.map +1 -1
  45. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js +2 -2
  46. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js.map +1 -1
  47. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js +11 -7
  48. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js.map +1 -1
  49. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.d.ts.map +1 -1
  50. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.js +3 -10
  51. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.js.map +1 -1
  52. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts +9 -4
  53. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts.map +1 -1
  54. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js +4 -4
  55. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js.map +1 -1
  56. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/WebWorker.d.ts +13 -0
  57. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/WebWorker.d.ts.map +1 -1
  58. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/WebWorker.js +14 -0
  59. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/WebWorker.js.map +1 -1
  60. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.js +5 -5
  61. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.js.map +1 -1
  62. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.js +2 -2
  63. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.js.map +1 -1
  64. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Browser.js +3 -3
  65. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Browser.js.map +1 -1
  66. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BrowserConnector.js +5 -3
  67. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BrowserConnector.js.map +1 -1
  68. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BrowserContext.js +6 -6
  69. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BrowserContext.js.map +1 -1
  70. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.d.ts +1 -1
  71. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.d.ts.map +1 -1
  72. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.js +3 -3
  73. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.js.map +1 -1
  74. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Deserializer.js +2 -2
  75. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Deserializer.js.map +1 -1
  76. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/ExposedFunction.js +6 -6
  77. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/ExposedFunction.js.map +1 -1
  78. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Frame.js +1 -1
  79. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Frame.js.map +1 -1
  80. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts +1 -0
  81. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts.map +1 -1
  82. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js +3 -0
  83. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js.map +1 -1
  84. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Realm.js +1 -1
  85. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Realm.js.map +1 -1
  86. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/BrowsingContext.d.ts +1 -0
  87. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  88. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/BrowsingContext.js +11 -0
  89. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  90. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.d.ts.map +1 -1
  91. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js +4 -4
  92. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js.map +1 -1
  93. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Binding.js +3 -3
  94. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Binding.js.map +1 -1
  95. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts.map +1 -1
  96. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js +13 -2
  97. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js.map +1 -1
  98. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/BrowserConnector.js +2 -2
  99. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/BrowserConnector.js.map +1 -1
  100. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Connection.js +2 -2
  101. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Connection.js.map +1 -1
  102. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Coverage.js +2 -2
  103. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Coverage.js.map +1 -1
  104. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ElementHandle.js +1 -1
  105. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ElementHandle.js.map +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.d.ts +1 -0
  107. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.d.ts.map +1 -1
  108. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.js +25 -4
  109. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.js.map +1 -1
  110. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ExecutionContext.js +3 -3
  111. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ExecutionContext.js.map +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Extension.d.ts.map +1 -1
  113. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Extension.js +9 -11
  114. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Extension.js.map +1 -1
  115. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js +3 -3
  116. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js.map +1 -1
  117. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.d.ts.map +1 -1
  118. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.js +7 -7
  119. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.js.map +1 -1
  120. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js +1 -1
  121. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js.map +1 -1
  122. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/JSHandle.js +1 -1
  123. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/JSHandle.js.map +1 -1
  124. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts +3 -1
  125. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  126. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js +18 -10
  127. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js.map +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts +1 -0
  129. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts.map +1 -1
  130. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.js +17 -11
  131. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.js.map +1 -1
  132. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js +3 -3
  133. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js.map +1 -1
  134. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.d.ts.map +1 -1
  135. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js +28 -10
  136. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js.map +1 -1
  137. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.d.ts.map +1 -1
  138. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.js +10 -6
  139. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.js.map +1 -1
  140. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebWorker.d.ts +3 -0
  141. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebWorker.d.ts.map +1 -1
  142. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebWorker.js +20 -5
  143. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebWorker.js.map +1 -1
  144. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.d.ts.map +1 -1
  145. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js +11 -0
  146. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js.map +1 -1
  147. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.js +2 -2
  148. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.js.map +1 -1
  149. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/CallbackRegistry.js +2 -2
  150. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/CallbackRegistry.js.map +1 -1
  151. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Configuration.d.ts +4 -2
  152. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Configuration.d.ts.map +1 -1
  153. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts +26 -13
  154. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts.map +1 -1
  155. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts +1 -6
  156. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts.map +1 -1
  157. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js +24 -33
  158. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js.map +1 -1
  159. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/EventEmitter.js +2 -2
  160. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/EventEmitter.js.map +1 -1
  161. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts +8 -1
  162. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts.map +1 -1
  163. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js +8 -1
  164. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js.map +1 -1
  165. package/front_end/third_party/puppeteer/package/lib/puppeteer/environment.d.ts +2 -0
  166. package/front_end/third_party/puppeteer/package/lib/puppeteer/environment.d.ts.map +1 -1
  167. package/front_end/third_party/puppeteer/package/lib/puppeteer/environment.js +4 -2
  168. package/front_end/third_party/puppeteer/package/lib/puppeteer/environment.js.map +1 -1
  169. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts +1 -1
  170. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts.map +1 -1
  171. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js +1 -1
  172. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js.map +1 -1
  173. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/TextContent.d.ts.map +1 -1
  174. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/TextContent.js +15 -5
  175. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/TextContent.js.map +1 -1
  176. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts +5 -1
  177. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  178. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js +17 -16
  179. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js.map +1 -1
  180. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  181. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ChromeLauncher.js +14 -9
  182. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ChromeLauncher.js.map +1 -1
  183. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/FirefoxLauncher.js +2 -2
  184. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/FirefoxLauncher.js.map +1 -1
  185. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.js +2 -2
  186. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.js.map +1 -1
  187. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/PipeTransport.js +3 -3
  188. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/PipeTransport.js.map +1 -1
  189. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.d.ts +20 -0
  190. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.d.ts.map +1 -1
  191. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.js +38 -9
  192. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.js.map +1 -1
  193. package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.d.ts +7 -0
  194. package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.d.ts.map +1 -0
  195. package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.js +16 -0
  196. package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.js.map +1 -0
  197. package/front_end/third_party/puppeteer/package/lib/puppeteer/puppeteer-core.d.ts +1 -0
  198. package/front_end/third_party/puppeteer/package/lib/puppeteer/puppeteer-core.d.ts.map +1 -1
  199. package/front_end/third_party/puppeteer/package/lib/puppeteer/puppeteer-core.js +3 -8
  200. package/front_end/third_party/puppeteer/package/lib/puppeteer/puppeteer-core.js.map +1 -1
  201. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
  202. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
  203. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js.map +1 -1
  204. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
  205. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
  206. package/front_end/third_party/puppeteer/package/lib/types.d.ts +60 -24
  207. package/front_end/third_party/puppeteer/package/package.json +4 -4
  208. package/front_end/third_party/puppeteer/package/src/api/Browser.ts +4 -8
  209. package/front_end/third_party/puppeteer/package/src/api/BrowserContext.ts +2 -2
  210. package/front_end/third_party/puppeteer/package/src/api/HTTPRequest.ts +10 -10
  211. package/front_end/third_party/puppeteer/package/src/api/JSHandle.ts +3 -10
  212. package/front_end/third_party/puppeteer/package/src/api/Page.ts +14 -8
  213. package/front_end/third_party/puppeteer/package/src/api/WebWorker.ts +30 -0
  214. package/front_end/third_party/puppeteer/package/src/api/locators/locators.ts +5 -5
  215. package/front_end/third_party/puppeteer/package/src/bidi/BidiOverCdp.ts +2 -2
  216. package/front_end/third_party/puppeteer/package/src/bidi/Browser.ts +3 -3
  217. package/front_end/third_party/puppeteer/package/src/bidi/BrowserConnector.ts +5 -3
  218. package/front_end/third_party/puppeteer/package/src/bidi/BrowserContext.ts +6 -6
  219. package/front_end/third_party/puppeteer/package/src/bidi/Connection.ts +4 -4
  220. package/front_end/third_party/puppeteer/package/src/bidi/Deserializer.ts +2 -2
  221. package/front_end/third_party/puppeteer/package/src/bidi/ExposedFunction.ts +6 -6
  222. package/front_end/third_party/puppeteer/package/src/bidi/Frame.ts +1 -1
  223. package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +4 -0
  224. package/front_end/third_party/puppeteer/package/src/bidi/Realm.ts +1 -1
  225. package/front_end/third_party/puppeteer/package/src/bidi/core/BrowsingContext.ts +11 -0
  226. package/front_end/third_party/puppeteer/package/src/cdp/Accessibility.ts +6 -4
  227. package/front_end/third_party/puppeteer/package/src/cdp/Binding.ts +3 -3
  228. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +14 -2
  229. package/front_end/third_party/puppeteer/package/src/cdp/BrowserConnector.ts +2 -2
  230. package/front_end/third_party/puppeteer/package/src/cdp/Connection.ts +2 -2
  231. package/front_end/third_party/puppeteer/package/src/cdp/Coverage.ts +2 -2
  232. package/front_end/third_party/puppeteer/package/src/cdp/ElementHandle.ts +1 -1
  233. package/front_end/third_party/puppeteer/package/src/cdp/EmulationManager.ts +36 -4
  234. package/front_end/third_party/puppeteer/package/src/cdp/ExecutionContext.ts +3 -3
  235. package/front_end/third_party/puppeteer/package/src/cdp/Extension.ts +16 -17
  236. package/front_end/third_party/puppeteer/package/src/cdp/Frame.ts +3 -3
  237. package/front_end/third_party/puppeteer/package/src/cdp/FrameManager.ts +12 -7
  238. package/front_end/third_party/puppeteer/package/src/cdp/HTTPRequest.ts +1 -1
  239. package/front_end/third_party/puppeteer/package/src/cdp/JSHandle.ts +1 -1
  240. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +22 -11
  241. package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +18 -10
  242. package/front_end/third_party/puppeteer/package/src/cdp/Target.ts +3 -3
  243. package/front_end/third_party/puppeteer/package/src/cdp/TargetManager.ts +37 -12
  244. package/front_end/third_party/puppeteer/package/src/cdp/WebMCP.ts +11 -9
  245. package/front_end/third_party/puppeteer/package/src/cdp/WebWorker.ts +33 -5
  246. package/front_end/third_party/puppeteer/package/src/common/BrowserConnector.ts +11 -0
  247. package/front_end/third_party/puppeteer/package/src/common/BrowserWebSocketTransport.ts +2 -2
  248. package/front_end/third_party/puppeteer/package/src/common/CallbackRegistry.ts +2 -2
  249. package/front_end/third_party/puppeteer/package/src/common/Configuration.ts +4 -2
  250. package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +26 -13
  251. package/front_end/third_party/puppeteer/package/src/common/Debug.ts +30 -40
  252. package/front_end/third_party/puppeteer/package/src/common/EventEmitter.ts +2 -2
  253. package/front_end/third_party/puppeteer/package/src/common/util.ts +9 -1
  254. package/front_end/third_party/puppeteer/package/src/environment.ts +7 -3
  255. package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
  256. package/front_end/third_party/puppeteer/package/src/injected/TextContent.ts +15 -5
  257. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +23 -23
  258. package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +19 -13
  259. package/front_end/third_party/puppeteer/package/src/node/FirefoxLauncher.ts +2 -2
  260. package/front_end/third_party/puppeteer/package/src/node/NodeWebSocketTransport.ts +2 -2
  261. package/front_end/third_party/puppeteer/package/src/node/PipeTransport.ts +3 -3
  262. package/front_end/third_party/puppeteer/package/src/node/ScreenRecorder.ts +44 -9
  263. package/front_end/third_party/puppeteer/package/src/node-env-setup.ts +18 -0
  264. package/front_end/third_party/puppeteer/package/src/puppeteer-core.ts +5 -9
  265. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  266. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  267. package/front_end/third_party/puppeteer/puppeteer-tsconfig.json +1 -0
  268. package/front_end/third_party/third-party-web/lib/nostats-subset.js +21 -15
  269. package/front_end/third_party/third-party-web/package/README.md +619 -582
  270. package/front_end/third_party/third-party-web/package/dist/entities-httparchive-nostats.json +1 -1
  271. package/front_end/third_party/third-party-web/package/dist/entities-httparchive.json +1 -1
  272. package/front_end/third_party/third-party-web/package/dist/entities-nostats.json +1 -1
  273. package/front_end/third_party/third-party-web/package/dist/entities.json +1 -1
  274. package/front_end/third_party/third-party-web/package/lib/create-entity-finder-api.js +27 -15
  275. package/front_end/third_party/third-party-web/package/lib/create-entity-finder-api.test.js +14 -0
  276. package/front_end/third_party/third-party-web/package/lib/entities.test.js +10 -0
  277. package/front_end/third_party/third-party-web/package/lib/index.test.js +6 -6
  278. package/front_end/third_party/third-party-web/package/lib/markdown/template.md +1 -3
  279. package/front_end/third_party/third-party-web/package/package.json +7 -3
  280. package/front_end/third_party/third-party-web/package.json +1 -1
  281. package/front_end/tsconfig.json +1 -2
  282. package/front_end/ui/components/buttons/floatingButton.css +3 -3
  283. package/front_end/ui/components/lists/list.css +2 -0
  284. package/front_end/ui/legacy/ListWidget.ts +8 -5
  285. package/front_end/ui/legacy/TextPrompt.ts +5 -2
  286. package/front_end/ui/legacy/textPrompt.css +1 -0
  287. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  288. package/inspector_overlay/tsconfig.json +3 -10
  289. package/mcp/tsconfig.json +1 -5
  290. package/package.json +1 -2
@@ -3,9 +3,11 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import {ExecuteJavaScriptTool} from './ExecuteJavaScript.js';
6
+ import {GetLighthouseAuditsTool} from './GetLighthouseAudits.js';
6
7
  import {GetNetworkRequestDetailsTool} from './GetNetworkRequestDetails.js';
7
8
  import {GetStylesTool} from './GetStyles.js';
8
9
  import {ListNetworkRequestsTool} from './ListNetworkRequests.js';
10
+ import {ResolveLighthousePathTool} from './ResolveLighthousePath.js';
9
11
  import {type AllToolsContext, type Tool, type ToolArgs, ToolName} from './Tool.js';
10
12
 
11
13
  /**
@@ -21,6 +23,8 @@ export const TOOLS = {
21
23
  [ToolName.GET_STYLES]: new GetStylesTool(),
22
24
  [ToolName.LIST_NETWORK_REQUESTS]: new ListNetworkRequestsTool(),
23
25
  [ToolName.GET_NETWORK_REQUEST_DETAILS]: new GetNetworkRequestDetailsTool(),
26
+ [ToolName.GET_LIGHTHOUSE_AUDITS]: new GetLighthouseAuditsTool(),
27
+ [ToolName.RESOLVE_LIGHTHOUSE_PATH]: new ResolveLighthousePathTool(),
24
28
  };
25
29
 
26
30
  /**
@@ -888,6 +888,10 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
888
888
  }
889
889
 
890
890
  handleHeaderInterception(interceptedRequest: SDK.NetworkManager.InterceptedRequest): Protocol.Fetch.HeaderEntry[] {
891
+ if (NetworkPersistenceManager.isForbiddenNetworkUrl(interceptedRequest.request.url as
892
+ Platform.DevToolsPath.UrlString)) {
893
+ return [];
894
+ }
891
895
  let result: Protocol.Fetch.HeaderEntry[] = interceptedRequest.responseHeaders || [];
892
896
  // 'rawPathFromUrl()''s return value is already (singly-)encoded, so we can
893
897
  // treat it as an 'EncodedPathString' here.
@@ -914,8 +918,12 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
914
918
  if (!this.#active || (method === 'OPTIONS')) {
915
919
  return;
916
920
  }
921
+ const requestUrl = interceptedRequest.request.url as Platform.DevToolsPath.UrlString;
922
+ if (NetworkPersistenceManager.isForbiddenNetworkUrl(requestUrl)) {
923
+ return;
924
+ }
917
925
  const proj = this.#project as FileSystem;
918
- const path = this.fileUrlFromNetworkUrl(interceptedRequest.request.url as Platform.DevToolsPath.UrlString);
926
+ const path = this.fileUrlFromNetworkUrl(requestUrl);
919
927
  const fileSystemUISourceCode = proj.uiSourceCodeForURL(path);
920
928
  let responseHeaders = this.handleHeaderInterception(interceptedRequest);
921
929
  if (!fileSystemUISourceCode && !responseHeaders.length) {
@@ -223,10 +223,6 @@ const UIStringsNotTranslate = {
223
223
  * @description Accessible label for the reveal button in the render-blocking requests widget.
224
224
  */
225
225
  revealRenderBlockingBreakdown: 'Reveal render-blocking requests',
226
- /**
227
- * @description Accessible label for the reveal button in the LCP element widget.
228
- */
229
- revealLcpElement: 'Reveal LCP element',
230
226
  /**
231
227
  * @description Accessible label for the reveal button in the performance summary widget.
232
228
  */
@@ -291,10 +287,6 @@ const UIStringsNotTranslate = {
291
287
  * @description Title for the 3rd parties widget.
292
288
  */
293
289
  thirdParties: '3rd parties',
294
- /**
295
- * @description Title for the LCP element widget.
296
- */
297
- lcpElement: 'LCP element',
298
290
  /**
299
291
  * @description Title for the performance summary widget.
300
292
  */
@@ -987,7 +979,7 @@ interface WidgetMakerResponse {
987
979
  // Can be null if the widget is only used to add the Reveal CTA.
988
980
  title: Lit.LitTemplate|Platform.UIString.LocalizedString|null;
989
981
  jslogContext?: string;
990
- accessibleRevealLabel: string;
982
+ accessibleRevealLabel: Platform.UIString.LocalizedString;
991
983
  }
992
984
 
993
985
  const nodeCache = new Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode>();
@@ -1620,8 +1612,8 @@ async function makeDomTreeWidget(widgetData: DomTreeAiWidget): Promise<WidgetMak
1620
1612
  return {
1621
1613
  renderedWidget,
1622
1614
  revealable: new SDK.DOMModel.DeferredDOMNode(root.domModel().target(), root.backendNodeId()),
1623
- accessibleRevealLabel: lockedString(UIStringsNotTranslate.revealLcpElement),
1624
- title: lockedString(UIStringsNotTranslate.lcpElement),
1615
+ accessibleRevealLabel: widgetData.data.accessibleRevealLabel,
1616
+ title: widgetData.data.title,
1625
1617
  jslogContext: 'dom-snapshot',
1626
1618
  };
1627
1619
  }
@@ -85,7 +85,8 @@ export class HostsPolicy {
85
85
  }
86
86
 
87
87
  class RegisteredExtension {
88
- constructor(readonly name: string, readonly hostsPolicy: HostsPolicy, readonly allowFileAccess: boolean) {
88
+ constructor(readonly origin: string, readonly name: string, readonly hostsPolicy: HostsPolicy,
89
+ readonly allowFileAccess: boolean) {
89
90
  }
90
91
 
91
92
  isAllowedOnTarget(inspectedURL?: Platform.DevToolsPath.UrlString): boolean {
@@ -104,6 +105,14 @@ class RegisteredExtension {
104
105
  return false;
105
106
  }
106
107
 
108
+ if (parsedURL.protocol === 'chrome-extension:') {
109
+ if (parsedURL.origin !== this.origin) {
110
+ if (!Root.Runtime.hostConfig.extensionsOnChromeUrls?.enabled) {
111
+ return false;
112
+ }
113
+ }
114
+ }
115
+
107
116
  if (!ExtensionServer.canInspectURL(inspectedURL)) {
108
117
  return false;
109
118
  }
@@ -953,27 +962,45 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
953
962
  */
954
963
  private extensionAllowedOnContentProvider(
955
964
  contentProvider: TextUtils.ContentProvider.ContentProvider, port: MessagePort): boolean {
956
- if (!(contentProvider instanceof Workspace.UISourceCode.UISourceCode)) {
957
- return this.extensionAllowedOnURL(contentProvider.contentURL(), port);
965
+ // 1. Exception for Scripts with sourceURL
966
+ if (contentProvider instanceof Workspace.UISourceCode.UISourceCode &&
967
+ contentProvider.contentType() === Common.ResourceType.resourceTypes.Script) {
968
+ const scripts =
969
+ Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().scriptsForUISourceCode(contentProvider);
970
+ if (scripts.length > 0) {
971
+ const uiSourceCodeTarget =
972
+ Bindings.NetworkProject.NetworkProject.targetForUISourceCode(contentProvider) ?? undefined;
973
+ if (uiSourceCodeTarget && !this.extensionAllowedOnTarget(uiSourceCodeTarget, port)) {
974
+ return false;
975
+ }
976
+ return scripts.every(script => {
977
+ if (script.hasSourceURL) {
978
+ return this.extensionAllowedOnTarget(script.target(), port);
979
+ }
980
+ return this.extensionAllowedOnURL(script.contentURL(), port) &&
981
+ this.extensionAllowedOnTarget(script.target(), port);
982
+ });
983
+ }
958
984
  }
959
985
 
960
- if (contentProvider.contentType() !== Common.ResourceType.resourceTypes.Script) {
961
- // We only check sourceURL magic comments for scripts (excluding ones coming from source maps).
962
- return this.extensionAllowedOnURL(contentProvider.contentURL(), port);
986
+ // 2. Standard Policy: Both URL and Target must be allowed
987
+
988
+ // 2a. Check URL
989
+ if (!this.extensionAllowedOnURL(contentProvider.contentURL(), port)) {
990
+ return false;
963
991
  }
964
992
 
965
- const scripts =
966
- Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().scriptsForUISourceCode(contentProvider);
967
- if (scripts.length === 0) {
968
- return this.extensionAllowedOnURL(contentProvider.contentURL(), port);
993
+ // 2b. Check Target (if one can be identified)
994
+ let target: SDK.Target.Target|undefined;
995
+ if (contentProvider instanceof SDK.NetworkRequest.NetworkRequest) {
996
+ target = SDK.NetworkManager.NetworkManager.forRequest(contentProvider)?.target();
997
+ } else if (contentProvider instanceof SDK.Resource.Resource) {
998
+ target = contentProvider.frame()?.resourceTreeModel().target();
999
+ } else if (contentProvider instanceof Workspace.UISourceCode.UISourceCode) {
1000
+ target = Bindings.NetworkProject.NetworkProject.targetForUISourceCode(contentProvider) ?? undefined;
969
1001
  }
970
1002
 
971
- return scripts.every(script => {
972
- if (script.hasSourceURL) {
973
- return this.extensionAllowedOnTarget(script.target(), port);
974
- }
975
- return this.extensionAllowedOnURL(script.contentURL(), port);
976
- });
1003
+ return !target || this.extensionAllowedOnTarget(target, port);
977
1004
  }
978
1005
 
979
1006
  /**
@@ -998,7 +1025,10 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
998
1025
  return {uiSourceCode};
999
1026
  }
1000
1027
 
1001
- private extensionAllowedOnTarget(target: SDK.Target.Target, port: MessagePort): boolean {
1028
+ private extensionAllowedOnTarget(target: SDK.Target.Target|undefined, port: MessagePort): boolean {
1029
+ if (!target) {
1030
+ return false;
1031
+ }
1002
1032
  return this.extensionAllowedOnURL(target.inspectedURL(), port);
1003
1033
  }
1004
1034
 
@@ -1061,7 +1091,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
1061
1091
  return this.status.E_BADARG('command', `expected ${Extensions.ExtensionAPI.PrivateAPI.Commands.GetHAR}`);
1062
1092
  }
1063
1093
  const requests =
1064
- Logs.NetworkLog.NetworkLog.instance().requests().filter(r => this.extensionAllowedOnURL(r.url(), port));
1094
+ Logs.NetworkLog.NetworkLog.instance().requests().filter(r => this.extensionAllowedOnContentProvider(r, port));
1065
1095
  const harLog = await HAR.Log.Log.build(requests, {sanitize: false});
1066
1096
  for (let i = 0; i < harLog.entries.length; ++i) {
1067
1097
  // @ts-expect-error
@@ -1310,26 +1340,34 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
1310
1340
 
1311
1341
  private notifyResourceAdded(event: Common.EventTarget.EventTargetEvent<Workspace.UISourceCode.UISourceCode>): void {
1312
1342
  const uiSourceCode = event.data;
1313
- this.postNotification(
1314
- Extensions.ExtensionAPI.PrivateAPI.Events.ResourceAdded, [this.makeResource(uiSourceCode)],
1315
- extension => extension.isAllowedOnTarget(uiSourceCode.url()));
1343
+ const target = Bindings.NetworkProject.NetworkProject.targetForUISourceCode(uiSourceCode);
1344
+ const targetUrl = target?.inspectedURL();
1345
+ this.postNotification(Extensions.ExtensionAPI.PrivateAPI.Events.ResourceAdded, [this.makeResource(uiSourceCode)],
1346
+ extension => extension.isAllowedOnTarget(uiSourceCode.url()) &&
1347
+ (!targetUrl || extension.isAllowedOnTarget(targetUrl)));
1316
1348
  }
1317
1349
 
1318
1350
  private notifyUISourceCodeContentCommitted(
1319
1351
  event: Common.EventTarget.EventTargetEvent<Workspace.Workspace.WorkingCopyCommittedEvent>): void {
1320
1352
  const {uiSourceCode, content} = event.data;
1321
- this.postNotification(
1322
- Extensions.ExtensionAPI.PrivateAPI.Events.ResourceContentCommitted, [this.makeResource(uiSourceCode), content],
1323
- extension => extension.isAllowedOnTarget(uiSourceCode.url()));
1353
+ const target = Bindings.NetworkProject.NetworkProject.targetForUISourceCode(uiSourceCode);
1354
+ const targetUrl = target?.inspectedURL();
1355
+ this.postNotification(Extensions.ExtensionAPI.PrivateAPI.Events.ResourceContentCommitted,
1356
+ [this.makeResource(uiSourceCode), content],
1357
+ extension => extension.isAllowedOnTarget(uiSourceCode.url()) &&
1358
+ (!targetUrl || extension.isAllowedOnTarget(targetUrl)));
1324
1359
  }
1325
1360
 
1326
1361
  private async notifyRequestFinished(event: Common.EventTarget.EventTargetEvent<SDK.NetworkRequest.NetworkRequest>):
1327
1362
  Promise<void> {
1328
1363
  const request = event.data;
1329
1364
  const entry = await HAR.Log.Entry.build(request, {sanitize: false});
1365
+ const networkManager = SDK.NetworkManager.NetworkManager.forRequest(request);
1366
+ const targetUrl = networkManager?.target()?.inspectedURL();
1330
1367
  this.postNotification(
1331
1368
  Extensions.ExtensionAPI.PrivateAPI.Events.NetworkRequestFinished, [this.requestId(request), entry],
1332
- extension => extension.isAllowedOnTarget(entry.request.url));
1369
+ extension => extension.isAllowedOnTarget(entry.request.url as Platform.DevToolsPath.UrlString) &&
1370
+ (!targetUrl || extension.isAllowedOnTarget(targetUrl)));
1333
1371
  }
1334
1372
 
1335
1373
  private notifyElementsSelectionChanged(): void {
@@ -1388,7 +1426,8 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
1388
1426
  const startPageURL = new URL((startPage));
1389
1427
  const extensionOrigin = startPageURL.origin;
1390
1428
  const name = extensionInfo.name || `Extension ${extensionOrigin}`;
1391
- const extensionRegistration = new RegisteredExtension(name, hostsPolicy, Boolean(extensionInfo.allowFileAccess));
1429
+ const extensionRegistration =
1430
+ new RegisteredExtension(extensionOrigin, name, hostsPolicy, Boolean(extensionInfo.allowFileAccess));
1392
1431
  if (!extensionRegistration.isAllowedOnTarget(inspectedURL)) {
1393
1432
  this.#pendingExtensions.push(extensionInfo);
1394
1433
  return;
@@ -1494,11 +1533,11 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
1494
1533
  private registerAutosubscriptionTargetManagerHandler<Events, T extends keyof Events>(
1495
1534
  eventTopic: string, modelClass: new(arg1: SDK.Target.Target) => SDK.SDKModel.SDKModel<Events>,
1496
1535
  frontendEventType: T, handler: Common.EventTarget.EventListener<Events, T>): void {
1497
- this.registerSubscriptionHandler(
1498
- eventTopic,
1499
- () => SDK.TargetManager.TargetManager.instance().addModelListener(modelClass, frontendEventType, handler, this),
1500
- () => SDK.TargetManager.TargetManager.instance().removeModelListener(
1501
- modelClass, frontendEventType, handler, this));
1536
+ this.registerSubscriptionHandler(eventTopic,
1537
+ () => SDK.TargetManager.TargetManager.instance().addModelListener(
1538
+ modelClass, frontendEventType, handler, this, {scoped: true}),
1539
+ () => SDK.TargetManager.TargetManager.instance().removeModelListener(
1540
+ modelClass, frontendEventType, handler, this));
1502
1541
  }
1503
1542
 
1504
1543
  private registerResourceContentCommittedHandler(
@@ -1609,25 +1648,6 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
1609
1648
  return this.status.E_FAILED('Permission denied');
1610
1649
  }
1611
1650
 
1612
- try {
1613
- const parsedUrl = new URL(frame.url);
1614
- let targetType = Host.UserMetrics.ExtensionEvalTarget.WEB_PAGE;
1615
- if (parsedUrl.protocol === 'chrome-extension:') {
1616
- if (parsedUrl.origin === securityOrigin) {
1617
- targetType = Host.UserMetrics.ExtensionEvalTarget.SAME_EXTENSION;
1618
- } else {
1619
- targetType = Host.UserMetrics.ExtensionEvalTarget.OTHER_EXTENSION;
1620
- if (!Root.Runtime.hostConfig.extensionsOnChromeUrls?.enabled) {
1621
- return this.status.E_FAILED(
1622
- 'Access to extension URLs is restricted; use --extensions-on-chrome-urls to enable.');
1623
- }
1624
- }
1625
- }
1626
- Host.userMetrics.extensionEvalTarget(targetType);
1627
- } catch {
1628
- // Ignore invalid URLs.
1629
- }
1630
-
1631
1651
  void context
1632
1652
  .evaluate(
1633
1653
  {
@@ -1627,7 +1627,7 @@ export class PseudoStateMarkerDecorator implements MarkerDecorator {
1627
1627
  return null;
1628
1628
  }
1629
1629
  return {
1630
- color: '--sys-color-orange-bright',
1630
+ color: 'var(--sys-color-orange-bright)',
1631
1631
  title: i18nString(UIStrings.elementStateS, {PH1: ':' + pseudoState.join(', :')}),
1632
1632
  };
1633
1633
  }
@@ -4,7 +4,6 @@
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
- import * as SDK from '../../core/sdk/sdk.js';
8
7
  import * as UI from '../../ui/legacy/legacy.js';
9
8
  import type * as Timeline from '../timeline/timeline.js';
10
9
 
@@ -72,7 +71,7 @@ UI.ViewManager.registerViewExtension({
72
71
  isPreviewFeature: true,
73
72
  async loadView(universe) {
74
73
  const Timeline = await loadTimelineModule();
75
- const resourceLoader = universe.context.get(SDK.PageResourceLoader.PageResourceLoader);
74
+ const {pageResourceLoader: resourceLoader} = universe;
76
75
  return Timeline.TimelinePanel.TimelinePanel.instance({forceNew: true, resourceLoader});
77
76
  },
78
77
  });