@myinterview/widget-react 1.1.23-beta-78ffddc → 1.1.23-binary-001
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/dist/cjs/components/CountDown.d.ts +2 -2
- package/dist/cjs/components/Counter.d.ts +2 -2
- package/dist/cjs/components/DeviceSelector.d.ts +1 -1
- package/dist/cjs/index.js +776 -2187
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/interfaces/widgetInterface.d.ts +7 -2
- package/dist/cjs/services/event.service.d.ts +6 -1
- package/dist/cjs/utils/constants.utils.d.ts +1 -0
- package/dist/esm/components/CountDown.d.ts +2 -2
- package/dist/esm/components/Counter.d.ts +2 -2
- package/dist/esm/components/DeviceSelector.d.ts +1 -1
- package/dist/esm/index.js +762 -2173
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/interfaces/widgetInterface.d.ts +7 -2
- package/dist/esm/services/event.service.d.ts +6 -1
- package/dist/esm/utils/constants.utils.d.ts +1 -0
- package/package.json +43 -43
package/dist/cjs/index.js
CHANGED
|
@@ -8,26 +8,51 @@ var reactDom = require('react-dom');
|
|
|
8
8
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
9
9
|
|
|
10
10
|
function _interopNamespace(e) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
if (e && e.__esModule) return e;
|
|
12
|
+
var n = Object.create(null);
|
|
13
|
+
if (e) {
|
|
14
|
+
Object.keys(e).forEach(function (k) {
|
|
15
|
+
if (k !== 'default') {
|
|
16
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
17
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: function () { return e[k]; }
|
|
20
|
+
});
|
|
21
|
+
}
|
|
20
22
|
});
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
n["default"] = e;
|
|
25
|
-
return Object.freeze(n);
|
|
23
|
+
}
|
|
24
|
+
n["default"] = e;
|
|
25
|
+
return Object.freeze(n);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
29
29
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
30
30
|
|
|
31
|
+
/*! *****************************************************************************
|
|
32
|
+
Copyright (c) Microsoft Corporation.
|
|
33
|
+
|
|
34
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
35
|
+
purpose with or without fee is hereby granted.
|
|
36
|
+
|
|
37
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
38
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
39
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
40
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
41
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
42
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
43
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
44
|
+
***************************************************************************** */
|
|
45
|
+
|
|
46
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
47
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
48
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
49
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
50
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
51
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
52
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
31
56
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
32
57
|
const objectToString = Object.prototype.toString;
|
|
33
58
|
|
|
@@ -948,12 +973,6 @@ function createStackParser(...parsers) {
|
|
|
948
973
|
// Remove webpack (error: *) wrappers
|
|
949
974
|
const cleanedLine = WEBPACK_ERROR_REGEXP.test(line) ? line.replace(WEBPACK_ERROR_REGEXP, '$1') : line;
|
|
950
975
|
|
|
951
|
-
// https://github.com/getsentry/sentry-javascript/issues/7813
|
|
952
|
-
// Skip Error: lines
|
|
953
|
-
if (cleanedLine.match(/\S*Error: /)) {
|
|
954
|
-
continue;
|
|
955
|
-
}
|
|
956
|
-
|
|
957
976
|
for (const parser of sortedParsers) {
|
|
958
977
|
const frame = parser(cleanedLine);
|
|
959
978
|
|
|
@@ -1138,8 +1157,6 @@ function supportsHistory() {
|
|
|
1138
1157
|
// eslint-disable-next-line deprecation/deprecation
|
|
1139
1158
|
const WINDOW$3 = getGlobalObject();
|
|
1140
1159
|
|
|
1141
|
-
const SENTRY_XHR_DATA_KEY = '__sentry_xhr_v2__';
|
|
1142
|
-
|
|
1143
1160
|
/**
|
|
1144
1161
|
* Instrument native APIs to call handlers that can be used to create breadcrumbs, APM spans etc.
|
|
1145
1162
|
* - Console API
|
|
@@ -1252,13 +1269,11 @@ function instrumentFetch() {
|
|
|
1252
1269
|
|
|
1253
1270
|
fill(WINDOW$3, 'fetch', function (originalFetch) {
|
|
1254
1271
|
return function (...args) {
|
|
1255
|
-
const { method, url } = parseFetchArgs(args);
|
|
1256
|
-
|
|
1257
1272
|
const handlerData = {
|
|
1258
1273
|
args,
|
|
1259
1274
|
fetchData: {
|
|
1260
|
-
method,
|
|
1261
|
-
url,
|
|
1275
|
+
method: getFetchMethod(args),
|
|
1276
|
+
url: getFetchUrl(args),
|
|
1262
1277
|
},
|
|
1263
1278
|
startTimestamp: Date.now(),
|
|
1264
1279
|
};
|
|
@@ -1293,53 +1308,29 @@ function instrumentFetch() {
|
|
|
1293
1308
|
});
|
|
1294
1309
|
}
|
|
1295
1310
|
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
if (typeof resource === 'string') {
|
|
1302
|
-
return resource;
|
|
1303
|
-
}
|
|
1304
|
-
|
|
1305
|
-
if (!resource) {
|
|
1306
|
-
return '';
|
|
1307
|
-
}
|
|
1308
|
-
|
|
1309
|
-
if (hasProp(resource, 'url')) {
|
|
1310
|
-
return resource.url;
|
|
1311
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
1312
|
+
/** Extract `method` from fetch call arguments */
|
|
1313
|
+
function getFetchMethod(fetchArgs = []) {
|
|
1314
|
+
if ('Request' in WINDOW$3 && isInstanceOf(fetchArgs[0], Request) && fetchArgs[0].method) {
|
|
1315
|
+
return String(fetchArgs[0].method).toUpperCase();
|
|
1311
1316
|
}
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
return resource.toString();
|
|
1317
|
+
if (fetchArgs[1] && fetchArgs[1].method) {
|
|
1318
|
+
return String(fetchArgs[1].method).toUpperCase();
|
|
1315
1319
|
}
|
|
1316
|
-
|
|
1317
|
-
return '';
|
|
1320
|
+
return 'GET';
|
|
1318
1321
|
}
|
|
1319
1322
|
|
|
1320
|
-
/**
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
if (fetchArgs.length === 0) {
|
|
1325
|
-
return { method: 'GET', url: '' };
|
|
1323
|
+
/** Extract `url` from fetch call arguments */
|
|
1324
|
+
function getFetchUrl(fetchArgs = []) {
|
|
1325
|
+
if (typeof fetchArgs[0] === 'string') {
|
|
1326
|
+
return fetchArgs[0];
|
|
1326
1327
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
const [url, options] = fetchArgs ;
|
|
1330
|
-
|
|
1331
|
-
return {
|
|
1332
|
-
url: getUrlFromResource(url),
|
|
1333
|
-
method: hasProp(options, 'method') ? String(options.method).toUpperCase() : 'GET',
|
|
1334
|
-
};
|
|
1328
|
+
if ('Request' in WINDOW$3 && isInstanceOf(fetchArgs[0], Request)) {
|
|
1329
|
+
return fetchArgs[0].url;
|
|
1335
1330
|
}
|
|
1336
|
-
|
|
1337
|
-
const arg = fetchArgs[0];
|
|
1338
|
-
return {
|
|
1339
|
-
url: getUrlFromResource(arg ),
|
|
1340
|
-
method: hasProp(arg, 'method') ? String(arg.method).toUpperCase() : 'GET',
|
|
1341
|
-
};
|
|
1331
|
+
return String(fetchArgs[0]);
|
|
1342
1332
|
}
|
|
1333
|
+
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
|
1343
1334
|
|
|
1344
1335
|
/** JSDoc */
|
|
1345
1336
|
function instrumentXHR() {
|
|
@@ -1352,11 +1343,10 @@ function instrumentXHR() {
|
|
|
1352
1343
|
fill(xhrproto, 'open', function (originalOpen) {
|
|
1353
1344
|
return function ( ...args) {
|
|
1354
1345
|
const url = args[1];
|
|
1355
|
-
const xhrInfo = (this
|
|
1346
|
+
const xhrInfo = (this.__sentry_xhr__ = {
|
|
1356
1347
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1357
1348
|
method: isString$2(args[0]) ? args[0].toUpperCase() : args[0],
|
|
1358
1349
|
url: args[1],
|
|
1359
|
-
request_headers: {},
|
|
1360
1350
|
});
|
|
1361
1351
|
|
|
1362
1352
|
// if Sentry key appears in URL, don't capture it as a request
|
|
@@ -1367,7 +1357,7 @@ function instrumentXHR() {
|
|
|
1367
1357
|
|
|
1368
1358
|
const onreadystatechangeHandler = () => {
|
|
1369
1359
|
// For whatever reason, this is not the same instance here as from the outer method
|
|
1370
|
-
const xhrInfo = this
|
|
1360
|
+
const xhrInfo = this.__sentry_xhr__;
|
|
1371
1361
|
|
|
1372
1362
|
if (!xhrInfo) {
|
|
1373
1363
|
return;
|
|
@@ -1402,32 +1392,14 @@ function instrumentXHR() {
|
|
|
1402
1392
|
this.addEventListener('readystatechange', onreadystatechangeHandler);
|
|
1403
1393
|
}
|
|
1404
1394
|
|
|
1405
|
-
// Intercepting `setRequestHeader` to access the request headers of XHR instance.
|
|
1406
|
-
// This will only work for user/library defined headers, not for the default/browser-assigned headers.
|
|
1407
|
-
// Request cookies are also unavailable for XHR, as `Cookie` header can't be defined by `setRequestHeader`.
|
|
1408
|
-
fill(this, 'setRequestHeader', function (original) {
|
|
1409
|
-
return function ( ...setRequestHeaderArgs) {
|
|
1410
|
-
const [header, value] = setRequestHeaderArgs ;
|
|
1411
|
-
|
|
1412
|
-
const xhrInfo = this[SENTRY_XHR_DATA_KEY];
|
|
1413
|
-
|
|
1414
|
-
if (xhrInfo) {
|
|
1415
|
-
xhrInfo.request_headers[header.toLowerCase()] = value;
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
return original.apply(this, setRequestHeaderArgs);
|
|
1419
|
-
};
|
|
1420
|
-
});
|
|
1421
|
-
|
|
1422
1395
|
return originalOpen.apply(this, args);
|
|
1423
1396
|
};
|
|
1424
1397
|
});
|
|
1425
1398
|
|
|
1426
1399
|
fill(xhrproto, 'send', function (originalSend) {
|
|
1427
1400
|
return function ( ...args) {
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
sentryXhrData.body = args[0];
|
|
1401
|
+
if (this.__sentry_xhr__ && args[0] !== undefined) {
|
|
1402
|
+
this.__sentry_xhr__.body = args[0];
|
|
1431
1403
|
}
|
|
1432
1404
|
|
|
1433
1405
|
triggerHandlers('xhr', {
|
|
@@ -1726,15 +1698,13 @@ function instrumentError() {
|
|
|
1726
1698
|
url,
|
|
1727
1699
|
});
|
|
1728
1700
|
|
|
1729
|
-
if (_oldOnErrorHandler
|
|
1701
|
+
if (_oldOnErrorHandler) {
|
|
1730
1702
|
// eslint-disable-next-line prefer-rest-params
|
|
1731
1703
|
return _oldOnErrorHandler.apply(this, arguments);
|
|
1732
1704
|
}
|
|
1733
1705
|
|
|
1734
1706
|
return false;
|
|
1735
1707
|
};
|
|
1736
|
-
|
|
1737
|
-
WINDOW$3.onerror.__SENTRY_INSTRUMENTED__ = true;
|
|
1738
1708
|
}
|
|
1739
1709
|
|
|
1740
1710
|
let _oldOnUnhandledRejectionHandler = null;
|
|
@@ -1745,15 +1715,13 @@ function instrumentUnhandledRejection() {
|
|
|
1745
1715
|
WINDOW$3.onunhandledrejection = function (e) {
|
|
1746
1716
|
triggerHandlers('unhandledrejection', e);
|
|
1747
1717
|
|
|
1748
|
-
if (_oldOnUnhandledRejectionHandler
|
|
1718
|
+
if (_oldOnUnhandledRejectionHandler) {
|
|
1749
1719
|
// eslint-disable-next-line prefer-rest-params
|
|
1750
1720
|
return _oldOnUnhandledRejectionHandler.apply(this, arguments);
|
|
1751
1721
|
}
|
|
1752
1722
|
|
|
1753
1723
|
return true;
|
|
1754
1724
|
};
|
|
1755
|
-
|
|
1756
|
-
WINDOW$3.onunhandledrejection.__SENTRY_INSTRUMENTED__ = true;
|
|
1757
1725
|
}
|
|
1758
1726
|
|
|
1759
1727
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
@@ -2051,7 +2019,7 @@ function loadModule(moduleName) {
|
|
|
2051
2019
|
* @returns A normalized version of the object, or `"**non-serializable**"` if any errors are thrown during normalization.
|
|
2052
2020
|
*/
|
|
2053
2021
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2054
|
-
function normalize(input, depth =
|
|
2022
|
+
function normalize(input, depth = +Infinity, maxProperties = +Infinity) {
|
|
2055
2023
|
try {
|
|
2056
2024
|
// since we're at the outermost level, we don't provide a key
|
|
2057
2025
|
return visit('', input, depth, maxProperties);
|
|
@@ -2097,10 +2065,7 @@ function visit(
|
|
|
2097
2065
|
const [memoize, unmemoize] = memo;
|
|
2098
2066
|
|
|
2099
2067
|
// Get the simple cases out of the way first
|
|
2100
|
-
if (
|
|
2101
|
-
value == null || // this matches null and undefined -> eqeq not eqeqeq
|
|
2102
|
-
(['number', 'boolean', 'string'].includes(typeof value) && !isNaN$1(value))
|
|
2103
|
-
) {
|
|
2068
|
+
if (value === null || (['number', 'boolean', 'string'].includes(typeof value) && !isNaN$1(value))) {
|
|
2104
2069
|
return value ;
|
|
2105
2070
|
}
|
|
2106
2071
|
|
|
@@ -2121,16 +2086,17 @@ function visit(
|
|
|
2121
2086
|
return value ;
|
|
2122
2087
|
}
|
|
2123
2088
|
|
|
2124
|
-
//
|
|
2125
|
-
//
|
|
2126
|
-
//
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2089
|
+
// Do not normalize objects that we know have already been normalized. As a general rule, the
|
|
2090
|
+
// "__sentry_skip_normalization__" property should only be used sparingly and only should only be set on objects that
|
|
2091
|
+
// have already been normalized.
|
|
2092
|
+
let overriddenDepth = depth;
|
|
2093
|
+
|
|
2094
|
+
if (typeof (value )['__sentry_override_normalization_depth__'] === 'number') {
|
|
2095
|
+
overriddenDepth = (value )['__sentry_override_normalization_depth__'] ;
|
|
2096
|
+
}
|
|
2131
2097
|
|
|
2132
2098
|
// We're also done if we've reached the max depth
|
|
2133
|
-
if (
|
|
2099
|
+
if (overriddenDepth === 0) {
|
|
2134
2100
|
// At this point we know `serialized` is a string of the form `"[object XXXX]"`. Clean it up so it's just `"[XXXX]"`.
|
|
2135
2101
|
return stringified.replace('object ', '');
|
|
2136
2102
|
}
|
|
@@ -2146,7 +2112,7 @@ function visit(
|
|
|
2146
2112
|
try {
|
|
2147
2113
|
const jsonValue = valueWithToJSON.toJSON();
|
|
2148
2114
|
// We need to normalize the return value of `.toJSON()` in case it has circular references
|
|
2149
|
-
return visit('', jsonValue,
|
|
2115
|
+
return visit('', jsonValue, overriddenDepth - 1, maxProperties, memo);
|
|
2150
2116
|
} catch (err) {
|
|
2151
2117
|
// pass (The built-in `toJSON` failed, but we can still try to do it ourselves)
|
|
2152
2118
|
}
|
|
@@ -2175,7 +2141,7 @@ function visit(
|
|
|
2175
2141
|
|
|
2176
2142
|
// Recursively visit all the child nodes
|
|
2177
2143
|
const visitValue = visitable[visitKey];
|
|
2178
|
-
normalized[visitKey] = visit(visitKey, visitValue,
|
|
2144
|
+
normalized[visitKey] = visit(visitKey, visitValue, overriddenDepth - 1, maxProperties, memo);
|
|
2179
2145
|
|
|
2180
2146
|
numAdded++;
|
|
2181
2147
|
}
|
|
@@ -2187,7 +2153,6 @@ function visit(
|
|
|
2187
2153
|
return normalized;
|
|
2188
2154
|
}
|
|
2189
2155
|
|
|
2190
|
-
/* eslint-disable complexity */
|
|
2191
2156
|
/**
|
|
2192
2157
|
* Stringify the given value. Handles various known special values and types.
|
|
2193
2158
|
*
|
|
@@ -2238,6 +2203,11 @@ function stringifyValue(
|
|
|
2238
2203
|
return '[NaN]';
|
|
2239
2204
|
}
|
|
2240
2205
|
|
|
2206
|
+
// this catches `undefined` (but not `null`, which is a primitive and can be serialized on its own)
|
|
2207
|
+
if (value === void 0) {
|
|
2208
|
+
return '[undefined]';
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2241
2211
|
if (typeof value === 'function') {
|
|
2242
2212
|
return `[Function: ${getFunctionName(value)}]`;
|
|
2243
2213
|
}
|
|
@@ -2255,19 +2225,11 @@ function stringifyValue(
|
|
|
2255
2225
|
// them to strings means that instances of classes which haven't defined their `toStringTag` will just come out as
|
|
2256
2226
|
// `"[object Object]"`. If we instead look at the constructor's name (which is the same as the name of the class),
|
|
2257
2227
|
// we can make sure that only plain objects come out that way.
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
// Handle HTML Elements
|
|
2261
|
-
if (/^HTML(\w*)Element$/.test(objName)) {
|
|
2262
|
-
return `[HTMLElement: ${objName}]`;
|
|
2263
|
-
}
|
|
2264
|
-
|
|
2265
|
-
return `[object ${objName}]`;
|
|
2228
|
+
return `[object ${getConstructorName(value)}]`;
|
|
2266
2229
|
} catch (err) {
|
|
2267
2230
|
return `**non-serializable** (${err})`;
|
|
2268
2231
|
}
|
|
2269
2232
|
}
|
|
2270
|
-
/* eslint-enable complexity */
|
|
2271
2233
|
|
|
2272
2234
|
function getConstructorName(value) {
|
|
2273
2235
|
const prototype = Object.getPrototypeOf(value);
|
|
@@ -2578,7 +2540,9 @@ function makePromiseBuffer(limit) {
|
|
|
2578
2540
|
* // environments where DOM might not be available
|
|
2579
2541
|
* @returns parsed URL object
|
|
2580
2542
|
*/
|
|
2581
|
-
function parseUrl(url)
|
|
2543
|
+
function parseUrl(url)
|
|
2544
|
+
|
|
2545
|
+
{
|
|
2582
2546
|
if (!url) {
|
|
2583
2547
|
return {};
|
|
2584
2548
|
}
|
|
@@ -2596,8 +2560,6 @@ function parseUrl(url) {
|
|
|
2596
2560
|
host: match[4],
|
|
2597
2561
|
path: match[5],
|
|
2598
2562
|
protocol: match[2],
|
|
2599
|
-
search: query,
|
|
2600
|
-
hash: fragment,
|
|
2601
2563
|
relative: match[5] + query + fragment, // everything minus origin
|
|
2602
2564
|
};
|
|
2603
2565
|
}
|
|
@@ -2982,7 +2944,6 @@ const ITEM_TYPE_TO_DATA_CATEGORY_MAP = {
|
|
|
2982
2944
|
profile: 'profile',
|
|
2983
2945
|
replay_event: 'replay',
|
|
2984
2946
|
replay_recording: 'replay',
|
|
2985
|
-
check_in: 'monitor',
|
|
2986
2947
|
};
|
|
2987
2948
|
|
|
2988
2949
|
/**
|
|
@@ -3012,14 +2973,16 @@ function createEventEnvelopeHeaders(
|
|
|
3012
2973
|
dsn,
|
|
3013
2974
|
) {
|
|
3014
2975
|
const dynamicSamplingContext = event.sdkProcessingMetadata && event.sdkProcessingMetadata.dynamicSamplingContext;
|
|
2976
|
+
|
|
3015
2977
|
return {
|
|
3016
2978
|
event_id: event.event_id ,
|
|
3017
2979
|
sent_at: new Date().toISOString(),
|
|
3018
2980
|
...(sdkInfo && { sdk: sdkInfo }),
|
|
3019
2981
|
...(!!tunnel && { dsn: dsnToString(dsn) }),
|
|
3020
|
-
...(
|
|
3021
|
-
|
|
3022
|
-
|
|
2982
|
+
...(event.type === 'transaction' &&
|
|
2983
|
+
dynamicSamplingContext && {
|
|
2984
|
+
trace: dropUndefinedKeys({ ...dynamicSamplingContext }),
|
|
2985
|
+
}),
|
|
3023
2986
|
};
|
|
3024
2987
|
}
|
|
3025
2988
|
|
|
@@ -3724,16 +3687,9 @@ class Scope {
|
|
|
3724
3687
|
// errors with transaction and it relies on that.
|
|
3725
3688
|
if (this._span) {
|
|
3726
3689
|
event.contexts = { trace: this._span.getTraceContext(), ...event.contexts };
|
|
3727
|
-
const
|
|
3728
|
-
if (
|
|
3729
|
-
event.
|
|
3730
|
-
dynamicSamplingContext: transaction.getDynamicSamplingContext(),
|
|
3731
|
-
...event.sdkProcessingMetadata,
|
|
3732
|
-
};
|
|
3733
|
-
const transactionName = transaction.name;
|
|
3734
|
-
if (transactionName) {
|
|
3735
|
-
event.tags = { transaction: transactionName, ...event.tags };
|
|
3736
|
-
}
|
|
3690
|
+
const transactionName = this._span.transaction && this._span.transaction.name;
|
|
3691
|
+
if (transactionName) {
|
|
3692
|
+
event.tags = { transaction: transactionName, ...event.tags };
|
|
3737
3693
|
}
|
|
3738
3694
|
}
|
|
3739
3695
|
|
|
@@ -3857,6 +3813,11 @@ const API_VERSION = 4;
|
|
|
3857
3813
|
*/
|
|
3858
3814
|
const DEFAULT_BREADCRUMBS = 100;
|
|
3859
3815
|
|
|
3816
|
+
/**
|
|
3817
|
+
* A layer in the process stack.
|
|
3818
|
+
* @hidden
|
|
3819
|
+
*/
|
|
3820
|
+
|
|
3860
3821
|
/**
|
|
3861
3822
|
* @inheritDoc
|
|
3862
3823
|
*/
|
|
@@ -4134,17 +4095,7 @@ class Hub {
|
|
|
4134
4095
|
* @inheritDoc
|
|
4135
4096
|
*/
|
|
4136
4097
|
startTransaction(context, customSamplingContext) {
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && !result) {
|
|
4140
|
-
// eslint-disable-next-line no-console
|
|
4141
|
-
console.warn(`Tracing extension 'startTransaction' has not been added. Call 'addTracingExtensions' before calling 'init':
|
|
4142
|
-
Sentry.addTracingExtensions();
|
|
4143
|
-
Sentry.init({...});
|
|
4144
|
-
`);
|
|
4145
|
-
}
|
|
4146
|
-
|
|
4147
|
-
return result;
|
|
4098
|
+
return this._callExtensionMethod('startTransaction', context, customSamplingContext);
|
|
4148
4099
|
}
|
|
4149
4100
|
|
|
4150
4101
|
/**
|
|
@@ -4229,10 +4180,13 @@ Sentry.init({...});
|
|
|
4229
4180
|
*/
|
|
4230
4181
|
_sendSessionUpdate() {
|
|
4231
4182
|
const { scope, client } = this.getStackTop();
|
|
4183
|
+
if (!scope) return;
|
|
4232
4184
|
|
|
4233
4185
|
const session = scope.getSession();
|
|
4234
|
-
if (session
|
|
4235
|
-
client.captureSession
|
|
4186
|
+
if (session) {
|
|
4187
|
+
if (client && client.captureSession) {
|
|
4188
|
+
client.captureSession(session);
|
|
4189
|
+
}
|
|
4236
4190
|
}
|
|
4237
4191
|
}
|
|
4238
4192
|
|
|
@@ -4302,28 +4256,47 @@ function getCurrentHub() {
|
|
|
4302
4256
|
// Get main carrier (global for every environment)
|
|
4303
4257
|
const registry = getMainCarrier();
|
|
4304
4258
|
|
|
4305
|
-
if (registry.__SENTRY__ && registry.__SENTRY__.acs) {
|
|
4306
|
-
const hub = registry.__SENTRY__.acs.getCurrentHub();
|
|
4307
|
-
|
|
4308
|
-
if (hub) {
|
|
4309
|
-
return hub;
|
|
4310
|
-
}
|
|
4311
|
-
}
|
|
4312
|
-
|
|
4313
|
-
// Return hub that lives on a global object
|
|
4314
|
-
return getGlobalHub(registry);
|
|
4315
|
-
}
|
|
4316
|
-
|
|
4317
|
-
function getGlobalHub(registry = getMainCarrier()) {
|
|
4318
4259
|
// If there's no hub, or its an old API, assign a new one
|
|
4319
4260
|
if (!hasHubOnCarrier(registry) || getHubFromCarrier(registry).isOlderThan(API_VERSION)) {
|
|
4320
4261
|
setHubOnCarrier(registry, new Hub());
|
|
4321
4262
|
}
|
|
4322
4263
|
|
|
4264
|
+
// Prefer domains over global if they are there (applicable only to Node environment)
|
|
4265
|
+
if (isNodeEnv()) {
|
|
4266
|
+
return getHubFromActiveDomain(registry);
|
|
4267
|
+
}
|
|
4323
4268
|
// Return hub that lives on a global object
|
|
4324
4269
|
return getHubFromCarrier(registry);
|
|
4325
4270
|
}
|
|
4326
4271
|
|
|
4272
|
+
/**
|
|
4273
|
+
* Try to read the hub from an active domain, and fallback to the registry if one doesn't exist
|
|
4274
|
+
* @returns discovered hub
|
|
4275
|
+
*/
|
|
4276
|
+
function getHubFromActiveDomain(registry) {
|
|
4277
|
+
try {
|
|
4278
|
+
const sentry = getMainCarrier().__SENTRY__;
|
|
4279
|
+
const activeDomain = sentry && sentry.extensions && sentry.extensions.domain && sentry.extensions.domain.active;
|
|
4280
|
+
|
|
4281
|
+
// If there's no active domain, just return global hub
|
|
4282
|
+
if (!activeDomain) {
|
|
4283
|
+
return getHubFromCarrier(registry);
|
|
4284
|
+
}
|
|
4285
|
+
|
|
4286
|
+
// If there's no hub on current domain, or it's an old API, assign a new one
|
|
4287
|
+
if (!hasHubOnCarrier(activeDomain) || getHubFromCarrier(activeDomain).isOlderThan(API_VERSION)) {
|
|
4288
|
+
const registryHubTopStack = getHubFromCarrier(registry).getStackTop();
|
|
4289
|
+
setHubOnCarrier(activeDomain, new Hub(registryHubTopStack.client, Scope.clone(registryHubTopStack.scope)));
|
|
4290
|
+
}
|
|
4291
|
+
|
|
4292
|
+
// Return hub that lives on a domain
|
|
4293
|
+
return getHubFromCarrier(activeDomain);
|
|
4294
|
+
} catch (_Oo) {
|
|
4295
|
+
// Return hub that lives on a global object
|
|
4296
|
+
return getHubFromCarrier(registry);
|
|
4297
|
+
}
|
|
4298
|
+
}
|
|
4299
|
+
|
|
4327
4300
|
/**
|
|
4328
4301
|
* This will tell whether a carrier has a hub on it or not
|
|
4329
4302
|
* @param carrier object
|
|
@@ -4397,69 +4370,6 @@ var SpanStatus; (function (SpanStatus) {
|
|
|
4397
4370
|
const DataLoss = 'data_loss'; SpanStatus["DataLoss"] = DataLoss;
|
|
4398
4371
|
})(SpanStatus || (SpanStatus = {}));
|
|
4399
4372
|
|
|
4400
|
-
/**
|
|
4401
|
-
* Wraps a function with a transaction/span and finishes the span after the function is done.
|
|
4402
|
-
*
|
|
4403
|
-
* Note that if you have not enabled tracing extensions via `addTracingExtensions`, this function
|
|
4404
|
-
* will not generate spans, and the `span` returned from the callback may be undefined.
|
|
4405
|
-
*
|
|
4406
|
-
* This function is meant to be used internally and may break at any time. Use at your own risk.
|
|
4407
|
-
*
|
|
4408
|
-
* @internal
|
|
4409
|
-
* @private
|
|
4410
|
-
*/
|
|
4411
|
-
function trace(
|
|
4412
|
-
context,
|
|
4413
|
-
callback,
|
|
4414
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
4415
|
-
onError = () => {},
|
|
4416
|
-
) {
|
|
4417
|
-
const ctx = { ...context };
|
|
4418
|
-
// If a name is set and a description is not, set the description to the name.
|
|
4419
|
-
if (ctx.name !== undefined && ctx.description === undefined) {
|
|
4420
|
-
ctx.description = ctx.name;
|
|
4421
|
-
}
|
|
4422
|
-
|
|
4423
|
-
const hub = getCurrentHub();
|
|
4424
|
-
const scope = hub.getScope();
|
|
4425
|
-
|
|
4426
|
-
const parentSpan = scope.getSpan();
|
|
4427
|
-
const activeSpan = parentSpan ? parentSpan.startChild(ctx) : hub.startTransaction(ctx);
|
|
4428
|
-
scope.setSpan(activeSpan);
|
|
4429
|
-
|
|
4430
|
-
function finishAndSetSpan() {
|
|
4431
|
-
activeSpan && activeSpan.finish();
|
|
4432
|
-
hub.getScope().setSpan(parentSpan);
|
|
4433
|
-
}
|
|
4434
|
-
|
|
4435
|
-
let maybePromiseResult;
|
|
4436
|
-
try {
|
|
4437
|
-
maybePromiseResult = callback(activeSpan);
|
|
4438
|
-
} catch (e) {
|
|
4439
|
-
activeSpan && activeSpan.setStatus('internal_error');
|
|
4440
|
-
onError(e);
|
|
4441
|
-
finishAndSetSpan();
|
|
4442
|
-
throw e;
|
|
4443
|
-
}
|
|
4444
|
-
|
|
4445
|
-
if (isThenable(maybePromiseResult)) {
|
|
4446
|
-
Promise.resolve(maybePromiseResult).then(
|
|
4447
|
-
() => {
|
|
4448
|
-
finishAndSetSpan();
|
|
4449
|
-
},
|
|
4450
|
-
e => {
|
|
4451
|
-
activeSpan && activeSpan.setStatus('internal_error');
|
|
4452
|
-
onError(e);
|
|
4453
|
-
finishAndSetSpan();
|
|
4454
|
-
},
|
|
4455
|
-
);
|
|
4456
|
-
} else {
|
|
4457
|
-
finishAndSetSpan();
|
|
4458
|
-
}
|
|
4459
|
-
|
|
4460
|
-
return maybePromiseResult;
|
|
4461
|
-
}
|
|
4462
|
-
|
|
4463
4373
|
// Note: All functions in this file are typed with a return value of `ReturnType<Hub[HUB_FUNCTION]>`,
|
|
4464
4374
|
// where HUB_FUNCTION is some method on the Hub class.
|
|
4465
4375
|
//
|
|
@@ -4801,11 +4711,7 @@ function prepareEvent(
|
|
|
4801
4711
|
|
|
4802
4712
|
applyClientOptions(prepared, options);
|
|
4803
4713
|
applyIntegrationsMetadata(prepared, integrations);
|
|
4804
|
-
|
|
4805
|
-
// Only apply debug metadata to error events.
|
|
4806
|
-
if (event.type === undefined) {
|
|
4807
|
-
applyDebugMetadata(prepared, options.stackParser);
|
|
4808
|
-
}
|
|
4714
|
+
applyDebugMetadata(prepared, options.stackParser);
|
|
4809
4715
|
|
|
4810
4716
|
// If we have scope given to us, use it as the base for further modifications.
|
|
4811
4717
|
// This allows us to prevent unnecessary copying of data if `captureContext` is not provided.
|
|
@@ -4882,8 +4788,6 @@ function applyClientOptions(event, options) {
|
|
|
4882
4788
|
}
|
|
4883
4789
|
}
|
|
4884
4790
|
|
|
4885
|
-
const debugIdStackParserCache = new WeakMap();
|
|
4886
|
-
|
|
4887
4791
|
/**
|
|
4888
4792
|
* Applies debug metadata images to the event in order to apply source maps by looking up their debug ID.
|
|
4889
4793
|
*/
|
|
@@ -4894,28 +4798,10 @@ function applyDebugMetadata(event, stackParser) {
|
|
|
4894
4798
|
return;
|
|
4895
4799
|
}
|
|
4896
4800
|
|
|
4897
|
-
let debugIdStackFramesCache;
|
|
4898
|
-
const cachedDebugIdStackFrameCache = debugIdStackParserCache.get(stackParser);
|
|
4899
|
-
if (cachedDebugIdStackFrameCache) {
|
|
4900
|
-
debugIdStackFramesCache = cachedDebugIdStackFrameCache;
|
|
4901
|
-
} else {
|
|
4902
|
-
debugIdStackFramesCache = new Map();
|
|
4903
|
-
debugIdStackParserCache.set(stackParser, debugIdStackFramesCache);
|
|
4904
|
-
}
|
|
4905
|
-
|
|
4906
4801
|
// Build a map of filename -> debug_id
|
|
4907
4802
|
const filenameDebugIdMap = Object.keys(debugIdMap).reduce((acc, debugIdStackTrace) => {
|
|
4908
|
-
|
|
4909
|
-
const
|
|
4910
|
-
if (cachedParsedStack) {
|
|
4911
|
-
parsedStack = cachedParsedStack;
|
|
4912
|
-
} else {
|
|
4913
|
-
parsedStack = stackParser(debugIdStackTrace);
|
|
4914
|
-
debugIdStackFramesCache.set(debugIdStackTrace, parsedStack);
|
|
4915
|
-
}
|
|
4916
|
-
|
|
4917
|
-
for (let i = parsedStack.length - 1; i >= 0; i--) {
|
|
4918
|
-
const stackFrame = parsedStack[i];
|
|
4803
|
+
const parsedStack = stackParser(debugIdStackTrace);
|
|
4804
|
+
for (const stackFrame of parsedStack) {
|
|
4919
4805
|
if (stackFrame.filename) {
|
|
4920
4806
|
acc[stackFrame.filename] = debugIdMap[debugIdStackTrace];
|
|
4921
4807
|
break;
|
|
@@ -5820,7 +5706,7 @@ function getEventForEnvelopeItem(item, type) {
|
|
|
5820
5706
|
return Array.isArray(item) ? (item )[1] : undefined;
|
|
5821
5707
|
}
|
|
5822
5708
|
|
|
5823
|
-
const SDK_VERSION = '7.
|
|
5709
|
+
const SDK_VERSION = '7.46.0';
|
|
5824
5710
|
|
|
5825
5711
|
let originalFunctionToString;
|
|
5826
5712
|
|
|
@@ -5843,17 +5729,11 @@ class FunctionToString {constructor() { FunctionToString.prototype.__init.call(
|
|
|
5843
5729
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
5844
5730
|
originalFunctionToString = Function.prototype.toString;
|
|
5845
5731
|
|
|
5846
|
-
//
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
const context = getOriginalFunction(this) || this;
|
|
5852
|
-
return originalFunctionToString.apply(context, args);
|
|
5853
|
-
};
|
|
5854
|
-
} catch (e) {
|
|
5855
|
-
// ignore errors here, just don't patch this
|
|
5856
|
-
}
|
|
5732
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5733
|
+
Function.prototype.toString = function ( ...args) {
|
|
5734
|
+
const context = getOriginalFunction(this) || this;
|
|
5735
|
+
return originalFunctionToString.apply(context, args);
|
|
5736
|
+
};
|
|
5857
5737
|
}
|
|
5858
5738
|
} FunctionToString.__initStatic();
|
|
5859
5739
|
|
|
@@ -6001,9 +5881,8 @@ function _getPossibleEventMessages(event) {
|
|
|
6001
5881
|
return [event.message];
|
|
6002
5882
|
}
|
|
6003
5883
|
if (event.exception) {
|
|
6004
|
-
const { values } = event.exception;
|
|
6005
5884
|
try {
|
|
6006
|
-
const { type = '', value = '' } = (values && values[
|
|
5885
|
+
const { type = '', value = '' } = (event.exception.values && event.exception.values[0]) || {};
|
|
6007
5886
|
return [`${value}`, `${type}: ${value}`];
|
|
6008
5887
|
} catch (oO) {
|
|
6009
5888
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(`Cannot extract message for event ${getEventDescription(event)}`);
|
|
@@ -6053,9 +5932,9 @@ function _getEventFilterUrl(event) {
|
|
|
6053
5932
|
}
|
|
6054
5933
|
|
|
6055
5934
|
var Integrations = /*#__PURE__*/Object.freeze({
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
5935
|
+
__proto__: null,
|
|
5936
|
+
FunctionToString: FunctionToString,
|
|
5937
|
+
InboundFilters: InboundFilters
|
|
6059
5938
|
});
|
|
6060
5939
|
|
|
6061
5940
|
const WINDOW$1 = GLOBAL_OBJ ;
|
|
@@ -6662,14 +6541,12 @@ function _consoleBreadcrumb(handlerData) {
|
|
|
6662
6541
|
function _xhrBreadcrumb(handlerData) {
|
|
6663
6542
|
const { startTimestamp, endTimestamp } = handlerData;
|
|
6664
6543
|
|
|
6665
|
-
const sentryXhrData = handlerData.xhr[SENTRY_XHR_DATA_KEY];
|
|
6666
|
-
|
|
6667
6544
|
// We only capture complete, non-sentry requests
|
|
6668
|
-
if (!startTimestamp || !endTimestamp || !
|
|
6545
|
+
if (!startTimestamp || !endTimestamp || !handlerData.xhr.__sentry_xhr__) {
|
|
6669
6546
|
return;
|
|
6670
6547
|
}
|
|
6671
6548
|
|
|
6672
|
-
const { method, url, status_code, body } =
|
|
6549
|
+
const { method, url, status_code, body } = handlerData.xhr.__sentry_xhr__;
|
|
6673
6550
|
|
|
6674
6551
|
const data = {
|
|
6675
6552
|
method,
|
|
@@ -6787,43 +6664,6 @@ function _isEvent(event) {
|
|
|
6787
6664
|
return event && !!(event ).target;
|
|
6788
6665
|
}
|
|
6789
6666
|
|
|
6790
|
-
/**
|
|
6791
|
-
* Creates an envelope from a user feedback.
|
|
6792
|
-
*/
|
|
6793
|
-
function createUserFeedbackEnvelope(
|
|
6794
|
-
feedback,
|
|
6795
|
-
{
|
|
6796
|
-
metadata,
|
|
6797
|
-
tunnel,
|
|
6798
|
-
dsn,
|
|
6799
|
-
}
|
|
6800
|
-
|
|
6801
|
-
,
|
|
6802
|
-
) {
|
|
6803
|
-
const headers = {
|
|
6804
|
-
event_id: feedback.event_id,
|
|
6805
|
-
sent_at: new Date().toISOString(),
|
|
6806
|
-
...(metadata &&
|
|
6807
|
-
metadata.sdk && {
|
|
6808
|
-
sdk: {
|
|
6809
|
-
name: metadata.sdk.name,
|
|
6810
|
-
version: metadata.sdk.version,
|
|
6811
|
-
},
|
|
6812
|
-
}),
|
|
6813
|
-
...(!!tunnel && !!dsn && { dsn: dsnToString(dsn) }),
|
|
6814
|
-
};
|
|
6815
|
-
const item = createUserFeedbackEnvelopeItem(feedback);
|
|
6816
|
-
|
|
6817
|
-
return createEnvelope(headers, [item]);
|
|
6818
|
-
}
|
|
6819
|
-
|
|
6820
|
-
function createUserFeedbackEnvelopeItem(feedback) {
|
|
6821
|
-
const feedbackHeaders = {
|
|
6822
|
-
type: 'user_report',
|
|
6823
|
-
};
|
|
6824
|
-
return [feedbackHeaders, feedback];
|
|
6825
|
-
}
|
|
6826
|
-
|
|
6827
6667
|
/**
|
|
6828
6668
|
* Configuration options for the Sentry Browser SDK.
|
|
6829
6669
|
* @see @sentry/types Options for more information.
|
|
@@ -6906,23 +6746,6 @@ class BrowserClient extends BaseClient {
|
|
|
6906
6746
|
super.sendEvent(event, hint);
|
|
6907
6747
|
}
|
|
6908
6748
|
|
|
6909
|
-
/**
|
|
6910
|
-
* Sends user feedback to Sentry.
|
|
6911
|
-
*/
|
|
6912
|
-
captureUserFeedback(feedback) {
|
|
6913
|
-
if (!this._isEnabled()) {
|
|
6914
|
-
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('SDK not enabled, will not capture user feedback.');
|
|
6915
|
-
return;
|
|
6916
|
-
}
|
|
6917
|
-
|
|
6918
|
-
const envelope = createUserFeedbackEnvelope(feedback, {
|
|
6919
|
-
metadata: this.getSdkMetadata(),
|
|
6920
|
-
dsn: this.getDsn(),
|
|
6921
|
-
tunnel: this.getOptions().tunnel,
|
|
6922
|
-
});
|
|
6923
|
-
void this._sendEnvelope(envelope);
|
|
6924
|
-
}
|
|
6925
|
-
|
|
6926
6749
|
/**
|
|
6927
6750
|
* @inheritDoc
|
|
6928
6751
|
*/
|
|
@@ -7165,7 +6988,7 @@ function createFrame(filename, func, lineno, colno) {
|
|
|
7165
6988
|
|
|
7166
6989
|
// Chromium based browsers: Chrome, Brave, new Opera, new Edge
|
|
7167
6990
|
const chromeRegex =
|
|
7168
|
-
/^\s*at (?:(
|
|
6991
|
+
/^\s*at (?:(.*\).*?|.*?) ?\((?:address at )?)?(?:async )?((?:file|https?|blob|chrome-extension|address|native|eval|webpack|<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
|
|
7169
6992
|
const chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/;
|
|
7170
6993
|
|
|
7171
6994
|
const chrome = line => {
|
|
@@ -7201,7 +7024,7 @@ const chromeStackLineParser = [CHROME_PRIORITY, chrome];
|
|
|
7201
7024
|
// generates filenames without a prefix like `file://` the filenames in the stacktrace are just 42.js
|
|
7202
7025
|
// We need this specific case for now because we want no other regex to match.
|
|
7203
7026
|
const geckoREgex =
|
|
7204
|
-
/^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:
|
|
7027
|
+
/^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:file|https?|blob|chrome|webpack|resource|moz-extension|safari-extension|safari-web-extension|capacitor)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
|
|
7205
7028
|
const geckoEvalRegex = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
|
|
7206
7029
|
|
|
7207
7030
|
const gecko = line => {
|
|
@@ -7233,7 +7056,8 @@ const gecko = line => {
|
|
|
7233
7056
|
|
|
7234
7057
|
const geckoStackLineParser = [GECKO_PRIORITY, gecko];
|
|
7235
7058
|
|
|
7236
|
-
const winjsRegex =
|
|
7059
|
+
const winjsRegex =
|
|
7060
|
+
/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
|
|
7237
7061
|
|
|
7238
7062
|
const winjs = line => {
|
|
7239
7063
|
const parts = winjsRegex.exec(line);
|
|
@@ -8279,13 +8103,13 @@ function startSessionTracking() {
|
|
|
8279
8103
|
}
|
|
8280
8104
|
|
|
8281
8105
|
var index$1 = /*#__PURE__*/Object.freeze({
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8106
|
+
__proto__: null,
|
|
8107
|
+
GlobalHandlers: GlobalHandlers,
|
|
8108
|
+
TryCatch: TryCatch,
|
|
8109
|
+
Breadcrumbs: Breadcrumbs,
|
|
8110
|
+
LinkedErrors: LinkedErrors,
|
|
8111
|
+
HttpContext: HttpContext,
|
|
8112
|
+
Dedupe: Dedupe
|
|
8289
8113
|
});
|
|
8290
8114
|
|
|
8291
8115
|
// exporting a separate copy of `WINDOW` rather than exporting the one from `@sentry/browser`
|
|
@@ -8298,14 +8122,11 @@ const REPLAY_SESSION_KEY = 'sentryReplaySession';
|
|
|
8298
8122
|
const REPLAY_EVENT_NAME = 'replay_event';
|
|
8299
8123
|
const UNABLE_TO_SEND_REPLAY = 'Unable to send Replay';
|
|
8300
8124
|
|
|
8301
|
-
// The idle limit for a session
|
|
8302
|
-
const
|
|
8303
|
-
|
|
8304
|
-
// The idle limit for a session after which the session expires.
|
|
8305
|
-
const SESSION_IDLE_EXPIRE_DURATION = 900000; // 15 minutes in ms
|
|
8125
|
+
// The idle limit for a session
|
|
8126
|
+
const SESSION_IDLE_DURATION = 300000; // 5 minutes in ms
|
|
8306
8127
|
|
|
8307
8128
|
// The maximum length of a session
|
|
8308
|
-
const MAX_SESSION_LIFE = 3600000; // 60 minutes
|
|
8129
|
+
const MAX_SESSION_LIFE = 3600000; // 60 minutes
|
|
8309
8130
|
|
|
8310
8131
|
/** Default flush delays */
|
|
8311
8132
|
const DEFAULT_FLUSH_MIN_DELAY = 5000;
|
|
@@ -8314,16 +8135,13 @@ const DEFAULT_FLUSH_MIN_DELAY = 5000;
|
|
|
8314
8135
|
const DEFAULT_FLUSH_MAX_DELAY = 5500;
|
|
8315
8136
|
|
|
8316
8137
|
/* How long to wait for error checkouts */
|
|
8317
|
-
const
|
|
8138
|
+
const ERROR_CHECKOUT_TIME = 60000;
|
|
8318
8139
|
|
|
8319
8140
|
const RETRY_BASE_INTERVAL = 5000;
|
|
8320
8141
|
const RETRY_MAX_COUNT = 3;
|
|
8321
8142
|
|
|
8322
|
-
/* The max (uncompressed) size in bytes of a network body. Any body larger than this will be
|
|
8323
|
-
const NETWORK_BODY_MAX_SIZE =
|
|
8324
|
-
|
|
8325
|
-
/* The max size of a single console arg that is captured. Any arg larger than this will be truncated. */
|
|
8326
|
-
const CONSOLE_ARG_MAX_SIZE = 5000;
|
|
8143
|
+
/* The max (uncompressed) size in bytes of a network body. Any body larger than this will be dropped. */
|
|
8144
|
+
const NETWORK_BODY_MAX_SIZE = 300000;
|
|
8327
8145
|
|
|
8328
8146
|
var NodeType$1;
|
|
8329
8147
|
(function (NodeType) {
|
|
@@ -8360,7 +8178,7 @@ function maskInputValue({ input, maskInputSelector, unmaskInputSelector, maskInp
|
|
|
8360
8178
|
if (unmaskInputSelector && input.matches(unmaskInputSelector)) {
|
|
8361
8179
|
return text;
|
|
8362
8180
|
}
|
|
8363
|
-
if (input.hasAttribute('
|
|
8181
|
+
if (input.hasAttribute('rr_is_password')) {
|
|
8364
8182
|
type = 'password';
|
|
8365
8183
|
}
|
|
8366
8184
|
if (isInputTypeMasked({ maskInputOptions, tagName, type }) ||
|
|
@@ -8393,21 +8211,6 @@ function is2DCanvasBlank(canvas) {
|
|
|
8393
8211
|
}
|
|
8394
8212
|
return true;
|
|
8395
8213
|
}
|
|
8396
|
-
function getInputType(element) {
|
|
8397
|
-
const type = element.type;
|
|
8398
|
-
return element.hasAttribute('data-rr-is-password')
|
|
8399
|
-
? 'password'
|
|
8400
|
-
: type
|
|
8401
|
-
? type.toLowerCase()
|
|
8402
|
-
: null;
|
|
8403
|
-
}
|
|
8404
|
-
function getInputValue(el, tagName, type) {
|
|
8405
|
-
typeof type === 'string' ? type.toLowerCase() : '';
|
|
8406
|
-
if (tagName === 'INPUT' && (type === 'radio' || type === 'checkbox')) {
|
|
8407
|
-
return el.getAttribute('value') || '';
|
|
8408
|
-
}
|
|
8409
|
-
return el.value;
|
|
8410
|
-
}
|
|
8411
8214
|
|
|
8412
8215
|
let _id = 1;
|
|
8413
8216
|
const tagNameRegex = new RegExp('[^a-z0-9-_:]');
|
|
@@ -8446,13 +8249,6 @@ function getCssRuleString(rule) {
|
|
|
8446
8249
|
catch (_a) {
|
|
8447
8250
|
}
|
|
8448
8251
|
}
|
|
8449
|
-
return validateStringifiedCssRule(cssStringified);
|
|
8450
|
-
}
|
|
8451
|
-
function validateStringifiedCssRule(cssStringified) {
|
|
8452
|
-
if (cssStringified.indexOf(':') > -1) {
|
|
8453
|
-
const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
|
|
8454
|
-
return cssStringified.replace(regex, '$1\\$2');
|
|
8455
|
-
}
|
|
8456
8252
|
return cssStringified;
|
|
8457
8253
|
}
|
|
8458
8254
|
function isCSSImportRule(rule) {
|
|
@@ -8461,7 +8257,7 @@ function isCSSImportRule(rule) {
|
|
|
8461
8257
|
function stringifyStyleSheet(sheet) {
|
|
8462
8258
|
return sheet.cssRules
|
|
8463
8259
|
? Array.from(sheet.cssRules)
|
|
8464
|
-
.map((rule) => rule.cssText
|
|
8260
|
+
.map((rule) => rule.cssText || '')
|
|
8465
8261
|
.join('')
|
|
8466
8262
|
: '';
|
|
8467
8263
|
}
|
|
@@ -8796,15 +8592,14 @@ function serializeNode(n, options) {
|
|
|
8796
8592
|
tagName === 'select' ||
|
|
8797
8593
|
tagName === 'option') {
|
|
8798
8594
|
const el = n;
|
|
8799
|
-
const
|
|
8800
|
-
const value = getInputValue(el, tagName.toUpperCase(), type);
|
|
8595
|
+
const value = getInputValue(tagName, el, attributes);
|
|
8801
8596
|
const checked = n.checked;
|
|
8802
|
-
if (type !== 'submit' &&
|
|
8803
|
-
type !== 'button' &&
|
|
8597
|
+
if (attributes.type !== 'submit' &&
|
|
8598
|
+
attributes.type !== 'button' &&
|
|
8804
8599
|
value) {
|
|
8805
8600
|
attributes.value = maskInputValue({
|
|
8806
8601
|
input: el,
|
|
8807
|
-
type,
|
|
8602
|
+
type: attributes.type,
|
|
8808
8603
|
tagName,
|
|
8809
8604
|
value,
|
|
8810
8605
|
maskInputSelector,
|
|
@@ -9277,8 +9072,15 @@ function snapshot(n, options) {
|
|
|
9277
9072
|
function skipAttribute(tagName, attributeName, value) {
|
|
9278
9073
|
return ((tagName === 'video' || tagName === 'audio') && attributeName === 'autoplay');
|
|
9279
9074
|
}
|
|
9075
|
+
function getInputValue(tagName, el, attributes) {
|
|
9076
|
+
if (tagName === 'input' &&
|
|
9077
|
+
(attributes.type === 'radio' || attributes.type === 'checkbox')) {
|
|
9078
|
+
return el.getAttribute('value') || '';
|
|
9079
|
+
}
|
|
9080
|
+
return el.value;
|
|
9081
|
+
}
|
|
9280
9082
|
|
|
9281
|
-
var EventType
|
|
9083
|
+
var EventType;
|
|
9282
9084
|
(function (EventType) {
|
|
9283
9085
|
EventType[EventType["DomContentLoaded"] = 0] = "DomContentLoaded";
|
|
9284
9086
|
EventType[EventType["Load"] = 1] = "Load";
|
|
@@ -9287,7 +9089,7 @@ var EventType$1;
|
|
|
9287
9089
|
EventType[EventType["Meta"] = 4] = "Meta";
|
|
9288
9090
|
EventType[EventType["Custom"] = 5] = "Custom";
|
|
9289
9091
|
EventType[EventType["Plugin"] = 6] = "Plugin";
|
|
9290
|
-
})(EventType
|
|
9092
|
+
})(EventType || (EventType = {}));
|
|
9291
9093
|
var IncrementalSource;
|
|
9292
9094
|
(function (IncrementalSource) {
|
|
9293
9095
|
IncrementalSource[IncrementalSource["Mutation"] = 0] = "Mutation";
|
|
@@ -9902,9 +9704,9 @@ class MutationBuffer {
|
|
|
9902
9704
|
this.attributes.push(item);
|
|
9903
9705
|
}
|
|
9904
9706
|
if (m.attributeName === 'type' &&
|
|
9905
|
-
target.tagName === 'INPUT' &&
|
|
9707
|
+
m.target.tagName === 'INPUT' &&
|
|
9906
9708
|
(m.oldValue || '').toLowerCase() === 'password') {
|
|
9907
|
-
target.setAttribute('
|
|
9709
|
+
m.target.setAttribute('rr_is_password', 'true');
|
|
9908
9710
|
}
|
|
9909
9711
|
if (m.attributeName === 'style') {
|
|
9910
9712
|
const old = this.doc.createElement('span');
|
|
@@ -10301,25 +10103,27 @@ function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, un
|
|
|
10301
10103
|
isBlocked(target, blockClass, blockSelector, unblockSelector)) {
|
|
10302
10104
|
return;
|
|
10303
10105
|
}
|
|
10304
|
-
|
|
10305
|
-
|
|
10306
|
-
|
|
10307
|
-
(ignoreSelector && el.matches(ignoreSelector))) {
|
|
10106
|
+
let type = target.type;
|
|
10107
|
+
if (target.classList.contains(ignoreClass) ||
|
|
10108
|
+
(ignoreSelector && target.matches(ignoreSelector))) {
|
|
10308
10109
|
return;
|
|
10309
10110
|
}
|
|
10310
|
-
let text =
|
|
10111
|
+
let text = target.value;
|
|
10311
10112
|
let isChecked = false;
|
|
10113
|
+
if (target.hasAttribute('rr_is_password')) {
|
|
10114
|
+
type = 'password';
|
|
10115
|
+
}
|
|
10312
10116
|
if (type === 'radio' || type === 'checkbox') {
|
|
10313
10117
|
isChecked = target.checked;
|
|
10314
10118
|
}
|
|
10315
|
-
if (hasInputMaskOptions({
|
|
10119
|
+
else if (hasInputMaskOptions({
|
|
10316
10120
|
maskInputOptions,
|
|
10317
10121
|
maskInputSelector,
|
|
10318
10122
|
tagName,
|
|
10319
10123
|
type,
|
|
10320
10124
|
})) {
|
|
10321
10125
|
text = maskInputValue({
|
|
10322
|
-
input:
|
|
10126
|
+
input: target,
|
|
10323
10127
|
maskInputOptions,
|
|
10324
10128
|
maskInputSelector,
|
|
10325
10129
|
unmaskInputSelector,
|
|
@@ -10336,18 +10140,8 @@ function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, un
|
|
|
10336
10140
|
.querySelectorAll(`input[type="radio"][name="${name}"]`)
|
|
10337
10141
|
.forEach((el) => {
|
|
10338
10142
|
if (el !== target) {
|
|
10339
|
-
const text = maskInputValue({
|
|
10340
|
-
input: el,
|
|
10341
|
-
maskInputOptions,
|
|
10342
|
-
maskInputSelector,
|
|
10343
|
-
unmaskInputSelector,
|
|
10344
|
-
tagName,
|
|
10345
|
-
type,
|
|
10346
|
-
value: getInputValue(el, tagName, type),
|
|
10347
|
-
maskInputFn,
|
|
10348
|
-
});
|
|
10349
10143
|
cbWithDedup(el, callbackWrapper(wrapEventWithUserTriggeredFlag)({
|
|
10350
|
-
text,
|
|
10144
|
+
text: el.value,
|
|
10351
10145
|
isChecked: !isChecked,
|
|
10352
10146
|
userTriggered: false,
|
|
10353
10147
|
}, userTriggeredOnInput));
|
|
@@ -11260,17 +11054,17 @@ function record(options = {}) {
|
|
|
11260
11054
|
wrappedEmit = (e, isCheckout) => {
|
|
11261
11055
|
var _a;
|
|
11262
11056
|
if (((_a = mutationBuffers[0]) === null || _a === void 0 ? void 0 : _a.isFrozen()) &&
|
|
11263
|
-
e.type !== EventType
|
|
11264
|
-
!(e.type === EventType
|
|
11057
|
+
e.type !== EventType.FullSnapshot &&
|
|
11058
|
+
!(e.type === EventType.IncrementalSnapshot &&
|
|
11265
11059
|
e.data.source === IncrementalSource.Mutation)) {
|
|
11266
11060
|
mutationBuffers.forEach((buf) => buf.unfreeze());
|
|
11267
11061
|
}
|
|
11268
11062
|
emit(eventProcessor(e), isCheckout);
|
|
11269
|
-
if (e.type === EventType
|
|
11063
|
+
if (e.type === EventType.FullSnapshot) {
|
|
11270
11064
|
lastFullSnapshotEvent = e;
|
|
11271
11065
|
incrementalSnapshotCount = 0;
|
|
11272
11066
|
}
|
|
11273
|
-
else if (e.type === EventType
|
|
11067
|
+
else if (e.type === EventType.IncrementalSnapshot) {
|
|
11274
11068
|
if (e.data.source === IncrementalSource.Mutation &&
|
|
11275
11069
|
e.data.isAttachIframe) {
|
|
11276
11070
|
return;
|
|
@@ -11286,16 +11080,16 @@ function record(options = {}) {
|
|
|
11286
11080
|
};
|
|
11287
11081
|
const wrappedMutationEmit = (m) => {
|
|
11288
11082
|
wrappedEmit(wrapEvent({
|
|
11289
|
-
type: EventType
|
|
11083
|
+
type: EventType.IncrementalSnapshot,
|
|
11290
11084
|
data: Object.assign({ source: IncrementalSource.Mutation }, m),
|
|
11291
11085
|
}));
|
|
11292
11086
|
};
|
|
11293
11087
|
const wrappedScrollEmit = (p) => wrappedEmit(wrapEvent({
|
|
11294
|
-
type: EventType
|
|
11088
|
+
type: EventType.IncrementalSnapshot,
|
|
11295
11089
|
data: Object.assign({ source: IncrementalSource.Scroll }, p),
|
|
11296
11090
|
}));
|
|
11297
11091
|
const wrappedCanvasMutationEmit = (p) => wrappedEmit(wrapEvent({
|
|
11298
|
-
type: EventType
|
|
11092
|
+
type: EventType.IncrementalSnapshot,
|
|
11299
11093
|
data: Object.assign({ source: IncrementalSource.CanvasMutation }, p),
|
|
11300
11094
|
}));
|
|
11301
11095
|
const iframeManager = new IframeManager({
|
|
@@ -11340,7 +11134,7 @@ function record(options = {}) {
|
|
|
11340
11134
|
takeFullSnapshot = (isCheckout = false) => {
|
|
11341
11135
|
var _a, _b, _c, _d;
|
|
11342
11136
|
wrappedEmit(wrapEvent({
|
|
11343
|
-
type: EventType
|
|
11137
|
+
type: EventType.Meta,
|
|
11344
11138
|
data: {
|
|
11345
11139
|
href: window.location.href,
|
|
11346
11140
|
width: getWindowWidth(),
|
|
@@ -11383,7 +11177,7 @@ function record(options = {}) {
|
|
|
11383
11177
|
}
|
|
11384
11178
|
mirror.map = idNodeMap;
|
|
11385
11179
|
wrappedEmit(wrapEvent({
|
|
11386
|
-
type: EventType
|
|
11180
|
+
type: EventType.FullSnapshot,
|
|
11387
11181
|
data: {
|
|
11388
11182
|
node,
|
|
11389
11183
|
initialOffset: {
|
|
@@ -11408,7 +11202,7 @@ function record(options = {}) {
|
|
|
11408
11202
|
const handlers = [];
|
|
11409
11203
|
handlers.push(on$1('DOMContentLoaded', () => {
|
|
11410
11204
|
wrappedEmit(wrapEvent({
|
|
11411
|
-
type: EventType
|
|
11205
|
+
type: EventType.DomContentLoaded,
|
|
11412
11206
|
data: {},
|
|
11413
11207
|
}));
|
|
11414
11208
|
}));
|
|
@@ -11418,40 +11212,40 @@ function record(options = {}) {
|
|
|
11418
11212
|
onMutation,
|
|
11419
11213
|
mutationCb: wrappedMutationEmit,
|
|
11420
11214
|
mousemoveCb: (positions, source) => wrappedEmit(wrapEvent({
|
|
11421
|
-
type: EventType
|
|
11215
|
+
type: EventType.IncrementalSnapshot,
|
|
11422
11216
|
data: {
|
|
11423
11217
|
source,
|
|
11424
11218
|
positions,
|
|
11425
11219
|
},
|
|
11426
11220
|
})),
|
|
11427
11221
|
mouseInteractionCb: (d) => wrappedEmit(wrapEvent({
|
|
11428
|
-
type: EventType
|
|
11222
|
+
type: EventType.IncrementalSnapshot,
|
|
11429
11223
|
data: Object.assign({ source: IncrementalSource.MouseInteraction }, d),
|
|
11430
11224
|
})),
|
|
11431
11225
|
scrollCb: wrappedScrollEmit,
|
|
11432
11226
|
viewportResizeCb: (d) => wrappedEmit(wrapEvent({
|
|
11433
|
-
type: EventType
|
|
11227
|
+
type: EventType.IncrementalSnapshot,
|
|
11434
11228
|
data: Object.assign({ source: IncrementalSource.ViewportResize }, d),
|
|
11435
11229
|
})),
|
|
11436
11230
|
inputCb: (v) => wrappedEmit(wrapEvent({
|
|
11437
|
-
type: EventType
|
|
11231
|
+
type: EventType.IncrementalSnapshot,
|
|
11438
11232
|
data: Object.assign({ source: IncrementalSource.Input }, v),
|
|
11439
11233
|
})),
|
|
11440
11234
|
mediaInteractionCb: (p) => wrappedEmit(wrapEvent({
|
|
11441
|
-
type: EventType
|
|
11235
|
+
type: EventType.IncrementalSnapshot,
|
|
11442
11236
|
data: Object.assign({ source: IncrementalSource.MediaInteraction }, p),
|
|
11443
11237
|
})),
|
|
11444
11238
|
styleSheetRuleCb: (r) => wrappedEmit(wrapEvent({
|
|
11445
|
-
type: EventType
|
|
11239
|
+
type: EventType.IncrementalSnapshot,
|
|
11446
11240
|
data: Object.assign({ source: IncrementalSource.StyleSheetRule }, r),
|
|
11447
11241
|
})),
|
|
11448
11242
|
styleDeclarationCb: (r) => wrappedEmit(wrapEvent({
|
|
11449
|
-
type: EventType
|
|
11243
|
+
type: EventType.IncrementalSnapshot,
|
|
11450
11244
|
data: Object.assign({ source: IncrementalSource.StyleDeclaration }, r),
|
|
11451
11245
|
})),
|
|
11452
11246
|
canvasMutationCb: wrappedCanvasMutationEmit,
|
|
11453
11247
|
fontCb: (p) => wrappedEmit(wrapEvent({
|
|
11454
|
-
type: EventType
|
|
11248
|
+
type: EventType.IncrementalSnapshot,
|
|
11455
11249
|
data: Object.assign({ source: IncrementalSource.Font }, p),
|
|
11456
11250
|
})),
|
|
11457
11251
|
blockClass,
|
|
@@ -11484,7 +11278,7 @@ function record(options = {}) {
|
|
|
11484
11278
|
observer: p.observer,
|
|
11485
11279
|
options: p.options,
|
|
11486
11280
|
callback: (payload) => wrappedEmit(wrapEvent({
|
|
11487
|
-
type: EventType
|
|
11281
|
+
type: EventType.Plugin,
|
|
11488
11282
|
data: {
|
|
11489
11283
|
plugin: p.name,
|
|
11490
11284
|
payload,
|
|
@@ -11512,7 +11306,7 @@ function record(options = {}) {
|
|
|
11512
11306
|
else {
|
|
11513
11307
|
handlers.push(on$1('load', () => {
|
|
11514
11308
|
wrappedEmit(wrapEvent({
|
|
11515
|
-
type: EventType
|
|
11309
|
+
type: EventType.Load,
|
|
11516
11310
|
data: {},
|
|
11517
11311
|
}));
|
|
11518
11312
|
init();
|
|
@@ -11531,7 +11325,7 @@ record.addCustomEvent = (tag, payload) => {
|
|
|
11531
11325
|
throw new Error('please add custom event after start recording');
|
|
11532
11326
|
}
|
|
11533
11327
|
wrappedEmit(wrapEvent({
|
|
11534
|
-
type: EventType
|
|
11328
|
+
type: EventType.Custom,
|
|
11535
11329
|
data: {
|
|
11536
11330
|
tag,
|
|
11537
11331
|
payload,
|
|
@@ -11549,475 +11343,6 @@ record.takeFullSnapshot = (isCheckout) => {
|
|
|
11549
11343
|
};
|
|
11550
11344
|
record.mirror = mirror;
|
|
11551
11345
|
|
|
11552
|
-
/**
|
|
11553
|
-
* Create a breadcrumb for a replay.
|
|
11554
|
-
*/
|
|
11555
|
-
function createBreadcrumb(
|
|
11556
|
-
breadcrumb,
|
|
11557
|
-
) {
|
|
11558
|
-
return {
|
|
11559
|
-
timestamp: Date.now() / 1000,
|
|
11560
|
-
type: 'default',
|
|
11561
|
-
...breadcrumb,
|
|
11562
|
-
};
|
|
11563
|
-
}
|
|
11564
|
-
|
|
11565
|
-
var NodeType;
|
|
11566
|
-
(function (NodeType) {
|
|
11567
|
-
NodeType[NodeType["Document"] = 0] = "Document";
|
|
11568
|
-
NodeType[NodeType["DocumentType"] = 1] = "DocumentType";
|
|
11569
|
-
NodeType[NodeType["Element"] = 2] = "Element";
|
|
11570
|
-
NodeType[NodeType["Text"] = 3] = "Text";
|
|
11571
|
-
NodeType[NodeType["CDATA"] = 4] = "CDATA";
|
|
11572
|
-
NodeType[NodeType["Comment"] = 5] = "Comment";
|
|
11573
|
-
})(NodeType || (NodeType = {}));
|
|
11574
|
-
|
|
11575
|
-
/**
|
|
11576
|
-
* Converts a timestamp to ms, if it was in s, or keeps it as ms.
|
|
11577
|
-
*/
|
|
11578
|
-
function timestampToMs(timestamp) {
|
|
11579
|
-
const isMs = timestamp > 9999999999;
|
|
11580
|
-
return isMs ? timestamp : timestamp * 1000;
|
|
11581
|
-
}
|
|
11582
|
-
|
|
11583
|
-
/**
|
|
11584
|
-
* Add an event to the event buffer.
|
|
11585
|
-
* `isCheckout` is true if this is either the very first event, or an event triggered by `checkoutEveryNms`.
|
|
11586
|
-
*/
|
|
11587
|
-
async function addEvent(
|
|
11588
|
-
replay,
|
|
11589
|
-
event,
|
|
11590
|
-
isCheckout,
|
|
11591
|
-
) {
|
|
11592
|
-
if (!replay.eventBuffer) {
|
|
11593
|
-
// This implies that `_isEnabled` is false
|
|
11594
|
-
return null;
|
|
11595
|
-
}
|
|
11596
|
-
|
|
11597
|
-
if (replay.isPaused()) {
|
|
11598
|
-
// Do not add to event buffer when recording is paused
|
|
11599
|
-
return null;
|
|
11600
|
-
}
|
|
11601
|
-
|
|
11602
|
-
const timestampInMs = timestampToMs(event.timestamp);
|
|
11603
|
-
|
|
11604
|
-
// Throw out events that happen more than 5 minutes ago. This can happen if
|
|
11605
|
-
// page has been left open and idle for a long period of time and user
|
|
11606
|
-
// comes back to trigger a new session. The performance entries rely on
|
|
11607
|
-
// `performance.timeOrigin`, which is when the page first opened.
|
|
11608
|
-
if (timestampInMs + replay.timeouts.sessionIdlePause < Date.now()) {
|
|
11609
|
-
return null;
|
|
11610
|
-
}
|
|
11611
|
-
|
|
11612
|
-
try {
|
|
11613
|
-
if (isCheckout) {
|
|
11614
|
-
replay.eventBuffer.clear();
|
|
11615
|
-
}
|
|
11616
|
-
|
|
11617
|
-
return await replay.eventBuffer.addEvent(event);
|
|
11618
|
-
} catch (error) {
|
|
11619
|
-
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(error);
|
|
11620
|
-
await replay.stop('addEvent');
|
|
11621
|
-
|
|
11622
|
-
const client = getCurrentHub().getClient();
|
|
11623
|
-
|
|
11624
|
-
if (client) {
|
|
11625
|
-
client.recordDroppedEvent('internal_sdk_error', 'replay');
|
|
11626
|
-
}
|
|
11627
|
-
}
|
|
11628
|
-
}
|
|
11629
|
-
|
|
11630
|
-
/**
|
|
11631
|
-
* Add a breadcrumb event to replay.
|
|
11632
|
-
*/
|
|
11633
|
-
function addBreadcrumbEvent(replay, breadcrumb) {
|
|
11634
|
-
if (breadcrumb.category === 'sentry.transaction') {
|
|
11635
|
-
return;
|
|
11636
|
-
}
|
|
11637
|
-
|
|
11638
|
-
if (['ui.click', 'ui.input'].includes(breadcrumb.category )) {
|
|
11639
|
-
replay.triggerUserActivity();
|
|
11640
|
-
} else {
|
|
11641
|
-
replay.checkAndHandleExpiredSession();
|
|
11642
|
-
}
|
|
11643
|
-
|
|
11644
|
-
replay.addUpdate(() => {
|
|
11645
|
-
void addEvent(replay, {
|
|
11646
|
-
type: EventType$1.Custom,
|
|
11647
|
-
// TODO: We were converting from ms to seconds for breadcrumbs, spans,
|
|
11648
|
-
// but maybe we should just keep them as milliseconds
|
|
11649
|
-
timestamp: (breadcrumb.timestamp || 0) * 1000,
|
|
11650
|
-
data: {
|
|
11651
|
-
tag: 'breadcrumb',
|
|
11652
|
-
// normalize to max. 10 depth and 1_000 properties per object
|
|
11653
|
-
payload: normalize(breadcrumb, 10, 1000),
|
|
11654
|
-
},
|
|
11655
|
-
});
|
|
11656
|
-
|
|
11657
|
-
// Do not flush after console log messages
|
|
11658
|
-
return breadcrumb.category === 'console';
|
|
11659
|
-
});
|
|
11660
|
-
}
|
|
11661
|
-
|
|
11662
|
-
/**
|
|
11663
|
-
* Detect a slow click on a button/a tag,
|
|
11664
|
-
* and potentially create a corresponding breadcrumb.
|
|
11665
|
-
*/
|
|
11666
|
-
function detectSlowClick(
|
|
11667
|
-
replay,
|
|
11668
|
-
config,
|
|
11669
|
-
clickBreadcrumb,
|
|
11670
|
-
node,
|
|
11671
|
-
) {
|
|
11672
|
-
if (ignoreElement(node, config)) {
|
|
11673
|
-
return;
|
|
11674
|
-
}
|
|
11675
|
-
|
|
11676
|
-
/*
|
|
11677
|
-
We consider a slow click a click on a button/a, which does not trigger one of:
|
|
11678
|
-
- DOM mutation
|
|
11679
|
-
- Scroll (within 100ms)
|
|
11680
|
-
Within the given threshold time.
|
|
11681
|
-
After time timeout time, we stop listening and mark it as a slow click anyhow.
|
|
11682
|
-
*/
|
|
11683
|
-
|
|
11684
|
-
let cleanup = () => {
|
|
11685
|
-
// replaced further down
|
|
11686
|
-
};
|
|
11687
|
-
|
|
11688
|
-
// After timeout time, def. consider this a slow click, and stop watching for mutations
|
|
11689
|
-
const timeout = setTimeout(() => {
|
|
11690
|
-
handleSlowClick(replay, clickBreadcrumb, config.timeout, 'timeout');
|
|
11691
|
-
cleanup();
|
|
11692
|
-
}, config.timeout);
|
|
11693
|
-
|
|
11694
|
-
const mutationHandler = () => {
|
|
11695
|
-
maybeHandleSlowClick(replay, clickBreadcrumb, config.threshold, config.timeout, 'mutation');
|
|
11696
|
-
cleanup();
|
|
11697
|
-
};
|
|
11698
|
-
|
|
11699
|
-
const scrollHandler = () => {
|
|
11700
|
-
maybeHandleSlowClick(replay, clickBreadcrumb, config.scrollTimeout, config.timeout, 'scroll');
|
|
11701
|
-
cleanup();
|
|
11702
|
-
};
|
|
11703
|
-
|
|
11704
|
-
const obs = new MutationObserver(mutationHandler);
|
|
11705
|
-
|
|
11706
|
-
obs.observe(WINDOW.document.documentElement, {
|
|
11707
|
-
attributes: true,
|
|
11708
|
-
characterData: true,
|
|
11709
|
-
childList: true,
|
|
11710
|
-
subtree: true,
|
|
11711
|
-
});
|
|
11712
|
-
|
|
11713
|
-
WINDOW.addEventListener('scroll', scrollHandler);
|
|
11714
|
-
|
|
11715
|
-
// Stop listening to scroll timeouts early
|
|
11716
|
-
const scrollTimeout = setTimeout(() => {
|
|
11717
|
-
WINDOW.removeEventListener('scroll', scrollHandler);
|
|
11718
|
-
}, config.scrollTimeout);
|
|
11719
|
-
|
|
11720
|
-
cleanup = () => {
|
|
11721
|
-
clearTimeout(timeout);
|
|
11722
|
-
clearTimeout(scrollTimeout);
|
|
11723
|
-
obs.disconnect();
|
|
11724
|
-
WINDOW.removeEventListener('scroll', scrollHandler);
|
|
11725
|
-
};
|
|
11726
|
-
}
|
|
11727
|
-
|
|
11728
|
-
function maybeHandleSlowClick(
|
|
11729
|
-
replay,
|
|
11730
|
-
clickBreadcrumb,
|
|
11731
|
-
threshold,
|
|
11732
|
-
timeout,
|
|
11733
|
-
endReason,
|
|
11734
|
-
) {
|
|
11735
|
-
const now = Date.now();
|
|
11736
|
-
const timeAfterClickMs = now - clickBreadcrumb.timestamp * 1000;
|
|
11737
|
-
|
|
11738
|
-
if (timeAfterClickMs > threshold) {
|
|
11739
|
-
handleSlowClick(replay, clickBreadcrumb, Math.min(timeAfterClickMs, timeout), endReason);
|
|
11740
|
-
return true;
|
|
11741
|
-
}
|
|
11742
|
-
|
|
11743
|
-
return false;
|
|
11744
|
-
}
|
|
11745
|
-
|
|
11746
|
-
function handleSlowClick(
|
|
11747
|
-
replay,
|
|
11748
|
-
clickBreadcrumb,
|
|
11749
|
-
timeAfterClickMs,
|
|
11750
|
-
endReason,
|
|
11751
|
-
) {
|
|
11752
|
-
const breadcrumb = {
|
|
11753
|
-
message: clickBreadcrumb.message,
|
|
11754
|
-
timestamp: clickBreadcrumb.timestamp,
|
|
11755
|
-
category: 'ui.slowClickDetected',
|
|
11756
|
-
data: {
|
|
11757
|
-
...clickBreadcrumb.data,
|
|
11758
|
-
url: WINDOW.location.href,
|
|
11759
|
-
// TODO FN: add parametrized route, when possible
|
|
11760
|
-
timeAfterClickMs,
|
|
11761
|
-
endReason,
|
|
11762
|
-
},
|
|
11763
|
-
};
|
|
11764
|
-
|
|
11765
|
-
addBreadcrumbEvent(replay, breadcrumb);
|
|
11766
|
-
}
|
|
11767
|
-
|
|
11768
|
-
const SLOW_CLICK_IGNORE_TAGS = ['SELECT', 'OPTION'];
|
|
11769
|
-
|
|
11770
|
-
function ignoreElement(node, config) {
|
|
11771
|
-
// If <input> tag, we only want to consider input[type='submit'] & input[type='button']
|
|
11772
|
-
if (node.tagName === 'INPUT' && !['submit', 'button'].includes(node.getAttribute('type') || '')) {
|
|
11773
|
-
return true;
|
|
11774
|
-
}
|
|
11775
|
-
|
|
11776
|
-
if (SLOW_CLICK_IGNORE_TAGS.includes(node.tagName)) {
|
|
11777
|
-
return true;
|
|
11778
|
-
}
|
|
11779
|
-
|
|
11780
|
-
// If <a> tag, detect special variants that may not lead to an action
|
|
11781
|
-
// If target !== _self, we may open the link somewhere else, which would lead to no action
|
|
11782
|
-
// Also, when downloading a file, we may not leave the page, but still not trigger an action
|
|
11783
|
-
if (
|
|
11784
|
-
node.tagName === 'A' &&
|
|
11785
|
-
(node.hasAttribute('download') || (node.hasAttribute('target') && node.getAttribute('target') !== '_self'))
|
|
11786
|
-
) {
|
|
11787
|
-
return true;
|
|
11788
|
-
}
|
|
11789
|
-
|
|
11790
|
-
if (config.ignoreSelector && node.matches(config.ignoreSelector)) {
|
|
11791
|
-
return true;
|
|
11792
|
-
}
|
|
11793
|
-
|
|
11794
|
-
return false;
|
|
11795
|
-
}
|
|
11796
|
-
|
|
11797
|
-
// Note that these are the serialized attributes and not attributes directly on
|
|
11798
|
-
// the DOM Node. Attributes we are interested in:
|
|
11799
|
-
const ATTRIBUTES_TO_RECORD = new Set([
|
|
11800
|
-
'id',
|
|
11801
|
-
'class',
|
|
11802
|
-
'aria-label',
|
|
11803
|
-
'role',
|
|
11804
|
-
'name',
|
|
11805
|
-
'alt',
|
|
11806
|
-
'title',
|
|
11807
|
-
'data-test-id',
|
|
11808
|
-
'data-testid',
|
|
11809
|
-
]);
|
|
11810
|
-
|
|
11811
|
-
/**
|
|
11812
|
-
* Inclusion list of attributes that we want to record from the DOM element
|
|
11813
|
-
*/
|
|
11814
|
-
function getAttributesToRecord(attributes) {
|
|
11815
|
-
const obj = {};
|
|
11816
|
-
for (const key in attributes) {
|
|
11817
|
-
if (ATTRIBUTES_TO_RECORD.has(key)) {
|
|
11818
|
-
let normalizedKey = key;
|
|
11819
|
-
|
|
11820
|
-
if (key === 'data-testid' || key === 'data-test-id') {
|
|
11821
|
-
normalizedKey = 'testId';
|
|
11822
|
-
}
|
|
11823
|
-
|
|
11824
|
-
obj[normalizedKey] = attributes[key];
|
|
11825
|
-
}
|
|
11826
|
-
}
|
|
11827
|
-
|
|
11828
|
-
return obj;
|
|
11829
|
-
}
|
|
11830
|
-
|
|
11831
|
-
const handleDomListener = (
|
|
11832
|
-
replay,
|
|
11833
|
-
) => {
|
|
11834
|
-
const slowClickExperiment = replay.getOptions()._experiments.slowClicks;
|
|
11835
|
-
|
|
11836
|
-
const slowClickConfig = slowClickExperiment
|
|
11837
|
-
? {
|
|
11838
|
-
threshold: slowClickExperiment.threshold,
|
|
11839
|
-
timeout: slowClickExperiment.timeout,
|
|
11840
|
-
scrollTimeout: slowClickExperiment.scrollTimeout,
|
|
11841
|
-
ignoreSelector: slowClickExperiment.ignoreSelectors ? slowClickExperiment.ignoreSelectors.join(',') : '',
|
|
11842
|
-
}
|
|
11843
|
-
: undefined;
|
|
11844
|
-
|
|
11845
|
-
return (handlerData) => {
|
|
11846
|
-
if (!replay.isEnabled()) {
|
|
11847
|
-
return;
|
|
11848
|
-
}
|
|
11849
|
-
|
|
11850
|
-
const result = handleDom(handlerData);
|
|
11851
|
-
|
|
11852
|
-
if (!result) {
|
|
11853
|
-
return;
|
|
11854
|
-
}
|
|
11855
|
-
|
|
11856
|
-
const isClick = handlerData.name === 'click';
|
|
11857
|
-
const event = isClick && (handlerData.event );
|
|
11858
|
-
// Ignore clicks if ctrl/alt/meta keys are held down as they alter behavior of clicks (e.g. open in new tab)
|
|
11859
|
-
if (isClick && slowClickConfig && event && !event.altKey && !event.metaKey && !event.ctrlKey) {
|
|
11860
|
-
detectSlowClick(
|
|
11861
|
-
replay,
|
|
11862
|
-
slowClickConfig,
|
|
11863
|
-
result ,
|
|
11864
|
-
getClickTargetNode(handlerData.event) ,
|
|
11865
|
-
);
|
|
11866
|
-
}
|
|
11867
|
-
|
|
11868
|
-
addBreadcrumbEvent(replay, result);
|
|
11869
|
-
};
|
|
11870
|
-
};
|
|
11871
|
-
|
|
11872
|
-
/** Get the base DOM breadcrumb. */
|
|
11873
|
-
function getBaseDomBreadcrumb(target, message) {
|
|
11874
|
-
// `__sn` property is the serialized node created by rrweb
|
|
11875
|
-
const serializedNode = target && isRrwebNode(target) && target.__sn.type === NodeType.Element ? target.__sn : null;
|
|
11876
|
-
|
|
11877
|
-
return {
|
|
11878
|
-
message,
|
|
11879
|
-
data: serializedNode
|
|
11880
|
-
? {
|
|
11881
|
-
nodeId: serializedNode.id,
|
|
11882
|
-
node: {
|
|
11883
|
-
id: serializedNode.id,
|
|
11884
|
-
tagName: serializedNode.tagName,
|
|
11885
|
-
textContent: target
|
|
11886
|
-
? Array.from(target.childNodes)
|
|
11887
|
-
.map(
|
|
11888
|
-
(node) => '__sn' in node && node.__sn.type === NodeType.Text && node.__sn.textContent,
|
|
11889
|
-
)
|
|
11890
|
-
.filter(Boolean) // filter out empty values
|
|
11891
|
-
.map(text => (text ).trim())
|
|
11892
|
-
.join('')
|
|
11893
|
-
: '',
|
|
11894
|
-
attributes: getAttributesToRecord(serializedNode.attributes),
|
|
11895
|
-
},
|
|
11896
|
-
}
|
|
11897
|
-
: {},
|
|
11898
|
-
};
|
|
11899
|
-
}
|
|
11900
|
-
|
|
11901
|
-
/**
|
|
11902
|
-
* An event handler to react to DOM events.
|
|
11903
|
-
* Exported for tests.
|
|
11904
|
-
*/
|
|
11905
|
-
function handleDom(handlerData) {
|
|
11906
|
-
const { target, message } = getDomTarget(handlerData);
|
|
11907
|
-
|
|
11908
|
-
return createBreadcrumb({
|
|
11909
|
-
category: `ui.${handlerData.name}`,
|
|
11910
|
-
...getBaseDomBreadcrumb(target, message),
|
|
11911
|
-
});
|
|
11912
|
-
}
|
|
11913
|
-
|
|
11914
|
-
function getDomTarget(handlerData) {
|
|
11915
|
-
const isClick = handlerData.name === 'click';
|
|
11916
|
-
|
|
11917
|
-
let message;
|
|
11918
|
-
let target = null;
|
|
11919
|
-
|
|
11920
|
-
// Accessing event.target can throw (see getsentry/raven-js#838, #768)
|
|
11921
|
-
try {
|
|
11922
|
-
target = isClick ? getClickTargetNode(handlerData.event) : getTargetNode(handlerData.event);
|
|
11923
|
-
message = htmlTreeAsString(target, { maxStringLength: 200 }) || '<unknown>';
|
|
11924
|
-
} catch (e) {
|
|
11925
|
-
message = '<unknown>';
|
|
11926
|
-
}
|
|
11927
|
-
|
|
11928
|
-
return { target, message };
|
|
11929
|
-
}
|
|
11930
|
-
|
|
11931
|
-
function isRrwebNode(node) {
|
|
11932
|
-
return '__sn' in node;
|
|
11933
|
-
}
|
|
11934
|
-
|
|
11935
|
-
function getTargetNode(event) {
|
|
11936
|
-
if (isEventWithTarget(event)) {
|
|
11937
|
-
return event.target ;
|
|
11938
|
-
}
|
|
11939
|
-
|
|
11940
|
-
return event;
|
|
11941
|
-
}
|
|
11942
|
-
|
|
11943
|
-
const INTERACTIVE_SELECTOR = 'button,a';
|
|
11944
|
-
|
|
11945
|
-
// For clicks, we check if the target is inside of a button or link
|
|
11946
|
-
// If so, we use this as the target instead
|
|
11947
|
-
// This is useful because if you click on the image in <button><img></button>,
|
|
11948
|
-
// The target will be the image, not the button, which we don't want here
|
|
11949
|
-
function getClickTargetNode(event) {
|
|
11950
|
-
const target = getTargetNode(event);
|
|
11951
|
-
|
|
11952
|
-
if (!target || !(target instanceof Element)) {
|
|
11953
|
-
return target;
|
|
11954
|
-
}
|
|
11955
|
-
|
|
11956
|
-
const closestInteractive = target.closest(INTERACTIVE_SELECTOR);
|
|
11957
|
-
return closestInteractive || target;
|
|
11958
|
-
}
|
|
11959
|
-
|
|
11960
|
-
function isEventWithTarget(event) {
|
|
11961
|
-
return typeof event === 'object' && !!event && 'target' in event;
|
|
11962
|
-
}
|
|
11963
|
-
|
|
11964
|
-
/** Handle keyboard events & create breadcrumbs. */
|
|
11965
|
-
function handleKeyboardEvent(replay, event) {
|
|
11966
|
-
if (!replay.isEnabled()) {
|
|
11967
|
-
return;
|
|
11968
|
-
}
|
|
11969
|
-
|
|
11970
|
-
replay.triggerUserActivity();
|
|
11971
|
-
|
|
11972
|
-
const breadcrumb = getKeyboardBreadcrumb(event);
|
|
11973
|
-
|
|
11974
|
-
if (!breadcrumb) {
|
|
11975
|
-
return;
|
|
11976
|
-
}
|
|
11977
|
-
|
|
11978
|
-
addBreadcrumbEvent(replay, breadcrumb);
|
|
11979
|
-
}
|
|
11980
|
-
|
|
11981
|
-
/** exported only for tests */
|
|
11982
|
-
function getKeyboardBreadcrumb(event) {
|
|
11983
|
-
const { metaKey, shiftKey, ctrlKey, altKey, key, target } = event;
|
|
11984
|
-
|
|
11985
|
-
// never capture for input fields
|
|
11986
|
-
if (!target || isInputElement(target )) {
|
|
11987
|
-
return null;
|
|
11988
|
-
}
|
|
11989
|
-
|
|
11990
|
-
// Note: We do not consider shift here, as that means "uppercase"
|
|
11991
|
-
const hasModifierKey = metaKey || ctrlKey || altKey;
|
|
11992
|
-
const isCharacterKey = key.length === 1; // other keys like Escape, Tab, etc have a longer length
|
|
11993
|
-
|
|
11994
|
-
// Do not capture breadcrumb if only a word key is pressed
|
|
11995
|
-
// This could leak e.g. user input
|
|
11996
|
-
if (!hasModifierKey && isCharacterKey) {
|
|
11997
|
-
return null;
|
|
11998
|
-
}
|
|
11999
|
-
|
|
12000
|
-
const message = htmlTreeAsString(target, { maxStringLength: 200 }) || '<unknown>';
|
|
12001
|
-
const baseBreadcrumb = getBaseDomBreadcrumb(target , message);
|
|
12002
|
-
|
|
12003
|
-
return createBreadcrumb({
|
|
12004
|
-
category: 'ui.keyDown',
|
|
12005
|
-
message,
|
|
12006
|
-
data: {
|
|
12007
|
-
...baseBreadcrumb.data,
|
|
12008
|
-
metaKey,
|
|
12009
|
-
shiftKey,
|
|
12010
|
-
ctrlKey,
|
|
12011
|
-
altKey,
|
|
12012
|
-
key,
|
|
12013
|
-
},
|
|
12014
|
-
});
|
|
12015
|
-
}
|
|
12016
|
-
|
|
12017
|
-
function isInputElement(target) {
|
|
12018
|
-
return target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable;
|
|
12019
|
-
}
|
|
12020
|
-
|
|
12021
11346
|
const NAVIGATION_ENTRY_KEYS = [
|
|
12022
11347
|
'name',
|
|
12023
11348
|
'type',
|
|
@@ -12171,19 +11496,20 @@ class EventBufferArray {
|
|
|
12171
11496
|
return this.events.length > 0;
|
|
12172
11497
|
}
|
|
12173
11498
|
|
|
12174
|
-
/** @inheritdoc */
|
|
12175
|
-
get type() {
|
|
12176
|
-
return 'sync';
|
|
12177
|
-
}
|
|
12178
|
-
|
|
12179
11499
|
/** @inheritdoc */
|
|
12180
11500
|
destroy() {
|
|
12181
11501
|
this.events = [];
|
|
12182
11502
|
}
|
|
12183
11503
|
|
|
12184
11504
|
/** @inheritdoc */
|
|
12185
|
-
async addEvent(event) {
|
|
11505
|
+
async addEvent(event, isCheckout) {
|
|
11506
|
+
if (isCheckout) {
|
|
11507
|
+
this.events = [event];
|
|
11508
|
+
return;
|
|
11509
|
+
}
|
|
11510
|
+
|
|
12186
11511
|
this.events.push(event);
|
|
11512
|
+
return;
|
|
12187
11513
|
}
|
|
12188
11514
|
|
|
12189
11515
|
/** @inheritdoc */
|
|
@@ -12197,22 +11523,6 @@ class EventBufferArray {
|
|
|
12197
11523
|
resolve(JSON.stringify(eventsRet));
|
|
12198
11524
|
});
|
|
12199
11525
|
}
|
|
12200
|
-
|
|
12201
|
-
/** @inheritdoc */
|
|
12202
|
-
clear() {
|
|
12203
|
-
this.events = [];
|
|
12204
|
-
}
|
|
12205
|
-
|
|
12206
|
-
/** @inheritdoc */
|
|
12207
|
-
getEarliestTimestamp() {
|
|
12208
|
-
const timestamp = this.events.map(event => event.timestamp).sort()[0];
|
|
12209
|
-
|
|
12210
|
-
if (!timestamp) {
|
|
12211
|
-
return null;
|
|
12212
|
-
}
|
|
12213
|
-
|
|
12214
|
-
return timestampToMs(timestamp);
|
|
12215
|
-
}
|
|
12216
11526
|
}
|
|
12217
11527
|
|
|
12218
11528
|
/**
|
|
@@ -12320,20 +11630,11 @@ class WorkerHandler {
|
|
|
12320
11630
|
* Exported only for testing.
|
|
12321
11631
|
*/
|
|
12322
11632
|
class EventBufferCompressionWorker {
|
|
11633
|
+
/** @inheritdoc */
|
|
12323
11634
|
|
|
12324
11635
|
constructor(worker) {
|
|
12325
11636
|
this._worker = new WorkerHandler(worker);
|
|
12326
|
-
this.
|
|
12327
|
-
}
|
|
12328
|
-
|
|
12329
|
-
/** @inheritdoc */
|
|
12330
|
-
get hasEvents() {
|
|
12331
|
-
return !!this._earliestTimestamp;
|
|
12332
|
-
}
|
|
12333
|
-
|
|
12334
|
-
/** @inheritdoc */
|
|
12335
|
-
get type() {
|
|
12336
|
-
return 'worker';
|
|
11637
|
+
this.hasEvents = false;
|
|
12337
11638
|
}
|
|
12338
11639
|
|
|
12339
11640
|
/**
|
|
@@ -12356,10 +11657,13 @@ class EventBufferCompressionWorker {
|
|
|
12356
11657
|
*
|
|
12357
11658
|
* Returns true if event was successfuly received and processed by worker.
|
|
12358
11659
|
*/
|
|
12359
|
-
addEvent(event) {
|
|
12360
|
-
|
|
12361
|
-
|
|
12362
|
-
|
|
11660
|
+
async addEvent(event, isCheckout) {
|
|
11661
|
+
this.hasEvents = true;
|
|
11662
|
+
|
|
11663
|
+
if (isCheckout) {
|
|
11664
|
+
// This event is a checkout, make sure worker buffer is cleared before
|
|
11665
|
+
// proceeding.
|
|
11666
|
+
await this._clear();
|
|
12363
11667
|
}
|
|
12364
11668
|
|
|
12365
11669
|
return this._sendEventToWorker(event);
|
|
@@ -12372,18 +11676,6 @@ class EventBufferCompressionWorker {
|
|
|
12372
11676
|
return this._finishRequest();
|
|
12373
11677
|
}
|
|
12374
11678
|
|
|
12375
|
-
/** @inheritdoc */
|
|
12376
|
-
clear() {
|
|
12377
|
-
this._earliestTimestamp = null;
|
|
12378
|
-
// We do not wait on this, as we assume the order of messages is consistent for the worker
|
|
12379
|
-
void this._worker.postMessage('clear');
|
|
12380
|
-
}
|
|
12381
|
-
|
|
12382
|
-
/** @inheritdoc */
|
|
12383
|
-
getEarliestTimestamp() {
|
|
12384
|
-
return this._earliestTimestamp;
|
|
12385
|
-
}
|
|
12386
|
-
|
|
12387
11679
|
/**
|
|
12388
11680
|
* Send the event to the worker.
|
|
12389
11681
|
*/
|
|
@@ -12397,10 +11689,15 @@ class EventBufferCompressionWorker {
|
|
|
12397
11689
|
async _finishRequest() {
|
|
12398
11690
|
const response = await this._worker.postMessage('finish');
|
|
12399
11691
|
|
|
12400
|
-
this.
|
|
11692
|
+
this.hasEvents = false;
|
|
12401
11693
|
|
|
12402
11694
|
return response;
|
|
12403
11695
|
}
|
|
11696
|
+
|
|
11697
|
+
/** Clear any pending events from the worker. */
|
|
11698
|
+
_clear() {
|
|
11699
|
+
return this._worker.postMessage('clear');
|
|
11700
|
+
}
|
|
12404
11701
|
}
|
|
12405
11702
|
|
|
12406
11703
|
/**
|
|
@@ -12418,11 +11715,6 @@ class EventBufferProxy {
|
|
|
12418
11715
|
this._ensureWorkerIsLoadedPromise = this._ensureWorkerIsLoaded();
|
|
12419
11716
|
}
|
|
12420
11717
|
|
|
12421
|
-
/** @inheritdoc */
|
|
12422
|
-
get type() {
|
|
12423
|
-
return this._used.type;
|
|
12424
|
-
}
|
|
12425
|
-
|
|
12426
11718
|
/** @inheritDoc */
|
|
12427
11719
|
get hasEvents() {
|
|
12428
11720
|
return this._used.hasEvents;
|
|
@@ -12434,23 +11726,13 @@ class EventBufferProxy {
|
|
|
12434
11726
|
this._compression.destroy();
|
|
12435
11727
|
}
|
|
12436
11728
|
|
|
12437
|
-
/** @inheritdoc */
|
|
12438
|
-
clear() {
|
|
12439
|
-
return this._used.clear();
|
|
12440
|
-
}
|
|
12441
|
-
|
|
12442
|
-
/** @inheritdoc */
|
|
12443
|
-
getEarliestTimestamp() {
|
|
12444
|
-
return this._used.getEarliestTimestamp();
|
|
12445
|
-
}
|
|
12446
|
-
|
|
12447
11729
|
/**
|
|
12448
11730
|
* Add an event to the event buffer.
|
|
12449
11731
|
*
|
|
12450
11732
|
* Returns true if event was successfully added.
|
|
12451
11733
|
*/
|
|
12452
|
-
addEvent(event) {
|
|
12453
|
-
return this._used.addEvent(event);
|
|
11734
|
+
addEvent(event, isCheckout) {
|
|
11735
|
+
return this._used.addEvent(event, isCheckout);
|
|
12454
11736
|
}
|
|
12455
11737
|
|
|
12456
11738
|
/** @inheritDoc */
|
|
@@ -12525,31 +11807,6 @@ function createEventBuffer({ useCompression }) {
|
|
|
12525
11807
|
return new EventBufferArray();
|
|
12526
11808
|
}
|
|
12527
11809
|
|
|
12528
|
-
/**
|
|
12529
|
-
* Removes the session from Session Storage and unsets session in replay instance
|
|
12530
|
-
*/
|
|
12531
|
-
function clearSession(replay) {
|
|
12532
|
-
deleteSession();
|
|
12533
|
-
replay.session = undefined;
|
|
12534
|
-
}
|
|
12535
|
-
|
|
12536
|
-
/**
|
|
12537
|
-
* Deletes a session from storage
|
|
12538
|
-
*/
|
|
12539
|
-
function deleteSession() {
|
|
12540
|
-
const hasSessionStorage = 'sessionStorage' in WINDOW;
|
|
12541
|
-
|
|
12542
|
-
if (!hasSessionStorage) {
|
|
12543
|
-
return;
|
|
12544
|
-
}
|
|
12545
|
-
|
|
12546
|
-
try {
|
|
12547
|
-
WINDOW.sessionStorage.removeItem(REPLAY_SESSION_KEY);
|
|
12548
|
-
} catch (e) {
|
|
12549
|
-
// Ignore potential SecurityError exceptions
|
|
12550
|
-
}
|
|
12551
|
-
}
|
|
12552
|
-
|
|
12553
11810
|
/**
|
|
12554
11811
|
* Given an initial timestamp and an expiry duration, checks to see if current
|
|
12555
11812
|
* time should be considered as expired.
|
|
@@ -12580,26 +11837,11 @@ function isSessionExpired(session, timeouts, targetTime = +new Date()) {
|
|
|
12580
11837
|
// First, check that maximum session length has not been exceeded
|
|
12581
11838
|
isExpired(session.started, timeouts.maxSessionLife, targetTime) ||
|
|
12582
11839
|
// check that the idle timeout has not been exceeded (i.e. user has
|
|
12583
|
-
// performed an action within the last `
|
|
12584
|
-
isExpired(session.lastActivity, timeouts.
|
|
11840
|
+
// performed an action within the last `idleTimeout` ms)
|
|
11841
|
+
isExpired(session.lastActivity, timeouts.sessionIdle, targetTime)
|
|
12585
11842
|
);
|
|
12586
11843
|
}
|
|
12587
11844
|
|
|
12588
|
-
/**
|
|
12589
|
-
* Given a sample rate, returns true if replay should be sampled.
|
|
12590
|
-
*
|
|
12591
|
-
* 1.0 = 100% sampling
|
|
12592
|
-
* 0.0 = 0% sampling
|
|
12593
|
-
*/
|
|
12594
|
-
function isSampled(sampleRate) {
|
|
12595
|
-
if (sampleRate === undefined) {
|
|
12596
|
-
return false;
|
|
12597
|
-
}
|
|
12598
|
-
|
|
12599
|
-
// Math.random() returns a number in range of 0 to 1 (inclusive of 0, but not 1)
|
|
12600
|
-
return Math.random() < sampleRate;
|
|
12601
|
-
}
|
|
12602
|
-
|
|
12603
11845
|
/**
|
|
12604
11846
|
* Save a session to session storage.
|
|
12605
11847
|
*/
|
|
@@ -12616,6 +11858,21 @@ function saveSession(session) {
|
|
|
12616
11858
|
}
|
|
12617
11859
|
}
|
|
12618
11860
|
|
|
11861
|
+
/**
|
|
11862
|
+
* Given a sample rate, returns true if replay should be sampled.
|
|
11863
|
+
*
|
|
11864
|
+
* 1.0 = 100% sampling
|
|
11865
|
+
* 0.0 = 0% sampling
|
|
11866
|
+
*/
|
|
11867
|
+
function isSampled(sampleRate) {
|
|
11868
|
+
if (sampleRate === undefined) {
|
|
11869
|
+
return false;
|
|
11870
|
+
}
|
|
11871
|
+
|
|
11872
|
+
// Math.random() returns a number in range of 0 to 1 (inclusive of 0, but not 1)
|
|
11873
|
+
return Math.random() < sampleRate;
|
|
11874
|
+
}
|
|
11875
|
+
|
|
12619
11876
|
/**
|
|
12620
11877
|
* Get a session with defaults & applied sampling.
|
|
12621
11878
|
*/
|
|
@@ -12634,15 +11891,14 @@ function makeSession(session) {
|
|
|
12634
11891
|
lastActivity,
|
|
12635
11892
|
segmentId,
|
|
12636
11893
|
sampled,
|
|
12637
|
-
shouldRefresh: true,
|
|
12638
11894
|
};
|
|
12639
11895
|
}
|
|
12640
11896
|
|
|
12641
11897
|
/**
|
|
12642
11898
|
* Get the sampled status for a session based on sample rates & current sampled status.
|
|
12643
11899
|
*/
|
|
12644
|
-
function getSessionSampleType(sessionSampleRate,
|
|
12645
|
-
return isSampled(sessionSampleRate) ? 'session' :
|
|
11900
|
+
function getSessionSampleType(sessionSampleRate, errorSampleRate) {
|
|
11901
|
+
return isSampled(sessionSampleRate) ? 'session' : isSampled(errorSampleRate) ? 'error' : false;
|
|
12646
11902
|
}
|
|
12647
11903
|
|
|
12648
11904
|
/**
|
|
@@ -12650,8 +11906,8 @@ function getSessionSampleType(sessionSampleRate, allowBuffering) {
|
|
|
12650
11906
|
* that all replays will be saved to as attachments. Currently, we only expect
|
|
12651
11907
|
* one of these Sentry events per "replay session".
|
|
12652
11908
|
*/
|
|
12653
|
-
function createSession({ sessionSampleRate,
|
|
12654
|
-
const sampled = getSessionSampleType(sessionSampleRate,
|
|
11909
|
+
function createSession({ sessionSampleRate, errorSampleRate, stickySession = false }) {
|
|
11910
|
+
const sampled = getSessionSampleType(sessionSampleRate, errorSampleRate);
|
|
12655
11911
|
const session = makeSession({
|
|
12656
11912
|
sampled,
|
|
12657
11913
|
});
|
|
@@ -12699,7 +11955,7 @@ function getSession({
|
|
|
12699
11955
|
currentSession,
|
|
12700
11956
|
stickySession,
|
|
12701
11957
|
sessionSampleRate,
|
|
12702
|
-
|
|
11958
|
+
errorSampleRate,
|
|
12703
11959
|
}) {
|
|
12704
11960
|
// If session exists and is passed, use it instead of always hitting session storage
|
|
12705
11961
|
const session = currentSession || (stickySession && fetchSession());
|
|
@@ -12712,9 +11968,8 @@ function getSession({
|
|
|
12712
11968
|
|
|
12713
11969
|
if (!isExpired) {
|
|
12714
11970
|
return { type: 'saved', session };
|
|
12715
|
-
} else if (
|
|
12716
|
-
//
|
|
12717
|
-
// This is the case if we have an error session that is completed (=triggered an error)
|
|
11971
|
+
} else if (session.sampled === 'error') {
|
|
11972
|
+
// Error samples should not be re-created when expired, but instead we stop when the replay is done
|
|
12718
11973
|
const discardedSession = makeSession({ sampled: false });
|
|
12719
11974
|
return { type: 'new', session: discardedSession };
|
|
12720
11975
|
} else {
|
|
@@ -12726,12 +11981,65 @@ function getSession({
|
|
|
12726
11981
|
const newSession = createSession({
|
|
12727
11982
|
stickySession,
|
|
12728
11983
|
sessionSampleRate,
|
|
12729
|
-
|
|
11984
|
+
errorSampleRate,
|
|
12730
11985
|
});
|
|
12731
11986
|
|
|
12732
11987
|
return { type: 'new', session: newSession };
|
|
12733
11988
|
}
|
|
12734
11989
|
|
|
11990
|
+
/**
|
|
11991
|
+
* Add an event to the event buffer.
|
|
11992
|
+
* `isCheckout` is true if this is either the very first event, or an event triggered by `checkoutEveryNms`.
|
|
11993
|
+
*/
|
|
11994
|
+
async function addEvent(
|
|
11995
|
+
replay,
|
|
11996
|
+
event,
|
|
11997
|
+
isCheckout,
|
|
11998
|
+
) {
|
|
11999
|
+
if (!replay.eventBuffer) {
|
|
12000
|
+
// This implies that `_isEnabled` is false
|
|
12001
|
+
return null;
|
|
12002
|
+
}
|
|
12003
|
+
|
|
12004
|
+
if (replay.isPaused()) {
|
|
12005
|
+
// Do not add to event buffer when recording is paused
|
|
12006
|
+
return null;
|
|
12007
|
+
}
|
|
12008
|
+
|
|
12009
|
+
// TODO: sadness -- we will want to normalize timestamps to be in ms -
|
|
12010
|
+
// requires coordination with frontend
|
|
12011
|
+
const isMs = event.timestamp > 9999999999;
|
|
12012
|
+
const timestampInMs = isMs ? event.timestamp : event.timestamp * 1000;
|
|
12013
|
+
|
|
12014
|
+
// Throw out events that happen more than 5 minutes ago. This can happen if
|
|
12015
|
+
// page has been left open and idle for a long period of time and user
|
|
12016
|
+
// comes back to trigger a new session. The performance entries rely on
|
|
12017
|
+
// `performance.timeOrigin`, which is when the page first opened.
|
|
12018
|
+
if (timestampInMs + replay.timeouts.sessionIdle < Date.now()) {
|
|
12019
|
+
return null;
|
|
12020
|
+
}
|
|
12021
|
+
|
|
12022
|
+
// Only record earliest event if a new session was created, otherwise it
|
|
12023
|
+
// shouldn't be relevant
|
|
12024
|
+
const earliestEvent = replay.getContext().earliestEvent;
|
|
12025
|
+
if (replay.session && replay.session.segmentId === 0 && (!earliestEvent || timestampInMs < earliestEvent)) {
|
|
12026
|
+
replay.getContext().earliestEvent = timestampInMs;
|
|
12027
|
+
}
|
|
12028
|
+
|
|
12029
|
+
try {
|
|
12030
|
+
return await replay.eventBuffer.addEvent(event, isCheckout);
|
|
12031
|
+
} catch (error) {
|
|
12032
|
+
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(error);
|
|
12033
|
+
replay.stop('addEvent');
|
|
12034
|
+
|
|
12035
|
+
const client = getCurrentHub().getClient();
|
|
12036
|
+
|
|
12037
|
+
if (client) {
|
|
12038
|
+
client.recordDroppedEvent('internal_sdk_error', 'replay');
|
|
12039
|
+
}
|
|
12040
|
+
}
|
|
12041
|
+
}
|
|
12042
|
+
|
|
12735
12043
|
/** If the event is an error event */
|
|
12736
12044
|
function isErrorEvent(event) {
|
|
12737
12045
|
return !event.type;
|
|
@@ -12781,21 +12089,31 @@ function handleAfterSendEvent(replay) {
|
|
|
12781
12089
|
return;
|
|
12782
12090
|
}
|
|
12783
12091
|
|
|
12784
|
-
// Add error to list of errorIds of replay
|
|
12785
|
-
// sampled because context will get reset at next checkout.
|
|
12786
|
-
// XXX: There is also a race condition where it's possible to capture an
|
|
12787
|
-
// error to Sentry before Replay SDK has loaded, but response returns after
|
|
12788
|
-
// it was loaded, and this gets called.
|
|
12092
|
+
// Add error to list of errorIds of replay
|
|
12789
12093
|
if (event.event_id) {
|
|
12790
12094
|
replay.getContext().errorIds.add(event.event_id);
|
|
12791
12095
|
}
|
|
12792
12096
|
|
|
12793
|
-
//
|
|
12097
|
+
// Trigger error recording
|
|
12794
12098
|
// Need to be very careful that this does not cause an infinite loop
|
|
12795
|
-
if (
|
|
12796
|
-
|
|
12797
|
-
|
|
12798
|
-
|
|
12099
|
+
if (
|
|
12100
|
+
replay.recordingMode === 'error' &&
|
|
12101
|
+
event.exception &&
|
|
12102
|
+
event.message !== UNABLE_TO_SEND_REPLAY // ignore this error because otherwise we could loop indefinitely with trying to capture replay and failing
|
|
12103
|
+
) {
|
|
12104
|
+
setTimeout(async () => {
|
|
12105
|
+
// Allow flush to complete before resuming as a session recording, otherwise
|
|
12106
|
+
// the checkout from `startRecording` may be included in the payload.
|
|
12107
|
+
// Prefer to keep the error replay as a separate (and smaller) segment
|
|
12108
|
+
// than the session replay.
|
|
12109
|
+
await replay.flushImmediate();
|
|
12110
|
+
|
|
12111
|
+
if (replay.stopRecording()) {
|
|
12112
|
+
// Reset all "capture on error" configuration before
|
|
12113
|
+
// starting a new recording
|
|
12114
|
+
replay.recordingMode = 'session';
|
|
12115
|
+
replay.startRecording();
|
|
12116
|
+
}
|
|
12799
12117
|
});
|
|
12800
12118
|
}
|
|
12801
12119
|
};
|
|
@@ -12817,6 +12135,166 @@ function isBaseTransportSend() {
|
|
|
12817
12135
|
);
|
|
12818
12136
|
}
|
|
12819
12137
|
|
|
12138
|
+
var NodeType;
|
|
12139
|
+
(function (NodeType) {
|
|
12140
|
+
NodeType[NodeType["Document"] = 0] = "Document";
|
|
12141
|
+
NodeType[NodeType["DocumentType"] = 1] = "DocumentType";
|
|
12142
|
+
NodeType[NodeType["Element"] = 2] = "Element";
|
|
12143
|
+
NodeType[NodeType["Text"] = 3] = "Text";
|
|
12144
|
+
NodeType[NodeType["CDATA"] = 4] = "CDATA";
|
|
12145
|
+
NodeType[NodeType["Comment"] = 5] = "Comment";
|
|
12146
|
+
})(NodeType || (NodeType = {}));
|
|
12147
|
+
|
|
12148
|
+
/**
|
|
12149
|
+
* Create a breadcrumb for a replay.
|
|
12150
|
+
*/
|
|
12151
|
+
function createBreadcrumb(
|
|
12152
|
+
breadcrumb,
|
|
12153
|
+
) {
|
|
12154
|
+
return {
|
|
12155
|
+
timestamp: Date.now() / 1000,
|
|
12156
|
+
type: 'default',
|
|
12157
|
+
...breadcrumb,
|
|
12158
|
+
};
|
|
12159
|
+
}
|
|
12160
|
+
|
|
12161
|
+
/**
|
|
12162
|
+
* Add a breadcrumb event to replay.
|
|
12163
|
+
*/
|
|
12164
|
+
function addBreadcrumbEvent(replay, breadcrumb) {
|
|
12165
|
+
if (breadcrumb.category === 'sentry.transaction') {
|
|
12166
|
+
return;
|
|
12167
|
+
}
|
|
12168
|
+
|
|
12169
|
+
if (['ui.click', 'ui.input'].includes(breadcrumb.category )) {
|
|
12170
|
+
replay.triggerUserActivity();
|
|
12171
|
+
} else {
|
|
12172
|
+
replay.checkAndHandleExpiredSession();
|
|
12173
|
+
}
|
|
12174
|
+
|
|
12175
|
+
replay.addUpdate(() => {
|
|
12176
|
+
void addEvent(replay, {
|
|
12177
|
+
type: EventType.Custom,
|
|
12178
|
+
// TODO: We were converting from ms to seconds for breadcrumbs, spans,
|
|
12179
|
+
// but maybe we should just keep them as milliseconds
|
|
12180
|
+
timestamp: (breadcrumb.timestamp || 0) * 1000,
|
|
12181
|
+
data: {
|
|
12182
|
+
tag: 'breadcrumb',
|
|
12183
|
+
payload: breadcrumb,
|
|
12184
|
+
},
|
|
12185
|
+
});
|
|
12186
|
+
|
|
12187
|
+
// Do not flush after console log messages
|
|
12188
|
+
return breadcrumb.category === 'console';
|
|
12189
|
+
});
|
|
12190
|
+
}
|
|
12191
|
+
|
|
12192
|
+
// Note that these are the serialized attributes and not attributes directly on
|
|
12193
|
+
// the DOM Node. Attributes we are interested in:
|
|
12194
|
+
const ATTRIBUTES_TO_RECORD = new Set([
|
|
12195
|
+
'id',
|
|
12196
|
+
'class',
|
|
12197
|
+
'aria-label',
|
|
12198
|
+
'role',
|
|
12199
|
+
'name',
|
|
12200
|
+
'alt',
|
|
12201
|
+
'title',
|
|
12202
|
+
'data-test-id',
|
|
12203
|
+
'data-testid',
|
|
12204
|
+
]);
|
|
12205
|
+
|
|
12206
|
+
/**
|
|
12207
|
+
* Inclusion list of attributes that we want to record from the DOM element
|
|
12208
|
+
*/
|
|
12209
|
+
function getAttributesToRecord(attributes) {
|
|
12210
|
+
const obj = {};
|
|
12211
|
+
for (const key in attributes) {
|
|
12212
|
+
if (ATTRIBUTES_TO_RECORD.has(key)) {
|
|
12213
|
+
let normalizedKey = key;
|
|
12214
|
+
|
|
12215
|
+
if (key === 'data-testid' || key === 'data-test-id') {
|
|
12216
|
+
normalizedKey = 'testId';
|
|
12217
|
+
}
|
|
12218
|
+
|
|
12219
|
+
obj[normalizedKey] = attributes[key];
|
|
12220
|
+
}
|
|
12221
|
+
}
|
|
12222
|
+
|
|
12223
|
+
return obj;
|
|
12224
|
+
}
|
|
12225
|
+
|
|
12226
|
+
const handleDomListener =
|
|
12227
|
+
(replay) =>
|
|
12228
|
+
(handlerData) => {
|
|
12229
|
+
if (!replay.isEnabled()) {
|
|
12230
|
+
return;
|
|
12231
|
+
}
|
|
12232
|
+
|
|
12233
|
+
const result = handleDom(handlerData);
|
|
12234
|
+
|
|
12235
|
+
if (!result) {
|
|
12236
|
+
return;
|
|
12237
|
+
}
|
|
12238
|
+
|
|
12239
|
+
addBreadcrumbEvent(replay, result);
|
|
12240
|
+
};
|
|
12241
|
+
|
|
12242
|
+
/**
|
|
12243
|
+
* An event handler to react to DOM events.
|
|
12244
|
+
*/
|
|
12245
|
+
function handleDom(handlerData) {
|
|
12246
|
+
let target;
|
|
12247
|
+
let targetNode;
|
|
12248
|
+
|
|
12249
|
+
// Accessing event.target can throw (see getsentry/raven-js#838, #768)
|
|
12250
|
+
try {
|
|
12251
|
+
targetNode = getTargetNode(handlerData);
|
|
12252
|
+
target = htmlTreeAsString(targetNode);
|
|
12253
|
+
} catch (e) {
|
|
12254
|
+
target = '<unknown>';
|
|
12255
|
+
}
|
|
12256
|
+
|
|
12257
|
+
// `__sn` property is the serialized node created by rrweb
|
|
12258
|
+
const serializedNode =
|
|
12259
|
+
targetNode && '__sn' in targetNode && targetNode.__sn.type === NodeType.Element ? targetNode.__sn : null;
|
|
12260
|
+
|
|
12261
|
+
return createBreadcrumb({
|
|
12262
|
+
category: `ui.${handlerData.name}`,
|
|
12263
|
+
message: target,
|
|
12264
|
+
data: serializedNode
|
|
12265
|
+
? {
|
|
12266
|
+
nodeId: serializedNode.id,
|
|
12267
|
+
node: {
|
|
12268
|
+
id: serializedNode.id,
|
|
12269
|
+
tagName: serializedNode.tagName,
|
|
12270
|
+
textContent: targetNode
|
|
12271
|
+
? Array.from(targetNode.childNodes)
|
|
12272
|
+
.map(
|
|
12273
|
+
(node) => '__sn' in node && node.__sn.type === NodeType.Text && node.__sn.textContent,
|
|
12274
|
+
)
|
|
12275
|
+
.filter(Boolean) // filter out empty values
|
|
12276
|
+
.map(text => (text ).trim())
|
|
12277
|
+
.join('')
|
|
12278
|
+
: '',
|
|
12279
|
+
attributes: getAttributesToRecord(serializedNode.attributes),
|
|
12280
|
+
},
|
|
12281
|
+
}
|
|
12282
|
+
: {},
|
|
12283
|
+
});
|
|
12284
|
+
}
|
|
12285
|
+
|
|
12286
|
+
function getTargetNode(handlerData) {
|
|
12287
|
+
if (isEventWithTarget(handlerData.event)) {
|
|
12288
|
+
return handlerData.event.target;
|
|
12289
|
+
}
|
|
12290
|
+
|
|
12291
|
+
return handlerData.event;
|
|
12292
|
+
}
|
|
12293
|
+
|
|
12294
|
+
function isEventWithTarget(event) {
|
|
12295
|
+
return !!(event ).target;
|
|
12296
|
+
}
|
|
12297
|
+
|
|
12820
12298
|
/**
|
|
12821
12299
|
* Returns true if we think the given event is an error originating inside of rrweb.
|
|
12822
12300
|
*/
|
|
@@ -12840,30 +12318,6 @@ function isRrwebError(event, hint) {
|
|
|
12840
12318
|
});
|
|
12841
12319
|
}
|
|
12842
12320
|
|
|
12843
|
-
/**
|
|
12844
|
-
* Determine if event should be sampled (only applies in buffer mode).
|
|
12845
|
-
* When an event is captured by `hanldleGlobalEvent`, when in buffer mode
|
|
12846
|
-
* we determine if we want to sample the error or not.
|
|
12847
|
-
*/
|
|
12848
|
-
function shouldSampleForBufferEvent(replay, event) {
|
|
12849
|
-
if (replay.recordingMode !== 'buffer') {
|
|
12850
|
-
return false;
|
|
12851
|
-
}
|
|
12852
|
-
|
|
12853
|
-
// ignore this error because otherwise we could loop indefinitely with
|
|
12854
|
-
// trying to capture replay and failing
|
|
12855
|
-
if (event.message === UNABLE_TO_SEND_REPLAY) {
|
|
12856
|
-
return false;
|
|
12857
|
-
}
|
|
12858
|
-
|
|
12859
|
-
// Require the event to be an error event & to have an exception
|
|
12860
|
-
if (!event.exception || event.type) {
|
|
12861
|
-
return false;
|
|
12862
|
-
}
|
|
12863
|
-
|
|
12864
|
-
return isSampled(replay.getOptions().errorSampleRate);
|
|
12865
|
-
}
|
|
12866
|
-
|
|
12867
12321
|
/**
|
|
12868
12322
|
* Returns a listener to be added to `addGlobalEventProcessor(listener)`.
|
|
12869
12323
|
*/
|
|
@@ -12893,16 +12347,8 @@ function handleGlobalEventListener(
|
|
|
12893
12347
|
return null;
|
|
12894
12348
|
}
|
|
12895
12349
|
|
|
12896
|
-
//
|
|
12897
|
-
|
|
12898
|
-
// And convert the buffer session to a full session
|
|
12899
|
-
const isErrorEventSampled = shouldSampleForBufferEvent(replay, event);
|
|
12900
|
-
|
|
12901
|
-
// Tag errors if it has been sampled in buffer mode, or if it is session mode
|
|
12902
|
-
// Only tag transactions if in session mode
|
|
12903
|
-
const shouldTagReplayId = isErrorEventSampled || replay.recordingMode === 'session';
|
|
12904
|
-
|
|
12905
|
-
if (shouldTagReplayId) {
|
|
12350
|
+
// Only tag transactions with replayId if not waiting for an error
|
|
12351
|
+
if (isErrorEvent(event) || (isTransactionEvent(event) && replay.recordingMode === 'session')) {
|
|
12906
12352
|
event.tags = { ...event.tags, replayId: replay.getSessionId() };
|
|
12907
12353
|
}
|
|
12908
12354
|
|
|
@@ -12952,7 +12398,7 @@ function createPerformanceSpans(
|
|
|
12952
12398
|
) {
|
|
12953
12399
|
return entries.map(({ type, start, end, name, data }) =>
|
|
12954
12400
|
addEvent(replay, {
|
|
12955
|
-
type: EventType
|
|
12401
|
+
type: EventType.Custom,
|
|
12956
12402
|
timestamp: start,
|
|
12957
12403
|
data: {
|
|
12958
12404
|
tag: 'performanceSpan',
|
|
@@ -13101,14 +12547,12 @@ function handleFetchSpanListener(replay) {
|
|
|
13101
12547
|
function handleXhr(handlerData) {
|
|
13102
12548
|
const { startTimestamp, endTimestamp, xhr } = handlerData;
|
|
13103
12549
|
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
if (!startTimestamp || !endTimestamp || !sentryXhrData) {
|
|
12550
|
+
if (!startTimestamp || !endTimestamp || !xhr.__sentry_xhr__) {
|
|
13107
12551
|
return null;
|
|
13108
12552
|
}
|
|
13109
12553
|
|
|
13110
12554
|
// This is only used as a fallback, so we know the body sizes are never set here
|
|
13111
|
-
const { method, url, status_code: statusCode } =
|
|
12555
|
+
const { method, url, status_code: statusCode } = xhr.__sentry_xhr__;
|
|
13112
12556
|
|
|
13113
12557
|
if (url === undefined) {
|
|
13114
12558
|
return null;
|
|
@@ -13141,393 +12585,6 @@ function handleXhrSpanListener(replay) {
|
|
|
13141
12585
|
};
|
|
13142
12586
|
}
|
|
13143
12587
|
|
|
13144
|
-
const OBJ = 10;
|
|
13145
|
-
const OBJ_KEY = 11;
|
|
13146
|
-
const OBJ_KEY_STR = 12;
|
|
13147
|
-
const OBJ_VAL = 13;
|
|
13148
|
-
const OBJ_VAL_STR = 14;
|
|
13149
|
-
const OBJ_VAL_COMPLETED = 15;
|
|
13150
|
-
|
|
13151
|
-
const ARR = 20;
|
|
13152
|
-
const ARR_VAL = 21;
|
|
13153
|
-
const ARR_VAL_STR = 22;
|
|
13154
|
-
const ARR_VAL_COMPLETED = 23;
|
|
13155
|
-
|
|
13156
|
-
const ALLOWED_PRIMITIVES = ['true', 'false', 'null'];
|
|
13157
|
-
|
|
13158
|
-
/**
|
|
13159
|
-
* Complete an incomplete JSON string.
|
|
13160
|
-
* This will ensure that the last element always has a `"~~"` to indicate it was truncated.
|
|
13161
|
-
* For example, `[1,2,` will be completed to `[1,2,"~~"]`
|
|
13162
|
-
* and `{"aa":"b` will be completed to `{"aa":"b~~"}`
|
|
13163
|
-
*/
|
|
13164
|
-
function completeJson(incompleteJson, stack) {
|
|
13165
|
-
if (!stack.length) {
|
|
13166
|
-
return incompleteJson;
|
|
13167
|
-
}
|
|
13168
|
-
|
|
13169
|
-
let json = incompleteJson;
|
|
13170
|
-
|
|
13171
|
-
// Most checks are only needed for the last step in the stack
|
|
13172
|
-
const lastPos = stack.length - 1;
|
|
13173
|
-
const lastStep = stack[lastPos];
|
|
13174
|
-
|
|
13175
|
-
json = _fixLastStep(json, lastStep);
|
|
13176
|
-
|
|
13177
|
-
// Complete remaining steps - just add closing brackets
|
|
13178
|
-
for (let i = lastPos; i >= 0; i--) {
|
|
13179
|
-
const step = stack[i];
|
|
13180
|
-
|
|
13181
|
-
switch (step) {
|
|
13182
|
-
case OBJ:
|
|
13183
|
-
json = `${json}}`;
|
|
13184
|
-
break;
|
|
13185
|
-
case ARR:
|
|
13186
|
-
json = `${json}]`;
|
|
13187
|
-
break;
|
|
13188
|
-
}
|
|
13189
|
-
}
|
|
13190
|
-
|
|
13191
|
-
return json;
|
|
13192
|
-
}
|
|
13193
|
-
|
|
13194
|
-
function _fixLastStep(json, lastStep) {
|
|
13195
|
-
switch (lastStep) {
|
|
13196
|
-
// Object cases
|
|
13197
|
-
case OBJ:
|
|
13198
|
-
return `${json}"~~":"~~"`;
|
|
13199
|
-
case OBJ_KEY:
|
|
13200
|
-
return `${json}:"~~"`;
|
|
13201
|
-
case OBJ_KEY_STR:
|
|
13202
|
-
return `${json}~~":"~~"`;
|
|
13203
|
-
case OBJ_VAL:
|
|
13204
|
-
return _maybeFixIncompleteObjValue(json);
|
|
13205
|
-
case OBJ_VAL_STR:
|
|
13206
|
-
return `${json}~~"`;
|
|
13207
|
-
case OBJ_VAL_COMPLETED:
|
|
13208
|
-
return `${json},"~~":"~~"`;
|
|
13209
|
-
|
|
13210
|
-
// Array cases
|
|
13211
|
-
case ARR:
|
|
13212
|
-
return `${json}"~~"`;
|
|
13213
|
-
case ARR_VAL:
|
|
13214
|
-
return _maybeFixIncompleteArrValue(json);
|
|
13215
|
-
case ARR_VAL_STR:
|
|
13216
|
-
return `${json}~~"`;
|
|
13217
|
-
case ARR_VAL_COMPLETED:
|
|
13218
|
-
return `${json},"~~"`;
|
|
13219
|
-
}
|
|
13220
|
-
|
|
13221
|
-
return json;
|
|
13222
|
-
}
|
|
13223
|
-
|
|
13224
|
-
function _maybeFixIncompleteArrValue(json) {
|
|
13225
|
-
const pos = _findLastArrayDelimiter(json);
|
|
13226
|
-
|
|
13227
|
-
if (pos > -1) {
|
|
13228
|
-
const part = json.slice(pos + 1);
|
|
13229
|
-
|
|
13230
|
-
if (ALLOWED_PRIMITIVES.includes(part.trim())) {
|
|
13231
|
-
return `${json},"~~"`;
|
|
13232
|
-
}
|
|
13233
|
-
|
|
13234
|
-
// Everything else is replaced with `"~~"`
|
|
13235
|
-
return `${json.slice(0, pos + 1)}"~~"`;
|
|
13236
|
-
}
|
|
13237
|
-
|
|
13238
|
-
// fallback, this shouldn't happen, to be save
|
|
13239
|
-
return json;
|
|
13240
|
-
}
|
|
13241
|
-
|
|
13242
|
-
function _findLastArrayDelimiter(json) {
|
|
13243
|
-
for (let i = json.length - 1; i >= 0; i--) {
|
|
13244
|
-
const char = json[i];
|
|
13245
|
-
|
|
13246
|
-
if (char === ',' || char === '[') {
|
|
13247
|
-
return i;
|
|
13248
|
-
}
|
|
13249
|
-
}
|
|
13250
|
-
|
|
13251
|
-
return -1;
|
|
13252
|
-
}
|
|
13253
|
-
|
|
13254
|
-
function _maybeFixIncompleteObjValue(json) {
|
|
13255
|
-
const startPos = json.lastIndexOf(':');
|
|
13256
|
-
|
|
13257
|
-
const part = json.slice(startPos + 1);
|
|
13258
|
-
|
|
13259
|
-
if (ALLOWED_PRIMITIVES.includes(part.trim())) {
|
|
13260
|
-
return `${json},"~~":"~~"`;
|
|
13261
|
-
}
|
|
13262
|
-
|
|
13263
|
-
// Everything else is replaced with `"~~"`
|
|
13264
|
-
// This also means we do not have incomplete numbers, e.g `[1` is replaced with `["~~"]`
|
|
13265
|
-
return `${json.slice(0, startPos + 1)}"~~"`;
|
|
13266
|
-
}
|
|
13267
|
-
|
|
13268
|
-
/**
|
|
13269
|
-
* Evaluate an (incomplete) JSON string.
|
|
13270
|
-
*/
|
|
13271
|
-
function evaluateJson(json) {
|
|
13272
|
-
const stack = [];
|
|
13273
|
-
|
|
13274
|
-
for (let pos = 0; pos < json.length; pos++) {
|
|
13275
|
-
_evaluateJsonPos(stack, json, pos);
|
|
13276
|
-
}
|
|
13277
|
-
|
|
13278
|
-
return stack;
|
|
13279
|
-
}
|
|
13280
|
-
|
|
13281
|
-
function _evaluateJsonPos(stack, json, pos) {
|
|
13282
|
-
const curStep = stack[stack.length - 1];
|
|
13283
|
-
|
|
13284
|
-
const char = json[pos];
|
|
13285
|
-
|
|
13286
|
-
const whitespaceRegex = /\s/;
|
|
13287
|
-
|
|
13288
|
-
if (whitespaceRegex.test(char)) {
|
|
13289
|
-
return;
|
|
13290
|
-
}
|
|
13291
|
-
|
|
13292
|
-
if (char === '"' && !_isEscaped(json, pos)) {
|
|
13293
|
-
_handleQuote(stack, curStep);
|
|
13294
|
-
return;
|
|
13295
|
-
}
|
|
13296
|
-
|
|
13297
|
-
switch (char) {
|
|
13298
|
-
case '{':
|
|
13299
|
-
_handleObj(stack, curStep);
|
|
13300
|
-
break;
|
|
13301
|
-
case '[':
|
|
13302
|
-
_handleArr(stack, curStep);
|
|
13303
|
-
break;
|
|
13304
|
-
case ':':
|
|
13305
|
-
_handleColon(stack, curStep);
|
|
13306
|
-
break;
|
|
13307
|
-
case ',':
|
|
13308
|
-
_handleComma(stack, curStep);
|
|
13309
|
-
break;
|
|
13310
|
-
case '}':
|
|
13311
|
-
_handleObjClose(stack, curStep);
|
|
13312
|
-
break;
|
|
13313
|
-
case ']':
|
|
13314
|
-
_handleArrClose(stack, curStep);
|
|
13315
|
-
break;
|
|
13316
|
-
}
|
|
13317
|
-
}
|
|
13318
|
-
|
|
13319
|
-
function _handleQuote(stack, curStep) {
|
|
13320
|
-
// End of obj value
|
|
13321
|
-
if (curStep === OBJ_VAL_STR) {
|
|
13322
|
-
stack.pop();
|
|
13323
|
-
stack.push(OBJ_VAL_COMPLETED);
|
|
13324
|
-
return;
|
|
13325
|
-
}
|
|
13326
|
-
|
|
13327
|
-
// End of arr value
|
|
13328
|
-
if (curStep === ARR_VAL_STR) {
|
|
13329
|
-
stack.pop();
|
|
13330
|
-
stack.push(ARR_VAL_COMPLETED);
|
|
13331
|
-
return;
|
|
13332
|
-
}
|
|
13333
|
-
|
|
13334
|
-
// Start of obj value
|
|
13335
|
-
if (curStep === OBJ_VAL) {
|
|
13336
|
-
stack.push(OBJ_VAL_STR);
|
|
13337
|
-
return;
|
|
13338
|
-
}
|
|
13339
|
-
|
|
13340
|
-
// Start of arr value
|
|
13341
|
-
if (curStep === ARR_VAL) {
|
|
13342
|
-
stack.push(ARR_VAL_STR);
|
|
13343
|
-
return;
|
|
13344
|
-
}
|
|
13345
|
-
|
|
13346
|
-
// Start of obj key
|
|
13347
|
-
if (curStep === OBJ) {
|
|
13348
|
-
stack.push(OBJ_KEY_STR);
|
|
13349
|
-
return;
|
|
13350
|
-
}
|
|
13351
|
-
|
|
13352
|
-
// End of obj key
|
|
13353
|
-
if (curStep === OBJ_KEY_STR) {
|
|
13354
|
-
stack.pop();
|
|
13355
|
-
stack.push(OBJ_KEY);
|
|
13356
|
-
return;
|
|
13357
|
-
}
|
|
13358
|
-
}
|
|
13359
|
-
|
|
13360
|
-
function _handleObj(stack, curStep) {
|
|
13361
|
-
// Initial object
|
|
13362
|
-
if (!curStep) {
|
|
13363
|
-
stack.push(OBJ);
|
|
13364
|
-
return;
|
|
13365
|
-
}
|
|
13366
|
-
|
|
13367
|
-
// New object as obj value
|
|
13368
|
-
if (curStep === OBJ_VAL) {
|
|
13369
|
-
stack.push(OBJ);
|
|
13370
|
-
return;
|
|
13371
|
-
}
|
|
13372
|
-
|
|
13373
|
-
// New object as array element
|
|
13374
|
-
if (curStep === ARR_VAL) {
|
|
13375
|
-
stack.push(OBJ);
|
|
13376
|
-
}
|
|
13377
|
-
|
|
13378
|
-
// New object as first array element
|
|
13379
|
-
if (curStep === ARR) {
|
|
13380
|
-
stack.push(OBJ);
|
|
13381
|
-
return;
|
|
13382
|
-
}
|
|
13383
|
-
}
|
|
13384
|
-
|
|
13385
|
-
function _handleArr(stack, curStep) {
|
|
13386
|
-
// Initial array
|
|
13387
|
-
if (!curStep) {
|
|
13388
|
-
stack.push(ARR);
|
|
13389
|
-
stack.push(ARR_VAL);
|
|
13390
|
-
return;
|
|
13391
|
-
}
|
|
13392
|
-
|
|
13393
|
-
// New array as obj value
|
|
13394
|
-
if (curStep === OBJ_VAL) {
|
|
13395
|
-
stack.push(ARR);
|
|
13396
|
-
stack.push(ARR_VAL);
|
|
13397
|
-
return;
|
|
13398
|
-
}
|
|
13399
|
-
|
|
13400
|
-
// New array as array element
|
|
13401
|
-
if (curStep === ARR_VAL) {
|
|
13402
|
-
stack.push(ARR);
|
|
13403
|
-
stack.push(ARR_VAL);
|
|
13404
|
-
}
|
|
13405
|
-
|
|
13406
|
-
// New array as first array element
|
|
13407
|
-
if (curStep === ARR) {
|
|
13408
|
-
stack.push(ARR);
|
|
13409
|
-
stack.push(ARR_VAL);
|
|
13410
|
-
return;
|
|
13411
|
-
}
|
|
13412
|
-
}
|
|
13413
|
-
|
|
13414
|
-
function _handleColon(stack, curStep) {
|
|
13415
|
-
if (curStep === OBJ_KEY) {
|
|
13416
|
-
stack.pop();
|
|
13417
|
-
stack.push(OBJ_VAL);
|
|
13418
|
-
}
|
|
13419
|
-
}
|
|
13420
|
-
|
|
13421
|
-
function _handleComma(stack, curStep) {
|
|
13422
|
-
// Comma after obj value
|
|
13423
|
-
if (curStep === OBJ_VAL) {
|
|
13424
|
-
stack.pop();
|
|
13425
|
-
return;
|
|
13426
|
-
}
|
|
13427
|
-
if (curStep === OBJ_VAL_COMPLETED) {
|
|
13428
|
-
// Pop OBJ_VAL_COMPLETED & OBJ_VAL
|
|
13429
|
-
stack.pop();
|
|
13430
|
-
stack.pop();
|
|
13431
|
-
return;
|
|
13432
|
-
}
|
|
13433
|
-
|
|
13434
|
-
// Comma after arr value
|
|
13435
|
-
if (curStep === ARR_VAL) {
|
|
13436
|
-
// do nothing - basically we'd pop ARR_VAL but add it right back
|
|
13437
|
-
return;
|
|
13438
|
-
}
|
|
13439
|
-
|
|
13440
|
-
if (curStep === ARR_VAL_COMPLETED) {
|
|
13441
|
-
// Pop ARR_VAL_COMPLETED
|
|
13442
|
-
stack.pop();
|
|
13443
|
-
|
|
13444
|
-
// basically we'd pop ARR_VAL but add it right back
|
|
13445
|
-
return;
|
|
13446
|
-
}
|
|
13447
|
-
}
|
|
13448
|
-
|
|
13449
|
-
function _handleObjClose(stack, curStep) {
|
|
13450
|
-
// Empty object {}
|
|
13451
|
-
if (curStep === OBJ) {
|
|
13452
|
-
stack.pop();
|
|
13453
|
-
}
|
|
13454
|
-
|
|
13455
|
-
// Object with element
|
|
13456
|
-
if (curStep === OBJ_VAL) {
|
|
13457
|
-
// Pop OBJ_VAL, OBJ
|
|
13458
|
-
stack.pop();
|
|
13459
|
-
stack.pop();
|
|
13460
|
-
}
|
|
13461
|
-
|
|
13462
|
-
// Obj with element
|
|
13463
|
-
if (curStep === OBJ_VAL_COMPLETED) {
|
|
13464
|
-
// Pop OBJ_VAL_COMPLETED, OBJ_VAL, OBJ
|
|
13465
|
-
stack.pop();
|
|
13466
|
-
stack.pop();
|
|
13467
|
-
stack.pop();
|
|
13468
|
-
}
|
|
13469
|
-
|
|
13470
|
-
// if was obj value, complete it
|
|
13471
|
-
if (stack[stack.length - 1] === OBJ_VAL) {
|
|
13472
|
-
stack.push(OBJ_VAL_COMPLETED);
|
|
13473
|
-
}
|
|
13474
|
-
|
|
13475
|
-
// if was arr value, complete it
|
|
13476
|
-
if (stack[stack.length - 1] === ARR_VAL) {
|
|
13477
|
-
stack.push(ARR_VAL_COMPLETED);
|
|
13478
|
-
}
|
|
13479
|
-
}
|
|
13480
|
-
|
|
13481
|
-
function _handleArrClose(stack, curStep) {
|
|
13482
|
-
// Empty array []
|
|
13483
|
-
if (curStep === ARR) {
|
|
13484
|
-
stack.pop();
|
|
13485
|
-
}
|
|
13486
|
-
|
|
13487
|
-
// Array with element
|
|
13488
|
-
if (curStep === ARR_VAL) {
|
|
13489
|
-
// Pop ARR_VAL, ARR
|
|
13490
|
-
stack.pop();
|
|
13491
|
-
stack.pop();
|
|
13492
|
-
}
|
|
13493
|
-
|
|
13494
|
-
// Array with element
|
|
13495
|
-
if (curStep === ARR_VAL_COMPLETED) {
|
|
13496
|
-
// Pop ARR_VAL_COMPLETED, ARR_VAL, ARR
|
|
13497
|
-
stack.pop();
|
|
13498
|
-
stack.pop();
|
|
13499
|
-
stack.pop();
|
|
13500
|
-
}
|
|
13501
|
-
|
|
13502
|
-
// if was obj value, complete it
|
|
13503
|
-
if (stack[stack.length - 1] === OBJ_VAL) {
|
|
13504
|
-
stack.push(OBJ_VAL_COMPLETED);
|
|
13505
|
-
}
|
|
13506
|
-
|
|
13507
|
-
// if was arr value, complete it
|
|
13508
|
-
if (stack[stack.length - 1] === ARR_VAL) {
|
|
13509
|
-
stack.push(ARR_VAL_COMPLETED);
|
|
13510
|
-
}
|
|
13511
|
-
}
|
|
13512
|
-
|
|
13513
|
-
function _isEscaped(str, pos) {
|
|
13514
|
-
const previousChar = str[pos - 1];
|
|
13515
|
-
|
|
13516
|
-
return previousChar === '\\' && !_isEscaped(str, pos - 1);
|
|
13517
|
-
}
|
|
13518
|
-
|
|
13519
|
-
/* eslint-disable max-lines */
|
|
13520
|
-
|
|
13521
|
-
/**
|
|
13522
|
-
* Takes an incomplete JSON string, and returns a hopefully valid JSON string.
|
|
13523
|
-
* Note that this _can_ fail, so you should check the return value is valid JSON.
|
|
13524
|
-
*/
|
|
13525
|
-
function fixJson(incompleteJson) {
|
|
13526
|
-
const stack = evaluateJson(incompleteJson);
|
|
13527
|
-
|
|
13528
|
-
return completeJson(incompleteJson, stack);
|
|
13529
|
-
}
|
|
13530
|
-
|
|
13531
12588
|
/** Get the size of a body. */
|
|
13532
12589
|
function getBodySize(
|
|
13533
12590
|
body,
|
|
@@ -13621,68 +12678,51 @@ function makeNetworkReplayBreadcrumb(
|
|
|
13621
12678
|
return result;
|
|
13622
12679
|
}
|
|
13623
12680
|
|
|
13624
|
-
/**
|
|
13625
|
-
function
|
|
13626
|
-
|
|
13627
|
-
|
|
13628
|
-
|
|
13629
|
-
|
|
13630
|
-
|
|
13631
|
-
|
|
13632
|
-
}
|
|
12681
|
+
/** Get either a JSON network body, or a text representation. */
|
|
12682
|
+
function getNetworkBody(bodyText) {
|
|
12683
|
+
if (!bodyText) {
|
|
12684
|
+
return;
|
|
12685
|
+
}
|
|
12686
|
+
|
|
12687
|
+
try {
|
|
12688
|
+
return JSON.parse(bodyText);
|
|
12689
|
+
} catch (e2) {
|
|
12690
|
+
// return text
|
|
12691
|
+
}
|
|
12692
|
+
|
|
12693
|
+
return bodyText;
|
|
13633
12694
|
}
|
|
13634
12695
|
|
|
13635
12696
|
/** Build the request or response part of a replay network breadcrumb. */
|
|
13636
12697
|
function buildNetworkRequestOrResponse(
|
|
13637
|
-
headers,
|
|
13638
12698
|
bodySize,
|
|
13639
12699
|
body,
|
|
13640
12700
|
) {
|
|
13641
|
-
if (!bodySize && Object.keys(headers).length === 0) {
|
|
13642
|
-
return undefined;
|
|
13643
|
-
}
|
|
13644
|
-
|
|
13645
12701
|
if (!bodySize) {
|
|
13646
|
-
return
|
|
13647
|
-
headers,
|
|
13648
|
-
};
|
|
12702
|
+
return undefined;
|
|
13649
12703
|
}
|
|
13650
12704
|
|
|
13651
12705
|
if (!body) {
|
|
13652
12706
|
return {
|
|
13653
|
-
headers,
|
|
13654
12707
|
size: bodySize,
|
|
13655
12708
|
};
|
|
13656
12709
|
}
|
|
13657
12710
|
|
|
13658
12711
|
const info = {
|
|
13659
|
-
headers,
|
|
13660
12712
|
size: bodySize,
|
|
13661
12713
|
};
|
|
13662
12714
|
|
|
13663
|
-
|
|
13664
|
-
|
|
13665
|
-
|
|
12715
|
+
if (bodySize < NETWORK_BODY_MAX_SIZE) {
|
|
12716
|
+
info.body = body;
|
|
12717
|
+
} else {
|
|
13666
12718
|
info._meta = {
|
|
13667
|
-
|
|
12719
|
+
errors: ['MAX_BODY_SIZE_EXCEEDED'],
|
|
13668
12720
|
};
|
|
13669
12721
|
}
|
|
13670
12722
|
|
|
13671
12723
|
return info;
|
|
13672
12724
|
}
|
|
13673
12725
|
|
|
13674
|
-
/** Filter a set of headers */
|
|
13675
|
-
function getAllowedHeaders(headers, allowedHeaders) {
|
|
13676
|
-
return Object.keys(headers).reduce((filteredHeaders, key) => {
|
|
13677
|
-
const normalizedKey = key.toLowerCase();
|
|
13678
|
-
// Avoid putting empty strings into the headers
|
|
13679
|
-
if (allowedHeaders.includes(normalizedKey) && headers[key]) {
|
|
13680
|
-
filteredHeaders[normalizedKey] = headers[key];
|
|
13681
|
-
}
|
|
13682
|
-
return filteredHeaders;
|
|
13683
|
-
}, {});
|
|
13684
|
-
}
|
|
13685
|
-
|
|
13686
12726
|
function _serializeFormData(formData) {
|
|
13687
12727
|
// This is a bit simplified, but gives us a decent estimate
|
|
13688
12728
|
// This converts e.g. { name: 'Anne Smith', age: 13 } to 'name=Anne+Smith&age=13'
|
|
@@ -13690,78 +12730,6 @@ function _serializeFormData(formData) {
|
|
|
13690
12730
|
return new URLSearchParams(formData).toString();
|
|
13691
12731
|
}
|
|
13692
12732
|
|
|
13693
|
-
function normalizeNetworkBody(body)
|
|
13694
|
-
|
|
13695
|
-
{
|
|
13696
|
-
if (!body || typeof body !== 'string') {
|
|
13697
|
-
return {
|
|
13698
|
-
body,
|
|
13699
|
-
warnings: [],
|
|
13700
|
-
};
|
|
13701
|
-
}
|
|
13702
|
-
|
|
13703
|
-
const exceedsSizeLimit = body.length > NETWORK_BODY_MAX_SIZE;
|
|
13704
|
-
|
|
13705
|
-
if (_strIsProbablyJson(body)) {
|
|
13706
|
-
try {
|
|
13707
|
-
const json = exceedsSizeLimit ? fixJson(body.slice(0, NETWORK_BODY_MAX_SIZE)) : body;
|
|
13708
|
-
const normalizedBody = JSON.parse(json);
|
|
13709
|
-
return {
|
|
13710
|
-
body: normalizedBody,
|
|
13711
|
-
warnings: exceedsSizeLimit ? ['JSON_TRUNCATED'] : [],
|
|
13712
|
-
};
|
|
13713
|
-
} catch (e3) {
|
|
13714
|
-
return {
|
|
13715
|
-
body: exceedsSizeLimit ? `${body.slice(0, NETWORK_BODY_MAX_SIZE)}…` : body,
|
|
13716
|
-
warnings: exceedsSizeLimit ? ['INVALID_JSON', 'TEXT_TRUNCATED'] : ['INVALID_JSON'],
|
|
13717
|
-
};
|
|
13718
|
-
}
|
|
13719
|
-
}
|
|
13720
|
-
|
|
13721
|
-
return {
|
|
13722
|
-
body: exceedsSizeLimit ? `${body.slice(0, NETWORK_BODY_MAX_SIZE)}…` : body,
|
|
13723
|
-
warnings: exceedsSizeLimit ? ['TEXT_TRUNCATED'] : [],
|
|
13724
|
-
};
|
|
13725
|
-
}
|
|
13726
|
-
|
|
13727
|
-
function _strIsProbablyJson(str) {
|
|
13728
|
-
const first = str[0];
|
|
13729
|
-
const last = str[str.length - 1];
|
|
13730
|
-
|
|
13731
|
-
// Simple check: If this does not start & end with {} or [], it's not JSON
|
|
13732
|
-
return (first === '[' && last === ']') || (first === '{' && last === '}');
|
|
13733
|
-
}
|
|
13734
|
-
|
|
13735
|
-
/** Match an URL against a list of strings/Regex. */
|
|
13736
|
-
function urlMatches(url, urls) {
|
|
13737
|
-
const fullUrl = getFullUrl(url);
|
|
13738
|
-
|
|
13739
|
-
return stringMatchesSomePattern(fullUrl, urls);
|
|
13740
|
-
}
|
|
13741
|
-
|
|
13742
|
-
/** exported for tests */
|
|
13743
|
-
function getFullUrl(url, baseURI = WINDOW.document.baseURI) {
|
|
13744
|
-
// Short circuit for common cases:
|
|
13745
|
-
if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith(WINDOW.location.origin)) {
|
|
13746
|
-
return url;
|
|
13747
|
-
}
|
|
13748
|
-
const fixedUrl = new URL(url, baseURI);
|
|
13749
|
-
|
|
13750
|
-
// If these do not match, we are not dealing with a relative URL, so just return it
|
|
13751
|
-
if (fixedUrl.origin !== new URL(baseURI).origin) {
|
|
13752
|
-
return url;
|
|
13753
|
-
}
|
|
13754
|
-
|
|
13755
|
-
const fullUrl = fixedUrl.href;
|
|
13756
|
-
|
|
13757
|
-
// Remove trailing slashes, if they don't match the original URL
|
|
13758
|
-
if (!url.endsWith('/') && fullUrl.endsWith('/')) {
|
|
13759
|
-
return fullUrl.slice(0, -1);
|
|
13760
|
-
}
|
|
13761
|
-
|
|
13762
|
-
return fullUrl;
|
|
13763
|
-
}
|
|
13764
|
-
|
|
13765
12733
|
/**
|
|
13766
12734
|
* Capture a fetch breadcrumb to a replay.
|
|
13767
12735
|
* This adds additional data (where approriate).
|
|
@@ -13769,9 +12737,7 @@ function getFullUrl(url, baseURI = WINDOW.document.baseURI) {
|
|
|
13769
12737
|
async function captureFetchBreadcrumbToReplay(
|
|
13770
12738
|
breadcrumb,
|
|
13771
12739
|
hint,
|
|
13772
|
-
options
|
|
13773
|
-
|
|
13774
|
-
,
|
|
12740
|
+
options,
|
|
13775
12741
|
) {
|
|
13776
12742
|
try {
|
|
13777
12743
|
const data = await _prepareFetchData(breadcrumb, hint, options);
|
|
@@ -13798,7 +12764,6 @@ function enrichFetchBreadcrumb(
|
|
|
13798
12764
|
|
|
13799
12765
|
const body = _getFetchRequestArgBody(input);
|
|
13800
12766
|
const reqSize = getBodySize(body, options.textEncoder);
|
|
13801
|
-
|
|
13802
12767
|
const resSize = response ? parseContentLengthHeader(response.headers.get('content-length')) : undefined;
|
|
13803
12768
|
|
|
13804
12769
|
if (reqSize !== undefined) {
|
|
@@ -13812,109 +12777,97 @@ function enrichFetchBreadcrumb(
|
|
|
13812
12777
|
async function _prepareFetchData(
|
|
13813
12778
|
breadcrumb,
|
|
13814
12779
|
hint,
|
|
13815
|
-
options
|
|
13816
|
-
|
|
13817
|
-
,
|
|
12780
|
+
options,
|
|
13818
12781
|
) {
|
|
13819
12782
|
const { startTimestamp, endTimestamp } = hint;
|
|
13820
12783
|
|
|
13821
12784
|
const {
|
|
13822
12785
|
url,
|
|
13823
12786
|
method,
|
|
13824
|
-
status_code: statusCode
|
|
12787
|
+
status_code: statusCode,
|
|
13825
12788
|
request_body_size: requestBodySize,
|
|
13826
12789
|
response_body_size: responseBodySize,
|
|
13827
12790
|
} = breadcrumb.data;
|
|
13828
12791
|
|
|
13829
|
-
const
|
|
13830
|
-
|
|
13831
|
-
const request = captureDetails
|
|
13832
|
-
? _getRequestInfo(options, hint.input, requestBodySize)
|
|
13833
|
-
: buildSkippedNetworkRequestOrResponse(requestBodySize);
|
|
13834
|
-
const response = await _getResponseInfo(captureDetails, options, hint.response, responseBodySize);
|
|
12792
|
+
const request = _getRequestInfo(options, hint.input, requestBodySize);
|
|
12793
|
+
const response = await _getResponseInfo(options, hint.response, responseBodySize);
|
|
13835
12794
|
|
|
13836
12795
|
return {
|
|
13837
12796
|
startTimestamp,
|
|
13838
12797
|
endTimestamp,
|
|
13839
12798
|
url,
|
|
13840
12799
|
method,
|
|
13841
|
-
statusCode,
|
|
12800
|
+
statusCode: statusCode || 0,
|
|
13842
12801
|
request,
|
|
13843
12802
|
response,
|
|
13844
12803
|
};
|
|
13845
12804
|
}
|
|
13846
12805
|
|
|
13847
12806
|
function _getRequestInfo(
|
|
13848
|
-
{
|
|
12807
|
+
{ captureBodies },
|
|
13849
12808
|
input,
|
|
13850
12809
|
requestBodySize,
|
|
13851
12810
|
) {
|
|
13852
|
-
|
|
13853
|
-
|
|
13854
|
-
if (!networkCaptureBodies) {
|
|
13855
|
-
return buildNetworkRequestOrResponse(headers, requestBodySize, undefined);
|
|
12811
|
+
if (!captureBodies) {
|
|
12812
|
+
return buildNetworkRequestOrResponse(requestBodySize, undefined);
|
|
13856
12813
|
}
|
|
13857
12814
|
|
|
13858
12815
|
// We only want to transmit string or string-like bodies
|
|
13859
12816
|
const requestBody = _getFetchRequestArgBody(input);
|
|
13860
|
-
const
|
|
13861
|
-
return buildNetworkRequestOrResponse(
|
|
12817
|
+
const body = getNetworkBody(getBodyString(requestBody));
|
|
12818
|
+
return buildNetworkRequestOrResponse(requestBodySize, body);
|
|
13862
12819
|
}
|
|
13863
12820
|
|
|
13864
12821
|
async function _getResponseInfo(
|
|
13865
|
-
|
|
13866
|
-
{
|
|
13867
|
-
networkCaptureBodies,
|
|
13868
|
-
textEncoder,
|
|
13869
|
-
networkResponseHeaders,
|
|
13870
|
-
}
|
|
13871
|
-
|
|
13872
|
-
,
|
|
12822
|
+
{ captureBodies, textEncoder },
|
|
13873
12823
|
response,
|
|
13874
12824
|
responseBodySize,
|
|
13875
12825
|
) {
|
|
13876
|
-
if (!
|
|
13877
|
-
return
|
|
13878
|
-
}
|
|
13879
|
-
|
|
13880
|
-
const headers = getAllHeaders(response.headers, networkResponseHeaders);
|
|
13881
|
-
|
|
13882
|
-
if (!networkCaptureBodies && responseBodySize !== undefined) {
|
|
13883
|
-
return buildNetworkRequestOrResponse(headers, responseBodySize, undefined);
|
|
12826
|
+
if (!captureBodies && responseBodySize !== undefined) {
|
|
12827
|
+
return buildNetworkRequestOrResponse(responseBodySize, undefined);
|
|
13884
12828
|
}
|
|
13885
12829
|
|
|
13886
12830
|
// Only clone the response if we need to
|
|
13887
12831
|
try {
|
|
13888
12832
|
// We have to clone this, as the body can only be read once
|
|
13889
12833
|
const res = response.clone();
|
|
13890
|
-
const bodyText = await _parseFetchBody(res);
|
|
12834
|
+
const { body, bodyText } = await _parseFetchBody(res);
|
|
13891
12835
|
|
|
13892
12836
|
const size =
|
|
13893
12837
|
bodyText && bodyText.length && responseBodySize === undefined
|
|
13894
12838
|
? getBodySize(bodyText, textEncoder)
|
|
13895
12839
|
: responseBodySize;
|
|
13896
12840
|
|
|
13897
|
-
if (
|
|
13898
|
-
return
|
|
12841
|
+
if (captureBodies) {
|
|
12842
|
+
return buildNetworkRequestOrResponse(size, body);
|
|
13899
12843
|
}
|
|
13900
12844
|
|
|
13901
|
-
|
|
13902
|
-
return buildNetworkRequestOrResponse(headers, size, bodyText);
|
|
13903
|
-
}
|
|
13904
|
-
|
|
13905
|
-
return buildNetworkRequestOrResponse(headers, size, undefined);
|
|
12845
|
+
return buildNetworkRequestOrResponse(size, undefined);
|
|
13906
12846
|
} catch (e) {
|
|
13907
12847
|
// fallback
|
|
13908
|
-
return buildNetworkRequestOrResponse(
|
|
12848
|
+
return buildNetworkRequestOrResponse(responseBodySize, undefined);
|
|
13909
12849
|
}
|
|
13910
12850
|
}
|
|
13911
12851
|
|
|
13912
|
-
async function _parseFetchBody(
|
|
12852
|
+
async function _parseFetchBody(
|
|
12853
|
+
response,
|
|
12854
|
+
) {
|
|
12855
|
+
let bodyText;
|
|
12856
|
+
|
|
13913
12857
|
try {
|
|
13914
|
-
|
|
12858
|
+
bodyText = await response.text();
|
|
13915
12859
|
} catch (e2) {
|
|
13916
|
-
return
|
|
12860
|
+
return {};
|
|
12861
|
+
}
|
|
12862
|
+
|
|
12863
|
+
try {
|
|
12864
|
+
const body = JSON.parse(bodyText);
|
|
12865
|
+
return { body, bodyText };
|
|
12866
|
+
} catch (e3) {
|
|
12867
|
+
// just send bodyText
|
|
13917
12868
|
}
|
|
12869
|
+
|
|
12870
|
+
return { bodyText, body: bodyText };
|
|
13918
12871
|
}
|
|
13919
12872
|
|
|
13920
12873
|
function _getFetchRequestArgBody(fetchArgs = []) {
|
|
@@ -13926,56 +12879,6 @@ function _getFetchRequestArgBody(fetchArgs = []) {
|
|
|
13926
12879
|
return (fetchArgs[1] ).body;
|
|
13927
12880
|
}
|
|
13928
12881
|
|
|
13929
|
-
function getAllHeaders(headers, allowedHeaders) {
|
|
13930
|
-
const allHeaders = {};
|
|
13931
|
-
|
|
13932
|
-
allowedHeaders.forEach(header => {
|
|
13933
|
-
if (headers.get(header)) {
|
|
13934
|
-
allHeaders[header] = headers.get(header) ;
|
|
13935
|
-
}
|
|
13936
|
-
});
|
|
13937
|
-
|
|
13938
|
-
return allHeaders;
|
|
13939
|
-
}
|
|
13940
|
-
|
|
13941
|
-
function getRequestHeaders(fetchArgs, allowedHeaders) {
|
|
13942
|
-
if (fetchArgs.length === 1 && typeof fetchArgs[0] !== 'string') {
|
|
13943
|
-
return getHeadersFromOptions(fetchArgs[0] , allowedHeaders);
|
|
13944
|
-
}
|
|
13945
|
-
|
|
13946
|
-
if (fetchArgs.length === 2) {
|
|
13947
|
-
return getHeadersFromOptions(fetchArgs[1] , allowedHeaders);
|
|
13948
|
-
}
|
|
13949
|
-
|
|
13950
|
-
return {};
|
|
13951
|
-
}
|
|
13952
|
-
|
|
13953
|
-
function getHeadersFromOptions(
|
|
13954
|
-
input,
|
|
13955
|
-
allowedHeaders,
|
|
13956
|
-
) {
|
|
13957
|
-
if (!input) {
|
|
13958
|
-
return {};
|
|
13959
|
-
}
|
|
13960
|
-
|
|
13961
|
-
const headers = input.headers;
|
|
13962
|
-
|
|
13963
|
-
if (!headers) {
|
|
13964
|
-
return {};
|
|
13965
|
-
}
|
|
13966
|
-
|
|
13967
|
-
if (headers instanceof Headers) {
|
|
13968
|
-
return getAllHeaders(headers, allowedHeaders);
|
|
13969
|
-
}
|
|
13970
|
-
|
|
13971
|
-
// We do not support this, as it is not really documented (anymore?)
|
|
13972
|
-
if (Array.isArray(headers)) {
|
|
13973
|
-
return {};
|
|
13974
|
-
}
|
|
13975
|
-
|
|
13976
|
-
return getAllowedHeaders(headers, allowedHeaders);
|
|
13977
|
-
}
|
|
13978
|
-
|
|
13979
12882
|
/**
|
|
13980
12883
|
* Capture an XHR breadcrumb to a replay.
|
|
13981
12884
|
* This adds additional data (where approriate).
|
|
@@ -14026,12 +12929,12 @@ function _prepareXhrData(
|
|
|
14026
12929
|
hint,
|
|
14027
12930
|
options,
|
|
14028
12931
|
) {
|
|
14029
|
-
const { startTimestamp, endTimestamp, input
|
|
12932
|
+
const { startTimestamp, endTimestamp, input } = hint;
|
|
14030
12933
|
|
|
14031
12934
|
const {
|
|
14032
12935
|
url,
|
|
14033
12936
|
method,
|
|
14034
|
-
status_code: statusCode
|
|
12937
|
+
status_code: statusCode,
|
|
14035
12938
|
request_body_size: requestBodySize,
|
|
14036
12939
|
response_body_size: responseBodySize,
|
|
14037
12940
|
} = breadcrumb.data;
|
|
@@ -14040,35 +12943,13 @@ function _prepareXhrData(
|
|
|
14040
12943
|
return null;
|
|
14041
12944
|
}
|
|
14042
12945
|
|
|
14043
|
-
if (!urlMatches(url, options.networkDetailAllowUrls)) {
|
|
14044
|
-
const request = buildSkippedNetworkRequestOrResponse(requestBodySize);
|
|
14045
|
-
const response = buildSkippedNetworkRequestOrResponse(responseBodySize);
|
|
14046
|
-
return {
|
|
14047
|
-
startTimestamp,
|
|
14048
|
-
endTimestamp,
|
|
14049
|
-
url,
|
|
14050
|
-
method,
|
|
14051
|
-
statusCode,
|
|
14052
|
-
request,
|
|
14053
|
-
response,
|
|
14054
|
-
};
|
|
14055
|
-
}
|
|
14056
|
-
|
|
14057
|
-
const xhrInfo = xhr[SENTRY_XHR_DATA_KEY];
|
|
14058
|
-
const networkRequestHeaders = xhrInfo
|
|
14059
|
-
? getAllowedHeaders(xhrInfo.request_headers, options.networkRequestHeaders)
|
|
14060
|
-
: {};
|
|
14061
|
-
const networkResponseHeaders = getAllowedHeaders(getResponseHeaders(xhr), options.networkResponseHeaders);
|
|
14062
|
-
|
|
14063
12946
|
const request = buildNetworkRequestOrResponse(
|
|
14064
|
-
networkRequestHeaders,
|
|
14065
12947
|
requestBodySize,
|
|
14066
|
-
options.
|
|
12948
|
+
options.captureBodies ? getNetworkBody(getBodyString(input)) : undefined,
|
|
14067
12949
|
);
|
|
14068
12950
|
const response = buildNetworkRequestOrResponse(
|
|
14069
|
-
networkResponseHeaders,
|
|
14070
12951
|
responseBodySize,
|
|
14071
|
-
options.
|
|
12952
|
+
options.captureBodies ? getNetworkBody(hint.xhr.responseText) : undefined,
|
|
14072
12953
|
);
|
|
14073
12954
|
|
|
14074
12955
|
return {
|
|
@@ -14076,26 +12957,12 @@ function _prepareXhrData(
|
|
|
14076
12957
|
endTimestamp,
|
|
14077
12958
|
url,
|
|
14078
12959
|
method,
|
|
14079
|
-
statusCode,
|
|
12960
|
+
statusCode: statusCode || 0,
|
|
14080
12961
|
request,
|
|
14081
12962
|
response,
|
|
14082
12963
|
};
|
|
14083
12964
|
}
|
|
14084
12965
|
|
|
14085
|
-
function getResponseHeaders(xhr) {
|
|
14086
|
-
const headers = xhr.getAllResponseHeaders();
|
|
14087
|
-
|
|
14088
|
-
if (!headers) {
|
|
14089
|
-
return {};
|
|
14090
|
-
}
|
|
14091
|
-
|
|
14092
|
-
return headers.split('\r\n').reduce((acc, line) => {
|
|
14093
|
-
const [key, value] = line.split(': ');
|
|
14094
|
-
acc[key.toLowerCase()] = value;
|
|
14095
|
-
return acc;
|
|
14096
|
-
}, {});
|
|
14097
|
-
}
|
|
14098
|
-
|
|
14099
12966
|
/**
|
|
14100
12967
|
* This method does two things:
|
|
14101
12968
|
* - It enriches the regular XHR/fetch breadcrumbs with request/response size data
|
|
@@ -14108,16 +12975,10 @@ function handleNetworkBreadcrumbs(replay) {
|
|
|
14108
12975
|
try {
|
|
14109
12976
|
const textEncoder = new TextEncoder();
|
|
14110
12977
|
|
|
14111
|
-
const { networkDetailAllowUrls, networkCaptureBodies, networkRequestHeaders, networkResponseHeaders } =
|
|
14112
|
-
replay.getOptions();
|
|
14113
|
-
|
|
14114
12978
|
const options = {
|
|
14115
12979
|
replay,
|
|
14116
12980
|
textEncoder,
|
|
14117
|
-
|
|
14118
|
-
networkCaptureBodies,
|
|
14119
|
-
networkRequestHeaders,
|
|
14120
|
-
networkResponseHeaders,
|
|
12981
|
+
captureBodies: replay.getOptions()._experiments.captureNetworkBodies || false,
|
|
14121
12982
|
};
|
|
14122
12983
|
|
|
14123
12984
|
if (client && client.on) {
|
|
@@ -14225,66 +13086,9 @@ function handleScope(scope) {
|
|
|
14225
13086
|
return null;
|
|
14226
13087
|
}
|
|
14227
13088
|
|
|
14228
|
-
if (newBreadcrumb.category === 'console') {
|
|
14229
|
-
return normalizeConsoleBreadcrumb(newBreadcrumb);
|
|
14230
|
-
}
|
|
14231
|
-
|
|
14232
13089
|
return createBreadcrumb(newBreadcrumb);
|
|
14233
13090
|
}
|
|
14234
13091
|
|
|
14235
|
-
/** exported for tests only */
|
|
14236
|
-
function normalizeConsoleBreadcrumb(breadcrumb) {
|
|
14237
|
-
const args = breadcrumb.data && breadcrumb.data.arguments;
|
|
14238
|
-
|
|
14239
|
-
if (!Array.isArray(args) || args.length === 0) {
|
|
14240
|
-
return createBreadcrumb(breadcrumb);
|
|
14241
|
-
}
|
|
14242
|
-
|
|
14243
|
-
let isTruncated = false;
|
|
14244
|
-
|
|
14245
|
-
// Avoid giant args captures
|
|
14246
|
-
const normalizedArgs = args.map(arg => {
|
|
14247
|
-
if (!arg) {
|
|
14248
|
-
return arg;
|
|
14249
|
-
}
|
|
14250
|
-
if (typeof arg === 'string') {
|
|
14251
|
-
if (arg.length > CONSOLE_ARG_MAX_SIZE) {
|
|
14252
|
-
isTruncated = true;
|
|
14253
|
-
return `${arg.slice(0, CONSOLE_ARG_MAX_SIZE)}…`;
|
|
14254
|
-
}
|
|
14255
|
-
|
|
14256
|
-
return arg;
|
|
14257
|
-
}
|
|
14258
|
-
if (typeof arg === 'object') {
|
|
14259
|
-
try {
|
|
14260
|
-
const normalizedArg = normalize(arg, 7);
|
|
14261
|
-
const stringified = JSON.stringify(normalizedArg);
|
|
14262
|
-
if (stringified.length > CONSOLE_ARG_MAX_SIZE) {
|
|
14263
|
-
const fixedJson = fixJson(stringified.slice(0, CONSOLE_ARG_MAX_SIZE));
|
|
14264
|
-
const json = JSON.parse(fixedJson);
|
|
14265
|
-
// We only set this after JSON.parse() was successfull, so we know we didn't run into `catch`
|
|
14266
|
-
isTruncated = true;
|
|
14267
|
-
return json;
|
|
14268
|
-
}
|
|
14269
|
-
return normalizedArg;
|
|
14270
|
-
} catch (e) {
|
|
14271
|
-
// fall back to default
|
|
14272
|
-
}
|
|
14273
|
-
}
|
|
14274
|
-
|
|
14275
|
-
return arg;
|
|
14276
|
-
});
|
|
14277
|
-
|
|
14278
|
-
return createBreadcrumb({
|
|
14279
|
-
...breadcrumb,
|
|
14280
|
-
data: {
|
|
14281
|
-
...breadcrumb.data,
|
|
14282
|
-
arguments: normalizedArgs,
|
|
14283
|
-
...(isTruncated ? { _meta: { warnings: ['CONSOLE_ARG_TRUNCATED'] } } : {}),
|
|
14284
|
-
},
|
|
14285
|
-
});
|
|
14286
|
-
}
|
|
14287
|
-
|
|
14288
13092
|
/**
|
|
14289
13093
|
* Add global listeners that cannot be removed.
|
|
14290
13094
|
*/
|
|
@@ -14309,8 +13113,7 @@ function addGlobalListeners(replay) {
|
|
|
14309
13113
|
client.on('afterSendEvent', handleAfterSendEvent(replay));
|
|
14310
13114
|
client.on('createDsc', (dsc) => {
|
|
14311
13115
|
const replayId = replay.getSessionId();
|
|
14312
|
-
|
|
14313
|
-
if (replayId && replay.isEnabled() && replay.recordingMode === 'session') {
|
|
13116
|
+
if (replayId) {
|
|
14314
13117
|
dsc.replay_id = replayId;
|
|
14315
13118
|
}
|
|
14316
13119
|
});
|
|
@@ -14590,23 +13393,6 @@ function debounce(func, wait, options) {
|
|
|
14590
13393
|
return debounced;
|
|
14591
13394
|
}
|
|
14592
13395
|
|
|
14593
|
-
/* eslint-disable @typescript-eslint/naming-convention */
|
|
14594
|
-
|
|
14595
|
-
var EventType; (function (EventType) {
|
|
14596
|
-
const DomContentLoaded = 0; EventType[EventType["DomContentLoaded"] = DomContentLoaded] = "DomContentLoaded";
|
|
14597
|
-
const Load = 1; EventType[EventType["Load"] = Load] = "Load";
|
|
14598
|
-
const FullSnapshot = 2; EventType[EventType["FullSnapshot"] = FullSnapshot] = "FullSnapshot";
|
|
14599
|
-
const IncrementalSnapshot = 3; EventType[EventType["IncrementalSnapshot"] = IncrementalSnapshot] = "IncrementalSnapshot";
|
|
14600
|
-
const Meta = 4; EventType[EventType["Meta"] = Meta] = "Meta";
|
|
14601
|
-
const Custom = 5; EventType[EventType["Custom"] = Custom] = "Custom";
|
|
14602
|
-
const Plugin = 6; EventType[EventType["Plugin"] = Plugin] = "Plugin";
|
|
14603
|
-
})(EventType || (EventType = {}));
|
|
14604
|
-
|
|
14605
|
-
/**
|
|
14606
|
-
* This is a partial copy of rrweb's eventWithTime type which only contains the properties
|
|
14607
|
-
* we specifcally need in the SDK.
|
|
14608
|
-
*/
|
|
14609
|
-
|
|
14610
13396
|
/**
|
|
14611
13397
|
* Handler for recording events.
|
|
14612
13398
|
*
|
|
@@ -14635,7 +13421,7 @@ function getHandleRecordingEmit(replay) {
|
|
|
14635
13421
|
// when an error occurs. Clear any state that happens before this current
|
|
14636
13422
|
// checkout. This needs to happen before `addEvent()` which updates state
|
|
14637
13423
|
// dependent on this reset.
|
|
14638
|
-
if (replay.recordingMode === '
|
|
13424
|
+
if (replay.recordingMode === 'error' && isCheckout) {
|
|
14639
13425
|
replay.setInitialState();
|
|
14640
13426
|
}
|
|
14641
13427
|
|
|
@@ -14649,14 +13435,6 @@ function getHandleRecordingEmit(replay) {
|
|
|
14649
13435
|
return false;
|
|
14650
13436
|
}
|
|
14651
13437
|
|
|
14652
|
-
// Additionally, create a meta event that will capture certain SDK settings.
|
|
14653
|
-
// In order to handle buffer mode, this needs to either be done when we
|
|
14654
|
-
// receive checkout events or at flush time.
|
|
14655
|
-
//
|
|
14656
|
-
// `isCheckout` is always true, but want to be explicit that it should
|
|
14657
|
-
// only be added for checkouts
|
|
14658
|
-
void addSettingsEvent(replay, isCheckout);
|
|
14659
|
-
|
|
14660
13438
|
// If there is a previousSessionId after a full snapshot occurs, then
|
|
14661
13439
|
// the replay session was started due to session expiration. The new session
|
|
14662
13440
|
// is started before triggering a new checkout and contains the id
|
|
@@ -14667,10 +13445,10 @@ function getHandleRecordingEmit(replay) {
|
|
|
14667
13445
|
return true;
|
|
14668
13446
|
}
|
|
14669
13447
|
|
|
14670
|
-
//
|
|
14671
|
-
//
|
|
14672
|
-
if (replay.recordingMode === '
|
|
14673
|
-
const earliestEvent = replay.
|
|
13448
|
+
// See note above re: session start needs to reflect the most recent
|
|
13449
|
+
// checkout.
|
|
13450
|
+
if (replay.recordingMode === 'error' && replay.session) {
|
|
13451
|
+
const { earliestEvent } = replay.getContext();
|
|
14674
13452
|
if (earliestEvent) {
|
|
14675
13453
|
replay.session.started = earliestEvent;
|
|
14676
13454
|
|
|
@@ -14694,46 +13472,6 @@ function getHandleRecordingEmit(replay) {
|
|
|
14694
13472
|
};
|
|
14695
13473
|
}
|
|
14696
13474
|
|
|
14697
|
-
/**
|
|
14698
|
-
* Exported for tests
|
|
14699
|
-
*/
|
|
14700
|
-
function createOptionsEvent(replay) {
|
|
14701
|
-
const options = replay.getOptions();
|
|
14702
|
-
return {
|
|
14703
|
-
type: EventType.Custom,
|
|
14704
|
-
timestamp: Date.now(),
|
|
14705
|
-
data: {
|
|
14706
|
-
tag: 'options',
|
|
14707
|
-
payload: {
|
|
14708
|
-
sessionSampleRate: options.sessionSampleRate,
|
|
14709
|
-
errorSampleRate: options.errorSampleRate,
|
|
14710
|
-
useCompressionOption: options.useCompression,
|
|
14711
|
-
blockAllMedia: options.blockAllMedia,
|
|
14712
|
-
maskAllText: options.maskAllText,
|
|
14713
|
-
maskAllInputs: options.maskAllInputs,
|
|
14714
|
-
useCompression: replay.eventBuffer ? replay.eventBuffer.type === 'worker' : false,
|
|
14715
|
-
networkDetailHasUrls: options.networkDetailAllowUrls.length > 0,
|
|
14716
|
-
networkCaptureBodies: options.networkCaptureBodies,
|
|
14717
|
-
networkRequestHasHeaders: options.networkRequestHeaders.length > 0,
|
|
14718
|
-
networkResponseHasHeaders: options.networkResponseHeaders.length > 0,
|
|
14719
|
-
},
|
|
14720
|
-
},
|
|
14721
|
-
};
|
|
14722
|
-
}
|
|
14723
|
-
|
|
14724
|
-
/**
|
|
14725
|
-
* Add a "meta" event that contains a simplified view on current configuration
|
|
14726
|
-
* options. This should only be included on the first segment of a recording.
|
|
14727
|
-
*/
|
|
14728
|
-
function addSettingsEvent(replay, isCheckout) {
|
|
14729
|
-
// Only need to add this event when sending the first segment
|
|
14730
|
-
if (!isCheckout || !replay.session || replay.session.segmentId !== 0) {
|
|
14731
|
-
return Promise.resolve(null);
|
|
14732
|
-
}
|
|
14733
|
-
|
|
14734
|
-
return addEvent(replay, createOptionsEvent(replay), false);
|
|
14735
|
-
}
|
|
14736
|
-
|
|
14737
13475
|
/**
|
|
14738
13476
|
* Create a replay envelope ready to be sent.
|
|
14739
13477
|
* This includes both the replay event, as well as the recording data.
|
|
@@ -14845,9 +13583,11 @@ async function sendReplayRequest({
|
|
|
14845
13583
|
recordingData,
|
|
14846
13584
|
replayId,
|
|
14847
13585
|
segmentId: segment_id,
|
|
13586
|
+
includeReplayStartTimestamp,
|
|
14848
13587
|
eventContext,
|
|
14849
13588
|
timestamp,
|
|
14850
13589
|
session,
|
|
13590
|
+
options,
|
|
14851
13591
|
}) {
|
|
14852
13592
|
const preparedRecordingData = prepareRecordingData({
|
|
14853
13593
|
recordingData,
|
|
@@ -14869,8 +13609,9 @@ async function sendReplayRequest({
|
|
|
14869
13609
|
}
|
|
14870
13610
|
|
|
14871
13611
|
const baseEvent = {
|
|
13612
|
+
// @ts-ignore private api
|
|
14872
13613
|
type: REPLAY_EVENT_NAME,
|
|
14873
|
-
replay_start_timestamp: initialTimestamp / 1000,
|
|
13614
|
+
...(includeReplayStartTimestamp ? { replay_start_timestamp: initialTimestamp / 1000 } : {}),
|
|
14874
13615
|
timestamp: timestamp / 1000,
|
|
14875
13616
|
error_ids: errorIds,
|
|
14876
13617
|
trace_ids: traceIds,
|
|
@@ -14889,6 +13630,15 @@ async function sendReplayRequest({
|
|
|
14889
13630
|
return;
|
|
14890
13631
|
}
|
|
14891
13632
|
|
|
13633
|
+
replayEvent.contexts = {
|
|
13634
|
+
...replayEvent.contexts,
|
|
13635
|
+
replay: {
|
|
13636
|
+
...(replayEvent.contexts && replayEvent.contexts.replay),
|
|
13637
|
+
session_sample_rate: options.sessionSampleRate,
|
|
13638
|
+
error_sample_rate: options.errorSampleRate,
|
|
13639
|
+
},
|
|
13640
|
+
};
|
|
13641
|
+
|
|
14892
13642
|
/*
|
|
14893
13643
|
For reference, the fully built event looks something like this:
|
|
14894
13644
|
{
|
|
@@ -14919,6 +13669,10 @@ async function sendReplayRequest({
|
|
|
14919
13669
|
},
|
|
14920
13670
|
"sdkProcessingMetadata": {},
|
|
14921
13671
|
"contexts": {
|
|
13672
|
+
"replay": {
|
|
13673
|
+
"session_sample_rate": 1,
|
|
13674
|
+
"error_sample_rate": 0,
|
|
13675
|
+
},
|
|
14922
13676
|
},
|
|
14923
13677
|
}
|
|
14924
13678
|
*/
|
|
@@ -15044,11 +13798,9 @@ class ReplayContainer {
|
|
|
15044
13798
|
__init2() {this.performanceEvents = [];}
|
|
15045
13799
|
|
|
15046
13800
|
/**
|
|
15047
|
-
* Recording can happen in one of
|
|
15048
|
-
*
|
|
15049
|
-
*
|
|
15050
|
-
* - having replaysOnErrorSampleRate > 0 to capture replay when an error occurs
|
|
15051
|
-
* - or calling `flush()` to send the replay
|
|
13801
|
+
* Recording can happen in one of two modes:
|
|
13802
|
+
* * session: Record the whole session, sending it continuously
|
|
13803
|
+
* * error: Always keep the last 60s of recording, and when an error occurs, send it immediately
|
|
15052
13804
|
*/
|
|
15053
13805
|
__init3() {this.recordingMode = 'session';}
|
|
15054
13806
|
|
|
@@ -15057,8 +13809,7 @@ class ReplayContainer {
|
|
|
15057
13809
|
* @hidden
|
|
15058
13810
|
*/
|
|
15059
13811
|
__init4() {this.timeouts = {
|
|
15060
|
-
|
|
15061
|
-
sessionIdleExpire: SESSION_IDLE_EXPIRE_DURATION,
|
|
13812
|
+
sessionIdle: SESSION_IDLE_DURATION,
|
|
15062
13813
|
maxSessionLife: MAX_SESSION_LIFE,
|
|
15063
13814
|
}; }
|
|
15064
13815
|
|
|
@@ -15102,6 +13853,7 @@ class ReplayContainer {
|
|
|
15102
13853
|
errorIds: new Set(),
|
|
15103
13854
|
traceIds: new Set(),
|
|
15104
13855
|
urls: [],
|
|
13856
|
+
earliestEvent: null,
|
|
15105
13857
|
initialTimestamp: Date.now(),
|
|
15106
13858
|
initialUrl: '',
|
|
15107
13859
|
};}
|
|
@@ -15111,7 +13863,7 @@ class ReplayContainer {
|
|
|
15111
13863
|
recordingOptions,
|
|
15112
13864
|
}
|
|
15113
13865
|
|
|
15114
|
-
) {ReplayContainer.prototype.__init.call(this);ReplayContainer.prototype.__init2.call(this);ReplayContainer.prototype.__init3.call(this);ReplayContainer.prototype.__init4.call(this);ReplayContainer.prototype.__init5.call(this);ReplayContainer.prototype.__init6.call(this);ReplayContainer.prototype.__init7.call(this);ReplayContainer.prototype.__init8.call(this);ReplayContainer.prototype.__init9.call(this);ReplayContainer.prototype.__init10.call(this);ReplayContainer.prototype.__init11.call(this);ReplayContainer.prototype.__init12.call(this);ReplayContainer.prototype.__init13.call(this);ReplayContainer.prototype.__init14.call(this);ReplayContainer.prototype.__init15.call(this);ReplayContainer.prototype.__init16.call(this);ReplayContainer.prototype.__init17.call(this);
|
|
13866
|
+
) {ReplayContainer.prototype.__init.call(this);ReplayContainer.prototype.__init2.call(this);ReplayContainer.prototype.__init3.call(this);ReplayContainer.prototype.__init4.call(this);ReplayContainer.prototype.__init5.call(this);ReplayContainer.prototype.__init6.call(this);ReplayContainer.prototype.__init7.call(this);ReplayContainer.prototype.__init8.call(this);ReplayContainer.prototype.__init9.call(this);ReplayContainer.prototype.__init10.call(this);ReplayContainer.prototype.__init11.call(this);ReplayContainer.prototype.__init12.call(this);ReplayContainer.prototype.__init13.call(this);ReplayContainer.prototype.__init14.call(this);ReplayContainer.prototype.__init15.call(this);ReplayContainer.prototype.__init16.call(this);ReplayContainer.prototype.__init17.call(this);
|
|
15115
13867
|
this._recordingOptions = recordingOptions;
|
|
15116
13868
|
this._options = options;
|
|
15117
13869
|
|
|
@@ -15141,102 +13893,49 @@ class ReplayContainer {
|
|
|
15141
13893
|
}
|
|
15142
13894
|
|
|
15143
13895
|
/**
|
|
15144
|
-
* Initializes the plugin
|
|
15145
|
-
*
|
|
13896
|
+
* Initializes the plugin.
|
|
13897
|
+
*
|
|
13898
|
+
* Creates or loads a session, attaches listeners to varying events (DOM,
|
|
13899
|
+
* _performanceObserver, Recording, Sentry SDK, etc)
|
|
15146
13900
|
*/
|
|
15147
|
-
|
|
15148
|
-
|
|
15149
|
-
|
|
15150
|
-
// If neither sample rate is > 0, then do nothing - user will need to call one of
|
|
15151
|
-
// `start()` or `startBuffering` themselves.
|
|
15152
|
-
if (errorSampleRate <= 0 && sessionSampleRate <= 0) {
|
|
15153
|
-
return;
|
|
15154
|
-
}
|
|
15155
|
-
|
|
15156
|
-
// Otherwise if there is _any_ sample rate set, try to load an existing
|
|
15157
|
-
// session, or create a new one.
|
|
15158
|
-
const isSessionSampled = this._loadAndCheckSession();
|
|
13901
|
+
start() {
|
|
13902
|
+
this.setInitialState();
|
|
15159
13903
|
|
|
15160
|
-
if (!
|
|
15161
|
-
// This should only occur if `errorSampleRate` is 0 and was unsampled for
|
|
15162
|
-
// session-based replay. In this case there is nothing to do.
|
|
13904
|
+
if (!this._loadAndCheckSession()) {
|
|
15163
13905
|
return;
|
|
15164
13906
|
}
|
|
15165
13907
|
|
|
13908
|
+
// If there is no session, then something bad has happened - can't continue
|
|
15166
13909
|
if (!this.session) {
|
|
15167
|
-
|
|
15168
|
-
this._handleException(new Error('Unable to initialize and create session'));
|
|
13910
|
+
this._handleException(new Error('No session found'));
|
|
15169
13911
|
return;
|
|
15170
13912
|
}
|
|
15171
13913
|
|
|
15172
|
-
if (this.session.sampled
|
|
15173
|
-
// If not sampled
|
|
15174
|
-
|
|
15175
|
-
// could have sessions from Session storage that are still `error` from
|
|
15176
|
-
// prior SDK version.
|
|
15177
|
-
this.recordingMode = 'buffer';
|
|
15178
|
-
}
|
|
15179
|
-
|
|
15180
|
-
this._initializeRecording();
|
|
15181
|
-
}
|
|
15182
|
-
|
|
15183
|
-
/**
|
|
15184
|
-
* Start a replay regardless of sampling rate. Calling this will always
|
|
15185
|
-
* create a new session. Will throw an error if replay is already in progress.
|
|
15186
|
-
*
|
|
15187
|
-
* Creates or loads a session, attaches listeners to varying events (DOM,
|
|
15188
|
-
* _performanceObserver, Recording, Sentry SDK, etc)
|
|
15189
|
-
*/
|
|
15190
|
-
start() {
|
|
15191
|
-
if (this._isEnabled && this.recordingMode === 'session') {
|
|
15192
|
-
throw new Error('Replay recording is already in progress');
|
|
13914
|
+
if (!this.session.sampled) {
|
|
13915
|
+
// If session was not sampled, then we do not initialize the integration at all.
|
|
13916
|
+
return;
|
|
15193
13917
|
}
|
|
15194
13918
|
|
|
15195
|
-
|
|
15196
|
-
|
|
13919
|
+
// If session is sampled for errors, then we need to set the recordingMode
|
|
13920
|
+
// to 'error', which will configure recording with different options.
|
|
13921
|
+
if (this.session.sampled === 'error') {
|
|
13922
|
+
this.recordingMode = 'error';
|
|
15197
13923
|
}
|
|
15198
13924
|
|
|
15199
|
-
|
|
13925
|
+
// setup() is generally called on page load or manually - in both cases we
|
|
13926
|
+
// should treat it as an activity
|
|
13927
|
+
this._updateSessionActivity();
|
|
15200
13928
|
|
|
15201
|
-
|
|
15202
|
-
|
|
15203
|
-
stickySession: Boolean(this._options.stickySession),
|
|
15204
|
-
currentSession: this.session,
|
|
15205
|
-
// This is intentional: create a new session-based replay when calling `start()`
|
|
15206
|
-
sessionSampleRate: 1,
|
|
15207
|
-
allowBuffering: false,
|
|
13929
|
+
this.eventBuffer = createEventBuffer({
|
|
13930
|
+
useCompression: this._options.useCompression,
|
|
15208
13931
|
});
|
|
15209
13932
|
|
|
15210
|
-
|
|
15211
|
-
this.session = session;
|
|
15212
|
-
|
|
15213
|
-
this._initializeRecording();
|
|
15214
|
-
}
|
|
15215
|
-
|
|
15216
|
-
/**
|
|
15217
|
-
* Start replay buffering. Buffers until `flush()` is called or, if
|
|
15218
|
-
* `replaysOnErrorSampleRate` > 0, an error occurs.
|
|
15219
|
-
*/
|
|
15220
|
-
startBuffering() {
|
|
15221
|
-
if (this._isEnabled) {
|
|
15222
|
-
throw new Error('Replay recording is already in progress');
|
|
15223
|
-
}
|
|
15224
|
-
|
|
15225
|
-
const previousSessionId = this.session && this.session.id;
|
|
15226
|
-
|
|
15227
|
-
const { session } = getSession({
|
|
15228
|
-
timeouts: this.timeouts,
|
|
15229
|
-
stickySession: Boolean(this._options.stickySession),
|
|
15230
|
-
currentSession: this.session,
|
|
15231
|
-
sessionSampleRate: 0,
|
|
15232
|
-
allowBuffering: true,
|
|
15233
|
-
});
|
|
13933
|
+
this._addListeners();
|
|
15234
13934
|
|
|
15235
|
-
|
|
15236
|
-
this.
|
|
13935
|
+
// Need to set as enabled before we start recording, as `record()` can trigger a flush with a new checkout
|
|
13936
|
+
this._isEnabled = true;
|
|
15237
13937
|
|
|
15238
|
-
this.
|
|
15239
|
-
this._initializeRecording();
|
|
13938
|
+
this.startRecording();
|
|
15240
13939
|
}
|
|
15241
13940
|
|
|
15242
13941
|
/**
|
|
@@ -15251,7 +13950,7 @@ class ReplayContainer {
|
|
|
15251
13950
|
// When running in error sampling mode, we need to overwrite `checkoutEveryNms`
|
|
15252
13951
|
// Without this, it would record forever, until an error happens, which we don't want
|
|
15253
13952
|
// instead, we'll always keep the last 60 seconds of replay before an error happened
|
|
15254
|
-
...(this.recordingMode === '
|
|
13953
|
+
...(this.recordingMode === 'error' && { checkoutEveryNms: ERROR_CHECKOUT_TIME }),
|
|
15255
13954
|
emit: getHandleRecordingEmit(this),
|
|
15256
13955
|
onMutation: this._onMutationHandler,
|
|
15257
13956
|
});
|
|
@@ -15262,18 +13961,17 @@ class ReplayContainer {
|
|
|
15262
13961
|
|
|
15263
13962
|
/**
|
|
15264
13963
|
* Stops the recording, if it was running.
|
|
15265
|
-
*
|
|
15266
|
-
* Returns true if it was previously stopped, or is now stopped,
|
|
15267
|
-
* otherwise false.
|
|
13964
|
+
* Returns true if it was stopped, else false.
|
|
15268
13965
|
*/
|
|
15269
13966
|
stopRecording() {
|
|
15270
13967
|
try {
|
|
15271
13968
|
if (this._stopRecording) {
|
|
15272
13969
|
this._stopRecording();
|
|
15273
13970
|
this._stopRecording = undefined;
|
|
13971
|
+
return true;
|
|
15274
13972
|
}
|
|
15275
13973
|
|
|
15276
|
-
return
|
|
13974
|
+
return false;
|
|
15277
13975
|
} catch (err) {
|
|
15278
13976
|
this._handleException(err);
|
|
15279
13977
|
return false;
|
|
@@ -15284,7 +13982,7 @@ class ReplayContainer {
|
|
|
15284
13982
|
* Currently, this needs to be manually called (e.g. for tests). Sentry SDK
|
|
15285
13983
|
* does not support a teardown
|
|
15286
13984
|
*/
|
|
15287
|
-
|
|
13985
|
+
stop(reason) {
|
|
15288
13986
|
if (!this._isEnabled) {
|
|
15289
13987
|
return;
|
|
15290
13988
|
}
|
|
@@ -15300,24 +13998,12 @@ class ReplayContainer {
|
|
|
15300
13998
|
log(msg);
|
|
15301
13999
|
}
|
|
15302
14000
|
|
|
15303
|
-
// We can't move `_isEnabled` after awaiting a flush, otherwise we can
|
|
15304
|
-
// enter into an infinite loop when `stop()` is called while flushing.
|
|
15305
14001
|
this._isEnabled = false;
|
|
15306
14002
|
this._removeListeners();
|
|
15307
14003
|
this.stopRecording();
|
|
15308
|
-
|
|
15309
|
-
this._debouncedFlush.cancel();
|
|
15310
|
-
// See comment above re: `_isEnabled`, we "force" a flush, ignoring the
|
|
15311
|
-
// `_isEnabled` state of the plugin since it was disabled above.
|
|
15312
|
-
await this._flush({ force: true });
|
|
15313
|
-
|
|
15314
|
-
// After flush, destroy event buffer
|
|
15315
14004
|
this.eventBuffer && this.eventBuffer.destroy();
|
|
15316
14005
|
this.eventBuffer = null;
|
|
15317
|
-
|
|
15318
|
-
// Clear session from session storage, note this means if a new session
|
|
15319
|
-
// is started after, it will not have `previousSessionId`
|
|
15320
|
-
clearSession(this);
|
|
14006
|
+
this._debouncedFlush.cancel();
|
|
15321
14007
|
} catch (err) {
|
|
15322
14008
|
this._handleException(err);
|
|
15323
14009
|
}
|
|
@@ -15348,45 +14034,6 @@ class ReplayContainer {
|
|
|
15348
14034
|
this.startRecording();
|
|
15349
14035
|
}
|
|
15350
14036
|
|
|
15351
|
-
/**
|
|
15352
|
-
* If not in "session" recording mode, flush event buffer which will create a new replay.
|
|
15353
|
-
* Unless `continueRecording` is false, the replay will continue to record and
|
|
15354
|
-
* behave as a "session"-based replay.
|
|
15355
|
-
*
|
|
15356
|
-
* Otherwise, queue up a flush.
|
|
15357
|
-
*/
|
|
15358
|
-
async sendBufferedReplayOrFlush({ continueRecording = true } = {}) {
|
|
15359
|
-
if (this.recordingMode === 'session') {
|
|
15360
|
-
return this.flushImmediate();
|
|
15361
|
-
}
|
|
15362
|
-
|
|
15363
|
-
// Allow flush to complete before resuming as a session recording, otherwise
|
|
15364
|
-
// the checkout from `startRecording` may be included in the payload.
|
|
15365
|
-
// Prefer to keep the error replay as a separate (and smaller) segment
|
|
15366
|
-
// than the session replay.
|
|
15367
|
-
await this.flushImmediate();
|
|
15368
|
-
|
|
15369
|
-
const hasStoppedRecording = this.stopRecording();
|
|
15370
|
-
|
|
15371
|
-
if (!continueRecording || !hasStoppedRecording) {
|
|
15372
|
-
return;
|
|
15373
|
-
}
|
|
15374
|
-
|
|
15375
|
-
// Re-start recording, but in "session" recording mode
|
|
15376
|
-
|
|
15377
|
-
// Reset all "capture on error" configuration before
|
|
15378
|
-
// starting a new recording
|
|
15379
|
-
this.recordingMode = 'session';
|
|
15380
|
-
|
|
15381
|
-
// Once this session ends, we do not want to refresh it
|
|
15382
|
-
if (this.session) {
|
|
15383
|
-
this.session.shouldRefresh = false;
|
|
15384
|
-
this._maybeSaveSession();
|
|
15385
|
-
}
|
|
15386
|
-
|
|
15387
|
-
this.startRecording();
|
|
15388
|
-
}
|
|
15389
|
-
|
|
15390
14037
|
/**
|
|
15391
14038
|
* We want to batch uploads of replay events. Save events only if
|
|
15392
14039
|
* `<flushMinDelay>` milliseconds have elapsed since the last event
|
|
@@ -15396,12 +14043,12 @@ class ReplayContainer {
|
|
|
15396
14043
|
* processing and hand back control to caller.
|
|
15397
14044
|
*/
|
|
15398
14045
|
addUpdate(cb) {
|
|
15399
|
-
// We need to always run `cb` (e.g. in the case of `this.recordingMode == '
|
|
14046
|
+
// We need to always run `cb` (e.g. in the case of `this.recordingMode == 'error'`)
|
|
15400
14047
|
const cbResult = cb();
|
|
15401
14048
|
|
|
15402
14049
|
// If this option is turned on then we will only want to call `flush`
|
|
15403
14050
|
// explicitly
|
|
15404
|
-
if (this.recordingMode === '
|
|
14051
|
+
if (this.recordingMode === 'error') {
|
|
15405
14052
|
return;
|
|
15406
14053
|
}
|
|
15407
14054
|
|
|
@@ -15473,12 +14120,12 @@ class ReplayContainer {
|
|
|
15473
14120
|
const oldSessionId = this.getSessionId();
|
|
15474
14121
|
|
|
15475
14122
|
// Prevent starting a new session if the last user activity is older than
|
|
15476
|
-
//
|
|
14123
|
+
// SESSION_IDLE_DURATION. Otherwise non-user activity can trigger a new
|
|
15477
14124
|
// session+recording. This creates noisy replays that do not have much
|
|
15478
14125
|
// content in them.
|
|
15479
14126
|
if (
|
|
15480
14127
|
this._lastActivity &&
|
|
15481
|
-
isExpired(this._lastActivity, this.timeouts.
|
|
14128
|
+
isExpired(this._lastActivity, this.timeouts.sessionIdle) &&
|
|
15482
14129
|
this.session &&
|
|
15483
14130
|
this.session.sampled === 'session'
|
|
15484
14131
|
) {
|
|
@@ -15528,30 +14175,6 @@ class ReplayContainer {
|
|
|
15528
14175
|
this._context.urls.push(url);
|
|
15529
14176
|
}
|
|
15530
14177
|
|
|
15531
|
-
/**
|
|
15532
|
-
* Initialize and start all listeners to varying events (DOM,
|
|
15533
|
-
* Performance Observer, Recording, Sentry SDK, etc)
|
|
15534
|
-
*/
|
|
15535
|
-
_initializeRecording() {
|
|
15536
|
-
this.setInitialState();
|
|
15537
|
-
|
|
15538
|
-
// this method is generally called on page load or manually - in both cases
|
|
15539
|
-
// we should treat it as an activity
|
|
15540
|
-
this._updateSessionActivity();
|
|
15541
|
-
|
|
15542
|
-
this.eventBuffer = createEventBuffer({
|
|
15543
|
-
useCompression: this._options.useCompression,
|
|
15544
|
-
});
|
|
15545
|
-
|
|
15546
|
-
this._removeListeners();
|
|
15547
|
-
this._addListeners();
|
|
15548
|
-
|
|
15549
|
-
// Need to set as enabled before we start recording, as `record()` can trigger a flush with a new checkout
|
|
15550
|
-
this._isEnabled = true;
|
|
15551
|
-
|
|
15552
|
-
this.startRecording();
|
|
15553
|
-
}
|
|
15554
|
-
|
|
15555
14178
|
/** A wrapper to conditionally capture exceptions. */
|
|
15556
14179
|
_handleException(error) {
|
|
15557
14180
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error('[Replay]', error);
|
|
@@ -15571,7 +14194,7 @@ class ReplayContainer {
|
|
|
15571
14194
|
stickySession: Boolean(this._options.stickySession),
|
|
15572
14195
|
currentSession: this.session,
|
|
15573
14196
|
sessionSampleRate: this._options.sessionSampleRate,
|
|
15574
|
-
|
|
14197
|
+
errorSampleRate: this._options.errorSampleRate,
|
|
15575
14198
|
});
|
|
15576
14199
|
|
|
15577
14200
|
// If session was newly created (i.e. was not loaded from storage), then
|
|
@@ -15588,7 +14211,7 @@ class ReplayContainer {
|
|
|
15588
14211
|
this.session = session;
|
|
15589
14212
|
|
|
15590
14213
|
if (!this.session.sampled) {
|
|
15591
|
-
|
|
14214
|
+
this.stop('session unsampled');
|
|
15592
14215
|
return false;
|
|
15593
14216
|
}
|
|
15594
14217
|
|
|
@@ -15603,7 +14226,6 @@ class ReplayContainer {
|
|
|
15603
14226
|
WINDOW.document.addEventListener('visibilitychange', this._handleVisibilityChange);
|
|
15604
14227
|
WINDOW.addEventListener('blur', this._handleWindowBlur);
|
|
15605
14228
|
WINDOW.addEventListener('focus', this._handleWindowFocus);
|
|
15606
|
-
WINDOW.addEventListener('keydown', this._handleKeyboardEvent);
|
|
15607
14229
|
|
|
15608
14230
|
// There is no way to remove these listeners, so ensure they are only added once
|
|
15609
14231
|
if (!this._hasInitializedCoreListeners) {
|
|
@@ -15632,7 +14254,6 @@ class ReplayContainer {
|
|
|
15632
14254
|
|
|
15633
14255
|
WINDOW.removeEventListener('blur', this._handleWindowBlur);
|
|
15634
14256
|
WINDOW.removeEventListener('focus', this._handleWindowFocus);
|
|
15635
|
-
WINDOW.removeEventListener('keydown', this._handleKeyboardEvent);
|
|
15636
14257
|
|
|
15637
14258
|
if (this._performanceObserver) {
|
|
15638
14259
|
this._performanceObserver.disconnect();
|
|
@@ -15683,11 +14304,6 @@ class ReplayContainer {
|
|
|
15683
14304
|
this._doChangeToForegroundTasks(breadcrumb);
|
|
15684
14305
|
};}
|
|
15685
14306
|
|
|
15686
|
-
/** Ensure page remains active when a key is pressed. */
|
|
15687
|
-
__init16() {this._handleKeyboardEvent = (event) => {
|
|
15688
|
-
handleKeyboardEvent(this, event);
|
|
15689
|
-
};}
|
|
15690
|
-
|
|
15691
14307
|
/**
|
|
15692
14308
|
* Tasks to run when we consider a page to be hidden (via blurring and/or visibility)
|
|
15693
14309
|
*/
|
|
@@ -15719,7 +14335,7 @@ class ReplayContainer {
|
|
|
15719
14335
|
const isSessionActive = this.checkAndHandleExpiredSession();
|
|
15720
14336
|
|
|
15721
14337
|
if (!isSessionActive) {
|
|
15722
|
-
// If the user has come back to the page within
|
|
14338
|
+
// If the user has come back to the page within SESSION_IDLE_DURATION
|
|
15723
14339
|
// ms, we will re-use the existing session, otherwise create a new
|
|
15724
14340
|
// session
|
|
15725
14341
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Replay] Document has become active, but session has expired');
|
|
@@ -15767,7 +14383,7 @@ class ReplayContainer {
|
|
|
15767
14383
|
_createCustomBreadcrumb(breadcrumb) {
|
|
15768
14384
|
this.addUpdate(() => {
|
|
15769
14385
|
void addEvent(this, {
|
|
15770
|
-
type: EventType
|
|
14386
|
+
type: EventType.Custom,
|
|
15771
14387
|
timestamp: breadcrumb.timestamp || 0,
|
|
15772
14388
|
data: {
|
|
15773
14389
|
tag: 'breadcrumb',
|
|
@@ -15793,7 +14409,7 @@ class ReplayContainer {
|
|
|
15793
14409
|
* Only flush if `this.recordingMode === 'session'`
|
|
15794
14410
|
*/
|
|
15795
14411
|
_conditionalFlush() {
|
|
15796
|
-
if (this.recordingMode === '
|
|
14412
|
+
if (this.recordingMode === 'error') {
|
|
15797
14413
|
return;
|
|
15798
14414
|
}
|
|
15799
14415
|
|
|
@@ -15808,35 +14424,22 @@ class ReplayContainer {
|
|
|
15808
14424
|
this._context.errorIds.clear();
|
|
15809
14425
|
this._context.traceIds.clear();
|
|
15810
14426
|
this._context.urls = [];
|
|
15811
|
-
|
|
15812
|
-
|
|
15813
|
-
/** Update the initial timestamp based on the buffer content. */
|
|
15814
|
-
_updateInitialTimestampFromEventBuffer() {
|
|
15815
|
-
const { session, eventBuffer } = this;
|
|
15816
|
-
if (!session || !eventBuffer) {
|
|
15817
|
-
return;
|
|
15818
|
-
}
|
|
15819
|
-
|
|
15820
|
-
// we only ever update this on the initial segment
|
|
15821
|
-
if (session.segmentId) {
|
|
15822
|
-
return;
|
|
15823
|
-
}
|
|
15824
|
-
|
|
15825
|
-
const earliestEvent = eventBuffer.getEarliestTimestamp();
|
|
15826
|
-
if (earliestEvent && earliestEvent < this._context.initialTimestamp) {
|
|
15827
|
-
this._context.initialTimestamp = earliestEvent;
|
|
15828
|
-
}
|
|
14427
|
+
this._context.earliestEvent = null;
|
|
15829
14428
|
}
|
|
15830
14429
|
|
|
15831
14430
|
/**
|
|
15832
14431
|
* Return and clear _context
|
|
15833
14432
|
*/
|
|
15834
14433
|
_popEventContext() {
|
|
14434
|
+
if (this._context.earliestEvent && this._context.earliestEvent < this._context.initialTimestamp) {
|
|
14435
|
+
this._context.initialTimestamp = this._context.earliestEvent;
|
|
14436
|
+
}
|
|
14437
|
+
|
|
15835
14438
|
const _context = {
|
|
15836
14439
|
initialTimestamp: this._context.initialTimestamp,
|
|
15837
14440
|
initialUrl: this._context.initialUrl,
|
|
15838
|
-
errorIds: Array.from(this._context.errorIds),
|
|
15839
|
-
traceIds: Array.from(this._context.traceIds),
|
|
14441
|
+
errorIds: Array.from(this._context.errorIds).filter(Boolean),
|
|
14442
|
+
traceIds: Array.from(this._context.traceIds).filter(Boolean),
|
|
15840
14443
|
urls: this._context.urls,
|
|
15841
14444
|
};
|
|
15842
14445
|
|
|
@@ -15875,9 +14478,6 @@ class ReplayContainer {
|
|
|
15875
14478
|
}
|
|
15876
14479
|
|
|
15877
14480
|
try {
|
|
15878
|
-
// This uses the data from the eventBuffer, so we need to call this before `finish()
|
|
15879
|
-
this._updateInitialTimestampFromEventBuffer();
|
|
15880
|
-
|
|
15881
14481
|
// Note this empties the event buffer regardless of outcome of sending replay
|
|
15882
14482
|
const recordingData = await this.eventBuffer.finish();
|
|
15883
14483
|
|
|
@@ -15893,6 +14493,7 @@ class ReplayContainer {
|
|
|
15893
14493
|
replayId,
|
|
15894
14494
|
recordingData,
|
|
15895
14495
|
segmentId,
|
|
14496
|
+
includeReplayStartTimestamp: segmentId === 0,
|
|
15896
14497
|
eventContext,
|
|
15897
14498
|
session: this.session,
|
|
15898
14499
|
options: this.getOptions(),
|
|
@@ -15904,7 +14505,7 @@ class ReplayContainer {
|
|
|
15904
14505
|
// This means we retried 3 times and all of them failed,
|
|
15905
14506
|
// or we ran into a problem we don't want to retry, like rate limiting.
|
|
15906
14507
|
// In this case, we want to completely stop the replay - otherwise, we may get inconsistent segments
|
|
15907
|
-
|
|
14508
|
+
this.stop('sendReplay');
|
|
15908
14509
|
|
|
15909
14510
|
const client = getCurrentHub().getClient();
|
|
15910
14511
|
|
|
@@ -15918,12 +14519,8 @@ class ReplayContainer {
|
|
|
15918
14519
|
* Flush recording data to Sentry. Creates a lock so that only a single flush
|
|
15919
14520
|
* can be active at a time. Do not call this directly.
|
|
15920
14521
|
*/
|
|
15921
|
-
|
|
15922
|
-
|
|
15923
|
-
}
|
|
15924
|
-
|
|
15925
|
-
= {}) => {
|
|
15926
|
-
if (!this._isEnabled && !force) {
|
|
14522
|
+
__init16() {this._flush = async () => {
|
|
14523
|
+
if (!this._isEnabled) {
|
|
15927
14524
|
// This can happen if e.g. the replay was stopped because of exceeding the retry limit
|
|
15928
14525
|
return;
|
|
15929
14526
|
}
|
|
@@ -15973,7 +14570,7 @@ class ReplayContainer {
|
|
|
15973
14570
|
}
|
|
15974
14571
|
|
|
15975
14572
|
/** Handler for rrweb.record.onMutation */
|
|
15976
|
-
|
|
14573
|
+
__init17() {this._onMutationHandler = (mutations) => {
|
|
15977
14574
|
const count = mutations.length;
|
|
15978
14575
|
|
|
15979
14576
|
const mutationLimit = this._options._experiments.mutationLimit || 0;
|
|
@@ -16107,8 +14704,6 @@ function isElectronNodeRenderer() {
|
|
|
16107
14704
|
const MEDIA_SELECTORS =
|
|
16108
14705
|
'img,image,svg,video,object,picture,embed,map,audio,link[rel="icon"],link[rel="apple-touch-icon"]';
|
|
16109
14706
|
|
|
16110
|
-
const DEFAULT_NETWORK_HEADERS = ['content-length', 'content-type', 'accept'];
|
|
16111
|
-
|
|
16112
14707
|
let _initialized = false;
|
|
16113
14708
|
|
|
16114
14709
|
/**
|
|
@@ -16149,11 +14744,6 @@ class Replay {
|
|
|
16149
14744
|
maskAllInputs = true,
|
|
16150
14745
|
blockAllMedia = true,
|
|
16151
14746
|
|
|
16152
|
-
networkDetailAllowUrls = [],
|
|
16153
|
-
networkCaptureBodies = true,
|
|
16154
|
-
networkRequestHeaders = [],
|
|
16155
|
-
networkResponseHeaders = [],
|
|
16156
|
-
|
|
16157
14747
|
mask = [],
|
|
16158
14748
|
unmask = [],
|
|
16159
14749
|
block = [],
|
|
@@ -16212,13 +14802,6 @@ class Replay {
|
|
|
16212
14802
|
errorSampleRate,
|
|
16213
14803
|
useCompression,
|
|
16214
14804
|
blockAllMedia,
|
|
16215
|
-
maskAllInputs,
|
|
16216
|
-
maskAllText,
|
|
16217
|
-
networkDetailAllowUrls,
|
|
16218
|
-
networkCaptureBodies,
|
|
16219
|
-
networkRequestHeaders: _getMergedNetworkHeaders(networkRequestHeaders),
|
|
16220
|
-
networkResponseHeaders: _getMergedNetworkHeaders(networkResponseHeaders),
|
|
16221
|
-
|
|
16222
14805
|
_experiments,
|
|
16223
14806
|
};
|
|
16224
14807
|
|
|
@@ -16272,7 +14855,14 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
|
|
|
16272
14855
|
}
|
|
16273
14856
|
|
|
16274
14857
|
/**
|
|
16275
|
-
*
|
|
14858
|
+
* We previously used to create a transaction in `setupOnce` and it would
|
|
14859
|
+
* potentially create a transaction before some native SDK integrations have run
|
|
14860
|
+
* and applied their own global event processor. An example is:
|
|
14861
|
+
* https://github.com/getsentry/sentry-javascript/blob/b47ceafbdac7f8b99093ce6023726ad4687edc48/packages/browser/src/integrations/useragent.ts
|
|
14862
|
+
*
|
|
14863
|
+
* So we call `replay.setup` in next event loop as a workaround to wait for other
|
|
14864
|
+
* global event processors to finish. This is no longer needed, but keeping it
|
|
14865
|
+
* here to avoid any future issues.
|
|
16276
14866
|
*/
|
|
16277
14867
|
setupOnce() {
|
|
16278
14868
|
if (!isBrowser()) {
|
|
@@ -16281,20 +14871,12 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
|
|
|
16281
14871
|
|
|
16282
14872
|
this._setup();
|
|
16283
14873
|
|
|
16284
|
-
//
|
|
16285
|
-
|
|
16286
|
-
// and applied their own global event processor. An example is:
|
|
16287
|
-
// https://github.com/getsentry/sentry-javascript/blob/b47ceafbdac7f8b99093ce6023726ad4687edc48/packages/browser/src/integrations/useragent.ts
|
|
16288
|
-
//
|
|
16289
|
-
// So we call `this._initialize()` in next event loop as a workaround to wait for other
|
|
16290
|
-
// global event processors to finish. This is no longer needed, but keeping it
|
|
16291
|
-
// here to avoid any future issues.
|
|
16292
|
-
setTimeout(() => this._initialize());
|
|
14874
|
+
// XXX: See method comments above
|
|
14875
|
+
setTimeout(() => this.start());
|
|
16293
14876
|
}
|
|
16294
14877
|
|
|
16295
14878
|
/**
|
|
16296
|
-
*
|
|
16297
|
-
* create a new session. Will throw an error if replay is already in progress.
|
|
14879
|
+
* Initializes the plugin.
|
|
16298
14880
|
*
|
|
16299
14881
|
* Creates or loads a session, attaches listeners to varying events (DOM,
|
|
16300
14882
|
* PerformanceObserver, Recording, Sentry SDK, etc)
|
|
@@ -16307,64 +14889,27 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
|
|
|
16307
14889
|
this._replay.start();
|
|
16308
14890
|
}
|
|
16309
14891
|
|
|
16310
|
-
/**
|
|
16311
|
-
* Start replay buffering. Buffers until `flush()` is called or, if
|
|
16312
|
-
* `replaysOnErrorSampleRate` > 0, until an error occurs.
|
|
16313
|
-
*/
|
|
16314
|
-
startBuffering() {
|
|
16315
|
-
if (!this._replay) {
|
|
16316
|
-
return;
|
|
16317
|
-
}
|
|
16318
|
-
|
|
16319
|
-
this._replay.startBuffering();
|
|
16320
|
-
}
|
|
16321
|
-
|
|
16322
14892
|
/**
|
|
16323
14893
|
* Currently, this needs to be manually called (e.g. for tests). Sentry SDK
|
|
16324
14894
|
* does not support a teardown
|
|
16325
14895
|
*/
|
|
16326
14896
|
stop() {
|
|
16327
14897
|
if (!this._replay) {
|
|
16328
|
-
return
|
|
16329
|
-
}
|
|
16330
|
-
|
|
16331
|
-
return this._replay.stop();
|
|
16332
|
-
}
|
|
16333
|
-
|
|
16334
|
-
/**
|
|
16335
|
-
* If not in "session" recording mode, flush event buffer which will create a new replay.
|
|
16336
|
-
* Unless `continueRecording` is false, the replay will continue to record and
|
|
16337
|
-
* behave as a "session"-based replay.
|
|
16338
|
-
*
|
|
16339
|
-
* Otherwise, queue up a flush.
|
|
16340
|
-
*/
|
|
16341
|
-
flush(options) {
|
|
16342
|
-
if (!this._replay || !this._replay.isEnabled()) {
|
|
16343
|
-
return Promise.resolve();
|
|
14898
|
+
return;
|
|
16344
14899
|
}
|
|
16345
14900
|
|
|
16346
|
-
|
|
14901
|
+
this._replay.stop();
|
|
16347
14902
|
}
|
|
16348
14903
|
|
|
16349
14904
|
/**
|
|
16350
|
-
*
|
|
14905
|
+
* Immediately send all pending events.
|
|
16351
14906
|
*/
|
|
16352
|
-
|
|
14907
|
+
flush() {
|
|
16353
14908
|
if (!this._replay || !this._replay.isEnabled()) {
|
|
16354
14909
|
return;
|
|
16355
14910
|
}
|
|
16356
14911
|
|
|
16357
|
-
return this._replay.
|
|
16358
|
-
}
|
|
16359
|
-
/**
|
|
16360
|
-
* Initializes replay.
|
|
16361
|
-
*/
|
|
16362
|
-
_initialize() {
|
|
16363
|
-
if (!this._replay) {
|
|
16364
|
-
return;
|
|
16365
|
-
}
|
|
16366
|
-
|
|
16367
|
-
this._replay.initializeSampling();
|
|
14912
|
+
return this._replay.flushImmediate();
|
|
16368
14913
|
}
|
|
16369
14914
|
|
|
16370
14915
|
/** Setup the integration. */
|
|
@@ -16415,10 +14960,6 @@ function loadReplayOptionsFromClient(initialOptions) {
|
|
|
16415
14960
|
return finalOptions;
|
|
16416
14961
|
}
|
|
16417
14962
|
|
|
16418
|
-
function _getMergedNetworkHeaders(headers) {
|
|
16419
|
-
return [...DEFAULT_NETWORK_HEADERS, ...headers.map(header => header.toLowerCase())];
|
|
16420
|
-
}
|
|
16421
|
-
|
|
16422
14963
|
/**
|
|
16423
14964
|
* Polyfill for the optional chain operator, `?.`, given previous conversion of the expression into an array of values,
|
|
16424
14965
|
* descriptors, and functions.
|
|
@@ -16856,9 +15397,6 @@ class Postgres {
|
|
|
16856
15397
|
const span = _optionalChain([parentSpan, 'optionalAccess', _6 => _6.startChild, 'call', _7 => _7({
|
|
16857
15398
|
description: typeof config === 'string' ? config : (config ).text,
|
|
16858
15399
|
op: 'db',
|
|
16859
|
-
data: {
|
|
16860
|
-
'db.system': 'postgresql',
|
|
16861
|
-
},
|
|
16862
15400
|
})]);
|
|
16863
15401
|
|
|
16864
15402
|
if (typeof callback === 'function') {
|
|
@@ -16935,9 +15473,6 @@ class Mysql {constructor() { Mysql.prototype.__init.call(this); }
|
|
|
16935
15473
|
const span = _optionalChain([parentSpan, 'optionalAccess', _4 => _4.startChild, 'call', _5 => _5({
|
|
16936
15474
|
description: typeof options === 'string' ? options : (options ).sql,
|
|
16937
15475
|
op: 'db',
|
|
16938
|
-
data: {
|
|
16939
|
-
'db.system': 'mysql',
|
|
16940
|
-
},
|
|
16941
15476
|
})]);
|
|
16942
15477
|
|
|
16943
15478
|
if (typeof callback === 'function') {
|
|
@@ -17159,7 +15694,6 @@ class Mongo {
|
|
|
17159
15694
|
collectionName: collection.collectionName,
|
|
17160
15695
|
dbName: collection.dbName,
|
|
17161
15696
|
namespace: collection.namespace,
|
|
17162
|
-
'db.system': 'mongodb',
|
|
17163
15697
|
};
|
|
17164
15698
|
const spanContext = {
|
|
17165
15699
|
op: 'db',
|
|
@@ -17246,15 +15780,31 @@ class Prisma {
|
|
|
17246
15780
|
}
|
|
17247
15781
|
|
|
17248
15782
|
this._client.$use((params, next) => {
|
|
15783
|
+
const scope = getCurrentHub().getScope();
|
|
15784
|
+
const parentSpan = _optionalChain([scope, 'optionalAccess', _2 => _2.getSpan, 'call', _3 => _3()]);
|
|
15785
|
+
|
|
17249
15786
|
const action = params.action;
|
|
17250
15787
|
const model = params.model;
|
|
17251
|
-
|
|
17252
|
-
|
|
17253
|
-
|
|
17254
|
-
|
|
15788
|
+
|
|
15789
|
+
const span = _optionalChain([parentSpan, 'optionalAccess', _4 => _4.startChild, 'call', _5 => _5({
|
|
15790
|
+
description: model ? `${model} ${action}` : action,
|
|
15791
|
+
op: 'db.sql.prisma',
|
|
15792
|
+
})]);
|
|
15793
|
+
|
|
15794
|
+
const rv = next(params);
|
|
15795
|
+
|
|
15796
|
+
if (isThenable(rv)) {
|
|
15797
|
+
return rv.then((res) => {
|
|
15798
|
+
_optionalChain([span, 'optionalAccess', _6 => _6.finish, 'call', _7 => _7()]);
|
|
15799
|
+
return res;
|
|
15800
|
+
});
|
|
15801
|
+
}
|
|
15802
|
+
|
|
15803
|
+
_optionalChain([span, 'optionalAccess', _8 => _8.finish, 'call', _9 => _9()]);
|
|
15804
|
+
return rv;
|
|
17255
15805
|
});
|
|
17256
15806
|
}
|
|
17257
|
-
}
|
|
15807
|
+
}Prisma.__initStatic();
|
|
17258
15808
|
|
|
17259
15809
|
/** Tracing integration for graphql package */
|
|
17260
15810
|
class GraphQL {constructor() { GraphQL.prototype.__init.call(this); }
|
|
@@ -25586,6 +24136,7 @@ var STATES$5;
|
|
|
25586
24136
|
STATES["RE_INIT_RECORDER__NEXT_QUESTION"] = "reInitRecorderNextQuestion";
|
|
25587
24137
|
STATES["UPLOADING"] = "uploading";
|
|
25588
24138
|
STATES["CONFIRM"] = "confirm";
|
|
24139
|
+
STATES["CONFIRM_WATING"] = "confirmWaiting";
|
|
25589
24140
|
STATES["FINISHED"] = "finished";
|
|
25590
24141
|
STATES["ERROR"] = "error";
|
|
25591
24142
|
})(STATES$5 || (STATES$5 = {}));
|
|
@@ -25639,6 +24190,7 @@ var ACTIONS$6;
|
|
|
25639
24190
|
ACTIONS["RESET_FAILED_RECORDING_ATTEMPTS"] = "resetFailedRecordingAttempts";
|
|
25640
24191
|
ACTIONS["CLEAR_VIDEO_ERROR"] = "clearVideoError";
|
|
25641
24192
|
ACTIONS["UPDATE_VIDEO_DIMENSIONS"] = "updateVideoDimensions";
|
|
24193
|
+
ACTIONS["UPDATE_UPLOADED_FALSE_COUNT"] = "updateUploadedFalseCount";
|
|
25642
24194
|
})(ACTIONS$6 || (ACTIONS$6 = {}));
|
|
25643
24195
|
var EVENTS$5;
|
|
25644
24196
|
(function (EVENTS) {
|
|
@@ -25694,6 +24246,7 @@ var GUARDS$3;
|
|
|
25694
24246
|
GUARDS["IS_RECORDER_READY"] = "isRecorderReady";
|
|
25695
24247
|
GUARDS["IS_ASSESSMENT_QUESTION"] = "isAssessmentQuestion";
|
|
25696
24248
|
GUARDS["IS_TIMES_UP"] = "isTimesUp";
|
|
24249
|
+
GUARDS["SHOULD_TRY_TO_CONFIRM"] = "shouldTryToConfirm";
|
|
25697
24250
|
})(GUARDS$3 || (GUARDS$3 = {}));
|
|
25698
24251
|
var TAGS;
|
|
25699
24252
|
(function (TAGS) {
|
|
@@ -25703,6 +24256,7 @@ var TAGS;
|
|
|
25703
24256
|
TAGS["DISPLAY_OUTER_VIEW"] = "displayOuterView";
|
|
25704
24257
|
TAGS["DISPLAY_QUESTION"] = "displayQuestion";
|
|
25705
24258
|
TAGS["DISPLAY_QUESTIONS_LIST"] = "displayQuestionsList";
|
|
24259
|
+
TAGS["DISPLAY_UPLOAD"] = "displayUpload";
|
|
25706
24260
|
TAGS["LOADING"] = "loading";
|
|
25707
24261
|
})(TAGS || (TAGS = {}));
|
|
25708
24262
|
|
|
@@ -30424,7 +28978,7 @@ const configGenerator = () => {
|
|
|
30424
28978
|
let release;
|
|
30425
28979
|
try {
|
|
30426
28980
|
environment !== null && environment !== void 0 ? environment : (environment = "staging");
|
|
30427
|
-
release !== null && release !== void 0 ? release : (release = "1.1.23");
|
|
28981
|
+
release !== null && release !== void 0 ? release : (release = "1.1.23-binary-001");
|
|
30428
28982
|
}
|
|
30429
28983
|
catch (_a) {
|
|
30430
28984
|
console.error('sentry configGenerator error');
|
|
@@ -30897,6 +29451,7 @@ const SECONDS_LEFT_HIGHLIGHT = 10;
|
|
|
30897
29451
|
const DEFAULT_ASSESSMENT_MAX_CHARS = 300;
|
|
30898
29452
|
const DEFAULT_ASSESSMENT_DURATION = 0;
|
|
30899
29453
|
const DEFAULT_VIDEO_DIMENSIONS = { width: 1280, height: 720 }; // Transcoder default dimensions (720p)
|
|
29454
|
+
const MAX_CONFIRM_ATTEMPTS = 5;
|
|
30900
29455
|
// Font
|
|
30901
29456
|
const FONT_URL = 'https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@400;600;700&display=swap';
|
|
30902
29457
|
var RETAKE_SPEED;
|
|
@@ -35057,8 +33612,8 @@ function memoizeOne(resultFn, isEqual) {
|
|
|
35057
33612
|
}
|
|
35058
33613
|
|
|
35059
33614
|
var memoizeOne_esm = /*#__PURE__*/Object.freeze({
|
|
35060
|
-
|
|
35061
|
-
|
|
33615
|
+
__proto__: null,
|
|
33616
|
+
'default': memoizeOne
|
|
35062
33617
|
});
|
|
35063
33618
|
|
|
35064
33619
|
var require$$2 = /*@__PURE__*/getAugmentedNamespace(memoizeOne_esm);
|
|
@@ -39018,6 +37573,11 @@ var EVENT_TYPES;
|
|
|
39018
37573
|
EVENT_TYPES["SOUND_RESTORED"] = "soundRestored";
|
|
39019
37574
|
EVENT_TYPES["TIMES_UP"] = "timesUp";
|
|
39020
37575
|
EVENT_TYPES["COMPLETED_INTERVIEW"] = "completedInterview";
|
|
37576
|
+
EVENT_TYPES["RECONNECTED"] = "reconnected";
|
|
37577
|
+
EVENT_TYPES["CONFIRM_UPLOADED_FAILED"] = "confirmUploadedFailed";
|
|
37578
|
+
EVENT_TYPES["FINISHED"] = "finished";
|
|
37579
|
+
EVENT_TYPES["ON_FINISH_SUCCEED"] = "onFinishSucceed";
|
|
37580
|
+
EVENT_TYPES["ON_FINISH_FAILED"] = "onFinishFailed";
|
|
39021
37581
|
})(EVENT_TYPES || (EVENT_TYPES = {}));
|
|
39022
37582
|
let event_id;
|
|
39023
37583
|
const updateEventId = (eventId) => { event_id = eventId; };
|
|
@@ -39567,31 +38127,6 @@ const Setup = ({ widgetMachine, sendToWidget, isPracticeDisabled, recordWithoutV
|
|
|
39567
38127
|
React__default["default"].createElement(C, { className: startButtonClassNames, color: "special", backgroundColor: "white", onClick: () => sendToWidget(EVENTS$5.QUESTION_MODE), disabled: !canStartInterview }, t(isResumed ? 'welcome.resumeInterview' : 'buttons.btn_start').toUpperCase()))));
|
|
39568
38128
|
};
|
|
39569
38129
|
|
|
39570
|
-
/*! *****************************************************************************
|
|
39571
|
-
Copyright (c) Microsoft Corporation.
|
|
39572
|
-
|
|
39573
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
39574
|
-
purpose with or without fee is hereby granted.
|
|
39575
|
-
|
|
39576
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
39577
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
39578
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
39579
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
39580
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
39581
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
39582
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
39583
|
-
***************************************************************************** */
|
|
39584
|
-
|
|
39585
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
39586
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
39587
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39588
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39589
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
39590
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
39591
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
39592
|
-
});
|
|
39593
|
-
}
|
|
39594
|
-
|
|
39595
38130
|
const uploadToS3 = (url, data, onProgress, timeout = 0) => s3AxiosInstance.put(url, data, {
|
|
39596
38131
|
headers: { 'Content-Type': 'video/webm' }, onUploadProgress: onProgress, timeout,
|
|
39597
38132
|
});
|
|
@@ -39662,8 +38197,8 @@ const OuterView = ({ widgetMachine, sendToWidget, recorderRef }) => {
|
|
|
39662
38197
|
const isQuestionDisplayed = widgetMachine.hasTag(TAGS.DISPLAY_QUESTION) || (isVideoQuestionState && !currentQuestionObj.thinkingTime);
|
|
39663
38198
|
const isPreviewState = widgetMachine.matches(STATES$5.PREVIEW);
|
|
39664
38199
|
const isUploadingState = widgetMachine.matches(STATES$5.UPLOADING);
|
|
39665
|
-
const isConfirmState = widgetMachine.matches(STATES$5.CONFIRM);
|
|
39666
38200
|
const isQuestionsListDisplayed = widgetMachine.hasTag(TAGS.DISPLAY_QUESTIONS_LIST);
|
|
38201
|
+
const isUploadDisplayed = widgetMachine.hasTag(TAGS.DISPLAY_UPLOAD);
|
|
39667
38202
|
const isRecording = recorderMachine.matches({ [STATES$6.RECORDING]: STATES$6.COLLECTING_BLOBS });
|
|
39668
38203
|
const isCountDown = recorderMachine.matches({ [STATES$6.RECORDING]: STATES$6.COUNT_DOWN });
|
|
39669
38204
|
const isPracticeMode = recordingType === TAKE_TYPES.PRACTICE;
|
|
@@ -39681,7 +38216,7 @@ const OuterView = ({ widgetMachine, sendToWidget, recorderRef }) => {
|
|
|
39681
38216
|
isSetupState && React__default["default"].createElement(Setup, { recordWithoutVideo: recordWithoutVideo, widgetMachine: widgetMachine, sendToWidget: sendToWidget, isPracticeDisabled: !!config.disablePractice }),
|
|
39682
38217
|
isQuestionsListDisplayed && React__default["default"].createElement(QuestionsList, { questions: questions, currentQuestion: currentQuestion, isPracticeMode: isPracticeMode, questionsStatus: questionsStatus }),
|
|
39683
38218
|
isQuestionDisplayed && React__default["default"].createElement(Question, { questionObj: currentQuestionObj }),
|
|
39684
|
-
|
|
38219
|
+
isUploadDisplayed && (React__default["default"].createElement(Upload, { isConnected: isConnected, totalFileSize: totalFileSize, totalUploadedFilesSize: totalUploadedFilesSize, totalUploadSpeed: totalUploadSpeed }))));
|
|
39685
38220
|
};
|
|
39686
38221
|
|
|
39687
38222
|
var actions = {};
|
|
@@ -43510,9 +42045,7 @@ var AsapAction = (function (_super) {
|
|
|
43510
42045
|
var actions = scheduler.actions;
|
|
43511
42046
|
if (id != null && ((_a = actions[actions.length - 1]) === null || _a === void 0 ? void 0 : _a.id) !== id) {
|
|
43512
42047
|
immediateProvider.clearImmediate(id);
|
|
43513
|
-
|
|
43514
|
-
scheduler._scheduled = undefined;
|
|
43515
|
-
}
|
|
42048
|
+
scheduler._scheduled = undefined;
|
|
43516
42049
|
}
|
|
43517
42050
|
return undefined;
|
|
43518
42051
|
};
|
|
@@ -44778,7 +43311,7 @@ const accUploaderMachine = createMachine({
|
|
|
44778
43311
|
actions: [ACTIONS$2.SENTRY],
|
|
44779
43312
|
},
|
|
44780
43313
|
{
|
|
44781
|
-
actions: [ACTIONS$2.
|
|
43314
|
+
actions: [ACTIONS$2.SENTRY],
|
|
44782
43315
|
target: `#uploader.${STATES$2.UPLOADED}`, // In case the video already uploaded
|
|
44783
43316
|
},
|
|
44784
43317
|
],
|
|
@@ -44795,7 +43328,6 @@ const accUploaderMachine = createMachine({
|
|
|
44795
43328
|
id: 'uploadToS3',
|
|
44796
43329
|
src: ({ signedUrl, file }) => (callback) => uploadToS3(signedUrl, file, callback),
|
|
44797
43330
|
onDone: {
|
|
44798
|
-
// actions: [ACTIONS.SET_UPLOADED],
|
|
44799
43331
|
target: `#uploader.${STATES$2.UPLOADED}`,
|
|
44800
43332
|
},
|
|
44801
43333
|
onError: {
|
|
@@ -45151,10 +43683,14 @@ const accWidgetMachine = createMachine({
|
|
|
45151
43683
|
failedRecordingMessage: VIDEO_CORRUPTED_STATES.NO_ERROR,
|
|
45152
43684
|
isResumed: false,
|
|
45153
43685
|
videoDimensions: DEFAULT_VIDEO_DIMENSIONS,
|
|
43686
|
+
confirmUploadedFalseCount: 0,
|
|
45154
43687
|
},
|
|
45155
43688
|
on: {
|
|
45156
43689
|
[EVENTS$1.CONNECTION_CHANGED]: {
|
|
45157
|
-
actions: [
|
|
43690
|
+
actions: [
|
|
43691
|
+
ACTIONS$6.SET_CONNECTION,
|
|
43692
|
+
{ type: ACTIONS$6.EMIT_TRACKING_EVENT, data: { eventType: EVENT_TYPES.RECONNECTED } },
|
|
43693
|
+
],
|
|
45158
43694
|
},
|
|
45159
43695
|
[EVENTS$5.UPLOADER_PROGRESS]: {
|
|
45160
43696
|
actions: [ACTIONS$6.UPDATE_TOTAL_UPLOADED_FILES_SIZE],
|
|
@@ -45681,7 +44217,7 @@ const accWidgetMachine = createMachine({
|
|
|
45681
44217
|
},
|
|
45682
44218
|
},
|
|
45683
44219
|
[STATES$5.UPLOADING]: {
|
|
45684
|
-
tags: [TAGS.DISPLAY_OUTER_VIEW],
|
|
44220
|
+
tags: [TAGS.DISPLAY_OUTER_VIEW, TAGS.DISPLAY_UPLOAD],
|
|
45685
44221
|
entry: [
|
|
45686
44222
|
{ type: ACTIONS$6.SESSION_EVENT, data: { event: 'widget_completed', type: 'date' } },
|
|
45687
44223
|
{ type: ACTIONS$6.CONSOLE_DEBUG, data: { message: DEBUG.UPLOADING_STATE } },
|
|
@@ -45695,30 +44231,57 @@ const accWidgetMachine = createMachine({
|
|
|
45695
44231
|
},
|
|
45696
44232
|
},
|
|
45697
44233
|
},
|
|
44234
|
+
[STATES$5.CONFIRM_WATING]: {
|
|
44235
|
+
tags: [TAGS.DISPLAY_OUTER_VIEW, TAGS.DISPLAY_UPLOAD],
|
|
44236
|
+
always: {
|
|
44237
|
+
target: STATES$5.CONFIRM,
|
|
44238
|
+
cond: GUARDS$3.IS_CONNECTED,
|
|
44239
|
+
},
|
|
44240
|
+
},
|
|
45698
44241
|
[STATES$5.CONFIRM]: {
|
|
45699
|
-
tags: [TAGS.DISPLAY_OUTER_VIEW],
|
|
44242
|
+
tags: [TAGS.DISPLAY_OUTER_VIEW, TAGS.DISPLAY_UPLOAD],
|
|
45700
44243
|
invoke: {
|
|
45701
44244
|
id: 'getVideo',
|
|
45702
44245
|
src: (context) => { var _a; return getVideo(((_a = context.widgetConfig.video) === null || _a === void 0 ? void 0 : _a.video_id) || ''); },
|
|
45703
|
-
onDone:
|
|
45704
|
-
|
|
45705
|
-
|
|
45706
|
-
|
|
44246
|
+
onDone: [
|
|
44247
|
+
{
|
|
44248
|
+
target: STATES$5.FINISHED,
|
|
44249
|
+
cond: (_, event) => !!event.data.data.data.video.uploaded,
|
|
44250
|
+
},
|
|
44251
|
+
{
|
|
44252
|
+
actions: [
|
|
44253
|
+
ACTIONS$6.UPDATE_UPLOADED_FALSE_COUNT,
|
|
44254
|
+
{ type: ACTIONS$6.SENTRY, data: { eventName: 'CONFIRM::UPLOADED_FALSE' } },
|
|
44255
|
+
],
|
|
44256
|
+
target: STATES$5.CONFIRM_WATING,
|
|
44257
|
+
cond: GUARDS$3.SHOULD_TRY_TO_CONFIRM,
|
|
44258
|
+
},
|
|
44259
|
+
{
|
|
44260
|
+
actions: [
|
|
44261
|
+
{ type: ACTIONS$6.SET_VIDEO_ERROR, data: { errorMessage: 'Error, Please contact support' } },
|
|
44262
|
+
{ type: ACTIONS$6.EMIT_TRACKING_EVENT, data: { eventType: EVENT_TYPES.CONFIRM_UPLOADED_FAILED } },
|
|
44263
|
+
],
|
|
44264
|
+
target: STATES$5.ERROR,
|
|
44265
|
+
},
|
|
44266
|
+
],
|
|
45707
44267
|
onError: [
|
|
45708
44268
|
{
|
|
45709
|
-
actions: [() => console.error('UPDATE_VIDEO_UPLADED_ERROR:'), console.error, ACTIONS$6.SENTRY],
|
|
44269
|
+
actions: [() => console.error('UPDATE_VIDEO_UPLADED_ERROR:'), console.error, { type: ACTIONS$6.SENTRY, data: { eventName: 'CONFIRM::ERROR__NOT_FOUND' } }],
|
|
45710
44270
|
target: STATES$5.FINISHED,
|
|
45711
44271
|
cond: (_, event) => event.data.response.status === STATUS_CODES.NOT_FOUND,
|
|
45712
44272
|
},
|
|
45713
44273
|
{
|
|
45714
|
-
actions: [ACTIONS$6.SENTRY],
|
|
45715
|
-
target: STATES$5.
|
|
44274
|
+
actions: [() => console.error('UPDATE_VIDEO_UPLADED_ERROR:'), console.error, { type: ACTIONS$6.SENTRY, data: { eventName: 'CONFIRM::ERROR' } }],
|
|
44275
|
+
target: STATES$5.CONFIRM_WATING,
|
|
45716
44276
|
},
|
|
45717
44277
|
],
|
|
45718
44278
|
},
|
|
45719
44279
|
},
|
|
45720
44280
|
[STATES$5.FINISHED]: {
|
|
45721
|
-
entry: [
|
|
44281
|
+
entry: [
|
|
44282
|
+
{ type: ACTIONS$6.CONSOLE_DEBUG, data: { message: DEBUG.INTERVIEW_SUBMITTED } },
|
|
44283
|
+
{ type: ACTIONS$6.EMIT_TRACKING_EVENT, data: { eventType: EVENT_TYPES.FINISHED } },
|
|
44284
|
+
],
|
|
45722
44285
|
type: 'final',
|
|
45723
44286
|
},
|
|
45724
44287
|
[STATES$5.ERROR]: {
|
|
@@ -45914,9 +44477,12 @@ const accWidgetMachine = createMachine({
|
|
|
45914
44477
|
widgetConfig: Object.assign(Object.assign({}, widgetConfig), { video: Object.assign(Object.assign({}, widgetConfig.video), { videos: (_b = (_a = widgetConfig.video) === null || _a === void 0 ? void 0 : _a.videos) === null || _b === void 0 ? void 0 : _b.map((video, idx) => ((idx !== questionNumber - 1) ? video : videoFile)) }) }),
|
|
45915
44478
|
});
|
|
45916
44479
|
}),
|
|
45917
|
-
[ACTIONS$6.SET_VIDEO_ERROR]: assign$2((_, event) =>
|
|
45918
|
-
|
|
45919
|
-
|
|
44480
|
+
[ACTIONS$6.SET_VIDEO_ERROR]: assign$2((_, event, meta) => {
|
|
44481
|
+
var _a, _b, _c, _d;
|
|
44482
|
+
return ({
|
|
44483
|
+
error: ((_b = (_a = event.data) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.data) || { errorMessage: ((_c = event.data) === null || _c === void 0 ? void 0 : _c.message) || ((_d = meta.action.data) === null || _d === void 0 ? void 0 : _d.errorMessage) },
|
|
44484
|
+
});
|
|
44485
|
+
}),
|
|
45920
44486
|
[ACTIONS$6.REVOKE_MEMORY]: send$2((_, event) => ({ type: EVENTS$4.REMOVE_TAKES, data: { questionToRemove: event.data.questionNumber } }), { to: ({ storageRef }) => storageRef }),
|
|
45921
44487
|
[ACTIONS$6.UPDATE_VIDEO_OBJECT]: assign$2(({ widgetConfig, recordingType }) => {
|
|
45922
44488
|
var _a, _b;
|
|
@@ -45950,6 +44516,9 @@ const accWidgetMachine = createMachine({
|
|
|
45950
44516
|
height: event.data.height,
|
|
45951
44517
|
},
|
|
45952
44518
|
})),
|
|
44519
|
+
[ACTIONS$6.UPDATE_UPLOADED_FALSE_COUNT]: assign$2(({ confirmUploadedFalseCount }) => ({
|
|
44520
|
+
confirmUploadedFalseCount: confirmUploadedFalseCount + 1,
|
|
44521
|
+
})),
|
|
45953
44522
|
},
|
|
45954
44523
|
services: {
|
|
45955
44524
|
[SERVICES$1.UPDATE_VIDEO_OBJECT_CALL]: ({ widgetConfig: { video }, recordingType, speedTestResult }, event, meta) => (callback, onReceive) => {
|
|
@@ -45993,6 +44562,7 @@ const accWidgetMachine = createMachine({
|
|
|
45993
44562
|
[GUARDS$3.IS_RECORDER_READY]: ({ recorderRef }) => (recorderRef === null || recorderRef === void 0 ? void 0 : recorderRef.getSnapshot().value) === STATES$6.IDLE,
|
|
45994
44563
|
[GUARDS$3.IS_ASSESSMENT_QUESTION]: ({ questions, currentQuestion }) => !!questions[currentQuestion - 1].answerType && questions[currentQuestion - 1].answerType !== ANSWER_TYPES.VIDEO,
|
|
45995
44564
|
[GUARDS$3.IS_TIMES_UP]: (_, event) => !!event.data.isTimesUp,
|
|
44565
|
+
[GUARDS$3.SHOULD_TRY_TO_CONFIRM]: ({ confirmUploadedFalseCount }) => confirmUploadedFalseCount <= MAX_CONFIRM_ATTEMPTS,
|
|
45996
44566
|
},
|
|
45997
44567
|
});
|
|
45998
44568
|
|
|
@@ -48515,10 +47085,25 @@ const Main = ({ widgetConfig, setShouldShowWaterMark, myinterviewRef, isWidgetMi
|
|
|
48515
47085
|
React.useEffect(() => {
|
|
48516
47086
|
setShouldShowWaterMark(!!(company === null || company === void 0 ? void 0 : company.shouldShowWaterMark));
|
|
48517
47087
|
}, [company === null || company === void 0 ? void 0 : company.shouldShowWaterMark]);
|
|
47088
|
+
const _onFinish = () => __awaiter(void 0, void 0, void 0, function* () { var _a, _b; return (_b = (_a = widgetConfig.config).onFinish) === null || _b === void 0 ? void 0 : _b.call(_a, { redirectUrl: candidate.redirectUrl, video_id: (video === null || video === void 0 ? void 0 : video.video_id) || '' }); });
|
|
48518
47089
|
React.useEffect(() => {
|
|
48519
|
-
var _a, _b;
|
|
48520
47090
|
if (machine.done) {
|
|
48521
|
-
|
|
47091
|
+
if (widgetConfig.config.onFinish) {
|
|
47092
|
+
_onFinish().then(() => {
|
|
47093
|
+
emitTrackEvent({ eventType: EVENT_TYPES.ON_FINISH_SUCCEED });
|
|
47094
|
+
}).catch((err) => {
|
|
47095
|
+
var _a;
|
|
47096
|
+
let errorMessage = '';
|
|
47097
|
+
try {
|
|
47098
|
+
errorMessage = (err === null || err === void 0 ? void 0 : err.message) || (err === null || err === void 0 ? void 0 : err.msg) || ((_a = err === null || err === void 0 ? void 0 : err.data) === null || _a === void 0 ? void 0 : _a.message);
|
|
47099
|
+
}
|
|
47100
|
+
catch (_b) {
|
|
47101
|
+
//
|
|
47102
|
+
}
|
|
47103
|
+
emitTrackEvent({ eventType: EVENT_TYPES.ON_FINISH_FAILED, extraData: { errorMessage } });
|
|
47104
|
+
throw err;
|
|
47105
|
+
});
|
|
47106
|
+
}
|
|
48522
47107
|
}
|
|
48523
47108
|
}, [machine.done]);
|
|
48524
47109
|
React.useEffect(() => {
|
|
@@ -48534,11 +47119,16 @@ const Main = ({ widgetConfig, setShouldShowWaterMark, myinterviewRef, isWidgetMi
|
|
|
48534
47119
|
});
|
|
48535
47120
|
}
|
|
48536
47121
|
}, [candidate, job === null || job === void 0 ? void 0 : job.language]);
|
|
47122
|
+
const setBackgroundOpacity = () => {
|
|
47123
|
+
var _a;
|
|
47124
|
+
(_a = myinterviewRef === null || myinterviewRef === void 0 ? void 0 : myinterviewRef.current) === null || _a === void 0 ? void 0 : _a.style.setProperty('--myinterview-background-opacity', isLoading || isErrorState ? '0' : '1');
|
|
47125
|
+
};
|
|
48537
47126
|
React.useEffect(() => {
|
|
48538
47127
|
var _a, _b;
|
|
48539
47128
|
if (isErrorState && (error === null || error === void 0 ? void 0 : error.statusCode) === 400) {
|
|
48540
47129
|
(_b = (_a = widgetConfig.config).onError) === null || _b === void 0 ? void 0 : _b.call(_a, { messageType: 'applied' });
|
|
48541
47130
|
}
|
|
47131
|
+
setBackgroundOpacity();
|
|
48542
47132
|
}, [isErrorState]);
|
|
48543
47133
|
const isResumed = React.useMemo(() => { var _a, _b; return !!((_b = (_a = widgetConfig.video) === null || _a === void 0 ? void 0 : _a.videos) === null || _b === void 0 ? void 0 : _b.some((v) => v.uploaded)); }, [widgetConfig.video]);
|
|
48544
47134
|
const handleScroll = (e) => {
|
|
@@ -48548,8 +47138,7 @@ const Main = ({ widgetConfig, setShouldShowWaterMark, myinterviewRef, isWidgetMi
|
|
|
48548
47138
|
(_b = viewsRef === null || viewsRef === void 0 ? void 0 : viewsRef.current) === null || _b === void 0 ? void 0 : _b.style.setProperty('--myinterview-widget-practice-opacity', scrollTop > 10 ? '0' : '1');
|
|
48549
47139
|
};
|
|
48550
47140
|
React.useEffect(() => {
|
|
48551
|
-
|
|
48552
|
-
(_a = myinterviewRef === null || myinterviewRef === void 0 ? void 0 : myinterviewRef.current) === null || _a === void 0 ? void 0 : _a.style.setProperty('--myinterview-background-opacity', isLoading || isErrorState ? '0' : '1');
|
|
47141
|
+
setBackgroundOpacity();
|
|
48553
47142
|
}, [isLoading]);
|
|
48554
47143
|
const onRetry = () => {
|
|
48555
47144
|
send(EVENTS$5.RETRY);
|
|
@@ -48747,15 +47336,15 @@ const Widget = ({ candidate, job, video, config, disabled = false, buttonText =
|
|
|
48747
47336
|
revertBodyStyling();
|
|
48748
47337
|
setIsWidgetOpen(false);
|
|
48749
47338
|
};
|
|
48750
|
-
const onInterviewCompleted = (data) => {
|
|
47339
|
+
const onInterviewCompleted = (data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
48751
47340
|
var _a;
|
|
48752
|
-
(_a = config.onFinish) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
|
48753
47341
|
onCloseWidget();
|
|
48754
|
-
|
|
47342
|
+
yield ((_a = config.onFinish) === null || _a === void 0 ? void 0 : _a.call(config, data));
|
|
47343
|
+
});
|
|
48755
47344
|
const onError = (data) => {
|
|
48756
47345
|
var _a;
|
|
48757
|
-
(_a = config.onError) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
|
48758
47346
|
onCloseWidget();
|
|
47347
|
+
(_a = config.onError) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
|
48759
47348
|
};
|
|
48760
47349
|
const openWidget = () => {
|
|
48761
47350
|
var _a;
|