clarity-js 0.6.28 → 0.6.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/clarity.js +108 -78
- package/build/clarity.min.js +1 -1
- package/build/clarity.module.js +108 -78
- package/package.json +1 -1
- package/src/core/api.ts +8 -0
- package/src/core/event.ts +4 -3
- package/src/core/version.ts +1 -1
- package/src/data/metadata.ts +1 -1
- package/src/data/upload.ts +11 -8
- package/src/diagnostic/internal.ts +1 -14
- package/src/layout/dom.ts +28 -13
- package/src/layout/mutation.ts +14 -12
- package/src/layout/node.ts +1 -0
- package/src/layout/selector.ts +14 -3
- package/test/helper.ts +10 -2
- package/types/core.d.ts +7 -0
- package/types/data.d.ts +3 -0
- package/types/layout.d.ts +1 -2
package/build/clarity.js
CHANGED
|
@@ -67,6 +67,13 @@ var config$1 = {
|
|
|
67
67
|
upgrade: null
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
+
function api(method) {
|
|
71
|
+
// Zone.js, a popular package for Angular, overrides native browser APIs which can lead to inconsistent state for single page applications.
|
|
72
|
+
// Example issue: https://github.com/angular/angular/issues/31712
|
|
73
|
+
// As a work around, we ensuring Clarity access APIs outside of Zone (and use native implementation instead)
|
|
74
|
+
return window["Zone" /* Zone */] && "__symbol__" /* Symbol */ in window["Zone" /* Zone */] ? window["Zone" /* Zone */]["__symbol__" /* Symbol */](method) : method;
|
|
75
|
+
}
|
|
76
|
+
|
|
70
77
|
var startTime = 0;
|
|
71
78
|
function start$E() {
|
|
72
79
|
startTime = performance.now();
|
|
@@ -80,7 +87,7 @@ function stop$B() {
|
|
|
80
87
|
startTime = 0;
|
|
81
88
|
}
|
|
82
89
|
|
|
83
|
-
var version$1 = "0.6.
|
|
90
|
+
var version$1 = "0.6.32";
|
|
84
91
|
|
|
85
92
|
// tslint:disable: no-bitwise
|
|
86
93
|
function hash (input) {
|
|
@@ -614,7 +621,7 @@ function mangleText(value) {
|
|
|
614
621
|
var index = value.indexOf(first);
|
|
615
622
|
var prefix = value.substr(0, index);
|
|
616
623
|
var suffix = value.substr(index + trimmed.length);
|
|
617
|
-
return ""
|
|
624
|
+
return "".concat(prefix).concat(trimmed.length.toString(36)).concat(suffix);
|
|
618
625
|
}
|
|
619
626
|
return value;
|
|
620
627
|
}
|
|
@@ -807,7 +814,7 @@ function suspend$1(timer) {
|
|
|
807
814
|
});
|
|
808
815
|
}
|
|
809
816
|
function key(timer) {
|
|
810
|
-
return timer.id
|
|
817
|
+
return "".concat(timer.id, ".").concat(timer.cost);
|
|
811
818
|
}
|
|
812
819
|
function wait() {
|
|
813
820
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -1032,7 +1039,7 @@ function encode$4 (type, timer, ts) {
|
|
|
1032
1039
|
}
|
|
1033
1040
|
tokens.push(suspend ? "*M" /* SuspendMutationTag */ : data[key]);
|
|
1034
1041
|
if (size && size.length === 2) {
|
|
1035
|
-
tokens.push(""
|
|
1042
|
+
tokens.push("".concat("#" /* Box */).concat(str$1(size[0]), ".").concat(str$1(size[1])));
|
|
1036
1043
|
}
|
|
1037
1044
|
break;
|
|
1038
1045
|
case "attributes":
|
|
@@ -1072,7 +1079,7 @@ function str$1(input) {
|
|
|
1072
1079
|
return input.toString(36);
|
|
1073
1080
|
}
|
|
1074
1081
|
function attribute(key, value, privacy) {
|
|
1075
|
-
return key
|
|
1082
|
+
return "".concat(key, "=").concat(scrub(value, key, privacy));
|
|
1076
1083
|
}
|
|
1077
1084
|
|
|
1078
1085
|
var data$b = [];
|
|
@@ -1225,13 +1232,12 @@ var history$3 = {};
|
|
|
1225
1232
|
var data$9;
|
|
1226
1233
|
function start$s() {
|
|
1227
1234
|
history$3 = {};
|
|
1228
|
-
bind(document, "securitypolicyviolation", csp);
|
|
1229
1235
|
}
|
|
1230
1236
|
function log$1(code, severity, name, message, stack) {
|
|
1231
1237
|
if (name === void 0) { name = null; }
|
|
1232
1238
|
if (message === void 0) { message = null; }
|
|
1233
1239
|
if (stack === void 0) { stack = null; }
|
|
1234
|
-
var key = name ? name
|
|
1240
|
+
var key = name ? "".concat(name, "|").concat(message) : "";
|
|
1235
1241
|
// While rare, it's possible for code to fail repeatedly during the lifetime of the same page
|
|
1236
1242
|
// In those cases, we only want to log the failure once and not spam logs with redundant information.
|
|
1237
1243
|
if (code in history$3 && history$3[code].indexOf(key) >= 0) {
|
|
@@ -1247,15 +1253,6 @@ function log$1(code, severity, name, message, stack) {
|
|
|
1247
1253
|
}
|
|
1248
1254
|
encode$3(33 /* Log */);
|
|
1249
1255
|
}
|
|
1250
|
-
function csp(e) {
|
|
1251
|
-
var upload = config$1.upload;
|
|
1252
|
-
var parts = upload ? upload.substr(0, upload.indexOf("/", "https://" /* HTTPS */.length)).split("." /* Dot */) : []; // Look for first "/" starting after initial "https://" string
|
|
1253
|
-
var domain = parts.length >= 2 ? parts.splice(-2).join("." /* Dot */) : null;
|
|
1254
|
-
// Capture content security policy violation only if disposition value is not explicitly set to "report"
|
|
1255
|
-
if (domain && e.blockedURI && e.blockedURI.indexOf(domain) >= 0 && e["disposition"] !== "report" /* Report */) {
|
|
1256
|
-
log$1(7 /* ContentSecurityPolicy */, 1 /* Warning */, e.blockedURI);
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
1256
|
function stop$r() {
|
|
1260
1257
|
history$3 = {};
|
|
1261
1258
|
}
|
|
@@ -1294,7 +1291,7 @@ function metrics(root, value) {
|
|
|
1294
1291
|
root.querySelectorAll(match).forEach(function (e) { max(metricId, num$2(e.innerText, scale)); });
|
|
1295
1292
|
break;
|
|
1296
1293
|
case 2 /* Attribute */:
|
|
1297
|
-
root.querySelectorAll("["
|
|
1294
|
+
root.querySelectorAll("[".concat(match, "]")).forEach(function (e) { max(metricId, num$2(e.getAttribute(match), scale, false)); });
|
|
1298
1295
|
break;
|
|
1299
1296
|
case 1 /* Javascript */:
|
|
1300
1297
|
max(metricId, evaluate(match, "number" /* Number */));
|
|
@@ -1316,7 +1313,7 @@ function dimensions(root, value) {
|
|
|
1316
1313
|
root.querySelectorAll(match).forEach(function (e) { log(dimensionId, str(e.innerText)); });
|
|
1317
1314
|
break;
|
|
1318
1315
|
case 2 /* Attribute */:
|
|
1319
|
-
root.querySelectorAll("["
|
|
1316
|
+
root.querySelectorAll("[".concat(match, "]")).forEach(function (e) { log(dimensionId, str(e.getAttribute(match))); });
|
|
1320
1317
|
break;
|
|
1321
1318
|
case 1 /* Javascript */:
|
|
1322
1319
|
log(dimensionId, str(evaluate(match, "string" /* String */)));
|
|
@@ -1383,7 +1380,7 @@ function selector (input, beta) {
|
|
|
1383
1380
|
if (beta === void 0) { beta = false; }
|
|
1384
1381
|
var a = input.attributes;
|
|
1385
1382
|
var prefix = input.prefix ? input.prefix[beta ? 1 /* Beta */ : 0 /* Stable */] : null;
|
|
1386
|
-
var suffix = beta || ((a && !("class" /* Class */ in a)) || TAGS.indexOf(input.tag) >= 0) ? ":nth-of-type("
|
|
1383
|
+
var suffix = beta || ((a && !("class" /* Class */ in a)) || TAGS.indexOf(input.tag) >= 0) ? ":nth-of-type(".concat(input.position, ")") : "" /* Empty */;
|
|
1387
1384
|
switch (input.tag) {
|
|
1388
1385
|
case "STYLE":
|
|
1389
1386
|
case "TITLE":
|
|
@@ -1398,28 +1395,36 @@ function selector (input, beta) {
|
|
|
1398
1395
|
if (prefix === null) {
|
|
1399
1396
|
return "" /* Empty */;
|
|
1400
1397
|
}
|
|
1401
|
-
prefix = prefix
|
|
1398
|
+
prefix = "".concat(prefix, ">");
|
|
1402
1399
|
input.tag = input.tag.indexOf("svg:" /* SvgPrefix */) === 0 ? input.tag.substr("svg:" /* SvgPrefix */.length) : input.tag;
|
|
1403
|
-
var selector = ""
|
|
1400
|
+
var selector = "".concat(prefix).concat(input.tag).concat(suffix);
|
|
1404
1401
|
var classes = "class" /* Class */ in a && a["class" /* Class */].length > 0 ? a["class" /* Class */].trim().split(/\s+/) : null;
|
|
1405
1402
|
if (beta) {
|
|
1406
1403
|
// In beta mode, update selector to use "id" field when available. There are two exceptions:
|
|
1407
1404
|
// (1) if "id" appears to be an auto generated string token, e.g. guid or a random id containing digits
|
|
1408
1405
|
// (2) if "id" appears inside a shadow DOM, in which case we continue to prefix up to shadow DOM to prevent conflicts
|
|
1409
|
-
var shadowStart = prefix.lastIndexOf("*S" /* ShadowDomTag */);
|
|
1410
|
-
var shadowEnd = prefix.indexOf(">", shadowStart) + 1;
|
|
1411
1406
|
var id = "id" /* Id */ in a && a["id" /* Id */].length > 0 ? a["id" /* Id */] : null;
|
|
1412
1407
|
classes = input.tag !== "BODY" /* BodyTag */ && classes ? classes.filter(function (c) { return !hasDigits(c); }) : [];
|
|
1413
|
-
selector = classes.length > 0 ? ""
|
|
1414
|
-
selector = id && hasDigits(id) === false ? (
|
|
1408
|
+
selector = classes.length > 0 ? "".concat(prefix).concat(input.tag, ".").concat(classes.join(".")).concat(suffix) : selector;
|
|
1409
|
+
selector = id && hasDigits(id) === false ? "".concat(getDomPrefix(prefix), "#").concat(id) : selector;
|
|
1415
1410
|
}
|
|
1416
1411
|
else {
|
|
1417
1412
|
// Otherwise, fallback to stable mode, where we include class names as part of the selector
|
|
1418
|
-
selector = classes ? ""
|
|
1413
|
+
selector = classes ? "".concat(prefix).concat(input.tag, ".").concat(classes.join(".")).concat(suffix) : selector;
|
|
1419
1414
|
}
|
|
1420
1415
|
return selector;
|
|
1421
1416
|
}
|
|
1422
1417
|
}
|
|
1418
|
+
function getDomPrefix(prefix) {
|
|
1419
|
+
var shadowDomStart = prefix.lastIndexOf("*S" /* ShadowDomTag */);
|
|
1420
|
+
var iframeDomStart = prefix.lastIndexOf("".concat("iframe:" /* IFramePrefix */).concat("HTML" /* HTML */));
|
|
1421
|
+
var domStart = Math.max(shadowDomStart, iframeDomStart);
|
|
1422
|
+
if (domStart < 0) {
|
|
1423
|
+
return "";
|
|
1424
|
+
}
|
|
1425
|
+
var domEnd = prefix.indexOf(">", domStart) + 1;
|
|
1426
|
+
return prefix.substr(0, domEnd);
|
|
1427
|
+
}
|
|
1423
1428
|
// Check if the given input string has digits or not
|
|
1424
1429
|
function hasDigits(value) {
|
|
1425
1430
|
for (var i = 0; i < value.length; i++) {
|
|
@@ -1434,19 +1439,21 @@ function hasDigits(value) {
|
|
|
1434
1439
|
var index = 1;
|
|
1435
1440
|
// Reference: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input#%3Cinput%3E_types
|
|
1436
1441
|
var DISALLOWED_TYPES = ["password", "hidden", "email", "tel"];
|
|
1437
|
-
var DISALLOWED_NAMES = ["addr", "cell", "code", "dob", "email", "mob", "name", "phone", "secret", "social", "ssn", "tel", "zip", "pass"];
|
|
1442
|
+
var DISALLOWED_NAMES = ["addr", "cell", "code", "dob", "email", "mob", "name", "phone", "secret", "social", "ssn", "tel", "zip", "pass", "card", "account", "cvv", "ccv"];
|
|
1438
1443
|
var DISALLOWED_MATCH = ["address", "password", "contact"];
|
|
1439
1444
|
var nodes = [];
|
|
1440
1445
|
var values = [];
|
|
1441
1446
|
var updateMap = [];
|
|
1442
1447
|
var hashMap = {};
|
|
1448
|
+
var override = [];
|
|
1449
|
+
var unmask = [];
|
|
1443
1450
|
// The WeakMap object is a collection of key/value pairs in which the keys are weakly referenced
|
|
1444
1451
|
var idMap = null; // Maps node => id.
|
|
1445
1452
|
var iframeMap = null; // Maps iframe's contentDocument => parent iframe element
|
|
1446
1453
|
var privacyMap = null; // Maps node => Privacy (enum)
|
|
1447
1454
|
function start$r() {
|
|
1448
1455
|
reset$g();
|
|
1449
|
-
parse(document);
|
|
1456
|
+
parse(document, true);
|
|
1450
1457
|
}
|
|
1451
1458
|
function stop$q() {
|
|
1452
1459
|
reset$g();
|
|
@@ -1457,16 +1464,23 @@ function reset$g() {
|
|
|
1457
1464
|
values = [];
|
|
1458
1465
|
updateMap = [];
|
|
1459
1466
|
hashMap = {};
|
|
1467
|
+
override = [];
|
|
1468
|
+
unmask = [];
|
|
1460
1469
|
idMap = new WeakMap();
|
|
1461
1470
|
iframeMap = new WeakMap();
|
|
1462
1471
|
privacyMap = new WeakMap();
|
|
1463
1472
|
}
|
|
1464
1473
|
// We parse new root nodes for any regions or masked nodes in the beginning (document) and
|
|
1465
1474
|
// later whenever there are new additions or modifications to DOM (mutations)
|
|
1466
|
-
function parse(root) {
|
|
1475
|
+
function parse(root, init) {
|
|
1476
|
+
if (init === void 0) { init = false; }
|
|
1467
1477
|
// Wrap selectors in a try / catch block.
|
|
1468
1478
|
// It's possible for script to receive invalid selectors, e.g. "'#id'" with extra quotes, and cause the code below to fail
|
|
1469
1479
|
try {
|
|
1480
|
+
// Parse unmask configuration into separate query selectors and override tokens as part of initialization
|
|
1481
|
+
if (init) {
|
|
1482
|
+
config$1.unmask.forEach(function (x) { return x.indexOf("!" /* Bang */) < 0 ? unmask.push(x) : override.push(x.substr(1)); });
|
|
1483
|
+
}
|
|
1470
1484
|
// Since mutations may happen on leaf nodes too, e.g. text nodes, which may not support all selector APIs.
|
|
1471
1485
|
// We ensure that the root note supports querySelectorAll API before executing the code below to identify new regions.
|
|
1472
1486
|
if ("querySelectorAll" in root) {
|
|
@@ -1474,7 +1488,7 @@ function parse(root) {
|
|
|
1474
1488
|
metrics(root, config$1.metrics);
|
|
1475
1489
|
dimensions(root, config$1.dimensions);
|
|
1476
1490
|
config$1.mask.forEach(function (x) { return root.querySelectorAll(x).forEach(function (e) { return privacyMap.set(e, 3 /* TextImage */); }); }); // Masked Elements
|
|
1477
|
-
|
|
1491
|
+
unmask.forEach(function (x) { return root.querySelectorAll(x).forEach(function (e) { return privacyMap.set(e, 0 /* None */); }); }); // Unmasked Elements
|
|
1478
1492
|
}
|
|
1479
1493
|
}
|
|
1480
1494
|
catch (e) {
|
|
@@ -1499,17 +1513,15 @@ function add(node, parent, data, source) {
|
|
|
1499
1513
|
var previousId = getPreviousId(node);
|
|
1500
1514
|
var privacy = config$1.content ? 1 /* Sensitive */ : 2 /* Text */;
|
|
1501
1515
|
var parentValue = null;
|
|
1502
|
-
var parentTag = "" /* Empty */;
|
|
1503
1516
|
var regionId = exists(node) ? id : null;
|
|
1504
1517
|
if (parentId >= 0 && values[parentId]) {
|
|
1505
1518
|
parentValue = values[parentId];
|
|
1506
|
-
parentTag = parentValue.data.tag;
|
|
1507
1519
|
parentValue.children.push(id);
|
|
1508
1520
|
regionId = regionId === null ? parentValue.region : regionId;
|
|
1509
1521
|
privacy = parentValue.metadata.privacy;
|
|
1510
1522
|
}
|
|
1511
1523
|
// Check to see if this particular node should be masked or not
|
|
1512
|
-
privacy = getPrivacy(node, data,
|
|
1524
|
+
privacy = getPrivacy(node, data, parentValue, privacy);
|
|
1513
1525
|
// If there's an explicit region attribute set on the element, use it to mark a region on the page
|
|
1514
1526
|
if (data.attributes && "data-clarity-region" /* RegionData */ in data.attributes) {
|
|
1515
1527
|
observe$b(node, data.attributes["data-clarity-region" /* RegionData */]);
|
|
@@ -1604,21 +1616,35 @@ function iframe(node) {
|
|
|
1604
1616
|
var doc = node.nodeType === Node.DOCUMENT_NODE ? node : null;
|
|
1605
1617
|
return doc && iframeMap.has(doc) ? iframeMap.get(doc) : null;
|
|
1606
1618
|
}
|
|
1607
|
-
function getPrivacy(node, data,
|
|
1619
|
+
function getPrivacy(node, data, parent, privacy) {
|
|
1608
1620
|
var attributes = data.attributes;
|
|
1609
1621
|
var tag = data.tag.toUpperCase();
|
|
1610
1622
|
// If this node was explicitly configured to contain sensitive content, use that information and return the value
|
|
1611
1623
|
if (privacyMap.has(node)) {
|
|
1612
1624
|
return privacyMap.get(node);
|
|
1613
1625
|
}
|
|
1626
|
+
// If it's a text node belonging to a STYLE or TITLE tag;
|
|
1627
|
+
// Or, the text node belongs to one of SCRUB_EXCEPTIONS
|
|
1628
|
+
// then reset the privacy setting to ensure we capture the content
|
|
1629
|
+
if (tag === "*T" /* TextTag */ && parent && parent.data) {
|
|
1630
|
+
var path = parent.selector ? parent.selector[0 /* Stable */] : "" /* Empty */;
|
|
1631
|
+
privacy = parent.data.tag === "STYLE" /* StyleTag */ || parent.data.tag === "TITLE" /* TitleTag */ ? 0 /* None */ : privacy;
|
|
1632
|
+
for (var _i = 0, override_1 = override; _i < override_1.length; _i++) {
|
|
1633
|
+
var entry = override_1[_i];
|
|
1634
|
+
if (path.indexOf(entry) >= 0) {
|
|
1635
|
+
privacy = 0 /* None */;
|
|
1636
|
+
break;
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1614
1640
|
// Do not proceed if attributes are missing for the node
|
|
1615
1641
|
if (attributes === null || attributes === undefined) {
|
|
1616
1642
|
return privacy;
|
|
1617
1643
|
}
|
|
1618
1644
|
// Look up for sensitive fields
|
|
1619
1645
|
if ("class" /* Class */ in attributes && privacy === 1 /* Sensitive */) {
|
|
1620
|
-
for (var
|
|
1621
|
-
var match = DISALLOWED_MATCH_1[
|
|
1646
|
+
for (var _a = 0, DISALLOWED_MATCH_1 = DISALLOWED_MATCH; _a < DISALLOWED_MATCH_1.length; _a++) {
|
|
1647
|
+
var match = DISALLOWED_MATCH_1[_a];
|
|
1622
1648
|
if (attributes["class" /* Class */].indexOf(match) >= 0) {
|
|
1623
1649
|
privacy = 2 /* Text */;
|
|
1624
1650
|
break;
|
|
@@ -1630,12 +1656,12 @@ function getPrivacy(node, data, parentTag, privacy) {
|
|
|
1630
1656
|
if (privacy === 0 /* None */) {
|
|
1631
1657
|
var field = "" /* Empty */;
|
|
1632
1658
|
// Be aggressive in looking up any attribute (id, class, name, etc.) for disallowed names
|
|
1633
|
-
for (var
|
|
1634
|
-
var attribute = _b
|
|
1659
|
+
for (var _b = 0, _c = Object.keys(attributes); _b < _c.length; _b++) {
|
|
1660
|
+
var attribute = _c[_b];
|
|
1635
1661
|
field += attributes[attribute].toLowerCase();
|
|
1636
1662
|
}
|
|
1637
|
-
for (var
|
|
1638
|
-
var name_1 = DISALLOWED_NAMES_1[
|
|
1663
|
+
for (var _d = 0, DISALLOWED_NAMES_1 = DISALLOWED_NAMES; _d < DISALLOWED_NAMES_1.length; _d++) {
|
|
1664
|
+
var name_1 = DISALLOWED_NAMES_1[_d];
|
|
1639
1665
|
if (field.indexOf(name_1) >= 0) {
|
|
1640
1666
|
privacy = 2 /* Text */;
|
|
1641
1667
|
break;
|
|
@@ -1658,11 +1684,6 @@ function getPrivacy(node, data, parentTag, privacy) {
|
|
|
1658
1684
|
if ("data-clarity-unmask" /* UnmaskData */ in attributes) {
|
|
1659
1685
|
privacy = 0 /* None */;
|
|
1660
1686
|
}
|
|
1661
|
-
// If it's a text node belonging to a STYLE or TITLE tag; then reset the privacy setting to ensure we capture the content
|
|
1662
|
-
var cTag = tag === "*T" /* TextTag */ ? parentTag : tag;
|
|
1663
|
-
if (cTag === "STYLE" /* StyleTag */ || cTag === "TITLE" /* TitleTag */) {
|
|
1664
|
-
privacy = 0 /* None */;
|
|
1665
|
-
}
|
|
1666
1687
|
return privacy;
|
|
1667
1688
|
}
|
|
1668
1689
|
function diff(a, b, field) {
|
|
@@ -2573,6 +2594,7 @@ function processNode (node, source) {
|
|
|
2573
2594
|
case Node.DOCUMENT_FRAGMENT_NODE:
|
|
2574
2595
|
var shadowRoot = node;
|
|
2575
2596
|
if (shadowRoot.host) {
|
|
2597
|
+
parse(shadowRoot);
|
|
2576
2598
|
var type = typeof (shadowRoot.constructor);
|
|
2577
2599
|
if (type === "function" /* Function */ && shadowRoot.constructor.toString().indexOf("[native code]" /* NativeCode */) >= 0) {
|
|
2578
2600
|
observe$2(shadowRoot);
|
|
@@ -2806,7 +2828,7 @@ function start$e() {
|
|
|
2806
2828
|
deleteRule = CSSStyleSheet.prototype.deleteRule;
|
|
2807
2829
|
}
|
|
2808
2830
|
if (attachShadow === null) {
|
|
2809
|
-
attachShadow =
|
|
2831
|
+
attachShadow = Element.prototype.attachShadow;
|
|
2810
2832
|
}
|
|
2811
2833
|
// Some popular open source libraries, like styled-components, optimize performance
|
|
2812
2834
|
// by injecting CSS using insertRule API vs. appending text node. A side effect of
|
|
@@ -2824,7 +2846,7 @@ function start$e() {
|
|
|
2824
2846
|
// In case we are unable to add a hook and browser throws an exception,
|
|
2825
2847
|
// reset attachShadow variable and resume processing like before
|
|
2826
2848
|
try {
|
|
2827
|
-
|
|
2849
|
+
Element.prototype.attachShadow = function () {
|
|
2828
2850
|
return schedule(attachShadow.apply(this, arguments));
|
|
2829
2851
|
};
|
|
2830
2852
|
}
|
|
@@ -2838,11 +2860,8 @@ function observe$1(node) {
|
|
|
2838
2860
|
// For this reason, we need to wire up mutations every time we see a new shadow dom.
|
|
2839
2861
|
// Also, wrap it inside a try / catch. In certain browsers (e.g. legacy Edge), observer on shadow dom can throw errors
|
|
2840
2862
|
try {
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
// As a temporary work around, ensuring Clarity can invoke MutationObserver outside of Zone (and use native implementation instead)
|
|
2844
|
-
var api = window["Zone" /* Zone */] && "__symbol__" /* Symbol */ in window["Zone" /* Zone */] ? window["Zone" /* Zone */]["__symbol__" /* Symbol */]("MutationObserver" /* MutationObserver */) : "MutationObserver" /* MutationObserver */;
|
|
2845
|
-
var observer = api in window ? new window[api](measure(handle$1)) : null;
|
|
2863
|
+
var m = api("MutationObserver" /* MutationObserver */);
|
|
2864
|
+
var observer = m in window ? new window[m](measure(handle$1)) : null;
|
|
2846
2865
|
if (observer) {
|
|
2847
2866
|
observer.observe(node, { attributes: true, childList: true, characterData: true, subtree: true });
|
|
2848
2867
|
observers.push(observer);
|
|
@@ -2880,7 +2899,7 @@ function stop$d() {
|
|
|
2880
2899
|
}
|
|
2881
2900
|
// Restoring original attachShadow
|
|
2882
2901
|
if (attachShadow != null) {
|
|
2883
|
-
|
|
2902
|
+
Element.prototype.attachShadow = attachShadow;
|
|
2884
2903
|
attachShadow = null;
|
|
2885
2904
|
}
|
|
2886
2905
|
history$2 = {};
|
|
@@ -2934,6 +2953,9 @@ function process$1() {
|
|
|
2934
2953
|
if (type && target && target.ownerDocument) {
|
|
2935
2954
|
parse(target.ownerDocument);
|
|
2936
2955
|
}
|
|
2956
|
+
if (type && target && target.nodeType == Node.DOCUMENT_FRAGMENT_NODE && target.host) {
|
|
2957
|
+
parse(target);
|
|
2958
|
+
}
|
|
2937
2959
|
switch (type) {
|
|
2938
2960
|
case "attributes" /* Attributes */:
|
|
2939
2961
|
processNode(target, 3 /* Attributes */);
|
|
@@ -3060,12 +3082,15 @@ function schedule(node) {
|
|
|
3060
3082
|
function trigger$1() {
|
|
3061
3083
|
for (var _i = 0, queue_1 = queue$1; _i < queue_1.length; _i++) {
|
|
3062
3084
|
var node = queue_1[_i];
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3085
|
+
// Generate a mutation for this node only if it still exists
|
|
3086
|
+
if (node) {
|
|
3087
|
+
var shadowRoot = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
|
|
3088
|
+
// Skip re-processing shadowRoot if it was already discovered
|
|
3089
|
+
if (shadowRoot && has(node)) {
|
|
3090
|
+
continue;
|
|
3091
|
+
}
|
|
3092
|
+
generate(node, shadowRoot ? "childList" /* ChildList */ : "characterData" /* CharacterData */);
|
|
3067
3093
|
}
|
|
3068
|
-
generate(node, shadowRoot ? "childList" /* ChildList */ : "characterData" /* CharacterData */);
|
|
3069
3094
|
}
|
|
3070
3095
|
queue$1 = [];
|
|
3071
3096
|
}
|
|
@@ -3417,8 +3442,8 @@ function upload(final) {
|
|
|
3417
3442
|
compute$8();
|
|
3418
3443
|
last = final === true;
|
|
3419
3444
|
e = JSON.stringify(envelope(last));
|
|
3420
|
-
a = "["
|
|
3421
|
-
p = sendPlaybackBytes ? "["
|
|
3445
|
+
a = "[".concat(analysis.join(), "]");
|
|
3446
|
+
p = sendPlaybackBytes ? "[".concat(playback.join(), "]") : "" /* Empty */;
|
|
3422
3447
|
encoded = { e: e, a: a, p: p };
|
|
3423
3448
|
payload = stringify(encoded);
|
|
3424
3449
|
if (!last) return [3 /*break*/, 1];
|
|
@@ -3445,7 +3470,7 @@ function upload(final) {
|
|
|
3445
3470
|
});
|
|
3446
3471
|
}
|
|
3447
3472
|
function stringify(encoded) {
|
|
3448
|
-
return encoded.p.length > 0 ? "{\"e\":"
|
|
3473
|
+
return encoded.p.length > 0 ? "{\"e\":".concat(encoded.e, ",\"a\":").concat(encoded.a, ",\"p\":").concat(encoded.p, "}") : "{\"e\":".concat(encoded.e, ",\"a\":").concat(encoded.a, "}");
|
|
3449
3474
|
}
|
|
3450
3475
|
function send(payload, zipped, sequence, beacon) {
|
|
3451
3476
|
if (beacon === void 0) { beacon = false; }
|
|
@@ -3458,10 +3483,14 @@ function send(payload, zipped, sequence, beacon) {
|
|
|
3458
3483
|
// However, we don't want to rely on it for every payload, since we have no ability to retry if the upload failed.
|
|
3459
3484
|
// Also, in case of sendBeacon, we do not have a way to alter HTTP headers and therefore can't send compressed payload
|
|
3460
3485
|
if (beacon && "sendBeacon" in navigator) {
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3486
|
+
try {
|
|
3487
|
+
// Navigator needs to be bound to sendBeacon before it is used to avoid errors in some browsers
|
|
3488
|
+
dispatched = navigator.sendBeacon.bind(navigator)(url, payload);
|
|
3489
|
+
if (dispatched) {
|
|
3490
|
+
done(sequence);
|
|
3491
|
+
}
|
|
3464
3492
|
}
|
|
3493
|
+
catch ( /* do nothing - and we will automatically fallback to XHR below */_a) { /* do nothing - and we will automatically fallback to XHR below */ }
|
|
3465
3494
|
}
|
|
3466
3495
|
// Before initiating XHR upload, we check if the data has already been uploaded using sendBeacon
|
|
3467
3496
|
// There are two cases when dispatched could still be false:
|
|
@@ -3505,7 +3534,7 @@ function check$3(xhr, sequence) {
|
|
|
3505
3534
|
if (xhr && xhr.readyState === 4 /* Done */ && transitData) {
|
|
3506
3535
|
// Attempt send payload again (as configured in settings) if we do not receive a success (2XX) response code back from the server
|
|
3507
3536
|
if ((xhr.status < 200 || xhr.status > 208) && transitData.attempts <= 1 /* RetryLimit */) {
|
|
3508
|
-
// We re-attempt in all cases except when server explicitly rejects our request with 4XX error
|
|
3537
|
+
// We re-attempt in all cases except when server explicitly rejects our request with 4XX error
|
|
3509
3538
|
if (xhr.status >= 400 && xhr.status < 500) {
|
|
3510
3539
|
// In case of a 4XX response from the server, we bail out instead of trying again
|
|
3511
3540
|
trigger(6 /* Server */);
|
|
@@ -3559,7 +3588,7 @@ function done(sequence) {
|
|
|
3559
3588
|
}
|
|
3560
3589
|
function delay() {
|
|
3561
3590
|
// Progressively increase delay as we continue to send more payloads from the client to the server
|
|
3562
|
-
// If we are not uploading data to a server, and instead invoking UploadCallback, in that case keep returning configured value
|
|
3591
|
+
// If we are not uploading data to a server, and instead invoking UploadCallback, in that case keep returning configured value
|
|
3563
3592
|
var gap = config$1.lean === false && discoverBytes > 0 ? 100 /* MinUploadDelay */ : data$1.sequence * config$1.delay;
|
|
3564
3593
|
return typeof config$1.upload === "string" /* String */ ? Math.max(Math.min(gap, 30000 /* MaxUploadDelay */), 100 /* MinUploadDelay */) : config$1.delay;
|
|
3565
3594
|
}
|
|
@@ -3721,7 +3750,7 @@ function log(dimension, value) {
|
|
|
3721
3750
|
// Check valid value before moving ahead
|
|
3722
3751
|
if (value) {
|
|
3723
3752
|
// Ensure received value is casted into a string if it wasn't a string to begin with
|
|
3724
|
-
value = ""
|
|
3753
|
+
value = "".concat(value);
|
|
3725
3754
|
if (!(dimension in data$3)) {
|
|
3726
3755
|
data$3[dimension] = [];
|
|
3727
3756
|
}
|
|
@@ -3806,9 +3835,10 @@ function userAgentData() {
|
|
|
3806
3835
|
"platformVersion",
|
|
3807
3836
|
"uaFullVersion"])
|
|
3808
3837
|
.then(function (ua) {
|
|
3838
|
+
var _a;
|
|
3809
3839
|
log(22 /* Platform */, ua.platform);
|
|
3810
3840
|
log(23 /* PlatformVersion */, ua.platformVersion);
|
|
3811
|
-
ua.brands.forEach(function (brand) {
|
|
3841
|
+
(_a = ua.brands) === null || _a === void 0 ? void 0 : _a.forEach(function (brand) {
|
|
3812
3842
|
log(24 /* Brand */, brand.name + "~" /* Tilde */ + brand.version);
|
|
3813
3843
|
});
|
|
3814
3844
|
log(25 /* Model */, ua.model);
|
|
@@ -3901,7 +3931,7 @@ function session() {
|
|
|
3901
3931
|
output.session = parts[0];
|
|
3902
3932
|
output.count = num(parts[2]) + 1;
|
|
3903
3933
|
output.upgrade = num(parts[3]);
|
|
3904
|
-
output.upload = parts.length >= 6 ? ""
|
|
3934
|
+
output.upload = parts.length >= 6 ? "".concat("https://" /* HTTPS */).concat(parts[5], "/").concat(parts[4]) : "".concat("https://" /* HTTPS */).concat(parts[4]);
|
|
3905
3935
|
}
|
|
3906
3936
|
}
|
|
3907
3937
|
return output;
|
|
@@ -3926,11 +3956,11 @@ function user() {
|
|
|
3926
3956
|
// Check if we either got version-less cookie value or saw multiple copies of the user cookie crumbs
|
|
3927
3957
|
// In both these cases, we go ahead and delete the existing cookie set on current domain
|
|
3928
3958
|
if (parts.length === 1 || count > 1) {
|
|
3929
|
-
var deleted = ""
|
|
3959
|
+
var deleted = "".concat(";" /* Semicolon */).concat("expires=" /* Expires */).concat((new Date(0)).toUTCString()).concat(";path=/" /* Path */);
|
|
3930
3960
|
// First, delete current user cookie which might be set on current sub-domain vs. root domain
|
|
3931
|
-
document.cookie = "_clck" /* CookieKey
|
|
3961
|
+
document.cookie = "".concat("_clck" /* CookieKey */, "=").concat(deleted);
|
|
3932
3962
|
// Second, same thing for current session cookie so it can be re-written later with the root domain
|
|
3933
|
-
document.cookie = "_clsk" /* SessionKey
|
|
3963
|
+
document.cookie = "".concat("_clsk" /* SessionKey */, "=").concat(deleted);
|
|
3934
3964
|
}
|
|
3935
3965
|
// End code for backward compatibility
|
|
3936
3966
|
// Read version information and timestamp from cookie, if available
|
|
@@ -3967,19 +3997,19 @@ function setCookie(key, value, time) {
|
|
|
3967
3997
|
var expiry = new Date();
|
|
3968
3998
|
expiry.setDate(expiry.getDate() + time);
|
|
3969
3999
|
var expires = expiry ? "expires=" /* Expires */ + expiry.toUTCString() : "" /* Empty */;
|
|
3970
|
-
var cookie = key
|
|
4000
|
+
var cookie = "".concat(key, "=").concat(value).concat(";" /* Semicolon */).concat(expires).concat(";path=/" /* Path */);
|
|
3971
4001
|
try {
|
|
3972
4002
|
// Attempt to get the root domain only once and fall back to writing cookie on the current domain.
|
|
3973
4003
|
if (rootDomain === null) {
|
|
3974
4004
|
var hostname = location.hostname ? location.hostname.split("." /* Dot */) : [];
|
|
3975
4005
|
// Walk backwards on a domain and attempt to set a cookie, until successful
|
|
3976
4006
|
for (var i = hostname.length - 1; i >= 0; i--) {
|
|
3977
|
-
rootDomain = "."
|
|
4007
|
+
rootDomain = ".".concat(hostname[i]).concat(rootDomain ? rootDomain : "" /* Empty */);
|
|
3978
4008
|
// We do not wish to attempt writing a cookie on the absolute last part of the domain, e.g. .com or .net.
|
|
3979
4009
|
// So we start attempting after second-last part, e.g. .domain.com (PASS) or .co.uk (FAIL)
|
|
3980
4010
|
if (i < hostname.length - 1) {
|
|
3981
4011
|
// Write the cookie on the current computed top level domain
|
|
3982
|
-
document.cookie = ""
|
|
4012
|
+
document.cookie = "".concat(cookie).concat(";" /* Semicolon */).concat("domain=" /* Domain */).concat(rootDomain);
|
|
3983
4013
|
// Once written, check if the cookie exists and its value matches exactly with what we intended to set
|
|
3984
4014
|
// Checking for exact value match helps us eliminate a corner case where the cookie may already be present with a different value
|
|
3985
4015
|
// If the check is successful, no more action is required and we can return from the function since rootDomain cookie is already set
|
|
@@ -3997,7 +4027,7 @@ function setCookie(key, value, time) {
|
|
|
3997
4027
|
catch (_a) {
|
|
3998
4028
|
rootDomain = "" /* Empty */;
|
|
3999
4029
|
}
|
|
4000
|
-
document.cookie = rootDomain ? ""
|
|
4030
|
+
document.cookie = rootDomain ? "".concat(cookie).concat(";" /* Semicolon */).concat("domain=" /* Domain */).concat(rootDomain) : cookie;
|
|
4001
4031
|
}
|
|
4002
4032
|
}
|
|
4003
4033
|
|
|
@@ -4093,7 +4123,7 @@ function bind(target, event, listener, capture) {
|
|
|
4093
4123
|
// Wrapping following lines inside try / catch to cover edge cases where we might try to access an inaccessible element.
|
|
4094
4124
|
// E.g. Iframe may start off as same-origin but later turn into cross-origin, and the following lines will throw an exception.
|
|
4095
4125
|
try {
|
|
4096
|
-
target
|
|
4126
|
+
target[api("addEventListener" /* AddEventListener */)](event, listener, capture);
|
|
4097
4127
|
bindings.push({ event: event, target: target, listener: listener, capture: capture });
|
|
4098
4128
|
}
|
|
4099
4129
|
catch ( /* do nothing */_a) { /* do nothing */ }
|
|
@@ -4104,7 +4134,7 @@ function reset$1() {
|
|
|
4104
4134
|
var binding = bindings_1[_i];
|
|
4105
4135
|
// Wrapping inside try / catch to avoid situations where the element may be destroyed before we get a chance to unbind
|
|
4106
4136
|
try {
|
|
4107
|
-
binding.target
|
|
4137
|
+
binding.target[api("removeEventListener" /* RemoveEventListener */)](binding.event, binding.listener, binding.capture);
|
|
4108
4138
|
}
|
|
4109
4139
|
catch ( /* do nothing */_a) { /* do nothing */ }
|
|
4110
4140
|
}
|