From 410756e5fda39bf88b5bca791ef998a1752690f2 Mon Sep 17 00:00:00 2001 From: eoghan Date: Tue, 9 Jun 2020 15:13:31 +0000 Subject: [PATCH] Avoid a build up of duplicate `adds` by delaying pushing to adds until emission time --- src/record/mutation.ts | 128 +++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 63 deletions(-) diff --git a/src/record/mutation.ts b/src/record/mutation.ts index d4487a466a..31e5818d40 100644 --- a/src/record/mutation.ts +++ b/src/record/mutation.ts @@ -24,7 +24,6 @@ export default class MutationBuffer { private texts: textCursor[] = []; private attributes: attributeCursor[] = []; private removes: removedNodeMutation[] = []; - private adds: addedNodeMutation[] = []; private movedMap: Record = {}; @@ -69,66 +68,6 @@ export default class MutationBuffer { public processMutations = (mutations: mutationRecord[]) => { mutations.forEach(this.processMutation); - /** - * Sometimes child node may be pushed before its newly added - * parent, so we init a queue to store these nodes. - */ - const addQueue: Node[] = []; - const pushAdd = (n: Node) => { - const parentId = mirror.getId((n.parentNode as Node) as INode); - const nextId = - n.nextSibling && mirror.getId((n.nextSibling as unknown) as INode); - if (parentId === -1 || nextId === -1) { - return addQueue.push(n); - } - this.adds.push({ - parentId, - nextId, - node: serializeNodeWithId( - n, - document, - mirror.map, - this.blockClass, - true, - this.inlineStylesheet, - this.maskAllInputs, - )!, - }); - }; - - for (const n of this.movedSet) { - pushAdd(n); - } - - for (const n of this.addedSet) { - if ( - !isAncestorInSet(this.droppedSet, n) && - !isParentRemoved(this.removes, n) - ) { - pushAdd(n); - } else if (isAncestorInSet(this.movedSet, n)) { - pushAdd(n); - } else { - this.droppedSet.add(n); - } - } - - while (addQueue.length) { - if ( - addQueue.every( - (n) => mirror.getId((n.parentNode as Node) as INode) === -1, - ) - ) { - /** - * If all nodes in queue could not find a serialized parent, - * it may be a bug or corner case. We need to escape the - * dead while loop at once. - */ - break; - } - pushAdd(addQueue.shift()!); - } - if (!this.paused) { this.emit(); } @@ -237,6 +176,70 @@ export default class MutationBuffer { }; public emit = () => { + + const adds: addedNodeMutation[] = []; + + /** + * Sometimes child node may be pushed before its newly added + * parent, so we init a queue to store these nodes. + */ + const addQueue: Node[] = []; + const pushAdd = (n: Node) => { + const parentId = mirror.getId((n.parentNode as Node) as INode); + const nextId = + n.nextSibling && mirror.getId((n.nextSibling as unknown) as INode); + if (parentId === -1 || nextId === -1) { + return addQueue.push(n); + } + adds.push({ + parentId, + nextId, + node: serializeNodeWithId( + n, + document, + mirror.map, + this.blockClass, + true, + this.inlineStylesheet, + this.maskAllInputs, + )!, + }); + }; + + for (const n of this.movedSet) { + pushAdd(n); + } + + for (const n of this.addedSet) { + if ( + !isAncestorInSet(this.droppedSet, n) && + !isParentRemoved(this.removes, n) + ) { + pushAdd(n); + } else if (isAncestorInSet(this.movedSet, n)) { + pushAdd(n); + } else { + this.droppedSet.add(n); + } + } + + while (addQueue.length) { + if ( + addQueue.every( + (n) => mirror.getId((n.parentNode as Node) as INode) === -1, + ) + ) { + /** + * If all nodes in queue could not find a serialized parent, + * it may be a bug or corner case. We need to escape the + * dead while loop at once. + */ + break; + } + pushAdd(addQueue.shift()!); + } + + const payload = { texts: this.texts .map((text) => ({ @@ -253,7 +256,7 @@ export default class MutationBuffer { // attribute mutation's id was not in the mirror map means the target node has been removed .filter((attribute) => mirror.has(attribute.id)), removes: this.removes, - adds: this.adds, + adds: adds, }; // payload may be empty if the mutations happened in some blocked elements if ( @@ -270,7 +273,6 @@ export default class MutationBuffer { this.texts = []; this.attributes = []; this.removes = []; - this.adds = []; this.addedSet = new Set(); this.movedSet = new Set(); this.droppedSet = new Set();