diff --git a/packages/rrdom/package.json b/packages/rrdom/package.json index 0e7f747d..6a87c55a 100644 --- a/packages/rrdom/package.json +++ b/packages/rrdom/package.json @@ -1,6 +1,6 @@ { "name": "@highlight-run/rrdom", - "version": "0.1.9", + "version": "0.1.10", "scripts": { "dev": "rollup -c -w", "bundle": "rollup --config", diff --git a/packages/rrdom/src/diff.ts b/packages/rrdom/src/diff.ts index e0f097f1..ef28095e 100644 --- a/packages/rrdom/src/diff.ts +++ b/packages/rrdom/src/diff.ts @@ -283,22 +283,22 @@ function diffChildren( ) { try { parentNode.insertBefore(oldStartNode, oldEndNode.nextSibling); - } catch (e) { - console.error(e, parentNode, oldStartNode, oldEndNode); diff(oldStartNode, newEndNode, replayer, rrnodeMirror); oldStartNode = oldChildren[++oldStartIndex]; newEndNode = newChildren[--newEndIndex]; + } catch (e) { + console.error(e, parentNode, oldStartNode, oldEndNode); } } else if ( replayer.mirror.getId(oldEndNode) === rrnodeMirror.getId(newStartNode) ) { try { parentNode.insertBefore(oldEndNode, oldStartNode); - } catch (e) { - console.error(e, parentNode, oldEndNode, oldStartNode); diff(oldEndNode, newStartNode, replayer, rrnodeMirror); oldEndNode = oldChildren[--oldEndIndex]; newStartNode = newChildren[++newStartIndex]; + } catch (e) { + console.error(e, parentNode, oldEndNode, oldStartNode); } } else { if (!oldIdToIndex) { @@ -314,10 +314,10 @@ function diffChildren( const nodeToMove = oldChildren[indexInOld]!; try { parentNode.insertBefore(nodeToMove, oldStartNode); - } catch (e) { - console.error(e, parentNode, nodeToMove, oldStartNode); diff(nodeToMove, newStartNode, replayer, rrnodeMirror); oldChildren[indexInOld] = undefined; + } catch (e) { + console.error(e, parentNode, nodeToMove, oldStartNode); } } else { const newNode = createOrGetNode( @@ -331,7 +331,7 @@ function diffChildren( * We should delete it before insert a serialized one. Otherwise, an error 'Only one element on document allowed' will be thrown. */ if ( - replayer.mirror.getMeta(parentNode)?.type === RRNodeType.Document && + parentNode.nodeName === '#document' && replayer.mirror.getMeta(newNode)?.type === RRNodeType.Element && (parentNode as Document).documentElement ) { @@ -341,9 +341,9 @@ function diffChildren( } try { parentNode.insertBefore(newNode, oldStartNode || null); + diff(newNode, newStartNode, replayer, rrnodeMirror); } catch (e) { console.error(e, parentNode, newNode, oldStartNode || null); - diff(newNode, newStartNode, replayer, rrnodeMirror); } } newStartNode = newChildren[++newStartIndex]; @@ -367,9 +367,9 @@ function diffChildren( ); try { parentNode.insertBefore(newNode, referenceNode); + diff(newNode, newChildren[newStartIndex], replayer, rrnodeMirror); } catch (e) { console.error(e, parentNode, newNode, referenceNode); - diff(newNode, newChildren[newStartIndex], replayer, rrnodeMirror); } } } else if (newStartIndex > newEndIndex) { diff --git a/packages/rrdom/test/diff.test.ts b/packages/rrdom/test/diff.test.ts index a52c7f31..656d10fb 100644 --- a/packages/rrdom/test/diff.test.ts +++ b/packages/rrdom/test/diff.test.ts @@ -1056,6 +1056,24 @@ describe('diff algorithm for rrdom', () => { expect(element.tagName).toBe('DIV'); expect(mirror.getId(element)).toEqual(2); }); + + it('should remove children from document before adding new nodes', () => { + document.write(''); // old document with elements that need removing + + const rrDocument = new RRDocument(); + const docType = rrDocument.createDocumentType('html', '', ''); + rrDocument.mirror.add(docType, getDefaultSN(docType, 1)); + rrDocument.appendChild(docType); + const htmlEl = rrDocument.createElement('html'); + rrDocument.mirror.add(htmlEl, getDefaultSN(htmlEl, 2)); + rrDocument.appendChild(htmlEl); + + diff(document, rrDocument, replayer); + expect(document.childNodes.length).toBe(2); + const element = document.childNodes[0] as HTMLElement; + expect(element.nodeType).toBe(element.DOCUMENT_TYPE_NODE); + expect(mirror.getId(element)).toEqual(1); + }); }); describe('create or get a Node', () => { diff --git a/packages/rrweb/package.json b/packages/rrweb/package.json index a0ab5b3a..e23e543b 100644 --- a/packages/rrweb/package.json +++ b/packages/rrweb/package.json @@ -1,6 +1,6 @@ { "name": "@highlight-run/rrweb", - "version": "2.0.10", + "version": "2.0.11", "description": "record and replay the web", "scripts": { "prepare": "npm run prepack", diff --git a/packages/rrweb/test/integration.test.ts b/packages/rrweb/test/integration.test.ts index 29b3ba63..fc6d4e4f 100644 --- a/packages/rrweb/test/integration.test.ts +++ b/packages/rrweb/test/integration.test.ts @@ -576,8 +576,7 @@ describe('record integration tests', function (this: ISuite) { ); }); }); - await page.waitForTimeout(20); // 20ms of sleep time - await waitForRAF(page); // wait for events to get created + await waitForRAF(page); const snapshots = await page.evaluate('window.snapshots'); assertSnapshot(snapshots);