diff --git a/.changeset/healthy-brooms-glow.md b/.changeset/healthy-brooms-glow.md new file mode 100644 index 0000000000..f180409a66 --- /dev/null +++ b/.changeset/healthy-brooms-glow.md @@ -0,0 +1,6 @@ +--- +"rrweb-snapshot": major +"rrweb": major +--- + +change optional params of serialize object diff --git a/packages/rrweb-snapshot/src/snapshot.ts b/packages/rrweb-snapshot/src/snapshot.ts index 88b6c8b0ae..5b4d07582d 100644 --- a/packages/rrweb-snapshot/src/snapshot.ts +++ b/packages/rrweb-snapshot/src/snapshot.ts @@ -207,7 +207,7 @@ export function absoluteToDoc(doc: Document, attributeValue: string): string { } function isSVGElement(el: Element): boolean { - return Boolean(el.tagName === 'svg' || (el as SVGElement).ownerSVGElement); + return el.tagName === 'svg' || !!(el as SVGElement).ownerSVGElement; } function getHref(doc: Document, customHref?: string) { @@ -445,43 +445,27 @@ function onceStylesheetLoaded( function serializeNode( n: Node, options: { - doc: Document; - mirror: Mirror; blockClass: string | RegExp; blockSelector: string | null; - needsMask: boolean; - inlineStylesheet: boolean; - maskInputOptions: MaskInputOptions; - maskTextFn: MaskTextFn | undefined; - maskInputFn: MaskInputFn | undefined; - dataURLOptions?: DataURLOptions; + dataURLOptions: DataURLOptions | undefined; + doc: Document; inlineImages: boolean; - recordCanvas: boolean; + inlineStylesheet: boolean; keepIframeSrcFn: KeepIframeSrcFn; + maskInputFn: MaskInputFn | undefined; + maskInputOptions: MaskInputOptions | undefined; + maskTextFn: MaskTextFn | undefined; + mirror: Mirror; + needsMask: boolean; /** * `newlyAddedElement: true` skips scrollTop and scrollLeft check */ - newlyAddedElement?: boolean; + newlyAddedElement: boolean; + recordCanvas: boolean; }, ): serializedNode | false { - const { - doc, - mirror, - blockClass, - blockSelector, - needsMask, - inlineStylesheet, - maskInputOptions = {}, - maskTextFn, - maskInputFn, - dataURLOptions = {}, - inlineImages, - recordCanvas, - keepIframeSrcFn, - newlyAddedElement = false, - } = options; // Only record root id when document object is not the base document - const rootId = getRootId(doc, mirror); + const rootId = getRootId(options.doc, options.mirror); switch (n.nodeType) { case n.DOCUMENT_NODE: if ((n as Document).compatMode !== 'CSS1Compat') { @@ -506,24 +490,24 @@ function serializeNode( }; case n.ELEMENT_NODE: return serializeElementNode(n as HTMLElement, { - doc, - blockClass, - blockSelector, - inlineStylesheet, - maskInputOptions, - maskInputFn, - dataURLOptions, - inlineImages, - recordCanvas, - keepIframeSrcFn, - newlyAddedElement, + blockClass: options.blockClass, + blockSelector: options.blockSelector, + dataURLOptions: options.dataURLOptions, + doc: options.doc, + inlineImages: options.inlineImages, + inlineStylesheet: options.inlineStylesheet, + keepIframeSrcFn: options.keepIframeSrcFn, + maskInputFn: options.maskInputFn, + maskInputOptions: options.maskInputOptions, + newlyAddedElement: options.newlyAddedElement, + recordCanvas: options.recordCanvas, rootId, }); case n.TEXT_NODE: return serializeTextNode(n as Text, { - doc, - needsMask, - maskTextFn, + doc: options.doc, + needsMask: options.needsMask, + maskTextFn: options.maskTextFn, rootId, }); case n.CDATA_SECTION_NODE: @@ -606,38 +590,23 @@ function serializeTextNode( function serializeElementNode( n: HTMLElement, options: { - doc: Document; blockClass: string | RegExp; blockSelector: string | null; - inlineStylesheet: boolean; - maskInputOptions: MaskInputOptions; - maskInputFn: MaskInputFn | undefined; - dataURLOptions?: DataURLOptions; + dataURLOptions: DataURLOptions | undefined; + doc: Document; inlineImages: boolean; - recordCanvas: boolean; + inlineStylesheet: boolean; keepIframeSrcFn: KeepIframeSrcFn; + maskInputFn: MaskInputFn | undefined; + maskInputOptions: MaskInputOptions | undefined; /** * `newlyAddedElement: true` skips scrollTop and scrollLeft check */ - newlyAddedElement?: boolean; + newlyAddedElement: boolean; + recordCanvas: boolean; rootId: number | undefined; }, ): serializedNode | false { - const { - doc, - blockClass, - blockSelector, - inlineStylesheet, - maskInputOptions = {}, - maskInputFn, - dataURLOptions = {}, - inlineImages, - recordCanvas, - keepIframeSrcFn, - newlyAddedElement = false, - rootId, - } = options; - const needBlock = _isBlockedElement(n, blockClass, blockSelector); const tagName = getValidTagName(n); let attributes: attributes = {}; const len = n.attributes.length; @@ -645,7 +614,7 @@ function serializeElementNode( const attr = n.attributes[i]; if (!ignoreAttribute(tagName, attr.name, attr.value)) { attributes[attr.name] = transformAttribute( - doc, + options.doc, tagName, toLowerCase(attr.name), attr.value, @@ -653,8 +622,8 @@ function serializeElementNode( } } // remote css - if (tagName === 'link' && inlineStylesheet) { - const stylesheet = Array.from(doc.styleSheets).find((s) => { + if (tagName === 'link' && options.inlineStylesheet) { + const stylesheet = Array.from(options.doc.styleSheets).find((s) => { return s.href === (n as HTMLLinkElement).href; }); let cssText: string | null = null; @@ -678,7 +647,7 @@ function serializeElementNode( (n as HTMLStyleElement).sheet as CSSStyleSheet, ); if (cssText) { - attributes._cssText = absoluteToStylesheet(cssText, getHref(doc)); + attributes._cssText = absoluteToStylesheet(cssText, getHref(options.doc)); } } // form fields @@ -697,15 +666,19 @@ function serializeElementNode( type: getInputType(n), tagName, value, - maskInputOptions, - maskInputFn, + maskInputOptions: options.maskInputOptions, + maskInputFn: options.maskInputFn, }); } else if (checked) { attributes.checked = checked; } } if (tagName === 'option') { - if ((n as HTMLOptionElement).selected && !maskInputOptions['select']) { + if ( + (n as HTMLOptionElement).selected && + options.maskInputOptions && + !options.maskInputOptions['select'] + ) { attributes.selected = true; } else { // ignore the html attribute (which corresponds to DOM (n as HTMLOptionElement).defaultSelected) @@ -714,29 +687,29 @@ function serializeElementNode( } } // canvas image data - if (tagName === 'canvas' && recordCanvas) { + if (tagName === 'canvas' && options.recordCanvas) { if ((n as ICanvas).__context === '2d') { // only record this on 2d canvas if (!is2DCanvasBlank(n as HTMLCanvasElement)) { attributes.rr_dataURL = (n as HTMLCanvasElement).toDataURL( - dataURLOptions.type, - dataURLOptions.quality, + options.dataURLOptions?.type, + options.dataURLOptions?.quality, ); } } else if (!('__context' in n)) { // context is unknown, better not call getContext to trigger it const canvasDataURL = (n as HTMLCanvasElement).toDataURL( - dataURLOptions.type, - dataURLOptions.quality, + options.dataURLOptions?.type, + options.dataURLOptions?.quality, ); // create blank canvas of same dimensions - const blankCanvas = doc.createElement('canvas'); + const blankCanvas = options.doc.createElement('canvas'); blankCanvas.width = (n as HTMLCanvasElement).width; blankCanvas.height = (n as HTMLCanvasElement).height; const blankCanvasDataURL = blankCanvas.toDataURL( - dataURLOptions.type, - dataURLOptions.quality, + options.dataURLOptions?.type, + options.dataURLOptions?.quality, ); // no need to save dataURL if it's the same as blank canvas @@ -746,9 +719,9 @@ function serializeElementNode( } } // save image offline - if (tagName === 'img' && inlineImages) { + if (tagName === 'img' && options.inlineImages) { if (!canvasService) { - canvasService = doc.createElement('canvas'); + canvasService = options.doc.createElement('canvas'); canvasCtx = canvasService.getContext('2d'); } const image = n as HTMLImageElement; @@ -762,8 +735,8 @@ function serializeElementNode( canvasService!.height = image.naturalHeight; canvasCtx!.drawImage(image, 0, 0); attributes.rr_dataURL = canvasService!.toDataURL( - dataURLOptions.type, - dataURLOptions.quality, + options.dataURLOptions?.type, + options.dataURLOptions?.quality, ); } catch (err) { if (image.crossOrigin !== 'anonymous') { @@ -801,7 +774,7 @@ function serializeElementNode( mediaAttributes.rr_mediaVolume = (n as HTMLMediaElement).volume; } // Scroll - if (!newlyAddedElement) { + if (!options.newlyAddedElement) { // `scrollTop` and `scrollLeft` are expensive calls because they trigger reflow. // Since `scrollTop` & `scrollLeft` are always 0 when an element is added to the DOM. // And scrolls also get picked up by rrweb's ScrollObserver @@ -814,6 +787,11 @@ function serializeElementNode( } } // block element + const needBlock = _isBlockedElement( + n, + options.blockClass, + options.blockSelector, + ); if (needBlock) { const { width, height } = n.getBoundingClientRect(); attributes = { @@ -823,7 +801,10 @@ function serializeElementNode( }; } // iframe - if (tagName === 'iframe' && !keepIframeSrcFn(attributes.src as string)) { + if ( + tagName === 'iframe' && + !options.keepIframeSrcFn(attributes.src as string) + ) { if (!(n as HTMLIFrameElement).contentDocument) { // we can't record it directly as we can't see into it // preserve the src attribute so a decision can be taken at replay time @@ -832,13 +813,6 @@ function serializeElementNode( delete attributes.src; // prevent auto loading } - let isCustomElement: true | undefined; - try { - if (customElements.get(tagName)) isCustomElement = true; - } catch (e) { - // In case old browsers don't support customElements - } - return { type: NodeType.Element, tagName, @@ -846,8 +820,11 @@ function serializeElementNode( childNodes: [], isSVG: isSVGElement(n as Element) || undefined, needBlock, - rootId, - isCustom: isCustomElement, + rootId: options.rootId, + isCustom: + (typeof customElements !== 'undefined' && + !!customElements.get(tagName)) || + undefined, }; } @@ -953,67 +930,73 @@ function slimDOMExcluded( return false; } +const DEFAULT_KEEP_IFRAME_SRC = () => false; +const DEFAULT_DATA_URL_OPTIONS = {}; + export function serializeNodeWithId( n: Node, options: { - doc: Document; - mirror: Mirror; blockClass: string | RegExp; blockSelector: string | null; + dataURLOptions: DataURLOptions | undefined; + doc: Document; + iframeLoadTimeout: number | undefined; + inlineImages: boolean | undefined; + inlineStylesheet: boolean; + keepIframeSrcFn: KeepIframeSrcFn | undefined; + maskInputFn: MaskInputFn | undefined; + maskInputOptions: MaskInputOptions | undefined; maskTextClass: string | RegExp; + maskTextFn: MaskTextFn | undefined; maskTextSelector: string | null; + mirror: Mirror; + needsMask: boolean | undefined; + newlyAddedElement: boolean | undefined; + onIframeLoad: + | (( + iframeNode: HTMLIFrameElement, + node: serializedElementNodeWithId, + ) => unknown) + | undefined; + onSerialize: ((n: Node) => unknown) | undefined; + onStylesheetLoad: + | (( + linkNode: HTMLLinkElement, + node: serializedElementNodeWithId, + ) => unknown) + | undefined; + preserveWhiteSpace: boolean | undefined; + recordCanvas: boolean | undefined; skipChild: boolean; - inlineStylesheet: boolean; - newlyAddedElement?: boolean; - maskInputOptions?: MaskInputOptions; - needsMask?: boolean; - maskTextFn: MaskTextFn | undefined; - maskInputFn: MaskInputFn | undefined; slimDOMOptions: SlimDOMOptions; - dataURLOptions?: DataURLOptions; - keepIframeSrcFn?: KeepIframeSrcFn; - inlineImages?: boolean; - recordCanvas?: boolean; - preserveWhiteSpace?: boolean; - onSerialize?: (n: Node) => unknown; - onIframeLoad?: ( - iframeNode: HTMLIFrameElement, - node: serializedElementNodeWithId, - ) => unknown; - iframeLoadTimeout?: number; - onStylesheetLoad?: ( - linkNode: HTMLLinkElement, - node: serializedElementNodeWithId, - ) => unknown; - stylesheetLoadTimeout?: number; + stylesheetLoadTimeout: number | undefined; }, ): serializedNodeWithId | null { const { - doc, - mirror, blockClass, blockSelector, - maskTextClass, - maskTextSelector, - skipChild = false, + dataURLOptions = DEFAULT_DATA_URL_OPTIONS, + doc, + iframeLoadTimeout = 5000, + inlineImages = false, inlineStylesheet = true, - maskInputOptions = {}, - maskTextFn, + keepIframeSrcFn = DEFAULT_KEEP_IFRAME_SRC, maskInputFn, - slimDOMOptions, - dataURLOptions = {}, - inlineImages = false, - recordCanvas = false, - onSerialize, + maskInputOptions, + maskTextClass, + maskTextFn, + maskTextSelector, + mirror, + newlyAddedElement = false, onIframeLoad, - iframeLoadTimeout = 5000, + onSerialize, onStylesheetLoad, + recordCanvas = false, + skipChild = false, + slimDOMOptions, stylesheetLoadTimeout = 5000, - keepIframeSrcFn = () => false, - newlyAddedElement = false, } = options; - let { needsMask } = options; - let { preserveWhiteSpace = true } = options; + let { needsMask, preserveWhiteSpace = true } = options; if (!needsMask) { // perf: if needsMask = true, children won't also need to check @@ -1027,20 +1010,20 @@ export function serializeNodeWithId( } const _serializedNode = serializeNode(n, { - doc, - mirror, blockClass, blockSelector, - needsMask, - inlineStylesheet, - maskInputOptions, - maskTextFn, - maskInputFn, dataURLOptions, + doc, inlineImages, - recordCanvas, + inlineStylesheet, keepIframeSrcFn, + maskInputFn, + maskInputOptions, + maskTextFn, + mirror, + needsMask, newlyAddedElement, + recordCanvas, }); if (!_serializedNode) { // TODO: dev only @@ -1098,29 +1081,30 @@ export function serializeNodeWithId( preserveWhiteSpace = false; } const bypassOptions = { - doc, - mirror, blockClass, blockSelector, - needsMask, - maskTextClass, - maskTextSelector, - skipChild, + dataURLOptions, + doc, + iframeLoadTimeout, + inlineImages, inlineStylesheet, + keepIframeSrcFn, + maskInputFn, maskInputOptions, + maskTextClass, maskTextFn, - maskInputFn, - slimDOMOptions, - dataURLOptions, - inlineImages, - recordCanvas, - preserveWhiteSpace, - onSerialize, + maskTextSelector, + mirror, + needsMask, + newlyAddedElement: undefined, onIframeLoad, - iframeLoadTimeout, + onSerialize, onStylesheetLoad, + preserveWhiteSpace, + recordCanvas, + skipChild, + slimDOMOptions, stylesheetLoadTimeout, - keepIframeSrcFn, }; if ( @@ -1130,8 +1114,11 @@ export function serializeNodeWithId( ) { // value parameter in DOM reflects the correct value, so ignore childNode } else { - for (const childN of Array.from(n.childNodes)) { - const serializedChildNode = serializeNodeWithId(childN, bypassOptions); + for (let i = 0; i < n.childNodes.length; i++) { + const serializedChildNode = serializeNodeWithId( + n.childNodes[i], + bypassOptions, + ); if (serializedChildNode) { serializedNode.childNodes.push(serializedChildNode); } @@ -1139,8 +1126,11 @@ export function serializeNodeWithId( } if (isElement(n) && n.shadowRoot) { - for (const childN of Array.from(n.shadowRoot.childNodes)) { - const serializedChildNode = serializeNodeWithId(childN, bypassOptions); + for (let i = 0; i < n.shadowRoot.childNodes.length; i++) { + const serializedChildNode = serializeNodeWithId( + n.shadowRoot.childNodes[i], + bypassOptions, + ); if (serializedChildNode) { isNativeShadowDom(n.shadowRoot) && (serializedChildNode.isShadow = true); @@ -1168,29 +1158,30 @@ export function serializeNodeWithId( const iframeDoc = (n as HTMLIFrameElement).contentDocument; if (iframeDoc && onIframeLoad) { const serializedIframeNode = serializeNodeWithId(iframeDoc, { - doc: iframeDoc, - mirror, blockClass, blockSelector, - needsMask, - maskTextClass, - maskTextSelector, - skipChild: false, + dataURLOptions, + doc: iframeDoc, + iframeLoadTimeout, + inlineImages, inlineStylesheet, + keepIframeSrcFn, + maskInputFn, maskInputOptions, + maskTextClass, maskTextFn, - maskInputFn, - slimDOMOptions, - dataURLOptions, - inlineImages, - recordCanvas, - preserveWhiteSpace, - onSerialize, + maskTextSelector, + mirror, + needsMask, + newlyAddedElement: undefined, onIframeLoad, - iframeLoadTimeout, + onSerialize, onStylesheetLoad, + preserveWhiteSpace, + recordCanvas, + skipChild: false, + slimDOMOptions, stylesheetLoadTimeout, - keepIframeSrcFn, }); if (serializedIframeNode) { @@ -1220,29 +1211,30 @@ export function serializeNodeWithId( () => { if (onStylesheetLoad) { const serializedLinkNode = serializeNodeWithId(n, { - doc, - mirror, blockClass, blockSelector, - needsMask, - maskTextClass, - maskTextSelector, - skipChild: false, + dataURLOptions, + doc, + iframeLoadTimeout, + inlineImages, inlineStylesheet, + keepIframeSrcFn, + maskInputFn, maskInputOptions, + maskTextClass, maskTextFn, - maskInputFn, - slimDOMOptions, - dataURLOptions, - inlineImages, - recordCanvas, - preserveWhiteSpace, - onSerialize, + maskTextSelector, + mirror, + needsMask, + newlyAddedElement: undefined, onIframeLoad, - iframeLoadTimeout, + onSerialize, onStylesheetLoad, + preserveWhiteSpace, + recordCanvas, + skipChild: false, + slimDOMOptions, stylesheetLoadTimeout, - keepIframeSrcFn, }); if (serializedLinkNode) { @@ -1262,82 +1254,45 @@ export function serializeNodeWithId( function snapshot( n: Document, - options?: { - mirror?: Mirror; + options: { blockClass?: string | RegExp; blockSelector?: string | null; - maskTextClass?: string | RegExp; - maskTextSelector?: string | null; + dataURLOptions?: DataURLOptions; + inlineImages?: boolean; inlineStylesheet?: boolean; maskAllInputs?: boolean | MaskInputOptions; - maskTextFn?: MaskTextFn; maskInputFn?: MaskInputFn; - slimDOM?: 'all' | boolean | SlimDOMOptions; - dataURLOptions?: DataURLOptions; - inlineImages?: boolean; - recordCanvas?: boolean; - preserveWhiteSpace?: boolean; - onSerialize?: (n: Node) => unknown; + maskTextClass?: string | RegExp; + maskTextFn?: MaskTextFn; + maskTextSelector?: string | null; + mirror?: Mirror; onIframeLoad?: ( iframeNode: HTMLIFrameElement, node: serializedElementNodeWithId, ) => unknown; - iframeLoadTimeout?: number; + onSerialize?: (n: Node) => unknown; onStylesheetLoad?: ( linkNode: HTMLLinkElement, node: serializedElementNodeWithId, ) => unknown; + preserveWhiteSpace?: boolean; + recordCanvas?: boolean; + slimDOM?: 'all' | boolean | SlimDOMOptions; + iframeLoadTimeout?: number; stylesheetLoadTimeout?: number; keepIframeSrcFn?: KeepIframeSrcFn; }, ): serializedNodeWithId | null { - const { - mirror = new Mirror(), - blockClass = 'rr-block', - blockSelector = null, - maskTextClass = 'rr-mask', - maskTextSelector = null, - inlineStylesheet = true, - inlineImages = false, - recordCanvas = false, - maskAllInputs = false, - maskTextFn, - maskInputFn, - slimDOM = false, - dataURLOptions, - preserveWhiteSpace, - onSerialize, - onIframeLoad, - iframeLoadTimeout, - onStylesheetLoad, - stylesheetLoadTimeout, - keepIframeSrcFn = () => false, - } = options || {}; + const slimDOM = options.slimDOM ?? false; + const maskAllInputs = options.maskAllInputs ?? false; + const maskInputOptions: MaskInputOptions = maskAllInputs === true - ? { - color: true, - date: true, - 'datetime-local': true, - email: true, - month: true, - number: true, - range: true, - search: true, - tel: true, - text: true, - time: true, - url: true, - week: true, - textarea: true, - select: true, - password: true, - } + ? MASK_ALL_INPUT_SETTINGS : maskAllInputs === false - ? { - password: true, - } + ? MASK_ONLY_PASSWORD_SETTINGS : maskAllInputs; + const slimDOMOptions: SlimDOMOptions = slimDOM === true || slimDOM === 'all' ? // if true: set of sensible options that should not throw away any information @@ -1356,33 +1311,58 @@ function snapshot( : slimDOM === false ? {} : slimDOM; + return serializeNodeWithId(n, { + blockClass: options.blockClass ?? 'rr-block', + blockSelector: options.blockSelector ?? null, + dataURLOptions: options.dataURLOptions, doc: n, - mirror, - blockClass, - blockSelector, - maskTextClass, - maskTextSelector, - skipChild: false, - inlineStylesheet, + iframeLoadTimeout: options.iframeLoadTimeout, + inlineImages: options.inlineImages ?? false, + inlineStylesheet: options.inlineStylesheet ?? true, + keepIframeSrcFn: options.keepIframeSrcFn, + maskInputFn: options.maskInputFn, maskInputOptions, - maskTextFn, - maskInputFn, - slimDOMOptions, - dataURLOptions, - inlineImages, - recordCanvas, - preserveWhiteSpace, - onSerialize, - onIframeLoad, - iframeLoadTimeout, - onStylesheetLoad, - stylesheetLoadTimeout, - keepIframeSrcFn, + maskTextClass: options.maskTextClass ?? 'rr-mask', + maskTextFn: options.maskTextFn, + maskTextSelector: options.maskTextSelector ?? null, + mirror: options.mirror ?? new Mirror(), + needsMask: undefined, newlyAddedElement: false, + onIframeLoad: options.onIframeLoad, + onSerialize: options.onSerialize, + onStylesheetLoad: options.onStylesheetLoad, + preserveWhiteSpace: options.preserveWhiteSpace, + recordCanvas: options.recordCanvas, + skipChild: false, + slimDOMOptions, + stylesheetLoadTimeout: options.stylesheetLoadTimeout, }); } +const MASK_ALL_INPUT_SETTINGS: MaskInputOptions = { + color: true, + date: true, + 'datetime-local': true, + email: true, + month: true, + number: true, + range: true, + search: true, + tel: true, + text: true, + time: true, + url: true, + week: true, + textarea: true, + select: true, + password: true, +}; + +const MASK_ONLY_PASSWORD_SETTINGS: MaskInputOptions = { + password: true, +}; + export function visitSnapshot( node: serializedNodeWithId, onVisit: (node: serializedNodeWithId) => unknown, diff --git a/packages/rrweb-snapshot/src/utils.ts b/packages/rrweb-snapshot/src/utils.ts index 13da20f0f5..44e5ad646c 100644 --- a/packages/rrweb-snapshot/src/utils.ts +++ b/packages/rrweb-snapshot/src/utils.ts @@ -221,7 +221,7 @@ export function maskInputValue({ maskInputFn, }: { element: HTMLElement; - maskInputOptions: MaskInputOptions; + maskInputOptions: MaskInputOptions | undefined; tagName: string; type: string | null; value: string | null; @@ -231,8 +231,9 @@ export function maskInputValue({ const actualType = type && toLowerCase(type); if ( - maskInputOptions[tagName.toLowerCase() as keyof MaskInputOptions] || - (actualType && maskInputOptions[actualType as keyof MaskInputOptions]) + maskInputOptions && + (maskInputOptions[tagName.toLowerCase() as keyof MaskInputOptions] || + (actualType && maskInputOptions[actualType as keyof MaskInputOptions])) ) { if (maskInputFn) { text = maskInputFn(text, element); diff --git a/packages/rrweb-snapshot/test/integration.test.ts b/packages/rrweb-snapshot/test/integration.test.ts index 23a19c1a29..208045b318 100644 --- a/packages/rrweb-snapshot/test/integration.test.ts +++ b/packages/rrweb-snapshot/test/integration.test.ts @@ -138,7 +138,7 @@ describe('integration tests', function (this: ISuite) { const rebuildHtml = ( (await page.evaluate(`${code} const x = new XMLSerializer(); - const snap = rrwebSnapshot.snapshot(document); + const snap = rrwebSnapshot.snapshot(document, {}); let out = x.serializeToString(rrwebSnapshot.rebuild(snap, { doc: document })); if (document.querySelector('html').getAttribute('xmlns') !== 'http://www.w3.org/1999/xhtml') { // this is just an artefact of serializeToString @@ -180,7 +180,7 @@ describe('integration tests', function (this: ISuite) { `pre-check: images will be rendered ~326px high in BackCompat mode, and ~588px in CSS1Compat mode; getting: ${renderedHeight}px`, ); const rebuildRenderedHeight = await page.evaluate(`${code} -const snap = rrwebSnapshot.snapshot(document); +const snap = rrwebSnapshot.snapshot(document, {}); const iframe = document.createElement('iframe'); iframe.setAttribute('width', document.body.clientWidth) iframe.setAttribute('height', document.body.clientHeight) @@ -422,7 +422,7 @@ describe('iframe integration tests', function (this: ISuite) { }); const snapshotResult = JSON.stringify( await page.evaluate(`${code}; - rrwebSnapshot.snapshot(document); + rrwebSnapshot.snapshot(document, {}); `), null, 2, @@ -465,7 +465,7 @@ describe('shadow DOM integration tests', function (this: ISuite) { }); const snapshotResult = JSON.stringify( await page.evaluate(`${code}; - rrwebSnapshot.snapshot(document); + rrwebSnapshot.snapshot(document, {}); `), null, 2, diff --git a/packages/rrweb/src/record/index.ts b/packages/rrweb/src/record/index.ts index 36300d0595..5e6fa1c4f5 100644 --- a/packages/rrweb/src/record/index.ts +++ b/packages/rrweb/src/record/index.ts @@ -375,19 +375,19 @@ function record( mutationBuffers.forEach((buf) => buf.lock()); // don't allow any mirror modifications during snapshotting const node = snapshot(document, { - mirror, blockClass, blockSelector, - maskTextClass, - maskTextSelector, + dataURLOptions, + inlineImages, inlineStylesheet, maskAllInputs: maskInputOptions, - maskTextFn, maskInputFn, - slimDOM: slimDOMOptions, - dataURLOptions, + maskTextClass, + maskTextFn, + maskTextSelector, + mirror, recordCanvas, - inlineImages, + slimDOM: slimDOMOptions, onSerialize: (n) => { if (isSerializedIframe(n, mirror)) { iframeManager.addIframe(n as HTMLIFrameElement); diff --git a/packages/rrweb/src/record/mutation.ts b/packages/rrweb/src/record/mutation.ts index a798441969..ec5109c929 100644 --- a/packages/rrweb/src/record/mutation.ts +++ b/packages/rrweb/src/record/mutation.ts @@ -300,22 +300,27 @@ export default class MutationBuffer { return addList.addNode(n); } const sn = serializeNodeWithId(n, { - doc: this.doc, - mirror: this.mirror, blockClass: this.blockClass, blockSelector: this.blockSelector, - maskTextClass: this.maskTextClass, - maskTextSelector: this.maskTextSelector, - skipChild: true, - newlyAddedElement: true, + dataURLOptions: this.dataURLOptions, + doc: this.doc, + iframeLoadTimeout: undefined, + inlineImages: this.inlineImages, inlineStylesheet: this.inlineStylesheet, + keepIframeSrcFn: undefined, + maskInputFn: this.maskInputFn, maskInputOptions: this.maskInputOptions, + maskTextClass: this.maskTextClass, maskTextFn: this.maskTextFn, - maskInputFn: this.maskInputFn, - slimDOMOptions: this.slimDOMOptions, - dataURLOptions: this.dataURLOptions, + maskTextSelector: this.maskTextSelector, + mirror: this.mirror, + needsMask: undefined, + newlyAddedElement: true, + preserveWhiteSpace: undefined, recordCanvas: this.recordCanvas, - inlineImages: this.inlineImages, + skipChild: true, + slimDOMOptions: this.slimDOMOptions, + stylesheetLoadTimeout: undefined, onSerialize: (currentN) => { if (isSerializedIframe(currentN, this.mirror)) { this.iframeManager.addIframe(currentN as HTMLIFrameElement);