@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/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
- 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]; }
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
- function hasProp(obj, prop) {
1297
- return !!obj && typeof obj === 'object' && !!(obj )[prop];
1298
- }
1299
-
1300
- function getUrlFromResource(resource) {
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
- if (resource.toString) {
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
- * Parses the fetch arguments to find the used Http method and the url of the request
1322
- */
1323
- function parseFetchArgs(fetchArgs) {
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
- if (fetchArgs.length === 2) {
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[SENTRY_XHR_DATA_KEY] = {
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[SENTRY_XHR_DATA_KEY];
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
- const sentryXhrData = this[SENTRY_XHR_DATA_KEY];
1429
- if (sentryXhrData && args[0] !== undefined) {
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 && !_oldOnErrorHandler.__SENTRY_LOADER__) {
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 && !_oldOnUnhandledRejectionHandler.__SENTRY_LOADER__) {
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 = 100, maxProperties = +Infinity) {
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
- // We can set `__sentry_override_normalization_depth__` on an object to ensure that from there
2125
- // We keep a certain amount of depth.
2126
- // This should be used sparingly, e.g. we use it for the redux integration to ensure we get a certain amount of state.
2127
- const remainingDepth =
2128
- typeof (value )['__sentry_override_normalization_depth__'] === 'number'
2129
- ? ((value )['__sentry_override_normalization_depth__'] )
2130
- : depth;
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 (remainingDepth === 0) {
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, remainingDepth - 1, maxProperties, memo);
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, remainingDepth - 1, maxProperties, memo);
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
- const objName = getConstructorName(value);
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
- ...(dynamicSamplingContext && {
3021
- trace: dropUndefinedKeys({ ...dynamicSamplingContext }),
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 transaction = this._span.transaction;
3728
- if (transaction) {
3729
- event.sdkProcessingMetadata = {
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
- const result = this._callExtensionMethod('startTransaction', context, customSamplingContext);
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 && client && client.captureSession) {
4235
- client.captureSession(session);
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
- let parsedStack;
4909
- const cachedParsedStack = debugIdStackFramesCache.get(debugIdStackTrace);
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.52.1';
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
- // intrinsics (like Function.prototype) might be immutable in some environments
5847
- // e.g. Node with --frozen-intrinsics, XS (an embedded JavaScript engine) or SES (a JavaScript proposal)
5848
- try {
5849
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5850
- Function.prototype.toString = function ( ...args) {
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[values.length - 1]) || {};
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
- __proto__: null,
6057
- FunctionToString: FunctionToString,
6058
- InboundFilters: InboundFilters
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 || !sentryXhrData) {
6545
+ if (!startTimestamp || !endTimestamp || !handlerData.xhr.__sentry_xhr__) {
6669
6546
  return;
6670
6547
  }
6671
6548
 
6672
- const { method, url, status_code, body } = sentryXhrData;
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 (?:(.+?\)(?: \[.+\])?|.*?) ?\((?:address at )?)?(?:async )?((?:<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
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*(.*?)(?:\((.*?)\))?(?:^|@)?((?:[-a-z]+)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
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 = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:[-a-z]+):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
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
- __proto__: null,
8283
- GlobalHandlers: GlobalHandlers,
8284
- TryCatch: TryCatch,
8285
- Breadcrumbs: Breadcrumbs,
8286
- LinkedErrors: LinkedErrors,
8287
- HttpContext: HttpContext,
8288
- Dedupe: Dedupe
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 after which recording is paused.
8302
- const SESSION_IDLE_PAUSE_DURATION = 300000; // 5 minutes in ms
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 in ms
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 BUFFER_CHECKOUT_TIME = 60000;
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 truncated. */
8323
- const NETWORK_BODY_MAX_SIZE = 150000;
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('data-rr-is-password')) {
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 ? validateStringifiedCssRule(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 type = getInputType(el);
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$1;
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$1 || (EventType$1 = {}));
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('data-rr-is-password', 'true');
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
- const el = target;
10305
- const type = getInputType(el);
10306
- if (el.classList.contains(ignoreClass) ||
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 = getInputValue(el, tagName, type);
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: el,
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$1.FullSnapshot &&
11264
- !(e.type === EventType$1.IncrementalSnapshot &&
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$1.FullSnapshot) {
11063
+ if (e.type === EventType.FullSnapshot) {
11270
11064
  lastFullSnapshotEvent = e;
11271
11065
  incrementalSnapshotCount = 0;
11272
11066
  }
11273
- else if (e.type === EventType$1.IncrementalSnapshot) {
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$1.IncrementalSnapshot,
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$1.IncrementalSnapshot,
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$1.IncrementalSnapshot,
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$1.Meta,
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$1.FullSnapshot,
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$1.DomContentLoaded,
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$1.IncrementalSnapshot,
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$1.IncrementalSnapshot,
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$1.IncrementalSnapshot,
11227
+ type: EventType.IncrementalSnapshot,
11434
11228
  data: Object.assign({ source: IncrementalSource.ViewportResize }, d),
11435
11229
  })),
11436
11230
  inputCb: (v) => wrappedEmit(wrapEvent({
11437
- type: EventType$1.IncrementalSnapshot,
11231
+ type: EventType.IncrementalSnapshot,
11438
11232
  data: Object.assign({ source: IncrementalSource.Input }, v),
11439
11233
  })),
11440
11234
  mediaInteractionCb: (p) => wrappedEmit(wrapEvent({
11441
- type: EventType$1.IncrementalSnapshot,
11235
+ type: EventType.IncrementalSnapshot,
11442
11236
  data: Object.assign({ source: IncrementalSource.MediaInteraction }, p),
11443
11237
  })),
11444
11238
  styleSheetRuleCb: (r) => wrappedEmit(wrapEvent({
11445
- type: EventType$1.IncrementalSnapshot,
11239
+ type: EventType.IncrementalSnapshot,
11446
11240
  data: Object.assign({ source: IncrementalSource.StyleSheetRule }, r),
11447
11241
  })),
11448
11242
  styleDeclarationCb: (r) => wrappedEmit(wrapEvent({
11449
- type: EventType$1.IncrementalSnapshot,
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$1.IncrementalSnapshot,
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$1.Plugin,
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$1.Load,
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$1.Custom,
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._earliestTimestamp = null;
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
- const timestamp = timestampToMs(event.timestamp);
12361
- if (!this._earliestTimestamp || timestamp < this._earliestTimestamp) {
12362
- this._earliestTimestamp = timestamp;
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._earliestTimestamp = null;
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 `sessionIdleExpire` ms)
12584
- isExpired(session.lastActivity, timeouts.sessionIdleExpire, targetTime)
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, allowBuffering) {
12645
- return isSampled(sessionSampleRate) ? 'session' : allowBuffering ? 'buffer' : false;
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, allowBuffering, stickySession = false }) {
12654
- const sampled = getSessionSampleType(sessionSampleRate, allowBuffering);
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
- allowBuffering,
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 (!session.shouldRefresh) {
12716
- // In this case, stop
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
- allowBuffering,
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. This is ok to do even if not
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
- // If error event is tagged with replay id it means it was sampled (when in buffer mode)
12097
+ // Trigger error recording
12794
12098
  // Need to be very careful that this does not cause an infinite loop
12795
- if (replay.recordingMode === 'buffer' && event.tags && event.tags.replayId) {
12796
- setTimeout(() => {
12797
- // Capture current event buffer as new replay
12798
- void replay.sendBufferedReplayOrFlush();
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
- // When in buffer mode, we decide to sample here.
12897
- // Later, in `handleAfterSendEvent`, if the replayId is set, we know that we sampled
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$1.Custom,
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
- const sentryXhrData = xhr[SENTRY_XHR_DATA_KEY];
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 } = sentryXhrData;
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
- /** Build the request or response part of a replay network breadcrumb that was skipped. */
13625
- function buildSkippedNetworkRequestOrResponse(bodySize) {
13626
- return {
13627
- headers: {},
13628
- size: bodySize,
13629
- _meta: {
13630
- warnings: ['URL_SKIPPED'],
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
- const { body: normalizedBody, warnings } = normalizeNetworkBody(body);
13664
- info.body = normalizedBody;
13665
- if (warnings.length > 0) {
12715
+ if (bodySize < NETWORK_BODY_MAX_SIZE) {
12716
+ info.body = body;
12717
+ } else {
13666
12718
  info._meta = {
13667
- warnings,
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 = 0,
12787
+ status_code: statusCode,
13825
12788
  request_body_size: requestBodySize,
13826
12789
  response_body_size: responseBodySize,
13827
12790
  } = breadcrumb.data;
13828
12791
 
13829
- const captureDetails = urlMatches(url, options.networkDetailAllowUrls);
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
- { networkCaptureBodies, networkRequestHeaders },
12807
+ { captureBodies },
13849
12808
  input,
13850
12809
  requestBodySize,
13851
12810
  ) {
13852
- const headers = getRequestHeaders(input, networkRequestHeaders);
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 bodyStr = getBodyString(requestBody);
13861
- return buildNetworkRequestOrResponse(headers, requestBodySize, bodyStr);
12817
+ const body = getNetworkBody(getBodyString(requestBody));
12818
+ return buildNetworkRequestOrResponse(requestBodySize, body);
13862
12819
  }
13863
12820
 
13864
12821
  async function _getResponseInfo(
13865
- captureDetails,
13866
- {
13867
- networkCaptureBodies,
13868
- textEncoder,
13869
- networkResponseHeaders,
13870
- }
13871
-
13872
- ,
12822
+ { captureBodies, textEncoder },
13873
12823
  response,
13874
12824
  responseBodySize,
13875
12825
  ) {
13876
- if (!captureDetails && responseBodySize !== undefined) {
13877
- return buildSkippedNetworkRequestOrResponse(responseBodySize);
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 (!captureDetails) {
13898
- return buildSkippedNetworkRequestOrResponse(size);
12841
+ if (captureBodies) {
12842
+ return buildNetworkRequestOrResponse(size, body);
13899
12843
  }
13900
12844
 
13901
- if (networkCaptureBodies) {
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(headers, responseBodySize, undefined);
12848
+ return buildNetworkRequestOrResponse(responseBodySize, undefined);
13909
12849
  }
13910
12850
  }
13911
12851
 
13912
- async function _parseFetchBody(response) {
12852
+ async function _parseFetchBody(
12853
+ response,
12854
+ ) {
12855
+ let bodyText;
12856
+
13913
12857
  try {
13914
- return await response.text();
12858
+ bodyText = await response.text();
13915
12859
  } catch (e2) {
13916
- return undefined;
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, xhr } = hint;
12932
+ const { startTimestamp, endTimestamp, input } = hint;
14030
12933
 
14031
12934
  const {
14032
12935
  url,
14033
12936
  method,
14034
- status_code: statusCode = 0,
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.networkCaptureBodies ? getBodyString(input) : undefined,
12948
+ options.captureBodies ? getNetworkBody(getBodyString(input)) : undefined,
14067
12949
  );
14068
12950
  const response = buildNetworkRequestOrResponse(
14069
- networkResponseHeaders,
14070
12951
  responseBodySize,
14071
- options.networkCaptureBodies ? hint.xhr.responseText : undefined,
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
- networkDetailAllowUrls,
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
- // We do not want to set the DSC when in buffer mode, as that means the replay has not been sent (yet)
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 === 'buffer' && isCheckout) {
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
- // When in buffer mode, make sure we adjust the session started date to the current earliest event of the buffer
14671
- // this should usually be the timestamp of the checkout event, but to be safe...
14672
- if (replay.recordingMode === 'buffer' && replay.session && replay.eventBuffer) {
14673
- const earliestEvent = replay.eventBuffer.getEarliestTimestamp();
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 three modes:
15048
- * - session: Record the whole session, sending it continuously
15049
- * - buffer: Always keep the last 60s of recording, requires:
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
- sessionIdlePause: SESSION_IDLE_PAUSE_DURATION,
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);ReplayContainer.prototype.__init18.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 based on sampling configuration. Should not be
15145
- * called outside of constructor.
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
- initializeSampling() {
15148
- const { errorSampleRate, sessionSampleRate } = this._options;
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 (!isSessionSampled) {
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
- // This should not happen, something wrong has occurred
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 && this.session.sampled !== 'session') {
15173
- // If not sampled as session-based, then recording mode will be `buffer`
15174
- // Note that we don't explicitly check if `sampled === 'buffer'` because we
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
- if (this._isEnabled && this.recordingMode === 'buffer') {
15196
- throw new Error('Replay buffering is in progress, call `flush()` to save the replay');
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
- const previousSessionId = this.session && this.session.id;
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
- const { session } = getSession({
15202
- timeouts: this.timeouts,
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
- session.previousSessionId = previousSessionId;
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
- session.previousSessionId = previousSessionId;
15236
- this.session = session;
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.recordingMode = 'buffer';
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 === 'buffer' && { checkoutEveryNms: BUFFER_CHECKOUT_TIME }),
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 true;
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
- async stop(reason) {
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 == 'buffer'`)
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 === 'buffer') {
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
- // SESSION_IDLE_PAUSE_DURATION. Otherwise non-user activity can trigger a new
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.sessionIdlePause) &&
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
- allowBuffering: this._options.errorSampleRate > 0,
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
- void this.stop('session unsampled');
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 SESSION_IDLE_PAUSE_DURATION
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$1.Custom,
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 === 'buffer') {
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
- void this.stop('sendReplay');
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
- __init17() {this._flush = async ({
15922
- force = false,
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
- __init18() {this._onMutationHandler = (mutations) => {
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
- * Setup and initialize replay container
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
- // Once upon a time, we tried to create a transaction in `setupOnce` and it would
16285
- // potentially create a transaction before some native SDK integrations have run
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
- * Start a replay regardless of sampling rate. Calling this will always
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 Promise.resolve();
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
- return this._replay.sendBufferedReplayOrFlush(options);
14901
+ this._replay.stop();
16347
14902
  }
16348
14903
 
16349
14904
  /**
16350
- * Get the current session ID.
14905
+ * Immediately send all pending events.
16351
14906
  */
16352
- getReplayId() {
14907
+ flush() {
16353
14908
  if (!this._replay || !this._replay.isEnabled()) {
16354
14909
  return;
16355
14910
  }
16356
14911
 
16357
- return this._replay.getSessionId();
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
- return trace(
17252
- { name: model ? `${model} ${action}` : action, op: 'db.sql.prisma', data: { 'db.system': 'prisma' } },
17253
- () => next(params),
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
- } Prisma.__initStatic();
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
- __proto__: null,
35061
- 'default': memoizeOne
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
- (isUploadingState || isConfirmState) && (React__default["default"].createElement(Upload, { isConnected: isConnected, totalFileSize: totalFileSize, totalUploadedFilesSize: totalUploadedFilesSize, totalUploadSpeed: totalUploadSpeed }))));
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
- if (scheduler._scheduled === id) {
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.SET_UPLOADED, ACTIONS$2.SENTRY],
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: [ACTIONS$6.SET_CONNECTION],
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
- target: STATES$5.FINISHED,
45705
- cond: (_, event) => !!event.data.data.data.video.uploaded,
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.CONFIRM,
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: [{ type: ACTIONS$6.CONSOLE_DEBUG, data: { message: DEBUG.INTERVIEW_SUBMITTED } }],
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
- error: event.data.response.data || { errorMessage: event.data.message },
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
- (_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) || '' });
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
- var _a;
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;