@sentry/browser 5.24.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.
- package/build/bundle.es6.js +525 -481
- package/build/bundle.es6.js.map +1 -1
- package/build/bundle.es6.min.js +2 -2
- package/build/bundle.es6.min.js.map +1 -1
- package/build/bundle.js +527 -483
- package/build/bundle.js.map +1 -1
- package/build/bundle.min.js +2 -2
- package/build/bundle.min.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/esm/version.d.ts +1 -1
- package/esm/version.js +1 -1
- package/esm/version.js.map +1 -1
- package/package.json +8 -5
package/build/bundle.es6.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @sentry/browser 5.
|
|
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;
|
|
@@ -874,13 +874,6 @@ var Sentry = (function (exports) {
|
|
|
874
874
|
? self
|
|
875
875
|
: fallbackGlobalObject);
|
|
876
876
|
}
|
|
877
|
-
/**
|
|
878
|
-
* Determines if running in react native
|
|
879
|
-
*/
|
|
880
|
-
function isReactNative() {
|
|
881
|
-
var _a;
|
|
882
|
-
return ((_a = getGlobalObject().navigator) === null || _a === void 0 ? void 0 : _a.product) === 'ReactNative';
|
|
883
|
-
}
|
|
884
877
|
/**
|
|
885
878
|
* UUID4 generator
|
|
886
879
|
*
|
|
@@ -1032,73 +1025,6 @@ var Sentry = (function (exports) {
|
|
|
1032
1025
|
return '';
|
|
1033
1026
|
}
|
|
1034
1027
|
}
|
|
1035
|
-
const INITIAL_TIME = Date.now();
|
|
1036
|
-
let prevNow = 0;
|
|
1037
|
-
const performanceFallback = {
|
|
1038
|
-
now() {
|
|
1039
|
-
let now = Date.now() - INITIAL_TIME;
|
|
1040
|
-
if (now < prevNow) {
|
|
1041
|
-
now = prevNow;
|
|
1042
|
-
}
|
|
1043
|
-
prevNow = now;
|
|
1044
|
-
return now;
|
|
1045
|
-
},
|
|
1046
|
-
timeOrigin: INITIAL_TIME,
|
|
1047
|
-
};
|
|
1048
|
-
/**
|
|
1049
|
-
* Performance wrapper for react native as performance.now() has been found to start off with an unusual offset.
|
|
1050
|
-
*/
|
|
1051
|
-
function getReactNativePerformanceWrapper() {
|
|
1052
|
-
// Performance only available >= RN 0.63
|
|
1053
|
-
const { performance } = getGlobalObject();
|
|
1054
|
-
if (performance && typeof performance.now === 'function') {
|
|
1055
|
-
const INITIAL_OFFSET = performance.now();
|
|
1056
|
-
return {
|
|
1057
|
-
now() {
|
|
1058
|
-
return performance.now() - INITIAL_OFFSET;
|
|
1059
|
-
},
|
|
1060
|
-
timeOrigin: INITIAL_TIME,
|
|
1061
|
-
};
|
|
1062
|
-
}
|
|
1063
|
-
return performanceFallback;
|
|
1064
|
-
}
|
|
1065
|
-
const crossPlatformPerformance = (() => {
|
|
1066
|
-
// React Native's performance.now() starts with a gigantic offset, so we need to wrap it.
|
|
1067
|
-
if (isReactNative()) {
|
|
1068
|
-
return getReactNativePerformanceWrapper();
|
|
1069
|
-
}
|
|
1070
|
-
if (isNodeEnv()) {
|
|
1071
|
-
try {
|
|
1072
|
-
const perfHooks = dynamicRequire(module, 'perf_hooks');
|
|
1073
|
-
return perfHooks.performance;
|
|
1074
|
-
}
|
|
1075
|
-
catch (_) {
|
|
1076
|
-
return performanceFallback;
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
const { performance } = getGlobalObject();
|
|
1080
|
-
if (!performance || !performance.now) {
|
|
1081
|
-
return performanceFallback;
|
|
1082
|
-
}
|
|
1083
|
-
// Polyfill for performance.timeOrigin.
|
|
1084
|
-
//
|
|
1085
|
-
// While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin
|
|
1086
|
-
// is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.
|
|
1087
|
-
if (performance.timeOrigin === undefined) {
|
|
1088
|
-
// As of writing, performance.timing is not available in Web Workers in mainstream browsers, so it is not always a
|
|
1089
|
-
// valid fallback. In the absence of a initial time provided by the browser, fallback to INITIAL_TIME.
|
|
1090
|
-
// @ts-ignore ignored because timeOrigin is a readonly property but we want to override
|
|
1091
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
1092
|
-
performance.timeOrigin = (performance.timing && performance.timing.navigationStart) || INITIAL_TIME;
|
|
1093
|
-
}
|
|
1094
|
-
return performance;
|
|
1095
|
-
})();
|
|
1096
|
-
/**
|
|
1097
|
-
* Returns a timestamp in seconds with milliseconds precision since the UNIX epoch calculated with the monotonic clock.
|
|
1098
|
-
*/
|
|
1099
|
-
function timestampWithMs() {
|
|
1100
|
-
return (crossPlatformPerformance.timeOrigin + crossPlatformPerformance.now()) / 1000;
|
|
1101
|
-
}
|
|
1102
1028
|
const defaultRetryAfter = 60 * 1000; // 60 seconds
|
|
1103
1029
|
/**
|
|
1104
1030
|
* Extracts Retry-After value from the request header or returns default value
|
|
@@ -1171,359 +1097,93 @@ var Sentry = (function (exports) {
|
|
|
1171
1097
|
global$1.__SENTRY__ = global$1.__SENTRY__ || {};
|
|
1172
1098
|
const logger = global$1.__SENTRY__.logger || (global$1.__SENTRY__.logger = new Logger());
|
|
1173
1099
|
|
|
1174
|
-
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
1175
|
-
/** SyncPromise internal states */
|
|
1176
|
-
var States;
|
|
1177
|
-
(function (States) {
|
|
1178
|
-
/** Pending */
|
|
1179
|
-
States["PENDING"] = "PENDING";
|
|
1180
|
-
/** Resolved / OK */
|
|
1181
|
-
States["RESOLVED"] = "RESOLVED";
|
|
1182
|
-
/** Rejected / Error */
|
|
1183
|
-
States["REJECTED"] = "REJECTED";
|
|
1184
|
-
})(States || (States = {}));
|
|
1185
1100
|
/**
|
|
1186
|
-
*
|
|
1187
|
-
*
|
|
1101
|
+
* Tells whether current environment supports Fetch API
|
|
1102
|
+
* {@link supportsFetch}.
|
|
1103
|
+
*
|
|
1104
|
+
* @returns Answer to the given question.
|
|
1188
1105
|
*/
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
this._handlers = [];
|
|
1193
|
-
/** JSDoc */
|
|
1194
|
-
this._resolve = (value) => {
|
|
1195
|
-
this._setResult(States.RESOLVED, value);
|
|
1196
|
-
};
|
|
1197
|
-
/** JSDoc */
|
|
1198
|
-
this._reject = (reason) => {
|
|
1199
|
-
this._setResult(States.REJECTED, reason);
|
|
1200
|
-
};
|
|
1201
|
-
/** JSDoc */
|
|
1202
|
-
this._setResult = (state, value) => {
|
|
1203
|
-
if (this._state !== States.PENDING) {
|
|
1204
|
-
return;
|
|
1205
|
-
}
|
|
1206
|
-
if (isThenable(value)) {
|
|
1207
|
-
value.then(this._resolve, this._reject);
|
|
1208
|
-
return;
|
|
1209
|
-
}
|
|
1210
|
-
this._state = state;
|
|
1211
|
-
this._value = value;
|
|
1212
|
-
this._executeHandlers();
|
|
1213
|
-
};
|
|
1214
|
-
// TODO: FIXME
|
|
1215
|
-
/** JSDoc */
|
|
1216
|
-
this._attachHandler = (handler) => {
|
|
1217
|
-
this._handlers = this._handlers.concat(handler);
|
|
1218
|
-
this._executeHandlers();
|
|
1219
|
-
};
|
|
1220
|
-
/** JSDoc */
|
|
1221
|
-
this._executeHandlers = () => {
|
|
1222
|
-
if (this._state === States.PENDING) {
|
|
1223
|
-
return;
|
|
1224
|
-
}
|
|
1225
|
-
const cachedHandlers = this._handlers.slice();
|
|
1226
|
-
this._handlers = [];
|
|
1227
|
-
cachedHandlers.forEach(handler => {
|
|
1228
|
-
if (handler.done) {
|
|
1229
|
-
return;
|
|
1230
|
-
}
|
|
1231
|
-
if (this._state === States.RESOLVED) {
|
|
1232
|
-
if (handler.onfulfilled) {
|
|
1233
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1234
|
-
handler.onfulfilled(this._value);
|
|
1235
|
-
}
|
|
1236
|
-
}
|
|
1237
|
-
if (this._state === States.REJECTED) {
|
|
1238
|
-
if (handler.onrejected) {
|
|
1239
|
-
handler.onrejected(this._value);
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
handler.done = true;
|
|
1243
|
-
});
|
|
1244
|
-
};
|
|
1245
|
-
try {
|
|
1246
|
-
executor(this._resolve, this._reject);
|
|
1247
|
-
}
|
|
1248
|
-
catch (e) {
|
|
1249
|
-
this._reject(e);
|
|
1250
|
-
}
|
|
1106
|
+
function supportsFetch() {
|
|
1107
|
+
if (!('fetch' in getGlobalObject())) {
|
|
1108
|
+
return false;
|
|
1251
1109
|
}
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1110
|
+
try {
|
|
1111
|
+
new Headers();
|
|
1112
|
+
new Request('');
|
|
1113
|
+
new Response();
|
|
1114
|
+
return true;
|
|
1257
1115
|
}
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
return new SyncPromise((_, reject) => {
|
|
1261
|
-
reject(reason);
|
|
1262
|
-
});
|
|
1116
|
+
catch (e) {
|
|
1117
|
+
return false;
|
|
1263
1118
|
}
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
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`) {
|
|
1149
|
+
try {
|
|
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);
|
|
1274
1156
|
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
resolvedCollection[index] = value;
|
|
1281
|
-
counter -= 1;
|
|
1282
|
-
if (counter !== 0) {
|
|
1283
|
-
return;
|
|
1284
|
-
}
|
|
1285
|
-
resolve(resolvedCollection);
|
|
1286
|
-
})
|
|
1287
|
-
.then(null, reject);
|
|
1288
|
-
});
|
|
1289
|
-
});
|
|
1157
|
+
doc.head.removeChild(sandbox);
|
|
1158
|
+
}
|
|
1159
|
+
catch (err) {
|
|
1160
|
+
logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err);
|
|
1161
|
+
}
|
|
1290
1162
|
}
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
}
|
|
1311
|
-
},
|
|
1312
|
-
onrejected: reason => {
|
|
1313
|
-
if (!onrejected) {
|
|
1314
|
-
reject(reason);
|
|
1315
|
-
return;
|
|
1316
|
-
}
|
|
1317
|
-
try {
|
|
1318
|
-
resolve(onrejected(reason));
|
|
1319
|
-
return;
|
|
1320
|
-
}
|
|
1321
|
-
catch (e) {
|
|
1322
|
-
reject(e);
|
|
1323
|
-
return;
|
|
1324
|
-
}
|
|
1325
|
-
},
|
|
1326
|
-
});
|
|
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;
|
|
1178
|
+
}
|
|
1179
|
+
try {
|
|
1180
|
+
new Request('_', {
|
|
1181
|
+
referrerPolicy: 'origin',
|
|
1327
1182
|
});
|
|
1183
|
+
return true;
|
|
1328
1184
|
}
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
return this.then(val => val, onrejected);
|
|
1332
|
-
}
|
|
1333
|
-
/** JSDoc */
|
|
1334
|
-
finally(onfinally) {
|
|
1335
|
-
return new SyncPromise((resolve, reject) => {
|
|
1336
|
-
let val;
|
|
1337
|
-
let isRejected;
|
|
1338
|
-
return this.then(value => {
|
|
1339
|
-
isRejected = false;
|
|
1340
|
-
val = value;
|
|
1341
|
-
if (onfinally) {
|
|
1342
|
-
onfinally();
|
|
1343
|
-
}
|
|
1344
|
-
}, reason => {
|
|
1345
|
-
isRejected = true;
|
|
1346
|
-
val = reason;
|
|
1347
|
-
if (onfinally) {
|
|
1348
|
-
onfinally();
|
|
1349
|
-
}
|
|
1350
|
-
}).then(() => {
|
|
1351
|
-
if (isRejected) {
|
|
1352
|
-
reject(val);
|
|
1353
|
-
return;
|
|
1354
|
-
}
|
|
1355
|
-
resolve(val);
|
|
1356
|
-
});
|
|
1357
|
-
});
|
|
1358
|
-
}
|
|
1359
|
-
/** JSDoc */
|
|
1360
|
-
toString() {
|
|
1361
|
-
return '[object SyncPromise]';
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
|
|
1365
|
-
/** A simple queue that holds promises. */
|
|
1366
|
-
class PromiseBuffer {
|
|
1367
|
-
constructor(_limit) {
|
|
1368
|
-
this._limit = _limit;
|
|
1369
|
-
/** Internal set of queued Promises */
|
|
1370
|
-
this._buffer = [];
|
|
1371
|
-
}
|
|
1372
|
-
/**
|
|
1373
|
-
* Says if the buffer is ready to take more requests
|
|
1374
|
-
*/
|
|
1375
|
-
isReady() {
|
|
1376
|
-
return this._limit === undefined || this.length() < this._limit;
|
|
1377
|
-
}
|
|
1378
|
-
/**
|
|
1379
|
-
* Add a promise to the queue.
|
|
1380
|
-
*
|
|
1381
|
-
* @param task Can be any PromiseLike<T>
|
|
1382
|
-
* @returns The original promise.
|
|
1383
|
-
*/
|
|
1384
|
-
add(task) {
|
|
1385
|
-
if (!this.isReady()) {
|
|
1386
|
-
return SyncPromise.reject(new SentryError('Not adding Promise due to buffer limit reached.'));
|
|
1387
|
-
}
|
|
1388
|
-
if (this._buffer.indexOf(task) === -1) {
|
|
1389
|
-
this._buffer.push(task);
|
|
1390
|
-
}
|
|
1391
|
-
task
|
|
1392
|
-
.then(() => this.remove(task))
|
|
1393
|
-
.then(null, () => this.remove(task).then(null, () => {
|
|
1394
|
-
// We have to add this catch here otherwise we have an unhandledPromiseRejection
|
|
1395
|
-
// because it's a new Promise chain.
|
|
1396
|
-
}));
|
|
1397
|
-
return task;
|
|
1398
|
-
}
|
|
1399
|
-
/**
|
|
1400
|
-
* Remove a promise to the queue.
|
|
1401
|
-
*
|
|
1402
|
-
* @param task Can be any PromiseLike<T>
|
|
1403
|
-
* @returns Removed promise.
|
|
1404
|
-
*/
|
|
1405
|
-
remove(task) {
|
|
1406
|
-
const removedTask = this._buffer.splice(this._buffer.indexOf(task), 1)[0];
|
|
1407
|
-
return removedTask;
|
|
1408
|
-
}
|
|
1409
|
-
/**
|
|
1410
|
-
* This function returns the number of unresolved promises in the queue.
|
|
1411
|
-
*/
|
|
1412
|
-
length() {
|
|
1413
|
-
return this._buffer.length;
|
|
1414
|
-
}
|
|
1415
|
-
/**
|
|
1416
|
-
* This will drain the whole queue, returns true if queue is empty or drained.
|
|
1417
|
-
* If timeout is provided and the queue takes longer to drain, the promise still resolves but with false.
|
|
1418
|
-
*
|
|
1419
|
-
* @param timeout Number in ms to wait until it resolves with false.
|
|
1420
|
-
*/
|
|
1421
|
-
drain(timeout) {
|
|
1422
|
-
return new SyncPromise(resolve => {
|
|
1423
|
-
const capturedSetTimeout = setTimeout(() => {
|
|
1424
|
-
if (timeout && timeout > 0) {
|
|
1425
|
-
resolve(false);
|
|
1426
|
-
}
|
|
1427
|
-
}, timeout);
|
|
1428
|
-
SyncPromise.all(this._buffer)
|
|
1429
|
-
.then(() => {
|
|
1430
|
-
clearTimeout(capturedSetTimeout);
|
|
1431
|
-
resolve(true);
|
|
1432
|
-
})
|
|
1433
|
-
.then(null, () => {
|
|
1434
|
-
resolve(true);
|
|
1435
|
-
});
|
|
1436
|
-
});
|
|
1437
|
-
}
|
|
1438
|
-
}
|
|
1439
|
-
|
|
1440
|
-
/**
|
|
1441
|
-
* Tells whether current environment supports Fetch API
|
|
1442
|
-
* {@link supportsFetch}.
|
|
1443
|
-
*
|
|
1444
|
-
* @returns Answer to the given question.
|
|
1445
|
-
*/
|
|
1446
|
-
function supportsFetch() {
|
|
1447
|
-
if (!('fetch' in getGlobalObject())) {
|
|
1448
|
-
return false;
|
|
1449
|
-
}
|
|
1450
|
-
try {
|
|
1451
|
-
new Headers();
|
|
1452
|
-
new Request('');
|
|
1453
|
-
new Response();
|
|
1454
|
-
return true;
|
|
1455
|
-
}
|
|
1456
|
-
catch (e) {
|
|
1457
|
-
return false;
|
|
1458
|
-
}
|
|
1459
|
-
}
|
|
1460
|
-
/**
|
|
1461
|
-
* isNativeFetch checks if the given function is a native implementation of fetch()
|
|
1462
|
-
*/
|
|
1463
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
1464
|
-
function isNativeFetch(func) {
|
|
1465
|
-
return func && /^function fetch\(\)\s+\{\s+\[native code\]\s+\}$/.test(func.toString());
|
|
1466
|
-
}
|
|
1467
|
-
/**
|
|
1468
|
-
* Tells whether current environment supports Fetch API natively
|
|
1469
|
-
* {@link supportsNativeFetch}.
|
|
1470
|
-
*
|
|
1471
|
-
* @returns true if `window.fetch` is natively implemented, false otherwise
|
|
1472
|
-
*/
|
|
1473
|
-
function supportsNativeFetch() {
|
|
1474
|
-
if (!supportsFetch()) {
|
|
1475
|
-
return false;
|
|
1476
|
-
}
|
|
1477
|
-
const global = getGlobalObject();
|
|
1478
|
-
// Fast path to avoid DOM I/O
|
|
1479
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
1480
|
-
if (isNativeFetch(global.fetch)) {
|
|
1481
|
-
return true;
|
|
1482
|
-
}
|
|
1483
|
-
// window.fetch is implemented, but is polyfilled or already wrapped (e.g: by a chrome extension)
|
|
1484
|
-
// so create a "pure" iframe to see if that has native fetch
|
|
1485
|
-
let result = false;
|
|
1486
|
-
const doc = global.document;
|
|
1487
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
1488
|
-
if (doc && typeof doc.createElement === `function`) {
|
|
1489
|
-
try {
|
|
1490
|
-
const sandbox = doc.createElement('iframe');
|
|
1491
|
-
sandbox.hidden = true;
|
|
1492
|
-
doc.head.appendChild(sandbox);
|
|
1493
|
-
if (sandbox.contentWindow && sandbox.contentWindow.fetch) {
|
|
1494
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
1495
|
-
result = isNativeFetch(sandbox.contentWindow.fetch);
|
|
1496
|
-
}
|
|
1497
|
-
doc.head.removeChild(sandbox);
|
|
1498
|
-
}
|
|
1499
|
-
catch (err) {
|
|
1500
|
-
logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err);
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
return result;
|
|
1504
|
-
}
|
|
1505
|
-
/**
|
|
1506
|
-
* Tells whether current environment supports Referrer Policy API
|
|
1507
|
-
* {@link supportsReferrerPolicy}.
|
|
1508
|
-
*
|
|
1509
|
-
* @returns Answer to the given question.
|
|
1510
|
-
*/
|
|
1511
|
-
function supportsReferrerPolicy() {
|
|
1512
|
-
// Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default
|
|
1513
|
-
// https://caniuse.com/#feat=referrer-policy
|
|
1514
|
-
// It doesn't. And it throw exception instead of ignoring this parameter...
|
|
1515
|
-
// REF: https://github.com/getsentry/raven-js/issues/1233
|
|
1516
|
-
if (!supportsFetch()) {
|
|
1517
|
-
return false;
|
|
1518
|
-
}
|
|
1519
|
-
try {
|
|
1520
|
-
new Request('_', {
|
|
1521
|
-
referrerPolicy: 'origin',
|
|
1522
|
-
});
|
|
1523
|
-
return true;
|
|
1524
|
-
}
|
|
1525
|
-
catch (e) {
|
|
1526
|
-
return false;
|
|
1185
|
+
catch (e) {
|
|
1186
|
+
return false;
|
|
1527
1187
|
}
|
|
1528
1188
|
}
|
|
1529
1189
|
/**
|
|
@@ -1645,7 +1305,7 @@ var Sentry = (function (exports) {
|
|
|
1645
1305
|
}
|
|
1646
1306
|
fill(global$2, 'fetch', function (originalFetch) {
|
|
1647
1307
|
return function (...args) {
|
|
1648
|
-
const
|
|
1308
|
+
const handlerData = {
|
|
1649
1309
|
args,
|
|
1650
1310
|
fetchData: {
|
|
1651
1311
|
method: getFetchMethod(args),
|
|
@@ -1653,13 +1313,13 @@ var Sentry = (function (exports) {
|
|
|
1653
1313
|
},
|
|
1654
1314
|
startTimestamp: Date.now(),
|
|
1655
1315
|
};
|
|
1656
|
-
triggerHandlers('fetch', Object.assign({},
|
|
1316
|
+
triggerHandlers('fetch', Object.assign({}, handlerData));
|
|
1657
1317
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1658
1318
|
return originalFetch.apply(global$2, args).then((response) => {
|
|
1659
|
-
triggerHandlers('fetch', Object.assign(Object.assign({},
|
|
1319
|
+
triggerHandlers('fetch', Object.assign(Object.assign({}, handlerData), { endTimestamp: Date.now(), response }));
|
|
1660
1320
|
return response;
|
|
1661
1321
|
}, (error) => {
|
|
1662
|
-
triggerHandlers('fetch', Object.assign(Object.assign({},
|
|
1322
|
+
triggerHandlers('fetch', Object.assign(Object.assign({}, handlerData), { endTimestamp: Date.now(), error }));
|
|
1663
1323
|
// NOTE: If you are a Sentry user, and you are seeing this stack frame,
|
|
1664
1324
|
// it means the sentry.javascript SDK caught an error invoking your application code.
|
|
1665
1325
|
// This is expected behavior and NOT indicative of a bug with sentry.javascript.
|
|
@@ -1695,7 +1355,7 @@ var Sentry = (function (exports) {
|
|
|
1695
1355
|
if (!('XMLHttpRequest' in global$2)) {
|
|
1696
1356
|
return;
|
|
1697
1357
|
}
|
|
1698
|
-
// Poor man implementation of ES6 `Map
|
|
1358
|
+
// Poor man's implementation of ES6 `Map`, tracking and keeping in sync key and value separately.
|
|
1699
1359
|
const requestKeys = [];
|
|
1700
1360
|
const requestValues = [];
|
|
1701
1361
|
const xhrproto = XMLHttpRequest.prototype;
|
|
@@ -1729,7 +1389,7 @@ var Sentry = (function (exports) {
|
|
|
1729
1389
|
try {
|
|
1730
1390
|
const requestPos = requestKeys.indexOf(xhr);
|
|
1731
1391
|
if (requestPos !== -1) {
|
|
1732
|
-
// Make sure to pop both
|
|
1392
|
+
// Make sure to pop both key and value to keep it in sync.
|
|
1733
1393
|
requestKeys.splice(requestPos);
|
|
1734
1394
|
const args = requestValues.splice(requestPos)[0];
|
|
1735
1395
|
if (xhr.__sentry_xhr__ && args[0] !== undefined) {
|
|
@@ -1987,56 +1647,427 @@ var Sentry = (function (exports) {
|
|
|
1987
1647
|
};
|
|
1988
1648
|
}
|
|
1989
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 = {}));
|
|
1990
1661
|
/**
|
|
1991
|
-
*
|
|
1992
|
-
*
|
|
1662
|
+
* Thenable class that behaves like a Promise and follows it's interface
|
|
1663
|
+
* but is not async internally
|
|
1993
1664
|
*/
|
|
1994
|
-
class
|
|
1995
|
-
constructor() {
|
|
1996
|
-
|
|
1997
|
-
this.
|
|
1998
|
-
/**
|
|
1999
|
-
this.
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
/**
|
|
2003
|
-
this.
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
/**
|
|
2007
|
-
this.
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
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.
|
|
1967
|
+
*/
|
|
1968
|
+
function getNodePerformance() {
|
|
1969
|
+
try {
|
|
1970
|
+
const perfHooks = dynamicRequire(module, 'perf_hooks');
|
|
1971
|
+
return perfHooks.performance;
|
|
1972
|
+
}
|
|
1973
|
+
catch (_) {
|
|
1974
|
+
return undefined;
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
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,
|
|
1985
|
+
};
|
|
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
|
+
})();
|
|
2022
|
+
|
|
2023
|
+
/**
|
|
2024
|
+
* Holds additional event information. {@link Scope.applyToEvent} will be
|
|
2025
|
+
* called by the client before an event will be sent.
|
|
2026
|
+
*/
|
|
2027
|
+
class Scope {
|
|
2028
|
+
constructor() {
|
|
2029
|
+
/** Flag if notifiying is happening. */
|
|
2030
|
+
this._notifyingListeners = false;
|
|
2031
|
+
/** Callback for client to receive scope changes. */
|
|
2032
|
+
this._scopeListeners = [];
|
|
2033
|
+
/** Callback list that will be called after {@link applyToEvent}. */
|
|
2034
|
+
this._eventProcessors = [];
|
|
2035
|
+
/** Array of breadcrumbs. */
|
|
2036
|
+
this._breadcrumbs = [];
|
|
2037
|
+
/** User */
|
|
2038
|
+
this._user = {};
|
|
2039
|
+
/** Tags */
|
|
2040
|
+
this._tags = {};
|
|
2041
|
+
/** Extra */
|
|
2042
|
+
this._extra = {};
|
|
2043
|
+
/** Contexts */
|
|
2044
|
+
this._contexts = {};
|
|
2045
|
+
}
|
|
2046
|
+
/**
|
|
2047
|
+
* Inherit values from the parent scope.
|
|
2048
|
+
* @param scope to clone.
|
|
2049
|
+
*/
|
|
2050
|
+
static clone(scope) {
|
|
2051
|
+
const newScope = new Scope();
|
|
2052
|
+
if (scope) {
|
|
2053
|
+
newScope._breadcrumbs = [...scope._breadcrumbs];
|
|
2054
|
+
newScope._tags = Object.assign({}, scope._tags);
|
|
2055
|
+
newScope._extra = Object.assign({}, scope._extra);
|
|
2056
|
+
newScope._contexts = Object.assign({}, scope._contexts);
|
|
2057
|
+
newScope._user = scope._user;
|
|
2058
|
+
newScope._level = scope._level;
|
|
2059
|
+
newScope._span = scope._span;
|
|
2060
|
+
newScope._transactionName = scope._transactionName;
|
|
2061
|
+
newScope._fingerprint = scope._fingerprint;
|
|
2062
|
+
newScope._eventProcessors = [...scope._eventProcessors];
|
|
2063
|
+
}
|
|
2064
|
+
return newScope;
|
|
2065
|
+
}
|
|
2066
|
+
/**
|
|
2067
|
+
* Add internal on change listener. Used for sub SDKs that need to store the scope.
|
|
2068
|
+
* @hidden
|
|
2069
|
+
*/
|
|
2070
|
+
addScopeListener(callback) {
|
|
2040
2071
|
this._scopeListeners.push(callback);
|
|
2041
2072
|
}
|
|
2042
2073
|
/**
|
|
@@ -2120,9 +2151,14 @@ var Sentry = (function (exports) {
|
|
|
2120
2151
|
/**
|
|
2121
2152
|
* @inheritDoc
|
|
2122
2153
|
*/
|
|
2123
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2124
2154
|
setContext(key, context) {
|
|
2125
|
-
|
|
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
|
+
}
|
|
2126
2162
|
this._notifyScopeListeners();
|
|
2127
2163
|
return this;
|
|
2128
2164
|
}
|
|
@@ -2144,10 +2180,18 @@ var Sentry = (function (exports) {
|
|
|
2144
2180
|
* @inheritDoc
|
|
2145
2181
|
*/
|
|
2146
2182
|
getTransaction() {
|
|
2183
|
+
var _a, _b, _c, _d;
|
|
2184
|
+
// often, this span will be a transaction, but it's not guaranteed to be
|
|
2147
2185
|
const span = this.getSpan();
|
|
2148
|
-
|
|
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]) {
|
|
2149
2192
|
return span.spanRecorder.spans[0];
|
|
2150
2193
|
}
|
|
2194
|
+
// neither way found a transaction
|
|
2151
2195
|
return undefined;
|
|
2152
2196
|
}
|
|
2153
2197
|
/**
|
|
@@ -2213,7 +2257,7 @@ var Sentry = (function (exports) {
|
|
|
2213
2257
|
* @inheritDoc
|
|
2214
2258
|
*/
|
|
2215
2259
|
addBreadcrumb(breadcrumb, maxBreadcrumbs) {
|
|
2216
|
-
const mergedBreadcrumb = Object.assign({ timestamp:
|
|
2260
|
+
const mergedBreadcrumb = Object.assign({ timestamp: dateTimestampInSeconds() }, breadcrumb);
|
|
2217
2261
|
this._breadcrumbs =
|
|
2218
2262
|
maxBreadcrumbs !== undefined && maxBreadcrumbs >= 0
|
|
2219
2263
|
? [...this._breadcrumbs, mergedBreadcrumb].slice(-maxBreadcrumbs)
|
|
@@ -2527,7 +2571,7 @@ var Sentry = (function (exports) {
|
|
|
2527
2571
|
if (maxBreadcrumbs <= 0) {
|
|
2528
2572
|
return;
|
|
2529
2573
|
}
|
|
2530
|
-
const timestamp =
|
|
2574
|
+
const timestamp = dateTimestampInSeconds();
|
|
2531
2575
|
const mergedBreadcrumb = Object.assign({ timestamp }, breadcrumb);
|
|
2532
2576
|
const finalBreadcrumb = beforeBreadcrumb
|
|
2533
2577
|
? consoleSandbox(() => beforeBreadcrumb(mergedBreadcrumb, hint))
|
|
@@ -3337,7 +3381,7 @@ var Sentry = (function (exports) {
|
|
|
3337
3381
|
*/
|
|
3338
3382
|
_prepareEvent(event, scope, hint) {
|
|
3339
3383
|
const { normalizeDepth = 3 } = this.getOptions();
|
|
3340
|
-
const prepared = Object.assign(Object.assign({}, event), { event_id: event.event_id || (hint && hint.event_id ? hint.event_id : uuid4()), timestamp: event.timestamp ||
|
|
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() });
|
|
3341
3385
|
this._applyClientOptions(prepared);
|
|
3342
3386
|
this._applyIntegrationsMetadata(prepared);
|
|
3343
3387
|
// If we have scope given to us, use it as the base for further modifications.
|
|
@@ -3621,7 +3665,7 @@ var Sentry = (function (exports) {
|
|
|
3621
3665
|
event_id: event.event_id,
|
|
3622
3666
|
// We need to add * 1000 since we divide it by 1000 by default but JS works with ms precision
|
|
3623
3667
|
// The reason we use timestampWithMs here is that all clocks across the SDK use the same clock
|
|
3624
|
-
sent_at: new Date(
|
|
3668
|
+
sent_at: new Date().toISOString(),
|
|
3625
3669
|
});
|
|
3626
3670
|
const itemHeaders = JSON.stringify({
|
|
3627
3671
|
type: event.type,
|
|
@@ -5342,7 +5386,7 @@ var Sentry = (function (exports) {
|
|
|
5342
5386
|
});
|
|
5343
5387
|
|
|
5344
5388
|
const SDK_NAME = 'sentry.javascript.browser';
|
|
5345
|
-
const SDK_VERSION = '5.
|
|
5389
|
+
const SDK_VERSION = '5.25.0';
|
|
5346
5390
|
|
|
5347
5391
|
/**
|
|
5348
5392
|
* The Sentry Browser SDK Client.
|