@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.
package/dist/rrweb.d.cts CHANGED
@@ -114,8 +114,6 @@ declare function iterateResolveTree(tree: ResolveTree, cb: (mutation: addedNodeM
114
114
 
115
115
  declare function legacy_isTouchEvent(event: MouseEvent | TouchEvent | PointerEvent): event is TouchEvent;
116
116
 
117
- export { listenerHandler }
118
-
119
117
  export declare let mirror: DeprecatedMirror;
120
118
 
121
119
  export { MouseInteractions }
@@ -124,10 +122,6 @@ declare let nowTimestamp: () => number;
124
122
 
125
123
  declare function on(type: string, fn: EventListenerOrEventListenerObject, target?: Document | IWindow): listenerHandler;
126
124
 
127
- declare function patch(source: {
128
- [key: string]: any;
129
- }, name: string, replacement: (...args: unknown[]) => unknown): () => void;
130
-
131
125
  declare type PlayerAssets = {
132
126
  emitter: Emitter;
133
127
  applyEventsSynchronously(events: Array<eventWithTime>): void;
@@ -433,7 +427,6 @@ declare namespace utils {
433
427
  on,
434
428
  throttle,
435
429
  hookSetter,
436
- patch,
437
430
  getWindowScroll,
438
431
  getWindowHeight,
439
432
  getWindowWidth,
package/dist/rrweb.d.ts CHANGED
@@ -114,8 +114,6 @@ declare function iterateResolveTree(tree: ResolveTree, cb: (mutation: addedNodeM
114
114
 
115
115
  declare function legacy_isTouchEvent(event: MouseEvent | TouchEvent | PointerEvent): event is TouchEvent;
116
116
 
117
- export { listenerHandler }
118
-
119
117
  export declare let mirror: DeprecatedMirror;
120
118
 
121
119
  export { MouseInteractions }
@@ -124,10 +122,6 @@ declare let nowTimestamp: () => number;
124
122
 
125
123
  declare function on(type: string, fn: EventListenerOrEventListenerObject, target?: Document | IWindow): listenerHandler;
126
124
 
127
- declare function patch(source: {
128
- [key: string]: any;
129
- }, name: string, replacement: (...args: unknown[]) => unknown): () => void;
130
-
131
125
  declare type PlayerAssets = {
132
126
  emitter: Emitter;
133
127
  applyEventsSynchronously(events: Array<eventWithTime>): void;
@@ -433,7 +427,6 @@ declare namespace utils {
433
427
  on,
434
428
  throttle,
435
429
  hookSetter,
436
- patch,
437
430
  getWindowScroll,
438
431
  getWindowHeight,
439
432
  getWindowWidth,
package/dist/rrweb.js CHANGED
@@ -142,6 +142,32 @@ function querySelectorAll$1(n2, selectors) {
142
142
  function mutationObserverCtor$1() {
143
143
  return getUntaintedPrototype$1("MutationObserver").constructor;
144
144
  }
145
+ function patch$1(source, name, replacement) {
146
+ try {
147
+ if (!(name in source)) {
148
+ return () => {
149
+ };
150
+ }
151
+ const original = source[name];
152
+ const wrapped = replacement(original);
153
+ if (typeof wrapped === "function") {
154
+ wrapped.prototype = wrapped.prototype || {};
155
+ Object.defineProperties(wrapped, {
156
+ __rrweb_original__: {
157
+ enumerable: false,
158
+ value: original
159
+ }
160
+ });
161
+ }
162
+ source[name] = wrapped;
163
+ return () => {
164
+ source[name] = original;
165
+ };
166
+ } catch {
167
+ return () => {
168
+ };
169
+ }
170
+ }
145
171
  const index$1 = {
146
172
  childNodes: childNodes$1,
147
173
  parentNode: parentNode$1,
@@ -154,7 +180,8 @@ const index$1 = {
154
180
  shadowRoot: shadowRoot$1,
155
181
  querySelector: querySelector$1,
156
182
  querySelectorAll: querySelectorAll$1,
157
- mutationObserver: mutationObserverCtor$1
183
+ mutationObserver: mutationObserverCtor$1,
184
+ patch: patch$1
158
185
  };
159
186
  function isElement(n2) {
160
187
  return n2.nodeType === n2.ELEMENT_NODE;
@@ -435,19 +462,27 @@ function absolutifyURLs(cssText, href) {
435
462
  }
436
463
  );
437
464
  }
438
- function normalizeCssString(cssText) {
439
- return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
465
+ function normalizeCssString(cssText, _testNoPxNorm = false) {
466
+ if (_testNoPxNorm) {
467
+ return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
468
+ } else {
469
+ return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "").replace(/0px/g, "0");
470
+ }
440
471
  }
441
- function splitCssText(cssText, style) {
472
+ function splitCssText(cssText, style, _testNoPxNorm = false) {
442
473
  const childNodes2 = Array.from(style.childNodes);
443
474
  const splits = [];
444
- let iterLimit = 0;
475
+ let iterCount = 0;
445
476
  if (childNodes2.length > 1 && cssText && typeof cssText === "string") {
446
- let cssTextNorm = normalizeCssString(cssText);
477
+ let cssTextNorm = normalizeCssString(cssText, _testNoPxNorm);
447
478
  const normFactor = cssTextNorm.length / cssText.length;
448
479
  for (let i2 = 1; i2 < childNodes2.length; i2++) {
449
480
  if (childNodes2[i2].textContent && typeof childNodes2[i2].textContent === "string") {
450
- const textContentNorm = normalizeCssString(childNodes2[i2].textContent);
481
+ const textContentNorm = normalizeCssString(
482
+ childNodes2[i2].textContent,
483
+ _testNoPxNorm
484
+ );
485
+ const jLimit = 100;
451
486
  let j = 3;
452
487
  for (; j < textContentNorm.length; j++) {
453
488
  if (
@@ -460,23 +495,49 @@ function splitCssText(cssText, style) {
460
495
  break;
461
496
  }
462
497
  for (; j < textContentNorm.length; j++) {
463
- const bit = textContentNorm.substring(0, j);
464
- const bits = cssTextNorm.split(bit);
498
+ let startSubstring = textContentNorm.substring(0, j);
499
+ let cssNormSplits = cssTextNorm.split(startSubstring);
465
500
  let splitNorm = -1;
466
- if (bits.length === 2) {
467
- splitNorm = cssTextNorm.indexOf(bit);
468
- } else if (bits.length > 2 && bits[0] === "" && childNodes2[i2 - 1].textContent !== "") {
469
- splitNorm = cssTextNorm.indexOf(bit, 1);
501
+ if (cssNormSplits.length === 2) {
502
+ splitNorm = cssNormSplits[0].length;
503
+ } else if (cssNormSplits.length > 2 && cssNormSplits[0] === "" && childNodes2[i2 - 1].textContent !== "") {
504
+ splitNorm = cssTextNorm.indexOf(startSubstring, 1);
505
+ } else if (cssNormSplits.length === 1) {
506
+ startSubstring = startSubstring.substring(
507
+ 0,
508
+ startSubstring.length - 1
509
+ );
510
+ cssNormSplits = cssTextNorm.split(startSubstring);
511
+ if (cssNormSplits.length <= 1) {
512
+ splits.push(cssText);
513
+ return splits;
514
+ }
515
+ j = jLimit + 1;
516
+ } else if (j === textContentNorm.length - 1) {
517
+ splitNorm = cssTextNorm.indexOf(startSubstring);
518
+ }
519
+ if (cssNormSplits.length >= 2 && j > jLimit) {
520
+ const prevTextContent = childNodes2[i2 - 1].textContent;
521
+ if (prevTextContent && typeof prevTextContent === "string") {
522
+ const prevMinLength = normalizeCssString(prevTextContent).length;
523
+ splitNorm = cssTextNorm.indexOf(startSubstring, prevMinLength);
524
+ }
525
+ if (splitNorm === -1) {
526
+ splitNorm = cssNormSplits[0].length;
527
+ }
470
528
  }
471
529
  if (splitNorm !== -1) {
472
530
  let k = Math.floor(splitNorm / normFactor);
473
531
  for (; k > 0 && k < cssText.length; ) {
474
- iterLimit += 1;
475
- if (iterLimit > 50 * childNodes2.length) {
532
+ iterCount += 1;
533
+ if (iterCount > 50 * childNodes2.length) {
476
534
  splits.push(cssText);
477
535
  return splits;
478
536
  }
479
- const normPart = normalizeCssString(cssText.substring(0, k));
537
+ const normPart = normalizeCssString(
538
+ cssText.substring(0, k),
539
+ _testNoPxNorm
540
+ );
480
541
  if (normPart.length === splitNorm) {
481
542
  splits.push(cssText.substring(0, k));
482
543
  cssText = cssText.substring(k);
@@ -5046,11 +5107,16 @@ function getTagName(n2) {
5046
5107
  function adaptCssForReplay(cssText, cache) {
5047
5108
  const cachedStyle = cache == null ? void 0 : cache.stylesWithHoverClass.get(cssText);
5048
5109
  if (cachedStyle) return cachedStyle;
5049
- const ast = postcss$1$1([
5050
- mediaSelectorPlugin,
5051
- pseudoClassPlugin
5052
- ]).process(cssText);
5053
- const result2 = ast.css;
5110
+ let result2 = cssText;
5111
+ try {
5112
+ const ast = postcss$1$1([
5113
+ mediaSelectorPlugin,
5114
+ pseudoClassPlugin
5115
+ ]).process(cssText);
5116
+ result2 = ast.css;
5117
+ } catch (error) {
5118
+ console.warn("Failed to adapt css for replay", error);
5119
+ }
5054
5120
  cache == null ? void 0 : cache.stylesWithHoverClass.set(cssText, result2);
5055
5121
  return result2;
5056
5122
  }
@@ -5071,11 +5137,39 @@ function applyCssSplits(n2, cssText, hackCss, cache) {
5071
5137
  while (cssTextSplits.length > 1 && cssTextSplits.length > childTextNodes.length) {
5072
5138
  cssTextSplits.splice(-2, 2, cssTextSplits.slice(-2).join(""));
5073
5139
  }
5140
+ let adaptedCss = "";
5141
+ if (hackCss) {
5142
+ adaptedCss = adaptCssForReplay(cssTextSplits.join(""), cache);
5143
+ }
5144
+ let startIndex = 0;
5074
5145
  for (let i2 = 0; i2 < childTextNodes.length; i2++) {
5146
+ if (i2 === cssTextSplits.length) {
5147
+ break;
5148
+ }
5075
5149
  const childTextNode = childTextNodes[i2];
5076
- const cssTextSection = cssTextSplits[i2];
5077
- if (childTextNode && cssTextSection) {
5078
- childTextNode.textContent = hackCss ? adaptCssForReplay(cssTextSection, cache) : cssTextSection;
5150
+ if (!hackCss) {
5151
+ childTextNode.textContent = cssTextSplits[i2];
5152
+ } else if (i2 < cssTextSplits.length - 1) {
5153
+ let endIndex = startIndex;
5154
+ let endSearch = cssTextSplits[i2 + 1].length;
5155
+ endSearch = Math.min(endSearch, 30);
5156
+ let found = false;
5157
+ for (; endSearch > 2; endSearch--) {
5158
+ const searchBit = cssTextSplits[i2 + 1].substring(0, endSearch);
5159
+ const searchIndex = adaptedCss.substring(startIndex).indexOf(searchBit);
5160
+ found = searchIndex !== -1;
5161
+ if (found) {
5162
+ endIndex += searchIndex;
5163
+ break;
5164
+ }
5165
+ }
5166
+ if (!found) {
5167
+ endIndex += cssTextSplits[i2].length;
5168
+ }
5169
+ childTextNode.textContent = adaptedCss.substring(startIndex, endIndex);
5170
+ startIndex = endIndex;
5171
+ } else {
5172
+ childTextNode.textContent = adaptedCss.substring(startIndex);
5079
5173
  }
5080
5174
  }
5081
5175
  }
@@ -10394,6 +10488,32 @@ function querySelectorAll(n2, selectors) {
10394
10488
  function mutationObserverCtor() {
10395
10489
  return getUntaintedPrototype("MutationObserver").constructor;
10396
10490
  }
10491
+ function patch(source, name, replacement) {
10492
+ try {
10493
+ if (!(name in source)) {
10494
+ return () => {
10495
+ };
10496
+ }
10497
+ const original = source[name];
10498
+ const wrapped = replacement(original);
10499
+ if (typeof wrapped === "function") {
10500
+ wrapped.prototype = wrapped.prototype || {};
10501
+ Object.defineProperties(wrapped, {
10502
+ __rrweb_original__: {
10503
+ enumerable: false,
10504
+ value: original
10505
+ }
10506
+ });
10507
+ }
10508
+ source[name] = wrapped;
10509
+ return () => {
10510
+ source[name] = original;
10511
+ };
10512
+ } catch {
10513
+ return () => {
10514
+ };
10515
+ }
10516
+ }
10397
10517
  const index = {
10398
10518
  childNodes,
10399
10519
  parentNode,
@@ -10406,7 +10526,8 @@ const index = {
10406
10526
  shadowRoot,
10407
10527
  querySelector,
10408
10528
  querySelectorAll,
10409
- mutationObserver: mutationObserverCtor
10529
+ mutationObserver: mutationObserverCtor,
10530
+ patch
10410
10531
  };
10411
10532
  function on(type, fn, target = document) {
10412
10533
  const options = { capture: true, passive: true };
@@ -10489,32 +10610,6 @@ function hookSetter(target, key, d, isRevoked, win = window) {
10489
10610
  );
10490
10611
  return () => hookSetter(target, key, original || {}, true);
10491
10612
  }
10492
- function patch(source, name, replacement) {
10493
- try {
10494
- if (!(name in source)) {
10495
- return () => {
10496
- };
10497
- }
10498
- const original = source[name];
10499
- const wrapped = replacement(original);
10500
- if (typeof wrapped === "function") {
10501
- wrapped.prototype = wrapped.prototype || {};
10502
- Object.defineProperties(wrapped, {
10503
- __rrweb_original__: {
10504
- enumerable: false,
10505
- value: original
10506
- }
10507
- });
10508
- }
10509
- source[name] = wrapped;
10510
- return () => {
10511
- source[name] = original;
10512
- };
10513
- } catch {
10514
- return () => {
10515
- };
10516
- }
10517
- }
10518
10613
  let nowTimestamp = Date.now;
10519
10614
  if (!/* @__PURE__ */ /[1-9][0-9]{12}/.test(Date.now().toString())) {
10520
10615
  nowTimestamp = () => (/* @__PURE__ */ new Date()).getTime();
@@ -10528,10 +10623,12 @@ function getWindowScroll(win) {
10528
10623
  };
10529
10624
  }
10530
10625
  function getWindowHeight(win) {
10531
- return win.innerHeight || win.document.documentElement && win.document.documentElement.clientHeight || win.document.body && win.document.body.clientHeight;
10626
+ var _a2, _b;
10627
+ return win.innerHeight || ((_a2 = win.document.documentElement) == null ? void 0 : _a2.clientHeight) || ((_b = win.document.body) == null ? void 0 : _b.clientHeight);
10532
10628
  }
10533
10629
  function getWindowWidth(win) {
10534
- return win.innerWidth || win.document.documentElement && win.document.documentElement.clientWidth || win.document.body && win.document.body.clientWidth;
10630
+ var _a2, _b;
10631
+ return win.innerWidth || ((_a2 = win.document.documentElement) == null ? void 0 : _a2.clientWidth) || ((_b = win.document.body) == null ? void 0 : _b.clientWidth);
10535
10632
  }
10536
10633
  function closestElementOfNode(node2) {
10537
10634
  if (!node2) {
@@ -10800,7 +10897,6 @@ const utils = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
10800
10897
  return nowTimestamp;
10801
10898
  },
10802
10899
  on,
10803
- patch,
10804
10900
  polyfill: polyfill$1,
10805
10901
  queueToResolveTrees,
10806
10902
  shadowHostInDom,
@@ -11243,10 +11339,18 @@ class MutationBuffer {
11243
11339
  this.attributes.push(item);
11244
11340
  this.attributeMap.set(textarea, item);
11245
11341
  }
11246
- item.attributes.value = Array.from(
11342
+ const value = Array.from(
11247
11343
  index.childNodes(textarea),
11248
11344
  (cn) => index.textContent(cn) || ""
11249
11345
  ).join("");
11346
+ item.attributes.value = maskInputValue({
11347
+ element: textarea,
11348
+ maskInputOptions: this.maskInputOptions,
11349
+ tagName: textarea.tagName,
11350
+ type: getInputType(textarea),
11351
+ value,
11352
+ maskInputFn: this.maskInputFn
11353
+ });
11250
11354
  });
11251
11355
  __publicField(this, "processMutation", (m) => {
11252
11356
  if (isIgnored(m.target, this.mirror, this.slimDOMOptions)) {
@@ -12860,7 +12964,7 @@ class ShadowDomManager {
12860
12964
  }
12861
12965
  init() {
12862
12966
  this.reset();
12863
- this.patchAttachShadow(Element, document);
12967
+ this.patchAttachShadow(Element, this.bypassOptions.win.document);
12864
12968
  }
12865
12969
  addShadowRoot(shadowRoot2, doc) {
12866
12970
  if (!isNativeShadowDom(shadowRoot2)) return;
@@ -14051,7 +14155,7 @@ function record(options = {}) {
14051
14155
  data: {}
14052
14156
  });
14053
14157
  if (recordAfter === "DOMContentLoaded") init();
14054
- })
14158
+ }, win.document)
14055
14159
  );
14056
14160
  handlers.push(
14057
14161
  on(
@@ -14680,11 +14784,19 @@ function createPlayerService(context, { getCastFn, applyEventsSynchronously, emi
14680
14784
  emitter.emit(ReplayerEvents.PlayBack);
14681
14785
  }
14682
14786
  const syncEvents = new Array();
14787
+ let renderedFullSnapshot = false;
14683
14788
  for (const event of neededEvents) {
14789
+ const isFullSnapshot = event.type === EventType.FullSnapshot;
14684
14790
  if (lastPlayedTimestamp && lastPlayedTimestamp < baselineTime && (event.timestamp <= lastPlayedTimestamp || event === lastPlayedEvent)) {
14791
+ if (isFullSnapshot) {
14792
+ renderedFullSnapshot = true;
14793
+ }
14685
14794
  continue;
14686
14795
  }
14687
- if (event.timestamp < baselineTime) {
14796
+ if (event.timestamp <= baselineTime || isFullSnapshot && !renderedFullSnapshot) {
14797
+ if (isFullSnapshot) {
14798
+ renderedFullSnapshot = true;
14799
+ }
14688
14800
  syncEvents.push(event);
14689
14801
  } else {
14690
14802
  const castFn = getCastFn(event, false);
@@ -15400,21 +15512,21 @@ class Replayer {
15400
15512
  if (plugin3.handler) plugin3.handler(event, isSync, { replayer: this });
15401
15513
  }
15402
15514
  this.service.send({ type: "CAST_EVENT", payload: { event } });
15403
- const last_index = this.service.state.context.events.length - 1;
15404
- if (!this.config.liveMode && event === this.service.state.context.events[last_index]) {
15515
+ const lastIndex = this.service.state.context.events.length - 1;
15516
+ if (!this.config.liveMode && event === this.service.state.context.events[lastIndex]) {
15405
15517
  const finish = () => {
15406
- if (last_index < this.service.state.context.events.length - 1) {
15518
+ if (lastIndex < this.service.state.context.events.length - 1) {
15407
15519
  return;
15408
15520
  }
15409
15521
  this.backToNormal();
15410
15522
  this.service.send("END");
15411
15523
  this.emitter.emit(ReplayerEvents.Finish);
15412
15524
  };
15413
- let finish_buffer = 50;
15525
+ let finishBuffer = 50;
15414
15526
  if (event.type === EventType.IncrementalSnapshot && event.data.source === IncrementalSource.MouseMove && event.data.positions.length) {
15415
- finish_buffer += Math.max(0, -event.data.positions[0].timeOffset);
15527
+ finishBuffer += Math.max(0, -event.data.positions[0].timeOffset);
15416
15528
  }
15417
- setTimeout(finish, finish_buffer);
15529
+ setTimeout(finish, finishBuffer);
15418
15530
  }
15419
15531
  this.emitter.emit(ReplayerEvents.EventCast, event);
15420
15532
  };
@@ -16391,7 +16503,7 @@ class Replayer {
16391
16503
  return false;
16392
16504
  };
16393
16505
  const appendNode = (mutation) => {
16394
- var _a2, _b;
16506
+ var _a2, _b, _c;
16395
16507
  if (!this.iframe.contentDocument) {
16396
16508
  return this.warn("Looks like your replayer has been destroyed.");
16397
16509
  }
@@ -16404,6 +16516,14 @@ class Replayer {
16404
16516
  }
16405
16517
  return queue.push(mutation);
16406
16518
  }
16519
+ if (mutation.node.type === NodeType.Document && ((_a2 = parent == null ? void 0 : parent.nodeName) == null ? void 0 : _a2.toLowerCase()) !== "iframe") {
16520
+ console.warn(
16521
+ "[Replayer] Skipping invalid document append to a non-iframe parent.",
16522
+ mutation,
16523
+ parent
16524
+ );
16525
+ return;
16526
+ }
16407
16527
  if (mutation.node.isShadow) {
16408
16528
  if (!hasShadowRoot(parent)) {
16409
16529
  parent.attachShadow({ mode: "open" });
@@ -16479,7 +16599,7 @@ class Replayer {
16479
16599
  }
16480
16600
  } else if ((parentSn == null ? void 0 : parentSn.type) === NodeType.Document) {
16481
16601
  const parentDoc = parent;
16482
- if (mutation.node.type === NodeType.DocumentType && ((_a2 = parentDoc.childNodes[0]) == null ? void 0 : _a2.nodeType) === Node.DOCUMENT_TYPE_NODE)
16602
+ if (mutation.node.type === NodeType.DocumentType && ((_b = parentDoc.childNodes[0]) == null ? void 0 : _b.nodeType) === Node.DOCUMENT_TYPE_NODE)
16483
16603
  parentDoc.removeChild(parentDoc.childNodes[0]);
16484
16604
  if (target.nodeName === "HTML" && parentDoc.documentElement)
16485
16605
  parentDoc.removeChild(
@@ -16497,7 +16617,7 @@ class Replayer {
16497
16617
  parent.appendChild(target);
16498
16618
  }
16499
16619
  afterAppend(target, mutation.node.id);
16500
- if (this.usingVirtualDom && target.nodeName === "#text" && parent.nodeName === "STYLE" && ((_b = parent.rules) == null ? void 0 : _b.length) > 0)
16620
+ if (this.usingVirtualDom && target.nodeName === "#text" && parent.nodeName === "STYLE" && ((_c = parent.rules) == null ? void 0 : _c.length) > 0)
16501
16621
  parent.rules = [];
16502
16622
  if (isSerializedIframe(target, this.mirror)) {
16503
16623
  const targetId = this.mirror.getId(target);
@@ -16597,18 +16717,27 @@ class Replayer {
16597
16717
  const newSn = mirror2.getMeta(
16598
16718
  target
16599
16719
  );
16720
+ const newNode = buildNodeWithSN(
16721
+ {
16722
+ ...newSn,
16723
+ attributes: {
16724
+ ...newSn.attributes,
16725
+ ...mutation.attributes
16726
+ }
16727
+ },
16728
+ {
16729
+ doc: target.ownerDocument,
16730
+ // can be Document or RRDocument
16731
+ mirror: mirror2,
16732
+ skipChild: true,
16733
+ hackCss: true,
16734
+ cache: this.cache
16735
+ }
16736
+ );
16600
16737
  Object.assign(
16601
16738
  newSn.attributes,
16602
16739
  mutation.attributes
16603
16740
  );
16604
- const newNode = buildNodeWithSN(newSn, {
16605
- doc: target.ownerDocument,
16606
- // can be Document or RRDocument
16607
- mirror: mirror2,
16608
- skipChild: true,
16609
- hackCss: true,
16610
- cache: this.cache
16611
- });
16612
16741
  const siblingNode = target.nextSibling;
16613
16742
  const parentNode2 = target.parentNode;
16614
16743
  if (newNode && parentNode2) {