From 50699e33ac0307798b69ef91994692e729c0dc6a Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Mon, 11 Aug 2025 11:49:19 -0400 Subject: [PATCH 1/3] feat(replay): Add option to skip `requestAnimationFrame` for canvas snapshots This adds an option to `snapshot()` to skip `requestAnimationFrame` when manually snapshotting. --- packages/replay-canvas/src/canvas.ts | 30 +++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/replay-canvas/src/canvas.ts b/packages/replay-canvas/src/canvas.ts index d026567e01b1..ad253fec22ce 100644 --- a/packages/replay-canvas/src/canvas.ts +++ b/packages/replay-canvas/src/canvas.ts @@ -3,8 +3,12 @@ import { defineIntegration } from '@sentry/core'; import type { CanvasManagerInterface, CanvasManagerOptions } from '@sentry-internal/replay'; import { CanvasManager } from '@sentry-internal/rrweb'; +interface SnapshotOptions { + skipRequestAnimationFrame?: boolean; +} + interface ReplayCanvasIntegration extends Integration { - snapshot: (canvasElement?: HTMLCanvasElement) => Promise; + snapshot: (canvasElement?: HTMLCanvasElement, options?: SnapshotOptions) => Promise; } interface ReplayCanvasOptions { @@ -106,9 +110,29 @@ export const _replayCanvasIntegration = ((options: Partial ...(CANVAS_QUALITY[quality || 'medium'] || CANVAS_QUALITY.medium), }; }, - async snapshot(canvasElement?: HTMLCanvasElement) { + async snapshot(canvasElement?: HTMLCanvasElement, options?: SnapshotOptions) { const canvasManager = await _canvasManager; - canvasManager.snapshot(canvasElement); + + canvasManager.snapshot(canvasElement, options); + // createImageBitmap(canvasElement).then(async imageBitmap => { + // // debug + // const canvas = document.getElementById('test'); + // canvas.height = imageBitmap.height; + // canvas.width = imageBitmap.width; + // // temp1.getContext("2d").drawImage(bitmap, 0, 0); + // // const canvas = new OffscreenCanvas(imageBitmap.width, imageBitmap.height); + // const ctx = canvas.getContext('2d'); + // + // // Draw the ImageBitmap onto the canvas + // ctx.drawImage(imageBitmap, 0, 0); + // + // // Convert the canvas content to a data URL (Base64 encoded PNG by default) + // const dataURL = await canvas.toDataURL('image/webp'); // Specify format if needed + // + // console.log(dataURL); + // canvasManager.snapshotBitmap(canvasElement, imageBitmap); + // imageBitmap.close(); + // }); }, }; }) satisfies IntegrationFn; From 69ee75e6ae8bd6ae1fd3bc635fcce45b081ae460 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Wed, 13 Aug 2025 12:23:19 -0400 Subject: [PATCH 2/3] bump rrweb --- packages/replay-canvas/package.json | 2 +- packages/replay-internal/package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/replay-canvas/package.json b/packages/replay-canvas/package.json index 9ad13954d08c..5d6d0a631ad3 100644 --- a/packages/replay-canvas/package.json +++ b/packages/replay-canvas/package.json @@ -66,7 +66,7 @@ }, "homepage": "https://docs.sentry.io/platforms/javascript/session-replay/", "devDependencies": { - "@sentry-internal/rrweb": "2.35.0" + "@sentry-internal/rrweb": "2.37.0" }, "dependencies": { "@sentry-internal/replay": "10.5.0", diff --git a/packages/replay-internal/package.json b/packages/replay-internal/package.json index 64ea2974abb0..d0b853e496b0 100644 --- a/packages/replay-internal/package.json +++ b/packages/replay-internal/package.json @@ -82,8 +82,8 @@ "devDependencies": { "@babel/core": "^7.27.7", "@sentry-internal/replay-worker": "10.5.0", - "@sentry-internal/rrweb": "2.35.0", - "@sentry-internal/rrweb-snapshot": "2.35.0", + "@sentry-internal/rrweb": "2.37.0", + "@sentry-internal/rrweb-snapshot": "2.37.0", "fflate": "0.8.2", "jest-matcher-utils": "^29.0.0", "jsdom-worker": "^0.3.0", From 39f4e0a97f844bed66b56185fd5784410b6e5918 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Wed, 13 Aug 2025 13:51:58 -0400 Subject: [PATCH 3/3] oops comments --- packages/replay-canvas/src/canvas.ts | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/packages/replay-canvas/src/canvas.ts b/packages/replay-canvas/src/canvas.ts index ad253fec22ce..7861572b190f 100644 --- a/packages/replay-canvas/src/canvas.ts +++ b/packages/replay-canvas/src/canvas.ts @@ -114,25 +114,6 @@ export const _replayCanvasIntegration = ((options: Partial const canvasManager = await _canvasManager; canvasManager.snapshot(canvasElement, options); - // createImageBitmap(canvasElement).then(async imageBitmap => { - // // debug - // const canvas = document.getElementById('test'); - // canvas.height = imageBitmap.height; - // canvas.width = imageBitmap.width; - // // temp1.getContext("2d").drawImage(bitmap, 0, 0); - // // const canvas = new OffscreenCanvas(imageBitmap.width, imageBitmap.height); - // const ctx = canvas.getContext('2d'); - // - // // Draw the ImageBitmap onto the canvas - // ctx.drawImage(imageBitmap, 0, 0); - // - // // Convert the canvas content to a data URL (Base64 encoded PNG by default) - // const dataURL = await canvas.toDataURL('image/webp'); // Specify format if needed - // - // console.log(dataURL); - // canvasManager.snapshotBitmap(canvasElement, imageBitmap); - // imageBitmap.close(); - // }); }, }; }) satisfies IntegrationFn;