@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.
- package/build/bundle.es6.js +545 -829
- 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 +552 -860
- package/build/bundle.js.map +1 -1
- package/build/bundle.min.js +2 -2
- package/build/bundle.min.js.map +1 -1
- package/dist/transports/fetch.d.ts +0 -5
- package/dist/transports/fetch.d.ts.map +1 -1
- package/dist/transports/fetch.js +0 -34
- package/dist/transports/fetch.js.map +1 -1
- package/dist/transports/xhr.d.ts +0 -5
- package/dist/transports/xhr.d.ts.map +1 -1
- package/dist/transports/xhr.js +0 -28
- package/dist/transports/xhr.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/esm/transports/fetch.d.ts +0 -5
- package/esm/transports/fetch.d.ts.map +1 -1
- package/esm/transports/fetch.js +1 -35
- package/esm/transports/fetch.js.map +1 -1
- package/esm/transports/xhr.d.ts +0 -5
- package/esm/transports/xhr.d.ts.map +1 -1
- package/esm/transports/xhr.js +1 -29
- package/esm/transports/xhr.js.map +1 -1
- package/esm/version.d.ts +1 -1
- package/esm/version.d.ts.map +1 -1
- package/esm/version.js +1 -1
- package/esm/version.js.map +1 -1
- package/package.json +8 -6
package/build/bundle.es6.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @sentry/browser 5.25.0
|
|
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
|
-
*
|
|
1222
|
-
*
|
|
1101
|
+
* Tells whether current environment supports Fetch API
|
|
1102
|
+
* {@link supportsFetch}.
|
|
1103
|
+
*
|
|
1104
|
+
* @returns Answer to the given question.
|
|
1223
1105
|
*/
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
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
|
-
|
|
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 (
|
|
1284
|
-
|
|
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
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
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
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
reject(reason);
|
|
1179
|
+
try {
|
|
1180
|
+
new Request('_', {
|
|
1181
|
+
referrerPolicy: 'origin',
|
|
1297
1182
|
});
|
|
1183
|
+
return true;
|
|
1298
1184
|
}
|
|
1299
|
-
|
|
1300
|
-
|
|
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
|
|
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({},
|
|
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({},
|
|
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({},
|
|
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
|
|
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
|
|
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
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
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
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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 =
|
|
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 ||
|
|
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(
|
|
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
|
|
5389
|
+
const SDK_VERSION = '5.25.0';
|
|
5674
5390
|
|
|
5675
5391
|
/**
|
|
5676
5392
|
* The Sentry Browser SDK Client.
|