From b693d667b558190f854fcb655945c48fba0a8ca2 Mon Sep 17 00:00:00 2001 From: Yanzhen Yu Date: Wed, 1 Apr 2026 12:00:00 +0800 Subject: [PATCH] create mirror during record --- src/index.ts | 11 ++++++-- src/record/index.ts | 7 ++++- src/record/mutation.ts | 37 ++++++++++++++------------ src/record/observer.ts | 34 +++++++++++++++++++---- src/record/shadow-dom-manager.ts | 12 ++++++++- src/replay/index.ts | 2 +- src/types.ts | 1 + src/utils.ts | 18 ++++++++----- test/record.test.ts | 4 +-- typings/index.d.ts | 4 +-- typings/record/index.d.ts | 1 + typings/record/mutation.d.ts | 5 ++-- typings/record/observer.d.ts | 4 +-- typings/record/shadow-dom-manager.d.ts | 4 ++- typings/types.d.ts | 1 + typings/utils.d.ts | 6 ++--- 16 files changed, 105 insertions(+), 46 deletions(-) diff --git a/src/index.ts b/src/index.ts index e57b8e42..d8e8dad3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ import record from './record'; import { Replayer } from './replay'; -import { mirror } from './utils'; +import { _mirror } from './utils'; import * as utils from './utils'; export { @@ -13,4 +13,11 @@ export { const { addCustomEvent } = record; const { freezePage } = record; -export { record, addCustomEvent, freezePage, Replayer, mirror, utils }; +export { + record, + addCustomEvent, + freezePage, + Replayer, + _mirror as mirror, + utils, +}; diff --git a/src/record/index.ts b/src/record/index.ts index 3a7668dc..585a5fc6 100644 --- a/src/record/index.ts +++ b/src/record/index.ts @@ -1,13 +1,13 @@ import { snapshot, MaskInputOptions, SlimDOMOptions } from 'rrweb-snapshot'; import { initObservers, mutationBuffers } from './observer'; import { - mirror, on, getWindowWidth, getWindowHeight, polyfill, isIframeINode, hasShadowRoot, + createMirror, } from '../utils'; import { EventType, @@ -33,6 +33,7 @@ let wrappedEmit!: (e: eventWithTime, isCheckout?: boolean) => void; let takeFullSnapshot!: (isCheckout?: boolean) => void; +const mirror = createMirror(); function record( options: recordOptions = {}, ): listenerHandler | undefined { @@ -215,6 +216,7 @@ function record( slimDOMOptions, iframeManager, }, + mirror, }); takeFullSnapshot = (isCheckout = false) => { @@ -418,6 +420,7 @@ function record( logOptions, blockSelector, slimDOMOptions, + mirror, iframeManager, shadowDomManager, }, @@ -490,4 +493,6 @@ record.takeFullSnapshot = (isCheckout?: boolean) => { takeFullSnapshot(isCheckout); }; +record.mirror = mirror; + export default record; diff --git a/src/record/mutation.ts b/src/record/mutation.ts index 4b65e796..8e744bca 100644 --- a/src/record/mutation.ts +++ b/src/record/mutation.ts @@ -18,9 +18,9 @@ import { removedNodeMutation, addedNodeMutation, MaskTextFn, + Mirror, } from '../types'; import { - mirror, isBlocked, isAncestorRemoved, isIgnored, @@ -171,6 +171,7 @@ export default class MutationBuffer { private slimDOMOptions: SlimDOMOptions; private doc: Document; + private mirror: Mirror; private iframeManager: IframeManager; private shadowDomManager: ShadowDomManager; @@ -186,6 +187,7 @@ export default class MutationBuffer { recordCanvas: boolean, slimDOMOptions: SlimDOMOptions, doc: Document, + mirror: Mirror, iframeManager: IframeManager, shadowDomManager: ShadowDomManager, ) { @@ -200,6 +202,7 @@ export default class MutationBuffer { this.slimDOMOptions = slimDOMOptions; this.emissionCallback = cb; this.doc = doc; + this.mirror = mirror; this.iframeManager = iframeManager; this.shadowDomManager = shadowDomManager; } @@ -251,7 +254,7 @@ export default class MutationBuffer { let nextId: number | null = IGNORED_NODE; // slimDOM: ignored while (nextId === IGNORED_NODE) { ns = ns && ns.nextSibling; - nextId = ns && mirror.getId((ns as unknown) as INode); + nextId = ns && this.mirror.getId((ns as unknown) as INode); } if (nextId === -1 && isBlocked(n.nextSibling, this.blockClass)) { nextId = null; @@ -267,15 +270,15 @@ export default class MutationBuffer { return; } const parentId = isShadowRoot(n.parentNode) - ? mirror.getId((shadowHost as unknown) as INode) - : mirror.getId((n.parentNode as Node) as INode); + ? this.mirror.getId((shadowHost as unknown) as INode) + : this.mirror.getId((n.parentNode as Node) as INode); const nextId = getNextId(n); if (parentId === -1 || nextId === -1) { return addList.addNode(n); } let sn = serializeNodeWithId(n, { doc: this.doc, - map: mirror.map, + map: this.mirror.map, blockClass: this.blockClass, blockSelector: this.blockSelector, maskTextClass: this.maskTextClass, @@ -308,7 +311,7 @@ export default class MutationBuffer { }; while (this.mapRemoves.length) { - mirror.removeNodeFromMap(this.mapRemoves.shift() as INode); + this.mirror.removeNodeFromMap(this.mapRemoves.shift() as INode); } for (const n of this.movedSet) { @@ -338,7 +341,7 @@ export default class MutationBuffer { while (addList.length) { let node: DoubleLinkedListNode | null = null; if (candidate) { - const parentId = mirror.getId( + const parentId = this.mirror.getId( (candidate.value.parentNode as Node) as INode, ); const nextId = getNextId(candidate.value); @@ -349,7 +352,7 @@ export default class MutationBuffer { if (!node) { for (let index = addList.length - 1; index >= 0; index--) { const _node = addList.get(index)!; - const parentId = mirror.getId( + const parentId = this.mirror.getId( (_node.value.parentNode as Node) as INode, ); const nextId = getNextId(_node.value); @@ -378,18 +381,18 @@ export default class MutationBuffer { const payload = { texts: this.texts .map((text) => ({ - id: mirror.getId(text.node as INode), + id: this.mirror.getId(text.node as INode), value: text.value, })) // text mutation's id was not in the mirror map means the target node has been removed - .filter((text) => mirror.has(text.id)), + .filter((text) => this.mirror.has(text.id)), attributes: this.attributes .map((attribute) => ({ - id: mirror.getId(attribute.node as INode), + id: this.mirror.getId(attribute.node as INode), attributes: attribute.attributes, })) // attribute mutation's id was not in the mirror map means the target node has been removed - .filter((attribute) => mirror.has(attribute.id)), + .filter((attribute) => this.mirror.has(attribute.id)), removes: this.removes, adds, }; @@ -466,10 +469,10 @@ export default class MutationBuffer { case 'childList': { m.addedNodes.forEach((n) => this.genAdds(n, m.target)); m.removedNodes.forEach((n) => { - const nodeId = mirror.getId(n as INode); + const nodeId = this.mirror.getId(n as INode); const parentId = isShadowRoot(m.target) - ? mirror.getId((m.target.host as unknown) as INode) - : mirror.getId(m.target as INode); + ? this.mirror.getId((m.target.host as unknown) as INode) + : this.mirror.getId(m.target as INode); if ( isBlocked(n, this.blockClass) || isBlocked(m.target, this.blockClass) || @@ -489,7 +492,7 @@ export default class MutationBuffer { * newly added node will be serialized without child nodes. * TODO: verify this */ - } else if (isAncestorRemoved(m.target as INode)) { + } else if (isAncestorRemoved(m.target as INode, this.mirror)) { /** * If parent id was not in the mirror map any more, it * means the parent node has already been removed. So @@ -560,7 +563,7 @@ function isParentRemoved(removes: removedNodeMutation[], n: Node): boolean { if (!parentNode) { return false; } - const parentId = mirror.getId((parentNode as Node) as INode); + const parentId = this.mirror.getId((parentNode as Node) as INode); if (removes.some((r) => r.id === parentId)) { return true; } diff --git a/src/record/observer.ts b/src/record/observer.ts index 2cc87efa..dd2a1934 100644 --- a/src/record/observer.ts +++ b/src/record/observer.ts @@ -1,7 +1,6 @@ import { INode, MaskInputOptions, SlimDOMOptions } from 'rrweb-snapshot'; import { FontFaceDescriptors, FontFaceSet } from 'css-font-loading-module'; import { - mirror, throttle, on, hookSetter, @@ -42,6 +41,7 @@ import { LogRecordOptions, Logger, LogLevel, + Mirror, } from '../types'; import MutationBuffer from './mutation'; import { stringify } from './stringify'; @@ -72,6 +72,7 @@ export function initMutationObserver( maskTextFn: MaskTextFn | undefined, recordCanvas: boolean, slimDOMOptions: SlimDOMOptions, + mirror: Mirror, iframeManager: IframeManager, shadowDomManager: ShadowDomManager, rootEl: Node, @@ -91,6 +92,7 @@ export function initMutationObserver( recordCanvas, slimDOMOptions, doc, + mirror, iframeManager, shadowDomManager, ); @@ -137,6 +139,7 @@ function initMoveObserver( cb: mousemoveCallBack, sampling: SamplingStrategy, doc: Document, + mirror: Mirror, ): listenerHandler { if (sampling.mousemove === false) { return () => {}; @@ -212,6 +215,7 @@ function initMoveObserver( function initMouseInteractionObserver( cb: mouseInteractionCallBack, doc: Document, + mirror: Mirror, blockClass: blockClass, sampling: SamplingStrategy, ): listenerHandler { @@ -264,6 +268,7 @@ function initMouseInteractionObserver( function initScrollObserver( cb: scrollCallback, doc: Document, + mirror: Mirror, blockClass: blockClass, sampling: SamplingStrategy, ): listenerHandler { @@ -315,6 +320,7 @@ const lastInputValueMap: WeakMap = new WeakMap(); function initInputObserver( cb: inputCallback, doc: Document, + mirror: Mirror, blockClass: blockClass, ignoreClass: string, maskInputOptions: MaskInputOptions, @@ -419,7 +425,10 @@ function initInputObserver( }; } -function initStyleSheetObserver(cb: styleSheetRuleCallback): listenerHandler { +function initStyleSheetObserver( + cb: styleSheetRuleCallback, + mirror: Mirror, +): listenerHandler { const insertRule = CSSStyleSheet.prototype.insertRule; CSSStyleSheet.prototype.insertRule = function (rule: string, index?: number) { const id = mirror.getId(this.ownerNode as INode); @@ -453,6 +462,7 @@ function initStyleSheetObserver(cb: styleSheetRuleCallback): listenerHandler { function initMediaInteractionObserver( mediaInteractionCb: mediaInteractionCallback, blockClass: blockClass, + mirror: Mirror, ): listenerHandler { const handler = (type: 'play' | 'pause') => (event: Event) => { const { target } = event; @@ -473,6 +483,7 @@ function initMediaInteractionObserver( function initCanvasMutationObserver( cb: canvasMutationCallback, blockClass: blockClass, + mirror: Mirror, ): listenerHandler { const props = Object.getOwnPropertyNames(CanvasRenderingContext2D.prototype); const handlers: listenerHandler[] = []; @@ -779,20 +790,28 @@ export function initObservers( o.maskTextFn, o.recordCanvas, o.slimDOMOptions, + o.mirror, o.iframeManager, o.shadowDomManager, o.doc, ); - const mousemoveHandler = initMoveObserver(o.mousemoveCb, o.sampling, o.doc); + const mousemoveHandler = initMoveObserver( + o.mousemoveCb, + o.sampling, + o.doc, + o.mirror, + ); const mouseInteractionHandler = initMouseInteractionObserver( o.mouseInteractionCb, o.doc, + o.mirror, o.blockClass, o.sampling, ); const scrollHandler = initScrollObserver( o.scrollCb, o.doc, + o.mirror, o.blockClass, o.sampling, ); @@ -800,6 +819,7 @@ export function initObservers( const inputHandler = initInputObserver( o.inputCb, o.doc, + o.mirror, o.blockClass, o.ignoreClass, o.maskInputOptions, @@ -809,10 +829,14 @@ export function initObservers( const mediaInteractionHandler = initMediaInteractionObserver( o.mediaInteractionCb, o.blockClass, + o.mirror, + ); + const styleSheetObserver = initStyleSheetObserver( + o.styleSheetRuleCb, + o.mirror, ); - const styleSheetObserver = initStyleSheetObserver(o.styleSheetRuleCb); const canvasMutationObserver = o.recordCanvas - ? initCanvasMutationObserver(o.canvasMutationCb, o.blockClass) + ? initCanvasMutationObserver(o.canvasMutationCb, o.blockClass, o.mirror) : () => {}; const fontObserver = o.collectFonts ? initFontObserver(o.fontCb) : () => {}; const logObserver = o.logOptions diff --git a/src/record/shadow-dom-manager.ts b/src/record/shadow-dom-manager.ts index 6681e11b..71d233d2 100644 --- a/src/record/shadow-dom-manager.ts +++ b/src/record/shadow-dom-manager.ts @@ -1,4 +1,10 @@ -import { mutationCallBack, blockClass, maskTextClass, MaskTextFn } from '../types'; +import { + mutationCallBack, + blockClass, + maskTextClass, + MaskTextFn, + Mirror, +} from '../types'; import { MaskInputOptions, SlimDOMOptions } from 'rrweb-snapshot'; import { IframeManager } from './iframe-manager'; import { initMutationObserver } from './observer'; @@ -19,13 +25,16 @@ type BypassOptions = { export class ShadowDomManager { private mutationCb: mutationCallBack; private bypassOptions: BypassOptions; + private mirror: Mirror; constructor(options: { mutationCb: mutationCallBack; bypassOptions: BypassOptions; + mirror: Mirror; }) { this.mutationCb = options.mutationCb; this.bypassOptions = options.bypassOptions; + this.mirror = this.mirror; } public addShadowRoot(shadowRoot: ShadowRoot, doc: Document) { @@ -41,6 +50,7 @@ export class ShadowDomManager { this.bypassOptions.maskTextFn, this.bypassOptions.recordCanvas, this.bypassOptions.slimDOMOptions, + this.mirror, this.bypassOptions.iframeManager, this, shadowRoot, diff --git a/src/replay/index.ts b/src/replay/index.ts index 97de88ba..6964eda8 100644 --- a/src/replay/index.ts +++ b/src/replay/index.ts @@ -779,7 +779,7 @@ export class Replayer { d.adds.forEach((m) => this.treeIndex.add(m)); d.texts.forEach((m) => this.treeIndex.text(m)); d.attributes.forEach((m) => this.treeIndex.attribute(m)); - d.removes.forEach((m) => this.treeIndex.remove(m)); + d.removes.forEach((m) => this.treeIndex.remove(m, this.mirror)); } this.applyMutation(d, isSync); break; diff --git a/src/types.ts b/src/types.ts index 3be785f0..0a040e3b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -243,6 +243,7 @@ export type observerParam = { collectFonts: boolean; slimDOMOptions: SlimDOMOptions; doc: Document; + mirror: Mirror; iframeManager: IframeManager; shadowDomManager: ShadowDomManager; }; diff --git a/src/utils.ts b/src/utils.ts index d579c9ae..59ee18e9 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -68,8 +68,12 @@ export function createMirror(): Mirror { // https://github.com/rrweb-io/rrweb/pull/407 const DEPARTED_MIRROR_ACCESS_WARNING = - 'Please stop import mirror directly. Instead of that, now you can use replayer.getMirror() to access the mirror instance of a replayer.'; -export let mirror: Mirror = { + 'Please stop import mirror directly. Instead of that,' + + '\r\n' + + 'now you can use replayer.getMirror() to access the mirror instance of a replayer,' + + '\r\n' + + 'or you can use record.mirror to access the mirror instance during recording.'; +export let _mirror: Mirror = { map: {}, getId() { console.error(DEPARTED_MIRROR_ACCESS_WARNING); @@ -90,8 +94,8 @@ export let mirror: Mirror = { console.error(DEPARTED_MIRROR_ACCESS_WARNING); }, }; -if (window.Proxy && window.Reflect) { - mirror = new Proxy(mirror, { +if (typeof window !== 'undefined' && window.Proxy && window.Reflect) { + _mirror = new Proxy(_mirror, { get(target, prop, receiver) { if (prop === 'map') { console.error(DEPARTED_MIRROR_ACCESS_WARNING); @@ -253,7 +257,7 @@ export function isIgnored(n: Node | INode): boolean { return false; } -export function isAncestorRemoved(target: INode): boolean { +export function isAncestorRemoved(target: INode, mirror: Mirror): boolean { if (isShadowRoot(target)) { return false; } @@ -271,7 +275,7 @@ export function isAncestorRemoved(target: INode): boolean { if (!target.parentNode) { return true; } - return isAncestorRemoved((target.parentNode as unknown) as INode); + return isAncestorRemoved((target.parentNode as unknown) as INode, mirror); } export function isTouchEvent( @@ -382,7 +386,7 @@ export class TreeIndex { this.indexes.set(treeNode.id, treeNode); } - public remove(mutation: removedNodeMutation) { + public remove(mutation: removedNodeMutation, mirror: Mirror) { const parentTreeNode = this.indexes.get(mutation.parentId); const treeNode = this.indexes.get(mutation.id); diff --git a/test/record.test.ts b/test/record.test.ts index fb6a3f79..025675a0 100644 --- a/test/record.test.ts +++ b/test/record.test.ts @@ -142,10 +142,10 @@ describe('record', function (this: ISuite) { } await this.page.waitFor(300); expect(this.events.length).to.equal(33); // before first automatic snapshot - await this.page.waitFor(200); // could be 33 or 35 events by now depending on speed of test env + await this.page.waitFor(200); // could be 33 or 35 events by now depending on speed of test env await this.page.type('input', 'a'); await this.page.waitFor(10); - expect(this.events.length).to.equal(36); // additionally includes the 2 checkout events + expect(this.events.length).to.equal(36); // additionally includes the 2 checkout events expect( this.events.filter( (event: eventWithTime) => event.type === EventType.Meta, diff --git a/typings/index.d.ts b/typings/index.d.ts index b6bf190e..6b6d18d1 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1,8 +1,8 @@ import record from './record'; import { Replayer } from './replay'; -import { mirror } from './utils'; +import { _mirror } from './utils'; import * as utils from './utils'; export { EventType, IncrementalSource, MouseInteractions, ReplayerEvents, } from './types'; declare const addCustomEvent: (tag: string, payload: T) => void; declare const freezePage: () => void; -export { record, addCustomEvent, freezePage, Replayer, mirror, utils }; +export { record, addCustomEvent, freezePage, Replayer, _mirror as mirror, utils, }; diff --git a/typings/record/index.d.ts b/typings/record/index.d.ts index 469fde38..c4f541c8 100644 --- a/typings/record/index.d.ts +++ b/typings/record/index.d.ts @@ -4,5 +4,6 @@ declare namespace record { var addCustomEvent: (tag: string, payload: T) => void; var freezePage: () => void; var takeFullSnapshot: (isCheckout?: boolean | undefined) => void; + var mirror: import("../types").Mirror; } export default record; diff --git a/typings/record/mutation.d.ts b/typings/record/mutation.d.ts index aaa05700..a512942c 100644 --- a/typings/record/mutation.d.ts +++ b/typings/record/mutation.d.ts @@ -1,5 +1,5 @@ import { MaskInputOptions, SlimDOMOptions } from 'rrweb-snapshot'; -import { mutationRecord, blockClass, maskTextClass, mutationCallBack, MaskTextFn } from '../types'; +import { mutationRecord, blockClass, maskTextClass, mutationCallBack, MaskTextFn, Mirror } from '../types'; import { IframeManager } from './iframe-manager'; import { ShadowDomManager } from './shadow-dom-manager'; export default class MutationBuffer { @@ -24,9 +24,10 @@ export default class MutationBuffer { private recordCanvas; private slimDOMOptions; private doc; + private mirror; private iframeManager; private shadowDomManager; - init(cb: mutationCallBack, blockClass: blockClass, blockSelector: string | null, maskTextClass: maskTextClass, maskTextSelector: string | null, inlineStylesheet: boolean, maskInputOptions: MaskInputOptions, maskTextFn: MaskTextFn | undefined, recordCanvas: boolean, slimDOMOptions: SlimDOMOptions, doc: Document, iframeManager: IframeManager, shadowDomManager: ShadowDomManager): void; + init(cb: mutationCallBack, blockClass: blockClass, blockSelector: string | null, maskTextClass: maskTextClass, maskTextSelector: string | null, inlineStylesheet: boolean, maskInputOptions: MaskInputOptions, maskTextFn: MaskTextFn | undefined, recordCanvas: boolean, slimDOMOptions: SlimDOMOptions, doc: Document, mirror: Mirror, iframeManager: IframeManager, shadowDomManager: ShadowDomManager): void; freeze(): void; unfreeze(): void; isFrozen(): boolean; diff --git a/typings/record/observer.d.ts b/typings/record/observer.d.ts index cfeda577..a82a370c 100644 --- a/typings/record/observer.d.ts +++ b/typings/record/observer.d.ts @@ -1,9 +1,9 @@ import { MaskInputOptions, SlimDOMOptions } from 'rrweb-snapshot'; -import { mutationCallBack, observerParam, listenerHandler, blockClass, maskTextClass, hooksParam, MaskTextFn } from '../types'; +import { mutationCallBack, observerParam, listenerHandler, blockClass, maskTextClass, hooksParam, MaskTextFn, Mirror } from '../types'; import MutationBuffer from './mutation'; import { IframeManager } from './iframe-manager'; import { ShadowDomManager } from './shadow-dom-manager'; export declare const mutationBuffers: MutationBuffer[]; -export declare function initMutationObserver(cb: mutationCallBack, doc: Document, blockClass: blockClass, blockSelector: string | null, maskTextClass: maskTextClass, maskTextSelector: string | null, inlineStylesheet: boolean, maskInputOptions: MaskInputOptions, maskTextFn: MaskTextFn | undefined, recordCanvas: boolean, slimDOMOptions: SlimDOMOptions, iframeManager: IframeManager, shadowDomManager: ShadowDomManager, rootEl: Node): MutationObserver; +export declare function initMutationObserver(cb: mutationCallBack, doc: Document, blockClass: blockClass, blockSelector: string | null, maskTextClass: maskTextClass, maskTextSelector: string | null, inlineStylesheet: boolean, maskInputOptions: MaskInputOptions, maskTextFn: MaskTextFn | undefined, recordCanvas: boolean, slimDOMOptions: SlimDOMOptions, mirror: Mirror, iframeManager: IframeManager, shadowDomManager: ShadowDomManager, rootEl: Node): MutationObserver; export declare const INPUT_TAGS: string[]; export declare function initObservers(o: observerParam, hooks?: hooksParam): listenerHandler; diff --git a/typings/record/shadow-dom-manager.d.ts b/typings/record/shadow-dom-manager.d.ts index 1df3bcda..b0c4e2bc 100644 --- a/typings/record/shadow-dom-manager.d.ts +++ b/typings/record/shadow-dom-manager.d.ts @@ -1,4 +1,4 @@ -import { mutationCallBack, blockClass, maskTextClass, MaskTextFn } from '../types'; +import { mutationCallBack, blockClass, maskTextClass, MaskTextFn, Mirror } from '../types'; import { MaskInputOptions, SlimDOMOptions } from 'rrweb-snapshot'; import { IframeManager } from './iframe-manager'; declare type BypassOptions = { @@ -16,9 +16,11 @@ declare type BypassOptions = { export declare class ShadowDomManager { private mutationCb; private bypassOptions; + private mirror; constructor(options: { mutationCb: mutationCallBack; bypassOptions: BypassOptions; + mirror: Mirror; }); addShadowRoot(shadowRoot: ShadowRoot, doc: Document): void; } diff --git a/typings/types.d.ts b/typings/types.d.ts index f42927fc..a71df5b9 100644 --- a/typings/types.d.ts +++ b/typings/types.d.ts @@ -168,6 +168,7 @@ export declare type observerParam = { collectFonts: boolean; slimDOMOptions: SlimDOMOptions; doc: Document; + mirror: Mirror; iframeManager: IframeManager; shadowDomManager: ShadowDomManager; }; diff --git a/typings/utils.d.ts b/typings/utils.d.ts index 749487bc..763fa503 100644 --- a/typings/utils.d.ts +++ b/typings/utils.d.ts @@ -2,7 +2,7 @@ import { Mirror, throttleOptions, listenerHandler, hookResetter, blockClass, eve import { INode, serializedNodeWithId } from 'rrweb-snapshot'; export declare function on(type: string, fn: EventListenerOrEventListenerObject, target?: Document | Window): listenerHandler; export declare function createMirror(): Mirror; -export declare let mirror: Mirror; +export declare let _mirror: Mirror; export declare function throttle(func: (arg: T) => void, wait: number, options?: throttleOptions): (arg: T) => void; export declare function hookSetter(target: T, key: string | number | symbol, d: PropertyDescriptor, isRevoked?: boolean, win?: Window & typeof globalThis): hookResetter; export declare function patch(source: { @@ -12,7 +12,7 @@ export declare function getWindowHeight(): number; export declare function getWindowWidth(): number; export declare function isBlocked(node: Node | null, blockClass: blockClass): boolean; export declare function isIgnored(n: Node | INode): boolean; -export declare function isAncestorRemoved(target: INode): boolean; +export declare function isAncestorRemoved(target: INode, mirror: Mirror): boolean; export declare function isTouchEvent(event: MouseEvent | TouchEvent): event is TouchEvent; export declare function polyfill(win?: Window & typeof globalThis): void; export declare function needCastInSyncMode(event: eventWithTime): boolean; @@ -35,7 +35,7 @@ export declare class TreeIndex { private inputMap; constructor(); add(mutation: addedNodeMutation): void; - remove(mutation: removedNodeMutation): void; + remove(mutation: removedNodeMutation, mirror: Mirror): void; text(mutation: textMutation): void; attribute(mutation: attributeMutation): void; scroll(d: scrollData): void;