diff --git a/packages/rrweb/src/replay/index.ts b/packages/rrweb/src/replay/index.ts index a80e1de592..a3a791c978 100644 --- a/packages/rrweb/src/replay/index.ts +++ b/packages/rrweb/src/replay/index.ts @@ -933,10 +933,7 @@ export class Replayer { sn?.tagName.toUpperCase() === 'HTML' ) { const { documentElement, head } = iframeEl.contentDocument!; - this.insertStyleRules( - documentElement as HTMLElement | RRElement, - head as HTMLElement | RRElement, - ); + this.insertStyleRules(documentElement, head); } // Skip the plugin onBuild callback in the virtual dom mode @@ -1302,7 +1299,7 @@ export class Replayer { if (!target) { return this.debugNodeNotFound(d, d.id); } - const mediaEl = target as HTMLMediaElement | RRMediaElement; + const mediaEl = target; const { events } = this.service.state.context; this.mediaManager.mediaMutation({ @@ -1439,13 +1436,13 @@ export class Replayer { return this.warnNodeNotFound(d, mutation.parentId); } if (mutation.isShadow && hasShadowRoot(parent as Node)) { - parent = (parent as Element | RRElement).shadowRoot; + parent = parent.shadowRoot; } // target may be removed with its parents before - mirror.removeNodeFromMap(target as Node & RRNode); + mirror.removeNodeFromMap(target); if (parent) try { - parent.removeChild(target as Node & RRNode); + parent.removeChild(target); /** * https://github.com/rrweb-io/rrweb/pull/887 * Remove any virtual style rules for stylesheets if a child text node is removed. @@ -1513,8 +1510,8 @@ export class Replayer { // If the parent is attached a shadow dom after it's created, it won't have a shadow root. if (!hasShadowRoot(parent)) { (parent as Element | RRElement).attachShadow({ mode: 'open' }); - parent = (parent as Element | RRElement).shadowRoot! as Node | RRNode; - } else parent = parent.shadowRoot as Node | RRNode; + parent = (parent as Element | RRElement).shadowRoot!; + } else parent = parent.shadowRoot; } let previous: Node | RRNode | null = null; @@ -1539,10 +1536,7 @@ export class Replayer { ? this.virtualDom : this.iframe.contentDocument; if (isSerializedIframe(parent, mirror)) { - this.attachDocumentToIframe( - mutation, - parent as HTMLIFrameElement | RRIFrameElement, - ); + this.attachDocumentToIframe(mutation, parent); return; } const afterAppend = (node: Node | RRNode, id: number) => { @@ -1598,7 +1592,7 @@ export class Replayer { // parent is textarea, will only keep one child node as the value for (const c of prospectiveSiblings) { if (c.nodeType === parent.TEXT_NODE) { - parent.removeChild(c as Node & RRNode); + parent.removeChild(c); } } } else if ( @@ -1626,7 +1620,7 @@ export class Replayer { * After the change of document, we may get another mutation which adds a new doctype or a HTML element, while the old one still exists in the dom. * So, we need to remove the old one first to avoid collision. */ - const parentDoc = parent as Document | RRDocument; + const parentDoc = parent; /** * To detect the exist of the old doctype before adding a new doctype. * We need to remove the old doctype before adding the new one. Otherwise, code will throw "mutation Failed to execute 'insertBefore' on 'Node': Only one doctype on document allowed". @@ -1635,15 +1629,13 @@ export class Replayer { mutation.node.type === NodeType.DocumentType && parentDoc.childNodes[0]?.nodeType === Node.DOCUMENT_TYPE_NODE ) - parentDoc.removeChild(parentDoc.childNodes[0] as Node & RRNode); + parentDoc.removeChild(parentDoc.childNodes[0]); /** * To detect the exist of the old HTML element before adding a new HTML element. * The reason is similar to the above. One document only allows exactly one DocType and one HTML Element. */ if (target.nodeName === 'HTML' && parentDoc.documentElement) - parentDoc.removeChild( - parentDoc.documentElement as HTMLElement & RRNode, - ); + parentDoc.removeChild(parentDoc.documentElement); } if (previous && previous.nextSibling && previous.nextSibling.parentNode) { @@ -1748,7 +1740,7 @@ export class Replayer { return this.warnNodeNotFound(d, mutation.id); } - const parentEl = target.parentElement as Element | RRElement; + const parentEl = target.parentElement; if (mutation.value && parentEl && parentEl.tagName === 'STYLE') { // assumes hackCss: true (which isn't currently configurable from rrweb) target.textContent = adaptCssForReplay(mutation.value, this.cache); @@ -1778,7 +1770,7 @@ export class Replayer { if (typeof attributeName === 'string') { const value = mutation.attributes[attributeName]; if (value === null) { - (target as Element | RRElement).removeAttribute(attributeName); + target.removeAttribute(attributeName); if (attributeName === 'open') removeDialogFromTopLevel(target, mutation); } else if (typeof value === 'string') { @@ -1790,7 +1782,7 @@ export class Replayer { ) { try { const newSn = mirror.getMeta( - target as Node & RRNode, + target, ) as serializedElementNodeWithId; const newNode = buildNodeWithSN( { @@ -1808,15 +1800,17 @@ export class Replayer { cache: this.cache, }, ); + // Update mirror meta's attributes + Object.assign( + newSn.attributes, + mutation.attributes as attributes, + ); const siblingNode = target.nextSibling; const parentNode = target.parentNode; if (newNode && parentNode) { - parentNode.removeChild(target as Node & RRNode); - parentNode.insertBefore( - newNode as Node & RRNode, - siblingNode as (Node & RRNode) | null, - ); - mirror.replace(mutation.id, newNode as Node & RRNode); + parentNode.removeChild(target); + parentNode.insertBefore(newNode, siblingNode); + mirror.replace(mutation.id, newNode); break; } } catch (e) { @@ -1836,10 +1830,7 @@ export class Replayer { textarea.appendChild(tn as TNode); } } else { - (target as Element | RRElement).setAttribute( - attributeName, - value, - ); + target.setAttribute(attributeName, value); } if ( @@ -1856,7 +1847,7 @@ export class Replayer { } } else if (attributeName === 'style') { const styleValues = value; - const targetEl = target as HTMLElement | RRElement; + const targetEl = target; for (const s in styleValues) { if (styleValues[s] === false) { targetEl.style.removeProperty(s); @@ -2131,7 +2122,7 @@ export class Replayer { const nextInMap = nextId && map[nextId]; if (previousInMap) { const { node, mutation } = previousInMap; - parent.insertBefore(node as Node & RRNode, target as Node & RRNode); + parent.insertBefore(node, target); delete map[mutation.node.id]; delete this.legacy_missingNodeRetryMap[mutation.node.id]; if (mutation.previousId || mutation.nextId) { @@ -2140,10 +2131,7 @@ export class Replayer { } if (nextInMap) { const { node, mutation } = nextInMap; - parent.insertBefore( - node as Node & RRNode, - target.nextSibling as Node & RRNode, - ); + parent.insertBefore(node, target.nextSibling); delete map[mutation.node.id]; delete this.legacy_missingNodeRetryMap[mutation.node.id]; if (mutation.previousId || mutation.nextId) {