Skip to content

Commit

Permalink
improve canvas serialization performance
Browse files Browse the repository at this point in the history
  • Loading branch information
Vadman97 committed Sep 23, 2024
1 parent d724257 commit 51c6e3d
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 6 deletions.
12 changes: 10 additions & 2 deletions packages/rrweb-snapshot/src/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,8 @@ function serializeTextNode(
cssCaptured?: boolean;
},
): serializedNode {
const { needsMask, maskTextFn, privacySetting, rootId, cssCaptured } = options;
const { needsMask, maskTextFn, privacySetting, rootId, cssCaptured } =
options;
// The parent node may not be a html element which has a tagName attribute.
// So just let it be undefined which is ok in this use case.
const parent = dom.parentNode(n);
Expand Down Expand Up @@ -551,7 +552,11 @@ function serializeTextNode(
n.parentElement?.getAttribute('data-hl-record');
const obfuscateDefaultPrivacy =
privacySetting === 'default' && shouldObfuscateTextByDefault(textContent);
if ((enableStrictPrivacy || obfuscateDefaultPrivacy) && !highlightOverwriteRecord && parentTagName) {
if (
(enableStrictPrivacy || obfuscateDefaultPrivacy) &&
!highlightOverwriteRecord &&
parentTagName
) {
const IGNORE_TAG_NAMES = new Set([
'HEAD',
'TITLE',
Expand Down Expand Up @@ -704,10 +709,13 @@ function serializeElementNode(
if ((n as ICanvas).__context === '2d') {
// only record this on 2d canvas
if (!is2DCanvasBlank(n as HTMLCanvasElement)) {
/** Start of Highlight Code
* Avoid capturing non-blank 2d canvas here - defer to canvas-manager.ts for better performance
attributes.rr_dataURL = (n as HTMLCanvasElement).toDataURL(
dataURLOptions.type,
dataURLOptions.quality,
);
End of Highlight Code **/
}
} else if (!('__context' in n)) {
// context is unknown, better not call getContext to trigger it
Expand Down
33 changes: 29 additions & 4 deletions packages/rrweb/src/record/observers/canvas/canvas-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export class CanvasManager {
],
},
],
}
};
this.debug(null, 'canvas worker recording mutation', mutation);
this.mutationCb(mutation);
};
Expand Down Expand Up @@ -337,9 +337,27 @@ export class CanvasManager {
let rafId: number;

const elementFoundTime: Map<number, number> = new Map();

const querySelectorAll = <T extends 'canvas' | 'video'>(
node: ParentNode,
selector: T,
): (T extends 'canvas' ? HTMLCanvasElement : HTMLVideoElement)[] => {
type NodeType = T extends 'canvas' ? HTMLCanvasElement : HTMLVideoElement;
const nodes: NodeType[] = [];
node.querySelectorAll(selector).forEach((n) => nodes.push(n as NodeType));
const nodeIterator = document.createNodeIterator(node, Node.ELEMENT_NODE);
let currentNode: Element | null;
while ((currentNode = nodeIterator.nextNode() as Element | null)) {
if (currentNode?.shadowRoot) {
nodes.push(...querySelectorAll(currentNode.shadowRoot, selector));
}
}
return nodes;
};

const getCanvas = (timestamp: DOMHighResTimeStamp): HTMLCanvasElement[] => {
const matchedCanvas: HTMLCanvasElement[] = [];
win.document.querySelectorAll('canvas').forEach((canvas) => {
querySelectorAll(win.document, 'canvas').forEach((canvas) => {
if (!isBlocked(canvas, blockClass, blockSelector, true)) {
this.debug(canvas, 'discovered canvas');
matchedCanvas.push(canvas);
Expand All @@ -355,7 +373,7 @@ export class CanvasManager {
const getVideos = (timestamp: DOMHighResTimeStamp): HTMLVideoElement[] => {
const matchedVideos: HTMLVideoElement[] = [];
if (recordVideos) {
win.document.querySelectorAll('video').forEach((video) => {
querySelectorAll(win.document, 'video').forEach((video) => {
if (video.src !== '' && video.src.indexOf('blob:') === -1) return;
if (!isBlocked(video, blockClass, blockSelector, true)) {
matchedVideos.push(video);
Expand Down Expand Up @@ -428,7 +446,14 @@ export class CanvasManager {
// video is not yet ready... this retry on the next sampling iteration.
// we don't want to crash the worker by sending an undefined bitmap
// if the video is not yet rendered.
if (video.width === 0 || video.height === 0 || actualWidth === 0 || actualHeight === 0 || boxWidth === 0 || boxHeight === 0) {
if (
video.width === 0 ||
video.height === 0 ||
actualWidth === 0 ||
actualHeight === 0 ||
boxWidth === 0 ||
boxHeight === 0
) {
this.debug(video, 'not yet ready', {
width: video.width,
height: video.height,
Expand Down

0 comments on commit 51c6e3d

Please sign in to comment.