@appsurify-testmap/rrweb-record 2.1.0-alpha.3 → 2.1.0-alpha.5

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.
@@ -880,32 +880,14 @@ function transformAttribute(doc, tagName, name, value) {
880
880
  }
881
881
  return value;
882
882
  }
883
- function isIgnoreAttribute(tagName, name, _value) {
883
+ function ignoreAttribute(tagName, name, _value) {
884
884
  return (tagName === "video" || tagName === "audio") && name === "autoplay";
885
885
  }
886
- function cleanAttributes(doc, element, ignoreAttribute) {
887
- const tagName = getValidTagName$1(element);
888
- const attributes = {};
889
- const len = element.attributes.length;
890
- for (let i2 = 0; i2 < len; i2++) {
891
- const attr = element.attributes[i2];
892
- const name = attr.name;
893
- const value = attr.value;
894
- const shouldIgnoreByName = typeof ignoreAttribute === "string" ? name === ignoreAttribute : ignoreAttribute.test(name);
895
- if (!shouldIgnoreByName && !isIgnoreAttribute(tagName, name)) {
896
- attributes[name] = transformAttribute(
897
- doc,
898
- tagName,
899
- toLowerCase(name),
900
- value
901
- );
902
- }
903
- }
904
- return attributes;
886
+ function isIncludeAttribute(name, include) {
887
+ return typeof include === "string" ? name.includes(include) : include.test(name);
905
888
  }
906
- function shouldIgnoreAttribute(ignore, name) {
907
- if (!ignore) return false;
908
- return typeof ignore === "string" ? name === ignore : ignore.test(name);
889
+ function isExcludeAttribute(name, exclude) {
890
+ return typeof exclude === "string" ? name.includes(exclude) : exclude.test(name);
909
891
  }
910
892
  function _isBlockedElement(element, blockClass, blockSelector) {
911
893
  try {
@@ -1036,7 +1018,8 @@ function serializeNode(n2, options) {
1036
1018
  mirror: mirror2,
1037
1019
  blockClass,
1038
1020
  blockSelector,
1039
- ignoreAttribute,
1021
+ excludeAttribute,
1022
+ includeAttribute,
1040
1023
  needsMask,
1041
1024
  inlineStylesheet,
1042
1025
  maskInputOptions = {},
@@ -1082,7 +1065,8 @@ function serializeNode(n2, options) {
1082
1065
  doc,
1083
1066
  blockClass,
1084
1067
  blockSelector,
1085
- ignoreAttribute,
1068
+ excludeAttribute,
1069
+ includeAttribute,
1086
1070
  inlineStylesheet,
1087
1071
  maskInputOptions,
1088
1072
  maskInputFn,
@@ -1160,7 +1144,8 @@ function serializeElementNode(n2, options) {
1160
1144
  doc,
1161
1145
  blockClass,
1162
1146
  blockSelector,
1163
- ignoreAttribute,
1147
+ excludeAttribute,
1148
+ includeAttribute,
1164
1149
  inlineStylesheet,
1165
1150
  maskInputOptions = {},
1166
1151
  maskInputFn,
@@ -1174,7 +1159,22 @@ function serializeElementNode(n2, options) {
1174
1159
  } = options;
1175
1160
  const needBlock = _isBlockedElement(n2, blockClass, blockSelector);
1176
1161
  const tagName = getValidTagName$1(n2);
1177
- let attributes = cleanAttributes(doc, n2, ignoreAttribute);
1162
+ let attributes = {};
1163
+ const len = n2.attributes.length;
1164
+ for (let i2 = 0; i2 < len; i2++) {
1165
+ const attr = n2.attributes[i2];
1166
+ if (isExcludeAttribute(attr.name, excludeAttribute) && !isIncludeAttribute(attr.name, includeAttribute)) {
1167
+ continue;
1168
+ }
1169
+ if (!ignoreAttribute(tagName, attr.name, attr.value)) {
1170
+ attributes[attr.name] = transformAttribute(
1171
+ doc,
1172
+ tagName,
1173
+ toLowerCase(attr.name),
1174
+ attr.value
1175
+ );
1176
+ }
1177
+ }
1178
1178
  if (tagName === "link" && inlineStylesheet) {
1179
1179
  const stylesheet = Array.from(doc.styleSheets).find((s2) => {
1180
1180
  return s2.href === n2.href;
@@ -1388,7 +1388,8 @@ function serializeNodeWithId(n2, options) {
1388
1388
  blockSelector,
1389
1389
  maskTextClass,
1390
1390
  maskTextSelector,
1391
- ignoreAttribute,
1391
+ excludeAttribute,
1392
+ includeAttribute,
1392
1393
  skipChild = false,
1393
1394
  inlineStylesheet = true,
1394
1395
  maskInputOptions = {},
@@ -1423,7 +1424,8 @@ function serializeNodeWithId(n2, options) {
1423
1424
  mirror: mirror2,
1424
1425
  blockClass,
1425
1426
  blockSelector,
1426
- ignoreAttribute,
1427
+ excludeAttribute,
1428
+ includeAttribute,
1427
1429
  needsMask,
1428
1430
  inlineStylesheet,
1429
1431
  maskInputOptions,
@@ -1476,7 +1478,8 @@ function serializeNodeWithId(n2, options) {
1476
1478
  needsMask,
1477
1479
  maskTextClass,
1478
1480
  maskTextSelector,
1479
- ignoreAttribute,
1481
+ excludeAttribute,
1482
+ includeAttribute,
1480
1483
  skipChild,
1481
1484
  inlineStylesheet,
1482
1485
  maskInputOptions,
@@ -1536,7 +1539,8 @@ function serializeNodeWithId(n2, options) {
1536
1539
  needsMask,
1537
1540
  maskTextClass,
1538
1541
  maskTextSelector,
1539
- ignoreAttribute,
1542
+ excludeAttribute,
1543
+ includeAttribute,
1540
1544
  skipChild: false,
1541
1545
  inlineStylesheet,
1542
1546
  maskInputOptions,
@@ -1578,7 +1582,8 @@ function serializeNodeWithId(n2, options) {
1578
1582
  needsMask,
1579
1583
  maskTextClass,
1580
1584
  maskTextSelector,
1581
- ignoreAttribute,
1585
+ excludeAttribute,
1586
+ includeAttribute,
1582
1587
  skipChild: false,
1583
1588
  inlineStylesheet,
1584
1589
  maskInputOptions,
@@ -1616,7 +1621,8 @@ function snapshot(n2, options) {
1616
1621
  blockSelector = null,
1617
1622
  maskTextClass = "rr-mask",
1618
1623
  maskTextSelector = null,
1619
- ignoreAttribute = "rr-ignore",
1624
+ excludeAttribute = /^$a/,
1625
+ includeAttribute = /.+/i,
1620
1626
  inlineStylesheet = true,
1621
1627
  inlineImages = false,
1622
1628
  recordCanvas = false,
@@ -1676,7 +1682,8 @@ function snapshot(n2, options) {
1676
1682
  blockSelector,
1677
1683
  maskTextClass,
1678
1684
  maskTextSelector,
1679
- ignoreAttribute,
1685
+ excludeAttribute,
1686
+ includeAttribute,
1680
1687
  skipChild: false,
1681
1688
  inlineStylesheet,
1682
1689
  maskInputOptions,
@@ -9184,7 +9191,7 @@ function hookSetter(target, key, d, isRevoked, win = window) {
9184
9191
  return () => hookSetter(target, key, original || {}, true);
9185
9192
  }
9186
9193
  function nowTimestamp() {
9187
- return performance.timeOrigin + performance.now();
9194
+ return Math.round(performance.timeOrigin + performance.now());
9188
9195
  }
9189
9196
  function getWindowScroll(win = window) {
9190
9197
  var _a2, _b, _c, _d;
@@ -9374,7 +9381,6 @@ var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => {
9374
9381
  IncrementalSource2[IncrementalSource2["Selection"] = 14] = "Selection";
9375
9382
  IncrementalSource2[IncrementalSource2["AdoptedStyleSheet"] = 15] = "AdoptedStyleSheet";
9376
9383
  IncrementalSource2[IncrementalSource2["CustomElement"] = 16] = "CustomElement";
9377
- IncrementalSource2[IncrementalSource2["VisibilityChange"] = 17] = "VisibilityChange";
9378
9384
  return IncrementalSource2;
9379
9385
  })(IncrementalSource || {});
9380
9386
  var MouseInteractions = /* @__PURE__ */ ((MouseInteractions2) => {
@@ -9520,7 +9526,8 @@ class MutationBuffer {
9520
9526
  __publicField(this, "blockSelector");
9521
9527
  __publicField(this, "maskTextClass");
9522
9528
  __publicField(this, "maskTextSelector");
9523
- __publicField(this, "ignoreAttribute");
9529
+ __publicField(this, "excludeAttribute");
9530
+ __publicField(this, "includeAttribute");
9524
9531
  __publicField(this, "inlineStylesheet");
9525
9532
  __publicField(this, "maskInputOptions");
9526
9533
  __publicField(this, "maskTextFn");
@@ -9584,7 +9591,8 @@ class MutationBuffer {
9584
9591
  blockSelector: this.blockSelector,
9585
9592
  maskTextClass: this.maskTextClass,
9586
9593
  maskTextSelector: this.maskTextSelector,
9587
- ignoreAttribute: this.ignoreAttribute || "",
9594
+ excludeAttribute: this.excludeAttribute,
9595
+ includeAttribute: this.includeAttribute,
9588
9596
  skipChild: true,
9589
9597
  newlyAddedElement: true,
9590
9598
  inlineStylesheet: this.inlineStylesheet,
@@ -9704,21 +9712,6 @@ class MutationBuffer {
9704
9712
  };
9705
9713
  }).filter((text) => !addedIds.has(text.id)).filter((text) => this.mirror.has(text.id)),
9706
9714
  attributes: this.attributes.map((attribute) => {
9707
- const element = attribute.node;
9708
- const filtered = {};
9709
- for (const [name, value] of Object.entries(attribute.attributes)) {
9710
- const isIgnored2 = shouldIgnoreAttribute(this.ignoreAttribute, name);
9711
- const existedBefore = element.hasAttribute(name);
9712
- const keep = value !== null && !isIgnored2 || value === null && (!isIgnored2 || attribute.attributes[name] !== null || existedBefore);
9713
- if (keep) {
9714
- filtered[name] = value;
9715
- }
9716
- }
9717
- return {
9718
- ...attribute,
9719
- attributes: filtered
9720
- };
9721
- }).filter((attribute) => Object.keys(attribute.attributes).length > 0).map((attribute) => {
9722
9715
  const { attributes } = attribute;
9723
9716
  if (typeof attributes.style === "string") {
9724
9717
  const diffAsStr = JSON.stringify(attribute.styleDiff);
@@ -9800,8 +9793,13 @@ class MutationBuffer {
9800
9793
  case "attributes": {
9801
9794
  const target = m.target;
9802
9795
  let attributeName = m.attributeName;
9803
- let value = target.getAttribute(attributeName);
9804
- if (value === null && m.oldValue === null) {
9796
+ let value = m.target.getAttribute(attributeName);
9797
+ const propValue = target[attributeName];
9798
+ const isPhantomAttributeMutation = value === null && !target.hasAttribute(attributeName) && m.oldValue !== null && (propValue === "" || propValue === null || typeof propValue === "undefined");
9799
+ if (isPhantomAttributeMutation && !isIncludeAttribute(attributeName, this.includeAttribute)) {
9800
+ return;
9801
+ }
9802
+ if (isExcludeAttribute(attributeName, this.excludeAttribute)) {
9805
9803
  return;
9806
9804
  }
9807
9805
  if (attributeName === "value") {
@@ -9839,14 +9837,21 @@ class MutationBuffer {
9839
9837
  if (attributeName === "type" && target.tagName === "INPUT" && (m.oldValue || "").toLowerCase() === "password") {
9840
9838
  target.setAttribute("data-rr-is-password", "true");
9841
9839
  }
9842
- if (!isIgnoreAttribute(target.tagName, attributeName) && // eslint-disable-next-line @typescript-eslint/no-unsafe-call
9843
- !shouldIgnoreAttribute(this.ignoreAttribute, attributeName)) {
9840
+ if (!ignoreAttribute(target.tagName, attributeName)) {
9844
9841
  item.attributes[attributeName] = transformAttribute(
9845
9842
  this.doc,
9846
9843
  toLowerCase(target.tagName),
9847
9844
  toLowerCase(attributeName),
9848
9845
  value
9849
9846
  );
9847
+ if (value === item.attributes[attributeName] && !isIncludeAttribute(attributeName, this.includeAttribute)) {
9848
+ delete item.attributes[attributeName];
9849
+ if (Object.keys(item.attributes).length === 0) {
9850
+ this.attributes = this.attributes.filter((a2) => a2 !== item);
9851
+ this.attributeMap.delete(m.target);
9852
+ }
9853
+ return;
9854
+ }
9850
9855
  if (attributeName === "style") {
9851
9856
  if (!this.unattachedDoc) {
9852
9857
  try {
@@ -9959,7 +9964,8 @@ class MutationBuffer {
9959
9964
  "blockSelector",
9960
9965
  "maskTextClass",
9961
9966
  "maskTextSelector",
9962
- "ignoreAttribute",
9967
+ "excludeAttribute",
9968
+ "includeAttribute",
9963
9969
  "inlineStylesheet",
9964
9970
  "maskInputOptions",
9965
9971
  "maskTextFn",
@@ -10098,60 +10104,6 @@ function initMutationObserver(options, rootEl) {
10098
10104
  });
10099
10105
  return observer;
10100
10106
  }
10101
- function initVisibilityObserver({
10102
- visibilityChangeCb,
10103
- doc,
10104
- mirror: mirror2,
10105
- sampling
10106
- }) {
10107
- if (!visibilityChangeCb) {
10108
- return () => {
10109
- };
10110
- }
10111
- const observedElements = /* @__PURE__ */ new WeakMap();
10112
- const debounceThreshold = typeof sampling.visibility === "number" ? sampling.visibility : 50;
10113
- const throttledCb = throttle(
10114
- callbackWrapper((entry) => {
10115
- const target = entry.target;
10116
- const id = mirror2.getId(target);
10117
- const isVisible = entry.isIntersecting || entry.intersectionRatio > 0;
10118
- if (id !== -1) {
10119
- visibilityChangeCb({
10120
- id,
10121
- isVisible,
10122
- visibilityRatio: entry.intersectionRatio
10123
- });
10124
- }
10125
- }),
10126
- debounceThreshold,
10127
- { leading: sampling.visibility !== false, trailing: true }
10128
- );
10129
- const observer = new IntersectionObserver((entries) => {
10130
- entries.forEach((entry) => {
10131
- const target = entry.target;
10132
- if (observedElements.has(target)) {
10133
- throttledCb(entry);
10134
- } else {
10135
- observedElements.set(target, true);
10136
- }
10137
- });
10138
- }, { root: null, threshold: [0.1, 0.9] });
10139
- doc.querySelectorAll("*").forEach((el) => observer.observe(el));
10140
- const mutationObserver = new MutationObserver((mutations) => {
10141
- mutations.forEach((mutation) => {
10142
- mutation.addedNodes.forEach((node2) => {
10143
- if (node2 instanceof Element) {
10144
- observer.observe(node2);
10145
- }
10146
- });
10147
- });
10148
- });
10149
- mutationObserver.observe(doc, { childList: true, subtree: true });
10150
- return () => {
10151
- observer.disconnect();
10152
- mutationObserver.disconnect();
10153
- };
10154
- }
10155
10107
  function initMoveObserver({
10156
10108
  mousemoveCb,
10157
10109
  sampling,
@@ -10431,6 +10383,20 @@ function initInputObserver({
10431
10383
  }
10432
10384
  function cbWithDedup(target, v2) {
10433
10385
  const lastInputValue = lastInputValueMap.get(target);
10386
+ const el = target;
10387
+ const hasPlaceholder = el.hasAttribute("placeholder");
10388
+ const isEmpty = el.value === "";
10389
+ const isDefaultEmpty = typeof el.defaultValue === "string" ? el.defaultValue === "" : true;
10390
+ const isNonUser = !v2.userTriggered;
10391
+ const isRepeatEmpty = !lastInputValue || lastInputValue.text === "";
10392
+ const isLikelyPhantom = hasPlaceholder && isEmpty && isDefaultEmpty && isRepeatEmpty && isNonUser && !v2.isChecked && el.type !== "hidden" && INPUT_TAGS.includes(el.tagName);
10393
+ const isRenderDrivenTextInput = el.tagName === "INPUT" && el.type === "text" && !v2.userTriggered && v2.text === el.defaultValue && !lastInputValue && el.hasAttribute("placeholder");
10394
+ const isValueFromDefault = !v2.userTriggered && el.value === el.defaultValue && !lastInputValue && el.hasAttribute("placeholder") && !v2.isChecked && el.type !== "hidden" && INPUT_TAGS.includes(el.tagName);
10395
+ const isPhantomCheckbox = el.type === "checkbox" && !v2.userTriggered && !v2.isChecked && !lastInputValue;
10396
+ const isPhantomRadio = el.type === "radio" && !v2.userTriggered && !v2.isChecked && !lastInputValue;
10397
+ if (isLikelyPhantom || isRenderDrivenTextInput || isValueFromDefault || isPhantomCheckbox || isPhantomRadio) {
10398
+ return;
10399
+ }
10434
10400
  if (!lastInputValue || lastInputValue.text !== v2.text || lastInputValue.isChecked !== v2.isChecked) {
10435
10401
  lastInputValueMap.set(target, v2);
10436
10402
  const id = mirror2.getId(target);
@@ -10968,7 +10934,6 @@ function initCustomElementObserver({
10968
10934
  function mergeHooks(o2, hooks) {
10969
10935
  const {
10970
10936
  mutationCb,
10971
- visibilityChangeCb,
10972
10937
  mousemoveCb,
10973
10938
  mouseInteractionCb,
10974
10939
  scrollCb,
@@ -10988,12 +10953,6 @@ function mergeHooks(o2, hooks) {
10988
10953
  }
10989
10954
  mutationCb(...p);
10990
10955
  };
10991
- o2.visibilityChangeCb = (...p) => {
10992
- if (hooks.visibilityChange) {
10993
- hooks.visibilityChange(...p);
10994
- }
10995
- visibilityChangeCb(...p);
10996
- };
10997
10956
  o2.mousemoveCb = (...p) => {
10998
10957
  if (hooks.mousemove) {
10999
10958
  hooks.mousemove(...p);
@@ -11086,7 +11045,6 @@ function initObservers(o2, hooks = {}) {
11086
11045
  });
11087
11046
  const inputHandler = initInputObserver(o2);
11088
11047
  const mediaInteractionHandler = initMediaInteractionObserver(o2);
11089
- const visibleHandler = initVisibilityObserver(o2);
11090
11048
  let styleSheetObserver = () => {
11091
11049
  };
11092
11050
  let adoptedStyleSheetObserver = () => {
@@ -11116,7 +11074,6 @@ function initObservers(o2, hooks = {}) {
11116
11074
  return callbackWrapper(() => {
11117
11075
  mutationBuffers.forEach((b) => b.reset());
11118
11076
  mutationObserver == null ? void 0 : mutationObserver.disconnect();
11119
- visibleHandler();
11120
11077
  mousemoveHandler();
11121
11078
  mouseInteractionHandler();
11122
11079
  scrollHandler();
@@ -12183,12 +12140,12 @@ function record(options = {}) {
12183
12140
  emit,
12184
12141
  checkoutEveryNms,
12185
12142
  checkoutEveryNth,
12186
- checkoutEveryEvc,
12187
12143
  blockClass = "rr-block",
12188
12144
  blockSelector = null,
12189
12145
  ignoreClass = "rr-ignore",
12190
12146
  ignoreSelector = null,
12191
- ignoreAttribute = "rr-ignore",
12147
+ excludeAttribute: _excludeAttribute,
12148
+ includeAttribute: _includeAttribute,
12192
12149
  maskTextClass = "rr-mask",
12193
12150
  maskTextSelector = null,
12194
12151
  inlineStylesheet = true,
@@ -12237,6 +12194,8 @@ function record(options = {}) {
12237
12194
  sampling.mousemove = mousemoveWait;
12238
12195
  }
12239
12196
  mirror.reset();
12197
+ const excludeAttribute = _excludeAttribute === void 0 ? /^$a/ : _excludeAttribute;
12198
+ const includeAttribute = _includeAttribute === void 0 ? /.+/i : _includeAttribute;
12240
12199
  const maskInputOptions = maskAllInputs === true ? {
12241
12200
  color: true,
12242
12201
  date: true,
@@ -12313,8 +12272,7 @@ function record(options = {}) {
12313
12272
  incrementalSnapshotCount++;
12314
12273
  const exceedCount = checkoutEveryNth && incrementalSnapshotCount >= checkoutEveryNth;
12315
12274
  const exceedTime = checkoutEveryNms && e2.timestamp - lastFullSnapshotEvent.timestamp > checkoutEveryNms;
12316
- const isVisibilityChanged = checkoutEveryEvc && e2.type === EventType.IncrementalSnapshot && e2.data.source === IncrementalSource.VisibilityChange;
12317
- if (exceedCount || exceedTime || isVisibilityChanged) {
12275
+ if (exceedCount || exceedTime) {
12318
12276
  takeFullSnapshot$1(true);
12319
12277
  }
12320
12278
  }
@@ -12387,7 +12345,8 @@ function record(options = {}) {
12387
12345
  blockSelector,
12388
12346
  maskTextClass,
12389
12347
  maskTextSelector,
12390
- ignoreAttribute,
12348
+ excludeAttribute,
12349
+ includeAttribute,
12391
12350
  inlineStylesheet,
12392
12351
  maskInputOptions,
12393
12352
  dataURLOptions,
@@ -12429,7 +12388,8 @@ function record(options = {}) {
12429
12388
  blockSelector,
12430
12389
  maskTextClass,
12431
12390
  maskTextSelector,
12432
- ignoreAttribute,
12391
+ excludeAttribute,
12392
+ includeAttribute,
12433
12393
  inlineStylesheet,
12434
12394
  maskAllInputs: maskInputOptions,
12435
12395
  maskTextFn,
@@ -12485,15 +12445,6 @@ function record(options = {}) {
12485
12445
  return callbackWrapper(initObservers)(
12486
12446
  {
12487
12447
  mutationCb: wrappedMutationEmit,
12488
- visibilityChangeCb: (v2) => {
12489
- wrappedEmit({
12490
- type: EventType.IncrementalSnapshot,
12491
- data: {
12492
- source: IncrementalSource.VisibilityChange,
12493
- ...v2
12494
- }
12495
- });
12496
- },
12497
12448
  mousemoveCb: (positions, source) => wrappedEmit({
12498
12449
  type: EventType.IncrementalSnapshot,
12499
12450
  data: {
@@ -12575,7 +12526,8 @@ function record(options = {}) {
12575
12526
  ignoreSelector,
12576
12527
  maskTextClass,
12577
12528
  maskTextSelector,
12578
- ignoreAttribute,
12529
+ excludeAttribute,
12530
+ includeAttribute,
12579
12531
  maskInputOptions,
12580
12532
  inlineStylesheet,
12581
12533
  sampling,