@highlight-run/rrweb 2.0.0-lambda.8 → 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.d.cts CHANGED
@@ -54,13 +54,14 @@ declare type AppendedIframe = {
54
54
 
55
55
  export declare function buildHostDocument(options: HostDocumentOptions): string;
56
56
 
57
- export declare function canvasMutation({ event, mutation, target, imageMap, canvasEventMap, errorHandler, }: {
57
+ export declare function canvasMutation({ event, mutation, target, imageMap, canvasEventMap, errorHandler, enforceCanvasArgAllowlist, }: {
58
58
  event: Parameters<Replayer['applyIncremental']>[0];
59
59
  mutation: canvasMutationData;
60
60
  target: HTMLCanvasElement;
61
61
  imageMap: Replayer['imageMap'];
62
62
  canvasEventMap: Replayer['canvasEventMap'];
63
63
  errorHandler: Replayer['warnCanvasMutationFailed'];
64
+ enforceCanvasArgAllowlist?: boolean;
64
65
  }): Promise<void>;
65
66
 
66
67
  declare function closestElementOfNode(node: Node | null): HTMLElement | null;
@@ -302,6 +303,7 @@ export declare type playerConfig = {
302
303
  insertStyleRules: string[];
303
304
  triggerFocus: boolean;
304
305
  UNSAFE_replayCanvas: boolean;
306
+ enforceCanvasArgAllowlist: boolean;
305
307
  cspContent?: string;
306
308
  pauseAnimation?: boolean;
307
309
  mouseTail: boolean | {
@@ -405,6 +407,7 @@ export declare type recordOptions<T> = {
405
407
  maskTextFn?: MaskTextFn;
406
408
  slimDOMOptions?: SlimDOMOptions | 'all' | true;
407
409
  ignoreCSSAttributes?: Set<string>;
410
+ styleSheetResyncInterval?: number;
408
411
  inlineStylesheet?: boolean;
409
412
  hooks?: hooksParam;
410
413
  packFn?: PackFn;
@@ -550,7 +553,7 @@ export declare const RRWEB_EMBEDDED_CHANNEL: "rrweb-embedded";
550
553
 
551
554
  export declare const RRWEB_EMBEDDED_PROTOCOL_VERSION: 1;
552
555
 
553
- declare const SERIALIZABLE_CONFIG_KEYS: readonly ["speed", "maxSpeed", "loadTimeout", "skipInactive", "inactivePeriodThreshold", "showWarning", "showDebug", "blockClass", "liveMode", "insertStyleRules", "triggerFocus", "UNSAFE_replayCanvas", "cspContent", "pauseAnimation", "mouseTail", "useVirtualDom", "inactiveThreshold", "inactiveSkipTime"];
556
+ declare const SERIALIZABLE_CONFIG_KEYS: readonly ["speed", "maxSpeed", "loadTimeout", "skipInactive", "inactivePeriodThreshold", "showWarning", "showDebug", "blockClass", "liveMode", "insertStyleRules", "triggerFocus", "UNSAFE_replayCanvas", "enforceCanvasArgAllowlist", "cspContent", "pauseAnimation", "mouseTail", "useVirtualDom", "inactiveThreshold", "inactiveSkipTime"];
554
557
 
555
558
  declare type SerializableConfigKey = (typeof SERIALIZABLE_CONFIG_KEYS)[number];
556
559
 
package/dist/rrweb.d.ts CHANGED
@@ -54,13 +54,14 @@ declare type AppendedIframe = {
54
54
 
55
55
  export declare function buildHostDocument(options: HostDocumentOptions): string;
56
56
 
57
- export declare function canvasMutation({ event, mutation, target, imageMap, canvasEventMap, errorHandler, }: {
57
+ export declare function canvasMutation({ event, mutation, target, imageMap, canvasEventMap, errorHandler, enforceCanvasArgAllowlist, }: {
58
58
  event: Parameters<Replayer['applyIncremental']>[0];
59
59
  mutation: canvasMutationData;
60
60
  target: HTMLCanvasElement;
61
61
  imageMap: Replayer['imageMap'];
62
62
  canvasEventMap: Replayer['canvasEventMap'];
63
63
  errorHandler: Replayer['warnCanvasMutationFailed'];
64
+ enforceCanvasArgAllowlist?: boolean;
64
65
  }): Promise<void>;
65
66
 
66
67
  declare function closestElementOfNode(node: Node | null): HTMLElement | null;
@@ -302,6 +303,7 @@ export declare type playerConfig = {
302
303
  insertStyleRules: string[];
303
304
  triggerFocus: boolean;
304
305
  UNSAFE_replayCanvas: boolean;
306
+ enforceCanvasArgAllowlist: boolean;
305
307
  cspContent?: string;
306
308
  pauseAnimation?: boolean;
307
309
  mouseTail: boolean | {
@@ -405,6 +407,7 @@ export declare type recordOptions<T> = {
405
407
  maskTextFn?: MaskTextFn;
406
408
  slimDOMOptions?: SlimDOMOptions | 'all' | true;
407
409
  ignoreCSSAttributes?: Set<string>;
410
+ styleSheetResyncInterval?: number;
408
411
  inlineStylesheet?: boolean;
409
412
  hooks?: hooksParam;
410
413
  packFn?: PackFn;
@@ -550,7 +553,7 @@ export declare const RRWEB_EMBEDDED_CHANNEL: "rrweb-embedded";
550
553
 
551
554
  export declare const RRWEB_EMBEDDED_PROTOCOL_VERSION: 1;
552
555
 
553
- declare const SERIALIZABLE_CONFIG_KEYS: readonly ["speed", "maxSpeed", "loadTimeout", "skipInactive", "inactivePeriodThreshold", "showWarning", "showDebug", "blockClass", "liveMode", "insertStyleRules", "triggerFocus", "UNSAFE_replayCanvas", "cspContent", "pauseAnimation", "mouseTail", "useVirtualDom", "inactiveThreshold", "inactiveSkipTime"];
556
+ declare const SERIALIZABLE_CONFIG_KEYS: readonly ["speed", "maxSpeed", "loadTimeout", "skipInactive", "inactivePeriodThreshold", "showWarning", "showDebug", "blockClass", "liveMode", "insertStyleRules", "triggerFocus", "UNSAFE_replayCanvas", "enforceCanvasArgAllowlist", "cspContent", "pauseAnimation", "mouseTail", "useVirtualDom", "inactiveThreshold", "inactiveSkipTime"];
554
557
 
555
558
  declare type SerializableConfigKey = (typeof SERIALIZABLE_CONFIG_KEYS)[number];
556
559
 
package/dist/rrweb.js CHANGED
@@ -13672,66 +13672,142 @@ function getIdAndStyleId(sheet, mirror2, styleMirror) {
13672
13672
  id
13673
13673
  };
13674
13674
  }
13675
- 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 }) {
13676
13688
  if (!win.CSSStyleSheet || !win.CSSStyleSheet.prototype) {
13677
13689
  return () => {
13678
13690
  };
13679
13691
  }
13680
- const insertRule = win.CSSStyleSheet.prototype.insertRule;
13681
- 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, {
13682
13709
  apply: callbackWrapper(
13683
- (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
+ }
13684
13718
  const [rule2, index2] = argumentsList;
13685
13719
  const { id, styleId } = getIdAndStyleId(
13686
13720
  thisArg,
13687
13721
  mirror2,
13688
13722
  stylesheetManager.styleMirror
13689
13723
  );
13690
- if (id && id !== -1 || styleId && styleId !== -1) {
13724
+ const reported = id && id !== -1 || styleId && styleId !== -1;
13725
+ if (reported) {
13691
13726
  styleSheetRuleCb({
13692
13727
  id,
13693
13728
  styleId,
13694
13729
  adds: [{ rule: rule2, index: index2 }]
13695
13730
  });
13696
13731
  }
13697
- 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;
13698
13743
  }
13699
13744
  )
13700
13745
  });
13701
- win.CSSStyleSheet.prototype.addRule = function(selector, styleBlock, index2 = this.cssRules.length) {
13702
- const rule2 = `${selector} { ${styleBlock} }`;
13703
- return win.CSSStyleSheet.prototype.insertRule.apply(this, [rule2, index2]);
13704
- };
13705
- const deleteRule = win.CSSStyleSheet.prototype.deleteRule;
13706
- win.CSSStyleSheet.prototype.deleteRule = new Proxy(deleteRule, {
13746
+ const patchDeleteRule = (target) => new Proxy(target, {
13707
13747
  apply: callbackWrapper(
13708
- (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
+ }
13709
13756
  const [index2] = argumentsList;
13710
13757
  const { id, styleId } = getIdAndStyleId(
13711
13758
  thisArg,
13712
13759
  mirror2,
13713
13760
  stylesheetManager.styleMirror
13714
13761
  );
13715
- if (id && id !== -1 || styleId && styleId !== -1) {
13762
+ const reported = id && id !== -1 || styleId && styleId !== -1;
13763
+ if (reported) {
13716
13764
  styleSheetRuleCb({
13717
13765
  id,
13718
13766
  styleId,
13719
13767
  removes: [{ index: index2 }]
13720
13768
  });
13721
13769
  }
13722
- 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;
13723
13781
  }
13724
13782
  )
13725
13783
  });
13726
- 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) {
13727
13800
  return win.CSSStyleSheet.prototype.deleteRule.apply(this, [index2]);
13728
13801
  };
13802
+ win.CSSStyleSheet.prototype.removeRule = removeRuleShim;
13729
13803
  let replace;
13804
+ let replaceProxy;
13730
13805
  if (win.CSSStyleSheet.prototype.replace) {
13731
13806
  replace = win.CSSStyleSheet.prototype.replace;
13732
- win.CSSStyleSheet.prototype.replace = new Proxy(replace, {
13807
+ replaceProxy = new Proxy(replace, {
13733
13808
  apply: callbackWrapper(
13734
13809
  (target, thisArg, argumentsList) => {
13810
+ if (stopped) return target.apply(thisArg, argumentsList);
13735
13811
  const [text] = argumentsList;
13736
13812
  const { id, styleId } = getIdAndStyleId(
13737
13813
  thisArg,
@@ -13749,13 +13825,16 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetM
13749
13825
  }
13750
13826
  )
13751
13827
  });
13828
+ win.CSSStyleSheet.prototype.replace = replaceProxy;
13752
13829
  }
13753
13830
  let replaceSync;
13831
+ let replaceSyncProxy;
13754
13832
  if (win.CSSStyleSheet.prototype.replaceSync) {
13755
13833
  replaceSync = win.CSSStyleSheet.prototype.replaceSync;
13756
- win.CSSStyleSheet.prototype.replaceSync = new Proxy(replaceSync, {
13834
+ replaceSyncProxy = new Proxy(replaceSync, {
13757
13835
  apply: callbackWrapper(
13758
13836
  (target, thisArg, argumentsList) => {
13837
+ if (stopped) return target.apply(thisArg, argumentsList);
13759
13838
  const [text] = argumentsList;
13760
13839
  const { id, styleId } = getIdAndStyleId(
13761
13840
  thisArg,
@@ -13773,6 +13852,7 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetM
13773
13852
  }
13774
13853
  )
13775
13854
  });
13855
+ win.CSSStyleSheet.prototype.replaceSync = replaceSyncProxy;
13776
13856
  }
13777
13857
  const supportedNestedCSSRuleTypes = {};
13778
13858
  if (canMonkeyPatchNestedCSSRule("CSSGroupingRule")) {
@@ -13789,6 +13869,7 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetM
13789
13869
  }
13790
13870
  }
13791
13871
  const unmodifiedFunctions = {};
13872
+ const nestedProxies = {};
13792
13873
  Object.entries(supportedNestedCSSRuleTypes).forEach(([typeKey, type]) => {
13793
13874
  unmodifiedFunctions[typeKey] = {
13794
13875
  // eslint-disable-next-line @typescript-eslint/unbound-method
@@ -13796,11 +13877,13 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetM
13796
13877
  // eslint-disable-next-line @typescript-eslint/unbound-method
13797
13878
  deleteRule: type.prototype.deleteRule
13798
13879
  };
13799
- type.prototype.insertRule = new Proxy(
13880
+ nestedProxies[typeKey] = {};
13881
+ nestedProxies[typeKey].insertRule = new Proxy(
13800
13882
  unmodifiedFunctions[typeKey].insertRule,
13801
13883
  {
13802
13884
  apply: callbackWrapper(
13803
13885
  (target, thisArg, argumentsList) => {
13886
+ if (stopped) return target.apply(thisArg, argumentsList);
13804
13887
  const [rule2, index2] = argumentsList;
13805
13888
  const { id, styleId } = getIdAndStyleId(
13806
13889
  thisArg.parentStyleSheet,
@@ -13828,11 +13911,12 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetM
13828
13911
  )
13829
13912
  }
13830
13913
  );
13831
- type.prototype.deleteRule = new Proxy(
13914
+ nestedProxies[typeKey].deleteRule = new Proxy(
13832
13915
  unmodifiedFunctions[typeKey].deleteRule,
13833
13916
  {
13834
13917
  apply: callbackWrapper(
13835
13918
  (target, thisArg, argumentsList) => {
13919
+ if (stopped) return target.apply(thisArg, argumentsList);
13836
13920
  const [index2] = argumentsList;
13837
13921
  const { id, styleId } = getIdAndStyleId(
13838
13922
  thisArg.parentStyleSheet,
@@ -13853,15 +13937,148 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror: mirror2, stylesheetM
13853
13937
  )
13854
13938
  }
13855
13939
  );
13940
+ type.prototype.insertRule = nestedProxies[typeKey].insertRule;
13941
+ type.prototype.deleteRule = nestedProxies[typeKey].deleteRule;
13856
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
+ }
13857
14049
  return callbackWrapper(() => {
13858
- win.CSSStyleSheet.prototype.insertRule = insertRule;
13859
- win.CSSStyleSheet.prototype.deleteRule = deleteRule;
13860
- replace && (win.CSSStyleSheet.prototype.replace = replace);
13861
- 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);
13862
14069
  Object.entries(supportedNestedCSSRuleTypes).forEach(([typeKey, type]) => {
13863
- type.prototype.insertRule = unmodifiedFunctions[typeKey].insertRule;
13864
- 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
+ );
13865
14082
  });
13866
14083
  });
13867
14084
  }
@@ -15629,6 +15846,7 @@ function record(options = {}) {
15629
15846
  keepIframeSrcFn = () => false,
15630
15847
  privacySetting = "default",
15631
15848
  ignoreCSSAttributes = /* @__PURE__ */ new Set([]),
15849
+ styleSheetResyncInterval = 2e3,
15632
15850
  errorHandler: errorHandler2,
15633
15851
  logger
15634
15852
  } = options;
@@ -16007,6 +16225,7 @@ function record(options = {}) {
16007
16225
  processedNodeManager,
16008
16226
  canvasManager,
16009
16227
  ignoreCSSAttributes,
16228
+ styleSheetResyncInterval,
16010
16229
  privacySetting,
16011
16230
  plugins: ((_a3 = plugins == null ? void 0 : plugins.filter((p) => p.observer)) == null ? void 0 : _a3.map((p) => ({
16012
16231
  observer: p.observer,
@@ -16893,12 +17112,36 @@ function variableListFor(ctx, ctor) {
16893
17112
  }
16894
17113
  return contextMap.get(ctor);
16895
17114
  }
16896
- 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) {
16897
17135
  return async (arg) => {
16898
17136
  if (arg && typeof arg === "object" && "rr_type" in arg) {
16899
17137
  if (preload) preload.isUnchanged = false;
16900
17138
  if (arg.rr_type === "ImageBitmap" && "args" in arg) {
16901
- 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);
16902
17145
  return await createImageBitmap.apply(null, args);
16903
17146
  } else if ("index" in arg) {
16904
17147
  if (preload || ctx === null) return arg;
@@ -16906,10 +17149,18 @@ function deserializeArg(imageMap, ctx, preload) {
16906
17149
  return variableListFor(ctx, name)[index2];
16907
17150
  } else if ("args" in arg) {
16908
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
+ }
16909
17158
  const ctor = window[name];
16910
17159
  return new ctor(
16911
17160
  ...await Promise.all(
16912
- args.map(deserializeArg(imageMap, ctx, preload))
17161
+ args.map(
17162
+ deserializeArg(imageMap, ctx, preload, enforceCanvasArgAllowlist)
17163
+ )
16913
17164
  )
16914
17165
  );
16915
17166
  } else if ("base64" in arg) {
@@ -16926,7 +17177,9 @@ function deserializeArg(imageMap, ctx, preload) {
16926
17177
  }
16927
17178
  } else if ("data" in arg && arg.rr_type === "Blob") {
16928
17179
  const blobContents = await Promise.all(
16929
- arg.data.map(deserializeArg(imageMap, ctx, preload))
17180
+ arg.data.map(
17181
+ deserializeArg(imageMap, ctx, preload, enforceCanvasArgAllowlist)
17182
+ )
16930
17183
  );
16931
17184
  const blob2 = new Blob(blobContents, {
16932
17185
  type: arg.type
@@ -16935,7 +17188,9 @@ function deserializeArg(imageMap, ctx, preload) {
16935
17188
  }
16936
17189
  } else if (Array.isArray(arg)) {
16937
17190
  const result2 = await Promise.all(
16938
- arg.map(deserializeArg(imageMap, ctx, preload))
17191
+ arg.map(
17192
+ deserializeArg(imageMap, ctx, preload, enforceCanvasArgAllowlist)
17193
+ )
16939
17194
  );
16940
17195
  return result2;
16941
17196
  }
@@ -16976,7 +17231,8 @@ async function webglMutation({
16976
17231
  target,
16977
17232
  type,
16978
17233
  imageMap,
16979
- errorHandler: errorHandler2
17234
+ errorHandler: errorHandler2,
17235
+ enforceCanvasArgAllowlist
16980
17236
  }) {
16981
17237
  try {
16982
17238
  const ctx = getContext(target, type);
@@ -16987,7 +17243,9 @@ async function webglMutation({
16987
17243
  }
16988
17244
  const original = ctx[mutation.property];
16989
17245
  const args = await Promise.all(
16990
- mutation.args.map(deserializeArg(imageMap, ctx))
17246
+ mutation.args.map(
17247
+ deserializeArg(imageMap, ctx, void 0, enforceCanvasArgAllowlist)
17248
+ )
16991
17249
  );
16992
17250
  const result2 = original.apply(ctx, args);
16993
17251
  saveToWebGLVarMap(ctx, result2);
@@ -17002,7 +17260,8 @@ async function canvasMutation$1({
17002
17260
  mutations,
17003
17261
  target,
17004
17262
  imageMap,
17005
- errorHandler: errorHandler2
17263
+ errorHandler: errorHandler2,
17264
+ enforceCanvasArgAllowlist
17006
17265
  }) {
17007
17266
  const ctx = target.getContext("2d");
17008
17267
  if (!ctx) {
@@ -17012,7 +17271,11 @@ async function canvasMutation$1({
17012
17271
  wrapCanvasContextDrawImage(ctx);
17013
17272
  const mutationArgsPromises = mutations.map(
17014
17273
  async (mutation) => {
17015
- 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
+ );
17016
17279
  }
17017
17280
  );
17018
17281
  const args = await Promise.all(mutationArgsPromises);
@@ -17042,7 +17305,8 @@ async function canvasMutation({
17042
17305
  target,
17043
17306
  imageMap,
17044
17307
  canvasEventMap,
17045
- errorHandler: errorHandler2
17308
+ errorHandler: errorHandler2,
17309
+ enforceCanvasArgAllowlist
17046
17310
  }) {
17047
17311
  try {
17048
17312
  const precomputedMutation = canvasEventMap.get(event) || mutation;
@@ -17055,7 +17319,8 @@ async function canvasMutation({
17055
17319
  type: mutation.type,
17056
17320
  target,
17057
17321
  imageMap,
17058
- errorHandler: errorHandler2
17322
+ errorHandler: errorHandler2,
17323
+ enforceCanvasArgAllowlist
17059
17324
  });
17060
17325
  }
17061
17326
  return;
@@ -17065,7 +17330,8 @@ async function canvasMutation({
17065
17330
  mutations: commands,
17066
17331
  target,
17067
17332
  imageMap,
17068
- errorHandler: errorHandler2
17333
+ errorHandler: errorHandler2,
17334
+ enforceCanvasArgAllowlist
17069
17335
  });
17070
17336
  } catch (error) {
17071
17337
  errorHandler2(mutation, error);
@@ -17508,6 +17774,7 @@ class Replayer {
17508
17774
  insertStyleRules: [],
17509
17775
  triggerFocus: true,
17510
17776
  UNSAFE_replayCanvas: false,
17777
+ enforceCanvasArgAllowlist: false,
17511
17778
  pauseAnimation: true,
17512
17779
  mouseTail: defaultMouseTailConfig,
17513
17780
  useVirtualDom: true,
@@ -17536,7 +17803,8 @@ class Replayer {
17536
17803
  target,
17537
17804
  imageMap: this.imageMap,
17538
17805
  canvasEventMap: this.canvasEventMap,
17539
- errorHandler: this.warnCanvasMutationFailed.bind(this)
17806
+ errorHandler: this.warnCanvasMutationFailed.bind(this),
17807
+ enforceCanvasArgAllowlist: this.config.enforceCanvasArgAllowlist
17540
17808
  });
17541
17809
  },
17542
17810
  applyInput: this.applyInput.bind(this),
@@ -18248,7 +18516,14 @@ class Replayer {
18248
18516
  const commands = await Promise.all(
18249
18517
  data.commands.map(async (c2) => {
18250
18518
  const args = await Promise.all(
18251
- 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
+ )
18252
18527
  );
18253
18528
  return { ...c2, args };
18254
18529
  })
@@ -18257,7 +18532,14 @@ class Replayer {
18257
18532
  this.canvasEventMap.set(event, { ...data, commands });
18258
18533
  } else {
18259
18534
  const args = await Promise.all(
18260
- 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
+ )
18261
18543
  );
18262
18544
  if (status.isUnchanged === false)
18263
18545
  this.canvasEventMap.set(event, { ...data, args });
@@ -18470,7 +18752,8 @@ class Replayer {
18470
18752
  target,
18471
18753
  imageMap: this.imageMap,
18472
18754
  canvasEventMap: this.canvasEventMap,
18473
- errorHandler: this.warnCanvasMutationFailed.bind(this)
18755
+ errorHandler: this.warnCanvasMutationFailed.bind(this),
18756
+ enforceCanvasArgAllowlist: this.config.enforceCanvasArgAllowlist
18474
18757
  });
18475
18758
  }
18476
18759
  break;
@@ -19208,6 +19491,7 @@ const SERIALIZABLE_CONFIG_KEYS = [
19208
19491
  "insertStyleRules",
19209
19492
  "triggerFocus",
19210
19493
  "UNSAFE_replayCanvas",
19494
+ "enforceCanvasArgAllowlist",
19211
19495
  "cspContent",
19212
19496
  "pauseAnimation",
19213
19497
  "mouseTail",