diff --git a/packages/rrweb-snapshot/src/rebuild.ts b/packages/rrweb-snapshot/src/rebuild.ts index 2bcfa8b1..5d3af466 100644 --- a/packages/rrweb-snapshot/src/rebuild.ts +++ b/packages/rrweb-snapshot/src/rebuild.ts @@ -321,18 +321,26 @@ export function buildNodeWithSN( // close before open to make sure document was closed doc.close(); doc.open(); - if (n.compatMode === 'BackCompat' && - (n.childNodes && n.childNodes[0].type !== NodeType.DocumentType) // there isn't one already defined - ) { + if ( + n.compatMode === 'BackCompat' && + n.childNodes && + n.childNodes[0].type !== NodeType.DocumentType // there isn't one already defined + ) { // Trigger compatMode in the iframe // this is needed as document.createElement('iframe') otherwise inherits a CSS1Compat mode from the parent replayer environment - if (n.childNodes[0].type === NodeType.Element && - 'xmlns' in n.childNodes[0].attributes && - n.childNodes[0].attributes.xmlns === 'http://www.w3.org/1999/xhtml') { + if ( + n.childNodes[0].type === NodeType.Element && + 'xmlns' in n.childNodes[0].attributes && + n.childNodes[0].attributes.xmlns === 'http://www.w3.org/1999/xhtml' + ) { // might as well use an xhtml doctype if we've got an xhtml namespace - doc.write(''); + doc.write( + '', + ); } else { - doc.write(''); + doc.write( + '', + ); } } node = doc; diff --git a/packages/rrweb/src/replay/index.ts b/packages/rrweb/src/replay/index.ts index b2f7998d..bac353d2 100644 --- a/packages/rrweb/src/replay/index.ts +++ b/packages/rrweb/src/replay/index.ts @@ -1428,6 +1428,21 @@ export class Replayer { return; } + if ( + '__sn' in parent && + parent.__sn.type === NodeType.Element && + parent.__sn.tagName === 'textarea' && + mutation.node.type === NodeType.Text + ) { + // https://github.com/rrweb-io/rrweb/issues/745 + // parent is textarea, will only keep one child node as the value + for (const c of Array.from(parent.childNodes)) { + if (c.nodeType === parent.TEXT_NODE) { + parent.removeChild(c); + } + } + } + if (previous && previous.nextSibling && previous.nextSibling.parentNode) { parent.insertBefore(target, previous.nextSibling); } else if (next && next.parentNode) {