@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.
package/dist/rrweb.cjs CHANGED
@@ -13229,6 +13229,7 @@ function initObservers(o2, hooks = {}) {
13229
13229
  selectionObserver();
13230
13230
  customElementObserver();
13231
13231
  pluginHandlers.forEach((h) => h());
13232
+ mutationBuffers.length = 0;
13232
13233
  });
13233
13234
  }
13234
13235
  function hasNestedCSSRule(prop) {
@@ -13315,6 +13316,9 @@ class IframeManager {
13315
13316
  __publicField(this, "loadListener");
13316
13317
  __publicField(this, "stylesheetManager");
13317
13318
  __publicField(this, "recordCrossOriginIframes");
13319
+ __publicField(this, "messageHandler");
13320
+ // Map window to handler for cleanup - windows are browser-owned and won't prevent GC
13321
+ __publicField(this, "nestedIframeListeners", /* @__PURE__ */ new Map());
13318
13322
  this.mutationCb = options.mutationCb;
13319
13323
  this.wrappedEmit = options.wrappedEmit;
13320
13324
  this.stylesheetManager = options.stylesheetManager;
@@ -13325,8 +13329,9 @@ class IframeManager {
13325
13329
  )
13326
13330
  );
13327
13331
  this.mirror = options.mirror;
13332
+ this.messageHandler = this.handleMessage.bind(this);
13328
13333
  if (this.recordCrossOriginIframes) {
13329
- window.addEventListener("message", this.handleMessage.bind(this));
13334
+ window.addEventListener("message", this.messageHandler);
13330
13335
  }
13331
13336
  }
