@sentry/browser 6.16.1 → 6.17.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 (111) hide show
  1. package/build/bundle.es6.js +1311 -1428
  2. package/build/bundle.es6.js.map +1 -1
  3. package/build/bundle.es6.min.js +2 -2
  4. package/build/bundle.es6.min.js.map +1 -1
  5. package/build/bundle.js +1350 -1483
  6. package/build/bundle.js.map +1 -1
  7. package/build/bundle.min.js +2 -2
  8. package/build/bundle.min.js.map +1 -1
  9. package/dist/eventbuilder.d.ts +2 -2
  10. package/dist/eventbuilder.d.ts.map +1 -1
  11. package/dist/eventbuilder.js +7 -7
  12. package/dist/eventbuilder.js.map +1 -1
  13. package/dist/exports.d.ts +1 -1
  14. package/dist/exports.d.ts.map +1 -1
  15. package/dist/exports.js +0 -1
  16. package/dist/exports.js.map +1 -1
  17. package/dist/helpers.d.ts.map +1 -1
  18. package/dist/helpers.js +26 -37
  19. package/dist/helpers.js.map +1 -1
  20. package/dist/integrations/breadcrumbs.d.ts +0 -20
  21. package/dist/integrations/breadcrumbs.d.ts.map +1 -1
  22. package/dist/integrations/breadcrumbs.js +132 -173
  23. package/dist/integrations/breadcrumbs.js.map +1 -1
  24. package/dist/integrations/dedupe.d.ts +0 -14
  25. package/dist/integrations/dedupe.d.ts.map +1 -1
  26. package/dist/integrations/dedupe.js +126 -126
  27. package/dist/integrations/dedupe.js.map +1 -1
  28. package/dist/integrations/globalhandlers.d.ts +7 -25
  29. package/dist/integrations/globalhandlers.d.ts.map +1 -1
  30. package/dist/integrations/globalhandlers.js +176 -168
  31. package/dist/integrations/globalhandlers.js.map +1 -1
  32. package/dist/integrations/linkederrors.d.ts +15 -13
  33. package/dist/integrations/linkederrors.d.ts.map +1 -1
  34. package/dist/integrations/linkederrors.js +26 -28
  35. package/dist/integrations/linkederrors.js.map +1 -1
  36. package/dist/integrations/trycatch.d.ts +0 -8
  37. package/dist/integrations/trycatch.d.ts.map +1 -1
  38. package/dist/integrations/trycatch.js +154 -153
  39. package/dist/integrations/trycatch.js.map +1 -1
  40. package/dist/integrations/useragent.js +2 -3
  41. package/dist/integrations/useragent.js.map +1 -1
  42. package/dist/sdk.d.ts.map +1 -1
  43. package/dist/sdk.js +23 -19
  44. package/dist/sdk.js.map +1 -1
  45. package/dist/transports/base.d.ts +9 -4
  46. package/dist/transports/base.d.ts.map +1 -1
  47. package/dist/transports/base.js +23 -19
  48. package/dist/transports/base.js.map +1 -1
  49. package/dist/transports/fetch.d.ts +2 -10
  50. package/dist/transports/fetch.d.ts.map +1 -1
  51. package/dist/transports/fetch.js +6 -20
  52. package/dist/transports/fetch.js.map +1 -1
  53. package/dist/transports/utils.d.ts.map +1 -1
  54. package/dist/transports/utils.js +7 -5
  55. package/dist/transports/utils.js.map +1 -1
  56. package/dist/transports/xhr.d.ts +2 -10
  57. package/dist/transports/xhr.d.ts.map +1 -1
  58. package/dist/transports/xhr.js +3 -17
  59. package/dist/transports/xhr.js.map +1 -1
  60. package/esm/eventbuilder.d.ts +2 -2
  61. package/esm/eventbuilder.d.ts.map +1 -1
  62. package/esm/eventbuilder.js +8 -8
  63. package/esm/eventbuilder.js.map +1 -1
  64. package/esm/exports.d.ts +1 -1
  65. package/esm/exports.d.ts.map +1 -1
  66. package/esm/exports.js +1 -1
  67. package/esm/exports.js.map +1 -1
  68. package/esm/helpers.d.ts.map +1 -1
  69. package/esm/helpers.js +28 -39
  70. package/esm/helpers.js.map +1 -1
  71. package/esm/integrations/breadcrumbs.d.ts +0 -20
  72. package/esm/integrations/breadcrumbs.d.ts.map +1 -1
  73. package/esm/integrations/breadcrumbs.js +134 -175
  74. package/esm/integrations/breadcrumbs.js.map +1 -1
  75. package/esm/integrations/dedupe.d.ts +0 -14
  76. package/esm/integrations/dedupe.d.ts.map +1 -1
  77. package/esm/integrations/dedupe.js +126 -126
  78. package/esm/integrations/dedupe.js.map +1 -1
  79. package/esm/integrations/globalhandlers.d.ts +7 -25
  80. package/esm/integrations/globalhandlers.d.ts.map +1 -1
  81. package/esm/integrations/globalhandlers.js +178 -170
  82. package/esm/integrations/globalhandlers.js.map +1 -1
  83. package/esm/integrations/linkederrors.d.ts +15 -13
  84. package/esm/integrations/linkederrors.d.ts.map +1 -1
  85. package/esm/integrations/linkederrors.js +24 -28
  86. package/esm/integrations/linkederrors.js.map +1 -1
  87. package/esm/integrations/trycatch.d.ts +0 -8
  88. package/esm/integrations/trycatch.d.ts.map +1 -1
  89. package/esm/integrations/trycatch.js +155 -154
  90. package/esm/integrations/trycatch.js.map +1 -1
  91. package/esm/integrations/useragent.js +2 -3
  92. package/esm/integrations/useragent.js.map +1 -1
  93. package/esm/sdk.d.ts.map +1 -1
  94. package/esm/sdk.js +24 -20
  95. package/esm/sdk.js.map +1 -1
  96. package/esm/transports/base.d.ts +9 -4
  97. package/esm/transports/base.d.ts.map +1 -1
  98. package/esm/transports/base.js +25 -21
  99. package/esm/transports/base.js.map +1 -1
  100. package/esm/transports/fetch.d.ts +2 -10
  101. package/esm/transports/fetch.d.ts.map +1 -1
  102. package/esm/transports/fetch.js +6 -20
  103. package/esm/transports/fetch.js.map +1 -1
  104. package/esm/transports/utils.d.ts.map +1 -1
  105. package/esm/transports/utils.js +8 -6
  106. package/esm/transports/utils.js.map +1 -1
  107. package/esm/transports/xhr.d.ts +2 -10
  108. package/esm/transports/xhr.d.ts.map +1 -1
  109. package/esm/transports/xhr.js +3 -17
  110. package/esm/transports/xhr.js.map +1 -1
  111. package/package.json +4 -5
