inlineImages: Setting of image.crossOrigin is not always necessary (#1468)

Setting of the `crossorigin` attribute is not necessary for same-origin images, and causes an immediate image reload (albeit from cache) necessitating the use of a load event listener which subsequently mutates the snapshot.  This change allows us to  avoid the mutation of the snapshot for the same-origin case.

* Modify inlineImages test to remove delay and show that we can inline images without mutation

* Add an explicit test for when the `image.crossOrigin = 'anonymous';` method is necessary.  Uses a combination of about:blank and our test server to simulate a cross-origin context

* Other test changes: there were some spurious rrweb mutations being generated by the addition of the crossorigin attribute that are now elimnated from the rrweb/__snapshots__/integration.test.ts.snap after this PR - this is good
This commit is contained in:
Eoghan Murray
2024-05-23 11:08:49 +01:00
committed by GitHub
parent 81c54abab2
commit 4014305944
8 changed files with 95 additions and 117 deletions

View File

@@ -747,8 +747,9 @@ function serializeElementNode(
canvasCtx = canvasService.getContext('2d');
}
const image = n as HTMLImageElement;
const oldValue = image.crossOrigin;
image.crossOrigin = 'anonymous';
const imageSrc: string =
image.currentSrc || image.getAttribute('src') || '<unknown-src>';
const priorCrossOrigin = image.crossOrigin;
const recordInlineImage = () => {
image.removeEventListener('load', recordInlineImage);
try {
@@ -760,13 +761,23 @@ function serializeElementNode(
dataURLOptions.quality,
);
} catch (err) {
console.warn(
`Cannot inline img src=${image.currentSrc}! Error: ${err as string}`,
);
if (image.crossOrigin !== 'anonymous') {
image.crossOrigin = 'anonymous';
if (image.complete && image.naturalWidth !== 0)
recordInlineImage(); // too early due to image reload
else image.addEventListener('load', recordInlineImage);
return;
} else {
console.warn(
`Cannot inline img src=${imageSrc}! Error: ${err as string}`,
);
}
}
if (image.crossOrigin === 'anonymous') {
priorCrossOrigin
? (attributes.crossOrigin = priorCrossOrigin)
: image.removeAttribute('crossorigin');
}
oldValue
? (attributes.crossOrigin = oldValue)
: image.removeAttribute('crossorigin');
};
// The image content may not have finished loading yet.
if (image.complete && image.naturalWidth !== 0) recordInlineImage();