@posthog/rrweb-record 0.0.45 → 0.0.47

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.
@@ -10547,7 +10547,7 @@ function initMutationObserver(options, rootEl) {
10547
10547
  childList: true,
10548
10548
  subtree: true
10549
10549
  });
10550
- return observer;
10550
+ return { observer, buffer: mutationBuffer };
10551
10551
  }
10552
10552
  function initMoveObserver({
10553
10553
  mousemoveCb,
@@ -11468,8 +11468,11 @@ function initObservers(o2, hooks = {}) {
11468
11468
  }
11469
11469
  mergeHooks(o2, hooks);
11470
11470
  let mutationObserver;
11471
+ let mutationBuffer;
11471
11472
  if (o2.recordDOM) {
11472
- mutationObserver = initMutationObserver(o2, o2.doc);
11473
+ const result2 = initMutationObserver(o2, o2.doc);
11474
+ mutationObserver = result2.observer;
11475
+ mutationBuffer = result2.buffer;
11473
11476
  }
11474
11477
  const mousemoveHandler = initMoveObserver(o2);
11475
11478
  const mouseInteractionHandler = initMouseInteractionObserver(o2);
@@ -11506,8 +11509,14 @@ function initObservers(o2, hooks = {}) {
11506
11509
  );
11507
11510
  }
11508
11511
  return callbackWrapper(() => {
11509
- mutationBuffers.forEach((b) => b.destroy());
11510
- mutationBuffers.forEach((b) => b.reset());
11512
+ if (mutationBuffer) {
11513
+ mutationBuffer.destroy();
11514
+ mutationBuffer.reset();
11515
+ const index2 = mutationBuffers.indexOf(mutationBuffer);
11516
+ if (index2 !== -1) {
11517
+ mutationBuffers.splice(index2, 1);
11518
+ }
11519
+ }
11511
11520
  mutationObserver == null ? void 0 : mutationObserver.disconnect();
11512
11521
  mousemoveHandler();
11513
11522
  mouseInteractionHandler();
@@ -11522,7 +11531,6 @@ function initObservers(o2, hooks = {}) {
11522
11531
  selectionObserver();
11523
11532
  customElementObserver();
11524
11533
  pluginHandlers.forEach((h) => h());
11525
- mutationBuffers.length = 0;
11526
11534
  });
11527
11535
  }
11528
11536
  function hasNestedCSSRule(prop) {
@@ -11922,7 +11930,7 @@ class ShadowDomManager {
11922
11930
  if (!isNativeShadowDom(shadowRoot2)) return;
11923
11931
  if (this.shadowDoms.has(shadowRoot2)) return;
11924
11932
  this.shadowDoms.add(shadowRoot2);
11925
- const observer = initMutationObserver(
11933
+ const { observer, buffer } = initMutationObserver(
11926
11934
  {
11927
11935
  ...this.bypassOptions,
11928
11936
  doc,
@@ -11932,7 +11940,15 @@ class ShadowDomManager {
11932
11940
  },
11933
11941
  shadowRoot2
11934
11942
  );
11935
- this.restoreHandlers.push(() => observer.disconnect());
11943
+ this.restoreHandlers.push(() => {
11944
+ observer.disconnect();
11945
+ buffer.destroy();
11946
+ buffer.reset();
11947
+ const index2 = mutationBuffers.indexOf(buffer);
11948
+ if (index2 !== -1) {
11949
+ mutationBuffers.splice(index2, 1);
11950
+ }
11951
+ });
11936
11952
  this.restoreHandlers.push(
11937
11953
  initScrollObserver({
11938
11954
  ...this.bypassOptions,
@@ -12322,7 +12338,7 @@ function initCanvasWebGLMutationObserver(cb, win, blockClass, blockSelector, dat
12322
12338
  handlers.forEach((h) => h());
12323
12339
  };
12324
12340
  }
12325
- const jsContent = '(function() {\n "use strict";\n var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\n var lookup = typeof Uint8Array === "undefined" ? [] : new Uint8Array(256);\n for (var i = 0; i < chars.length; i++) {\n lookup[chars.charCodeAt(i)] = i;\n }\n var encode = function(arraybuffer) {\n var bytes = new Uint8Array(arraybuffer), i2, len = bytes.length, base64 = "";\n for (i2 = 0; i2 < len; i2 += 3) {\n base64 += chars[bytes[i2] >> 2];\n base64 += chars[(bytes[i2] & 3) << 4 | bytes[i2 + 1] >> 4];\n base64 += chars[(bytes[i2 + 1] & 15) << 2 | bytes[i2 + 2] >> 6];\n base64 += chars[bytes[i2 + 2] & 63];\n }\n if (len % 3 === 2) {\n base64 = base64.substring(0, base64.length - 1) + "=";\n } else if (len % 3 === 1) {\n base64 = base64.substring(0, base64.length - 2) + "==";\n }\n return base64;\n };\n const lastBlobMap = /* @__PURE__ */ new Map();\n const transparentBlobMap = /* @__PURE__ */ new Map();\n async function getTransparentBlobFor(width, height, dataURLOptions) {\n const id = `${width}-${height}`;\n if ("OffscreenCanvas" in globalThis) {\n if (transparentBlobMap.has(id)) return transparentBlobMap.get(id);\n const offscreen = new OffscreenCanvas(width, height);\n offscreen.getContext("2d");\n const blob = await offscreen.convertToBlob(dataURLOptions);\n const arrayBuffer = await blob.arrayBuffer();\n const base64 = encode(arrayBuffer);\n transparentBlobMap.set(id, base64);\n return base64;\n } else {\n return "";\n }\n }\n const worker = self;\n let reusableCanvas = null;\n let reusableCtx = null;\n worker.onmessage = async function(e) {\n if ("OffscreenCanvas" in globalThis) {\n const { id, bitmap, width, height, dataURLOptions } = e.data;\n const transparentBase64 = getTransparentBlobFor(\n width,\n height,\n dataURLOptions\n );\n if (!reusableCanvas || reusableCanvas.width !== width || reusableCanvas.height !== height) {\n reusableCanvas = new OffscreenCanvas(width, height);\n reusableCtx = reusableCanvas.getContext("2d");\n }\n reusableCtx.clearRect(0, 0, width, height);\n reusableCtx.drawImage(bitmap, 0, 0);\n bitmap.close();\n const blob = await reusableCanvas.convertToBlob(dataURLOptions);\n const type = blob.type;\n const arrayBuffer = await blob.arrayBuffer();\n const base64 = encode(arrayBuffer);\n if (!lastBlobMap.has(id) && await transparentBase64 === base64) {\n lastBlobMap.set(id, base64);\n return worker.postMessage({ id });\n }\n if (lastBlobMap.get(id) === base64) return worker.postMessage({ id });\n worker.postMessage({\n id,\n type,\n base64,\n width,\n height\n });\n lastBlobMap.set(id, base64);\n } else {\n e.data.bitmap.close();\n return worker.postMessage({ id: e.data.id });\n }\n };\n})();\n//# sourceMappingURL=image-bitmap-data-url-worker-ChEIhO0o.js.map\n';
12341
+ const jsContent = '(function() {\n "use strict";\n var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\n var lookup = typeof Uint8Array === "undefined" ? [] : new Uint8Array(256);\n for (var i = 0; i < chars.length; i++) {\n lookup[chars.charCodeAt(i)] = i;\n }\n var encode = function(arraybuffer) {\n var bytes = new Uint8Array(arraybuffer), i2, len = bytes.length, base64 = "";\n for (i2 = 0; i2 < len; i2 += 3) {\n base64 += chars[bytes[i2] >> 2];\n base64 += chars[(bytes[i2] & 3) << 4 | bytes[i2 + 1] >> 4];\n base64 += chars[(bytes[i2 + 1] & 15) << 2 | bytes[i2 + 2] >> 6];\n base64 += chars[bytes[i2 + 2] & 63];\n }\n if (len % 3 === 2) {\n base64 = base64.substring(0, base64.length - 1) + "=";\n } else if (len % 3 === 1) {\n base64 = base64.substring(0, base64.length - 2) + "==";\n }\n return base64;\n };\n const lastFingerprintMap = /* @__PURE__ */ new Map();\n const transparentBlobMap = /* @__PURE__ */ new Map();\n function fnv1aHash(buffer) {\n const view = new Uint8Array(buffer);\n let hash = 2166136261;\n for (let i2 = 0; i2 < view.length; i2++) {\n hash ^= view[i2];\n hash = hash * 16777619 | 0;\n }\n return (hash >>> 0).toString(16);\n }\n async function getTransparentBlobFor(width, height, dataURLOptions) {\n const id = `${width}-${height}`;\n if ("OffscreenCanvas" in globalThis) {\n if (transparentBlobMap.has(id)) return transparentBlobMap.get(id);\n const offscreen = new OffscreenCanvas(width, height);\n offscreen.getContext("2d");\n const blob = await offscreen.convertToBlob(dataURLOptions);\n const arrayBuffer = await blob.arrayBuffer();\n const base64 = encode(arrayBuffer);\n transparentBlobMap.set(id, base64);\n return base64;\n } else {\n return "";\n }\n }\n const worker = self;\n let reusableCanvas = null;\n let reusableCtx = null;\n worker.onmessage = async function(e) {\n if ("OffscreenCanvas" in globalThis) {\n const { id, bitmap, width, height, dataURLOptions } = e.data;\n const transparentBase64 = getTransparentBlobFor(\n width,\n height,\n dataURLOptions\n );\n if (!reusableCanvas || reusableCanvas.width !== width || reusableCanvas.height !== height) {\n reusableCanvas = new OffscreenCanvas(width, height);\n reusableCtx = reusableCanvas.getContext("2d");\n }\n reusableCtx.clearRect(0, 0, width, height);\n reusableCtx.drawImage(bitmap, 0, 0);\n bitmap.close();\n const blob = await reusableCanvas.convertToBlob(dataURLOptions);\n const type = blob.type;\n const arrayBuffer = await blob.arrayBuffer();\n const fingerprint = fnv1aHash(arrayBuffer);\n if (!lastFingerprintMap.has(id)) {\n const base642 = encode(arrayBuffer);\n if (await transparentBase64 === base642) {\n lastFingerprintMap.set(id, fingerprint);\n return worker.postMessage({ id });\n }\n lastFingerprintMap.set(id, fingerprint);\n worker.postMessage({ id, type, base64: base642, width, height });\n return;\n }\n if (lastFingerprintMap.get(id) === fingerprint)\n return worker.postMessage({ id });\n const base64 = encode(arrayBuffer);\n worker.postMessage({ id, type, base64, width, height });\n lastFingerprintMap.set(id, fingerprint);\n } else {\n e.data.bitmap.close();\n return worker.postMessage({ id: e.data.id });\n }\n };\n})();\n//# sourceMappingURL=image-bitmap-data-url-worker-B8-18rdG.js.map\n';
12326
12342
  const blob = typeof self !== "undefined" && self.Blob && new Blob([jsContent], { type: "text/javascript;charset=utf-8" });
12327
12343
  function WorkerWrapper(options) {
12328
12344
  let objURL;
@@ -12789,6 +12805,26 @@ function record(options = {}) {
12789
12805
  polyfill$1();
12790
12806
  let lastFullSnapshotEvent;
12791
12807
  let incrementalSnapshotCount = 0;
12808
+ const iframeObserverCleanups = /* @__PURE__ */ new Map();
12809
+ function cleanupDetachedIframeObservers() {
12810
+ for (const [iframeId, cleanup] of iframeObserverCleanups) {
12811
+ const iframe = mirror.getNode(iframeId);
12812
+ if (!iframe) {
12813
+ cleanup();
12814
+ iframeObserverCleanups.delete(iframeId);
12815
+ continue;
12816
+ }
12817
+ try {
12818
+ if (!iframe.contentDocument || !iframe.contentDocument.defaultView) {
12819
+ cleanup();
12820
+ iframeObserverCleanups.delete(iframeId);
12821
+ }
12822
+ } catch {
12823
+ cleanup();
12824
+ iframeObserverCleanups.delete(iframeId);
12825
+ }
12826
+ }
12827
+ }
12792
12828
  const eventProcessor = (e2) => {
12793
12829
  for (const plugin of plugins || []) {
12794
12830
  if (plugin.eventProcessor) {
@@ -12839,9 +12875,15 @@ function record(options = {}) {
12839
12875
  const addedIds = m.adds.length > 0 ? new Set(m.adds.map((add) => add.node.id)) : null;
12840
12876
  m.removes.forEach(({ id }) => {
12841
12877
  if (!addedIds || !addedIds.has(id)) {
12878
+ const cleanup = iframeObserverCleanups.get(id);
12879
+ if (cleanup) {
12880
+ cleanup();
12881
+ iframeObserverCleanups.delete(id);
12882
+ }
12842
12883
  iframeManager.removeIframeById(id);
12843
12884
  }
12844
12885
  });
12886
+ cleanupDetachedIframeObservers();
12845
12887
  }
12846
12888
  wrappedEmit({
12847
12889
  type: EventType.IncrementalSnapshot,
@@ -13129,7 +13171,12 @@ function record(options = {}) {
13129
13171
  };
13130
13172
  const loadListener = (iframeEl) => {
13131
13173
  try {
13132
- handlers.push(observe(iframeEl.contentDocument));
13174
+ const iframeId = mirror.getId(iframeEl);
13175
+ const cleanup = observe(iframeEl.contentDocument);
13176
+ handlers.push(cleanup);
13177
+ if (iframeId !== -1) {
13178
+ iframeObserverCleanups.set(iframeId, cleanup);
13179
+ }
13133
13180
  } catch (error) {
13134
13181
  console.warn(error);
13135
13182
  }
@@ -13171,6 +13218,7 @@ function record(options = {}) {
13171
13218
  processedNodeManager.destroy();
13172
13219
  iframeManager.removeLoadListener();
13173
13220
  iframeManager.destroy();
13221
+ iframeObserverCleanups.clear();
13174
13222
  mirror.reset();
13175
13223
  recording = false;
13176
13224
  unregisterErrorHandler();