Skip to content

Commit 804a131

Browse files
authored
fix: use RAF timing in rrweb snapshots (#1103)
1 parent ec5e174 commit 804a131

File tree

1 file changed

+72
-38
lines changed

1 file changed

+72
-38
lines changed

src/browser/history/rrweb.ts

Lines changed: 72 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,57 +14,91 @@ export async function installRrwebAndCollectEvents(
1414
): Promise<eventWithTime[]> {
1515
/* eslint-disable @typescript-eslint/ban-ts-comment */
1616
return runWithoutHistory<Promise<eventWithTime[]>>({ callstack }, () =>
17-
session.execute(rrwebRecordFnCode => {
18-
try {
17+
session.execute(
18+
(rrwebRecordFnCode, serverTime) => {
1919
// @ts-expect-error
20-
if (!window.rrweb) {
21-
window.eval(rrwebRecordFnCode);
20+
if (!window.__testplaneTiming) {
2221
// @ts-expect-error
23-
window.lastProcessedRrwebEvent = -1;
24-
// @ts-expect-error
25-
window.rrwebEvents = [];
22+
window.__testplaneTiming = {
23+
serverTime: serverTime,
24+
baseRaf: null,
25+
initialized: true,
26+
};
2627

27-
// @ts-expect-error
28-
window.rrweb.record({
28+
requestAnimationFrame(timestamp => {
2929
// @ts-expect-error
30-
emit(event) {
31-
// @ts-expect-error
32-
window.rrwebEvents.push(event);
33-
},
30+
window.__testplaneTiming.baseRaf = timestamp;
3431
});
32+
}
3533

34+
try {
3635
// @ts-expect-error
37-
window.rrweb.record.addCustomEvent("color-scheme-change", {
38-
colorScheme:
39-
window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches
40-
? "dark"
41-
: "light",
42-
});
36+
if (!window.rrweb) {
37+
window.eval(rrwebRecordFnCode);
38+
// @ts-expect-error
39+
window.lastProcessedRrwebEvent = -1;
40+
// @ts-expect-error
41+
window.rrwebEvents = [];
4342

44-
window.matchMedia &&
45-
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", event => {
43+
// @ts-expect-error
44+
window.rrweb.record({
4645
// @ts-expect-error
47-
window.rrweb.record.addCustomEvent("color-scheme-change", {
48-
colorScheme: event.matches ? "dark" : "light",
49-
});
46+
emit(event) {
47+
// We use this complex RAF-based timing, because users might have Date.now() stubbed
48+
requestAnimationFrame(currentRaf => {
49+
// @ts-expect-error
50+
const baseRaf = window.__testplaneTiming.baseRaf;
51+
// @ts-expect-error
52+
const serverTime = window.__testplaneTiming.serverTime;
53+
54+
if (baseRaf !== null) {
55+
event.timestamp = Math.floor(serverTime + (currentRaf - baseRaf));
56+
} else {
57+
// RAF not ready, use server time
58+
event.timestamp = serverTime;
59+
}
60+
61+
// @ts-expect-error
62+
window.rrwebEvents.push(event);
63+
});
64+
},
5065
});
66+
67+
// @ts-expect-error
68+
window.rrweb.record.addCustomEvent("color-scheme-change", {
69+
colorScheme:
70+
window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches
71+
? "dark"
72+
: "light",
73+
});
74+
75+
window.matchMedia &&
76+
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", event => {
77+
// @ts-expect-error
78+
window.rrweb.record.addCustomEvent("color-scheme-change", {
79+
colorScheme: event.matches ? "dark" : "light",
80+
});
81+
});
82+
}
83+
} catch (e) {
84+
/**/
5185
}
52-
} catch (e) {
53-
/**/
54-
}
5586

56-
let result;
57-
try {
58-
// @ts-expect-error
59-
result = window.rrwebEvents.slice(window.lastProcessedRrwebEvent + 1);
60-
// @ts-expect-error
61-
window.lastProcessedRrwebEvent = window.rrwebEvents.length - 1;
62-
} catch {
63-
result = [];
64-
}
87+
let result;
88+
try {
89+
// @ts-expect-error
90+
result = window.rrwebEvents.slice(window.lastProcessedRrwebEvent + 1);
91+
// @ts-expect-error
92+
window.lastProcessedRrwebEvent = window.rrwebEvents.length - 1;
93+
} catch {
94+
result = [];
95+
}
6596

66-
return result;
67-
}, rrwebCode),
97+
return result;
98+
},
99+
rrwebCode,
100+
Date.now(),
101+
),
68102
);
69103
/* eslint-enable @typescript-eslint/ban-ts-comment */
70104
}

0 commit comments

Comments
 (0)