-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
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:
- IncrementalSnapshot type events with a source of StyleSheetRule that add rules use
CSSStyleSheet.insertRule(rule, index)to add them to the style element. diffin rrdom usesNode.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.- 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 usingNode.insertBefore(). When you inspect the element, all of the styles that were inserted will be missing. Fiddle example: https://jsfiddle.net/8ps3zmf7/
- This can be repro'd in the console pretty easily. adding a style element in the dom, inserting styles on it using
- As I understand the code,
buildFromDom()copies an existing dom state into a 'virtual dom' representation.buildFromDom()calls through tobuildFromNode(). 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. - 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.