@posthog/rrweb 0.0.25 → 0.0.27

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.
@@ -13251,6 +13251,7 @@ function initObservers(o2, hooks = {}) {
13251
13251
  selectionObserver();
13252
13252
  customElementObserver();
13253
13253
  pluginHandlers.forEach((h) => h());
13254
+ mutationBuffers.length = 0;
13254
13255
  });
13255
13256
  }
13256
13257
  function hasNestedCSSRule(prop) {
@@ -13337,6 +13338,8 @@ class IframeManager {
13337
13338
  __publicField(this, "loadListener");
13338
13339
  __publicField(this, "stylesheetManager");
13339
13340
  __publicField(this, "recordCrossOriginIframes");
13341
+ __publicField(this, "messageHandler");
13342
+ __publicField(this, "nestedIframeListeners", /* @__PURE__ */ new Map());
13340
13343
  this.mutationCb = options.mutationCb;
13341
13344
  this.wrappedEmit = options.wrappedEmit;
13342
13345
  this.stylesheetManager = options.stylesheetManager;
@@ -13347,8 +13350,9 @@ class IframeManager {
13347
13350
  )
13348
13351
  );
13349
13352
  this.mirror = options.mirror;
13353
+ this.messageHandler = this.handleMessage.bind(this);
13350
13354
  if (this.recordCrossOriginIframes) {
13351
- window.addEventListener("message", this.handleMessage.bind(this));
13355
+ window.addEventListener("message", this.messageHandler);
13352
13356
  }
13353
13357
  }
