@myinterview/widget-react 1.1.23-binary-check-one → 1.1.23-binary-002
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/CountDown.d.ts +2 -2
- package/dist/cjs/components/Counter.d.ts +2 -2
- package/dist/cjs/components/DeviceSelector.d.ts +1 -1
- package/dist/cjs/index.js +886 -2362
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/interfaces/widgetInterface.d.ts +7 -2
- package/dist/cjs/services/event.service.d.ts +6 -1
- package/dist/cjs/utils/constants.utils.d.ts +1 -0
- package/dist/esm/components/CountDown.d.ts +2 -2
- package/dist/esm/components/Counter.d.ts +2 -2
- package/dist/esm/components/DeviceSelector.d.ts +1 -1
- package/dist/esm/index.js +872 -2348
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/interfaces/widgetInterface.d.ts +7 -2
- package/dist/esm/services/event.service.d.ts +6 -1
- package/dist/esm/utils/constants.utils.d.ts +1 -0
- package/package.json +64 -64
package/dist/esm/index.js
CHANGED
|
@@ -2,6 +2,31 @@ import * as React from 'react';
|
|
|
2
2
|
import React__default, { createContext, forwardRef, useRef, useEffect, useState, useLayoutEffect, useImperativeHandle, useDebugValue, useContext, createElement, useCallback, useMemo } from 'react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
|
|
5
|
+
/*! *****************************************************************************
|
|
6
|
+
Copyright (c) Microsoft Corporation.
|
|
7
|
+
|
|
8
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
9
|
+
purpose with or without fee is hereby granted.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
12
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
13
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
14
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
15
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
16
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
17
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
18
|
+
***************************************************************************** */
|
|
19
|
+
|
|
20
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
21
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
22
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
23
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
24
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
25
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
26
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
5
30
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
6
31
|
const objectToString = Object.prototype.toString;
|
|
7
32
|
|
|
@@ -370,83 +395,19 @@ function getLocationHref() {
|
|
|
370
395
|
}
|
|
371
396
|
}
|
|
372
397
|
|
|
373
|
-
/**
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
const CONSOLE_LEVELS = ['debug', 'info', 'warn', 'error', 'log', 'assert', 'trace'] ;
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* Temporarily disable sentry console instrumentations.
|
|
380
|
-
*
|
|
381
|
-
* @param callback The function to run against the original `console` messages
|
|
382
|
-
* @returns The results of the callback
|
|
383
|
-
*/
|
|
384
|
-
function consoleSandbox(callback) {
|
|
385
|
-
if (!('console' in GLOBAL_OBJ)) {
|
|
386
|
-
return callback();
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
const originalConsole = GLOBAL_OBJ.console ;
|
|
390
|
-
const wrappedLevels = {};
|
|
391
|
-
|
|
392
|
-
// Restore all wrapped console methods
|
|
393
|
-
CONSOLE_LEVELS.forEach(level => {
|
|
394
|
-
// TODO(v7): Remove this check as it's only needed for Node 6
|
|
395
|
-
const originalWrappedFunc =
|
|
396
|
-
originalConsole[level] && (originalConsole[level] ).__sentry_original__;
|
|
397
|
-
if (level in originalConsole && originalWrappedFunc) {
|
|
398
|
-
wrappedLevels[level] = originalConsole[level] ;
|
|
399
|
-
originalConsole[level] = originalWrappedFunc ;
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
try {
|
|
404
|
-
return callback();
|
|
405
|
-
} finally {
|
|
406
|
-
// Revert restoration to wrapped state
|
|
407
|
-
Object.keys(wrappedLevels).forEach(level => {
|
|
408
|
-
originalConsole[level] = wrappedLevels[level ];
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
function makeLogger() {
|
|
414
|
-
let enabled = false;
|
|
415
|
-
const logger = {
|
|
416
|
-
enable: () => {
|
|
417
|
-
enabled = true;
|
|
418
|
-
},
|
|
419
|
-
disable: () => {
|
|
420
|
-
enabled = false;
|
|
421
|
-
},
|
|
422
|
-
};
|
|
398
|
+
/** An error emitted by Sentry SDKs and related utilities. */
|
|
399
|
+
class SentryError extends Error {
|
|
400
|
+
/** Display name of this error instance. */
|
|
423
401
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
}
|
|
433
|
-
};
|
|
434
|
-
});
|
|
435
|
-
} else {
|
|
436
|
-
CONSOLE_LEVELS.forEach(name => {
|
|
437
|
-
logger[name] = () => undefined;
|
|
438
|
-
});
|
|
402
|
+
constructor( message, logLevel = 'warn') {
|
|
403
|
+
super(message);this.message = message;
|
|
404
|
+
this.name = new.target.prototype.constructor.name;
|
|
405
|
+
// This sets the prototype to be `Error`, not `SentryError`. It's unclear why we do this, but commenting this line
|
|
406
|
+
// out causes various (seemingly totally unrelated) playwright tests consistently time out. FYI, this makes
|
|
407
|
+
// instances of `SentryError` fail `obj instanceof SentryError` checks.
|
|
408
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
409
|
+
this.logLevel = logLevel;
|
|
439
410
|
}
|
|
440
|
-
|
|
441
|
-
return logger ;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// Ensure we only have a single logger instance, even if multiple versions of @sentry/utils are being used
|
|
445
|
-
let logger;
|
|
446
|
-
if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
|
|
447
|
-
logger = getGlobalSingleton('logger', makeLogger);
|
|
448
|
-
} else {
|
|
449
|
-
logger = makeLogger();
|
|
450
411
|
}
|
|
451
412
|
|
|
452
413
|
/** Regular expression used to parse a Dsn. */
|
|
@@ -477,16 +438,13 @@ function dsnToString(dsn, withPassword = false) {
|
|
|
477
438
|
* Parses a Dsn from a given string.
|
|
478
439
|
*
|
|
479
440
|
* @param str A Dsn as string
|
|
480
|
-
* @returns Dsn as DsnComponents
|
|
441
|
+
* @returns Dsn as DsnComponents
|
|
481
442
|
*/
|
|
482
443
|
function dsnFromString(str) {
|
|
483
444
|
const match = DSN_REGEX.exec(str);
|
|
484
445
|
|
|
485
446
|
if (!match) {
|
|
486
|
-
|
|
487
|
-
// eslint-disable-next-line no-console
|
|
488
|
-
console.error(`Invalid Sentry Dsn: ${str}`);
|
|
489
|
-
return undefined;
|
|
447
|
+
throw new SentryError(`Invalid Sentry Dsn: ${str}`);
|
|
490
448
|
}
|
|
491
449
|
|
|
492
450
|
const [protocol, publicKey, pass = '', host, port = '', lastPath] = match.slice(1);
|
|
@@ -523,69 +481,119 @@ function dsnFromComponents(components) {
|
|
|
523
481
|
|
|
524
482
|
function validateDsn(dsn) {
|
|
525
483
|
if (!(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
|
|
526
|
-
return
|
|
484
|
+
return;
|
|
527
485
|
}
|
|
528
486
|
|
|
529
487
|
const { port, projectId, protocol } = dsn;
|
|
530
488
|
|
|
531
489
|
const requiredComponents = ['protocol', 'publicKey', 'host', 'projectId'];
|
|
532
|
-
|
|
490
|
+
requiredComponents.forEach(component => {
|
|
533
491
|
if (!dsn[component]) {
|
|
534
|
-
|
|
535
|
-
return true;
|
|
492
|
+
throw new SentryError(`Invalid Sentry Dsn: ${component} missing`);
|
|
536
493
|
}
|
|
537
|
-
return false;
|
|
538
494
|
});
|
|
539
495
|
|
|
540
|
-
if (hasMissingRequiredComponent) {
|
|
541
|
-
return false;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
496
|
if (!projectId.match(/^\d+$/)) {
|
|
545
|
-
|
|
546
|
-
return false;
|
|
497
|
+
throw new SentryError(`Invalid Sentry Dsn: Invalid projectId ${projectId}`);
|
|
547
498
|
}
|
|
548
499
|
|
|
549
500
|
if (!isValidProtocol(protocol)) {
|
|
550
|
-
|
|
551
|
-
return false;
|
|
501
|
+
throw new SentryError(`Invalid Sentry Dsn: Invalid protocol ${protocol}`);
|
|
552
502
|
}
|
|
553
503
|
|
|
554
504
|
if (port && isNaN(parseInt(port, 10))) {
|
|
555
|
-
|
|
556
|
-
return false;
|
|
505
|
+
throw new SentryError(`Invalid Sentry Dsn: Invalid port ${port}`);
|
|
557
506
|
}
|
|
558
507
|
|
|
559
508
|
return true;
|
|
560
509
|
}
|
|
561
510
|
|
|
562
|
-
/**
|
|
563
|
-
* Creates a valid Sentry Dsn object, identifying a Sentry instance and project.
|
|
564
|
-
* @returns a valid DsnComponents object or `undefined` if @param from is an invalid DSN source
|
|
565
|
-
*/
|
|
511
|
+
/** The Sentry Dsn, identifying a Sentry instance and project. */
|
|
566
512
|
function makeDsn(from) {
|
|
567
513
|
const components = typeof from === 'string' ? dsnFromString(from) : dsnFromComponents(from);
|
|
568
|
-
|
|
569
|
-
return undefined;
|
|
570
|
-
}
|
|
514
|
+
validateDsn(components);
|
|
571
515
|
return components;
|
|
572
516
|
}
|
|
573
517
|
|
|
574
|
-
/**
|
|
575
|
-
|
|
576
|
-
/** Display name of this error instance. */
|
|
518
|
+
/** Prefix for logging strings */
|
|
519
|
+
const PREFIX = 'Sentry Logger ';
|
|
577
520
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
521
|
+
const CONSOLE_LEVELS = ['debug', 'info', 'warn', 'error', 'log', 'assert', 'trace'] ;
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Temporarily disable sentry console instrumentations.
|
|
525
|
+
*
|
|
526
|
+
* @param callback The function to run against the original `console` messages
|
|
527
|
+
* @returns The results of the callback
|
|
528
|
+
*/
|
|
529
|
+
function consoleSandbox(callback) {
|
|
530
|
+
if (!('console' in GLOBAL_OBJ)) {
|
|
531
|
+
return callback();
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
const originalConsole = GLOBAL_OBJ.console ;
|
|
535
|
+
const wrappedLevels = {};
|
|
536
|
+
|
|
537
|
+
// Restore all wrapped console methods
|
|
538
|
+
CONSOLE_LEVELS.forEach(level => {
|
|
539
|
+
// TODO(v7): Remove this check as it's only needed for Node 6
|
|
540
|
+
const originalWrappedFunc =
|
|
541
|
+
originalConsole[level] && (originalConsole[level] ).__sentry_original__;
|
|
542
|
+
if (level in originalConsole && originalWrappedFunc) {
|
|
543
|
+
wrappedLevels[level] = originalConsole[level] ;
|
|
544
|
+
originalConsole[level] = originalWrappedFunc ;
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
try {
|
|
549
|
+
return callback();
|
|
550
|
+
} finally {
|
|
551
|
+
// Revert restoration to wrapped state
|
|
552
|
+
Object.keys(wrappedLevels).forEach(level => {
|
|
553
|
+
originalConsole[level] = wrappedLevels[level ];
|
|
554
|
+
});
|
|
586
555
|
}
|
|
587
556
|
}
|
|
588
557
|
|
|
558
|
+
function makeLogger() {
|
|
559
|
+
let enabled = false;
|
|
560
|
+
const logger = {
|
|
561
|
+
enable: () => {
|
|
562
|
+
enabled = true;
|
|
563
|
+
},
|
|
564
|
+
disable: () => {
|
|
565
|
+
enabled = false;
|
|
566
|
+
},
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
|
|
570
|
+
CONSOLE_LEVELS.forEach(name => {
|
|
571
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
572
|
+
logger[name] = (...args) => {
|
|
573
|
+
if (enabled) {
|
|
574
|
+
consoleSandbox(() => {
|
|
575
|
+
GLOBAL_OBJ.console[name](`${PREFIX}[${name}]:`, ...args);
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
});
|
|
580
|
+
} else {
|
|
581
|
+
CONSOLE_LEVELS.forEach(name => {
|
|
582
|
+
logger[name] = () => undefined;
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
return logger ;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// Ensure we only have a single logger instance, even if multiple versions of @sentry/utils are being used
|
|
590
|
+
let logger;
|
|
591
|
+
if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
|
|
592
|
+
logger = getGlobalSingleton('logger', makeLogger);
|
|
593
|
+
} else {
|
|
594
|
+
logger = makeLogger();
|
|
595
|
+
}
|
|
596
|
+
|
|
589
597
|
/**
|
|
590
598
|
* Truncates given string to the maximum characters count
|
|
591
599
|
*
|
|
@@ -939,12 +947,6 @@ function createStackParser(...parsers) {
|
|
|
939
947
|
// Remove webpack (error: *) wrappers
|
|
940
948
|
const cleanedLine = WEBPACK_ERROR_REGEXP.test(line) ? line.replace(WEBPACK_ERROR_REGEXP, '$1') : line;
|
|
941
949
|
|
|
942
|
-
// https://github.com/getsentry/sentry-javascript/issues/7813
|
|
943
|
-
// Skip Error: lines
|
|
944
|
-
if (cleanedLine.match(/\S*Error: /)) {
|
|
945
|
-
continue;
|
|
946
|
-
}
|
|
947
|
-
|
|
948
950
|
for (const parser of sortedParsers) {
|
|
949
951
|
const frame = parser(cleanedLine);
|
|
950
952
|
|
|
@@ -1129,8 +1131,6 @@ function supportsHistory() {
|
|
|
1129
1131
|
// eslint-disable-next-line deprecation/deprecation
|
|
1130
1132
|
const WINDOW$3 = getGlobalObject();
|
|
1131
1133
|
|
|
1132
|
-
const SENTRY_XHR_DATA_KEY = '__sentry_xhr_v2__';
|
|
1133
|
-
|
|
1134
1134
|
/**
|
|
1135
1135
|
* Instrument native APIs to call handlers that can be used to create breadcrumbs, APM spans etc.
|
|
1136
1136
|
* - Console API
|
|
@@ -1243,13 +1243,11 @@ function instrumentFetch() {
|
|
|
1243
1243
|
|
|
1244
1244
|
fill(WINDOW$3, 'fetch', function (originalFetch) {
|
|
1245
1245
|
return function (...args) {
|
|
1246
|
-
const { method, url } = parseFetchArgs(args);
|
|
1247
|
-
|
|
1248
1246
|
const handlerData = {
|
|
1249
1247
|
args,
|
|
1250
1248
|
fetchData: {
|
|
1251
|
-
method,
|
|
1252
|
-
url,
|
|
1249
|
+
method: getFetchMethod(args),
|
|
1250
|
+
url: getFetchUrl(args),
|
|
1253
1251
|
},
|
|
1254
1252
|
startTimestamp: Date.now(),
|
|
1255
1253
|
};
|
|
@@ -1284,53 +1282,29 @@ function instrumentFetch() {
|
|
|
1284
1282
|
});
|
|
1285
1283
|
}
|
|
1286
1284
|
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
if (typeof resource === 'string') {
|
|
1293
|
-
return resource;
|
|
1294
|
-
}
|
|
1295
|
-
|
|
1296
|
-
if (!resource) {
|
|
1297
|
-
return '';
|
|
1298
|
-
}
|
|
1299
|
-
|
|
1300
|
-
if (hasProp(resource, 'url')) {
|
|
1301
|
-
return resource.url;
|
|
1285
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
1286
|
+
/** Extract `method` from fetch call arguments */
|
|
1287
|
+
function getFetchMethod(fetchArgs = []) {
|
|
1288
|
+
if ('Request' in WINDOW$3 && isInstanceOf(fetchArgs[0], Request) && fetchArgs[0].method) {
|
|
1289
|
+
return String(fetchArgs[0].method).toUpperCase();
|
|
1302
1290
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
return resource.toString();
|
|
1291
|
+
if (fetchArgs[1] && fetchArgs[1].method) {
|
|
1292
|
+
return String(fetchArgs[1].method).toUpperCase();
|
|
1306
1293
|
}
|
|
1307
|
-
|
|
1308
|
-
return '';
|
|
1294
|
+
return 'GET';
|
|
1309
1295
|
}
|
|
1310
1296
|
|
|
1311
|
-
/**
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
if (fetchArgs.length === 0) {
|
|
1316
|
-
return { method: 'GET', url: '' };
|
|
1297
|
+
/** Extract `url` from fetch call arguments */
|
|
1298
|
+
function getFetchUrl(fetchArgs = []) {
|
|
1299
|
+
if (typeof fetchArgs[0] === 'string') {
|
|
1300
|
+
return fetchArgs[0];
|
|
1317
1301
|
}
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
const [url, options] = fetchArgs ;
|
|
1321
|
-
|
|
1322
|
-
return {
|
|
1323
|
-
url: getUrlFromResource(url),
|
|
1324
|
-
method: hasProp(options, 'method') ? String(options.method).toUpperCase() : 'GET',
|
|
1325
|
-
};
|
|
1302
|
+
if ('Request' in WINDOW$3 && isInstanceOf(fetchArgs[0], Request)) {
|
|
1303
|
+
return fetchArgs[0].url;
|
|
1326
1304
|
}
|
|
1327
|
-
|
|
1328
|
-
const arg = fetchArgs[0];
|
|
1329
|
-
return {
|
|
1330
|
-
url: getUrlFromResource(arg ),
|
|
1331
|
-
method: hasProp(arg, 'method') ? String(arg.method).toUpperCase() : 'GET',
|
|
1332
|
-
};
|
|
1305
|
+
return String(fetchArgs[0]);
|
|
1333
1306
|
}
|
|
1307
|
+
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
|
1334
1308
|
|
|
1335
1309
|
/** JSDoc */
|
|
1336
1310
|
function instrumentXHR() {
|
|
@@ -1343,11 +1317,10 @@ function instrumentXHR() {
|
|
|
1343
1317
|
fill(xhrproto, 'open', function (originalOpen) {
|
|
1344
1318
|
return function ( ...args) {
|
|
1345
1319
|
const url = args[1];
|
|
1346
|
-
const xhrInfo = (this
|
|
1320
|
+
const xhrInfo = (this.__sentry_xhr__ = {
|
|
1347
1321
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1348
1322
|
method: isString$2(args[0]) ? args[0].toUpperCase() : args[0],
|
|
1349
1323
|
url: args[1],
|
|
1350
|
-
request_headers: {},
|
|
1351
1324
|
});
|
|
1352
1325
|
|
|
1353
1326
|
// if Sentry key appears in URL, don't capture it as a request
|
|
@@ -1358,7 +1331,7 @@ function instrumentXHR() {
|
|
|
1358
1331
|
|
|
1359
1332
|
const onreadystatechangeHandler = () => {
|
|
1360
1333
|
// For whatever reason, this is not the same instance here as from the outer method
|
|
1361
|
-
const xhrInfo = this
|
|
1334
|
+
const xhrInfo = this.__sentry_xhr__;
|
|
1362
1335
|
|
|
1363
1336
|
if (!xhrInfo) {
|
|
1364
1337
|
return;
|
|
@@ -1393,32 +1366,14 @@ function instrumentXHR() {
|
|
|
1393
1366
|
this.addEventListener('readystatechange', onreadystatechangeHandler);
|
|
1394
1367
|
}
|
|
1395
1368
|
|
|
1396
|
-
// Intercepting `setRequestHeader` to access the request headers of XHR instance.
|
|
1397
|
-
// This will only work for user/library defined headers, not for the default/browser-assigned headers.
|
|
1398
|
-
// Request cookies are also unavailable for XHR, as `Cookie` header can't be defined by `setRequestHeader`.
|
|
1399
|
-
fill(this, 'setRequestHeader', function (original) {
|
|
1400
|
-
return function ( ...setRequestHeaderArgs) {
|
|
1401
|
-
const [header, value] = setRequestHeaderArgs ;
|
|
1402
|
-
|
|
1403
|
-
const xhrInfo = this[SENTRY_XHR_DATA_KEY];
|
|
1404
|
-
|
|
1405
|
-
if (xhrInfo) {
|
|
1406
|
-
xhrInfo.request_headers[header.toLowerCase()] = value;
|
|
1407
|
-
}
|
|
1408
|
-
|
|
1409
|
-
return original.apply(this, setRequestHeaderArgs);
|
|
1410
|
-
};
|
|
1411
|
-
});
|
|
1412
|
-
|
|
1413
1369
|
return originalOpen.apply(this, args);
|
|
1414
1370
|
};
|
|
1415
1371
|
});
|
|
1416
1372
|
|
|
1417
1373
|
fill(xhrproto, 'send', function (originalSend) {
|
|
1418
1374
|
return function ( ...args) {
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
sentryXhrData.body = args[0];
|
|
1375
|
+
if (this.__sentry_xhr__ && args[0] !== undefined) {
|
|
1376
|
+
this.__sentry_xhr__.body = args[0];
|
|
1422
1377
|
}
|
|
1423
1378
|
|
|
1424
1379
|
triggerHandlers('xhr', {
|
|
@@ -1717,15 +1672,13 @@ function instrumentError() {
|
|
|
1717
1672
|
url,
|
|
1718
1673
|
});
|
|
1719
1674
|
|
|
1720
|
-
if (_oldOnErrorHandler
|
|
1675
|
+
if (_oldOnErrorHandler) {
|
|
1721
1676
|
// eslint-disable-next-line prefer-rest-params
|
|
1722
1677
|
return _oldOnErrorHandler.apply(this, arguments);
|
|
1723
1678
|
}
|
|
1724
1679
|
|
|
1725
1680
|
return false;
|
|
1726
1681
|
};
|
|
1727
|
-
|
|
1728
|
-
WINDOW$3.onerror.__SENTRY_INSTRUMENTED__ = true;
|
|
1729
1682
|
}
|
|
1730
1683
|
|
|
1731
1684
|
let _oldOnUnhandledRejectionHandler = null;
|
|
@@ -1736,15 +1689,13 @@ function instrumentUnhandledRejection() {
|
|
|
1736
1689
|
WINDOW$3.onunhandledrejection = function (e) {
|
|
1737
1690
|
triggerHandlers('unhandledrejection', e);
|
|
1738
1691
|
|
|
1739
|
-
if (_oldOnUnhandledRejectionHandler
|
|
1692
|
+
if (_oldOnUnhandledRejectionHandler) {
|
|
1740
1693
|
// eslint-disable-next-line prefer-rest-params
|
|
1741
1694
|
return _oldOnUnhandledRejectionHandler.apply(this, arguments);
|
|
1742
1695
|
}
|
|
1743
1696
|
|
|
1744
1697
|
return true;
|
|
1745
1698
|
};
|
|
1746
|
-
|
|
1747
|
-
WINDOW$3.onunhandledrejection.__SENTRY_INSTRUMENTED__ = true;
|
|
1748
1699
|
}
|
|
1749
1700
|
|
|
1750
1701
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
@@ -2042,7 +1993,7 @@ function loadModule(moduleName) {
|
|
|
2042
1993
|
* @returns A normalized version of the object, or `"**non-serializable**"` if any errors are thrown during normalization.
|
|
2043
1994
|
*/
|
|
2044
1995
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2045
|
-
function normalize(input, depth =
|
|
1996
|
+
function normalize(input, depth = +Infinity, maxProperties = +Infinity) {
|
|
2046
1997
|
try {
|
|
2047
1998
|
// since we're at the outermost level, we don't provide a key
|
|
2048
1999
|
return visit('', input, depth, maxProperties);
|
|
@@ -2088,10 +2039,7 @@ function visit(
|
|
|
2088
2039
|
const [memoize, unmemoize] = memo;
|
|
2089
2040
|
|
|
2090
2041
|
// Get the simple cases out of the way first
|
|
2091
|
-
if (
|
|
2092
|
-
value == null || // this matches null and undefined -> eqeq not eqeqeq
|
|
2093
|
-
(['number', 'boolean', 'string'].includes(typeof value) && !isNaN$1(value))
|
|
2094
|
-
) {
|
|
2042
|
+
if (value === null || (['number', 'boolean', 'string'].includes(typeof value) && !isNaN$1(value))) {
|
|
2095
2043
|
return value ;
|
|
2096
2044
|
}
|
|
2097
2045
|
|
|
@@ -2112,16 +2060,17 @@ function visit(
|
|
|
2112
2060
|
return value ;
|
|
2113
2061
|
}
|
|
2114
2062
|
|
|
2115
|
-
//
|
|
2116
|
-
//
|
|
2117
|
-
//
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2063
|
+
// Do not normalize objects that we know have already been normalized. As a general rule, the
|
|
2064
|
+
// "__sentry_skip_normalization__" property should only be used sparingly and only should only be set on objects that
|
|
2065
|
+
// have already been normalized.
|
|
2066
|
+
let overriddenDepth = depth;
|
|
2067
|
+
|
|
2068
|
+
if (typeof (value )['__sentry_override_normalization_depth__'] === 'number') {
|
|
2069
|
+
overriddenDepth = (value )['__sentry_override_normalization_depth__'] ;
|
|
2070
|
+
}
|
|
2122
2071
|
|
|
2123
2072
|
// We're also done if we've reached the max depth
|
|
2124
|
-
if (
|
|
2073
|
+
if (overriddenDepth === 0) {
|
|
2125
2074
|
// At this point we know `serialized` is a string of the form `"[object XXXX]"`. Clean it up so it's just `"[XXXX]"`.
|
|
2126
2075
|
return stringified.replace('object ', '');
|
|
2127
2076
|
}
|
|
@@ -2137,7 +2086,7 @@ function visit(
|
|
|
2137
2086
|
try {
|
|
2138
2087
|
const jsonValue = valueWithToJSON.toJSON();
|
|
2139
2088
|
// We need to normalize the return value of `.toJSON()` in case it has circular references
|
|
2140
|
-
return visit('', jsonValue,
|
|
2089
|
+
return visit('', jsonValue, overriddenDepth - 1, maxProperties, memo);
|
|
2141
2090
|
} catch (err) {
|
|
2142
2091
|
// pass (The built-in `toJSON` failed, but we can still try to do it ourselves)
|
|
2143
2092
|
}
|
|
@@ -2166,7 +2115,7 @@ function visit(
|
|
|
2166
2115
|
|
|
2167
2116
|
// Recursively visit all the child nodes
|
|
2168
2117
|
const visitValue = visitable[visitKey];
|
|
2169
|
-
normalized[visitKey] = visit(visitKey, visitValue,
|
|
2118
|
+
normalized[visitKey] = visit(visitKey, visitValue, overriddenDepth - 1, maxProperties, memo);
|
|
2170
2119
|
|
|
2171
2120
|
numAdded++;
|
|
2172
2121
|
}
|
|
@@ -2178,7 +2127,6 @@ function visit(
|
|
|
2178
2127
|
return normalized;
|
|
2179
2128
|
}
|
|
2180
2129
|
|
|
2181
|
-
/* eslint-disable complexity */
|
|
2182
2130
|
/**
|
|
2183
2131
|
* Stringify the given value. Handles various known special values and types.
|
|
2184
2132
|
*
|
|
@@ -2229,6 +2177,11 @@ function stringifyValue(
|
|
|
2229
2177
|
return '[NaN]';
|
|
2230
2178
|
}
|
|
2231
2179
|
|
|
2180
|
+
// this catches `undefined` (but not `null`, which is a primitive and can be serialized on its own)
|
|
2181
|
+
if (value === void 0) {
|
|
2182
|
+
return '[undefined]';
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2232
2185
|
if (typeof value === 'function') {
|
|
2233
2186
|
return `[Function: ${getFunctionName(value)}]`;
|
|
2234
2187
|
}
|
|
@@ -2246,19 +2199,11 @@ function stringifyValue(
|
|
|
2246
2199
|
// them to strings means that instances of classes which haven't defined their `toStringTag` will just come out as
|
|
2247
2200
|
// `"[object Object]"`. If we instead look at the constructor's name (which is the same as the name of the class),
|
|
2248
2201
|
// we can make sure that only plain objects come out that way.
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
// Handle HTML Elements
|
|
2252
|
-
if (/^HTML(\w*)Element$/.test(objName)) {
|
|
2253
|
-
return `[HTMLElement: ${objName}]`;
|
|
2254
|
-
}
|
|
2255
|
-
|
|
2256
|
-
return `[object ${objName}]`;
|
|
2202
|
+
return `[object ${getConstructorName(value)}]`;
|
|
2257
2203
|
} catch (err) {
|
|
2258
2204
|
return `**non-serializable** (${err})`;
|
|
2259
2205
|
}
|
|
2260
2206
|
}
|
|
2261
|
-
/* eslint-enable complexity */
|
|
2262
2207
|
|
|
2263
2208
|
function getConstructorName(value) {
|
|
2264
2209
|
const prototype = Object.getPrototypeOf(value);
|
|
@@ -2569,7 +2514,9 @@ function makePromiseBuffer(limit) {
|
|
|
2569
2514
|
* // environments where DOM might not be available
|
|
2570
2515
|
* @returns parsed URL object
|
|
2571
2516
|
*/
|
|
2572
|
-
function parseUrl(url)
|
|
2517
|
+
function parseUrl(url)
|
|
2518
|
+
|
|
2519
|
+
{
|
|
2573
2520
|
if (!url) {
|
|
2574
2521
|
return {};
|
|
2575
2522
|
}
|
|
@@ -2587,8 +2534,6 @@ function parseUrl(url) {
|
|
|
2587
2534
|
host: match[4],
|
|
2588
2535
|
path: match[5],
|
|
2589
2536
|
protocol: match[2],
|
|
2590
|
-
search: query,
|
|
2591
|
-
hash: fragment,
|
|
2592
2537
|
relative: match[5] + query + fragment, // everything minus origin
|
|
2593
2538
|
};
|
|
2594
2539
|
}
|
|
@@ -2973,7 +2918,6 @@ const ITEM_TYPE_TO_DATA_CATEGORY_MAP = {
|
|
|
2973
2918
|
profile: 'profile',
|
|
2974
2919
|
replay_event: 'replay',
|
|
2975
2920
|
replay_recording: 'replay',
|
|
2976
|
-
check_in: 'monitor',
|
|
2977
2921
|
};
|
|
2978
2922
|
|
|
2979
2923
|
/**
|
|
@@ -3003,14 +2947,16 @@ function createEventEnvelopeHeaders(
|
|
|
3003
2947
|
dsn,
|
|
3004
2948
|
) {
|
|
3005
2949
|
const dynamicSamplingContext = event.sdkProcessingMetadata && event.sdkProcessingMetadata.dynamicSamplingContext;
|
|
2950
|
+
|
|
3006
2951
|
return {
|
|
3007
2952
|
event_id: event.event_id ,
|
|
3008
2953
|
sent_at: new Date().toISOString(),
|
|
3009
2954
|
...(sdkInfo && { sdk: sdkInfo }),
|
|
3010
2955
|
...(!!tunnel && { dsn: dsnToString(dsn) }),
|
|
3011
|
-
...(
|
|
3012
|
-
|
|
3013
|
-
|
|
2956
|
+
...(event.type === 'transaction' &&
|
|
2957
|
+
dynamicSamplingContext && {
|
|
2958
|
+
trace: dropUndefinedKeys({ ...dynamicSamplingContext }),
|
|
2959
|
+
}),
|
|
3014
2960
|
};
|
|
3015
2961
|
}
|
|
3016
2962
|
|
|
@@ -3715,16 +3661,9 @@ class Scope {
|
|
|
3715
3661
|
// errors with transaction and it relies on that.
|
|
3716
3662
|
if (this._span) {
|
|
3717
3663
|
event.contexts = { trace: this._span.getTraceContext(), ...event.contexts };
|
|
3718
|
-
const
|
|
3719
|
-
if (
|
|
3720
|
-
event.
|
|
3721
|
-
dynamicSamplingContext: transaction.getDynamicSamplingContext(),
|
|
3722
|
-
...event.sdkProcessingMetadata,
|
|
3723
|
-
};
|
|
3724
|
-
const transactionName = transaction.name;
|
|
3725
|
-
if (transactionName) {
|
|
3726
|
-
event.tags = { transaction: transactionName, ...event.tags };
|
|
3727
|
-
}
|
|
3664
|
+
const transactionName = this._span.transaction && this._span.transaction.name;
|
|
3665
|
+
if (transactionName) {
|
|
3666
|
+
event.tags = { transaction: transactionName, ...event.tags };
|
|
3728
3667
|
}
|
|
3729
3668
|
}
|
|
3730
3669
|
|
|
@@ -3848,6 +3787,11 @@ const API_VERSION = 4;
|
|
|
3848
3787
|
*/
|
|
3849
3788
|
const DEFAULT_BREADCRUMBS = 100;
|
|
3850
3789
|
|
|
3790
|
+
/**
|
|
3791
|
+
* A layer in the process stack.
|
|
3792
|
+
* @hidden
|
|
3793
|
+
*/
|
|
3794
|
+
|
|
3851
3795
|
/**
|
|
3852
3796
|
* @inheritDoc
|
|
3853
3797
|
*/
|
|
@@ -4125,17 +4069,7 @@ class Hub {
|
|
|
4125
4069
|
* @inheritDoc
|
|
4126
4070
|
*/
|
|
4127
4071
|
startTransaction(context, customSamplingContext) {
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && !result) {
|
|
4131
|
-
// eslint-disable-next-line no-console
|
|
4132
|
-
console.warn(`Tracing extension 'startTransaction' has not been added. Call 'addTracingExtensions' before calling 'init':
|
|
4133
|
-
Sentry.addTracingExtensions();
|
|
4134
|
-
Sentry.init({...});
|
|
4135
|
-
`);
|
|
4136
|
-
}
|
|
4137
|
-
|
|
4138
|
-
return result;
|
|
4072
|
+
return this._callExtensionMethod('startTransaction', context, customSamplingContext);
|
|
4139
4073
|
}
|
|
4140
4074
|
|
|
4141
4075
|
/**
|
|
@@ -4220,10 +4154,13 @@ Sentry.init({...});
|
|
|
4220
4154
|
*/
|
|
4221
4155
|
_sendSessionUpdate() {
|
|
4222
4156
|
const { scope, client } = this.getStackTop();
|
|
4157
|
+
if (!scope) return;
|
|
4223
4158
|
|
|
4224
4159
|
const session = scope.getSession();
|
|
4225
|
-
if (session
|
|
4226
|
-
client.captureSession
|
|
4160
|
+
if (session) {
|
|
4161
|
+
if (client && client.captureSession) {
|
|
4162
|
+
client.captureSession(session);
|
|
4163
|
+
}
|
|
4227
4164
|
}
|
|
4228
4165
|
}
|
|
4229
4166
|
|
|
@@ -4293,28 +4230,47 @@ function getCurrentHub() {
|
|
|
4293
4230
|
// Get main carrier (global for every environment)
|
|
4294
4231
|
const registry = getMainCarrier();
|
|
4295
4232
|
|
|
4296
|
-
if (registry.__SENTRY__ && registry.__SENTRY__.acs) {
|
|
4297
|
-
const hub = registry.__SENTRY__.acs.getCurrentHub();
|
|
4298
|
-
|
|
4299
|
-
if (hub) {
|
|
4300
|
-
return hub;
|
|
4301
|
-
}
|
|
4302
|
-
}
|
|
4303
|
-
|
|
4304
|
-
// Return hub that lives on a global object
|
|
4305
|
-
return getGlobalHub(registry);
|
|
4306
|
-
}
|
|
4307
|
-
|
|
4308
|
-
function getGlobalHub(registry = getMainCarrier()) {
|
|
4309
4233
|
// If there's no hub, or its an old API, assign a new one
|
|
4310
4234
|
if (!hasHubOnCarrier(registry) || getHubFromCarrier(registry).isOlderThan(API_VERSION)) {
|
|
4311
4235
|
setHubOnCarrier(registry, new Hub());
|
|
4312
4236
|
}
|
|
4313
4237
|
|
|
4238
|
+
// Prefer domains over global if they are there (applicable only to Node environment)
|
|
4239
|
+
if (isNodeEnv()) {
|
|
4240
|
+
return getHubFromActiveDomain(registry);
|
|
4241
|
+
}
|
|
4314
4242
|
// Return hub that lives on a global object
|
|
4315
4243
|
return getHubFromCarrier(registry);
|
|
4316
4244
|
}
|
|
4317
4245
|
|
|
4246
|
+
/**
|
|
4247
|
+
* Try to read the hub from an active domain, and fallback to the registry if one doesn't exist
|
|
4248
|
+
* @returns discovered hub
|
|
4249
|
+
*/
|
|
4250
|
+
function getHubFromActiveDomain(registry) {
|
|
4251
|
+
try {
|
|
4252
|
+
const sentry = getMainCarrier().__SENTRY__;
|
|
4253
|
+
const activeDomain = sentry && sentry.extensions && sentry.extensions.domain && sentry.extensions.domain.active;
|
|
4254
|
+
|
|
4255
|
+
// If there's no active domain, just return global hub
|
|
4256
|
+
if (!activeDomain) {
|
|
4257
|
+
return getHubFromCarrier(registry);
|
|
4258
|
+
}
|
|
4259
|
+
|
|
4260
|
+
// If there's no hub on current domain, or it's an old API, assign a new one
|
|
4261
|
+
if (!hasHubOnCarrier(activeDomain) || getHubFromCarrier(activeDomain).isOlderThan(API_VERSION)) {
|
|
4262
|
+
const registryHubTopStack = getHubFromCarrier(registry).getStackTop();
|
|
4263
|
+
setHubOnCarrier(activeDomain, new Hub(registryHubTopStack.client, Scope.clone(registryHubTopStack.scope)));
|
|
4264
|
+
}
|
|
4265
|
+
|
|
4266
|
+
// Return hub that lives on a domain
|
|
4267
|
+
return getHubFromCarrier(activeDomain);
|
|
4268
|
+
} catch (_Oo) {
|
|
4269
|
+
// Return hub that lives on a global object
|
|
4270
|
+
return getHubFromCarrier(registry);
|
|
4271
|
+
}
|
|
4272
|
+
}
|
|
4273
|
+
|
|
4318
4274
|
/**
|
|
4319
4275
|
* This will tell whether a carrier has a hub on it or not
|
|
4320
4276
|
* @param carrier object
|
|
@@ -4388,69 +4344,6 @@ var SpanStatus; (function (SpanStatus) {
|
|
|
4388
4344
|
const DataLoss = 'data_loss'; SpanStatus["DataLoss"] = DataLoss;
|
|
4389
4345
|
})(SpanStatus || (SpanStatus = {}));
|
|
4390
4346
|
|
|
4391
|
-
/**
|
|
4392
|
-
* Wraps a function with a transaction/span and finishes the span after the function is done.
|
|
4393
|
-
*
|
|
4394
|
-
* Note that if you have not enabled tracing extensions via `addTracingExtensions`, this function
|
|
4395
|
-
* will not generate spans, and the `span` returned from the callback may be undefined.
|
|
4396
|
-
*
|
|
4397
|
-
* This function is meant to be used internally and may break at any time. Use at your own risk.
|
|
4398
|
-
*
|
|
4399
|
-
* @internal
|
|
4400
|
-
* @private
|
|
4401
|
-
*/
|
|
4402
|
-
function trace(
|
|
4403
|
-
context,
|
|
4404
|
-
callback,
|
|
4405
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
4406
|
-
onError = () => {},
|
|
4407
|
-
) {
|
|
4408
|
-
const ctx = { ...context };
|
|
4409
|
-
// If a name is set and a description is not, set the description to the name.
|
|
4410
|
-
if (ctx.name !== undefined && ctx.description === undefined) {
|
|
4411
|
-
ctx.description = ctx.name;
|
|
4412
|
-
}
|
|
4413
|
-
|
|
4414
|
-
const hub = getCurrentHub();
|
|
4415
|
-
const scope = hub.getScope();
|
|
4416
|
-
|
|
4417
|
-
const parentSpan = scope.getSpan();
|
|
4418
|
-
const activeSpan = parentSpan ? parentSpan.startChild(ctx) : hub.startTransaction(ctx);
|
|
4419
|
-
scope.setSpan(activeSpan);
|
|
4420
|
-
|
|
4421
|
-
function finishAndSetSpan() {
|
|
4422
|
-
activeSpan && activeSpan.finish();
|
|
4423
|
-
hub.getScope().setSpan(parentSpan);
|
|
4424
|
-
}
|
|
4425
|
-
|
|
4426
|
-
let maybePromiseResult;
|
|
4427
|
-
try {
|
|
4428
|
-
maybePromiseResult = callback(activeSpan);
|
|
4429
|
-
} catch (e) {
|
|
4430
|
-
activeSpan && activeSpan.setStatus('internal_error');
|
|
4431
|
-
onError(e);
|
|
4432
|
-
finishAndSetSpan();
|
|
4433
|
-
throw e;
|
|
4434
|
-
}
|
|
4435
|
-
|
|
4436
|
-
if (isThenable(maybePromiseResult)) {
|
|
4437
|
-
Promise.resolve(maybePromiseResult).then(
|
|
4438
|
-
() => {
|
|
4439
|
-
finishAndSetSpan();
|
|
4440
|
-
},
|
|
4441
|
-
e => {
|
|
4442
|
-
activeSpan && activeSpan.setStatus('internal_error');
|
|
4443
|
-
onError(e);
|
|
4444
|
-
finishAndSetSpan();
|
|
4445
|
-
},
|
|
4446
|
-
);
|
|
4447
|
-
} else {
|
|
4448
|
-
finishAndSetSpan();
|
|
4449
|
-
}
|
|
4450
|
-
|
|
4451
|
-
return maybePromiseResult;
|
|
4452
|
-
}
|
|
4453
|
-
|
|
4454
4347
|
// Note: All functions in this file are typed with a return value of `ReturnType<Hub[HUB_FUNCTION]>`,
|
|
4455
4348
|
// where HUB_FUNCTION is some method on the Hub class.
|
|
4456
4349
|
//
|
|
@@ -4792,11 +4685,7 @@ function prepareEvent(
|
|
|
4792
4685
|
|
|
4793
4686
|
applyClientOptions(prepared, options);
|
|
4794
4687
|
applyIntegrationsMetadata(prepared, integrations);
|
|
4795
|
-
|
|
4796
|
-
// Only apply debug metadata to error events.
|
|
4797
|
-
if (event.type === undefined) {
|
|
4798
|
-
applyDebugMetadata(prepared, options.stackParser);
|
|
4799
|
-
}
|
|
4688
|
+
applyDebugMetadata(prepared, options.stackParser);
|
|
4800
4689
|
|
|
4801
4690
|
// If we have scope given to us, use it as the base for further modifications.
|
|
4802
4691
|
// This allows us to prevent unnecessary copying of data if `captureContext` is not provided.
|
|
@@ -4873,8 +4762,6 @@ function applyClientOptions(event, options) {
|
|
|
4873
4762
|
}
|
|
4874
4763
|
}
|
|
4875
4764
|
|
|
4876
|
-
const debugIdStackParserCache = new WeakMap();
|
|
4877
|
-
|
|
4878
4765
|
/**
|
|
4879
4766
|
* Applies debug metadata images to the event in order to apply source maps by looking up their debug ID.
|
|
4880
4767
|
*/
|
|
@@ -4885,28 +4772,10 @@ function applyDebugMetadata(event, stackParser) {
|
|
|
4885
4772
|
return;
|
|
4886
4773
|
}
|
|
4887
4774
|
|
|
4888
|
-
let debugIdStackFramesCache;
|
|
4889
|
-
const cachedDebugIdStackFrameCache = debugIdStackParserCache.get(stackParser);
|
|
4890
|
-
if (cachedDebugIdStackFrameCache) {
|
|
4891
|
-
debugIdStackFramesCache = cachedDebugIdStackFrameCache;
|
|
4892
|
-
} else {
|
|
4893
|
-
debugIdStackFramesCache = new Map();
|
|
4894
|
-
debugIdStackParserCache.set(stackParser, debugIdStackFramesCache);
|
|
4895
|
-
}
|
|
4896
|
-
|
|
4897
4775
|
// Build a map of filename -> debug_id
|
|
4898
4776
|
const filenameDebugIdMap = Object.keys(debugIdMap).reduce((acc, debugIdStackTrace) => {
|
|
4899
|
-
|
|
4900
|
-
const
|
|
4901
|
-
if (cachedParsedStack) {
|
|
4902
|
-
parsedStack = cachedParsedStack;
|
|
4903
|
-
} else {
|
|
4904
|
-
parsedStack = stackParser(debugIdStackTrace);
|
|
4905
|
-
debugIdStackFramesCache.set(debugIdStackTrace, parsedStack);
|
|
4906
|
-
}
|
|
4907
|
-
|
|
4908
|
-
for (let i = parsedStack.length - 1; i >= 0; i--) {
|
|
4909
|
-
const stackFrame = parsedStack[i];
|
|
4777
|
+
const parsedStack = stackParser(debugIdStackTrace);
|
|
4778
|
+
for (const stackFrame of parsedStack) {
|
|
4910
4779
|
if (stackFrame.filename) {
|
|
4911
4780
|
acc[stackFrame.filename] = debugIdMap[debugIdStackTrace];
|
|
4912
4781
|
break;
|
|
@@ -5083,20 +4952,16 @@ class BaseClient {
|
|
|
5083
4952
|
*/
|
|
5084
4953
|
constructor(options) {BaseClient.prototype.__init.call(this);BaseClient.prototype.__init2.call(this);BaseClient.prototype.__init3.call(this);BaseClient.prototype.__init4.call(this);BaseClient.prototype.__init5.call(this);
|
|
5085
4954
|
this._options = options;
|
|
5086
|
-
|
|
5087
4955
|
if (options.dsn) {
|
|
5088
4956
|
this._dsn = makeDsn(options.dsn);
|
|
5089
|
-
} else {
|
|
5090
|
-
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('No DSN provided, client will not do anything.');
|
|
5091
|
-
}
|
|
5092
|
-
|
|
5093
|
-
if (this._dsn) {
|
|
5094
4957
|
const url = getEnvelopeEndpointWithUrlEncodedAuth(this._dsn, options);
|
|
5095
4958
|
this._transport = options.transport({
|
|
5096
4959
|
recordDroppedEvent: this.recordDroppedEvent.bind(this),
|
|
5097
4960
|
...options.transportOptions,
|
|
5098
4961
|
url,
|
|
5099
4962
|
});
|
|
4963
|
+
} else {
|
|
4964
|
+
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('No DSN provided, client will not do anything.');
|
|
5100
4965
|
}
|
|
5101
4966
|
}
|
|
5102
4967
|
|
|
@@ -5815,7 +5680,7 @@ function getEventForEnvelopeItem(item, type) {
|
|
|
5815
5680
|
return Array.isArray(item) ? (item )[1] : undefined;
|
|
5816
5681
|
}
|
|
5817
5682
|
|
|
5818
|
-
const SDK_VERSION = '7.
|
|
5683
|
+
const SDK_VERSION = '7.46.0';
|
|
5819
5684
|
|
|
5820
5685
|
let originalFunctionToString;
|
|
5821
5686
|
|
|
@@ -5838,17 +5703,11 @@ class FunctionToString {constructor() { FunctionToString.prototype.__init.call(
|
|
|
5838
5703
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
5839
5704
|
originalFunctionToString = Function.prototype.toString;
|
|
5840
5705
|
|
|
5841
|
-
//
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
const context = getOriginalFunction(this) || this;
|
|
5847
|
-
return originalFunctionToString.apply(context, args);
|
|
5848
|
-
};
|
|
5849
|
-
} catch (e) {
|
|
5850
|
-
// ignore errors here, just don't patch this
|
|
5851
|
-
}
|
|
5706
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5707
|
+
Function.prototype.toString = function ( ...args) {
|
|
5708
|
+
const context = getOriginalFunction(this) || this;
|
|
5709
|
+
return originalFunctionToString.apply(context, args);
|
|
5710
|
+
};
|
|
5852
5711
|
}
|
|
5853
5712
|
} FunctionToString.__initStatic();
|
|
5854
5713
|
|
|
@@ -5996,9 +5855,8 @@ function _getPossibleEventMessages(event) {
|
|
|
5996
5855
|
return [event.message];
|
|
5997
5856
|
}
|
|
5998
5857
|
if (event.exception) {
|
|
5999
|
-
const { values } = event.exception;
|
|
6000
5858
|
try {
|
|
6001
|
-
const { type = '', value = '' } = (values && values[
|
|
5859
|
+
const { type = '', value = '' } = (event.exception.values && event.exception.values[0]) || {};
|
|
6002
5860
|
return [`${value}`, `${type}: ${value}`];
|
|
6003
5861
|
} catch (oO) {
|
|
6004
5862
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(`Cannot extract message for event ${getEventDescription(event)}`);
|
|
@@ -6048,9 +5906,9 @@ function _getEventFilterUrl(event) {
|
|
|
6048
5906
|
}
|
|
6049
5907
|
|
|
6050
5908
|
var Integrations = /*#__PURE__*/Object.freeze({
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
5909
|
+
__proto__: null,
|
|
5910
|
+
FunctionToString: FunctionToString,
|
|
5911
|
+
InboundFilters: InboundFilters
|
|
6054
5912
|
});
|
|
6055
5913
|
|
|
6056
5914
|
const WINDOW$1 = GLOBAL_OBJ ;
|
|
@@ -6657,14 +6515,12 @@ function _consoleBreadcrumb(handlerData) {
|
|
|
6657
6515
|
function _xhrBreadcrumb(handlerData) {
|
|
6658
6516
|
const { startTimestamp, endTimestamp } = handlerData;
|
|
6659
6517
|
|
|
6660
|
-
const sentryXhrData = handlerData.xhr[SENTRY_XHR_DATA_KEY];
|
|
6661
|
-
|
|
6662
6518
|
// We only capture complete, non-sentry requests
|
|
6663
|
-
if (!startTimestamp || !endTimestamp || !
|
|
6519
|
+
if (!startTimestamp || !endTimestamp || !handlerData.xhr.__sentry_xhr__) {
|
|
6664
6520
|
return;
|
|
6665
6521
|
}
|
|
6666
6522
|
|
|
6667
|
-
const { method, url, status_code, body } =
|
|
6523
|
+
const { method, url, status_code, body } = handlerData.xhr.__sentry_xhr__;
|
|
6668
6524
|
|
|
6669
6525
|
const data = {
|
|
6670
6526
|
method,
|
|
@@ -6782,43 +6638,6 @@ function _isEvent(event) {
|
|
|
6782
6638
|
return event && !!(event ).target;
|
|
6783
6639
|
}
|
|
6784
6640
|
|
|
6785
|
-
/**
|
|
6786
|
-
* Creates an envelope from a user feedback.
|
|
6787
|
-
*/
|
|
6788
|
-
function createUserFeedbackEnvelope(
|
|
6789
|
-
feedback,
|
|
6790
|
-
{
|
|
6791
|
-
metadata,
|
|
6792
|
-
tunnel,
|
|
6793
|
-
dsn,
|
|
6794
|
-
}
|
|
6795
|
-
|
|
6796
|
-
,
|
|
6797
|
-
) {
|
|
6798
|
-
const headers = {
|
|
6799
|
-
event_id: feedback.event_id,
|
|
6800
|
-
sent_at: new Date().toISOString(),
|
|
6801
|
-
...(metadata &&
|
|
6802
|
-
metadata.sdk && {
|
|
6803
|
-
sdk: {
|
|
6804
|
-
name: metadata.sdk.name,
|
|
6805
|
-
version: metadata.sdk.version,
|
|
6806
|
-
},
|
|
6807
|
-
}),
|
|
6808
|
-
...(!!tunnel && !!dsn && { dsn: dsnToString(dsn) }),
|
|
6809
|
-
};
|
|
6810
|
-
const item = createUserFeedbackEnvelopeItem(feedback);
|
|
6811
|
-
|
|
6812
|
-
return createEnvelope(headers, [item]);
|
|
6813
|
-
}
|
|
6814
|
-
|
|
6815
|
-
function createUserFeedbackEnvelopeItem(feedback) {
|
|
6816
|
-
const feedbackHeaders = {
|
|
6817
|
-
type: 'user_report',
|
|
6818
|
-
};
|
|
6819
|
-
return [feedbackHeaders, feedback];
|
|
6820
|
-
}
|
|
6821
|
-
|
|
6822
6641
|
/**
|
|
6823
6642
|
* Configuration options for the Sentry Browser SDK.
|
|
6824
6643
|
* @see @sentry/types Options for more information.
|
|
@@ -6901,23 +6720,6 @@ class BrowserClient extends BaseClient {
|
|
|
6901
6720
|
super.sendEvent(event, hint);
|
|
6902
6721
|
}
|
|
6903
6722
|
|
|
6904
|
-
/**
|
|
6905
|
-
* Sends user feedback to Sentry.
|
|
6906
|
-
*/
|
|
6907
|
-
captureUserFeedback(feedback) {
|
|
6908
|
-
if (!this._isEnabled()) {
|
|
6909
|
-
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('SDK not enabled, will not capture user feedback.');
|
|
6910
|
-
return;
|
|
6911
|
-
}
|
|
6912
|
-
|
|
6913
|
-
const envelope = createUserFeedbackEnvelope(feedback, {
|
|
6914
|
-
metadata: this.getSdkMetadata(),
|
|
6915
|
-
dsn: this.getDsn(),
|
|
6916
|
-
tunnel: this.getOptions().tunnel,
|
|
6917
|
-
});
|
|
6918
|
-
void this._sendEnvelope(envelope);
|
|
6919
|
-
}
|
|
6920
|
-
|
|
6921
6723
|
/**
|
|
6922
6724
|
* @inheritDoc
|
|
6923
6725
|
*/
|
|
@@ -7160,7 +6962,7 @@ function createFrame(filename, func, lineno, colno) {
|
|
|
7160
6962
|
|
|
7161
6963
|
// Chromium based browsers: Chrome, Brave, new Opera, new Edge
|
|
7162
6964
|
const chromeRegex =
|
|
7163
|
-
/^\s*at (?:(
|
|
6965
|
+
/^\s*at (?:(.*\).*?|.*?) ?\((?:address at )?)?(?:async )?((?:file|https?|blob|chrome-extension|address|native|eval|webpack|<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
|
|
7164
6966
|
const chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/;
|
|
7165
6967
|
|
|
7166
6968
|
const chrome = line => {
|
|
@@ -7196,7 +6998,7 @@ const chromeStackLineParser = [CHROME_PRIORITY, chrome];
|
|
|
7196
6998
|
// generates filenames without a prefix like `file://` the filenames in the stacktrace are just 42.js
|
|
7197
6999
|
// We need this specific case for now because we want no other regex to match.
|
|
7198
7000
|
const geckoREgex =
|
|
7199
|
-
/^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:
|
|
7001
|
+
/^\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;
|
|
7200
7002
|
const geckoEvalRegex = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
|
|
7201
7003
|
|
|
7202
7004
|
const gecko = line => {
|
|
@@ -7228,7 +7030,8 @@ const gecko = line => {
|
|
|
7228
7030
|
|
|
7229
7031
|
const geckoStackLineParser = [GECKO_PRIORITY, gecko];
|
|
7230
7032
|
|
|
7231
|
-
const winjsRegex =
|
|
7033
|
+
const winjsRegex =
|
|
7034
|
+
/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
|
|
7232
7035
|
|
|
7233
7036
|
const winjs = line => {
|
|
7234
7037
|
const parts = winjsRegex.exec(line);
|
|
@@ -8274,13 +8077,13 @@ function startSessionTracking() {
|
|
|
8274
8077
|
}
|
|
8275
8078
|
|
|
8276
8079
|
var index$1 = /*#__PURE__*/Object.freeze({
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8080
|
+
__proto__: null,
|
|
8081
|
+
GlobalHandlers: GlobalHandlers,
|
|
8082
|
+
TryCatch: TryCatch,
|
|
8083
|
+
Breadcrumbs: Breadcrumbs,
|
|
8084
|
+
LinkedErrors: LinkedErrors,
|
|
8085
|
+
HttpContext: HttpContext,
|
|
8086
|
+
Dedupe: Dedupe
|
|
8284
8087
|
});
|
|
8285
8088
|
|
|
8286
8089
|
// exporting a separate copy of `WINDOW` rather than exporting the one from `@sentry/browser`
|
|
@@ -8293,14 +8096,11 @@ const REPLAY_SESSION_KEY = 'sentryReplaySession';
|
|
|
8293
8096
|
const REPLAY_EVENT_NAME = 'replay_event';
|
|
8294
8097
|
const UNABLE_TO_SEND_REPLAY = 'Unable to send Replay';
|
|
8295
8098
|
|
|
8296
|
-
// The idle limit for a session
|
|
8297
|
-
const
|
|
8298
|
-
|
|
8299
|
-
// The idle limit for a session after which the session expires.
|
|
8300
|
-
const SESSION_IDLE_EXPIRE_DURATION = 900000; // 15 minutes in ms
|
|
8099
|
+
// The idle limit for a session
|
|
8100
|
+
const SESSION_IDLE_DURATION = 300000; // 5 minutes in ms
|
|
8301
8101
|
|
|
8302
8102
|
// The maximum length of a session
|
|
8303
|
-
const MAX_SESSION_LIFE = 3600000; // 60 minutes
|
|
8103
|
+
const MAX_SESSION_LIFE = 3600000; // 60 minutes
|
|
8304
8104
|
|
|
8305
8105
|
/** Default flush delays */
|
|
8306
8106
|
const DEFAULT_FLUSH_MIN_DELAY = 5000;
|
|
@@ -8309,16 +8109,13 @@ const DEFAULT_FLUSH_MIN_DELAY = 5000;
|
|
|
8309
8109
|
const DEFAULT_FLUSH_MAX_DELAY = 5500;
|
|
8310
8110
|
|
|
8311
8111
|
/* How long to wait for error checkouts */
|
|
8312
|
-
const
|
|
8112
|
+
const ERROR_CHECKOUT_TIME = 60000;
|
|
8313
8113
|
|
|
8314
8114
|
const RETRY_BASE_INTERVAL = 5000;
|
|
8315
8115
|
const RETRY_MAX_COUNT = 3;
|
|
8316
8116
|
|
|
8317
|
-
/* The max (uncompressed) size in bytes of a network body. Any body larger than this will be
|
|
8318
|
-
const NETWORK_BODY_MAX_SIZE =
|
|
8319
|
-
|
|
8320
|
-
/* The max size of a single console arg that is captured. Any arg larger than this will be truncated. */
|
|
8321
|
-
const CONSOLE_ARG_MAX_SIZE = 5000;
|
|
8117
|
+
/* The max (uncompressed) size in bytes of a network body. Any body larger than this will be dropped. */
|
|
8118
|
+
const NETWORK_BODY_MAX_SIZE = 300000;
|
|
8322
8119
|
|
|
8323
8120
|
var NodeType$1;
|
|
8324
8121
|
(function (NodeType) {
|
|
@@ -8355,7 +8152,7 @@ function maskInputValue({ input, maskInputSelector, unmaskInputSelector, maskInp
|
|
|
8355
8152
|
if (unmaskInputSelector && input.matches(unmaskInputSelector)) {
|
|
8356
8153
|
return text;
|
|
8357
8154
|
}
|
|
8358
|
-
if (input.hasAttribute('
|
|
8155
|
+
if (input.hasAttribute('rr_is_password')) {
|
|
8359
8156
|
type = 'password';
|
|
8360
8157
|
}
|
|
8361
8158
|
if (isInputTypeMasked({ maskInputOptions, tagName, type }) ||
|
|
@@ -8388,21 +8185,6 @@ function is2DCanvasBlank(canvas) {
|
|
|
8388
8185
|
}
|
|
8389
8186
|
return true;
|
|
8390
8187
|
}
|
|
8391
|
-
function getInputType(element) {
|
|
8392
|
-
const type = element.type;
|
|
8393
|
-
return element.hasAttribute('data-rr-is-password')
|
|
8394
|
-
? 'password'
|
|
8395
|
-
: type
|
|
8396
|
-
? type.toLowerCase()
|
|
8397
|
-
: null;
|
|
8398
|
-
}
|
|
8399
|
-
function getInputValue(el, tagName, type) {
|
|
8400
|
-
typeof type === 'string' ? type.toLowerCase() : '';
|
|
8401
|
-
if (tagName === 'INPUT' && (type === 'radio' || type === 'checkbox')) {
|
|
8402
|
-
return el.getAttribute('value') || '';
|
|
8403
|
-
}
|
|
8404
|
-
return el.value;
|
|
8405
|
-
}
|
|
8406
8188
|
|
|
8407
8189
|
let _id = 1;
|
|
8408
8190
|
const tagNameRegex = new RegExp('[^a-z0-9-_:]');
|
|
@@ -8441,13 +8223,6 @@ function getCssRuleString(rule) {
|
|
|
8441
8223
|
catch (_a) {
|
|
8442
8224
|
}
|
|
8443
8225
|
}
|
|
8444
|
-
return validateStringifiedCssRule(cssStringified);
|
|
8445
|
-
}
|
|
8446
|
-
function validateStringifiedCssRule(cssStringified) {
|
|
8447
|
-
if (cssStringified.indexOf(':') > -1) {
|
|
8448
|
-
const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
|
|
8449
|
-
return cssStringified.replace(regex, '$1\\$2');
|
|
8450
|
-
}
|
|
8451
8226
|
return cssStringified;
|
|
8452
8227
|
}
|
|
8453
8228
|
function isCSSImportRule(rule) {
|
|
@@ -8456,7 +8231,7 @@ function isCSSImportRule(rule) {
|
|
|
8456
8231
|
function stringifyStyleSheet(sheet) {
|
|
8457
8232
|
return sheet.cssRules
|
|
8458
8233
|
? Array.from(sheet.cssRules)
|
|
8459
|
-
.map((rule) => rule.cssText
|
|
8234
|
+
.map((rule) => rule.cssText || '')
|
|
8460
8235
|
.join('')
|
|
8461
8236
|
: '';
|
|
8462
8237
|
}
|
|
@@ -8791,15 +8566,14 @@ function serializeNode(n, options) {
|
|
|
8791
8566
|
tagName === 'select' ||
|
|
8792
8567
|
tagName === 'option') {
|
|
8793
8568
|
const el = n;
|
|
8794
|
-
const
|
|
8795
|
-
const value = getInputValue(el, tagName.toUpperCase(), type);
|
|
8569
|
+
const value = getInputValue(tagName, el, attributes);
|
|
8796
8570
|
const checked = n.checked;
|
|
8797
|
-
if (type !== 'submit' &&
|
|
8798
|
-
type !== 'button' &&
|
|
8571
|
+
if (attributes.type !== 'submit' &&
|
|
8572
|
+
attributes.type !== 'button' &&
|
|
8799
8573
|
value) {
|
|
8800
8574
|
attributes.value = maskInputValue({
|
|
8801
8575
|
input: el,
|
|
8802
|
-
type,
|
|
8576
|
+
type: attributes.type,
|
|
8803
8577
|
tagName,
|
|
8804
8578
|
value,
|
|
8805
8579
|
maskInputSelector,
|
|
@@ -9272,8 +9046,15 @@ function snapshot(n, options) {
|
|
|
9272
9046
|
function skipAttribute(tagName, attributeName, value) {
|
|
9273
9047
|
return ((tagName === 'video' || tagName === 'audio') && attributeName === 'autoplay');
|
|
9274
9048
|
}
|
|
9049
|
+
function getInputValue(tagName, el, attributes) {
|
|
9050
|
+
if (tagName === 'input' &&
|
|
9051
|
+
(attributes.type === 'radio' || attributes.type === 'checkbox')) {
|
|
9052
|
+
return el.getAttribute('value') || '';
|
|
9053
|
+
}
|
|
9054
|
+
return el.value;
|
|
9055
|
+
}
|
|
9275
9056
|
|
|
9276
|
-
var EventType
|
|
9057
|
+
var EventType;
|
|
9277
9058
|
(function (EventType) {
|
|
9278
9059
|
EventType[EventType["DomContentLoaded"] = 0] = "DomContentLoaded";
|
|
9279
9060
|
EventType[EventType["Load"] = 1] = "Load";
|
|
@@ -9282,7 +9063,7 @@ var EventType$1;
|
|
|
9282
9063
|
EventType[EventType["Meta"] = 4] = "Meta";
|
|
9283
9064
|
EventType[EventType["Custom"] = 5] = "Custom";
|
|
9284
9065
|
EventType[EventType["Plugin"] = 6] = "Plugin";
|
|
9285
|
-
})(EventType
|
|
9066
|
+
})(EventType || (EventType = {}));
|
|
9286
9067
|
var IncrementalSource;
|
|
9287
9068
|
(function (IncrementalSource) {
|
|
9288
9069
|
IncrementalSource[IncrementalSource["Mutation"] = 0] = "Mutation";
|
|
@@ -9897,9 +9678,9 @@ class MutationBuffer {
|
|
|
9897
9678
|
this.attributes.push(item);
|
|
9898
9679
|
}
|
|
9899
9680
|
if (m.attributeName === 'type' &&
|
|
9900
|
-
target.tagName === 'INPUT' &&
|
|
9681
|
+
m.target.tagName === 'INPUT' &&
|
|
9901
9682
|
(m.oldValue || '').toLowerCase() === 'password') {
|
|
9902
|
-
target.setAttribute('
|
|
9683
|
+
m.target.setAttribute('rr_is_password', 'true');
|
|
9903
9684
|
}
|
|
9904
9685
|
if (m.attributeName === 'style') {
|
|
9905
9686
|
const old = this.doc.createElement('span');
|
|
@@ -10296,25 +10077,27 @@ function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, un
|
|
|
10296
10077
|
isBlocked(target, blockClass, blockSelector, unblockSelector)) {
|
|
10297
10078
|
return;
|
|
10298
10079
|
}
|
|
10299
|
-
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
(ignoreSelector && el.matches(ignoreSelector))) {
|
|
10080
|
+
let type = target.type;
|
|
10081
|
+
if (target.classList.contains(ignoreClass) ||
|
|
10082
|
+
(ignoreSelector && target.matches(ignoreSelector))) {
|
|
10303
10083
|
return;
|
|
10304
10084
|
}
|
|
10305
|
-
let text =
|
|
10085
|
+
let text = target.value;
|
|
10306
10086
|
let isChecked = false;
|
|
10087
|
+
if (target.hasAttribute('rr_is_password')) {
|
|
10088
|
+
type = 'password';
|
|
10089
|
+
}
|
|
10307
10090
|
if (type === 'radio' || type === 'checkbox') {
|
|
10308
10091
|
isChecked = target.checked;
|
|
10309
10092
|
}
|
|
10310
|
-
if (hasInputMaskOptions({
|
|
10093
|
+
else if (hasInputMaskOptions({
|
|
10311
10094
|
maskInputOptions,
|
|
10312
10095
|
maskInputSelector,
|
|
10313
10096
|
tagName,
|
|
10314
10097
|
type,
|
|
10315
10098
|
})) {
|
|
10316
10099
|
text = maskInputValue({
|
|
10317
|
-
input:
|
|
10100
|
+
input: target,
|
|
10318
10101
|
maskInputOptions,
|
|
10319
10102
|
maskInputSelector,
|
|
10320
10103
|
unmaskInputSelector,
|
|
@@ -10331,18 +10114,8 @@ function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, un
|
|
|
10331
10114
|
.querySelectorAll(`input[type="radio"][name="${name}"]`)
|
|
10332
10115
|
.forEach((el) => {
|
|
10333
10116
|
if (el !== target) {
|
|
10334
|
-
const text = maskInputValue({
|
|
10335
|
-
input: el,
|
|
10336
|
-
maskInputOptions,
|
|
10337
|
-
maskInputSelector,
|
|
10338
|
-
unmaskInputSelector,
|
|
10339
|
-
tagName,
|
|
10340
|
-
type,
|
|
10341
|
-
value: getInputValue(el, tagName, type),
|
|
10342
|
-
maskInputFn,
|
|
10343
|
-
});
|
|
10344
10117
|
cbWithDedup(el, callbackWrapper(wrapEventWithUserTriggeredFlag)({
|
|
10345
|
-
text,
|
|
10118
|
+
text: el.value,
|
|
10346
10119
|
isChecked: !isChecked,
|
|
10347
10120
|
userTriggered: false,
|
|
10348
10121
|
}, userTriggeredOnInput));
|
|
@@ -11255,17 +11028,17 @@ function record(options = {}) {
|
|
|
11255
11028
|
wrappedEmit = (e, isCheckout) => {
|
|
11256
11029
|
var _a;
|
|
11257
11030
|
if (((_a = mutationBuffers[0]) === null || _a === void 0 ? void 0 : _a.isFrozen()) &&
|
|
11258
|
-
e.type !== EventType
|
|
11259
|
-
!(e.type === EventType
|
|
11031
|
+
e.type !== EventType.FullSnapshot &&
|
|
11032
|
+
!(e.type === EventType.IncrementalSnapshot &&
|
|
11260
11033
|
e.data.source === IncrementalSource.Mutation)) {
|
|
11261
11034
|
mutationBuffers.forEach((buf) => buf.unfreeze());
|
|
11262
11035
|
}
|
|
11263
11036
|
emit(eventProcessor(e), isCheckout);
|
|
11264
|
-
if (e.type === EventType
|
|
11037
|
+
if (e.type === EventType.FullSnapshot) {
|
|
11265
11038
|
lastFullSnapshotEvent = e;
|
|
11266
11039
|
incrementalSnapshotCount = 0;
|
|
11267
11040
|
}
|
|
11268
|
-
else if (e.type === EventType
|
|
11041
|
+
else if (e.type === EventType.IncrementalSnapshot) {
|
|
11269
11042
|
if (e.data.source === IncrementalSource.Mutation &&
|
|
11270
11043
|
e.data.isAttachIframe) {
|
|
11271
11044
|
return;
|
|
@@ -11281,16 +11054,16 @@ function record(options = {}) {
|
|
|
11281
11054
|
};
|
|
11282
11055
|
const wrappedMutationEmit = (m) => {
|
|
11283
11056
|
wrappedEmit(wrapEvent({
|
|
11284
|
-
type: EventType
|
|
11057
|
+
type: EventType.IncrementalSnapshot,
|
|
11285
11058
|
data: Object.assign({ source: IncrementalSource.Mutation }, m),
|
|
11286
11059
|
}));
|
|
11287
11060
|
};
|
|
11288
11061
|
const wrappedScrollEmit = (p) => wrappedEmit(wrapEvent({
|
|
11289
|
-
type: EventType
|
|
11062
|
+
type: EventType.IncrementalSnapshot,
|
|
11290
11063
|
data: Object.assign({ source: IncrementalSource.Scroll }, p),
|
|
11291
11064
|
}));
|
|
11292
11065
|
const wrappedCanvasMutationEmit = (p) => wrappedEmit(wrapEvent({
|
|
11293
|
-
type: EventType
|
|
11066
|
+
type: EventType.IncrementalSnapshot,
|
|
11294
11067
|
data: Object.assign({ source: IncrementalSource.CanvasMutation }, p),
|
|
11295
11068
|
}));
|
|
11296
11069
|
const iframeManager = new IframeManager({
|
|
@@ -11335,7 +11108,7 @@ function record(options = {}) {
|
|
|
11335
11108
|
takeFullSnapshot = (isCheckout = false) => {
|
|
11336
11109
|
var _a, _b, _c, _d;
|
|
11337
11110
|
wrappedEmit(wrapEvent({
|
|
11338
|
-
type: EventType
|
|
11111
|
+
type: EventType.Meta,
|
|
11339
11112
|
data: {
|
|
11340
11113
|
href: window.location.href,
|
|
11341
11114
|
width: getWindowWidth(),
|
|
@@ -11378,7 +11151,7 @@ function record(options = {}) {
|
|
|
11378
11151
|
}
|
|
11379
11152
|
mirror.map = idNodeMap;
|
|
11380
11153
|
wrappedEmit(wrapEvent({
|
|
11381
|
-
type: EventType
|
|
11154
|
+
type: EventType.FullSnapshot,
|
|
11382
11155
|
data: {
|
|
11383
11156
|
node,
|
|
11384
11157
|
initialOffset: {
|
|
@@ -11403,7 +11176,7 @@ function record(options = {}) {
|
|
|
11403
11176
|
const handlers = [];
|
|
11404
11177
|
handlers.push(on$1('DOMContentLoaded', () => {
|
|
11405
11178
|
wrappedEmit(wrapEvent({
|
|
11406
|
-
type: EventType
|
|
11179
|
+
type: EventType.DomContentLoaded,
|
|
11407
11180
|
data: {},
|
|
11408
11181
|
}));
|
|
11409
11182
|
}));
|
|
@@ -11413,40 +11186,40 @@ function record(options = {}) {
|
|
|
11413
11186
|
onMutation,
|
|
11414
11187
|
mutationCb: wrappedMutationEmit,
|
|
11415
11188
|
mousemoveCb: (positions, source) => wrappedEmit(wrapEvent({
|
|
11416
|
-
type: EventType
|
|
11189
|
+
type: EventType.IncrementalSnapshot,
|
|
11417
11190
|
data: {
|
|
11418
11191
|
source,
|
|
11419
11192
|
positions,
|
|
11420
11193
|
},
|
|
11421
11194
|
})),
|
|
11422
11195
|
mouseInteractionCb: (d) => wrappedEmit(wrapEvent({
|
|
11423
|
-
type: EventType
|
|
11196
|
+
type: EventType.IncrementalSnapshot,
|
|
11424
11197
|
data: Object.assign({ source: IncrementalSource.MouseInteraction }, d),
|
|
11425
11198
|
})),
|
|
11426
11199
|
scrollCb: wrappedScrollEmit,
|
|
11427
11200
|
viewportResizeCb: (d) => wrappedEmit(wrapEvent({
|
|
11428
|
-
type: EventType
|
|
11201
|
+
type: EventType.IncrementalSnapshot,
|
|
11429
11202
|
data: Object.assign({ source: IncrementalSource.ViewportResize }, d),
|
|
11430
11203
|
})),
|
|
11431
11204
|
inputCb: (v) => wrappedEmit(wrapEvent({
|
|
11432
|
-
type: EventType
|
|
11205
|
+
type: EventType.IncrementalSnapshot,
|
|
11433
11206
|
data: Object.assign({ source: IncrementalSource.Input }, v),
|
|
11434
11207
|
})),
|
|
11435
11208
|
mediaInteractionCb: (p) => wrappedEmit(wrapEvent({
|
|
11436
|
-
type: EventType
|
|
11209
|
+
type: EventType.IncrementalSnapshot,
|
|
11437
11210
|
data: Object.assign({ source: IncrementalSource.MediaInteraction }, p),
|
|
11438
11211
|
})),
|
|
11439
11212
|
styleSheetRuleCb: (r) => wrappedEmit(wrapEvent({
|
|
11440
|
-
type: EventType
|
|
11213
|
+
type: EventType.IncrementalSnapshot,
|
|
11441
11214
|
data: Object.assign({ source: IncrementalSource.StyleSheetRule }, r),
|
|
11442
11215
|
})),
|
|
11443
11216
|
styleDeclarationCb: (r) => wrappedEmit(wrapEvent({
|
|
11444
|
-
type: EventType
|
|
11217
|
+
type: EventType.IncrementalSnapshot,
|
|
11445
11218
|
data: Object.assign({ source: IncrementalSource.StyleDeclaration }, r),
|
|
11446
11219
|
})),
|
|
11447
11220
|
canvasMutationCb: wrappedCanvasMutationEmit,
|
|
11448
11221
|
fontCb: (p) => wrappedEmit(wrapEvent({
|
|
11449
|
-
type: EventType
|
|
11222
|
+
type: EventType.IncrementalSnapshot,
|
|
11450
11223
|
data: Object.assign({ source: IncrementalSource.Font }, p),
|
|
11451
11224
|
})),
|
|
11452
11225
|
blockClass,
|
|
@@ -11479,7 +11252,7 @@ function record(options = {}) {
|
|
|
11479
11252
|
observer: p.observer,
|
|
11480
11253
|
options: p.options,
|
|
11481
11254
|
callback: (payload) => wrappedEmit(wrapEvent({
|
|
11482
|
-
type: EventType
|
|
11255
|
+
type: EventType.Plugin,
|
|
11483
11256
|
data: {
|
|
11484
11257
|
plugin: p.name,
|
|
11485
11258
|
payload,
|
|
@@ -11507,7 +11280,7 @@ function record(options = {}) {
|
|
|
11507
11280
|
else {
|
|
11508
11281
|
handlers.push(on$1('load', () => {
|
|
11509
11282
|
wrappedEmit(wrapEvent({
|
|
11510
|
-
type: EventType
|
|
11283
|
+
type: EventType.Load,
|
|
11511
11284
|
data: {},
|
|
11512
11285
|
}));
|
|
11513
11286
|
init();
|
|
@@ -11526,7 +11299,7 @@ record.addCustomEvent = (tag, payload) => {
|
|
|
11526
11299
|
throw new Error('please add custom event after start recording');
|
|
11527
11300
|
}
|
|
11528
11301
|
wrappedEmit(wrapEvent({
|
|
11529
|
-
type: EventType
|
|
11302
|
+
type: EventType.Custom,
|
|
11530
11303
|
data: {
|
|
11531
11304
|
tag,
|
|
11532
11305
|
payload,
|
|
@@ -11544,503 +11317,6 @@ record.takeFullSnapshot = (isCheckout) => {
|
|
|
11544
11317
|
};
|
|
11545
11318
|
record.mirror = mirror;
|
|
11546
11319
|
|
|
11547
|
-
/**
|
|
11548
|
-
* Create a breadcrumb for a replay.
|
|
11549
|
-
*/
|
|
11550
|
-
function createBreadcrumb(
|
|
11551
|
-
breadcrumb,
|
|
11552
|
-
) {
|
|
11553
|
-
return {
|
|
11554
|
-
timestamp: Date.now() / 1000,
|
|
11555
|
-
type: 'default',
|
|
11556
|
-
...breadcrumb,
|
|
11557
|
-
};
|
|
11558
|
-
}
|
|
11559
|
-
|
|
11560
|
-
var NodeType;
|
|
11561
|
-
(function (NodeType) {
|
|
11562
|
-
NodeType[NodeType["Document"] = 0] = "Document";
|
|
11563
|
-
NodeType[NodeType["DocumentType"] = 1] = "DocumentType";
|
|
11564
|
-
NodeType[NodeType["Element"] = 2] = "Element";
|
|
11565
|
-
NodeType[NodeType["Text"] = 3] = "Text";
|
|
11566
|
-
NodeType[NodeType["CDATA"] = 4] = "CDATA";
|
|
11567
|
-
NodeType[NodeType["Comment"] = 5] = "Comment";
|
|
11568
|
-
})(NodeType || (NodeType = {}));
|
|
11569
|
-
|
|
11570
|
-
/* eslint-disable @typescript-eslint/naming-convention */
|
|
11571
|
-
|
|
11572
|
-
var EventType; (function (EventType) {
|
|
11573
|
-
const DomContentLoaded = 0; EventType[EventType["DomContentLoaded"] = DomContentLoaded] = "DomContentLoaded";
|
|
11574
|
-
const Load = 1; EventType[EventType["Load"] = Load] = "Load";
|
|
11575
|
-
const FullSnapshot = 2; EventType[EventType["FullSnapshot"] = FullSnapshot] = "FullSnapshot";
|
|
11576
|
-
const IncrementalSnapshot = 3; EventType[EventType["IncrementalSnapshot"] = IncrementalSnapshot] = "IncrementalSnapshot";
|
|
11577
|
-
const Meta = 4; EventType[EventType["Meta"] = Meta] = "Meta";
|
|
11578
|
-
const Custom = 5; EventType[EventType["Custom"] = Custom] = "Custom";
|
|
11579
|
-
const Plugin = 6; EventType[EventType["Plugin"] = Plugin] = "Plugin";
|
|
11580
|
-
})(EventType || (EventType = {}));
|
|
11581
|
-
|
|
11582
|
-
/**
|
|
11583
|
-
* This is a partial copy of rrweb's eventWithTime type which only contains the properties
|
|
11584
|
-
* we specifcally need in the SDK.
|
|
11585
|
-
*/
|
|
11586
|
-
|
|
11587
|
-
/**
|
|
11588
|
-
* Converts a timestamp to ms, if it was in s, or keeps it as ms.
|
|
11589
|
-
*/
|
|
11590
|
-
function timestampToMs(timestamp) {
|
|
11591
|
-
const isMs = timestamp > 9999999999;
|
|
11592
|
-
return isMs ? timestamp : timestamp * 1000;
|
|
11593
|
-
}
|
|
11594
|
-
|
|
11595
|
-
/**
|
|
11596
|
-
* Add an event to the event buffer.
|
|
11597
|
-
* `isCheckout` is true if this is either the very first event, or an event triggered by `checkoutEveryNms`.
|
|
11598
|
-
*/
|
|
11599
|
-
async function addEvent(
|
|
11600
|
-
replay,
|
|
11601
|
-
event,
|
|
11602
|
-
isCheckout,
|
|
11603
|
-
) {
|
|
11604
|
-
if (!replay.eventBuffer) {
|
|
11605
|
-
// This implies that `_isEnabled` is false
|
|
11606
|
-
return null;
|
|
11607
|
-
}
|
|
11608
|
-
|
|
11609
|
-
if (replay.isPaused()) {
|
|
11610
|
-
// Do not add to event buffer when recording is paused
|
|
11611
|
-
return null;
|
|
11612
|
-
}
|
|
11613
|
-
|
|
11614
|
-
const timestampInMs = timestampToMs(event.timestamp);
|
|
11615
|
-
|
|
11616
|
-
// Throw out events that happen more than 5 minutes ago. This can happen if
|
|
11617
|
-
// page has been left open and idle for a long period of time and user
|
|
11618
|
-
// comes back to trigger a new session. The performance entries rely on
|
|
11619
|
-
// `performance.timeOrigin`, which is when the page first opened.
|
|
11620
|
-
if (timestampInMs + replay.timeouts.sessionIdlePause < Date.now()) {
|
|
11621
|
-
return null;
|
|
11622
|
-
}
|
|
11623
|
-
|
|
11624
|
-
try {
|
|
11625
|
-
if (isCheckout) {
|
|
11626
|
-
replay.eventBuffer.clear();
|
|
11627
|
-
}
|
|
11628
|
-
|
|
11629
|
-
const replayOptions = replay.getOptions();
|
|
11630
|
-
|
|
11631
|
-
const eventAfterPossibleCallback =
|
|
11632
|
-
typeof replayOptions.beforeAddRecordingEvent === 'function' && event.type === EventType.Custom
|
|
11633
|
-
? replayOptions.beforeAddRecordingEvent(event)
|
|
11634
|
-
: event;
|
|
11635
|
-
|
|
11636
|
-
if (!eventAfterPossibleCallback) {
|
|
11637
|
-
return;
|
|
11638
|
-
}
|
|
11639
|
-
|
|
11640
|
-
return await replay.eventBuffer.addEvent(eventAfterPossibleCallback);
|
|
11641
|
-
} catch (error) {
|
|
11642
|
-
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(error);
|
|
11643
|
-
await replay.stop('addEvent');
|
|
11644
|
-
|
|
11645
|
-
const client = getCurrentHub().getClient();
|
|
11646
|
-
|
|
11647
|
-
if (client) {
|
|
11648
|
-
client.recordDroppedEvent('internal_sdk_error', 'replay');
|
|
11649
|
-
}
|
|
11650
|
-
}
|
|
11651
|
-
}
|
|
11652
|
-
|
|
11653
|
-
/**
|
|
11654
|
-
* Add a breadcrumb event to replay.
|
|
11655
|
-
*/
|
|
11656
|
-
function addBreadcrumbEvent(replay, breadcrumb) {
|
|
11657
|
-
if (breadcrumb.category === 'sentry.transaction') {
|
|
11658
|
-
return;
|
|
11659
|
-
}
|
|
11660
|
-
|
|
11661
|
-
if (['ui.click', 'ui.input'].includes(breadcrumb.category )) {
|
|
11662
|
-
replay.triggerUserActivity();
|
|
11663
|
-
} else {
|
|
11664
|
-
replay.checkAndHandleExpiredSession();
|
|
11665
|
-
}
|
|
11666
|
-
|
|
11667
|
-
replay.addUpdate(() => {
|
|
11668
|
-
void addEvent(replay, {
|
|
11669
|
-
type: EventType$1.Custom,
|
|
11670
|
-
// TODO: We were converting from ms to seconds for breadcrumbs, spans,
|
|
11671
|
-
// but maybe we should just keep them as milliseconds
|
|
11672
|
-
timestamp: (breadcrumb.timestamp || 0) * 1000,
|
|
11673
|
-
data: {
|
|
11674
|
-
tag: 'breadcrumb',
|
|
11675
|
-
// normalize to max. 10 depth and 1_000 properties per object
|
|
11676
|
-
payload: normalize(breadcrumb, 10, 1000),
|
|
11677
|
-
},
|
|
11678
|
-
});
|
|
11679
|
-
|
|
11680
|
-
// Do not flush after console log messages
|
|
11681
|
-
return breadcrumb.category === 'console';
|
|
11682
|
-
});
|
|
11683
|
-
}
|
|
11684
|
-
|
|
11685
|
-
/**
|
|
11686
|
-
* Detect a slow click on a button/a tag,
|
|
11687
|
-
* and potentially create a corresponding breadcrumb.
|
|
11688
|
-
*/
|
|
11689
|
-
function detectSlowClick(
|
|
11690
|
-
replay,
|
|
11691
|
-
config,
|
|
11692
|
-
clickBreadcrumb,
|
|
11693
|
-
node,
|
|
11694
|
-
) {
|
|
11695
|
-
if (ignoreElement(node, config)) {
|
|
11696
|
-
return;
|
|
11697
|
-
}
|
|
11698
|
-
|
|
11699
|
-
/*
|
|
11700
|
-
We consider a slow click a click on a button/a, which does not trigger one of:
|
|
11701
|
-
- DOM mutation
|
|
11702
|
-
- Scroll (within 100ms)
|
|
11703
|
-
Within the given threshold time.
|
|
11704
|
-
After time timeout time, we stop listening and mark it as a slow click anyhow.
|
|
11705
|
-
*/
|
|
11706
|
-
|
|
11707
|
-
let cleanup = () => {
|
|
11708
|
-
// replaced further down
|
|
11709
|
-
};
|
|
11710
|
-
|
|
11711
|
-
// After timeout time, def. consider this a slow click, and stop watching for mutations
|
|
11712
|
-
const timeout = setTimeout(() => {
|
|
11713
|
-
handleSlowClick(replay, clickBreadcrumb, config.timeout, 'timeout');
|
|
11714
|
-
cleanup();
|
|
11715
|
-
}, config.timeout);
|
|
11716
|
-
|
|
11717
|
-
const mutationHandler = () => {
|
|
11718
|
-
maybeHandleSlowClick(replay, clickBreadcrumb, config.threshold, config.timeout, 'mutation');
|
|
11719
|
-
cleanup();
|
|
11720
|
-
};
|
|
11721
|
-
|
|
11722
|
-
const scrollHandler = () => {
|
|
11723
|
-
maybeHandleSlowClick(replay, clickBreadcrumb, config.scrollTimeout, config.timeout, 'scroll');
|
|
11724
|
-
cleanup();
|
|
11725
|
-
};
|
|
11726
|
-
|
|
11727
|
-
const obs = new MutationObserver(mutationHandler);
|
|
11728
|
-
|
|
11729
|
-
obs.observe(WINDOW.document.documentElement, {
|
|
11730
|
-
attributes: true,
|
|
11731
|
-
characterData: true,
|
|
11732
|
-
childList: true,
|
|
11733
|
-
subtree: true,
|
|
11734
|
-
});
|
|
11735
|
-
|
|
11736
|
-
WINDOW.addEventListener('scroll', scrollHandler);
|
|
11737
|
-
|
|
11738
|
-
// Stop listening to scroll timeouts early
|
|
11739
|
-
const scrollTimeout = setTimeout(() => {
|
|
11740
|
-
WINDOW.removeEventListener('scroll', scrollHandler);
|
|
11741
|
-
}, config.scrollTimeout);
|
|
11742
|
-
|
|
11743
|
-
cleanup = () => {
|
|
11744
|
-
clearTimeout(timeout);
|
|
11745
|
-
clearTimeout(scrollTimeout);
|
|
11746
|
-
obs.disconnect();
|
|
11747
|
-
WINDOW.removeEventListener('scroll', scrollHandler);
|
|
11748
|
-
};
|
|
11749
|
-
}
|
|
11750
|
-
|
|
11751
|
-
function maybeHandleSlowClick(
|
|
11752
|
-
replay,
|
|
11753
|
-
clickBreadcrumb,
|
|
11754
|
-
threshold,
|
|
11755
|
-
timeout,
|
|
11756
|
-
endReason,
|
|
11757
|
-
) {
|
|
11758
|
-
const now = Date.now();
|
|
11759
|
-
const timeAfterClickMs = now - clickBreadcrumb.timestamp * 1000;
|
|
11760
|
-
|
|
11761
|
-
if (timeAfterClickMs > threshold) {
|
|
11762
|
-
handleSlowClick(replay, clickBreadcrumb, Math.min(timeAfterClickMs, timeout), endReason);
|
|
11763
|
-
return true;
|
|
11764
|
-
}
|
|
11765
|
-
|
|
11766
|
-
return false;
|
|
11767
|
-
}
|
|
11768
|
-
|
|
11769
|
-
function handleSlowClick(
|
|
11770
|
-
replay,
|
|
11771
|
-
clickBreadcrumb,
|
|
11772
|
-
timeAfterClickMs,
|
|
11773
|
-
endReason,
|
|
11774
|
-
) {
|
|
11775
|
-
const breadcrumb = {
|
|
11776
|
-
message: clickBreadcrumb.message,
|
|
11777
|
-
timestamp: clickBreadcrumb.timestamp,
|
|
11778
|
-
category: 'ui.slowClickDetected',
|
|
11779
|
-
data: {
|
|
11780
|
-
...clickBreadcrumb.data,
|
|
11781
|
-
url: WINDOW.location.href,
|
|
11782
|
-
// TODO FN: add parametrized route, when possible
|
|
11783
|
-
timeAfterClickMs,
|
|
11784
|
-
endReason,
|
|
11785
|
-
},
|
|
11786
|
-
};
|
|
11787
|
-
|
|
11788
|
-
addBreadcrumbEvent(replay, breadcrumb);
|
|
11789
|
-
}
|
|
11790
|
-
|
|
11791
|
-
const SLOW_CLICK_IGNORE_TAGS = ['SELECT', 'OPTION'];
|
|
11792
|
-
|
|
11793
|
-
function ignoreElement(node, config) {
|
|
11794
|
-
// If <input> tag, we only want to consider input[type='submit'] & input[type='button']
|
|
11795
|
-
if (node.tagName === 'INPUT' && !['submit', 'button'].includes(node.getAttribute('type') || '')) {
|
|
11796
|
-
return true;
|
|
11797
|
-
}
|
|
11798
|
-
|
|
11799
|
-
if (SLOW_CLICK_IGNORE_TAGS.includes(node.tagName)) {
|
|
11800
|
-
return true;
|
|
11801
|
-
}
|
|
11802
|
-
|
|
11803
|
-
// If <a> tag, detect special variants that may not lead to an action
|
|
11804
|
-
// If target !== _self, we may open the link somewhere else, which would lead to no action
|
|
11805
|
-
// Also, when downloading a file, we may not leave the page, but still not trigger an action
|
|
11806
|
-
if (
|
|
11807
|
-
node.tagName === 'A' &&
|
|
11808
|
-
(node.hasAttribute('download') || (node.hasAttribute('target') && node.getAttribute('target') !== '_self'))
|
|
11809
|
-
) {
|
|
11810
|
-
return true;
|
|
11811
|
-
}
|
|
11812
|
-
|
|
11813
|
-
if (config.ignoreSelector && node.matches(config.ignoreSelector)) {
|
|
11814
|
-
return true;
|
|
11815
|
-
}
|
|
11816
|
-
|
|
11817
|
-
return false;
|
|
11818
|
-
}
|
|
11819
|
-
|
|
11820
|
-
// Note that these are the serialized attributes and not attributes directly on
|
|
11821
|
-
// the DOM Node. Attributes we are interested in:
|
|
11822
|
-
const ATTRIBUTES_TO_RECORD = new Set([
|
|
11823
|
-
'id',
|
|
11824
|
-
'class',
|
|
11825
|
-
'aria-label',
|
|
11826
|
-
'role',
|
|
11827
|
-
'name',
|
|
11828
|
-
'alt',
|
|
11829
|
-
'title',
|
|
11830
|
-
'data-test-id',
|
|
11831
|
-
'data-testid',
|
|
11832
|
-
]);
|
|
11833
|
-
|
|
11834
|
-
/**
|
|
11835
|
-
* Inclusion list of attributes that we want to record from the DOM element
|
|
11836
|
-
*/
|
|
11837
|
-
function getAttributesToRecord(attributes) {
|
|
11838
|
-
const obj = {};
|
|
11839
|
-
for (const key in attributes) {
|
|
11840
|
-
if (ATTRIBUTES_TO_RECORD.has(key)) {
|
|
11841
|
-
let normalizedKey = key;
|
|
11842
|
-
|
|
11843
|
-
if (key === 'data-testid' || key === 'data-test-id') {
|
|
11844
|
-
normalizedKey = 'testId';
|
|
11845
|
-
}
|
|
11846
|
-
|
|
11847
|
-
obj[normalizedKey] = attributes[key];
|
|
11848
|
-
}
|
|
11849
|
-
}
|
|
11850
|
-
|
|
11851
|
-
return obj;
|
|
11852
|
-
}
|
|
11853
|
-
|
|
11854
|
-
const handleDomListener = (
|
|
11855
|
-
replay,
|
|
11856
|
-
) => {
|
|
11857
|
-
const slowClickExperiment = replay.getOptions()._experiments.slowClicks;
|
|
11858
|
-
|
|
11859
|
-
const slowClickConfig = slowClickExperiment
|
|
11860
|
-
? {
|
|
11861
|
-
threshold: slowClickExperiment.threshold,
|
|
11862
|
-
timeout: slowClickExperiment.timeout,
|
|
11863
|
-
scrollTimeout: slowClickExperiment.scrollTimeout,
|
|
11864
|
-
ignoreSelector: slowClickExperiment.ignoreSelectors ? slowClickExperiment.ignoreSelectors.join(',') : '',
|
|
11865
|
-
}
|
|
11866
|
-
: undefined;
|
|
11867
|
-
|
|
11868
|
-
return (handlerData) => {
|
|
11869
|
-
if (!replay.isEnabled()) {
|
|
11870
|
-
return;
|
|
11871
|
-
}
|
|
11872
|
-
|
|
11873
|
-
const result = handleDom(handlerData);
|
|
11874
|
-
|
|
11875
|
-
if (!result) {
|
|
11876
|
-
return;
|
|
11877
|
-
}
|
|
11878
|
-
|
|
11879
|
-
const isClick = handlerData.name === 'click';
|
|
11880
|
-
const event = isClick && (handlerData.event );
|
|
11881
|
-
// Ignore clicks if ctrl/alt/meta keys are held down as they alter behavior of clicks (e.g. open in new tab)
|
|
11882
|
-
if (isClick && slowClickConfig && event && !event.altKey && !event.metaKey && !event.ctrlKey) {
|
|
11883
|
-
detectSlowClick(
|
|
11884
|
-
replay,
|
|
11885
|
-
slowClickConfig,
|
|
11886
|
-
result ,
|
|
11887
|
-
getClickTargetNode(handlerData.event) ,
|
|
11888
|
-
);
|
|
11889
|
-
}
|
|
11890
|
-
|
|
11891
|
-
addBreadcrumbEvent(replay, result);
|
|
11892
|
-
};
|
|
11893
|
-
};
|
|
11894
|
-
|
|
11895
|
-
/** Get the base DOM breadcrumb. */
|
|
11896
|
-
function getBaseDomBreadcrumb(target, message) {
|
|
11897
|
-
// `__sn` property is the serialized node created by rrweb
|
|
11898
|
-
const serializedNode = target && isRrwebNode(target) && target.__sn.type === NodeType.Element ? target.__sn : null;
|
|
11899
|
-
|
|
11900
|
-
return {
|
|
11901
|
-
message,
|
|
11902
|
-
data: serializedNode
|
|
11903
|
-
? {
|
|
11904
|
-
nodeId: serializedNode.id,
|
|
11905
|
-
node: {
|
|
11906
|
-
id: serializedNode.id,
|
|
11907
|
-
tagName: serializedNode.tagName,
|
|
11908
|
-
textContent: target
|
|
11909
|
-
? Array.from(target.childNodes)
|
|
11910
|
-
.map(
|
|
11911
|
-
(node) => '__sn' in node && node.__sn.type === NodeType.Text && node.__sn.textContent,
|
|
11912
|
-
)
|
|
11913
|
-
.filter(Boolean) // filter out empty values
|
|
11914
|
-
.map(text => (text ).trim())
|
|
11915
|
-
.join('')
|
|
11916
|
-
: '',
|
|
11917
|
-
attributes: getAttributesToRecord(serializedNode.attributes),
|
|
11918
|
-
},
|
|
11919
|
-
}
|
|
11920
|
-
: {},
|
|
11921
|
-
};
|
|
11922
|
-
}
|
|
11923
|
-
|
|
11924
|
-
/**
|
|
11925
|
-
* An event handler to react to DOM events.
|
|
11926
|
-
* Exported for tests.
|
|
11927
|
-
*/
|
|
11928
|
-
function handleDom(handlerData) {
|
|
11929
|
-
const { target, message } = getDomTarget(handlerData);
|
|
11930
|
-
|
|
11931
|
-
return createBreadcrumb({
|
|
11932
|
-
category: `ui.${handlerData.name}`,
|
|
11933
|
-
...getBaseDomBreadcrumb(target, message),
|
|
11934
|
-
});
|
|
11935
|
-
}
|
|
11936
|
-
|
|
11937
|
-
function getDomTarget(handlerData) {
|
|
11938
|
-
const isClick = handlerData.name === 'click';
|
|
11939
|
-
|
|
11940
|
-
let message;
|
|
11941
|
-
let target = null;
|
|
11942
|
-
|
|
11943
|
-
// Accessing event.target can throw (see getsentry/raven-js#838, #768)
|
|
11944
|
-
try {
|
|
11945
|
-
target = isClick ? getClickTargetNode(handlerData.event) : getTargetNode(handlerData.event);
|
|
11946
|
-
message = htmlTreeAsString(target, { maxStringLength: 200 }) || '<unknown>';
|
|
11947
|
-
} catch (e) {
|
|
11948
|
-
message = '<unknown>';
|
|
11949
|
-
}
|
|
11950
|
-
|
|
11951
|
-
return { target, message };
|
|
11952
|
-
}
|
|
11953
|
-
|
|
11954
|
-
function isRrwebNode(node) {
|
|
11955
|
-
return '__sn' in node;
|
|
11956
|
-
}
|
|
11957
|
-
|
|
11958
|
-
function getTargetNode(event) {
|
|
11959
|
-
if (isEventWithTarget(event)) {
|
|
11960
|
-
return event.target ;
|
|
11961
|
-
}
|
|
11962
|
-
|
|
11963
|
-
return event;
|
|
11964
|
-
}
|
|
11965
|
-
|
|
11966
|
-
const INTERACTIVE_SELECTOR = 'button,a';
|
|
11967
|
-
|
|
11968
|
-
// For clicks, we check if the target is inside of a button or link
|
|
11969
|
-
// If so, we use this as the target instead
|
|
11970
|
-
// This is useful because if you click on the image in <button><img></button>,
|
|
11971
|
-
// The target will be the image, not the button, which we don't want here
|
|
11972
|
-
function getClickTargetNode(event) {
|
|
11973
|
-
const target = getTargetNode(event);
|
|
11974
|
-
|
|
11975
|
-
if (!target || !(target instanceof Element)) {
|
|
11976
|
-
return target;
|
|
11977
|
-
}
|
|
11978
|
-
|
|
11979
|
-
const closestInteractive = target.closest(INTERACTIVE_SELECTOR);
|
|
11980
|
-
return closestInteractive || target;
|
|
11981
|
-
}
|
|
11982
|
-
|
|
11983
|
-
function isEventWithTarget(event) {
|
|
11984
|
-
return typeof event === 'object' && !!event && 'target' in event;
|
|
11985
|
-
}
|
|
11986
|
-
|
|
11987
|
-
/** Handle keyboard events & create breadcrumbs. */
|
|
11988
|
-
function handleKeyboardEvent(replay, event) {
|
|
11989
|
-
if (!replay.isEnabled()) {
|
|
11990
|
-
return;
|
|
11991
|
-
}
|
|
11992
|
-
|
|
11993
|
-
replay.triggerUserActivity();
|
|
11994
|
-
|
|
11995
|
-
const breadcrumb = getKeyboardBreadcrumb(event);
|
|
11996
|
-
|
|
11997
|
-
if (!breadcrumb) {
|
|
11998
|
-
return;
|
|
11999
|
-
}
|
|
12000
|
-
|
|
12001
|
-
addBreadcrumbEvent(replay, breadcrumb);
|
|
12002
|
-
}
|
|
12003
|
-
|
|
12004
|
-
/** exported only for tests */
|
|
12005
|
-
function getKeyboardBreadcrumb(event) {
|
|
12006
|
-
const { metaKey, shiftKey, ctrlKey, altKey, key, target } = event;
|
|
12007
|
-
|
|
12008
|
-
// never capture for input fields
|
|
12009
|
-
if (!target || isInputElement(target )) {
|
|
12010
|
-
return null;
|
|
12011
|
-
}
|
|
12012
|
-
|
|
12013
|
-
// Note: We do not consider shift here, as that means "uppercase"
|
|
12014
|
-
const hasModifierKey = metaKey || ctrlKey || altKey;
|
|
12015
|
-
const isCharacterKey = key.length === 1; // other keys like Escape, Tab, etc have a longer length
|
|
12016
|
-
|
|
12017
|
-
// Do not capture breadcrumb if only a word key is pressed
|
|
12018
|
-
// This could leak e.g. user input
|
|
12019
|
-
if (!hasModifierKey && isCharacterKey) {
|
|
12020
|
-
return null;
|
|
12021
|
-
}
|
|
12022
|
-
|
|
12023
|
-
const message = htmlTreeAsString(target, { maxStringLength: 200 }) || '<unknown>';
|
|
12024
|
-
const baseBreadcrumb = getBaseDomBreadcrumb(target , message);
|
|
12025
|
-
|
|
12026
|
-
return createBreadcrumb({
|
|
12027
|
-
category: 'ui.keyDown',
|
|
12028
|
-
message,
|
|
12029
|
-
data: {
|
|
12030
|
-
...baseBreadcrumb.data,
|
|
12031
|
-
metaKey,
|
|
12032
|
-
shiftKey,
|
|
12033
|
-
ctrlKey,
|
|
12034
|
-
altKey,
|
|
12035
|
-
key,
|
|
12036
|
-
},
|
|
12037
|
-
});
|
|
12038
|
-
}
|
|
12039
|
-
|
|
12040
|
-
function isInputElement(target) {
|
|
12041
|
-
return target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable;
|
|
12042
|
-
}
|
|
12043
|
-
|
|
12044
11320
|
const NAVIGATION_ENTRY_KEYS = [
|
|
12045
11321
|
'name',
|
|
12046
11322
|
'type',
|
|
@@ -12194,19 +11470,20 @@ class EventBufferArray {
|
|
|
12194
11470
|
return this.events.length > 0;
|
|
12195
11471
|
}
|
|
12196
11472
|
|
|
12197
|
-
/** @inheritdoc */
|
|
12198
|
-
get type() {
|
|
12199
|
-
return 'sync';
|
|
12200
|
-
}
|
|
12201
|
-
|
|
12202
11473
|
/** @inheritdoc */
|
|
12203
11474
|
destroy() {
|
|
12204
11475
|
this.events = [];
|
|
12205
11476
|
}
|
|
12206
11477
|
|
|
12207
11478
|
/** @inheritdoc */
|
|
12208
|
-
async addEvent(event) {
|
|
11479
|
+
async addEvent(event, isCheckout) {
|
|
11480
|
+
if (isCheckout) {
|
|
11481
|
+
this.events = [event];
|
|
11482
|
+
return;
|
|
11483
|
+
}
|
|
11484
|
+
|
|
12209
11485
|
this.events.push(event);
|
|
11486
|
+
return;
|
|
12210
11487
|
}
|
|
12211
11488
|
|
|
12212
11489
|
/** @inheritdoc */
|
|
@@ -12220,22 +11497,6 @@ class EventBufferArray {
|
|
|
12220
11497
|
resolve(JSON.stringify(eventsRet));
|
|
12221
11498
|
});
|
|
12222
11499
|
}
|
|
12223
|
-
|
|
12224
|
-
/** @inheritdoc */
|
|
12225
|
-
clear() {
|
|
12226
|
-
this.events = [];
|
|
12227
|
-
}
|
|
12228
|
-
|
|
12229
|
-
/** @inheritdoc */
|
|
12230
|
-
getEarliestTimestamp() {
|
|
12231
|
-
const timestamp = this.events.map(event => event.timestamp).sort()[0];
|
|
12232
|
-
|
|
12233
|
-
if (!timestamp) {
|
|
12234
|
-
return null;
|
|
12235
|
-
}
|
|
12236
|
-
|
|
12237
|
-
return timestampToMs(timestamp);
|
|
12238
|
-
}
|
|
12239
11500
|
}
|
|
12240
11501
|
|
|
12241
11502
|
/**
|
|
@@ -12343,20 +11604,11 @@ class WorkerHandler {
|
|
|
12343
11604
|
* Exported only for testing.
|
|
12344
11605
|
*/
|
|
12345
11606
|
class EventBufferCompressionWorker {
|
|
11607
|
+
/** @inheritdoc */
|
|
12346
11608
|
|
|
12347
11609
|
constructor(worker) {
|
|
12348
11610
|
this._worker = new WorkerHandler(worker);
|
|
12349
|
-
this.
|
|
12350
|
-
}
|
|
12351
|
-
|
|
12352
|
-
/** @inheritdoc */
|
|
12353
|
-
get hasEvents() {
|
|
12354
|
-
return !!this._earliestTimestamp;
|
|
12355
|
-
}
|
|
12356
|
-
|
|
12357
|
-
/** @inheritdoc */
|
|
12358
|
-
get type() {
|
|
12359
|
-
return 'worker';
|
|
11611
|
+
this.hasEvents = false;
|
|
12360
11612
|
}
|
|
12361
11613
|
|
|
12362
11614
|
/**
|
|
@@ -12379,10 +11631,13 @@ class EventBufferCompressionWorker {
|
|
|
12379
11631
|
*
|
|
12380
11632
|
* Returns true if event was successfuly received and processed by worker.
|
|
12381
11633
|
*/
|
|
12382
|
-
addEvent(event) {
|
|
12383
|
-
|
|
12384
|
-
|
|
12385
|
-
|
|
11634
|
+
async addEvent(event, isCheckout) {
|
|
11635
|
+
this.hasEvents = true;
|
|
11636
|
+
|
|
11637
|
+
if (isCheckout) {
|
|
11638
|
+
// This event is a checkout, make sure worker buffer is cleared before
|
|
11639
|
+
// proceeding.
|
|
11640
|
+
await this._clear();
|
|
12386
11641
|
}
|
|
12387
11642
|
|
|
12388
11643
|
return this._sendEventToWorker(event);
|
|
@@ -12395,18 +11650,6 @@ class EventBufferCompressionWorker {
|
|
|
12395
11650
|
return this._finishRequest();
|
|
12396
11651
|
}
|
|
12397
11652
|
|
|
12398
|
-
/** @inheritdoc */
|
|
12399
|
-
clear() {
|
|
12400
|
-
this._earliestTimestamp = null;
|
|
12401
|
-
// We do not wait on this, as we assume the order of messages is consistent for the worker
|
|
12402
|
-
void this._worker.postMessage('clear');
|
|
12403
|
-
}
|
|
12404
|
-
|
|
12405
|
-
/** @inheritdoc */
|
|
12406
|
-
getEarliestTimestamp() {
|
|
12407
|
-
return this._earliestTimestamp;
|
|
12408
|
-
}
|
|
12409
|
-
|
|
12410
11653
|
/**
|
|
12411
11654
|
* Send the event to the worker.
|
|
12412
11655
|
*/
|
|
@@ -12420,10 +11663,15 @@ class EventBufferCompressionWorker {
|
|
|
12420
11663
|
async _finishRequest() {
|
|
12421
11664
|
const response = await this._worker.postMessage('finish');
|
|
12422
11665
|
|
|
12423
|
-
this.
|
|
11666
|
+
this.hasEvents = false;
|
|
12424
11667
|
|
|
12425
11668
|
return response;
|
|
12426
11669
|
}
|
|
11670
|
+
|
|
11671
|
+
/** Clear any pending events from the worker. */
|
|
11672
|
+
_clear() {
|
|
11673
|
+
return this._worker.postMessage('clear');
|
|
11674
|
+
}
|
|
12427
11675
|
}
|
|
12428
11676
|
|
|
12429
11677
|
/**
|
|
@@ -12441,11 +11689,6 @@ class EventBufferProxy {
|
|
|
12441
11689
|
this._ensureWorkerIsLoadedPromise = this._ensureWorkerIsLoaded();
|
|
12442
11690
|
}
|
|
12443
11691
|
|
|
12444
|
-
/** @inheritdoc */
|
|
12445
|
-
get type() {
|
|
12446
|
-
return this._used.type;
|
|
12447
|
-
}
|
|
12448
|
-
|
|
12449
11692
|
/** @inheritDoc */
|
|
12450
11693
|
get hasEvents() {
|
|
12451
11694
|
return this._used.hasEvents;
|
|
@@ -12457,23 +11700,13 @@ class EventBufferProxy {
|
|
|
12457
11700
|
this._compression.destroy();
|
|
12458
11701
|
}
|
|
12459
11702
|
|
|
12460
|
-
/** @inheritdoc */
|
|
12461
|
-
clear() {
|
|
12462
|
-
return this._used.clear();
|
|
12463
|
-
}
|
|
12464
|
-
|
|
12465
|
-
/** @inheritdoc */
|
|
12466
|
-
getEarliestTimestamp() {
|
|
12467
|
-
return this._used.getEarliestTimestamp();
|
|
12468
|
-
}
|
|
12469
|
-
|
|
12470
11703
|
/**
|
|
12471
11704
|
* Add an event to the event buffer.
|
|
12472
11705
|
*
|
|
12473
11706
|
* Returns true if event was successfully added.
|
|
12474
11707
|
*/
|
|
12475
|
-
addEvent(event) {
|
|
12476
|
-
return this._used.addEvent(event);
|
|
11708
|
+
addEvent(event, isCheckout) {
|
|
11709
|
+
return this._used.addEvent(event, isCheckout);
|
|
12477
11710
|
}
|
|
12478
11711
|
|
|
12479
11712
|
/** @inheritDoc */
|
|
@@ -12548,31 +11781,6 @@ function createEventBuffer({ useCompression }) {
|
|
|
12548
11781
|
return new EventBufferArray();
|
|
12549
11782
|
}
|
|
12550
11783
|
|
|
12551
|
-
/**
|
|
12552
|
-
* Removes the session from Session Storage and unsets session in replay instance
|
|
12553
|
-
*/
|
|
12554
|
-
function clearSession(replay) {
|
|
12555
|
-
deleteSession();
|
|
12556
|
-
replay.session = undefined;
|
|
12557
|
-
}
|
|
12558
|
-
|
|
12559
|
-
/**
|
|
12560
|
-
* Deletes a session from storage
|
|
12561
|
-
*/
|
|
12562
|
-
function deleteSession() {
|
|
12563
|
-
const hasSessionStorage = 'sessionStorage' in WINDOW;
|
|
12564
|
-
|
|
12565
|
-
if (!hasSessionStorage) {
|
|
12566
|
-
return;
|
|
12567
|
-
}
|
|
12568
|
-
|
|
12569
|
-
try {
|
|
12570
|
-
WINDOW.sessionStorage.removeItem(REPLAY_SESSION_KEY);
|
|
12571
|
-
} catch (e) {
|
|
12572
|
-
// Ignore potential SecurityError exceptions
|
|
12573
|
-
}
|
|
12574
|
-
}
|
|
12575
|
-
|
|
12576
11784
|
/**
|
|
12577
11785
|
* Given an initial timestamp and an expiry duration, checks to see if current
|
|
12578
11786
|
* time should be considered as expired.
|
|
@@ -12603,26 +11811,11 @@ function isSessionExpired(session, timeouts, targetTime = +new Date()) {
|
|
|
12603
11811
|
// First, check that maximum session length has not been exceeded
|
|
12604
11812
|
isExpired(session.started, timeouts.maxSessionLife, targetTime) ||
|
|
12605
11813
|
// check that the idle timeout has not been exceeded (i.e. user has
|
|
12606
|
-
// performed an action within the last `
|
|
12607
|
-
isExpired(session.lastActivity, timeouts.
|
|
11814
|
+
// performed an action within the last `idleTimeout` ms)
|
|
11815
|
+
isExpired(session.lastActivity, timeouts.sessionIdle, targetTime)
|
|
12608
11816
|
);
|
|
12609
11817
|
}
|
|
12610
11818
|
|
|
12611
|
-
/**
|
|
12612
|
-
* Given a sample rate, returns true if replay should be sampled.
|
|
12613
|
-
*
|
|
12614
|
-
* 1.0 = 100% sampling
|
|
12615
|
-
* 0.0 = 0% sampling
|
|
12616
|
-
*/
|
|
12617
|
-
function isSampled(sampleRate) {
|
|
12618
|
-
if (sampleRate === undefined) {
|
|
12619
|
-
return false;
|
|
12620
|
-
}
|
|
12621
|
-
|
|
12622
|
-
// Math.random() returns a number in range of 0 to 1 (inclusive of 0, but not 1)
|
|
12623
|
-
return Math.random() < sampleRate;
|
|
12624
|
-
}
|
|
12625
|
-
|
|
12626
11819
|
/**
|
|
12627
11820
|
* Save a session to session storage.
|
|
12628
11821
|
*/
|
|
@@ -12639,6 +11832,21 @@ function saveSession(session) {
|
|
|
12639
11832
|
}
|
|
12640
11833
|
}
|
|
12641
11834
|
|
|
11835
|
+
/**
|
|
11836
|
+
* Given a sample rate, returns true if replay should be sampled.
|
|
11837
|
+
*
|
|
11838
|
+
* 1.0 = 100% sampling
|
|
11839
|
+
* 0.0 = 0% sampling
|
|
11840
|
+
*/
|
|
11841
|
+
function isSampled(sampleRate) {
|
|
11842
|
+
if (sampleRate === undefined) {
|
|
11843
|
+
return false;
|
|
11844
|
+
}
|
|
11845
|
+
|
|
11846
|
+
// Math.random() returns a number in range of 0 to 1 (inclusive of 0, but not 1)
|
|
11847
|
+
return Math.random() < sampleRate;
|
|
11848
|
+
}
|
|
11849
|
+
|
|
12642
11850
|
/**
|
|
12643
11851
|
* Get a session with defaults & applied sampling.
|
|
12644
11852
|
*/
|
|
@@ -12657,15 +11865,14 @@ function makeSession(session) {
|
|
|
12657
11865
|
lastActivity,
|
|
12658
11866
|
segmentId,
|
|
12659
11867
|
sampled,
|
|
12660
|
-
shouldRefresh: true,
|
|
12661
11868
|
};
|
|
12662
11869
|
}
|
|
12663
11870
|
|
|
12664
11871
|
/**
|
|
12665
11872
|
* Get the sampled status for a session based on sample rates & current sampled status.
|
|
12666
11873
|
*/
|
|
12667
|
-
function getSessionSampleType(sessionSampleRate,
|
|
12668
|
-
return isSampled(sessionSampleRate) ? 'session' :
|
|
11874
|
+
function getSessionSampleType(sessionSampleRate, errorSampleRate) {
|
|
11875
|
+
return isSampled(sessionSampleRate) ? 'session' : isSampled(errorSampleRate) ? 'error' : false;
|
|
12669
11876
|
}
|
|
12670
11877
|
|
|
12671
11878
|
/**
|
|
@@ -12673,8 +11880,8 @@ function getSessionSampleType(sessionSampleRate, allowBuffering) {
|
|
|
12673
11880
|
* that all replays will be saved to as attachments. Currently, we only expect
|
|
12674
11881
|
* one of these Sentry events per "replay session".
|
|
12675
11882
|
*/
|
|
12676
|
-
function createSession({ sessionSampleRate,
|
|
12677
|
-
const sampled = getSessionSampleType(sessionSampleRate,
|
|
11883
|
+
function createSession({ sessionSampleRate, errorSampleRate, stickySession = false }) {
|
|
11884
|
+
const sampled = getSessionSampleType(sessionSampleRate, errorSampleRate);
|
|
12678
11885
|
const session = makeSession({
|
|
12679
11886
|
sampled,
|
|
12680
11887
|
});
|
|
@@ -12722,7 +11929,7 @@ function getSession({
|
|
|
12722
11929
|
currentSession,
|
|
12723
11930
|
stickySession,
|
|
12724
11931
|
sessionSampleRate,
|
|
12725
|
-
|
|
11932
|
+
errorSampleRate,
|
|
12726
11933
|
}) {
|
|
12727
11934
|
// If session exists and is passed, use it instead of always hitting session storage
|
|
12728
11935
|
const session = currentSession || (stickySession && fetchSession());
|
|
@@ -12735,9 +11942,8 @@ function getSession({
|
|
|
12735
11942
|
|
|
12736
11943
|
if (!isExpired) {
|
|
12737
11944
|
return { type: 'saved', session };
|
|
12738
|
-
} else if (
|
|
12739
|
-
//
|
|
12740
|
-
// This is the case if we have an error session that is completed (=triggered an error)
|
|
11945
|
+
} else if (session.sampled === 'error') {
|
|
11946
|
+
// Error samples should not be re-created when expired, but instead we stop when the replay is done
|
|
12741
11947
|
const discardedSession = makeSession({ sampled: false });
|
|
12742
11948
|
return { type: 'new', session: discardedSession };
|
|
12743
11949
|
} else {
|
|
@@ -12749,12 +11955,65 @@ function getSession({
|
|
|
12749
11955
|
const newSession = createSession({
|
|
12750
11956
|
stickySession,
|
|
12751
11957
|
sessionSampleRate,
|
|
12752
|
-
|
|
11958
|
+
errorSampleRate,
|
|
12753
11959
|
});
|
|
12754
11960
|
|
|
12755
11961
|
return { type: 'new', session: newSession };
|
|
12756
11962
|
}
|
|
12757
11963
|
|
|
11964
|
+
/**
|
|
11965
|
+
* Add an event to the event buffer.
|
|
11966
|
+
* `isCheckout` is true if this is either the very first event, or an event triggered by `checkoutEveryNms`.
|
|
11967
|
+
*/
|
|
11968
|
+
async function addEvent(
|
|
11969
|
+
replay,
|
|
11970
|
+
event,
|
|
11971
|
+
isCheckout,
|
|
11972
|
+
) {
|
|
11973
|
+
if (!replay.eventBuffer) {
|
|
11974
|
+
// This implies that `_isEnabled` is false
|
|
11975
|
+
return null;
|
|
11976
|
+
}
|
|
11977
|
+
|
|
11978
|
+
if (replay.isPaused()) {
|
|
11979
|
+
// Do not add to event buffer when recording is paused
|
|
11980
|
+
return null;
|
|
11981
|
+
}
|
|
11982
|
+
|
|
11983
|
+
// TODO: sadness -- we will want to normalize timestamps to be in ms -
|
|
11984
|
+
// requires coordination with frontend
|
|
11985
|
+
const isMs = event.timestamp > 9999999999;
|
|
11986
|
+
const timestampInMs = isMs ? event.timestamp : event.timestamp * 1000;
|
|
11987
|
+
|
|
11988
|
+
// Throw out events that happen more than 5 minutes ago. This can happen if
|
|
11989
|
+
// page has been left open and idle for a long period of time and user
|
|
11990
|
+
// comes back to trigger a new session. The performance entries rely on
|
|
11991
|
+
// `performance.timeOrigin`, which is when the page first opened.
|
|
11992
|
+
if (timestampInMs + replay.timeouts.sessionIdle < Date.now()) {
|
|
11993
|
+
return null;
|
|
11994
|
+
}
|
|
11995
|
+
|
|
11996
|
+
// Only record earliest event if a new session was created, otherwise it
|
|
11997
|
+
// shouldn't be relevant
|
|
11998
|
+
const earliestEvent = replay.getContext().earliestEvent;
|
|
11999
|
+
if (replay.session && replay.session.segmentId === 0 && (!earliestEvent || timestampInMs < earliestEvent)) {
|
|
12000
|
+
replay.getContext().earliestEvent = timestampInMs;
|
|
12001
|
+
}
|
|
12002
|
+
|
|
12003
|
+
try {
|
|
12004
|
+
return await replay.eventBuffer.addEvent(event, isCheckout);
|
|
12005
|
+
} catch (error) {
|
|
12006
|
+
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(error);
|
|
12007
|
+
replay.stop('addEvent');
|
|
12008
|
+
|
|
12009
|
+
const client = getCurrentHub().getClient();
|
|
12010
|
+
|
|
12011
|
+
if (client) {
|
|
12012
|
+
client.recordDroppedEvent('internal_sdk_error', 'replay');
|
|
12013
|
+
}
|
|
12014
|
+
}
|
|
12015
|
+
}
|
|
12016
|
+
|
|
12758
12017
|
/** If the event is an error event */
|
|
12759
12018
|
function isErrorEvent(event) {
|
|
12760
12019
|
return !event.type;
|
|
@@ -12804,21 +12063,31 @@ function handleAfterSendEvent(replay) {
|
|
|
12804
12063
|
return;
|
|
12805
12064
|
}
|
|
12806
12065
|
|
|
12807
|
-
// Add error to list of errorIds of replay
|
|
12808
|
-
// sampled because context will get reset at next checkout.
|
|
12809
|
-
// XXX: There is also a race condition where it's possible to capture an
|
|
12810
|
-
// error to Sentry before Replay SDK has loaded, but response returns after
|
|
12811
|
-
// it was loaded, and this gets called.
|
|
12066
|
+
// Add error to list of errorIds of replay
|
|
12812
12067
|
if (event.event_id) {
|
|
12813
12068
|
replay.getContext().errorIds.add(event.event_id);
|
|
12814
12069
|
}
|
|
12815
12070
|
|
|
12816
|
-
//
|
|
12071
|
+
// Trigger error recording
|
|
12817
12072
|
// Need to be very careful that this does not cause an infinite loop
|
|
12818
|
-
if (
|
|
12819
|
-
|
|
12820
|
-
|
|
12821
|
-
|
|
12073
|
+
if (
|
|
12074
|
+
replay.recordingMode === 'error' &&
|
|
12075
|
+
event.exception &&
|
|
12076
|
+
event.message !== UNABLE_TO_SEND_REPLAY // ignore this error because otherwise we could loop indefinitely with trying to capture replay and failing
|
|
12077
|
+
) {
|
|
12078
|
+
setTimeout(async () => {
|
|
12079
|
+
// Allow flush to complete before resuming as a session recording, otherwise
|
|
12080
|
+
// the checkout from `startRecording` may be included in the payload.
|
|
12081
|
+
// Prefer to keep the error replay as a separate (and smaller) segment
|
|
12082
|
+
// than the session replay.
|
|
12083
|
+
await replay.flushImmediate();
|
|
12084
|
+
|
|
12085
|
+
if (replay.stopRecording()) {
|
|
12086
|
+
// Reset all "capture on error" configuration before
|
|
12087
|
+
// starting a new recording
|
|
12088
|
+
replay.recordingMode = 'session';
|
|
12089
|
+
replay.startRecording();
|
|
12090
|
+
}
|
|
12822
12091
|
});
|
|
12823
12092
|
}
|
|
12824
12093
|
};
|
|
@@ -12840,6 +12109,166 @@ function isBaseTransportSend() {
|
|
|
12840
12109
|
);
|
|
12841
12110
|
}
|
|
12842
12111
|
|
|
12112
|
+
var NodeType;
|
|
12113
|
+
(function (NodeType) {
|
|
12114
|
+
NodeType[NodeType["Document"] = 0] = "Document";
|
|
12115
|
+
NodeType[NodeType["DocumentType"] = 1] = "DocumentType";
|
|
12116
|
+
NodeType[NodeType["Element"] = 2] = "Element";
|
|
12117
|
+
NodeType[NodeType["Text"] = 3] = "Text";
|
|
12118
|
+
NodeType[NodeType["CDATA"] = 4] = "CDATA";
|
|
12119
|
+
NodeType[NodeType["Comment"] = 5] = "Comment";
|
|
12120
|
+
})(NodeType || (NodeType = {}));
|
|
12121
|
+
|
|
12122
|
+
/**
|
|
12123
|
+
* Create a breadcrumb for a replay.
|
|
12124
|
+
*/
|
|
12125
|
+
function createBreadcrumb(
|
|
12126
|
+
breadcrumb,
|
|
12127
|
+
) {
|
|
12128
|
+
return {
|
|
12129
|
+
timestamp: Date.now() / 1000,
|
|
12130
|
+
type: 'default',
|
|
12131
|
+
...breadcrumb,
|
|
12132
|
+
};
|
|
12133
|
+
}
|
|
12134
|
+
|
|
12135
|
+
/**
|
|
12136
|
+
* Add a breadcrumb event to replay.
|
|
12137
|
+
*/
|
|
12138
|
+
function addBreadcrumbEvent(replay, breadcrumb) {
|
|
12139
|
+
if (breadcrumb.category === 'sentry.transaction') {
|
|
12140
|
+
return;
|
|
12141
|
+
}
|
|
12142
|
+
|
|
12143
|
+
if (['ui.click', 'ui.input'].includes(breadcrumb.category )) {
|
|
12144
|
+
replay.triggerUserActivity();
|
|
12145
|
+
} else {
|
|
12146
|
+
replay.checkAndHandleExpiredSession();
|
|
12147
|
+
}
|
|
12148
|
+
|
|
12149
|
+
replay.addUpdate(() => {
|
|
12150
|
+
void addEvent(replay, {
|
|
12151
|
+
type: EventType.Custom,
|
|
12152
|
+
// TODO: We were converting from ms to seconds for breadcrumbs, spans,
|
|
12153
|
+
// but maybe we should just keep them as milliseconds
|
|
12154
|
+
timestamp: (breadcrumb.timestamp || 0) * 1000,
|
|
12155
|
+
data: {
|
|
12156
|
+
tag: 'breadcrumb',
|
|
12157
|
+
payload: breadcrumb,
|
|
12158
|
+
},
|
|
12159
|
+
});
|
|
12160
|
+
|
|
12161
|
+
// Do not flush after console log messages
|
|
12162
|
+
return breadcrumb.category === 'console';
|
|
12163
|
+
});
|
|
12164
|
+
}
|
|
12165
|
+
|
|
12166
|
+
// Note that these are the serialized attributes and not attributes directly on
|
|
12167
|
+
// the DOM Node. Attributes we are interested in:
|
|
12168
|
+
const ATTRIBUTES_TO_RECORD = new Set([
|
|
12169
|
+
'id',
|
|
12170
|
+
'class',
|
|
12171
|
+
'aria-label',
|
|
12172
|
+
'role',
|
|
12173
|
+
'name',
|
|
12174
|
+
'alt',
|
|
12175
|
+
'title',
|
|
12176
|
+
'data-test-id',
|
|
12177
|
+
'data-testid',
|
|
12178
|
+
]);
|
|
12179
|
+
|
|
12180
|
+
/**
|
|
12181
|
+
* Inclusion list of attributes that we want to record from the DOM element
|
|
12182
|
+
*/
|
|
12183
|
+
function getAttributesToRecord(attributes) {
|
|
12184
|
+
const obj = {};
|
|
12185
|
+
for (const key in attributes) {
|
|
12186
|
+
if (ATTRIBUTES_TO_RECORD.has(key)) {
|
|
12187
|
+
let normalizedKey = key;
|
|
12188
|
+
|
|
12189
|
+
if (key === 'data-testid' || key === 'data-test-id') {
|
|
12190
|
+
normalizedKey = 'testId';
|
|
12191
|
+
}
|
|
12192
|
+
|
|
12193
|
+
obj[normalizedKey] = attributes[key];
|
|
12194
|
+
}
|
|
12195
|
+
}
|
|
12196
|
+
|
|
12197
|
+
return obj;
|
|
12198
|
+
}
|
|
12199
|
+
|
|
12200
|
+
const handleDomListener =
|
|
12201
|
+
(replay) =>
|
|
12202
|
+
(handlerData) => {
|
|
12203
|
+
if (!replay.isEnabled()) {
|
|
12204
|
+
return;
|
|
12205
|
+
}
|
|
12206
|
+
|
|
12207
|
+
const result = handleDom(handlerData);
|
|
12208
|
+
|
|
12209
|
+
if (!result) {
|
|
12210
|
+
return;
|
|
12211
|
+
}
|
|
12212
|
+
|
|
12213
|
+
addBreadcrumbEvent(replay, result);
|
|
12214
|
+
};
|
|
12215
|
+
|
|
12216
|
+
/**
|
|
12217
|
+
* An event handler to react to DOM events.
|
|
12218
|
+
*/
|
|
12219
|
+
function handleDom(handlerData) {
|
|
12220
|
+
let target;
|
|
12221
|
+
let targetNode;
|
|
12222
|
+
|
|
12223
|
+
// Accessing event.target can throw (see getsentry/raven-js#838, #768)
|
|
12224
|
+
try {
|
|
12225
|
+
targetNode = getTargetNode(handlerData);
|
|
12226
|
+
target = htmlTreeAsString(targetNode);
|
|
12227
|
+
} catch (e) {
|
|
12228
|
+
target = '<unknown>';
|
|
12229
|
+
}
|
|
12230
|
+
|
|
12231
|
+
// `__sn` property is the serialized node created by rrweb
|
|
12232
|
+
const serializedNode =
|
|
12233
|
+
targetNode && '__sn' in targetNode && targetNode.__sn.type === NodeType.Element ? targetNode.__sn : null;
|
|
12234
|
+
|
|
12235
|
+
return createBreadcrumb({
|
|
12236
|
+
category: `ui.${handlerData.name}`,
|
|
12237
|
+
message: target,
|
|
12238
|
+
data: serializedNode
|
|
12239
|
+
? {
|
|
12240
|
+
nodeId: serializedNode.id,
|
|
12241
|
+
node: {
|
|
12242
|
+
id: serializedNode.id,
|
|
12243
|
+
tagName: serializedNode.tagName,
|
|
12244
|
+
textContent: targetNode
|
|
12245
|
+
? Array.from(targetNode.childNodes)
|
|
12246
|
+
.map(
|
|
12247
|
+
(node) => '__sn' in node && node.__sn.type === NodeType.Text && node.__sn.textContent,
|
|
12248
|
+
)
|
|
12249
|
+
.filter(Boolean) // filter out empty values
|
|
12250
|
+
.map(text => (text ).trim())
|
|
12251
|
+
.join('')
|
|
12252
|
+
: '',
|
|
12253
|
+
attributes: getAttributesToRecord(serializedNode.attributes),
|
|
12254
|
+
},
|
|
12255
|
+
}
|
|
12256
|
+
: {},
|
|
12257
|
+
});
|
|
12258
|
+
}
|
|
12259
|
+
|
|
12260
|
+
function getTargetNode(handlerData) {
|
|
12261
|
+
if (isEventWithTarget(handlerData.event)) {
|
|
12262
|
+
return handlerData.event.target;
|
|
12263
|
+
}
|
|
12264
|
+
|
|
12265
|
+
return handlerData.event;
|
|
12266
|
+
}
|
|
12267
|
+
|
|
12268
|
+
function isEventWithTarget(event) {
|
|
12269
|
+
return !!(event ).target;
|
|
12270
|
+
}
|
|
12271
|
+
|
|
12843
12272
|
/**
|
|
12844
12273
|
* Returns true if we think the given event is an error originating inside of rrweb.
|
|
12845
12274
|
*/
|
|
@@ -12863,30 +12292,6 @@ function isRrwebError(event, hint) {
|
|
|
12863
12292
|
});
|
|
12864
12293
|
}
|
|
12865
12294
|
|
|
12866
|
-
/**
|
|
12867
|
-
* Determine if event should be sampled (only applies in buffer mode).
|
|
12868
|
-
* When an event is captured by `hanldleGlobalEvent`, when in buffer mode
|
|
12869
|
-
* we determine if we want to sample the error or not.
|
|
12870
|
-
*/
|
|
12871
|
-
function shouldSampleForBufferEvent(replay, event) {
|
|
12872
|
-
if (replay.recordingMode !== 'buffer') {
|
|
12873
|
-
return false;
|
|
12874
|
-
}
|
|
12875
|
-
|
|
12876
|
-
// ignore this error because otherwise we could loop indefinitely with
|
|
12877
|
-
// trying to capture replay and failing
|
|
12878
|
-
if (event.message === UNABLE_TO_SEND_REPLAY) {
|
|
12879
|
-
return false;
|
|
12880
|
-
}
|
|
12881
|
-
|
|
12882
|
-
// Require the event to be an error event & to have an exception
|
|
12883
|
-
if (!event.exception || event.type) {
|
|
12884
|
-
return false;
|
|
12885
|
-
}
|
|
12886
|
-
|
|
12887
|
-
return isSampled(replay.getOptions().errorSampleRate);
|
|
12888
|
-
}
|
|
12889
|
-
|
|
12890
12295
|
/**
|
|
12891
12296
|
* Returns a listener to be added to `addGlobalEventProcessor(listener)`.
|
|
12892
12297
|
*/
|
|
@@ -12916,16 +12321,8 @@ function handleGlobalEventListener(
|
|
|
12916
12321
|
return null;
|
|
12917
12322
|
}
|
|
12918
12323
|
|
|
12919
|
-
//
|
|
12920
|
-
|
|
12921
|
-
// And convert the buffer session to a full session
|
|
12922
|
-
const isErrorEventSampled = shouldSampleForBufferEvent(replay, event);
|
|
12923
|
-
|
|
12924
|
-
// Tag errors if it has been sampled in buffer mode, or if it is session mode
|
|
12925
|
-
// Only tag transactions if in session mode
|
|
12926
|
-
const shouldTagReplayId = isErrorEventSampled || replay.recordingMode === 'session';
|
|
12927
|
-
|
|
12928
|
-
if (shouldTagReplayId) {
|
|
12324
|
+
// Only tag transactions with replayId if not waiting for an error
|
|
12325
|
+
if (isErrorEvent(event) || (isTransactionEvent(event) && replay.recordingMode === 'session')) {
|
|
12929
12326
|
event.tags = { ...event.tags, replayId: replay.getSessionId() };
|
|
12930
12327
|
}
|
|
12931
12328
|
|
|
@@ -12975,7 +12372,7 @@ function createPerformanceSpans(
|
|
|
12975
12372
|
) {
|
|
12976
12373
|
return entries.map(({ type, start, end, name, data }) =>
|
|
12977
12374
|
addEvent(replay, {
|
|
12978
|
-
type: EventType
|
|
12375
|
+
type: EventType.Custom,
|
|
12979
12376
|
timestamp: start,
|
|
12980
12377
|
data: {
|
|
12981
12378
|
tag: 'performanceSpan',
|
|
@@ -13124,14 +12521,12 @@ function handleFetchSpanListener(replay) {
|
|
|
13124
12521
|
function handleXhr(handlerData) {
|
|
13125
12522
|
const { startTimestamp, endTimestamp, xhr } = handlerData;
|
|
13126
12523
|
|
|
13127
|
-
|
|
13128
|
-
|
|
13129
|
-
if (!startTimestamp || !endTimestamp || !sentryXhrData) {
|
|
12524
|
+
if (!startTimestamp || !endTimestamp || !xhr.__sentry_xhr__) {
|
|
13130
12525
|
return null;
|
|
13131
12526
|
}
|
|
13132
12527
|
|
|
13133
12528
|
// This is only used as a fallback, so we know the body sizes are never set here
|
|
13134
|
-
const { method, url, status_code: statusCode } =
|
|
12529
|
+
const { method, url, status_code: statusCode } = xhr.__sentry_xhr__;
|
|
13135
12530
|
|
|
13136
12531
|
if (url === undefined) {
|
|
13137
12532
|
return null;
|
|
@@ -13164,393 +12559,6 @@ function handleXhrSpanListener(replay) {
|
|
|
13164
12559
|
};
|
|
13165
12560
|
}
|
|
13166
12561
|
|
|
13167
|
-
const OBJ = 10;
|
|
13168
|
-
const OBJ_KEY = 11;
|
|
13169
|
-
const OBJ_KEY_STR = 12;
|
|
13170
|
-
const OBJ_VAL = 13;
|
|
13171
|
-
const OBJ_VAL_STR = 14;
|
|
13172
|
-
const OBJ_VAL_COMPLETED = 15;
|
|
13173
|
-
|
|
13174
|
-
const ARR = 20;
|
|
13175
|
-
const ARR_VAL = 21;
|
|
13176
|
-
const ARR_VAL_STR = 22;
|
|
13177
|
-
const ARR_VAL_COMPLETED = 23;
|
|
13178
|
-
|
|
13179
|
-
const ALLOWED_PRIMITIVES = ['true', 'false', 'null'];
|
|
13180
|
-
|
|
13181
|
-
/**
|
|
13182
|
-
* Complete an incomplete JSON string.
|
|
13183
|
-
* This will ensure that the last element always has a `"~~"` to indicate it was truncated.
|
|
13184
|
-
* For example, `[1,2,` will be completed to `[1,2,"~~"]`
|
|
13185
|
-
* and `{"aa":"b` will be completed to `{"aa":"b~~"}`
|
|
13186
|
-
*/
|
|
13187
|
-
function completeJson(incompleteJson, stack) {
|
|
13188
|
-
if (!stack.length) {
|
|
13189
|
-
return incompleteJson;
|
|
13190
|
-
}
|
|
13191
|
-
|
|
13192
|
-
let json = incompleteJson;
|
|
13193
|
-
|
|
13194
|
-
// Most checks are only needed for the last step in the stack
|
|
13195
|
-
const lastPos = stack.length - 1;
|
|
13196
|
-
const lastStep = stack[lastPos];
|
|
13197
|
-
|
|
13198
|
-
json = _fixLastStep(json, lastStep);
|
|
13199
|
-
|
|
13200
|
-
// Complete remaining steps - just add closing brackets
|
|
13201
|
-
for (let i = lastPos; i >= 0; i--) {
|
|
13202
|
-
const step = stack[i];
|
|
13203
|
-
|
|
13204
|
-
switch (step) {
|
|
13205
|
-
case OBJ:
|
|
13206
|
-
json = `${json}}`;
|
|
13207
|
-
break;
|
|
13208
|
-
case ARR:
|
|
13209
|
-
json = `${json}]`;
|
|
13210
|
-
break;
|
|
13211
|
-
}
|
|
13212
|
-
}
|
|
13213
|
-
|
|
13214
|
-
return json;
|
|
13215
|
-
}
|
|
13216
|
-
|
|
13217
|
-
function _fixLastStep(json, lastStep) {
|
|
13218
|
-
switch (lastStep) {
|
|
13219
|
-
// Object cases
|
|
13220
|
-
case OBJ:
|
|
13221
|
-
return `${json}"~~":"~~"`;
|
|
13222
|
-
case OBJ_KEY:
|
|
13223
|
-
return `${json}:"~~"`;
|
|
13224
|
-
case OBJ_KEY_STR:
|
|
13225
|
-
return `${json}~~":"~~"`;
|
|
13226
|
-
case OBJ_VAL:
|
|
13227
|
-
return _maybeFixIncompleteObjValue(json);
|
|
13228
|
-
case OBJ_VAL_STR:
|
|
13229
|
-
return `${json}~~"`;
|
|
13230
|
-
case OBJ_VAL_COMPLETED:
|
|
13231
|
-
return `${json},"~~":"~~"`;
|
|
13232
|
-
|
|
13233
|
-
// Array cases
|
|
13234
|
-
case ARR:
|
|
13235
|
-
return `${json}"~~"`;
|
|
13236
|
-
case ARR_VAL:
|
|
13237
|
-
return _maybeFixIncompleteArrValue(json);
|
|
13238
|
-
case ARR_VAL_STR:
|
|
13239
|
-
return `${json}~~"`;
|
|
13240
|
-
case ARR_VAL_COMPLETED:
|
|
13241
|
-
return `${json},"~~"`;
|
|
13242
|
-
}
|
|
13243
|
-
|
|
13244
|
-
return json;
|
|
13245
|
-
}
|
|
13246
|
-
|
|
13247
|
-
function _maybeFixIncompleteArrValue(json) {
|
|
13248
|
-
const pos = _findLastArrayDelimiter(json);
|
|
13249
|
-
|
|
13250
|
-
if (pos > -1) {
|
|
13251
|
-
const part = json.slice(pos + 1);
|
|
13252
|
-
|
|
13253
|
-
if (ALLOWED_PRIMITIVES.includes(part.trim())) {
|
|
13254
|
-
return `${json},"~~"`;
|
|
13255
|
-
}
|
|
13256
|
-
|
|
13257
|
-
// Everything else is replaced with `"~~"`
|
|
13258
|
-
return `${json.slice(0, pos + 1)}"~~"`;
|
|
13259
|
-
}
|
|
13260
|
-
|
|
13261
|
-
// fallback, this shouldn't happen, to be save
|
|
13262
|
-
return json;
|
|
13263
|
-
}
|
|
13264
|
-
|
|
13265
|
-
function _findLastArrayDelimiter(json) {
|
|
13266
|
-
for (let i = json.length - 1; i >= 0; i--) {
|
|
13267
|
-
const char = json[i];
|
|
13268
|
-
|
|
13269
|
-
if (char === ',' || char === '[') {
|
|
13270
|
-
return i;
|
|
13271
|
-
}
|
|
13272
|
-
}
|
|
13273
|
-
|
|
13274
|
-
return -1;
|
|
13275
|
-
}
|
|
13276
|
-
|
|
13277
|
-
function _maybeFixIncompleteObjValue(json) {
|
|
13278
|
-
const startPos = json.lastIndexOf(':');
|
|
13279
|
-
|
|
13280
|
-
const part = json.slice(startPos + 1);
|
|
13281
|
-
|
|
13282
|
-
if (ALLOWED_PRIMITIVES.includes(part.trim())) {
|
|
13283
|
-
return `${json},"~~":"~~"`;
|
|
13284
|
-
}
|
|
13285
|
-
|
|
13286
|
-
// Everything else is replaced with `"~~"`
|
|
13287
|
-
// This also means we do not have incomplete numbers, e.g `[1` is replaced with `["~~"]`
|
|
13288
|
-
return `${json.slice(0, startPos + 1)}"~~"`;
|
|
13289
|
-
}
|
|
13290
|
-
|
|
13291
|
-
/**
|
|
13292
|
-
* Evaluate an (incomplete) JSON string.
|
|
13293
|
-
*/
|
|
13294
|
-
function evaluateJson(json) {
|
|
13295
|
-
const stack = [];
|
|
13296
|
-
|
|
13297
|
-
for (let pos = 0; pos < json.length; pos++) {
|
|
13298
|
-
_evaluateJsonPos(stack, json, pos);
|
|
13299
|
-
}
|
|
13300
|
-
|
|
13301
|
-
return stack;
|
|
13302
|
-
}
|
|
13303
|
-
|
|
13304
|
-
function _evaluateJsonPos(stack, json, pos) {
|
|
13305
|
-
const curStep = stack[stack.length - 1];
|
|
13306
|
-
|
|
13307
|
-
const char = json[pos];
|
|
13308
|
-
|
|
13309
|
-
const whitespaceRegex = /\s/;
|
|
13310
|
-
|
|
13311
|
-
if (whitespaceRegex.test(char)) {
|
|
13312
|
-
return;
|
|
13313
|
-
}
|
|
13314
|
-
|
|
13315
|
-
if (char === '"' && !_isEscaped(json, pos)) {
|
|
13316
|
-
_handleQuote(stack, curStep);
|
|
13317
|
-
return;
|
|
13318
|
-
}
|
|
13319
|
-
|
|
13320
|
-
switch (char) {
|
|
13321
|
-
case '{':
|
|
13322
|
-
_handleObj(stack, curStep);
|
|
13323
|
-
break;
|
|
13324
|
-
case '[':
|
|
13325
|
-
_handleArr(stack, curStep);
|
|
13326
|
-
break;
|
|
13327
|
-
case ':':
|
|
13328
|
-
_handleColon(stack, curStep);
|
|
13329
|
-
break;
|
|
13330
|
-
case ',':
|
|
13331
|
-
_handleComma(stack, curStep);
|
|
13332
|
-
break;
|
|
13333
|
-
case '}':
|
|
13334
|
-
_handleObjClose(stack, curStep);
|
|
13335
|
-
break;
|
|
13336
|
-
case ']':
|
|
13337
|
-
_handleArrClose(stack, curStep);
|
|
13338
|
-
break;
|
|
13339
|
-
}
|
|
13340
|
-
}
|
|
13341
|
-
|
|
13342
|
-
function _handleQuote(stack, curStep) {
|
|
13343
|
-
// End of obj value
|
|
13344
|
-
if (curStep === OBJ_VAL_STR) {
|
|
13345
|
-
stack.pop();
|
|
13346
|
-
stack.push(OBJ_VAL_COMPLETED);
|
|
13347
|
-
return;
|
|
13348
|
-
}
|
|
13349
|
-
|
|
13350
|
-
// End of arr value
|
|
13351
|
-
if (curStep === ARR_VAL_STR) {
|
|
13352
|
-
stack.pop();
|
|
13353
|
-
stack.push(ARR_VAL_COMPLETED);
|
|
13354
|
-
return;
|
|
13355
|
-
}
|
|
13356
|
-
|
|
13357
|
-
// Start of obj value
|
|
13358
|
-
if (curStep === OBJ_VAL) {
|
|
13359
|
-
stack.push(OBJ_VAL_STR);
|
|
13360
|
-
return;
|
|
13361
|
-
}
|
|
13362
|
-
|
|
13363
|
-
// Start of arr value
|
|
13364
|
-
if (curStep === ARR_VAL) {
|
|
13365
|
-
stack.push(ARR_VAL_STR);
|
|
13366
|
-
return;
|
|
13367
|
-
}
|
|
13368
|
-
|
|
13369
|
-
// Start of obj key
|
|
13370
|
-
if (curStep === OBJ) {
|
|
13371
|
-
stack.push(OBJ_KEY_STR);
|
|
13372
|
-
return;
|
|
13373
|
-
}
|
|
13374
|
-
|
|
13375
|
-
// End of obj key
|
|
13376
|
-
if (curStep === OBJ_KEY_STR) {
|
|
13377
|
-
stack.pop();
|
|
13378
|
-
stack.push(OBJ_KEY);
|
|
13379
|
-
return;
|
|
13380
|
-
}
|
|
13381
|
-
}
|
|
13382
|
-
|
|
13383
|
-
function _handleObj(stack, curStep) {
|
|
13384
|
-
// Initial object
|
|
13385
|
-
if (!curStep) {
|
|
13386
|
-
stack.push(OBJ);
|
|
13387
|
-
return;
|
|
13388
|
-
}
|
|
13389
|
-
|
|
13390
|
-
// New object as obj value
|
|
13391
|
-
if (curStep === OBJ_VAL) {
|
|
13392
|
-
stack.push(OBJ);
|
|
13393
|
-
return;
|
|
13394
|
-
}
|
|
13395
|
-
|
|
13396
|
-
// New object as array element
|
|
13397
|
-
if (curStep === ARR_VAL) {
|
|
13398
|
-
stack.push(OBJ);
|
|
13399
|
-
}
|
|
13400
|
-
|
|
13401
|
-
// New object as first array element
|
|
13402
|
-
if (curStep === ARR) {
|
|
13403
|
-
stack.push(OBJ);
|
|
13404
|
-
return;
|
|
13405
|
-
}
|
|
13406
|
-
}
|
|
13407
|
-
|
|
13408
|
-
function _handleArr(stack, curStep) {
|
|
13409
|
-
// Initial array
|
|
13410
|
-
if (!curStep) {
|
|
13411
|
-
stack.push(ARR);
|
|
13412
|
-
stack.push(ARR_VAL);
|
|
13413
|
-
return;
|
|
13414
|
-
}
|
|
13415
|
-
|
|
13416
|
-
// New array as obj value
|
|
13417
|
-
if (curStep === OBJ_VAL) {
|
|
13418
|
-
stack.push(ARR);
|
|
13419
|
-
stack.push(ARR_VAL);
|
|
13420
|
-
return;
|
|
13421
|
-
}
|
|
13422
|
-
|
|
13423
|
-
// New array as array element
|
|
13424
|
-
if (curStep === ARR_VAL) {
|
|
13425
|
-
stack.push(ARR);
|
|
13426
|
-
stack.push(ARR_VAL);
|
|
13427
|
-
}
|
|
13428
|
-
|
|
13429
|
-
// New array as first array element
|
|
13430
|
-
if (curStep === ARR) {
|
|
13431
|
-
stack.push(ARR);
|
|
13432
|
-
stack.push(ARR_VAL);
|
|
13433
|
-
return;
|
|
13434
|
-
}
|
|
13435
|
-
}
|
|
13436
|
-
|
|
13437
|
-
function _handleColon(stack, curStep) {
|
|
13438
|
-
if (curStep === OBJ_KEY) {
|
|
13439
|
-
stack.pop();
|
|
13440
|
-
stack.push(OBJ_VAL);
|
|
13441
|
-
}
|
|
13442
|
-
}
|
|
13443
|
-
|
|
13444
|
-
function _handleComma(stack, curStep) {
|
|
13445
|
-
// Comma after obj value
|
|
13446
|
-
if (curStep === OBJ_VAL) {
|
|
13447
|
-
stack.pop();
|
|
13448
|
-
return;
|
|
13449
|
-
}
|
|
13450
|
-
if (curStep === OBJ_VAL_COMPLETED) {
|
|
13451
|
-
// Pop OBJ_VAL_COMPLETED & OBJ_VAL
|
|
13452
|
-
stack.pop();
|
|
13453
|
-
stack.pop();
|
|
13454
|
-
return;
|
|
13455
|
-
}
|
|
13456
|
-
|
|
13457
|
-
// Comma after arr value
|
|
13458
|
-
if (curStep === ARR_VAL) {
|
|
13459
|
-
// do nothing - basically we'd pop ARR_VAL but add it right back
|
|
13460
|
-
return;
|
|
13461
|
-
}
|
|
13462
|
-
|
|
13463
|
-
if (curStep === ARR_VAL_COMPLETED) {
|
|
13464
|
-
// Pop ARR_VAL_COMPLETED
|
|
13465
|
-
stack.pop();
|
|
13466
|
-
|
|
13467
|
-
// basically we'd pop ARR_VAL but add it right back
|
|
13468
|
-
return;
|
|
13469
|
-
}
|
|
13470
|
-
}
|
|
13471
|
-
|
|
13472
|
-
function _handleObjClose(stack, curStep) {
|
|
13473
|
-
// Empty object {}
|
|
13474
|
-
if (curStep === OBJ) {
|
|
13475
|
-
stack.pop();
|
|
13476
|
-
}
|
|
13477
|
-
|
|
13478
|
-
// Object with element
|
|
13479
|
-
if (curStep === OBJ_VAL) {
|
|
13480
|
-
// Pop OBJ_VAL, OBJ
|
|
13481
|
-
stack.pop();
|
|
13482
|
-
stack.pop();
|
|
13483
|
-
}
|
|
13484
|
-
|
|
13485
|
-
// Obj with element
|
|
13486
|
-
if (curStep === OBJ_VAL_COMPLETED) {
|
|
13487
|
-
// Pop OBJ_VAL_COMPLETED, OBJ_VAL, OBJ
|
|
13488
|
-
stack.pop();
|
|
13489
|
-
stack.pop();
|
|
13490
|
-
stack.pop();
|
|
13491
|
-
}
|
|
13492
|
-
|
|
13493
|
-
// if was obj value, complete it
|
|
13494
|
-
if (stack[stack.length - 1] === OBJ_VAL) {
|
|
13495
|
-
stack.push(OBJ_VAL_COMPLETED);
|
|
13496
|
-
}
|
|
13497
|
-
|
|
13498
|
-
// if was arr value, complete it
|
|
13499
|
-
if (stack[stack.length - 1] === ARR_VAL) {
|
|
13500
|
-
stack.push(ARR_VAL_COMPLETED);
|
|
13501
|
-
}
|
|
13502
|
-
}
|
|
13503
|
-
|
|
13504
|
-
function _handleArrClose(stack, curStep) {
|
|
13505
|
-
// Empty array []
|
|
13506
|
-
if (curStep === ARR) {
|
|
13507
|
-
stack.pop();
|
|
13508
|
-
}
|
|
13509
|
-
|
|
13510
|
-
// Array with element
|
|
13511
|
-
if (curStep === ARR_VAL) {
|
|
13512
|
-
// Pop ARR_VAL, ARR
|
|
13513
|
-
stack.pop();
|
|
13514
|
-
stack.pop();
|
|
13515
|
-
}
|
|
13516
|
-
|
|
13517
|
-
// Array with element
|
|
13518
|
-
if (curStep === ARR_VAL_COMPLETED) {
|
|
13519
|
-
// Pop ARR_VAL_COMPLETED, ARR_VAL, ARR
|
|
13520
|
-
stack.pop();
|
|
13521
|
-
stack.pop();
|
|
13522
|
-
stack.pop();
|
|
13523
|
-
}
|
|
13524
|
-
|
|
13525
|
-
// if was obj value, complete it
|
|
13526
|
-
if (stack[stack.length - 1] === OBJ_VAL) {
|
|
13527
|
-
stack.push(OBJ_VAL_COMPLETED);
|
|
13528
|
-
}
|
|
13529
|
-
|
|
13530
|
-
// if was arr value, complete it
|
|
13531
|
-
if (stack[stack.length - 1] === ARR_VAL) {
|
|
13532
|
-
stack.push(ARR_VAL_COMPLETED);
|
|
13533
|
-
}
|
|
13534
|
-
}
|
|
13535
|
-
|
|
13536
|
-
function _isEscaped(str, pos) {
|
|
13537
|
-
const previousChar = str[pos - 1];
|
|
13538
|
-
|
|
13539
|
-
return previousChar === '\\' && !_isEscaped(str, pos - 1);
|
|
13540
|
-
}
|
|
13541
|
-
|
|
13542
|
-
/* eslint-disable max-lines */
|
|
13543
|
-
|
|
13544
|
-
/**
|
|
13545
|
-
* Takes an incomplete JSON string, and returns a hopefully valid JSON string.
|
|
13546
|
-
* Note that this _can_ fail, so you should check the return value is valid JSON.
|
|
13547
|
-
*/
|
|
13548
|
-
function fixJson(incompleteJson) {
|
|
13549
|
-
const stack = evaluateJson(incompleteJson);
|
|
13550
|
-
|
|
13551
|
-
return completeJson(incompleteJson, stack);
|
|
13552
|
-
}
|
|
13553
|
-
|
|
13554
12562
|
/** Get the size of a body. */
|
|
13555
12563
|
function getBodySize(
|
|
13556
12564
|
body,
|
|
@@ -13644,68 +12652,51 @@ function makeNetworkReplayBreadcrumb(
|
|
|
13644
12652
|
return result;
|
|
13645
12653
|
}
|
|
13646
12654
|
|
|
13647
|
-
/**
|
|
13648
|
-
function
|
|
13649
|
-
|
|
13650
|
-
|
|
13651
|
-
|
|
13652
|
-
|
|
13653
|
-
|
|
13654
|
-
|
|
13655
|
-
}
|
|
12655
|
+
/** Get either a JSON network body, or a text representation. */
|
|
12656
|
+
function getNetworkBody(bodyText) {
|
|
12657
|
+
if (!bodyText) {
|
|
12658
|
+
return;
|
|
12659
|
+
}
|
|
12660
|
+
|
|
12661
|
+
try {
|
|
12662
|
+
return JSON.parse(bodyText);
|
|
12663
|
+
} catch (e2) {
|
|
12664
|
+
// return text
|
|
12665
|
+
}
|
|
12666
|
+
|
|
12667
|
+
return bodyText;
|
|
13656
12668
|
}
|
|
13657
12669
|
|
|
13658
12670
|
/** Build the request or response part of a replay network breadcrumb. */
|
|
13659
12671
|
function buildNetworkRequestOrResponse(
|
|
13660
|
-
headers,
|
|
13661
12672
|
bodySize,
|
|
13662
12673
|
body,
|
|
13663
12674
|
) {
|
|
13664
|
-
if (!bodySize && Object.keys(headers).length === 0) {
|
|
13665
|
-
return undefined;
|
|
13666
|
-
}
|
|
13667
|
-
|
|
13668
12675
|
if (!bodySize) {
|
|
13669
|
-
return
|
|
13670
|
-
headers,
|
|
13671
|
-
};
|
|
12676
|
+
return undefined;
|
|
13672
12677
|
}
|
|
13673
12678
|
|
|
13674
12679
|
if (!body) {
|
|
13675
12680
|
return {
|
|
13676
|
-
headers,
|
|
13677
12681
|
size: bodySize,
|
|
13678
12682
|
};
|
|
13679
12683
|
}
|
|
13680
12684
|
|
|
13681
12685
|
const info = {
|
|
13682
|
-
headers,
|
|
13683
12686
|
size: bodySize,
|
|
13684
12687
|
};
|
|
13685
12688
|
|
|
13686
|
-
|
|
13687
|
-
|
|
13688
|
-
|
|
12689
|
+
if (bodySize < NETWORK_BODY_MAX_SIZE) {
|
|
12690
|
+
info.body = body;
|
|
12691
|
+
} else {
|
|
13689
12692
|
info._meta = {
|
|
13690
|
-
|
|
12693
|
+
errors: ['MAX_BODY_SIZE_EXCEEDED'],
|
|
13691
12694
|
};
|
|
13692
12695
|
}
|
|
13693
12696
|
|
|
13694
12697
|
return info;
|
|
13695
12698
|
}
|
|
13696
12699
|
|
|
13697
|
-
/** Filter a set of headers */
|
|
13698
|
-
function getAllowedHeaders(headers, allowedHeaders) {
|
|
13699
|
-
return Object.keys(headers).reduce((filteredHeaders, key) => {
|
|
13700
|
-
const normalizedKey = key.toLowerCase();
|
|
13701
|
-
// Avoid putting empty strings into the headers
|
|
13702
|
-
if (allowedHeaders.includes(normalizedKey) && headers[key]) {
|
|
13703
|
-
filteredHeaders[normalizedKey] = headers[key];
|
|
13704
|
-
}
|
|
13705
|
-
return filteredHeaders;
|
|
13706
|
-
}, {});
|
|
13707
|
-
}
|
|
13708
|
-
|
|
13709
12700
|
function _serializeFormData(formData) {
|
|
13710
12701
|
// This is a bit simplified, but gives us a decent estimate
|
|
13711
12702
|
// This converts e.g. { name: 'Anne Smith', age: 13 } to 'name=Anne+Smith&age=13'
|
|
@@ -13713,78 +12704,6 @@ function _serializeFormData(formData) {
|
|
|
13713
12704
|
return new URLSearchParams(formData).toString();
|
|
13714
12705
|
}
|
|
13715
12706
|
|
|
13716
|
-
function normalizeNetworkBody(body)
|
|
13717
|
-
|
|
13718
|
-
{
|
|
13719
|
-
if (!body || typeof body !== 'string') {
|
|
13720
|
-
return {
|
|
13721
|
-
body,
|
|
13722
|
-
warnings: [],
|
|
13723
|
-
};
|
|
13724
|
-
}
|
|
13725
|
-
|
|
13726
|
-
const exceedsSizeLimit = body.length > NETWORK_BODY_MAX_SIZE;
|
|
13727
|
-
|
|
13728
|
-
if (_strIsProbablyJson(body)) {
|
|
13729
|
-
try {
|
|
13730
|
-
const json = exceedsSizeLimit ? fixJson(body.slice(0, NETWORK_BODY_MAX_SIZE)) : body;
|
|
13731
|
-
const normalizedBody = JSON.parse(json);
|
|
13732
|
-
return {
|
|
13733
|
-
body: normalizedBody,
|
|
13734
|
-
warnings: exceedsSizeLimit ? ['JSON_TRUNCATED'] : [],
|
|
13735
|
-
};
|
|
13736
|
-
} catch (e3) {
|
|
13737
|
-
return {
|
|
13738
|
-
body: exceedsSizeLimit ? `${body.slice(0, NETWORK_BODY_MAX_SIZE)}…` : body,
|
|
13739
|
-
warnings: exceedsSizeLimit ? ['INVALID_JSON', 'TEXT_TRUNCATED'] : ['INVALID_JSON'],
|
|
13740
|
-
};
|
|
13741
|
-
}
|
|
13742
|
-
}
|
|
13743
|
-
|
|
13744
|
-
return {
|
|
13745
|
-
body: exceedsSizeLimit ? `${body.slice(0, NETWORK_BODY_MAX_SIZE)}…` : body,
|
|
13746
|
-
warnings: exceedsSizeLimit ? ['TEXT_TRUNCATED'] : [],
|
|
13747
|
-
};
|
|
13748
|
-
}
|
|
13749
|
-
|
|
13750
|
-
function _strIsProbablyJson(str) {
|
|
13751
|
-
const first = str[0];
|
|
13752
|
-
const last = str[str.length - 1];
|
|
13753
|
-
|
|
13754
|
-
// Simple check: If this does not start & end with {} or [], it's not JSON
|
|
13755
|
-
return (first === '[' && last === ']') || (first === '{' && last === '}');
|
|
13756
|
-
}
|
|
13757
|
-
|
|
13758
|
-
/** Match an URL against a list of strings/Regex. */
|
|
13759
|
-
function urlMatches(url, urls) {
|
|
13760
|
-
const fullUrl = getFullUrl(url);
|
|
13761
|
-
|
|
13762
|
-
return stringMatchesSomePattern(fullUrl, urls);
|
|
13763
|
-
}
|
|
13764
|
-
|
|
13765
|
-
/** exported for tests */
|
|
13766
|
-
function getFullUrl(url, baseURI = WINDOW.document.baseURI) {
|
|
13767
|
-
// Short circuit for common cases:
|
|
13768
|
-
if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith(WINDOW.location.origin)) {
|
|
13769
|
-
return url;
|
|
13770
|
-
}
|
|
13771
|
-
const fixedUrl = new URL(url, baseURI);
|
|
13772
|
-
|
|
13773
|
-
// If these do not match, we are not dealing with a relative URL, so just return it
|
|
13774
|
-
if (fixedUrl.origin !== new URL(baseURI).origin) {
|
|
13775
|
-
return url;
|
|
13776
|
-
}
|
|
13777
|
-
|
|
13778
|
-
const fullUrl = fixedUrl.href;
|
|
13779
|
-
|
|
13780
|
-
// Remove trailing slashes, if they don't match the original URL
|
|
13781
|
-
if (!url.endsWith('/') && fullUrl.endsWith('/')) {
|
|
13782
|
-
return fullUrl.slice(0, -1);
|
|
13783
|
-
}
|
|
13784
|
-
|
|
13785
|
-
return fullUrl;
|
|
13786
|
-
}
|
|
13787
|
-
|
|
13788
12707
|
/**
|
|
13789
12708
|
* Capture a fetch breadcrumb to a replay.
|
|
13790
12709
|
* This adds additional data (where approriate).
|
|
@@ -13792,9 +12711,7 @@ function getFullUrl(url, baseURI = WINDOW.document.baseURI) {
|
|
|
13792
12711
|
async function captureFetchBreadcrumbToReplay(
|
|
13793
12712
|
breadcrumb,
|
|
13794
12713
|
hint,
|
|
13795
|
-
options
|
|
13796
|
-
|
|
13797
|
-
,
|
|
12714
|
+
options,
|
|
13798
12715
|
) {
|
|
13799
12716
|
try {
|
|
13800
12717
|
const data = await _prepareFetchData(breadcrumb, hint, options);
|
|
@@ -13821,7 +12738,6 @@ function enrichFetchBreadcrumb(
|
|
|
13821
12738
|
|
|
13822
12739
|
const body = _getFetchRequestArgBody(input);
|
|
13823
12740
|
const reqSize = getBodySize(body, options.textEncoder);
|
|
13824
|
-
|
|
13825
12741
|
const resSize = response ? parseContentLengthHeader(response.headers.get('content-length')) : undefined;
|
|
13826
12742
|
|
|
13827
12743
|
if (reqSize !== undefined) {
|
|
@@ -13835,109 +12751,97 @@ function enrichFetchBreadcrumb(
|
|
|
13835
12751
|
async function _prepareFetchData(
|
|
13836
12752
|
breadcrumb,
|
|
13837
12753
|
hint,
|
|
13838
|
-
options
|
|
13839
|
-
|
|
13840
|
-
,
|
|
12754
|
+
options,
|
|
13841
12755
|
) {
|
|
13842
12756
|
const { startTimestamp, endTimestamp } = hint;
|
|
13843
12757
|
|
|
13844
12758
|
const {
|
|
13845
12759
|
url,
|
|
13846
12760
|
method,
|
|
13847
|
-
status_code: statusCode
|
|
12761
|
+
status_code: statusCode,
|
|
13848
12762
|
request_body_size: requestBodySize,
|
|
13849
12763
|
response_body_size: responseBodySize,
|
|
13850
12764
|
} = breadcrumb.data;
|
|
13851
12765
|
|
|
13852
|
-
const
|
|
13853
|
-
|
|
13854
|
-
const request = captureDetails
|
|
13855
|
-
? _getRequestInfo(options, hint.input, requestBodySize)
|
|
13856
|
-
: buildSkippedNetworkRequestOrResponse(requestBodySize);
|
|
13857
|
-
const response = await _getResponseInfo(captureDetails, options, hint.response, responseBodySize);
|
|
12766
|
+
const request = _getRequestInfo(options, hint.input, requestBodySize);
|
|
12767
|
+
const response = await _getResponseInfo(options, hint.response, responseBodySize);
|
|
13858
12768
|
|
|
13859
12769
|
return {
|
|
13860
12770
|
startTimestamp,
|
|
13861
12771
|
endTimestamp,
|
|
13862
12772
|
url,
|
|
13863
12773
|
method,
|
|
13864
|
-
statusCode,
|
|
12774
|
+
statusCode: statusCode || 0,
|
|
13865
12775
|
request,
|
|
13866
12776
|
response,
|
|
13867
12777
|
};
|
|
13868
12778
|
}
|
|
13869
12779
|
|
|
13870
12780
|
function _getRequestInfo(
|
|
13871
|
-
{
|
|
12781
|
+
{ captureBodies },
|
|
13872
12782
|
input,
|
|
13873
12783
|
requestBodySize,
|
|
13874
12784
|
) {
|
|
13875
|
-
|
|
13876
|
-
|
|
13877
|
-
if (!networkCaptureBodies) {
|
|
13878
|
-
return buildNetworkRequestOrResponse(headers, requestBodySize, undefined);
|
|
12785
|
+
if (!captureBodies) {
|
|
12786
|
+
return buildNetworkRequestOrResponse(requestBodySize, undefined);
|
|
13879
12787
|
}
|
|
13880
12788
|
|
|
13881
12789
|
// We only want to transmit string or string-like bodies
|
|
13882
12790
|
const requestBody = _getFetchRequestArgBody(input);
|
|
13883
|
-
const
|
|
13884
|
-
return buildNetworkRequestOrResponse(
|
|
12791
|
+
const body = getNetworkBody(getBodyString(requestBody));
|
|
12792
|
+
return buildNetworkRequestOrResponse(requestBodySize, body);
|
|
13885
12793
|
}
|
|
13886
12794
|
|
|
13887
12795
|
async function _getResponseInfo(
|
|
13888
|
-
|
|
13889
|
-
{
|
|
13890
|
-
networkCaptureBodies,
|
|
13891
|
-
textEncoder,
|
|
13892
|
-
networkResponseHeaders,
|
|
13893
|
-
}
|
|
13894
|
-
|
|
13895
|
-
,
|
|
12796
|
+
{ captureBodies, textEncoder },
|
|
13896
12797
|
response,
|
|
13897
12798
|
responseBodySize,
|
|
13898
12799
|
) {
|
|
13899
|
-
if (!
|
|
13900
|
-
return
|
|
13901
|
-
}
|
|
13902
|
-
|
|
13903
|
-
const headers = getAllHeaders(response.headers, networkResponseHeaders);
|
|
13904
|
-
|
|
13905
|
-
if (!networkCaptureBodies && responseBodySize !== undefined) {
|
|
13906
|
-
return buildNetworkRequestOrResponse(headers, responseBodySize, undefined);
|
|
12800
|
+
if (!captureBodies && responseBodySize !== undefined) {
|
|
12801
|
+
return buildNetworkRequestOrResponse(responseBodySize, undefined);
|
|
13907
12802
|
}
|
|
13908
12803
|
|
|
13909
12804
|
// Only clone the response if we need to
|
|
13910
12805
|
try {
|
|
13911
12806
|
// We have to clone this, as the body can only be read once
|
|
13912
12807
|
const res = response.clone();
|
|
13913
|
-
const bodyText = await _parseFetchBody(res);
|
|
12808
|
+
const { body, bodyText } = await _parseFetchBody(res);
|
|
13914
12809
|
|
|
13915
12810
|
const size =
|
|
13916
12811
|
bodyText && bodyText.length && responseBodySize === undefined
|
|
13917
12812
|
? getBodySize(bodyText, textEncoder)
|
|
13918
12813
|
: responseBodySize;
|
|
13919
12814
|
|
|
13920
|
-
if (
|
|
13921
|
-
return
|
|
13922
|
-
}
|
|
13923
|
-
|
|
13924
|
-
if (networkCaptureBodies) {
|
|
13925
|
-
return buildNetworkRequestOrResponse(headers, size, bodyText);
|
|
12815
|
+
if (captureBodies) {
|
|
12816
|
+
return buildNetworkRequestOrResponse(size, body);
|
|
13926
12817
|
}
|
|
13927
12818
|
|
|
13928
|
-
return buildNetworkRequestOrResponse(
|
|
12819
|
+
return buildNetworkRequestOrResponse(size, undefined);
|
|
13929
12820
|
} catch (e) {
|
|
13930
12821
|
// fallback
|
|
13931
|
-
return buildNetworkRequestOrResponse(
|
|
12822
|
+
return buildNetworkRequestOrResponse(responseBodySize, undefined);
|
|
13932
12823
|
}
|
|
13933
12824
|
}
|
|
13934
12825
|
|
|
13935
|
-
async function _parseFetchBody(
|
|
12826
|
+
async function _parseFetchBody(
|
|
12827
|
+
response,
|
|
12828
|
+
) {
|
|
12829
|
+
let bodyText;
|
|
12830
|
+
|
|
13936
12831
|
try {
|
|
13937
|
-
|
|
12832
|
+
bodyText = await response.text();
|
|
13938
12833
|
} catch (e2) {
|
|
13939
|
-
return
|
|
12834
|
+
return {};
|
|
13940
12835
|
}
|
|
12836
|
+
|
|
12837
|
+
try {
|
|
12838
|
+
const body = JSON.parse(bodyText);
|
|
12839
|
+
return { body, bodyText };
|
|
12840
|
+
} catch (e3) {
|
|
12841
|
+
// just send bodyText
|
|
12842
|
+
}
|
|
12843
|
+
|
|
12844
|
+
return { bodyText, body: bodyText };
|
|
13941
12845
|
}
|
|
13942
12846
|
|
|
13943
12847
|
function _getFetchRequestArgBody(fetchArgs = []) {
|
|
@@ -13949,56 +12853,6 @@ function _getFetchRequestArgBody(fetchArgs = []) {
|
|
|
13949
12853
|
return (fetchArgs[1] ).body;
|
|
13950
12854
|
}
|
|
13951
12855
|
|
|
13952
|
-
function getAllHeaders(headers, allowedHeaders) {
|
|
13953
|
-
const allHeaders = {};
|
|
13954
|
-
|
|
13955
|
-
allowedHeaders.forEach(header => {
|
|
13956
|
-
if (headers.get(header)) {
|
|
13957
|
-
allHeaders[header] = headers.get(header) ;
|
|
13958
|
-
}
|
|
13959
|
-
});
|
|
13960
|
-
|
|
13961
|
-
return allHeaders;
|
|
13962
|
-
}
|
|
13963
|
-
|
|
13964
|
-
function getRequestHeaders(fetchArgs, allowedHeaders) {
|
|
13965
|
-
if (fetchArgs.length === 1 && typeof fetchArgs[0] !== 'string') {
|
|
13966
|
-
return getHeadersFromOptions(fetchArgs[0] , allowedHeaders);
|
|
13967
|
-
}
|
|
13968
|
-
|
|
13969
|
-
if (fetchArgs.length === 2) {
|
|
13970
|
-
return getHeadersFromOptions(fetchArgs[1] , allowedHeaders);
|
|
13971
|
-
}
|
|
13972
|
-
|
|
13973
|
-
return {};
|
|
13974
|
-
}
|
|
13975
|
-
|
|
13976
|
-
function getHeadersFromOptions(
|
|
13977
|
-
input,
|
|
13978
|
-
allowedHeaders,
|
|
13979
|
-
) {
|
|
13980
|
-
if (!input) {
|
|
13981
|
-
return {};
|
|
13982
|
-
}
|
|
13983
|
-
|
|
13984
|
-
const headers = input.headers;
|
|
13985
|
-
|
|
13986
|
-
if (!headers) {
|
|
13987
|
-
return {};
|
|
13988
|
-
}
|
|
13989
|
-
|
|
13990
|
-
if (headers instanceof Headers) {
|
|
13991
|
-
return getAllHeaders(headers, allowedHeaders);
|
|
13992
|
-
}
|
|
13993
|
-
|
|
13994
|
-
// We do not support this, as it is not really documented (anymore?)
|
|
13995
|
-
if (Array.isArray(headers)) {
|
|
13996
|
-
return {};
|
|
13997
|
-
}
|
|
13998
|
-
|
|
13999
|
-
return getAllowedHeaders(headers, allowedHeaders);
|
|
14000
|
-
}
|
|
14001
|
-
|
|
14002
12856
|
/**
|
|
14003
12857
|
* Capture an XHR breadcrumb to a replay.
|
|
14004
12858
|
* This adds additional data (where approriate).
|
|
@@ -14049,12 +12903,12 @@ function _prepareXhrData(
|
|
|
14049
12903
|
hint,
|
|
14050
12904
|
options,
|
|
14051
12905
|
) {
|
|
14052
|
-
const { startTimestamp, endTimestamp, input
|
|
12906
|
+
const { startTimestamp, endTimestamp, input } = hint;
|
|
14053
12907
|
|
|
14054
12908
|
const {
|
|
14055
12909
|
url,
|
|
14056
12910
|
method,
|
|
14057
|
-
status_code: statusCode
|
|
12911
|
+
status_code: statusCode,
|
|
14058
12912
|
request_body_size: requestBodySize,
|
|
14059
12913
|
response_body_size: responseBodySize,
|
|
14060
12914
|
} = breadcrumb.data;
|
|
@@ -14063,35 +12917,13 @@ function _prepareXhrData(
|
|
|
14063
12917
|
return null;
|
|
14064
12918
|
}
|
|
14065
12919
|
|
|
14066
|
-
if (!urlMatches(url, options.networkDetailAllowUrls)) {
|
|
14067
|
-
const request = buildSkippedNetworkRequestOrResponse(requestBodySize);
|
|
14068
|
-
const response = buildSkippedNetworkRequestOrResponse(responseBodySize);
|
|
14069
|
-
return {
|
|
14070
|
-
startTimestamp,
|
|
14071
|
-
endTimestamp,
|
|
14072
|
-
url,
|
|
14073
|
-
method,
|
|
14074
|
-
statusCode,
|
|
14075
|
-
request,
|
|
14076
|
-
response,
|
|
14077
|
-
};
|
|
14078
|
-
}
|
|
14079
|
-
|
|
14080
|
-
const xhrInfo = xhr[SENTRY_XHR_DATA_KEY];
|
|
14081
|
-
const networkRequestHeaders = xhrInfo
|
|
14082
|
-
? getAllowedHeaders(xhrInfo.request_headers, options.networkRequestHeaders)
|
|
14083
|
-
: {};
|
|
14084
|
-
const networkResponseHeaders = getAllowedHeaders(getResponseHeaders(xhr), options.networkResponseHeaders);
|
|
14085
|
-
|
|
14086
12920
|
const request = buildNetworkRequestOrResponse(
|
|
14087
|
-
networkRequestHeaders,
|
|
14088
12921
|
requestBodySize,
|
|
14089
|
-
options.
|
|
12922
|
+
options.captureBodies ? getNetworkBody(getBodyString(input)) : undefined,
|
|
14090
12923
|
);
|
|
14091
12924
|
const response = buildNetworkRequestOrResponse(
|
|
14092
|
-
networkResponseHeaders,
|
|
14093
12925
|
responseBodySize,
|
|
14094
|
-
options.
|
|
12926
|
+
options.captureBodies ? getNetworkBody(hint.xhr.responseText) : undefined,
|
|
14095
12927
|
);
|
|
14096
12928
|
|
|
14097
12929
|
return {
|
|
@@ -14099,26 +12931,12 @@ function _prepareXhrData(
|
|
|
14099
12931
|
endTimestamp,
|
|
14100
12932
|
url,
|
|
14101
12933
|
method,
|
|
14102
|
-
statusCode,
|
|
12934
|
+
statusCode: statusCode || 0,
|
|
14103
12935
|
request,
|
|
14104
12936
|
response,
|
|
14105
12937
|
};
|
|
14106
12938
|
}
|
|
14107
12939
|
|
|
14108
|
-
function getResponseHeaders(xhr) {
|
|
14109
|
-
const headers = xhr.getAllResponseHeaders();
|
|
14110
|
-
|
|
14111
|
-
if (!headers) {
|
|
14112
|
-
return {};
|
|
14113
|
-
}
|
|
14114
|
-
|
|
14115
|
-
return headers.split('\r\n').reduce((acc, line) => {
|
|
14116
|
-
const [key, value] = line.split(': ');
|
|
14117
|
-
acc[key.toLowerCase()] = value;
|
|
14118
|
-
return acc;
|
|
14119
|
-
}, {});
|
|
14120
|
-
}
|
|
14121
|
-
|
|
14122
12940
|
/**
|
|
14123
12941
|
* This method does two things:
|
|
14124
12942
|
* - It enriches the regular XHR/fetch breadcrumbs with request/response size data
|
|
@@ -14131,16 +12949,10 @@ function handleNetworkBreadcrumbs(replay) {
|
|
|
14131
12949
|
try {
|
|
14132
12950
|
const textEncoder = new TextEncoder();
|
|
14133
12951
|
|
|
14134
|
-
const { networkDetailAllowUrls, networkCaptureBodies, networkRequestHeaders, networkResponseHeaders } =
|
|
14135
|
-
replay.getOptions();
|
|
14136
|
-
|
|
14137
12952
|
const options = {
|
|
14138
12953
|
replay,
|
|
14139
12954
|
textEncoder,
|
|
14140
|
-
|
|
14141
|
-
networkCaptureBodies,
|
|
14142
|
-
networkRequestHeaders,
|
|
14143
|
-
networkResponseHeaders,
|
|
12955
|
+
captureBodies: replay.getOptions()._experiments.captureNetworkBodies || false,
|
|
14144
12956
|
};
|
|
14145
12957
|
|
|
14146
12958
|
if (client && client.on) {
|
|
@@ -14248,66 +13060,9 @@ function handleScope(scope) {
|
|
|
14248
13060
|
return null;
|
|
14249
13061
|
}
|
|
14250
13062
|
|
|
14251
|
-
if (newBreadcrumb.category === 'console') {
|
|
14252
|
-
return normalizeConsoleBreadcrumb(newBreadcrumb);
|
|
14253
|
-
}
|
|
14254
|
-
|
|
14255
13063
|
return createBreadcrumb(newBreadcrumb);
|
|
14256
13064
|
}
|
|
14257
13065
|
|
|
14258
|
-
/** exported for tests only */
|
|
14259
|
-
function normalizeConsoleBreadcrumb(breadcrumb) {
|
|
14260
|
-
const args = breadcrumb.data && breadcrumb.data.arguments;
|
|
14261
|
-
|
|
14262
|
-
if (!Array.isArray(args) || args.length === 0) {
|
|
14263
|
-
return createBreadcrumb(breadcrumb);
|
|
14264
|
-
}
|
|
14265
|
-
|
|
14266
|
-
let isTruncated = false;
|
|
14267
|
-
|
|
14268
|
-
// Avoid giant args captures
|
|
14269
|
-
const normalizedArgs = args.map(arg => {
|
|
14270
|
-
if (!arg) {
|
|
14271
|
-
return arg;
|
|
14272
|
-
}
|
|
14273
|
-
if (typeof arg === 'string') {
|
|
14274
|
-
if (arg.length > CONSOLE_ARG_MAX_SIZE) {
|
|
14275
|
-
isTruncated = true;
|
|
14276
|
-
return `${arg.slice(0, CONSOLE_ARG_MAX_SIZE)}…`;
|
|
14277
|
-
}
|
|
14278
|
-
|
|
14279
|
-
return arg;
|
|
14280
|
-
}
|
|
14281
|
-
if (typeof arg === 'object') {
|
|
14282
|
-
try {
|
|
14283
|
-
const normalizedArg = normalize(arg, 7);
|
|
14284
|
-
const stringified = JSON.stringify(normalizedArg);
|
|
14285
|
-
if (stringified.length > CONSOLE_ARG_MAX_SIZE) {
|
|
14286
|
-
const fixedJson = fixJson(stringified.slice(0, CONSOLE_ARG_MAX_SIZE));
|
|
14287
|
-
const json = JSON.parse(fixedJson);
|
|
14288
|
-
// We only set this after JSON.parse() was successfull, so we know we didn't run into `catch`
|
|
14289
|
-
isTruncated = true;
|
|
14290
|
-
return json;
|
|
14291
|
-
}
|
|
14292
|
-
return normalizedArg;
|
|
14293
|
-
} catch (e) {
|
|
14294
|
-
// fall back to default
|
|
14295
|
-
}
|
|
14296
|
-
}
|
|
14297
|
-
|
|
14298
|
-
return arg;
|
|
14299
|
-
});
|
|
14300
|
-
|
|
14301
|
-
return createBreadcrumb({
|
|
14302
|
-
...breadcrumb,
|
|
14303
|
-
data: {
|
|
14304
|
-
...breadcrumb.data,
|
|
14305
|
-
arguments: normalizedArgs,
|
|
14306
|
-
...(isTruncated ? { _meta: { warnings: ['CONSOLE_ARG_TRUNCATED'] } } : {}),
|
|
14307
|
-
},
|
|
14308
|
-
});
|
|
14309
|
-
}
|
|
14310
|
-
|
|
14311
13066
|
/**
|
|
14312
13067
|
* Add global listeners that cannot be removed.
|
|
14313
13068
|
*/
|
|
@@ -14332,8 +13087,7 @@ function addGlobalListeners(replay) {
|
|
|
14332
13087
|
client.on('afterSendEvent', handleAfterSendEvent(replay));
|
|
14333
13088
|
client.on('createDsc', (dsc) => {
|
|
14334
13089
|
const replayId = replay.getSessionId();
|
|
14335
|
-
|
|
14336
|
-
if (replayId && replay.isEnabled() && replay.recordingMode === 'session') {
|
|
13090
|
+
if (replayId) {
|
|
14337
13091
|
dsc.replay_id = replayId;
|
|
14338
13092
|
}
|
|
14339
13093
|
});
|
|
@@ -14641,7 +13395,7 @@ function getHandleRecordingEmit(replay) {
|
|
|
14641
13395
|
// when an error occurs. Clear any state that happens before this current
|
|
14642
13396
|
// checkout. This needs to happen before `addEvent()` which updates state
|
|
14643
13397
|
// dependent on this reset.
|
|
14644
|
-
if (replay.recordingMode === '
|
|
13398
|
+
if (replay.recordingMode === 'error' && isCheckout) {
|
|
14645
13399
|
replay.setInitialState();
|
|
14646
13400
|
}
|
|
14647
13401
|
|
|
@@ -14655,14 +13409,6 @@ function getHandleRecordingEmit(replay) {
|
|
|
14655
13409
|
return false;
|
|
14656
13410
|
}
|
|
14657
13411
|
|
|
14658
|
-
// Additionally, create a meta event that will capture certain SDK settings.
|
|
14659
|
-
// In order to handle buffer mode, this needs to either be done when we
|
|
14660
|
-
// receive checkout events or at flush time.
|
|
14661
|
-
//
|
|
14662
|
-
// `isCheckout` is always true, but want to be explicit that it should
|
|
14663
|
-
// only be added for checkouts
|
|
14664
|
-
void addSettingsEvent(replay, isCheckout);
|
|
14665
|
-
|
|
14666
13412
|
// If there is a previousSessionId after a full snapshot occurs, then
|
|
14667
13413
|
// the replay session was started due to session expiration. The new session
|
|
14668
13414
|
// is started before triggering a new checkout and contains the id
|
|
@@ -14673,10 +13419,10 @@ function getHandleRecordingEmit(replay) {
|
|
|
14673
13419
|
return true;
|
|
14674
13420
|
}
|
|
14675
13421
|
|
|
14676
|
-
//
|
|
14677
|
-
//
|
|
14678
|
-
if (replay.recordingMode === '
|
|
14679
|
-
const earliestEvent = replay.
|
|
13422
|
+
// See note above re: session start needs to reflect the most recent
|
|
13423
|
+
// checkout.
|
|
13424
|
+
if (replay.recordingMode === 'error' && replay.session) {
|
|
13425
|
+
const { earliestEvent } = replay.getContext();
|
|
14680
13426
|
if (earliestEvent) {
|
|
14681
13427
|
replay.session.started = earliestEvent;
|
|
14682
13428
|
|
|
@@ -14686,30 +13432,6 @@ function getHandleRecordingEmit(replay) {
|
|
|
14686
13432
|
}
|
|
14687
13433
|
}
|
|
14688
13434
|
|
|
14689
|
-
const options = replay.getOptions();
|
|
14690
|
-
|
|
14691
|
-
// TODO: We want this as an experiment so that we can test
|
|
14692
|
-
// internally and create metrics before making this the default
|
|
14693
|
-
if (options._experiments.delayFlushOnCheckout) {
|
|
14694
|
-
// If the full snapshot is due to an initial load, we will not have
|
|
14695
|
-
// a previous session ID. In this case, we want to buffer events
|
|
14696
|
-
// for a set amount of time before flushing. This can help avoid
|
|
14697
|
-
// capturing replays of users that immediately close the window.
|
|
14698
|
-
setTimeout(() => replay.conditionalFlush(), options._experiments.delayFlushOnCheckout);
|
|
14699
|
-
|
|
14700
|
-
// Cancel any previously debounced flushes to ensure there are no [near]
|
|
14701
|
-
// simultaneous flushes happening. The latter request should be
|
|
14702
|
-
// insignificant in this case, so wait for additional user interaction to
|
|
14703
|
-
// trigger a new flush.
|
|
14704
|
-
//
|
|
14705
|
-
// This can happen because there's no guarantee that a recording event
|
|
14706
|
-
// happens first. e.g. a mouse click can happen and trigger a debounced
|
|
14707
|
-
// flush before the checkout.
|
|
14708
|
-
replay.cancelFlush();
|
|
14709
|
-
|
|
14710
|
-
return true;
|
|
14711
|
-
}
|
|
14712
|
-
|
|
14713
13435
|
// Flush immediately so that we do not miss the first segment, otherwise
|
|
14714
13436
|
// it can prevent loading on the UI. This will cause an increase in short
|
|
14715
13437
|
// replays (e.g. opening and closing a tab quickly), but these can be
|
|
@@ -14724,46 +13446,6 @@ function getHandleRecordingEmit(replay) {
|
|
|
14724
13446
|
};
|
|
14725
13447
|
}
|
|
14726
13448
|
|
|
14727
|
-
/**
|
|
14728
|
-
* Exported for tests
|
|
14729
|
-
*/
|
|
14730
|
-
function createOptionsEvent(replay) {
|
|
14731
|
-
const options = replay.getOptions();
|
|
14732
|
-
return {
|
|
14733
|
-
type: EventType.Custom,
|
|
14734
|
-
timestamp: Date.now(),
|
|
14735
|
-
data: {
|
|
14736
|
-
tag: 'options',
|
|
14737
|
-
payload: {
|
|
14738
|
-
sessionSampleRate: options.sessionSampleRate,
|
|
14739
|
-
errorSampleRate: options.errorSampleRate,
|
|
14740
|
-
useCompressionOption: options.useCompression,
|
|
14741
|
-
blockAllMedia: options.blockAllMedia,
|
|
14742
|
-
maskAllText: options.maskAllText,
|
|
14743
|
-
maskAllInputs: options.maskAllInputs,
|
|
14744
|
-
useCompression: replay.eventBuffer ? replay.eventBuffer.type === 'worker' : false,
|
|
14745
|
-
networkDetailHasUrls: options.networkDetailAllowUrls.length > 0,
|
|
14746
|
-
networkCaptureBodies: options.networkCaptureBodies,
|
|
14747
|
-
networkRequestHasHeaders: options.networkRequestHeaders.length > 0,
|
|
14748
|
-
networkResponseHasHeaders: options.networkResponseHeaders.length > 0,
|
|
14749
|
-
},
|
|
14750
|
-
},
|
|
14751
|
-
};
|
|
14752
|
-
}
|
|
14753
|
-
|
|
14754
|
-
/**
|
|
14755
|
-
* Add a "meta" event that contains a simplified view on current configuration
|
|
14756
|
-
* options. This should only be included on the first segment of a recording.
|
|
14757
|
-
*/
|
|
14758
|
-
function addSettingsEvent(replay, isCheckout) {
|
|
14759
|
-
// Only need to add this event when sending the first segment
|
|
14760
|
-
if (!isCheckout || !replay.session || replay.session.segmentId !== 0) {
|
|
14761
|
-
return Promise.resolve(null);
|
|
14762
|
-
}
|
|
14763
|
-
|
|
14764
|
-
return addEvent(replay, createOptionsEvent(replay), false);
|
|
14765
|
-
}
|
|
14766
|
-
|
|
14767
13449
|
/**
|
|
14768
13450
|
* Create a replay envelope ready to be sent.
|
|
14769
13451
|
* This includes both the replay event, as well as the recording data.
|
|
@@ -14875,9 +13557,11 @@ async function sendReplayRequest({
|
|
|
14875
13557
|
recordingData,
|
|
14876
13558
|
replayId,
|
|
14877
13559
|
segmentId: segment_id,
|
|
13560
|
+
includeReplayStartTimestamp,
|
|
14878
13561
|
eventContext,
|
|
14879
13562
|
timestamp,
|
|
14880
13563
|
session,
|
|
13564
|
+
options,
|
|
14881
13565
|
}) {
|
|
14882
13566
|
const preparedRecordingData = prepareRecordingData({
|
|
14883
13567
|
recordingData,
|
|
@@ -14899,8 +13583,9 @@ async function sendReplayRequest({
|
|
|
14899
13583
|
}
|
|
14900
13584
|
|
|
14901
13585
|
const baseEvent = {
|
|
13586
|
+
// @ts-ignore private api
|
|
14902
13587
|
type: REPLAY_EVENT_NAME,
|
|
14903
|
-
replay_start_timestamp: initialTimestamp / 1000,
|
|
13588
|
+
...(includeReplayStartTimestamp ? { replay_start_timestamp: initialTimestamp / 1000 } : {}),
|
|
14904
13589
|
timestamp: timestamp / 1000,
|
|
14905
13590
|
error_ids: errorIds,
|
|
14906
13591
|
trace_ids: traceIds,
|
|
@@ -14919,6 +13604,15 @@ async function sendReplayRequest({
|
|
|
14919
13604
|
return;
|
|
14920
13605
|
}
|
|
14921
13606
|
|
|
13607
|
+
replayEvent.contexts = {
|
|
13608
|
+
...replayEvent.contexts,
|
|
13609
|
+
replay: {
|
|
13610
|
+
...(replayEvent.contexts && replayEvent.contexts.replay),
|
|
13611
|
+
session_sample_rate: options.sessionSampleRate,
|
|
13612
|
+
error_sample_rate: options.errorSampleRate,
|
|
13613
|
+
},
|
|
13614
|
+
};
|
|
13615
|
+
|
|
14922
13616
|
/*
|
|
14923
13617
|
For reference, the fully built event looks something like this:
|
|
14924
13618
|
{
|
|
@@ -14949,6 +13643,10 @@ async function sendReplayRequest({
|
|
|
14949
13643
|
},
|
|
14950
13644
|
"sdkProcessingMetadata": {},
|
|
14951
13645
|
"contexts": {
|
|
13646
|
+
"replay": {
|
|
13647
|
+
"session_sample_rate": 1,
|
|
13648
|
+
"error_sample_rate": 0,
|
|
13649
|
+
},
|
|
14952
13650
|
},
|
|
14953
13651
|
}
|
|
14954
13652
|
*/
|
|
@@ -15074,11 +13772,9 @@ class ReplayContainer {
|
|
|
15074
13772
|
__init2() {this.performanceEvents = [];}
|
|
15075
13773
|
|
|
15076
13774
|
/**
|
|
15077
|
-
* Recording can happen in one of
|
|
15078
|
-
*
|
|
15079
|
-
*
|
|
15080
|
-
* - having replaysOnErrorSampleRate > 0 to capture replay when an error occurs
|
|
15081
|
-
* - or calling `flush()` to send the replay
|
|
13775
|
+
* Recording can happen in one of two modes:
|
|
13776
|
+
* * session: Record the whole session, sending it continuously
|
|
13777
|
+
* * error: Always keep the last 60s of recording, and when an error occurs, send it immediately
|
|
15082
13778
|
*/
|
|
15083
13779
|
__init3() {this.recordingMode = 'session';}
|
|
15084
13780
|
|
|
@@ -15087,8 +13783,7 @@ class ReplayContainer {
|
|
|
15087
13783
|
* @hidden
|
|
15088
13784
|
*/
|
|
15089
13785
|
__init4() {this.timeouts = {
|
|
15090
|
-
|
|
15091
|
-
sessionIdleExpire: SESSION_IDLE_EXPIRE_DURATION,
|
|
13786
|
+
sessionIdle: SESSION_IDLE_DURATION,
|
|
15092
13787
|
maxSessionLife: MAX_SESSION_LIFE,
|
|
15093
13788
|
}; }
|
|
15094
13789
|
|
|
@@ -15132,6 +13827,7 @@ class ReplayContainer {
|
|
|
15132
13827
|
errorIds: new Set(),
|
|
15133
13828
|
traceIds: new Set(),
|
|
15134
13829
|
urls: [],
|
|
13830
|
+
earliestEvent: null,
|
|
15135
13831
|
initialTimestamp: Date.now(),
|
|
15136
13832
|
initialUrl: '',
|
|
15137
13833
|
};}
|
|
@@ -15141,7 +13837,7 @@ class ReplayContainer {
|
|
|
15141
13837
|
recordingOptions,
|
|
15142
13838
|
}
|
|
15143
13839
|
|
|
15144
|
-
) {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);
|
|
13840
|
+
) {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);
|
|
15145
13841
|
this._recordingOptions = recordingOptions;
|
|
15146
13842
|
this._options = options;
|
|
15147
13843
|
|
|
@@ -15171,102 +13867,49 @@ class ReplayContainer {
|
|
|
15171
13867
|
}
|
|
15172
13868
|
|
|
15173
13869
|
/**
|
|
15174
|
-
* Initializes the plugin
|
|
15175
|
-
*
|
|
13870
|
+
* Initializes the plugin.
|
|
13871
|
+
*
|
|
13872
|
+
* Creates or loads a session, attaches listeners to varying events (DOM,
|
|
13873
|
+
* _performanceObserver, Recording, Sentry SDK, etc)
|
|
15176
13874
|
*/
|
|
15177
|
-
|
|
15178
|
-
|
|
15179
|
-
|
|
15180
|
-
// If neither sample rate is > 0, then do nothing - user will need to call one of
|
|
15181
|
-
// `start()` or `startBuffering` themselves.
|
|
15182
|
-
if (errorSampleRate <= 0 && sessionSampleRate <= 0) {
|
|
15183
|
-
return;
|
|
15184
|
-
}
|
|
15185
|
-
|
|
15186
|
-
// Otherwise if there is _any_ sample rate set, try to load an existing
|
|
15187
|
-
// session, or create a new one.
|
|
15188
|
-
const isSessionSampled = this._loadAndCheckSession();
|
|
13875
|
+
start() {
|
|
13876
|
+
this.setInitialState();
|
|
15189
13877
|
|
|
15190
|
-
if (!
|
|
15191
|
-
// This should only occur if `errorSampleRate` is 0 and was unsampled for
|
|
15192
|
-
// session-based replay. In this case there is nothing to do.
|
|
13878
|
+
if (!this._loadAndCheckSession()) {
|
|
15193
13879
|
return;
|
|
15194
13880
|
}
|
|
15195
13881
|
|
|
13882
|
+
// If there is no session, then something bad has happened - can't continue
|
|
15196
13883
|
if (!this.session) {
|
|
15197
|
-
|
|
15198
|
-
this._handleException(new Error('Unable to initialize and create session'));
|
|
13884
|
+
this._handleException(new Error('No session found'));
|
|
15199
13885
|
return;
|
|
15200
13886
|
}
|
|
15201
13887
|
|
|
15202
|
-
if (this.session.sampled
|
|
15203
|
-
// If not sampled
|
|
15204
|
-
|
|
15205
|
-
// could have sessions from Session storage that are still `error` from
|
|
15206
|
-
// prior SDK version.
|
|
15207
|
-
this.recordingMode = 'buffer';
|
|
15208
|
-
}
|
|
15209
|
-
|
|
15210
|
-
this._initializeRecording();
|
|
15211
|
-
}
|
|
15212
|
-
|
|
15213
|
-
/**
|
|
15214
|
-
* Start a replay regardless of sampling rate. Calling this will always
|
|
15215
|
-
* create a new session. Will throw an error if replay is already in progress.
|
|
15216
|
-
*
|
|
15217
|
-
* Creates or loads a session, attaches listeners to varying events (DOM,
|
|
15218
|
-
* _performanceObserver, Recording, Sentry SDK, etc)
|
|
15219
|
-
*/
|
|
15220
|
-
start() {
|
|
15221
|
-
if (this._isEnabled && this.recordingMode === 'session') {
|
|
15222
|
-
throw new Error('Replay recording is already in progress');
|
|
13888
|
+
if (!this.session.sampled) {
|
|
13889
|
+
// If session was not sampled, then we do not initialize the integration at all.
|
|
13890
|
+
return;
|
|
15223
13891
|
}
|
|
15224
13892
|
|
|
15225
|
-
|
|
15226
|
-
|
|
13893
|
+
// If session is sampled for errors, then we need to set the recordingMode
|
|
13894
|
+
// to 'error', which will configure recording with different options.
|
|
13895
|
+
if (this.session.sampled === 'error') {
|
|
13896
|
+
this.recordingMode = 'error';
|
|
15227
13897
|
}
|
|
15228
13898
|
|
|
15229
|
-
|
|
13899
|
+
// setup() is generally called on page load or manually - in both cases we
|
|
13900
|
+
// should treat it as an activity
|
|
13901
|
+
this._updateSessionActivity();
|
|
15230
13902
|
|
|
15231
|
-
|
|
15232
|
-
|
|
15233
|
-
stickySession: Boolean(this._options.stickySession),
|
|
15234
|
-
currentSession: this.session,
|
|
15235
|
-
// This is intentional: create a new session-based replay when calling `start()`
|
|
15236
|
-
sessionSampleRate: 1,
|
|
15237
|
-
allowBuffering: false,
|
|
13903
|
+
this.eventBuffer = createEventBuffer({
|
|
13904
|
+
useCompression: this._options.useCompression,
|
|
15238
13905
|
});
|
|
15239
13906
|
|
|
15240
|
-
|
|
15241
|
-
this.session = session;
|
|
15242
|
-
|
|
15243
|
-
this._initializeRecording();
|
|
15244
|
-
}
|
|
15245
|
-
|
|
15246
|
-
/**
|
|
15247
|
-
* Start replay buffering. Buffers until `flush()` is called or, if
|
|
15248
|
-
* `replaysOnErrorSampleRate` > 0, an error occurs.
|
|
15249
|
-
*/
|
|
15250
|
-
startBuffering() {
|
|
15251
|
-
if (this._isEnabled) {
|
|
15252
|
-
throw new Error('Replay recording is already in progress');
|
|
15253
|
-
}
|
|
15254
|
-
|
|
15255
|
-
const previousSessionId = this.session && this.session.id;
|
|
15256
|
-
|
|
15257
|
-
const { session } = getSession({
|
|
15258
|
-
timeouts: this.timeouts,
|
|
15259
|
-
stickySession: Boolean(this._options.stickySession),
|
|
15260
|
-
currentSession: this.session,
|
|
15261
|
-
sessionSampleRate: 0,
|
|
15262
|
-
allowBuffering: true,
|
|
15263
|
-
});
|
|
13907
|
+
this._addListeners();
|
|
15264
13908
|
|
|
15265
|
-
|
|
15266
|
-
this.
|
|
13909
|
+
// Need to set as enabled before we start recording, as `record()` can trigger a flush with a new checkout
|
|
13910
|
+
this._isEnabled = true;
|
|
15267
13911
|
|
|
15268
|
-
this.
|
|
15269
|
-
this._initializeRecording();
|
|
13912
|
+
this.startRecording();
|
|
15270
13913
|
}
|
|
15271
13914
|
|
|
15272
13915
|
/**
|
|
@@ -15281,7 +13924,7 @@ class ReplayContainer {
|
|
|
15281
13924
|
// When running in error sampling mode, we need to overwrite `checkoutEveryNms`
|
|
15282
13925
|
// Without this, it would record forever, until an error happens, which we don't want
|
|
15283
13926
|
// instead, we'll always keep the last 60 seconds of replay before an error happened
|
|
15284
|
-
...(this.recordingMode === '
|
|
13927
|
+
...(this.recordingMode === 'error' && { checkoutEveryNms: ERROR_CHECKOUT_TIME }),
|
|
15285
13928
|
emit: getHandleRecordingEmit(this),
|
|
15286
13929
|
onMutation: this._onMutationHandler,
|
|
15287
13930
|
});
|
|
@@ -15292,18 +13935,17 @@ class ReplayContainer {
|
|
|
15292
13935
|
|
|
15293
13936
|
/**
|
|
15294
13937
|
* Stops the recording, if it was running.
|
|
15295
|
-
*
|
|
15296
|
-
* Returns true if it was previously stopped, or is now stopped,
|
|
15297
|
-
* otherwise false.
|
|
13938
|
+
* Returns true if it was stopped, else false.
|
|
15298
13939
|
*/
|
|
15299
13940
|
stopRecording() {
|
|
15300
13941
|
try {
|
|
15301
13942
|
if (this._stopRecording) {
|
|
15302
13943
|
this._stopRecording();
|
|
15303
13944
|
this._stopRecording = undefined;
|
|
13945
|
+
return true;
|
|
15304
13946
|
}
|
|
15305
13947
|
|
|
15306
|
-
return
|
|
13948
|
+
return false;
|
|
15307
13949
|
} catch (err) {
|
|
15308
13950
|
this._handleException(err);
|
|
15309
13951
|
return false;
|
|
@@ -15314,7 +13956,7 @@ class ReplayContainer {
|
|
|
15314
13956
|
* Currently, this needs to be manually called (e.g. for tests). Sentry SDK
|
|
15315
13957
|
* does not support a teardown
|
|
15316
13958
|
*/
|
|
15317
|
-
|
|
13959
|
+
stop(reason) {
|
|
15318
13960
|
if (!this._isEnabled) {
|
|
15319
13961
|
return;
|
|
15320
13962
|
}
|
|
@@ -15330,24 +13972,12 @@ class ReplayContainer {
|
|
|
15330
13972
|
log(msg);
|
|
15331
13973
|
}
|
|
15332
13974
|
|
|
15333
|
-
// We can't move `_isEnabled` after awaiting a flush, otherwise we can
|
|
15334
|
-
// enter into an infinite loop when `stop()` is called while flushing.
|
|
15335
13975
|
this._isEnabled = false;
|
|
15336
13976
|
this._removeListeners();
|
|
15337
13977
|
this.stopRecording();
|
|
15338
|
-
|
|
15339
|
-
this._debouncedFlush.cancel();
|
|
15340
|
-
// See comment above re: `_isEnabled`, we "force" a flush, ignoring the
|
|
15341
|
-
// `_isEnabled` state of the plugin since it was disabled above.
|
|
15342
|
-
await this._flush({ force: true });
|
|
15343
|
-
|
|
15344
|
-
// After flush, destroy event buffer
|
|
15345
13978
|
this.eventBuffer && this.eventBuffer.destroy();
|
|
15346
13979
|
this.eventBuffer = null;
|
|
15347
|
-
|
|
15348
|
-
// Clear session from session storage, note this means if a new session
|
|
15349
|
-
// is started after, it will not have `previousSessionId`
|
|
15350
|
-
clearSession(this);
|
|
13980
|
+
this._debouncedFlush.cancel();
|
|
15351
13981
|
} catch (err) {
|
|
15352
13982
|
this._handleException(err);
|
|
15353
13983
|
}
|
|
@@ -15378,45 +14008,6 @@ class ReplayContainer {
|
|
|
15378
14008
|
this.startRecording();
|
|
15379
14009
|
}
|
|
15380
14010
|
|
|
15381
|
-
/**
|
|
15382
|
-
* If not in "session" recording mode, flush event buffer which will create a new replay.
|
|
15383
|
-
* Unless `continueRecording` is false, the replay will continue to record and
|
|
15384
|
-
* behave as a "session"-based replay.
|
|
15385
|
-
*
|
|
15386
|
-
* Otherwise, queue up a flush.
|
|
15387
|
-
*/
|
|
15388
|
-
async sendBufferedReplayOrFlush({ continueRecording = true } = {}) {
|
|
15389
|
-
if (this.recordingMode === 'session') {
|
|
15390
|
-
return this.flushImmediate();
|
|
15391
|
-
}
|
|
15392
|
-
|
|
15393
|
-
// Allow flush to complete before resuming as a session recording, otherwise
|
|
15394
|
-
// the checkout from `startRecording` may be included in the payload.
|
|
15395
|
-
// Prefer to keep the error replay as a separate (and smaller) segment
|
|
15396
|
-
// than the session replay.
|
|
15397
|
-
await this.flushImmediate();
|
|
15398
|
-
|
|
15399
|
-
const hasStoppedRecording = this.stopRecording();
|
|
15400
|
-
|
|
15401
|
-
if (!continueRecording || !hasStoppedRecording) {
|
|
15402
|
-
return;
|
|
15403
|
-
}
|
|
15404
|
-
|
|
15405
|
-
// Re-start recording, but in "session" recording mode
|
|
15406
|
-
|
|
15407
|
-
// Reset all "capture on error" configuration before
|
|
15408
|
-
// starting a new recording
|
|
15409
|
-
this.recordingMode = 'session';
|
|
15410
|
-
|
|
15411
|
-
// Once this session ends, we do not want to refresh it
|
|
15412
|
-
if (this.session) {
|
|
15413
|
-
this.session.shouldRefresh = false;
|
|
15414
|
-
this._maybeSaveSession();
|
|
15415
|
-
}
|
|
15416
|
-
|
|
15417
|
-
this.startRecording();
|
|
15418
|
-
}
|
|
15419
|
-
|
|
15420
14011
|
/**
|
|
15421
14012
|
* We want to batch uploads of replay events. Save events only if
|
|
15422
14013
|
* `<flushMinDelay>` milliseconds have elapsed since the last event
|
|
@@ -15426,12 +14017,12 @@ class ReplayContainer {
|
|
|
15426
14017
|
* processing and hand back control to caller.
|
|
15427
14018
|
*/
|
|
15428
14019
|
addUpdate(cb) {
|
|
15429
|
-
// We need to always run `cb` (e.g. in the case of `this.recordingMode == '
|
|
14020
|
+
// We need to always run `cb` (e.g. in the case of `this.recordingMode == 'error'`)
|
|
15430
14021
|
const cbResult = cb();
|
|
15431
14022
|
|
|
15432
14023
|
// If this option is turned on then we will only want to call `flush`
|
|
15433
14024
|
// explicitly
|
|
15434
|
-
if (this.recordingMode === '
|
|
14025
|
+
if (this.recordingMode === 'error') {
|
|
15435
14026
|
return;
|
|
15436
14027
|
}
|
|
15437
14028
|
|
|
@@ -15475,17 +14066,7 @@ class ReplayContainer {
|
|
|
15475
14066
|
}
|
|
15476
14067
|
|
|
15477
14068
|
/**
|
|
15478
|
-
*
|
|
15479
|
-
*/
|
|
15480
|
-
conditionalFlush() {
|
|
15481
|
-
if (this.recordingMode === 'buffer') {
|
|
15482
|
-
return Promise.resolve();
|
|
15483
|
-
}
|
|
15484
|
-
|
|
15485
|
-
return this.flushImmediate();
|
|
15486
|
-
}
|
|
15487
|
-
|
|
15488
|
-
/**
|
|
14069
|
+
*
|
|
15489
14070
|
* Always flush via `_debouncedFlush` so that we do not have flushes triggered
|
|
15490
14071
|
* from calling both `flush` and `_debouncedFlush`. Otherwise, there could be
|
|
15491
14072
|
* cases of mulitple flushes happening closely together.
|
|
@@ -15496,13 +14077,6 @@ class ReplayContainer {
|
|
|
15496
14077
|
return this._debouncedFlush.flush() ;
|
|
15497
14078
|
}
|
|
15498
14079
|
|
|
15499
|
-
/**
|
|
15500
|
-
* Cancels queued up flushes.
|
|
15501
|
-
*/
|
|
15502
|
-
cancelFlush() {
|
|
15503
|
-
this._debouncedFlush.cancel();
|
|
15504
|
-
}
|
|
15505
|
-
|
|
15506
14080
|
/** Get the current sesion (=replay) ID */
|
|
15507
14081
|
getSessionId() {
|
|
15508
14082
|
return this.session && this.session.id;
|
|
@@ -15520,12 +14094,12 @@ class ReplayContainer {
|
|
|
15520
14094
|
const oldSessionId = this.getSessionId();
|
|
15521
14095
|
|
|
15522
14096
|
// Prevent starting a new session if the last user activity is older than
|
|
15523
|
-
//
|
|
14097
|
+
// SESSION_IDLE_DURATION. Otherwise non-user activity can trigger a new
|
|
15524
14098
|
// session+recording. This creates noisy replays that do not have much
|
|
15525
14099
|
// content in them.
|
|
15526
14100
|
if (
|
|
15527
14101
|
this._lastActivity &&
|
|
15528
|
-
isExpired(this._lastActivity, this.timeouts.
|
|
14102
|
+
isExpired(this._lastActivity, this.timeouts.sessionIdle) &&
|
|
15529
14103
|
this.session &&
|
|
15530
14104
|
this.session.sampled === 'session'
|
|
15531
14105
|
) {
|
|
@@ -15575,30 +14149,6 @@ class ReplayContainer {
|
|
|
15575
14149
|
this._context.urls.push(url);
|
|
15576
14150
|
}
|
|
15577
14151
|
|
|
15578
|
-
/**
|
|
15579
|
-
* Initialize and start all listeners to varying events (DOM,
|
|
15580
|
-
* Performance Observer, Recording, Sentry SDK, etc)
|
|
15581
|
-
*/
|
|
15582
|
-
_initializeRecording() {
|
|
15583
|
-
this.setInitialState();
|
|
15584
|
-
|
|
15585
|
-
// this method is generally called on page load or manually - in both cases
|
|
15586
|
-
// we should treat it as an activity
|
|
15587
|
-
this._updateSessionActivity();
|
|
15588
|
-
|
|
15589
|
-
this.eventBuffer = createEventBuffer({
|
|
15590
|
-
useCompression: this._options.useCompression,
|
|
15591
|
-
});
|
|
15592
|
-
|
|
15593
|
-
this._removeListeners();
|
|
15594
|
-
this._addListeners();
|
|
15595
|
-
|
|
15596
|
-
// Need to set as enabled before we start recording, as `record()` can trigger a flush with a new checkout
|
|
15597
|
-
this._isEnabled = true;
|
|
15598
|
-
|
|
15599
|
-
this.startRecording();
|
|
15600
|
-
}
|
|
15601
|
-
|
|
15602
14152
|
/** A wrapper to conditionally capture exceptions. */
|
|
15603
14153
|
_handleException(error) {
|
|
15604
14154
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error('[Replay]', error);
|
|
@@ -15618,7 +14168,7 @@ class ReplayContainer {
|
|
|
15618
14168
|
stickySession: Boolean(this._options.stickySession),
|
|
15619
14169
|
currentSession: this.session,
|
|
15620
14170
|
sessionSampleRate: this._options.sessionSampleRate,
|
|
15621
|
-
|
|
14171
|
+
errorSampleRate: this._options.errorSampleRate,
|
|
15622
14172
|
});
|
|
15623
14173
|
|
|
15624
14174
|
// If session was newly created (i.e. was not loaded from storage), then
|
|
@@ -15635,7 +14185,7 @@ class ReplayContainer {
|
|
|
15635
14185
|
this.session = session;
|
|
15636
14186
|
|
|
15637
14187
|
if (!this.session.sampled) {
|
|
15638
|
-
|
|
14188
|
+
this.stop('session unsampled');
|
|
15639
14189
|
return false;
|
|
15640
14190
|
}
|
|
15641
14191
|
|
|
@@ -15650,7 +14200,6 @@ class ReplayContainer {
|
|
|
15650
14200
|
WINDOW.document.addEventListener('visibilitychange', this._handleVisibilityChange);
|
|
15651
14201
|
WINDOW.addEventListener('blur', this._handleWindowBlur);
|
|
15652
14202
|
WINDOW.addEventListener('focus', this._handleWindowFocus);
|
|
15653
|
-
WINDOW.addEventListener('keydown', this._handleKeyboardEvent);
|
|
15654
14203
|
|
|
15655
14204
|
// There is no way to remove these listeners, so ensure they are only added once
|
|
15656
14205
|
if (!this._hasInitializedCoreListeners) {
|
|
@@ -15679,7 +14228,6 @@ class ReplayContainer {
|
|
|
15679
14228
|
|
|
15680
14229
|
WINDOW.removeEventListener('blur', this._handleWindowBlur);
|
|
15681
14230
|
WINDOW.removeEventListener('focus', this._handleWindowFocus);
|
|
15682
|
-
WINDOW.removeEventListener('keydown', this._handleKeyboardEvent);
|
|
15683
14231
|
|
|
15684
14232
|
if (this._performanceObserver) {
|
|
15685
14233
|
this._performanceObserver.disconnect();
|
|
@@ -15730,11 +14278,6 @@ class ReplayContainer {
|
|
|
15730
14278
|
this._doChangeToForegroundTasks(breadcrumb);
|
|
15731
14279
|
};}
|
|
15732
14280
|
|
|
15733
|
-
/** Ensure page remains active when a key is pressed. */
|
|
15734
|
-
__init16() {this._handleKeyboardEvent = (event) => {
|
|
15735
|
-
handleKeyboardEvent(this, event);
|
|
15736
|
-
};}
|
|
15737
|
-
|
|
15738
14281
|
/**
|
|
15739
14282
|
* Tasks to run when we consider a page to be hidden (via blurring and/or visibility)
|
|
15740
14283
|
*/
|
|
@@ -15752,7 +14295,7 @@ class ReplayContainer {
|
|
|
15752
14295
|
// Send replay when the page/tab becomes hidden. There is no reason to send
|
|
15753
14296
|
// replay if it becomes visible, since no actions we care about were done
|
|
15754
14297
|
// while it was hidden
|
|
15755
|
-
|
|
14298
|
+
this._conditionalFlush();
|
|
15756
14299
|
}
|
|
15757
14300
|
|
|
15758
14301
|
/**
|
|
@@ -15766,7 +14309,7 @@ class ReplayContainer {
|
|
|
15766
14309
|
const isSessionActive = this.checkAndHandleExpiredSession();
|
|
15767
14310
|
|
|
15768
14311
|
if (!isSessionActive) {
|
|
15769
|
-
// If the user has come back to the page within
|
|
14312
|
+
// If the user has come back to the page within SESSION_IDLE_DURATION
|
|
15770
14313
|
// ms, we will re-use the existing session, otherwise create a new
|
|
15771
14314
|
// session
|
|
15772
14315
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Replay] Document has become active, but session has expired');
|
|
@@ -15814,7 +14357,7 @@ class ReplayContainer {
|
|
|
15814
14357
|
_createCustomBreadcrumb(breadcrumb) {
|
|
15815
14358
|
this.addUpdate(() => {
|
|
15816
14359
|
void addEvent(this, {
|
|
15817
|
-
type: EventType
|
|
14360
|
+
type: EventType.Custom,
|
|
15818
14361
|
timestamp: breadcrumb.timestamp || 0,
|
|
15819
14362
|
data: {
|
|
15820
14363
|
tag: 'breadcrumb',
|
|
@@ -15836,6 +14379,17 @@ class ReplayContainer {
|
|
|
15836
14379
|
return Promise.all(createPerformanceSpans(this, createPerformanceEntries(entries)));
|
|
15837
14380
|
}
|
|
15838
14381
|
|
|
14382
|
+
/**
|
|
14383
|
+
* Only flush if `this.recordingMode === 'session'`
|
|
14384
|
+
*/
|
|
14385
|
+
_conditionalFlush() {
|
|
14386
|
+
if (this.recordingMode === 'error') {
|
|
14387
|
+
return;
|
|
14388
|
+
}
|
|
14389
|
+
|
|
14390
|
+
void this.flushImmediate();
|
|
14391
|
+
}
|
|
14392
|
+
|
|
15839
14393
|
/**
|
|
15840
14394
|
* Clear _context
|
|
15841
14395
|
*/
|
|
@@ -15844,35 +14398,22 @@ class ReplayContainer {
|
|
|
15844
14398
|
this._context.errorIds.clear();
|
|
15845
14399
|
this._context.traceIds.clear();
|
|
15846
14400
|
this._context.urls = [];
|
|
15847
|
-
|
|
15848
|
-
|
|
15849
|
-
/** Update the initial timestamp based on the buffer content. */
|
|
15850
|
-
_updateInitialTimestampFromEventBuffer() {
|
|
15851
|
-
const { session, eventBuffer } = this;
|
|
15852
|
-
if (!session || !eventBuffer) {
|
|
15853
|
-
return;
|
|
15854
|
-
}
|
|
15855
|
-
|
|
15856
|
-
// we only ever update this on the initial segment
|
|
15857
|
-
if (session.segmentId) {
|
|
15858
|
-
return;
|
|
15859
|
-
}
|
|
15860
|
-
|
|
15861
|
-
const earliestEvent = eventBuffer.getEarliestTimestamp();
|
|
15862
|
-
if (earliestEvent && earliestEvent < this._context.initialTimestamp) {
|
|
15863
|
-
this._context.initialTimestamp = earliestEvent;
|
|
15864
|
-
}
|
|
14401
|
+
this._context.earliestEvent = null;
|
|
15865
14402
|
}
|
|
15866
14403
|
|
|
15867
14404
|
/**
|
|
15868
14405
|
* Return and clear _context
|
|
15869
14406
|
*/
|
|
15870
14407
|
_popEventContext() {
|
|
14408
|
+
if (this._context.earliestEvent && this._context.earliestEvent < this._context.initialTimestamp) {
|
|
14409
|
+
this._context.initialTimestamp = this._context.earliestEvent;
|
|
14410
|
+
}
|
|
14411
|
+
|
|
15871
14412
|
const _context = {
|
|
15872
14413
|
initialTimestamp: this._context.initialTimestamp,
|
|
15873
14414
|
initialUrl: this._context.initialUrl,
|
|
15874
|
-
errorIds: Array.from(this._context.errorIds),
|
|
15875
|
-
traceIds: Array.from(this._context.traceIds),
|
|
14415
|
+
errorIds: Array.from(this._context.errorIds).filter(Boolean),
|
|
14416
|
+
traceIds: Array.from(this._context.traceIds).filter(Boolean),
|
|
15876
14417
|
urls: this._context.urls,
|
|
15877
14418
|
};
|
|
15878
14419
|
|
|
@@ -15911,9 +14452,6 @@ class ReplayContainer {
|
|
|
15911
14452
|
}
|
|
15912
14453
|
|
|
15913
14454
|
try {
|
|
15914
|
-
// This uses the data from the eventBuffer, so we need to call this before `finish()
|
|
15915
|
-
this._updateInitialTimestampFromEventBuffer();
|
|
15916
|
-
|
|
15917
14455
|
// Note this empties the event buffer regardless of outcome of sending replay
|
|
15918
14456
|
const recordingData = await this.eventBuffer.finish();
|
|
15919
14457
|
|
|
@@ -15929,6 +14467,7 @@ class ReplayContainer {
|
|
|
15929
14467
|
replayId,
|
|
15930
14468
|
recordingData,
|
|
15931
14469
|
segmentId,
|
|
14470
|
+
includeReplayStartTimestamp: segmentId === 0,
|
|
15932
14471
|
eventContext,
|
|
15933
14472
|
session: this.session,
|
|
15934
14473
|
options: this.getOptions(),
|
|
@@ -15940,7 +14479,7 @@ class ReplayContainer {
|
|
|
15940
14479
|
// This means we retried 3 times and all of them failed,
|
|
15941
14480
|
// or we ran into a problem we don't want to retry, like rate limiting.
|
|
15942
14481
|
// In this case, we want to completely stop the replay - otherwise, we may get inconsistent segments
|
|
15943
|
-
|
|
14482
|
+
this.stop('sendReplay');
|
|
15944
14483
|
|
|
15945
14484
|
const client = getCurrentHub().getClient();
|
|
15946
14485
|
|
|
@@ -15954,12 +14493,8 @@ class ReplayContainer {
|
|
|
15954
14493
|
* Flush recording data to Sentry. Creates a lock so that only a single flush
|
|
15955
14494
|
* can be active at a time. Do not call this directly.
|
|
15956
14495
|
*/
|
|
15957
|
-
|
|
15958
|
-
|
|
15959
|
-
}
|
|
15960
|
-
|
|
15961
|
-
= {}) => {
|
|
15962
|
-
if (!this._isEnabled && !force) {
|
|
14496
|
+
__init16() {this._flush = async () => {
|
|
14497
|
+
if (!this._isEnabled) {
|
|
15963
14498
|
// This can happen if e.g. the replay was stopped because of exceeding the retry limit
|
|
15964
14499
|
return;
|
|
15965
14500
|
}
|
|
@@ -16009,7 +14544,7 @@ class ReplayContainer {
|
|
|
16009
14544
|
}
|
|
16010
14545
|
|
|
16011
14546
|
/** Handler for rrweb.record.onMutation */
|
|
16012
|
-
|
|
14547
|
+
__init17() {this._onMutationHandler = (mutations) => {
|
|
16013
14548
|
const count = mutations.length;
|
|
16014
14549
|
|
|
16015
14550
|
const mutationLimit = this._options._experiments.mutationLimit || 0;
|
|
@@ -16143,8 +14678,6 @@ function isElectronNodeRenderer() {
|
|
|
16143
14678
|
const MEDIA_SELECTORS =
|
|
16144
14679
|
'img,image,svg,video,object,picture,embed,map,audio,link[rel="icon"],link[rel="apple-touch-icon"]';
|
|
16145
14680
|
|
|
16146
|
-
const DEFAULT_NETWORK_HEADERS = ['content-length', 'content-type', 'accept'];
|
|
16147
|
-
|
|
16148
14681
|
let _initialized = false;
|
|
16149
14682
|
|
|
16150
14683
|
/**
|
|
@@ -16185,11 +14718,6 @@ class Replay {
|
|
|
16185
14718
|
maskAllInputs = true,
|
|
16186
14719
|
blockAllMedia = true,
|
|
16187
14720
|
|
|
16188
|
-
networkDetailAllowUrls = [],
|
|
16189
|
-
networkCaptureBodies = true,
|
|
16190
|
-
networkRequestHeaders = [],
|
|
16191
|
-
networkResponseHeaders = [],
|
|
16192
|
-
|
|
16193
14721
|
mask = [],
|
|
16194
14722
|
unmask = [],
|
|
16195
14723
|
block = [],
|
|
@@ -16197,8 +14725,6 @@ class Replay {
|
|
|
16197
14725
|
ignore = [],
|
|
16198
14726
|
maskFn,
|
|
16199
14727
|
|
|
16200
|
-
beforeAddRecordingEvent,
|
|
16201
|
-
|
|
16202
14728
|
// eslint-disable-next-line deprecation/deprecation
|
|
16203
14729
|
blockClass,
|
|
16204
14730
|
// eslint-disable-next-line deprecation/deprecation
|
|
@@ -16250,14 +14776,6 @@ class Replay {
|
|
|
16250
14776
|
errorSampleRate,
|
|
16251
14777
|
useCompression,
|
|
16252
14778
|
blockAllMedia,
|
|
16253
|
-
maskAllInputs,
|
|
16254
|
-
maskAllText,
|
|
16255
|
-
networkDetailAllowUrls,
|
|
16256
|
-
networkCaptureBodies,
|
|
16257
|
-
networkRequestHeaders: _getMergedNetworkHeaders(networkRequestHeaders),
|
|
16258
|
-
networkResponseHeaders: _getMergedNetworkHeaders(networkResponseHeaders),
|
|
16259
|
-
beforeAddRecordingEvent,
|
|
16260
|
-
|
|
16261
14779
|
_experiments,
|
|
16262
14780
|
};
|
|
16263
14781
|
|
|
@@ -16311,7 +14829,14 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
|
|
|
16311
14829
|
}
|
|
16312
14830
|
|
|
16313
14831
|
/**
|
|
16314
|
-
*
|
|
14832
|
+
* We previously used to create a transaction in `setupOnce` and it would
|
|
14833
|
+
* potentially create a transaction before some native SDK integrations have run
|
|
14834
|
+
* and applied their own global event processor. An example is:
|
|
14835
|
+
* https://github.com/getsentry/sentry-javascript/blob/b47ceafbdac7f8b99093ce6023726ad4687edc48/packages/browser/src/integrations/useragent.ts
|
|
14836
|
+
*
|
|
14837
|
+
* So we call `replay.setup` in next event loop as a workaround to wait for other
|
|
14838
|
+
* global event processors to finish. This is no longer needed, but keeping it
|
|
14839
|
+
* here to avoid any future issues.
|
|
16315
14840
|
*/
|
|
16316
14841
|
setupOnce() {
|
|
16317
14842
|
if (!isBrowser()) {
|
|
@@ -16320,20 +14845,12 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
|
|
|
16320
14845
|
|
|
16321
14846
|
this._setup();
|
|
16322
14847
|
|
|
16323
|
-
//
|
|
16324
|
-
|
|
16325
|
-
// and applied their own global event processor. An example is:
|
|
16326
|
-
// https://github.com/getsentry/sentry-javascript/blob/b47ceafbdac7f8b99093ce6023726ad4687edc48/packages/browser/src/integrations/useragent.ts
|
|
16327
|
-
//
|
|
16328
|
-
// So we call `this._initialize()` in next event loop as a workaround to wait for other
|
|
16329
|
-
// global event processors to finish. This is no longer needed, but keeping it
|
|
16330
|
-
// here to avoid any future issues.
|
|
16331
|
-
setTimeout(() => this._initialize());
|
|
14848
|
+
// XXX: See method comments above
|
|
14849
|
+
setTimeout(() => this.start());
|
|
16332
14850
|
}
|
|
16333
14851
|
|
|
16334
14852
|
/**
|
|
16335
|
-
*
|
|
16336
|
-
* create a new session. Will throw an error if replay is already in progress.
|
|
14853
|
+
* Initializes the plugin.
|
|
16337
14854
|
*
|
|
16338
14855
|
* Creates or loads a session, attaches listeners to varying events (DOM,
|
|
16339
14856
|
* PerformanceObserver, Recording, Sentry SDK, etc)
|
|
@@ -16346,64 +14863,27 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
|
|
|
16346
14863
|
this._replay.start();
|
|
16347
14864
|
}
|
|
16348
14865
|
|
|
16349
|
-
/**
|
|
16350
|
-
* Start replay buffering. Buffers until `flush()` is called or, if
|
|
16351
|
-
* `replaysOnErrorSampleRate` > 0, until an error occurs.
|
|
16352
|
-
*/
|
|
16353
|
-
startBuffering() {
|
|
16354
|
-
if (!this._replay) {
|
|
16355
|
-
return;
|
|
16356
|
-
}
|
|
16357
|
-
|
|
16358
|
-
this._replay.startBuffering();
|
|
16359
|
-
}
|
|
16360
|
-
|
|
16361
14866
|
/**
|
|
16362
14867
|
* Currently, this needs to be manually called (e.g. for tests). Sentry SDK
|
|
16363
14868
|
* does not support a teardown
|
|
16364
14869
|
*/
|
|
16365
14870
|
stop() {
|
|
16366
14871
|
if (!this._replay) {
|
|
16367
|
-
return
|
|
16368
|
-
}
|
|
16369
|
-
|
|
16370
|
-
return this._replay.stop();
|
|
16371
|
-
}
|
|
16372
|
-
|
|
16373
|
-
/**
|
|
16374
|
-
* If not in "session" recording mode, flush event buffer which will create a new replay.
|
|
16375
|
-
* Unless `continueRecording` is false, the replay will continue to record and
|
|
16376
|
-
* behave as a "session"-based replay.
|
|
16377
|
-
*
|
|
16378
|
-
* Otherwise, queue up a flush.
|
|
16379
|
-
*/
|
|
16380
|
-
flush(options) {
|
|
16381
|
-
if (!this._replay || !this._replay.isEnabled()) {
|
|
16382
|
-
return Promise.resolve();
|
|
14872
|
+
return;
|
|
16383
14873
|
}
|
|
16384
14874
|
|
|
16385
|
-
|
|
14875
|
+
this._replay.stop();
|
|
16386
14876
|
}
|
|
16387
14877
|
|
|
16388
14878
|
/**
|
|
16389
|
-
*
|
|
14879
|
+
* Immediately send all pending events.
|
|
16390
14880
|
*/
|
|
16391
|
-
|
|
14881
|
+
flush() {
|
|
16392
14882
|
if (!this._replay || !this._replay.isEnabled()) {
|
|
16393
14883
|
return;
|
|
16394
14884
|
}
|
|
16395
14885
|
|
|
16396
|
-
return this._replay.
|
|
16397
|
-
}
|
|
16398
|
-
/**
|
|
16399
|
-
* Initializes replay.
|
|
16400
|
-
*/
|
|
16401
|
-
_initialize() {
|
|
16402
|
-
if (!this._replay) {
|
|
16403
|
-
return;
|
|
16404
|
-
}
|
|
16405
|
-
|
|
16406
|
-
this._replay.initializeSampling();
|
|
14886
|
+
return this._replay.flushImmediate();
|
|
16407
14887
|
}
|
|
16408
14888
|
|
|
16409
14889
|
/** Setup the integration. */
|
|
@@ -16454,10 +14934,6 @@ function loadReplayOptionsFromClient(initialOptions) {
|
|
|
16454
14934
|
return finalOptions;
|
|
16455
14935
|
}
|
|
16456
14936
|
|
|
16457
|
-
function _getMergedNetworkHeaders(headers) {
|
|
16458
|
-
return [...DEFAULT_NETWORK_HEADERS, ...headers.map(header => header.toLowerCase())];
|
|
16459
|
-
}
|
|
16460
|
-
|
|
16461
14937
|
/**
|
|
16462
14938
|
* Polyfill for the optional chain operator, `?.`, given previous conversion of the expression into an array of values,
|
|
16463
14939
|
* descriptors, and functions.
|
|
@@ -16895,9 +15371,6 @@ class Postgres {
|
|
|
16895
15371
|
const span = _optionalChain([parentSpan, 'optionalAccess', _6 => _6.startChild, 'call', _7 => _7({
|
|
16896
15372
|
description: typeof config === 'string' ? config : (config ).text,
|
|
16897
15373
|
op: 'db',
|
|
16898
|
-
data: {
|
|
16899
|
-
'db.system': 'postgresql',
|
|
16900
|
-
},
|
|
16901
15374
|
})]);
|
|
16902
15375
|
|
|
16903
15376
|
if (typeof callback === 'function') {
|
|
@@ -16974,9 +15447,6 @@ class Mysql {constructor() { Mysql.prototype.__init.call(this); }
|
|
|
16974
15447
|
const span = _optionalChain([parentSpan, 'optionalAccess', _4 => _4.startChild, 'call', _5 => _5({
|
|
16975
15448
|
description: typeof options === 'string' ? options : (options ).sql,
|
|
16976
15449
|
op: 'db',
|
|
16977
|
-
data: {
|
|
16978
|
-
'db.system': 'mysql',
|
|
16979
|
-
},
|
|
16980
15450
|
})]);
|
|
16981
15451
|
|
|
16982
15452
|
if (typeof callback === 'function') {
|
|
@@ -17198,7 +15668,6 @@ class Mongo {
|
|
|
17198
15668
|
collectionName: collection.collectionName,
|
|
17199
15669
|
dbName: collection.dbName,
|
|
17200
15670
|
namespace: collection.namespace,
|
|
17201
|
-
'db.system': 'mongodb',
|
|
17202
15671
|
};
|
|
17203
15672
|
const spanContext = {
|
|
17204
15673
|
op: 'db',
|
|
@@ -17285,15 +15754,31 @@ class Prisma {
|
|
|
17285
15754
|
}
|
|
17286
15755
|
|
|
17287
15756
|
this._client.$use((params, next) => {
|
|
15757
|
+
const scope = getCurrentHub().getScope();
|
|
15758
|
+
const parentSpan = _optionalChain([scope, 'optionalAccess', _2 => _2.getSpan, 'call', _3 => _3()]);
|
|
15759
|
+
|
|
17288
15760
|
const action = params.action;
|
|
17289
15761
|
const model = params.model;
|
|
17290
|
-
|
|
17291
|
-
|
|
17292
|
-
|
|
17293
|
-
|
|
15762
|
+
|
|
15763
|
+
const span = _optionalChain([parentSpan, 'optionalAccess', _4 => _4.startChild, 'call', _5 => _5({
|
|
15764
|
+
description: model ? `${model} ${action}` : action,
|
|
15765
|
+
op: 'db.sql.prisma',
|
|
15766
|
+
})]);
|
|
15767
|
+
|
|
15768
|
+
const rv = next(params);
|
|
15769
|
+
|
|
15770
|
+
if (isThenable(rv)) {
|
|
15771
|
+
return rv.then((res) => {
|
|
15772
|
+
_optionalChain([span, 'optionalAccess', _6 => _6.finish, 'call', _7 => _7()]);
|
|
15773
|
+
return res;
|
|
15774
|
+
});
|
|
15775
|
+
}
|
|
15776
|
+
|
|
15777
|
+
_optionalChain([span, 'optionalAccess', _8 => _8.finish, 'call', _9 => _9()]);
|
|
15778
|
+
return rv;
|
|
17294
15779
|
});
|
|
17295
15780
|
}
|
|
17296
|
-
}
|
|
15781
|
+
}Prisma.__initStatic();
|
|
17297
15782
|
|
|
17298
15783
|
/** Tracing integration for graphql package */
|
|
17299
15784
|
class GraphQL {constructor() { GraphQL.prototype.__init.call(this); }
|
|
@@ -25625,6 +24110,7 @@ var STATES$5;
|
|
|
25625
24110
|
STATES["RE_INIT_RECORDER__NEXT_QUESTION"] = "reInitRecorderNextQuestion";
|
|
25626
24111
|
STATES["UPLOADING"] = "uploading";
|
|
25627
24112
|
STATES["CONFIRM"] = "confirm";
|
|
24113
|
+
STATES["CONFIRM_WATING"] = "confirmWaiting";
|
|
25628
24114
|
STATES["FINISHED"] = "finished";
|
|
25629
24115
|
STATES["ERROR"] = "error";
|
|
25630
24116
|
})(STATES$5 || (STATES$5 = {}));
|
|
@@ -25678,6 +24164,7 @@ var ACTIONS$6;
|
|
|
25678
24164
|
ACTIONS["RESET_FAILED_RECORDING_ATTEMPTS"] = "resetFailedRecordingAttempts";
|
|
25679
24165
|
ACTIONS["CLEAR_VIDEO_ERROR"] = "clearVideoError";
|
|
25680
24166
|
ACTIONS["UPDATE_VIDEO_DIMENSIONS"] = "updateVideoDimensions";
|
|
24167
|
+
ACTIONS["UPDATE_UPLOADED_FALSE_COUNT"] = "updateUploadedFalseCount";
|
|
25681
24168
|
})(ACTIONS$6 || (ACTIONS$6 = {}));
|
|
25682
24169
|
var EVENTS$5;
|
|
25683
24170
|
(function (EVENTS) {
|
|
@@ -25733,6 +24220,7 @@ var GUARDS$3;
|
|
|
25733
24220
|
GUARDS["IS_RECORDER_READY"] = "isRecorderReady";
|
|
25734
24221
|
GUARDS["IS_ASSESSMENT_QUESTION"] = "isAssessmentQuestion";
|
|
25735
24222
|
GUARDS["IS_TIMES_UP"] = "isTimesUp";
|
|
24223
|
+
GUARDS["SHOULD_TRY_TO_CONFIRM"] = "shouldTryToConfirm";
|
|
25736
24224
|
})(GUARDS$3 || (GUARDS$3 = {}));
|
|
25737
24225
|
var TAGS;
|
|
25738
24226
|
(function (TAGS) {
|
|
@@ -25742,6 +24230,7 @@ var TAGS;
|
|
|
25742
24230
|
TAGS["DISPLAY_OUTER_VIEW"] = "displayOuterView";
|
|
25743
24231
|
TAGS["DISPLAY_QUESTION"] = "displayQuestion";
|
|
25744
24232
|
TAGS["DISPLAY_QUESTIONS_LIST"] = "displayQuestionsList";
|
|
24233
|
+
TAGS["DISPLAY_UPLOAD"] = "displayUpload";
|
|
25745
24234
|
TAGS["LOADING"] = "loading";
|
|
25746
24235
|
})(TAGS || (TAGS = {}));
|
|
25747
24236
|
|
|
@@ -30463,7 +28952,7 @@ const configGenerator = () => {
|
|
|
30463
28952
|
let release;
|
|
30464
28953
|
try {
|
|
30465
28954
|
environment !== null && environment !== void 0 ? environment : (environment = "staging");
|
|
30466
|
-
release !== null && release !== void 0 ? release : (release = "1.1.23-binary-
|
|
28955
|
+
release !== null && release !== void 0 ? release : (release = "1.1.23-binary-002");
|
|
30467
28956
|
}
|
|
30468
28957
|
catch (_a) {
|
|
30469
28958
|
console.error('sentry configGenerator error');
|
|
@@ -30936,6 +29425,7 @@ const SECONDS_LEFT_HIGHLIGHT = 10;
|
|
|
30936
29425
|
const DEFAULT_ASSESSMENT_MAX_CHARS = 300;
|
|
30937
29426
|
const DEFAULT_ASSESSMENT_DURATION = 0;
|
|
30938
29427
|
const DEFAULT_VIDEO_DIMENSIONS = { width: 1280, height: 720 }; // Transcoder default dimensions (720p)
|
|
29428
|
+
const MAX_CONFIRM_ATTEMPTS = 5;
|
|
30939
29429
|
// Font
|
|
30940
29430
|
const FONT_URL = 'https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@400;600;700&display=swap';
|
|
30941
29431
|
var RETAKE_SPEED;
|
|
@@ -35096,8 +33586,8 @@ function memoizeOne(resultFn, isEqual) {
|
|
|
35096
33586
|
}
|
|
35097
33587
|
|
|
35098
33588
|
var memoizeOne_esm = /*#__PURE__*/Object.freeze({
|
|
35099
|
-
|
|
35100
|
-
|
|
33589
|
+
__proto__: null,
|
|
33590
|
+
'default': memoizeOne
|
|
35101
33591
|
});
|
|
35102
33592
|
|
|
35103
33593
|
var require$$2 = /*@__PURE__*/getAugmentedNamespace(memoizeOne_esm);
|
|
@@ -39057,6 +37547,11 @@ var EVENT_TYPES;
|
|
|
39057
37547
|
EVENT_TYPES["SOUND_RESTORED"] = "soundRestored";
|
|
39058
37548
|
EVENT_TYPES["TIMES_UP"] = "timesUp";
|
|
39059
37549
|
EVENT_TYPES["COMPLETED_INTERVIEW"] = "completedInterview";
|
|
37550
|
+
EVENT_TYPES["RECONNECTED"] = "reconnected";
|
|
37551
|
+
EVENT_TYPES["CONFIRM_UPLOADED_FAILED"] = "confirmUploadedFailed";
|
|
37552
|
+
EVENT_TYPES["FINISHED"] = "finished";
|
|
37553
|
+
EVENT_TYPES["ON_FINISH_SUCCEED"] = "onFinishSucceed";
|
|
37554
|
+
EVENT_TYPES["ON_FINISH_FAILED"] = "onFinishFailed";
|
|
39060
37555
|
})(EVENT_TYPES || (EVENT_TYPES = {}));
|
|
39061
37556
|
let event_id;
|
|
39062
37557
|
const updateEventId = (eventId) => { event_id = eventId; };
|
|
@@ -39606,31 +38101,6 @@ const Setup = ({ widgetMachine, sendToWidget, isPracticeDisabled, recordWithoutV
|
|
|
39606
38101
|
React__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()))));
|
|
39607
38102
|
};
|
|
39608
38103
|
|
|
39609
|
-
/*! *****************************************************************************
|
|
39610
|
-
Copyright (c) Microsoft Corporation.
|
|
39611
|
-
|
|
39612
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
39613
|
-
purpose with or without fee is hereby granted.
|
|
39614
|
-
|
|
39615
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
39616
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
39617
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
39618
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
39619
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
39620
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
39621
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
39622
|
-
***************************************************************************** */
|
|
39623
|
-
|
|
39624
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
39625
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
39626
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39627
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39628
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
39629
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
39630
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
39631
|
-
});
|
|
39632
|
-
}
|
|
39633
|
-
|
|
39634
38104
|
const uploadToS3 = (url, data, onProgress, timeout = 0) => s3AxiosInstance.put(url, data, {
|
|
39635
38105
|
headers: { 'Content-Type': 'video/webm' }, onUploadProgress: onProgress, timeout,
|
|
39636
38106
|
});
|
|
@@ -39701,8 +38171,8 @@ const OuterView = ({ widgetMachine, sendToWidget, recorderRef }) => {
|
|
|
39701
38171
|
const isQuestionDisplayed = widgetMachine.hasTag(TAGS.DISPLAY_QUESTION) || (isVideoQuestionState && !currentQuestionObj.thinkingTime);
|
|
39702
38172
|
const isPreviewState = widgetMachine.matches(STATES$5.PREVIEW);
|
|
39703
38173
|
const isUploadingState = widgetMachine.matches(STATES$5.UPLOADING);
|
|
39704
|
-
const isConfirmState = widgetMachine.matches(STATES$5.CONFIRM);
|
|
39705
38174
|
const isQuestionsListDisplayed = widgetMachine.hasTag(TAGS.DISPLAY_QUESTIONS_LIST);
|
|
38175
|
+
const isUploadDisplayed = widgetMachine.hasTag(TAGS.DISPLAY_UPLOAD);
|
|
39706
38176
|
const isRecording = recorderMachine.matches({ [STATES$6.RECORDING]: STATES$6.COLLECTING_BLOBS });
|
|
39707
38177
|
const isCountDown = recorderMachine.matches({ [STATES$6.RECORDING]: STATES$6.COUNT_DOWN });
|
|
39708
38178
|
const isPracticeMode = recordingType === TAKE_TYPES.PRACTICE;
|
|
@@ -39720,7 +38190,7 @@ const OuterView = ({ widgetMachine, sendToWidget, recorderRef }) => {
|
|
|
39720
38190
|
isSetupState && React__default.createElement(Setup, { recordWithoutVideo: recordWithoutVideo, widgetMachine: widgetMachine, sendToWidget: sendToWidget, isPracticeDisabled: !!config.disablePractice }),
|
|
39721
38191
|
isQuestionsListDisplayed && React__default.createElement(QuestionsList, { questions: questions, currentQuestion: currentQuestion, isPracticeMode: isPracticeMode, questionsStatus: questionsStatus }),
|
|
39722
38192
|
isQuestionDisplayed && React__default.createElement(Question, { questionObj: currentQuestionObj }),
|
|
39723
|
-
|
|
38193
|
+
isUploadDisplayed && (React__default.createElement(Upload, { isConnected: isConnected, totalFileSize: totalFileSize, totalUploadedFilesSize: totalUploadedFilesSize, totalUploadSpeed: totalUploadSpeed }))));
|
|
39724
38194
|
};
|
|
39725
38195
|
|
|
39726
38196
|
var actions = {};
|
|
@@ -43549,9 +42019,7 @@ var AsapAction = (function (_super) {
|
|
|
43549
42019
|
var actions = scheduler.actions;
|
|
43550
42020
|
if (id != null && ((_a = actions[actions.length - 1]) === null || _a === void 0 ? void 0 : _a.id) !== id) {
|
|
43551
42021
|
immediateProvider.clearImmediate(id);
|
|
43552
|
-
|
|
43553
|
-
scheduler._scheduled = undefined;
|
|
43554
|
-
}
|
|
42022
|
+
scheduler._scheduled = undefined;
|
|
43555
42023
|
}
|
|
43556
42024
|
return undefined;
|
|
43557
42025
|
};
|
|
@@ -44817,7 +43285,7 @@ const accUploaderMachine = createMachine({
|
|
|
44817
43285
|
actions: [ACTIONS$2.SENTRY],
|
|
44818
43286
|
},
|
|
44819
43287
|
{
|
|
44820
|
-
actions: [ACTIONS$2.
|
|
43288
|
+
actions: [ACTIONS$2.SENTRY],
|
|
44821
43289
|
target: `#uploader.${STATES$2.UPLOADED}`, // In case the video already uploaded
|
|
44822
43290
|
},
|
|
44823
43291
|
],
|
|
@@ -44834,7 +43302,6 @@ const accUploaderMachine = createMachine({
|
|
|
44834
43302
|
id: 'uploadToS3',
|
|
44835
43303
|
src: ({ signedUrl, file }) => (callback) => uploadToS3(signedUrl, file, callback),
|
|
44836
43304
|
onDone: {
|
|
44837
|
-
// actions: [ACTIONS.SET_UPLOADED],
|
|
44838
43305
|
target: `#uploader.${STATES$2.UPLOADED}`,
|
|
44839
43306
|
},
|
|
44840
43307
|
onError: {
|
|
@@ -45190,10 +43657,14 @@ const accWidgetMachine = createMachine({
|
|
|
45190
43657
|
failedRecordingMessage: VIDEO_CORRUPTED_STATES.NO_ERROR,
|
|
45191
43658
|
isResumed: false,
|
|
45192
43659
|
videoDimensions: DEFAULT_VIDEO_DIMENSIONS,
|
|
43660
|
+
confirmUploadedFalseCount: 0,
|
|
45193
43661
|
},
|
|
45194
43662
|
on: {
|
|
45195
43663
|
[EVENTS$1.CONNECTION_CHANGED]: {
|
|
45196
|
-
actions: [
|
|
43664
|
+
actions: [
|
|
43665
|
+
ACTIONS$6.SET_CONNECTION,
|
|
43666
|
+
{ type: ACTIONS$6.EMIT_TRACKING_EVENT, data: { eventType: EVENT_TYPES.RECONNECTED } },
|
|
43667
|
+
],
|
|
45197
43668
|
},
|
|
45198
43669
|
[EVENTS$5.UPLOADER_PROGRESS]: {
|
|
45199
43670
|
actions: [ACTIONS$6.UPDATE_TOTAL_UPLOADED_FILES_SIZE],
|
|
@@ -45720,7 +44191,7 @@ const accWidgetMachine = createMachine({
|
|
|
45720
44191
|
},
|
|
45721
44192
|
},
|
|
45722
44193
|
[STATES$5.UPLOADING]: {
|
|
45723
|
-
tags: [TAGS.DISPLAY_OUTER_VIEW],
|
|
44194
|
+
tags: [TAGS.DISPLAY_OUTER_VIEW, TAGS.DISPLAY_UPLOAD],
|
|
45724
44195
|
entry: [
|
|
45725
44196
|
{ type: ACTIONS$6.SESSION_EVENT, data: { event: 'widget_completed', type: 'date' } },
|
|
45726
44197
|
{ type: ACTIONS$6.CONSOLE_DEBUG, data: { message: DEBUG.UPLOADING_STATE } },
|
|
@@ -45734,30 +44205,57 @@ const accWidgetMachine = createMachine({
|
|
|
45734
44205
|
},
|
|
45735
44206
|
},
|
|
45736
44207
|
},
|
|
44208
|
+
[STATES$5.CONFIRM_WATING]: {
|
|
44209
|
+
tags: [TAGS.DISPLAY_OUTER_VIEW, TAGS.DISPLAY_UPLOAD],
|
|
44210
|
+
always: {
|
|
44211
|
+
target: STATES$5.CONFIRM,
|
|
44212
|
+
cond: GUARDS$3.IS_CONNECTED,
|
|
44213
|
+
},
|
|
44214
|
+
},
|
|
45737
44215
|
[STATES$5.CONFIRM]: {
|
|
45738
|
-
tags: [TAGS.DISPLAY_OUTER_VIEW],
|
|
44216
|
+
tags: [TAGS.DISPLAY_OUTER_VIEW, TAGS.DISPLAY_UPLOAD],
|
|
45739
44217
|
invoke: {
|
|
45740
44218
|
id: 'getVideo',
|
|
45741
44219
|
src: (context) => { var _a; return getVideo(((_a = context.widgetConfig.video) === null || _a === void 0 ? void 0 : _a.video_id) || ''); },
|
|
45742
|
-
onDone:
|
|
45743
|
-
|
|
45744
|
-
|
|
45745
|
-
|
|
44220
|
+
onDone: [
|
|
44221
|
+
{
|
|
44222
|
+
target: STATES$5.FINISHED,
|
|
44223
|
+
cond: (_, event) => !!event.data.data.data.video.uploaded,
|
|
44224
|
+
},
|
|
44225
|
+
{
|
|
44226
|
+
actions: [
|
|
44227
|
+
ACTIONS$6.UPDATE_UPLOADED_FALSE_COUNT,
|
|
44228
|
+
{ type: ACTIONS$6.SENTRY, data: { eventName: 'CONFIRM::UPLOADED_FALSE' } },
|
|
44229
|
+
],
|
|
44230
|
+
target: STATES$5.CONFIRM_WATING,
|
|
44231
|
+
cond: GUARDS$3.SHOULD_TRY_TO_CONFIRM,
|
|
44232
|
+
},
|
|
44233
|
+
{
|
|
44234
|
+
actions: [
|
|
44235
|
+
{ type: ACTIONS$6.SET_VIDEO_ERROR, data: { errorMessage: 'Error, Please contact support' } },
|
|
44236
|
+
{ type: ACTIONS$6.EMIT_TRACKING_EVENT, data: { eventType: EVENT_TYPES.CONFIRM_UPLOADED_FAILED } },
|
|
44237
|
+
],
|
|
44238
|
+
target: STATES$5.ERROR,
|
|
44239
|
+
},
|
|
44240
|
+
],
|
|
45746
44241
|
onError: [
|
|
45747
44242
|
{
|
|
45748
|
-
actions: [() => console.error('UPDATE_VIDEO_UPLADED_ERROR:'), console.error, ACTIONS$6.SENTRY],
|
|
44243
|
+
actions: [() => console.error('UPDATE_VIDEO_UPLADED_ERROR:'), console.error, { type: ACTIONS$6.SENTRY, data: { eventName: 'CONFIRM::ERROR__NOT_FOUND' } }],
|
|
45749
44244
|
target: STATES$5.FINISHED,
|
|
45750
44245
|
cond: (_, event) => event.data.response.status === STATUS_CODES.NOT_FOUND,
|
|
45751
44246
|
},
|
|
45752
44247
|
{
|
|
45753
|
-
actions: [ACTIONS$6.SENTRY],
|
|
45754
|
-
target: STATES$5.
|
|
44248
|
+
actions: [() => console.error('UPDATE_VIDEO_UPLADED_ERROR:'), console.error, { type: ACTIONS$6.SENTRY, data: { eventName: 'CONFIRM::ERROR' } }],
|
|
44249
|
+
target: STATES$5.CONFIRM_WATING,
|
|
45755
44250
|
},
|
|
45756
44251
|
],
|
|
45757
44252
|
},
|
|
45758
44253
|
},
|
|
45759
44254
|
[STATES$5.FINISHED]: {
|
|
45760
|
-
entry: [
|
|
44255
|
+
entry: [
|
|
44256
|
+
{ type: ACTIONS$6.CONSOLE_DEBUG, data: { message: DEBUG.INTERVIEW_SUBMITTED } },
|
|
44257
|
+
{ type: ACTIONS$6.EMIT_TRACKING_EVENT, data: { eventType: EVENT_TYPES.FINISHED } },
|
|
44258
|
+
],
|
|
45761
44259
|
type: 'final',
|
|
45762
44260
|
},
|
|
45763
44261
|
[STATES$5.ERROR]: {
|
|
@@ -45953,9 +44451,12 @@ const accWidgetMachine = createMachine({
|
|
|
45953
44451
|
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)) }) }),
|
|
45954
44452
|
});
|
|
45955
44453
|
}),
|
|
45956
|
-
[ACTIONS$6.SET_VIDEO_ERROR]: assign$2((_, event) =>
|
|
45957
|
-
|
|
45958
|
-
|
|
44454
|
+
[ACTIONS$6.SET_VIDEO_ERROR]: assign$2((_, event, meta) => {
|
|
44455
|
+
var _a, _b, _c, _d;
|
|
44456
|
+
return ({
|
|
44457
|
+
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) },
|
|
44458
|
+
});
|
|
44459
|
+
}),
|
|
45959
44460
|
[ACTIONS$6.REVOKE_MEMORY]: send$2((_, event) => ({ type: EVENTS$4.REMOVE_TAKES, data: { questionToRemove: event.data.questionNumber } }), { to: ({ storageRef }) => storageRef }),
|
|
45960
44461
|
[ACTIONS$6.UPDATE_VIDEO_OBJECT]: assign$2(({ widgetConfig, recordingType }) => {
|
|
45961
44462
|
var _a, _b;
|
|
@@ -45989,6 +44490,9 @@ const accWidgetMachine = createMachine({
|
|
|
45989
44490
|
height: event.data.height,
|
|
45990
44491
|
},
|
|
45991
44492
|
})),
|
|
44493
|
+
[ACTIONS$6.UPDATE_UPLOADED_FALSE_COUNT]: assign$2(({ confirmUploadedFalseCount }) => ({
|
|
44494
|
+
confirmUploadedFalseCount: confirmUploadedFalseCount + 1,
|
|
44495
|
+
})),
|
|
45992
44496
|
},
|
|
45993
44497
|
services: {
|
|
45994
44498
|
[SERVICES$1.UPDATE_VIDEO_OBJECT_CALL]: ({ widgetConfig: { video }, recordingType, speedTestResult }, event, meta) => (callback, onReceive) => {
|
|
@@ -46032,6 +44536,7 @@ const accWidgetMachine = createMachine({
|
|
|
46032
44536
|
[GUARDS$3.IS_RECORDER_READY]: ({ recorderRef }) => (recorderRef === null || recorderRef === void 0 ? void 0 : recorderRef.getSnapshot().value) === STATES$6.IDLE,
|
|
46033
44537
|
[GUARDS$3.IS_ASSESSMENT_QUESTION]: ({ questions, currentQuestion }) => !!questions[currentQuestion - 1].answerType && questions[currentQuestion - 1].answerType !== ANSWER_TYPES.VIDEO,
|
|
46034
44538
|
[GUARDS$3.IS_TIMES_UP]: (_, event) => !!event.data.isTimesUp,
|
|
44539
|
+
[GUARDS$3.SHOULD_TRY_TO_CONFIRM]: ({ confirmUploadedFalseCount }) => confirmUploadedFalseCount <= MAX_CONFIRM_ATTEMPTS,
|
|
46035
44540
|
},
|
|
46036
44541
|
});
|
|
46037
44542
|
|
|
@@ -48554,10 +47059,25 @@ const Main = ({ widgetConfig, setShouldShowWaterMark, myinterviewRef, isWidgetMi
|
|
|
48554
47059
|
useEffect(() => {
|
|
48555
47060
|
setShouldShowWaterMark(!!(company === null || company === void 0 ? void 0 : company.shouldShowWaterMark));
|
|
48556
47061
|
}, [company === null || company === void 0 ? void 0 : company.shouldShowWaterMark]);
|
|
47062
|
+
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) || '' }); });
|
|
48557
47063
|
useEffect(() => {
|
|
48558
|
-
var _a, _b;
|
|
48559
47064
|
if (machine.done) {
|
|
48560
|
-
|
|
47065
|
+
if (widgetConfig.config.onFinish) {
|
|
47066
|
+
_onFinish().then(() => {
|
|
47067
|
+
emitTrackEvent({ eventType: EVENT_TYPES.ON_FINISH_SUCCEED });
|
|
47068
|
+
}).catch((err) => {
|
|
47069
|
+
var _a;
|
|
47070
|
+
let errorMessage = '';
|
|
47071
|
+
try {
|
|
47072
|
+
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);
|
|
47073
|
+
}
|
|
47074
|
+
catch (_b) {
|
|
47075
|
+
//
|
|
47076
|
+
}
|
|
47077
|
+
emitTrackEvent({ eventType: EVENT_TYPES.ON_FINISH_FAILED, extraData: { errorMessage } });
|
|
47078
|
+
throw err;
|
|
47079
|
+
});
|
|
47080
|
+
}
|
|
48561
47081
|
}
|
|
48562
47082
|
}, [machine.done]);
|
|
48563
47083
|
useEffect(() => {
|
|
@@ -48573,11 +47093,16 @@ const Main = ({ widgetConfig, setShouldShowWaterMark, myinterviewRef, isWidgetMi
|
|
|
48573
47093
|
});
|
|
48574
47094
|
}
|
|
48575
47095
|
}, [candidate, job === null || job === void 0 ? void 0 : job.language]);
|
|
47096
|
+
const setBackgroundOpacity = () => {
|
|
47097
|
+
var _a;
|
|
47098
|
+
(_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');
|
|
47099
|
+
};
|
|
48576
47100
|
useEffect(() => {
|
|
48577
47101
|
var _a, _b;
|
|
48578
47102
|
if (isErrorState && (error === null || error === void 0 ? void 0 : error.statusCode) === 400) {
|
|
48579
47103
|
(_b = (_a = widgetConfig.config).onError) === null || _b === void 0 ? void 0 : _b.call(_a, { messageType: 'applied' });
|
|
48580
47104
|
}
|
|
47105
|
+
setBackgroundOpacity();
|
|
48581
47106
|
}, [isErrorState]);
|
|
48582
47107
|
const isResumed = 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]);
|
|
48583
47108
|
const handleScroll = (e) => {
|
|
@@ -48587,8 +47112,7 @@ const Main = ({ widgetConfig, setShouldShowWaterMark, myinterviewRef, isWidgetMi
|
|
|
48587
47112
|
(_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');
|
|
48588
47113
|
};
|
|
48589
47114
|
useEffect(() => {
|
|
48590
|
-
|
|
48591
|
-
(_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');
|
|
47115
|
+
setBackgroundOpacity();
|
|
48592
47116
|
}, [isLoading]);
|
|
48593
47117
|
const onRetry = () => {
|
|
48594
47118
|
send(EVENTS$5.RETRY);
|
|
@@ -48786,15 +47310,15 @@ const Widget = ({ candidate, job, video, config, disabled = false, buttonText =
|
|
|
48786
47310
|
revertBodyStyling();
|
|
48787
47311
|
setIsWidgetOpen(false);
|
|
48788
47312
|
};
|
|
48789
|
-
const onInterviewCompleted = (data) => {
|
|
47313
|
+
const onInterviewCompleted = (data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
48790
47314
|
var _a;
|
|
48791
|
-
(_a = config.onFinish) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
|
48792
47315
|
onCloseWidget();
|
|
48793
|
-
|
|
47316
|
+
yield ((_a = config.onFinish) === null || _a === void 0 ? void 0 : _a.call(config, data));
|
|
47317
|
+
});
|
|
48794
47318
|
const onError = (data) => {
|
|
48795
47319
|
var _a;
|
|
48796
|
-
(_a = config.onError) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
|
48797
47320
|
onCloseWidget();
|
|
47321
|
+
(_a = config.onError) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
|
48798
47322
|
};
|
|
48799
47323
|
const openWidget = () => {
|
|
48800
47324
|
var _a;
|