@screeb/rrweb 1.0.8 → 1.0.11

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.
@@ -188,6 +188,32 @@ function querySelectorAll$1(n2, selectors) {
188
188
  function mutationObserverCtor$1() {
189
189
  return getUntaintedPrototype$1("MutationObserver").constructor;
190
190
  }
191
+ function patch$1(source, name, replacement) {
192
+ try {
193
+ if (!(name in source)) {
194
+ return () => {
195
+ };
196
+ }
197
+ const original = source[name];
198
+ const wrapped = replacement(original);
199
+ if (typeof wrapped === "function") {
200
+ wrapped.prototype = wrapped.prototype || {};
201
+ Object.defineProperties(wrapped, {
202
+ __rrweb_original__: {
203
+ enumerable: false,
204
+ value: original
205
+ }
206
+ });
207
+ }
208
+ source[name] = wrapped;
209
+ return () => {
210
+ source[name] = original;
211
+ };
212
+ } catch (e2) {
213
+ return () => {
214
+ };
215
+ }
216
+ }
191
217
  const index$1 = {
192
218
  childNodes: childNodes$1,
193
219
  parentNode: parentNode$1,
@@ -200,7 +226,8 @@ const index$1 = {
200
226
  shadowRoot: shadowRoot$1,
201
227
  querySelector: querySelector$1,
202
228
  querySelectorAll: querySelectorAll$1,
203
- mutationObserver: mutationObserverCtor$1
229
+ mutationObserver: mutationObserverCtor$1,
230
+ patch: patch$1
204
231
  };
205
232
  function isElement(n2) {
206
233
  return n2.nodeType === n2.ELEMENT_NODE;
@@ -482,19 +509,27 @@ function absolutifyURLs(cssText, href) {
482
509
  }
483
510
  );
484
511
  }
485
- function normalizeCssString(cssText) {
486
- return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
512
+ function normalizeCssString(cssText, _testNoPxNorm = false) {
513
+ if (_testNoPxNorm) {
514
+ return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
515
+ } else {
516
+ return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "").replace(/0px/g, "0");
517
+ }
487
518
  }
488
- function splitCssText(cssText, style) {
519
+ function splitCssText(cssText, style, _testNoPxNorm = false) {
489
520
  const childNodes2 = Array.from(style.childNodes);
490
521
  const splits = [];
491
- let iterLimit = 0;
522
+ let iterCount = 0;
492
523
  if (childNodes2.length > 1 && cssText && typeof cssText === "string") {
493
- let cssTextNorm = normalizeCssString(cssText);
524
+ let cssTextNorm = normalizeCssString(cssText, _testNoPxNorm);
494
525
  const normFactor = cssTextNorm.length / cssText.length;
495
526
  for (let i2 = 1; i2 < childNodes2.length; i2++) {
496
527
  if (childNodes2[i2].textContent && typeof childNodes2[i2].textContent === "string") {
497
- const textContentNorm = normalizeCssString(childNodes2[i2].textContent);
528
+ const textContentNorm = normalizeCssString(
529
+ childNodes2[i2].textContent,
530
+ _testNoPxNorm
531
+ );
532
+ const jLimit = 100;
498
533
  let j = 3;
499
534
  for (; j < textContentNorm.length; j++) {
500
535
  if (
@@ -507,23 +542,49 @@ function splitCssText(cssText, style) {
507
542
  break;
508
543
  }
509
544
  for (; j < textContentNorm.length; j++) {
510
- const bit = textContentNorm.substring(0, j);
511
- const bits = cssTextNorm.split(bit);
545
+ let startSubstring = textContentNorm.substring(0, j);
546
+ let cssNormSplits = cssTextNorm.split(startSubstring);
512
547
  let splitNorm = -1;
513
- if (bits.length === 2) {
514
- splitNorm = cssTextNorm.indexOf(bit);
515
- } else if (bits.length > 2 && bits[0] === "" && childNodes2[i2 - 1].textContent !== "") {
516
- splitNorm = cssTextNorm.indexOf(bit, 1);
548
+ if (cssNormSplits.length === 2) {
549
+ splitNorm = cssNormSplits[0].length;
550
+ } else if (cssNormSplits.length > 2 && cssNormSplits[0] === "" && childNodes2[i2 - 1].textContent !== "") {
551
+ splitNorm = cssTextNorm.indexOf(startSubstring, 1);
552
+ } else if (cssNormSplits.length === 1) {
553
+ startSubstring = startSubstring.substring(
554
+ 0,
555
+ startSubstring.length - 1
556
+ );
557
+ cssNormSplits = cssTextNorm.split(startSubstring);
558
+ if (cssNormSplits.length <= 1) {
559
+ splits.push(cssText);
560
+ return splits;
561
+ }
562
+ j = jLimit + 1;
563
+ } else if (j === textContentNorm.length - 1) {
564
+ splitNorm = cssTextNorm.indexOf(startSubstring);
565
+ }
566
+ if (cssNormSplits.length >= 2 && j > jLimit) {
567
+ const prevTextContent = childNodes2[i2 - 1].textContent;
568
+ if (prevTextContent && typeof prevTextContent === "string") {
569
+ const prevMinLength = normalizeCssString(prevTextContent).length;
570
+ splitNorm = cssTextNorm.indexOf(startSubstring, prevMinLength);
571
+ }
572
+ if (splitNorm === -1) {
573
+ splitNorm = cssNormSplits[0].length;
574
+ }
517
575
  }
518
576
  if (splitNorm !== -1) {
519
577
  let k = Math.floor(splitNorm / normFactor);
520
578
  for (; k > 0 && k < cssText.length; ) {
521
- iterLimit += 1;
522
- if (iterLimit > 50 * childNodes2.length) {
579
+ iterCount += 1;
580
+ if (iterCount > 50 * childNodes2.length) {
523
581
  splits.push(cssText);
524
582
  return splits;
525
583
  }
526
- const normPart = normalizeCssString(cssText.substring(0, k));
584
+ const normPart = normalizeCssString(
585
+ cssText.substring(0, k),
586
+ _testNoPxNorm
587
+ );
527
588
  if (normPart.length === splitNorm) {
528
589
  splits.push(cssText.substring(0, k));
529
590
  cssText = cssText.substring(k);
@@ -5097,11 +5158,16 @@ function getTagName(n2) {
5097
5158
  function adaptCssForReplay(cssText, cache) {
5098
5159
  const cachedStyle = cache == null ? void 0 : cache.stylesWithHoverClass.get(cssText);
5099
5160
  if (cachedStyle) return cachedStyle;
5100
- const ast = postcss$1$1([
5101
- mediaSelectorPlugin,
5102
- pseudoClassPlugin
5103
- ]).process(cssText);
5104
- const result2 = ast.css;
5161
+ let result2 = cssText;
5162
+ try {
5163
+ const ast = postcss$1$1([
5164
+ mediaSelectorPlugin,
5165
+ pseudoClassPlugin
5166
+ ]).process(cssText);
5167
+ result2 = ast.css;
5168
+ } catch (error) {
5169
+ console.warn("Failed to adapt css for replay", error);
5170
+ }
5105
5171
  cache == null ? void 0 : cache.stylesWithHoverClass.set(cssText, result2);
5106
5172
  return result2;
5107
5173
  }
@@ -5122,11 +5188,39 @@ function applyCssSplits(n2, cssText, hackCss, cache) {
5122
5188
  while (cssTextSplits.length > 1 && cssTextSplits.length > childTextNodes.length) {
5123
5189
  cssTextSplits.splice(-2, 2, cssTextSplits.slice(-2).join(""));
5124
5190
  }
5191
+ let adaptedCss = "";
5192
+ if (hackCss) {
5193
+ adaptedCss = adaptCssForReplay(cssTextSplits.join(""), cache);
5194
+ }
5195
+ let startIndex = 0;
5125
5196
  for (let i2 = 0; i2 < childTextNodes.length; i2++) {
5197
+ if (i2 === cssTextSplits.length) {
5198
+ break;
5199
+ }
5126
5200
  const childTextNode = childTextNodes[i2];
5127
- const cssTextSection = cssTextSplits[i2];
5128
- if (childTextNode && cssTextSection) {
5129
- childTextNode.textContent = hackCss ? adaptCssForReplay(cssTextSection, cache) : cssTextSection;
5201
+ if (!hackCss) {
5202
+ childTextNode.textContent = cssTextSplits[i2];
5203
+ } else if (i2 < cssTextSplits.length - 1) {
5204
+ let endIndex = startIndex;
5205
+ let endSearch = cssTextSplits[i2 + 1].length;
5206
+ endSearch = Math.min(endSearch, 30);
5207
+ let found = false;
5208
+ for (; endSearch > 2; endSearch--) {
5209
+ const searchBit = cssTextSplits[i2 + 1].substring(0, endSearch);
5210
+ const searchIndex = adaptedCss.substring(startIndex).indexOf(searchBit);
5211
+ found = searchIndex !== -1;
5212
+ if (found) {
5213
+ endIndex += searchIndex;
5214
+ break;
5215
+ }
5216
+ }
5217
+ if (!found) {
5218
+ endIndex += cssTextSplits[i2].length;
5219
+ }
5220
+ childTextNode.textContent = adaptedCss.substring(startIndex, endIndex);
5221
+ startIndex = endIndex;
5222
+ } else {
5223
+ childTextNode.textContent = adaptedCss.substring(startIndex);
5130
5224
  }
5131
5225
  }
5132
5226
  }
@@ -10449,6 +10543,32 @@ function querySelectorAll(n2, selectors) {
10449
10543
  function mutationObserverCtor() {
10450
10544
  return getUntaintedPrototype("MutationObserver").constructor;
10451
10545
  }
10546
+ function patch(source, name, replacement) {
10547
+ try {
10548
+ if (!(name in source)) {
10549
+ return () => {
10550
+ };
10551
+ }
10552
+ const original = source[name];
10553
+ const wrapped = replacement(original);
10554
+ if (typeof wrapped === "function") {
10555
+ wrapped.prototype = wrapped.prototype || {};
10556
+ Object.defineProperties(wrapped, {
10557
+ __rrweb_original__: {
10558
+ enumerable: false,
10559
+ value: original
10560
+ }
10561
+ });
10562
+ }
10563
+ source[name] = wrapped;
10564
+ return () => {
10565
+ source[name] = original;
10566
+ };
10567
+ } catch (e2) {
10568
+ return () => {
10569
+ };
10570
+ }
10571
+ }
10452
10572
  const index = {
10453
10573
  childNodes,
10454
10574
  parentNode,
@@ -10461,7 +10581,8 @@ const index = {
10461
10581
  shadowRoot,
10462
10582
  querySelector,
10463
10583
  querySelectorAll,
10464
- mutationObserver: mutationObserverCtor
10584
+ mutationObserver: mutationObserverCtor,
10585
+ patch
10465
10586
  };
10466
10587
  function on(type, fn, target = document) {
10467
10588
  const options = { capture: true, passive: true };
@@ -10544,32 +10665,6 @@ function hookSetter(target, key, d, isRevoked, win = window) {
10544
10665
  );
10545
10666
  return () => hookSetter(target, key, original || {}, true);
10546
10667
  }
10547
- function patch(source, name, replacement) {
10548
- try {
10549
- if (!(name in source)) {
10550
- return () => {
10551
- };
10552
- }
10553
- const original = source[name];
10554
- const wrapped = replacement(original);
10555
- if (typeof wrapped === "function") {
10556
- wrapped.prototype = wrapped.prototype || {};
10557
- Object.defineProperties(wrapped, {
10558
- __rrweb_original__: {
10559
- enumerable: false,
10560
- value: original
10561
- }
10562
- });
10563
- }
10564
- source[name] = wrapped;
10565
- return () => {
10566
- source[name] = original;
10567
- };
10568
- } catch (e2) {
10569
- return () => {
10570
- };
10571
- }
10572
- }
10573
10668
  let nowTimestamp = Date.now;
10574
10669
  if (!/* @__PURE__ */ /[1-9][0-9]{12}/.test(Date.now().toString())) {
10575
10670
  nowTimestamp = () => (/* @__PURE__ */ new Date()).getTime();
@@ -10583,10 +10678,12 @@ function getWindowScroll(win) {
10583
10678
  };
10584
10679
  }
10585
10680
  function getWindowHeight(win) {
10586
- return win.innerHeight || win.document.documentElement && win.document.documentElement.clientHeight || win.document.body && win.document.body.clientHeight;
10681
+ var _a2, _b;
10682
+ return win.innerHeight || ((_a2 = win.document.documentElement) == null ? void 0 : _a2.clientHeight) || ((_b = win.document.body) == null ? void 0 : _b.clientHeight);
10587
10683
  }
10588
10684
  function getWindowWidth(win) {
10589
- return win.innerWidth || win.document.documentElement && win.document.documentElement.clientWidth || win.document.body && win.document.body.clientWidth;
10685
+ var _a2, _b;
10686
+ return win.innerWidth || ((_a2 = win.document.documentElement) == null ? void 0 : _a2.clientWidth) || ((_b = win.document.body) == null ? void 0 : _b.clientWidth);
10590
10687
  }
10591
10688
  function closestElementOfNode(node2) {
10592
10689
  if (!node2) {
@@ -10856,7 +10953,6 @@ const utils = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
10856
10953
  return nowTimestamp;
10857
10954
  },
10858
10955
  on,
10859
- patch,
10860
10956
  polyfill: polyfill$1,
10861
10957
  queueToResolveTrees,
10862
10958
  shadowHostInDom,
@@ -11282,10 +11378,18 @@ class MutationBuffer {
11282
11378
  this.attributes.push(item);
11283
11379
  this.attributeMap.set(textarea, item);
11284
11380
  }
11285
- item.attributes.value = Array.from(
11381
+ const value = Array.from(
11286
11382
  index.childNodes(textarea),
11287
11383
  (cn) => index.textContent(cn) || ""
11288
11384
  ).join("");
11385
+ item.attributes.value = maskInputValue({
11386
+ element: textarea,
11387
+ maskInputOptions: this.maskInputOptions,
11388
+ tagName: textarea.tagName,
11389
+ type: getInputType(textarea),
11390
+ value,
11391
+ maskInputFn: this.maskInputFn
11392
+ });
11289
11393
  });
11290
11394
  __publicField(this, "processMutation", (m) => {
11291
11395
  if (isIgnored(m.target, this.mirror, this.slimDOMOptions)) {
@@ -12894,7 +12998,7 @@ class ShadowDomManager {
12894
12998
  }
12895
12999
  init() {
12896
13000
  this.reset();
12897
- this.patchAttachShadow(Element, document);
13001
+ this.patchAttachShadow(Element, this.bypassOptions.win.document);
12898
13002
  }
12899
13003
  addShadowRoot(shadowRoot2, doc) {
12900
13004
  if (!isNativeShadowDom(shadowRoot2)) return;
@@ -14070,7 +14174,7 @@ function record(options = {}) {
14070
14174
  data: {}
14071
14175
  });
14072
14176
  if (recordAfter === "DOMContentLoaded") init();
14073
- })
14177
+ }, win.document)
14074
14178
  );
14075
14179
  handlers.push(
14076
14180
  on(
@@ -14698,11 +14802,19 @@ function createPlayerService(context, { getCastFn, applyEventsSynchronously, emi
14698
14802
  emitter.emit(ReplayerEvents.PlayBack);
14699
14803
  }
14700
14804
  const syncEvents = new Array();
14805
+ let renderedFullSnapshot = false;
14701
14806
  for (const event of neededEvents) {
14807
+ const isFullSnapshot = event.type === EventType.FullSnapshot;
14702
14808
  if (lastPlayedTimestamp && lastPlayedTimestamp < baselineTime && (event.timestamp <= lastPlayedTimestamp || event === lastPlayedEvent)) {
14809
+ if (isFullSnapshot) {
14810
+ renderedFullSnapshot = true;
14811
+ }
14703
14812
  continue;
14704
14813
  }
14705
- if (event.timestamp < baselineTime) {
14814
+ if (event.timestamp <= baselineTime || isFullSnapshot && !renderedFullSnapshot) {
14815
+ if (isFullSnapshot) {
14816
+ renderedFullSnapshot = true;
14817
+ }
14706
14818
  syncEvents.push(event);
14707
14819
  } else {
14708
14820
  const castFn = getCastFn(event, false);
@@ -15410,21 +15522,21 @@ class Replayer {
15410
15522
  if (plugin3.handler) plugin3.handler(event, isSync, { replayer: this });
15411
15523
  }
15412
15524
  this.service.send({ type: "CAST_EVENT", payload: { event } });
15413
- const last_index = this.service.state.context.events.length - 1;
15414
- if (!this.config.liveMode && event === this.service.state.context.events[last_index]) {
15525
+ const lastIndex = this.service.state.context.events.length - 1;
15526
+ if (!this.config.liveMode && event === this.service.state.context.events[lastIndex]) {
15415
15527
  const finish = () => {
15416
- if (last_index < this.service.state.context.events.length - 1) {
15528
+ if (lastIndex < this.service.state.context.events.length - 1) {
15417
15529
  return;
15418
15530
  }
15419
15531
  this.backToNormal();
15420
15532
  this.service.send("END");
15421
15533
  this.emitter.emit(ReplayerEvents.Finish);
15422
15534
  };
15423
- let finish_buffer = 50;
15535
+ let finishBuffer = 50;
15424
15536
  if (event.type === EventType.IncrementalSnapshot && event.data.source === IncrementalSource.MouseMove && event.data.positions.length) {
15425
- finish_buffer += Math.max(0, -event.data.positions[0].timeOffset);
15537
+ finishBuffer += Math.max(0, -event.data.positions[0].timeOffset);
15426
15538
  }
15427
- setTimeout(finish, finish_buffer);
15539
+ setTimeout(finish, finishBuffer);
15428
15540
  }
15429
15541
  this.emitter.emit(ReplayerEvents.EventCast, event);
15430
15542
  };
@@ -16399,7 +16511,7 @@ class Replayer {
16399
16511
  return false;
16400
16512
  };
16401
16513
  const appendNode = (mutation) => {
16402
- var _a2, _b;
16514
+ var _a2, _b, _c;
16403
16515
  if (!this.iframe.contentDocument) {
16404
16516
  return this.warn("Looks like your replayer has been destroyed.");
16405
16517
  }
@@ -16412,6 +16524,14 @@ class Replayer {
16412
16524
  }
16413
16525
  return queue.push(mutation);
16414
16526
  }
16527
+ if (mutation.node.type === NodeType.Document && ((_a2 = parent == null ? void 0 : parent.nodeName) == null ? void 0 : _a2.toLowerCase()) !== "iframe") {
16528
+ console.warn(
16529
+ "[Replayer] Skipping invalid document append to a non-iframe parent.",
16530
+ mutation,
16531
+ parent
16532
+ );
16533
+ return;
16534
+ }
16415
16535
  if (mutation.node.isShadow) {
16416
16536
  if (!hasShadowRoot(parent)) {
16417
16537
  parent.attachShadow({ mode: "open" });
@@ -16487,7 +16607,7 @@ class Replayer {
16487
16607
  }
16488
16608
  } else if ((parentSn == null ? void 0 : parentSn.type) === NodeType.Document) {
16489
16609
  const parentDoc = parent;
16490
- if (mutation.node.type === NodeType.DocumentType && ((_a2 = parentDoc.childNodes[0]) == null ? void 0 : _a2.nodeType) === Node.DOCUMENT_TYPE_NODE)
16610
+ if (mutation.node.type === NodeType.DocumentType && ((_b = parentDoc.childNodes[0]) == null ? void 0 : _b.nodeType) === Node.DOCUMENT_TYPE_NODE)
16491
16611
  parentDoc.removeChild(parentDoc.childNodes[0]);
16492
16612
  if (target.nodeName === "HTML" && parentDoc.documentElement)
16493
16613
  parentDoc.removeChild(
@@ -16505,7 +16625,7 @@ class Replayer {
16505
16625
  parent.appendChild(target);
16506
16626
  }
16507
16627
  afterAppend(target, mutation.node.id);
16508
- if (this.usingVirtualDom && target.nodeName === "#text" && parent.nodeName === "STYLE" && ((_b = parent.rules) == null ? void 0 : _b.length) > 0)
16628
+ if (this.usingVirtualDom && target.nodeName === "#text" && parent.nodeName === "STYLE" && ((_c = parent.rules) == null ? void 0 : _c.length) > 0)
16509
16629
  parent.rules = [];
16510
16630
  if (isSerializedIframe(target, this.mirror)) {
16511
16631
  const targetId = this.mirror.getId(target);
@@ -16605,18 +16725,23 @@ class Replayer {
16605
16725
  const newSn = mirror2.getMeta(
16606
16726
  target
16607
16727
  );
16728
+ const newNode = buildNodeWithSN(
16729
+ __spreadProps(__spreadValues({}, newSn), {
16730
+ attributes: __spreadValues(__spreadValues({}, newSn.attributes), mutation.attributes)
16731
+ }),
16732
+ {
16733
+ doc: target.ownerDocument,
16734
+ // can be Document or RRDocument
16735
+ mirror: mirror2,
16736
+ skipChild: true,
16737
+ hackCss: true,
16738
+ cache: this.cache
16739
+ }
16740
+ );
16608
16741
  Object.assign(
16609
16742
  newSn.attributes,
16610
16743
  mutation.attributes
16611
16744
  );
16612
- const newNode = buildNodeWithSN(newSn, {
16613
- doc: target.ownerDocument,
16614
- // can be Document or RRDocument
16615
- mirror: mirror2,
16616
- skipChild: true,
16617
- hackCss: true,
16618
- cache: this.cache
16619
- });
16620
16745
  const siblingNode = target.nextSibling;
16621
16746
  const parentNode2 = target.parentNode;
16622
16747
  if (newNode && parentNode2) {