Skip to content

[Bug]: CSSRules inserted w/ CSSStyleSheet.insertRule() are lost on skipping w/ virtualDom #1344

@jaj1014

Description

@jaj1014

Preflight Checklist

  • I have searched the issue tracker for a bug report that matches the one I want to file, without success.

What package is this bug report for?

rrweb

Version

2.0.0-alpha.11

Expected Behavior

When using virtualDom, CSSRules inserted (CSSStyleSheet.insertRule()) on a style element should persist when skipping.

Actual Behavior

When using virtualDom, CSSRules (CSSStyleSheet.insertRule()) inserted on a style element are lost when skipping.

Steps to Reproduce

What I found to be the crux of the issue is actually in rrdom when diff()'ing current dom against the virtual dom. If a style element which had IncrementalSource.StyleSheetRule events applied gets moved due to the diff, it loses those inserted style rules. This appears to be a side effect of using Node.insertBefore() on style elements.

jsfiddle demonstrating what insertBefore does: https://jsfiddle.net/8ps3zmf7/

While this is where I noticed things breaking down, there is more contributing to the issue. I've included more detail on my overall learnings in 'Additional Information' below.

Testcase Gist URL

No response

Additional Information

I did a fair amount of debugging to try to figure out what was happening to cause the issue and these are the things I found:

  1. IncrementalSnapshot type events with a source of StyleSheetRule that add rules use CSSStyleSheet.insertRule(rule, index) to add them to the style element.
  2. diff in rrdom uses Node.insertBefore() to 'move' elements to their updated location based on the diff algo. When used on a style element (or parent elements which contain style elements as children), only rules derived from innerText/innerHTML persist. Any inserted styles (CSSStyleSheet.insertRule()) do not persist with the style element to it's new location.
    1. This can be repro'd in the console pretty easily. adding a style element in the dom, inserting styles on it using CSSStyleSheet.insertRule(rule, index), then moving the element using Node.insertBefore(). When you inspect the element, all of the styles that were inserted will be missing. Fiddle example: https://jsfiddle.net/8ps3zmf7/
  3. As I understand the code, buildFromDom() copies an existing dom state into a 'virtual dom' representation. buildFromDom() calls through to buildFromNode(). When it's called with a Style element node, it only copies attributes of the serializedNode it gets from the dom mirror which does not contains style rules that were inserted.
  4. When IncrementalSnapshot type events with a source of StyleSheetRule are applied, these rules are not tracked - only applied to the element via CSSStyleSheet.insertRule().

Putting these different pieces together, it creates a situation where styles have been 'lost' and the recording is no longer accurate. The crux of the scenario that leads to the styles being lost is the style element who's CSSStyleSheet gets styles inserted gets moved around in the dom due to the diff. If it does not get moved, then it still has all it's styles and this issue never crops up.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions