Fix mutation edge case when blocked class gets unblocked #867
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Context:
RRweb uses MutationObserver feature of browser to fetch 100s of mutation records.
Processes all these mutation records to generate
adds,removes,attributesdata of mutation event in a minimal fashion.One of those optimizations is to ensure that rrweb doesn't generate
addsdata for a node if its parent is anyways beingremovedin another sibling mutation record.Detailed Description of Edge case:
However, there is an edge case bug in this optimization exercise when we use the
blockClassfeature.If an element is blocked, we don't serialize and record it.
Let's take a following scenario where we have some elements which are blocked from recording and we see a bunch of mutation records with following actions:
Since an element is removed (Action-2), we add it's nodeId to the
removedset.However since this node was not serialized (as it was part of a block class), we shouldn't track it's nodeId in the
removedset. RRweb is smart and does check if a node was part ofblockClassbefore adding it to theremovedset. But in this case the element which was blocked has it's class name changed to an unblocked class (Action-1). So the check that the node was part ofblockClassfails and we track an unserialized node in theremovedset. For unserialized nodes, we track the id by value of-1.Now coming to Action-3 where lots of element nodes are added to an unrelated element, some of them could have their parentId defaulted to
-1while being added to the DOM (since the order of serialization is not always from parent to child). So RRweb's optimization logic thinks that there is no need to add this element to the mutation event as it's parent-1is part of theremovedset.How to repro?
Run rrweb replayer on this html document and click on both the
Mutatebuttons.In the original session, each
Mutatebutton will create two new buttons.In the replay, each
Mutatebutton will create only one new button.How did I test?
Ran the repl command with my fix and verified that both the new buttons appear per each click on
Mutatebutton.