Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rrweb-worker package #1448

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Conversation

daibhin
Copy link
Contributor

@daibhin daibhin commented Apr 12, 2024

Since #1309 it looks like canvas mutations are not captured in certain environments. As was described in a comment on the change

From my investigations it looks like the worker in the canvas-mutation is not capturing messages in the onmessage handler:

worker.onmessage = (e) => {
const { id } = e.data;
snapshotInProgressMap.set(id, false);
if (!('base64' in e.data)) return;
const { base64, type, width, height } = e.data;
this.mutationCb({
id,
type: CanvasContext['2D'],
commands: [
{
property: 'clearRect', // wipe canvas
args: [0, 0, width, height],
},
{
property: 'drawImage', // draws (semi-transparent) image
args: [
{
rr_type: 'ImageBitmap',
args: [
{
rr_type: 'Blob',
data: [{ rr_type: 'ArrayBuffer', base64 }],
type,
},
],
} as CanvasArg,
0,
0,
],
},
],
});
};
const timeBetweenSnapshots = 1000 / fps;
let lastSnapshotTime = 0;
let rafId: number;
const getCanvas = (): HTMLCanvasElement[] => {
const matchedCanvas: HTMLCanvasElement[] = [];
win.document.querySelectorAll('canvas').forEach((canvas) => {
if (!isBlocked(canvas, blockClass, blockSelector, true)) {
matchedCanvas.push(canvas);
}
});
return matchedCanvas;
};
const takeCanvasSnapshots = (timestamp: DOMHighResTimeStamp) => {
if (
lastSnapshotTime &&
timestamp - lastSnapshotTime < timeBetweenSnapshots
) {
rafId = requestAnimationFrame(takeCanvasSnapshots);
return;
}
lastSnapshotTime = timestamp;
getCanvas()
// eslint-disable-next-line @typescript-eslint/no-misused-promises
.forEach(async (canvas: HTMLCanvasElement) => {
const id = this.mirror.getId(canvas);
if (snapshotInProgressMap.get(id)) return;
// The browser throws if the canvas is 0 in size
// Uncaught (in promise) DOMException: Failed to execute 'createImageBitmap' on 'Window': The source image width is 0.
// Assuming the same happens with height
if (canvas.width === 0 || canvas.height === 0) return;
snapshotInProgressMap.set(id, true);
if (['webgl', 'webgl2'].includes((canvas as ICanvas).__context)) {
// if the canvas hasn't been modified recently,
// its contents won't be in memory and `createImageBitmap`
// will return a transparent imageBitmap
const context = canvas.getContext((canvas as ICanvas).__context) as
| WebGLRenderingContext
| WebGL2RenderingContext
| null;
if (
context?.getContextAttributes()?.preserveDrawingBuffer === false
) {
// Hack to load canvas back into memory so `createImageBitmap` can grab it's contents.
// Context: https://twitter.com/Juice10/status/1499775271758704643
// Preferably we set `preserveDrawingBuffer` to true, but that's not always possible,
// especially when canvas is loaded before rrweb.
// This hack can wipe the background color of the canvas in the (unlikely) event that
// the canvas background was changed but clear was not called directly afterwards.
// Example of this hack having negative side effect: https://visgl.github.io/react-map-gl/examples/layers
context.clear(context.COLOR_BUFFER_BIT);
}
}
const bitmap = await createImageBitmap(canvas);
worker.postMessage(
{
id,
bitmap,
width: canvas.width,
height: canvas.height,
dataURLOptions: options.dataURLOptions,
},
[bitmap],
);

I couldn't find any reason this stopped working but another bug (#1377) suggests that it is altering the outputted worker.

@mydea also discovered that the current worker setup might be causing issues with tree shaking and has adapted their fork to include a new rrweb-worker package. I went ahead and ported their solution over here as proposed in #1376.

This removes the reliance on rollup-plugin-web-worker-loader which introduced the behaviour I'm seeing

Copy link

changeset-bot bot commented Apr 12, 2024

⚠️ No Changeset found

Latest commit: 948c365

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant