diff --git a/.changeset/small-olives-arrive.md b/.changeset/small-olives-arrive.md new file mode 100644 index 0000000000..36bacbc168 --- /dev/null +++ b/.changeset/small-olives-arrive.md @@ -0,0 +1,5 @@ +--- +'rrweb-snapshot': patch +--- + +Fix: [#1172](https://github.com/rrweb-io/rrweb/issues/1172) don't replace original onload function of Images diff --git a/packages/rrweb-snapshot/src/snapshot.ts b/packages/rrweb-snapshot/src/snapshot.ts index 4b88464fd3..dd0bef968a 100644 --- a/packages/rrweb-snapshot/src/snapshot.ts +++ b/packages/rrweb-snapshot/src/snapshot.ts @@ -736,6 +736,7 @@ function serializeElementNode( const oldValue = image.crossOrigin; image.crossOrigin = 'anonymous'; const recordInlineImage = () => { + image.removeEventListener('load', recordInlineImage); try { canvasService!.width = image.naturalWidth; canvasService!.height = image.naturalHeight; @@ -755,7 +756,7 @@ function serializeElementNode( }; // The image content may not have finished loading yet. if (image.complete && image.naturalWidth !== 0) recordInlineImage(); - else image.onload = recordInlineImage; + else image.addEventListener('load', recordInlineImage); } // media elements if (tagName === 'audio' || tagName === 'video') { diff --git a/packages/rrweb-snapshot/test/html/picture-with-inline-onload.html b/packages/rrweb-snapshot/test/html/picture-with-inline-onload.html new file mode 100644 index 0000000000..cc0fed38ef --- /dev/null +++ b/packages/rrweb-snapshot/test/html/picture-with-inline-onload.html @@ -0,0 +1,10 @@ + +
+ + + diff --git a/packages/rrweb-snapshot/test/integration.test.ts b/packages/rrweb-snapshot/test/integration.test.ts index c937726071..dcc6a3ec0b 100644 --- a/packages/rrweb-snapshot/test/integration.test.ts +++ b/packages/rrweb-snapshot/test/integration.test.ts @@ -303,6 +303,28 @@ iframe.contentDocument.querySelector('center').clientHeight )) as string; assert(snapshot.includes('-webkit-background-clip: text;')); }); + + it('images with inline onload should work', async () => { + const page: puppeteer.Page = await browser.newPage(); + + await page.goto( + 'http://localhost:3030/html/picture-with-inline-onload.html', + { + waitUntil: 'load', + }, + ); + await page.waitForSelector('img', { timeout: 1000 }); + await page.evaluate(`${code}var snapshot = rrweb.snapshot(document, { + dataURLOptions: { type: "image/webp", quality: 0.8 }, + inlineImages: true, + inlineStylesheet: false + })`); + await waitForRAF(page); + const fnName = (await page.evaluate( + 'document.querySelector("img").onload.name', + )) as string; + assert(fnName === 'onload'); + }); }); describe('iframe integration tests', function (this: ISuite) {