13332
13337
  addIframe(iframeEl) {
@@ -13337,8 +13342,11 @@ class IframeManager {
13337
13342
  addLoadListener(cb) {
13338
13343
  this.loadListener = cb;
13339
13344
  }
13345
+ removeLoadListener() {
13346
+ this.loadListener = void 0;
13347
+ }
13340
13348
  attachIframe(iframeEl, childSn) {
13341
- var _a2, _b;
13349
+ var _a2;
13342
13350
  this.mutationCb({
13343
13351
  adds: [
13344
13352
  {
@@ -13352,12 +13360,13 @@ class IframeManager {
13352
13360
  attributes: [],
13353
13361
  isAttachIframe: true
13354
13362
  });
13355
- if (this.recordCrossOriginIframes)
13356
- (_a2 = iframeEl.contentWindow) == null ? void 0 : _a2.addEventListener(
13357
- "message",
13358
- this.handleMessage.bind(this)
13359
- );
13360
- (_b = this.loadListener) == null ? void 0 : _b.call(this, iframeEl);
13363
+ const win = iframeEl.contentWindow;
13364
+ if (this.recordCrossOriginIframes && win && !this.nestedIframeListeners.has(win)) {
13365
+ const nestedHandler = this.handleMessage.bind(this);
13366
+ this.nestedIframeListeners.set(win, nestedHandler);
13367
+ win.addEventListener("message", nestedHandler);
13368
+ }
13369
+ (_a2 = this.loadListener) == null ? void 0 : _a2.call(this, iframeEl);
13361
13370
  if (iframeEl.contentDocument && iframeEl.contentDocument.adoptedStyleSheets && iframeEl.contentDocument.adoptedStyleSheets.length > 0)
13362
13371
  this.stylesheetManager.adoptStyleSheets(
13363
13372
  iframeEl.contentDocument.adoptedStyleSheets,
@@ -13535,6 +13544,15 @@ class IframeManager {
13535
13544
  });
13536
13545
  }
13537
13546
  }
13547
+ destroy() {
13548
+ if (this.recordCrossOriginIframes) {
13549
+ window.removeEventListener("message", this.messageHandler);
13550
+ }
13551
+ this.nestedIframeListeners.forEach((handler, contentWindow) => {
13552
+ contentWindow.removeEventListener("message", handler);
13553
+ });
13554
+ this.nestedIframeListeners.clear();
13555
+ }
13538
13556
  }
13539
13557
  class ShadowDomManager {
13540
13558
  constructor(options) {
@@ -14729,13 +14747,14 @@ function record(options = {}) {
14729
14747
  hooks
14730
14748
  );
14731
14749
  };
14732
- iframeManager.addLoadListener((iframeEl) => {
14750
+ const loadListener = (iframeEl) => {
14733
14751
  try {
14734
14752
  handlers.push(observe(iframeEl.contentDocument));
14735
14753
  } catch (error) {
14736
14754
  console.warn(error);
14737
14755
  }
14738
- });
14756
+ };
14757
+ iframeManager.addLoadListener(loadListener);
14739
14758
  const init = () => {
14740
14759
  takeFullSnapshot$1();
14741
14760
  handlers.push(observe(document));
@@ -14770,6 +14789,8 @@ function record(options = {}) {
14770
14789
  return () => {
14771
14790
  handlers.forEach((h) => h());
14772
14791
  processedNodeManager.destroy();
14792
+ iframeManager.removeLoadListener();
14793
+ iframeManager.destroy();
14773
14794
  recording = false;
14774
14795
  unregisterErrorHandler();
14775
14796
  };
@@ -15992,6 +16013,12 @@ class Replayer {
15992
16013
  __publicField(this, "constructedStyleMutations", []);
15993
16014
  // Similar to the reason for constructedStyleMutations.
15994
16015
  __publicField(this, "adoptedStyleSheets", []);
16016
+ // Track resources for cleanup
16017
+ __publicField(this, "emitterHandlers", []);
16018
+ __publicField(this, "serviceSubscription");
16019
+ __publicField(this, "speedServiceSubscription");
16020
+ __publicField(this, "timeouts", /* @__PURE__ */ new Set());
16021
+ __publicField(this, "styleSheetLoadListeners", /* @__PURE__ */ new Map());
15995
16022
  __publicField(this, "handleResize", (dimension) => {
15996
16023
  this.iframe.style.display = "inherit";
15997
16024
  for (const el of [this.mouseTail, this.iframe]) {
@@ -16151,12 +16178,12 @@ class Replayer {
16151
16178
  this.handleResize = this.handleResize.bind(this);
16152
16179
  this.getCastFn = this.getCastFn.bind(this);
16153
16180
  this.applyEventsSynchronously = this.applyEventsSynchronously.bind(this);
16154
- this.emitter.on(ReplayerEvents.Resize, this.handleResize);
16181
+ this.addEmitterHandler(ReplayerEvents.Resize, this.handleResize);
16155
16182
  this.setupDom();
16156
16183
  for (const plugin of this.config.plugins || []) {
16157
16184
  if (plugin.getMirror) plugin.getMirror({ nodeMirror: this.mirror });
16158
16185
  }
16159
- this.emitter.on(ReplayerEvents.Flush, () => {
16186
+ const flushHandler = () => {
16160
16187
  if (this.usingVirtualDom) {
16161
16188
  const replayerHandler = {
16162
16189
  mirror: this.mirror,
@@ -16252,13 +16279,15 @@ class Replayer {
16252
16279
  this.applySelection(this.lastSelectionData);
16253
16280
  this.lastSelectionData = null;
16254
16281
  }
16255
- });
16256
- this.emitter.on(ReplayerEvents.PlayBack, () => {
16282
+ };
16283
+ this.addEmitterHandler(ReplayerEvents.Flush, flushHandler);
16284
+ const playBackHandler = () => {
16257
16285
  this.firstFullSnapshot = null;
16258
16286
  this.mirror.reset();
16259
16287
  this.styleMirror.reset();
16260
16288
  this.mediaManager.reset();
16261
- });
16289
+ };
16290
+ this.addEmitterHandler(ReplayerEvents.PlayBack, playBackHandler);
16262
16291
  const timer = new Timer([], {
16263
16292
  speed: this.config.speed
16264
16293
  });
@@ -16282,7 +16311,7 @@ class Replayer {
16282
16311
  }
16283
16312
  );
16284
16313
  this.service.start();
16285
- this.service.subscribe((state) => {
16314
+ this.serviceSubscription = this.service.subscribe((state) => {
16286
16315
  this.emitter.emit(ReplayerEvents.StateChange, {
16287
16316
  player: state
16288
16317
  });
@@ -16292,7 +16321,7 @@ class Replayer {
16292
16321
  timer
16293
16322
  });
16294
16323
  this.speedService.start();
16295
- this.speedService.subscribe((state) => {
16324
+ this.speedServiceSubscription = this.speedService.subscribe((state) => {
16296
16325
  this.emitter.emit(ReplayerEvents.StateChange, {
16297
16326
  speed: state
16298
16327
  });
@@ -16312,7 +16341,7 @@ class Replayer {
16312
16341
  );
16313
16342
  if (firstMeta) {
16314
16343
  const { width, height } = firstMeta.data;
16315
- setTimeout(() => {
16344
+ this.addTimeout(() => {
16316
16345
  this.emitter.emit(ReplayerEvents.Resize, {
16317
16346
  width,
16318
16347
  height
@@ -16320,7 +16349,7 @@ class Replayer {
16320
16349
  }, 0);
16321
16350
  }
16322
16351
  if (firstFullsnapshot) {
16323
- setTimeout(() => {
16352
+ this.addTimeout(() => {
16324
16353
  var _a2;
16325
16354
  if (this.firstFullSnapshot) {
16326
16355
  return;
@@ -16349,6 +16378,24 @@ class Replayer {
16349
16378
  this.emitter.off(event, handler);
16350
16379
  return this;
16351
16380
  }
16381
+ /**
16382
+ * Track emitter handlers for cleanup
16383
+ */
16384
+ addEmitterHandler(event, handler) {
16385
+ this.emitter.on(event, handler);
16386
+ this.emitterHandlers.push({ event, handler });
16387
+ }
16388
+ /**
16389
+ * Track timeouts for cleanup
16390
+ */
16391
+ addTimeout(callback, delay) {
16392
+ const timeout = setTimeout(() => {
16393
+ this.timeouts.delete(timeout);
16394
+ callback();
16395
+ }, delay);
16396
+ this.timeouts.add(timeout);
16397
+ return timeout;
16398
+ }
16352
16399
  setConfig(config) {
16353
16400
  Object.keys(config).forEach((key) => {
16354
16401
  config[key];
@@ -16451,10 +16498,31 @@ class Replayer {
16451
16498
  * Memory occupation can be released by removing all references to this replayer.
16452
16499
  */
16453
16500
  destroy() {
16501
+ var _a2, _b;
16502
+ if (!this.wrapper || !this.wrapper.parentNode) {
16503
+ return;
16504
+ }
16454
16505
  this.pause();
16506
+ this.emitterHandlers.forEach(({ event, handler }) => {
16507
+ this.emitter.off(event, handler);
16508
+ });
16509
+ this.emitterHandlers = [];
16510
+ (_a2 = this.serviceSubscription) == null ? void 0 : _a2.unsubscribe();
16511
+ (_b = this.speedServiceSubscription) == null ? void 0 : _b.unsubscribe();
16512
+ this.serviceSubscription = void 0;
16513
+ this.speedServiceSubscription = void 0;
16514
+ this.timeouts.forEach((timeout) => clearTimeout(timeout));
16515
+ this.timeouts.clear();
16516
+ this.styleSheetLoadListeners.forEach((handler, element) => {
16517
+ element.removeEventListener("load", handler);
16518
+ });
16519
+ this.styleSheetLoadListeners.clear();
16520
+ this.imageMap.clear();
16521
+ this.canvasEventMap.clear();
16455
16522
  this.mirror.reset();
16456
16523
  this.styleMirror.reset();
16457
16524
  this.mediaManager.reset();
16525
+ this.resetCache();
16458
16526
  this.config.root.removeChild(this.wrapper);
16459
16527
  this.emitter.emit(ReplayerEvents.Destroy);
16460
16528
  }