@kalayanasundaram123/rrweb 2.0.1 → 2.0.3

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.1",
3
+ "version": "2.0.3",
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,30 +13960,17 @@ 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);
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;
13986
13969
  }
13970
+ return (hash >>> 0).toString(16);
13971
+ }
13972
+ function canSnapshotCanvas() {
13973
+ return typeof OffscreenCanvas !== "undefined";
13987
13974
  }
13988
13975
  class CanvasManager {
13989
13976
  constructor(options) {
@@ -13999,7 +13986,9 @@ class CanvasManager {
13999
13986
  __publicField(this, "frozen", false);
14000
13987
  __publicField(this, "locked", false);
14001
13988
  __publicField(this, "snapshotInProgressMap", /* @__PURE__ */ new Map());
14002
- __publicField(this, "worker", null);
13989
+ __publicField(this, "lastFingerprintMap", /* @__PURE__ */ new Map());
13990
+ __publicField(this, "snapshotCanvas", null);
13991
+ __publicField(this, "snapshotCtx", null);
14003
13992
  __publicField(this, "lastSnapshotTime", 0);
14004
13993
  __publicField(this, "processMutation", (target, mutation) => {
14005
13994
  const newFrame = this.rafStamps.invokeId && this.rafStamps.latestId !== this.rafStamps.invokeId;
@@ -14015,20 +14004,16 @@ class CanvasManager {
14015
14004
  this.mutationCb = options.mutationCb;
14016
14005
  this.mirror = options.mirror;
14017
14006
  this.options = options;
14018
- if (recordCanvas && typeof sampling === "number") {
14019
- this.worker = this.initFPSWorker();
14020
- }
14021
14007
  this.addWindow(win);
14022
14008
  if (recordCanvas && sampling === "all") {
14023
14009
  this.startRAFTimestamping();
14024
14010
  this.startPendingCanvasMutationFlusher();
14025
14011
  }
14026
- if (recordCanvas && typeof sampling === "number") {
14012
+ if (recordCanvas && typeof sampling === "number" && canSnapshotCanvas()) {
14027
14013
  this.initCanvasFPSObserver();
14028
14014
  }
14029
14015
  }
14030
14016
  reset() {
14031
- var _a2;
14032
14017
  this.pendingCanvasMutations.clear();
14033
14018
  this.restoreHandlers.forEach((handler) => {
14034
14019
  try {
@@ -14040,9 +14025,10 @@ class CanvasManager {
14040
14025
  this.windowsSet = /* @__PURE__ */ new WeakSet();
14041
14026
  this.windows = [];
14042
14027
  this.shadowDoms = /* @__PURE__ */ new Set();
14043
- (_a2 = this.worker) == null ? void 0 : _a2.terminate();
14044
- this.worker = null;
14045
14028
  this.snapshotInProgressMap = /* @__PURE__ */ new Map();
14029
+ this.lastFingerprintMap = /* @__PURE__ */ new Map();
14030
+ this.snapshotCanvas = null;
14031
+ this.snapshotCtx = null;
14046
14032
  }
14047
14033
  freeze() {
14048
14034
  this.frozen = true;
@@ -14095,45 +14081,74 @@ class CanvasManager {
14095
14081
  resetShadowRoots() {
14096
14082
  this.shadowDoms = /* @__PURE__ */ new Set();
14097
14083
  }
14098
- initFPSWorker() {
14099
- const worker = new WorkerWrapper();
14100
- worker.onmessage = (e2) => {
14101
- const data = e2.data;
14102
- const { id } = data;
14103
- this.snapshotInProgressMap.set(id, false);
14104
- if (!("base64" in data)) return;
14105
- const { base64, type, width, height } = data;
14106
- this.mutationCb({
14084
+ /**
14085
+ * Encode one canvas frame (an ImageBitmap of the canvas) to a data blob on
14086
+ * the main thread, de-duplicating unchanged frames, and emit it as a canvas
14087
+ * mutation. Replaces the old blob-URL Worker, which crashed the renderer when
14088
+ * created inside sandboxed frames.
14089
+ */
14090
+ async snapshotImageBitmap(id, bitmap, width, height, dataURLOptions) {
14091
+ try {
14092
+ let offscreen = this.snapshotCanvas;
14093
+ if (!offscreen || offscreen.width !== width || offscreen.height !== height) {
14094
+ offscreen = new OffscreenCanvas(width, height);
14095
+ this.snapshotCanvas = offscreen;
14096
+ this.snapshotCtx = offscreen.getContext("2d");
14097
+ }
14098
+ const ctx = this.snapshotCtx;
14099
+ if (!ctx) return;
14100
+ ctx.clearRect(0, 0, width, height);
14101
+ ctx.drawImage(bitmap, 0, 0);
14102
+ const blob = await offscreen.convertToBlob(
14103
+ dataURLOptions
14104
+ );
14105
+ const arrayBuffer = await blob.arrayBuffer();
14106
+ const fingerprint = fnv1aHash(arrayBuffer);
14107
+ if (this.lastFingerprintMap.get(id) === fingerprint) return;
14108
+ this.lastFingerprintMap.set(id, fingerprint);
14109
+ this.emitCanvasSnapshot(
14107
14110
  id,
14108
- type: CanvasContext["2D"],
14109
- commands: [
14110
- {
14111
- property: "clearRect",
14112
- // wipe canvas
14113
- args: [0, 0, width, height]
14114
- },
14115
- {
14116
- property: "drawImage",
14117
- // draws (semi-transparent) image
14118
- args: [
14119
- {
14120
- rr_type: "ImageBitmap",
14121
- args: [
14122
- {
14123
- rr_type: "Blob",
14124
- data: [{ rr_type: "ArrayBuffer", base64 }],
14125
- type
14126
- }
14127
- ]
14128
- },
14129
- 0,
14130
- 0
14131
- ]
14132
- }
14133
- ]
14134
- });
14135
- };
14136
- return worker;
14111
+ encode(arrayBuffer),
14112
+ blob.type,
14113
+ width,
14114
+ height
14115
+ );
14116
+ } catch (e2) {
14117
+ } finally {
14118
+ bitmap.close();
14119
+ this.snapshotInProgressMap.set(id, false);
14120
+ }
14121
+ }
14122
+ emitCanvasSnapshot(id, base64, type, width, height) {
14123
+ this.mutationCb({
14124
+ id,
14125
+ type: CanvasContext["2D"],
14126
+ commands: [
14127
+ {
14128
+ property: "clearRect",
14129
+ // wipe canvas
14130
+ args: [0, 0, width, height]
14131
+ },
14132
+ {
14133
+ property: "drawImage",
14134
+ // draws (semi-transparent) image
14135
+ args: [
14136
+ {
14137
+ rr_type: "ImageBitmap",
14138
+ args: [
14139
+ {
14140
+ rr_type: "Blob",
14141
+ data: [{ rr_type: "ArrayBuffer", base64 }],
14142
+ type
14143
+ }
14144
+ ]
14145
+ },
14146
+ 0,
14147
+ 0
14148
+ ]
14149
+ }
14150
+ ]
14151
+ });
14137
14152
  }
14138
14153
  initCanvasFPSObserver() {
14139
14154
  let rafId;
@@ -14231,20 +14246,12 @@ class CanvasManager {
14231
14246
  context.clear(context.COLOR_BUFFER_BIT);
14232
14247
  }
14233
14248
  }
14234
- createImageBitmap(canvas).then((bitmap) => {
14235
- var _a3;
14236
- (_a3 = this.worker) == null ? void 0 : _a3.postMessage(
14237
- {
14238
- id,
14239
- bitmap,
14240
- width: canvas.width,
14241
- height: canvas.height,
14242
- dataURLOptions
14243
- },
14244
- [bitmap]
14245
- );
14246
- }).catch(() => {
14247
- this.snapshotInProgressMap.delete(id);
14249
+ const width = canvas.width;
14250
+ const height = canvas.height;
14251
+ createImageBitmap(canvas).then(
14252
+ (bitmap) => this.snapshotImageBitmap(id, bitmap, width, height, dataURLOptions)
14253
+ ).catch(() => {
14254
+ this.snapshotInProgressMap.set(id, false);
14248
14255
  });
14249
14256
  });
14250
14257
  }
@@ -15619,10 +15626,10 @@ function deserializeArg(imageMap, ctx, preload) {
15619
15626
  const blobContents = await Promise.all(
15620
15627
  arg.data.map(deserializeArg(imageMap, ctx, preload))
15621
15628
  );
15622
- const blob2 = new Blob(blobContents, {
15629
+ const blob = new Blob(blobContents, {
15623
15630
  type: arg.type
15624
15631
  });
15625
- return blob2;
15632
+ return blob;
15626
15633
  }
15627
15634
  } else if (Array.isArray(arg)) {
15628
15635
  const result2 = await Promise.all(