@kalayanasundaram123/rrweb 2.0.2 → 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.2",
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,37 +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);
13987
13971
  }
13988
- function canCreateBlobWorker(win) {
13989
- try {
13990
- return typeof Worker !== "undefined" && win.origin != null && win.origin !== "null";
13991
- } catch (e2) {
13992
- return false;
13993
- }
13972
+ function canSnapshotCanvas() {
13973
+ return typeof OffscreenCanvas !== "undefined";
13994
13974
  }
13995
13975
  class CanvasManager {
13996
13976
  constructor(options) {
@@ -14006,7 +13986,9 @@ class CanvasManager {
14006
13986
  __publicField(this, "frozen", false);
14007
13987
  __publicField(this, "locked", false);
14008
13988
  __publicField(this, "snapshotInProgressMap", /* @__PURE__ */ new Map());
14009
- __publicField(this, "worker", null);
13989
+ __publicField(this, "lastFingerprintMap", /* @__PURE__ */ new Map());
13990
+ __publicField(this, "snapshotCanvas", null);
13991
+ __publicField(this, "snapshotCtx", null);
14010
13992
  __publicField(this, "lastSnapshotTime", 0);
14011
13993
  __publicField(this, "processMutation", (target, mutation) => {
14012
13994
  const newFrame = this.rafStamps.invokeId && this.rafStamps.latestId !== this.rafStamps.invokeId;
@@ -14022,20 +14004,16 @@ class CanvasManager {
14022
14004
  this.mutationCb = options.mutationCb;
14023
14005
  this.mirror = options.mirror;
14024
14006
  this.options = options;
14025
- if (recordCanvas && typeof sampling === "number" && canCreateBlobWorker(win)) {
14026
- this.worker = this.initFPSWorker();
14027
- }
14028
14007
  this.addWindow(win);
14029
14008
  if (recordCanvas && sampling === "all") {
14030
14009
  this.startRAFTimestamping();
14031
14010
  this.startPendingCanvasMutationFlusher();
14032
14011
  }
14033
- if (recordCanvas && typeof sampling === "number" && this.worker) {
14012
+ if (recordCanvas && typeof sampling === "number" && canSnapshotCanvas()) {
14034
14013
  this.initCanvasFPSObserver();
14035
14014
  }
14036
14015
  }
14037
14016
  reset() {
14038
- var _a2;
14039
14017
  this.pendingCanvasMutations.clear();
14040
14018
  this.restoreHandlers.forEach((handler) => {
14041
14019
  try {
@@ -14047,9 +14025,10 @@ class CanvasManager {
14047
14025
  this.windowsSet = /* @__PURE__ */ new WeakSet();
14048
14026
  this.windows = [];
14049
14027
  this.shadowDoms = /* @__PURE__ */ new Set();
14050
- (_a2 = this.worker) == null ? void 0 : _a2.terminate();
14051
- this.worker = null;
14052
14028
  this.snapshotInProgressMap = /* @__PURE__ */ new Map();
14029
+ this.lastFingerprintMap = /* @__PURE__ */ new Map();
14030
+ this.snapshotCanvas = null;
14031
+ this.snapshotCtx = null;
14053
14032
  }
14054
14033
  freeze() {
14055
14034
  this.frozen = true;
@@ -14102,45 +14081,74 @@ class CanvasManager {
14102
14081
  resetShadowRoots() {
14103
14082
  this.shadowDoms = /* @__PURE__ */ new Set();
14104
14083
  }
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({
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(
14114
14110
  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;
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
+ });
14144
14152
  }
14145
14153
  initCanvasFPSObserver() {
14146
14154
  let rafId;
@@ -14238,20 +14246,12 @@ class CanvasManager {
14238
14246
  context.clear(context.COLOR_BUFFER_BIT);
14239
14247
  }
14240
14248
  }
14241
- createImageBitmap(canvas).then((bitmap) => {
14242
- var _a3;
14243
- (_a3 = this.worker) == null ? void 0 : _a3.postMessage(
14244
- {
14245
- id,
14246
- bitmap,
14247
- width: canvas.width,
14248
- height: canvas.height,
14249
- dataURLOptions
14250
- },
14251
- [bitmap]
14252
- );
14253
- }).catch(() => {
14254
- 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);
14255
14255
  });
14256
14256
  });
14257
14257
  }
@@ -15626,10 +15626,10 @@ function deserializeArg(imageMap, ctx, preload) {
15626
15626
  const blobContents = await Promise.all(
15627
15627
  arg.data.map(deserializeArg(imageMap, ctx, preload))
15628
15628
  );
15629
- const blob2 = new Blob(blobContents, {
15629
+ const blob = new Blob(blobContents, {
15630
15630
  type: arg.type
15631
15631
  });
15632
- return blob2;
15632
+ return blob;
15633
15633
  }
15634
15634
  } else if (Array.isArray(arg)) {
15635
15635
  const result2 = await Promise.all(