@kalayanasundaram123/rrweb 2.0.2 → 2.0.4

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
@@ -4963,10 +4963,10 @@ function requireNoWorkResult$1() {
4963
4963
  let str = stringify;
4964
4964
  this.result = new Result(this._processor, root2, this._opts);
4965
4965
  this.result.css = css;
4966
- let self2 = this;
4966
+ let self = this;
4967
4967
  Object.defineProperty(this.result, "root", {
4968
4968
  get() {
4969
- return self2.root;
4969
+ return self.root;
4970
4970
  }
4971
4971
  });
4972
4972
  let map = new MapGenerator(str, root2, this._opts, css);
@@ -9244,10 +9244,10 @@ function requireNoWorkResult() {
9244
9244
  let str = stringify;
9245
9245
  this.result = new Result(this._processor, root2, this._opts);
9246
9246
  this.result.css = css;
9247
- let self2 = this;
9247
+ let self = this;
9248
9248
  Object.defineProperty(this.result, "root", {
9249
9249
  get() {
9250
- return self2.root;
9250
+ return self.root;
9251
9251
  }
9252
9252
  });
9253
9253
  let map = new MapGenerator(str, root2, this._opts, css);
@@ -13938,38 +13938,38 @@ function initCanvasWebGLMutationObserver(cb, win, blockClass, blockSelector) {
13938
13938
  handlers.forEach((h) => h());
13939
13939
  };
13940
13940
  }
13941
- const jsContent = '(function() {\n "use strict";\n var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\n var lookup = typeof Uint8Array === "undefined" ? [] : new Uint8Array(256);\n for (var i = 0; i < chars.length; i++) {\n lookup[chars.charCodeAt(i)] = i;\n }\n var encode = function(arraybuffer) {\n var bytes = new Uint8Array(arraybuffer), i2, len = bytes.length, base64 = "";\n for (i2 = 0; i2 < len; i2 += 3) {\n base64 += chars[bytes[i2] >> 2];\n base64 += chars[(bytes[i2] & 3) << 4 | bytes[i2 + 1] >> 4];\n base64 += chars[(bytes[i2 + 1] & 15) << 2 | bytes[i2 + 2] >> 6];\n base64 += chars[bytes[i2 + 2] & 63];\n }\n if (len % 3 === 2) {\n base64 = base64.substring(0, base64.length - 1) + "=";\n } else if (len % 3 === 1) {\n base64 = base64.substring(0, base64.length - 2) + "==";\n }\n return base64;\n };\n const lastFingerprintMap = /* @__PURE__ */ new Map();\n const transparentBlobMap = /* @__PURE__ */ new Map();\n function fnv1aHash(buffer) {\n const view = new Uint8Array(buffer);\n let hash = 2166136261;\n for (let i2 = 0; i2 < view.length; i2++) {\n hash ^= view[i2];\n hash = hash * 16777619 | 0;\n }\n return (hash >>> 0).toString(16);\n }\n async function getTransparentBlobFor(width, height, dataURLOptions) {\n const id = `${width}-${height}`;\n if ("OffscreenCanvas" in globalThis) {\n if (transparentBlobMap.has(id)) return transparentBlobMap.get(id);\n const offscreen = new OffscreenCanvas(width, height);\n offscreen.getContext("2d");\n const blob = await offscreen.convertToBlob(dataURLOptions);\n const arrayBuffer = await blob.arrayBuffer();\n const base64 = encode(arrayBuffer);\n transparentBlobMap.set(id, base64);\n return base64;\n } else {\n return "";\n }\n }\n const worker = self;\n let reusableCanvas = null;\n let reusableCtx = null;\n worker.onmessage = async function(e) {\n if ("OffscreenCanvas" in globalThis) {\n const { id, bitmap, width, height, dataURLOptions } = e.data;\n try {\n const transparentBase64 = getTransparentBlobFor(\n width,\n height,\n dataURLOptions\n );\n if (!reusableCanvas || reusableCanvas.width !== width || reusableCanvas.height !== height) {\n reusableCanvas = new OffscreenCanvas(width, height);\n reusableCtx = reusableCanvas.getContext("2d");\n }\n reusableCtx.clearRect(0, 0, width, height);\n reusableCtx.drawImage(bitmap, 0, 0);\n bitmap.close();\n const blob = await reusableCanvas.convertToBlob(dataURLOptions);\n const type = blob.type;\n const arrayBuffer = await blob.arrayBuffer();\n const fingerprint = fnv1aHash(arrayBuffer);\n if (!lastFingerprintMap.has(id)) {\n const base642 = encode(arrayBuffer);\n if (await transparentBase64 === base642) {\n lastFingerprintMap.set(id, fingerprint);\n return worker.postMessage({ id });\n }\n lastFingerprintMap.set(id, fingerprint);\n worker.postMessage({ id, type, base64: base642, width, height });\n return;\n }\n if (lastFingerprintMap.get(id) === fingerprint) {\n return worker.postMessage({ id });\n }\n const base64 = encode(arrayBuffer);\n worker.postMessage({ id, type, base64, width, height });\n lastFingerprintMap.set(id, fingerprint);\n } catch {\n worker.postMessage({ id });\n }\n } else {\n e.data.bitmap.close();\n return worker.postMessage({ id: e.data.id });\n }\n };\n})();\n//# sourceMappingURL=image-bitmap-data-url-worker-DIbJg1p8.js.map\n';
13942
- const blob = typeof self !== "undefined" && self.Blob && new Blob([jsContent], { type: "text/javascript;charset=utf-8" });
13943
- function WorkerWrapper(options) {
13944
- let objURL;
13945
- try {
13946
- objURL = blob && (self.URL || self.webkitURL).createObjectURL(blob);
13947
- if (!objURL) throw "";
13948
- const worker = new Worker(objURL, {
13949
- name: options == null ? void 0 : options.name
13950
- });
13951
- worker.addEventListener("error", () => {
13952
- (self.URL || self.webkitURL).revokeObjectURL(objURL);
13953
- });
13954
- return worker;
13955
- } catch (e2) {
13956
- return new Worker(
13957
- "data:text/javascript;charset=utf-8," + encodeURIComponent(jsContent),
13958
- {
13959
- name: options == null ? void 0 : options.name
13960
- }
13961
- );
13962
- } finally {
13963
- objURL && (self.URL || self.webkitURL).revokeObjectURL(objURL);
13964
- }
13965
- }
13966
- function canCreateBlobWorker(win) {
13967
- try {
13968
- return typeof Worker !== "undefined" && win.origin != null && win.origin !== "null";
13969
- } catch {
13970
- return false;
13971
- }
13972
- }
13941
+ function fnv1aHash(buffer) {
13942
+ const view = new Uint8Array(buffer);
13943
+ let hash = 2166136261;
13944
+ for (let i2 = 0; i2 < view.length; i2++) {
13945
+ hash ^= view[i2];
13946
+ hash = hash * 16777619 | 0;
13947
+ }
13948
+ return (hash >>> 0).toString(16);
13949
+ }
13950
+ function canSnapshotCanvas() {
13951
+ return typeof OffscreenCanvas !== "undefined";
13952
+ }
13953
+ const FPS_WORKER_SOURCE = `
13954
+ var _C='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
13955
+ function _enc(ab){var b=new Uint8Array(ab),i,n=b.length,o='';for(i=0;i<n;i+=3){o+=_C[b[i]>>2];o+=_C[(b[i]&3)<<4|b[i+1]>>4];o+=_C[(b[i+1]&15)<<2|b[i+2]>>6];o+=_C[b[i+2]&63];}if(n%3===2){o=o.substring(0,o.length-1)+'=';}else if(n%3===1){o=o.substring(0,o.length-2)+'==';}return o;}
13956
+ function _fp(ab){var v=new Uint8Array(ab),h=0x811c9dc5;for(var i=0;i<v.length;i++){h^=v[i];h=(h*0x01000193)|0;}return (h>>>0).toString(16);}
13957
+ var _last=new Map(),_cv=null,_ctx=null;
13958
+ self.onmessage=async function(e){
13959
+ var d=e.data,id=d.id,bm=d.bitmap,w=d.width,h=d.height,opt=d.dataURLOptions;
13960
+ try{
13961
+ if(!('OffscreenCanvas' in self)){bm.close();return self.postMessage({id:id});}
13962
+ if(!_cv||_cv.width!==w||_cv.height!==h){_cv=new OffscreenCanvas(w,h);_ctx=_cv.getContext('2d');}
13963
+ _ctx.clearRect(0,0,w,h);_ctx.drawImage(bm,0,0);bm.close();
13964
+ var blob=await _cv.convertToBlob(opt);
13965
+ var buf=await blob.arrayBuffer();
13966
+ var fp=_fp(buf);
13967
+ if(_last.get(id)===fp)return self.postMessage({id:id});
13968
+ _last.set(id,fp);
13969
+ self.postMessage({id:id,type:blob.type,base64:_enc(buf),width:w,height:h});
13970
+ }catch(err){try{bm.close();}catch(_){}self.postMessage({id:id});}
13971
+ };
13972
+ `;
13973
13973
  class CanvasManager {
13974
13974
  constructor(options) {
13975
13975
  __publicField(this, "pendingCanvasMutations", /* @__PURE__ */ new Map());
@@ -13989,6 +13989,11 @@ class CanvasManager {
13989
13989
  __publicField(this, "frozen", false);
13990
13990
  __publicField(this, "locked", false);
13991
13991
  __publicField(this, "snapshotInProgressMap", /* @__PURE__ */ new Map());
13992
+ __publicField(this, "lastFingerprintMap", /* @__PURE__ */ new Map());
13993
+ __publicField(this, "snapshotCanvas", null);
13994
+ __publicField(this, "snapshotCtx", null);
13995
+ // Encode worker (created from a `data:` URL). null => encode on the main
13996
+ // thread instead (worker unavailable or blocked by CSP).
13992
13997
  __publicField(this, "worker", null);
13993
13998
  __publicField(this, "lastSnapshotTime", 0);
13994
13999
  __publicField(this, "processMutation", (target, mutation) => {
@@ -14005,15 +14010,13 @@ class CanvasManager {
14005
14010
  this.mutationCb = options.mutationCb;
14006
14011
  this.mirror = options.mirror;
14007
14012
  this.options = options;
14008
- if (recordCanvas && typeof sampling === "number" && canCreateBlobWorker(win)) {
14009
- this.worker = this.initFPSWorker();
14010
- }
14011
14013
  this.addWindow(win);
14012
14014
  if (recordCanvas && sampling === "all") {
14013
14015
  this.startRAFTimestamping();
14014
14016
  this.startPendingCanvasMutationFlusher();
14015
14017
  }
14016
- if (recordCanvas && typeof sampling === "number" && this.worker) {
14018
+ if (recordCanvas && typeof sampling === "number" && canSnapshotCanvas()) {
14019
+ this.worker = this.initFPSWorker();
14017
14020
  this.initCanvasFPSObserver();
14018
14021
  }
14019
14022
  }
@@ -14030,9 +14033,12 @@ class CanvasManager {
14030
14033
  this.windowsSet = /* @__PURE__ */ new WeakSet();
14031
14034
  this.windows = [];
14032
14035
  this.shadowDoms = /* @__PURE__ */ new Set();
14036
+ this.snapshotInProgressMap = /* @__PURE__ */ new Map();
14037
+ this.lastFingerprintMap = /* @__PURE__ */ new Map();
14038
+ this.snapshotCanvas = null;
14039
+ this.snapshotCtx = null;
14033
14040
  (_a2 = this.worker) == null ? void 0 : _a2.terminate();
14034
14041
  this.worker = null;
14035
- this.snapshotInProgressMap = /* @__PURE__ */ new Map();
14036
14042
  }
14037
14043
  freeze() {
14038
14044
  this.frozen = true;
@@ -14046,6 +14052,29 @@ class CanvasManager {
14046
14052
  unlock() {
14047
14053
  this.locked = false;
14048
14054
  }
14055
+ initFPSWorker() {
14056
+ try {
14057
+ const worker = new Worker(
14058
+ "data:application/javascript;charset=utf-8," + encodeURIComponent(FPS_WORKER_SOURCE)
14059
+ );
14060
+ worker.onmessage = (e2) => {
14061
+ const data = e2.data;
14062
+ const { id } = data;
14063
+ this.snapshotInProgressMap.set(id, false);
14064
+ if (data.base64 === void 0) return;
14065
+ this.emitCanvasSnapshot(
14066
+ id,
14067
+ data.base64,
14068
+ data.type || "image/png",
14069
+ data.width || 0,
14070
+ data.height || 0
14071
+ );
14072
+ };
14073
+ return worker;
14074
+ } catch {
14075
+ return null;
14076
+ }
14077
+ }
14049
14078
  /**
14050
14079
  * Begin observing canvas activity inside `win` — the top window, or the
14051
14080
  * `contentWindow` of a same-origin iframe. De-duplicated, so it is safe to
@@ -14085,45 +14114,74 @@ class CanvasManager {
14085
14114
  resetShadowRoots() {
14086
14115
  this.shadowDoms = /* @__PURE__ */ new Set();
14087
14116
  }
14088
- initFPSWorker() {
14089
- const worker = new WorkerWrapper();
14090
- worker.onmessage = (e2) => {
14091
- const data = e2.data;
14092
- const { id } = data;
14093
- this.snapshotInProgressMap.set(id, false);
14094
- if (!("base64" in data)) return;
14095
- const { base64, type, width, height } = data;
14096
- this.mutationCb({
14117
+ /**
14118
+ * Encode one canvas frame (an ImageBitmap of the canvas) to a data blob on
14119
+ * the main thread, de-duplicating unchanged frames, and emit it as a canvas
14120
+ * mutation. Replaces the old blob-URL Worker, which crashed the renderer when
14121
+ * created inside sandboxed frames.
14122
+ */
14123
+ async snapshotImageBitmap(id, bitmap, width, height, dataURLOptions) {
14124
+ try {
14125
+ let offscreen = this.snapshotCanvas;
14126
+ if (!offscreen || offscreen.width !== width || offscreen.height !== height) {
14127
+ offscreen = new OffscreenCanvas(width, height);
14128
+ this.snapshotCanvas = offscreen;
14129
+ this.snapshotCtx = offscreen.getContext("2d");
14130
+ }
14131
+ const ctx = this.snapshotCtx;
14132
+ if (!ctx) return;
14133
+ ctx.clearRect(0, 0, width, height);
14134
+ ctx.drawImage(bitmap, 0, 0);
14135
+ const blob = await offscreen.convertToBlob(
14136
+ dataURLOptions
14137
+ );
14138
+ const arrayBuffer = await blob.arrayBuffer();
14139
+ const fingerprint = fnv1aHash(arrayBuffer);
14140
+ if (this.lastFingerprintMap.get(id) === fingerprint) return;
14141
+ this.lastFingerprintMap.set(id, fingerprint);
14142
+ this.emitCanvasSnapshot(
14097
14143
  id,
14098
- type: CanvasContext["2D"],
14099
- commands: [
14100
- {
14101
- property: "clearRect",
14102
- // wipe canvas
14103
- args: [0, 0, width, height]
14104
- },
14105
- {
14106
- property: "drawImage",
14107
- // draws (semi-transparent) image
14108
- args: [
14109
- {
14110
- rr_type: "ImageBitmap",
14111
- args: [
14112
- {
14113
- rr_type: "Blob",
14114
- data: [{ rr_type: "ArrayBuffer", base64 }],
14115
- type
14116
- }
14117
- ]
14118
- },
14119
- 0,
14120
- 0
14121
- ]
14122
- }
14123
- ]
14124
- });
14125
- };
14126
- return worker;
14144
+ encode(arrayBuffer),
14145
+ blob.type,
14146
+ width,
14147
+ height
14148
+ );
14149
+ } catch {
14150
+ } finally {
14151
+ bitmap.close();
14152
+ this.snapshotInProgressMap.set(id, false);
14153
+ }
14154
+ }
14155
+ emitCanvasSnapshot(id, base64, type, width, height) {
14156
+ this.mutationCb({
14157
+ id,
14158
+ type: CanvasContext["2D"],
14159
+ commands: [
14160
+ {
14161
+ property: "clearRect",
14162
+ // wipe canvas
14163
+ args: [0, 0, width, height]
14164
+ },
14165
+ {
14166
+ property: "drawImage",
14167
+ // draws (semi-transparent) image
14168
+ args: [
14169
+ {
14170
+ rr_type: "ImageBitmap",
14171
+ args: [
14172
+ {
14173
+ rr_type: "Blob",
14174
+ data: [{ rr_type: "ArrayBuffer", base64 }],
14175
+ type
14176
+ }
14177
+ ]
14178
+ },
14179
+ 0,
14180
+ 0
14181
+ ]
14182
+ }
14183
+ ]
14184
+ });
14127
14185
  }
14128
14186
  initCanvasFPSObserver() {
14129
14187
  let rafId;
@@ -14221,20 +14279,25 @@ class CanvasManager {
14221
14279
  context.clear(context.COLOR_BUFFER_BIT);
14222
14280
  }
14223
14281
  }
14282
+ const width = canvas.width;
14283
+ const height = canvas.height;
14224
14284
  createImageBitmap(canvas).then((bitmap) => {
14225
- var _a3;
14226
- (_a3 = this.worker) == null ? void 0 : _a3.postMessage(
14227
- {
14285
+ if (this.worker) {
14286
+ this.worker.postMessage(
14287
+ { id, bitmap, width, height, dataURLOptions },
14288
+ [bitmap]
14289
+ );
14290
+ } else {
14291
+ void this.snapshotImageBitmap(
14228
14292
  id,
14229
14293
  bitmap,
14230
- width: canvas.width,
14231
- height: canvas.height,
14294
+ width,
14295
+ height,
14232
14296
  dataURLOptions
14233
- },
14234
- [bitmap]
14235
- );
14297
+ );
14298
+ }
14236
14299
  }).catch(() => {
14237
- this.snapshotInProgressMap.delete(id);
14300
+ this.snapshotInProgressMap.set(id, false);
14238
14301
  });
14239
14302
  });
14240
14303
  }
@@ -15624,10 +15687,10 @@ function deserializeArg(imageMap, ctx, preload) {
15624
15687
  const blobContents = await Promise.all(
15625
15688
  arg.data.map(deserializeArg(imageMap, ctx, preload))
15626
15689
  );
15627
- const blob2 = new Blob(blobContents, {
15690
+ const blob = new Blob(blobContents, {
15628
15691
  type: arg.type
15629
15692
  });
15630
- return blob2;
15693
+ return blob;
15631
15694
  }
15632
15695
  } else if (Array.isArray(arg)) {
15633
15696
  const result2 = await Promise.all(