@highlight-run/rrweb 2.0.0-lambda.7 → 2.0.0-lambda.9

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
@@ -1873,6 +1873,7 @@ function requireStringifier$1() {
1873
1873
  hasRequiredStringifier$1 = 1;
1874
1874
  const STYLE_TAG = /(<)(\/?style\b)/gi;
1875
1875
  const COMMENT_OPEN = /(<)(!--)/g;
1876
+ const AT_NAME_END = /[\t\n\f\r "#'()/;[\\\]{}]/;
1876
1877
  function escapeHTMLInCSS(str) {
1877
1878
  if (typeof str !== "string") return str;
1878
1879
  if (!str.includes("<")) return str;
@@ -1898,12 +1899,13 @@ function requireStringifier$1() {
1898
1899
  function atruleStart(str, node2) {
1899
1900
  let name = "@" + node2.name;
1900
1901
  let params = node2.params ? str.rawValue(node2, "params") : "";
1901
- if (typeof node2.raws.afterName !== "undefined") {
1902
- name += node2.raws.afterName;
1903
- } else if (params) {
1904
- name += " ";
1902
+ let afterName = node2.raws.afterName;
1903
+ if (typeof afterName === "undefined") {
1904
+ afterName = params ? " " : "";
1905
+ } else if (afterName === "" && params && !AT_NAME_END.test(params[0])) {
1906
+ afterName = " ";
1905
1907
  }
1906
- return name + params;
1908
+ return name + afterName + params;
1907
1909
  }
1908
1910
  function pushBody(str, stack, node2) {
1909
1911
  let nodes = node2.nodes;
@@ -1915,10 +1917,15 @@ function requireStringifier$1() {
1915
1917
  let semicolon = str.raw(node2, "semicolon");
1916
1918
  let isDocument = node2.type === "document";
1917
1919
  for (let i2 = nodes.length - 1; i2 >= 0; i2--) {
1920
+ let child = nodes[i2];
1921
+ let childSemicolon = last !== i2 || semicolon;
1922
+ if (!childSemicolon && i2 < nodes.length - 1 && (child.type === "atrule" && !child.nodes || child.type === "decl" && child.prop.startsWith("--"))) {
1923
+ childSemicolon = true;
1924
+ }
1918
1925
  stack.push({
1919
1926
  document: isDocument,
1920
- node: nodes[i2],
1921
- semicolon: last !== i2 || semicolon
1927
+ node: child,
1928
+ semicolon: childSemicolon
1922
1929
  });
1923
1930
  }
1924
1931
  }
@@ -2209,6 +2216,9 @@ function requireStringifier$1() {
2209
2216
  return value;
2210
2217
  }
2211
2218
  root(node2) {
2219
+ if (node2.source && node2.source.input.hasBOM) {
2220
+ this.builder("\uFEFF", node2, "start");
2221
+ }
2212
2222
  this.body(node2);
2213
2223
  if (node2.raws.after) {
2214
2224
  let after = node2.raws.after;
@@ -3281,15 +3291,12 @@ function requirePreviousMap$1() {
3281
3291
  }
3282
3292
  loadFile(path, cssFile, trusted) {
3283
3293
  if (!trusted && !this.unsafeMap) {
3284
- if (!/\.map$/i.test(path)) {
3294
+ if (!/\.map$/i.test(path)) return void 0;
3295
+ if (!cssFile) return void 0;
3296
+ let rel = relative(dirname(cssFile), path);
3297
+ if (rel === ".." || rel.startsWith(".." + sep) || isAbsolute(rel)) {
3285
3298
  return void 0;
3286
3299
  }
3287
- if (cssFile) {
3288
- let relativePath = relative(dirname(cssFile), path);
3289
- if (relativePath === ".." || relativePath.startsWith(".." + sep) || isAbsolute(relativePath)) {
3290
- return void 0;
3291
- }
3292
- }
3293
3300
  }
3294
3301
  this.root = dirname(path);
3295
3302
  if (existsSync(path)) {
@@ -3661,6 +3668,7 @@ function requireList$1() {
3661
3668
  return list.split(string, spaces);
3662
3669
  },
3663
3670
  split(string, separators, last) {
3671
+ if (!string) return [];
3664
3672
  let array = [];
3665
3673
  let current = "";
3666
3674
  let split = false;
@@ -4947,11 +4955,16 @@ var hasRequiredWarning$1;
4947
4955
  function requireWarning$1() {
4948
4956
  if (hasRequiredWarning$1) return warning$1;
4949
4957
  hasRequiredWarning$1 = 1;
4958
+ let Container = requireContainer$1();
4959
+ let { my } = requireSymbols$1();
4950
4960
  class Warning {
4951
4961
  constructor(text, opts = {}) {
4952
4962
  this.type = "warning";
4953
4963
  this.text = text;
4954
4964
  if (opts.node && opts.node.source) {
4965
+ if (!opts.node[my]) {
4966
+ Container.rebuild(opts.node);
4967
+ }
4955
4968
  let range = opts.node.rangeBy(opts);
4956
4969
  this.line = range.start.line;
4957
4970
  this.column = range.start.column;
@@ -5461,14 +5474,19 @@ function requireLazyResult$1() {
5461
5474
  }
5462
5475
  if (visit2.iterator !== 0) {
5463
5476
  let iterator = visit2.iterator;
5477
+ if (visit2.descending) {
5478
+ visit2.descending = false;
5479
+ node2.indexes[iterator] += 1;
5480
+ }
5464
5481
  let child;
5465
5482
  while (child = node2.nodes[node2.indexes[iterator]]) {
5466
- node2.indexes[iterator] += 1;
5467
5483
  if (!child[isClean]) {
5468
5484
  child[isClean] = true;
5485
+ visit2.descending = true;
5469
5486
  stack.push(toStack(child));
5470
5487
  return;
5471
5488
  }
5489
+ node2.indexes[iterator] += 1;
5472
5490
  }
5473
5491
  visit2.iterator = 0;
5474
5492
  delete node2.indexes[iterator];
@@ -5498,12 +5516,16 @@ function requireLazyResult$1() {
5498
5516
  let visitNode = visit2.node;
5499
5517
  if (visit2.iterator !== 0) {
5500
5518
  let iterator = visit2.iterator;
5519
+ if (visit2.descending) {
5520
+ visit2.descending = false;
5521
+ visitNode.indexes[iterator] += 1;
5522
+ }
5501
5523
  let child;
5502
5524
  let descended = false;
5503
5525
  while (child = visitNode.nodes[visitNode.indexes[iterator]]) {
5504
- visitNode.indexes[iterator] += 1;
5505
5526
  if (!child[isClean]) {
5506
5527
  child[isClean] = true;
5528
+ visit2.descending = true;
5507
5529
  stack.push({
5508
5530
  eventIndex: 0,
5509
5531
  events: getEvents(child),
@@ -5513,6 +5535,7 @@ function requireLazyResult$1() {
5513
5535
  descended = true;
5514
5536
  break;
5515
5537
  }
5538
+ visitNode.indexes[iterator] += 1;
5516
5539
  }
5517
5540
  if (descended) continue;
5518
5541
  visit2.iterator = 0;
@@ -5675,7 +5698,7 @@ function requireProcessor$1() {
5675
5698
  let Root = requireRoot$1();
5676
5699
  class Processor {
5677
5700
  constructor(plugins = []) {
5678
- this.version = "8.5.19";
5701
+ this.version = "8.5.25";
5679
5702
  this.plugins = this.normalize(plugins);
5680
5703
  }
5681
5704
  normalize(plugins) {
@@ -6542,6 +6565,7 @@ function requireStringifier() {
6542
6565
  hasRequiredStringifier = 1;
6543
6566
  const STYLE_TAG = /(<)(\/?style\b)/gi;
6544
6567
  const COMMENT_OPEN = /(<)(!--)/g;
6568
+ const AT_NAME_END = /[\t\n\f\r "#'()/;[\\\]{}]/;
6545
6569
  function escapeHTMLInCSS(str) {
6546
6570
  if (typeof str !== "string") return str;
6547
6571
  if (!str.includes("<")) return str;
@@ -6567,12 +6591,13 @@ function requireStringifier() {
6567
6591
  function atruleStart(str, node2) {
6568
6592
  let name = "@" + node2.name;
6569
6593
  let params = node2.params ? str.rawValue(node2, "params") : "";
6570
- if (typeof node2.raws.afterName !== "undefined") {
6571
- name += node2.raws.afterName;
6572
- } else if (params) {
6573
- name += " ";
6594
+ let afterName = node2.raws.afterName;
6595
+ if (typeof afterName === "undefined") {
6596
+ afterName = params ? " " : "";
6597
+ } else if (afterName === "" && params && !AT_NAME_END.test(params[0])) {
6598
+ afterName = " ";
6574
6599
  }
6575
- return name + params;
6600
+ return name + afterName + params;
6576
6601
  }
6577
6602
  function pushBody(str, stack, node2) {
6578
6603
  let nodes = node2.nodes;
@@ -6584,10 +6609,15 @@ function requireStringifier() {
6584
6609
  let semicolon = str.raw(node2, "semicolon");
6585
6610
  let isDocument = node2.type === "document";
6586
6611
  for (let i2 = nodes.length - 1; i2 >= 0; i2--) {
6612
+ let child = nodes[i2];
6613
+ let childSemicolon = last !== i2 || semicolon;
6614
+ if (!childSemicolon && i2 < nodes.length - 1 && (child.type === "atrule" && !child.nodes || child.type === "decl" && child.prop.startsWith("--"))) {
6615
+ childSemicolon = true;
6616
+ }
6587
6617
  stack.push({
6588
6618
  document: isDocument,
6589
- node: nodes[i2],
6590
- semicolon: last !== i2 || semicolon
6619
+ node: child,
6620
+ semicolon: childSemicolon
6591
6621
  });
6592
6622
  }
6593
6623
  }
@@ -6878,6 +6908,9 @@ function requireStringifier() {
6878
6908
  return value;
6879
6909
  }
6880
6910
  root(node2) {
6911
+ if (node2.source && node2.source.input.hasBOM) {
6912
+ this.builder("\uFEFF", node2, "start");
6913
+ }
6881
6914
  this.body(node2);
6882
6915
  if (node2.raws.after) {
6883
6916
  let after = node2.raws.after;
@@ -7950,15 +7983,12 @@ function requirePreviousMap() {
7950
7983
  }
7951
7984
  loadFile(path, cssFile, trusted) {
7952
7985
  if (!trusted && !this.unsafeMap) {
7953
- if (!/\.map$/i.test(path)) {
7986
+ if (!/\.map$/i.test(path)) return void 0;
7987
+ if (!cssFile) return void 0;
7988
+ let rel = relative(dirname(cssFile), path);
7989
+ if (rel === ".." || rel.startsWith(".." + sep) || isAbsolute(rel)) {
7954
7990
  return void 0;
7955
7991
  }
7956
- if (cssFile) {
7957
- let relativePath = relative(dirname(cssFile), path);
7958
- if (relativePath === ".." || relativePath.startsWith(".." + sep) || isAbsolute(relativePath)) {
7959
- return void 0;
7960
- }
7961
- }
7962
7992
  }
7963
7993
  this.root = dirname(path);
7964
7994
  if (existsSync(path)) {
@@ -8330,6 +8360,7 @@ function requireList() {
8330
8360
  return list.split(string, spaces);
8331
8361
  },
8332
8362
  split(string, separators, last) {
8363
+ if (!string) return [];
8333
8364
  let array = [];
8334
8365
  let current = "";
8335
8366
  let split = false;
@@ -9616,11 +9647,16 @@ var hasRequiredWarning;
9616
9647
  function requireWarning() {
9617
9648
  if (hasRequiredWarning) return warning;
9618
9649
  hasRequiredWarning = 1;
9650
+ let Container = requireContainer();
9651
+ let { my } = requireSymbols();
9619
9652
  class Warning {
9620
9653
  constructor(text, opts = {}) {
9621
9654
  this.type = "warning";
9622
9655
  this.text = text;
9623
9656
  if (opts.node && opts.node.source) {
9657
+ if (!opts.node[my]) {
9658
+ Container.rebuild(opts.node);
9659
+ }
9624
9660
  let range = opts.node.rangeBy(opts);
9625
9661
  this.line = range.start.line;
9626
9662
  this.column = range.start.column;
@@ -10130,14 +10166,19 @@ function requireLazyResult() {
10130
10166
  }
10131
10167
  if (visit2.iterator !== 0) {
10132
10168
  let iterator = visit2.iterator;
10169
+ if (visit2.descending) {
10170
+ visit2.descending = false;
10171
+ node2.indexes[iterator] += 1;
10172
+ }
10133
10173
  let child;
10134
10174
  while (child = node2.nodes[node2.indexes[iterator]]) {
10135
- node2.indexes[iterator] += 1;
10136
10175
  if (!child[isClean]) {
10137
10176
  child[isClean] = true;
10177
+ visit2.descending = true;
10138
10178
  stack.push(toStack(child));
10139
10179
  return;
10140
10180
  }
10181
+ node2.indexes[iterator] += 1;
10141
10182
  }
10142
10183
  visit2.iterator = 0;
10143
10184
  delete node2.indexes[iterator];
@@ -10167,12 +10208,16 @@ function requireLazyResult() {
10167
10208
  let visitNode = visit2.node;
10168
10209
  if (visit2.iterator !== 0) {
10169
10210
  let iterator = visit2.iterator;
10211
+ if (visit2.descending) {
10212
+ visit2.descending = false;
10213
+ visitNode.indexes[iterator] += 1;
10214
+ }
10170
10215
  let child;
10171
10216
  let descended = false;
10172
10217
  while (child = visitNode.nodes[visitNode.indexes[iterator]]) {
10173
- visitNode.indexes[iterator] += 1;
10174
10218
  if (!child[isClean]) {
10175
10219
  child[isClean] = true;
10220
+ visit2.descending = true;
10176
10221
  stack.push({
10177
10222
  eventIndex: 0,
10178
10223
  events: getEvents(child),
@@ -10182,6 +10227,7 @@ function requireLazyResult() {
10182
10227
  descended = true;
10183
10228
  break;
10184
10229
  }
10230
+ visitNode.indexes[iterator] += 1;
10185
10231
  }
10186
10232
  if (descended) continue;
10187
10233
  visit2.iterator = 0;
@@ -10344,7 +10390,7 @@ function requireProcessor() {
10344
10390
  let Root = requireRoot();
10345
10391
  class Processor {
10346
10392
  constructor(plugins = []) {
10347
- this.version = "8.5.19";
10393
+ this.version = "8.5.25";
10348
10394
  this.plugins = this.normalize(plugins);
10349
10395
  }
10350
10396
  normalize(plugins) {
@@ -13626,66 +13672,142 @@ function getIdAndStyleId(sheet, mirror2, styleMirror) {
13626
13672
  id
13627
13673
  };
13628
13674
  }
13629
- function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetManager }, { win }) {
13675
+ function restorePatchedMethod(target, key, ours, restoreTo) {
13676
+ if (target[key] === ours) {
13677
+ target[key] = restoreTo;
13678
+ }
13679
+ }
13680
+ const MAX_CSSOM_REPATCH_ATTEMPTS = 5;
13681
+ function initStyleSheetObserver({
13682
+ styleSheetRuleCb,
13683
+ mirror: mirror2,
13684
+ stylesheetManager,
13685
+ doc,
13686
+ styleSheetResyncInterval
13687
+ }, { win }) {
13630
13688
  if (!win.CSSStyleSheet || !win.CSSStyleSheet.prototype) {
13631
13689
  return () => {
13632
13690
  };
13633
13691
  }
13634
- const insertRule = win.CSSStyleSheet.prototype.insertRule;
13635
- win.CSSStyleSheet.prototype.insertRule = new Proxy(insertRule, {
13692
+ const reportedRuleCounts = /* @__PURE__ */ new WeakMap();
13693
+ const unreconcilableSheets = /* @__PURE__ */ new WeakSet();
13694
+ let probing = false;
13695
+ let probeInsertObserved = false;
13696
+ let probeDeleteObserved = false;
13697
+ let probeSheet;
13698
+ let stopped = false;
13699
+ let insideInsertRule = false;
13700
+ let insideDeleteRule = false;
13701
+ const noteReportedRules = (sheet, delta) => {
13702
+ const state = reportedRuleCounts.get(sheet);
13703
+ if (state) {
13704
+ state.reported = Math.max(0, state.reported + delta);
13705
+ state.everSeen = Math.max(state.everSeen, state.reported);
13706
+ }
13707
+ };
13708
+ const patchInsertRule = (target) => new Proxy(target, {
13636
13709
  apply: callbackWrapper(
13637
- (target, thisArg, argumentsList) => {
13710
+ (nativeFn, thisArg, argumentsList) => {
13711
+ if (probing) {
13712
+ probeInsertObserved = true;
13713
+ return nativeFn.apply(thisArg, argumentsList);
13714
+ }
13715
+ if (stopped || insideInsertRule) {
13716
+ return nativeFn.apply(thisArg, argumentsList);
13717
+ }
13638
13718
  const [rule2, index2] = argumentsList;
13639
13719
  const { id, styleId } = getIdAndStyleId(
13640
13720
  thisArg,
13641
13721
  mirror2,
13642
13722
  stylesheetManager.styleMirror
13643
13723
  );
13644
- if (id && id !== -1 || styleId && styleId !== -1) {
13724
+ const reported = id && id !== -1 || styleId && styleId !== -1;
13725
+ if (reported) {
13645
13726
  styleSheetRuleCb({
13646
13727
  id,
13647
13728
  styleId,
13648
13729
  adds: [{ rule: rule2, index: index2 }]
13649
13730
  });
13650
13731
  }
13651
- return target.apply(thisArg, argumentsList);
13732
+ insideInsertRule = true;
13733
+ let result2;
13734
+ try {
13735
+ result2 = nativeFn.apply(thisArg, argumentsList);
13736
+ } finally {
13737
+ insideInsertRule = false;
13738
+ }
13739
+ if (reported) {
13740
+ noteReportedRules(thisArg, 1);
13741
+ }
13742
+ return result2;
13652
13743
  }
13653
13744
  )
13654
13745
  });
13655
- win.CSSStyleSheet.prototype.addRule = function(selector, styleBlock, index2 = this.cssRules.length) {
13656
- const rule2 = `${selector} { ${styleBlock} }`;
13657
- return win.CSSStyleSheet.prototype.insertRule.apply(this, [rule2, index2]);
13658
- };
13659
- const deleteRule = win.CSSStyleSheet.prototype.deleteRule;
13660
- win.CSSStyleSheet.prototype.deleteRule = new Proxy(deleteRule, {
13746
+ const patchDeleteRule = (target) => new Proxy(target, {
13661
13747
  apply: callbackWrapper(
13662
- (target, thisArg, argumentsList) => {
13748
+ (nativeFn, thisArg, argumentsList) => {
13749
+ if (probing) {
13750
+ probeDeleteObserved = true;
13751
+ return nativeFn.apply(thisArg, argumentsList);
13752
+ }
13753
+ if (stopped || insideDeleteRule) {
13754
+ return nativeFn.apply(thisArg, argumentsList);
13755
+ }
13663
13756
  const [index2] = argumentsList;
13664
13757
  const { id, styleId } = getIdAndStyleId(
13665
13758
  thisArg,
13666
13759
  mirror2,
13667
13760
  stylesheetManager.styleMirror
13668
13761
  );
13669
- if (id && id !== -1 || styleId && styleId !== -1) {
13762
+ const reported = id && id !== -1 || styleId && styleId !== -1;
13763
+ if (reported) {
13670
13764
  styleSheetRuleCb({
13671
13765
  id,
13672
13766
  styleId,
13673
13767
  removes: [{ index: index2 }]
13674
13768
  });
13675
13769
  }
13676
- return target.apply(thisArg, argumentsList);
13770
+ insideDeleteRule = true;
13771
+ let result2;
13772
+ try {
13773
+ result2 = nativeFn.apply(thisArg, argumentsList);
13774
+ } finally {
13775
+ insideDeleteRule = false;
13776
+ }
13777
+ if (reported) {
13778
+ noteReportedRules(thisArg, -1);
13779
+ }
13780
+ return result2;
13677
13781
  }
13678
13782
  )
13679
13783
  });
13680
- win.CSSStyleSheet.prototype.removeRule = function(index2) {
13784
+ const insertRule = win.CSSStyleSheet.prototype.insertRule;
13785
+ let insertRuleProxy = patchInsertRule(insertRule);
13786
+ let restoreInsertRuleTo = insertRule;
13787
+ win.CSSStyleSheet.prototype.insertRule = insertRuleProxy;
13788
+ const addRule = win.CSSStyleSheet.prototype.addRule;
13789
+ const addRuleShim = function(selector, styleBlock, index2 = this.cssRules.length) {
13790
+ const rule2 = `${selector} { ${styleBlock} }`;
13791
+ return win.CSSStyleSheet.prototype.insertRule.apply(this, [rule2, index2]);
13792
+ };
13793
+ win.CSSStyleSheet.prototype.addRule = addRuleShim;
13794
+ const deleteRule = win.CSSStyleSheet.prototype.deleteRule;
13795
+ let deleteRuleProxy = patchDeleteRule(deleteRule);
13796
+ let restoreDeleteRuleTo = deleteRule;
13797
+ win.CSSStyleSheet.prototype.deleteRule = deleteRuleProxy;
13798
+ const removeRule = win.CSSStyleSheet.prototype.removeRule;
13799
+ const removeRuleShim = function(index2) {
13681
13800
  return win.CSSStyleSheet.prototype.deleteRule.apply(this, [index2]);
13682
13801
  };
13802
+ win.CSSStyleSheet.prototype.removeRule = removeRuleShim;
13683
13803
  let replace;
13804
+ let replaceProxy;
13684
13805
  if (win.CSSStyleSheet.prototype.replace) {
13685
13806
  replace = win.CSSStyleSheet.prototype.replace;
13686
- win.CSSStyleSheet.prototype.replace = new Proxy(replace, {
13807
+ replaceProxy = new Proxy(replace, {
13687
13808
  apply: callbackWrapper(
13688
13809
  (target, thisArg, argumentsList) => {
13810
+ if (stopped) return target.apply(thisArg, argumentsList);
13689
13811
  const [text] = argumentsList;
13690
13812
  const { id, styleId } = getIdAndStyleId(
13691
13813
  thisArg,
@@ -13703,13 +13825,16 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetM
13703
13825
  }
13704
13826
  )
13705
13827
  });
13828
+ win.CSSStyleSheet.prototype.replace = replaceProxy;
13706
13829
  }
13707
13830
  let replaceSync;
13831
+ let replaceSyncProxy;
13708
13832
  if (win.CSSStyleSheet.prototype.replaceSync) {
13709
13833
  replaceSync = win.CSSStyleSheet.prototype.replaceSync;
13710
- win.CSSStyleSheet.prototype.replaceSync = new Proxy(replaceSync, {
13834
+ replaceSyncProxy = new Proxy(replaceSync, {
13711
13835
  apply: callbackWrapper(
13712
13836
  (target, thisArg, argumentsList) => {
13837
+ if (stopped) return target.apply(thisArg, argumentsList);
13713
13838
  const [text] = argumentsList;
13714
13839
  const { id, styleId } = getIdAndStyleId(
13715
13840
  thisArg,
@@ -13727,6 +13852,7 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetM
13727
13852
  }
13728
13853
  )
13729
13854
  });
13855
+ win.CSSStyleSheet.prototype.replaceSync = replaceSyncProxy;
13730
13856
  }
13731
13857
  const supportedNestedCSSRuleTypes = {};
13732
13858
  if (canMonkeyPatchNestedCSSRule("CSSGroupingRule")) {
@@ -13743,6 +13869,7 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetM
13743
13869
  }
13744
13870
  }
13745
13871
  const unmodifiedFunctions = {};
13872
+ const nestedProxies = {};
13746
13873
  Object.entries(supportedNestedCSSRuleTypes).forEach(([typeKey, type]) => {
13747
13874
  unmodifiedFunctions[typeKey] = {
13748
13875
  // eslint-disable-next-line @typescript-eslint/unbound-method
@@ -13750,11 +13877,13 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetM
13750
13877
  // eslint-disable-next-line @typescript-eslint/unbound-method
13751
13878
  deleteRule: type.prototype.deleteRule
13752
13879
  };
13753
- type.prototype.insertRule = new Proxy(
13880
+ nestedProxies[typeKey] = {};
13881
+ nestedProxies[typeKey].insertRule = new Proxy(
13754
13882
  unmodifiedFunctions[typeKey].insertRule,
13755
13883
  {
13756
13884
  apply: callbackWrapper(
13757
13885
  (target, thisArg, argumentsList) => {
13886
+ if (stopped) return target.apply(thisArg, argumentsList);
13758
13887
  const [rule2, index2] = argumentsList;
13759
13888
  const { id, styleId } = getIdAndStyleId(
13760
13889
  thisArg.parentStyleSheet,
@@ -13782,11 +13911,12 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetM
13782
13911
  )
13783
13912
  }
13784
13913
  );
13785
- type.prototype.deleteRule = new Proxy(
13914
+ nestedProxies[typeKey].deleteRule = new Proxy(
13786
13915
  unmodifiedFunctions[typeKey].deleteRule,
13787
13916
  {
13788
13917
  apply: callbackWrapper(
13789
13918
  (target, thisArg, argumentsList) => {
13919
+ if (stopped) return target.apply(thisArg, argumentsList);
13790
13920
  const [index2] = argumentsList;
13791
13921
  const { id, styleId } = getIdAndStyleId(
13792
13922
  thisArg.parentStyleSheet,
@@ -13807,15 +13937,148 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetM
13807
13937
  )
13808
13938
  }
13809
13939
  );
13940
+ type.prototype.insertRule = nestedProxies[typeKey].insertRule;
13941
+ type.prototype.deleteRule = nestedProxies[typeKey].deleteRule;
13810
13942
  });
13943
+ const captureIsHealthy = () => {
13944
+ probing = true;
13945
+ probeInsertObserved = false;
13946
+ probeDeleteObserved = false;
13947
+ try {
13948
+ const probe = probeSheet ?? (probeSheet = new win.CSSStyleSheet());
13949
+ probe.insertRule(":root {}", 0);
13950
+ probe.deleteRule(0);
13951
+ } catch (error) {
13952
+ return {
13953
+ insertRule: win.CSSStyleSheet.prototype.insertRule === insertRuleProxy,
13954
+ deleteRule: win.CSSStyleSheet.prototype.deleteRule === deleteRuleProxy
13955
+ };
13956
+ } finally {
13957
+ probing = false;
13958
+ }
13959
+ return {
13960
+ insertRule: probeInsertObserved,
13961
+ deleteRule: probeDeleteObserved
13962
+ };
13963
+ };
13964
+ let repatchAttempts = 0;
13965
+ const repatch = (health) => {
13966
+ if (repatchAttempts >= MAX_CSSOM_REPATCH_ATTEMPTS) return;
13967
+ repatchAttempts += 1;
13968
+ if (!health.insertRule) {
13969
+ restoreInsertRuleTo = win.CSSStyleSheet.prototype.insertRule;
13970
+ insertRuleProxy = patchInsertRule(restoreInsertRuleTo);
13971
+ win.CSSStyleSheet.prototype.insertRule = insertRuleProxy;
13972
+ }
13973
+ if (!health.deleteRule) {
13974
+ restoreDeleteRuleTo = win.CSSStyleSheet.prototype.deleteRule;
13975
+ deleteRuleProxy = patchDeleteRule(restoreDeleteRuleTo);
13976
+ win.CSSStyleSheet.prototype.deleteRule = deleteRuleProxy;
13977
+ }
13978
+ };
13979
+ const resyncCssomStyleSheets = (trusted) => {
13980
+ for (let i2 = 0; i2 < doc.styleSheets.length; i2++) {
13981
+ const sheet = doc.styleSheets[i2];
13982
+ if (unreconcilableSheets.has(sheet)) continue;
13983
+ const owner = sheet.ownerNode;
13984
+ if (!owner || toLowerCase(owner.nodeName) !== "style") continue;
13985
+ if ((owner.textContent || "").trim().length) continue;
13986
+ const id = mirror2.getId(owner);
13987
+ if (!id || id === -1) continue;
13988
+ let rules2;
13989
+ try {
13990
+ rules2 = sheet.cssRules;
13991
+ } catch (error) {
13992
+ continue;
13993
+ }
13994
+ const live = rules2.length;
13995
+ let state = reportedRuleCounts.get(sheet);
13996
+ if (!state) {
13997
+ if (Array.from(rules2).some((rule2) => isCSSImportRule(rule2))) {
13998
+ unreconcilableSheets.add(sheet);
13999
+ continue;
14000
+ }
14001
+ state = { reported: live, everSeen: live };
14002
+ reportedRuleCounts.set(sheet, state);
14003
+ if (trusted) continue;
14004
+ replaceReplayerCopy(id, state, rules2);
14005
+ continue;
14006
+ }
14007
+ state.everSeen = Math.max(state.everSeen, live);
14008
+ if (live === state.reported) continue;
14009
+ if (live > state.reported) {
14010
+ const adds = [];
14011
+ for (let index2 = state.reported; index2 < live; index2++) {
14012
+ adds.push({ rule: rules2[index2].cssText, index: index2 });
14013
+ }
14014
+ styleSheetRuleCb({ id, adds });
14015
+ state.reported = live;
14016
+ } else {
14017
+ replaceReplayerCopy(id, state, rules2);
14018
+ }
14019
+ }
14020
+ };
14021
+ function replaceReplayerCopy(id, state, rules2) {
14022
+ const removes = [];
14023
+ for (let index2 = state.everSeen - 1; index2 >= 0; index2--) {
14024
+ removes.push({ index: index2 });
14025
+ }
14026
+ if (removes.length) styleSheetRuleCb({ id, removes });
14027
+ styleSheetRuleCb({
14028
+ id,
14029
+ adds: Array.from(rules2, (rule2, index2) => ({
14030
+ rule: rule2.cssText,
14031
+ index: index2
14032
+ }))
14033
+ });
14034
+ state.reported = rules2.length;
14035
+ state.everSeen = rules2.length;
14036
+ }
14037
+ let resyncTimer;
14038
+ if (styleSheetResyncInterval > 0) {
14039
+ resyncTimer = win.setInterval(
14040
+ callbackWrapper(() => {
14041
+ const health = captureIsHealthy();
14042
+ const healthy = health.insertRule && health.deleteRule;
14043
+ if (!healthy) repatch(health);
14044
+ resyncCssomStyleSheets(healthy);
14045
+ }),
14046
+ styleSheetResyncInterval
14047
+ );
14048
+ }
13811
14049
  return callbackWrapper(() => {
13812
- win.CSSStyleSheet.prototype.insertRule = insertRule;
13813
- win.CSSStyleSheet.prototype.deleteRule = deleteRule;
13814
- replace && (win.CSSStyleSheet.prototype.replace = replace);
13815
- replaceSync && (win.CSSStyleSheet.prototype.replaceSync = replaceSync);
14050
+ if (resyncTimer !== void 0) win.clearInterval(resyncTimer);
14051
+ stopped = true;
14052
+ const proto = win.CSSStyleSheet.prototype;
14053
+ restorePatchedMethod(
14054
+ proto,
14055
+ "insertRule",
14056
+ insertRuleProxy,
14057
+ restoreInsertRuleTo
14058
+ );
14059
+ restorePatchedMethod(
14060
+ proto,
14061
+ "deleteRule",
14062
+ deleteRuleProxy,
14063
+ restoreDeleteRuleTo
14064
+ );
14065
+ restorePatchedMethod(proto, "addRule", addRuleShim, addRule);
14066
+ restorePatchedMethod(proto, "removeRule", removeRuleShim, removeRule);
14067
+ replaceProxy && restorePatchedMethod(proto, "replace", replaceProxy, replace);
14068
+ replaceSyncProxy && restorePatchedMethod(proto, "replaceSync", replaceSyncProxy, replaceSync);
13816
14069
  Object.entries(supportedNestedCSSRuleTypes).forEach(([typeKey, type]) => {
13817
- type.prototype.insertRule = unmodifiedFunctions[typeKey].insertRule;
13818
- type.prototype.deleteRule = unmodifiedFunctions[typeKey].deleteRule;
14070
+ restorePatchedMethod(
14071
+ type.prototype,
14072
+ "insertRule",
14073
+ nestedProxies[typeKey].insertRule,
14074
+ unmodifiedFunctions[typeKey].insertRule
14075
+ );
14076
+ restorePatchedMethod(
14077
+ type.prototype,
14078
+ "deleteRule",
14079
+ nestedProxies[typeKey].deleteRule,
14080
+ unmodifiedFunctions[typeKey].deleteRule
14081
+ );
13819
14082
  });
13820
14083
  });
13821
14084
  }
@@ -15583,6 +15846,7 @@ function record(options = {}) {
15583
15846
  keepIframeSrcFn = () => false,
15584
15847
  privacySetting = "default",
15585
15848
  ignoreCSSAttributes = /* @__PURE__ */ new Set([]),
15849
+ styleSheetResyncInterval = 2e3,
15586
15850
  errorHandler: errorHandler2,
15587
15851
  logger
15588
15852
  } = options;
@@ -15961,6 +16225,7 @@ function record(options = {}) {
15961
16225
  processedNodeManager,
15962
16226
  canvasManager,
15963
16227
  ignoreCSSAttributes,
16228
+ styleSheetResyncInterval,
15964
16229
  privacySetting,
15965
16230
  plugins: ((_a3 = plugins == null ? void 0 : plugins.filter((p) => p.observer)) == null ? void 0 : _a3.map((p) => ({
15966
16231
  observer: p.observer,
@@ -16847,12 +17112,36 @@ function variableListFor(ctx, ctor) {
16847
17112
  }
16848
17113
  return contextMap.get(ctor);
16849
17114
  }
16850
- function deserializeArg(imageMap, ctx, preload) {
17115
+ const canvasArgConstructors = /* @__PURE__ */ new Set([
17116
+ "Int8Array",
17117
+ "Int16Array",
17118
+ "Int32Array",
17119
+ "Uint8Array",
17120
+ "Uint8ClampedArray",
17121
+ "Uint16Array",
17122
+ "Uint32Array",
17123
+ "Float32Array",
17124
+ "Float64Array",
17125
+ "DataView",
17126
+ "ImageData",
17127
+ // normally serialized as base64, but reachable in `args` form through
17128
+ // recordings made by older clients and through nested `DataView` args.
17129
+ "ArrayBuffer",
17130
+ // wraps nested args in recordings made by older clients — see the
17131
+ // `preloadAllImages` tests for the shape.
17132
+ "Array"
17133
+ ]);
17134
+ function deserializeArg(imageMap, ctx, preload, enforceCanvasArgAllowlist = false) {
16851
17135
  return async (arg) => {
16852
17136
  if (arg && typeof arg === "object" && "rr_type" in arg) {
16853
17137
  if (preload) preload.isUnchanged = false;
16854
17138
  if (arg.rr_type === "ImageBitmap" && "args" in arg) {
16855
- const args = await deserializeArg(imageMap, ctx, preload)(arg.args);
17139
+ const args = await deserializeArg(
17140
+ imageMap,
17141
+ ctx,
17142
+ preload,
17143
+ enforceCanvasArgAllowlist
17144
+ )(arg.args);
16856
17145
  return await createImageBitmap.apply(null, args);
16857
17146
  } else if ("index" in arg) {
16858
17147
  if (preload || ctx === null) return arg;
@@ -16860,10 +17149,18 @@ function deserializeArg(imageMap, ctx, preload) {
16860
17149
  return variableListFor(ctx, name)[index2];
16861
17150
  } else if ("args" in arg) {
16862
17151
  const { rr_type: name, args } = arg;
17152
+ if (enforceCanvasArgAllowlist && !canvasArgConstructors.has(name)) {
17153
+ console.warn(
17154
+ `[replayer] refusing to construct canvas arg of unknown type: ${name}`
17155
+ );
17156
+ return null;
17157
+ }
16863
17158
  const ctor = window[name];
16864
17159
  return new ctor(
16865
17160
  ...await Promise.all(
16866
- args.map(deserializeArg(imageMap, ctx, preload))
17161
+ args.map(
17162
+ deserializeArg(imageMap, ctx, preload, enforceCanvasArgAllowlist)
17163
+ )
16867
17164
  )
16868
17165
  );
16869
17166
  } else if ("base64" in arg) {
@@ -16880,7 +17177,9 @@ function deserializeArg(imageMap, ctx, preload) {
16880
17177
  }
16881
17178
  } else if ("data" in arg && arg.rr_type === "Blob") {
16882
17179
  const blobContents = await Promise.all(
16883
- arg.data.map(deserializeArg(imageMap, ctx, preload))
17180
+ arg.data.map(
17181
+ deserializeArg(imageMap, ctx, preload, enforceCanvasArgAllowlist)
17182
+ )
16884
17183
  );
16885
17184
  const blob2 = new Blob(blobContents, {
16886
17185
  type: arg.type
@@ -16889,7 +17188,9 @@ function deserializeArg(imageMap, ctx, preload) {
16889
17188
  }
16890
17189
  } else if (Array.isArray(arg)) {
16891
17190
  const result2 = await Promise.all(
16892
- arg.map(deserializeArg(imageMap, ctx, preload))
17191
+ arg.map(
17192
+ deserializeArg(imageMap, ctx, preload, enforceCanvasArgAllowlist)
17193
+ )
16893
17194
  );
16894
17195
  return result2;
16895
17196
  }
@@ -16930,7 +17231,8 @@ async function webglMutation({
16930
17231
  target,
16931
17232
  type,
16932
17233
  imageMap,
16933
- errorHandler: errorHandler2
17234
+ errorHandler: errorHandler2,
17235
+ enforceCanvasArgAllowlist
16934
17236
  }) {
16935
17237
  try {
16936
17238
  const ctx = getContext(target, type);
@@ -16941,7 +17243,9 @@ async function webglMutation({
16941
17243
  }
16942
17244
  const original = ctx[mutation.property];
16943
17245
  const args = await Promise.all(
16944
- mutation.args.map(deserializeArg(imageMap, ctx))
17246
+ mutation.args.map(
17247
+ deserializeArg(imageMap, ctx, void 0, enforceCanvasArgAllowlist)
17248
+ )
16945
17249
  );
16946
17250
  const result2 = original.apply(ctx, args);
16947
17251
  saveToWebGLVarMap(ctx, result2);
@@ -16956,7 +17260,8 @@ async function canvasMutation$1({
16956
17260
  mutations,
16957
17261
  target,
16958
17262
  imageMap,
16959
- errorHandler: errorHandler2
17263
+ errorHandler: errorHandler2,
17264
+ enforceCanvasArgAllowlist
16960
17265
  }) {
16961
17266
  const ctx = target.getContext("2d");
16962
17267
  if (!ctx) {
@@ -16966,7 +17271,11 @@ async function canvasMutation$1({
16966
17271
  wrapCanvasContextDrawImage(ctx);
16967
17272
  const mutationArgsPromises = mutations.map(
16968
17273
  async (mutation) => {
16969
- return Promise.all(mutation.args.map(deserializeArg(imageMap, ctx)));
17274
+ return Promise.all(
17275
+ mutation.args.map(
17276
+ deserializeArg(imageMap, ctx, void 0, enforceCanvasArgAllowlist)
17277
+ )
17278
+ );
16970
17279
  }
16971
17280
  );
16972
17281
  const args = await Promise.all(mutationArgsPromises);
@@ -16996,7 +17305,8 @@ async function canvasMutation({
16996
17305
  target,
16997
17306
  imageMap,
16998
17307
  canvasEventMap,
16999
- errorHandler: errorHandler2
17308
+ errorHandler: errorHandler2,
17309
+ enforceCanvasArgAllowlist
17000
17310
  }) {
17001
17311
  try {
17002
17312
  const precomputedMutation = canvasEventMap.get(event) || mutation;
@@ -17009,7 +17319,8 @@ async function canvasMutation({
17009
17319
  type: mutation.type,
17010
17320
  target,
17011
17321
  imageMap,
17012
- errorHandler: errorHandler2
17322
+ errorHandler: errorHandler2,
17323
+ enforceCanvasArgAllowlist
17013
17324
  });
17014
17325
  }
17015
17326
  return;
@@ -17019,7 +17330,8 @@ async function canvasMutation({
17019
17330
  mutations: commands,
17020
17331
  target,
17021
17332
  imageMap,
17022
- errorHandler: errorHandler2
17333
+ errorHandler: errorHandler2,
17334
+ enforceCanvasArgAllowlist
17023
17335
  });
17024
17336
  } catch (error) {
17025
17337
  errorHandler2(mutation, error);
@@ -17462,6 +17774,7 @@ class Replayer {
17462
17774
  insertStyleRules: [],
17463
17775
  triggerFocus: true,
17464
17776
  UNSAFE_replayCanvas: false,
17777
+ enforceCanvasArgAllowlist: false,
17465
17778
  pauseAnimation: true,
17466
17779
  mouseTail: defaultMouseTailConfig,
17467
17780
  useVirtualDom: true,
@@ -17490,7 +17803,8 @@ class Replayer {
17490
17803
  target,
17491
17804
  imageMap: this.imageMap,
17492
17805
  canvasEventMap: this.canvasEventMap,
17493
- errorHandler: this.warnCanvasMutationFailed.bind(this)
17806
+ errorHandler: this.warnCanvasMutationFailed.bind(this),
17807
+ enforceCanvasArgAllowlist: this.config.enforceCanvasArgAllowlist
17494
17808
  });
17495
17809
  },
17496
17810
  applyInput: this.applyInput.bind(this),
@@ -18202,7 +18516,14 @@ class Replayer {
18202
18516
  const commands = await Promise.all(
18203
18517
  data.commands.map(async (c2) => {
18204
18518
  const args = await Promise.all(
18205
- c2.args.map(deserializeArg(this.imageMap, null, status))
18519
+ c2.args.map(
18520
+ deserializeArg(
18521
+ this.imageMap,
18522
+ null,
18523
+ status,
18524
+ this.config.enforceCanvasArgAllowlist
18525
+ )
18526
+ )
18206
18527
  );
18207
18528
  return { ...c2, args };
18208
18529
  })
@@ -18211,7 +18532,14 @@ class Replayer {
18211
18532
  this.canvasEventMap.set(event, { ...data, commands });
18212
18533
  } else {
18213
18534
  const args = await Promise.all(
18214
- data.args.map(deserializeArg(this.imageMap, null, status))
18535
+ data.args.map(
18536
+ deserializeArg(
18537
+ this.imageMap,
18538
+ null,
18539
+ status,
18540
+ this.config.enforceCanvasArgAllowlist
18541
+ )
18542
+ )
18215
18543
  );
18216
18544
  if (status.isUnchanged === false)
18217
18545
  this.canvasEventMap.set(event, { ...data, args });
@@ -18424,7 +18752,8 @@ class Replayer {
18424
18752
  target,
18425
18753
  imageMap: this.imageMap,
18426
18754
  canvasEventMap: this.canvasEventMap,
18427
- errorHandler: this.warnCanvasMutationFailed.bind(this)
18755
+ errorHandler: this.warnCanvasMutationFailed.bind(this),
18756
+ enforceCanvasArgAllowlist: this.config.enforceCanvasArgAllowlist
18428
18757
  });
18429
18758
  }
18430
18759
  break;
@@ -19147,20 +19476,531 @@ class Replayer {
19147
19476
  this.config.logger.log(REPLAY_CONSOLE_PREFIX, ...args);
19148
19477
  }
19149
19478
  }
19479
+ const RRWEB_EMBEDDED_CHANNEL = "rrweb-embedded";
19480
+ const RRWEB_EMBEDDED_PROTOCOL_VERSION = 1;
19481
+ const SERIALIZABLE_CONFIG_KEYS = [
19482
+ "speed",
19483
+ "maxSpeed",
19484
+ "loadTimeout",
19485
+ "skipInactive",
19486
+ "inactivePeriodThreshold",
19487
+ "showWarning",
19488
+ "showDebug",
19489
+ "blockClass",
19490
+ "liveMode",
19491
+ "insertStyleRules",
19492
+ "triggerFocus",
19493
+ "UNSAFE_replayCanvas",
19494
+ "enforceCanvasArgAllowlist",
19495
+ "cspContent",
19496
+ "pauseAnimation",
19497
+ "mouseTail",
19498
+ "useVirtualDom",
19499
+ "inactiveThreshold",
19500
+ "inactiveSkipTime"
19501
+ ];
19502
+ function pickSerializableConfig(config) {
19503
+ const out = {};
19504
+ if (config && typeof config === "object") {
19505
+ for (const key of SERIALIZABLE_CONFIG_KEYS) {
19506
+ const value = config[key];
19507
+ if (value !== void 0 && typeof value !== "function") {
19508
+ out[key] = value;
19509
+ }
19510
+ }
19511
+ }
19512
+ return out;
19513
+ }
19514
+ function wrap(message) {
19515
+ return {
19516
+ channel: RRWEB_EMBEDDED_CHANNEL,
19517
+ version: RRWEB_EMBEDDED_PROTOCOL_VERSION,
19518
+ message
19519
+ };
19520
+ }
19521
+ function isEnvelope(data) {
19522
+ if (!data || typeof data !== "object") return false;
19523
+ const e2 = data;
19524
+ return e2.channel === RRWEB_EMBEDDED_CHANNEL && e2.version === RRWEB_EMBEDDED_PROTOCOL_VERSION && !!e2.message && typeof e2.message === "object" && typeof e2.message.type === "string";
19525
+ }
19526
+ const PAYLOAD_EVENTS = /* @__PURE__ */ new Set([
19527
+ ReplayerEvents.Resize,
19528
+ ReplayerEvents.EventCast,
19529
+ ReplayerEvents.CustomEvent
19530
+ ]);
19531
+ class EmbeddedReplayerHost {
19532
+ constructor(options = {}) {
19533
+ __publicField(this, "root");
19534
+ __publicField(this, "parentWindow");
19535
+ __publicField(this, "timeUpdateIntervalMs");
19536
+ __publicField(this, "expectedParentOrigin");
19537
+ __publicField(this, "replayer", null);
19538
+ __publicField(this, "playing", false);
19539
+ __publicField(this, "timer", null);
19540
+ __publicField(this, "started", false);
19541
+ /**
19542
+ * Last layout the parent asked for. Retained because each `Replayer` builds
19543
+ * its own wrapper element, so a re-init would otherwise drop the scaling and
19544
+ * render the replay at 1:1 in the corner.
19545
+ */
19546
+ __publicField(this, "layout", null);
19547
+ __publicField(this, "onMessage", (event) => {
19548
+ if (event.source !== this.parentWindow) return;
19549
+ if (this.expectedParentOrigin === null) return;
19550
+ if (event.origin !== this.expectedParentOrigin) return;
19551
+ if (!isEnvelope(event.data)) return;
19552
+ try {
19553
+ this.handle(event.data.message);
19554
+ } catch (err) {
19555
+ this.post({
19556
+ type: "error",
19557
+ message: err instanceof Error ? err.message : String(err)
19558
+ });
19559
+ }
19560
+ });
19561
+ this.root = options.root ?? document.body;
19562
+ this.parentWindow = options.parentWindow ?? window.parent;
19563
+ this.timeUpdateIntervalMs = options.timeUpdateIntervalMs ?? 50;
19564
+ this.expectedParentOrigin = options.expectedParentOrigin ?? new URLSearchParams(location.search).get("parentOrigin") ?? null;
19565
+ }
19566
+ /** Install the message listener and announce readiness to the parent. */
19567
+ start() {
19568
+ if (this.started) return;
19569
+ this.started = true;
19570
+ if (this.expectedParentOrigin === null) {
19571
+ console.warn(
19572
+ "[rrweb-embedded] no parentOrigin configured; all incoming messages will be ignored"
19573
+ );
19574
+ }
19575
+ window.addEventListener("message", this.onMessage);
19576
+ this.post({ type: "ready" });
19577
+ }
19578
+ /** Tear everything down (also invoked on a `destroy` command). */
19579
+ stop() {
19580
+ var _a2;
19581
+ window.removeEventListener("message", this.onMessage);
19582
+ this.setPlaying(false);
19583
+ (_a2 = this.replayer) == null ? void 0 : _a2.destroy();
19584
+ this.replayer = null;
19585
+ this.started = false;
19586
+ }
19587
+ handle(command) {
19588
+ var _a2, _b, _c, _d, _e, _f, _g;
19589
+ switch (command.type) {
19590
+ case "ping":
19591
+ this.post({ type: "ready" });
19592
+ return;
19593
+ case "init":
19594
+ this.init(command.events, command.config, command.autoplay);
19595
+ return;
19596
+ case "play":
19597
+ (_a2 = this.replayer) == null ? void 0 : _a2.play(command.timeOffset ?? 0);
19598
+ this.setPlaying(true);
19599
+ return;
19600
+ case "pause":
19601
+ (_b = this.replayer) == null ? void 0 : _b.pause(command.timeOffset);
19602
+ this.setPlaying(false);
19603
+ this.postTime();
19604
+ return;
19605
+ case "resume":
19606
+ (_c = this.replayer) == null ? void 0 : _c.resume(command.timeOffset ?? 0);
19607
+ this.setPlaying(true);
19608
+ return;
19609
+ case "setLayout":
19610
+ this.layout = {
19611
+ scale: command.scale,
19612
+ anchor: command.anchor ?? "center"
19613
+ };
19614
+ this.applyLayout();
19615
+ this.postDimensions();
19616
+ return;
19617
+ case "setConfig":
19618
+ (_d = this.replayer) == null ? void 0 : _d.setConfig(pickSerializableConfig(command.config));
19619
+ return;
19620
+ case "replaceEvents":
19621
+ if (this.replayer) {
19622
+ this.replayer.replaceEvents(command.events);
19623
+ this.postInitialized();
19624
+ }
19625
+ return;
19626
+ case "addEvent":
19627
+ (_e = this.replayer) == null ? void 0 : _e.addEvent(command.event);
19628
+ return;
19629
+ case "enableInteract":
19630
+ (_f = this.replayer) == null ? void 0 : _f.enableInteract();
19631
+ return;
19632
+ case "disableInteract":
19633
+ (_g = this.replayer) == null ? void 0 : _g.disableInteract();
19634
+ return;
19635
+ case "destroy":
19636
+ this.stop();
19637
+ return;
19638
+ }
19639
+ }
19640
+ init(events, config, autoplay) {
19641
+ if (this.replayer) {
19642
+ this.setPlaying(false);
19643
+ this.replayer.destroy();
19644
+ }
19645
+ const replayerConfig = {
19646
+ ...pickSerializableConfig(config),
19647
+ root: this.root
19648
+ };
19649
+ this.replayer = new Replayer(events, replayerConfig);
19650
+ this.wireEvents(this.replayer);
19651
+ this.applyLayout();
19652
+ this.postInitialized();
19653
+ this.postDimensions();
19654
+ if (autoplay) {
19655
+ this.replayer.play(0);
19656
+ this.setPlaying(true);
19657
+ }
19658
+ }
19659
+ /**
19660
+ * Translate the parent's layout intent into styles on the replay wrapper.
19661
+ *
19662
+ * Mirrors what an embedder would otherwise apply from its own stylesheet:
19663
+ * `transform-origin: top left` with `left: 50%` to center horizontally, and
19664
+ * either `top: 50%` + a -50% Y translate to center vertically, or `top: 0`
19665
+ * with no Y translate to anchor at the top edge.
19666
+ */
19667
+ applyLayout() {
19668
+ var _a2;
19669
+ const wrapper = (_a2 = this.replayer) == null ? void 0 : _a2.wrapper;
19670
+ if (!wrapper || !this.layout) return;
19671
+ const { scale, anchor } = this.layout;
19672
+ const top = anchor === "top";
19673
+ wrapper.style.position = "absolute";
19674
+ wrapper.style.transformOrigin = "top left";
19675
+ wrapper.style.left = "50%";
19676
+ wrapper.style.top = top ? "0" : "50%";
19677
+ wrapper.style.transform = top ? `scale(${scale}) translate(-50%, 0)` : `scale(${scale}) translate(-50%, -50%)`;
19678
+ }
19679
+ /** Report the wrapper's rendered geometry; the parent cannot measure it. */
19680
+ postDimensions() {
19681
+ var _a2;
19682
+ const wrapper = (_a2 = this.replayer) == null ? void 0 : _a2.wrapper;
19683
+ if (!wrapper) return;
19684
+ const rect = wrapper.getBoundingClientRect();
19685
+ this.post({
19686
+ type: "dimensions",
19687
+ width: rect.width,
19688
+ height: rect.height,
19689
+ top: rect.top,
19690
+ left: rect.left
19691
+ });
19692
+ }
19693
+ /** Push the stable getters (metadata, activity intervals) to the parent. */
19694
+ postInitialized() {
19695
+ if (!this.replayer) return;
19696
+ this.post({
19697
+ type: "initialized",
19698
+ metadata: this.replayer.getMetaData(),
19699
+ activityIntervals: this.replayer.getActivityIntervals()
19700
+ });
19701
+ }
19702
+ wireEvents(replayer) {
19703
+ for (const name of Object.values(ReplayerEvents)) {
19704
+ replayer.on(name, (payload) => {
19705
+ if (name === ReplayerEvents.Finish) {
19706
+ this.setPlaying(false);
19707
+ this.postTime();
19708
+ }
19709
+ if (name === ReplayerEvents.Resize) {
19710
+ this.postDimensions();
19711
+ }
19712
+ this.post(
19713
+ PAYLOAD_EVENTS.has(name) && payload !== void 0 ? { type: "replayer-event", event: name, payload } : { type: "replayer-event", event: name }
19714
+ );
19715
+ });
19716
+ }
19717
+ }
19718
+ /* --- current-time telemetry ------------------------------------------- */
19719
+ setPlaying(playing) {
19720
+ if (this.playing === playing) return;
19721
+ this.playing = playing;
19722
+ if (playing) this.startTimePump();
19723
+ else this.stopTimePump();
19724
+ }
19725
+ startTimePump() {
19726
+ if (this.timer !== null) return;
19727
+ this.timer = setInterval(() => this.postTime(), this.timeUpdateIntervalMs);
19728
+ }
19729
+ /**
19730
+ * Push the current playback position across the bridge.
19731
+ *
19732
+ * The parent cannot read the position synchronously — it lives in this realm
19733
+ * behind an origin boundary — so the client's `getCurrentTime()` is only ever
19734
+ * as fresh as the last push. While playing, the pump keeps it current. When
19735
+ * playback stops the pump stops too, so the last pumped value would be up to
19736
+ * one interval stale; callers that seek from it (`play(getCurrentTime())` to
19737
+ * resume) would drift backwards. Pausing and finishing therefore push one
19738
+ * final, settled value.
19739
+ */
19740
+ postTime() {
19741
+ if (!this.replayer) return;
19742
+ this.post({ type: "time", currentTime: this.replayer.getCurrentTime() });
19743
+ }
19744
+ stopTimePump() {
19745
+ if (this.timer !== null) {
19746
+ clearInterval(this.timer);
19747
+ this.timer = null;
19748
+ }
19749
+ }
19750
+ post(message) {
19751
+ this.parentWindow.postMessage(
19752
+ wrap(message),
19753
+ this.expectedParentOrigin ?? "*"
19754
+ );
19755
+ }
19756
+ }
19757
+ function startEmbeddedReplayerHost(options) {
19758
+ const host2 = new EmbeddedReplayerHost(options);
19759
+ host2.start();
19760
+ return host2;
19761
+ }
19762
+ class EmbeddedReplayerClient {
19763
+ constructor(iframe, options = {}) {
19764
+ __publicField(this, "iframe");
19765
+ __publicField(this, "hostOrigin");
19766
+ __publicField(this, "listeners", /* @__PURE__ */ new Map());
19767
+ __publicField(this, "metadata", null);
19768
+ __publicField(this, "activityIntervals", []);
19769
+ __publicField(this, "dimensions", null);
19770
+ __publicField(this, "lastCurrentTime", 0);
19771
+ __publicField(this, "ready", false);
19772
+ __publicField(this, "readyResolvers", []);
19773
+ __publicField(this, "disposed", false);
19774
+ /**
19775
+ * Commands issued before the host handshakes. A command posted while the
19776
+ * iframe is still on its initial `about:blank` (which carries the PARENT's
19777
+ * origin) is rejected by the browser as an origin mismatch and lost — the
19778
+ * viewer calls `setLayout` on mount, well before the host boots. Buffer until
19779
+ * `ready`, then flush; by then the frame is on the host origin.
19780
+ */
19781
+ __publicField(this, "pending", []);
19782
+ __publicField(this, "onMessage", (event) => {
19783
+ if (event.source !== this.iframe.contentWindow) return;
19784
+ if (!isEnvelope(event.data)) return;
19785
+ this.handle(event.data.message);
19786
+ });
19787
+ this.iframe = iframe;
19788
+ this.hostOrigin = options.hostOrigin ?? "*";
19789
+ window.addEventListener("message", this.onMessage);
19790
+ this.probe();
19791
+ }
19792
+ /** Resolves once the host iframe has loaded and announced readiness. */
19793
+ whenReady() {
19794
+ if (this.ready) return Promise.resolve();
19795
+ return new Promise((resolve) => this.readyResolvers.push(resolve));
19796
+ }
19797
+ /* --- commands --------------------------------------------------------- */
19798
+ init(events, config, autoplay = false) {
19799
+ this.send({ type: "init", events, config, autoplay });
19800
+ }
19801
+ play(timeOffset) {
19802
+ this.send({ type: "play", timeOffset });
19803
+ }
19804
+ pause(timeOffset) {
19805
+ this.send({ type: "pause", timeOffset });
19806
+ }
19807
+ resume(timeOffset) {
19808
+ this.send({ type: "resume", timeOffset });
19809
+ }
19810
+ setConfig(config) {
19811
+ this.send({ type: "setConfig", config });
19812
+ }
19813
+ /**
19814
+ * Scale and position the replay. Compute `scale` from your own container size
19815
+ * and the recorded viewport, as you would when driving a local `Replayer`;
19816
+ * the host applies it, since the wrapper element is not reachable from here.
19817
+ * The layout is retained across re-inits.
19818
+ */
19819
+ setLayout(scale, anchor) {
19820
+ this.send({ type: "setLayout", scale, anchor });
19821
+ }
19822
+ replaceEvents(events) {
19823
+ this.send({ type: "replaceEvents", events });
19824
+ }
19825
+ addEvent(event) {
19826
+ this.send({ type: "addEvent", event });
19827
+ }
19828
+ enableInteract() {
19829
+ this.send({ type: "enableInteract" });
19830
+ }
19831
+ disableInteract() {
19832
+ this.send({ type: "disableInteract" });
19833
+ }
19834
+ /** Tear down: destroys the host replayer and detaches the listener. */
19835
+ destroy() {
19836
+ if (this.disposed) return;
19837
+ this.disposed = true;
19838
+ try {
19839
+ this.send({ type: "destroy" });
19840
+ } finally {
19841
+ window.removeEventListener("message", this.onMessage);
19842
+ this.listeners.clear();
19843
+ }
19844
+ }
19845
+ /* --- event surface ---------------------------------------------------- */
19846
+ on(event, listener) {
19847
+ let set = this.listeners.get(event);
19848
+ if (!set) {
19849
+ set = /* @__PURE__ */ new Set();
19850
+ this.listeners.set(event, set);
19851
+ }
19852
+ set.add(listener);
19853
+ }
19854
+ off(event, listener) {
19855
+ var _a2;
19856
+ (_a2 = this.listeners.get(event)) == null ? void 0 : _a2.delete(listener);
19857
+ }
19858
+ /* --- getters ---------------------------------------------------------- */
19859
+ // Cached getters mirroring the local Replayer's synchronous ones. Metadata
19860
+ // and activity intervals arrive on `initialized` (re-sent on replaceEvents);
19861
+ // current time is streamed by the host while playing.
19862
+ /** Last-known current time (pushed by the host while playing). */
19863
+ getCurrentTime() {
19864
+ return this.lastCurrentTime;
19865
+ }
19866
+ getMetaData() {
19867
+ return this.metadata;
19868
+ }
19869
+ getActivityIntervals() {
19870
+ return this.activityIntervals;
19871
+ }
19872
+ /**
19873
+ * Rendered geometry of the replay, in the host document's coordinate space —
19874
+ * the cross-origin stand-in for `replayer.wrapper.getBoundingClientRect()`.
19875
+ * Null until the host has reported it (listen for `'dimensions'`).
19876
+ */
19877
+ getDimensions() {
19878
+ return this.dimensions;
19879
+ }
19880
+ /* --- internals -------------------------------------------------------- */
19881
+ send(command) {
19882
+ if (!this.ready) {
19883
+ this.pending.push(command);
19884
+ return;
19885
+ }
19886
+ this.postToHost(command);
19887
+ }
19888
+ postToHost(command) {
19889
+ const target = this.iframe.contentWindow;
19890
+ if (!target) return;
19891
+ target.postMessage(wrap(command), this.hostOrigin);
19892
+ }
19893
+ flushPending() {
19894
+ const queued = this.pending;
19895
+ this.pending = [];
19896
+ queued.forEach((command) => this.postToHost(command));
19897
+ }
19898
+ /** Data-free handshake probe; see the note in the constructor. */
19899
+ probe() {
19900
+ var _a2;
19901
+ (_a2 = this.iframe.contentWindow) == null ? void 0 : _a2.postMessage(wrap({ type: "ping" }), "*");
19902
+ }
19903
+ handle(message) {
19904
+ switch (message.type) {
19905
+ case "ready":
19906
+ this.ready = true;
19907
+ this.flushPending();
19908
+ this.readyResolvers.forEach((r2) => r2());
19909
+ this.readyResolvers = [];
19910
+ return;
19911
+ case "initialized":
19912
+ this.metadata = message.metadata;
19913
+ this.activityIntervals = message.activityIntervals;
19914
+ this.emit("initialized", message.metadata);
19915
+ return;
19916
+ case "replayer-event":
19917
+ this.emit(message.event, message.payload);
19918
+ return;
19919
+ case "time":
19920
+ this.lastCurrentTime = message.currentTime;
19921
+ this.emit("time", message.currentTime);
19922
+ return;
19923
+ case "dimensions":
19924
+ this.dimensions = {
19925
+ width: message.width,
19926
+ height: message.height,
19927
+ top: message.top,
19928
+ left: message.left
19929
+ };
19930
+ this.emit("dimensions", this.dimensions);
19931
+ return;
19932
+ case "error":
19933
+ this.emit("error", message.message);
19934
+ return;
19935
+ }
19936
+ }
19937
+ emit(event, payload) {
19938
+ var _a2;
19939
+ (_a2 = this.listeners.get(event)) == null ? void 0 : _a2.forEach((listener) => listener(payload));
19940
+ }
19941
+ }
19942
+ function originOf(url) {
19943
+ try {
19944
+ return new URL(url).origin;
19945
+ } catch {
19946
+ return "'self'";
19947
+ }
19948
+ }
19949
+ function buildHostDocument(options) {
19950
+ const scriptOrigin = originOf(options.scriptUrl);
19951
+ const styleSources = [
19952
+ "'unsafe-inline'",
19953
+ scriptOrigin,
19954
+ ...options.extraStyleSources ?? []
19955
+ ].join(" ");
19956
+ const csp = [
19957
+ `default-src 'none'`,
19958
+ `script-src ${scriptOrigin}`,
19959
+ `style-src ${styleSources}`,
19960
+ `img-src * data: blob:`,
19961
+ `font-src * data:`,
19962
+ `media-src * data: blob:`,
19963
+ `frame-src *`,
19964
+ `connect-src 'none'`,
19965
+ `worker-src 'none'`
19966
+ ].join("; ");
19967
+ const styleTag = options.styleUrl ? `<link rel="stylesheet" href="${escapeAttr(options.styleUrl)}">` : "";
19968
+ return `<!DOCTYPE html>
19969
+ <html>
19970
+ <head>
19971
+ <meta charset="utf-8">
19972
+ <meta http-equiv="Content-Security-Policy" content="${escapeAttr(csp)}">
19973
+ <style>html,body{margin:0;padding:0;height:100%;overflow:hidden;background:transparent}</style>
19974
+ ${styleTag}
19975
+ <script type="module" src="${escapeAttr(options.scriptUrl)}"><\/script>
19976
+ </head>
19977
+ <body></body>
19978
+ </html>`;
19979
+ }
19980
+ function escapeAttr(value) {
19981
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
19982
+ }
19150
19983
  const { addCustomEvent } = record;
19151
19984
  const { freezePage } = record;
19152
19985
  const { takeFullSnapshot } = record;
19153
19986
  export {
19987
+ EmbeddedReplayerClient,
19988
+ EmbeddedReplayerHost,
19154
19989
  EventType,
19155
19990
  IncrementalSource,
19156
19991
  MouseInteractions,
19992
+ RRWEB_EMBEDDED_CHANNEL,
19993
+ RRWEB_EMBEDDED_PROTOCOL_VERSION,
19157
19994
  Replayer,
19158
19995
  ReplayerEvents,
19159
19996
  addCustomEvent,
19997
+ buildHostDocument,
19160
19998
  canvasMutation,
19161
19999
  freezePage,
19162
20000
  _mirror as mirror,
20001
+ pickSerializableConfig,
19163
20002
  record,
20003
+ startEmbeddedReplayerHost,
19164
20004
  takeFullSnapshot,
19165
20005
  utils
19166
20006
  };