fix: remote CSS does not get rebuilt properly (#1618)
* fix: remote CSS does not get rebuilt properly This fixes an issue where inlined CSS from a remotely loaded `<link>` does not get applied properly due to object reference mutation. * add changeset * ci-cd on ubuntu-22.04 instead of latest * keep mirror meta synced
This commit is contained in:
5
.changeset/red-peaches-explode.md
Normal file
5
.changeset/red-peaches-explode.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"rrweb": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
This fixes an issue where inlined CSS from a remotely loaded `<link>` does not get applied properly due to object reference mutation.
|
||||||
@@ -1792,17 +1792,27 @@ export class Replayer {
|
|||||||
const newSn = mirror.getMeta(
|
const newSn = mirror.getMeta(
|
||||||
target as Node & RRNode,
|
target as Node & RRNode,
|
||||||
) as serializedElementNodeWithId;
|
) as serializedElementNodeWithId;
|
||||||
|
const newNode = buildNodeWithSN(
|
||||||
|
{
|
||||||
|
...newSn,
|
||||||
|
attributes: {
|
||||||
|
...newSn.attributes,
|
||||||
|
...(mutation.attributes as attributes),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: target.ownerDocument as Document, // can be Document or RRDocument
|
||||||
|
mirror: mirror as Mirror,
|
||||||
|
skipChild: true,
|
||||||
|
hackCss: true,
|
||||||
|
cache: this.cache,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
// Update mirror meta's attributes
|
||||||
Object.assign(
|
Object.assign(
|
||||||
newSn.attributes,
|
newSn.attributes,
|
||||||
mutation.attributes as attributes,
|
mutation.attributes as attributes,
|
||||||
);
|
);
|
||||||
const newNode = buildNodeWithSN(newSn, {
|
|
||||||
doc: target.ownerDocument as Document, // can be Document or RRDocument
|
|
||||||
mirror: mirror as Mirror,
|
|
||||||
skipChild: true,
|
|
||||||
hackCss: true,
|
|
||||||
cache: this.cache,
|
|
||||||
});
|
|
||||||
const siblingNode = target.nextSibling;
|
const siblingNode = target.nextSibling;
|
||||||
const parentNode = target.parentNode;
|
const parentNode = target.parentNode;
|
||||||
if (newNode && parentNode) {
|
if (newNode && parentNode) {
|
||||||
|
|||||||
@@ -158,6 +158,73 @@ file-cid-3
|
|||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`replayer > can handle remote stylesheets 1`] = `
|
||||||
|
"file-frame-2
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv=\\"Content-Type\\" content=\\"text/html; charset=UTF-8\\" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class=\\"replayer-wrapper\\">
|
||||||
|
<div class=\\"replayer-mouse\\"></div>
|
||||||
|
<canvas
|
||||||
|
class=\\"replayer-mouse-tail\\"
|
||||||
|
width=\\"1000\\"
|
||||||
|
height=\\"800\\"
|
||||||
|
style=\\"display: inherit\\"
|
||||||
|
></canvas
|
||||||
|
><iframe
|
||||||
|
sandbox=\\"allow-same-origin\\"
|
||||||
|
scrolling=\\"no\\"
|
||||||
|
width=\\"1000\\"
|
||||||
|
height=\\"800\\"
|
||||||
|
style=\\"display: inherit; pointer-events: none\\"
|
||||||
|
></iframe>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
file-frame-3
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv=\\"Content-Type\\" content=\\"text/html; charset=UTF-8\\" />
|
||||||
|
<link rel=\\"stylesheet\\" type=\\"text/css\\" href=\\"file-cid-0\\" />
|
||||||
|
<link rel=\\"stylesheet\\" type=\\"text/css\\" href=\\"file-cid-1\\" />
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
file-cid-0
|
||||||
|
@charset \\"utf-8\\";
|
||||||
|
|
||||||
|
.rr-block { background: currentcolor; }
|
||||||
|
|
||||||
|
noscript { display: none !important; }
|
||||||
|
|
||||||
|
html.rrweb-paused *, html.rrweb-paused ::before, html.rrweb-paused ::after { animation-play-state: paused !important; }
|
||||||
|
|
||||||
|
|
||||||
|
file-cid-1
|
||||||
|
@charset \\"utf-8\\";
|
||||||
|
|
||||||
|
.OverlayDrawer-modal-187 { }
|
||||||
|
|
||||||
|
.OverlayDrawer-paper-188 { width: 100%; }
|
||||||
|
|
||||||
|
@media (min-width: 48em) {
|
||||||
|
.OverlayDrawer-paper-188 { width: 38rem; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 48em) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 48em) {
|
||||||
|
}
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`replayer > can handle removing style elements 1`] = `
|
exports[`replayer > can handle removing style elements 1`] = `
|
||||||
"file-frame-1
|
"file-frame-1
|
||||||
<html>
|
<html>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
launchPuppeteer,
|
launchPuppeteer,
|
||||||
sampleEvents as events,
|
sampleEvents as events,
|
||||||
sampleStyleSheetRemoveEvents as stylesheetRemoveEvents,
|
sampleStyleSheetRemoveEvents as stylesheetRemoveEvents,
|
||||||
|
sampleRemoteStyleSheetEvents as remoteStyleSheetEvents,
|
||||||
waitForRAF,
|
waitForRAF,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import styleSheetRuleEvents from './events/style-sheet-rule-events';
|
import styleSheetRuleEvents from './events/style-sheet-rule-events';
|
||||||
@@ -209,6 +210,23 @@ describe('replayer', function () {
|
|||||||
await assertDomSnapshot(page);
|
await assertDomSnapshot(page);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('can handle remote stylesheets', async () => {
|
||||||
|
await page.evaluate(`events = ${JSON.stringify(remoteStyleSheetEvents)}`);
|
||||||
|
const actionLength = await page.evaluate(`
|
||||||
|
const { Replayer } = rrweb;
|
||||||
|
const replayer = new Replayer(events);
|
||||||
|
replayer.play(2500);
|
||||||
|
replayer['timer']['actions'].length;
|
||||||
|
`);
|
||||||
|
expect(actionLength).toEqual(
|
||||||
|
remoteStyleSheetEvents.filter(
|
||||||
|
(e) => e.timestamp - remoteStyleSheetEvents[0].timestamp >= 2500,
|
||||||
|
).length,
|
||||||
|
);
|
||||||
|
|
||||||
|
await assertDomSnapshot(page);
|
||||||
|
});
|
||||||
|
|
||||||
it('can fast forward selection events', async () => {
|
it('can fast forward selection events', async () => {
|
||||||
await page.evaluate(`events = ${JSON.stringify(selectionEvents)}`);
|
await page.evaluate(`events = ${JSON.stringify(selectionEvents)}`);
|
||||||
|
|
||||||
|
|||||||
@@ -561,6 +561,98 @@ export const sampleStyleSheetRemoveEvents: eventWithTime[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const sampleRemoteStyleSheetEvents: eventWithTime[] = [
|
||||||
|
{
|
||||||
|
type: EventType.DomContentLoaded,
|
||||||
|
data: {},
|
||||||
|
timestamp: now,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: EventType.Load,
|
||||||
|
data: {},
|
||||||
|
timestamp: now + 1000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: EventType.Meta,
|
||||||
|
data: {
|
||||||
|
href: 'http://localhost',
|
||||||
|
width: 1000,
|
||||||
|
height: 800,
|
||||||
|
},
|
||||||
|
timestamp: now + 1000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: EventType.FullSnapshot,
|
||||||
|
data: {
|
||||||
|
node: {
|
||||||
|
type: 0,
|
||||||
|
childNodes: [
|
||||||
|
{
|
||||||
|
type: 2,
|
||||||
|
tagName: 'html',
|
||||||
|
attributes: {},
|
||||||
|
childNodes: [
|
||||||
|
{
|
||||||
|
type: 2,
|
||||||
|
tagName: 'head',
|
||||||
|
attributes: {},
|
||||||
|
childNodes: [
|
||||||
|
{
|
||||||
|
type: 2,
|
||||||
|
tagName: 'link',
|
||||||
|
attributes: {
|
||||||
|
rel: 'stylesheet',
|
||||||
|
href: '',
|
||||||
|
},
|
||||||
|
childNodes: [],
|
||||||
|
id: 4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 2,
|
||||||
|
tagName: 'body',
|
||||||
|
attributes: {},
|
||||||
|
childNodes: [],
|
||||||
|
id: 6,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
initialOffset: {
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
timestamp: now + 1000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: EventType.IncrementalSnapshot,
|
||||||
|
data: {
|
||||||
|
source: IncrementalSource.Mutation,
|
||||||
|
texts: [],
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
attributes: {
|
||||||
|
href: null,
|
||||||
|
rel: null,
|
||||||
|
_cssText:
|
||||||
|
'.OverlayDrawer-modal-187 { }.OverlayDrawer-paper-188 { width: 100%; }@media (min-width: 48em) {\n .OverlayDrawer-paper-188 { width: 38rem; }\n}@media (min-width: 48em) {\n}@media (min-width: 48em) {\n}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
removes: [],
|
||||||
|
adds: [],
|
||||||
|
},
|
||||||
|
timestamp: now + 2000,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export const polyfillWebGLGlobals = () => {
|
export const polyfillWebGLGlobals = () => {
|
||||||
// polyfill as jsdom does not have support for these classes
|
// polyfill as jsdom does not have support for these classes
|
||||||
// consider replacing with https://www.npmjs.com/package/canvas
|
// consider replacing with https://www.npmjs.com/package/canvas
|
||||||
|
|||||||
Reference in New Issue
Block a user