Skip to content

Commit 73a808a

Browse files
billyvgmydea
andauthored
fix(replay): Fix potential broken CSS in styled-components (#9234)
Fixes an issue where the Replay integration can potentially break applications that use `styled-components`. `styled-components` [relies on an exception being throw](https://github.com/styled-components/styled-components/blob/b7b374bb1ceff1699f7035b15881bc807110199a/packages/styled-components/src/sheet/Tag.ts#L32-L40) for CSS rules that are not supported by the browser engine. However, our SDK suppressed any exceptions thrown from within rrweb, so `styled-components` assumes that an unsupported rule was inserted successfully and increases a rule index, which causes following inserted rules to fail due to an out-of-bounds error. This was a regression from v1 as [we were always re-throwing the exception](https://github.com/getsentry/rrweb/blob/sentry-v1/packages/rrweb/src/sentry/callbackWrapper.ts#L17) Fixes #9170 --------- Co-authored-by: Francesco Novy <[email protected]>
1 parent a8c8564 commit 73a808a

File tree

3 files changed

+47
-6
lines changed

3 files changed

+47
-6
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<body>
7+
</body>
8+
</html>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { expect } from '@playwright/test';
2+
3+
import { sentryTest } from '../../../utils/fixtures';
4+
import { shouldSkipReplayTest } from '../../../utils/replayHelpers';
5+
6+
sentryTest('exceptions within rrweb and re-thrown and annotated', async ({ getLocalTestPath, page, browserName }) => {
7+
if (shouldSkipReplayTest() || browserName !== 'chromium') {
8+
sentryTest.skip();
9+
}
10+
11+
const url = await getLocalTestPath({ testDir: __dirname });
12+
13+
await page.goto(url);
14+
15+
expect(
16+
await page.evaluate(() => {
17+
try {
18+
const s = new CSSStyleSheet();
19+
s.insertRule('body::-ms-expand{display: none}');
20+
s.insertRule('body {background-color: #fff;}');
21+
return s.cssRules.length;
22+
} catch {
23+
return false;
24+
}
25+
}),
26+
).toBe(false);
27+
28+
expect(
29+
await page.evaluate(() => {
30+
const s = new CSSStyleSheet();
31+
s.insertRule('body {background-color: #fff;}');
32+
return s.cssRules.length;
33+
}),
34+
).toBe(1);
35+
});

packages/replay/src/integration.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,15 +145,13 @@ export class Replay implements Integration {
145145
// collect fonts, but be aware that `sentry.io` needs to be an allowed
146146
// origin for playback
147147
collectFonts: true,
148-
errorHandler: (err: Error) => {
148+
errorHandler: (err: Error & { __rrweb__?: boolean }) => {
149149
try {
150-
// @ts-expect-error Set this so that replay SDK can ignore errors originating from rrweb
151150
err.__rrweb__ = true;
152-
} catch {
153-
// avoid any potential hazards here
151+
} catch (error) {
152+
// ignore errors here
153+
// this can happen if the error is frozen or does not allow mutation for other reasons
154154
}
155-
// return true to suppress throwing the error inside of rrweb
156-
return true;
157155
},
158156
};
159157

0 commit comments

Comments
 (0)