@sentry/browser 11.0.0-alpha.0 → 11.0.0-alpha.2

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 (240) hide show
  1. package/build/npm/cjs/dev/client.js.map +1 -1
  2. package/build/npm/cjs/dev/helpers.js +2 -1
  3. package/build/npm/cjs/dev/helpers.js.map +1 -1
  4. package/build/npm/cjs/dev/index.js +7 -4
  5. package/build/npm/cjs/dev/index.js.map +1 -1
  6. package/build/npm/cjs/dev/integrations/bfcache.js +113 -0
  7. package/build/npm/cjs/dev/integrations/bfcache.js.map +1 -0
  8. package/build/npm/cjs/dev/integrations/breadcrumbs.js +1 -1
  9. package/build/npm/cjs/dev/integrations/breadcrumbs.js.map +1 -1
  10. package/build/npm/cjs/dev/integrations/fetchStreamPerformance.js +11 -11
  11. package/build/npm/cjs/dev/integrations/fetchStreamPerformance.js.map +1 -1
  12. package/build/npm/cjs/dev/integrations/globalhandlers.js +2 -1
  13. package/build/npm/cjs/dev/integrations/globalhandlers.js.map +1 -1
  14. package/build/npm/cjs/dev/integrations/graphqlClient.js +3 -3
  15. package/build/npm/cjs/dev/integrations/graphqlClient.js.map +1 -1
  16. package/build/npm/cjs/dev/integrations/httpclient.js.map +1 -1
  17. package/build/npm/cjs/dev/integrations/reportingobserver.js +4 -1
  18. package/build/npm/cjs/dev/integrations/reportingobserver.js.map +1 -1
  19. package/build/npm/cjs/dev/integrations/spotlight.js +2 -1
  20. package/build/npm/cjs/dev/integrations/spotlight.js.map +1 -1
  21. package/build/npm/cjs/dev/integrations/view-hierarchy.js +2 -1
  22. package/build/npm/cjs/dev/integrations/view-hierarchy.js.map +1 -1
  23. package/build/npm/cjs/dev/profiling/index.js.map +1 -1
  24. package/build/npm/cjs/dev/profiling/integration.js +21 -91
  25. package/build/npm/cjs/dev/profiling/integration.js.map +1 -1
  26. package/build/npm/cjs/dev/profiling/utils.js +0 -283
  27. package/build/npm/cjs/dev/profiling/utils.js.map +1 -1
  28. package/build/npm/cjs/dev/sdk.js +0 -4
  29. package/build/npm/cjs/dev/sdk.js.map +1 -1
  30. package/build/npm/cjs/dev/tracing/backgroundtab.js +5 -1
  31. package/build/npm/cjs/dev/tracing/backgroundtab.js.map +1 -1
  32. package/build/npm/cjs/dev/tracing/browserTracingIntegration.js +30 -86
  33. package/build/npm/cjs/dev/tracing/browserTracingIntegration.js.map +1 -1
  34. package/build/npm/cjs/dev/tracing/linkedTraces.js +3 -3
  35. package/build/npm/cjs/dev/tracing/linkedTraces.js.map +1 -1
  36. package/build/npm/cjs/dev/tracing/request.js +7 -9
  37. package/build/npm/cjs/dev/tracing/request.js.map +1 -1
  38. package/build/npm/cjs/dev/utils/detectBrowserExtension.js +2 -1
  39. package/build/npm/cjs/dev/utils/detectBrowserExtension.js.map +1 -1
  40. package/build/npm/cjs/dev/utils/lazyLoadIntegration.js +1 -0
  41. package/build/npm/cjs/dev/utils/lazyLoadIntegration.js.map +1 -1
  42. package/build/npm/cjs/prod/client.js.map +1 -1
  43. package/build/npm/cjs/prod/helpers.js +2 -1
  44. package/build/npm/cjs/prod/helpers.js.map +1 -1
  45. package/build/npm/cjs/prod/index.js +7 -4
  46. package/build/npm/cjs/prod/index.js.map +1 -1
  47. package/build/npm/cjs/prod/integrations/bfcache.js +113 -0
  48. package/build/npm/cjs/prod/integrations/bfcache.js.map +1 -0
  49. package/build/npm/cjs/prod/integrations/breadcrumbs.js +1 -1
  50. package/build/npm/cjs/prod/integrations/breadcrumbs.js.map +1 -1
  51. package/build/npm/cjs/prod/integrations/fetchStreamPerformance.js +11 -11
  52. package/build/npm/cjs/prod/integrations/fetchStreamPerformance.js.map +1 -1
  53. package/build/npm/cjs/prod/integrations/globalhandlers.js +2 -1
  54. package/build/npm/cjs/prod/integrations/globalhandlers.js.map +1 -1
  55. package/build/npm/cjs/prod/integrations/graphqlClient.js +3 -3
  56. package/build/npm/cjs/prod/integrations/graphqlClient.js.map +1 -1
  57. package/build/npm/cjs/prod/integrations/httpclient.js.map +1 -1
  58. package/build/npm/cjs/prod/integrations/reportingobserver.js +4 -1
  59. package/build/npm/cjs/prod/integrations/reportingobserver.js.map +1 -1
  60. package/build/npm/cjs/prod/integrations/spotlight.js +2 -1
  61. package/build/npm/cjs/prod/integrations/spotlight.js.map +1 -1
  62. package/build/npm/cjs/prod/integrations/view-hierarchy.js +2 -1
  63. package/build/npm/cjs/prod/integrations/view-hierarchy.js.map +1 -1
  64. package/build/npm/cjs/prod/profiling/index.js.map +1 -1
  65. package/build/npm/cjs/prod/profiling/integration.js +21 -91
  66. package/build/npm/cjs/prod/profiling/integration.js.map +1 -1
  67. package/build/npm/cjs/prod/profiling/utils.js +0 -283
  68. package/build/npm/cjs/prod/profiling/utils.js.map +1 -1
  69. package/build/npm/cjs/prod/sdk.js +0 -4
  70. package/build/npm/cjs/prod/sdk.js.map +1 -1
  71. package/build/npm/cjs/prod/tracing/backgroundtab.js +5 -1
  72. package/build/npm/cjs/prod/tracing/backgroundtab.js.map +1 -1
  73. package/build/npm/cjs/prod/tracing/browserTracingIntegration.js +30 -86
  74. package/build/npm/cjs/prod/tracing/browserTracingIntegration.js.map +1 -1
  75. package/build/npm/cjs/prod/tracing/linkedTraces.js +3 -3
  76. package/build/npm/cjs/prod/tracing/linkedTraces.js.map +1 -1
  77. package/build/npm/cjs/prod/tracing/request.js +7 -9
  78. package/build/npm/cjs/prod/tracing/request.js.map +1 -1
  79. package/build/npm/cjs/prod/utils/detectBrowserExtension.js +2 -1
  80. package/build/npm/cjs/prod/utils/detectBrowserExtension.js.map +1 -1
  81. package/build/npm/cjs/prod/utils/lazyLoadIntegration.js +1 -0
  82. package/build/npm/cjs/prod/utils/lazyLoadIntegration.js.map +1 -1
  83. package/build/npm/esm/dev/client.js.map +1 -1
  84. package/build/npm/esm/dev/helpers.js +2 -1
  85. package/build/npm/esm/dev/helpers.js.map +1 -1
  86. package/build/npm/esm/dev/index.js +4 -4
  87. package/build/npm/esm/dev/integrations/bfcache.js +109 -0
  88. package/build/npm/esm/dev/integrations/bfcache.js.map +1 -0
  89. package/build/npm/esm/dev/integrations/breadcrumbs.js +2 -2
  90. package/build/npm/esm/dev/integrations/breadcrumbs.js.map +1 -1
  91. package/build/npm/esm/dev/integrations/fetchStreamPerformance.js +3 -3
  92. package/build/npm/esm/dev/integrations/fetchStreamPerformance.js.map +1 -1
  93. package/build/npm/esm/dev/integrations/globalhandlers.js +2 -1
  94. package/build/npm/esm/dev/integrations/globalhandlers.js.map +1 -1
  95. package/build/npm/esm/dev/integrations/graphqlClient.js +5 -5
  96. package/build/npm/esm/dev/integrations/graphqlClient.js.map +1 -1
  97. package/build/npm/esm/dev/integrations/httpclient.js.map +1 -1
  98. package/build/npm/esm/dev/integrations/reportingobserver.js +4 -1
  99. package/build/npm/esm/dev/integrations/reportingobserver.js.map +1 -1
  100. package/build/npm/esm/dev/integrations/spotlight.js +2 -1
  101. package/build/npm/esm/dev/integrations/spotlight.js.map +1 -1
  102. package/build/npm/esm/dev/integrations/view-hierarchy.js +2 -1
  103. package/build/npm/esm/dev/integrations/view-hierarchy.js.map +1 -1
  104. package/build/npm/esm/dev/package.json +1 -1
  105. package/build/npm/esm/dev/profiling/index.js.map +1 -1
  106. package/build/npm/esm/dev/profiling/integration.js +22 -92
  107. package/build/npm/esm/dev/profiling/integration.js.map +1 -1
  108. package/build/npm/esm/dev/profiling/utils.js +2 -272
  109. package/build/npm/esm/dev/profiling/utils.js.map +1 -1
  110. package/build/npm/esm/dev/sdk.js +0 -4
  111. package/build/npm/esm/dev/sdk.js.map +1 -1
  112. package/build/npm/esm/dev/tracing/backgroundtab.js +5 -1
  113. package/build/npm/esm/dev/tracing/backgroundtab.js.map +1 -1
  114. package/build/npm/esm/dev/tracing/browserTracingIntegration.js +32 -87
  115. package/build/npm/esm/dev/tracing/browserTracingIntegration.js.map +1 -1
  116. package/build/npm/esm/dev/tracing/linkedTraces.js +3 -3
  117. package/build/npm/esm/dev/tracing/linkedTraces.js.map +1 -1
  118. package/build/npm/esm/dev/tracing/request.js +9 -11
  119. package/build/npm/esm/dev/tracing/request.js.map +1 -1
  120. package/build/npm/esm/dev/utils/detectBrowserExtension.js +2 -1
  121. package/build/npm/esm/dev/utils/detectBrowserExtension.js.map +1 -1
  122. package/build/npm/esm/dev/utils/lazyLoadIntegration.js +1 -0
  123. package/build/npm/esm/dev/utils/lazyLoadIntegration.js.map +1 -1
  124. package/build/npm/esm/prod/client.js.map +1 -1
  125. package/build/npm/esm/prod/helpers.js +2 -1
  126. package/build/npm/esm/prod/helpers.js.map +1 -1
  127. package/build/npm/esm/prod/index.js +4 -4
  128. package/build/npm/esm/prod/integrations/bfcache.js +109 -0
  129. package/build/npm/esm/prod/integrations/bfcache.js.map +1 -0
  130. package/build/npm/esm/prod/integrations/breadcrumbs.js +2 -2
  131. package/build/npm/esm/prod/integrations/breadcrumbs.js.map +1 -1
  132. package/build/npm/esm/prod/integrations/fetchStreamPerformance.js +3 -3
  133. package/build/npm/esm/prod/integrations/fetchStreamPerformance.js.map +1 -1
  134. package/build/npm/esm/prod/integrations/globalhandlers.js +2 -1
  135. package/build/npm/esm/prod/integrations/globalhandlers.js.map +1 -1
  136. package/build/npm/esm/prod/integrations/graphqlClient.js +5 -5
  137. package/build/npm/esm/prod/integrations/graphqlClient.js.map +1 -1
  138. package/build/npm/esm/prod/integrations/httpclient.js.map +1 -1
  139. package/build/npm/esm/prod/integrations/reportingobserver.js +4 -1
  140. package/build/npm/esm/prod/integrations/reportingobserver.js.map +1 -1
  141. package/build/npm/esm/prod/integrations/spotlight.js +2 -1
  142. package/build/npm/esm/prod/integrations/spotlight.js.map +1 -1
  143. package/build/npm/esm/prod/integrations/view-hierarchy.js +2 -1
  144. package/build/npm/esm/prod/integrations/view-hierarchy.js.map +1 -1
  145. package/build/npm/esm/prod/package.json +1 -1
  146. package/build/npm/esm/prod/profiling/index.js.map +1 -1
  147. package/build/npm/esm/prod/profiling/integration.js +22 -92
  148. package/build/npm/esm/prod/profiling/integration.js.map +1 -1
  149. package/build/npm/esm/prod/profiling/utils.js +2 -272
  150. package/build/npm/esm/prod/profiling/utils.js.map +1 -1
  151. package/build/npm/esm/prod/sdk.js +0 -4
  152. package/build/npm/esm/prod/sdk.js.map +1 -1
  153. package/build/npm/esm/prod/tracing/backgroundtab.js +5 -1
  154. package/build/npm/esm/prod/tracing/backgroundtab.js.map +1 -1
  155. package/build/npm/esm/prod/tracing/browserTracingIntegration.js +32 -87
  156. package/build/npm/esm/prod/tracing/browserTracingIntegration.js.map +1 -1
  157. package/build/npm/esm/prod/tracing/linkedTraces.js +3 -3
  158. package/build/npm/esm/prod/tracing/linkedTraces.js.map +1 -1
  159. package/build/npm/esm/prod/tracing/request.js +9 -11
  160. package/build/npm/esm/prod/tracing/request.js.map +1 -1
  161. package/build/npm/esm/prod/utils/detectBrowserExtension.js +2 -1
  162. package/build/npm/esm/prod/utils/detectBrowserExtension.js.map +1 -1
  163. package/build/npm/esm/prod/utils/lazyLoadIntegration.js +1 -0
  164. package/build/npm/esm/prod/utils/lazyLoadIntegration.js.map +1 -1
  165. package/build/npm/types/client.d.ts +22 -1
  166. package/build/npm/types/client.d.ts.map +1 -1
  167. package/build/npm/types/exports.d.ts +2 -2
  168. package/build/npm/types/exports.d.ts.map +1 -1
  169. package/build/npm/types/helpers.d.ts.map +1 -1
  170. package/build/npm/types/index.bundle.d.ts +2 -2
  171. package/build/npm/types/index.bundle.d.ts.map +1 -1
  172. package/build/npm/types/index.bundle.feedback.d.ts +2 -2
  173. package/build/npm/types/index.bundle.feedback.d.ts.map +1 -1
  174. package/build/npm/types/index.bundle.logs.metrics.d.ts +1 -1
  175. package/build/npm/types/index.bundle.logs.metrics.d.ts.map +1 -1
  176. package/build/npm/types/index.bundle.replay.d.ts +2 -2
  177. package/build/npm/types/index.bundle.replay.d.ts.map +1 -1
  178. package/build/npm/types/index.bundle.replay.feedback.d.ts +2 -2
  179. package/build/npm/types/index.bundle.replay.feedback.d.ts.map +1 -1
  180. package/build/npm/types/index.bundle.replay.logs.metrics.d.ts +1 -1
  181. package/build/npm/types/index.bundle.replay.logs.metrics.d.ts.map +1 -1
  182. package/build/npm/types/index.bundle.tracing.d.ts +5 -4
  183. package/build/npm/types/index.bundle.tracing.d.ts.map +1 -1
  184. package/build/npm/types/index.bundle.tracing.logs.metrics.d.ts +4 -3
  185. package/build/npm/types/index.bundle.tracing.logs.metrics.d.ts.map +1 -1
  186. package/build/npm/types/index.bundle.tracing.replay.d.ts +5 -4
  187. package/build/npm/types/index.bundle.tracing.replay.d.ts.map +1 -1
  188. package/build/npm/types/index.bundle.tracing.replay.feedback.d.ts +5 -4
  189. package/build/npm/types/index.bundle.tracing.replay.feedback.d.ts.map +1 -1
  190. package/build/npm/types/index.bundle.tracing.replay.feedback.logs.metrics.d.ts +4 -3
  191. package/build/npm/types/index.bundle.tracing.replay.feedback.logs.metrics.d.ts.map +1 -1
  192. package/build/npm/types/index.bundle.tracing.replay.logs.metrics.d.ts +4 -3
  193. package/build/npm/types/index.bundle.tracing.replay.logs.metrics.d.ts.map +1 -1
  194. package/build/npm/types/index.d.ts +6 -5
  195. package/build/npm/types/index.d.ts.map +1 -1
  196. package/build/npm/types/integrations/bfcache.d.ts +42 -0
  197. package/build/npm/types/integrations/bfcache.d.ts.map +1 -0
  198. package/build/npm/types/integrations/breadcrumbs.d.ts.map +1 -1
  199. package/build/npm/types/integrations/graphqlClient.d.ts.map +1 -1
  200. package/build/npm/types/integrations/httpclient.d.ts.map +1 -1
  201. package/build/npm/types/integrations/interactions.d.ts +2 -0
  202. package/build/npm/types/integrations/interactions.d.ts.map +1 -0
  203. package/build/npm/types/integrations/reportingobserver.d.ts.map +1 -1
  204. package/build/npm/types/integrations/spotlight.d.ts.map +1 -1
  205. package/build/npm/types/integrations/view-hierarchy.d.ts.map +1 -1
  206. package/build/npm/types/profiling/index.d.ts.map +1 -1
  207. package/build/npm/types/profiling/integration.d.ts.map +1 -1
  208. package/build/npm/types/profiling/utils.d.ts +1 -74
  209. package/build/npm/types/profiling/utils.d.ts.map +1 -1
  210. package/build/npm/types/sdk.d.ts.map +1 -1
  211. package/build/npm/types/tracing/backgroundtab.d.ts.map +1 -1
  212. package/build/npm/types/tracing/browserTracingIntegration.d.ts +0 -19
  213. package/build/npm/types/tracing/browserTracingIntegration.d.ts.map +1 -1
  214. package/build/npm/types/tracing/linkedTraces.d.ts.map +1 -1
  215. package/build/npm/types/tracing/request.d.ts +1 -13
  216. package/build/npm/types/tracing/request.d.ts.map +1 -1
  217. package/build/npm/types/utils/detectBrowserExtension.d.ts.map +1 -1
  218. package/build/npm/types/utils/lazyLoadIntegration.d.ts +1 -1
  219. package/build/npm/types/utils/lazyLoadIntegration.d.ts.map +1 -1
  220. package/package.json +10 -9
  221. package/build/npm/cjs/dev/integrations/spanstreaming.js +0 -34
  222. package/build/npm/cjs/dev/integrations/spanstreaming.js.map +0 -1
  223. package/build/npm/cjs/dev/profiling/startProfileForSpan.js +0 -91
  224. package/build/npm/cjs/dev/profiling/startProfileForSpan.js.map +0 -1
  225. package/build/npm/cjs/prod/integrations/spanstreaming.js +0 -34
  226. package/build/npm/cjs/prod/integrations/spanstreaming.js.map +0 -1
  227. package/build/npm/cjs/prod/profiling/startProfileForSpan.js +0 -91
  228. package/build/npm/cjs/prod/profiling/startProfileForSpan.js.map +0 -1
  229. package/build/npm/esm/dev/integrations/spanstreaming.js +0 -31
  230. package/build/npm/esm/dev/integrations/spanstreaming.js.map +0 -1
  231. package/build/npm/esm/dev/profiling/startProfileForSpan.js +0 -89
  232. package/build/npm/esm/dev/profiling/startProfileForSpan.js.map +0 -1
  233. package/build/npm/esm/prod/integrations/spanstreaming.js +0 -31
  234. package/build/npm/esm/prod/integrations/spanstreaming.js.map +0 -1
  235. package/build/npm/esm/prod/profiling/startProfileForSpan.js +0 -89
  236. package/build/npm/esm/prod/profiling/startProfileForSpan.js.map +0 -1
  237. package/build/npm/types/integrations/spanstreaming.d.ts +0 -5
  238. package/build/npm/types/integrations/spanstreaming.d.ts.map +0 -1
  239. package/build/npm/types/profiling/startProfileForSpan.d.ts +0 -8
  240. package/build/npm/types/profiling/startProfileForSpan.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sources":["../../../../src/client.ts"],"sourcesContent":["import type {\n BrowserClientProfilingOptions,\n BrowserClientReplayOptions,\n ClientOptions,\n Event,\n EventHint,\n Options as CoreOptions,\n ParameterizedString,\n Scope,\n SeverityLevel,\n} from '@sentry/core/browser';\nimport { addAutoIpAddressToSession, applySdkMetadata, Client, getSDKSource } from '@sentry/core/browser';\nimport { eventFromException, eventFromMessage } from './eventbuilder';\nimport { WINDOW } from './helpers';\nimport type { BrowserTransportOptions } from './transports/types';\n\n/**\n * A magic string that build tooling can leverage in order to inject a release value into the SDK.\n */\ndeclare const __SENTRY_RELEASE__: string | undefined;\n\ntype BrowserSpecificOptions = BrowserClientReplayOptions &\n BrowserClientProfilingOptions & {\n /** If configured, this URL will be used as base URL for lazy loading integration. */\n cdnBaseUrl?: string;\n\n /**\n * Important: Only set this option if you know what you are doing!\n *\n * By default, the SDK will check if `Sentry.init` is called in a browser extension.\n * In case it is, it will stop initialization and log a warning\n * because browser extensions require a different Sentry initialization process:\n * https://docs.sentry.io/platforms/javascript/best-practices/shared-environments/\n *\n * Setting up the SDK in a browser extension with global error monitoring is not recommended\n * and will likely flood you with errors from other web sites or extensions. This can heavily\n * impact your quota and cause interference with your and other Sentry SDKs in shared environments.\n *\n * If this check wrongfully flags your setup as a browser extension, you can set this\n * option to `true` to skip the check.\n *\n * @default false\n */\n skipBrowserExtensionCheck?: boolean;\n\n /**\n * If you use Spotlight by Sentry during development, use\n * this option to forward captured Sentry events to Spotlight.\n *\n * Either set it to true, or provide a specific Spotlight Sidecar URL.\n *\n * More details: https://spotlightjs.com/\n *\n * IMPORTANT: Only set this option to `true` while developing, not in production!\n */\n spotlight?: boolean | string;\n };\n/**\n * Configuration options for the Sentry Browser SDK.\n * @see @sentry/core Options for more information.\n */\nexport type BrowserOptions = CoreOptions<BrowserTransportOptions> & BrowserSpecificOptions;\n\n/**\n * Configuration options for the Sentry Browser SDK Client class\n * @see BrowserClient for more information.\n */\nexport type BrowserClientOptions = ClientOptions<BrowserTransportOptions> & BrowserSpecificOptions;\n\n/**\n * The Sentry Browser SDK Client.\n *\n * @see BrowserOptions for documentation on configuration options.\n * @see SentryClient for usage documentation.\n */\nexport class BrowserClient extends Client<BrowserClientOptions> {\n /**\n * Creates a new Browser SDK instance.\n *\n * @param options Configuration options for this SDK.\n */\n public constructor(options: BrowserClientOptions) {\n const opts = applyDefaultOptions(options);\n const sdkSource = WINDOW.SENTRY_SDK_SOURCE || getSDKSource();\n applySdkMetadata(opts, 'browser', ['browser'], sdkSource);\n\n super(opts);\n\n // Unhandled errors don't actually crash the browser, so we report `unhandled` rather than `crashed`.\n this._unhandledSessionStatus = 'unhandled';\n\n const { userInfo } = this.getDataCollectionOptions();\n\n if (opts._metadata?.sdk) {\n opts._metadata.sdk.settings = {\n // Only allow IP inferral by Relay if the user opted in via dataCollection\n infer_ip: userInfo ? 'auto' : 'never',\n // purposefully allowing already passed settings to override the default\n ...opts._metadata.sdk.settings,\n };\n }\n\n const { sendClientReports } = this._options;\n\n // Flush buffered data when the page becomes hidden (e.g. tab switch, navigation, or the page\n // being discarded). `flush()` emits the `flush` hook, which drains the span (streaming), log and\n // metric buffers and hands the resulting envelopes to the transport (which uses `keepalive`).\n // Client report outcomes don't listen to the `flush` hook, so we flush them separately.\n if (WINDOW.document) {\n WINDOW.document.addEventListener('visibilitychange', () => {\n if (WINDOW.document.visibilityState === 'hidden') {\n if (sendClientReports) {\n this._flushOutcomes();\n }\n // Defer the flush to a microtask so that visibilitychange listeners registered after this\n // one have already run. In particular, browser tracing's background-tab detection ends the\n // active pageload/navigation (segment) span when the page is hidden. Deferring ensures that\n // segment span has been added to the streaming buffer before we flush, so it is sent\n // together with its child spans instead of being orphaned.\n queueMicrotask(() => {\n void this.flush();\n });\n }\n });\n }\n\n if (userInfo) {\n this.on('beforeSendSession', addAutoIpAddressToSession);\n }\n }\n\n /**\n * @inheritDoc\n */\n public eventFromException(exception: unknown, hint?: EventHint): PromiseLike<Event> {\n return eventFromException(this._options.stackParser, exception, hint, this._options.attachStacktrace);\n }\n\n /**\n * @inheritDoc\n */\n public eventFromMessage(\n message: ParameterizedString,\n level: SeverityLevel = 'info',\n hint?: EventHint,\n ): PromiseLike<Event> {\n return eventFromMessage(this._options.stackParser, message, level, hint, this._options.attachStacktrace);\n }\n\n /**\n * @inheritDoc\n */\n protected _prepareEvent(\n event: Event,\n hint: EventHint,\n currentScope: Scope,\n isolationScope: Scope,\n ): PromiseLike<Event | null> {\n event.platform = event.platform || 'javascript';\n\n return super._prepareEvent(event, hint, currentScope, isolationScope);\n }\n}\n\n/** Exported only for tests. */\nexport function applyDefaultOptions<T extends Partial<BrowserClientOptions>>(optionsArg: T): T {\n return {\n release:\n typeof __SENTRY_RELEASE__ === 'string' // This allows build tooling to find-and-replace __SENTRY_RELEASE__ to inject a release value\n ? __SENTRY_RELEASE__\n : WINDOW.SENTRY_RELEASE?.id, // This supports the variable that sentry-webpack-plugin injects\n sendClientReports: true,\n // We default this to true, as it is the safer scenario\n parentSpanIsAlwaysRootSpan: true,\n ...optionsArg,\n };\n}\n"],"names":[],"mappings":";;;;AA2EO,MAAM,sBAAsB,MAAA,CAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvD,YAAY,OAAA,EAA+B;AAChD,IAAA,MAAM,IAAA,GAAO,oBAAoB,OAAO,CAAA;AACxC,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,iBAAA,IAAqB,YAAA,EAAa;AAC3D,IAAA,gBAAA,CAAiB,IAAA,EAAM,SAAA,EAAW,CAAC,SAAS,GAAG,SAAS,CAAA;AAExD,IAAA,KAAA,CAAM,IAAI,CAAA;AAGV,IAAA,IAAA,CAAK,uBAAA,GAA0B,WAAA;AAE/B,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,IAAA,CAAK,wBAAA,EAAyB;AAEnD,IAAA,IAAI,IAAA,CAAK,WAAW,GAAA,EAAK;AACvB,MAAA,IAAA,CAAK,SAAA,CAAU,IAAI,QAAA,GAAW;AAAA;AAAA,QAE5B,QAAA,EAAU,WAAW,MAAA,GAAS,OAAA;AAAA;AAAA,QAE9B,GAAG,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI;AAAA,OACxB;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,iBAAA,EAAkB,GAAI,IAAA,CAAK,QAAA;AAMnC,IAAA,IAAI,OAAO,QAAA,EAAU;AACnB,MAAA,MAAA,CAAO,QAAA,CAAS,gBAAA,CAAiB,kBAAA,EAAoB,MAAM;AACzD,QAAA,IAAI,MAAA,CAAO,QAAA,CAAS,eAAA,KAAoB,QAAA,EAAU;AAChD,UAAA,IAAI,iBAAA,EAAmB;AACrB,YAAA,IAAA,CAAK,cAAA,EAAe;AAAA,UACtB;AAMA,UAAA,cAAA,CAAe,MAAM;AACnB,YAAA,KAAK,KAAK,KAAA,EAAM;AAAA,UAClB,CAAC,CAAA;AAAA,QACH;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,IAAA,CAAK,EAAA,CAAG,qBAAqB,yBAAyB,CAAA;AAAA,IACxD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,kBAAA,CAAmB,WAAoB,IAAA,EAAsC;AAClF,IAAA,OAAO,kBAAA,CAAmB,KAAK,QAAA,CAAS,WAAA,EAAa,WAAW,IAAA,EAAM,IAAA,CAAK,SAAS,gBAAgB,CAAA;AAAA,EACtG;AAAA;AAAA;AAAA;AAAA,EAKO,gBAAA,CACL,OAAA,EACA,KAAA,GAAuB,MAAA,EACvB,IAAA,EACoB;AACpB,IAAA,OAAO,gBAAA,CAAiB,KAAK,QAAA,CAAS,WAAA,EAAa,SAAS,KAAA,EAAO,IAAA,EAAM,IAAA,CAAK,QAAA,CAAS,gBAAgB,CAAA;AAAA,EACzG;AAAA;AAAA;AAAA;AAAA,EAKU,aAAA,CACR,KAAA,EACA,IAAA,EACA,YAAA,EACA,cAAA,EAC2B;AAC3B,IAAA,KAAA,CAAM,QAAA,GAAW,MAAM,QAAA,IAAY,YAAA;AAEnC,IAAA,OAAO,KAAA,CAAM,aAAA,CAAc,KAAA,EAAO,IAAA,EAAM,cAAc,cAAc,CAAA;AAAA,EACtE;AACF;AAGO,SAAS,oBAA6D,UAAA,EAAkB;AAC7F,EAAA,OAAO;AAAA,IACL,SACE,OAAO,kBAAA,KAAuB,QAAA,GAC1B,kBAAA,GACA,OAAO,cAAA,EAAgB,EAAA;AAAA;AAAA,IAC7B,iBAAA,EAAmB,IAAA;AAAA;AAAA,IAEnB,0BAAA,EAA4B,IAAA;AAAA,IAC5B,GAAG;AAAA,GACL;AACF;;;;"}
1
+ {"version":3,"file":"client.js","sources":["../../../../src/client.ts"],"sourcesContent":["import type {\n BrowserClientReplayOptions,\n ClientOptions,\n Event,\n EventHint,\n Options as CoreOptions,\n ParameterizedString,\n Scope,\n SeverityLevel,\n} from '@sentry/core/browser';\nimport { addAutoIpAddressToSession, applySdkMetadata, Client, getSDKSource } from '@sentry/core/browser';\nimport { eventFromException, eventFromMessage } from './eventbuilder';\nimport { WINDOW } from './helpers';\nimport type { BrowserTransportOptions } from './transports/types';\n\n/**\n * A magic string that build tooling can leverage in order to inject a release value into the SDK.\n */\ndeclare const __SENTRY_RELEASE__: string | undefined;\n\nexport type BrowserClientProfilingOptions = {\n /**\n * Sets profiling session sample rate for the entire profiling session.\n *\n * A profiling session corresponds to a user session, meaning it is set once at integration initialization and\n * persisted until the next page reload. This rate determines what percentage of user sessions will have profiling enabled.\n * @default 0\n */\n profileSessionSampleRate?: number;\n\n /**\n * Set the lifecycle mode of the profiler.\n * - **manual**: The profiler will be manually started and stopped via `startProfiler`/`stopProfiler`.\n * If a session is sampled, is dependent on the `profileSessionSampleRate`.\n * - **trace**: The profiler will be automatically started when a root span exists and stopped when there are no\n * more sampled root spans. Whether a session is sampled, is dependent on the `profileSessionSampleRate` and the\n * existing sampling configuration for tracing (`tracesSampleRate`/`tracesSampler`).\n *\n * @default 'manual'\n */\n profileLifecycle?: 'manual' | 'trace';\n};\n\ntype BrowserSpecificOptions = BrowserClientReplayOptions &\n BrowserClientProfilingOptions & {\n /** If configured, this URL will be used as base URL for lazy loading integration. */\n cdnBaseUrl?: string;\n\n /**\n * Important: Only set this option if you know what you are doing!\n *\n * By default, the SDK will check if `Sentry.init` is called in a browser extension.\n * In case it is, it will stop initialization and log a warning\n * because browser extensions require a different Sentry initialization process:\n * https://docs.sentry.io/platforms/javascript/best-practices/shared-environments/\n *\n * Setting up the SDK in a browser extension with global error monitoring is not recommended\n * and will likely flood you with errors from other web sites or extensions. This can heavily\n * impact your quota and cause interference with your and other Sentry SDKs in shared environments.\n *\n * If this check wrongfully flags your setup as a browser extension, you can set this\n * option to `true` to skip the check.\n *\n * @default false\n */\n skipBrowserExtensionCheck?: boolean;\n\n /**\n * If you use Spotlight by Sentry during development, use\n * this option to forward captured Sentry events to Spotlight.\n *\n * Either set it to true, or provide a specific Spotlight Sidecar URL.\n *\n * More details: https://spotlightjs.com/\n *\n * IMPORTANT: Only set this option to `true` while developing, not in production!\n */\n spotlight?: boolean | string;\n };\n/**\n * Configuration options for the Sentry Browser SDK.\n * @see @sentry/core Options for more information.\n */\nexport type BrowserOptions = CoreOptions<BrowserTransportOptions> & BrowserSpecificOptions;\n\n/**\n * Configuration options for the Sentry Browser SDK Client class\n * @see BrowserClient for more information.\n */\nexport type BrowserClientOptions = ClientOptions<BrowserTransportOptions> & BrowserSpecificOptions;\n\n/**\n * The Sentry Browser SDK Client.\n *\n * @see BrowserOptions for documentation on configuration options.\n * @see SentryClient for usage documentation.\n */\nexport class BrowserClient extends Client<BrowserClientOptions> {\n /**\n * Creates a new Browser SDK instance.\n *\n * @param options Configuration options for this SDK.\n */\n public constructor(options: BrowserClientOptions) {\n const opts = applyDefaultOptions(options);\n const sdkSource = WINDOW.SENTRY_SDK_SOURCE || getSDKSource();\n applySdkMetadata(opts, 'browser', ['browser'], sdkSource);\n\n super(opts);\n\n // Unhandled errors don't actually crash the browser, so we report `unhandled` rather than `crashed`.\n this._unhandledSessionStatus = 'unhandled';\n\n const { userInfo } = this.getDataCollectionOptions();\n\n if (opts._metadata?.sdk) {\n opts._metadata.sdk.settings = {\n // Only allow IP inferral by Relay if the user opted in via dataCollection\n infer_ip: userInfo ? 'auto' : 'never',\n // purposefully allowing already passed settings to override the default\n ...opts._metadata.sdk.settings,\n };\n }\n\n const { sendClientReports } = this._options;\n\n // Flush buffered data when the page becomes hidden (e.g. tab switch, navigation, or the page\n // being discarded). `flush()` emits the `flush` hook, which drains the span (streaming), log and\n // metric buffers and hands the resulting envelopes to the transport (which uses `keepalive`).\n // Client report outcomes don't listen to the `flush` hook, so we flush them separately.\n if (WINDOW.document) {\n WINDOW.document.addEventListener('visibilitychange', () => {\n if (WINDOW.document.visibilityState === 'hidden') {\n if (sendClientReports) {\n this._flushOutcomes();\n }\n // Defer the flush to a microtask so that visibilitychange listeners registered after this\n // one have already run. In particular, browser tracing's background-tab detection ends the\n // active pageload/navigation (segment) span when the page is hidden. Deferring ensures that\n // segment span has been added to the streaming buffer before we flush, so it is sent\n // together with its child spans instead of being orphaned.\n queueMicrotask(() => {\n void this.flush();\n });\n }\n });\n }\n\n if (userInfo) {\n this.on('beforeSendSession', addAutoIpAddressToSession);\n }\n }\n\n /**\n * @inheritDoc\n */\n public eventFromException(exception: unknown, hint?: EventHint): PromiseLike<Event> {\n return eventFromException(this._options.stackParser, exception, hint, this._options.attachStacktrace);\n }\n\n /**\n * @inheritDoc\n */\n public eventFromMessage(\n message: ParameterizedString,\n level: SeverityLevel = 'info',\n hint?: EventHint,\n ): PromiseLike<Event> {\n return eventFromMessage(this._options.stackParser, message, level, hint, this._options.attachStacktrace);\n }\n\n /**\n * @inheritDoc\n */\n protected _prepareEvent(\n event: Event,\n hint: EventHint,\n currentScope: Scope,\n isolationScope: Scope,\n ): PromiseLike<Event | null> {\n event.platform = event.platform || 'javascript';\n\n return super._prepareEvent(event, hint, currentScope, isolationScope);\n }\n}\n\n/** Exported only for tests. */\nexport function applyDefaultOptions<T extends Partial<BrowserClientOptions>>(optionsArg: T): T {\n return {\n release:\n typeof __SENTRY_RELEASE__ === 'string' // This allows build tooling to find-and-replace __SENTRY_RELEASE__ to inject a release value\n ? __SENTRY_RELEASE__\n : WINDOW.SENTRY_RELEASE?.id, // This supports the variable that sentry-webpack-plugin injects\n sendClientReports: true,\n // We default this to true, as it is the safer scenario\n parentSpanIsAlwaysRootSpan: true,\n ...optionsArg,\n };\n}\n"],"names":[],"mappings":";;;;AAiGO,MAAM,sBAAsB,MAAA,CAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvD,YAAY,OAAA,EAA+B;AAChD,IAAA,MAAM,IAAA,GAAO,oBAAoB,OAAO,CAAA;AACxC,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,iBAAA,IAAqB,YAAA,EAAa;AAC3D,IAAA,gBAAA,CAAiB,IAAA,EAAM,SAAA,EAAW,CAAC,SAAS,GAAG,SAAS,CAAA;AAExD,IAAA,KAAA,CAAM,IAAI,CAAA;AAGV,IAAA,IAAA,CAAK,uBAAA,GAA0B,WAAA;AAE/B,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,IAAA,CAAK,wBAAA,EAAyB;AAEnD,IAAA,IAAI,IAAA,CAAK,WAAW,GAAA,EAAK;AACvB,MAAA,IAAA,CAAK,SAAA,CAAU,IAAI,QAAA,GAAW;AAAA;AAAA,QAE5B,QAAA,EAAU,WAAW,MAAA,GAAS,OAAA;AAAA;AAAA,QAE9B,GAAG,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI;AAAA,OACxB;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,iBAAA,EAAkB,GAAI,IAAA,CAAK,QAAA;AAMnC,IAAA,IAAI,OAAO,QAAA,EAAU;AACnB,MAAA,MAAA,CAAO,QAAA,CAAS,gBAAA,CAAiB,kBAAA,EAAoB,MAAM;AACzD,QAAA,IAAI,MAAA,CAAO,QAAA,CAAS,eAAA,KAAoB,QAAA,EAAU;AAChD,UAAA,IAAI,iBAAA,EAAmB;AACrB,YAAA,IAAA,CAAK,cAAA,EAAe;AAAA,UACtB;AAMA,UAAA,cAAA,CAAe,MAAM;AACnB,YAAA,KAAK,KAAK,KAAA,EAAM;AAAA,UAClB,CAAC,CAAA;AAAA,QACH;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,IAAA,CAAK,EAAA,CAAG,qBAAqB,yBAAyB,CAAA;AAAA,IACxD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,kBAAA,CAAmB,WAAoB,IAAA,EAAsC;AAClF,IAAA,OAAO,kBAAA,CAAmB,KAAK,QAAA,CAAS,WAAA,EAAa,WAAW,IAAA,EAAM,IAAA,CAAK,SAAS,gBAAgB,CAAA;AAAA,EACtG;AAAA;AAAA;AAAA;AAAA,EAKO,gBAAA,CACL,OAAA,EACA,KAAA,GAAuB,MAAA,EACvB,IAAA,EACoB;AACpB,IAAA,OAAO,gBAAA,CAAiB,KAAK,QAAA,CAAS,WAAA,EAAa,SAAS,KAAA,EAAO,IAAA,EAAM,IAAA,CAAK,QAAA,CAAS,gBAAgB,CAAA;AAAA,EACzG;AAAA;AAAA;AAAA;AAAA,EAKU,aAAA,CACR,KAAA,EACA,IAAA,EACA,YAAA,EACA,cAAA,EAC2B;AAC3B,IAAA,KAAA,CAAM,QAAA,GAAW,MAAM,QAAA,IAAY,YAAA;AAEnC,IAAA,OAAO,KAAA,CAAM,aAAA,CAAc,KAAA,EAAO,IAAA,EAAM,cAAc,cAAc,CAAA;AAAA,EACtE;AACF;AAGO,SAAS,oBAA6D,UAAA,EAAkB;AAC7F,EAAA,OAAO;AAAA,IACL,SACE,OAAO,kBAAA,KAAuB,QAAA,GAC1B,kBAAA,GACA,OAAO,cAAA,EAAgB,EAAA;AAAA;AAAA,IAC7B,iBAAA,EAAmB,IAAA;AAAA;AAAA,IAEnB,0BAAA,EAA4B,IAAA;AAAA,IAC5B,GAAG;AAAA,GACL;AACF;;;;"}
@@ -1,4 +1,5 @@
1
- import { GLOBAL_OBJ, getOriginalFunction, markFunctionWrapped, addNonEnumerableProperty, withScope, addExceptionTypeValue, addExceptionMechanism, captureException, getLocationHref } from '@sentry/core/browser';
1
+ import { GLOBAL_OBJ, getOriginalFunction, markFunctionWrapped, addNonEnumerableProperty, withScope, addExceptionTypeValue, addExceptionMechanism, captureException } from '@sentry/core/browser';
2
+ import { getLocationHref } from '@sentry/browser-utils';
2
3
 
3
4
  const WINDOW = GLOBAL_OBJ;
4
5
  let ignoreOnError = 0;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sources":["../../../../src/helpers.ts"],"sourcesContent":["import type { Mechanism, WrappedFunction } from '@sentry/core/browser';\nimport {\n addExceptionMechanism,\n addExceptionTypeValue,\n addNonEnumerableProperty,\n captureException,\n getLocationHref,\n getOriginalFunction,\n GLOBAL_OBJ,\n markFunctionWrapped,\n withScope,\n} from '@sentry/core/browser';\n\nexport const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\nlet ignoreOnError: number = 0;\n\n/**\n * @hidden\n */\nexport function shouldIgnoreOnError(): boolean {\n return ignoreOnError > 0;\n}\n\n/**\n * @hidden\n */\nexport function ignoreNextOnError(): void {\n // onerror should trigger before setTimeout\n ignoreOnError++;\n setTimeout(() => {\n ignoreOnError--;\n });\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\ntype WrappableFunction = Function;\n\nexport function wrap<T extends WrappableFunction>(\n fn: T,\n options?: {\n mechanism?: Mechanism;\n },\n): WrappedFunction<T>;\nexport function wrap<NonFunction>(\n fn: NonFunction,\n options?: {\n mechanism?: Mechanism;\n },\n): NonFunction;\n/**\n * Instruments the given function and sends an event to Sentry every time the\n * function throws an exception.\n *\n * @param fn A function to wrap. It is generally safe to pass an unbound function, because the returned wrapper always\n * has a correct `this` context.\n * @returns The wrapped function.\n * @hidden\n */\nexport function wrap<T extends WrappableFunction, NonFunction>(\n fn: T | NonFunction,\n options: {\n mechanism?: Mechanism;\n } = {},\n): NonFunction | WrappedFunction<T> {\n // for future readers what this does is wrap a function and then create\n // a bi-directional wrapping between them.\n //\n // example: wrapped = wrap(original);\n // original.__sentry_wrapped__ -> wrapped\n // wrapped.__sentry_original__ -> original\n\n function isFunction(fn: T | NonFunction): fn is T {\n return typeof fn === 'function';\n }\n\n if (!isFunction(fn)) {\n return fn;\n }\n\n try {\n // If we're dealing with a function that was previously wrapped, return the original wrapper.\n // Check via hasOwnProperty so a `__sentry_wrapped__` inherited from a wrapped `Function.prototype`\n // is not mistaken for a real wrapper.\n const hasOwnWrapper = Object.prototype.hasOwnProperty.call(fn, '__sentry_wrapped__');\n if (hasOwnWrapper) {\n const wrapper = (fn as WrappedFunction<T>).__sentry_wrapped__;\n if (typeof wrapper === 'function') {\n return wrapper;\n } else {\n // If we find that the `__sentry_wrapped__` function is not a function at the time of accessing it, it means\n // that something messed with it. In that case we want to return the originally passed function.\n return fn;\n }\n }\n\n // We don't wanna wrap it twice\n if (getOriginalFunction(fn)) {\n return fn;\n }\n } catch {\n // Just accessing custom props in some Selenium environments\n // can cause a \"Permission denied\" exception (see raven-js#495).\n // Bail on wrapping and return the function as-is (defers to window.onerror).\n return fn;\n }\n\n // Wrap the function itself\n // It is important that `sentryWrapped` is not an arrow function to preserve the context of `this`\n const sentryWrapped = function (this: unknown, ...args: unknown[]): unknown {\n // Track depth on GLOBAL_OBJ so the thirdPartyErrorFilterIntegration (in @sentry/core) can detect\n // that processEvent is running inside a sentryWrapped call, even with minified/bundled code.\n GLOBAL_OBJ._sentryWrappedDepth = (GLOBAL_OBJ._sentryWrappedDepth || 0) + 1;\n try {\n // Also wrap arguments that are themselves functions\n const wrappedArguments = args.map(arg => wrap(arg, options));\n\n // Attempt to invoke user-land function\n // NOTE: If you are a Sentry user, and you are seeing this stack frame, it\n // means the sentry.javascript SDK caught an error invoking your application code. This\n // is expected behavior and NOT indicative of a bug with sentry.javascript.\n return fn.apply(this, wrappedArguments);\n } catch (ex) {\n ignoreNextOnError();\n\n withScope(scope => {\n scope.addEventProcessor(event => {\n if (options.mechanism) {\n addExceptionTypeValue(event, undefined, undefined);\n addExceptionMechanism(event, options.mechanism);\n }\n\n event.extra = {\n ...event.extra,\n arguments: args,\n };\n\n return event;\n });\n\n // no need to add a mechanism here, we already add it via an event processor above\n captureException(ex);\n });\n\n throw ex;\n } finally {\n GLOBAL_OBJ._sentryWrappedDepth = (GLOBAL_OBJ._sentryWrappedDepth || 0) - 1;\n }\n } as unknown as WrappedFunction<T>;\n\n // Wrap the wrapped function in a proxy, to ensure any other properties of the original function remain available\n try {\n for (const property in fn) {\n if (Object.prototype.hasOwnProperty.call(fn, property)) {\n sentryWrapped[property as keyof T] = fn[property as keyof T];\n }\n }\n } catch {\n // Accessing some objects may throw\n // ref: https://github.com/getsentry/sentry-javascript/issues/1168\n }\n\n // Signal that this function has been wrapped/filled already\n // for both debugging and to prevent it to being wrapped/filled twice\n markFunctionWrapped(sentryWrapped, fn);\n\n addNonEnumerableProperty(fn, '__sentry_wrapped__', sentryWrapped);\n\n // Restore original function name (not all browsers allow that)\n try {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const descriptor = Object.getOwnPropertyDescriptor(sentryWrapped, 'name')!;\n if (descriptor.configurable) {\n Object.defineProperty(sentryWrapped, 'name', {\n get(): string {\n return fn.name;\n },\n });\n }\n } catch {\n // This may throw if e.g. the descriptor does not exist, or a browser does not allow redefining `name`.\n // to save some bytes we simply try-catch this\n }\n\n return sentryWrapped;\n}\n\n/**\n * Get HTTP request data from the current page.\n */\nexport function getHttpRequestData(): { url: string; headers: Record<string, string> } {\n // grab as much info as exists and add it to the event\n const url = getLocationHref();\n const { referrer } = WINDOW.document || {};\n const { userAgent } = WINDOW.navigator || {};\n\n const headers = {\n ...(referrer && { Referer: referrer }),\n ...(userAgent && { 'User-Agent': userAgent }),\n };\n const request = {\n url,\n headers,\n };\n\n return request;\n}\n"],"names":["fn"],"mappings":";;AAaO,MAAM,MAAA,GAAS;AAEtB,IAAI,aAAA,GAAwB,CAAA;AAKrB,SAAS,mBAAA,GAA+B;AAC7C,EAAA,OAAO,aAAA,GAAgB,CAAA;AACzB;AAKO,SAAS,iBAAA,GAA0B;AAExC,EAAA,aAAA,EAAA;AACA,EAAA,UAAA,CAAW,MAAM;AACf,IAAA,aAAA,EAAA;AAAA,EACF,CAAC,CAAA;AACH;AA0BO,SAAS,IAAA,CACd,EAAA,EACA,OAAA,GAEI,EAAC,EAC6B;AAQlC,EAAA,SAAS,WAAWA,GAAAA,EAA8B;AAChD,IAAA,OAAO,OAAOA,GAAAA,KAAO,UAAA;AAAA,EACvB;AAEA,EAAA,IAAI,CAAC,UAAA,CAAW,EAAE,CAAA,EAAG;AACnB,IAAA,OAAO,EAAA;AAAA,EACT;AAEA,EAAA,IAAI;AAIF,IAAA,MAAM,gBAAgB,MAAA,CAAO,SAAA,CAAU,cAAA,CAAe,IAAA,CAAK,IAAI,oBAAoB,CAAA;AACnF,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,MAAM,UAAW,EAAA,CAA0B,kBAAA;AAC3C,MAAA,IAAI,OAAO,YAAY,UAAA,EAAY;AACjC,QAAA,OAAO,OAAA;AAAA,MACT,CAAA,MAAO;AAGL,QAAA,OAAO,EAAA;AAAA,MACT;AAAA,IACF;AAGA,IAAA,IAAI,mBAAA,CAAoB,EAAE,CAAA,EAAG;AAC3B,MAAA,OAAO,EAAA;AAAA,IACT;AAAA,EACF,CAAA,CAAA,MAAQ;AAIN,IAAA,OAAO,EAAA;AAAA,EACT;AAIA,EAAA,MAAM,aAAA,GAAgB,YAA4B,IAAA,EAA0B;AAG1E,IAAA,UAAA,CAAW,mBAAA,GAAA,CAAuB,UAAA,CAAW,mBAAA,IAAuB,CAAA,IAAK,CAAA;AACzE,IAAA,IAAI;AAEF,MAAA,MAAM,mBAAmB,IAAA,CAAK,GAAA,CAAI,SAAO,IAAA,CAAK,GAAA,EAAK,OAAO,CAAC,CAAA;AAM3D,MAAA,OAAO,EAAA,CAAG,KAAA,CAAM,IAAA,EAAM,gBAAgB,CAAA;AAAA,IACxC,SAAS,EAAA,EAAI;AACX,MAAA,iBAAA,EAAkB;AAElB,MAAA,SAAA,CAAU,CAAA,KAAA,KAAS;AACjB,QAAA,KAAA,CAAM,kBAAkB,CAAA,KAAA,KAAS;AAC/B,UAAA,IAAI,QAAQ,SAAA,EAAW;AACrB,YAAA,qBAAA,CAAsB,KAAA,EAAO,QAAW,MAAS,CAAA;AACjD,YAAA,qBAAA,CAAsB,KAAA,EAAO,QAAQ,SAAS,CAAA;AAAA,UAChD;AAEA,UAAA,KAAA,CAAM,KAAA,GAAQ;AAAA,YACZ,GAAG,KAAA,CAAM,KAAA;AAAA,YACT,SAAA,EAAW;AAAA,WACb;AAEA,UAAA,OAAO,KAAA;AAAA,QACT,CAAC,CAAA;AAGD,QAAA,gBAAA,CAAiB,EAAE,CAAA;AAAA,MACrB,CAAC,CAAA;AAED,MAAA,MAAM,EAAA;AAAA,IACR,CAAA,SAAE;AACA,MAAA,UAAA,CAAW,mBAAA,GAAA,CAAuB,UAAA,CAAW,mBAAA,IAAuB,CAAA,IAAK,CAAA;AAAA,IAC3E;AAAA,EACF,CAAA;AAGA,EAAA,IAAI;AACF,IAAA,KAAA,MAAW,YAAY,EAAA,EAAI;AACzB,MAAA,IAAI,OAAO,SAAA,CAAU,cAAA,CAAe,IAAA,CAAK,EAAA,EAAI,QAAQ,CAAA,EAAG;AACtD,QAAA,aAAA,CAAc,QAAmB,CAAA,GAAI,EAAA,CAAG,QAAmB,CAAA;AAAA,MAC7D;AAAA,IACF;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAGR;AAIA,EAAA,mBAAA,CAAoB,eAAe,EAAE,CAAA;AAErC,EAAA,wBAAA,CAAyB,EAAA,EAAI,sBAAsB,aAAa,CAAA;AAGhE,EAAA,IAAI;AAEF,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,wBAAA,CAAyB,aAAA,EAAe,MAAM,CAAA;AACxE,IAAA,IAAI,WAAW,YAAA,EAAc;AAC3B,MAAA,MAAA,CAAO,cAAA,CAAe,eAAe,MAAA,EAAQ;AAAA,QAC3C,GAAA,GAAc;AACZ,UAAA,OAAO,EAAA,CAAG,IAAA;AAAA,QACZ;AAAA,OACD,CAAA;AAAA,IACH;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAGR;AAEA,EAAA,OAAO,aAAA;AACT;AAKO,SAAS,kBAAA,GAAuE;AAErF,EAAA,MAAM,MAAM,eAAA,EAAgB;AAC5B,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAA,CAAO,YAAY,EAAC;AACzC,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAA,CAAO,aAAa,EAAC;AAE3C,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,GAAI,QAAA,IAAY,EAAE,OAAA,EAAS,QAAA,EAAS;AAAA,IACpC,GAAI,SAAA,IAAa,EAAE,YAAA,EAAc,SAAA;AAAU,GAC7C;AACA,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,GAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO,OAAA;AACT;;;;"}
1
+ {"version":3,"file":"helpers.js","sources":["../../../../src/helpers.ts"],"sourcesContent":["import type { Mechanism, WrappedFunction } from '@sentry/core/browser';\nimport {\n addExceptionMechanism,\n addExceptionTypeValue,\n addNonEnumerableProperty,\n captureException,\n getOriginalFunction,\n GLOBAL_OBJ,\n markFunctionWrapped,\n withScope,\n} from '@sentry/core/browser';\nimport { getLocationHref } from '@sentry/browser-utils';\n\nexport const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\nlet ignoreOnError: number = 0;\n\n/**\n * @hidden\n */\nexport function shouldIgnoreOnError(): boolean {\n return ignoreOnError > 0;\n}\n\n/**\n * @hidden\n */\nexport function ignoreNextOnError(): void {\n // onerror should trigger before setTimeout\n ignoreOnError++;\n setTimeout(() => {\n ignoreOnError--;\n });\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\ntype WrappableFunction = Function;\n\nexport function wrap<T extends WrappableFunction>(\n fn: T,\n options?: {\n mechanism?: Mechanism;\n },\n): WrappedFunction<T>;\nexport function wrap<NonFunction>(\n fn: NonFunction,\n options?: {\n mechanism?: Mechanism;\n },\n): NonFunction;\n/**\n * Instruments the given function and sends an event to Sentry every time the\n * function throws an exception.\n *\n * @param fn A function to wrap. It is generally safe to pass an unbound function, because the returned wrapper always\n * has a correct `this` context.\n * @returns The wrapped function.\n * @hidden\n */\nexport function wrap<T extends WrappableFunction, NonFunction>(\n fn: T | NonFunction,\n options: {\n mechanism?: Mechanism;\n } = {},\n): NonFunction | WrappedFunction<T> {\n // for future readers what this does is wrap a function and then create\n // a bi-directional wrapping between them.\n //\n // example: wrapped = wrap(original);\n // original.__sentry_wrapped__ -> wrapped\n // wrapped.__sentry_original__ -> original\n\n function isFunction(fn: T | NonFunction): fn is T {\n return typeof fn === 'function';\n }\n\n if (!isFunction(fn)) {\n return fn;\n }\n\n try {\n // If we're dealing with a function that was previously wrapped, return the original wrapper.\n // Check via hasOwnProperty so a `__sentry_wrapped__` inherited from a wrapped `Function.prototype`\n // is not mistaken for a real wrapper.\n const hasOwnWrapper = Object.prototype.hasOwnProperty.call(fn, '__sentry_wrapped__');\n if (hasOwnWrapper) {\n const wrapper = (fn as WrappedFunction<T>).__sentry_wrapped__;\n if (typeof wrapper === 'function') {\n return wrapper;\n } else {\n // If we find that the `__sentry_wrapped__` function is not a function at the time of accessing it, it means\n // that something messed with it. In that case we want to return the originally passed function.\n return fn;\n }\n }\n\n // We don't wanna wrap it twice\n if (getOriginalFunction(fn)) {\n return fn;\n }\n } catch {\n // Just accessing custom props in some Selenium environments\n // can cause a \"Permission denied\" exception (see raven-js#495).\n // Bail on wrapping and return the function as-is (defers to window.onerror).\n return fn;\n }\n\n // Wrap the function itself\n // It is important that `sentryWrapped` is not an arrow function to preserve the context of `this`\n const sentryWrapped = function (this: unknown, ...args: unknown[]): unknown {\n // Track depth on GLOBAL_OBJ so the thirdPartyErrorFilterIntegration (in @sentry/core) can detect\n // that processEvent is running inside a sentryWrapped call, even with minified/bundled code.\n GLOBAL_OBJ._sentryWrappedDepth = (GLOBAL_OBJ._sentryWrappedDepth || 0) + 1;\n try {\n // Also wrap arguments that are themselves functions\n const wrappedArguments = args.map(arg => wrap(arg, options));\n\n // Attempt to invoke user-land function\n // NOTE: If you are a Sentry user, and you are seeing this stack frame, it\n // means the sentry.javascript SDK caught an error invoking your application code. This\n // is expected behavior and NOT indicative of a bug with sentry.javascript.\n return fn.apply(this, wrappedArguments);\n } catch (ex) {\n ignoreNextOnError();\n\n withScope(scope => {\n scope.addEventProcessor(event => {\n if (options.mechanism) {\n addExceptionTypeValue(event, undefined, undefined);\n addExceptionMechanism(event, options.mechanism);\n }\n\n event.extra = {\n ...event.extra,\n arguments: args,\n };\n\n return event;\n });\n\n // no need to add a mechanism here, we already add it via an event processor above\n captureException(ex);\n });\n\n throw ex;\n } finally {\n GLOBAL_OBJ._sentryWrappedDepth = (GLOBAL_OBJ._sentryWrappedDepth || 0) - 1;\n }\n } as unknown as WrappedFunction<T>;\n\n // Wrap the wrapped function in a proxy, to ensure any other properties of the original function remain available\n try {\n for (const property in fn) {\n if (Object.prototype.hasOwnProperty.call(fn, property)) {\n sentryWrapped[property as keyof T] = fn[property as keyof T];\n }\n }\n } catch {\n // Accessing some objects may throw\n // ref: https://github.com/getsentry/sentry-javascript/issues/1168\n }\n\n // Signal that this function has been wrapped/filled already\n // for both debugging and to prevent it to being wrapped/filled twice\n markFunctionWrapped(sentryWrapped, fn);\n\n addNonEnumerableProperty(fn, '__sentry_wrapped__', sentryWrapped);\n\n // Restore original function name (not all browsers allow that)\n try {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const descriptor = Object.getOwnPropertyDescriptor(sentryWrapped, 'name')!;\n if (descriptor.configurable) {\n Object.defineProperty(sentryWrapped, 'name', {\n get(): string {\n return fn.name;\n },\n });\n }\n } catch {\n // This may throw if e.g. the descriptor does not exist, or a browser does not allow redefining `name`.\n // to save some bytes we simply try-catch this\n }\n\n return sentryWrapped;\n}\n\n/**\n * Get HTTP request data from the current page.\n */\nexport function getHttpRequestData(): { url: string; headers: Record<string, string> } {\n // grab as much info as exists and add it to the event\n const url = getLocationHref();\n const { referrer } = WINDOW.document || {};\n const { userAgent } = WINDOW.navigator || {};\n\n const headers = {\n ...(referrer && { Referer: referrer }),\n ...(userAgent && { 'User-Agent': userAgent }),\n };\n const request = {\n url,\n headers,\n };\n\n return request;\n}\n"],"names":["fn"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  export { feedbackAsyncIntegration } from './feedbackAsync.js';
2
2
  export { feedbackSyncIntegration as feedbackIntegration, feedbackSyncIntegration } from './feedbackSync.js';
3
- export { MULTIPLEXED_TRANSPORT_EXTRA_KEY, SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, bindScopeToEmitter, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, captureSession, close, consoleLoggingIntegration, continueTrace, createConsolaReporter, createTransport, dedupeIntegration, endSession, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, logger, makeMultiplexedTransport, metrics, moduleMetadataIntegration, parameterize, registerSpanErrorInstrumentation, rewriteFramesIntegration, setAttribute, setAttributes, setContext, setConversationId, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSession, startSpan, startSpanManual, supabaseIntegration, suppressTracing, thirdPartyErrorFilterIntegration, updateSpanName, withActiveSpan, withIsolationScope, withScope, withStaticSpan, withStreamedSpan, zodErrorsIntegration } from '@sentry/core/browser';
3
+ export { MULTIPLEXED_TRANSPORT_EXTRA_KEY, SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SENTRY_SEGMENT_NAME_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, bindScopeToEmitter, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, captureSession, close, consoleLoggingIntegration, continueTrace, createConsolaReporter, createTransport, dedupeIntegration, endSession, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, logger, makeMultiplexedTransport, metrics, moduleMetadataIntegration, parameterize, registerSpanErrorInstrumentation, rewriteFramesIntegration, setAttribute, setAttributes, setContext, setConversationId, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanStreamingIntegration, spanToBaggageHeader, spanToJSON, spanToStaticSpanJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSession, startSpan, startSpanManual, supabaseIntegration, suppressTracing, thirdPartyErrorFilterIntegration, updateSpanName, withActiveSpan, withIsolationScope, withScope, withStaticSpan, withStreamedSpan, zodErrorsIntegration } from '@sentry/core/browser';
4
4
  export { WINDOW } from './helpers.js';
5
5
  export { BrowserClient } from './client.js';
6
6
  export { makeFetchTransport } from './transports/fetch.js';
@@ -26,14 +26,14 @@ export { getReplay, replayIntegration } from '@sentry/replay';
26
26
  export { replayCanvasIntegration } from '@sentry/replay-canvas';
27
27
  export { getFeedback, sendFeedback } from '@sentry/feedback';
28
28
  export { defaultRequestInstrumentationOptions, instrumentOutgoingRequests } from './tracing/request.js';
29
- export { browserTracingIntegration, isBotUserAgent, startBrowserTracingNavigationSpan, startBrowserTracingPageLoadSpan } from './tracing/browserTracingIntegration.js';
30
- export { elementTimingIntegration, getAbsoluteUrl, userTimingIntegration } from '@sentry/browser-utils';
29
+ export { browserTracingIntegration, startBrowserTracingNavigationSpan, startBrowserTracingPageLoadSpan } from './tracing/browserTracingIntegration.js';
30
+ export { elementTimingIntegration, getAbsoluteUrl, interactionsIntegration, isBotUserAgent, userTimingIntegration } from '@sentry/browser-utils';
31
31
  export { normalizeStringifyValue } from './normalizeStringifyValue.js';
32
32
  export { reportPageLoaded } from './tracing/reportPageLoaded.js';
33
33
  export { setActiveSpanInBrowser } from './tracing/setActiveSpan.js';
34
- export { spanStreamingIntegration } from './integrations/spanstreaming.js';
35
34
  export { fetchStreamPerformanceIntegration } from './integrations/fetchStreamPerformance.js';
36
35
  export { webVitalsIntegration } from './integrations/webVitals.js';
36
+ export { bfcacheIntegration } from './integrations/bfcache.js';
37
37
  export { makeBrowserOfflineTransport } from './transports/offline.js';
38
38
  export { browserProfilingIntegration } from './profiling/integration.js';
39
39
  export { spotlightBrowserIntegration } from './integrations/spotlight.js';
@@ -0,0 +1,109 @@
1
+ import { SENTRY_ORIGIN, SENTRY_SEGMENT_NAME, BROWSER_BFCACHE_FRAME, BROWSER_BFCACHE_REASON, BROWSER_BFCACHE_NOT_RESTORED_REASON_COUNT, BROWSER_BFCACHE_OUTCOME } from '@sentry/conventions/attributes';
2
+ import { defineIntegration, debug, metrics, getCurrentScope } from '@sentry/core/browser';
3
+ import { DEBUG_BUILD } from '../debug-build.js';
4
+ import { WINDOW } from '../helpers.js';
5
+
6
+ const INTEGRATION_NAME = "Bfcache";
7
+ const bfcacheIntegration = defineIntegration((options = {}) => {
8
+ const maxReasons = _resolveMaxReasons(options.maxReasons);
9
+ return {
10
+ name: INTEGRATION_NAME,
11
+ setupOnce() {
12
+ if (!WINDOW.addEventListener || !WINDOW.performance?.getEntriesByType) {
13
+ DEBUG_BUILD && debug.log(`[${INTEGRATION_NAME}] Browser APIs unavailable, skipping instrumentation.`);
14
+ return;
15
+ }
16
+ function onPageShow(event) {
17
+ const routeName = _getSegmentName();
18
+ if (event.persisted) {
19
+ _captureBFCacheNavigation("hit", 0, routeName);
20
+ return;
21
+ }
22
+ const navigationEntry = WINDOW.performance.getEntriesByType("navigation")[0];
23
+ if (navigationEntry?.type !== "back_forward") {
24
+ return;
25
+ }
26
+ const reasons = _collectNotRestoredReasons(navigationEntry.notRestoredReasons, maxReasons);
27
+ _captureBFCacheNavigation("miss", reasons.length, routeName);
28
+ if (typeof navigationEntry.duration === "number" && navigationEntry.duration > 0) {
29
+ metrics.distribution("browser.bfcache.reload.duration", navigationEntry.duration, {
30
+ unit: "millisecond",
31
+ attributes: _withOriginAttr({
32
+ [SENTRY_SEGMENT_NAME]: routeName
33
+ })
34
+ });
35
+ }
36
+ reasons.forEach((r) => _captureBFCacheReason(r, routeName));
37
+ }
38
+ WINDOW.addEventListener("pageshow", onPageShow, true);
39
+ }
40
+ };
41
+ });
42
+ function _captureBFCacheNavigation(outcome, reasonCount, routeName) {
43
+ metrics.count("browser.bfcache.navigation", 1, {
44
+ attributes: _withOriginAttr({
45
+ [BROWSER_BFCACHE_OUTCOME]: outcome,
46
+ // Attribute should be present if reasons are >= 1
47
+ [BROWSER_BFCACHE_NOT_RESTORED_REASON_COUNT]: reasonCount || void 0,
48
+ [SENTRY_SEGMENT_NAME]: routeName
49
+ })
50
+ });
51
+ }
52
+ function _captureBFCacheReason({ reason, frame }, routeName) {
53
+ metrics.count("browser.bfcache.not_restored", 1, {
54
+ attributes: _withOriginAttr({
55
+ [BROWSER_BFCACHE_REASON]: reason,
56
+ [BROWSER_BFCACHE_FRAME]: frame,
57
+ [SENTRY_SEGMENT_NAME]: routeName
58
+ })
59
+ });
60
+ }
61
+ function _getSegmentName() {
62
+ return getCurrentScope().getScopeData().transactionName || WINDOW.location?.pathname;
63
+ }
64
+ function _resolveMaxReasons(maxReasons) {
65
+ if (maxReasons == null) {
66
+ return Infinity;
67
+ }
68
+ if (maxReasons < 1) {
69
+ DEBUG_BUILD && debug.warn(`[${INTEGRATION_NAME}] \`maxReasons\` must be at least 1, got ${maxReasons}. Using 1 instead.`);
70
+ return 1;
71
+ }
72
+ return maxReasons;
73
+ }
74
+ function _collectNotRestoredReasons(notRestoredReasons, maxReasons) {
75
+ const reasons = [];
76
+ if (!notRestoredReasons || maxReasons <= 0) {
77
+ return reasons;
78
+ }
79
+ _collectReasonsFromFrame(notRestoredReasons, "top", reasons, maxReasons);
80
+ return reasons;
81
+ }
82
+ function _collectReasonsFromFrame(frame, frameType, collectedReasons, maxReasons) {
83
+ if (collectedReasons.length >= maxReasons) {
84
+ return;
85
+ }
86
+ frame.reasons?.forEach((reason) => {
87
+ if (collectedReasons.length >= maxReasons) {
88
+ return;
89
+ }
90
+ const reasonValue = typeof reason === "string" ? reason : reason.reason;
91
+ if (!reasonValue) {
92
+ return;
93
+ }
94
+ collectedReasons.push({
95
+ reason: reasonValue,
96
+ frame: frameType
97
+ });
98
+ });
99
+ frame.children?.forEach((child) => {
100
+ _collectReasonsFromFrame(child, "child", collectedReasons, maxReasons);
101
+ });
102
+ }
103
+ function _withOriginAttr(attributes) {
104
+ attributes[SENTRY_ORIGIN] = "auto.browser.bfcache";
105
+ return attributes;
106
+ }
107
+
108
+ export { _collectNotRestoredReasons, _resolveMaxReasons, bfcacheIntegration };
109
+ //# sourceMappingURL=bfcache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bfcache.js","sources":["../../../../../src/integrations/bfcache.ts"],"sourcesContent":["import {\n SENTRY_SEGMENT_NAME,\n BROWSER_BFCACHE_FRAME,\n BROWSER_BFCACHE_NOT_RESTORED_REASON_COUNT,\n BROWSER_BFCACHE_OUTCOME,\n BROWSER_BFCACHE_REASON,\n SENTRY_ORIGIN,\n} from '@sentry/conventions/attributes';\nimport type { IntegrationFn, SpanAttributes } from '@sentry/core/browser';\nimport { debug, defineIntegration, getCurrentScope, metrics } from '@sentry/core/browser';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\n\nconst INTEGRATION_NAME = 'Bfcache';\n\ntype BFCacheOutcome = 'hit' | 'miss';\n\ntype BFCacheFrame = 'top' | 'child';\n\ninterface BFCacheIntegrationOptions {\n /**\n * Maximum number of not-restored reasons to emit per miss.\n *\n * By default every reason is reported. Set this to cap the number emitted per miss.\n * Values below 1 are clamped to 1.\n */\n maxReasons: number;\n}\n\ninterface NotRestoredReason {\n reason?: string;\n}\n\ninterface NotRestoredReasons {\n children?: NotRestoredReasons[] | null;\n reasons?: (NotRestoredReason | string)[] | null;\n}\n\ninterface NavigationTimingWithNotRestoredReasons extends PerformanceNavigationTiming {\n notRestoredReasons?: NotRestoredReasons | null;\n}\n\ninterface CollectedReason {\n reason: string;\n frame: BFCacheFrame;\n}\n\n/**\n * Captures bfcache hit/miss counters and Chromium notRestoredReasons when available.\n */\nexport const bfcacheIntegration = defineIntegration((options: Partial<BFCacheIntegrationOptions> = {}) => {\n const maxReasons = _resolveMaxReasons(options.maxReasons);\n\n return {\n name: INTEGRATION_NAME,\n\n setupOnce() {\n if (!WINDOW.addEventListener || !WINDOW.performance?.getEntriesByType) {\n DEBUG_BUILD && debug.log(`[${INTEGRATION_NAME}] Browser APIs unavailable, skipping instrumentation.`);\n return;\n }\n\n function onPageShow(event: PageTransitionEvent) {\n const routeName = _getSegmentName();\n if (event.persisted) {\n _captureBFCacheNavigation('hit', 0, routeName);\n return;\n }\n\n const navigationEntry = WINDOW.performance.getEntriesByType('navigation')[0] as\n | NavigationTimingWithNotRestoredReasons\n | undefined;\n\n if (navigationEntry?.type !== 'back_forward') {\n return;\n }\n\n const reasons = _collectNotRestoredReasons(navigationEntry.notRestoredReasons, maxReasons);\n _captureBFCacheNavigation('miss', reasons.length, routeName);\n\n // Measures how expensive the fallback reload was when a back/forward navigation missed bfcache.\n if (typeof navigationEntry.duration === 'number' && navigationEntry.duration > 0) {\n metrics.distribution('browser.bfcache.reload.duration', navigationEntry.duration, {\n unit: 'millisecond',\n attributes: _withOriginAttr({\n [SENTRY_SEGMENT_NAME]: routeName,\n }),\n });\n }\n\n reasons.forEach(r => _captureBFCacheReason(r, routeName));\n }\n\n // Listener should stay active because the event can trigger for an initial show before the bfcache entry coming into the second one.\n // This can be platform-dependent so we need to skip as many events till we get to the one containing the entry.\n // So we can't have { once } or a cleanup logic here, which is fine because `setupOnce` registers it a single time regardless of how many clients are created.\n WINDOW.addEventListener('pageshow', onPageShow, true);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Captures a bf navigation as a metric and records the outcome and reason count.\n */\nfunction _captureBFCacheNavigation(outcome: BFCacheOutcome, reasonCount: number, routeName?: string): void {\n metrics.count('browser.bfcache.navigation', 1, {\n attributes: _withOriginAttr({\n [BROWSER_BFCACHE_OUTCOME]: outcome,\n // Attribute should be present if reasons are >= 1\n [BROWSER_BFCACHE_NOT_RESTORED_REASON_COUNT]: reasonCount || undefined,\n [SENTRY_SEGMENT_NAME]: routeName,\n }),\n });\n}\n\n/**\n * Maps a collected reason to a metric and captures/sends it.\n */\nfunction _captureBFCacheReason({ reason, frame }: CollectedReason, routeName?: string) {\n metrics.count('browser.bfcache.not_restored', 1, {\n attributes: _withOriginAttr({\n [BROWSER_BFCACHE_REASON]: reason,\n [BROWSER_BFCACHE_FRAME]: frame,\n [SENTRY_SEGMENT_NAME]: routeName,\n }),\n });\n}\n\n/**\n * The segment name for a bfcache navigation, read from the scope rather than any span.\n *\n * A hit restore is silent to tracing (no pageload span), but the frozen scope still holds the last\n * transaction name a downstream SDK (Vue/React/etc.) set before the freeze, so we reuse that. On a miss the\n * page reloads with a fresh scope, so this is the new pageload name. Falls back to the raw pathname when unset.\n */\nfunction _getSegmentName(): string | undefined {\n return getCurrentScope().getScopeData().transactionName || WINDOW.location?.pathname;\n}\n\n/**\n * Resolves the configured `maxReasons` cap. Reports every reason by default and clamps values below 1 to 1,\n * since a cap under 1 would silently drop all reasons.\n *\n * Exported for tests only.\n */\nexport function _resolveMaxReasons(maxReasons: number | undefined): number {\n if (maxReasons == null) {\n return Infinity;\n }\n\n if (maxReasons < 1) {\n DEBUG_BUILD &&\n debug.warn(`[${INTEGRATION_NAME}] \\`maxReasons\\` must be at least 1, got ${maxReasons}. Using 1 instead.`);\n return 1;\n }\n\n return maxReasons;\n}\n\n/**\n * Flattens the (possibly nested) bfcache `notRestoredReasons` tree into a capped list of reasons.\n *\n * Exported for tests only.\n */\nexport function _collectNotRestoredReasons(\n notRestoredReasons: NotRestoredReasons | null | undefined,\n maxReasons: number,\n): CollectedReason[] {\n const reasons: CollectedReason[] = [];\n\n if (!notRestoredReasons || maxReasons <= 0) {\n return reasons;\n }\n\n _collectReasonsFromFrame(notRestoredReasons, 'top', reasons, maxReasons);\n\n return reasons;\n}\n\nfunction _collectReasonsFromFrame(\n frame: NotRestoredReasons,\n frameType: BFCacheFrame,\n collectedReasons: CollectedReason[],\n maxReasons: number,\n): void {\n if (collectedReasons.length >= maxReasons) {\n return;\n }\n\n frame.reasons?.forEach(reason => {\n if (collectedReasons.length >= maxReasons) {\n return;\n }\n\n const reasonValue = typeof reason === 'string' ? reason : reason.reason;\n if (!reasonValue) {\n return;\n }\n\n collectedReasons.push({\n reason: reasonValue,\n frame: frameType,\n });\n });\n\n frame.children?.forEach(child => {\n _collectReasonsFromFrame(child, 'child', collectedReasons, maxReasons);\n });\n}\n\n/**\n * Adds the origin attributes to a set of attributes, it mutates the original attributes.\n */\nfunction _withOriginAttr(attributes: SpanAttributes): SpanAttributes {\n attributes[SENTRY_ORIGIN] = 'auto.browser.bfcache';\n\n return attributes;\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { defineIntegration, addConsoleInstrumentationHandler, addFetchInstrumentationHandler, getClient, safeJoin, severityLevelFromString, addBreadcrumb, debug, getComponentName, getBreadcrumbLogLevelFromHttpStatusCode, parseUrl, getEventDescription } from '@sentry/core/browser';
2
- import { addClickKeypressInstrumentationHandler, addXhrInstrumentationHandler, addHistoryInstrumentationHandler, htmlTreeAsString, SENTRY_XHR_DATA_KEY } from '@sentry/browser-utils';
1
+ import { defineIntegration, addConsoleInstrumentationHandler, addFetchInstrumentationHandler, getClient, safeJoin, severityLevelFromString, addBreadcrumb, debug, getBreadcrumbLogLevelFromHttpStatusCode, parseUrl, getEventDescription } from '@sentry/core/browser';
2
+ import { addClickKeypressInstrumentationHandler, addXhrInstrumentationHandler, addHistoryInstrumentationHandler, htmlTreeAsString, getComponentName, SENTRY_XHR_DATA_KEY } from '@sentry/browser-utils';
3
3
  import { DEBUG_BUILD } from '../debug-build.js';
4
4
  import { WINDOW } from '../helpers.js';
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"breadcrumbs.js","sources":["../../../../../src/integrations/breadcrumbs.ts"],"sourcesContent":["/* eslint-disable max-lines */\n\nimport type {\n Breadcrumb,\n Client,\n Event as SentryEvent,\n FetchBreadcrumbData,\n FetchBreadcrumbHint,\n HandlerDataConsole,\n HandlerDataDom,\n HandlerDataFetch,\n HandlerDataHistory,\n HandlerDataXhr,\n IntegrationFn,\n XhrBreadcrumbData,\n XhrBreadcrumbHint,\n} from '@sentry/core/browser';\nimport {\n addBreadcrumb,\n addConsoleInstrumentationHandler,\n addFetchInstrumentationHandler,\n debug,\n defineIntegration,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getComponentName,\n getEventDescription,\n parseUrl,\n safeJoin,\n severityLevelFromString,\n} from '@sentry/core/browser';\nimport type { FetchHint, XhrHint } from '@sentry/browser-utils';\nimport {\n addClickKeypressInstrumentationHandler,\n addHistoryInstrumentationHandler,\n addXhrInstrumentationHandler,\n htmlTreeAsString,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\n\ninterface BreadcrumbsOptions {\n console: boolean;\n dom:\n | boolean\n | {\n serializeAttribute?: string | string[];\n maxStringLength?: number;\n };\n fetch: boolean;\n history: boolean;\n sentry: boolean;\n xhr: boolean;\n}\n\n/** maxStringLength gets capped to prevent 100 breadcrumbs exceeding 1MB event payload size */\nconst MAX_ALLOWED_STRING_LENGTH = 1024;\n\nconst INTEGRATION_NAME = 'Breadcrumbs' as const;\n\nconst _breadcrumbsIntegration = ((options: Partial<BreadcrumbsOptions> = {}) => {\n const _options = {\n console: true,\n dom: true,\n fetch: true,\n history: true,\n sentry: true,\n xhr: true,\n ...options,\n };\n\n return {\n name: INTEGRATION_NAME,\n setup(client) {\n // TODO(v11): Remove this functionality and use `consoleIntegration` from @sentry/core instead.\n if (_options.console) {\n addConsoleInstrumentationHandler(_getConsoleBreadcrumbHandler(client));\n }\n if (_options.dom) {\n addClickKeypressInstrumentationHandler(_getDomBreadcrumbHandler(client, _options.dom));\n }\n if (_options.xhr) {\n addXhrInstrumentationHandler(_getXhrBreadcrumbHandler(client));\n }\n if (_options.fetch) {\n addFetchInstrumentationHandler(_getFetchBreadcrumbHandler(client));\n }\n if (_options.history) {\n addHistoryInstrumentationHandler(_getHistoryBreadcrumbHandler(client));\n }\n if (_options.sentry) {\n client.on('beforeSendEvent', _getSentryBreadcrumbHandler(client));\n }\n },\n };\n}) satisfies IntegrationFn;\n\nexport const breadcrumbsIntegration = defineIntegration(_breadcrumbsIntegration);\n\n/**\n * Adds a breadcrumb for Sentry events or transactions if this option is enabled.\n */\nfunction _getSentryBreadcrumbHandler(client: Client): (event: SentryEvent) => void {\n return function addSentryBreadcrumb(event: SentryEvent): void {\n if (getClient() !== client) {\n return;\n }\n\n addBreadcrumb(\n {\n category: `sentry.${event.type === 'transaction' ? 'transaction' : 'event'}`,\n event_id: event.event_id,\n level: event.level,\n message: getEventDescription(event),\n },\n {\n event,\n },\n );\n };\n}\n\n/**\n * A HOC that creates a function that creates breadcrumbs from DOM API calls.\n * This is a HOC so that we get access to dom options in the closure.\n */\nfunction _getDomBreadcrumbHandler(\n client: Client,\n dom: BreadcrumbsOptions['dom'],\n): (handlerData: HandlerDataDom) => void {\n return function _innerDomBreadcrumb(handlerData: HandlerDataDom): void {\n if (getClient() !== client) {\n return;\n }\n\n let target;\n let componentName;\n let keyAttrs = typeof dom === 'object' ? dom.serializeAttribute : undefined;\n\n let maxStringLength =\n typeof dom === 'object' && typeof dom.maxStringLength === 'number' ? dom.maxStringLength : undefined;\n if (maxStringLength && maxStringLength > MAX_ALLOWED_STRING_LENGTH) {\n DEBUG_BUILD &&\n debug.warn(\n `\\`dom.maxStringLength\\` cannot exceed ${MAX_ALLOWED_STRING_LENGTH}, but a value of ${maxStringLength} was configured. Sentry will use ${MAX_ALLOWED_STRING_LENGTH} instead.`,\n );\n maxStringLength = MAX_ALLOWED_STRING_LENGTH;\n }\n\n if (typeof keyAttrs === 'string') {\n keyAttrs = [keyAttrs];\n }\n\n // Accessing event.target can throw (see getsentry/raven-js#838, #768)\n try {\n const event = handlerData.event as Event | Node;\n const element = _isEvent(event) ? event.target : event;\n\n target = htmlTreeAsString(element, { keyAttrs, maxStringLength });\n componentName = getComponentName(element);\n } catch {\n target = '<unknown>';\n }\n\n if (target.length === 0) {\n return;\n }\n\n const breadcrumb: Breadcrumb = {\n category: `ui.${handlerData.name}`,\n message: target,\n };\n\n if (componentName) {\n breadcrumb.data = { 'ui.component_name': componentName };\n }\n\n addBreadcrumb(breadcrumb, {\n event: handlerData.event,\n name: handlerData.name,\n global: handlerData.global,\n });\n };\n}\n\n/**\n * Creates breadcrumbs from console API calls\n */\nfunction _getConsoleBreadcrumbHandler(client: Client): (handlerData: HandlerDataConsole) => void {\n return function _consoleBreadcrumb(handlerData: HandlerDataConsole): void {\n if (getClient() !== client) {\n return;\n }\n\n const breadcrumb = {\n category: 'console',\n data: {\n arguments: handlerData.args,\n logger: 'console',\n },\n level: severityLevelFromString(handlerData.level),\n message: safeJoin(handlerData.args, ' '),\n };\n\n if (handlerData.level === 'assert') {\n if (handlerData.args[0] === false) {\n breadcrumb.message = `Assertion failed: ${safeJoin(handlerData.args.slice(1), ' ') || 'console.assert'}`;\n breadcrumb.data.arguments = handlerData.args.slice(1);\n } else {\n // Don't capture a breadcrumb for passed assertions\n return;\n }\n }\n\n addBreadcrumb(breadcrumb, {\n input: handlerData.args,\n level: handlerData.level,\n });\n };\n}\n\n/**\n * Creates breadcrumbs from XHR API calls\n */\nfunction _getXhrBreadcrumbHandler(client: Client): (handlerData: HandlerDataXhr) => void {\n return function _xhrBreadcrumb(handlerData: HandlerDataXhr): void {\n if (getClient() !== client) {\n return;\n }\n\n const { startTimestamp, endTimestamp } = handlerData;\n\n const sentryXhrData = handlerData.xhr[SENTRY_XHR_DATA_KEY];\n\n // We only capture complete, non-sentry requests\n if (!startTimestamp || !endTimestamp || !sentryXhrData) {\n return;\n }\n\n const { method, url, status_code, body } = sentryXhrData;\n\n const data: XhrBreadcrumbData = {\n method,\n url,\n status_code,\n };\n\n const hint: XhrBreadcrumbHint = {\n xhr: handlerData.xhr,\n input: body,\n startTimestamp,\n endTimestamp,\n };\n\n const breadcrumb = {\n category: 'xhr',\n data,\n type: 'http',\n level: getBreadcrumbLogLevelFromHttpStatusCode(status_code),\n };\n\n client.emit('beforeOutgoingRequestBreadcrumb', breadcrumb, hint as XhrHint);\n\n addBreadcrumb(breadcrumb, hint);\n };\n}\n\n/**\n * Creates breadcrumbs from fetch API calls\n */\nfunction _getFetchBreadcrumbHandler(client: Client): (handlerData: HandlerDataFetch) => void {\n return function _fetchBreadcrumb(handlerData: HandlerDataFetch): void {\n if (getClient() !== client) {\n return;\n }\n\n const { startTimestamp, endTimestamp } = handlerData;\n\n // We only capture complete fetch requests\n if (!endTimestamp) {\n return;\n }\n\n if (handlerData.fetchData.url.match(/sentry_key/) && handlerData.fetchData.method === 'POST') {\n // We will not create breadcrumbs for fetch requests that contain `sentry_key` (internal sentry requests)\n return;\n }\n\n if (handlerData.error) {\n const hint: FetchBreadcrumbHint = {\n data: handlerData.error,\n input: handlerData.args,\n startTimestamp,\n endTimestamp,\n };\n\n const breadcrumb = {\n category: 'fetch',\n data: handlerData.fetchData,\n level: 'error',\n type: 'http',\n } satisfies Breadcrumb;\n\n client.emit('beforeOutgoingRequestBreadcrumb', breadcrumb, hint as FetchHint);\n\n addBreadcrumb(breadcrumb, hint);\n } else {\n const response = handlerData.response as Response | undefined;\n const data: FetchBreadcrumbData = {\n ...handlerData.fetchData,\n status_code: response?.status,\n };\n\n const hint: FetchBreadcrumbHint = {\n input: handlerData.args,\n response,\n startTimestamp,\n endTimestamp,\n };\n\n const breadcrumb = {\n category: 'fetch',\n data,\n type: 'http',\n level: getBreadcrumbLogLevelFromHttpStatusCode(data.status_code),\n };\n\n client.emit('beforeOutgoingRequestBreadcrumb', breadcrumb, hint as FetchHint);\n\n addBreadcrumb(breadcrumb, hint);\n }\n };\n}\n\n/**\n * Creates breadcrumbs from history API calls\n */\nfunction _getHistoryBreadcrumbHandler(client: Client): (handlerData: HandlerDataHistory) => void {\n return function _historyBreadcrumb(handlerData: HandlerDataHistory): void {\n if (getClient() !== client) {\n return;\n }\n\n let from: string | undefined = handlerData.from;\n let to: string | undefined = handlerData.to;\n const parsedLoc = parseUrl(WINDOW.location.href);\n let parsedFrom = from ? parseUrl(from) : undefined;\n const parsedTo = parseUrl(to);\n\n // Initial pushState doesn't provide `from` information\n if (!parsedFrom?.path) {\n parsedFrom = parsedLoc;\n }\n\n // Use only the path component of the URL if the URL matches the current\n // document (almost all the time when using pushState)\n if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host) {\n to = parsedTo.relative;\n }\n if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host) {\n from = parsedFrom.relative;\n }\n\n addBreadcrumb({\n category: 'navigation',\n data: {\n from,\n to,\n },\n });\n };\n}\n\nfunction _isEvent(event: unknown): event is Event {\n return !!event && !!(event as Record<string, unknown>).target;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"breadcrumbs.js","sources":["../../../../../src/integrations/breadcrumbs.ts"],"sourcesContent":["/* eslint-disable max-lines */\n\nimport type {\n Breadcrumb,\n Client,\n Event as SentryEvent,\n FetchBreadcrumbData,\n FetchBreadcrumbHint,\n HandlerDataConsole,\n HandlerDataFetch,\n IntegrationFn,\n XhrBreadcrumbData,\n XhrBreadcrumbHint,\n} from '@sentry/core/browser';\nimport {\n addBreadcrumb,\n addConsoleInstrumentationHandler,\n addFetchInstrumentationHandler,\n debug,\n defineIntegration,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getEventDescription,\n parseUrl,\n safeJoin,\n severityLevelFromString,\n} from '@sentry/core/browser';\nimport type { FetchHint, HandlerDataDom, HandlerDataHistory, HandlerDataXhr, XhrHint } from '@sentry/browser-utils';\nimport {\n addClickKeypressInstrumentationHandler,\n addHistoryInstrumentationHandler,\n addXhrInstrumentationHandler,\n htmlTreeAsString,\n getComponentName,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\n\ninterface BreadcrumbsOptions {\n console: boolean;\n dom:\n | boolean\n | {\n serializeAttribute?: string | string[];\n maxStringLength?: number;\n };\n fetch: boolean;\n history: boolean;\n sentry: boolean;\n xhr: boolean;\n}\n\n/** maxStringLength gets capped to prevent 100 breadcrumbs exceeding 1MB event payload size */\nconst MAX_ALLOWED_STRING_LENGTH = 1024;\n\nconst INTEGRATION_NAME = 'Breadcrumbs' as const;\n\nconst _breadcrumbsIntegration = ((options: Partial<BreadcrumbsOptions> = {}) => {\n const _options = {\n console: true,\n dom: true,\n fetch: true,\n history: true,\n sentry: true,\n xhr: true,\n ...options,\n };\n\n return {\n name: INTEGRATION_NAME,\n setup(client) {\n // TODO(v11): Remove this functionality and use `consoleIntegration` from @sentry/core instead.\n if (_options.console) {\n addConsoleInstrumentationHandler(_getConsoleBreadcrumbHandler(client));\n }\n if (_options.dom) {\n addClickKeypressInstrumentationHandler(_getDomBreadcrumbHandler(client, _options.dom));\n }\n if (_options.xhr) {\n addXhrInstrumentationHandler(_getXhrBreadcrumbHandler(client));\n }\n if (_options.fetch) {\n addFetchInstrumentationHandler(_getFetchBreadcrumbHandler(client));\n }\n if (_options.history) {\n addHistoryInstrumentationHandler(_getHistoryBreadcrumbHandler(client));\n }\n if (_options.sentry) {\n client.on('beforeSendEvent', _getSentryBreadcrumbHandler(client));\n }\n },\n };\n}) satisfies IntegrationFn;\n\nexport const breadcrumbsIntegration = defineIntegration(_breadcrumbsIntegration);\n\n/**\n * Adds a breadcrumb for Sentry events or transactions if this option is enabled.\n */\nfunction _getSentryBreadcrumbHandler(client: Client): (event: SentryEvent) => void {\n return function addSentryBreadcrumb(event: SentryEvent): void {\n if (getClient() !== client) {\n return;\n }\n\n addBreadcrumb(\n {\n category: `sentry.${event.type === 'transaction' ? 'transaction' : 'event'}`,\n event_id: event.event_id,\n level: event.level,\n message: getEventDescription(event),\n },\n {\n event,\n },\n );\n };\n}\n\n/**\n * A HOC that creates a function that creates breadcrumbs from DOM API calls.\n * This is a HOC so that we get access to dom options in the closure.\n */\nfunction _getDomBreadcrumbHandler(\n client: Client,\n dom: BreadcrumbsOptions['dom'],\n): (handlerData: HandlerDataDom) => void {\n return function _innerDomBreadcrumb(handlerData: HandlerDataDom): void {\n if (getClient() !== client) {\n return;\n }\n\n let target;\n let componentName;\n let keyAttrs = typeof dom === 'object' ? dom.serializeAttribute : undefined;\n\n let maxStringLength =\n typeof dom === 'object' && typeof dom.maxStringLength === 'number' ? dom.maxStringLength : undefined;\n if (maxStringLength && maxStringLength > MAX_ALLOWED_STRING_LENGTH) {\n DEBUG_BUILD &&\n debug.warn(\n `\\`dom.maxStringLength\\` cannot exceed ${MAX_ALLOWED_STRING_LENGTH}, but a value of ${maxStringLength} was configured. Sentry will use ${MAX_ALLOWED_STRING_LENGTH} instead.`,\n );\n maxStringLength = MAX_ALLOWED_STRING_LENGTH;\n }\n\n if (typeof keyAttrs === 'string') {\n keyAttrs = [keyAttrs];\n }\n\n // Accessing event.target can throw (see getsentry/raven-js#838, #768)\n try {\n const event = handlerData.event as Event | Node;\n const element = _isEvent(event) ? event.target : event;\n\n target = htmlTreeAsString(element, { keyAttrs, maxStringLength });\n componentName = getComponentName(element);\n } catch {\n target = '<unknown>';\n }\n\n if (target.length === 0) {\n return;\n }\n\n const breadcrumb: Breadcrumb = {\n category: `ui.${handlerData.name}`,\n message: target,\n };\n\n if (componentName) {\n breadcrumb.data = { 'ui.component_name': componentName };\n }\n\n addBreadcrumb(breadcrumb, {\n event: handlerData.event,\n name: handlerData.name,\n global: handlerData.global,\n });\n };\n}\n\n/**\n * Creates breadcrumbs from console API calls\n */\nfunction _getConsoleBreadcrumbHandler(client: Client): (handlerData: HandlerDataConsole) => void {\n return function _consoleBreadcrumb(handlerData: HandlerDataConsole): void {\n if (getClient() !== client) {\n return;\n }\n\n const breadcrumb = {\n category: 'console',\n data: {\n arguments: handlerData.args,\n logger: 'console',\n },\n level: severityLevelFromString(handlerData.level),\n message: safeJoin(handlerData.args, ' '),\n };\n\n if (handlerData.level === 'assert') {\n if (handlerData.args[0] === false) {\n breadcrumb.message = `Assertion failed: ${safeJoin(handlerData.args.slice(1), ' ') || 'console.assert'}`;\n breadcrumb.data.arguments = handlerData.args.slice(1);\n } else {\n // Don't capture a breadcrumb for passed assertions\n return;\n }\n }\n\n addBreadcrumb(breadcrumb, {\n input: handlerData.args,\n level: handlerData.level,\n });\n };\n}\n\n/**\n * Creates breadcrumbs from XHR API calls\n */\nfunction _getXhrBreadcrumbHandler(client: Client): (handlerData: HandlerDataXhr) => void {\n return function _xhrBreadcrumb(handlerData: HandlerDataXhr): void {\n if (getClient() !== client) {\n return;\n }\n\n const { startTimestamp, endTimestamp } = handlerData;\n\n const sentryXhrData = handlerData.xhr[SENTRY_XHR_DATA_KEY];\n\n // We only capture complete, non-sentry requests\n if (!startTimestamp || !endTimestamp || !sentryXhrData) {\n return;\n }\n\n const { method, url, status_code, body } = sentryXhrData;\n\n const data: XhrBreadcrumbData = {\n method,\n url,\n status_code,\n };\n\n const hint: XhrBreadcrumbHint = {\n xhr: handlerData.xhr,\n input: body,\n startTimestamp,\n endTimestamp,\n };\n\n const breadcrumb = {\n category: 'xhr',\n data,\n type: 'http',\n level: getBreadcrumbLogLevelFromHttpStatusCode(status_code),\n };\n\n client.emit('beforeOutgoingRequestBreadcrumb', breadcrumb, hint as XhrHint);\n\n addBreadcrumb(breadcrumb, hint);\n };\n}\n\n/**\n * Creates breadcrumbs from fetch API calls\n */\nfunction _getFetchBreadcrumbHandler(client: Client): (handlerData: HandlerDataFetch) => void {\n return function _fetchBreadcrumb(handlerData: HandlerDataFetch): void {\n if (getClient() !== client) {\n return;\n }\n\n const { startTimestamp, endTimestamp } = handlerData;\n\n // We only capture complete fetch requests\n if (!endTimestamp) {\n return;\n }\n\n if (handlerData.fetchData.url.match(/sentry_key/) && handlerData.fetchData.method === 'POST') {\n // We will not create breadcrumbs for fetch requests that contain `sentry_key` (internal sentry requests)\n return;\n }\n\n if (handlerData.error) {\n const hint: FetchBreadcrumbHint = {\n data: handlerData.error,\n input: handlerData.args,\n startTimestamp,\n endTimestamp,\n };\n\n const breadcrumb = {\n category: 'fetch',\n data: handlerData.fetchData,\n level: 'error',\n type: 'http',\n } satisfies Breadcrumb;\n\n client.emit('beforeOutgoingRequestBreadcrumb', breadcrumb, hint as FetchHint);\n\n addBreadcrumb(breadcrumb, hint);\n } else {\n const response = handlerData.response as Response | undefined;\n const data: FetchBreadcrumbData = {\n ...handlerData.fetchData,\n status_code: response?.status,\n };\n\n const hint: FetchBreadcrumbHint = {\n input: handlerData.args,\n response,\n startTimestamp,\n endTimestamp,\n };\n\n const breadcrumb = {\n category: 'fetch',\n data,\n type: 'http',\n level: getBreadcrumbLogLevelFromHttpStatusCode(data.status_code),\n };\n\n client.emit('beforeOutgoingRequestBreadcrumb', breadcrumb, hint as FetchHint);\n\n addBreadcrumb(breadcrumb, hint);\n }\n };\n}\n\n/**\n * Creates breadcrumbs from history API calls\n */\nfunction _getHistoryBreadcrumbHandler(client: Client): (handlerData: HandlerDataHistory) => void {\n return function _historyBreadcrumb(handlerData: HandlerDataHistory): void {\n if (getClient() !== client) {\n return;\n }\n\n let from: string | undefined = handlerData.from;\n let to: string | undefined = handlerData.to;\n const parsedLoc = parseUrl(WINDOW.location.href);\n let parsedFrom = from ? parseUrl(from) : undefined;\n const parsedTo = parseUrl(to);\n\n // Initial pushState doesn't provide `from` information\n if (!parsedFrom?.path) {\n parsedFrom = parsedLoc;\n }\n\n // Use only the path component of the URL if the URL matches the current\n // document (almost all the time when using pushState)\n if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host) {\n to = parsedTo.relative;\n }\n if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host) {\n from = parsedFrom.relative;\n }\n\n addBreadcrumb({\n category: 'navigation',\n data: {\n from,\n to,\n },\n });\n };\n}\n\nfunction _isEvent(event: unknown): event is Event {\n return !!event && !!(event as Record<string, unknown>).target;\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { URL_FULL } from '@sentry/conventions/attributes';
2
- import { defineIntegration, addFetchEndInstrumentationHandler, addFetchInstrumentationHandler, parseStringToURLObject, stripDataUrlContent, getSanitizedUrlStringFromUrlObject, startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, filterCollectedUrl } from '@sentry/core';
1
+ import { HTTP_REQUEST_METHOD, URL_FULL } from '@sentry/conventions/attributes';
2
+ import { defineIntegration, addFetchEndInstrumentationHandler, addFetchInstrumentationHandler, parseStringToURLObject, stripDataUrlContent, getSanitizedUrlStringFromUrlObject, startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, filterCollectedUrl } from '@sentry/core/browser';
3
3
 
4
4
  const responseToStreamSpan = /* @__PURE__ */ new WeakMap();
5
5
  const responseToFallbackTimeout = /* @__PURE__ */ new WeakMap();
@@ -36,7 +36,7 @@ const fetchStreamPerformanceIntegration = defineIntegration(() => {
36
36
  startTime: handlerData.endTimestamp,
37
37
  attributes: {
38
38
  [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),
39
- "http.method": method,
39
+ [HTTP_REQUEST_METHOD]: method,
40
40
  type: "fetch",
41
41
  [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.client.stream",
42
42
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.browser.stream"
@@ -1 +1 @@
1
- {"version":3,"file":"fetchStreamPerformance.js","sources":["../../../../../src/integrations/fetchStreamPerformance.ts"],"sourcesContent":["import { URL_FULL } from '@sentry/conventions/attributes';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n defineIntegration,\n getSanitizedUrlStringFromUrlObject,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startInactiveSpan,\n stripDataUrlContent,\n filterCollectedUrl,\n} from '@sentry/core';\n\nconst responseToStreamSpan = new WeakMap<object, Span>();\nconst responseToFallbackTimeout = new WeakMap<object, ReturnType<typeof setTimeout>>();\n\n// Matches the max timeout in `resolveResponse` in packages/core/src/instrument/fetch.ts\nconst STREAM_RESOLVE_FALLBACK_MS = 90_000;\n\nconst STREAMING_CONTENT_TYPES = ['text/event-stream', 'application/x-ndjson', 'application/stream+json'];\n\n/**\n * Tracks streamed fetch response bodies by creating an `http.client.stream` sibling span.\n *\n * The regular `http.client` span ends when response headers arrive. This integration adds\n * a span that starts at header arrival and ends when the body fully resolves:\n *\n * ```\n * --------- pageload --------------------------------\n * -- http.client --\n * -- http.client.stream -------\n * ```\n */\nexport const fetchStreamPerformanceIntegration = defineIntegration(() => {\n return {\n name: 'FetchStreamPerformance' as const,\n\n setup() {\n // End the stream span when the response body finishes resolving\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const streamSpan = responseToStreamSpan.get(handlerData.response);\n if (streamSpan && handlerData.endTimestamp) {\n streamSpan.end(handlerData.endTimestamp);\n\n const fallbackTimeout = responseToFallbackTimeout.get(handlerData.response);\n if (fallbackTimeout) {\n clearTimeout(fallbackTimeout);\n }\n }\n }\n });\n\n addFetchInstrumentationHandler(handlerData => {\n // Only create the stream span once headers have arrived\n if (handlerData.endTimestamp && handlerData.response) {\n // Only create stream spans for responses that are likely streamed:\n // 1. No content-length header (streamed responses don't know the size upfront)\n // 2. Content-type is a known streaming type (avoids false positives on HTTP/2\n // where content-length is often omitted even for regular responses)\n const contentType = handlerData.response.headers?.get('content-type') || '';\n if (\n handlerData.response.headers?.get('content-length') ||\n !STREAMING_CONTENT_TYPES.some(t => contentType.startsWith(t))\n ) {\n return;\n }\n\n const url = handlerData.fetchData?.url || '';\n const method = handlerData.fetchData?.method || 'GET';\n\n const parsedUrl = parseStringToURLObject(url);\n const sanitizedUrl = url.startsWith('data:')\n ? stripDataUrlContent(url)\n : parsedUrl\n ? getSanitizedUrlStringFromUrlObject(parsedUrl)\n : url;\n\n const streamSpan = startInactiveSpan({\n name: `${method} ${sanitizedUrl}`,\n startTime: handlerData.endTimestamp,\n attributes: {\n [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),\n 'http.method': method,\n type: 'fetch',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client.stream',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser.stream',\n },\n });\n\n responseToStreamSpan.set(handlerData.response, streamSpan);\n\n // prevent the span from leaking indefinitely if the body never resolves\n const fallbackTimeout = setTimeout(() => {\n if (streamSpan.isRecording()) {\n streamSpan.end();\n }\n }, STREAM_RESOLVE_FALLBACK_MS);\n\n responseToFallbackTimeout.set(handlerData.response, fallbackTimeout);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":[],"mappings":";;;AAeA,MAAM,oBAAA,uBAA2B,OAAA,EAAsB;AACvD,MAAM,yBAAA,uBAAgC,OAAA,EAA+C;AAGrF,MAAM,0BAAA,GAA6B,GAAA;AAEnC,MAAM,uBAAA,GAA0B,CAAC,mBAAA,EAAqB,sBAAA,EAAwB,yBAAyB,CAAA;AAchG,MAAM,iCAAA,GAAoC,kBAAkB,MAAM;AACvE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,wBAAA;AAAA,IAEN,KAAA,GAAQ;AAEN,MAAA,iCAAA,CAAkC,CAAA,WAAA,KAAe;AAC/C,QAAA,IAAI,YAAY,QAAA,EAAU;AACxB,UAAA,MAAM,UAAA,GAAa,oBAAA,CAAqB,GAAA,CAAI,WAAA,CAAY,QAAQ,CAAA;AAChE,UAAA,IAAI,UAAA,IAAc,YAAY,YAAA,EAAc;AAC1C,YAAA,UAAA,CAAW,GAAA,CAAI,YAAY,YAAY,CAAA;AAEvC,YAAA,MAAM,eAAA,GAAkB,yBAAA,CAA0B,GAAA,CAAI,WAAA,CAAY,QAAQ,CAAA;AAC1E,YAAA,IAAI,eAAA,EAAiB;AACnB,cAAA,YAAA,CAAa,eAAe,CAAA;AAAA,YAC9B;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC,CAAA;AAED,MAAA,8BAAA,CAA+B,CAAA,WAAA,KAAe;AAE5C,QAAA,IAAI,WAAA,CAAY,YAAA,IAAgB,WAAA,CAAY,QAAA,EAAU;AAKpD,UAAA,MAAM,cAAc,WAAA,CAAY,QAAA,CAAS,OAAA,EAAS,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AACzE,UAAA,IACE,WAAA,CAAY,QAAA,CAAS,OAAA,EAAS,GAAA,CAAI,gBAAgB,CAAA,IAClD,CAAC,uBAAA,CAAwB,IAAA,CAAK,CAAA,CAAA,KAAK,WAAA,CAAY,UAAA,CAAW,CAAC,CAAC,CAAA,EAC5D;AACA,YAAA;AAAA,UACF;AAEA,UAAA,MAAM,GAAA,GAAM,WAAA,CAAY,SAAA,EAAW,GAAA,IAAO,EAAA;AAC1C,UAAA,MAAM,MAAA,GAAS,WAAA,CAAY,SAAA,EAAW,MAAA,IAAU,KAAA;AAEhD,UAAA,MAAM,SAAA,GAAY,uBAAuB,GAAG,CAAA;AAC5C,UAAA,MAAM,YAAA,GAAe,GAAA,CAAI,UAAA,CAAW,OAAO,CAAA,GACvC,mBAAA,CAAoB,GAAG,CAAA,GACvB,SAAA,GACE,kCAAA,CAAmC,SAAS,CAAA,GAC5C,GAAA;AAEN,UAAA,MAAM,aAAa,iBAAA,CAAkB;AAAA,YACnC,IAAA,EAAM,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AAAA,YAC/B,WAAW,WAAA,CAAY,YAAA;AAAA,YACvB,UAAA,EAAY;AAAA,cACV,CAAC,QAAQ,GAAG,kBAAA,CAAmB,mBAAA,CAAoB,GAAG,CAAC,CAAA;AAAA,cACvD,aAAA,EAAe,MAAA;AAAA,cACf,IAAA,EAAM,OAAA;AAAA,cACN,CAAC,4BAA4B,GAAG,oBAAA;AAAA,cAChC,CAAC,gCAAgC,GAAG;AAAA;AACtC,WACD,CAAA;AAED,UAAA,oBAAA,CAAqB,GAAA,CAAI,WAAA,CAAY,QAAA,EAAU,UAAU,CAAA;AAGzD,UAAA,MAAM,eAAA,GAAkB,WAAW,MAAM;AACvC,YAAA,IAAI,UAAA,CAAW,aAAY,EAAG;AAC5B,cAAA,UAAA,CAAW,GAAA,EAAI;AAAA,YACjB;AAAA,UACF,GAAG,0BAA0B,CAAA;AAE7B,UAAA,yBAAA,CAA0B,GAAA,CAAI,WAAA,CAAY,QAAA,EAAU,eAAe,CAAA;AAAA,QACrE;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"fetchStreamPerformance.js","sources":["../../../../../src/integrations/fetchStreamPerformance.ts"],"sourcesContent":["import { HTTP_REQUEST_METHOD, URL_FULL } from '@sentry/conventions/attributes';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n defineIntegration,\n getSanitizedUrlStringFromUrlObject,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n stripDataUrlContent,\n filterCollectedUrl,\n startInactiveSpan,\n} from '@sentry/core/browser';\n\nconst responseToStreamSpan = new WeakMap<object, Span>();\nconst responseToFallbackTimeout = new WeakMap<object, ReturnType<typeof setTimeout>>();\n\n// Matches the max timeout in `resolveResponse` in packages/core/src/instrument/fetch.ts\nconst STREAM_RESOLVE_FALLBACK_MS = 90_000;\n\nconst STREAMING_CONTENT_TYPES = ['text/event-stream', 'application/x-ndjson', 'application/stream+json'];\n\n/**\n * Tracks streamed fetch response bodies by creating an `http.client.stream` sibling span.\n *\n * The regular `http.client` span ends when response headers arrive. This integration adds\n * a span that starts at header arrival and ends when the body fully resolves:\n *\n * ```\n * --------- pageload --------------------------------\n * -- http.client --\n * -- http.client.stream -------\n * ```\n */\nexport const fetchStreamPerformanceIntegration = defineIntegration(() => {\n return {\n name: 'FetchStreamPerformance' as const,\n\n setup() {\n // End the stream span when the response body finishes resolving\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const streamSpan = responseToStreamSpan.get(handlerData.response);\n if (streamSpan && handlerData.endTimestamp) {\n streamSpan.end(handlerData.endTimestamp);\n\n const fallbackTimeout = responseToFallbackTimeout.get(handlerData.response);\n if (fallbackTimeout) {\n clearTimeout(fallbackTimeout);\n }\n }\n }\n });\n\n addFetchInstrumentationHandler(handlerData => {\n // Only create the stream span once headers have arrived\n if (handlerData.endTimestamp && handlerData.response) {\n // Only create stream spans for responses that are likely streamed:\n // 1. No content-length header (streamed responses don't know the size upfront)\n // 2. Content-type is a known streaming type (avoids false positives on HTTP/2\n // where content-length is often omitted even for regular responses)\n const contentType = handlerData.response.headers?.get('content-type') || '';\n if (\n handlerData.response.headers?.get('content-length') ||\n !STREAMING_CONTENT_TYPES.some(t => contentType.startsWith(t))\n ) {\n return;\n }\n\n const url = handlerData.fetchData?.url || '';\n const method = handlerData.fetchData?.method || 'GET';\n\n const parsedUrl = parseStringToURLObject(url);\n const sanitizedUrl = url.startsWith('data:')\n ? stripDataUrlContent(url)\n : parsedUrl\n ? getSanitizedUrlStringFromUrlObject(parsedUrl)\n : url;\n\n const streamSpan = startInactiveSpan({\n name: `${method} ${sanitizedUrl}`,\n startTime: handlerData.endTimestamp,\n attributes: {\n [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),\n [HTTP_REQUEST_METHOD]: method,\n type: 'fetch',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client.stream',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser.stream',\n },\n });\n\n responseToStreamSpan.set(handlerData.response, streamSpan);\n\n // prevent the span from leaking indefinitely if the body never resolves\n const fallbackTimeout = setTimeout(() => {\n if (streamSpan.isRecording()) {\n streamSpan.end();\n }\n }, STREAM_RESOLVE_FALLBACK_MS);\n\n responseToFallbackTimeout.set(handlerData.response, fallbackTimeout);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":[],"mappings":";;;AAeA,MAAM,oBAAA,uBAA2B,OAAA,EAAsB;AACvD,MAAM,yBAAA,uBAAgC,OAAA,EAA+C;AAGrF,MAAM,0BAAA,GAA6B,GAAA;AAEnC,MAAM,uBAAA,GAA0B,CAAC,mBAAA,EAAqB,sBAAA,EAAwB,yBAAyB,CAAA;AAchG,MAAM,iCAAA,GAAoC,kBAAkB,MAAM;AACvE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,wBAAA;AAAA,IAEN,KAAA,GAAQ;AAEN,MAAA,iCAAA,CAAkC,CAAA,WAAA,KAAe;AAC/C,QAAA,IAAI,YAAY,QAAA,EAAU;AACxB,UAAA,MAAM,UAAA,GAAa,oBAAA,CAAqB,GAAA,CAAI,WAAA,CAAY,QAAQ,CAAA;AAChE,UAAA,IAAI,UAAA,IAAc,YAAY,YAAA,EAAc;AAC1C,YAAA,UAAA,CAAW,GAAA,CAAI,YAAY,YAAY,CAAA;AAEvC,YAAA,MAAM,eAAA,GAAkB,yBAAA,CAA0B,GAAA,CAAI,WAAA,CAAY,QAAQ,CAAA;AAC1E,YAAA,IAAI,eAAA,EAAiB;AACnB,cAAA,YAAA,CAAa,eAAe,CAAA;AAAA,YAC9B;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC,CAAA;AAED,MAAA,8BAAA,CAA+B,CAAA,WAAA,KAAe;AAE5C,QAAA,IAAI,WAAA,CAAY,YAAA,IAAgB,WAAA,CAAY,QAAA,EAAU;AAKpD,UAAA,MAAM,cAAc,WAAA,CAAY,QAAA,CAAS,OAAA,EAAS,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AACzE,UAAA,IACE,WAAA,CAAY,QAAA,CAAS,OAAA,EAAS,GAAA,CAAI,gBAAgB,CAAA,IAClD,CAAC,uBAAA,CAAwB,IAAA,CAAK,CAAA,CAAA,KAAK,WAAA,CAAY,UAAA,CAAW,CAAC,CAAC,CAAA,EAC5D;AACA,YAAA;AAAA,UACF;AAEA,UAAA,MAAM,GAAA,GAAM,WAAA,CAAY,SAAA,EAAW,GAAA,IAAO,EAAA;AAC1C,UAAA,MAAM,MAAA,GAAS,WAAA,CAAY,SAAA,EAAW,MAAA,IAAU,KAAA;AAEhD,UAAA,MAAM,SAAA,GAAY,uBAAuB,GAAG,CAAA;AAC5C,UAAA,MAAM,YAAA,GAAe,GAAA,CAAI,UAAA,CAAW,OAAO,CAAA,GACvC,mBAAA,CAAoB,GAAG,CAAA,GACvB,SAAA,GACE,kCAAA,CAAmC,SAAS,CAAA,GAC5C,GAAA;AAEN,UAAA,MAAM,aAAa,iBAAA,CAAkB;AAAA,YACnC,IAAA,EAAM,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AAAA,YAC/B,WAAW,WAAA,CAAY,YAAA;AAAA,YACvB,UAAA,EAAY;AAAA,cACV,CAAC,QAAQ,GAAG,kBAAA,CAAmB,mBAAA,CAAoB,GAAG,CAAC,CAAA;AAAA,cACvD,CAAC,mBAAmB,GAAG,MAAA;AAAA,cACvB,IAAA,EAAM,OAAA;AAAA,cACN,CAAC,4BAA4B,GAAG,oBAAA;AAAA,cAChC,CAAC,gCAAgC,GAAG;AAAA;AACtC,WACD,CAAA;AAED,UAAA,oBAAA,CAAqB,GAAA,CAAI,WAAA,CAAY,QAAA,EAAU,UAAU,CAAA;AAGzD,UAAA,MAAM,eAAA,GAAkB,WAAW,MAAM;AACvC,YAAA,IAAI,UAAA,CAAW,aAAY,EAAG;AAC5B,cAAA,UAAA,CAAW,GAAA,EAAI;AAAA,YACjB;AAAA,UACF,GAAG,0BAA0B,CAAA;AAE7B,UAAA,yBAAA,CAA0B,GAAA,CAAI,WAAA,CAAY,QAAA,EAAU,eAAe,CAAA;AAAA,QACrE;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAC;;;;"}
@@ -1,5 +1,6 @@
1
- import { defineIntegration, addGlobalErrorInstrumentationHandler, getClient, captureEvent, debug, addGlobalUnhandledRejectionInstrumentationHandler, isPrimitive, UNKNOWN_FUNCTION, getLocationHref, isString, stripDataUrlContent } from '@sentry/core/browser';
1
+ import { defineIntegration, addGlobalErrorInstrumentationHandler, getClient, captureEvent, debug, addGlobalUnhandledRejectionInstrumentationHandler, isPrimitive, UNKNOWN_FUNCTION, isString, stripDataUrlContent } from '@sentry/core/browser';
2
2
  import { DEBUG_BUILD } from '../debug-build.js';
3
+ import { getLocationHref } from '@sentry/browser-utils';
3
4
  import { eventFromUnknownInput } from '../eventbuilder.js';
4
5
  import { shouldIgnoreOnError } from '../helpers.js';
5
6
 
@@ -1 +1 @@
1
- {"version":3,"file":"globalhandlers.js","sources":["../../../../../src/integrations/globalhandlers.ts"],"sourcesContent":["import type { Client, Event, IntegrationFn, Primitive, StackParser } from '@sentry/core/browser';\nimport {\n addGlobalErrorInstrumentationHandler,\n addGlobalUnhandledRejectionInstrumentationHandler,\n captureEvent,\n debug,\n defineIntegration,\n getClient,\n getLocationHref,\n isPrimitive,\n isString,\n stripDataUrlContent,\n UNKNOWN_FUNCTION,\n} from '@sentry/core/browser';\nimport type { BrowserClient } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { eventFromUnknownInput } from '../eventbuilder';\nimport { shouldIgnoreOnError } from '../helpers';\n\ntype GlobalHandlersIntegrationsOptionKeys = 'onerror' | 'onunhandledrejection';\n\ntype GlobalHandlersIntegrations = Record<GlobalHandlersIntegrationsOptionKeys, boolean>;\n\nconst INTEGRATION_NAME = 'GlobalHandlers' as const;\n\nconst _globalHandlersIntegration = ((options: Partial<GlobalHandlersIntegrations> = {}) => {\n const _options = {\n onerror: true,\n onunhandledrejection: true,\n ...options,\n };\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n Error.stackTraceLimit = 50;\n },\n setup(client) {\n if (_options.onerror) {\n _installGlobalOnErrorHandler(client);\n globalHandlerLog('onerror');\n }\n if (_options.onunhandledrejection) {\n _installGlobalOnUnhandledRejectionHandler(client);\n globalHandlerLog('onunhandledrejection');\n }\n },\n };\n}) satisfies IntegrationFn;\n\nexport const globalHandlersIntegration = defineIntegration(_globalHandlersIntegration);\n\nfunction _installGlobalOnErrorHandler(client: Client): void {\n addGlobalErrorInstrumentationHandler(data => {\n const { stackParser, attachStacktrace } = getOptions();\n\n if (getClient() !== client || shouldIgnoreOnError()) {\n return;\n }\n\n const { msg, url, line, column, error } = data;\n\n const event = _enhanceEventWithInitialFrame(\n eventFromUnknownInput(stackParser, error || msg, undefined, attachStacktrace, false),\n url,\n line,\n column,\n );\n\n event.level = 'error';\n\n captureEvent(event, {\n originalException: error,\n mechanism: {\n handled: false,\n type: 'auto.browser.global_handlers.onerror',\n },\n });\n });\n}\n\nfunction _installGlobalOnUnhandledRejectionHandler(client: Client): void {\n addGlobalUnhandledRejectionInstrumentationHandler(e => {\n const { stackParser, attachStacktrace } = getOptions();\n\n if (getClient() !== client || shouldIgnoreOnError()) {\n return;\n }\n\n const error = _getUnhandledRejectionError(e);\n\n const event = isPrimitive(error)\n ? _eventFromRejectionWithPrimitive(error)\n : eventFromUnknownInput(stackParser, error, undefined, attachStacktrace, true);\n\n event.level = 'error';\n\n captureEvent(event, {\n originalException: error,\n mechanism: {\n handled: false,\n type: 'auto.browser.global_handlers.onunhandledrejection',\n },\n });\n });\n}\n\n/**\n *\n */\nexport function _getUnhandledRejectionError(error: unknown): unknown {\n if (isPrimitive(error)) {\n return error;\n }\n\n // dig the object of the rejection out of known event types\n try {\n type ErrorWithReason = { reason: unknown };\n // PromiseRejectionEvents store the object of the rejection under 'reason'\n // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent\n if ('reason' in (error as ErrorWithReason)) {\n return (error as ErrorWithReason).reason;\n }\n\n type CustomEventWithDetail = { detail: { reason: unknown } };\n // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents\n // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into\n // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec\n // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and\n // https://github.com/getsentry/sentry-javascript/issues/2380\n if ('detail' in (error as CustomEventWithDetail) && 'reason' in (error as CustomEventWithDetail).detail) {\n return (error as CustomEventWithDetail).detail.reason;\n }\n } catch {} // eslint-disable-line no-empty\n\n return error;\n}\n\n/**\n * Create an event from a promise rejection where the `reason` is a primitive.\n *\n * @param reason: The `reason` property of the promise rejection\n * @returns An Event object with an appropriate `exception` value\n */\nexport function _eventFromRejectionWithPrimitive(reason: Primitive): Event {\n return {\n exception: {\n values: [\n {\n type: 'UnhandledRejection',\n // String() is needed because the Primitive type includes symbols (which can't be automatically stringified)\n value: `Non-Error promise rejection captured with value: ${String(reason)}`,\n },\n ],\n },\n };\n}\n\nfunction _enhanceEventWithInitialFrame(\n event: Event,\n url: string | undefined,\n lineno: number | undefined,\n colno: number | undefined,\n): Event {\n // event.exception\n const e = (event.exception = event.exception || {});\n // event.exception.values\n const ev = (e.values = e.values || []);\n // event.exception.values[0]\n const ev0 = (ev[0] = ev[0] || {});\n // event.exception.values[0].stacktrace\n const ev0s = (ev0.stacktrace = ev0.stacktrace || {});\n // event.exception.values[0].stacktrace.frames\n const ev0sf = (ev0s.frames = ev0s.frames || []);\n\n if (ev0sf.length === 0) {\n ev0sf.push({\n colno,\n lineno,\n filename: getFilenameFromUrl(url) ?? getLocationHref(),\n function: UNKNOWN_FUNCTION,\n in_app: true,\n });\n }\n\n return event;\n}\n\nfunction globalHandlerLog(type: string): void {\n DEBUG_BUILD && debug.log(`Global Handler attached: ${type}`);\n}\n\nfunction getOptions(): { stackParser: StackParser; attachStacktrace?: boolean } {\n const client = getClient<BrowserClient>();\n const options = client?.getOptions() || {\n stackParser: () => [],\n attachStacktrace: false,\n };\n return options;\n}\n\nfunction getFilenameFromUrl(url: string | undefined): string | undefined {\n if (!isString(url) || url.length === 0) {\n return undefined;\n }\n\n // Strip data URL content to avoid long base64 strings in stack frames\n // (e.g. when initializing a Worker with a base64 encoded script)\n // Don't include data prefix for filenames as it's not useful for stack traces\n // Wrap with < > to indicate it's a placeholder\n if (url.startsWith('data:')) {\n return `<${stripDataUrlContent(url, false)}>`;\n }\n\n return url;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"globalhandlers.js","sources":["../../../../../src/integrations/globalhandlers.ts"],"sourcesContent":["import type { Client, Event, IntegrationFn, Primitive, StackParser } from '@sentry/core/browser';\nimport {\n addGlobalErrorInstrumentationHandler,\n addGlobalUnhandledRejectionInstrumentationHandler,\n captureEvent,\n debug,\n defineIntegration,\n getClient,\n isPrimitive,\n isString,\n stripDataUrlContent,\n UNKNOWN_FUNCTION,\n} from '@sentry/core/browser';\nimport type { BrowserClient } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { getLocationHref } from '@sentry/browser-utils';\nimport { eventFromUnknownInput } from '../eventbuilder';\nimport { shouldIgnoreOnError } from '../helpers';\n\ntype GlobalHandlersIntegrationsOptionKeys = 'onerror' | 'onunhandledrejection';\n\ntype GlobalHandlersIntegrations = Record<GlobalHandlersIntegrationsOptionKeys, boolean>;\n\nconst INTEGRATION_NAME = 'GlobalHandlers' as const;\n\nconst _globalHandlersIntegration = ((options: Partial<GlobalHandlersIntegrations> = {}) => {\n const _options = {\n onerror: true,\n onunhandledrejection: true,\n ...options,\n };\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n Error.stackTraceLimit = 50;\n },\n setup(client) {\n if (_options.onerror) {\n _installGlobalOnErrorHandler(client);\n globalHandlerLog('onerror');\n }\n if (_options.onunhandledrejection) {\n _installGlobalOnUnhandledRejectionHandler(client);\n globalHandlerLog('onunhandledrejection');\n }\n },\n };\n}) satisfies IntegrationFn;\n\nexport const globalHandlersIntegration = defineIntegration(_globalHandlersIntegration);\n\nfunction _installGlobalOnErrorHandler(client: Client): void {\n addGlobalErrorInstrumentationHandler(data => {\n const { stackParser, attachStacktrace } = getOptions();\n\n if (getClient() !== client || shouldIgnoreOnError()) {\n return;\n }\n\n const { msg, url, line, column, error } = data;\n\n const event = _enhanceEventWithInitialFrame(\n eventFromUnknownInput(stackParser, error || msg, undefined, attachStacktrace, false),\n url,\n line,\n column,\n );\n\n event.level = 'error';\n\n captureEvent(event, {\n originalException: error,\n mechanism: {\n handled: false,\n type: 'auto.browser.global_handlers.onerror',\n },\n });\n });\n}\n\nfunction _installGlobalOnUnhandledRejectionHandler(client: Client): void {\n addGlobalUnhandledRejectionInstrumentationHandler(e => {\n const { stackParser, attachStacktrace } = getOptions();\n\n if (getClient() !== client || shouldIgnoreOnError()) {\n return;\n }\n\n const error = _getUnhandledRejectionError(e);\n\n const event = isPrimitive(error)\n ? _eventFromRejectionWithPrimitive(error)\n : eventFromUnknownInput(stackParser, error, undefined, attachStacktrace, true);\n\n event.level = 'error';\n\n captureEvent(event, {\n originalException: error,\n mechanism: {\n handled: false,\n type: 'auto.browser.global_handlers.onunhandledrejection',\n },\n });\n });\n}\n\n/**\n *\n */\nexport function _getUnhandledRejectionError(error: unknown): unknown {\n if (isPrimitive(error)) {\n return error;\n }\n\n // dig the object of the rejection out of known event types\n try {\n type ErrorWithReason = { reason: unknown };\n // PromiseRejectionEvents store the object of the rejection under 'reason'\n // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent\n if ('reason' in (error as ErrorWithReason)) {\n return (error as ErrorWithReason).reason;\n }\n\n type CustomEventWithDetail = { detail: { reason: unknown } };\n // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents\n // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into\n // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec\n // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and\n // https://github.com/getsentry/sentry-javascript/issues/2380\n if ('detail' in (error as CustomEventWithDetail) && 'reason' in (error as CustomEventWithDetail).detail) {\n return (error as CustomEventWithDetail).detail.reason;\n }\n } catch {} // eslint-disable-line no-empty\n\n return error;\n}\n\n/**\n * Create an event from a promise rejection where the `reason` is a primitive.\n *\n * @param reason: The `reason` property of the promise rejection\n * @returns An Event object with an appropriate `exception` value\n */\nexport function _eventFromRejectionWithPrimitive(reason: Primitive): Event {\n return {\n exception: {\n values: [\n {\n type: 'UnhandledRejection',\n // String() is needed because the Primitive type includes symbols (which can't be automatically stringified)\n value: `Non-Error promise rejection captured with value: ${String(reason)}`,\n },\n ],\n },\n };\n}\n\nfunction _enhanceEventWithInitialFrame(\n event: Event,\n url: string | undefined,\n lineno: number | undefined,\n colno: number | undefined,\n): Event {\n // event.exception\n const e = (event.exception = event.exception || {});\n // event.exception.values\n const ev = (e.values = e.values || []);\n // event.exception.values[0]\n const ev0 = (ev[0] = ev[0] || {});\n // event.exception.values[0].stacktrace\n const ev0s = (ev0.stacktrace = ev0.stacktrace || {});\n // event.exception.values[0].stacktrace.frames\n const ev0sf = (ev0s.frames = ev0s.frames || []);\n\n if (ev0sf.length === 0) {\n ev0sf.push({\n colno,\n lineno,\n filename: getFilenameFromUrl(url) ?? getLocationHref(),\n function: UNKNOWN_FUNCTION,\n in_app: true,\n });\n }\n\n return event;\n}\n\nfunction globalHandlerLog(type: string): void {\n DEBUG_BUILD && debug.log(`Global Handler attached: ${type}`);\n}\n\nfunction getOptions(): { stackParser: StackParser; attachStacktrace?: boolean } {\n const client = getClient<BrowserClient>();\n const options = client?.getOptions() || {\n stackParser: () => [],\n attachStacktrace: false,\n };\n return options;\n}\n\nfunction getFilenameFromUrl(url: string | undefined): string | undefined {\n if (!isString(url) || url.length === 0) {\n return undefined;\n }\n\n // Strip data URL content to avoid long base64 strings in stack frames\n // (e.g. when initializing a Worker with a base64 encoded script)\n // Don't include data prefix for filenames as it's not useful for stack traces\n // Wrap with < > to indicate it's a placeholder\n if (url.startsWith('data:')) {\n return `<${stripDataUrlContent(url, false)}>`;\n }\n\n return url;\n}\n"],"names":[],"mappings":";;;;;;AAuBA,MAAM,gBAAA,GAAmB,gBAAA;AAEzB,MAAM,0BAAA,IAA8B,CAAC,OAAA,GAA+C,EAAC,KAAM;AACzF,EAAA,MAAM,QAAA,GAAW;AAAA,IACf,OAAA,EAAS,IAAA;AAAA,IACT,oBAAA,EAAsB,IAAA;AAAA,IACtB,GAAG;AAAA,GACL;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,SAAA,GAAY;AACV,MAAA,KAAA,CAAM,eAAA,GAAkB,EAAA;AAAA,IAC1B,CAAA;AAAA,IACA,MAAM,MAAA,EAAQ;AACZ,MAAA,IAAI,SAAS,OAAA,EAAS;AACpB,QAAA,4BAAA,CAA6B,MAAM,CAAA;AACnC,QAAA,gBAAA,CAAiB,SAAS,CAAA;AAAA,MAC5B;AACA,MAAA,IAAI,SAAS,oBAAA,EAAsB;AACjC,QAAA,yCAAA,CAA0C,MAAM,CAAA;AAChD,QAAA,gBAAA,CAAiB,sBAAsB,CAAA;AAAA,MACzC;AAAA,IACF;AAAA,GACF;AACF,CAAA,CAAA;AAEO,MAAM,yBAAA,GAA4B,kBAAkB,0BAA0B;AAErF,SAAS,6BAA6B,MAAA,EAAsB;AAC1D,EAAA,oCAAA,CAAqC,CAAA,IAAA,KAAQ;AAC3C,IAAA,MAAM,EAAE,WAAA,EAAa,gBAAA,EAAiB,GAAI,UAAA,EAAW;AAErD,IAAA,IAAI,SAAA,EAAU,KAAM,MAAA,IAAU,mBAAA,EAAoB,EAAG;AACnD,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,GAAA,EAAK,GAAA,EAAK,IAAA,EAAM,MAAA,EAAQ,OAAM,GAAI,IAAA;AAE1C,IAAA,MAAM,KAAA,GAAQ,6BAAA;AAAA,MACZ,sBAAsB,WAAA,EAAa,KAAA,IAAS,GAAA,EAAK,MAAA,EAAW,kBAAkB,KAAK,CAAA;AAAA,MACnF,GAAA;AAAA,MACA,IAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,KAAA,CAAM,KAAA,GAAQ,OAAA;AAEd,IAAA,YAAA,CAAa,KAAA,EAAO;AAAA,MAClB,iBAAA,EAAmB,KAAA;AAAA,MACnB,SAAA,EAAW;AAAA,QACT,OAAA,EAAS,KAAA;AAAA,QACT,IAAA,EAAM;AAAA;AACR,KACD,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAEA,SAAS,0CAA0C,MAAA,EAAsB;AACvE,EAAA,iDAAA,CAAkD,CAAA,CAAA,KAAK;AACrD,IAAA,MAAM,EAAE,WAAA,EAAa,gBAAA,EAAiB,GAAI,UAAA,EAAW;AAErD,IAAA,IAAI,SAAA,EAAU,KAAM,MAAA,IAAU,mBAAA,EAAoB,EAAG;AACnD,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,KAAA,GAAQ,4BAA4B,CAAC,CAAA;AAE3C,IAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,KAAK,CAAA,GAC3B,gCAAA,CAAiC,KAAK,CAAA,GACtC,qBAAA,CAAsB,WAAA,EAAa,KAAA,EAAO,MAAA,EAAW,gBAAA,EAAkB,IAAI,CAAA;AAE/E,IAAA,KAAA,CAAM,KAAA,GAAQ,OAAA;AAEd,IAAA,YAAA,CAAa,KAAA,EAAO;AAAA,MAClB,iBAAA,EAAmB,KAAA;AAAA,MACnB,SAAA,EAAW;AAAA,QACT,OAAA,EAAS,KAAA;AAAA,QACT,IAAA,EAAM;AAAA;AACR,KACD,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAKO,SAAS,4BAA4B,KAAA,EAAyB;AACnE,EAAA,IAAI,WAAA,CAAY,KAAK,CAAA,EAAG;AACtB,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,IAAI;AAIF,IAAA,IAAI,YAAa,KAAA,EAA2B;AAC1C,MAAA,OAAQ,KAAA,CAA0B,MAAA;AAAA,IACpC;AAQA,IAAA,IAAI,QAAA,IAAa,KAAA,IAAmC,QAAA,IAAa,KAAA,CAAgC,MAAA,EAAQ;AACvG,MAAA,OAAQ,MAAgC,MAAA,CAAO,MAAA;AAAA,IACjD;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAAC;AAET,EAAA,OAAO,KAAA;AACT;AAQO,SAAS,iCAAiC,MAAA,EAA0B;AACzE,EAAA,OAAO;AAAA,IACL,SAAA,EAAW;AAAA,MACT,MAAA,EAAQ;AAAA,QACN;AAAA,UACE,IAAA,EAAM,oBAAA;AAAA;AAAA,UAEN,KAAA,EAAO,CAAA,iDAAA,EAAoD,MAAA,CAAO,MAAM,CAAC,CAAA;AAAA;AAC3E;AACF;AACF,GACF;AACF;AAEA,SAAS,6BAAA,CACP,KAAA,EACA,GAAA,EACA,MAAA,EACA,KAAA,EACO;AAEP,EAAA,MAAM,CAAA,GAAK,KAAA,CAAM,SAAA,GAAY,KAAA,CAAM,aAAa,EAAC;AAEjD,EAAA,MAAM,EAAA,GAAM,CAAA,CAAE,MAAA,GAAS,CAAA,CAAE,UAAU,EAAC;AAEpC,EAAA,MAAM,MAAO,EAAA,CAAG,CAAC,IAAI,EAAA,CAAG,CAAC,KAAK,EAAC;AAE/B,EAAA,MAAM,IAAA,GAAQ,GAAA,CAAI,UAAA,GAAa,GAAA,CAAI,cAAc,EAAC;AAElD,EAAA,MAAM,KAAA,GAAS,IAAA,CAAK,MAAA,GAAS,IAAA,CAAK,UAAU,EAAC;AAE7C,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,KAAA,CAAM,IAAA,CAAK;AAAA,MACT,KAAA;AAAA,MACA,MAAA;AAAA,MACA,QAAA,EAAU,kBAAA,CAAmB,GAAG,CAAA,IAAK,eAAA,EAAgB;AAAA,MACrD,QAAA,EAAU,gBAAA;AAAA,MACV,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,iBAAiB,IAAA,EAAoB;AAC5C,EAAA,WAAA,IAAe,KAAA,CAAM,GAAA,CAAI,CAAA,yBAAA,EAA4B,IAAI,CAAA,CAAE,CAAA;AAC7D;AAEA,SAAS,UAAA,GAAuE;AAC9E,EAAA,MAAM,SAAS,SAAA,EAAyB;AACxC,EAAA,MAAM,OAAA,GAAU,MAAA,EAAQ,UAAA,EAAW,IAAK;AAAA,IACtC,WAAA,EAAa,MAAM,EAAC;AAAA,IACpB,gBAAA,EAAkB;AAAA,GACpB;AACA,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,mBAAmB,GAAA,EAA6C;AACvE,EAAA,IAAI,CAAC,QAAA,CAAS,GAAG,CAAA,IAAK,GAAA,CAAI,WAAW,CAAA,EAAG;AACtC,IAAA,OAAO,MAAA;AAAA,EACT;AAMA,EAAA,IAAI,GAAA,CAAI,UAAA,CAAW,OAAO,CAAA,EAAG;AAC3B,IAAA,OAAO,CAAA,CAAA,EAAI,mBAAA,CAAoB,GAAA,EAAK,KAAK,CAAC,CAAA,CAAA,CAAA;AAAA,EAC5C;AAEA,EAAA,OAAO,GAAA;AACT;;;;"}
@@ -1,6 +1,6 @@
1
- import { defineIntegration, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD, isString, stringMatchesSomePattern, isObjectLike } from '@sentry/core/browser';
1
+ import { defineIntegration, spanToJSON, SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD, isString, stringMatchesSomePattern, isObjectLike } from '@sentry/core/browser';
2
2
  import { SENTRY_XHR_DATA_KEY, getBodyString, getFetchRequestArgBody } from '@sentry/browser-utils';
3
- import { URL_FULL, GRAPHQL_DOCUMENT } from '@sentry/conventions/attributes';
3
+ import { SENTRY_OP, URL_FULL, HTTP_METHOD, GRAPHQL_DOCUMENT } from '@sentry/conventions/attributes';
4
4
 
5
5
  const INTEGRATION_NAME = "GraphQLClient";
6
6
  const _graphqlClientIntegration = ((options) => {
@@ -15,14 +15,14 @@ const _graphqlClientIntegration = ((options) => {
15
15
  function _updateSpanWithGraphQLData(client, options) {
16
16
  client.on("beforeOutgoingRequestSpan", (span, hint) => {
17
17
  const spanJSON = spanToJSON(span);
18
- const spanAttributes = spanJSON.data || {};
19
- const spanOp = spanAttributes[SEMANTIC_ATTRIBUTE_SENTRY_OP];
18
+ const spanAttributes = spanJSON.attributes;
19
+ const spanOp = spanAttributes[SENTRY_OP];
20
20
  const isHttpClientSpan = spanOp === "http.client";
21
21
  if (!isHttpClientSpan) {
22
22
  return;
23
23
  }
24
24
  const httpUrl = spanAttributes[URL_FULL];
25
- const httpMethod = spanAttributes[SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD] || spanAttributes["http.method"];
25
+ const httpMethod = spanAttributes[SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD] || spanAttributes[HTTP_METHOD];
26
26
  if (!isString(httpUrl) || !isString(httpMethod)) {
27
27
  return;
28
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"graphqlClient.js","sources":["../../../../../src/integrations/graphqlClient.ts"],"sourcesContent":["import type { Client, IntegrationFn } from '@sentry/core/browser';\nimport {\n defineIntegration,\n isObjectLike,\n isString,\n SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n spanToJSON,\n stringMatchesSomePattern,\n} from '@sentry/core/browser';\nimport type { FetchHint, XhrHint } from '@sentry/browser-utils';\nimport { getBodyString, getFetchRequestArgBody, SENTRY_XHR_DATA_KEY } from '@sentry/browser-utils';\nimport { GRAPHQL_DOCUMENT, URL_FULL } from '@sentry/conventions/attributes';\n\ninterface GraphQLClientOptions {\n endpoints: Array<string | RegExp>;\n}\n\n/** Standard graphql request shape: https://graphql.org/learn/serving-over-http/#post-request-and-body */\ninterface GraphQLStandardRequest {\n query: string;\n operationName?: string;\n variables?: Record<string, unknown>;\n extensions?: Record<string, unknown>;\n}\n\n/** Persisted operation request */\ninterface GraphQLPersistedRequest {\n operationName: string;\n variables?: Record<string, unknown>;\n extensions: {\n persistedQuery: {\n version: number;\n sha256Hash: string;\n };\n } & Record<string, unknown>;\n}\n\ntype GraphQLRequestPayload = GraphQLStandardRequest | GraphQLPersistedRequest;\n\ninterface GraphQLOperation {\n operationType?: string;\n operationName?: string;\n}\n\nconst INTEGRATION_NAME = 'GraphQLClient' as const;\n\nconst _graphqlClientIntegration = ((options: GraphQLClientOptions) => {\n return {\n name: INTEGRATION_NAME,\n setup(client: Client) {\n _updateSpanWithGraphQLData(client, options);\n _updateBreadcrumbWithGraphQLData(client, options);\n },\n };\n}) satisfies IntegrationFn;\n\nfunction _updateSpanWithGraphQLData(client: Client, options: GraphQLClientOptions): void {\n client.on('beforeOutgoingRequestSpan', (span, hint) => {\n const spanJSON = spanToJSON(span);\n\n const spanAttributes = spanJSON.data || {};\n const spanOp = spanAttributes[SEMANTIC_ATTRIBUTE_SENTRY_OP];\n\n const isHttpClientSpan = spanOp === 'http.client';\n\n if (!isHttpClientSpan) {\n return;\n }\n\n const httpUrl = spanAttributes[URL_FULL];\n const httpMethod = spanAttributes[SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD] || spanAttributes['http.method'];\n\n if (!isString(httpUrl) || !isString(httpMethod)) {\n return;\n }\n\n const { endpoints } = options;\n const isTracedGraphqlEndpoint = stringMatchesSomePattern(httpUrl, endpoints);\n const payload = getRequestPayloadXhrOrFetch(hint as XhrHint | FetchHint);\n\n if (isTracedGraphqlEndpoint && payload) {\n const graphqlBody = getGraphQLRequestPayload(payload);\n\n if (graphqlBody) {\n const operationInfo = _getGraphQLOperation(graphqlBody);\n span.updateName(`${httpMethod} ${httpUrl} (${operationInfo})`);\n\n // Handle standard requests - capture the query document when enabled via dataCollection (default true)\n if (isStandardRequest(graphqlBody) && client.getDataCollectionOptions().graphQL.document === true) {\n span.setAttribute(GRAPHQL_DOCUMENT, graphqlBody.query);\n }\n\n // Handle persisted operations - capture hash for debugging\n if (isPersistedRequest(graphqlBody)) {\n span.setAttribute('graphql.persisted_query.hash.sha256', graphqlBody.extensions.persistedQuery.sha256Hash);\n span.setAttribute('graphql.persisted_query.version', graphqlBody.extensions.persistedQuery.version);\n }\n }\n }\n });\n}\n\nfunction _updateBreadcrumbWithGraphQLData(client: Client, options: GraphQLClientOptions): void {\n client.on('beforeOutgoingRequestBreadcrumb', (breadcrumb, handlerData) => {\n const { category, type, data } = breadcrumb;\n\n const isFetch = category === 'fetch';\n const isXhr = category === 'xhr';\n const isHttpBreadcrumb = type === 'http';\n\n if (isHttpBreadcrumb && (isFetch || isXhr)) {\n const httpUrl = data?.url;\n const { endpoints } = options;\n\n const isTracedGraphqlEndpoint = stringMatchesSomePattern(httpUrl, endpoints);\n const payload = getRequestPayloadXhrOrFetch(handlerData as XhrHint | FetchHint);\n\n if (isTracedGraphqlEndpoint && data && payload) {\n const graphqlBody = getGraphQLRequestPayload(payload);\n\n if (!data.graphql && graphqlBody) {\n const operationInfo = _getGraphQLOperation(graphqlBody);\n\n data['graphql.operation'] = operationInfo;\n\n if (isStandardRequest(graphqlBody) && client.getDataCollectionOptions().graphQL.document === true) {\n data[GRAPHQL_DOCUMENT] = graphqlBody.query;\n }\n\n if (isPersistedRequest(graphqlBody)) {\n data['graphql.persisted_query.hash.sha256'] = graphqlBody.extensions.persistedQuery.sha256Hash;\n data['graphql.persisted_query.version'] = graphqlBody.extensions.persistedQuery.version;\n }\n }\n }\n }\n });\n}\n\n/**\n * @param requestBody - GraphQL request\n * @returns A formatted version of the request: 'TYPE NAME' or 'TYPE' or 'persisted NAME'\n */\nexport function _getGraphQLOperation(requestBody: GraphQLRequestPayload): string {\n // Handle persisted operations\n if (isPersistedRequest(requestBody)) {\n return `persisted ${requestBody.operationName}`;\n }\n\n // Handle standard GraphQL requests\n if (isStandardRequest(requestBody)) {\n const { query: graphqlQuery, operationName: graphqlOperationName } = requestBody;\n const { operationName = graphqlOperationName, operationType } = parseGraphQLQuery(graphqlQuery);\n const operationInfo = operationName ? `${operationType} ${operationName}` : `${operationType}`;\n return operationInfo;\n }\n\n // Fallback for unknown request types\n return 'unknown';\n}\n\n/**\n * Get the request body/payload based on the shape of the hint.\n *\n * Exported for tests only.\n */\nexport function getRequestPayloadXhrOrFetch(hint: XhrHint | FetchHint): string | undefined {\n const isXhr = 'xhr' in hint;\n\n let body: string | undefined;\n\n if (isXhr) {\n const sentryXhrData = hint.xhr[SENTRY_XHR_DATA_KEY];\n body = sentryXhrData && getBodyString(sentryXhrData.body)[0];\n } else {\n const sentryFetchData = getFetchRequestArgBody(hint.input);\n body = getBodyString(sentryFetchData)[0];\n }\n\n return body;\n}\n\n/**\n * Extract the name and type of the operation from the GraphQL query.\n *\n * Exported for tests only.\n */\nexport function parseGraphQLQuery(query: string): GraphQLOperation {\n const namedQueryRe = /^(?:\\s*)(query|mutation|subscription)(?:\\s*)(\\w+)(?:\\s*)[{(]/;\n const unnamedQueryRe = /^(?:\\s*)(query|mutation|subscription)(?:\\s*)[{(]/;\n\n const namedMatch = query.match(namedQueryRe);\n if (namedMatch) {\n return {\n operationType: namedMatch[1],\n operationName: namedMatch[2],\n };\n }\n\n const unnamedMatch = query.match(unnamedQueryRe);\n if (unnamedMatch) {\n return {\n operationType: unnamedMatch[1],\n operationName: undefined,\n };\n }\n return {\n operationType: undefined,\n operationName: undefined,\n };\n}\n\n/**\n * Helper to safely check if a value is a non-null object\n */\n\n/**\n * Type guard to check if a request is a standard GraphQL request\n */\nfunction isStandardRequest(payload: unknown): payload is GraphQLStandardRequest {\n return isObjectLike(payload) && typeof payload.query === 'string';\n}\n\n/**\n * Type guard to check if a request is a persisted operation request\n */\nfunction isPersistedRequest(payload: unknown): payload is GraphQLPersistedRequest {\n return (\n isObjectLike(payload) &&\n typeof payload.operationName === 'string' &&\n isObjectLike(payload.extensions) &&\n isObjectLike(payload.extensions.persistedQuery) &&\n typeof payload.extensions.persistedQuery.sha256Hash === 'string' &&\n typeof payload.extensions.persistedQuery.version === 'number'\n );\n}\n\n/**\n * Extract the payload of a request if it's GraphQL.\n * Exported for tests only.\n * @param payload - A valid JSON string\n * @returns A POJO or undefined\n */\nexport function getGraphQLRequestPayload(payload: string): GraphQLRequestPayload | undefined {\n try {\n const requestBody = JSON.parse(payload);\n\n // Return any valid GraphQL request (standard, persisted, or APQ retry with both)\n if (isStandardRequest(requestBody) || isPersistedRequest(requestBody)) {\n return requestBody;\n }\n\n // Not a GraphQL request\n return undefined;\n } catch {\n // Invalid JSON\n return undefined;\n }\n}\n\n/**\n * This integration ensures that GraphQL requests made in the browser\n * have their GraphQL-specific data captured and attached to spans and breadcrumbs.\n */\nexport const graphqlClientIntegration = defineIntegration(_graphqlClientIntegration);\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"graphqlClient.js","sources":["../../../../../src/integrations/graphqlClient.ts"],"sourcesContent":["import type { Client, IntegrationFn } from '@sentry/core/browser';\nimport {\n defineIntegration,\n isObjectLike,\n isString,\n SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD,\n spanToJSON,\n stringMatchesSomePattern,\n} from '@sentry/core/browser';\nimport type { FetchHint, XhrHint } from '@sentry/browser-utils';\nimport { getBodyString, getFetchRequestArgBody, SENTRY_XHR_DATA_KEY } from '@sentry/browser-utils';\nimport { GRAPHQL_DOCUMENT, HTTP_METHOD, SENTRY_OP, URL_FULL } from '@sentry/conventions/attributes';\n\ninterface GraphQLClientOptions {\n endpoints: Array<string | RegExp>;\n}\n\n/** Standard graphql request shape: https://graphql.org/learn/serving-over-http/#post-request-and-body */\ninterface GraphQLStandardRequest {\n query: string;\n operationName?: string;\n variables?: Record<string, unknown>;\n extensions?: Record<string, unknown>;\n}\n\n/** Persisted operation request */\ninterface GraphQLPersistedRequest {\n operationName: string;\n variables?: Record<string, unknown>;\n extensions: {\n persistedQuery: {\n version: number;\n sha256Hash: string;\n };\n } & Record<string, unknown>;\n}\n\ntype GraphQLRequestPayload = GraphQLStandardRequest | GraphQLPersistedRequest;\n\ninterface GraphQLOperation {\n operationType?: string;\n operationName?: string;\n}\n\nconst INTEGRATION_NAME = 'GraphQLClient' as const;\n\nconst _graphqlClientIntegration = ((options: GraphQLClientOptions) => {\n return {\n name: INTEGRATION_NAME,\n setup(client: Client) {\n _updateSpanWithGraphQLData(client, options);\n _updateBreadcrumbWithGraphQLData(client, options);\n },\n };\n}) satisfies IntegrationFn;\n\nfunction _updateSpanWithGraphQLData(client: Client, options: GraphQLClientOptions): void {\n client.on('beforeOutgoingRequestSpan', (span, hint) => {\n const spanJSON = spanToJSON(span);\n\n const spanAttributes = spanJSON.attributes;\n const spanOp = spanAttributes[SENTRY_OP];\n\n const isHttpClientSpan = spanOp === 'http.client';\n\n if (!isHttpClientSpan) {\n return;\n }\n\n const httpUrl = spanAttributes[URL_FULL];\n // oxlint-disable-next-line typescript/no-deprecated\n const httpMethod = spanAttributes[SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD] || spanAttributes[HTTP_METHOD];\n\n if (!isString(httpUrl) || !isString(httpMethod)) {\n return;\n }\n\n const { endpoints } = options;\n const isTracedGraphqlEndpoint = stringMatchesSomePattern(httpUrl, endpoints);\n const payload = getRequestPayloadXhrOrFetch(hint as XhrHint | FetchHint);\n\n if (isTracedGraphqlEndpoint && payload) {\n const graphqlBody = getGraphQLRequestPayload(payload);\n\n if (graphqlBody) {\n const operationInfo = _getGraphQLOperation(graphqlBody);\n span.updateName(`${httpMethod} ${httpUrl} (${operationInfo})`);\n\n // Handle standard requests - capture the query document when enabled via dataCollection (default true)\n if (isStandardRequest(graphqlBody) && client.getDataCollectionOptions().graphQL.document === true) {\n span.setAttribute(GRAPHQL_DOCUMENT, graphqlBody.query);\n }\n\n // Handle persisted operations - capture hash for debugging\n if (isPersistedRequest(graphqlBody)) {\n span.setAttribute('graphql.persisted_query.hash.sha256', graphqlBody.extensions.persistedQuery.sha256Hash);\n span.setAttribute('graphql.persisted_query.version', graphqlBody.extensions.persistedQuery.version);\n }\n }\n }\n });\n}\n\nfunction _updateBreadcrumbWithGraphQLData(client: Client, options: GraphQLClientOptions): void {\n client.on('beforeOutgoingRequestBreadcrumb', (breadcrumb, handlerData) => {\n const { category, type, data } = breadcrumb;\n\n const isFetch = category === 'fetch';\n const isXhr = category === 'xhr';\n const isHttpBreadcrumb = type === 'http';\n\n if (isHttpBreadcrumb && (isFetch || isXhr)) {\n const httpUrl = data?.url;\n const { endpoints } = options;\n\n const isTracedGraphqlEndpoint = stringMatchesSomePattern(httpUrl, endpoints);\n const payload = getRequestPayloadXhrOrFetch(handlerData as XhrHint | FetchHint);\n\n if (isTracedGraphqlEndpoint && data && payload) {\n const graphqlBody = getGraphQLRequestPayload(payload);\n\n if (!data.graphql && graphqlBody) {\n const operationInfo = _getGraphQLOperation(graphqlBody);\n\n data['graphql.operation'] = operationInfo;\n\n if (isStandardRequest(graphqlBody) && client.getDataCollectionOptions().graphQL.document === true) {\n data[GRAPHQL_DOCUMENT] = graphqlBody.query;\n }\n\n if (isPersistedRequest(graphqlBody)) {\n data['graphql.persisted_query.hash.sha256'] = graphqlBody.extensions.persistedQuery.sha256Hash;\n data['graphql.persisted_query.version'] = graphqlBody.extensions.persistedQuery.version;\n }\n }\n }\n }\n });\n}\n\n/**\n * @param requestBody - GraphQL request\n * @returns A formatted version of the request: 'TYPE NAME' or 'TYPE' or 'persisted NAME'\n */\nexport function _getGraphQLOperation(requestBody: GraphQLRequestPayload): string {\n // Handle persisted operations\n if (isPersistedRequest(requestBody)) {\n return `persisted ${requestBody.operationName}`;\n }\n\n // Handle standard GraphQL requests\n if (isStandardRequest(requestBody)) {\n const { query: graphqlQuery, operationName: graphqlOperationName } = requestBody;\n const { operationName = graphqlOperationName, operationType } = parseGraphQLQuery(graphqlQuery);\n const operationInfo = operationName ? `${operationType} ${operationName}` : `${operationType}`;\n return operationInfo;\n }\n\n // Fallback for unknown request types\n return 'unknown';\n}\n\n/**\n * Get the request body/payload based on the shape of the hint.\n *\n * Exported for tests only.\n */\nexport function getRequestPayloadXhrOrFetch(hint: XhrHint | FetchHint): string | undefined {\n const isXhr = 'xhr' in hint;\n\n let body: string | undefined;\n\n if (isXhr) {\n const sentryXhrData = hint.xhr[SENTRY_XHR_DATA_KEY];\n body = sentryXhrData && getBodyString(sentryXhrData.body)[0];\n } else {\n const sentryFetchData = getFetchRequestArgBody(hint.input);\n body = getBodyString(sentryFetchData)[0];\n }\n\n return body;\n}\n\n/**\n * Extract the name and type of the operation from the GraphQL query.\n *\n * Exported for tests only.\n */\nexport function parseGraphQLQuery(query: string): GraphQLOperation {\n const namedQueryRe = /^(?:\\s*)(query|mutation|subscription)(?:\\s*)(\\w+)(?:\\s*)[{(]/;\n const unnamedQueryRe = /^(?:\\s*)(query|mutation|subscription)(?:\\s*)[{(]/;\n\n const namedMatch = query.match(namedQueryRe);\n if (namedMatch) {\n return {\n operationType: namedMatch[1],\n operationName: namedMatch[2],\n };\n }\n\n const unnamedMatch = query.match(unnamedQueryRe);\n if (unnamedMatch) {\n return {\n operationType: unnamedMatch[1],\n operationName: undefined,\n };\n }\n return {\n operationType: undefined,\n operationName: undefined,\n };\n}\n\n/**\n * Helper to safely check if a value is a non-null object\n */\n\n/**\n * Type guard to check if a request is a standard GraphQL request\n */\nfunction isStandardRequest(payload: unknown): payload is GraphQLStandardRequest {\n return isObjectLike(payload) && typeof payload.query === 'string';\n}\n\n/**\n * Type guard to check if a request is a persisted operation request\n */\nfunction isPersistedRequest(payload: unknown): payload is GraphQLPersistedRequest {\n return (\n isObjectLike(payload) &&\n typeof payload.operationName === 'string' &&\n isObjectLike(payload.extensions) &&\n isObjectLike(payload.extensions.persistedQuery) &&\n typeof payload.extensions.persistedQuery.sha256Hash === 'string' &&\n typeof payload.extensions.persistedQuery.version === 'number'\n );\n}\n\n/**\n * Extract the payload of a request if it's GraphQL.\n * Exported for tests only.\n * @param payload - A valid JSON string\n * @returns A POJO or undefined\n */\nexport function getGraphQLRequestPayload(payload: string): GraphQLRequestPayload | undefined {\n try {\n const requestBody = JSON.parse(payload);\n\n // Return any valid GraphQL request (standard, persisted, or APQ retry with both)\n if (isStandardRequest(requestBody) || isPersistedRequest(requestBody)) {\n return requestBody;\n }\n\n // Not a GraphQL request\n return undefined;\n } catch {\n // Invalid JSON\n return undefined;\n }\n}\n\n/**\n * This integration ensures that GraphQL requests made in the browser\n * have their GraphQL-specific data captured and attached to spans and breadcrumbs.\n */\nexport const graphqlClientIntegration = defineIntegration(_graphqlClientIntegration);\n"],"names":[],"mappings":";;;;AA4CA,MAAM,gBAAA,GAAmB,eAAA;AAEzB,MAAM,yBAAA,IAA6B,CAAC,OAAA,KAAkC;AACpE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,MAAM,MAAA,EAAgB;AACpB,MAAA,0BAAA,CAA2B,QAAQ,OAAO,CAAA;AAC1C,MAAA,gCAAA,CAAiC,QAAQ,OAAO,CAAA;AAAA,IAClD;AAAA,GACF;AACF,CAAA,CAAA;AAEA,SAAS,0BAAA,CAA2B,QAAgB,OAAA,EAAqC;AACvF,EAAA,MAAA,CAAO,EAAA,CAAG,2BAAA,EAA6B,CAAC,IAAA,EAAM,IAAA,KAAS;AACrD,IAAA,MAAM,QAAA,GAAW,WAAW,IAAI,CAAA;AAEhC,IAAA,MAAM,iBAAiB,QAAA,CAAS,UAAA;AAChC,IAAA,MAAM,MAAA,GAAS,eAAe,SAAS,CAAA;AAEvC,IAAA,MAAM,mBAAmB,MAAA,KAAW,aAAA;AAEpC,IAAA,IAAI,CAAC,gBAAA,EAAkB;AACrB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,eAAe,QAAQ,CAAA;AAEvC,IAAA,MAAM,UAAA,GAAa,cAAA,CAAe,sCAAsC,CAAA,IAAK,eAAe,WAAW,CAAA;AAEvG,IAAA,IAAI,CAAC,QAAA,CAAS,OAAO,KAAK,CAAC,QAAA,CAAS,UAAU,CAAA,EAAG;AAC/C,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,WAAU,GAAI,OAAA;AACtB,IAAA,MAAM,uBAAA,GAA0B,wBAAA,CAAyB,OAAA,EAAS,SAAS,CAAA;AAC3E,IAAA,MAAM,OAAA,GAAU,4BAA4B,IAA2B,CAAA;AAEvE,IAAA,IAAI,2BAA2B,OAAA,EAAS;AACtC,MAAA,MAAM,WAAA,GAAc,yBAAyB,OAAO,CAAA;AAEpD,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,aAAA,GAAgB,qBAAqB,WAAW,CAAA;AACtD,QAAA,IAAA,CAAK,WAAW,CAAA,EAAG,UAAU,IAAI,OAAO,CAAA,EAAA,EAAK,aAAa,CAAA,CAAA,CAAG,CAAA;AAG7D,QAAA,IAAI,iBAAA,CAAkB,WAAW,CAAA,IAAK,MAAA,CAAO,0BAAyB,CAAE,OAAA,CAAQ,aAAa,IAAA,EAAM;AACjG,UAAA,IAAA,CAAK,YAAA,CAAa,gBAAA,EAAkB,WAAA,CAAY,KAAK,CAAA;AAAA,QACvD;AAGA,QAAA,IAAI,kBAAA,CAAmB,WAAW,CAAA,EAAG;AACnC,UAAA,IAAA,CAAK,YAAA,CAAa,qCAAA,EAAuC,WAAA,CAAY,UAAA,CAAW,eAAe,UAAU,CAAA;AACzG,UAAA,IAAA,CAAK,YAAA,CAAa,iCAAA,EAAmC,WAAA,CAAY,UAAA,CAAW,eAAe,OAAO,CAAA;AAAA,QACpG;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AACH;AAEA,SAAS,gCAAA,CAAiC,QAAgB,OAAA,EAAqC;AAC7F,EAAA,MAAA,CAAO,EAAA,CAAG,iCAAA,EAAmC,CAAC,UAAA,EAAY,WAAA,KAAgB;AACxE,IAAA,MAAM,EAAE,QAAA,EAAU,IAAA,EAAM,IAAA,EAAK,GAAI,UAAA;AAEjC,IAAA,MAAM,UAAU,QAAA,KAAa,OAAA;AAC7B,IAAA,MAAM,QAAQ,QAAA,KAAa,KAAA;AAC3B,IAAA,MAAM,mBAAmB,IAAA,KAAS,MAAA;AAElC,IAAA,IAAI,gBAAA,KAAqB,WAAW,KAAA,CAAA,EAAQ;AAC1C,MAAA,MAAM,UAAU,IAAA,EAAM,GAAA;AACtB,MAAA,MAAM,EAAE,WAAU,GAAI,OAAA;AAEtB,MAAA,MAAM,uBAAA,GAA0B,wBAAA,CAAyB,OAAA,EAAS,SAAS,CAAA;AAC3E,MAAA,MAAM,OAAA,GAAU,4BAA4B,WAAkC,CAAA;AAE9E,MAAA,IAAI,uBAAA,IAA2B,QAAQ,OAAA,EAAS;AAC9C,QAAA,MAAM,WAAA,GAAc,yBAAyB,OAAO,CAAA;AAEpD,QAAA,IAAI,CAAC,IAAA,CAAK,OAAA,IAAW,WAAA,EAAa;AAChC,UAAA,MAAM,aAAA,GAAgB,qBAAqB,WAAW,CAAA;AAEtD,UAAA,IAAA,CAAK,mBAAmB,CAAA,GAAI,aAAA;AAE5B,UAAA,IAAI,iBAAA,CAAkB,WAAW,CAAA,IAAK,MAAA,CAAO,0BAAyB,CAAE,OAAA,CAAQ,aAAa,IAAA,EAAM;AACjG,YAAA,IAAA,CAAK,gBAAgB,IAAI,WAAA,CAAY,KAAA;AAAA,UACvC;AAEA,UAAA,IAAI,kBAAA,CAAmB,WAAW,CAAA,EAAG;AACnC,YAAA,IAAA,CAAK,qCAAqC,CAAA,GAAI,WAAA,CAAY,UAAA,CAAW,cAAA,CAAe,UAAA;AACpF,YAAA,IAAA,CAAK,iCAAiC,CAAA,GAAI,WAAA,CAAY,UAAA,CAAW,cAAA,CAAe,OAAA;AAAA,UAClF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AACH;AAMO,SAAS,qBAAqB,WAAA,EAA4C;AAE/E,EAAA,IAAI,kBAAA,CAAmB,WAAW,CAAA,EAAG;AACnC,IAAA,OAAO,CAAA,UAAA,EAAa,YAAY,aAAa,CAAA,CAAA;AAAA,EAC/C;AAGA,EAAA,IAAI,iBAAA,CAAkB,WAAW,CAAA,EAAG;AAClC,IAAA,MAAM,EAAE,KAAA,EAAO,YAAA,EAAc,aAAA,EAAe,sBAAqB,GAAI,WAAA;AACrE,IAAA,MAAM,EAAE,aAAA,GAAgB,oBAAA,EAAsB,aAAA,EAAc,GAAI,kBAAkB,YAAY,CAAA;AAC9F,IAAA,MAAM,aAAA,GAAgB,gBAAgB,CAAA,EAAG,aAAa,IAAI,aAAa,CAAA,CAAA,GAAK,GAAG,aAAa,CAAA,CAAA;AAC5F,IAAA,OAAO,aAAA;AAAA,EACT;AAGA,EAAA,OAAO,SAAA;AACT;AAOO,SAAS,4BAA4B,IAAA,EAA+C;AACzF,EAAA,MAAM,QAAQ,KAAA,IAAS,IAAA;AAEvB,EAAA,IAAI,IAAA;AAEJ,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,GAAA,CAAI,mBAAmB,CAAA;AAClD,IAAA,IAAA,GAAO,aAAA,IAAiB,aAAA,CAAc,aAAA,CAAc,IAAI,EAAE,CAAC,CAAA;AAAA,EAC7D,CAAA,MAAO;AACL,IAAA,MAAM,eAAA,GAAkB,sBAAA,CAAuB,IAAA,CAAK,KAAK,CAAA;AACzD,IAAA,IAAA,GAAO,aAAA,CAAc,eAAe,CAAA,CAAE,CAAC,CAAA;AAAA,EACzC;AAEA,EAAA,OAAO,IAAA;AACT;AAOO,SAAS,kBAAkB,KAAA,EAAiC;AACjE,EAAA,MAAM,YAAA,GAAe,8DAAA;AACrB,EAAA,MAAM,cAAA,GAAiB,kDAAA;AAEvB,EAAA,MAAM,UAAA,GAAa,KAAA,CAAM,KAAA,CAAM,YAAY,CAAA;AAC3C,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,OAAO;AAAA,MACL,aAAA,EAAe,WAAW,CAAC,CAAA;AAAA,MAC3B,aAAA,EAAe,WAAW,CAAC;AAAA,KAC7B;AAAA,EACF;AAEA,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,KAAA,CAAM,cAAc,CAAA;AAC/C,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,OAAO;AAAA,MACL,aAAA,EAAe,aAAa,CAAC,CAAA;AAAA,MAC7B,aAAA,EAAe;AAAA,KACjB;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,aAAA,EAAe,MAAA;AAAA,IACf,aAAA,EAAe;AAAA,GACjB;AACF;AASA,SAAS,kBAAkB,OAAA,EAAqD;AAC9E,EAAA,OAAO,YAAA,CAAa,OAAO,CAAA,IAAK,OAAO,QAAQ,KAAA,KAAU,QAAA;AAC3D;AAKA,SAAS,mBAAmB,OAAA,EAAsD;AAChF,EAAA,OACE,YAAA,CAAa,OAAO,CAAA,IACpB,OAAO,OAAA,CAAQ,aAAA,KAAkB,QAAA,IACjC,YAAA,CAAa,OAAA,CAAQ,UAAU,CAAA,IAC/B,YAAA,CAAa,OAAA,CAAQ,WAAW,cAAc,CAAA,IAC9C,OAAO,OAAA,CAAQ,UAAA,CAAW,cAAA,CAAe,UAAA,KAAe,QAAA,IACxD,OAAO,OAAA,CAAQ,UAAA,CAAW,cAAA,CAAe,OAAA,KAAY,QAAA;AAEzD;AAQO,SAAS,yBAAyB,OAAA,EAAoD;AAC3F,EAAA,IAAI;AACF,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AAGtC,IAAA,IAAI,iBAAA,CAAkB,WAAW,CAAA,IAAK,kBAAA,CAAmB,WAAW,CAAA,EAAG;AACrE,MAAA,OAAO,WAAA;AAAA,IACT;AAGA,IAAA,OAAO,KAAA,CAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAMO,MAAM,wBAAA,GAA2B,kBAAkB,yBAAyB;;;;"}