13354
13358
  addIframe(iframeEl) {
@@ -13359,8 +13363,11 @@ class IframeManager {
13359
13363
  addLoadListener(cb) {
13360
13364
  this.loadListener = cb;
13361
13365
  }
13366
+ removeLoadListener() {
13367
+ this.loadListener = void 0;
13368
+ }
13362
13369
  attachIframe(iframeEl, childSn) {
13363
- var _a2, _b;
13370
+ var _a2;
13364
13371
  this.mutationCb({
13365
13372
  adds: [
13366
13373
  {
@@ -13374,12 +13381,13 @@ class IframeManager {
13374
13381
  attributes: [],
13375
13382
  isAttachIframe: true
13376
13383
  });
13377
- if (this.recordCrossOriginIframes)
13378
- (_a2 = iframeEl.contentWindow) == null ? void 0 : _a2.addEventListener(
13379
- "message",
13380
- this.handleMessage.bind(this)
13381
- );
13382
- (_b = this.loadListener) == null ? void 0 : _b.call(this, iframeEl);
13384
+ const win = iframeEl.contentWindow;
13385
+ if (this.recordCrossOriginIframes && win && !this.nestedIframeListeners.has(win)) {
13386
+ const nestedHandler = this.handleMessage.bind(this);
13387
+ this.nestedIframeListeners.set(win, nestedHandler);
13388
+ win.addEventListener("message", nestedHandler);
13389
+ }
13390
+ (_a2 = this.loadListener) == null ? void 0 : _a2.call(this, iframeEl);
13383
13391
  if (iframeEl.contentDocument && iframeEl.contentDocument.adoptedStyleSheets && iframeEl.contentDocument.adoptedStyleSheets.length > 0)
13384
13392
  this.stylesheetManager.adoptStyleSheets(
13385
13393
  iframeEl.contentDocument.adoptedStyleSheets,
@@ -13557,6 +13565,15 @@ class IframeManager {
13557
13565
  });
13558
13566
  }
13559
13567
  }
13568
+ destroy() {
13569
+ if (this.recordCrossOriginIframes) {
13570
+ window.removeEventListener("message", this.messageHandler);
13571
+ }
13572
+ this.nestedIframeListeners.forEach((handler, contentWindow) => {
13573
+ contentWindow.removeEventListener("message", handler);
13574
+ });
13575
+ this.nestedIframeListeners.clear();
13576
+ }
13560
13577
  }
13561
13578
  class ShadowDomManager {
13562
13579
  constructor(options) {
@@ -14736,13 +14753,14 @@ function record(options = {}) {
14736
14753
  hooks
14737
14754
  );
14738
14755
  };
14739
- iframeManager.addLoadListener((iframeEl) => {
14756
+ const loadListener = (iframeEl) => {
14740
14757
  try {
14741
14758
  handlers.push(observe(iframeEl.contentDocument));
14742
14759
  } catch (error) {
14743
14760
  console.warn(error);
14744
14761
  }
14745
- });
14762
+ };
14763
+ iframeManager.addLoadListener(loadListener);
14746
14764
  const init = () => {
14747
14765
  takeFullSnapshot$1();
14748
14766
  handlers.push(observe(document));
@@ -14777,6 +14795,8 @@ function record(options = {}) {
14777
14795
  return () => {
14778
14796
  handlers.forEach((h) => h());
14779
14797
  processedNodeManager.destroy();
14798
+ iframeManager.removeLoadListener();
14799
+ iframeManager.destroy();
14780
14800
  recording = false;
14781
14801
  unregisterErrorHandler();
14782
14802
  };
@@ -15990,6 +16010,11 @@ class Replayer {
15990
16010
  __publicField(this, "lastSelectionData", null);
15991
16011
  __publicField(this, "constructedStyleMutations", []);
15992
16012
  __publicField(this, "adoptedStyleSheets", []);
16013
+ __publicField(this, "emitterHandlers", []);
16014
+ __publicField(this, "serviceSubscription");
16015
+ __publicField(this, "speedServiceSubscription");
16016
+ __publicField(this, "timeouts", /* @__PURE__ */ new Set());
16017
+ __publicField(this, "styleSheetLoadListeners", /* @__PURE__ */ new Map());
15993
16018
  __publicField(this, "handleResize", (dimension) => {
15994
16019
  this.iframe.style.display = "inherit";
15995
16020
  for (const el of [this.mouseTail, this.iframe]) {
@@ -16149,12 +16174,12 @@ class Replayer {
16149
16174
  this.handleResize = this.handleResize.bind(this);
16150
16175
  this.getCastFn = this.getCastFn.bind(this);
16151
16176
  this.applyEventsSynchronously = this.applyEventsSynchronously.bind(this);
16152
- this.emitter.on(ReplayerEvents.Resize, this.handleResize);
16177
+ this.addEmitterHandler(ReplayerEvents.Resize, this.handleResize);
16153
16178
  this.setupDom();
16154
16179
  for (const plugin of this.config.plugins || []) {
16155
16180
  if (plugin.getMirror) plugin.getMirror({ nodeMirror: this.mirror });
16156
16181
  }
16157
- this.emitter.on(ReplayerEvents.Flush, () => {
16182
+ const flushHandler = () => {
16158
16183
  if (this.usingVirtualDom) {
16159
16184
  const replayerHandler = {
16160
16185
  mirror: this.mirror,
@@ -16250,13 +16275,15 @@ class Replayer {
16250
16275
  this.applySelection(this.lastSelectionData);
16251
16276
  this.lastSelectionData = null;
16252
16277
  }
16253
- });
16254
- this.emitter.on(ReplayerEvents.PlayBack, () => {
16278
+ };
16279
+ this.addEmitterHandler(ReplayerEvents.Flush, flushHandler);
16280
+ const playBackHandler = () => {
16255
16281
  this.firstFullSnapshot = null;
16256
16282
  this.mirror.reset();
16257
16283
  this.styleMirror.reset();
16258
16284
  this.mediaManager.reset();
16259
- });
16285
+ };
16286
+ this.addEmitterHandler(ReplayerEvents.PlayBack, playBackHandler);
16260
16287
  const timer = new Timer([], {
16261
16288
  speed: this.config.speed
16262
16289
  });
@@ -16280,7 +16307,7 @@ class Replayer {
16280
16307
  }
16281
16308
  );
16282
16309
  this.service.start();
16283
- this.service.subscribe((state) => {
16310
+ this.serviceSubscription = this.service.subscribe((state) => {
16284
16311
  this.emitter.emit(ReplayerEvents.StateChange, {
16285
16312
  player: state
16286
16313
  });
@@ -16290,7 +16317,7 @@ class Replayer {
16290
16317
  timer
16291
16318
  });
16292
16319
  this.speedService.start();
16293
- this.speedService.subscribe((state) => {
16320
+ this.speedServiceSubscription = this.speedService.subscribe((state) => {
16294
16321
  this.emitter.emit(ReplayerEvents.StateChange, {
16295
16322
  speed: state
16296
16323
  });
@@ -16310,7 +16337,7 @@ class Replayer {
16310
16337
  );
16311
16338
  if (firstMeta) {
16312
16339
  const { width, height } = firstMeta.data;
16313
- setTimeout(() => {
16340
+ this.addTimeout(() => {
16314
16341
  this.emitter.emit(ReplayerEvents.Resize, {
16315
16342
  width,
16316
16343
  height
@@ -16318,7 +16345,7 @@ class Replayer {
16318
16345
  }, 0);
16319
16346
  }
16320
16347
  if (firstFullsnapshot) {
16321
- setTimeout(() => {
16348
+ this.addTimeout(() => {
16322
16349
  var _a2;
16323
16350
  if (this.firstFullSnapshot) {
16324
16351
  return;
@@ -16347,6 +16374,24 @@ class Replayer {
16347
16374
  this.emitter.off(event, handler);
16348
16375
  return this;
16349
16376
  }
16377
+ /**
16378
+ * Track emitter handlers for cleanup
16379
+ */
16380
+ addEmitterHandler(event, handler) {
16381
+ this.emitter.on(event, handler);
16382
+ this.emitterHandlers.push({ event, handler });
16383
+ }
16384
+ /**
16385
+ * Track timeouts for cleanup
16386
+ */
16387
+ addTimeout(callback, delay) {
16388
+ const timeout = setTimeout(() => {
16389
+ this.timeouts.delete(timeout);
16390
+ callback();
16391
+ }, delay);
16392
+ this.timeouts.add(timeout);
16393
+ return timeout;
16394
+ }
16350
16395
  setConfig(config) {
16351
16396
  Object.keys(config).forEach((key) => {
16352
16397
  config[key];
@@ -16449,10 +16494,31 @@ class Replayer {
16449
16494
  * Memory occupation can be released by removing all references to this replayer.
16450
16495
  */
16451
16496
  destroy() {
16497
+ var _a2, _b;
16498
+ if (!this.wrapper || !this.wrapper.parentNode) {
16499
+ return;
16500
+ }
16452
16501
  this.pause();
16502
+ this.emitterHandlers.forEach(({ event, handler }) => {
16503
+ this.emitter.off(event, handler);
16504
+ });
16505
+ this.emitterHandlers = [];
16506
+ (_a2 = this.serviceSubscription) == null ? void 0 : _a2.unsubscribe();
16507
+ (_b = this.speedServiceSubscription) == null ? void 0 : _b.unsubscribe();
16508
+ this.serviceSubscription = void 0;
16509
+ this.speedServiceSubscription = void 0;
16510
+ this.timeouts.forEach((timeout) => clearTimeout(timeout));
16511
+ this.timeouts.clear();
16512
+ this.styleSheetLoadListeners.forEach((handler, element) => {
16513
+ element.removeEventListener("load", handler);
16514
+ });
16515
+ this.styleSheetLoadListeners.clear();
16516
+ this.imageMap.clear();
16517
+ this.canvasEventMap.clear();
16453
16518
  this.mirror.reset();
16454
16519
  this.styleMirror.reset();
16455
16520
  this.mediaManager.reset();
16521
+ this.resetCache();
16456
16522
  this.config.root.removeChild(this.wrapper);
16457
16523
  this.emitter.emit(ReplayerEvents.Destroy);
16458
16524
  }