… crashes
Both issues report an uncaught CssSyntaxError taking down the replayer:
rrweb-io#1734 from empty longhand declarations the browser's CSSOM produces for
shorthand properties (e.g. `border-top-style: ;`), rrweb-io#1692 from a
/* rr_split */ marker landing inside a quoted attribute selector.
Verified against main: both are already handled by the combination of
rrweb-io#1600 (splits are rejoined before being handed to postcss, so a split
never has to parse on its own) and rrweb-io#1580 (postcss failures are caught
and logged instead of thrown). Reproduced the exact "Unclosed string"
error from rrweb-io#1734's stack trace directly against adaptCssForReplay and
confirmed it degrades to a console.warn + original text instead of
propagating.
Adding these as permanent regressions, using the reporters' own
snippets where possible, so the fix in rrweb-io#1600/rrweb-io#1580 doesn't silently
regress and so rrweb-io#1734/rrweb-io#1692 can be closed with a paper trail.
Summary
Both #1734 and #1692 report the replayer crashing with an uncaught
CssSyntaxErrorfrom postcss:var()(e.g.border-top-style: ;), causing"Unclosed string"./* rr_split */marker landing inside a quoted attribute selector ([class~="..."]), so one half of the split is invalid CSS on its own, causing"Unclosed bracket".I went looking for the root cause and, checking against current
main, both are already fixed by two earlier PRs:applyCssSplitsnow rejoins all splits (cssTextSplits.join('')) before handing the text toadaptCssForReplay/postcss, so a split fragment is never parsed on its own. I reproduced [Bug]: CSS splitting causes corrupted css that causes a processing error failing to replay #1692's exact failure shape (a split landing mid-attribute-selector) and confirmed it rejoins correctly without throwing.adaptCssForReplaywraps the postcss call in try/catch and falls back to the original, unmodified CSS text on failure instead of throwing. I reproduced the exact"Unclosed string"error from [Bug]: Empty css rules break replay with "CssSyntaxError CssSyntaxError: Unclosed string" error #1734's stack trace directly againstadaptCssForReplayand confirmed it now degrades to aconsole.warn+ original text instead of propagating and crashing the replayer.Since I couldn't get the reporters' full page CSS (their repros are truncated CSSOM snippets from a much larger stylesheet), I can't reproduce their exact crash byte-for-byte, but I've reproduced the identical failure mode from each report (same postcss error type, same code path) and confirmed both are handled gracefully on
main.This PR doesn't change any behavior — it adds these cases as permanent regression tests (using the reporters' own snippets where possible) so the #1600/#1580 fixes can't silently regress, and so #1734 and #1692 have a paper trail for closing them.
Test plan
css.test.ts:applyCssSplits css rejoiner > rejoins a split that lands inside a quoted attribute selector without corrupting it (#1692)adaptCssForReplay with malformed css (#1734) > does not throw on empty longhand declarations produced by the browser CSSOMadaptCssForReplay with malformed css (#1734) > falls back to the original text instead of throwing on genuinely unparseable css— this one reproduces the literal"Unclosed string"postcss error from [Bug]: Empty css rules break replay with "CssSyntaxError CssSyntaxError: Unclosed string" error #1734's stack tracerrweb-snapshotsuite passes: 93/93 (1 pre-existing skip).tsc -noEmitclean.Addresses #1734, #1692