Skip to content

Commit

Permalink
ref(perf): less recursion and a few minor optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasBa committed Aug 10, 2023
1 parent 8750f7f commit 5b05e6b
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 43 deletions.
13 changes: 9 additions & 4 deletions packages/rrdom/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,11 +367,16 @@ export class Mirror implements IMirror<RRNode> {
// removes the node from idNodeMap
// doesn't remove the node from nodeMetaMap
removeNodeFromMap(n: RRNode) {
const id = this.getId(n);
this.idNodeMap.delete(id);
const queue = [n];

if (n.childNodes) {
n.childNodes.forEach((childNode) => this.removeNodeFromMap(childNode));
while (queue.length > 0) {
const n = queue.pop()!;
const id = this.getId(n);
this.idNodeMap.delete(id);

if (n.childNodes) {
n.childNodes.forEach((childNode) => queue.push(childNode));
}
}
}
has(id: number): boolean {
Expand Down
30 changes: 20 additions & 10 deletions packages/rrweb-snapshot/src/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,10 @@ export function _isBlockedElement(

try {
if (typeof blockClass === 'string') {
if(!element.classList.length) return false;
if(element.classList.length === 1 && element.classList[0] === blockClass) {
return true;
}
if (element.classList.contains(blockClass)) {
return true;
}
Expand Down Expand Up @@ -339,9 +343,12 @@ export function needMaskingText(
? (node as HTMLElement)
: node.parentElement;

if (el === null) return false;
if (!el) return false;

try {
if (typeof maskTextClass === 'string') {
if(!el.classList.length) return false;
if(el.classList.length === 1 && el.classList[0] === maskTextClass) return true;
if (el.classList.contains(maskTextClass)) return true;
if (el.matches(`.${maskTextClass} *`)) return true;
} else {
Expand Down Expand Up @@ -657,14 +664,14 @@ function serializeElementNode(
const len = n.attributes.length;
for (let i = 0; i < len; i++) {
const attr = n.attributes[i];
if (!ignoreAttribute(tagName, attr.name, attr.value)) {
attributes[attr.name] = transformAttribute(
doc,
tagName,
toLowerCase(attr.name),
attr.value,
);
}
if (ignoreAttribute(tagName, attr.name, attr.value)) continue;

attributes[attr.name] = transformAttribute(
doc,
tagName,
toLowerCase(attr.name),
attr.value,
);
}
// remote css
if (tagName === 'link' && inlineStylesheet) {
Expand Down Expand Up @@ -1054,7 +1061,10 @@ export function serializeNodeWithId(
id = genId();
}

const serializedNode = Object.assign(_serializedNode, { id });
const serializedNode = {
..._serializedNode,
id,
};
// add IGNORED_NODE to mirror to track nextSiblings
mirror.add(n, serializedNode);

Expand Down
24 changes: 19 additions & 5 deletions packages/rrweb-snapshot/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@ export class Mirror implements IMirror<Node> {
getId(n: Node | undefined | null): number {
if (!n) return -1;

const id = this.getMeta(n)?.id;
if(!this.nodeMetaMap.has(n)) {
return -1;
}

const id = this.getMetaId(n);

// if n is not a serialized Node, use -1 as its id.
return id ?? -1;
Expand All @@ -119,16 +123,26 @@ export class Mirror implements IMirror<Node> {
return this.nodeMetaMap.get(n) || null;
}

getMetaId(n: Node): number | null {
return this.getMeta(n)?.id ?? null;
}

// removes the node from idNodeMap
// doesn't remove the node from nodeMetaMap
removeNodeFromMap(n: Node) {
const id = this.getId(n);
this.idNodeMap.delete(id);

if (n.childNodes) {
n.childNodes.forEach((childNode) =>
this.removeNodeFromMap(childNode as unknown as Node),
);
const removeQueue = [n];

while(removeQueue.length){
const node = removeQueue.pop()!;
this.idNodeMap.delete(this.getId(node));

if (node.childNodes) {
node.childNodes.forEach(c => removeQueue.push(c))
}

}
}
has(id: number): boolean {
Expand Down
56 changes: 33 additions & 23 deletions packages/rrweb/src/record/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -769,33 +769,39 @@ function isParentRemoved(
mirror: Mirror,
): boolean {
if (removes.length === 0) return false;
return _isParentRemoved(removes, n, mirror, undefined);
return _isParentRemoved(removes, n, mirror, new Set());
}

function _isParentRemoved(
removes: removedNodeMutation[],
n: Node,
mirror: Mirror,
removeSet: Set<number> | undefined,
removeSet: Set<number>,
): boolean {
const { parentNode } = n;
if (!parentNode) {
return false;
}
const queue = [n];
while (queue.length) {
const { parentNode } = queue.pop()!;
if (!parentNode) {
return false;
}

const removedLookupSet = removeSet || new Set();
const parentId = mirror.getId(parentNode);
for (let i = 0; i < removes.length; i++) {
const removedNode = removes[i];
if (removedNode.id === parentId) {
const parentId = mirror.getId(parentNode);
if (removeSet.has(parentId)) {
return true;
}
removedLookupSet.add(removedNode.id);
}
if (removedLookupSet.has(parentId)) {
return true;

for (let i = 0; i < removes.length; i++) {
const removedNode = removes[i];
if (removedNode.id === parentId) {
return true;
}
removeSet.add(removedNode.id);
}

queue.push(parentNode);
}
return _isParentRemoved(removes, parentNode, mirror, removedLookupSet);

return false;
}

function isAncestorInSet(set: Set<Node>, n: Node): boolean {
Expand All @@ -804,12 +810,16 @@ function isAncestorInSet(set: Set<Node>, n: Node): boolean {
}

function _isAncestorInSet(set: Set<Node>, n: Node): boolean {
const { parentNode } = n;
if (!parentNode) {
return false;
}
if (set.has(parentNode)) {
return true;
const queue = [n];
while (queue.length) {
const { parentNode } = queue.pop()!;
if (!parentNode) {
return false;
}
if (set.has(parentNode)) {
return true;
}
queue.push(parentNode);
}
return _isAncestorInSet(set, parentNode);
return false;
}
10 changes: 9 additions & 1 deletion packages/rrweb/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,13 +238,21 @@ export function isBlocked(
node.nodeType === node.ELEMENT_NODE
? (node as HTMLElement)
: node.parentElement;

if (!el) return false;

try {
if (typeof blockClass === 'string') {
if(!checkAncestors){
if(el.classList.length === 1) return el.classList[0] === blockClass;
return el.classList.length > 0 && el.classList.contains(blockClass);
}

if(el.classList.length === 1) return el.classList[0] === blockClass || el.matches(`.${blockClass} *`);
return (
el.classList.length > 0 &&
el.classList.contains(blockClass) ||
(checkAncestors && el.matches(`.${blockClass} *`))
el.matches(`.${blockClass} *`)
);
}
return classMatchesRegex(el, blockClass, checkAncestors);
Expand Down

0 comments on commit 5b05e6b

Please sign in to comment.