@sentry/browser 9.22.0 → 9.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/build/npm/cjs/client.js +34 -24
  2. package/build/npm/cjs/client.js.map +1 -1
  3. package/build/npm/cjs/index.js +1 -0
  4. package/build/npm/cjs/index.js.map +1 -1
  5. package/build/npm/cjs/sdk.js +10 -89
  6. package/build/npm/cjs/sdk.js.map +1 -1
  7. package/build/npm/cjs/tracing/browserTracingIntegration.js +37 -41
  8. package/build/npm/cjs/tracing/browserTracingIntegration.js.map +1 -1
  9. package/build/npm/cjs/utils/detectBrowserExtension.js +59 -0
  10. package/build/npm/cjs/utils/detectBrowserExtension.js.map +1 -0
  11. package/build/npm/esm/client.js +34 -25
  12. package/build/npm/esm/client.js.map +1 -1
  13. package/build/npm/esm/index.js +1 -1
  14. package/build/npm/esm/package.json +1 -1
  15. package/build/npm/esm/sdk.js +12 -90
  16. package/build/npm/esm/sdk.js.map +1 -1
  17. package/build/npm/esm/tracing/browserTracingIntegration.js +39 -43
  18. package/build/npm/esm/tracing/browserTracingIntegration.js.map +1 -1
  19. package/build/npm/esm/utils/detectBrowserExtension.js +57 -0
  20. package/build/npm/esm/utils/detectBrowserExtension.js.map +1 -0
  21. package/build/npm/types/client.d.ts +9 -5
  22. package/build/npm/types/client.d.ts.map +1 -1
  23. package/build/npm/types/exports.d.ts +1 -1
  24. package/build/npm/types/exports.d.ts.map +1 -1
  25. package/build/npm/types/sdk.d.ts +1 -3
  26. package/build/npm/types/sdk.d.ts.map +1 -1
  27. package/build/npm/types/tracing/browserTracingIntegration.d.ts +7 -0
  28. package/build/npm/types/tracing/browserTracingIntegration.d.ts.map +1 -1
  29. package/build/npm/types/utils/detectBrowserExtension.d.ts +6 -0
  30. package/build/npm/types/utils/detectBrowserExtension.d.ts.map +1 -0
  31. package/build/npm/types-ts3.8/client.d.ts +9 -5
  32. package/build/npm/types-ts3.8/exports.d.ts +1 -1
  33. package/build/npm/types-ts3.8/sdk.d.ts +1 -3
  34. package/build/npm/types-ts3.8/tracing/browserTracingIntegration.d.ts +7 -0
  35. package/build/npm/types-ts3.8/utils/detectBrowserExtension.d.ts +6 -0
  36. package/package.json +7 -7
