diff --git a/.changeset/late-keys-whisper.md b/.changeset/late-keys-whisper.md new file mode 100644 index 0000000000..daf97ae1dc --- /dev/null +++ b/.changeset/late-keys-whisper.md @@ -0,0 +1,5 @@ +--- +'rrweb': patch +--- + +Optimize isParentRemoved for large remove lists diff --git a/packages/rrweb/src/record/mutation.ts b/packages/rrweb/src/record/mutation.ts index f4267af340..5c126555e8 100644 --- a/packages/rrweb/src/record/mutation.ts +++ b/packages/rrweb/src/record/mutation.ts @@ -144,6 +144,7 @@ export default class MutationBuffer { private attributes: attributeCursor[] = []; private attributeMap = new WeakMap(); private removes: removedNodeMutation[] = []; + private removesMap = new Map(); private mapRemoves: Node[] = []; private movedMap: Record = {}; @@ -353,7 +354,7 @@ export default class MutationBuffer { for (const n of this.movedSet) { if ( - isParentRemoved(this.removes, n, this.mirror) && + isParentRemoved(this.removesMap, n, this.mirror) && !this.movedSet.has(n.parentNode!) ) { continue; @@ -364,7 +365,7 @@ export default class MutationBuffer { for (const n of this.addedSet) { if ( !isAncestorInSet(this.droppedSet, n) && - !isParentRemoved(this.removes, n, this.mirror) + !isParentRemoved(this.removesMap, n, this.mirror) ) { pushAdd(n); } else if (isAncestorInSet(this.movedSet, n)) { @@ -503,6 +504,7 @@ export default class MutationBuffer { this.attributes = []; this.attributeMap = new WeakMap(); this.removes = []; + this.removesMap = new Map(); this.addedSet = new Set(); this.movedSet = new Set(); this.droppedSet = new Set(); @@ -726,6 +728,7 @@ export default class MutationBuffer { ? true : undefined, }); + this.removesMap.set(nodeId, this.removes.length - 1); } this.mapRemoves.push(n); }); @@ -789,16 +792,16 @@ function deepDelete(addsSet: Set, n: Node) { } function isParentRemoved( - removes: removedNodeMutation[], + removesMap: Map, n: Node, mirror: Mirror, ): boolean { - if (removes.length === 0) return false; - return _isParentRemoved(removes, n, mirror); + if (removesMap.size === 0) return false; + return _isParentRemoved(removesMap, n, mirror); } function _isParentRemoved( - removes: removedNodeMutation[], + removesMap: Map, n: Node, mirror: Mirror, ): boolean { @@ -807,10 +810,10 @@ function _isParentRemoved( return false; } const parentId = mirror.getId(parentNode); - if (removes.some((r) => r.id === parentId)) { + if (removesMap.has(parentId)) { return true; } - return _isParentRemoved(removes, parentNode, mirror); + return _isParentRemoved(removesMap, parentNode, mirror); } function isAncestorInSet(set: Set, n: Node): boolean {