@glimt/record 0.0.58 → 0.0.60

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.
@@ -1034,6 +1034,223 @@ const _AsyncStylesheetManager$1 = class _AsyncStylesheetManager {
1034
1034
  __publicField$1(_AsyncStylesheetManager$1, "instance");
1035
1035
  let AsyncStylesheetManager$1 = _AsyncStylesheetManager$1;
1036
1036
  const asyncStylesheetManager$1 = new AsyncStylesheetManager$1();
1037
+ const serializeLinkInline = ({
1038
+ attributes,
1039
+ doc,
1040
+ n: n2
1041
+ }) => {
1042
+ const styleSheets2 = Array.from(doc.styleSheets);
1043
+ let stylesheet = null;
1044
+ for (let i2 = 0; i2 < styleSheets2.length; i2++) {
1045
+ if (styleSheets2[i2].href === n2.href) {
1046
+ stylesheet = styleSheets2[i2];
1047
+ break;
1048
+ }
1049
+ }
1050
+ let cssText = null;
1051
+ if (stylesheet) {
1052
+ cssText = stringifyStylesheet$1(stylesheet);
1053
+ }
1054
+ if (!cssText) {
1055
+ cssText = asyncStylesheetManager$1.getClonedCssTextIfAvailable(
1056
+ n2.href
1057
+ );
1058
+ }
1059
+ if (cssText) {
1060
+ delete attributes.rel;
1061
+ delete attributes.href;
1062
+ attributes._cssText = cssText;
1063
+ } else {
1064
+ const requestCssId = `css-request-${Math.random().toString(36).slice(2)}`;
1065
+ asyncStylesheetManager$1.requestClone({
1066
+ forElement: n2,
1067
+ requestCssId
1068
+ });
1069
+ attributes._requestCssId = requestCssId;
1070
+ }
1071
+ return attributes;
1072
+ };
1073
+ const serializeStyleInline = ({
1074
+ attributes,
1075
+ n: n2
1076
+ }) => {
1077
+ let cssText = stringifyStylesheet$1(
1078
+ n2.sheet
1079
+ );
1080
+ if (cssText) {
1081
+ if (n2.childNodes.length > 1) {
1082
+ cssText = markCssSplits(cssText, n2);
1083
+ }
1084
+ attributes._cssText = cssText;
1085
+ }
1086
+ return attributes;
1087
+ };
1088
+ const serializeUserFields = ({
1089
+ attributes,
1090
+ n: n2,
1091
+ tagName,
1092
+ maskInputOptions,
1093
+ maskInputFn
1094
+ }) => {
1095
+ const value = n2.value;
1096
+ const checked = n2.checked;
1097
+ if (attributes.type !== "radio" && attributes.type !== "checkbox" && attributes.type !== "submit" && attributes.type !== "button" && value) {
1098
+ attributes.value = maskInputValue({
1099
+ element: n2,
1100
+ type: getInputType(n2),
1101
+ tagName,
1102
+ value,
1103
+ maskInputOptions,
1104
+ maskInputFn
1105
+ });
1106
+ } else if (checked) {
1107
+ attributes.checked = checked;
1108
+ }
1109
+ return attributes;
1110
+ };
1111
+ const serializeOption = ({
1112
+ attributes,
1113
+ n: n2,
1114
+ maskInputOptions
1115
+ }) => {
1116
+ if (n2.selected && !maskInputOptions["select"]) {
1117
+ attributes.selected = true;
1118
+ } else {
1119
+ delete attributes.selected;
1120
+ }
1121
+ return attributes;
1122
+ };
1123
+ const runIdleCallback = (cb) => {
1124
+ if ("requestIdleCallback" in window) {
1125
+ window.requestIdleCallback(cb);
1126
+ } else {
1127
+ setTimeout(cb, 100);
1128
+ }
1129
+ };
1130
+ const serializeCanvas = ({
1131
+ attributes,
1132
+ n: n2,
1133
+ dataURLOptions,
1134
+ doc
1135
+ }) => {
1136
+ let context = "getContext" in n2 ? n2.getContext("2d") : null;
1137
+ if (context != null) {
1138
+ if (!is2DCanvasBlank(n2, context)) {
1139
+ attributes.rr_dataURL = n2.toDataURL(
1140
+ dataURLOptions.type,
1141
+ dataURLOptions.quality
1142
+ );
1143
+ }
1144
+ } else if (n2.width !== 0 && n2.height !== 0) {
1145
+ const canvasDataURL = n2.toDataURL(
1146
+ dataURLOptions.type,
1147
+ dataURLOptions.quality
1148
+ );
1149
+ attributes.rr_dataURL = canvasDataURL;
1150
+ runIdleCallback(() => {
1151
+ try {
1152
+ const blankCanvas = doc.createElement("canvas");
1153
+ blankCanvas.width = n2.width;
1154
+ blankCanvas.height = n2.height;
1155
+ const blankCanvasDataURL = blankCanvas.toDataURL(
1156
+ dataURLOptions.type,
1157
+ dataURLOptions.quality
1158
+ );
1159
+ if (canvasDataURL === blankCanvasDataURL) {
1160
+ delete attributes.rr_dataURL;
1161
+ }
1162
+ } catch (e2) {
1163
+ }
1164
+ });
1165
+ }
1166
+ return attributes;
1167
+ };
1168
+ const serializeImageInline = ({
1169
+ attributes,
1170
+ n: n2,
1171
+ canvasService: canvasService2,
1172
+ canvasCtx: canvasCtx2,
1173
+ dataURLOptions,
1174
+ doc
1175
+ }) => {
1176
+ if (!canvasService2) {
1177
+ canvasService2 = doc.createElement("canvas");
1178
+ canvasCtx2 = canvasService2.getContext("2d");
1179
+ }
1180
+ const image = n2;
1181
+ let overrideImage = null;
1182
+ let calls = 0;
1183
+ const imageSrc = (image.currentSrc || image.getAttribute("src") || "<unknown-src>") + "";
1184
+ const imageHeight = image.naturalHeight;
1185
+ const imageWidth = image.naturalWidth;
1186
+ const inlineImageCleanup = () => {
1187
+ overrideImage = null;
1188
+ };
1189
+ const recordInlineImage = () => {
1190
+ calls++;
1191
+ if (calls > 3) return;
1192
+ (overrideImage != null ? overrideImage : image).removeEventListener("error", onImageLoadError);
1193
+ try {
1194
+ canvasService2.width = imageWidth;
1195
+ canvasService2.height = imageHeight;
1196
+ canvasCtx2.drawImage(image, 0, 0);
1197
+ attributes.rr_dataURL = canvasService2.toDataURL(
1198
+ dataURLOptions.type,
1199
+ dataURLOptions.quality
1200
+ );
1201
+ } catch (err) {
1202
+ if (image.crossOrigin !== "anonymous") {
1203
+ if (shouldTryAnonymousFetchingOnCorsError$1()) {
1204
+ overrideImage = new Image();
1205
+ overrideImage.src = imageSrc;
1206
+ overrideImage.crossOrigin = "anonymous";
1207
+ overrideImage.height = imageHeight;
1208
+ overrideImage.width = imageWidth;
1209
+ if (overrideImage.complete && overrideImage.naturalWidth !== 0) {
1210
+ recordInlineImage();
1211
+ } else {
1212
+ overrideImage.addEventListener("load", recordInlineImage, {
1213
+ once: true
1214
+ });
1215
+ overrideImage.addEventListener("error", onImageLoadError, {
1216
+ once: true
1217
+ });
1218
+ }
1219
+ return;
1220
+ }
1221
+ } else {
1222
+ if (isDebug$1())
1223
+ console.warn(
1224
+ `Cannot inline img src=${imageSrc}! Error: ${err}`
1225
+ );
1226
+ }
1227
+ }
1228
+ inlineImageCleanup();
1229
+ };
1230
+ const onImageLoadError = () => {
1231
+ (overrideImage != null ? overrideImage : image).removeEventListener("load", recordInlineImage);
1232
+ inlineImageCleanup();
1233
+ };
1234
+ if (image.complete && image.naturalWidth !== 0) recordInlineImage();
1235
+ else {
1236
+ image.addEventListener("load", recordInlineImage, { once: true });
1237
+ image.addEventListener("error", onImageLoadError, { once: true });
1238
+ }
1239
+ return attributes;
1240
+ };
1241
+ const serializeMediaElements = ({
1242
+ attributes,
1243
+ n: n2
1244
+ }) => {
1245
+ const mediaAttributes = attributes;
1246
+ mediaAttributes.rr_mediaState = n2.paused ? "paused" : "played";
1247
+ mediaAttributes.rr_mediaCurrentTime = n2.currentTime;
1248
+ mediaAttributes.rr_mediaPlaybackRate = n2.playbackRate;
1249
+ mediaAttributes.rr_mediaMuted = n2.muted;
1250
+ mediaAttributes.rr_mediaLoop = n2.loop;
1251
+ mediaAttributes.rr_mediaVolume = n2.volume;
1252
+ return attributes;
1253
+ };
1037
1254
  let _id = 1;
1038
1255
  const tagNameRegex = new RegExp("[^a-z0-9-_:]");
1039
1256
  const IGNORED_NODE = -2;
@@ -1050,8 +1267,8 @@ function getValidTagName$1(element) {
1050
1267
  }
1051
1268
  return processedTagName;
1052
1269
  }
