@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kalayanasundaram123/rrweb",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "record and replay the web",
5
5
  "scripts": {
6
6
  "prepare": "npm run prepack",
package/umd/rrweb.js CHANGED
@@ -5009,10 +5009,10 @@ function requireNoWorkResult$1() {
5009
5009
  let str = stringify;
5010
5010
  this.result = new Result(this._processor, root2, this._opts);
5011
5011
  this.result.css = css;
5012
- let self2 = this;
5012
+ let self = this;
5013
5013
  Object.defineProperty(this.result, "root", {
5014
5014
  get() {
5015
- return self2.root;
5015
+ return self.root;
5016
5016
  }
5017
5017
  });
5018
5018
  let map = new MapGenerator(str, root2, this._opts, css);
@@ -9289,10 +9289,10 @@ function requireNoWorkResult() {
9289
9289
  let str = stringify;
9290
9290
  this.result = new Result(this._processor, root2, this._opts);
9291
9291
  this.result.css = css;
9292
- let self2 = this;
9292
+ let self = this;
9293
9293
  Object.defineProperty(this.result, "root", {
9294
9294
  get() {
9295
- return self2.root;
9295
+ return self.root;
9296
9296
  }
9297
9297
  });
9298
9298
  let map = new MapGenerator(str, root2, this._opts, css);
@@ -13960,38 +13960,38 @@ function initCanvasWebGLMutationObserver(cb, win, blockClass, blockSelector) {
13960
13960
  handlers.forEach((h) => h());
13961
13961
  };
13962
13962
  }
13963
- 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';
13964
- const blob = typeof self !== "undefined" && self.Blob && new Blob([jsContent], { type: "text/javascript;charset=utf-8" });
13965
- function WorkerWrapper(options) {
13966
- let objURL;
13967
- try {
13968
- objURL = blob && (self.URL || self.webkitURL).createObjectURL(blob);
13969
- if (!objURL) throw "";
13970
- const worker = new Worker(objURL, {
13971
- name: options == null ? void 0 : options.name
13972
- });
13973
- worker.addEventListener("error", () => {
13974
- (self.URL || self.webkitURL).revokeObjectURL(objURL);
13975
- });
13976
- return worker;
13977
- } catch (e2) {
13978
- return new Worker(
13979
- "data:text/javascript;charset=utf-8," + encodeURIComponent(jsContent),
13980
- {
13981
- name: options == null ? void 0 : options.name
13982
- }
13983
- );
13984
- } finally {
13985
- objURL && (self.URL || self.webkitURL).revokeObjectURL(objURL);
13986
- }
13987
- }
13988
- function canCreateBlobWorker(win) {
13989
- try {
13990
- return typeof Worker !== "undefined" && win.origin != null && win.origin !== "null";
13991
- } catch (e2) {
13992
- return false;
13993
- }
13994
- }
13963
+ function fnv1aHash(buffer) {
13964
+ const view = new Uint8Array(buffer);
13965
+ let hash = 2166136261;
13966
+ for (let i2 = 0; i2 < view.length; i2++) {
13967
+ hash ^= view[i2];
13968
+ hash = hash * 16777619 | 0;
13969
+ }
13970
+ return (hash >>> 0).toString(16);
13971
+ }
13972
+ function canSnapshotCanvas() {
13973
+ return typeof OffscreenCanvas !== "undefined";
13974
+ }
13975
+ const FPS_WORKER_SOURCE = `
13976
+ var _C='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
13977
+ 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;}
13978
+ 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);}
13979
+ var _last=new Map(),_cv=null,_ctx=null;
13980
+ self.onmessage=async function(e){
13981
+ var d=e.data,id=d.id,bm=d.bitmap,w=d.width,h=d.height,opt=d.dataURLOptions;
13982
+ try{
13983
+ if(!('OffscreenCanvas' in self)){bm.close();return self.postMessage({id:id});}
13984
+ if(!_cv||_cv.width!==w||_cv.height!==h){_cv=new OffscreenCanvas(w,h);_ctx=_cv.getContext('2d');}
13985
+ _ctx.clearRect(0,0,w,h);_ctx.drawImage(bm,0,0);bm.close();
13986
+ var blob=await _cv.convertToBlob(opt);
13987
+ var buf=await blob.arrayBuffer();
13988
+ var fp=_fp(buf);
13989
+ if(_last.get(id)===fp)return self.postMessage({id:id});
13990
+ _last.set(id,fp);
13991
+ self.postMessage({id:id,type:blob.type,base64:_enc(buf),width:w,height:h});
13992
+ }catch(err){try{bm.close();}catch(_){}self.postMessage({id:id});}
13993
+ };
13994
+ `;
13995
13995
  class CanvasManager {
13996
13996
  constructor(options) {
13997
13997
  __publicField(this, "pendingCanvasMutations", /* @__PURE__ */ new Map());
@@ -14006,6 +14006,9 @@ class CanvasManager {
14006
14006
  __publicField(this, "frozen", false);
14007
14007
  __publicField(this, "locked", false);
14008
14008
  __publicField(this, "snapshotInProgressMap", /* @__PURE__ */ new Map());
14009
+ __publicField(this, "lastFingerprintMap", /* @__PURE__ */ new Map());
14010
+ __publicField(this, "snapshotCanvas", null);
14011
+ __publicField(this, "snapshotCtx", null);
14009
14012
  __publicField(this, "worker", null);
14010
14013
  __publicField(this, "lastSnapshotTime", 0);
14011
14014
  __publicField(this, "processMutation", (target, mutation) => {
@@ -14022,15 +14025,13 @@ class CanvasManager {
14022
14025
  this.mutationCb = options.mutationCb;
14023
14026
  this.mirror = options.mirror;
14024
14027
  this.options = options;
14025
- if (recordCanvas && typeof sampling === "number" && canCreateBlobWorker(win)) {
14026
- this.worker = this.initFPSWorker();
14027
- }
14028
14028
  this.addWindow(win);
14029
14029
  if (recordCanvas && sampling === "all") {
14030
14030
  this.startRAFTimestamping();
14031
14031
  this.startPendingCanvasMutationFlusher();
14032
14032
  }
14033
- if (recordCanvas && typeof sampling === "number" && this.worker) {
14033
+ if (recordCanvas && typeof sampling === "number" && canSnapshotCanvas()) {
14034
+ this.worker = this.initFPSWorker();
14034
14035
  this.initCanvasFPSObserver();
14035
14036
  }
14036
14037
  }
@@ -14047,9 +14048,12 @@ class CanvasManager {
14047
14048
  this.windowsSet = /* @__PURE__ */ new WeakSet();
14048
14049
  this.windows = [];
14049
14050
  this.shadowDoms = /* @__PURE__ */ new Set();
14051
+ this.snapshotInProgressMap = /* @__PURE__ */ new Map();
14052
+ this.lastFingerprintMap = /* @__PURE__ */ new Map();
14053
+ this.snapshotCanvas = null;
14054
+ this.snapshotCtx = null;
14050
14055
  (_a2 = this.worker) == null ? void 0 : _a2.terminate();
14051
14056
  this.worker = null;
14052
- this.snapshotInProgressMap = /* @__PURE__ */ new Map();
14053
14057
  }
14054
14058
  freeze() {
14055
14059
  this.frozen = true;
@@ -14063,6 +14067,29 @@ class CanvasManager {
14063
14067
  unlock() {
14064
14068
  this.locked = false;
14065
14069
  }
14070
+ initFPSWorker() {
14071
+ try {
14072
+ const worker = new Worker(
14073
+ "data:application/javascript;charset=utf-8," + encodeURIComponent(FPS_WORKER_SOURCE)
14074
+ );
14075
+ worker.onmessage = (e2) => {
14076
+ const data = e2.data;
14077
+ const { id } = data;
14078
+ this.snapshotInProgressMap.set(id, false);
14079
+ if (data.base64 === void 0) return;
14080
+ this.emitCanvasSnapshot(
14081
+ id,
14082
+ data.base64,
14083
+ data.type || "image/png",
14084
+ data.width || 0,
14085
+ data.height || 0
14086
+ );
14087
+ };
14088
+ return worker;
14089
+ } catch (e2) {
14090
+ return null;
14091
+ }
14092
+ }
14066
14093
  /**
14067
14094
  * Begin observing canvas activity inside `win` — the top window, or the
14068
14095
  * `contentWindow` of a same-origin iframe. De-duplicated, so it is safe to
@@ -14102,45 +14129,74 @@ class CanvasManager {
14102
14129
  resetShadowRoots() {
14103
14130
  this.shadowDoms = /* @__PURE__ */ new Set();
14104
14131
  }
14105
- initFPSWorker() {
14106
- const worker = new WorkerWrapper();
14107
- worker.onmessage = (e2) => {
14108
- const data = e2.data;
14109
- const { id } = data;
14110
- this.snapshotInProgressMap.set(id, false);
14111
- if (!("base64" in data)) return;
14112
- const { base64, type, width, height } = data;
14113
- this.mutationCb({
14132
+ /**
14133
+ * Encode one canvas frame (an ImageBitmap of the canvas) to a data blob on
14134
+ * the main thread, de-duplicating unchanged frames, and emit it as a canvas
14135
+ * mutation. Replaces the old blob-URL Worker, which crashed the renderer when
14136
+ * created inside sandboxed frames.
14137
+ */
14138
+ async snapshotImageBitmap(id, bitmap, width, height, dataURLOptions) {
14139
+ try {
14140
+ let offscreen = this.snapshotCanvas;
14141
+ if (!offscreen || offscreen.width !== width || offscreen.height !== height) {
14142
+ offscreen = new OffscreenCanvas(width, height);
14143
+ this.snapshotCanvas = offscreen;
14144
+ this.snapshotCtx = offscreen.getContext("2d");
14145
+ }
14146
+ const ctx = this.snapshotCtx;
14147
+ if (!ctx) return;
14148
+ ctx.clearRect(0, 0, width, height);
14149
+ ctx.drawImage(bitmap, 0, 0);
14150
+ const blob = await offscreen.convertToBlob(
14151
+ dataURLOptions
14152
+ );
14153
+ const arrayBuffer = await blob.arrayBuffer();
14154
+ const fingerprint = fnv1aHash(arrayBuffer);
14155
+ if (this.lastFingerprintMap.get(id) === fingerprint) return;
14156
+ this.lastFingerprintMap.set(id, fingerprint);
14157
+ this.emitCanvasSnapshot(
14114
14158
  id,
14115
- type: CanvasContext["2D"],
14116
- commands: [
14117
- {
14118
- property: "clearRect",
14119
- // wipe canvas
14120
- args: [0, 0, width, height]
14121
- },
14122
- {
14123
- property: "drawImage",
14124
- // draws (semi-transparent) image
14125
- args: [
14126
- {
14127
- rr_type: "ImageBitmap",
14128
- args: [
14129
- {
14130
- rr_type: "Blob",
14131
- data: [{ rr_type: "ArrayBuffer", base64 }],
14132
- type
14133
- }
14134
- ]
14135
- },
14136
- 0,
14137
- 0
14138
- ]
14139
- }
14140
- ]
14141
- });
14142
- };
14143
- return worker;
14159
+ encode(arrayBuffer),
14160
+ blob.type,
14161
+ width,
14162
+ height
14163
+ );
14164
+ } catch (e2) {
14165
+ } finally {
14166
+ bitmap.close();
14167
+ this.snapshotInProgressMap.set(id, false);
14168
+ }
14169
+ }
14170
+ emitCanvasSnapshot(id, base64, type, width, height) {
14171
+ this.mutationCb({
14172
+ id,
14173
+ type: CanvasContext["2D"],
14174
+ commands: [
14175
+ {
14176
+ property: "clearRect",
14177
+ // wipe canvas
14178
+ args: [0, 0, width, height]
14179
+ },
14180
+ {
14181
+ property: "drawImage",
14182
+ // draws (semi-transparent) image
14183
+ args: [
14184
+ {
14185
+ rr_type: "ImageBitmap",
14186
+ args: [
14187
+ {
14188
+ rr_type: "Blob",
14189
+ data: [{ rr_type: "ArrayBuffer", base64 }],
14190
+ type
14191
+ }
14192
+ ]
14193
+ },
14194
+ 0,
14195
+ 0
14196
+ ]
14197
+ }
14198
+ ]
14199
+ });
14144
14200
  }
14145
14201
  initCanvasFPSObserver() {
14146
14202
  let rafId;
@@ -14238,20 +14294,25 @@ class CanvasManager {
14238
14294
  context.clear(context.COLOR_BUFFER_BIT);
14239
14295
  }
14240
14296
  }
14297
+ const width = canvas.width;
14298
+ const height = canvas.height;
14241
14299
  createImageBitmap(canvas).then((bitmap) => {
14242
- var _a3;
14243
- (_a3 = this.worker) == null ? void 0 : _a3.postMessage(
14244
- {
14300
+ if (this.worker) {
14301
+ this.worker.postMessage(
14302
+ { id, bitmap, width, height, dataURLOptions },
14303
+ [bitmap]
14304
+ );
14305
+ } else {
14306
+ void this.snapshotImageBitmap(
14245
14307
  id,
14246
14308
  bitmap,
14247
- width: canvas.width,
14248
- height: canvas.height,
14309
+ width,
14310
+ height,
14249
14311
  dataURLOptions
14250
- },
14251
- [bitmap]
14252
- );
14312
+ );
14313
+ }
14253
14314
  }).catch(() => {
14254
- this.snapshotInProgressMap.delete(id);
14315
+ this.snapshotInProgressMap.set(id, false);
14255
14316
  });
14256
14317
  });
14257
14318
  }
@@ -15626,10 +15687,10 @@ function deserializeArg(imageMap, ctx, preload) {
15626
15687
  const blobContents = await Promise.all(
15627
15688
  arg.data.map(deserializeArg(imageMap, ctx, preload))
15628
15689
  );
15629
- const blob2 = new Blob(blobContents, {
15690
+ const blob = new Blob(blobContents, {
15630
15691
  type: arg.type
15631
15692
  });
15632
- return blob2;
15693
+ return blob;
15633
15694
  }
15634
15695
  } else if (Array.isArray(arg)) {
15635
15696
  const result2 = await Promise.all(