Skip to content

Commit

Permalink
Don't use the CSSOM when there's var() present as it fails badly rr…
Browse files Browse the repository at this point in the history
  • Loading branch information
eoghanmurray committed Jul 27, 2023
1 parent c6600e7 commit b25d447
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 1 deletion.
5 changes: 4 additions & 1 deletion packages/rrweb/src/record/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,10 @@ export default class MutationBuffer {
target.setAttribute('data-rr-is-password', 'true');
}

if (attributeName === 'style') {
if (attributeName === 'style' &&
(value as string).indexOf('var(') === -1 &&
typeof item.attributes.style !== 'string'
) {
const old = unattachedDoc.createElement('span');
if (m.oldValue) {
old.setAttribute('style', m.oldValue);
Expand Down
128 changes: 128 additions & 0 deletions packages/rrweb/test/__snapshots__/integration.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3391,6 +3391,134 @@ exports[`record integration tests can record node mutations 1`] = `
]"
`;

exports[`record integration tests can record style changes compactly and preserve css var() functions 1`] = `
"[
{
\\"type\\": 0,
\\"data\\": {}
},
{
\\"type\\": 1,
\\"data\\": {}
},
{
\\"type\\": 4,
\\"data\\": {
\\"href\\": \\"about:blank\\",
\\"width\\": 1920,
\\"height\\": 1080
}
},
{
\\"type\\": 2,
\\"data\\": {
\\"node\\": {
\\"type\\": 0,
\\"childNodes\\": [
{
\\"type\\": 2,
\\"tagName\\": \\"html\\",
\\"attributes\\": {},
\\"childNodes\\": [
{
\\"type\\": 2,
\\"tagName\\": \\"head\\",
\\"attributes\\": {},
\\"childNodes\\": [],
\\"id\\": 3
},
{
\\"type\\": 2,
\\"tagName\\": \\"body\\",
\\"attributes\\": {},
\\"childNodes\\": [
{
\\"type\\": 3,
\\"textContent\\": \\"\\\\n \\",
\\"id\\": 5
},
{
\\"type\\": 2,
\\"tagName\\": \\"script\\",
\\"attributes\\": {},
\\"childNodes\\": [
{
\\"type\\": 3,
\\"textContent\\": \\"SCRIPT_PLACEHOLDER\\",
\\"id\\": 7
}
],
\\"id\\": 6
},
{
\\"type\\": 3,
\\"textContent\\": \\"\\\\n \\\\n \\\\n\\\\n\\",
\\"id\\": 8
}
],
\\"id\\": 4
}
],
\\"id\\": 2
}
],
\\"compatMode\\": \\"BackCompat\\",
\\"id\\": 1
},
\\"initialOffset\\": {
\\"left\\": 0,
\\"top\\": 0
}
}
},
{
\\"type\\": 3,
\\"data\\": {
\\"source\\": 0,
\\"texts\\": [],
\\"attributes\\": [
{
\\"id\\": 4,
\\"attributes\\": {
\\"style\\": \\"background: var(--mystery)\\"
}
}
],
\\"removes\\": [],
\\"adds\\": []
}
},
{
\\"type\\": 3,
\\"data\\": {
\\"source\\": 0,
\\"texts\\": [],
\\"attributes\\": [
{
\\"id\\": 4,
\\"attributes\\": {
\\"style\\": {
\\"background-color\\": \\"black\\",
\\"background-image\\": false,
\\"background-position-x\\": false,
\\"background-position-y\\": false,
\\"background-size\\": false,
\\"background-repeat-x\\": false,
\\"background-repeat-y\\": false,
\\"background-attachment\\": false,
\\"background-origin\\": false,
\\"background-clip\\": false
}
}
}
],
\\"removes\\": [],
\\"adds\\": []
}
}
]"
`;

exports[`record integration tests can use maskInputOptions to configure which type of inputs should be masked 1`] = `
"[
{
Expand Down
23 changes: 23 additions & 0 deletions packages/rrweb/test/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,29 @@ describe('record integration tests', function (this: ISuite) {
assertSnapshot(snapshots);
});

it('can record style changes compactly and preserve css var() functions', async () => {
const page: puppeteer.Page = await browser.newPage();
await page.goto('about:blank');
await page.setContent(getHtml.call(this, 'blank.html'), {
waitUntil: 'networkidle0',
});

// goal here is to ensure var(--mystery) ends up in the mutations
await page.evaluate(
'document.body.setAttribute("style", "background: var(--mystery)")',
);
await page.waitForTimeout(50);
// and here that we can revert to { background: false, background-color: 'black' } format (assuming we've used string format for above)
await page.evaluate(
'document.body.setAttribute("style", "background-color: black")',
);

const snapshots = (await page.evaluate(
'window.snapshots',
)) as eventWithTime[];
assertSnapshot(snapshots);
});

it('can freeze mutations', async () => {
const page: puppeteer.Page = await browser.newPage();
await page.goto('about:blank');
Expand Down

0 comments on commit b25d447

Please sign in to comment.