@appsurify-testmap/rrweb-all 2.1.0-alpha.3 → 2.1.0-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/rrweb-all.js CHANGED
@@ -890,32 +890,14 @@ function transformAttribute(doc, tagName, name, value) {
890
890
  }
891
891
  return value;
892
892
  }
893
- function isIgnoreAttribute(tagName, name, _value) {
893
+ function ignoreAttribute(tagName, name, _value) {
894
894
  return (tagName === "video" || tagName === "audio") && name === "autoplay";
895
895
  }
896
- function cleanAttributes(doc, element, ignoreAttribute) {
897
- const tagName = getValidTagName$1(element);
898
- const attributes = {};
899
- const len = element.attributes.length;
900
- for (let i2 = 0; i2 < len; i2++) {
901
- const attr = element.attributes[i2];
902
- const name = attr.name;
903
- const value = attr.value;
904
- const shouldIgnoreByName = typeof ignoreAttribute === "string" ? name === ignoreAttribute : ignoreAttribute.test(name);
905
- if (!shouldIgnoreByName && !isIgnoreAttribute(tagName, name)) {
906
- attributes[name] = transformAttribute(
907
- doc,
908
- tagName,
909
- toLowerCase(name),
910
- value
911
- );
912
- }
913
- }
914
- return attributes;
896
+ function isIncludeAttribute(name, include) {
897
+ return typeof include === "string" ? name.includes(include) : include.test(name);
915
898
  }
916
- function shouldIgnoreAttribute(ignore, name) {
917
- if (!ignore) return false;
918
- return typeof ignore === "string" ? name === ignore : ignore.test(name);
899
+ function isExcludeAttribute(name, exclude) {
900
+ return typeof exclude === "string" ? name.includes(exclude) : exclude.test(name);
919
901
  }
920
902
  function _isBlockedElement(element, blockClass, blockSelector) {
921
903
  try {
@@ -1046,7 +1028,8 @@ function serializeNode(n2, options) {
1046
1028
  mirror: mirror2,
1047
1029
  blockClass,
1048
1030
  blockSelector,
1049
- ignoreAttribute,
1031
+ excludeAttribute,
1032
+ includeAttribute,
1050
1033
  needsMask,
1051
1034
  inlineStylesheet,
1052
1035
  maskInputOptions = {},
@@ -1092,7 +1075,8 @@ function serializeNode(n2, options) {
1092
1075
  doc,
1093
1076
  blockClass,
1094
1077
  blockSelector,
1095
- ignoreAttribute,
1078
+ excludeAttribute,
1079
+ includeAttribute,
1096
1080
  inlineStylesheet,
1097
1081
  maskInputOptions,
1098
1082
  maskInputFn,
@@ -1170,7 +1154,8 @@ function serializeElementNode(n2, options) {
1170
1154
  doc,
1171
1155
  blockClass,
1172
1156
  blockSelector,
1173
- ignoreAttribute,
1157
+ excludeAttribute,
1158
+ includeAttribute,
1174
1159
  inlineStylesheet,
1175
1160
  maskInputOptions = {},
1176
1161
  maskInputFn,
@@ -1184,7 +1169,22 @@ function serializeElementNode(n2, options) {
1184
1169
  } = options;
1185
1170
  const needBlock = _isBlockedElement(n2, blockClass, blockSelector);
1186
1171
  const tagName = getValidTagName$1(n2);
1187
- let attributes = cleanAttributes(doc, n2, ignoreAttribute);
1172
+ let attributes = {};
1173
+ const len = n2.attributes.length;
1174
+ for (let i2 = 0; i2 < len; i2++) {
1175
+ const attr = n2.attributes[i2];
1176
+ if (isExcludeAttribute(attr.name, excludeAttribute) && !isIncludeAttribute(attr.name, includeAttribute)) {
1177
+ continue;
1178
+ }
1179
+ if (!ignoreAttribute(tagName, attr.name, attr.value)) {
1180
+ attributes[attr.name] = transformAttribute(
1181
+ doc,
1182
+ tagName,
1183
+ toLowerCase(attr.name),
1184
+ attr.value
1185
+ );
1186
+ }
1187
+ }
1188
1188
  if (tagName === "link" && inlineStylesheet) {
1189
1189
  const stylesheet = Array.from(doc.styleSheets).find((s2) => {
1190
1190
  return s2.href === n2.href;
@@ -1398,7 +1398,8 @@ function serializeNodeWithId(n2, options) {
1398
1398
  blockSelector,
1399
1399
  maskTextClass,
1400
1400
  maskTextSelector,
1401
- ignoreAttribute,
1401
+ excludeAttribute,
1402
+ includeAttribute,
1402
1403
  skipChild = false,
1403
1404
  inlineStylesheet = true,
1404
1405
  maskInputOptions = {},
@@ -1433,7 +1434,8 @@ function serializeNodeWithId(n2, options) {
1433
1434
  mirror: mirror2,
1434
1435
  blockClass,
1435
1436
  blockSelector,
1436
- ignoreAttribute,
1437
+ excludeAttribute,
1438
+ includeAttribute,
1437
1439
  needsMask,
1438
1440
  inlineStylesheet,
1439
1441
  maskInputOptions,
@@ -1486,7 +1488,8 @@ function serializeNodeWithId(n2, options) {
1486
1488
  needsMask,
1487
1489
  maskTextClass,
1488
1490
  maskTextSelector,
1489
- ignoreAttribute,
1491
+ excludeAttribute,
1492
+ includeAttribute,
1490
1493
  skipChild,
1491
1494
  inlineStylesheet,
1492
1495
  maskInputOptions,
@@ -1546,7 +1549,8 @@ function serializeNodeWithId(n2, options) {
1546
1549
  needsMask,
1547
1550
  maskTextClass,
1548
1551
  maskTextSelector,
1549
- ignoreAttribute,
1552
+ excludeAttribute,
1553
+ includeAttribute,
1550
1554
  skipChild: false,
1551
1555
  inlineStylesheet,
1552
1556
  maskInputOptions,
@@ -1588,7 +1592,8 @@ function serializeNodeWithId(n2, options) {
1588
1592
  needsMask,
1589
1593
  maskTextClass,
1590
1594
  maskTextSelector,
1591
- ignoreAttribute,
1595
+ excludeAttribute,
1596
+ includeAttribute,
1592
1597
  skipChild: false,
1593
1598
  inlineStylesheet,
1594
1599
  maskInputOptions,
@@ -1626,7 +1631,8 @@ function snapshot(n2, options) {
1626
1631
  blockSelector = null,
1627
1632
  maskTextClass = "rr-mask",
1628
1633
  maskTextSelector = null,
1629
- ignoreAttribute = "rr-ignore",
1634
+ excludeAttribute = /^$a/,
1635
+ includeAttribute = /.+/i,
1630
1636
  inlineStylesheet = true,
1631
1637
  inlineImages = false,
1632
1638
  recordCanvas = false,
@@ -1686,7 +1692,8 @@ function snapshot(n2, options) {
1686
1692
  blockSelector,
1687
1693
  maskTextClass,
1688
1694
  maskTextSelector,
1689
- ignoreAttribute,
1695
+ excludeAttribute,
1696
+ includeAttribute,
1690
1697
  skipChild: false,
1691
1698
  inlineStylesheet,
1692
1699
  maskInputOptions,
@@ -10922,7 +10929,7 @@ function hookSetter(target, key, d, isRevoked, win = window) {
10922
10929
  return () => hookSetter(target, key, original || {}, true);
10923
10930
  }
10924
10931
  function nowTimestamp() {
10925
- return performance.timeOrigin + performance.now();
10932
+ return Math.round(performance.timeOrigin + performance.now());
10926
10933
  }
10927
10934
  function getWindowScroll(win = window) {
10928
10935
  var _a2, _b2, _c, _d;
@@ -11239,7 +11246,6 @@ var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => {
11239
11246
  IncrementalSource2[IncrementalSource2["Selection"] = 14] = "Selection";
11240
11247
  IncrementalSource2[IncrementalSource2["AdoptedStyleSheet"] = 15] = "AdoptedStyleSheet";
11241
11248
  IncrementalSource2[IncrementalSource2["CustomElement"] = 16] = "CustomElement";
11242
- IncrementalSource2[IncrementalSource2["VisibilityChange"] = 17] = "VisibilityChange";
11243
11249
  return IncrementalSource2;
11244
11250
  })(IncrementalSource || {});
11245
11251
  var MouseInteractions = /* @__PURE__ */ ((MouseInteractions2) => {
@@ -11405,7 +11411,8 @@ class MutationBuffer {
11405
11411
  __publicField(this, "blockSelector");
11406
11412
  __publicField(this, "maskTextClass");
11407
11413
  __publicField(this, "maskTextSelector");
11408
- __publicField(this, "ignoreAttribute");
11414
+ __publicField(this, "excludeAttribute");
11415
+ __publicField(this, "includeAttribute");
11409
11416
  __publicField(this, "inlineStylesheet");
11410
11417
  __publicField(this, "maskInputOptions");
11411
11418
  __publicField(this, "maskTextFn");
@@ -11469,7 +11476,8 @@ class MutationBuffer {
11469
11476
  blockSelector: this.blockSelector,
11470
11477
  maskTextClass: this.maskTextClass,
11471
11478
  maskTextSelector: this.maskTextSelector,
11472
- ignoreAttribute: this.ignoreAttribute || "",
11479
+ excludeAttribute: this.excludeAttribute,
11480
+ includeAttribute: this.includeAttribute,
11473
11481
  skipChild: true,
11474
11482
  newlyAddedElement: true,
11475
11483
  inlineStylesheet: this.inlineStylesheet,
@@ -11589,21 +11597,6 @@ class MutationBuffer {
11589
11597
  };
11590
11598
  }).filter((text) => !addedIds.has(text.id)).filter((text) => this.mirror.has(text.id)),
11591
11599
  attributes: this.attributes.map((attribute) => {
11592
- const element = attribute.node;
11593
- const filtered = {};
11594
- for (const [name, value] of Object.entries(attribute.attributes)) {
11595
- const isIgnored2 = shouldIgnoreAttribute(this.ignoreAttribute, name);
11596
- const existedBefore = element.hasAttribute(name);
11597
- const keep = value !== null && !isIgnored2 || value === null && (!isIgnored2 || attribute.attributes[name] !== null || existedBefore);
11598
- if (keep) {
11599
- filtered[name] = value;
11600
- }
11601
- }
11602
- return {
11603
- ...attribute,
11604
- attributes: filtered
11605
- };
11606
- }).filter((attribute) => Object.keys(attribute.attributes).length > 0).map((attribute) => {
11607
11600
  const { attributes } = attribute;
11608
11601
  if (typeof attributes.style === "string") {
11609
11602
  const diffAsStr = JSON.stringify(attribute.styleDiff);
@@ -11685,8 +11678,13 @@ class MutationBuffer {
11685
11678
  case "attributes": {
11686
11679
  const target = m.target;
11687
11680
  let attributeName = m.attributeName;
11688
- let value = target.getAttribute(attributeName);
11689
- if (value === null && m.oldValue === null) {
11681
+ let value = m.target.getAttribute(attributeName);
11682
+ const propValue = target[attributeName];
11683
+ const isPhantomAttributeMutation = value === null && !target.hasAttribute(attributeName) && m.oldValue !== null && (propValue === "" || propValue === null || typeof propValue === "undefined");
11684
+ if (isPhantomAttributeMutation && !isIncludeAttribute(attributeName, this.includeAttribute)) {
11685
+ return;
11686
+ }
11687
+ if (isExcludeAttribute(attributeName, this.excludeAttribute)) {
11690
11688
  return;
11691
11689
  }
11692
11690
  if (attributeName === "value") {
@@ -11724,14 +11722,21 @@ class MutationBuffer {
11724
11722
  if (attributeName === "type" && target.tagName === "INPUT" && (m.oldValue || "").toLowerCase() === "password") {
11725
11723
  target.setAttribute("data-rr-is-password", "true");
11726
11724
  }
11727
- if (!isIgnoreAttribute(target.tagName, attributeName) && // eslint-disable-next-line @typescript-eslint/no-unsafe-call
11728
- !shouldIgnoreAttribute(this.ignoreAttribute, attributeName)) {
11725
+ if (!ignoreAttribute(target.tagName, attributeName)) {
11729
11726
  item.attributes[attributeName] = transformAttribute(
11730
11727
  this.doc,
11731
11728
  toLowerCase(target.tagName),
11732
11729
  toLowerCase(attributeName),
11733
11730
  value
11734
11731
  );
11732
+ if (value === item.attributes[attributeName] && !isIncludeAttribute(attributeName, this.includeAttribute)) {
11733
+ delete item.attributes[attributeName];
11734
+ if (Object.keys(item.attributes).length === 0) {
11735
+ this.attributes = this.attributes.filter((a2) => a2 !== item);
11736
+ this.attributeMap.delete(m.target);
11737
+ }
11738
+ return;
11739
+ }
11735
11740
  if (attributeName === "style") {
11736
11741
  if (!this.unattachedDoc) {
11737
11742
  try {
@@ -11844,7 +11849,8 @@ class MutationBuffer {
11844
11849
  "blockSelector",
11845
11850
  "maskTextClass",
11846
11851
  "maskTextSelector",
11847
- "ignoreAttribute",
11852
+ "excludeAttribute",
11853
+ "includeAttribute",
11848
11854
  "inlineStylesheet",
11849
11855
  "maskInputOptions",
11850
11856
  "maskTextFn",
@@ -11983,60 +11989,6 @@ function initMutationObserver(options, rootEl) {
11983
11989
  });
11984
11990
  return observer;
11985
11991
  }
11986
- function initVisibilityObserver({
11987
- visibilityChangeCb,
11988
- doc,
11989
- mirror: mirror2,
11990
- sampling
11991
- }) {
11992
- if (!visibilityChangeCb) {
11993
- return () => {
11994
- };
11995
- }
11996
- const observedElements = /* @__PURE__ */ new WeakMap();
11997
- const debounceThreshold = typeof sampling.visibility === "number" ? sampling.visibility : 50;
11998
- const throttledCb = throttle(
11999
- callbackWrapper((entry) => {
12000
- const target = entry.target;
12001
- const id = mirror2.getId(target);
12002
- const isVisible = entry.isIntersecting || entry.intersectionRatio > 0;
12003
- if (id !== -1) {
12004
- visibilityChangeCb({
12005
- id,
12006
- isVisible,
12007
- visibilityRatio: entry.intersectionRatio
12008
- });
12009
- }
12010
- }),
12011
- debounceThreshold,
12012
- { leading: sampling.visibility !== false, trailing: true }
12013
- );
12014
- const observer = new IntersectionObserver((entries) => {
12015
- entries.forEach((entry) => {
12016
- const target = entry.target;
12017
- if (observedElements.has(target)) {
12018
- throttledCb(entry);
12019
- } else {
12020
- observedElements.set(target, true);
12021
- }
12022
- });
12023
- }, { root: null, threshold: [0.1, 0.9] });
12024
- doc.querySelectorAll("*").forEach((el) => observer.observe(el));
12025
- const mutationObserver = new MutationObserver((mutations) => {
12026
- mutations.forEach((mutation) => {
12027
- mutation.addedNodes.forEach((node2) => {
12028
- if (node2 instanceof Element) {
12029
- observer.observe(node2);
12030
- }
12031
- });
12032
- });
12033
- });
12034
- mutationObserver.observe(doc, { childList: true, subtree: true });
12035
- return () => {
12036
- observer.disconnect();
12037
- mutationObserver.disconnect();
12038
- };
12039
- }
12040
11992
  function initMoveObserver({
12041
11993
  mousemoveCb,
12042
11994
  sampling,
@@ -12316,6 +12268,20 @@ function initInputObserver({
12316
12268
  }
12317
12269
  function cbWithDedup(target, v2) {
12318
12270
  const lastInputValue = lastInputValueMap.get(target);
12271
+ const el = target;
12272
+ const hasPlaceholder = el.hasAttribute("placeholder");
12273
+ const isEmpty = el.value === "";
12274
+ const isDefaultEmpty = typeof el.defaultValue === "string" ? el.defaultValue === "" : true;
12275
+ const isNonUser = !v2.userTriggered;
12276
+ const isRepeatEmpty = !lastInputValue || lastInputValue.text === "";
12277
+ const isLikelyPhantom = hasPlaceholder && isEmpty && isDefaultEmpty && isRepeatEmpty && isNonUser && !v2.isChecked && el.type !== "hidden" && INPUT_TAGS.includes(el.tagName);
12278
+ const isRenderDrivenTextInput = el.tagName === "INPUT" && el.type === "text" && !v2.userTriggered && v2.text === el.defaultValue && !lastInputValue && el.hasAttribute("placeholder");
12279
+ const isValueFromDefault = !v2.userTriggered && el.value === el.defaultValue && !lastInputValue && el.hasAttribute("placeholder") && !v2.isChecked && el.type !== "hidden" && INPUT_TAGS.includes(el.tagName);
12280
+ const isPhantomCheckbox = el.type === "checkbox" && !v2.userTriggered && !v2.isChecked && !lastInputValue;
12281
+ const isPhantomRadio = el.type === "radio" && !v2.userTriggered && !v2.isChecked && !lastInputValue;
12282
+ if (isLikelyPhantom || isRenderDrivenTextInput || isValueFromDefault || isPhantomCheckbox || isPhantomRadio) {
12283
+ return;
12284
+ }
12319
12285
  if (!lastInputValue || lastInputValue.text !== v2.text || lastInputValue.isChecked !== v2.isChecked) {
12320
12286
  lastInputValueMap.set(target, v2);
12321
12287
  const id = mirror2.getId(target);
@@ -12853,7 +12819,6 @@ function initCustomElementObserver({
12853
12819
  function mergeHooks(o2, hooks) {
12854
12820
  const {
12855
12821
  mutationCb,
12856
- visibilityChangeCb,
12857
12822
  mousemoveCb,
12858
12823
  mouseInteractionCb,
12859
12824
  scrollCb,
@@ -12873,12 +12838,6 @@ function mergeHooks(o2, hooks) {
12873
12838
  }
12874
12839
  mutationCb(...p);
12875
12840
  };
12876
- o2.visibilityChangeCb = (...p) => {
12877
- if (hooks.visibilityChange) {
12878
- hooks.visibilityChange(...p);
12879
- }
12880
- visibilityChangeCb(...p);
12881
- };
12882
12841
  o2.mousemoveCb = (...p) => {
12883
12842
  if (hooks.mousemove) {
12884
12843
  hooks.mousemove(...p);
@@ -12971,7 +12930,6 @@ function initObservers(o2, hooks = {}) {
12971
12930
  });
12972
12931
  const inputHandler = initInputObserver(o2);
12973
12932
  const mediaInteractionHandler = initMediaInteractionObserver(o2);
12974
- const visibleHandler = initVisibilityObserver(o2);
12975
12933
  let styleSheetObserver = () => {
12976
12934
  };
12977
12935
  let adoptedStyleSheetObserver = () => {
@@ -13001,7 +12959,6 @@ function initObservers(o2, hooks = {}) {
13001
12959
  return callbackWrapper(() => {
13002
12960
  mutationBuffers.forEach((b) => b.reset());
13003
12961
  mutationObserver == null ? void 0 : mutationObserver.disconnect();
13004
- visibleHandler();
13005
12962
  mousemoveHandler();
13006
12963
  mouseInteractionHandler();
13007
12964
  scrollHandler();
@@ -14072,6 +14029,7 @@ let wrappedEmit;
14072
14029
  let takeFullSnapshot$1;
14073
14030
  let canvasManager;
14074
14031
  let recording = false;
14032
+ const preRecordingCustomEvents = [];
14075
14033
  try {
14076
14034
  if (Array.from([1], (x2) => x2 * 2)[0] !== 2) {
14077
14035
  const cleanFrame = document.createElement("iframe");
@@ -14088,12 +14046,12 @@ function record(options = {}) {
14088
14046
  emit,
14089
14047
  checkoutEveryNms,
14090
14048
  checkoutEveryNth,
14091
- checkoutEveryEvc,
14092
14049
  blockClass = "rr-block",
14093
14050
  blockSelector = null,
14094
14051
  ignoreClass = "rr-ignore",
14095
14052
  ignoreSelector = null,
14096
- ignoreAttribute = "rr-ignore",
14053
+ excludeAttribute: _excludeAttribute,
14054
+ includeAttribute: _includeAttribute,
14097
14055
  maskTextClass = "rr-mask",
14098
14056
  maskTextSelector = null,
14099
14057
  inlineStylesheet = true,
@@ -14111,6 +14069,7 @@ function record(options = {}) {
14111
14069
  recordCanvas = false,
14112
14070
  recordCrossOriginIframes = false,
14113
14071
  recordAfter = options.recordAfter === "DOMContentLoaded" ? options.recordAfter : "load",
14072
+ flushCustomQueue = options.flushCustomQueue !== void 0 ? options.flushCustomQueue : "after",
14114
14073
  userTriggeredOnInput = false,
14115
14074
  collectFonts = false,
14116
14075
  inlineImages = false,
@@ -14142,6 +14101,8 @@ function record(options = {}) {
14142
14101
  sampling.mousemove = mousemoveWait;
14143
14102
  }
14144
14103
  mirror.reset();
14104
+ const excludeAttribute = _excludeAttribute === void 0 ? /^$a/ : _excludeAttribute;
14105
+ const includeAttribute = _includeAttribute === void 0 ? /.+/i : _includeAttribute;
14145
14106
  const maskInputOptions = maskAllInputs === true ? {
14146
14107
  color: true,
14147
14108
  date: true,
@@ -14218,8 +14179,7 @@ function record(options = {}) {
14218
14179
  incrementalSnapshotCount++;
14219
14180
  const exceedCount = checkoutEveryNth && incrementalSnapshotCount >= checkoutEveryNth;
14220
14181
  const exceedTime = checkoutEveryNms && e2.timestamp - lastFullSnapshotEvent.timestamp > checkoutEveryNms;
14221
- const isVisibilityChanged = checkoutEveryEvc && e2.type === EventType.IncrementalSnapshot && e2.data.source === IncrementalSource.VisibilityChange;
14222
- if (exceedCount || exceedTime || isVisibilityChanged) {
14182
+ if (exceedCount || exceedTime) {
14223
14183
  takeFullSnapshot$1(true);
14224
14184
  }
14225
14185
  }
@@ -14292,7 +14252,8 @@ function record(options = {}) {
14292
14252
  blockSelector,
14293
14253
  maskTextClass,
14294
14254
  maskTextSelector,
14295
- ignoreAttribute,
14255
+ excludeAttribute,
14256
+ includeAttribute,
14296
14257
  inlineStylesheet,
14297
14258
  maskInputOptions,
14298
14259
  dataURLOptions,
@@ -14334,7 +14295,8 @@ function record(options = {}) {
14334
14295
  blockSelector,
14335
14296
  maskTextClass,
14336
14297
  maskTextSelector,
14337
- ignoreAttribute,
14298
+ excludeAttribute,
14299
+ includeAttribute,
14338
14300
  inlineStylesheet,
14339
14301
  maskAllInputs: maskInputOptions,
14340
14302
  maskTextFn,
@@ -14390,15 +14352,6 @@ function record(options = {}) {
14390
14352
  return callbackWrapper(initObservers)(
14391
14353
  {
14392
14354
  mutationCb: wrappedMutationEmit,
14393
- visibilityChangeCb: (v2) => {
14394
- wrappedEmit({
14395
- type: EventType.IncrementalSnapshot,
14396
- data: {
14397
- source: IncrementalSource.VisibilityChange,
14398
- ...v2
14399
- }
14400
- });
14401
- },
14402
14355
  mousemoveCb: (positions, source) => wrappedEmit({
14403
14356
  type: EventType.IncrementalSnapshot,
14404
14357
  data: {
@@ -14480,7 +14433,8 @@ function record(options = {}) {
14480
14433
  ignoreSelector,
14481
14434
  maskTextClass,
14482
14435
  maskTextSelector,
14483
- ignoreAttribute,
14436
+ excludeAttribute,
14437
+ includeAttribute,
14484
14438
  maskInputOptions,
14485
14439
  inlineStylesheet,
14486
14440
  sampling,
@@ -14526,9 +14480,15 @@ function record(options = {}) {
14526
14480
  }
14527
14481
  });
14528
14482
  const init = () => {
14483
+ if (flushCustomQueue === "before") {
14484
+ flushPreRecordingEvents();
14485
+ }
14529
14486
  takeFullSnapshot$1();
14530
14487
  handlers.push(observe(document));
14531
14488
  recording = true;
14489
+ if (flushCustomQueue === "after") {
14490
+ flushPreRecordingEvents();
14491
+ }
14532
14492
  };
14533
14493
  if (document.readyState === "interactive" || document.readyState === "complete") {
14534
14494
  init();
@@ -14557,6 +14517,7 @@ function record(options = {}) {
14557
14517
  );
14558
14518
  }
14559
14519
  return () => {
14520
+ flushPreRecordingEvents();
14560
14521
  handlers.forEach((h) => h());
14561
14522
  processedNodeManager.destroy();
14562
14523
  recording = false;
@@ -14566,17 +14527,26 @@ function record(options = {}) {
14566
14527
  console.warn(error);
14567
14528
  }
14568
14529
  }
14569
- record.addCustomEvent = (tag, payload) => {
14570
- if (!recording) {
14571
- throw new Error("please add custom event after start recording");
14530
+ function flushPreRecordingEvents() {
14531
+ for (const e2 of preRecordingCustomEvents) {
14532
+ wrappedEmit(e2);
14572
14533
  }
14573
- wrappedEmit({
14534
+ preRecordingCustomEvents.length = 0;
14535
+ }
14536
+ record.addCustomEvent = (tag, payload) => {
14537
+ const customEvent = {
14574
14538
  type: EventType.Custom,
14575
14539
  data: {
14576
14540
  tag,
14577
14541
  payload
14578
14542
  }
14579
- });
14543
+ };
14544
+ if (!recording) {
14545
+ console.warn(`[rrweb] CustomEvent buffered before recording start: ${tag}`);
14546
+ preRecordingCustomEvents.push(customEvent);
14547
+ return;
14548
+ }
14549
+ wrappedEmit(customEvent);
14580
14550
  };
14581
14551
  record.freezePage = () => {
14582
14552
  mutationBuffers.forEach((buf) => buf.freeze());