@sentry/browser 5.25.0-beta.2 → 5.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- /*! @sentry/browser 5.25.0-beta.2 (84e835c) | https://github.com/getsentry/sentry-javascript */
1
+ /*! @sentry/browser 5.25.0 (bca2c59) | https://github.com/getsentry/sentry-javascript */
2
2
  var Sentry = (function (exports) {
3
3
  /** Console logging verbosity for the SDK. */
4
4
  var LogLevel;
@@ -13,21 +13,6 @@ var Sentry = (function (exports) {
13
13
  LogLevel[LogLevel["Verbose"] = 3] = "Verbose";
14
14
  })(LogLevel || (LogLevel = {}));
15
15
 
16
- /**
17
- * Session Status
18
- */
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
-
31
16
  /** JSDoc */
32
17
  (function (Severity) {
33
18
  /** JSDoc */
@@ -853,26 +838,6 @@ var Sentry = (function (exports) {
853
838
  return truncate(serialized, maxLength);
854
839
  }
855
840
  return '';
856
- }
857
- /**
858
- * Given any object, return the new object with removed keys that value was `undefined`.
859
- * Works recursively on objects and arrays.
860
- */
861
- function dropUndefinedKeys(val) {
862
- if (isPlainObject(val)) {
863
- const obj = val;
864
- const rv = {};
865
- for (const key of Object.keys(obj)) {
866
- if (typeof obj[key] !== 'undefined') {
867
- rv[key] = dropUndefinedKeys(obj[key]);
868
- }
869
- }
870
- return rv;
871
- }
872
- if (Array.isArray(val)) {
873
- return val.map(dropUndefinedKeys);
874
- }
875
- return val;
876
841
  }
877
842
 
878
843
  /**
@@ -909,13 +874,6 @@ var Sentry = (function (exports) {
909
874
  ? self
910
875
  : fallbackGlobalObject);
911
876
  }
912
- /**
913
- * Determines if running in react native
914
- */
915
- function isReactNative() {
916
- var _a;
917
- return ((_a = getGlobalObject().navigator) === null || _a === void 0 ? void 0 : _a.product) === 'ReactNative';
918
- }
919
877
  /**
920
878
  * UUID4 generator
921
879
  *
@@ -1067,73 +1025,6 @@ var Sentry = (function (exports) {
1067
1025
  return '';
1068
1026
  }
1069
1027
  }
1070
- const INITIAL_TIME = Date.now();
1071
- let prevNow = 0;
1072
- const performanceFallback = {
1073
- now() {
1074
- let now = Date.now() - INITIAL_TIME;
1075
- if (now < prevNow) {
1076
- now = prevNow;
1077
- }
1078
- prevNow = now;
1079
- return now;
1080
- },
1081
- timeOrigin: INITIAL_TIME,
1082
- };
1083
- /**
1084
- * Performance wrapper for react native as performance.now() has been found to start off with an unusual offset.
1085
- */
1086
- function getReactNativePerformanceWrapper() {
1087
- // Performance only available >= RN 0.63
1088
- const { performance } = getGlobalObject();
1089
- if (performance && typeof performance.now === 'function') {
1090
- const INITIAL_OFFSET = performance.now();
1091
- return {
1092
- now() {
1093
- return performance.now() - INITIAL_OFFSET;
1094
- },
1095
- timeOrigin: INITIAL_TIME,
1096
- };
1097
- }
1098
- return performanceFallback;
1099
- }
1100
- const crossPlatformPerformance = (() => {
1101
- // React Native's performance.now() starts with a gigantic offset, so we need to wrap it.
1102
- if (isReactNative()) {
1103
- return getReactNativePerformanceWrapper();
1104
- }
1105
- if (isNodeEnv()) {
1106
- try {
1107
- const perfHooks = dynamicRequire(module, 'perf_hooks');
1108
- return perfHooks.performance;
1109
- }
1110
- catch (_) {
1111
- return performanceFallback;
1112
- }
1113
- }
1114
- const { performance } = getGlobalObject();
1115
- if (!performance || !performance.now) {
1116
- return performanceFallback;
1117
- }
1118
- // Polyfill for performance.timeOrigin.
1119
- //
1120
- // While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin
1121
- // is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.
1122
- if (performance.timeOrigin === undefined) {
1123
- // As of writing, performance.timing is not available in Web Workers in mainstream browsers, so it is not always a
1124
- // valid fallback. In the absence of a initial time provided by the browser, fallback to INITIAL_TIME.
1125
- // @ts-ignore ignored because timeOrigin is a readonly property but we want to override
1126
- // eslint-disable-next-line deprecation/deprecation
1127
- performance.timeOrigin = (performance.timing && performance.timing.navigationStart) || INITIAL_TIME;
1128
- }
1129
- return performance;
1130
- })();
1131
- /**
1132
- * Returns a timestamp in seconds with milliseconds precision since the UNIX epoch calculated with the monotonic clock.
1133
- */
1134
- function timestampWithMs() {
1135
- return (crossPlatformPerformance.timeOrigin + crossPlatformPerformance.now()) / 1000;
1136
- }
1137
1028
  const defaultRetryAfter = 60 * 1000; // 60 seconds
1138
1029
  /**
1139
1030
  * Extracts Retry-After value from the request header or returns default value
@@ -1206,359 +1097,93 @@ var Sentry = (function (exports) {
1206
1097
  global$1.__SENTRY__ = global$1.__SENTRY__ || {};
1207
1098
  const logger = global$1.__SENTRY__.logger || (global$1.__SENTRY__.logger = new Logger());
1208
1099
 
1209
- /* eslint-disable @typescript-eslint/explicit-function-return-type */
1210
- /** SyncPromise internal states */
1211
- var States;
1212
- (function (States) {
1213
- /** Pending */
1214
- States["PENDING"] = "PENDING";
1215
- /** Resolved / OK */
1216
- States["RESOLVED"] = "RESOLVED";
1217
- /** Rejected / Error */
1218
- States["REJECTED"] = "REJECTED";
1219
- })(States || (States = {}));
1220
1100
  /**
1221
- * Thenable class that behaves like a Promise and follows it's interface
1222
- * but is not async internally
1101
+ * Tells whether current environment supports Fetch API
1102
+ * {@link supportsFetch}.
1103
+ *
1104
+ * @returns Answer to the given question.
1223
1105
  */
1224
- class SyncPromise {
1225
- constructor(executor) {
1226
- this._state = States.PENDING;
1227
- this._handlers = [];
1228
- /** JSDoc */
1229
- this._resolve = (value) => {
1230
- this._setResult(States.RESOLVED, value);
1231
- };
1232
- /** JSDoc */
1233
- this._reject = (reason) => {
1234
- this._setResult(States.REJECTED, reason);
1235
- };
1236
- /** JSDoc */
1237
- this._setResult = (state, value) => {
1238
- if (this._state !== States.PENDING) {
1239
- return;
1240
- }
1241
- if (isThenable(value)) {
1242
- value.then(this._resolve, this._reject);
1243
- return;
1244
- }
1245
- this._state = state;
1246
- this._value = value;
1247
- this._executeHandlers();
1248
- };
1249
- // TODO: FIXME
1250
- /** JSDoc */
1251
- this._attachHandler = (handler) => {
1252
- this._handlers = this._handlers.concat(handler);
1253
- this._executeHandlers();
1254
- };
1255
- /** JSDoc */
1256
- this._executeHandlers = () => {
1257
- if (this._state === States.PENDING) {
1258
- return;
1259
- }
1260
- const cachedHandlers = this._handlers.slice();
1261
- this._handlers = [];
1262
- cachedHandlers.forEach(handler => {
1263
- if (handler.done) {
1264
- return;
1265
- }
1266
- if (this._state === States.RESOLVED) {
1267
- if (handler.onfulfilled) {
1268
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
1269
- handler.onfulfilled(this._value);
1270
- }
1271
- }
1272
- if (this._state === States.REJECTED) {
1273
- if (handler.onrejected) {
1274
- handler.onrejected(this._value);
1275
- }
1276
- }
1277
- handler.done = true;
1278
- });
1279
- };
1106
+ function supportsFetch() {
1107
+ if (!('fetch' in getGlobalObject())) {
1108
+ return false;
1109
+ }
1110
+ try {
1111
+ new Headers();
1112
+ new Request('');
1113
+ new Response();
1114
+ return true;
1115
+ }
1116
+ catch (e) {
1117
+ return false;
1118
+ }
1119
+ }
1120
+ /**
1121
+ * isNativeFetch checks if the given function is a native implementation of fetch()
1122
+ */
1123
+ // eslint-disable-next-line @typescript-eslint/ban-types
1124
+ function isNativeFetch(func) {
1125
+ return func && /^function fetch\(\)\s+\{\s+\[native code\]\s+\}$/.test(func.toString());
1126
+ }
1127
+ /**
1128
+ * Tells whether current environment supports Fetch API natively
1129
+ * {@link supportsNativeFetch}.
1130
+ *
1131
+ * @returns true if `window.fetch` is natively implemented, false otherwise
1132
+ */
1133
+ function supportsNativeFetch() {
1134
+ if (!supportsFetch()) {
1135
+ return false;
1136
+ }
1137
+ const global = getGlobalObject();
1138
+ // Fast path to avoid DOM I/O
1139
+ // eslint-disable-next-line @typescript-eslint/unbound-method
1140
+ if (isNativeFetch(global.fetch)) {
1141
+ return true;
1142
+ }
1143
+ // window.fetch is implemented, but is polyfilled or already wrapped (e.g: by a chrome extension)
1144
+ // so create a "pure" iframe to see if that has native fetch
1145
+ let result = false;
1146
+ const doc = global.document;
1147
+ // eslint-disable-next-line deprecation/deprecation
1148
+ if (doc && typeof doc.createElement === `function`) {
1280
1149
  try {
1281
- executor(this._resolve, this._reject);
1150
+ const sandbox = doc.createElement('iframe');
1151
+ sandbox.hidden = true;
1152
+ doc.head.appendChild(sandbox);
1153
+ if (sandbox.contentWindow && sandbox.contentWindow.fetch) {
1154
+ // eslint-disable-next-line @typescript-eslint/unbound-method
1155
+ result = isNativeFetch(sandbox.contentWindow.fetch);
1156
+ }
1157
+ doc.head.removeChild(sandbox);
1282
1158
  }
1283
- catch (e) {
1284
- this._reject(e);
1159
+ catch (err) {
1160
+ logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err);
1285
1161
  }
1286
1162
  }
1287
- /** JSDoc */
1288
- static resolve(value) {
1289
- return new SyncPromise(resolve => {
1290
- resolve(value);
1291
- });
1163
+ return result;
1164
+ }
1165
+ /**
1166
+ * Tells whether current environment supports Referrer Policy API
1167
+ * {@link supportsReferrerPolicy}.
1168
+ *
1169
+ * @returns Answer to the given question.
1170
+ */
1171
+ function supportsReferrerPolicy() {
1172
+ // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default
1173
+ // https://caniuse.com/#feat=referrer-policy
1174
+ // It doesn't. And it throw exception instead of ignoring this parameter...
1175
+ // REF: https://github.com/getsentry/raven-js/issues/1233
1176
+ if (!supportsFetch()) {
1177
+ return false;
1292
1178
  }
1293
- /** JSDoc */
1294
- static reject(reason) {
1295
- return new SyncPromise((_, reject) => {
1296
- reject(reason);
1179
+ try {
1180
+ new Request('_', {
1181
+ referrerPolicy: 'origin',
1297
1182
  });
1183
+ return true;
1298
1184
  }
1299
- /** JSDoc */
1300
- static all(collection) {
1301
- return new SyncPromise((resolve, reject) => {
1302
- if (!Array.isArray(collection)) {
1303
- reject(new TypeError(`Promise.all requires an array as input.`));
1304
- return;
1305
- }
1306
- if (collection.length === 0) {
1307
- resolve([]);
1308
- return;
1309
- }
1310
- let counter = collection.length;
1311
- const resolvedCollection = [];
1312
- collection.forEach((item, index) => {
1313
- SyncPromise.resolve(item)
1314
- .then(value => {
1315
- resolvedCollection[index] = value;
1316
- counter -= 1;
1317
- if (counter !== 0) {
1318
- return;
1319
- }
1320
- resolve(resolvedCollection);
1321
- })
1322
- .then(null, reject);
1323
- });
1324
- });
1325
- }
1326
- /** JSDoc */
1327
- then(onfulfilled, onrejected) {
1328
- return new SyncPromise((resolve, reject) => {
1329
- this._attachHandler({
1330
- done: false,
1331
- onfulfilled: result => {
1332
- if (!onfulfilled) {
1333
- // TODO: ¯\_(ツ)_/¯
1334
- // TODO: FIXME
1335
- resolve(result);
1336
- return;
1337
- }
1338
- try {
1339
- resolve(onfulfilled(result));
1340
- return;
1341
- }
1342
- catch (e) {
1343
- reject(e);
1344
- return;
1345
- }
1346
- },
1347
- onrejected: reason => {
1348
- if (!onrejected) {
1349
- reject(reason);
1350
- return;
1351
- }
1352
- try {
1353
- resolve(onrejected(reason));
1354
- return;
1355
- }
1356
- catch (e) {
1357
- reject(e);
1358
- return;
1359
- }
1360
- },
1361
- });
1362
- });
1363
- }
1364
- /** JSDoc */
1365
- catch(onrejected) {
1366
- return this.then(val => val, onrejected);
1367
- }
1368
- /** JSDoc */
1369
- finally(onfinally) {
1370
- return new SyncPromise((resolve, reject) => {
1371
- let val;
1372
- let isRejected;
1373
- return this.then(value => {
1374
- isRejected = false;
1375
- val = value;
1376
- if (onfinally) {
1377
- onfinally();
1378
- }
1379
- }, reason => {
1380
- isRejected = true;
1381
- val = reason;
1382
- if (onfinally) {
1383
- onfinally();
1384
- }
1385
- }).then(() => {
1386
- if (isRejected) {
1387
- reject(val);
1388
- return;
1389
- }
1390
- resolve(val);
1391
- });
1392
- });
1393
- }
1394
- /** JSDoc */
1395
- toString() {
1396
- return '[object SyncPromise]';
1397
- }
1398
- }
1399
-
1400
- /** A simple queue that holds promises. */
1401
- class PromiseBuffer {
1402
- constructor(_limit) {
1403
- this._limit = _limit;
1404
- /** Internal set of queued Promises */
1405
- this._buffer = [];
1406
- }
1407
- /**
1408
- * Says if the buffer is ready to take more requests
1409
- */
1410
- isReady() {
1411
- return this._limit === undefined || this.length() < this._limit;
1412
- }
1413
- /**
1414
- * Add a promise to the queue.
1415
- *
1416
- * @param task Can be any PromiseLike<T>
1417
- * @returns The original promise.
1418
- */
1419
- add(task) {
1420
- if (!this.isReady()) {
1421
- return SyncPromise.reject(new SentryError('Not adding Promise due to buffer limit reached.'));
1422
- }
1423
- if (this._buffer.indexOf(task) === -1) {
1424
- this._buffer.push(task);
1425
- }
1426
- task
1427
- .then(() => this.remove(task))
1428
- .then(null, () => this.remove(task).then(null, () => {
1429
- // We have to add this catch here otherwise we have an unhandledPromiseRejection
1430
- // because it's a new Promise chain.
1431
- }));
1432
- return task;
1433
- }
1434
- /**
1435
- * Remove a promise to the queue.
1436
- *
1437
- * @param task Can be any PromiseLike<T>
1438
- * @returns Removed promise.
1439
- */
1440
- remove(task) {
1441
- const removedTask = this._buffer.splice(this._buffer.indexOf(task), 1)[0];
1442
- return removedTask;
1443
- }
1444
- /**
1445
- * This function returns the number of unresolved promises in the queue.
1446
- */
1447
- length() {
1448
- return this._buffer.length;
1449
- }
1450
- /**
1451
- * This will drain the whole queue, returns true if queue is empty or drained.
1452
- * If timeout is provided and the queue takes longer to drain, the promise still resolves but with false.
1453
- *
1454
- * @param timeout Number in ms to wait until it resolves with false.
1455
- */
1456
- drain(timeout) {
1457
- return new SyncPromise(resolve => {
1458
- const capturedSetTimeout = setTimeout(() => {
1459
- if (timeout && timeout > 0) {
1460
- resolve(false);
1461
- }
1462
- }, timeout);
1463
- SyncPromise.all(this._buffer)
1464
- .then(() => {
1465
- clearTimeout(capturedSetTimeout);
1466
- resolve(true);
1467
- })
1468
- .then(null, () => {
1469
- resolve(true);
1470
- });
1471
- });
1472
- }
1473
- }
1474
-
1475
- /**
1476
- * Tells whether current environment supports Fetch API
1477
- * {@link supportsFetch}.
1478
- *
1479
- * @returns Answer to the given question.
1480
- */
1481
- function supportsFetch() {
1482
- if (!('fetch' in getGlobalObject())) {
1483
- return false;
1484
- }
1485
- try {
1486
- new Headers();
1487
- new Request('');
1488
- new Response();
1489
- return true;
1490
- }
1491
- catch (e) {
1492
- return false;
1493
- }
1494
- }
1495
- /**
1496
- * isNativeFetch checks if the given function is a native implementation of fetch()
1497
- */
1498
- // eslint-disable-next-line @typescript-eslint/ban-types
1499
- function isNativeFetch(func) {
1500
- return func && /^function fetch\(\)\s+\{\s+\[native code\]\s+\}$/.test(func.toString());
1501
- }
1502
- /**
1503
- * Tells whether current environment supports Fetch API natively
1504
- * {@link supportsNativeFetch}.
1505
- *
1506
- * @returns true if `window.fetch` is natively implemented, false otherwise
1507
- */
1508
- function supportsNativeFetch() {
1509
- if (!supportsFetch()) {
1510
- return false;
1511
- }
1512
- const global = getGlobalObject();
1513
- // Fast path to avoid DOM I/O
1514
- // eslint-disable-next-line @typescript-eslint/unbound-method
1515
- if (isNativeFetch(global.fetch)) {
1516
- return true;
1517
- }
1518
- // window.fetch is implemented, but is polyfilled or already wrapped (e.g: by a chrome extension)
1519
- // so create a "pure" iframe to see if that has native fetch
1520
- let result = false;
1521
- const doc = global.document;
1522
- // eslint-disable-next-line deprecation/deprecation
1523
- if (doc && typeof doc.createElement === `function`) {
1524
- try {
1525
- const sandbox = doc.createElement('iframe');
1526
- sandbox.hidden = true;
1527
- doc.head.appendChild(sandbox);
1528
- if (sandbox.contentWindow && sandbox.contentWindow.fetch) {
1529
- // eslint-disable-next-line @typescript-eslint/unbound-method
1530
- result = isNativeFetch(sandbox.contentWindow.fetch);
1531
- }
1532
- doc.head.removeChild(sandbox);
1533
- }
1534
- catch (err) {
1535
- logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err);
1536
- }
1537
- }
1538
- return result;
1539
- }
1540
- /**
1541
- * Tells whether current environment supports Referrer Policy API
1542
- * {@link supportsReferrerPolicy}.
1543
- *
1544
- * @returns Answer to the given question.
1545
- */
1546
- function supportsReferrerPolicy() {
1547
- // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default
1548
- // https://caniuse.com/#feat=referrer-policy
1549
- // It doesn't. And it throw exception instead of ignoring this parameter...
1550
- // REF: https://github.com/getsentry/raven-js/issues/1233
1551
- if (!supportsFetch()) {
1552
- return false;
1553
- }
1554
- try {
1555
- new Request('_', {
1556
- referrerPolicy: 'origin',
1557
- });
1558
- return true;
1559
- }
1560
- catch (e) {
1561
- return false;
1185
+ catch (e) {
1186
+ return false;
1562
1187
  }
1563
1188
  }
1564
1189
  /**
@@ -1680,7 +1305,7 @@ var Sentry = (function (exports) {
1680
1305
  }
1681
1306
  fill(global$2, 'fetch', function (originalFetch) {
1682
1307
  return function (...args) {
1683
- const commonHandlerData = {
1308
+ const handlerData = {
1684
1309
  args,
1685
1310
  fetchData: {
1686
1311
  method: getFetchMethod(args),
@@ -1688,13 +1313,13 @@ var Sentry = (function (exports) {
1688
1313
  },
1689
1314
  startTimestamp: Date.now(),
1690
1315
  };
1691
- triggerHandlers('fetch', Object.assign({}, commonHandlerData));
1316
+ triggerHandlers('fetch', Object.assign({}, handlerData));
1692
1317
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
1693
1318
  return originalFetch.apply(global$2, args).then((response) => {
1694
- triggerHandlers('fetch', Object.assign(Object.assign({}, commonHandlerData), { endTimestamp: Date.now(), response }));
1319
+ triggerHandlers('fetch', Object.assign(Object.assign({}, handlerData), { endTimestamp: Date.now(), response }));
1695
1320
  return response;
1696
1321
  }, (error) => {
1697
- triggerHandlers('fetch', Object.assign(Object.assign({}, commonHandlerData), { endTimestamp: Date.now(), error }));
1322
+ triggerHandlers('fetch', Object.assign(Object.assign({}, handlerData), { endTimestamp: Date.now(), error }));
1698
1323
  // NOTE: If you are a Sentry user, and you are seeing this stack frame,
1699
1324
  // it means the sentry.javascript SDK caught an error invoking your application code.
1700
1325
  // This is expected behavior and NOT indicative of a bug with sentry.javascript.
@@ -1730,7 +1355,7 @@ var Sentry = (function (exports) {
1730
1355
  if (!('XMLHttpRequest' in global$2)) {
1731
1356
  return;
1732
1357
  }
1733
- // Poor man implementation of ES6 `Map` by tracking and keeping in sync key and value separately.
1358
+ // Poor man's implementation of ES6 `Map`, tracking and keeping in sync key and value separately.
1734
1359
  const requestKeys = [];
1735
1360
  const requestValues = [];
1736
1361
  const xhrproto = XMLHttpRequest.prototype;
@@ -1764,7 +1389,7 @@ var Sentry = (function (exports) {
1764
1389
  try {
1765
1390
  const requestPos = requestKeys.indexOf(xhr);
1766
1391
  if (requestPos !== -1) {
1767
- // Make sure to pop both, key and value to keep it in sync.
1392
+ // Make sure to pop both key and value to keep it in sync.
1768
1393
  requestKeys.splice(requestPos);
1769
1394
  const args = requestValues.splice(requestPos)[0];
1770
1395
  if (xhr.__sentry_xhr__ && args[0] !== undefined) {
@@ -1952,75 +1577,448 @@ var Sentry = (function (exports) {
1952
1577
  };
1953
1578
  }
1954
1579
  /**
1955
- * Wraps addEventListener to capture keypress UI events
1956
- * @param handler function that will be triggered
1957
- * @returns wrapped keypress events handler
1958
- * @hidden
1580
+ * Wraps addEventListener to capture keypress UI events
1581
+ * @param handler function that will be triggered
1582
+ * @returns wrapped keypress events handler
1583
+ * @hidden
1584
+ */
1585
+ function keypressEventHandler(handler) {
1586
+ // TODO: if somehow user switches keypress target before
1587
+ // debounce timeout is triggered, we will only capture
1588
+ // a single breadcrumb from the FIRST target (acceptable?)
1589
+ return (event) => {
1590
+ let target;
1591
+ try {
1592
+ target = event.target;
1593
+ }
1594
+ catch (e) {
1595
+ // just accessing event properties can throw an exception in some rare circumstances
1596
+ // see: https://github.com/getsentry/raven-js/issues/838
1597
+ return;
1598
+ }
1599
+ const tagName = target && target.tagName;
1600
+ // only consider keypress events on actual input elements
1601
+ // this will disregard keypresses targeting body (e.g. tabbing
1602
+ // through elements, hotkeys, etc)
1603
+ if (!tagName || (tagName !== 'INPUT' && tagName !== 'TEXTAREA' && !target.isContentEditable)) {
1604
+ return;
1605
+ }
1606
+ // record first keypress in a series, but ignore subsequent
1607
+ // keypresses until debounce clears
1608
+ if (!keypressTimeout) {
1609
+ domEventHandler('input', handler)(event);
1610
+ }
1611
+ clearTimeout(keypressTimeout);
1612
+ keypressTimeout = setTimeout(() => {
1613
+ keypressTimeout = undefined;
1614
+ }, debounceDuration);
1615
+ };
1616
+ }
1617
+ let _oldOnErrorHandler = null;
1618
+ /** JSDoc */
1619
+ function instrumentError() {
1620
+ _oldOnErrorHandler = global$2.onerror;
1621
+ global$2.onerror = function (msg, url, line, column, error) {
1622
+ triggerHandlers('error', {
1623
+ column,
1624
+ error,
1625
+ line,
1626
+ msg,
1627
+ url,
1628
+ });
1629
+ if (_oldOnErrorHandler) {
1630
+ // eslint-disable-next-line prefer-rest-params
1631
+ return _oldOnErrorHandler.apply(this, arguments);
1632
+ }
1633
+ return false;
1634
+ };
1635
+ }
1636
+ let _oldOnUnhandledRejectionHandler = null;
1637
+ /** JSDoc */
1638
+ function instrumentUnhandledRejection() {
1639
+ _oldOnUnhandledRejectionHandler = global$2.onunhandledrejection;
1640
+ global$2.onunhandledrejection = function (e) {
1641
+ triggerHandlers('unhandledrejection', e);
1642
+ if (_oldOnUnhandledRejectionHandler) {
1643
+ // eslint-disable-next-line prefer-rest-params
1644
+ return _oldOnUnhandledRejectionHandler.apply(this, arguments);
1645
+ }
1646
+ return true;
1647
+ };
1648
+ }
1649
+
1650
+ /* eslint-disable @typescript-eslint/explicit-function-return-type */
1651
+ /** SyncPromise internal states */
1652
+ var States;
1653
+ (function (States) {
1654
+ /** Pending */
1655
+ States["PENDING"] = "PENDING";
1656
+ /** Resolved / OK */
1657
+ States["RESOLVED"] = "RESOLVED";
1658
+ /** Rejected / Error */
1659
+ States["REJECTED"] = "REJECTED";
1660
+ })(States || (States = {}));
1661
+ /**
1662
+ * Thenable class that behaves like a Promise and follows it's interface
1663
+ * but is not async internally
1664
+ */
1665
+ class SyncPromise {
1666
+ constructor(executor) {
1667
+ this._state = States.PENDING;
1668
+ this._handlers = [];
1669
+ /** JSDoc */
1670
+ this._resolve = (value) => {
1671
+ this._setResult(States.RESOLVED, value);
1672
+ };
1673
+ /** JSDoc */
1674
+ this._reject = (reason) => {
1675
+ this._setResult(States.REJECTED, reason);
1676
+ };
1677
+ /** JSDoc */
1678
+ this._setResult = (state, value) => {
1679
+ if (this._state !== States.PENDING) {
1680
+ return;
1681
+ }
1682
+ if (isThenable(value)) {
1683
+ value.then(this._resolve, this._reject);
1684
+ return;
1685
+ }
1686
+ this._state = state;
1687
+ this._value = value;
1688
+ this._executeHandlers();
1689
+ };
1690
+ // TODO: FIXME
1691
+ /** JSDoc */
1692
+ this._attachHandler = (handler) => {
1693
+ this._handlers = this._handlers.concat(handler);
1694
+ this._executeHandlers();
1695
+ };
1696
+ /** JSDoc */
1697
+ this._executeHandlers = () => {
1698
+ if (this._state === States.PENDING) {
1699
+ return;
1700
+ }
1701
+ const cachedHandlers = this._handlers.slice();
1702
+ this._handlers = [];
1703
+ cachedHandlers.forEach(handler => {
1704
+ if (handler.done) {
1705
+ return;
1706
+ }
1707
+ if (this._state === States.RESOLVED) {
1708
+ if (handler.onfulfilled) {
1709
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
1710
+ handler.onfulfilled(this._value);
1711
+ }
1712
+ }
1713
+ if (this._state === States.REJECTED) {
1714
+ if (handler.onrejected) {
1715
+ handler.onrejected(this._value);
1716
+ }
1717
+ }
1718
+ handler.done = true;
1719
+ });
1720
+ };
1721
+ try {
1722
+ executor(this._resolve, this._reject);
1723
+ }
1724
+ catch (e) {
1725
+ this._reject(e);
1726
+ }
1727
+ }
1728
+ /** JSDoc */
1729
+ static resolve(value) {
1730
+ return new SyncPromise(resolve => {
1731
+ resolve(value);
1732
+ });
1733
+ }
1734
+ /** JSDoc */
1735
+ static reject(reason) {
1736
+ return new SyncPromise((_, reject) => {
1737
+ reject(reason);
1738
+ });
1739
+ }
1740
+ /** JSDoc */
1741
+ static all(collection) {
1742
+ return new SyncPromise((resolve, reject) => {
1743
+ if (!Array.isArray(collection)) {
1744
+ reject(new TypeError(`Promise.all requires an array as input.`));
1745
+ return;
1746
+ }
1747
+ if (collection.length === 0) {
1748
+ resolve([]);
1749
+ return;
1750
+ }
1751
+ let counter = collection.length;
1752
+ const resolvedCollection = [];
1753
+ collection.forEach((item, index) => {
1754
+ SyncPromise.resolve(item)
1755
+ .then(value => {
1756
+ resolvedCollection[index] = value;
1757
+ counter -= 1;
1758
+ if (counter !== 0) {
1759
+ return;
1760
+ }
1761
+ resolve(resolvedCollection);
1762
+ })
1763
+ .then(null, reject);
1764
+ });
1765
+ });
1766
+ }
1767
+ /** JSDoc */
1768
+ then(onfulfilled, onrejected) {
1769
+ return new SyncPromise((resolve, reject) => {
1770
+ this._attachHandler({
1771
+ done: false,
1772
+ onfulfilled: result => {
1773
+ if (!onfulfilled) {
1774
+ // TODO: ¯\_(ツ)_/¯
1775
+ // TODO: FIXME
1776
+ resolve(result);
1777
+ return;
1778
+ }
1779
+ try {
1780
+ resolve(onfulfilled(result));
1781
+ return;
1782
+ }
1783
+ catch (e) {
1784
+ reject(e);
1785
+ return;
1786
+ }
1787
+ },
1788
+ onrejected: reason => {
1789
+ if (!onrejected) {
1790
+ reject(reason);
1791
+ return;
1792
+ }
1793
+ try {
1794
+ resolve(onrejected(reason));
1795
+ return;
1796
+ }
1797
+ catch (e) {
1798
+ reject(e);
1799
+ return;
1800
+ }
1801
+ },
1802
+ });
1803
+ });
1804
+ }
1805
+ /** JSDoc */
1806
+ catch(onrejected) {
1807
+ return this.then(val => val, onrejected);
1808
+ }
1809
+ /** JSDoc */
1810
+ finally(onfinally) {
1811
+ return new SyncPromise((resolve, reject) => {
1812
+ let val;
1813
+ let isRejected;
1814
+ return this.then(value => {
1815
+ isRejected = false;
1816
+ val = value;
1817
+ if (onfinally) {
1818
+ onfinally();
1819
+ }
1820
+ }, reason => {
1821
+ isRejected = true;
1822
+ val = reason;
1823
+ if (onfinally) {
1824
+ onfinally();
1825
+ }
1826
+ }).then(() => {
1827
+ if (isRejected) {
1828
+ reject(val);
1829
+ return;
1830
+ }
1831
+ resolve(val);
1832
+ });
1833
+ });
1834
+ }
1835
+ /** JSDoc */
1836
+ toString() {
1837
+ return '[object SyncPromise]';
1838
+ }
1839
+ }
1840
+
1841
+ /** A simple queue that holds promises. */
1842
+ class PromiseBuffer {
1843
+ constructor(_limit) {
1844
+ this._limit = _limit;
1845
+ /** Internal set of queued Promises */
1846
+ this._buffer = [];
1847
+ }
1848
+ /**
1849
+ * Says if the buffer is ready to take more requests
1850
+ */
1851
+ isReady() {
1852
+ return this._limit === undefined || this.length() < this._limit;
1853
+ }
1854
+ /**
1855
+ * Add a promise to the queue.
1856
+ *
1857
+ * @param task Can be any PromiseLike<T>
1858
+ * @returns The original promise.
1859
+ */
1860
+ add(task) {
1861
+ if (!this.isReady()) {
1862
+ return SyncPromise.reject(new SentryError('Not adding Promise due to buffer limit reached.'));
1863
+ }
1864
+ if (this._buffer.indexOf(task) === -1) {
1865
+ this._buffer.push(task);
1866
+ }
1867
+ task
1868
+ .then(() => this.remove(task))
1869
+ .then(null, () => this.remove(task).then(null, () => {
1870
+ // We have to add this catch here otherwise we have an unhandledPromiseRejection
1871
+ // because it's a new Promise chain.
1872
+ }));
1873
+ return task;
1874
+ }
1875
+ /**
1876
+ * Remove a promise to the queue.
1877
+ *
1878
+ * @param task Can be any PromiseLike<T>
1879
+ * @returns Removed promise.
1880
+ */
1881
+ remove(task) {
1882
+ const removedTask = this._buffer.splice(this._buffer.indexOf(task), 1)[0];
1883
+ return removedTask;
1884
+ }
1885
+ /**
1886
+ * This function returns the number of unresolved promises in the queue.
1887
+ */
1888
+ length() {
1889
+ return this._buffer.length;
1890
+ }
1891
+ /**
1892
+ * This will drain the whole queue, returns true if queue is empty or drained.
1893
+ * If timeout is provided and the queue takes longer to drain, the promise still resolves but with false.
1894
+ *
1895
+ * @param timeout Number in ms to wait until it resolves with false.
1896
+ */
1897
+ drain(timeout) {
1898
+ return new SyncPromise(resolve => {
1899
+ const capturedSetTimeout = setTimeout(() => {
1900
+ if (timeout && timeout > 0) {
1901
+ resolve(false);
1902
+ }
1903
+ }, timeout);
1904
+ SyncPromise.all(this._buffer)
1905
+ .then(() => {
1906
+ clearTimeout(capturedSetTimeout);
1907
+ resolve(true);
1908
+ })
1909
+ .then(null, () => {
1910
+ resolve(true);
1911
+ });
1912
+ });
1913
+ }
1914
+ }
1915
+
1916
+ /**
1917
+ * A TimestampSource implementation for environments that do not support the Performance Web API natively.
1918
+ *
1919
+ * Note that this TimestampSource does not use a monotonic clock. A call to `nowSeconds` may return a timestamp earlier
1920
+ * than a previously returned value. We do not try to emulate a monotonic behavior in order to facilitate debugging. It
1921
+ * is more obvious to explain "why does my span have negative duration" than "why my spans have zero duration".
1922
+ */
1923
+ const dateTimestampSource = {
1924
+ nowSeconds: () => Date.now() / 1000,
1925
+ };
1926
+ /**
1927
+ * Returns a wrapper around the native Performance API browser implementation, or undefined for browsers that do not
1928
+ * support the API.
1929
+ *
1930
+ * Wrapping the native API works around differences in behavior from different browsers.
1931
+ */
1932
+ function getBrowserPerformance() {
1933
+ const { performance } = getGlobalObject();
1934
+ if (!performance || !performance.now) {
1935
+ return undefined;
1936
+ }
1937
+ // Replace performance.timeOrigin with our own timeOrigin based on Date.now().
1938
+ //
1939
+ // This is a partial workaround for browsers reporting performance.timeOrigin such that performance.timeOrigin +
1940
+ // performance.now() gives a date arbitrarily in the past.
1941
+ //
1942
+ // Additionally, computing timeOrigin in this way fills the gap for browsers where performance.timeOrigin is
1943
+ // undefined.
1944
+ //
1945
+ // The assumption that performance.timeOrigin + performance.now() ~= Date.now() is flawed, but we depend on it to
1946
+ // interact with data coming out of performance entries.
1947
+ //
1948
+ // Note that despite recommendations against it in the spec, browsers implement the Performance API with a clock that
1949
+ // might stop when the computer is asleep (and perhaps under other circumstances). Such behavior causes
1950
+ // performance.timeOrigin + performance.now() to have an arbitrary skew over Date.now(). In laptop computers, we have
1951
+ // observed skews that can be as long as days, weeks or months.
1952
+ //
1953
+ // See https://github.com/getsentry/sentry-javascript/issues/2590.
1954
+ //
1955
+ // BUG: despite our best intentions, this workaround has its limitations. It mostly addresses timings of pageload
1956
+ // transactions, but ignores the skew built up over time that can aversely affect timestamps of navigation
1957
+ // transactions of long-lived web pages.
1958
+ const timeOrigin = Date.now() - performance.now();
1959
+ return {
1960
+ now: () => performance.now(),
1961
+ timeOrigin,
1962
+ };
1963
+ }
1964
+ /**
1965
+ * Returns the native Performance API implementation from Node.js. Returns undefined in old Node.js versions that don't
1966
+ * implement the API.
1959
1967
  */
1960
- function keypressEventHandler(handler) {
1961
- // TODO: if somehow user switches keypress target before
1962
- // debounce timeout is triggered, we will only capture
1963
- // a single breadcrumb from the FIRST target (acceptable?)
1964
- return (event) => {
1965
- let target;
1966
- try {
1967
- target = event.target;
1968
- }
1969
- catch (e) {
1970
- // just accessing event properties can throw an exception in some rare circumstances
1971
- // see: https://github.com/getsentry/raven-js/issues/838
1972
- return;
1973
- }
1974
- const tagName = target && target.tagName;
1975
- // only consider keypress events on actual input elements
1976
- // this will disregard keypresses targeting body (e.g. tabbing
1977
- // through elements, hotkeys, etc)
1978
- if (!tagName || (tagName !== 'INPUT' && tagName !== 'TEXTAREA' && !target.isContentEditable)) {
1979
- return;
1980
- }
1981
- // record first keypress in a series, but ignore subsequent
1982
- // keypresses until debounce clears
1983
- if (!keypressTimeout) {
1984
- domEventHandler('input', handler)(event);
1985
- }
1986
- clearTimeout(keypressTimeout);
1987
- keypressTimeout = setTimeout(() => {
1988
- keypressTimeout = undefined;
1989
- }, debounceDuration);
1990
- };
1991
- }
1992
- let _oldOnErrorHandler = null;
1993
- /** JSDoc */
1994
- function instrumentError() {
1995
- _oldOnErrorHandler = global$2.onerror;
1996
- global$2.onerror = function (msg, url, line, column, error) {
1997
- triggerHandlers('error', {
1998
- column,
1999
- error,
2000
- line,
2001
- msg,
2002
- url,
2003
- });
2004
- if (_oldOnErrorHandler) {
2005
- // eslint-disable-next-line prefer-rest-params
2006
- return _oldOnErrorHandler.apply(this, arguments);
2007
- }
2008
- return false;
2009
- };
1968
+ function getNodePerformance() {
1969
+ try {
1970
+ const perfHooks = dynamicRequire(module, 'perf_hooks');
1971
+ return perfHooks.performance;
1972
+ }
1973
+ catch (_) {
1974
+ return undefined;
1975
+ }
2010
1976
  }
2011
- let _oldOnUnhandledRejectionHandler = null;
2012
- /** JSDoc */
2013
- function instrumentUnhandledRejection() {
2014
- _oldOnUnhandledRejectionHandler = global$2.onunhandledrejection;
2015
- global$2.onunhandledrejection = function (e) {
2016
- triggerHandlers('unhandledrejection', e);
2017
- if (_oldOnUnhandledRejectionHandler) {
2018
- // eslint-disable-next-line prefer-rest-params
2019
- return _oldOnUnhandledRejectionHandler.apply(this, arguments);
2020
- }
2021
- return true;
1977
+ /**
1978
+ * The Performance API implementation for the current platform, if available.
1979
+ */
1980
+ const platformPerformance = isNodeEnv() ? getNodePerformance() : getBrowserPerformance();
1981
+ const timestampSource = platformPerformance === undefined
1982
+ ? dateTimestampSource
1983
+ : {
1984
+ nowSeconds: () => (platformPerformance.timeOrigin + platformPerformance.now()) / 1000,
2022
1985
  };
2023
- }
1986
+ /**
1987
+ * Returns a timestamp in seconds since the UNIX epoch using the Date API.
1988
+ */
1989
+ const dateTimestampInSeconds = dateTimestampSource.nowSeconds.bind(dateTimestampSource);
1990
+ /**
1991
+ * Returns a timestamp in seconds since the UNIX epoch using either the Performance or Date APIs, depending on the
1992
+ * availability of the Performance API.
1993
+ *
1994
+ * See `usingPerformanceAPI` to test whether the Performance API is used.
1995
+ *
1996
+ * BUG: Note that because of how browsers implement the Performance API, the clock might stop when the computer is
1997
+ * asleep. This creates a skew between `dateTimestampInSeconds` and `timestampInSeconds`. The
1998
+ * skew can grow to arbitrary amounts like days, weeks or months.
1999
+ * See https://github.com/getsentry/sentry-javascript/issues/2590.
2000
+ */
2001
+ const timestampInSeconds = timestampSource.nowSeconds.bind(timestampSource);
2002
+ /**
2003
+ * The number of milliseconds since the UNIX epoch. This value is only usable in a browser, and only when the
2004
+ * performance API is available.
2005
+ */
2006
+ const browserPerformanceTimeOrigin = (() => {
2007
+ const { performance } = getGlobalObject();
2008
+ if (!performance) {
2009
+ return undefined;
2010
+ }
2011
+ if (performance.timeOrigin) {
2012
+ return performance.timeOrigin;
2013
+ }
2014
+ // While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin
2015
+ // is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.
2016
+ // Also as of writing, performance.timing is not available in Web Workers in mainstream browsers, so it is not always
2017
+ // a valid fallback. In the absence of an initial time provided by the browser, fallback to the current time from the
2018
+ // Date API.
2019
+ // eslint-disable-next-line deprecation/deprecation
2020
+ return (performance.timing && performance.timing.navigationStart) || Date.now();
2021
+ })();
2024
2022
 
2025
2023
  /**
2026
2024
  * Holds additional event information. {@link Scope.applyToEvent} will be
@@ -2041,10 +2039,8 @@ var Sentry = (function (exports) {
2041
2039
  /** Tags */
2042
2040
  this._tags = {};
2043
2041
  /** Extra */
2044
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2045
2042
  this._extra = {};
2046
2043
  /** Contexts */
2047
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2048
2044
  this._contexts = {};
2049
2045
  }
2050
2046
  /**
@@ -2061,7 +2057,6 @@ var Sentry = (function (exports) {
2061
2057
  newScope._user = scope._user;
2062
2058
  newScope._level = scope._level;
2063
2059
  newScope._span = scope._span;
2064
- newScope._session = scope._session;
2065
2060
  newScope._transactionName = scope._transactionName;
2066
2061
  newScope._fingerprint = scope._fingerprint;
2067
2062
  newScope._eventProcessors = [...scope._eventProcessors];
@@ -2087,18 +2082,9 @@ var Sentry = (function (exports) {
2087
2082
  */
2088
2083
  setUser(user) {
2089
2084
  this._user = user || {};
2090
- if (this._session) {
2091
- this._session.update({ user });
2092
- }
2093
2085
  this._notifyScopeListeners();
2094
2086
  return this;
2095
2087
  }
2096
- /**
2097
- * @inheritDoc
2098
- */
2099
- getUser() {
2100
- return this._user;
2101
- }
2102
2088
  /**
2103
2089
  * @inheritDoc
2104
2090
  */
@@ -2165,9 +2151,14 @@ var Sentry = (function (exports) {
2165
2151
  /**
2166
2152
  * @inheritDoc
2167
2153
  */
2168
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2169
2154
  setContext(key, context) {
2170
- this._contexts = Object.assign(Object.assign({}, this._contexts), { [key]: context });
2155
+ if (context === null) {
2156
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
2157
+ delete this._contexts[key];
2158
+ }
2159
+ else {
2160
+ this._contexts = Object.assign(Object.assign({}, this._contexts), { [key]: context });
2161
+ }
2171
2162
  this._notifyScopeListeners();
2172
2163
  return this;
2173
2164
  }
@@ -2189,31 +2180,20 @@ var Sentry = (function (exports) {
2189
2180
  * @inheritDoc
2190
2181
  */
2191
2182
  getTransaction() {
2183
+ var _a, _b, _c, _d;
2184
+ // often, this span will be a transaction, but it's not guaranteed to be
2192
2185
  const span = this.getSpan();
2193
- if (span && span.spanRecorder && span.spanRecorder.spans[0]) {
2186
+ // try it the new way first
2187
+ if ((_a = span) === null || _a === void 0 ? void 0 : _a.transaction) {
2188
+ return (_b = span) === null || _b === void 0 ? void 0 : _b.transaction;
2189
+ }
2190
+ // fallback to the old way (known bug: this only finds transactions with sampled = true)
2191
+ if ((_d = (_c = span) === null || _c === void 0 ? void 0 : _c.spanRecorder) === null || _d === void 0 ? void 0 : _d.spans[0]) {
2194
2192
  return span.spanRecorder.spans[0];
2195
2193
  }
2194
+ // neither way found a transaction
2196
2195
  return undefined;
2197
2196
  }
2198
- /**
2199
- * @inheritDoc
2200
- */
2201
- setSession(session) {
2202
- if (!session) {
2203
- delete this._session;
2204
- }
2205
- else {
2206
- this._session = session;
2207
- }
2208
- this._notifyScopeListeners();
2209
- return this;
2210
- }
2211
- /**
2212
- * @inheritDoc
2213
- */
2214
- getSession() {
2215
- return this._session;
2216
- }
2217
2197
  /**
2218
2198
  * @inheritDoc
2219
2199
  */
@@ -2270,7 +2250,6 @@ var Sentry = (function (exports) {
2270
2250
  this._transactionName = undefined;
2271
2251
  this._fingerprint = undefined;
2272
2252
  this._span = undefined;
2273
- this._session = undefined;
2274
2253
  this._notifyScopeListeners();
2275
2254
  return this;
2276
2255
  }
@@ -2278,7 +2257,7 @@ var Sentry = (function (exports) {
2278
2257
  * @inheritDoc
2279
2258
  */
2280
2259
  addBreadcrumb(breadcrumb, maxBreadcrumbs) {
2281
- const mergedBreadcrumb = Object.assign({ timestamp: timestampWithMs() }, breadcrumb);
2260
+ const mergedBreadcrumb = Object.assign({ timestamp: dateTimestampInSeconds() }, breadcrumb);
2282
2261
  this._breadcrumbs =
2283
2262
  maxBreadcrumbs !== undefined && maxBreadcrumbs >= 0
2284
2263
  ? [...this._breadcrumbs, mergedBreadcrumb].slice(-maxBreadcrumbs)
@@ -2408,95 +2387,6 @@ var Sentry = (function (exports) {
2408
2387
  getGlobalEventProcessors().push(callback);
2409
2388
  }
2410
2389
 
2411
- /**
2412
- * @inheritdoc
2413
- */
2414
- class Session {
2415
- constructor(context) {
2416
- this.errors = 0;
2417
- this.sid = uuid4();
2418
- this.timestamp = Date.now();
2419
- this.started = Date.now();
2420
- this.status = SessionStatus.Ok;
2421
- console.log('new session constructed'); // eslint-disable-line no-console
2422
- if (context) {
2423
- this.update(context);
2424
- }
2425
- }
2426
- /** JSDoc */
2427
- // eslint-disable-next-line complexity
2428
- update(context) {
2429
- if (context.user) {
2430
- if (context.user.ip_address) {
2431
- this.ip_address = context.user.ip_address;
2432
- }
2433
- if (!context.did) {
2434
- this.did = context.user.id || context.user.email || context.user.username;
2435
- }
2436
- }
2437
- this.timestamp = context.timestamp || Date.now();
2438
- if (context.sid) {
2439
- // Good enough uuid validation for now
2440
- this.sid = context.sid.length === 32 ? context.sid : uuid4();
2441
- }
2442
- if (context.did) {
2443
- this.did = `${context.did}`;
2444
- }
2445
- if (typeof context.started === 'number') {
2446
- this.started = context.started;
2447
- }
2448
- if (typeof context.duration === 'number') {
2449
- this.duration = context.duration;
2450
- }
2451
- if (context.release) {
2452
- this.release = context.release;
2453
- }
2454
- if (context.environment) {
2455
- this.environment = context.environment;
2456
- }
2457
- if (context.ip_address) {
2458
- this.ip_address = context.ip_address;
2459
- }
2460
- if (context.user_agent) {
2461
- this.user_agent = context.user_agent;
2462
- }
2463
- if (typeof context.errors === 'number') {
2464
- this.errors = context.errors;
2465
- }
2466
- if (context.status) {
2467
- this.status = context.status;
2468
- }
2469
- }
2470
- /** JSDoc */
2471
- close(status) {
2472
- if (status) {
2473
- this.update({ status });
2474
- }
2475
- else if (this.status === SessionStatus.Ok) {
2476
- this.update({ status: SessionStatus.Exited });
2477
- }
2478
- }
2479
- /** JSDoc */
2480
- toJSON() {
2481
- return dropUndefinedKeys({
2482
- sid: `${this.sid}`,
2483
- init: true,
2484
- started: new Date(this.started).toISOString(),
2485
- timestamp: new Date(this.timestamp).toISOString(),
2486
- status: this.status,
2487
- errors: this.errors,
2488
- did: typeof this.did === 'number' || typeof this.did === 'string' ? `${this.did}` : undefined,
2489
- duration: this.duration,
2490
- attrs: dropUndefinedKeys({
2491
- release: this.release,
2492
- environment: this.environment,
2493
- ip_address: this.ip_address,
2494
- user_agent: this.user_agent,
2495
- }),
2496
- });
2497
- }
2498
- }
2499
-
2500
2390
  /**
2501
2391
  * API compatibility version of this hub.
2502
2392
  *
@@ -2681,7 +2571,7 @@ var Sentry = (function (exports) {
2681
2571
  if (maxBreadcrumbs <= 0) {
2682
2572
  return;
2683
2573
  }
2684
- const timestamp = timestampWithMs();
2574
+ const timestamp = dateTimestampInSeconds();
2685
2575
  const mergedBreadcrumb = Object.assign({ timestamp }, breadcrumb);
2686
2576
  const finalBreadcrumb = beforeBreadcrumb
2687
2577
  ? consoleSandbox(() => beforeBreadcrumb(mergedBreadcrumb, hint))
@@ -2807,41 +2697,6 @@ var Sentry = (function (exports) {
2807
2697
  traceHeaders() {
2808
2698
  return this._callExtensionMethod('traceHeaders');
2809
2699
  }
2810
- /**
2811
- * @inheritDoc
2812
- */
2813
- startSession() {
2814
- const top = this.getStackTop();
2815
- if (!top.scope) {
2816
- return;
2817
- }
2818
- const client = top.client;
2819
- const { release, environment } = (client && client.getOptions()) || {};
2820
- // End existing session if there's one
2821
- this.endSession();
2822
- top.scope.setSession(new Session({
2823
- release,
2824
- environment,
2825
- user: top.scope.getUser(),
2826
- }));
2827
- }
2828
- /**
2829
- * @inheritDoc
2830
- */
2831
- endSession() {
2832
- const top = this.getStackTop();
2833
- if (!top.scope) {
2834
- return;
2835
- }
2836
- const session = top.scope.getSession();
2837
- if (session) {
2838
- session.close();
2839
- if (top.client) {
2840
- top.client.captureSession(session);
2841
- }
2842
- }
2843
- top.scope.setSession(undefined);
2844
- }
2845
2700
  /**
2846
2701
  * Internal helper function to call a method on the top client if it exists.
2847
2702
  *
@@ -3423,17 +3278,6 @@ var Sentry = (function (exports) {
3423
3278
  });
3424
3279
  return eventId;
3425
3280
  }
3426
- /**
3427
- * @inheritDoc
3428
- */
3429
- captureSession(session) {
3430
- if (!session.release) {
3431
- logger.warn('Discarded session update because of missing release');
3432
- }
3433
- else {
3434
- this._sendSession(session);
3435
- }
3436
- }
3437
3281
  /**
3438
3282
  * @inheritDoc
3439
3283
  */
@@ -3487,38 +3331,6 @@ var Sentry = (function (exports) {
3487
3331
  return null;
3488
3332
  }
3489
3333
  }
3490
- /** Updates existing session based on the provided event */
3491
- _updateSessionFromEvent(session, event) {
3492
- let crashed = false;
3493
- let errored = false;
3494
- let user_agent;
3495
- const exceptions = event.exception && event.exception.values;
3496
- if (exceptions) {
3497
- errored = true;
3498
- for (const ex of exceptions) {
3499
- const mechanism = ex.mechanism;
3500
- if (mechanism && mechanism.handled === false) {
3501
- crashed = true;
3502
- break;
3503
- }
3504
- }
3505
- }
3506
- const user = event.user;
3507
- if (!session.user_agent) {
3508
- const headers = event.request ? event.request.headers : {};
3509
- for (const key in headers) {
3510
- if (key.toLowerCase() === 'user-agent') {
3511
- user_agent = headers[key];
3512
- break;
3513
- }
3514
- }
3515
- }
3516
- session.update(Object.assign(Object.assign({}, (crashed && { status: SessionStatus.Crashed })), { user, user_agent: user_agent, errors: session.errors + Number(errored || crashed) }));
3517
- }
3518
- /** Deliver captured session to Sentry */
3519
- _sendSession(session) {
3520
- this._getBackend().sendSession(session);
3521
- }
3522
3334
  /** Waits for the client to be done with processing. */
3523
3335
  _isClientProcessing(timeout) {
3524
3336
  return new SyncPromise(resolve => {
@@ -3569,7 +3381,7 @@ var Sentry = (function (exports) {
3569
3381
  */
3570
3382
  _prepareEvent(event, scope, hint) {
3571
3383
  const { normalizeDepth = 3 } = this.getOptions();
3572
- const prepared = Object.assign(Object.assign({}, event), { event_id: event.event_id || (hint && hint.event_id ? hint.event_id : uuid4()), timestamp: event.timestamp || timestampWithMs() });
3384
+ const prepared = Object.assign(Object.assign({}, event), { event_id: event.event_id || (hint && hint.event_id ? hint.event_id : uuid4()), timestamp: event.timestamp || dateTimestampInSeconds() });
3573
3385
  this._applyClientOptions(prepared);
3574
3386
  this._applyIntegrationsMetadata(prepared);
3575
3387
  // If we have scope given to us, use it as the base for further modifications.
@@ -3715,12 +3527,6 @@ var Sentry = (function (exports) {
3715
3527
  const isInternalException = hint && hint.data && hint.data.__sentry__ === true;
3716
3528
  // We skip beforeSend in case of transactions
3717
3529
  if (isInternalException || !beforeSend || isTransaction) {
3718
- if (!isTransaction) {
3719
- const session = scope && scope.getSession();
3720
- if (session) {
3721
- this._updateSessionFromEvent(session, finalEvent);
3722
- }
3723
- }
3724
3530
  this._sendEvent(finalEvent);
3725
3531
  resolve(finalEvent);
3726
3532
  return;
@@ -3739,10 +3545,6 @@ var Sentry = (function (exports) {
3739
3545
  resolve(null);
3740
3546
  return;
3741
3547
  }
3742
- const session = scope && scope.getSession();
3743
- if (session) {
3744
- this._updateSessionFromEvent(session, finalEvent);
3745
- }
3746
3548
  // From here on we are really async
3747
3549
  this._sendEvent(finalEvent);
3748
3550
  resolve(finalEvent);
@@ -3832,18 +3634,6 @@ var Sentry = (function (exports) {
3832
3634
  logger.error(`Error while sending event: ${reason}`);
3833
3635
  });
3834
3636
  }
3835
- /**
3836
- * @inheritDoc
3837
- */
3838
- sendSession(session) {
3839
- if (!this._transport.sendSession) {
3840
- logger.warn('sendSession not implemented for a transport used');
3841
- return;
3842
- }
3843
- this._transport.sendSession(session).then(null, reason => {
3844
- logger.error(`Error while sending session: ${reason}`);
3845
- });
3846
- }
3847
3637
  /**
3848
3638
  * @inheritDoc
3849
3639
  */
@@ -3858,19 +3648,6 @@ var Sentry = (function (exports) {
3858
3648
  }
3859
3649
  }
3860
3650
 
3861
- /** Creates a SentryRequest from an event. */
3862
- function sessionToSentryRequest(session, api) {
3863
- const envelopeHeaders = JSON.stringify({
3864
- sent_at: new Date(timestampWithMs() * 1000).toISOString(),
3865
- });
3866
- const itemHeaders = JSON.stringify({
3867
- type: 'session',
3868
- });
3869
- return {
3870
- body: `${envelopeHeaders}\n${itemHeaders}\n${JSON.stringify(session)}`,
3871
- url: api.getEnvelopeEndpointWithUrlEncodedAuth(),
3872
- };
3873
- }
3874
3651
  /** Creates a SentryRequest from an event. */
3875
3652
  function eventToSentryRequest(event, api) {
3876
3653
  const useEnvelope = event.type === 'transaction';
@@ -3888,7 +3665,7 @@ var Sentry = (function (exports) {
3888
3665
  event_id: event.event_id,
3889
3666
  // We need to add * 1000 since we divide it by 1000 by default but JS works with ms precision
3890
3667
  // The reason we use timestampWithMs here is that all clocks across the SDK use the same clock
3891
- sent_at: new Date(timestampWithMs() * 1000).toISOString(),
3668
+ sent_at: new Date().toISOString(),
3892
3669
  });
3893
3670
  const itemHeaders = JSON.stringify({
3894
3671
  type: event.type,
@@ -4615,40 +4392,6 @@ var Sentry = (function (exports) {
4615
4392
  .catch(reject);
4616
4393
  }));
4617
4394
  }
4618
- /**
4619
- * @inheritDoc
4620
- */
4621
- sendSession(session) {
4622
- const sentryReq = sessionToSentryRequest(session, this._api);
4623
- const options = {
4624
- body: sentryReq.body,
4625
- method: 'POST',
4626
- // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default
4627
- // https://caniuse.com/#feat=referrer-policy
4628
- // It doesn't. And it throw exception instead of ignoring this parameter...
4629
- // REF: https://github.com/getsentry/raven-js/issues/1233
4630
- referrerPolicy: (supportsReferrerPolicy() ? 'origin' : ''),
4631
- };
4632
- if (this.options.fetchParameters !== undefined) {
4633
- Object.assign(options, this.options.fetchParameters);
4634
- }
4635
- if (this.options.headers !== undefined) {
4636
- options.headers = this.options.headers;
4637
- }
4638
- return new SyncPromise((resolve, reject) => {
4639
- global$3
4640
- .fetch(sentryReq.url, options)
4641
- .then(response => {
4642
- const status = exports.Status.fromHttpCode(response.status);
4643
- if (status === exports.Status.Success) {
4644
- resolve({ status });
4645
- return;
4646
- }
4647
- reject(response);
4648
- })
4649
- .catch(reject);
4650
- });
4651
- }
4652
4395
  }
4653
4396
 
4654
4397
  /** `XHR` based transport */
@@ -4702,33 +4445,6 @@ var Sentry = (function (exports) {
4702
4445
  request.send(sentryReq.body);
4703
4446
  }));
4704
4447
  }
4705
- /**
4706
- * @inheritDoc
4707
- */
4708
- sendSession(session) {
4709
- const sentryReq = sessionToSentryRequest(session, this._api);
4710
- return new SyncPromise((resolve, reject) => {
4711
- const request = new XMLHttpRequest();
4712
- request.onreadystatechange = () => {
4713
- if (request.readyState !== 4) {
4714
- return;
4715
- }
4716
- const status = exports.Status.fromHttpCode(request.status);
4717
- if (status === exports.Status.Success) {
4718
- resolve({ status });
4719
- return;
4720
- }
4721
- reject(request);
4722
- };
4723
- request.open('POST', sentryReq.url);
4724
- for (const header in this.options.headers) {
4725
- if (this.options.headers.hasOwnProperty(header)) {
4726
- request.setRequestHeader(header, this.options.headers[header]);
4727
- }
4728
- }
4729
- request.send(sentryReq.body);
4730
- });
4731
- }
4732
4448
  }
4733
4449
 
4734
4450
 
@@ -5670,7 +5386,7 @@ var Sentry = (function (exports) {
5670
5386
  });
5671
5387
 
5672
5388
  const SDK_NAME = 'sentry.javascript.browser';
5673
- const SDK_VERSION = '5.25.0-beta.2';
5389
+ const SDK_VERSION = '5.25.0';
5674
5390
 
5675
5391
  /**
5676
5392
  * The Sentry Browser SDK Client.