Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into fixAdaptCssWithSplit
Browse files Browse the repository at this point in the history
  • Loading branch information
eoghanmurray committed Jan 29, 2025
2 parents 73245ca + 83c66c4 commit 22d2424
Show file tree
Hide file tree
Showing 21 changed files with 646 additions and 398 deletions.
2 changes: 2 additions & 0 deletions .changeset/eslint-camelcase-devonly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
5 changes: 5 additions & 0 deletions .changeset/four-panthers-fly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rrweb/web-extension": patch
---

web-extension: improve recording stability across tabs and enable session import
5 changes: 5 additions & 0 deletions .changeset/red-peaches-explode.md
Original file line number Diff line number Diff line change
@@ -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.
3 changes: 3 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,8 @@ module.exports = {
rules: {
'tsdoc/syntax': 'warn',
'@typescript-eslint/prefer-as-const': 'warn',
'camelcase': ['error', {
allow: ['rr_.*', 'legacy_.*', 'UNSAFE_.*', '__rrweb_.*'],
}],
},
};
2 changes: 1 addition & 1 deletion .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: lts/*

- name: Install Dependencies
run: yarn install --frozen-lockfile

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
"dev": "yarn turbo run dev --concurrency=18",
"repl": "cd packages/rrweb && npm run repl",
"live-stream": "cd packages/rrweb && yarn live-stream",
"lint": "yarn run concurrently --success=all -r -m=1 'yarn run markdownlint docs' 'yarn eslint packages/*/src --ext .ts,.tsx,.js,.jsx,.svelte'",
"lint:report": "yarn eslint --output-file eslint_report.json --format json packages/*/src --ext .ts,.tsx,.js,.jsx",
"lint": "yarn run concurrently --success=all -r -m=1 'yarn run markdownlint docs' 'ESLINT_USE_FLAT_CONFIG=false yarn eslint packages/*/src --ext .ts,.tsx,.js,.jsx,.svelte'",
"lint:report": "ESLINT_USE_FLAT_CONFIG=false yarn eslint --output-file eslint_report.json --format json packages/*/src --ext .ts,.tsx,.js,.jsx",
"release": "yarn build:all && changeset publish"
},
"resolutions": {
Expand Down
36 changes: 23 additions & 13 deletions packages/rrweb/src/replay/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -760,30 +760,30 @@ export class Replayer {
this.service.send({ type: 'CAST_EVENT', payload: { event } });

// events are kept sorted by timestamp, check if this is the last event
const last_index = this.service.state.context.events.length - 1;
const lastIndex = this.service.state.context.events.length - 1;
if (
!this.config.liveMode &&
event === this.service.state.context.events[last_index]
event === this.service.state.context.events[lastIndex]
) {
const finish = () => {
if (last_index < this.service.state.context.events.length - 1) {
if (lastIndex < this.service.state.context.events.length - 1) {
// more events have been added since the setTimeout
return;
}
this.backToNormal();
this.service.send('END');
this.emitter.emit(ReplayerEvents.Finish);
};
let finish_buffer = 50; // allow for checking whether new events aren't just about to be loaded in
let finishBuffer = 50; // allow for checking whether new events aren't just about to be loaded in
if (
event.type === EventType.IncrementalSnapshot &&
event.data.source === IncrementalSource.MouseMove &&
event.data.positions.length
) {
// extend finish event if the last event is a mouse move so that the timer isn't stopped by the service before checking the last event
finish_buffer += Math.max(0, -event.data.positions[0].timeOffset);
finishBuffer += Math.max(0, -event.data.positions[0].timeOffset);
}
setTimeout(finish, finish_buffer);
setTimeout(finish, finishBuffer);
}

this.emitter.emit(ReplayerEvents.EventCast, event);
Expand Down Expand Up @@ -1792,17 +1792,27 @@ export class Replayer {
const newSn = mirror.getMeta(
target as Node & RRNode,
) 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(
newSn.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 parentNode = target.parentNode;
if (newNode && parentNode) {
Expand Down
67 changes: 67 additions & 0 deletions packages/rrweb/test/__snapshots__/replayer.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -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`] = `
"file-frame-1
<html>
Expand Down
18 changes: 18 additions & 0 deletions packages/rrweb/test/replayer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
launchPuppeteer,
sampleEvents as events,
sampleStyleSheetRemoveEvents as stylesheetRemoveEvents,
sampleRemoteStyleSheetEvents as remoteStyleSheetEvents,
waitForRAF,
} from './utils';
import styleSheetRuleEvents from './events/style-sheet-rule-events';
Expand Down Expand Up @@ -209,6 +210,23 @@ describe('replayer', function () {
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 () => {
await page.evaluate(`events = ${JSON.stringify(selectionEvents)}`);

Expand Down
92 changes: 92 additions & 0 deletions packages/rrweb/test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => {
// polyfill as jsdom does not have support for these classes
// consider replacing with https://www.npmjs.com/package/canvas
Expand Down
Loading

0 comments on commit 22d2424

Please sign in to comment.