@@ -0,0 +1,59 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+ const debugBuild = require('../debug-build.js');
5
+ const helpers = require('../helpers.js');
6
+
7
+ /**
8
+ * Returns true if the SDK is running in an embedded browser extension.
9
+ * Stand-alone browser extensions (which do not share the same data as the main browser page) are fine.
10
+ */
11
+ function checkAndWarnIfIsEmbeddedBrowserExtension() {
12
+ if (_isEmbeddedBrowserExtension()) {
13
+ if (debugBuild.DEBUG_BUILD) {
14
+ core.consoleSandbox(() => {
15
+ // eslint-disable-next-line no-console
16
+ console.error(
17
+ '[Sentry] You cannot use Sentry.init() in a browser extension, see: https://docs.sentry.io/platforms/javascript/best-practices/browser-extensions/',
18
+ );
19
+ });
20
+ }
21
+
22
+ return true;
23
+ }
24
+
25
+ return false;
26
+ }
27
+
28
+ function _isEmbeddedBrowserExtension() {
29
+ if (typeof helpers.WINDOW.window === 'undefined') {
30
+ // No need to show the error if we're not in a browser window environment (e.g. service workers)
31
+ return false;
32
+ }
33
+
34
+ const _window = helpers.WINDOW ;
35
+
36
+ // Running the SDK in NW.js, which appears like a browser extension but isn't, is also fine
37
+ // see: https://github.com/getsentry/sentry-javascript/issues/12668
38
+ if (_window.nw) {
39
+ return false;
40
+ }
41
+
42
+ const extensionObject = _window['chrome'] || _window['browser'];
43
+
44
+ if (!extensionObject?.runtime?.id) {
45
+ return false;
46
+ }
47
+
48
+ const href = core.getLocationHref();
49
+ const extensionProtocols = ['chrome-extension', 'moz-extension', 'ms-browser-extension', 'safari-web-extension'];
50
+
51
+ // Running the SDK in a dedicated extension page and calling Sentry.init is fine; no risk of data leakage
52
+ const isDedicatedExtensionPage =
53
+ helpers.WINDOW === helpers.WINDOW.top && extensionProtocols.some(protocol => href.startsWith(`${protocol}://`));
54
+
55
+ return !isDedicatedExtensionPage;
56
+ }
57
+
58
+ exports.checkAndWarnIfIsEmbeddedBrowserExtension = checkAndWarnIfIsEmbeddedBrowserExtension;
59
+ //# sourceMappingURL=detectBrowserExtension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detectBrowserExtension.js","sources":["../../../../src/utils/detectBrowserExtension.ts"],"sourcesContent":["import { consoleSandbox, getLocationHref } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\n\ntype ExtensionRuntime = {\n runtime?: {\n id?: string;\n };\n};\ntype ExtensionProperties = {\n chrome?: ExtensionRuntime;\n browser?: ExtensionRuntime;\n nw?: unknown;\n};\n\n/**\n * Returns true if the SDK is running in an embedded browser extension.\n * Stand-alone browser extensions (which do not share the same data as the main browser page) are fine.\n */\nexport function checkAndWarnIfIsEmbeddedBrowserExtension(): boolean {\n if (_isEmbeddedBrowserExtension()) {\n if (DEBUG_BUILD) {\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.error(\n '[Sentry] You cannot use Sentry.init() in a browser extension, see: https://docs.sentry.io/platforms/javascript/best-practices/browser-extensions/',\n );\n });\n }\n\n return true;\n }\n\n return false;\n}\n\nfunction _isEmbeddedBrowserExtension(): boolean {\n if (typeof WINDOW.window === 'undefined') {\n // No need to show the error if we're not in a browser window environment (e.g. service workers)\n return false;\n }\n\n const _window = WINDOW as typeof WINDOW & ExtensionProperties;\n\n // Running the SDK in NW.js, which appears like a browser extension but isn't, is also fine\n // see: https://github.com/getsentry/sentry-javascript/issues/12668\n if (_window.nw) {\n return false;\n }\n\n const extensionObject = _window['chrome'] || _window['browser'];\n\n if (!extensionObject?.runtime?.id) {\n return false;\n }\n\n const href = getLocationHref();\n const extensionProtocols = ['chrome-extension', 'moz-extension', 'ms-browser-extension', 'safari-web-extension'];\n\n // Running the SDK in a dedicated extension page and calling Sentry.init is fine; no risk of data leakage\n const isDedicatedExtensionPage =\n WINDOW === WINDOW.top && extensionProtocols.some(protocol => href.startsWith(`${protocol}://`));\n\n return !isDedicatedExtensionPage;\n}\n"],"names":["DEBUG_BUILD","consoleSandbox","WINDOW","getLocationHref"],"mappings":";;;;;;AAeA;AACA;AACA;AACA;AACO,SAAS,wCAAwC,GAAY;AACpE,EAAE,IAAI,2BAA2B,EAAE,EAAE;AACrC,IAAI,IAAIA,sBAAW,EAAE;AACrB,MAAMC,mBAAc,CAAC,MAAM;AAC3B;AACA,QAAQ,OAAO,CAAC,KAAK;AACrB,UAAU,mJAAmJ;AAC7J,SAAS;AACT,OAAO,CAAC;AACR;;AAEA,IAAI,OAAO,IAAI;AACf;;AAEA,EAAE,OAAO,KAAK;AACd;;AAEA,SAAS,2BAA2B,GAAY;AAChD,EAAE,IAAI,OAAOC,cAAM,CAAC,MAAO,KAAI,WAAW,EAAE;AAC5C;AACA,IAAI,OAAO,KAAK;AAChB;;AAEA,EAAE,MAAM,OAAQ,GAAEA,cAAO;;AAEzB;AACA;AACA,EAAE,IAAI,OAAO,CAAC,EAAE,EAAE;AAClB,IAAI,OAAO,KAAK;AAChB;;AAEA,EAAE,MAAM,eAAgB,GAAE,OAAO,CAAC,QAAQ,CAAA,IAAK,OAAO,CAAC,SAAS,CAAC;;AAEjE,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,EAAE,EAAE,EAAE;AACrC,IAAI,OAAO,KAAK;AAChB;;AAEA,EAAE,MAAM,IAAA,GAAOC,oBAAe,EAAE;AAChC,EAAE,MAAM,kBAAmB,GAAE,CAAC,kBAAkB,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,CAAC;;AAElH;AACA,EAAE,MAAM,wBAAyB;AACjC,IAAID,mBAAWA,cAAM,CAAC,GAAA,IAAO,kBAAkB,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,UAAU,CAAC,CAAC,EAAA,QAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;AAEA,EAAA,OAAA,CAAA,wBAAA;AACA;;;;"}
@@ -2,13 +2,12 @@ import { Client, getSDKSource, applySdkMetadata, _INTERNAL_flushLogsBuffer, addA
2
2
  import { eventFromException, eventFromMessage } from './eventbuilder.js';
3
3
  import { WINDOW } from './helpers.js';
4
4
 
5
- const DEFAULT_FLUSH_INTERVAL = 5000;
6
-
7
5
  /**
8
- * Configuration options for the Sentry Browser SDK.
9
- * @see @sentry/core Options for more information.
6
+ * A magic string that build tooling can leverage in order to inject a release value into the SDK.
10
7
  */
11
8
 
9
+ const DEFAULT_FLUSH_INTERVAL = 5000;
10
+
12
11
  /**
13
12
  * The Sentry Browser SDK Client.
14
13
  *
@@ -23,51 +22,47 @@ class BrowserClient extends Client {
23
22
  * @param options Configuration options for this SDK.
24
23
  */
25
24
  constructor(options) {
26
- const opts = {
27
- // We default this to true, as it is the safer scenario
28
- parentSpanIsAlwaysRootSpan: true,
29
- ...options,
30
- };
25
+ const opts = applyDefaultOptions(options);
31
26
  const sdkSource = WINDOW.SENTRY_SDK_SOURCE || getSDKSource();
32
27
  applySdkMetadata(opts, 'browser', ['browser'], sdkSource);
33
28
 
34
29
  super(opts);
35
30
 
36
- // eslint-disable-next-line @typescript-eslint/no-this-alias
37
- const client = this;
38
- const { sendDefaultPii, _experiments } = client._options;
31
+ const { sendDefaultPii, sendClientReports, _experiments } = this._options;
39
32
  const enableLogs = _experiments?.enableLogs;
40
33
 
41
- if (opts.sendClientReports && WINDOW.document) {
34
+ if (WINDOW.document && (sendClientReports || enableLogs)) {
42
35
  WINDOW.document.addEventListener('visibilitychange', () => {
43
36
  if (WINDOW.document.visibilityState === 'hidden') {
44
- this._flushOutcomes();
37
+ if (sendClientReports) {
38
+ this._flushOutcomes();
39
+ }
45
40
  if (enableLogs) {
46
- _INTERNAL_flushLogsBuffer(client);
41
+ _INTERNAL_flushLogsBuffer(this);
47
42
  }
48
43
  }
49
44
  });
50
45
  }
51
46
 
52
47
  if (enableLogs) {
53
- client.on('flush', () => {
54
- _INTERNAL_flushLogsBuffer(client);
48
+ this.on('flush', () => {
49
+ _INTERNAL_flushLogsBuffer(this);
55
50
  });
56
51
 
57
- client.on('afterCaptureLog', () => {
58
- if (client._logFlushIdleTimeout) {
59
- clearTimeout(client._logFlushIdleTimeout);
52
+ this.on('afterCaptureLog', () => {
53
+ if (this._logFlushIdleTimeout) {
54
+ clearTimeout(this._logFlushIdleTimeout);
60
55
  }
61
56
 
62
- client._logFlushIdleTimeout = setTimeout(() => {
63
- _INTERNAL_flushLogsBuffer(client);
57
+ this._logFlushIdleTimeout = setTimeout(() => {
58
+ _INTERNAL_flushLogsBuffer(this);
64
59
  }, DEFAULT_FLUSH_INTERVAL);
65
60
  });
66
61
  }
67
62
 
68
63
  if (sendDefaultPii) {
69
- client.on('postprocessEvent', addAutoIpAddressToUser);
70
- client.on('beforeSendSession', addAutoIpAddressToSession);
64
+ this.on('postprocessEvent', addAutoIpAddressToUser);
65
+ this.on('beforeSendSession', addAutoIpAddressToSession);
71
66
  }
72
67
  }
73
68
 
@@ -104,5 +99,19 @@ class BrowserClient extends Client {
104
99
  }
105
100
  }
106
101
 
107
- export { BrowserClient };
102
+ /** Exported only for tests. */
103
+ function applyDefaultOptions(optionsArg) {
104
+ return {
105
+ release:
106
+ typeof __SENTRY_RELEASE__ === 'string' // This allows build tooling to find-and-replace __SENTRY_RELEASE__ to inject a release value
107
+ ? __SENTRY_RELEASE__
108
+ : WINDOW.SENTRY_RELEASE?.id, // This supports the variable that sentry-webpack-plugin injects
109
+ sendClientReports: true,
110
+ // We default this to true, as it is the safer scenario
111
+ parentSpanIsAlwaysRootSpan: true,
112
+ ...optionsArg,
113
+ };
114
+ }
115
+
116
+ export { BrowserClient, applyDefaultOptions };
108
117
  //# sourceMappingURL=client.js.map
@@ -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,\n ParameterizedString,\n Scope,\n SeverityLevel,\n} from '@sentry/core';\nimport {\n _INTERNAL_flushLogsBuffer,\n addAutoIpAddressToSession,\n addAutoIpAddressToUser,\n applySdkMetadata,\n Client,\n getSDKSource,\n} from '@sentry/core';\nimport { eventFromException, eventFromMessage } from './eventbuilder';\nimport { WINDOW } from './helpers';\nimport type { BrowserTransportOptions } from './transports/types';\n\nconst DEFAULT_FLUSH_INTERVAL = 5000;\n\n/**\n * Configuration options for the Sentry Browser SDK.\n * @see @sentry/core Options for more information.\n */\nexport type BrowserOptions = Options<BrowserTransportOptions> &\n BrowserClientReplayOptions &\n BrowserClientProfilingOptions & {\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/**\n * Configuration options for the Sentry Browser SDK Client class\n * @see BrowserClient for more information.\n */\nexport type BrowserClientOptions = ClientOptions<BrowserTransportOptions> &\n BrowserClientReplayOptions &\n BrowserClientProfilingOptions & {\n /** If configured, this URL will be used as base URL for lazy loading integration. */\n cdnBaseUrl?: string;\n };\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 private _logFlushIdleTimeout: ReturnType<typeof setTimeout> | undefined;\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 = {\n // We default this to true, as it is the safer scenario\n parentSpanIsAlwaysRootSpan: true,\n ...options,\n };\n const sdkSource = WINDOW.SENTRY_SDK_SOURCE || getSDKSource();\n applySdkMetadata(opts, 'browser', ['browser'], sdkSource);\n\n super(opts);\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const client = this;\n const { sendDefaultPii, _experiments } = client._options;\n const enableLogs = _experiments?.enableLogs;\n\n if (opts.sendClientReports && WINDOW.document) {\n WINDOW.document.addEventListener('visibilitychange', () => {\n if (WINDOW.document.visibilityState === 'hidden') {\n this._flushOutcomes();\n if (enableLogs) {\n _INTERNAL_flushLogsBuffer(client);\n }\n }\n });\n }\n\n if (enableLogs) {\n client.on('flush', () => {\n _INTERNAL_flushLogsBuffer(client);\n });\n\n client.on('afterCaptureLog', () => {\n if (client._logFlushIdleTimeout) {\n clearTimeout(client._logFlushIdleTimeout);\n }\n\n client._logFlushIdleTimeout = setTimeout(() => {\n _INTERNAL_flushLogsBuffer(client);\n }, DEFAULT_FLUSH_INTERVAL);\n });\n }\n\n if (sendDefaultPii) {\n client.on('postprocessEvent', addAutoIpAddressToUser);\n client.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"],"names":[],"mappings":"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"}
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,\n ParameterizedString,\n Scope,\n SeverityLevel,\n} from '@sentry/core';\nimport {\n _INTERNAL_flushLogsBuffer,\n addAutoIpAddressToSession,\n addAutoIpAddressToUser,\n applySdkMetadata,\n Client,\n getSDKSource,\n} from '@sentry/core';\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\nconst DEFAULT_FLUSH_INTERVAL = 5000;\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 * Configuration options for the Sentry Browser SDK.\n * @see @sentry/core Options for more information.\n */\nexport type BrowserOptions = Options<BrowserTransportOptions> &\n BrowserSpecificOptions & {\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/**\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 private _logFlushIdleTimeout: ReturnType<typeof setTimeout> | undefined;\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 const { sendDefaultPii, sendClientReports, _experiments } = this._options;\n const enableLogs = _experiments?.enableLogs;\n\n if (WINDOW.document && (sendClientReports || enableLogs)) {\n WINDOW.document.addEventListener('visibilitychange', () => {\n if (WINDOW.document.visibilityState === 'hidden') {\n if (sendClientReports) {\n this._flushOutcomes();\n }\n if (enableLogs) {\n _INTERNAL_flushLogsBuffer(this);\n }\n }\n });\n }\n\n if (enableLogs) {\n this.on('flush', () => {\n _INTERNAL_flushLogsBuffer(this);\n });\n\n this.on('afterCaptureLog', () => {\n if (this._logFlushIdleTimeout) {\n clearTimeout(this._logFlushIdleTimeout);\n }\n\n this._logFlushIdleTimeout = setTimeout(() => {\n _INTERNAL_flushLogsBuffer(this);\n }, DEFAULT_FLUSH_INTERVAL);\n });\n }\n\n if (sendDefaultPii) {\n this.on('postprocessEvent', addAutoIpAddressToUser);\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":"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"}
@@ -2,7 +2,7 @@ export { feedbackAsyncIntegration } from './feedbackAsync.js';
2
2
  export { feedbackSyncIntegration as feedbackIntegration, feedbackSyncIntegration } from './feedbackSync.js';
3
3
  import * as log from './log.js';
4
4
  export { log as logger };
5
- export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, captureSession, close, consoleLoggingIntegration, continueTrace, createTransport, dedupeIntegration, endSession, eventFiltersIntegration, extraErrorDataIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, inboundFiltersIntegration, instrumentSupabaseClient, isInitialized, lastEventId, makeMultiplexedTransport, moduleMetadataIntegration, parameterize, registerSpanErrorInstrumentation, rewriteFramesIntegration, setContext, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSession, startSpan, startSpanManual, supabaseIntegration, suppressTracing, thirdPartyErrorFilterIntegration, updateSpanName, withActiveSpan, withIsolationScope, withScope, zodErrorsIntegration } from '@sentry/core';
5
+ export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, captureSession, close, consoleLoggingIntegration, continueTrace, createTransport, dedupeIntegration, endSession, eventFiltersIntegration, extraErrorDataIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, inboundFiltersIntegration, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, makeMultiplexedTransport, moduleMetadataIntegration, parameterize, registerSpanErrorInstrumentation, rewriteFramesIntegration, setContext, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSession, startSpan, startSpanManual, supabaseIntegration, suppressTracing, thirdPartyErrorFilterIntegration, updateSpanName, withActiveSpan, withIsolationScope, withScope, zodErrorsIntegration } from '@sentry/core';
6
6
  export { WINDOW } from './helpers.js';
7
7
  export { BrowserClient } from './client.js';
8
8
  export { makeFetchTransport } from './transports/fetch.js';
@@ -1 +1 @@
1
- {"type":"module","version":"9.22.0","sideEffects":false}
1
+ {"type":"module","version":"9.23.0","sideEffects":false}
@@ -1,7 +1,5 @@
1
- import { inboundFiltersIntegration, functionToStringIntegration, dedupeIntegration, getIntegrationsToSetup, stackParserFromStackParserOptions, initAndBind, consoleSandbox, getLocationHref } from '@sentry/core';
1
+ import { inboundFiltersIntegration, functionToStringIntegration, dedupeIntegration, getIntegrationsToSetup, stackParserFromStackParserOptions, initAndBind } from '@sentry/core';
2
2
  import { BrowserClient } from './client.js';
3
- import { DEBUG_BUILD } from './debug-build.js';
4
- import { WINDOW } from './helpers.js';
5
3
  import { breadcrumbsIntegration } from './integrations/breadcrumbs.js';
6
4
  import { browserApiErrorsIntegration } from './integrations/browserapierrors.js';
7
5
  import { browserSessionIntegration } from './integrations/browsersession.js';
@@ -10,6 +8,7 @@ import { httpContextIntegration } from './integrations/httpcontext.js';
10
8
  import { linkedErrorsIntegration } from './integrations/linkederrors.js';
11
9
  import { defaultStackParser } from './stack-parsers.js';
12
10
  import { makeFetchTransport } from './transports/fetch.js';
11
+ import { checkAndWarnIfIsEmbeddedBrowserExtension } from './utils/detectBrowserExtension.js';
13
12
 
14
13
  /** Get the default integrations for the browser SDK. */
15
14
  function getDefaultIntegrations(_options) {
@@ -32,40 +31,6 @@ function getDefaultIntegrations(_options) {
32
31
  ];
33
32
  }
34
33
 
35
- /** Exported only for tests. */
36
- function applyDefaultOptions(optionsArg = {}) {
37
- const defaultOptions = {
38
- defaultIntegrations: getDefaultIntegrations(),
39
- release:
40
- typeof __SENTRY_RELEASE__ === 'string' // This allows build tooling to find-and-replace __SENTRY_RELEASE__ to inject a release value
41
- ? __SENTRY_RELEASE__
42
- : WINDOW.SENTRY_RELEASE?.id, // This supports the variable that sentry-webpack-plugin injects
43
- sendClientReports: true,
44
- };
45
-
46
- return {
47
- ...defaultOptions,
48
- ...dropTopLevelUndefinedKeys(optionsArg),
49
- };
50
- }
51
-
52
- /**
53
- * In contrast to the regular `dropUndefinedKeys` method,
54
- * this one does not deep-drop keys, but only on the top level.
55
- */
56
- function dropTopLevelUndefinedKeys(obj) {
57
- const mutatetedObj = {};
58
-
59
- for (const k of Object.getOwnPropertyNames(obj)) {
60
- const key = k ;
61
- if (obj[key] !== undefined) {
62
- mutatetedObj[key] = obj[key];
63
- }
64
- }
65
-
66
- return mutatetedObj;
67
- }
68
-
69
34
  /**
70
35
  * The Sentry Browser SDK Client.
71
36
  *
@@ -112,19 +77,21 @@ function dropTopLevelUndefinedKeys(obj) {
112
77
  *
113
78
  * @see {@link BrowserOptions} for documentation on configuration options.
114
79
  */
115
- function init(browserOptions = {}) {
116
- if (!browserOptions.skipBrowserExtensionCheck && _checkForBrowserExtension()) {
117
- return;
118
- }
80
+ function init(options = {}) {
81
+ const shouldDisableBecauseIsBrowserExtenstion =
82
+ !options.skipBrowserExtensionCheck && checkAndWarnIfIsEmbeddedBrowserExtension();
119
83
 
120
- const options = applyDefaultOptions(browserOptions);
121
84
  const clientOptions = {
122
85
  ...options,
86
+ enabled: shouldDisableBecauseIsBrowserExtenstion ? false : options.enabled,
123
87
  stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),
124
- integrations: getIntegrationsToSetup(options),
88
+ integrations: getIntegrationsToSetup({
89
+ integrations: options.integrations,
90
+ defaultIntegrations:
91
+ options.defaultIntegrations == null ? getDefaultIntegrations() : options.defaultIntegrations,
92
+ }),
125
93
  transport: options.transport || makeFetchTransport,
126
94
  };
127
-
128
95
  return initAndBind(BrowserClient, clientOptions);
129
96
  }
130
97
 
@@ -144,50 +111,5 @@ function onLoad(callback) {
144
111
  callback();
145
112
  }
146
113
 
147
- function _isEmbeddedBrowserExtension() {
148
- if (typeof WINDOW.window === 'undefined') {
149
- // No need to show the error if we're not in a browser window environment (e.g. service workers)
150
- return false;
151
- }
152
-
153
- const _window = WINDOW ;
154
-
155
- // Running the SDK in NW.js, which appears like a browser extension but isn't, is also fine
156
- // see: https://github.com/getsentry/sentry-javascript/issues/12668
157
- if (_window.nw) {
158
- return false;
159
- }
160
-
161
- const extensionObject = _window['chrome'] || _window['browser'];
162
-
163
- if (!extensionObject?.runtime?.id) {
164
- return false;
165
- }
166
-
167
- const href = getLocationHref();
168
- const extensionProtocols = ['chrome-extension', 'moz-extension', 'ms-browser-extension', 'safari-web-extension'];
169
-
170
- // Running the SDK in a dedicated extension page and calling Sentry.init is fine; no risk of data leakage
171
- const isDedicatedExtensionPage =
172
- WINDOW === WINDOW.top && extensionProtocols.some(protocol => href.startsWith(`${protocol}://`));
173
-
174
- return !isDedicatedExtensionPage;
175
- }
176
-
177
- function _checkForBrowserExtension() {
178
- if (_isEmbeddedBrowserExtension()) {
179
- if (DEBUG_BUILD) {
180
- consoleSandbox(() => {
181
- // eslint-disable-next-line no-console
182
- console.error(
183
- '[Sentry] You cannot use Sentry.init() in a browser extension, see: https://docs.sentry.io/platforms/javascript/best-practices/browser-extensions/',
184
- );
185
- });
186
- }
187
-
188
- return true;
189
- }
190
- }
191
-
192
- export { applyDefaultOptions, forceLoad, getDefaultIntegrations, init, onLoad };
114
+ export { forceLoad, getDefaultIntegrations, init, onLoad };
193
115
  //# sourceMappingURL=sdk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.js","sources":["../../../src/sdk.ts"],"sourcesContent":["import type { Client, Integration, Options } from '@sentry/core';\nimport {\n consoleSandbox,\n dedupeIntegration,\n functionToStringIntegration,\n getIntegrationsToSetup,\n getLocationHref,\n inboundFiltersIntegration,\n initAndBind,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport type { BrowserClientOptions, BrowserOptions } from './client';\nimport { BrowserClient } from './client';\nimport { DEBUG_BUILD } from './debug-build';\nimport { WINDOW } from './helpers';\nimport { breadcrumbsIntegration } from './integrations/breadcrumbs';\nimport { browserApiErrorsIntegration } from './integrations/browserapierrors';\nimport { browserSessionIntegration } from './integrations/browsersession';\nimport { globalHandlersIntegration } from './integrations/globalhandlers';\nimport { httpContextIntegration } from './integrations/httpcontext';\nimport { linkedErrorsIntegration } from './integrations/linkederrors';\nimport { defaultStackParser } from './stack-parsers';\nimport { makeFetchTransport } from './transports/fetch';\n\ntype ExtensionProperties = {\n chrome?: Runtime;\n browser?: Runtime;\n nw?: unknown;\n};\ntype Runtime = {\n runtime?: {\n id?: string;\n };\n};\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\n/** Get the default integrations for the browser SDK. */\nexport function getDefaultIntegrations(_options: Options): Integration[] {\n /**\n * Note: Please make sure this stays in sync with Angular SDK, which re-exports\n * `getDefaultIntegrations` but with an adjusted set of integrations.\n */\n return [\n // TODO(v10): Replace with `eventFiltersIntegration` once we remove the deprecated `inboundFiltersIntegration`\n // eslint-disable-next-line deprecation/deprecation\n inboundFiltersIntegration(),\n functionToStringIntegration(),\n browserApiErrorsIntegration(),\n breadcrumbsIntegration(),\n globalHandlersIntegration(),\n linkedErrorsIntegration(),\n dedupeIntegration(),\n httpContextIntegration(),\n browserSessionIntegration(),\n ];\n}\n\n/** Exported only for tests. */\nexport function applyDefaultOptions(optionsArg: BrowserOptions = {}): BrowserOptions {\n const defaultOptions: BrowserOptions = {\n defaultIntegrations: getDefaultIntegrations(optionsArg),\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 };\n\n return {\n ...defaultOptions,\n ...dropTopLevelUndefinedKeys(optionsArg),\n };\n}\n\n/**\n * In contrast to the regular `dropUndefinedKeys` method,\n * this one does not deep-drop keys, but only on the top level.\n */\nfunction dropTopLevelUndefinedKeys<T extends object>(obj: T): Partial<T> {\n const mutatetedObj: Partial<T> = {};\n\n for (const k of Object.getOwnPropertyNames(obj)) {\n const key = k as keyof T;\n if (obj[key] !== undefined) {\n mutatetedObj[key] = obj[key];\n }\n }\n\n return mutatetedObj;\n}\n\n/**\n * The Sentry Browser SDK Client.\n *\n * To use this SDK, call the {@link init} function as early as possible when\n * loading the web page. To set context information or send manual events, use\n * the provided methods.\n *\n * @example\n *\n * ```\n *\n * import { init } from '@sentry/browser';\n *\n * init({\n * dsn: '__DSN__',\n * // ...\n * });\n * ```\n *\n * @example\n * ```\n *\n * import { addBreadcrumb } from '@sentry/browser';\n * addBreadcrumb({\n * message: 'My Breadcrumb',\n * // ...\n * });\n * ```\n *\n * @example\n *\n * ```\n *\n * import * as Sentry from '@sentry/browser';\n * Sentry.captureMessage('Hello, world!');\n * Sentry.captureException(new Error('Good bye'));\n * Sentry.captureEvent({\n * message: 'Manual',\n * stacktrace: [\n * // ...\n * ],\n * });\n * ```\n *\n * @see {@link BrowserOptions} for documentation on configuration options.\n */\nexport function init(browserOptions: BrowserOptions = {}): Client | undefined {\n if (!browserOptions.skipBrowserExtensionCheck && _checkForBrowserExtension()) {\n return;\n }\n\n const options = applyDefaultOptions(browserOptions);\n const clientOptions: BrowserClientOptions = {\n ...options,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n integrations: getIntegrationsToSetup(options),\n transport: options.transport || makeFetchTransport,\n };\n\n return initAndBind(BrowserClient, clientOptions);\n}\n\n/**\n * This function is here to be API compatible with the loader.\n * @hidden\n */\nexport function forceLoad(): void {\n // Noop\n}\n\n/**\n * This function is here to be API compatible with the loader.\n * @hidden\n */\nexport function onLoad(callback: () => void): void {\n callback();\n}\n\nfunction _isEmbeddedBrowserExtension(): boolean {\n if (typeof WINDOW.window === 'undefined') {\n // No need to show the error if we're not in a browser window environment (e.g. service workers)\n return false;\n }\n\n const _window = WINDOW as typeof WINDOW & ExtensionProperties;\n\n // Running the SDK in NW.js, which appears like a browser extension but isn't, is also fine\n // see: https://github.com/getsentry/sentry-javascript/issues/12668\n if (_window.nw) {\n return false;\n }\n\n const extensionObject = _window['chrome'] || _window['browser'];\n\n if (!extensionObject?.runtime?.id) {\n return false;\n }\n\n const href = getLocationHref();\n const extensionProtocols = ['chrome-extension', 'moz-extension', 'ms-browser-extension', 'safari-web-extension'];\n\n // Running the SDK in a dedicated extension page and calling Sentry.init is fine; no risk of data leakage\n const isDedicatedExtensionPage =\n WINDOW === WINDOW.top && extensionProtocols.some(protocol => href.startsWith(`${protocol}://`));\n\n return !isDedicatedExtensionPage;\n}\n\nfunction _checkForBrowserExtension(): true | void {\n if (_isEmbeddedBrowserExtension()) {\n if (DEBUG_BUILD) {\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.error(\n '[Sentry] You cannot use Sentry.init() in a browser extension, see: https://docs.sentry.io/platforms/javascript/best-practices/browser-extensions/',\n );\n });\n }\n\n return true;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sdk.js","sources":["../../../src/sdk.ts"],"sourcesContent":["import type { Client, Integration, Options } from '@sentry/core';\nimport {\n dedupeIntegration,\n functionToStringIntegration,\n getIntegrationsToSetup,\n inboundFiltersIntegration,\n initAndBind,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport type { BrowserClientOptions, BrowserOptions } from './client';\nimport { BrowserClient } from './client';\nimport { breadcrumbsIntegration } from './integrations/breadcrumbs';\nimport { browserApiErrorsIntegration } from './integrations/browserapierrors';\nimport { browserSessionIntegration } from './integrations/browsersession';\nimport { globalHandlersIntegration } from './integrations/globalhandlers';\nimport { httpContextIntegration } from './integrations/httpcontext';\nimport { linkedErrorsIntegration } from './integrations/linkederrors';\nimport { defaultStackParser } from './stack-parsers';\nimport { makeFetchTransport } from './transports/fetch';\nimport { checkAndWarnIfIsEmbeddedBrowserExtension } from './utils/detectBrowserExtension';\n\n/** Get the default integrations for the browser SDK. */\nexport function getDefaultIntegrations(_options: Options): Integration[] {\n /**\n * Note: Please make sure this stays in sync with Angular SDK, which re-exports\n * `getDefaultIntegrations` but with an adjusted set of integrations.\n */\n return [\n // TODO(v10): Replace with `eventFiltersIntegration` once we remove the deprecated `inboundFiltersIntegration`\n // eslint-disable-next-line deprecation/deprecation\n inboundFiltersIntegration(),\n functionToStringIntegration(),\n browserApiErrorsIntegration(),\n breadcrumbsIntegration(),\n globalHandlersIntegration(),\n linkedErrorsIntegration(),\n dedupeIntegration(),\n httpContextIntegration(),\n browserSessionIntegration(),\n ];\n}\n\n/**\n * The Sentry Browser SDK Client.\n *\n * To use this SDK, call the {@link init} function as early as possible when\n * loading the web page. To set context information or send manual events, use\n * the provided methods.\n *\n * @example\n *\n * ```\n *\n * import { init } from '@sentry/browser';\n *\n * init({\n * dsn: '__DSN__',\n * // ...\n * });\n * ```\n *\n * @example\n * ```\n *\n * import { addBreadcrumb } from '@sentry/browser';\n * addBreadcrumb({\n * message: 'My Breadcrumb',\n * // ...\n * });\n * ```\n *\n * @example\n *\n * ```\n *\n * import * as Sentry from '@sentry/browser';\n * Sentry.captureMessage('Hello, world!');\n * Sentry.captureException(new Error('Good bye'));\n * Sentry.captureEvent({\n * message: 'Manual',\n * stacktrace: [\n * // ...\n * ],\n * });\n * ```\n *\n * @see {@link BrowserOptions} for documentation on configuration options.\n */\nexport function init(options: BrowserOptions = {}): Client | undefined {\n const shouldDisableBecauseIsBrowserExtenstion =\n !options.skipBrowserExtensionCheck && checkAndWarnIfIsEmbeddedBrowserExtension();\n\n const clientOptions: BrowserClientOptions = {\n ...options,\n enabled: shouldDisableBecauseIsBrowserExtenstion ? false : options.enabled,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n integrations: getIntegrationsToSetup({\n integrations: options.integrations,\n defaultIntegrations:\n options.defaultIntegrations == null ? getDefaultIntegrations(options) : options.defaultIntegrations,\n }),\n transport: options.transport || makeFetchTransport,\n };\n return initAndBind(BrowserClient, clientOptions);\n}\n\n/**\n * This function is here to be API compatible with the loader.\n * @hidden\n */\nexport function forceLoad(): void {\n // Noop\n}\n\n/**\n * This function is here to be API compatible with the loader.\n * @hidden\n */\nexport function onLoad(callback: () => void): void {\n callback();\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAqBA;AACO,SAAS,sBAAsB,CAAC,QAAQ,EAA0B;AACzE;AACA;AACA;AACA;AACA,EAAE,OAAO;AACT;AACA;AACA,IAAI,yBAAyB,EAAE;AAC/B,IAAI,2BAA2B,EAAE;AACjC,IAAI,2BAA2B,EAAE;AACjC,IAAI,sBAAsB,EAAE;AAC5B,IAAI,yBAAyB,EAAE;AAC/B,IAAI,uBAAuB,EAAE;AAC7B,IAAI,iBAAiB,EAAE;AACvB,IAAI,sBAAsB,EAAE;AAC5B,IAAI,yBAAyB,EAAE;AAC/B,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,GAAmB,EAAE,EAAsB;AACvE,EAAE,MAAM,uCAAwC;AAChD,IAAI,CAAC,OAAO,CAAC,6BAA6B,wCAAwC,EAAE;;AAEpF,EAAE,MAAM,aAAa,GAAyB;AAC9C,IAAI,GAAG,OAAO;AACd,IAAI,OAAO,EAAE,uCAAwC,GAAE,QAAQ,OAAO,CAAC,OAAO;AAC9E,IAAI,WAAW,EAAE,iCAAiC,CAAC,OAAO,CAAC,WAAA,IAAe,kBAAkB,CAAC;AAC7F,IAAI,YAAY,EAAE,sBAAsB,CAAC;AACzC,MAAM,YAAY,EAAE,OAAO,CAAC,YAAY;AACxC,MAAM,mBAAmB;AACzB,QAAQ,OAAO,CAAC,mBAAoB,IAAG,IAAK,GAAE,sBAAsB,CAAQ,CAAA,GAAI,OAAO,CAAC,mBAAmB;AAC3G,KAAK,CAAC;AACN,IAAI,SAAS,EAAE,OAAO,CAAC,SAAA,IAAa,kBAAkB;AACtD,GAAG;AACH,EAAE,OAAO,WAAW,CAAC,aAAa,EAAE,aAAa,CAAC;AAClD;;AAEA;AACA;AACA;AACA;AACO,SAAS,SAAS,GAAS;AAClC;AACA;;AAEA;AACA;AACA;AACA;AACO,SAAS,MAAM,CAAC,QAAQ,EAAoB;AACnD,EAAE,QAAQ,EAAE;AACZ;;;;"}
@@ -1,5 +1,5 @@
1
- import { TRACING_DEFAULTS, registerSpanErrorInstrumentation, GLOBAL_OBJ, getLocationHref, getClient, getIsolationScope, generateTraceId, getCurrentScope, propagationContextFromHeaders, browserPerformanceTimeOrigin, parseStringToURLObject, spanToJSON, logger, SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startIdleSpan, getDynamicSamplingContextFromSpan, spanIsSampled, addNonEnumerableProperty, consoleSandbox, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
2
- import { startTrackingWebVitals, startTrackingINP, startTrackingLongAnimationFrames, startTrackingLongTasks, startTrackingInteractions, addHistoryInstrumentationHandler, registerInpInteractionListener, addPerformanceEntries } from '@sentry-internal/browser-utils';
1
+ import { TRACING_DEFAULTS, getLocationHref, browserPerformanceTimeOrigin, parseStringToURLObject, getCurrentScope, registerSpanErrorInstrumentation, GLOBAL_OBJ, getClient, getIsolationScope, generateTraceId, propagationContextFromHeaders, spanToJSON, logger, SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startIdleSpan, getDynamicSamplingContextFromSpan, spanIsSampled, addNonEnumerableProperty, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
2
+ import { addHistoryInstrumentationHandler, registerInpInteractionListener, startTrackingWebVitals, startTrackingINP, startTrackingLongAnimationFrames, startTrackingLongTasks, startTrackingInteractions, addPerformanceEntries } from '@sentry-internal/browser-utils';
3
3
  import { DEBUG_BUILD } from '../debug-build.js';
4
4
  import { WINDOW, getHttpRequestData } from '../helpers.js';
5
5
  import { registerBackgroundTabDetection } from './backgroundtab.js';
@@ -16,14 +16,13 @@ const DEFAULT_BROWSER_TRACING_OPTIONS = {
16
16
  enableLongTask: true,
17
17
  enableLongAnimationFrame: true,
18
18
  enableInp: true,
19
+ ignoreResourceSpans: [],
19
20
  linkPreviousTrace: 'in-memory',
20
21
  consistentTraceSampling: false,
21
22
  _experiments: {},
22
23
  ...defaultRequestInstrumentationOptions,
23
24
  };
24
25
 
25
- let _hasBeenInitialized = false;
26
-
27
26
  /**
28
27
  * The Browser Tracing integration automatically instruments browser pageload/navigation
29
28
  * actions as transactions, and captures requests, metrics and errors as spans.
@@ -34,14 +33,10 @@ let _hasBeenInitialized = false;
34
33
  * We explicitly export the proper type here, as this has to be extended in some cases.
35
34
  */
36
35
  const browserTracingIntegration = ((_options = {}) => {
37
- if (_hasBeenInitialized) {
38
- consoleSandbox(() => {
39
- // eslint-disable-next-line no-console
40
- console.warn('Multiple browserTracingIntegration instances are not supported.');
41
- });
42
- }
43
-
44
- _hasBeenInitialized = true;
36
+ const latestRoute = {
37
+ name: undefined,
38
+ source: undefined,
39
+ };
45
40
 
46
41
  /**
47
42
  * This is just a small wrapper that makes `document` optional.
@@ -49,8 +44,6 @@ const browserTracingIntegration = ((_options = {}) => {
49
44
  */
50
45
  const optionalWindowDocument = WINDOW.document ;
51
46
 
52
- registerSpanErrorInstrumentation();
53
-
54
47
  const {
55
48
  enableInp,
56
49
  enableLongTask,
@@ -66,6 +59,7 @@ const browserTracingIntegration = ((_options = {}) => {
66
59
  trackFetchStreamPerformance,
67
60
  shouldCreateSpanForRequest,
68
61
  enableHTTPTimings,
62
+ ignoreResourceSpans,
69
63
  instrumentPageLoad,
70
64
  instrumentNavigation,
71
65
  linkPreviousTrace,
@@ -76,31 +70,7 @@ const browserTracingIntegration = ((_options = {}) => {
76
70
  ..._options,
77
71
  };
78
72
 
79
- const _collectWebVitals = startTrackingWebVitals({ recordClsStandaloneSpans: enableStandaloneClsSpans || false });
80
-
81
- if (enableInp) {
82
- startTrackingINP();
83
- }
84
-
85
- if (
86
- enableLongAnimationFrame &&
87
- GLOBAL_OBJ.PerformanceObserver &&
88
- PerformanceObserver.supportedEntryTypes &&
89
- PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')
90
- ) {
91
- startTrackingLongAnimationFrames();
92
- } else if (enableLongTask) {
93
- startTrackingLongTasks();
94
- }
95
-
96
- if (enableInteractions) {
97
- startTrackingInteractions();
98
- }
99
-
100
- const latestRoute = {
101
- name: undefined,
102
- source: undefined,
103
- };
73
+ let _collectWebVitals;
104
74
 
105
75
  /** Create routing idle transaction. */
106
76
  function _createRouteSpan(client, startSpanOptions) {
@@ -129,8 +99,10 @@ const browserTracingIntegration = ((_options = {}) => {
129
99
  // should wait for finish signal if it's a pageload transaction
130
100
  disableAutoFinish: isPageloadTransaction,
131
101
  beforeSpanEnd: span => {
132
- _collectWebVitals();
133
- addPerformanceEntries(span, { recordClsOnPageloadSpan: !enableStandaloneClsSpans });
102
+ // This will generally always be defined here, because it is set in `setup()` of the integration
103
+ // but technically, it is optional, so we guard here to be extra safe
104
+ _collectWebVitals?.();
105
+ addPerformanceEntries(span, { recordClsOnPageloadSpan: !enableStandaloneClsSpans, ignoreResourceSpans });
134
106
  setActiveIdleSpan(client, undefined);
135
107
 
136
108
  // A trace should stay consistent over the entire timespan of one route - even after the pageload/navigation ended.
@@ -167,8 +139,29 @@ const browserTracingIntegration = ((_options = {}) => {
167
139
 
168
140
  return {
169
141
  name: BROWSER_TRACING_INTEGRATION_ID,
170
- afterAllSetup(client) {
171
- let startingUrl = getLocationHref();
142
+ setup(client) {
143
+ registerSpanErrorInstrumentation();
144
+
145
+ _collectWebVitals = startTrackingWebVitals({ recordClsStandaloneSpans: enableStandaloneClsSpans || false });
146
+
147
+ if (enableInp) {
148
+ startTrackingINP();
149
+ }
150
+
151
+ if (
152
+ enableLongAnimationFrame &&
153
+ GLOBAL_OBJ.PerformanceObserver &&
154
+ PerformanceObserver.supportedEntryTypes &&
155
+ PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')
156
+ ) {
157
+ startTrackingLongAnimationFrames();
158
+ } else if (enableLongTask) {
159
+ startTrackingLongTasks();
160
+ }
161
+
162
+ if (enableInteractions) {
163
+ startTrackingInteractions();
164
+ }
172
165
 
173
166
  function maybeEndActiveSpan() {
174
167
  const activeSpan = getActiveIdleSpan(client);
@@ -229,6 +222,9 @@ const browserTracingIntegration = ((_options = {}) => {
229
222
  ...startSpanOptions,
230
223
  });
231
224
  });
225
+ },
226
+ afterAllSetup(client) {
227
+ let startingUrl = getLocationHref();
232
228
 
233
229
  if (linkPreviousTrace !== 'off') {
234
230
  linkTraces(client, { linkPreviousTrace, consistentTraceSampling });