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