@posthog/rrweb 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.
package/dist/rrweb.js CHANGED
@@ -12615,7 +12615,7 @@ function initMutationObserver(options, rootEl) {
12615
12615
  childList: true,
12616
12616
  subtree: true
12617
12617
  });
12618
- return observer;
12618
+ return { observer, buffer: mutationBuffer };
12619
12619
  }
12620
12620
  function initMoveObserver({
12621
12621
  mousemoveCb,
@@ -13536,8 +13536,11 @@ function initObservers(o2, hooks = {}) {
13536
13536
  }
13537
13537
  mergeHooks(o2, hooks);
13538
13538
  let mutationObserver;
13539
+ let mutationBuffer;
13539
13540
  if (o2.recordDOM) {
13540
- mutationObserver = initMutationObserver(o2, o2.doc);
13541
+ const result2 = initMutationObserver(o2, o2.doc);
13542
+ mutationObserver = result2.observer;
13543
+ mutationBuffer = result2.buffer;
13541
13544
  }
13542
13545
  const mousemoveHandler = initMoveObserver(o2);
13543
13546
  const mouseInteractionHandler = initMouseInteractionObserver(o2);
@@ -13574,8 +13577,14 @@ function initObservers(o2, hooks = {}) {
13574
13577
  );
13575
13578
  }
13576
13579
  return callbackWrapper(() => {
13577
- mutationBuffers.forEach((b) => b.destroy());
13578
- mutationBuffers.forEach((b) => b.reset());
13580
+ if (mutationBuffer) {
13581
+ mutationBuffer.destroy();
13582
+ mutationBuffer.reset();
13583
+ const index2 = mutationBuffers.indexOf(mutationBuffer);
13584
+ if (index2 !== -1) {
13585
+ mutationBuffers.splice(index2, 1);
13586
+ }
13587
+ }
13579
13588
  mutationObserver == null ? void 0 : mutationObserver.disconnect();
13580
13589
  mousemoveHandler();
13581
13590
  mouseInteractionHandler();
@@ -13590,7 +13599,6 @@ function initObservers(o2, hooks = {}) {
13590
13599
  selectionObserver();
13591
13600
  customElementObserver();
13592
13601
  pluginHandlers.forEach((h) => h());
13593
- mutationBuffers.length = 0;
13594
13602
  });
13595
13603
  }
13596
13604
  function hasNestedCSSRule(prop) {
@@ -13991,7 +13999,7 @@ class ShadowDomManager {
13991
13999
  if (!isNativeShadowDom(shadowRoot2)) return;
13992
14000
  if (this.shadowDoms.has(shadowRoot2)) return;
13993
14001
  this.shadowDoms.add(shadowRoot2);
13994
- const observer = initMutationObserver(
14002
+ const { observer, buffer } = initMutationObserver(
13995
14003
  {
13996
14004
  ...this.bypassOptions,
13997
14005
  doc,
@@ -14001,7 +14009,15 @@ class ShadowDomManager {
14001
14009
  },
14002
14010
  shadowRoot2
14003
14011
  );
14004
- this.restoreHandlers.push(() => observer.disconnect());
14012
+ this.restoreHandlers.push(() => {
14013
+ observer.disconnect();
14014
+ buffer.destroy();
14015
+ buffer.reset();
14016
+ const index2 = mutationBuffers.indexOf(buffer);
14017
+ if (index2 !== -1) {
14018
+ mutationBuffers.splice(index2, 1);
14019
+ }
14020
+ });
14005
14021
  this.restoreHandlers.push(
14006
14022
  initScrollObserver({
14007
14023
  ...this.bypassOptions,
@@ -14411,7 +14427,7 @@ function initCanvasWebGLMutationObserver(cb, win, blockClass, blockSelector, dat
14411
14427
  handlers.forEach((h) => h());
14412
14428
  };
14413
14429
  }
14414
- 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';
14430
+ 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';
14415
14431
  const blob = typeof self !== "undefined" && self.Blob && new Blob([jsContent], { type: "text/javascript;charset=utf-8" });
14416
14432
  function WorkerWrapper(options) {
14417
14433
  let objURL;
@@ -14878,6 +14894,26 @@ function record(options = {}) {
14878
14894
  polyfill$1();
14879
14895
  let lastFullSnapshotEvent;
14880
14896
  let incrementalSnapshotCount = 0;
14897
+ const iframeObserverCleanups = /* @__PURE__ */ new Map();
14898
+ function cleanupDetachedIframeObservers() {
14899
+ for (const [iframeId, cleanup] of iframeObserverCleanups) {
14900
+ const iframe = mirror.getNode(iframeId);
14901
+ if (!iframe) {
14902
+ cleanup();
14903
+ iframeObserverCleanups.delete(iframeId);
14904
+ continue;
14905
+ }
14906
+ try {
14907
+ if (!iframe.contentDocument || !iframe.contentDocument.defaultView) {
14908
+ cleanup();
14909
+ iframeObserverCleanups.delete(iframeId);
14910
+ }
14911
+ } catch {
14912
+ cleanup();
14913
+ iframeObserverCleanups.delete(iframeId);
14914
+ }
14915
+ }
14916
+ }
14881
14917
  const eventProcessor = (e2) => {
14882
14918
  for (const plugin of plugins || []) {
14883
14919
  if (plugin.eventProcessor) {
@@ -14928,9 +14964,15 @@ function record(options = {}) {
14928
14964
  const addedIds = m.adds.length > 0 ? new Set(m.adds.map((add) => add.node.id)) : null;
14929
14965
  m.removes.forEach(({ id }) => {
14930
14966
  if (!addedIds || !addedIds.has(id)) {
14967
+ const cleanup = iframeObserverCleanups.get(id);
14968
+ if (cleanup) {
14969
+ cleanup();
14970
+ iframeObserverCleanups.delete(id);
14971
+ }
14931
14972
  iframeManager.removeIframeById(id);
14932
14973
  }
14933
14974
  });
14975
+ cleanupDetachedIframeObservers();
14934
14976
  }
14935
14977
  wrappedEmit({
14936
14978
  type: EventType.IncrementalSnapshot,
@@ -15218,7 +15260,12 @@ function record(options = {}) {
15218
15260
  };
15219
15261
  const loadListener = (iframeEl) => {
15220
15262
  try {
15221
- handlers.push(observe(iframeEl.contentDocument));
15263
+ const iframeId = mirror.getId(iframeEl);
15264
+ const cleanup = observe(iframeEl.contentDocument);
15265
+ handlers.push(cleanup);
15266
+ if (iframeId !== -1) {
15267
+ iframeObserverCleanups.set(iframeId, cleanup);
15268
+ }
15222
15269
  } catch (error) {
15223
15270
  console.warn(error);
15224
15271
  }
@@ -15260,6 +15307,7 @@ function record(options = {}) {
15260
15307
  processedNodeManager.destroy();
15261
15308
  iframeManager.removeLoadListener();
15262
15309
  iframeManager.destroy();
15310
+ iframeObserverCleanups.clear();
15263
15311
  mirror.reset();
15264
15312
  recording = false;
15265
15313
  unregisterErrorHandler();