@@ -1,43 +1,8 @@
1
- /*! @sentry/browser 6.16.1 (6919d17) | https://github.com/getsentry/sentry-javascript */
1
+ /*! @sentry/browser 6.17.2 (37b1213) | https://github.com/getsentry/sentry-javascript */
2
2
  var Sentry = (function (exports) {
3
- /** Console logging verbosity for the SDK. */
4
- var LogLevel;
5
- (function (LogLevel) {
6
- /** No logs will be generated. */
7
- LogLevel[LogLevel["None"] = 0] = "None";
8
- /** Only SDK internal errors will be logged. */
9
- LogLevel[LogLevel["Error"] = 1] = "Error";
10
- /** Information useful for debugging the SDK will be logged. */
11
- LogLevel[LogLevel["Debug"] = 2] = "Debug";
12
- /** All SDK actions will be logged. */
13
- LogLevel[LogLevel["Verbose"] = 3] = "Verbose";
14
- })(LogLevel || (LogLevel = {}));
15
-
16
3
  /**
17
- * Session Status
4
+ * TODO(v7): Remove this enum and replace with SeverityLevel
18
5
  */
19
- var SessionStatus;
20
- (function (SessionStatus) {
21
- /** JSDoc */
22
- SessionStatus["Ok"] = "ok";
23
- /** JSDoc */
24
- SessionStatus["Exited"] = "exited";
25
- /** JSDoc */
26
- SessionStatus["Crashed"] = "crashed";
27
- /** JSDoc */
28
- SessionStatus["Abnormal"] = "abnormal";
29
- })(SessionStatus || (SessionStatus = {}));
30
- var RequestSessionStatus;
31
- (function (RequestSessionStatus) {
32
- /** JSDoc */
33
- RequestSessionStatus["Ok"] = "ok";
34
- /** JSDoc */
35
- RequestSessionStatus["Errored"] = "errored";
36
- /** JSDoc */
37
- RequestSessionStatus["Crashed"] = "crashed";
38
- })(RequestSessionStatus || (RequestSessionStatus = {}));
39
-
40
- /** JSDoc */
41
6
  (function (Severity) {
42
7
  /** JSDoc */
43
8
  Severity["Fatal"] = "fatal";
@@ -54,95 +19,7 @@ var Sentry = (function (exports) {
54
19
  /** JSDoc */
55
20
  Severity["Critical"] = "critical";
56
21
  })(exports.Severity || (exports.Severity = {}));
57
- // eslint-disable-next-line @typescript-eslint/no-namespace, import/export
58
- (function (Severity) {
59
- /**
60
- * Converts a string-based level into a {@link Severity}.
61
- *
62
- * @param level string representation of Severity
63
- * @returns Severity
64
- */
65
- function fromString(level) {
66
- switch (level) {
67
- case 'debug':
68
- return Severity.Debug;
69
- case 'info':
70
- return Severity.Info;
71
- case 'warn':
72
- case 'warning':
73
- return Severity.Warning;
74
- case 'error':
75
- return Severity.Error;
76
- case 'fatal':
77
- return Severity.Fatal;
78
- case 'critical':
79
- return Severity.Critical;
80
- case 'log':
81
- default:
82
- return Severity.Log;
83
- }
84
- }
85
- Severity.fromString = fromString;
86
- })(exports.Severity || (exports.Severity = {}));
87
-
88
- /** The status of an event. */
89
- (function (Status) {
90
- /** The status could not be determined. */
91
- Status["Unknown"] = "unknown";
92
- /** The event was skipped due to configuration or callbacks. */
93
- Status["Skipped"] = "skipped";
94
- /** The event was sent to Sentry successfully. */
95
- Status["Success"] = "success";
96
- /** The client is currently rate limited and will try again later. */
97
- Status["RateLimit"] = "rate_limit";
98
- /** The event could not be processed. */
99
- Status["Invalid"] = "invalid";
100
- /** A server-side error occurred during submission. */
101
- Status["Failed"] = "failed";
102
- })(exports.Status || (exports.Status = {}));
103
- // eslint-disable-next-line @typescript-eslint/no-namespace, import/export
104
- (function (Status) {
105
- /**
106
- * Converts a HTTP status code into a {@link Status}.
107
- *
108
- * @param code The HTTP response status code.
109
- * @returns The send status or {@link Status.Unknown}.
110
- */
111
- function fromHttpCode(code) {
112
- if (code >= 200 && code < 300) {
113
- return Status.Success;
114
- }
115
- if (code === 429) {
116
- return Status.RateLimit;
117
- }
118
- if (code >= 400 && code < 500) {
119
- return Status.Invalid;
120
- }
121
- if (code >= 500) {
122
- return Status.Failed;
123
- }
124
- return Status.Unknown;
125
- }
126
- Status.fromHttpCode = fromHttpCode;
127
- })(exports.Status || (exports.Status = {}));
128
-
129
- var TransactionSamplingMethod;
130
- (function (TransactionSamplingMethod) {
131
- TransactionSamplingMethod["Explicit"] = "explicitly_set";
132
- TransactionSamplingMethod["Sampler"] = "client_sampler";
133
- TransactionSamplingMethod["Rate"] = "client_rate";
134
- TransactionSamplingMethod["Inheritance"] = "inheritance";
135
- })(TransactionSamplingMethod || (TransactionSamplingMethod = {}));
136
-
137
- var Outcome;
138
- (function (Outcome) {
139
- Outcome["BeforeSend"] = "before_send";
140
- Outcome["EventProcessor"] = "event_processor";
141
- Outcome["NetworkError"] = "network_error";
142
- Outcome["QueueOverflow"] = "queue_overflow";
143
- Outcome["RateLimitBackoff"] = "ratelimit_backoff";
144
- Outcome["SampleRate"] = "sample_rate";
145
- })(Outcome || (Outcome = {}));
22
+ const SeverityLevels = ['fatal', 'error', 'warning', 'log', 'info', 'debug', 'critical'];
146
23
 
147
24
  /**
148
25
  * Consumes the promise and logs the error when it rejects.
@@ -157,6 +34,33 @@ var Sentry = (function (exports) {
157
34
  });
158
35
  }
159
36
 
37
+ /**
38
+ * This module mostly exists for optimizations in the build process
39
+ * through rollup and terser. We define some global constants which
40
+ * are normally undefined. However terser overrides these with global
41
+ * definitions which can be evaluated by the static analyzer when
42
+ * creating a bundle.
43
+ *
44
+ * In turn the `isDebugBuild` and `isBrowserBundle` functions are pure
45
+ * and can help us remove unused code from the bundles.
46
+ */
47
+ /**
48
+ * Figures out if we're building with debug functionality.
49
+ *
50
+ * @returns true if this is a debug build
51
+ */
52
+ function isDebugBuild() {
53
+ return typeof __SENTRY_NO_DEBUG__ !== 'undefined' && !__SENTRY_BROWSER_BUNDLE__;
54
+ }
55
+ /**
56
+ * Figures out if we're building a browser bundle.
57
+ *
58
+ * @returns true if this is a browser bundle build.
59
+ */
60
+ function isBrowserBundle() {
61
+ return typeof __SENTRY_BROWSER_BUNDLE__ !== 'undefined' && !!__SENTRY_BROWSER_BUNDLE__;
62
+ }
63
+
160
64
  /**
161
65
  * NOTE: In order to avoid circular dependencies, if you add a function to this module and it needs to print something,
162
66
  * you must either a) use `console.log` rather than the logger, or b) put your function elsewhere.
@@ -167,7 +71,10 @@ var Sentry = (function (exports) {
167
71
  * @returns Answer to given question
168
72
  */
169
73
  function isNodeEnv() {
170
- return Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]';
74
+ // explicitly check for browser bundles as those can be optimized statically
75
+ // by terser/rollup.
76
+ return (!isBrowserBundle() &&
77
+ Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]');
171
78
  }
172
79
  /**
173
80
  * Requires a module which is protected against bundler minification.
@@ -202,6 +109,8 @@ var Sentry = (function (exports) {
202
109
 
203
110
  /* eslint-disable @typescript-eslint/no-explicit-any */
204
111
  /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
112
+ // eslint-disable-next-line @typescript-eslint/unbound-method
113
+ const objectToString = Object.prototype.toString;
205
114
  /**
206
115
  * Checks whether given value's type is one of a few Error or Error-like
207
116
  * {@link isError}.
@@ -210,17 +119,18 @@ var Sentry = (function (exports) {
210
119
  * @returns A boolean representing the result.
211
120
  */
212
121
  function isError(wat) {
213
- switch (Object.prototype.toString.call(wat)) {
122
+ switch (objectToString.call(wat)) {
214
123
  case '[object Error]':
215
- return true;
216
124
  case '[object Exception]':
217
- return true;
218
125
  case '[object DOMException]':
219
126
  return true;
220
127
  default:
221
128
  return isInstanceOf(wat, Error);
222
129
  }
223
130
  }
131
+ function isBuiltin(wat, ty) {
132
+ return objectToString.call(wat) === `[object ${ty}]`;
133
+ }
224
134
  /**
225
135
  * Checks whether given value's type is ErrorEvent
226
136
  * {@link isErrorEvent}.
@@ -229,7 +139,7 @@ var Sentry = (function (exports) {
229
139
  * @returns A boolean representing the result.
230
140
  */
231
141
  function isErrorEvent(wat) {
232
- return Object.prototype.toString.call(wat) === '[object ErrorEvent]';
142
+ return isBuiltin(wat, 'ErrorEvent');
233
143
  }
234
144
  /**
235
145
  * Checks whether given value's type is DOMError
@@ -239,7 +149,7 @@ var Sentry = (function (exports) {
239
149
  * @returns A boolean representing the result.
240
150
  */
241
151
  function isDOMError(wat) {
242
- return Object.prototype.toString.call(wat) === '[object DOMError]';
152
+ return isBuiltin(wat, 'DOMError');
243
153
  }
244
154
  /**
245
155
  * Checks whether given value's type is DOMException
@@ -249,7 +159,7 @@ var Sentry = (function (exports) {
249
159
  * @returns A boolean representing the result.
250
160
  */
251
161
  function isDOMException(wat) {
252
- return Object.prototype.toString.call(wat) === '[object DOMException]';
162
+ return isBuiltin(wat, 'DOMException');
253
163
  }
254
164
  /**
255
165
  * Checks whether given value's type is a string
@@ -259,10 +169,10 @@ var Sentry = (function (exports) {
259
169
  * @returns A boolean representing the result.
260
170
  */
261
171
  function isString(wat) {
262
- return Object.prototype.toString.call(wat) === '[object String]';
172
+ return isBuiltin(wat, 'String');
263
173
  }
264
174
  /**
265
- * Checks whether given value's is a primitive (undefined, null, number, boolean, string, bigint, symbol)
175
+ * Checks whether given value is a primitive (undefined, null, number, boolean, string, bigint, symbol)
266
176
  * {@link isPrimitive}.
267
177
  *
268
178
  * @param wat A value to be checked.
@@ -279,7 +189,7 @@ var Sentry = (function (exports) {
279
189
  * @returns A boolean representing the result.
280
190
  */
281
191
  function isPlainObject(wat) {
282
- return Object.prototype.toString.call(wat) === '[object Object]';
192
+ return isBuiltin(wat, 'Object');
283
193
  }
284
194
  /**
285
195
  * Checks whether given value's type is an Event instance
@@ -309,7 +219,7 @@ var Sentry = (function (exports) {
309
219
  * @returns A boolean representing the result.
310
220
  */
311
221
  function isRegExp(wat) {
312
- return Object.prototype.toString.call(wat) === '[object RegExp]';
222
+ return isBuiltin(wat, 'RegExp');
313
223
  }
314
224
  /**
315
225
  * Checks whether given value has a then function.
@@ -393,7 +303,6 @@ var Sentry = (function (exports) {
393
303
  * @returns generated DOM path
394
304
  */
395
305
  function _htmlElementAsString(el, keyAttrs) {
396
- var _a, _b;
397
306
  const elem = el;
398
307
  const out = [];
399
308
  let className;
@@ -406,9 +315,10 @@ var Sentry = (function (exports) {
406
315
  }
407
316
  out.push(elem.tagName.toLowerCase());
408
317
  // Pairs of attribute keys defined in `serializeAttribute` and their values on element.
409
- const keyAttrPairs = ((_a = keyAttrs) === null || _a === void 0 ? void 0 : _a.length) ? keyAttrs.filter(keyAttr => elem.getAttribute(keyAttr)).map(keyAttr => [keyAttr, elem.getAttribute(keyAttr)])
318
+ const keyAttrPairs = keyAttrs && keyAttrs.length
319
+ ? keyAttrs.filter(keyAttr => elem.getAttribute(keyAttr)).map(keyAttr => [keyAttr, elem.getAttribute(keyAttr)])
410
320
  : null;
411
- if ((_b = keyAttrPairs) === null || _b === void 0 ? void 0 : _b.length) {
321
+ if (keyAttrPairs && keyAttrPairs.length) {
412
322
  keyAttrPairs.forEach(keyAttrPair => {
413
323
  out.push(`[${keyAttrPair[0]}="${keyAttrPair[1]}"]`);
414
324
  });
@@ -485,88 +395,87 @@ var Sentry = (function (exports) {
485
395
 
486
396
  /** Regular expression used to parse a Dsn. */
487
397
  const DSN_REGEX = /^(?:(\w+):)\/\/(?:(\w+)(?::(\w+))?@)([\w.-]+)(?::(\d+))?\/(.+)/;
488
- /** Error message */
489
- const ERROR_MESSAGE = 'Invalid Dsn';
490
- /** The Sentry Dsn, identifying a Sentry instance and project. */
491
- class Dsn {
492
- /** Creates a new Dsn component */
493
- constructor(from) {
494
- if (typeof from === 'string') {
495
- this._fromString(from);
496
- }
497
- else {
498
- this._fromComponents(from);
499
- }
500
- this._validate();
398
+ function isValidProtocol(protocol) {
399
+ return protocol === 'http' || protocol === 'https';
400
+ }
401
+ /**
402
+ * Renders the string representation of this Dsn.
403
+ *
404
+ * By default, this will render the public representation without the password
405
+ * component. To get the deprecated private representation, set `withPassword`
406
+ * to true.
407
+ *
408
+ * @param withPassword When set to true, the password will be included.
409
+ */
410
+ function dsnToString(dsn, withPassword = false) {
411
+ const { host, path, pass, port, projectId, protocol, publicKey } = dsn;
412
+ return (`${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ''}` +
413
+ `@${host}${port ? `:${port}` : ''}/${path ? `${path}/` : path}${projectId}`);
414
+ }
415
+ function dsnFromString(str) {
416
+ const match = DSN_REGEX.exec(str);
417
+ if (!match) {
418
+ throw new SentryError(`Invalid Sentry Dsn: ${str}`);
501
419
  }
502
- /**
503
- * Renders the string representation of this Dsn.
504
- *
505
- * By default, this will render the public representation without the password
506
- * component. To get the deprecated private representation, set `withPassword`
507
- * to true.
508
- *
509
- * @param withPassword When set to true, the password will be included.
510
- */
511
- toString(withPassword = false) {
512
- const { host, path, pass, port, projectId, protocol, publicKey } = this;
513
- return (`${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ''}` +
514
- `@${host}${port ? `:${port}` : ''}/${path ? `${path}/` : path}${projectId}`);
515
- }
516
- /** Parses a string into this Dsn. */
517
- _fromString(str) {
518
- const match = DSN_REGEX.exec(str);
519
- if (!match) {
520
- throw new SentryError(ERROR_MESSAGE);
521
- }
522
- const [protocol, publicKey, pass = '', host, port = '', lastPath] = match.slice(1);
523
- let path = '';
524
- let projectId = lastPath;
525
- const split = projectId.split('/');
526
- if (split.length > 1) {
527
- path = split.slice(0, -1).join('/');
528
- projectId = split.pop();
529
- }
530
- if (projectId) {
531
- const projectMatch = projectId.match(/^\d+/);
532
- if (projectMatch) {
533
- projectId = projectMatch[0];
534
- }
535
- }
536
- this._fromComponents({ host, pass, path, projectId, port, protocol: protocol, publicKey });
537
- }
538
- /** Maps Dsn components into this instance. */
539
- _fromComponents(components) {
540
- // TODO this is for backwards compatibility, and can be removed in a future version
541
- if ('user' in components && !('publicKey' in components)) {
542
- components.publicKey = components.user;
543
- }
544
- this.user = components.publicKey || '';
545
- this.protocol = components.protocol;
546
- this.publicKey = components.publicKey || '';
547
- this.pass = components.pass || '';
548
- this.host = components.host;
549
- this.port = components.port || '';
550
- this.path = components.path || '';
551
- this.projectId = components.projectId;
552
- }
553
- /** Validates this Dsn and throws on error. */
554
- _validate() {
555
- ['protocol', 'publicKey', 'host', 'projectId'].forEach(component => {
556
- if (!this[component]) {
557
- throw new SentryError(`${ERROR_MESSAGE}: ${component} missing`);
558
- }
559
- });
560
- if (!this.projectId.match(/^\d+$/)) {
561
- throw new SentryError(`${ERROR_MESSAGE}: Invalid projectId ${this.projectId}`);
562
- }
563
- if (this.protocol !== 'http' && this.protocol !== 'https') {
564
- throw new SentryError(`${ERROR_MESSAGE}: Invalid protocol ${this.protocol}`);
420
+ const [protocol, publicKey, pass = '', host, port = '', lastPath] = match.slice(1);
421
+ let path = '';
422
+ let projectId = lastPath;
423
+ const split = projectId.split('/');
424
+ if (split.length > 1) {
425
+ path = split.slice(0, -1).join('/');
426
+ projectId = split.pop();
427
+ }
428
+ if (projectId) {
429
+ const projectMatch = projectId.match(/^\d+/);
430
+ if (projectMatch) {
431
+ projectId = projectMatch[0];
565
432
  }
566
- if (this.port && isNaN(parseInt(this.port, 10))) {
567
- throw new SentryError(`${ERROR_MESSAGE}: Invalid port ${this.port}`);
433
+ }
434
+ return dsnFromComponents({ host, pass, path, projectId, port, protocol: protocol, publicKey });
435
+ }
436
+ function dsnFromComponents(components) {
437
+ // TODO this is for backwards compatibility, and can be removed in a future version
438
+ if ('user' in components && !('publicKey' in components)) {
439
+ components.publicKey = components.user;
440
+ }
441
+ return {
442
+ user: components.publicKey || '',
443
+ protocol: components.protocol,
444
+ publicKey: components.publicKey || '',
445
+ pass: components.pass || '',
446
+ host: components.host,
447
+ port: components.port || '',
448
+ path: components.path || '',
449
+ projectId: components.projectId,
450
+ };
451
+ }
452
+ function validateDsn(dsn) {
453
+ if (!isDebugBuild()) {
454
+ return;
455
+ }
456
+ const { port, projectId, protocol } = dsn;
457
+ const requiredComponents = ['protocol', 'publicKey', 'host', 'projectId'];
458
+ requiredComponents.forEach(component => {
459
+ if (!dsn[component]) {
460
+ throw new SentryError(`Invalid Sentry Dsn: ${component} missing`);
568
461
  }
462
+ });
463
+ if (!projectId.match(/^\d+$/)) {
464
+ throw new SentryError(`Invalid Sentry Dsn: Invalid projectId ${projectId}`);
465
+ }
466
+ if (!isValidProtocol(protocol)) {
467
+ throw new SentryError(`Invalid Sentry Dsn: Invalid protocol ${protocol}`);
468
+ }
469
+ if (port && isNaN(parseInt(port, 10))) {
470
+ throw new SentryError(`Invalid Sentry Dsn: Invalid port ${port}`);
569
471
  }
472
+ return true;
473
+ }
474
+ /** The Sentry Dsn, identifying a Sentry instance and project. */
475
+ function makeDsn(from) {
476
+ const components = typeof from === 'string' ? dsnFromString(from) : dsnFromComponents(from);
477
+ validateDsn(components);
478
+ return components;
570
479
  }
571
480
 
572
481
  // TODO: Implement different loggers for different environments
@@ -653,54 +562,44 @@ var Sentry = (function (exports) {
653
562
 
654
563
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
655
564
  /* eslint-disable @typescript-eslint/no-explicit-any */
656
- /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
657
565
  /**
658
- * Memo class used for decycle json objects. Uses WeakSet if available otherwise array.
566
+ * Helper to decycle json objects
659
567
  */
660
- class Memo {
661
- constructor() {
662
- this._hasWeakSet = typeof WeakSet === 'function';
663
- this._inner = this._hasWeakSet ? new WeakSet() : [];
664
- }
665
- /**
666
- * Sets obj to remember.
667
- * @param obj Object to remember
668
- */
669
- memoize(obj) {
670
- if (this._hasWeakSet) {
671
- if (this._inner.has(obj)) {
568
+ function memoBuilder() {
569
+ const hasWeakSet = typeof WeakSet === 'function';
570
+ const inner = hasWeakSet ? new WeakSet() : [];
571
+ function memoize(obj) {
572
+ if (hasWeakSet) {
573
+ if (inner.has(obj)) {
672
574
  return true;
673
575
  }
674
- this._inner.add(obj);
576
+ inner.add(obj);
675
577
  return false;
676
578
  }
677
579
  // eslint-disable-next-line @typescript-eslint/prefer-for-of
678
- for (let i = 0; i < this._inner.length; i++) {
679
- const value = this._inner[i];
580
+ for (let i = 0; i < inner.length; i++) {
581
+ const value = inner[i];
680
582
  if (value === obj) {
681
583
  return true;
682
584
  }
683
585
  }
684
- this._inner.push(obj);
586
+ inner.push(obj);
685
587
  return false;
686
588
  }
687
- /**
688
- * Removes object from internal storage.
689
- * @param obj Object to forget
690
- */
691
- unmemoize(obj) {
692
- if (this._hasWeakSet) {
693
- this._inner.delete(obj);
589
+ function unmemoize(obj) {
590
+ if (hasWeakSet) {
591
+ inner.delete(obj);
694
592
  }
695
593
  else {
696
- for (let i = 0; i < this._inner.length; i++) {
697
- if (this._inner[i] === obj) {
698
- this._inner.splice(i, 1);
594
+ for (let i = 0; i < inner.length; i++) {
595
+ if (inner[i] === obj) {
596
+ inner.splice(i, 1);
699
597
  break;
700
598
  }
701
599
  }
702
600
  }
703
601
  }
602
+ return [memoize, unmemoize];
704
603
  }
705
604
 
706
605
  const defaultFunctionName = '<anonymous>';
@@ -797,13 +696,7 @@ var Sentry = (function (exports) {
797
696
  // otherwise it'll throw "TypeError: Object.defineProperties called on non-object"
798
697
  if (typeof wrapped === 'function') {
799
698
  try {
800
- wrapped.prototype = wrapped.prototype || {};
801
- Object.defineProperties(wrapped, {
802
- __sentry_original__: {
803
- enumerable: false,
804
- value: original,
805
- },
806
- });
699
+ markFunctionWrapped(wrapped, original);
807
700
  }
808
701
  catch (_Oo) {
809
702
  // This can throw if multiple fill happens on a global object like XMLHttpRequest
@@ -812,6 +705,41 @@ var Sentry = (function (exports) {
812
705
  }
813
706
  source[name] = wrapped;
814
707
  }
708
+ /**
709
+ * Defines a non enumerable property. This creates a non enumerable property on an object.
710
+ *
711
+ * @param func The function to set a property to
712
+ * @param name the name of the special sentry property
713
+ * @param value the property to define
714
+ */
715
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
716
+ function addNonEnumerableProperty(func, name, value) {
717
+ Object.defineProperty(func, name, {
718
+ value: value,
719
+ });
720
+ }
721
+ /**
722
+ * Remembers the original function on the wrapped function and
723
+ * patches up the prototype.
724
+ *
725
+ * @param wrapped the wrapper function
726
+ * @param original the original function that gets wrapped
727
+ */
728
+ function markFunctionWrapped(wrapped, original) {
729
+ const proto = original.prototype || {};
730
+ wrapped.prototype = original.prototype = proto;
731
+ addNonEnumerableProperty(wrapped, '__sentry_original__', original);
732
+ }
733
+ /**
734
+ * This extracts the original function if available. See
735
+ * `markFunctionWrapped` for more information.
736
+ *
737
+ * @param func the function to unwrap
738
+ * @returns the unwrapped version of the function if available.
739
+ */
740
+ function getOriginalFunction(func) {
741
+ return func.__sentry_original__;
742
+ }
815
743
  /**
816
744
  * Encodes given object into url-friendly format
817
745
  *
@@ -910,11 +838,11 @@ var Sentry = (function (exports) {
910
838
  * unchanged.
911
839
  */
912
840
  function serializeValue(value) {
913
- const type = Object.prototype.toString.call(value);
914
841
  // Node.js REPL notation
915
842
  if (typeof value === 'string') {
916
843
  return value;
917
844
  }
845
+ const type = Object.prototype.toString.call(value);
918
846
  if (type === '[object Object]') {
919
847
  return '[Object]';
920
848
  }
@@ -984,8 +912,8 @@ var Sentry = (function (exports) {
984
912
  * @param memo Optional Memo class handling decycling
985
913
  */
986
914
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
987
- function walk(key, value, depth = +Infinity, memo = new Memo()) {
988
- // If we reach the maximum depth, serialize whatever has left
915
+ function walk(key, value, depth = +Infinity, memo = memoBuilder()) {
916
+ // If we reach the maximum depth, serialize whatever is left
989
917
  if (depth === 0) {
990
918
  return serializeValue(value);
991
919
  }
@@ -995,17 +923,18 @@ var Sentry = (function (exports) {
995
923
  return value.toJSON();
996
924
  }
997
925
  /* eslint-enable @typescript-eslint/no-unsafe-member-access */
998
- // If normalized value is a primitive, there are no branches left to walk, so we can just bail out, as theres no point in going down that branch any further
926
+ // If normalized value is a primitive, there are no branches left to walk, so bail out
999
927
  const normalized = normalizeValue(value, key);
1000
928
  if (isPrimitive(normalized)) {
1001
929
  return normalized;
1002
930
  }
1003
- // Create source that we will use for next itterations, either objectified error object (Error type with extracted keys:value pairs) or the input itself
931
+ // Create source that we will use for the next iteration. It will either be an objectified error object (`Error` type
932
+ // with extracted key:value pairs) or the input itself.
1004
933
  const source = getWalkSource(value);
1005
934
  // Create an accumulator that will act as a parent for all future itterations of that branch
1006
935
  const acc = Array.isArray(value) ? [] : {};
1007
936
  // If we already walked that branch, bail out, as it's circular reference
1008
- if (memo.memoize(value)) {
937
+ if (memo[0](value)) {
1009
938
  return '[Circular ~]';
1010
939
  }
1011
940
  // Walk all keys of the source
@@ -1018,7 +947,7 @@ var Sentry = (function (exports) {
1018
947
  acc[innerKey] = walk(innerKey, source[innerKey], depth - 1, memo);
1019
948
  }
1020
949
  // Once walked through all the branches, remove the parent from memo storage
1021
- memo.unmemoize(value);
950
+ memo[1](value);
1022
951
  // Return accumulated values
1023
952
  return acc;
1024
953
  }
@@ -1151,7 +1080,9 @@ var Sentry = (function (exports) {
1151
1080
  doc.head.removeChild(sandbox);
1152
1081
  }
1153
1082
  catch (err) {
1154
- logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err);
1083
+ if (isDebugBuild()) {
1084
+ logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err);
1085
+ }
1155
1086
  }
1156
1087
  }
1157
1088
  return result;
@@ -1163,9 +1094,9 @@ var Sentry = (function (exports) {
1163
1094
  * @returns Answer to the given question.
1164
1095
  */
1165
1096
  function supportsReferrerPolicy() {
1166
- // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default
1167
- // https://caniuse.com/#feat=referrer-policy
1168
- // It doesn't. And it throw exception instead of ignoring this parameter...
1097
+ // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default'
1098
+ // (see https://caniuse.com/#feat=referrer-policy),
1099
+ // it doesn't. And it throws an exception instead of ignoring this parameter...
1169
1100
  // REF: https://github.com/getsentry/raven-js/issues/1233
1170
1101
  if (!supportsFetch()) {
1171
1102
  return false;
@@ -1250,13 +1181,10 @@ var Sentry = (function (exports) {
1250
1181
  * Use at your own risk, this might break without changelog notice, only used internally.
1251
1182
  * @hidden
1252
1183
  */
1253
- function addInstrumentationHandler(handler) {
1254
- if (!handler || typeof handler.type !== 'string' || typeof handler.callback !== 'function') {
1255
- return;
1256
- }
1257
- handlers[handler.type] = handlers[handler.type] || [];
1258
- handlers[handler.type].push(handler.callback);
1259
- instrument(handler.type);
1184
+ function addInstrumentationHandler(type, callback) {
1185
+ handlers[type] = handlers[type] || [];
1186
+ handlers[type].push(callback);
1187
+ instrument(type);
1260
1188
  }
1261
1189
  /** JSDoc */
1262
1190
  function triggerHandlers(type, data) {
@@ -1268,7 +1196,9 @@ var Sentry = (function (exports) {
1268
1196
  handler(data);
1269
1197
  }
1270
1198
  catch (e) {
1271
- logger.error(`Error while triggering instrumentation handler.\nType: ${type}\nName: ${getFunctionName(handler)}\nError: ${e}`);
1199
+ if (isDebugBuild()) {
1200
+ logger.error(`Error while triggering instrumentation handler.\nType: ${type}\nName: ${getFunctionName(handler)}\nError: ${e}`);
1201
+ }
1272
1202
  }
1273
1203
  }
1274
1204
  }
@@ -1349,23 +1279,20 @@ var Sentry = (function (exports) {
1349
1279
  if (!('XMLHttpRequest' in global$2)) {
1350
1280
  return;
1351
1281
  }
1352
- // Poor man's implementation of ES6 `Map`, tracking and keeping in sync key and value separately.
1353
- const requestKeys = [];
1354
- const requestValues = [];
1355
1282
  const xhrproto = XMLHttpRequest.prototype;
1356
1283
  fill(xhrproto, 'open', function (originalOpen) {
1357
1284
  return function (...args) {
1358
1285
  // eslint-disable-next-line @typescript-eslint/no-this-alias
1359
1286
  const xhr = this;
1360
1287
  const url = args[1];
1361
- xhr.__sentry_xhr__ = {
1288
+ const xhrInfo = (xhr.__sentry_xhr__ = {
1362
1289
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
1363
1290
  method: isString(args[0]) ? args[0].toUpperCase() : args[0],
1364
1291
  url: args[1],
1365
- };
1292
+ });
1366
1293
  // if Sentry key appears in URL, don't capture it as a request
1367
1294
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
1368
- if (isString(url) && xhr.__sentry_xhr__.method === 'POST' && url.match(/sentry_key/)) {
1295
+ if (isString(url) && xhrInfo.method === 'POST' && url.match(/sentry_key/)) {
1369
1296
  xhr.__sentry_own_request__ = true;
1370
1297
  }
1371
1298
  const onreadystatechangeHandler = function () {
@@ -1373,23 +1300,7 @@ var Sentry = (function (exports) {
1373
1300
  try {
1374
1301
  // touching statusCode in some platforms throws
1375
1302
  // an exception
1376
- if (xhr.__sentry_xhr__) {
1377
- xhr.__sentry_xhr__.status_code = xhr.status;
1378
- }
1379
- }
1380
- catch (e) {
1381
- /* do nothing */
1382
- }
1383
- try {
1384
- const requestPos = requestKeys.indexOf(xhr);
1385
- if (requestPos !== -1) {
1386
- // Make sure to pop both key and value to keep it in sync.
1387
- requestKeys.splice(requestPos);
1388
- const args = requestValues.splice(requestPos)[0];
1389
- if (xhr.__sentry_xhr__ && args[0] !== undefined) {
1390
- xhr.__sentry_xhr__.body = args[0];
1391
- }
1392
- }
1303
+ xhrInfo.status_code = xhr.status;
1393
1304
  }
1394
1305
  catch (e) {
1395
1306
  /* do nothing */
@@ -1418,8 +1329,9 @@ var Sentry = (function (exports) {
1418
1329
  });
1419
1330
  fill(xhrproto, 'send', function (originalSend) {
1420
1331
  return function (...args) {
1421
- requestKeys.push(this);
1422
- requestValues.push(args);
1332
+ if (this.__sentry_xhr__ && args[0] !== undefined) {
1333
+ this.__sentry_xhr__.body = args[0];
1334
+ }
1423
1335
  triggerHandlers('xhr', {
1424
1336
  args,
1425
1337
  startTimestamp: Date.now(),
@@ -1754,22 +1666,26 @@ var Sentry = (function (exports) {
1754
1666
  relative: match[5] + query + fragment,
1755
1667
  };
1756
1668
  }
1669
+ function getFirstException(event) {
1670
+ return event.exception && event.exception.values ? event.exception.values[0] : undefined;
1671
+ }
1757
1672
  /**
1758
1673
  * Extracts either message or type+value from an event that can be used for user-facing logs
1759
1674
  * @returns event's description
1760
1675
  */
1761
1676
  function getEventDescription(event) {
1762
- if (event.message) {
1763
- return event.message;
1677
+ const { message, event_id: eventId } = event;
1678
+ if (message) {
1679
+ return message;
1764
1680
  }
1765
- if (event.exception && event.exception.values && event.exception.values[0]) {
1766
- const exception = event.exception.values[0];
1767
- if (exception.type && exception.value) {
1768
- return `${exception.type}: ${exception.value}`;
1681
+ const firstException = getFirstException(event);
1682
+ if (firstException) {
1683
+ if (firstException.type && firstException.value) {
1684
+ return `${firstException.type}: ${firstException.value}`;
1769
1685
  }
1770
- return exception.type || exception.value || event.event_id || '<unknown>';
1686
+ return firstException.type || firstException.value || eventId || '<unknown>';
1771
1687
  }
1772
- return event.event_id || '<unknown>';
1688
+ return eventId || '<unknown>';
1773
1689
  }
1774
1690
  /**
1775
1691
  * Adds exception values, type and value to an synthetic Exception.
@@ -1779,11 +1695,15 @@ var Sentry = (function (exports) {
1779
1695
  * @hidden
1780
1696
  */
1781
1697
  function addExceptionTypeValue(event, value, type) {
1782
- event.exception = event.exception || {};
1783
- event.exception.values = event.exception.values || [];
1784
- event.exception.values[0] = event.exception.values[0] || {};
1785
- event.exception.values[0].value = event.exception.values[0].value || value || '';
1786
- event.exception.values[0].type = event.exception.values[0].type || type || 'Error';
1698
+ const exception = (event.exception = event.exception || {});
1699
+ const values = (exception.values = exception.values || []);
1700
+ const firstException = (values[0] = values[0] || {});
1701
+ if (!firstException.value) {
1702
+ firstException.value = value || '';
1703
+ }
1704
+ if (!firstException.type) {
1705
+ firstException.type = type || 'Error';
1706
+ }
1787
1707
  }
1788
1708
  /**
1789
1709
  * Adds exception mechanism data to a given event. Uses defaults if the second parameter is not passed.
@@ -1793,17 +1713,16 @@ var Sentry = (function (exports) {
1793
1713
  * @hidden
1794
1714
  */
1795
1715
  function addExceptionMechanism(event, newMechanism) {
1796
- var _a;
1797
- if (!event.exception || !event.exception.values) {
1716
+ const firstException = getFirstException(event);
1717
+ if (!firstException) {
1798
1718
  return;
1799
1719
  }
1800
- const exceptionValue0 = event.exception.values[0];
1801
1720
  const defaultMechanism = { type: 'generic', handled: true };
1802
- const currentMechanism = exceptionValue0.mechanism;
1803
- exceptionValue0.mechanism = Object.assign(Object.assign(Object.assign({}, defaultMechanism), currentMechanism), newMechanism);
1721
+ const currentMechanism = firstException.mechanism;
1722
+ firstException.mechanism = Object.assign(Object.assign(Object.assign({}, defaultMechanism), currentMechanism), newMechanism);
1804
1723
  if (newMechanism && 'data' in newMechanism) {
1805
- const mergedData = Object.assign(Object.assign({}, (_a = currentMechanism) === null || _a === void 0 ? void 0 : _a.data), newMechanism.data);
1806
- exceptionValue0.mechanism.data = mergedData;
1724
+ const mergedData = Object.assign(Object.assign({}, (currentMechanism && currentMechanism.data)), newMechanism.data);
1725
+ firstException.mechanism.data = mergedData;
1807
1726
  }
1808
1727
  }
1809
1728
  const defaultRetryAfter = 60 * 1000; // 60 seconds
@@ -1848,17 +1767,14 @@ var Sentry = (function (exports) {
1848
1767
  * @returns `true` if the exception has already been captured, `false` if not (with the side effect of marking it seen)
1849
1768
  */
1850
1769
  function checkOrSetAlreadyCaught(exception) {
1851
- var _a;
1852
1770
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
1853
- if ((_a = exception) === null || _a === void 0 ? void 0 : _a.__sentry_captured__) {
1771
+ if (exception && exception.__sentry_captured__) {
1854
1772
  return true;
1855
1773
  }
1856
1774
  try {
1857
1775
  // set it this way rather than by assignment so that it's not ennumerable and therefore isn't recorded by the
1858
1776
  // `ExtraErrorData` integration
1859
- Object.defineProperty(exception, '__sentry_captured__', {
1860
- value: true,
1861
- });
1777
+ addNonEnumerableProperty(exception, '__sentry_captured__', true);
1862
1778
  }
1863
1779
  catch (err) {
1864
1780
  // `exception` is a primitive, so we can't mark it seen
@@ -1867,25 +1783,47 @@ var Sentry = (function (exports) {
1867
1783
  }
1868
1784
 
1869
1785
  /* eslint-disable @typescript-eslint/explicit-function-return-type */
1786
+ /**
1787
+ * Creates a resolved sync promise.
1788
+ *
1789
+ * @param value the value to resolve the promise with
1790
+ * @returns the resolved sync promise
1791
+ */
1792
+ function resolvedSyncPromise(value) {
1793
+ return new SyncPromise(resolve => {
1794
+ resolve(value);
1795
+ });
1796
+ }
1797
+ /**
1798
+ * Creates a rejected sync promise.
1799
+ *
1800
+ * @param value the value to reject the promise with
1801
+ * @returns the rejected sync promise
1802
+ */
1803
+ function rejectedSyncPromise(reason) {
1804
+ return new SyncPromise((_, reject) => {
1805
+ reject(reason);
1806
+ });
1807
+ }
1870
1808
  /**
1871
1809
  * Thenable class that behaves like a Promise and follows it's interface
1872
1810
  * but is not async internally
1873
1811
  */
1874
1812
  class SyncPromise {
1875
1813
  constructor(executor) {
1876
- this._state = "PENDING" /* PENDING */;
1814
+ this._state = 0 /* PENDING */;
1877
1815
  this._handlers = [];
1878
1816
  /** JSDoc */
1879
1817
  this._resolve = (value) => {
1880
- this._setResult("RESOLVED" /* RESOLVED */, value);
1818
+ this._setResult(1 /* RESOLVED */, value);
1881
1819
  };
1882
1820
  /** JSDoc */
1883
1821
  this._reject = (reason) => {
1884
- this._setResult("REJECTED" /* REJECTED */, reason);
1822
+ this._setResult(2 /* REJECTED */, reason);
1885
1823
  };
1886
1824
  /** JSDoc */
1887
1825
  this._setResult = (state, value) => {
1888
- if (this._state !== "PENDING" /* PENDING */) {
1826
+ if (this._state !== 0 /* PENDING */) {
1889
1827
  return;
1890
1828
  }
1891
1829
  if (isThenable(value)) {
@@ -1896,35 +1834,25 @@ var Sentry = (function (exports) {
1896
1834
  this._value = value;
1897
1835
  this._executeHandlers();
1898
1836
  };
1899
- // TODO: FIXME
1900
- /** JSDoc */
1901
- this._attachHandler = (handler) => {
1902
- this._handlers = this._handlers.concat(handler);
1903
- this._executeHandlers();
1904
- };
1905
1837
  /** JSDoc */
1906
1838
  this._executeHandlers = () => {
1907
- if (this._state === "PENDING" /* PENDING */) {
1839
+ if (this._state === 0 /* PENDING */) {
1908
1840
  return;
1909
1841
  }
1910
1842
  const cachedHandlers = this._handlers.slice();
1911
1843
  this._handlers = [];
1912
1844
  cachedHandlers.forEach(handler => {
1913
- if (handler.done) {
1845
+ if (handler[0]) {
1914
1846
  return;
1915
1847
  }
1916
- if (this._state === "RESOLVED" /* RESOLVED */) {
1917
- if (handler.onfulfilled) {
1918
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
1919
- handler.onfulfilled(this._value);
1920
- }
1848
+ if (this._state === 1 /* RESOLVED */) {
1849
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
1850
+ handler[1](this._value);
1921
1851
  }
1922
- if (this._state === "REJECTED" /* REJECTED */) {
1923
- if (handler.onrejected) {
1924
- handler.onrejected(this._value);
1925
- }
1852
+ if (this._state === 2 /* REJECTED */) {
1853
+ handler[2](this._value);
1926
1854
  }
1927
- handler.done = true;
1855
+ handler[0] = true;
1928
1856
  });
1929
1857
  };
1930
1858
  try {
@@ -1935,80 +1863,40 @@ var Sentry = (function (exports) {
1935
1863
  }
1936
1864
  }
1937
1865
  /** JSDoc */
1938
- static resolve(value) {
1939
- return new SyncPromise(resolve => {
1940
- resolve(value);
1941
- });
1942
- }
1943
- /** JSDoc */
1944
- static reject(reason) {
1945
- return new SyncPromise((_, reject) => {
1946
- reject(reason);
1947
- });
1948
- }
1949
- /** JSDoc */
1950
- static all(collection) {
1951
- return new SyncPromise((resolve, reject) => {
1952
- if (!Array.isArray(collection)) {
1953
- reject(new TypeError(`Promise.all requires an array as input.`));
1954
- return;
1955
- }
1956
- if (collection.length === 0) {
1957
- resolve([]);
1958
- return;
1959
- }
1960
- let counter = collection.length;
1961
- const resolvedCollection = [];
1962
- collection.forEach((item, index) => {
1963
- void SyncPromise.resolve(item)
1964
- .then(value => {
1965
- resolvedCollection[index] = value;
1966
- counter -= 1;
1967
- if (counter !== 0) {
1968
- return;
1969
- }
1970
- resolve(resolvedCollection);
1971
- })
1972
- .then(null, reject);
1973
- });
1974
- });
1975
- }
1976
- /** JSDoc */
1977
1866
  then(onfulfilled, onrejected) {
1978
1867
  return new SyncPromise((resolve, reject) => {
1979
- this._attachHandler({
1980
- done: false,
1981
- onfulfilled: result => {
1868
+ this._handlers.push([
1869
+ false,
1870
+ result => {
1982
1871
  if (!onfulfilled) {
1983
1872
  // TODO: ¯\_(ツ)_/¯
1984
1873
  // TODO: FIXME
1985
1874
  resolve(result);
1986
- return;
1987
- }
1988
- try {
1989
- resolve(onfulfilled(result));
1990
- return;
1991
1875
  }
1992
- catch (e) {
1993
- reject(e);
1994
- return;
1876
+ else {
1877
+ try {
1878
+ resolve(onfulfilled(result));
1879
+ }
1880
+ catch (e) {
1881
+ reject(e);
1882
+ }
1995
1883
  }
1996
1884
  },
1997
- onrejected: reason => {
1885
+ reason => {
1998
1886
  if (!onrejected) {
1999
1887
  reject(reason);
2000
- return;
2001
1888
  }
2002
- try {
2003
- resolve(onrejected(reason));
2004
- return;
2005
- }
2006
- catch (e) {
2007
- reject(e);
2008
- return;
1889
+ else {
1890
+ try {
1891
+ resolve(onrejected(reason));
1892
+ }
1893
+ catch (e) {
1894
+ reject(e);
1895
+ }
2009
1896
  }
2010
1897
  },
2011
- });
1898
+ ]);
1899
+ this._executeHandlers();
2012
1900
  });
2013
1901
  }
2014
1902
  /** JSDoc */
@@ -2041,24 +1929,25 @@ var Sentry = (function (exports) {
2041
1929
  });
2042
1930
  });
2043
1931
  }
2044
- /** JSDoc */
2045
- toString() {
2046
- return '[object SyncPromise]';
2047
- }
2048
1932
  }
2049
1933
 
2050
- /** A simple queue that holds promises. */
2051
- class PromiseBuffer {
2052
- constructor(_limit) {
2053
- this._limit = _limit;
2054
- /** Internal set of queued Promises */
2055
- this._buffer = [];
1934
+ /**
1935
+ * Creates an new PromiseBuffer object with the specified limit
1936
+ * @param limit max number of promises that can be stored in the buffer
1937
+ */
1938
+ function makePromiseBuffer(limit) {
1939
+ const buffer = [];
1940
+ function isReady() {
1941
+ return limit === undefined || buffer.length < limit;
2056
1942
  }
2057
1943
  /**
2058
- * Says if the buffer is ready to take more requests
1944
+ * Remove a promise from the queue.
1945
+ *
1946
+ * @param task Can be any PromiseLike<T>
1947
+ * @returns Removed promise.
2059
1948
  */
2060
- isReady() {
2061
- return this._limit === undefined || this.length() < this._limit;
1949
+ function remove(task) {
1950
+ return buffer.splice(buffer.indexOf(task), 1)[0];
2062
1951
  }
2063
1952
  /**
2064
1953
  * Add a promise (representing an in-flight action) to the queue, and set it to remove itself on fulfillment.
@@ -2070,41 +1959,25 @@ var Sentry = (function (exports) {
2070
1959
  * limit check.
2071
1960
  * @returns The original promise.
2072
1961
  */
2073
- add(taskProducer) {
2074
- if (!this.isReady()) {
2075
- return SyncPromise.reject(new SentryError('Not adding Promise due to buffer limit reached.'));
1962
+ function add(taskProducer) {
1963
+ if (!isReady()) {
1964
+ return rejectedSyncPromise(new SentryError('Not adding Promise due to buffer limit reached.'));
2076
1965
  }
2077
1966
  // start the task and add its promise to the queue
2078
1967
  const task = taskProducer();
2079
- if (this._buffer.indexOf(task) === -1) {
2080
- this._buffer.push(task);
1968
+ if (buffer.indexOf(task) === -1) {
1969
+ buffer.push(task);
2081
1970
  }
2082
1971
  void task
2083
- .then(() => this.remove(task))
1972
+ .then(() => remove(task))
2084
1973
  // Use `then(null, rejectionHandler)` rather than `catch(rejectionHandler)` so that we can use `PromiseLike`
2085
1974
  // rather than `Promise`. `PromiseLike` doesn't have a `.catch` method, making its polyfill smaller. (ES5 didn't
2086
1975
  // have promises, so TS has to polyfill when down-compiling.)
2087
- .then(null, () => this.remove(task).then(null, () => {
2088
- // We have to add another catch here because `this.remove()` starts a new promise chain.
1976
+ .then(null, () => remove(task).then(null, () => {
1977
+ // We have to add another catch here because `remove()` starts a new promise chain.
2089
1978
  }));
2090
1979
  return task;
2091
1980
  }
2092
- /**
2093
- * Remove a promise from the queue.
2094
- *
2095
- * @param task Can be any PromiseLike<T>
2096
- * @returns Removed promise.
2097
- */
2098
- remove(task) {
2099
- const removedTask = this._buffer.splice(this._buffer.indexOf(task), 1)[0];
2100
- return removedTask;
2101
- }
2102
- /**
2103
- * This function returns the number of unresolved promises in the queue.
2104
- */
2105
- length() {
2106
- return this._buffer.length;
2107
- }
2108
1981
  /**
2109
1982
  * Wait for all promises in the queue to resolve or for timeout to expire, whichever comes first.
2110
1983
  *
@@ -2114,8 +1987,12 @@ var Sentry = (function (exports) {
2114
1987
  * @returns A promise which will resolve to `true` if the queue is already empty or drains before the timeout, and
2115
1988
  * `false` otherwise
2116
1989
  */
2117
- drain(timeout) {
2118
- return new SyncPromise(resolve => {
1990
+ function drain(timeout) {
1991
+ return new SyncPromise((resolve, reject) => {
1992
+ let counter = buffer.length;
1993
+ if (!counter) {
1994
+ return resolve(true);
1995
+ }
2119
1996
  // wait for `timeout` ms and then resolve to `false` (if not cancelled first)
2120
1997
  const capturedSetTimeout = setTimeout(() => {
2121
1998
  if (timeout && timeout > 0) {
@@ -2123,16 +2000,62 @@ var Sentry = (function (exports) {
2123
2000
  }
2124
2001
  }, timeout);
2125
2002
  // if all promises resolve in time, cancel the timer and resolve to `true`
2126
- void SyncPromise.all(this._buffer)
2127
- .then(() => {
2128
- clearTimeout(capturedSetTimeout);
2129
- resolve(true);
2130
- })
2131
- .then(null, () => {
2132
- resolve(true);
2003
+ buffer.forEach(item => {
2004
+ void resolvedSyncPromise(item).then(() => {
2005
+ // eslint-disable-next-line no-plusplus
2006
+ if (!--counter) {
2007
+ clearTimeout(capturedSetTimeout);
2008
+ resolve(true);
2009
+ }
2010
+ }, reject);
2133
2011
  });
2134
2012
  });
2135
2013
  }
2014
+ return {
2015
+ $: buffer,
2016
+ add,
2017
+ drain,
2018
+ };
2019
+ }
2020
+
2021
+ function isSupportedSeverity(level) {
2022
+ return SeverityLevels.indexOf(level) !== -1;
2023
+ }
2024
+ /**
2025
+ * Converts a string-based level into a {@link Severity}.
2026
+ *
2027
+ * @param level string representation of Severity
2028
+ * @returns Severity
2029
+ */
2030
+ function severityFromString(level) {
2031
+ if (level === 'warn')
2032
+ return exports.Severity.Warning;
2033
+ if (isSupportedSeverity(level)) {
2034
+ return level;
2035
+ }
2036
+ return exports.Severity.Log;
2037
+ }
2038
+
2039
+ /**
2040
+ * Converts an HTTP status code to sentry status {@link EventStatus}.
2041
+ *
2042
+ * @param code number HTTP status code
2043
+ * @returns EventStatus
2044
+ */
2045
+ function eventStatusFromHttpCode(code) {
2046
+ if (code >= 200 && code < 300) {
2047
+ return 'success';
2048
+ }
2049
+ if (code === 429) {
2050
+ return 'rate_limit';
2051
+ }
2052
+ if (code >= 400 && code < 500) {
2053
+ return 'invalid';
2054
+ }
2055
+ if (code >= 500) {
2056
+ return 'failed';
2057
+ }
2058
+ return 'unknown';
2136
2059
  }
2137
2060
 
2138
2061
  /**
@@ -2291,6 +2214,11 @@ var Sentry = (function (exports) {
2291
2214
  this._extra = {};
2292
2215
  /** Contexts */
2293
2216
  this._contexts = {};
2217
+ /**
2218
+ * A place to stash data which is needed at some point in the SDK's event processing pipeline but which shouldn't get
2219
+ * sent to Sentry
2220
+ */
2221
+ this._sdkProcessingMetadata = {};
2294
2222
  }
2295
2223
  /**
2296
2224
  * Inherit values from the parent scope.
@@ -2453,19 +2381,10 @@ var Sentry = (function (exports) {
2453
2381
  * @inheritDoc
2454
2382
  */
2455
2383
  getTransaction() {
2456
- var _a, _b, _c, _d;
2457
- // often, this span will be a transaction, but it's not guaranteed to be
2384
+ // Often, this span (if it exists at all) will be a transaction, but it's not guaranteed to be. Regardless, it will
2385
+ // have a pointer to the currently-active transaction.
2458
2386
  const span = this.getSpan();
2459
- // try it the new way first
2460
- if ((_a = span) === null || _a === void 0 ? void 0 : _a.transaction) {
2461
- return (_b = span) === null || _b === void 0 ? void 0 : _b.transaction;
2462
- }
2463
- // fallback to the old way (known bug: this only finds transactions with sampled = true)
2464
- if ((_d = (_c = span) === null || _c === void 0 ? void 0 : _c.spanRecorder) === null || _d === void 0 ? void 0 : _d.spans[0]) {
2465
- return span.spanRecorder.spans[0];
2466
- }
2467
- // neither way found a transaction
2468
- return undefined;
2387
+ return span && span.transaction;
2469
2388
  }
2470
2389
  /**
2471
2390
  * @inheritDoc
@@ -2584,7 +2503,6 @@ var Sentry = (function (exports) {
2584
2503
  * @hidden
2585
2504
  */
2586
2505
  applyToEvent(event, hint) {
2587
- var _a;
2588
2506
  if (this._extra && Object.keys(this._extra).length) {
2589
2507
  event.extra = Object.assign(Object.assign({}, this._extra), event.extra);
2590
2508
  }
@@ -2608,7 +2526,7 @@ var Sentry = (function (exports) {
2608
2526
  // errors with transaction and it relies on that.
2609
2527
  if (this._span) {
2610
2528
  event.contexts = Object.assign({ trace: this._span.getTraceContext() }, event.contexts);
2611
- const transactionName = (_a = this._span.transaction) === null || _a === void 0 ? void 0 : _a.name;
2529
+ const transactionName = this._span.transaction && this._span.transaction.name;
2612
2530
  if (transactionName) {
2613
2531
  event.tags = Object.assign({ transaction: transactionName }, event.tags);
2614
2532
  }
@@ -2616,8 +2534,16 @@ var Sentry = (function (exports) {
2616
2534
  this._applyFingerprint(event);
2617
2535
  event.breadcrumbs = [...(event.breadcrumbs || []), ...this._breadcrumbs];
2618
2536
  event.breadcrumbs = event.breadcrumbs.length > 0 ? event.breadcrumbs : undefined;
2537
+ event.sdkProcessingMetadata = this._sdkProcessingMetadata;
2619
2538
  return this._notifyEventProcessors([...getGlobalEventProcessors(), ...this._eventProcessors], event, hint);
2620
2539
  }
2540
+ /**
2541
+ * Add data which will be accessible during event processing but won't get sent to Sentry
2542
+ */
2543
+ setSDKProcessingMetadata(newData) {
2544
+ this._sdkProcessingMetadata = Object.assign(Object.assign({}, this._sdkProcessingMetadata), newData);
2545
+ return this;
2546
+ }
2621
2547
  /**
2622
2548
  * This will be called after {@link applyToEvent} is finished.
2623
2549
  */
@@ -2705,7 +2631,7 @@ var Sentry = (function (exports) {
2705
2631
  this.errors = 0;
2706
2632
  this.sid = uuid4();
2707
2633
  this.duration = 0;
2708
- this.status = SessionStatus.Ok;
2634
+ this.status = 'ok';
2709
2635
  this.init = true;
2710
2636
  this.ignoreDuration = false;
2711
2637
  // Both timestamp and started are in seconds since the UNIX epoch.
@@ -2778,8 +2704,8 @@ var Sentry = (function (exports) {
2778
2704
  if (status) {
2779
2705
  this.update({ status });
2780
2706
  }
2781
- else if (this.status === SessionStatus.Ok) {
2782
- this.update({ status: SessionStatus.Exited });
2707
+ else if (this.status === 'ok') {
2708
+ this.update({ status: 'exited' });
2783
2709
  }
2784
2710
  else {
2785
2711
  this.update();
@@ -2797,17 +2723,16 @@ var Sentry = (function (exports) {
2797
2723
  errors: this.errors,
2798
2724
  did: typeof this.did === 'number' || typeof this.did === 'string' ? `${this.did}` : undefined,
2799
2725
  duration: this.duration,
2800
- attrs: dropUndefinedKeys({
2726
+ attrs: {
2801
2727
  release: this.release,
2802
2728
  environment: this.environment,
2803
2729
  ip_address: this.ipAddress,
2804
2730
  user_agent: this.userAgent,
2805
- }),
2731
+ },
2806
2732
  });
2807
2733
  }
2808
2734
  }
2809
2735
 
2810
- /* eslint-disable max-lines */
2811
2736
  /**
2812
2737
  * API compatibility version of this hub.
2813
2738
  *
@@ -3117,11 +3042,17 @@ var Sentry = (function (exports) {
3117
3042
  * @inheritDoc
3118
3043
  */
3119
3044
  endSession() {
3120
- var _a, _b, _c, _d, _e;
3121
- (_c = (_b = (_a = this.getStackTop()) === null || _a === void 0 ? void 0 : _a.scope) === null || _b === void 0 ? void 0 : _b.getSession()) === null || _c === void 0 ? void 0 : _c.close();
3045
+ const layer = this.getStackTop();
3046
+ const scope = layer && layer.scope;
3047
+ const session = scope && scope.getSession();
3048
+ if (session) {
3049
+ session.close();
3050
+ }
3122
3051
  this._sendSessionUpdate();
3123
3052
  // the session is over; take it off of the scope
3124
- (_e = (_d = this.getStackTop()) === null || _d === void 0 ? void 0 : _d.scope) === null || _e === void 0 ? void 0 : _e.setSession();
3053
+ if (scope) {
3054
+ scope.setSession();
3055
+ }
3125
3056
  }
3126
3057
  /**
3127
3058
  * @inheritDoc
@@ -3137,8 +3068,8 @@ var Sentry = (function (exports) {
3137
3068
  if (scope) {
3138
3069
  // End existing session if there's one
3139
3070
  const currentSession = scope.getSession && scope.getSession();
3140
- if (currentSession && currentSession.status === SessionStatus.Ok) {
3141
- currentSession.update({ status: SessionStatus.Exited });
3071
+ if (currentSession && currentSession.status === 'ok') {
3072
+ currentSession.update({ status: 'exited' });
3142
3073
  }
3143
3074
  this.endSession();
3144
3075
  // Afterwards we set the new session on the scope
@@ -3240,9 +3171,9 @@ var Sentry = (function (exports) {
3240
3171
  * @returns discovered hub
3241
3172
  */
3242
3173
  function getHubFromActiveDomain(registry) {
3243
- var _a, _b, _c;
3244
3174
  try {
3245
- const activeDomain = (_c = (_b = (_a = getMainCarrier().__SENTRY__) === null || _a === void 0 ? void 0 : _a.extensions) === null || _b === void 0 ? void 0 : _b.domain) === null || _c === void 0 ? void 0 : _c.active;
3175
+ const sentry = getMainCarrier().__SENTRY__;
3176
+ const activeDomain = sentry && sentry.extensions && sentry.extensions.domain && sentry.extensions.domain.active;
3246
3177
  // If there's no active domain, just return global hub
3247
3178
  if (!activeDomain) {
3248
3179
  return getHubFromCarrier(registry);
@@ -3333,7 +3264,7 @@ var Sentry = (function (exports) {
3333
3264
  * Captures a message event and sends it to Sentry.
3334
3265
  *
3335
3266
  * @param message The message to send to Sentry.
3336
- * @param level Define the level of the message.
3267
+ * @param Severity Define the level of the message.
3337
3268
  * @returns The generated eventId.
3338
3269
  */
3339
3270
  function captureMessage(message, captureContext) {
@@ -3465,134 +3396,83 @@ var Sentry = (function (exports) {
3465
3396
  }
3466
3397
 
3467
3398
  const SENTRY_API_VERSION = '7';
3399
+ /** Initializes API Details */
3400
+ function initAPIDetails(dsn, metadata, tunnel) {
3401
+ return {
3402
+ initDsn: dsn,
3403
+ metadata: metadata || {},
3404
+ dsn: makeDsn(dsn),
3405
+ tunnel,
3406
+ };
3407
+ }
3408
+ /** Returns the prefix to construct Sentry ingestion API endpoints. */
3409
+ function getBaseApiEndpoint(dsn) {
3410
+ const protocol = dsn.protocol ? `${dsn.protocol}:` : '';
3411
+ const port = dsn.port ? `:${dsn.port}` : '';
3412
+ return `${protocol}//${dsn.host}${port}${dsn.path ? `/${dsn.path}` : ''}/api/`;
3413
+ }
3414
+ /** Returns the ingest API endpoint for target. */
3415
+ function _getIngestEndpoint(dsn, target) {
3416
+ return `${getBaseApiEndpoint(dsn)}${dsn.projectId}/${target}/`;
3417
+ }
3418
+ /** Returns a URL-encoded string with auth config suitable for a query string. */
3419
+ function _encodedAuth(dsn) {
3420
+ return urlEncode({
3421
+ // We send only the minimum set of required information. See
3422
+ // https://github.com/getsentry/sentry-javascript/issues/2572.
3423
+ sentry_key: dsn.publicKey,
3424
+ sentry_version: SENTRY_API_VERSION,
3425
+ });
3426
+ }
3427
+ /** Returns the store endpoint URL. */
3428
+ function getStoreEndpoint(dsn) {
3429
+ return _getIngestEndpoint(dsn, 'store');
3430
+ }
3468
3431
  /**
3469
- * Helper class to provide urls, headers and metadata that can be used to form
3470
- * different types of requests to Sentry endpoints.
3471
- * Supports both envelopes and regular event requests.
3472
- **/
3473
- class API {
3474
- /** Create a new instance of API */
3475
- constructor(dsn, metadata = {}, tunnel) {
3476
- this.dsn = dsn;
3477
- this._dsnObject = new Dsn(dsn);
3478
- this.metadata = metadata;
3479
- this._tunnel = tunnel;
3480
- }
3481
- /** Returns the Dsn object. */
3482
- getDsn() {
3483
- return this._dsnObject;
3484
- }
3485
- /** Does this transport force envelopes? */
3486
- forceEnvelope() {
3487
- return !!this._tunnel;
3488
- }
3489
- /** Returns the prefix to construct Sentry ingestion API endpoints. */
3490
- getBaseApiEndpoint() {
3491
- const dsn = this.getDsn();
3492
- const protocol = dsn.protocol ? `${dsn.protocol}:` : '';
3493
- const port = dsn.port ? `:${dsn.port}` : '';
3494
- return `${protocol}//${dsn.host}${port}${dsn.path ? `/${dsn.path}` : ''}/api/`;
3495
- }
3496
- /** Returns the store endpoint URL. */
3497
- getStoreEndpoint() {
3498
- return this._getIngestEndpoint('store');
3499
- }
3500
- /**
3501
- * Returns the store endpoint URL with auth in the query string.
3502
- *
3503
- * Sending auth as part of the query string and not as custom HTTP headers avoids CORS preflight requests.
3504
- */
3505
- getStoreEndpointWithUrlEncodedAuth() {
3506
- return `${this.getStoreEndpoint()}?${this._encodedAuth()}`;
3507
- }
3508
- /**
3509
- * Returns the envelope endpoint URL with auth in the query string.
3510
- *
3511
- * Sending auth as part of the query string and not as custom HTTP headers avoids CORS preflight requests.
3512
- */
3513
- getEnvelopeEndpointWithUrlEncodedAuth() {
3514
- if (this.forceEnvelope()) {
3515
- return this._tunnel;
3516
- }
3517
- return `${this._getEnvelopeEndpoint()}?${this._encodedAuth()}`;
3518
- }
3519
- /** Returns only the path component for the store endpoint. */
3520
- getStoreEndpointPath() {
3521
- const dsn = this.getDsn();
3522
- return `${dsn.path ? `/${dsn.path}` : ''}/api/${dsn.projectId}/store/`;
3523
- }
3524
- /**
3525
- * Returns an object that can be used in request headers.
3526
- * This is needed for node and the old /store endpoint in sentry
3527
- */
3528
- getRequestHeaders(clientName, clientVersion) {
3529
- // CHANGE THIS to use metadata but keep clientName and clientVersion compatible
3530
- const dsn = this.getDsn();
3531
- const header = [`Sentry sentry_version=${SENTRY_API_VERSION}`];
3532
- header.push(`sentry_client=${clientName}/${clientVersion}`);
3533
- header.push(`sentry_key=${dsn.publicKey}`);
3534
- if (dsn.pass) {
3535
- header.push(`sentry_secret=${dsn.pass}`);
3432
+ * Returns the store endpoint URL with auth in the query string.
3433
+ *
3434
+ * Sending auth as part of the query string and not as custom HTTP headers avoids CORS preflight requests.
3435
+ */
3436
+ function getStoreEndpointWithUrlEncodedAuth(dsn) {
3437
+ return `${getStoreEndpoint(dsn)}?${_encodedAuth(dsn)}`;
3438
+ }
3439
+ /** Returns the envelope endpoint URL. */
3440
+ function _getEnvelopeEndpoint(dsn) {
3441
+ return _getIngestEndpoint(dsn, 'envelope');
3442
+ }
3443
+ /**
3444
+ * Returns the envelope endpoint URL with auth in the query string.
3445
+ *
3446
+ * Sending auth as part of the query string and not as custom HTTP headers avoids CORS preflight requests.
3447
+ */
3448
+ function getEnvelopeEndpointWithUrlEncodedAuth(dsn, tunnel) {
3449
+ return tunnel ? tunnel : `${_getEnvelopeEndpoint(dsn)}?${_encodedAuth(dsn)}`;
3450
+ }
3451
+ /** Returns the url to the report dialog endpoint. */
3452
+ function getReportDialogEndpoint(dsnLike, dialogOptions) {
3453
+ const dsn = makeDsn(dsnLike);
3454
+ const endpoint = `${getBaseApiEndpoint(dsn)}embed/error-page/`;
3455
+ let encodedOptions = `dsn=${dsnToString(dsn)}`;
3456
+ for (const key in dialogOptions) {
3457
+ if (key === 'dsn') {
3458
+ continue;
3536
3459
  }
3537
- return {
3538
- 'Content-Type': 'application/json',
3539
- 'X-Sentry-Auth': header.join(', '),
3540
- };
3541
- }
3542
- /** Returns the url to the report dialog endpoint. */
3543
- getReportDialogEndpoint(dialogOptions = {}) {
3544
- const dsn = this.getDsn();
3545
- const endpoint = `${this.getBaseApiEndpoint()}embed/error-page/`;
3546
- const encodedOptions = [];
3547
- encodedOptions.push(`dsn=${dsn.toString()}`);
3548
- for (const key in dialogOptions) {
3549
- if (key === 'dsn') {
3460
+ if (key === 'user') {
3461
+ if (!dialogOptions.user) {
3550
3462
  continue;
3551
3463
  }
3552
- if (key === 'user') {
3553
- if (!dialogOptions.user) {
3554
- continue;
3555
- }
3556
- if (dialogOptions.user.name) {
3557
- encodedOptions.push(`name=${encodeURIComponent(dialogOptions.user.name)}`);
3558
- }
3559
- if (dialogOptions.user.email) {
3560
- encodedOptions.push(`email=${encodeURIComponent(dialogOptions.user.email)}`);
3561
- }
3464
+ if (dialogOptions.user.name) {
3465
+ encodedOptions += `&name=${encodeURIComponent(dialogOptions.user.name)}`;
3562
3466
  }
3563
- else {
3564
- encodedOptions.push(`${encodeURIComponent(key)}=${encodeURIComponent(dialogOptions[key])}`);
3467
+ if (dialogOptions.user.email) {
3468
+ encodedOptions += `&email=${encodeURIComponent(dialogOptions.user.email)}`;
3565
3469
  }
3566
3470
  }
3567
- if (encodedOptions.length) {
3568
- return `${endpoint}?${encodedOptions.join('&')}`;
3569
- }
3570
- return endpoint;
3571
- }
3572
- /** Returns the envelope endpoint URL. */
3573
- _getEnvelopeEndpoint() {
3574
- return this._getIngestEndpoint('envelope');
3575
- }
3576
- /** Returns the ingest API endpoint for target. */
3577
- _getIngestEndpoint(target) {
3578
- if (this._tunnel) {
3579
- return this._tunnel;
3471
+ else {
3472
+ encodedOptions += `&${encodeURIComponent(key)}=${encodeURIComponent(dialogOptions[key])}`;
3580
3473
  }
3581
- const base = this.getBaseApiEndpoint();
3582
- const dsn = this.getDsn();
3583
- return `${base}${dsn.projectId}/${target}/`;
3584
- }
3585
- /** Returns a URL-encoded string with auth config suitable for a query string. */
3586
- _encodedAuth() {
3587
- const dsn = this.getDsn();
3588
- const auth = {
3589
- // We send only the minimum set of required information. See
3590
- // https://github.com/getsentry/sentry-javascript/issues/2572.
3591
- sentry_key: dsn.publicKey,
3592
- sentry_version: SENTRY_API_VERSION,
3593
- };
3594
- return urlEncode(auth);
3595
3474
  }
3475
+ return `${endpoint}?${encodedOptions}`;
3596
3476
  }
3597
3477
 
3598
3478
  const installedIntegrations = [];
@@ -3656,7 +3536,7 @@ var Sentry = (function (exports) {
3656
3536
  // set the `initialized` flag so we don't run through the process again unecessarily; use `Object.defineProperty`
3657
3537
  // because by default it creates a property which is nonenumerable, which we want since `initialized` shouldn't be
3658
3538
  // considered a member of the index the way the actual integrations are
3659
- Object.defineProperty(integrations, 'initialized', { value: true });
3539
+ addNonEnumerableProperty(integrations, 'initialized', true);
3660
3540
  return integrations;
3661
3541
  }
3662
3542
 
@@ -3709,7 +3589,7 @@ var Sentry = (function (exports) {
3709
3589
  this._backend = new backendClass(options);
3710
3590
  this._options = options;
3711
3591
  if (options.dsn) {
3712
- this._dsn = new Dsn(options.dsn);
3592
+ this._dsn = makeDsn(options.dsn);
3713
3593
  }
3714
3594
  }
3715
3595
  /**
@@ -3750,9 +3630,8 @@ var Sentry = (function (exports) {
3750
3630
  * @inheritDoc
3751
3631
  */
3752
3632
  captureEvent(event, hint, scope) {
3753
- var _a;
3754
3633
  // ensure we haven't captured this very object before
3755
- if (((_a = hint) === null || _a === void 0 ? void 0 : _a.originalException) && checkOrSetAlreadyCaught(hint.originalException)) {
3634
+ if (hint && hint.originalException && checkOrSetAlreadyCaught(hint.originalException)) {
3756
3635
  logger.log(ALREADY_SEEN_ERROR);
3757
3636
  return;
3758
3637
  }
@@ -3767,11 +3646,15 @@ var Sentry = (function (exports) {
3767
3646
  */
3768
3647
  captureSession(session) {
3769
3648
  if (!this._isEnabled()) {
3770
- logger.warn('SDK not enabled, will not capture session.');
3649
+ if (isDebugBuild()) {
3650
+ logger.warn('SDK not enabled, will not capture session.');
3651
+ }
3771
3652
  return;
3772
3653
  }
3773
3654
  if (!(typeof session.release === 'string')) {
3774
- logger.warn('Discarded session because of missing or non-string release');
3655
+ if (isDebugBuild()) {
3656
+ logger.warn('Discarded session because of missing or non-string release');
3657
+ }
3775
3658
  }
3776
3659
  else {
3777
3660
  this._sendSession(session);
@@ -3854,10 +3737,10 @@ var Sentry = (function (exports) {
3854
3737
  // A session is updated and that session update is sent in only one of the two following scenarios:
3855
3738
  // 1. Session with non terminal status and 0 errors + an error occurred -> Will set error count to 1 and send update
3856
3739
  // 2. Session with non terminal status and 1 error + a crash occurred -> Will set status crashed and send update
3857
- const sessionNonTerminal = session.status === SessionStatus.Ok;
3740
+ const sessionNonTerminal = session.status === 'ok';
3858
3741
  const shouldUpdateAndSend = (sessionNonTerminal && session.errors === 0) || (sessionNonTerminal && crashed);
3859
3742
  if (shouldUpdateAndSend) {
3860
- session.update(Object.assign(Object.assign({}, (crashed && { status: SessionStatus.Crashed })), { errors: session.errors || Number(errored || crashed) }));
3743
+ session.update(Object.assign(Object.assign({}, (crashed && { status: 'crashed' })), { errors: session.errors || Number(errored || crashed) }));
3861
3744
  this.captureSession(session);
3862
3745
  }
3863
3746
  }
@@ -3928,7 +3811,7 @@ var Sentry = (function (exports) {
3928
3811
  finalScope = Scope.clone(finalScope).update(hint.captureContext);
3929
3812
  }
3930
3813
  // We prepare the result here with a resolved Event.
3931
- let result = SyncPromise.resolve(prepared);
3814
+ let result = resolvedSyncPromise(prepared);
3932
3815
  // This should be the last thing called, since we want that
3933
3816
  // {@link Hub.addEventProcessor} gets the finished prepared event.
3934
3817
  if (finalScope) {
@@ -3978,10 +3861,7 @@ var Sentry = (function (exports) {
3978
3861
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
3979
3862
  normalized.contexts.trace = event.contexts.trace;
3980
3863
  }
3981
- const { _experiments = {} } = this.getOptions();
3982
- if (_experiments.ensureNoCircularStructures) {
3983
- return normalize(normalized);
3984
- }
3864
+ event.sdkProcessingMetadata = Object.assign(Object.assign({}, event.sdkProcessingMetadata), { baseClientNormalized: true });
3985
3865
  return normalized;
3986
3866
  }
3987
3867
  /**
@@ -4060,26 +3940,29 @@ var Sentry = (function (exports) {
4060
3940
  * @returns A SyncPromise that resolves with the event or rejects in case event was/will not be send.
4061
3941
  */
4062
3942
  _processEvent(event, hint, scope) {
4063
- var _a, _b;
4064
3943
  // eslint-disable-next-line @typescript-eslint/unbound-method
4065
3944
  const { beforeSend, sampleRate } = this.getOptions();
4066
3945
  const transport = this.getTransport();
3946
+ function recordLostEvent(outcome, category) {
3947
+ if (transport.recordLostEvent) {
3948
+ transport.recordLostEvent(outcome, category);
3949
+ }
3950
+ }
4067
3951
  if (!this._isEnabled()) {
4068
- return SyncPromise.reject(new SentryError('SDK not enabled, will not capture event.'));
3952
+ return rejectedSyncPromise(new SentryError('SDK not enabled, will not capture event.'));
4069
3953
  }
4070
3954
  const isTransaction = event.type === 'transaction';
4071
3955
  // 1.0 === 100% events are sent
4072
3956
  // 0.0 === 0% events are sent
4073
3957
  // Sampling for transaction happens somewhere else
4074
3958
  if (!isTransaction && typeof sampleRate === 'number' && Math.random() > sampleRate) {
4075
- (_b = (_a = transport).recordLostEvent) === null || _b === void 0 ? void 0 : _b.call(_a, Outcome.SampleRate, 'event');
4076
- return SyncPromise.reject(new SentryError(`Discarding event because it's not included in the random sample (sampling rate = ${sampleRate})`));
3959
+ recordLostEvent('sample_rate', 'event');
3960
+ return rejectedSyncPromise(new SentryError(`Discarding event because it's not included in the random sample (sampling rate = ${sampleRate})`));
4077
3961
  }
4078
3962
  return this._prepareEvent(event, scope, hint)
4079
3963
  .then(prepared => {
4080
- var _a, _b;
4081
3964
  if (prepared === null) {
4082
- (_b = (_a = transport).recordLostEvent) === null || _b === void 0 ? void 0 : _b.call(_a, Outcome.EventProcessor, event.type || 'event');
3965
+ recordLostEvent('event_processor', event.type || 'event');
4083
3966
  throw new SentryError('An event processor returned null, will not send event.');
4084
3967
  }
4085
3968
  const isInternalException = hint && hint.data && hint.data.__sentry__ === true;
@@ -4087,12 +3970,11 @@ var Sentry = (function (exports) {
4087
3970
  return prepared;
4088
3971
  }
4089
3972
  const beforeSendResult = beforeSend(prepared, hint);
4090
- return this._ensureBeforeSendRv(beforeSendResult);
3973
+ return _ensureBeforeSendRv(beforeSendResult);
4091
3974
  })
4092
3975
  .then(processedEvent => {
4093
- var _a, _b;
4094
3976
  if (processedEvent === null) {
4095
- (_b = (_a = transport).recordLostEvent) === null || _b === void 0 ? void 0 : _b.call(_a, Outcome.BeforeSend, event.type || 'event');
3977
+ recordLostEvent('before_send', event.type || 'event');
4096
3978
  throw new SentryError('`beforeSend` returned `null`, will not send event.');
4097
3979
  }
4098
3980
  const session = scope && scope.getSession && scope.getSession();
@@ -4128,26 +4010,26 @@ var Sentry = (function (exports) {
4128
4010
  return reason;
4129
4011
  });
4130
4012
  }
4131
- /**
4132
- * Verifies that return value of configured `beforeSend` is of expected type.
4133
- */
4134
- _ensureBeforeSendRv(rv) {
4135
- const nullErr = '`beforeSend` method has to return `null` or a valid event.';
4136
- if (isThenable(rv)) {
4137
- return rv.then(event => {
4138
- if (!(isPlainObject(event) || event === null)) {
4139
- throw new SentryError(nullErr);
4140
- }
4141
- return event;
4142
- }, e => {
4143
- throw new SentryError(`beforeSend rejected with ${e}`);
4144
- });
4145
- }
4146
- else if (!(isPlainObject(rv) || rv === null)) {
4147
- throw new SentryError(nullErr);
4148
- }
4149
- return rv;
4013
+ }
4014
+ /**
4015
+ * Verifies that return value of configured `beforeSend` is of expected type.
4016
+ */
4017
+ function _ensureBeforeSendRv(rv) {
4018
+ const nullErr = '`beforeSend` method has to return `null` or a valid event.';
4019
+ if (isThenable(rv)) {
4020
+ return rv.then(event => {
4021
+ if (!(isPlainObject(event) || event === null)) {
4022
+ throw new SentryError(nullErr);
4023
+ }
4024
+ return event;
4025
+ }, e => {
4026
+ throw new SentryError(`beforeSend rejected with ${e}`);
4027
+ });
4028
+ }
4029
+ else if (!(isPlainObject(rv) || rv === null)) {
4030
+ throw new SentryError(nullErr);
4150
4031
  }
4032
+ return rv;
4151
4033
  }
4152
4034
 
4153
4035
  /** Noop transport */
@@ -4156,16 +4038,16 @@ var Sentry = (function (exports) {
4156
4038
  * @inheritDoc
4157
4039
  */
4158
4040
  sendEvent(_) {
4159
- return SyncPromise.resolve({
4041
+ return resolvedSyncPromise({
4160
4042
  reason: `NoopTransport: Event has been skipped because no Dsn is configured.`,
4161
- status: exports.Status.Skipped,
4043
+ status: 'skipped',
4162
4044
  });
4163
4045
  }
4164
4046
  /**
4165
4047
  * @inheritDoc
4166
4048
  */
4167
4049
  close(_) {
4168
- return SyncPromise.resolve(true);
4050
+ return resolvedSyncPromise(true);
4169
4051
  }
4170
4052
  }
4171
4053
 
@@ -4200,7 +4082,9 @@ var Sentry = (function (exports) {
4200
4082
  */
4201
4083
  sendEvent(event) {
4202
4084
  void this._transport.sendEvent(event).then(null, reason => {
4203
- logger.error(`Error while sending event: ${reason}`);
4085
+ if (isDebugBuild()) {
4086
+ logger.error(`Error while sending event: ${reason}`);
4087
+ }
4204
4088
  });
4205
4089
  }
4206
4090
  /**
@@ -4208,11 +4092,15 @@ var Sentry = (function (exports) {
4208
4092
  */
4209
4093
  sendSession(session) {
4210
4094
  if (!this._transport.sendSession) {
4211
- logger.warn("Dropping session because custom transport doesn't implement sendSession");
4095
+ if (isDebugBuild()) {
4096
+ logger.warn("Dropping session because custom transport doesn't implement sendSession");
4097
+ }
4212
4098
  return;
4213
4099
  }
4214
4100
  void this._transport.sendSession(session).then(null, reason => {
4215
- logger.error(`Error while sending session: ${reason}`);
4101
+ if (isDebugBuild()) {
4102
+ logger.error(`Error while sending session: ${reason}`);
4103
+ }
4216
4104
  });
4217
4105
  }
4218
4106
  /**
@@ -4229,31 +4117,6 @@ var Sentry = (function (exports) {
4229
4117
  }
4230
4118
  }
4231
4119
 
4232
- /*! *****************************************************************************
4233
- Copyright (c) Microsoft Corporation. All rights reserved.
4234
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4235
- this file except in compliance with the License. You may obtain a copy of the
4236
- License at http://www.apache.org/licenses/LICENSE-2.0
4237
-
4238
- THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
4239
- KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
4240
- WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
4241
- MERCHANTABLITY OR NON-INFRINGEMENT.
4242
-
4243
- See the Apache Version 2.0 License for specific language governing permissions
4244
- and limitations under the License.
4245
- ***************************************************************************** */
4246
-
4247
- function __rest(s, e) {
4248
- var t = {};
4249
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4250
- t[p] = s[p];
4251
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
4252
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
4253
- t[p[i]] = s[p[i]];
4254
- return t;
4255
- }
4256
-
4257
4120
  /** Extract sdk info from from the API metadata */
4258
4121
  function getSdkMetadataForEnvelopeHeader(api) {
4259
4122
  if (!api.metadata || !api.metadata.sdk) {
@@ -4280,7 +4143,7 @@ var Sentry = (function (exports) {
4280
4143
  /** Creates a SentryRequest from a Session. */
4281
4144
  function sessionToSentryRequest(session, api) {
4282
4145
  const sdkInfo = getSdkMetadataForEnvelopeHeader(api);
4283
- const envelopeHeaders = JSON.stringify(Object.assign(Object.assign({ sent_at: new Date().toISOString() }, (sdkInfo && { sdk: sdkInfo })), (api.forceEnvelope() && { dsn: api.getDsn().toString() })));
4146
+ const envelopeHeaders = JSON.stringify(Object.assign(Object.assign({ sent_at: new Date().toISOString() }, (sdkInfo && { sdk: sdkInfo })), (!!api.tunnel && { dsn: dsnToString(api.dsn) })));
4284
4147
  // I know this is hacky but we don't want to add `session` to request type since it's never rate limited
4285
4148
  const type = 'aggregates' in session ? 'sessions' : 'session';
4286
4149
  const itemHeaders = JSON.stringify({
@@ -4289,26 +4152,70 @@ var Sentry = (function (exports) {
4289
4152
  return {
4290
4153
  body: `${envelopeHeaders}\n${itemHeaders}\n${JSON.stringify(session)}`,
4291
4154
  type,
4292
- url: api.getEnvelopeEndpointWithUrlEncodedAuth(),
4155
+ url: getEnvelopeEndpointWithUrlEncodedAuth(api.dsn, api.tunnel),
4293
4156
  };
4294
4157
  }
4295
4158
  /** Creates a SentryRequest from an event. */
4296
4159
  function eventToSentryRequest(event, api) {
4297
4160
  const sdkInfo = getSdkMetadataForEnvelopeHeader(api);
4298
4161
  const eventType = event.type || 'event';
4299
- const useEnvelope = eventType === 'transaction' || api.forceEnvelope();
4300
- const _a = event.debug_meta || {}, { transactionSampling } = _a, metadata = __rest(_a, ["transactionSampling"]);
4162
+ const useEnvelope = eventType === 'transaction' || !!api.tunnel;
4163
+ const { transactionSampling } = event.sdkProcessingMetadata || {};
4301
4164
  const { method: samplingMethod, rate: sampleRate } = transactionSampling || {};
4302
- if (Object.keys(metadata).length === 0) {
4303
- delete event.debug_meta;
4165
+ // TODO: Below is a temporary hack in order to debug a serialization error - see
4166
+ // https://github.com/getsentry/sentry-javascript/issues/2809 and
4167
+ // https://github.com/getsentry/sentry-javascript/pull/4425. TL;DR: even though we normalize all events (which should
4168
+ // prevent this), something is causing `JSON.stringify` to throw a circular reference error.
4169
+ //
4170
+ // When it's time to remove it:
4171
+ // 1. Delete everything between here and where the request object `req` is created, EXCEPT the line deleting
4172
+ // `sdkProcessingMetadata`
4173
+ // 2. Restore the original version of the request body, which is commented out
4174
+ // 3. Search for `skippedNormalization` and pull out the companion hack in the browser playwright tests
4175
+ enhanceEventWithSdkInfo(event, api.metadata.sdk);
4176
+ event.tags = event.tags || {};
4177
+ event.extra = event.extra || {};
4178
+ // In theory, all events should be marked as having gone through normalization and so
4179
+ // we should never set this tag
4180
+ if (!(event.sdkProcessingMetadata && event.sdkProcessingMetadata.baseClientNormalized)) {
4181
+ event.tags.skippedNormalization = true;
4182
+ }
4183
+ // prevent this data from being sent to sentry
4184
+ // TODO: This is NOT part of the hack - DO NOT DELETE
4185
+ delete event.sdkProcessingMetadata;
4186
+ let body;
4187
+ try {
4188
+ // 99.9% of events should get through just fine - no change in behavior for them
4189
+ body = JSON.stringify(event);
4304
4190
  }
4305
- else {
4306
- event.debug_meta = metadata;
4191
+ catch (err) {
4192
+ // Record data about the error without replacing original event data, then force renormalization
4193
+ event.tags.JSONStringifyError = true;
4194
+ event.extra.JSONStringifyError = err;
4195
+ try {
4196
+ body = JSON.stringify(normalize(event));
4197
+ }
4198
+ catch (newErr) {
4199
+ // At this point even renormalization hasn't worked, meaning something about the event data has gone very wrong.
4200
+ // Time to cut our losses and record only the new error. With luck, even in the problematic cases we're trying to
4201
+ // debug with this hack, we won't ever land here.
4202
+ const innerErr = newErr;
4203
+ body = JSON.stringify({
4204
+ message: 'JSON.stringify error after renormalization',
4205
+ // setting `extra: { innerErr }` here for some reason results in an empty object, so unpack manually
4206
+ extra: { message: innerErr.message, stack: innerErr.stack },
4207
+ });
4208
+ }
4307
4209
  }
4308
4210
  const req = {
4309
- body: JSON.stringify(sdkInfo ? enhanceEventWithSdkInfo(event, api.metadata.sdk) : event),
4211
+ // this is the relevant line of code before the hack was added, to make it easy to undo said hack once we've solved
4212
+ // the mystery
4213
+ // body: JSON.stringify(sdkInfo ? enhanceEventWithSdkInfo(event, api.metadata.sdk) : event),
4214
+ body,
4310
4215
  type: eventType,
4311
- url: useEnvelope ? api.getEnvelopeEndpointWithUrlEncodedAuth() : api.getStoreEndpointWithUrlEncodedAuth(),
4216
+ url: useEnvelope
4217
+ ? getEnvelopeEndpointWithUrlEncodedAuth(api.dsn, api.tunnel)
4218
+ : getStoreEndpointWithUrlEncodedAuth(api.dsn),
4312
4219
  };
4313
4220
  // https://develop.sentry.dev/sdk/envelopes/
4314
4221
  // Since we don't need to manipulate envelopes nor store them, there is no
@@ -4316,7 +4223,7 @@ var Sentry = (function (exports) {
4316
4223
  // deserialization. Instead, we only implement a minimal subset of the spec to
4317
4224
  // serialize events inline here.
4318
4225
  if (useEnvelope) {
4319
- const envelopeHeaders = JSON.stringify(Object.assign(Object.assign({ event_id: event.event_id, sent_at: new Date().toISOString() }, (sdkInfo && { sdk: sdkInfo })), (api.forceEnvelope() && { dsn: api.getDsn().toString() })));
4226
+ const envelopeHeaders = JSON.stringify(Object.assign(Object.assign({ event_id: event.event_id, sent_at: new Date().toISOString() }, (sdkInfo && { sdk: sdkInfo })), (!!api.tunnel && { dsn: dsnToString(api.dsn) })));
4320
4227
  const itemHeaders = JSON.stringify({
4321
4228
  type: eventType,
4322
4229
  // TODO: Right now, sampleRate may or may not be defined (it won't be in the cases of inheritance and
@@ -4341,17 +4248,19 @@ var Sentry = (function (exports) {
4341
4248
  * @param options Options to pass to the client.
4342
4249
  */
4343
4250
  function initAndBind(clientClass, options) {
4344
- var _a;
4345
4251
  if (options.debug === true) {
4346
4252
  logger.enable();
4347
4253
  }
4348
4254
  const hub = getCurrentHub();
4349
- (_a = hub.getScope()) === null || _a === void 0 ? void 0 : _a.update(options.initialScope);
4255
+ const scope = hub.getScope();
4256
+ if (scope) {
4257
+ scope.update(options.initialScope);
4258
+ }
4350
4259
  const client = new clientClass(options);
4351
4260
  hub.bindClient(client);
4352
4261
  }
4353
4262
 
4354
- const SDK_VERSION = '6.16.1';
4263
+ const SDK_VERSION = '6.17.2';
4355
4264
 
4356
4265
  let originalFunctionToString;
4357
4266
  /** Patch toString calls to return proper name for wrapped functions */
@@ -4370,7 +4279,7 @@ var Sentry = (function (exports) {
4370
4279
  originalFunctionToString = Function.prototype.toString;
4371
4280
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4372
4281
  Function.prototype.toString = function (...args) {
4373
- const context = this.__sentry_original__ || this;
4282
+ const context = getOriginalFunction(this) || this;
4374
4283
  return originalFunctionToString.apply(context, args);
4375
4284
  };
4376
4285
  }
@@ -4422,19 +4331,27 @@ var Sentry = (function (exports) {
4422
4331
  /** JSDoc */
4423
4332
  _shouldDropEvent(event, options) {
4424
4333
  if (this._isSentryError(event, options)) {
4425
- logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`);
4334
+ if (isDebugBuild()) {
4335
+ logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`);
4336
+ }
4426
4337
  return true;
4427
4338
  }
4428
4339
  if (this._isIgnoredError(event, options)) {
4429
- logger.warn(`Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`);
4340
+ if (isDebugBuild()) {
4341
+ logger.warn(`Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`);
4342
+ }
4430
4343
  return true;
4431
4344
  }
4432
4345
  if (this._isDeniedUrl(event, options)) {
4433
- logger.warn(`Event dropped due to being matched by \`denyUrls\` option.\nEvent: ${getEventDescription(event)}.\nUrl: ${this._getEventFilterUrl(event)}`);
4346
+ if (isDebugBuild()) {
4347
+ logger.warn(`Event dropped due to being matched by \`denyUrls\` option.\nEvent: ${getEventDescription(event)}.\nUrl: ${this._getEventFilterUrl(event)}`);
4348
+ }
4434
4349
  return true;
4435
4350
  }
4436
4351
  if (!this._isAllowedUrl(event, options)) {
4437
- logger.warn(`Event dropped due to not being matched by \`allowUrls\` option.\nEvent: ${getEventDescription(event)}.\nUrl: ${this._getEventFilterUrl(event)}`);
4352
+ if (isDebugBuild()) {
4353
+ logger.warn(`Event dropped due to not being matched by \`allowUrls\` option.\nEvent: ${getEventDescription(event)}.\nUrl: ${this._getEventFilterUrl(event)}`);
4354
+ }
4438
4355
  return true;
4439
4356
  }
4440
4357
  return false;
@@ -4445,16 +4362,14 @@ var Sentry = (function (exports) {
4445
4362
  return false;
4446
4363
  }
4447
4364
  try {
4448
- return ((event &&
4449
- event.exception &&
4450
- event.exception.values &&
4451
- event.exception.values[0] &&
4452
- event.exception.values[0].type === 'SentryError') ||
4453
- false);
4365
+ // @ts-ignore can't be a sentry error if undefined
4366
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
4367
+ return event.exception.values[0].type === 'SentryError';
4454
4368
  }
4455
- catch (_oO) {
4456
- return false;
4369
+ catch (e) {
4370
+ // ignore
4457
4371
  }
4372
+ return false;
4458
4373
  }
4459
4374
  /** JSDoc */
4460
4375
  _isIgnoredError(event, options) {
@@ -4521,7 +4436,9 @@ var Sentry = (function (exports) {
4521
4436
  return [`${value}`, `${type}: ${value}`];
4522
4437
  }
4523
4438
  catch (oO) {
4524
- logger.error(`Cannot extract message for event ${getEventDescription(event)}`);
4439
+ if (isDebugBuild()) {
4440
+ logger.error(`Cannot extract message for event ${getEventDescription(event)}`);
4441
+ }
4525
4442
  return [];
4526
4443
  }
4527
4444
  }
@@ -4529,10 +4446,9 @@ var Sentry = (function (exports) {
4529
4446
  }
4530
4447
  /** JSDoc */
4531
4448
  _getLastValidUrl(frames = []) {
4532
- var _a, _b;
4533
4449
  for (let i = frames.length - 1; i >= 0; i--) {
4534
4450
  const frame = frames[i];
4535
- if (((_a = frame) === null || _a === void 0 ? void 0 : _a.filename) !== '<anonymous>' && ((_b = frame) === null || _b === void 0 ? void 0 : _b.filename) !== '[native code]') {
4451
+ if (frame && frame.filename !== '<anonymous>' && frame.filename !== '[native code]') {
4536
4452
  return frame.filename || null;
4537
4453
  }
4538
4454
  }
@@ -4542,17 +4458,22 @@ var Sentry = (function (exports) {
4542
4458
  _getEventFilterUrl(event) {
4543
4459
  try {
4544
4460
  if (event.stacktrace) {
4545
- const frames = event.stacktrace.frames;
4546
- return this._getLastValidUrl(frames);
4461
+ return this._getLastValidUrl(event.stacktrace.frames);
4462
+ }
4463
+ let frames;
4464
+ try {
4465
+ // @ts-ignore we only care about frames if the whole thing here is defined
4466
+ frames = event.exception.values[0].stacktrace.frames;
4547
4467
  }
4548
- if (event.exception) {
4549
- const frames = event.exception.values && event.exception.values[0].stacktrace && event.exception.values[0].stacktrace.frames;
4550
- return this._getLastValidUrl(frames);
4468
+ catch (e) {
4469
+ // ignore
4551
4470
  }
4552
- return null;
4471
+ return frames ? this._getLastValidUrl(frames) : null;
4553
4472
  }
4554
4473
  catch (oO) {
4555
- logger.error(`Cannot extract url for event ${getEventDescription(event)}`);
4474
+ if (isDebugBuild()) {
4475
+ logger.error(`Cannot extract url for event ${getEventDescription(event)}`);
4476
+ }
4556
4477
  return null;
4557
4478
  }
4558
4479
  }
@@ -4914,7 +4835,7 @@ var Sentry = (function (exports) {
4914
4835
  }
4915
4836
 
4916
4837
  /**
4917
- * Builds and Event from a Exception
4838
+ * Creates an {@link Event} from all inputs to `captureException` and non-primitive inputs to `captureMessage`.
4918
4839
  * @hidden
4919
4840
  */
4920
4841
  function eventFromException(options, exception, hint) {
@@ -4927,7 +4848,7 @@ var Sentry = (function (exports) {
4927
4848
  if (hint && hint.event_id) {
4928
4849
  event.event_id = hint.event_id;
4929
4850
  }
4930
- return SyncPromise.resolve(event);
4851
+ return resolvedSyncPromise(event);
4931
4852
  }
4932
4853
  /**
4933
4854
  * Builds and Event from a Message
@@ -4942,7 +4863,7 @@ var Sentry = (function (exports) {
4942
4863
  if (hint && hint.event_id) {
4943
4864
  event.event_id = hint.event_id;
4944
4865
  }
4945
- return SyncPromise.resolve(event);
4866
+ return resolvedSyncPromise(event);
4946
4867
  }
4947
4868
  /**
4948
4869
  * @hidden
@@ -4986,11 +4907,11 @@ var Sentry = (function (exports) {
4986
4907
  return event;
4987
4908
  }
4988
4909
  if (isPlainObject(exception) || isEvent(exception)) {
4989
- // If it is plain Object or Event, serialize it manually and extract options
4990
- // This will allow us to group events based on top-level keys
4991
- // which is much better than creating new group when any key/value change
4910
+ // If it's a plain object or an instance of `Event` (the built-in JS kind, not this SDK's `Event` type), serialize
4911
+ // it manually. This will allow us to group events based on top-level keys which is much better than creating a new
4912
+ // group on any key/value change.
4992
4913
  const objectException = exception;
4993
- event = eventFromPlainObject(objectException, syntheticException, options.rejection);
4914
+ event = eventFromPlainObject(objectException, syntheticException, options.isRejection);
4994
4915
  addExceptionMechanism(event, {
4995
4916
  synthetic: true,
4996
4917
  });
@@ -5070,7 +4991,6 @@ var Sentry = (function (exports) {
5070
4991
  * Safari: resource blocked by content blocker
5071
4992
  */
5072
4993
  function getNativeFetchImplementation() {
5073
- var _a, _b;
5074
4994
  if (cachedFetchImpl) {
5075
4995
  return cachedFetchImpl;
5076
4996
  }
@@ -5082,18 +5002,21 @@ var Sentry = (function (exports) {
5082
5002
  const document = global$3.document;
5083
5003
  let fetchImpl = global$3.fetch;
5084
5004
  // eslint-disable-next-line deprecation/deprecation
5085
- if (typeof ((_a = document) === null || _a === void 0 ? void 0 : _a.createElement) === `function`) {
5005
+ if (document && typeof document.createElement === `function`) {
5086
5006
  try {
5087
5007
  const sandbox = document.createElement('iframe');
5088
5008
  sandbox.hidden = true;
5089
5009
  document.head.appendChild(sandbox);
5090
- if ((_b = sandbox.contentWindow) === null || _b === void 0 ? void 0 : _b.fetch) {
5091
- fetchImpl = sandbox.contentWindow.fetch;
5010
+ const contentWindow = sandbox.contentWindow;
5011
+ if (contentWindow && contentWindow.fetch) {
5012
+ fetchImpl = contentWindow.fetch;
5092
5013
  }
5093
5014
  document.head.removeChild(sandbox);
5094
5015
  }
5095
5016
  catch (e) {
5096
- logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', e);
5017
+ if (isDebugBuild()) {
5018
+ logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', e);
5019
+ }
5097
5020
  }
5098
5021
  }
5099
5022
  return (cachedFetchImpl = fetchImpl.bind(global$3));
@@ -5124,25 +5047,23 @@ var Sentry = (function (exports) {
5124
5047
  }
5125
5048
  }
5126
5049
 
5127
- const CATEGORY_MAPPING = {
5128
- event: 'error',
5129
- transaction: 'transaction',
5130
- session: 'session',
5131
- attachment: 'attachment',
5132
- };
5050
+ function requestTypeToCategory(ty) {
5051
+ const tyStr = ty;
5052
+ return tyStr === 'event' ? 'error' : tyStr;
5053
+ }
5133
5054
  const global$4 = getGlobalObject();
5134
5055
  /** Base Transport class implementation */
5135
5056
  class BaseTransport {
5136
5057
  constructor(options) {
5137
5058
  this.options = options;
5138
5059
  /** A simple buffer holding all requests. */
5139
- this._buffer = new PromiseBuffer(30);
5060
+ this._buffer = makePromiseBuffer(30);
5140
5061
  /** Locks transport after receiving rate limits in a response */
5141
5062
  this._rateLimits = {};
5142
5063
  this._outcomes = {};
5143
- this._api = new API(options.dsn, options._metadata, options.tunnel);
5064
+ this._api = initAPIDetails(options.dsn, options._metadata, options.tunnel);
5144
5065
  // eslint-disable-next-line deprecation/deprecation
5145
- this.url = this._api.getStoreEndpointWithUrlEncodedAuth();
5066
+ this.url = getStoreEndpointWithUrlEncodedAuth(this._api.dsn);
5146
5067
  if (this.options.sendClientReports && global$4.document) {
5147
5068
  global$4.document.addEventListener('visibilitychange', () => {
5148
5069
  if (global$4.document.visibilityState === 'hidden') {
@@ -5154,8 +5075,14 @@ var Sentry = (function (exports) {
5154
5075
  /**
5155
5076
  * @inheritDoc
5156
5077
  */
5157
- sendEvent(_) {
5158
- throw new SentryError('Transport Class has to implement `sendEvent` method');
5078
+ sendEvent(event) {
5079
+ return this._sendRequest(eventToSentryRequest(event, this._api), event);
5080
+ }
5081
+ /**
5082
+ * @inheritDoc
5083
+ */
5084
+ sendSession(session) {
5085
+ return this._sendRequest(sessionToSentryRequest(session, this._api), session);
5159
5086
  }
5160
5087
  /**
5161
5088
  * @inheritDoc
@@ -5176,7 +5103,7 @@ var Sentry = (function (exports) {
5176
5103
  // We could use nested maps, but it's much easier to read and type this way.
5177
5104
  // A correct type for map-based implementation if we want to go that route
5178
5105
  // would be `Partial<Record<SentryRequestType, Partial<Record<Outcome, number>>>>`
5179
- const key = `${CATEGORY_MAPPING[category]}:${reason}`;
5106
+ const key = `${requestTypeToCategory(category)}:${reason}`;
5180
5107
  logger.log(`Adding outcome: ${key}`);
5181
5108
  this._outcomes[key] = (_a = this._outcomes[key], (_a !== null && _a !== void 0 ? _a : 0)) + 1;
5182
5109
  }
@@ -5195,9 +5122,9 @@ var Sentry = (function (exports) {
5195
5122
  return;
5196
5123
  }
5197
5124
  logger.log(`Flushing outcomes:\n${JSON.stringify(outcomes, null, 2)}`);
5198
- const url = this._api.getEnvelopeEndpointWithUrlEncodedAuth();
5125
+ const url = getEnvelopeEndpointWithUrlEncodedAuth(this._api.dsn, this._api.tunnel);
5199
5126
  // Envelope header is required to be at least an empty object
5200
- const envelopeHeader = JSON.stringify(Object.assign({}, (this.options.tunnel && { dsn: this._api.getDsn().toString() })));
5127
+ const envelopeHeader = JSON.stringify(Object.assign({}, (this._api.tunnel && { dsn: dsnToString(this._api.dsn) })));
5201
5128
  const itemHeaders = JSON.stringify({
5202
5129
  type: 'client_report',
5203
5130
  });
@@ -5224,15 +5151,16 @@ var Sentry = (function (exports) {
5224
5151
  * Handle Sentry repsonse for promise-based transports.
5225
5152
  */
5226
5153
  _handleResponse({ requestType, response, headers, resolve, reject, }) {
5227
- const status = exports.Status.fromHttpCode(response.status);
5154
+ const status = eventStatusFromHttpCode(response.status);
5228
5155
  /**
5229
5156
  * "The name is case-insensitive."
5230
5157
  * https://developer.mozilla.org/en-US/docs/Web/API/Headers/get
5231
5158
  */
5232
5159
  const limited = this._handleRateLimit(headers);
5233
- if (limited)
5160
+ if (limited && isDebugBuild()) {
5234
5161
  logger.warn(`Too many ${requestType} requests, backing off until: ${this._disabledUntil(requestType)}`);
5235
- if (status === exports.Status.Success) {
5162
+ }
5163
+ if (status === 'success') {
5236
5164
  resolve({ status });
5237
5165
  return;
5238
5166
  }
@@ -5242,7 +5170,7 @@ var Sentry = (function (exports) {
5242
5170
  * Gets the time that given category is disabled until for rate limiting
5243
5171
  */
5244
5172
  _disabledUntil(requestType) {
5245
- const category = CATEGORY_MAPPING[requestType];
5173
+ const category = requestTypeToCategory(requestType);
5246
5174
  return this._rateLimits[category] || this._rateLimits.all;
5247
5175
  }
5248
5176
  /**
@@ -5293,25 +5221,13 @@ var Sentry = (function (exports) {
5293
5221
  super(options);
5294
5222
  this._fetch = fetchImpl;
5295
5223
  }
5296
- /**
5297
- * @inheritDoc
5298
- */
5299
- sendEvent(event) {
5300
- return this._sendRequest(eventToSentryRequest(event, this._api), event);
5301
- }
5302
- /**
5303
- * @inheritDoc
5304
- */
5305
- sendSession(session) {
5306
- return this._sendRequest(sessionToSentryRequest(session, this._api), session);
5307
- }
5308
5224
  /**
5309
5225
  * @param sentryRequest Prepared SentryRequest to be delivered
5310
5226
  * @param originalPayload Original payload used to create SentryRequest
5311
5227
  */
5312
5228
  _sendRequest(sentryRequest, originalPayload) {
5313
5229
  if (this._isRateLimited(sentryRequest.type)) {
5314
- this.recordLostEvent(Outcome.RateLimitBackoff, sentryRequest.type);
5230
+ this.recordLostEvent('ratelimit_backoff', sentryRequest.type);
5315
5231
  return Promise.reject({
5316
5232
  event: originalPayload,
5317
5233
  type: sentryRequest.type,
@@ -5322,9 +5238,9 @@ var Sentry = (function (exports) {
5322
5238
  const options = {
5323
5239
  body: sentryRequest.body,
5324
5240
  method: 'POST',
5325
- // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default
5326
- // https://caniuse.com/#feat=referrer-policy
5327
- // It doesn't. And it throw exception instead of ignoring this parameter...
5241
+ // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default'
5242
+ // (see https://caniuse.com/#feat=referrer-policy),
5243
+ // it doesn't. And it throws an exception instead of ignoring this parameter...
5328
5244
  // REF: https://github.com/getsentry/raven-js/issues/1233
5329
5245
  referrerPolicy: (supportsReferrerPolicy() ? 'origin' : ''),
5330
5246
  };
@@ -5355,10 +5271,10 @@ var Sentry = (function (exports) {
5355
5271
  .then(undefined, reason => {
5356
5272
  // It's either buffer rejection or any other xhr/fetch error, which are treated as NetworkError.
5357
5273
  if (reason instanceof SentryError) {
5358
- this.recordLostEvent(Outcome.QueueOverflow, sentryRequest.type);
5274
+ this.recordLostEvent('queue_overflow', sentryRequest.type);
5359
5275
  }
5360
5276
  else {
5361
- this.recordLostEvent(Outcome.NetworkError, sentryRequest.type);
5277
+ this.recordLostEvent('network_error', sentryRequest.type);
5362
5278
  }
5363
5279
  throw reason;
5364
5280
  });
@@ -5367,25 +5283,13 @@ var Sentry = (function (exports) {
5367
5283
 
5368
5284
  /** `XHR` based transport */
5369
5285
  class XHRTransport extends BaseTransport {
5370
- /**
5371
- * @inheritDoc
5372
- */
5373
- sendEvent(event) {
5374
- return this._sendRequest(eventToSentryRequest(event, this._api), event);
5375
- }
5376
- /**
5377
- * @inheritDoc
5378
- */
5379
- sendSession(session) {
5380
- return this._sendRequest(sessionToSentryRequest(session, this._api), session);
5381
- }
5382
5286
  /**
5383
5287
  * @param sentryRequest Prepared SentryRequest to be delivered
5384
5288
  * @param originalPayload Original payload used to create SentryRequest
5385
5289
  */
5386
5290
  _sendRequest(sentryRequest, originalPayload) {
5387
5291
  if (this._isRateLimited(sentryRequest.type)) {
5388
- this.recordLostEvent(Outcome.RateLimitBackoff, sentryRequest.type);
5292
+ this.recordLostEvent('ratelimit_backoff', sentryRequest.type);
5389
5293
  return Promise.reject({
5390
5294
  event: originalPayload,
5391
5295
  type: sentryRequest.type,
@@ -5416,10 +5320,10 @@ var Sentry = (function (exports) {
5416
5320
  .then(undefined, reason => {
5417
5321
  // It's either buffer rejection or any other xhr/fetch error, which are treated as NetworkError.
5418
5322
  if (reason instanceof SentryError) {
5419
- this.recordLostEvent(Outcome.QueueOverflow, sentryRequest.type);
5323
+ this.recordLostEvent('queue_overflow', sentryRequest.type);
5420
5324
  }
5421
5325
  else {
5422
- this.recordLostEvent(Outcome.NetworkError, sentryRequest.type);
5326
+ this.recordLostEvent('network_error', sentryRequest.type);
5423
5327
  }
5424
5328
  throw reason;
5425
5329
  });
@@ -5498,18 +5402,26 @@ var Sentry = (function (exports) {
5498
5402
  * @hidden
5499
5403
  */
5500
5404
  function wrap(fn, options = {}, before) {
5405
+ // for future readers what this does is wrap a function and then create
5406
+ // a bi-directional wrapping between them.
5407
+ //
5408
+ // example: wrapped = wrap(original);
5409
+ // original.__sentry_wrapped__ -> wrapped
5410
+ // wrapped.__sentry_original__ -> original
5501
5411
  if (typeof fn !== 'function') {
5502
5412
  return fn;
5503
5413
  }
5504
5414
  try {
5415
+ // if we're dealing with a function that was previously wrapped, return
5416
+ // the original wrapper.
5417
+ const wrapper = fn.__sentry_wrapped__;
5418
+ if (wrapper) {
5419
+ return wrapper;
5420
+ }
5505
5421
  // We don't wanna wrap it twice
5506
- if (fn.__sentry__) {
5422
+ if (getOriginalFunction(fn)) {
5507
5423
  return fn;
5508
5424
  }
5509
- // If this has already been wrapped in the past, return that wrapped function
5510
- if (fn.__sentry_wrapped__) {
5511
- return fn.__sentry_wrapped__;
5512
- }
5513
5425
  }
5514
5426
  catch (e) {
5515
5427
  // Just accessing custom props in some Selenium environments
@@ -5527,14 +5439,6 @@ var Sentry = (function (exports) {
5527
5439
  }
5528
5440
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
5529
5441
  const wrappedArguments = args.map((arg) => wrap(arg, options));
5530
- if (fn.handleEvent) {
5531
- // Attempt to invoke user-land function
5532
- // NOTE: If you are a Sentry user, and you are seeing this stack frame, it
5533
- // means the sentry.javascript SDK caught an error invoking your application code. This
5534
- // is expected behavior and NOT indicative of a bug with sentry.javascript.
5535
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
5536
- return fn.handleEvent.apply(this, wrappedArguments);
5537
- }
5538
5442
  // Attempt to invoke user-land function
5539
5443
  // NOTE: If you are a Sentry user, and you are seeing this stack frame, it
5540
5444
  // means the sentry.javascript SDK caught an error invoking your application code. This
@@ -5545,13 +5449,12 @@ var Sentry = (function (exports) {
5545
5449
  ignoreNextOnError();
5546
5450
  withScope((scope) => {
5547
5451
  scope.addEventProcessor((event) => {
5548
- const processedEvent = Object.assign({}, event);
5549
5452
  if (options.mechanism) {
5550
- addExceptionTypeValue(processedEvent, undefined, undefined);
5551
- addExceptionMechanism(processedEvent, options.mechanism);
5453
+ addExceptionTypeValue(event, undefined, undefined);
5454
+ addExceptionMechanism(event, options.mechanism);
5552
5455
  }
5553
- processedEvent.extra = Object.assign(Object.assign({}, processedEvent.extra), { arguments: args });
5554
- return processedEvent;
5456
+ event.extra = Object.assign(Object.assign({}, event.extra), { arguments: args });
5457
+ return event;
5555
5458
  });
5556
5459
  captureException(ex);
5557
5460
  });
@@ -5569,24 +5472,10 @@ var Sentry = (function (exports) {
5569
5472
  }
5570
5473
  }
5571
5474
  catch (_oO) { } // eslint-disable-line no-empty
5572
- fn.prototype = fn.prototype || {};
5573
- sentryWrapped.prototype = fn.prototype;
5574
- Object.defineProperty(fn, '__sentry_wrapped__', {
5575
- enumerable: false,
5576
- value: sentryWrapped,
5577
- });
5578
5475
  // Signal that this function has been wrapped/filled already
5579
5476
  // for both debugging and to prevent it to being wrapped/filled twice
5580
- Object.defineProperties(sentryWrapped, {
5581
- __sentry__: {
5582
- enumerable: false,
5583
- value: true,
5584
- },
5585
- __sentry_original__: {
5586
- enumerable: false,
5587
- value: fn,
5588
- },
5589
- });
5477
+ markFunctionWrapped(sentryWrapped, fn);
5478
+ addNonEnumerableProperty(fn, '__sentry_wrapped__', sentryWrapped);
5590
5479
  // Restore original function name (not all browsers allow that)
5591
5480
  try {
5592
5481
  const descriptor = Object.getOwnPropertyDescriptor(sentryWrapped, 'name');
@@ -5611,16 +5500,20 @@ var Sentry = (function (exports) {
5611
5500
  return;
5612
5501
  }
5613
5502
  if (!options.eventId) {
5614
- logger.error(`Missing eventId option in showReportDialog call`);
5503
+ if (isDebugBuild()) {
5504
+ logger.error(`Missing eventId option in showReportDialog call`);
5505
+ }
5615
5506
  return;
5616
5507
  }
5617
5508
  if (!options.dsn) {
5618
- logger.error(`Missing dsn option in showReportDialog call`);
5509
+ if (isDebugBuild()) {
5510
+ logger.error(`Missing dsn option in showReportDialog call`);
5511
+ }
5619
5512
  return;
5620
5513
  }
5621
5514
  const script = global$5.document.createElement('script');
5622
5515
  script.async = true;
5623
- script.src = new API(options.dsn).getReportDialogEndpoint(options);
5516
+ script.src = getReportDialogEndpoint(options.dsn, options);
5624
5517
  if (options.onLoad) {
5625
5518
  // eslint-disable-next-line @typescript-eslint/unbound-method
5626
5519
  script.onload = options.onLoad;
@@ -5640,10 +5533,14 @@ var Sentry = (function (exports) {
5640
5533
  * @inheritDoc
5641
5534
  */
5642
5535
  this.name = GlobalHandlers.id;
5643
- /** JSDoc */
5644
- this._onErrorHandlerInstalled = false;
5645
- /** JSDoc */
5646
- this._onUnhandledRejectionHandlerInstalled = false;
5536
+ /**
5537
+ * Stores references functions to installing handlers. Will set to undefined
5538
+ * after they have been run so that they are not used twice.
5539
+ */
5540
+ this._installFunc = {
5541
+ onerror: _installGlobalOnErrorHandler,
5542
+ onunhandledrejection: _installGlobalOnUnhandledRejectionHandler,
5543
+ };
5647
5544
  this._options = Object.assign({ onerror: true, onunhandledrejection: true }, options);
5648
5545
  }
5649
5546
  /**
@@ -5651,176 +5548,182 @@ var Sentry = (function (exports) {
5651
5548
  */
5652
5549
  setupOnce() {
5653
5550
  Error.stackTraceLimit = 50;
5654
- if (this._options.onerror) {
5655
- logger.log('Global Handler attached: onerror');
5656
- this._installGlobalOnErrorHandler();
5657
- }
5658
- if (this._options.onunhandledrejection) {
5659
- logger.log('Global Handler attached: onunhandledrejection');
5660
- this._installGlobalOnUnhandledRejectionHandler();
5551
+ const options = this._options;
5552
+ // We can disable guard-for-in as we construct the options object above + do checks against
5553
+ // `this._installFunc` for the property.
5554
+ // eslint-disable-next-line guard-for-in
5555
+ for (const key in options) {
5556
+ const installFunc = this._installFunc[key];
5557
+ if (installFunc && options[key]) {
5558
+ globalHandlerLog(key);
5559
+ installFunc();
5560
+ this._installFunc[key] = undefined;
5561
+ }
5661
5562
  }
5662
5563
  }
5663
- /** JSDoc */
5664
- _installGlobalOnErrorHandler() {
5665
- if (this._onErrorHandlerInstalled) {
5564
+ }
5565
+ /**
5566
+ * @inheritDoc
5567
+ */
5568
+ GlobalHandlers.id = 'GlobalHandlers';
5569
+ /** JSDoc */
5570
+ function _installGlobalOnErrorHandler() {
5571
+ addInstrumentationHandler('error',
5572
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5573
+ (data) => {
5574
+ const [hub, attachStacktrace] = getHubAndAttachStacktrace();
5575
+ if (!hub.getIntegration(GlobalHandlers)) {
5666
5576
  return;
5667
5577
  }
5668
- addInstrumentationHandler({
5669
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5670
- callback: (data) => {
5671
- const error = data.error;
5672
- const currentHub = getCurrentHub();
5673
- const hasIntegration = currentHub.getIntegration(GlobalHandlers);
5674
- const isFailedOwnDelivery = error && error.__sentry_own_request__ === true;
5675
- if (!hasIntegration || shouldIgnoreOnError() || isFailedOwnDelivery) {
5676
- return;
5677
- }
5678
- const client = currentHub.getClient();
5679
- const event = error === undefined && isString(data.msg)
5680
- ? this._eventFromIncompleteOnError(data.msg, data.url, data.line, data.column)
5681
- : this._enhanceEventWithInitialFrame(eventFromUnknownInput(error || data.msg, undefined, {
5682
- attachStacktrace: client && client.getOptions().attachStacktrace,
5683
- rejection: false,
5684
- }), data.url, data.line, data.column);
5685
- addExceptionMechanism(event, {
5686
- handled: false,
5687
- type: 'onerror',
5688
- });
5689
- currentHub.captureEvent(event, {
5690
- originalException: error,
5691
- });
5692
- },
5693
- type: 'error',
5694
- });
5695
- this._onErrorHandlerInstalled = true;
5696
- }
5697
- /** JSDoc */
5698
- _installGlobalOnUnhandledRejectionHandler() {
5699
- if (this._onUnhandledRejectionHandlerInstalled) {
5578
+ const { msg, url, line, column, error } = data;
5579
+ if (shouldIgnoreOnError() || (error && error.__sentry_own_request__)) {
5700
5580
  return;
5701
5581
  }
5702
- addInstrumentationHandler({
5703
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5704
- callback: (e) => {
5705
- let error = e;
5706
- // dig the object of the rejection out of known event types
5707
- try {
5708
- // PromiseRejectionEvents store the object of the rejection under 'reason'
5709
- // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent
5710
- if ('reason' in e) {
5711
- error = e.reason;
5712
- }
5713
- // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents
5714
- // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into
5715
- // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec
5716
- // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and
5717
- // https://github.com/getsentry/sentry-javascript/issues/2380
5718
- else if ('detail' in e && 'reason' in e.detail) {
5719
- error = e.detail.reason;
5720
- }
5721
- }
5722
- catch (_oO) {
5723
- // no-empty
5724
- }
5725
- const currentHub = getCurrentHub();
5726
- const hasIntegration = currentHub.getIntegration(GlobalHandlers);
5727
- const isFailedOwnDelivery = error && error.__sentry_own_request__ === true;
5728
- if (!hasIntegration || shouldIgnoreOnError() || isFailedOwnDelivery) {
5729
- return true;
5730
- }
5731
- const client = currentHub.getClient();
5732
- const event = isPrimitive(error)
5733
- ? this._eventFromRejectionWithPrimitive(error)
5734
- : eventFromUnknownInput(error, undefined, {
5735
- attachStacktrace: client && client.getOptions().attachStacktrace,
5736
- rejection: true,
5737
- });
5738
- event.level = exports.Severity.Error;
5739
- addExceptionMechanism(event, {
5740
- handled: false,
5741
- type: 'onunhandledrejection',
5742
- });
5743
- currentHub.captureEvent(event, {
5744
- originalException: error,
5745
- });
5746
- return;
5747
- },
5748
- type: 'unhandledrejection',
5749
- });
5750
- this._onUnhandledRejectionHandlerInstalled = true;
5751
- }
5752
- /**
5753
- * This function creates a stack from an old, error-less onerror handler.
5754
- */
5755
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5756
- _eventFromIncompleteOnError(msg, url, line, column) {
5757
- const ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i;
5758
- // If 'message' is ErrorEvent, get real message from inside
5759
- let message = isErrorEvent(msg) ? msg.message : msg;
5760
- let name;
5761
- const groups = message.match(ERROR_TYPES_RE);
5762
- if (groups) {
5763
- name = groups[1];
5764
- message = groups[2];
5765
- }
5766
- const event = {
5767
- exception: {
5768
- values: [
5769
- {
5770
- type: name || 'Error',
5771
- value: message,
5772
- },
5773
- ],
5774
- },
5775
- };
5776
- return this._enhanceEventWithInitialFrame(event, url, line, column);
5777
- }
5778
- /**
5779
- * Create an event from a promise rejection where the `reason` is a primitive.
5780
- *
5781
- * @param reason: The `reason` property of the promise rejection
5782
- * @returns An Event object with an appropriate `exception` value
5783
- */
5784
- _eventFromRejectionWithPrimitive(reason) {
5785
- return {
5786
- exception: {
5787
- values: [
5788
- {
5789
- type: 'UnhandledRejection',
5790
- // String() is needed because the Primitive type includes symbols (which can't be automatically stringified)
5791
- value: `Non-Error promise rejection captured with value: ${String(reason)}`,
5792
- },
5793
- ],
5794
- },
5795
- };
5796
- }
5797
- /** JSDoc */
5582
+ const event = error === undefined && isString(msg)
5583
+ ? _eventFromIncompleteOnError(msg, url, line, column)
5584
+ : _enhanceEventWithInitialFrame(eventFromUnknownInput(error || msg, undefined, {
5585
+ attachStacktrace,
5586
+ isRejection: false,
5587
+ }), url, line, column);
5588
+ addMechanismAndCapture(hub, error, event, 'onerror');
5589
+ });
5590
+ }
5591
+ /** JSDoc */
5592
+ function _installGlobalOnUnhandledRejectionHandler() {
5593
+ addInstrumentationHandler('unhandledrejection',
5798
5594
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5799
- _enhanceEventWithInitialFrame(event, url, line, column) {
5800
- event.exception = event.exception || {};
5801
- event.exception.values = event.exception.values || [];
5802
- event.exception.values[0] = event.exception.values[0] || {};
5803
- event.exception.values[0].stacktrace = event.exception.values[0].stacktrace || {};
5804
- event.exception.values[0].stacktrace.frames = event.exception.values[0].stacktrace.frames || [];
5805
- const colno = isNaN(parseInt(column, 10)) ? undefined : column;
5806
- const lineno = isNaN(parseInt(line, 10)) ? undefined : line;
5807
- const filename = isString(url) && url.length > 0 ? url : getLocationHref();
5808
- if (event.exception.values[0].stacktrace.frames.length === 0) {
5809
- event.exception.values[0].stacktrace.frames.push({
5810
- colno,
5811
- filename,
5812
- function: '?',
5813
- in_app: true,
5814
- lineno,
5815
- });
5595
+ (e) => {
5596
+ const [hub, attachStacktrace] = getHubAndAttachStacktrace();
5597
+ if (!hub.getIntegration(GlobalHandlers)) {
5598
+ return;
5816
5599
  }
5817
- return event;
5818
- }
5600
+ let error = e;
5601
+ // dig the object of the rejection out of known event types
5602
+ try {
5603
+ // PromiseRejectionEvents store the object of the rejection under 'reason'
5604
+ // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent
5605
+ if ('reason' in e) {
5606
+ error = e.reason;
5607
+ }
5608
+ // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents
5609
+ // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into
5610
+ // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec
5611
+ // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and
5612
+ // https://github.com/getsentry/sentry-javascript/issues/2380
5613
+ else if ('detail' in e && 'reason' in e.detail) {
5614
+ error = e.detail.reason;
5615
+ }
5616
+ }
5617
+ catch (_oO) {
5618
+ // no-empty
5619
+ }
5620
+ if (shouldIgnoreOnError() || (error && error.__sentry_own_request__)) {
5621
+ return true;
5622
+ }
5623
+ const event = isPrimitive(error)
5624
+ ? _eventFromRejectionWithPrimitive(error)
5625
+ : eventFromUnknownInput(error, undefined, {
5626
+ attachStacktrace,
5627
+ isRejection: true,
5628
+ });
5629
+ event.level = exports.Severity.Error;
5630
+ addMechanismAndCapture(hub, error, event, 'onunhandledrejection');
5631
+ return;
5632
+ });
5819
5633
  }
5820
5634
  /**
5821
- * @inheritDoc
5635
+ * Create an event from a promise rejection where the `reason` is a primitive.
5636
+ *
5637
+ * @param reason: The `reason` property of the promise rejection
5638
+ * @returns An Event object with an appropriate `exception` value
5639
+ */
5640
+ function _eventFromRejectionWithPrimitive(reason) {
5641
+ return {
5642
+ exception: {
5643
+ values: [
5644
+ {
5645
+ type: 'UnhandledRejection',
5646
+ // String() is needed because the Primitive type includes symbols (which can't be automatically stringified)
5647
+ value: `Non-Error promise rejection captured with value: ${String(reason)}`,
5648
+ },
5649
+ ],
5650
+ },
5651
+ };
5652
+ }
5653
+ /**
5654
+ * This function creates a stack from an old, error-less onerror handler.
5822
5655
  */
5823
- GlobalHandlers.id = 'GlobalHandlers';
5656
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5657
+ function _eventFromIncompleteOnError(msg, url, line, column) {
5658
+ const ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i;
5659
+ // If 'message' is ErrorEvent, get real message from inside
5660
+ let message = isErrorEvent(msg) ? msg.message : msg;
5661
+ let name = 'Error';
5662
+ const groups = message.match(ERROR_TYPES_RE);
5663
+ if (groups) {
5664
+ name = groups[1];
5665
+ message = groups[2];
5666
+ }
5667
+ const event = {
5668
+ exception: {
5669
+ values: [
5670
+ {
5671
+ type: name,
5672
+ value: message,
5673
+ },
5674
+ ],
5675
+ },
5676
+ };
5677
+ return _enhanceEventWithInitialFrame(event, url, line, column);
5678
+ }
5679
+ /** JSDoc */
5680
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5681
+ function _enhanceEventWithInitialFrame(event, url, line, column) {
5682
+ // event.exception
5683
+ const e = (event.exception = event.exception || {});
5684
+ // event.exception.values
5685
+ const ev = (e.values = e.values || []);
5686
+ // event.exception.values[0]
5687
+ const ev0 = (ev[0] = ev[0] || {});
5688
+ // event.exception.values[0].stacktrace
5689
+ const ev0s = (ev0.stacktrace = ev0.stacktrace || {});
5690
+ // event.exception.values[0].stacktrace.frames
5691
+ const ev0sf = (ev0s.frames = ev0s.frames || []);
5692
+ const colno = isNaN(parseInt(column, 10)) ? undefined : column;
5693
+ const lineno = isNaN(parseInt(line, 10)) ? undefined : line;
5694
+ const filename = isString(url) && url.length > 0 ? url : getLocationHref();
5695
+ // event.exception.values[0].stacktrace.frames
5696
+ if (ev0sf.length === 0) {
5697
+ ev0sf.push({
5698
+ colno,
5699
+ filename,
5700
+ function: '?',
5701
+ in_app: true,
5702
+ lineno,
5703
+ });
5704
+ }
5705
+ return event;
5706
+ }
5707
+ function globalHandlerLog(type) {
5708
+ if (isDebugBuild()) {
5709
+ logger.log(`Global Handler attached: ${type}`);
5710
+ }
5711
+ }
5712
+ function addMechanismAndCapture(hub, error, event, type) {
5713
+ addExceptionMechanism(event, {
5714
+ handled: false,
5715
+ type,
5716
+ });
5717
+ hub.captureEvent(event, {
5718
+ originalException: error,
5719
+ });
5720
+ }
5721
+ function getHubAndAttachStacktrace() {
5722
+ const hub = getCurrentHub();
5723
+ const client = hub.getClient();
5724
+ const attachStacktrace = client && client.getOptions().attachStacktrace;
5725
+ return [hub, attachStacktrace];
5726
+ }
5824
5727
 
5825
5728
  const DEFAULT_EVENT_TARGET = [
5826
5729
  'EventTarget',
@@ -5872,172 +5775,173 @@ var Sentry = (function (exports) {
5872
5775
  setupOnce() {
5873
5776
  const global = getGlobalObject();
5874
5777
  if (this._options.setTimeout) {
5875
- fill(global, 'setTimeout', this._wrapTimeFunction.bind(this));
5778
+ fill(global, 'setTimeout', _wrapTimeFunction);
5876
5779
  }
5877
5780
  if (this._options.setInterval) {
5878
- fill(global, 'setInterval', this._wrapTimeFunction.bind(this));
5781
+ fill(global, 'setInterval', _wrapTimeFunction);
5879
5782
  }
5880
5783
  if (this._options.requestAnimationFrame) {
5881
- fill(global, 'requestAnimationFrame', this._wrapRAF.bind(this));
5784
+ fill(global, 'requestAnimationFrame', _wrapRAF);
5882
5785
  }
5883
5786
  if (this._options.XMLHttpRequest && 'XMLHttpRequest' in global) {
5884
- fill(XMLHttpRequest.prototype, 'send', this._wrapXHR.bind(this));
5787
+ fill(XMLHttpRequest.prototype, 'send', _wrapXHR);
5885
5788
  }
5886
- if (this._options.eventTarget) {
5887
- const eventTarget = Array.isArray(this._options.eventTarget) ? this._options.eventTarget : DEFAULT_EVENT_TARGET;
5888
- eventTarget.forEach(this._wrapEventTarget.bind(this));
5789
+ const eventTargetOption = this._options.eventTarget;
5790
+ if (eventTargetOption) {
5791
+ const eventTarget = Array.isArray(eventTargetOption) ? eventTargetOption : DEFAULT_EVENT_TARGET;
5792
+ eventTarget.forEach(_wrapEventTarget);
5889
5793
  }
5890
5794
  }
5891
- /** JSDoc */
5892
- _wrapTimeFunction(original) {
5893
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5894
- return function (...args) {
5895
- const originalCallback = args[0];
5896
- args[0] = wrap(originalCallback, {
5897
- mechanism: {
5898
- data: { function: getFunctionName(original) },
5899
- handled: true,
5900
- type: 'instrument',
5901
- },
5902
- });
5903
- return original.apply(this, args);
5904
- };
5905
- }
5906
- /** JSDoc */
5795
+ }
5796
+ /**
5797
+ * @inheritDoc
5798
+ */
5799
+ TryCatch.id = 'TryCatch';
5800
+ /** JSDoc */
5801
+ function _wrapTimeFunction(original) {
5907
5802
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5908
- _wrapRAF(original) {
5909
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5910
- return function (callback) {
5911
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
5912
- return original.call(this, wrap(callback, {
5913
- mechanism: {
5914
- data: {
5915
- function: 'requestAnimationFrame',
5916
- handler: getFunctionName(original),
5917
- },
5918
- handled: true,
5919
- type: 'instrument',
5803
+ return function (...args) {
5804
+ const originalCallback = args[0];
5805
+ args[0] = wrap(originalCallback, {
5806
+ mechanism: {
5807
+ data: { function: getFunctionName(original) },
5808
+ handled: true,
5809
+ type: 'instrument',
5810
+ },
5811
+ });
5812
+ return original.apply(this, args);
5813
+ };
5814
+ }
5815
+ /** JSDoc */
5816
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5817
+ function _wrapRAF(original) {
5818
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5819
+ return function (callback) {
5820
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
5821
+ return original.call(this, wrap(callback, {
5822
+ mechanism: {
5823
+ data: {
5824
+ function: 'requestAnimationFrame',
5825
+ handler: getFunctionName(original),
5920
5826
  },
5921
- }));
5922
- };
5923
- }
5924
- /** JSDoc */
5925
- _wrapEventTarget(target) {
5926
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5927
- const global = getGlobalObject();
5928
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
5929
- const proto = global[target] && global[target].prototype;
5930
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, no-prototype-builtins
5931
- if (!proto || !proto.hasOwnProperty || !proto.hasOwnProperty('addEventListener')) {
5932
- return;
5933
- }
5934
- fill(proto, 'addEventListener', function (original) {
5935
- return function (eventName, fn, options) {
5936
- try {
5937
- if (typeof fn.handleEvent === 'function') {
5938
- fn.handleEvent = wrap(fn.handleEvent.bind(fn), {
5939
- mechanism: {
5940
- data: {
5941
- function: 'handleEvent',
5942
- handler: getFunctionName(fn),
5943
- target,
5944
- },
5945
- handled: true,
5946
- type: 'instrument',
5947
- },
5948
- });
5949
- }
5950
- }
5951
- catch (err) {
5952
- // can sometimes get 'Permission denied to access property "handle Event'
5953
- }
5954
- return original.call(this, eventName,
5827
+ handled: true,
5828
+ type: 'instrument',
5829
+ },
5830
+ }));
5831
+ };
5832
+ }
5833
+ /** JSDoc */
5834
+ function _wrapXHR(originalSend) {
5835
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5836
+ return function (...args) {
5837
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
5838
+ const xhr = this;
5839
+ const xmlHttpRequestProps = ['onload', 'onerror', 'onprogress', 'onreadystatechange'];
5840
+ xmlHttpRequestProps.forEach(prop => {
5841
+ if (prop in xhr && typeof xhr[prop] === 'function') {
5955
5842
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5956
- wrap(fn, {
5957
- mechanism: {
5958
- data: {
5959
- function: 'addEventListener',
5960
- handler: getFunctionName(fn),
5961
- target,
5843
+ fill(xhr, prop, function (original) {
5844
+ const wrapOptions = {
5845
+ mechanism: {
5846
+ data: {
5847
+ function: prop,
5848
+ handler: getFunctionName(original),
5849
+ },
5850
+ handled: true,
5851
+ type: 'instrument',
5962
5852
  },
5963
- handled: true,
5964
- type: 'instrument',
5965
- },
5966
- }), options);
5967
- };
5968
- });
5969
- fill(proto, 'removeEventListener', function (originalRemoveEventListener) {
5970
- return function (eventName, fn, options) {
5971
- var _a;
5972
- /**
5973
- * There are 2 possible scenarios here:
5974
- *
5975
- * 1. Someone passes a callback, which was attached prior to Sentry initialization, or by using unmodified
5976
- * method, eg. `document.addEventListener.call(el, name, handler). In this case, we treat this function
5977
- * as a pass-through, and call original `removeEventListener` with it.
5978
- *
5979
- * 2. Someone passes a callback, which was attached after Sentry was initialized, which means that it was using
5980
- * our wrapped version of `addEventListener`, which internally calls `wrap` helper.
5981
- * This helper "wraps" whole callback inside a try/catch statement, and attached appropriate metadata to it,
5982
- * in order for us to make a distinction between wrapped/non-wrapped functions possible.
5983
- * If a function was wrapped, it has additional property of `__sentry_wrapped__`, holding the handler.
5984
- *
5985
- * When someone adds a handler prior to initialization, and then do it again, but after,
5986
- * then we have to detach both of them. Otherwise, if we'd detach only wrapped one, it'd be impossible
5987
- * to get rid of the initial handler and it'd stick there forever.
5988
- */
5989
- const wrappedEventHandler = fn;
5990
- try {
5991
- const originalEventHandler = (_a = wrappedEventHandler) === null || _a === void 0 ? void 0 : _a.__sentry_wrapped__;
5992
- if (originalEventHandler) {
5993
- originalRemoveEventListener.call(this, eventName, originalEventHandler, options);
5853
+ };
5854
+ // If Instrument integration has been called before TryCatch, get the name of original function
5855
+ const originalFunction = getOriginalFunction(original);
5856
+ if (originalFunction) {
5857
+ wrapOptions.mechanism.data.handler = getFunctionName(originalFunction);
5994
5858
  }
5995
- }
5996
- catch (e) {
5997
- // ignore, accessing __sentry_wrapped__ will throw in some Selenium environments
5998
- }
5999
- return originalRemoveEventListener.call(this, eventName, wrappedEventHandler, options);
6000
- };
5859
+ // Otherwise wrap directly
5860
+ return wrap(original, wrapOptions);
5861
+ });
5862
+ }
6001
5863
  });
5864
+ return originalSend.apply(this, args);
5865
+ };
5866
+ }
5867
+ /** JSDoc */
5868
+ function _wrapEventTarget(target) {
5869
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5870
+ const global = getGlobalObject();
5871
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
5872
+ const proto = global[target] && global[target].prototype;
5873
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, no-prototype-builtins
5874
+ if (!proto || !proto.hasOwnProperty || !proto.hasOwnProperty('addEventListener')) {
5875
+ return;
6002
5876
  }
6003
- /** JSDoc */
6004
- _wrapXHR(originalSend) {
6005
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6006
- return function (...args) {
6007
- // eslint-disable-next-line @typescript-eslint/no-this-alias
6008
- const xhr = this;
6009
- const xmlHttpRequestProps = ['onload', 'onerror', 'onprogress', 'onreadystatechange'];
6010
- xmlHttpRequestProps.forEach(prop => {
6011
- if (prop in xhr && typeof xhr[prop] === 'function') {
6012
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6013
- fill(xhr, prop, function (original) {
6014
- const wrapOptions = {
6015
- mechanism: {
6016
- data: {
6017
- function: prop,
6018
- handler: getFunctionName(original),
6019
- },
6020
- handled: true,
6021
- type: 'instrument',
5877
+ fill(proto, 'addEventListener', function (original) {
5878
+ return function (eventName, fn, options) {
5879
+ try {
5880
+ if (typeof fn.handleEvent === 'function') {
5881
+ fn.handleEvent = wrap(fn.handleEvent.bind(fn), {
5882
+ mechanism: {
5883
+ data: {
5884
+ function: 'handleEvent',
5885
+ handler: getFunctionName(fn),
5886
+ target,
6022
5887
  },
6023
- };
6024
- // If Instrument integration has been called before TryCatch, get the name of original function
6025
- if (original.__sentry_original__) {
6026
- wrapOptions.mechanism.data.handler = getFunctionName(original.__sentry_original__);
6027
- }
6028
- // Otherwise wrap directly
6029
- return wrap(original, wrapOptions);
5888
+ handled: true,
5889
+ type: 'instrument',
5890
+ },
6030
5891
  });
6031
5892
  }
6032
- });
6033
- return originalSend.apply(this, args);
5893
+ }
5894
+ catch (err) {
5895
+ // can sometimes get 'Permission denied to access property "handle Event'
5896
+ }
5897
+ return original.call(this, eventName,
5898
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5899
+ wrap(fn, {
5900
+ mechanism: {
5901
+ data: {
5902
+ function: 'addEventListener',
5903
+ handler: getFunctionName(fn),
5904
+ target,
5905
+ },
5906
+ handled: true,
5907
+ type: 'instrument',
5908
+ },
5909
+ }), options);
6034
5910
  };
6035
- }
6036
- }
6037
- /**
6038
- * @inheritDoc
6039
- */
6040
- TryCatch.id = 'TryCatch';
5911
+ });
5912
+ fill(proto, 'removeEventListener', function (originalRemoveEventListener) {
5913
+ return function (eventName, fn, options) {
5914
+ /**
5915
+ * There are 2 possible scenarios here:
5916
+ *
5917
+ * 1. Someone passes a callback, which was attached prior to Sentry initialization, or by using unmodified
5918
+ * method, eg. `document.addEventListener.call(el, name, handler). In this case, we treat this function
5919
+ * as a pass-through, and call original `removeEventListener` with it.
5920
+ *
5921
+ * 2. Someone passes a callback, which was attached after Sentry was initialized, which means that it was using
5922
+ * our wrapped version of `addEventListener`, which internally calls `wrap` helper.
5923
+ * This helper "wraps" whole callback inside a try/catch statement, and attached appropriate metadata to it,
5924
+ * in order for us to make a distinction between wrapped/non-wrapped functions possible.
5925
+ * If a function was wrapped, it has additional property of `__sentry_wrapped__`, holding the handler.
5926
+ *
5927
+ * When someone adds a handler prior to initialization, and then do it again, but after,
5928
+ * then we have to detach both of them. Otherwise, if we'd detach only wrapped one, it'd be impossible
5929
+ * to get rid of the initial handler and it'd stick there forever.
5930
+ */
5931
+ const wrappedEventHandler = fn;
5932
+ try {
5933
+ const originalEventHandler = wrappedEventHandler && wrappedEventHandler.__sentry_wrapped__;
5934
+ if (originalEventHandler) {
5935
+ originalRemoveEventListener.call(this, eventName, originalEventHandler, options);
5936
+ }
5937
+ }
5938
+ catch (e) {
5939
+ // ignore, accessing __sentry_wrapped__ will throw in some Selenium environments
5940
+ }
5941
+ return originalRemoveEventListener.call(this, eventName, wrappedEventHandler, options);
5942
+ };
5943
+ });
5944
+ }
6041
5945
 
6042
5946
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
6043
5947
  /**
@@ -6081,82 +5985,36 @@ var Sentry = (function (exports) {
6081
5985
  */
6082
5986
  setupOnce() {
6083
5987
  if (this._options.console) {
6084
- addInstrumentationHandler({
6085
- callback: (...args) => {
6086
- this._consoleBreadcrumb(...args);
6087
- },
6088
- type: 'console',
6089
- });
5988
+ addInstrumentationHandler('console', _consoleBreadcrumb);
6090
5989
  }
6091
5990
  if (this._options.dom) {
6092
- addInstrumentationHandler({
6093
- callback: (...args) => {
6094
- this._domBreadcrumb(...args);
6095
- },
6096
- type: 'dom',
6097
- });
5991
+ addInstrumentationHandler('dom', _domBreadcrumb(this._options.dom));
6098
5992
  }
6099
5993
  if (this._options.xhr) {
6100
- addInstrumentationHandler({
6101
- callback: (...args) => {
6102
- this._xhrBreadcrumb(...args);
6103
- },
6104
- type: 'xhr',
6105
- });
5994
+ addInstrumentationHandler('xhr', _xhrBreadcrumb);
6106
5995
  }
6107
5996
  if (this._options.fetch) {
6108
- addInstrumentationHandler({
6109
- callback: (...args) => {
6110
- this._fetchBreadcrumb(...args);
6111
- },
6112
- type: 'fetch',
6113
- });
5997
+ addInstrumentationHandler('fetch', _fetchBreadcrumb);
6114
5998
  }
6115
5999
  if (this._options.history) {
6116
- addInstrumentationHandler({
6117
- callback: (...args) => {
6118
- this._historyBreadcrumb(...args);
6119
- },
6120
- type: 'history',
6121
- });
6122
- }
6123
- }
6124
- /**
6125
- * Creates breadcrumbs from console API calls
6126
- */
6127
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6128
- _consoleBreadcrumb(handlerData) {
6129
- const breadcrumb = {
6130
- category: 'console',
6131
- data: {
6132
- arguments: handlerData.args,
6133
- logger: 'console',
6134
- },
6135
- level: exports.Severity.fromString(handlerData.level),
6136
- message: safeJoin(handlerData.args, ' '),
6137
- };
6138
- if (handlerData.level === 'assert') {
6139
- if (handlerData.args[0] === false) {
6140
- breadcrumb.message = `Assertion failed: ${safeJoin(handlerData.args.slice(1), ' ') || 'console.assert'}`;
6141
- breadcrumb.data.arguments = handlerData.args.slice(1);
6142
- }
6143
- else {
6144
- // Don't capture a breadcrumb for passed assertions
6145
- return;
6146
- }
6000
+ addInstrumentationHandler('history', _historyBreadcrumb);
6147
6001
  }
6148
- getCurrentHub().addBreadcrumb(breadcrumb, {
6149
- input: handlerData.args,
6150
- level: handlerData.level,
6151
- });
6152
6002
  }
6153
- /**
6154
- * Creates breadcrumbs from DOM API calls
6155
- */
6003
+ }
6004
+ /**
6005
+ * @inheritDoc
6006
+ */
6007
+ Breadcrumbs.id = 'Breadcrumbs';
6008
+ /**
6009
+ * A HOC that creaes a function that creates breadcrumbs from DOM API calls.
6010
+ * This is a HOC so that we get access to dom options in the closure.
6011
+ */
6012
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6013
+ function _domBreadcrumb(dom) {
6156
6014
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6157
- _domBreadcrumb(handlerData) {
6015
+ function _innerDomBreadcrumb(handlerData) {
6158
6016
  let target;
6159
- let keyAttrs = typeof this._options.dom === 'object' ? this._options.dom.serializeAttribute : undefined;
6017
+ let keyAttrs = typeof dom === 'object' ? dom.serializeAttribute : undefined;
6160
6018
  if (typeof keyAttrs === 'string') {
6161
6019
  keyAttrs = [keyAttrs];
6162
6020
  }
@@ -6181,103 +6039,129 @@ var Sentry = (function (exports) {
6181
6039
  global: handlerData.global,
6182
6040
  });
6183
6041
  }
6184
- /**
6185
- * Creates breadcrumbs from XHR API calls
6186
- */
6187
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6188
- _xhrBreadcrumb(handlerData) {
6189
- if (handlerData.endTimestamp) {
6190
- // We only capture complete, non-sentry requests
6191
- if (handlerData.xhr.__sentry_own_request__) {
6192
- return;
6193
- }
6194
- const { method, url, status_code, body } = handlerData.xhr.__sentry_xhr__ || {};
6195
- getCurrentHub().addBreadcrumb({
6196
- category: 'xhr',
6197
- data: {
6198
- method,
6199
- url,
6200
- status_code,
6201
- },
6202
- type: 'http',
6203
- }, {
6204
- xhr: handlerData.xhr,
6205
- input: body,
6206
- });
6207
- return;
6208
- }
6209
- }
6210
- /**
6211
- * Creates breadcrumbs from fetch API calls
6212
- */
6213
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6214
- _fetchBreadcrumb(handlerData) {
6215
- // We only capture complete fetch requests
6216
- if (!handlerData.endTimestamp) {
6217
- return;
6218
- }
6219
- if (handlerData.fetchData.url.match(/sentry_key/) && handlerData.fetchData.method === 'POST') {
6220
- // We will not create breadcrumbs for fetch requests that contain `sentry_key` (internal sentry requests)
6221
- return;
6222
- }
6223
- if (handlerData.error) {
6224
- getCurrentHub().addBreadcrumb({
6225
- category: 'fetch',
6226
- data: handlerData.fetchData,
6227
- level: exports.Severity.Error,
6228
- type: 'http',
6229
- }, {
6230
- data: handlerData.error,
6231
- input: handlerData.args,
6232
- });
6042
+ return _innerDomBreadcrumb;
6043
+ }
6044
+ /**
6045
+ * Creates breadcrumbs from console API calls
6046
+ */
6047
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6048
+ function _consoleBreadcrumb(handlerData) {
6049
+ const breadcrumb = {
6050
+ category: 'console',
6051
+ data: {
6052
+ arguments: handlerData.args,
6053
+ logger: 'console',
6054
+ },
6055
+ level: severityFromString(handlerData.level),
6056
+ message: safeJoin(handlerData.args, ' '),
6057
+ };
6058
+ if (handlerData.level === 'assert') {
6059
+ if (handlerData.args[0] === false) {
6060
+ breadcrumb.message = `Assertion failed: ${safeJoin(handlerData.args.slice(1), ' ') || 'console.assert'}`;
6061
+ breadcrumb.data.arguments = handlerData.args.slice(1);
6233
6062
  }
6234
6063
  else {
6235
- getCurrentHub().addBreadcrumb({
6236
- category: 'fetch',
6237
- data: Object.assign(Object.assign({}, handlerData.fetchData), { status_code: handlerData.response.status }),
6238
- type: 'http',
6239
- }, {
6240
- input: handlerData.args,
6241
- response: handlerData.response,
6242
- });
6064
+ // Don't capture a breadcrumb for passed assertions
6065
+ return;
6243
6066
  }
6244
6067
  }
6245
- /**
6246
- * Creates breadcrumbs from history API calls
6247
- */
6248
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6249
- _historyBreadcrumb(handlerData) {
6250
- const global = getGlobalObject();
6251
- let from = handlerData.from;
6252
- let to = handlerData.to;
6253
- const parsedLoc = parseUrl(global.location.href);
6254
- let parsedFrom = parseUrl(from);
6255
- const parsedTo = parseUrl(to);
6256
- // Initial pushState doesn't provide `from` information
6257
- if (!parsedFrom.path) {
6258
- parsedFrom = parsedLoc;
6259
- }
6260
- // Use only the path component of the URL if the URL matches the current
6261
- // document (almost all the time when using pushState)
6262
- if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host) {
6263
- to = parsedTo.relative;
6264
- }
6265
- if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host) {
6266
- from = parsedFrom.relative;
6068
+ getCurrentHub().addBreadcrumb(breadcrumb, {
6069
+ input: handlerData.args,
6070
+ level: handlerData.level,
6071
+ });
6072
+ }
6073
+ /**
6074
+ * Creates breadcrumbs from XHR API calls
6075
+ */
6076
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6077
+ function _xhrBreadcrumb(handlerData) {
6078
+ if (handlerData.endTimestamp) {
6079
+ // We only capture complete, non-sentry requests
6080
+ if (handlerData.xhr.__sentry_own_request__) {
6081
+ return;
6267
6082
  }
6083
+ const { method, url, status_code, body } = handlerData.xhr.__sentry_xhr__ || {};
6268
6084
  getCurrentHub().addBreadcrumb({
6269
- category: 'navigation',
6085
+ category: 'xhr',
6270
6086
  data: {
6271
- from,
6272
- to,
6087
+ method,
6088
+ url,
6089
+ status_code,
6273
6090
  },
6091
+ type: 'http',
6092
+ }, {
6093
+ xhr: handlerData.xhr,
6094
+ input: body,
6274
6095
  });
6096
+ return;
6275
6097
  }
6276
6098
  }
6277
6099
  /**
6278
- * @inheritDoc
6100
+ * Creates breadcrumbs from fetch API calls
6101
+ */
6102
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6103
+ function _fetchBreadcrumb(handlerData) {
6104
+ // We only capture complete fetch requests
6105
+ if (!handlerData.endTimestamp) {
6106
+ return;
6107
+ }
6108
+ if (handlerData.fetchData.url.match(/sentry_key/) && handlerData.fetchData.method === 'POST') {
6109
+ // We will not create breadcrumbs for fetch requests that contain `sentry_key` (internal sentry requests)
6110
+ return;
6111
+ }
6112
+ if (handlerData.error) {
6113
+ getCurrentHub().addBreadcrumb({
6114
+ category: 'fetch',
6115
+ data: handlerData.fetchData,
6116
+ level: exports.Severity.Error,
6117
+ type: 'http',
6118
+ }, {
6119
+ data: handlerData.error,
6120
+ input: handlerData.args,
6121
+ });
6122
+ }
6123
+ else {
6124
+ getCurrentHub().addBreadcrumb({
6125
+ category: 'fetch',
6126
+ data: Object.assign(Object.assign({}, handlerData.fetchData), { status_code: handlerData.response.status }),
6127
+ type: 'http',
6128
+ }, {
6129
+ input: handlerData.args,
6130
+ response: handlerData.response,
6131
+ });
6132
+ }
6133
+ }
6134
+ /**
6135
+ * Creates breadcrumbs from history API calls
6279
6136
  */
6280
- Breadcrumbs.id = 'Breadcrumbs';
6137
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6138
+ function _historyBreadcrumb(handlerData) {
6139
+ const global = getGlobalObject();
6140
+ let from = handlerData.from;
6141
+ let to = handlerData.to;
6142
+ const parsedLoc = parseUrl(global.location.href);
6143
+ let parsedFrom = parseUrl(from);
6144
+ const parsedTo = parseUrl(to);
6145
+ // Initial pushState doesn't provide `from` information
6146
+ if (!parsedFrom.path) {
6147
+ parsedFrom = parsedLoc;
6148
+ }
6149
+ // Use only the path component of the URL if the URL matches the current
6150
+ // document (almost all the time when using pushState)
6151
+ if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host) {
6152
+ to = parsedTo.relative;
6153
+ }
6154
+ if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host) {
6155
+ from = parsedFrom.relative;
6156
+ }
6157
+ getCurrentHub().addBreadcrumb({
6158
+ category: 'navigation',
6159
+ data: {
6160
+ from,
6161
+ to,
6162
+ },
6163
+ });
6164
+ }
6281
6165
 
6282
6166
  const DEFAULT_KEY = 'cause';
6283
6167
  const DEFAULT_LIMIT = 5;
@@ -6300,40 +6184,36 @@ var Sentry = (function (exports) {
6300
6184
  setupOnce() {
6301
6185
  addGlobalEventProcessor((event, hint) => {
6302
6186
  const self = getCurrentHub().getIntegration(LinkedErrors);
6303
- if (self) {
6304
- const handler = self._handler && self._handler.bind(self);
6305
- return typeof handler === 'function' ? handler(event, hint) : event;
6306
- }
6307
- return event;
6187
+ return self ? _handler(self._key, self._limit, event, hint) : event;
6308
6188
  });
6309
6189
  }
6310
- /**
6311
- * @inheritDoc
6312
- */
6313
- _handler(event, hint) {
6314
- if (!event.exception || !event.exception.values || !hint || !isInstanceOf(hint.originalException, Error)) {
6315
- return event;
6316
- }
6317
- const linkedErrors = this._walkErrorTree(hint.originalException, this._key);
6318
- event.exception.values = [...linkedErrors, ...event.exception.values];
6190
+ }
6191
+ /**
6192
+ * @inheritDoc
6193
+ */
6194
+ LinkedErrors.id = 'LinkedErrors';
6195
+ /**
6196
+ * @inheritDoc
6197
+ */
6198
+ function _handler(key, limit, event, hint) {
6199
+ if (!event.exception || !event.exception.values || !hint || !isInstanceOf(hint.originalException, Error)) {
6319
6200
  return event;
6320
6201
  }
6321
- /**
6322
- * @inheritDoc
6323
- */
6324
- _walkErrorTree(error, key, stack = []) {
6325
- if (!isInstanceOf(error[key], Error) || stack.length + 1 >= this._limit) {
6326
- return stack;
6327
- }
6328
- const stacktrace = computeStackTrace(error[key]);
6329
- const exception = exceptionFromStacktrace(stacktrace);
6330
- return this._walkErrorTree(error[key], key, [exception, ...stack]);
6331
- }
6202
+ const linkedErrors = _walkErrorTree(limit, hint.originalException, key);
6203
+ event.exception.values = [...linkedErrors, ...event.exception.values];
6204
+ return event;
6332
6205
  }
6333
6206
  /**
6334
- * @inheritDoc
6207
+ * JSDOC
6335
6208
  */
6336
- LinkedErrors.id = 'LinkedErrors';
6209
+ function _walkErrorTree(limit, error, key, stack = []) {
6210
+ if (!isInstanceOf(error[key], Error) || stack.length + 1 >= limit) {
6211
+ return stack;
6212
+ }
6213
+ const stacktrace = computeStackTrace(error[key]);
6214
+ const exception = exceptionFromStacktrace(stacktrace);
6215
+ return _walkErrorTree(limit, error[key], key, [exception, ...stack]);
6216
+ }
6337
6217
 
6338
6218
  const global$6 = getGlobalObject();
6339
6219
  /** UserAgent */
@@ -6349,17 +6229,16 @@ var Sentry = (function (exports) {
6349
6229
  */
6350
6230
  setupOnce() {
6351
6231
  addGlobalEventProcessor((event) => {
6352
- var _a, _b, _c;
6353
6232
  if (getCurrentHub().getIntegration(UserAgent)) {
6354
6233
  // if none of the information we want exists, don't bother
6355
6234
  if (!global$6.navigator && !global$6.location && !global$6.document) {
6356
6235
  return event;
6357
6236
  }
6358
6237
  // grab as much info as exists and add it to the event
6359
- const url = ((_a = event.request) === null || _a === void 0 ? void 0 : _a.url) || ((_b = global$6.location) === null || _b === void 0 ? void 0 : _b.href);
6238
+ const url = (event.request && event.request.url) || (global$6.location && global$6.location.href);
6360
6239
  const { referrer } = global$6.document || {};
6361
6240
  const { userAgent } = global$6.navigator || {};
6362
- const headers = Object.assign(Object.assign(Object.assign({}, (_c = event.request) === null || _c === void 0 ? void 0 : _c.headers), (referrer && { Referer: referrer })), (userAgent && { 'User-Agent': userAgent }));
6241
+ const headers = Object.assign(Object.assign(Object.assign({}, (event.request && event.request.headers)), (referrer && { Referer: referrer })), (userAgent && { 'User-Agent': userAgent }));
6363
6242
  const request = Object.assign(Object.assign({}, (url && { url })), { headers });
6364
6243
  return Object.assign(Object.assign({}, event), { request });
6365
6244
  }
@@ -6389,7 +6268,7 @@ var Sentry = (function (exports) {
6389
6268
  if (self) {
6390
6269
  // Juuust in case something goes wrong
6391
6270
  try {
6392
- if (self._shouldDropEvent(currentEvent, self._previousEvent)) {
6271
+ if (_shouldDropEvent(currentEvent, self._previousEvent)) {
6393
6272
  logger.warn(`Event dropped due to being a duplicate of previously captured event.`);
6394
6273
  return null;
6395
6274
  }
@@ -6402,139 +6281,139 @@ var Sentry = (function (exports) {
6402
6281
  return currentEvent;
6403
6282
  });
6404
6283
  }
6405
- /** JSDoc */
6406
- _shouldDropEvent(currentEvent, previousEvent) {
6407
- if (!previousEvent) {
6408
- return false;
6409
- }
6410
- if (this._isSameMessageEvent(currentEvent, previousEvent)) {
6411
- return true;
6412
- }
6413
- if (this._isSameExceptionEvent(currentEvent, previousEvent)) {
6414
- return true;
6415
- }
6284
+ }
6285
+ /**
6286
+ * @inheritDoc
6287
+ */
6288
+ Dedupe.id = 'Dedupe';
6289
+ /** JSDoc */
6290
+ function _shouldDropEvent(currentEvent, previousEvent) {
6291
+ if (!previousEvent) {
6416
6292
  return false;
6417
6293
  }
6418
- /** JSDoc */
6419
- _isSameMessageEvent(currentEvent, previousEvent) {
6420
- const currentMessage = currentEvent.message;
6421
- const previousMessage = previousEvent.message;
6422
- // If neither event has a message property, they were both exceptions, so bail out
6423
- if (!currentMessage && !previousMessage) {
6424
- return false;
6425
- }
6426
- // If only one event has a stacktrace, but not the other one, they are not the same
6427
- if ((currentMessage && !previousMessage) || (!currentMessage && previousMessage)) {
6428
- return false;
6429
- }
6430
- if (currentMessage !== previousMessage) {
6431
- return false;
6432
- }
6433
- if (!this._isSameFingerprint(currentEvent, previousEvent)) {
6434
- return false;
6435
- }
6436
- if (!this._isSameStacktrace(currentEvent, previousEvent)) {
6437
- return false;
6438
- }
6294
+ if (_isSameMessageEvent(currentEvent, previousEvent)) {
6439
6295
  return true;
6440
6296
  }
6441
- /** JSDoc */
6442
- _getFramesFromEvent(event) {
6443
- const exception = event.exception;
6444
- if (exception) {
6445
- try {
6446
- // @ts-ignore Object could be undefined
6447
- return exception.values[0].stacktrace.frames;
6448
- }
6449
- catch (_oO) {
6450
- return undefined;
6451
- }
6452
- }
6453
- else if (event.stacktrace) {
6454
- return event.stacktrace.frames;
6455
- }
6456
- return undefined;
6297
+ if (_isSameExceptionEvent(currentEvent, previousEvent)) {
6298
+ return true;
6457
6299
  }
6458
- /** JSDoc */
6459
- _isSameStacktrace(currentEvent, previousEvent) {
6460
- let currentFrames = this._getFramesFromEvent(currentEvent);
6461
- let previousFrames = this._getFramesFromEvent(previousEvent);
6462
- // If neither event has a stacktrace, they are assumed to be the same
6463
- if (!currentFrames && !previousFrames) {
6464
- return true;
6465
- }
6466
- // If only one event has a stacktrace, but not the other one, they are not the same
6467
- if ((currentFrames && !previousFrames) || (!currentFrames && previousFrames)) {
6468
- return false;
6469
- }
6470
- currentFrames = currentFrames;
6471
- previousFrames = previousFrames;
6472
- // If number of frames differ, they are not the same
6473
- if (previousFrames.length !== currentFrames.length) {
6474
- return false;
6475
- }
6476
- // Otherwise, compare the two
6477
- for (let i = 0; i < previousFrames.length; i++) {
6478
- const frameA = previousFrames[i];
6479
- const frameB = currentFrames[i];
6480
- if (frameA.filename !== frameB.filename ||
6481
- frameA.lineno !== frameB.lineno ||
6482
- frameA.colno !== frameB.colno ||
6483
- frameA.function !== frameB.function) {
6484
- return false;
6485
- }
6486
- }
6300
+ return false;
6301
+ }
6302
+ /** JSDoc */
6303
+ function _isSameMessageEvent(currentEvent, previousEvent) {
6304
+ const currentMessage = currentEvent.message;
6305
+ const previousMessage = previousEvent.message;
6306
+ // If neither event has a message property, they were both exceptions, so bail out
6307
+ if (!currentMessage && !previousMessage) {
6308
+ return false;
6309
+ }
6310
+ // If only one event has a stacktrace, but not the other one, they are not the same
6311
+ if ((currentMessage && !previousMessage) || (!currentMessage && previousMessage)) {
6312
+ return false;
6313
+ }
6314
+ if (currentMessage !== previousMessage) {
6315
+ return false;
6316
+ }
6317
+ if (!_isSameFingerprint(currentEvent, previousEvent)) {
6318
+ return false;
6319
+ }
6320
+ if (!_isSameStacktrace(currentEvent, previousEvent)) {
6321
+ return false;
6322
+ }
6323
+ return true;
6324
+ }
6325
+ /** JSDoc */
6326
+ function _isSameExceptionEvent(currentEvent, previousEvent) {
6327
+ const previousException = _getExceptionFromEvent(previousEvent);
6328
+ const currentException = _getExceptionFromEvent(currentEvent);
6329
+ if (!previousException || !currentException) {
6330
+ return false;
6331
+ }
6332
+ if (previousException.type !== currentException.type || previousException.value !== currentException.value) {
6333
+ return false;
6334
+ }
6335
+ if (!_isSameFingerprint(currentEvent, previousEvent)) {
6336
+ return false;
6337
+ }
6338
+ if (!_isSameStacktrace(currentEvent, previousEvent)) {
6339
+ return false;
6340
+ }
6341
+ return true;
6342
+ }
6343
+ /** JSDoc */
6344
+ function _isSameStacktrace(currentEvent, previousEvent) {
6345
+ let currentFrames = _getFramesFromEvent(currentEvent);
6346
+ let previousFrames = _getFramesFromEvent(previousEvent);
6347
+ // If neither event has a stacktrace, they are assumed to be the same
6348
+ if (!currentFrames && !previousFrames) {
6487
6349
  return true;
6488
6350
  }
6489
- /** JSDoc */
6490
- _getExceptionFromEvent(event) {
6491
- return event.exception && event.exception.values && event.exception.values[0];
6351
+ // If only one event has a stacktrace, but not the other one, they are not the same
6352
+ if ((currentFrames && !previousFrames) || (!currentFrames && previousFrames)) {
6353
+ return false;
6492
6354
  }
6493
- /** JSDoc */
6494
- _isSameExceptionEvent(currentEvent, previousEvent) {
6495
- const previousException = this._getExceptionFromEvent(previousEvent);
6496
- const currentException = this._getExceptionFromEvent(currentEvent);
6497
- if (!previousException || !currentException) {
6498
- return false;
6499
- }
6500
- if (previousException.type !== currentException.type || previousException.value !== currentException.value) {
6501
- return false;
6502
- }
6503
- if (!this._isSameFingerprint(currentEvent, previousEvent)) {
6504
- return false;
6505
- }
6506
- if (!this._isSameStacktrace(currentEvent, previousEvent)) {
6355
+ currentFrames = currentFrames;
6356
+ previousFrames = previousFrames;
6357
+ // If number of frames differ, they are not the same
6358
+ if (previousFrames.length !== currentFrames.length) {
6359
+ return false;
6360
+ }
6361
+ // Otherwise, compare the two
6362
+ for (let i = 0; i < previousFrames.length; i++) {
6363
+ const frameA = previousFrames[i];
6364
+ const frameB = currentFrames[i];
6365
+ if (frameA.filename !== frameB.filename ||
6366
+ frameA.lineno !== frameB.lineno ||
6367
+ frameA.colno !== frameB.colno ||
6368
+ frameA.function !== frameB.function) {
6507
6369
  return false;
6508
6370
  }
6371
+ }
6372
+ return true;
6373
+ }
6374
+ /** JSDoc */
6375
+ function _isSameFingerprint(currentEvent, previousEvent) {
6376
+ let currentFingerprint = currentEvent.fingerprint;
6377
+ let previousFingerprint = previousEvent.fingerprint;
6378
+ // If neither event has a fingerprint, they are assumed to be the same
6379
+ if (!currentFingerprint && !previousFingerprint) {
6509
6380
  return true;
6510
6381
  }
6511
- /** JSDoc */
6512
- _isSameFingerprint(currentEvent, previousEvent) {
6513
- let currentFingerprint = currentEvent.fingerprint;
6514
- let previousFingerprint = previousEvent.fingerprint;
6515
- // If neither event has a fingerprint, they are assumed to be the same
6516
- if (!currentFingerprint && !previousFingerprint) {
6517
- return true;
6518
- }
6519
- // If only one event has a fingerprint, but not the other one, they are not the same
6520
- if ((currentFingerprint && !previousFingerprint) || (!currentFingerprint && previousFingerprint)) {
6521
- return false;
6522
- }
6523
- currentFingerprint = currentFingerprint;
6524
- previousFingerprint = previousFingerprint;
6525
- // Otherwise, compare the two
6382
+ // If only one event has a fingerprint, but not the other one, they are not the same
6383
+ if ((currentFingerprint && !previousFingerprint) || (!currentFingerprint && previousFingerprint)) {
6384
+ return false;
6385
+ }
6386
+ currentFingerprint = currentFingerprint;
6387
+ previousFingerprint = previousFingerprint;
6388
+ // Otherwise, compare the two
6389
+ try {
6390
+ return !!(currentFingerprint.join('') === previousFingerprint.join(''));
6391
+ }
6392
+ catch (_oO) {
6393
+ return false;
6394
+ }
6395
+ }
6396
+ /** JSDoc */
6397
+ function _getExceptionFromEvent(event) {
6398
+ return event.exception && event.exception.values && event.exception.values[0];
6399
+ }
6400
+ /** JSDoc */
6401
+ function _getFramesFromEvent(event) {
6402
+ const exception = event.exception;
6403
+ if (exception) {
6526
6404
  try {
6527
- return !!(currentFingerprint.join('') === previousFingerprint.join(''));
6405
+ // @ts-ignore Object could be undefined
6406
+ return exception.values[0].stacktrace.frames;
6528
6407
  }
6529
6408
  catch (_oO) {
6530
- return false;
6409
+ return undefined;
6531
6410
  }
6532
6411
  }
6533
- }
6534
- /**
6535
- * @inheritDoc
6536
- */
6537
- Dedupe.id = 'Dedupe';
6412
+ else if (event.stacktrace) {
6413
+ return event.stacktrace.frames;
6414
+ }
6415
+ return undefined;
6416
+ }
6538
6417
 
6539
6418
 
6540
6419
 
@@ -6753,8 +6632,10 @@ var Sentry = (function (exports) {
6753
6632
  if (client) {
6754
6633
  return client.flush(timeout);
6755
6634
  }
6756
- logger.warn('Cannot flush events. No client defined.');
6757
- return SyncPromise.resolve(false);
6635
+ if (isDebugBuild()) {
6636
+ logger.warn('Cannot flush events. No client defined.');
6637
+ }
6638
+ return resolvedSyncPromise(false);
6758
6639
  }
6759
6640
  /**
6760
6641
  * Call `close()` on the current client, if there is one. See {@link Client.close}.
@@ -6769,8 +6650,10 @@ var Sentry = (function (exports) {
6769
6650
  if (client) {
6770
6651
  return client.close(timeout);
6771
6652
  }
6772
- logger.warn('Cannot flush events and disable SDK. No client defined.');
6773
- return SyncPromise.resolve(false);
6653
+ if (isDebugBuild()) {
6654
+ logger.warn('Cannot flush events and disable SDK. No client defined.');
6655
+ }
6656
+ return resolvedSyncPromise(false);
6774
6657
  }
6775
6658
  /**
6776
6659
  * Wrap code within a try/catch block so the SDK is able to capture errors.
@@ -6783,6 +6666,10 @@ var Sentry = (function (exports) {
6783
6666
  function wrap$1(fn) {
6784
6667
  return wrap(fn)();
6785
6668
  }
6669
+ function startSessionOnHub(hub) {
6670
+ hub.startSession({ ignoreDuration: true });
6671
+ hub.captureSession();
6672
+ }
6786
6673
  /**
6787
6674
  * Enable automatic Session Tracking for the initial page load.
6788
6675
  */
@@ -6790,7 +6677,9 @@ var Sentry = (function (exports) {
6790
6677
  const window = getGlobalObject();
6791
6678
  const document = window.document;
6792
6679
  if (typeof document === 'undefined') {
6793
- logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.');
6680
+ if (isDebugBuild()) {
6681
+ logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.');
6682
+ }
6794
6683
  return;
6795
6684
  }
6796
6685
  const hub = getCurrentHub();
@@ -6800,26 +6689,20 @@ var Sentry = (function (exports) {
6800
6689
  // https://github.com/getsentry/sentry-javascript/issues/3207 and
6801
6690
  // https://github.com/getsentry/sentry-javascript/issues/3234 and
6802
6691
  // https://github.com/getsentry/sentry-javascript/issues/3278.
6803
- if (typeof hub.startSession !== 'function' || typeof hub.captureSession !== 'function') {
6692
+ if (!hub.captureSession) {
6804
6693
  return;
6805
6694
  }
6806
6695
  // The session duration for browser sessions does not track a meaningful
6807
6696
  // concept that can be used as a metric.
6808
6697
  // Automatically captured sessions are akin to page views, and thus we
6809
6698
  // discard their duration.
6810
- hub.startSession({ ignoreDuration: true });
6811
- hub.captureSession();
6699
+ startSessionOnHub(hub);
6812
6700
  // We want to create a session for every navigation as well
6813
- addInstrumentationHandler({
6814
- callback: ({ from, to }) => {
6815
- // Don't create an additional session for the initial route or if the location did not change
6816
- if (from === undefined || from === to) {
6817
- return;
6818
- }
6819
- hub.startSession({ ignoreDuration: true });
6820
- hub.captureSession();
6821
- },
6822
- type: 'history',
6701
+ addInstrumentationHandler('history', ({ from, to }) => {
6702
+ // Don't create an additional session for the initial route or if the location did not change
6703
+ if (!(from === undefined || from === to)) {
6704
+ startSessionOnHub(getCurrentHub());
6705
+ }
6823
6706
  });
6824
6707
  }
6825
6708