From 4709c720cdf8d9562eadd75d827d68fecabadd57 Mon Sep 17 00:00:00 2001 From: Yanzhen Yu Date: Mon, 5 Nov 2018 13:20:42 +0800 Subject: [PATCH] also resolve missing previous node --- src/replay/index.ts | 44 +++++++++++++++----------- src/types.ts | 11 ++++--- test/__snapshots__/integration.ts.snap | 6 +++- 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/replay/index.ts b/src/replay/index.ts index 134f55af..d5ca8024 100644 --- a/src/replay/index.ts +++ b/src/replay/index.ts @@ -11,7 +11,9 @@ import { playerConfig, playerMetaData, viewportResizeDimention, - missingNextNodeMap, + missingNodeMap, + addedNodeMutation, + missingNode, } from '../types'; import { mirror } from '../utils'; @@ -218,7 +220,7 @@ export class Replayer { } }); - const missingNextNodeMap: missingNextNodeMap = {}; + const missingNodeMap: missingNodeMap = {}; d.adds.forEach(mutation => { const target = buildNodeWithSN( mutation.node, @@ -236,8 +238,8 @@ export class Replayer { next = mirror.getNode(mutation.nextId) as Node; } - if (mutation.nextId === -1) { - missingNextNodeMap[mutation.node.id] = { + if (mutation.previousId === -1 || mutation.nextId === -1) { + missingNodeMap[mutation.node.id] = { node: target, mutation, }; @@ -252,16 +254,13 @@ export class Replayer { parent.appendChild(target); } - if (mutation.previousId) { - this.resolveMissingNode( - missingNextNodeMap, - parent, - target, - mutation.previousId, - ); + if (mutation.previousId || mutation.nextId) { + this.resolveMissingNode(missingNodeMap, parent, target, mutation); } }); - // TODO: assert missingNextNodeMap has no key after resolve + if (Object.keys(missingNodeMap).length) { + console.warn('Found unresolved missing node map', missingNodeMap); + } d.texts.forEach(mutation => { const target = (mirror.getNode(mutation.id) as Node) as Text; @@ -343,17 +342,24 @@ export class Replayer { } private resolveMissingNode( - map: missingNextNodeMap, + map: missingNodeMap, parent: Node, target: Node, - previousId: number, + targetMutation: addedNodeMutation, ) { - if (map[previousId]) { - const { node, mutation } = map[previousId]; - parent.insertBefore(node, target); + const { previousId, nextId } = targetMutation; + const previousInMap = previousId && map[previousId]; + const nextInMap = nextId && map[nextId]; + if (previousInMap || nextInMap) { + const { node, mutation } = (previousInMap || nextInMap) as missingNode; + if (previousInMap) { + parent.insertBefore(node, target); + } else { + parent.insertBefore(node, target.nextSibling); + } delete map[mutation.node.id]; - if (mutation.previousId) { - this.resolveMissingNode(map, parent, node as Node, mutation.previousId); + if (mutation.previousId || mutation.nextId) { + this.resolveMissingNode(map, parent, node as Node, mutation); } } } diff --git a/src/types.ts b/src/types.ts index df29c00e..906c81d4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -232,9 +232,10 @@ export type playerMetaData = { totalTime: number; }; -export type missingNextNodeMap = { - [id: number]: { - node: Node; - mutation: addedNodeMutation; - }; +export type missingNode = { + node: Node; + mutation: addedNodeMutation; +}; +export type missingNodeMap = { + [id: number]: missingNode; }; diff --git a/test/__snapshots__/integration.ts.snap b/test/__snapshots__/integration.ts.snap index 80689e97..4008732b 100644 --- a/test/__snapshots__/integration.ts.snap +++ b/test/__snapshots__/integration.ts.snap @@ -1215,7 +1215,7 @@ exports[`select2 1`] = ` { \\"type\\": 4, \\"data\\": { - \\"href\\": \\"data:text/html,%0A%0A%0A %0A %0A %0A Select2 3.5%0A %0A%0A%0A
%0A Select2 is a jQuery replacement for select boxes.%0A
%0A In the 3.5 version it use a quite complicated DOM generation strategy which is a good battle-test for rrweb's recorder.%0A
%0A %0A %0A %0A %0A%0A %0A %0A %0A\\", + \\"href\\": \\"data:text/html,%0A%0A%0A %0A %0A %0A Select2 3.5%0A %0A%0A%0A
%0A Select2 is a jQuery replacement for select boxes.%0A
%0A In the 3.5 version it use a quite complicated DOM generation strategy which is a good battle-test for rrweb's recorder.%0A
%0A %0A %0A %0A %0A%0A %0A %0A %0A\\", \\"width\\": 1920, \\"height\\": 1080 }, @@ -1910,6 +1910,7 @@ exports[`select2 1`] = ` }, { \\"parentId\\": 18, + \\"previousId\\": -1, \\"nextId\\": null, \\"node\\": { \\"type\\": 2, @@ -2046,6 +2047,7 @@ exports[`select2 1`] = ` { \\"parentId\\": 84, \\"previousId\\": null, + \\"nextId\\": -1, \\"node\\": { \\"type\\": 2, \\"tagName\\": \\"li\\", @@ -2076,6 +2078,7 @@ exports[`select2 1`] = ` { \\"parentId\\": 86, \\"previousId\\": null, + \\"nextId\\": -1, \\"node\\": { \\"type\\": 2, \\"tagName\\": \\"span\\", @@ -2130,6 +2133,7 @@ exports[`select2 1`] = ` { \\"parentId\\": 90, \\"previousId\\": null, + \\"nextId\\": -1, \\"node\\": { \\"type\\": 2, \\"tagName\\": \\"span\\",