1053
- let canvasService;
1054
- let canvasCtx;
1270
+ let canvasService = null;
1271
+ let canvasCtx = null;
1055
1272
  const SRCSET_NOT_SPACES = /^[^ \t\n\r\u000c]+/;
1056
1273
  const SRCSET_COMMAS_OR_SPACES = /^[, \t\n\r\u000c]+/;
1057
1274
  function getAbsoluteSrcsetString(doc, attributeValue) {
@@ -1363,13 +1580,6 @@ function getRootId(doc, mirror2) {
1363
1580
  const docId = mirror2.getId(doc);
1364
1581
  return docId === 1 ? void 0 : docId;
1365
1582
  }
1366
- const runIdleCallback = (cb) => {
1367
- if ("requestIdleCallback" in window) {
1368
- window.requestIdleCallback(cb);
1369
- } else {
1370
- setTimeout(cb, 100);
1371
- }
1372
- };
1373
1583
  function serializeTextNode(n2, options) {
1374
1584
  const { needsMask, maskTextFn, rootId, cssCaptured } = options;
1375
1585
  const parent = index.parentNode(n2);
@@ -1424,179 +1634,77 @@ function serializeElementNode(n2, options) {
1424
1634
  );
1425
1635
  }
1426
1636
  }
1427
- if (tagName === "link" && inlineStylesheet) {
1428
- const styleSheets2 = Array.from(doc.styleSheets);
1429
- let stylesheet = null;
1430
- for (let i2 = 0; i2 < styleSheets2.length; i2++) {
1431
- if (styleSheets2[i2].href === n2.href) {
1432
- stylesheet = styleSheets2[i2];
1433
- break;
1637
+ switch (tagName) {
1638
+ case "link":
1639
+ if (inlineStylesheet) {
1640
+ attributes = serializeLinkInline({
1641
+ doc,
1642
+ attributes,
1643
+ n: n2
1644
+ });
1434
1645
  }
1435
- }
1436
- let cssText = null;
1437
- if (stylesheet) {
1438
- cssText = stringifyStylesheet$1(stylesheet);
1439
- }
1440
- if (!cssText) {
1441
- cssText = asyncStylesheetManager$1.getClonedCssTextIfAvailable(
1442
- n2.href
1443
- );
1444
- }
1445
- if (cssText) {
1446
- delete attributes.rel;
1447
- delete attributes.href;
1448
- attributes._cssText = cssText;
1449
- } else {
1450
- const requestCssId = `css-request-${Math.random().toString(36).slice(2)}`;
1451
- asyncStylesheetManager$1.requestClone({
1452
- forElement: n2,
1453
- requestCssId
1454
- });
1455
- attributes._requestCssId = requestCssId;
1456
- }
1457
- }
1458
- if (tagName === "style" && n2.sheet) {
1459
- let cssText = stringifyStylesheet$1(
1460
- n2.sheet
1461
- );
1462
- if (cssText) {
1463
- if (n2.childNodes.length > 1) {
1464
- cssText = markCssSplits(cssText, n2);
1646
+ break;
1647
+ case "style":
1648
+ if (n2.sheet) {
1649
+ attributes = serializeStyleInline({
1650
+ attributes,
1651
+ n: n2
1652
+ });
1465
1653
  }
1466
- attributes._cssText = cssText;
1467
- }
1468
- }
1469
- if (tagName === "input" || tagName === "textarea" || tagName === "select") {
1470
- const value = n2.value;
1471
- const checked = n2.checked;
1472
- if (attributes.type !== "radio" && attributes.type !== "checkbox" && attributes.type !== "submit" && attributes.type !== "button" && value) {
1473
- attributes.value = maskInputValue({
1474
- element: n2,
1475
- type: getInputType(n2),
1654
+ break;
1655
+ case "input":
1656
+ case "textarea":
1657
+ case "select":
1658
+ attributes = serializeUserFields({
1659
+ attributes,
1660
+ n: n2,
1476
1661
  tagName,
1477
- value,
1478
1662
  maskInputOptions,
1479
1663
  maskInputFn
1480
1664
  });
1481
- } else if (checked) {
1482
- attributes.checked = checked;
1483
- }
1484
- }
1485
- if (tagName === "option") {
1486
- if (n2.selected && !maskInputOptions["select"]) {
1487
- attributes.selected = true;
1488
- } else {
1489
- delete attributes.selected;
1490
- }
1491
- }
1492
- if (tagName === "dialog" && n2.open) {
1493
- attributes.rr_open_mode = n2.matches("dialog:modal") ? "modal" : "non-modal";
1494
- }
1495
- if (tagName === "canvas" && recordCanvas) {
1496
- let context = "getContext" in n2 ? n2.getContext("2d") : null;
1497
- if (context != null) {
1498
- if (!is2DCanvasBlank(n2, context)) {
1499
- attributes.rr_dataURL = n2.toDataURL(
1500
- dataURLOptions.type,
1501
- dataURLOptions.quality
1502
- );
1503
- }
1504
- } else if (n2.width !== 0 && n2.height !== 0) {
1505
- const canvasDataURL = n2.toDataURL(
1506
- dataURLOptions.type,
1507
- dataURLOptions.quality
1508
- );
1509
- attributes.rr_dataURL = canvasDataURL;
1510
- runIdleCallback(() => {
1511
- try {
1512
- const blankCanvas = doc.createElement("canvas");
1513
- blankCanvas.width = n2.width;
1514
- blankCanvas.height = n2.height;
1515
- const blankCanvasDataURL = blankCanvas.toDataURL(
1516
- dataURLOptions.type,
1517
- dataURLOptions.quality
1518
- );
1519
- if (canvasDataURL === blankCanvasDataURL) {
1520
- delete attributes.rr_dataURL;
1521
- }
1522
- } catch (e2) {
1523
- }
1665
+ break;
1666
+ case "option":
1667
+ attributes = serializeOption({
1668
+ attributes,
1669
+ n: n2,
1670
+ maskInputOptions
1524
1671
  });
1525
- }
1526
- }
1527
- if (tagName === "img" && inlineImages) {
1528
- if (!canvasService) {
1529
- canvasService = doc.createElement("canvas");
1530
- canvasCtx = canvasService.getContext("2d");
1531
- }
1532
- const image = n2;
1533
- let overrideImage = null;
1534
- let calls = 0;
1535
- const imageSrc = (image.currentSrc || image.getAttribute("src") || "<unknown-src>") + "";
1536
- const imageHeight = image.naturalHeight;
1537
- const imageWidth = image.naturalWidth;
1538
- const inlineImageCleanup = () => {
1539
- overrideImage = null;
1540
- };
1541
- const recordInlineImage = () => {
1542
- calls++;
1543
- if (calls > 3) return;
1544
- (overrideImage != null ? overrideImage : image).removeEventListener("error", onImageLoadError);
1545
- try {
1546
- canvasService.width = imageWidth;
1547
- canvasService.height = imageHeight;
1548
- canvasCtx.drawImage(image, 0, 0);
1549
- attributes.rr_dataURL = canvasService.toDataURL(
1550
- dataURLOptions.type,
1551
- dataURLOptions.quality
1552
- );
1553
- } catch (err) {
1554
- if (image.crossOrigin !== "anonymous") {
1555
- if (shouldTryAnonymousFetchingOnCorsError$1()) {
1556
- overrideImage = new Image();
1557
- overrideImage.src = imageSrc;
1558
- overrideImage.crossOrigin = "anonymous";
1559
- overrideImage.height = imageHeight;
1560
- overrideImage.width = imageWidth;
1561
- if (overrideImage.complete && overrideImage.naturalWidth !== 0) {
1562
- recordInlineImage();
1563
- } else {
1564
- overrideImage.addEventListener("load", recordInlineImage, {
1565
- once: true
1566
- });
1567
- overrideImage.addEventListener("error", onImageLoadError, {
1568
- once: true
1569
- });
1570
- }
1571
- return;
1572
- }
1573
- } else {
1574
- if (isDebug$1())
1575
- console.warn(
1576
- `Cannot inline img src=${imageSrc}! Error: ${err}`
1577
- );
1578
- }
1672
+ break;
1673
+ case "dialog":
1674
+ if (n2.open) {
1675
+ attributes.rr_open_mode = n2.matches(
1676
+ "dialog:modal"
1677
+ ) ? "modal" : "non-modal";
1579
1678
  }
1580
- inlineImageCleanup();
1581
- };
1582
- const onImageLoadError = () => {
1583
- (overrideImage != null ? overrideImage : image).removeEventListener("load", recordInlineImage);
1584
- inlineImageCleanup();
1585
- };
1586
- if (image.complete && image.naturalWidth !== 0) recordInlineImage();
1587
- else {
1588
- image.addEventListener("load", recordInlineImage, { once: true });
1589
- image.addEventListener("error", onImageLoadError, { once: true });
1590
- }
1591
- }
1592
- if (tagName === "audio" || tagName === "video") {
1593
- const mediaAttributes = attributes;
1594
- mediaAttributes.rr_mediaState = n2.paused ? "paused" : "played";
1595
- mediaAttributes.rr_mediaCurrentTime = n2.currentTime;
1596
- mediaAttributes.rr_mediaPlaybackRate = n2.playbackRate;
1597
- mediaAttributes.rr_mediaMuted = n2.muted;
1598
- mediaAttributes.rr_mediaLoop = n2.loop;
1599
- mediaAttributes.rr_mediaVolume = n2.volume;
1679
+ break;
1680
+ case "canvas":
1681
+ if (recordCanvas) {
1682
+ attributes = serializeCanvas({
1683
+ attributes,
1684
+ n: n2,
1685
+ dataURLOptions,
1686
+ doc
1687
+ });
1688
+ }
1689
+ case "img":
1690
+ if (inlineImages) {
1691
+ attributes = serializeImageInline({
1692
+ attributes,
1693
+ n: n2,
1694
+ canvasService,
1695
+ canvasCtx,
1696
+ dataURLOptions,
1697
+ doc
1698
+ });
1699
+ }
1700
+ break;
1701
+ case "audio":
1702
+ case "video":
1703
+ attributes = serializeMediaElements({
1704
+ attributes,
1705
+ n: n2
1706
+ });
1707
+ break;
1600
1708
  }
1601
1709
  if (!newlyAddedElement) {
1602
1710
  if (n2.scrollLeft) {
@@ -1675,7 +1783,12 @@ function slimDOMExcluded(sn, slimDOMOptions) {
1675
1783
  }
1676
1784
  return false;
1677
1785
  }
1786
+ const debugging = {
1787
+ index: 0,
1788
+ store: {}
1789
+ };
1678
1790
  function serializeNodeWithId(n2, options) {
1791
+ const start = Date.now();
1679
1792
  const {
1680
1793
  doc,
1681
1794
  mirror: mirror2,
@@ -1905,6 +2018,23 @@ function serializeNodeWithId(n2, options) {
1905
2018
  stylesheetLoadTimeout
1906
2019
  );
1907
2020
  }
2021
+ debugging.index++;
2022
+ const took = Date.now() - start;
2023
+ if (!(n2.nodeName in debugging.store)) {
2024
+ debugging.store[n2.nodeName] = [];
2025
+ }
2026
+ debugging.store[n2.nodeName].push(took);
2027
+ if (debugging.index % 1e3 === 0) {
2028
+ debugging.index = 0;
2029
+ const avgs = Object.entries(debugging.store).map(([key, values]) => {
2030
+ return {
2031
+ key,
2032
+ avg: values.reduce((a2, b) => a2 + b, 0) / values.length
2033
+ };
2034
+ });
2035
+ console.log("last 1000 avgs", JSON.parse(JSON.stringify(avgs)));
2036
+ debugging.store = {};
2037
+ }
1908
2038
  return serializedNode;
1909
2039
  }
1910
2040
  function snapshot(n2, options) {