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 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.28";
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 "" + prefix + trimmed.length.toString(36) + suffix;
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 + "." + timer.cost;
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("" + "#" /* Box */ + str$1(size[0]) + "." + str$1(size[1]));
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 + "=" + scrub(value, key, privacy);
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 + "|" + message : "";
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("[" + match + "]").forEach(function (e) { max(metricId, num$2(e.getAttribute(match), scale, false)); });
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("[" + match + "]").forEach(function (e) { log(dimensionId, str(e.getAttribute(match))); });
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(" + input.position + ")" : "" /* Empty */;
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 = "" + prefix + input.tag + suffix;
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 ? "" + prefix + input.tag + "." + classes.join(".") + suffix : selector;
1414
- selector = id && hasDigits(id) === false ? (shadowStart >= 0 ? prefix.substr(0, shadowEnd) + "#" + id : "#" + id) : selector;
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 ? "" + prefix + input.tag + "." + classes.join(".") + suffix : selector;
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
- config$1.unmask.forEach(function (x) { return root.querySelectorAll(x).forEach(function (e) { return privacyMap.set(e, 0 /* None */); }); }); // Unmasked Elements
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, parentTag, privacy);
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, parentTag, privacy) {
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 _i = 0, DISALLOWED_MATCH_1 = DISALLOWED_MATCH; _i < DISALLOWED_MATCH_1.length; _i++) {
1621
- var match = DISALLOWED_MATCH_1[_i];
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 _a = 0, _b = Object.keys(attributes); _a < _b.length; _a++) {
1634
- var attribute = _b[_a];
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 _c = 0, DISALLOWED_NAMES_1 = DISALLOWED_NAMES; _c < DISALLOWED_NAMES_1.length; _c++) {
1638
- var name_1 = DISALLOWED_NAMES_1[_c];
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 = HTMLElement.prototype.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
- HTMLElement.prototype.attachShadow = function () {
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
- // In an edge case, it's possible to get stuck into infinite Mutation loop within Angular applications
2842
- // This appears to be an issue with Zone.js package, see: https://github.com/angular/angular/issues/31712
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
- HTMLElement.prototype.attachShadow = attachShadow;
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
- var shadowRoot = node && node.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
3064
- // Skip re-processing shadowRoot if it was already discovered
3065
- if (shadowRoot && has(node)) {
3066
- continue;
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 = "[" + analysis.join() + "]";
3421
- p = sendPlaybackBytes ? "[" + playback.join() + "]" : "" /* Empty */;
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\":" + encoded.e + ",\"a\":" + encoded.a + ",\"p\":" + encoded.p + "}" : "{\"e\":" + encoded.e + ",\"a\":" + encoded.a + "}";
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
- dispatched = navigator.sendBeacon(url, payload);
3462
- if (dispatched) {
3463
- done(sequence);
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 = "" + 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 ? "" + "https://" /* HTTPS */ + parts[5] + "/" + parts[4] : "" + "https://" /* HTTPS */ + parts[4];
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 = "" + ";" /* Semicolon */ + "expires=" /* Expires */ + (new Date(0)).toUTCString() + ";path=/" /* Path */;
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 */ + "=" + deleted;
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 */ + "=" + deleted;
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 + "=" + value + ";" /* Semicolon */ + expires + ";path=/" /* Path */;
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 = "." + hostname[i] + (rootDomain ? rootDomain : "" /* Empty */);
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 = "" + cookie + ";" /* Semicolon */ + "domain=" /* Domain */ + rootDomain;
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 ? "" + cookie + ";" /* Semicolon */ + "domain=" /* Domain */ + rootDomain : cookie;
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.addEventListener(event, listener, capture);
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.removeEventListener(binding.event, binding.listener, binding.capture);
4137
+ binding.target[api("removeEventListener" /* RemoveEventListener */)](binding.event, binding.listener, binding.capture);
4108
4138
  }
4109
4139
  catch ( /* do nothing */_a) { /* do nothing */ }
4110
4140
  }