ref: isParentRemoved to cache subtree (#1543)
* ref: isParentRemoved to cache subtree * ref: cache at insertion too * ref: remove wrapper function --------- Co-authored-by: Justin Halsall <Juice10@users.noreply.github.com>
This commit is contained in:
5
.changeset/swift-pots-search.md
Normal file
5
.changeset/swift-pots-search.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"rrweb": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Optimize isParentRemoved check
|
||||||
@@ -169,6 +169,7 @@ export default class MutationBuffer {
|
|||||||
private addedSet = new Set<Node>();
|
private addedSet = new Set<Node>();
|
||||||
private movedSet = new Set<Node>();
|
private movedSet = new Set<Node>();
|
||||||
private droppedSet = new Set<Node>();
|
private droppedSet = new Set<Node>();
|
||||||
|
private removesSubTreeCache = new Set<Node>();
|
||||||
|
|
||||||
private mutationCb: observerParam['mutationCb'];
|
private mutationCb: observerParam['mutationCb'];
|
||||||
private blockClass: observerParam['blockClass'];
|
private blockClass: observerParam['blockClass'];
|
||||||
@@ -367,7 +368,7 @@ export default class MutationBuffer {
|
|||||||
|
|
||||||
for (const n of this.movedSet) {
|
for (const n of this.movedSet) {
|
||||||
if (
|
if (
|
||||||
isParentRemoved(this.removes, n, this.mirror) &&
|
isParentRemoved(this.removesSubTreeCache, n, this.mirror) &&
|
||||||
!this.movedSet.has(dom.parentNode(n)!)
|
!this.movedSet.has(dom.parentNode(n)!)
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
@@ -378,7 +379,7 @@ export default class MutationBuffer {
|
|||||||
for (const n of this.addedSet) {
|
for (const n of this.addedSet) {
|
||||||
if (
|
if (
|
||||||
!isAncestorInSet(this.droppedSet, n) &&
|
!isAncestorInSet(this.droppedSet, n) &&
|
||||||
!isParentRemoved(this.removes, n, this.mirror)
|
!isParentRemoved(this.removesSubTreeCache, n, this.mirror)
|
||||||
) {
|
) {
|
||||||
pushAdd(n);
|
pushAdd(n);
|
||||||
} else if (isAncestorInSet(this.movedSet, n)) {
|
} else if (isAncestorInSet(this.movedSet, n)) {
|
||||||
@@ -514,6 +515,7 @@ export default class MutationBuffer {
|
|||||||
this.addedSet = new Set<Node>();
|
this.addedSet = new Set<Node>();
|
||||||
this.movedSet = new Set<Node>();
|
this.movedSet = new Set<Node>();
|
||||||
this.droppedSet = new Set<Node>();
|
this.droppedSet = new Set<Node>();
|
||||||
|
this.removesSubTreeCache = new Set<Node>();
|
||||||
this.movedMap = {};
|
this.movedMap = {};
|
||||||
|
|
||||||
this.mutationCb(payload);
|
this.mutationCb(payload);
|
||||||
@@ -740,6 +742,7 @@ export default class MutationBuffer {
|
|||||||
? true
|
? true
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
processRemoves(n, this.removesSubTreeCache);
|
||||||
}
|
}
|
||||||
this.mapRemoves.push(n);
|
this.mapRemoves.push(n);
|
||||||
});
|
});
|
||||||
@@ -803,29 +806,33 @@ function deepDelete(addsSet: Set<Node>, n: Node) {
|
|||||||
dom.childNodes(n).forEach((childN) => deepDelete(addsSet, childN));
|
dom.childNodes(n).forEach((childN) => deepDelete(addsSet, childN));
|
||||||
}
|
}
|
||||||
|
|
||||||
function isParentRemoved(
|
function processRemoves(n: Node, cache: Set<Node>) {
|
||||||
removes: removedNodeMutation[],
|
const queue = [n];
|
||||||
n: Node,
|
|
||||||
mirror: Mirror,
|
while (queue.length) {
|
||||||
): boolean {
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
if (removes.length === 0) return false;
|
const next = queue.pop()!;
|
||||||
|
if (cache.has(next)) continue;
|
||||||
|
cache.add(next);
|
||||||
|
dom.childNodes(next).forEach((n) => queue.push(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isParentRemoved(removes: Set<Node>, n: Node, mirror: Mirror): boolean {
|
||||||
|
if (removes.size === 0) return false;
|
||||||
return _isParentRemoved(removes, n, mirror);
|
return _isParentRemoved(removes, n, mirror);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _isParentRemoved(
|
function _isParentRemoved(
|
||||||
removes: removedNodeMutation[],
|
removes: Set<Node>,
|
||||||
n: Node,
|
n: Node,
|
||||||
mirror: Mirror,
|
_mirror: Mirror,
|
||||||
): boolean {
|
): boolean {
|
||||||
let node: ParentNode | null = dom.parentNode(n);
|
const node: ParentNode | null = dom.parentNode(n);
|
||||||
while (node) {
|
if (!node) return false;
|
||||||
const parentId = mirror.getId(node);
|
return removes.has(node);
|
||||||
if (removes.some((r) => r.id === parentId)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
node = dom.parentNode(node);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isAncestorInSet(set: Set<Node>, n: Node): boolean {
|
function isAncestorInSet(set: Set<Node>, n: Node): boolean {
|
||||||
|
|||||||
Reference in New Issue
Block a user