From d7c72bff0724b46a6fa94af455220626a27104fe Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Fri, 2 Jun 2023 12:16:37 +0200 Subject: [PATCH] fix: Ensure attributes are lowercased when checking (#1183) * fix: Ensure attributes are lowercased when checking * add changeset * fix to lower case * Apply formatting changes --------- Co-authored-by: mydea --- .changeset/lovely-students-boil.md | 6 ++++++ packages/rrweb-snapshot/src/snapshot.ts | 11 ++++++----- packages/rrweb-snapshot/src/utils.ts | 8 ++++++-- packages/rrweb/src/record/mutation.ts | 5 +++-- packages/rrweb/src/record/observer.ts | 8 ++++++-- packages/rrweb/src/replay/index.ts | 3 ++- 6 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 .changeset/lovely-students-boil.md diff --git a/.changeset/lovely-students-boil.md b/.changeset/lovely-students-boil.md new file mode 100644 index 0000000000..9c710bf1c6 --- /dev/null +++ b/.changeset/lovely-students-boil.md @@ -0,0 +1,6 @@ +--- +'rrweb-snapshot': patch +'rrweb': patch +--- + +fix: Ensure attributes are lowercased when checking diff --git a/packages/rrweb-snapshot/src/snapshot.ts b/packages/rrweb-snapshot/src/snapshot.ts index 0eeb289b4f..51f76f46f8 100644 --- a/packages/rrweb-snapshot/src/snapshot.ts +++ b/packages/rrweb-snapshot/src/snapshot.ts @@ -21,6 +21,7 @@ import { isNativeShadowDom, getCssRulesString, getInputType, + toLowerCase, } from './utils'; let _id = 1; @@ -32,12 +33,12 @@ export function genId(): number { return _id++; } -function getValidTagName(element: HTMLElement): string { +function getValidTagName(element: HTMLElement): Lowercase { if (element instanceof HTMLFormElement) { return 'form'; } - const processedTagName = element.tagName.toLowerCase().trim(); + const processedTagName = toLowerCase(element.tagName); if (tagNameRegex.test(processedTagName)) { // if the tag name is odd and we cannot extract @@ -222,8 +223,8 @@ function getHref() { export function transformAttribute( doc: Document, - tagName: string, - name: string, + tagName: Lowercase, + name: Lowercase, value: string | null, ): string | null { if (!value) { @@ -638,7 +639,7 @@ function serializeElementNode( attributes[attr.name] = transformAttribute( doc, tagName, - attr.name, + toLowerCase(attr.name), attr.value, ); } diff --git a/packages/rrweb-snapshot/src/utils.ts b/packages/rrweb-snapshot/src/utils.ts index c2f85e6e08..b124680b57 100644 --- a/packages/rrweb-snapshot/src/utils.ts +++ b/packages/rrweb-snapshot/src/utils.ts @@ -169,7 +169,7 @@ export function maskInputValue({ maskInputFn?: MaskInputFn; }): string { let text = value || ''; - const actualType = type && type.toLowerCase(); + const actualType = type && toLowerCase(type); if ( maskInputOptions[tagName.toLowerCase() as keyof MaskInputOptions] || @@ -184,6 +184,10 @@ export function maskInputValue({ return text; } +export function toLowerCase(str: T): Lowercase { + return str.toLowerCase() as unknown as Lowercase; +} + const ORIGINAL_ATTRIBUTE_NAME = '__rrweb_original__'; type PatchedGetImageData = { [ORIGINAL_ATTRIBUTE_NAME]: CanvasImageData['getImageData']; @@ -265,6 +269,6 @@ export function getInputType(element: HTMLElement): Lowercase | null { ? 'password' : type ? // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - (type.toLowerCase() as Lowercase) + toLowerCase(type) : null; } diff --git a/packages/rrweb/src/record/mutation.ts b/packages/rrweb/src/record/mutation.ts index f352424b5f..39a6107635 100644 --- a/packages/rrweb/src/record/mutation.ts +++ b/packages/rrweb/src/record/mutation.ts @@ -9,6 +9,7 @@ import { Mirror, isNativeShadowDom, getInputType, + toLowerCase, } from 'rrweb-snapshot'; import type { observerParam, MutationBufferParam } from '../types'; import type { @@ -597,8 +598,8 @@ export default class MutationBuffer { // overwrite attribute if the mutations was triggered in same time item.attributes[attributeName] = transformAttribute( this.doc, - target.tagName, - attributeName, + toLowerCase(target.tagName), + toLowerCase(attributeName), value, ); } diff --git a/packages/rrweb/src/record/observer.ts b/packages/rrweb/src/record/observer.ts index afd68f1864..754f92400b 100644 --- a/packages/rrweb/src/record/observer.ts +++ b/packages/rrweb/src/record/observer.ts @@ -3,6 +3,7 @@ import { maskInputValue, Mirror, getInputType, + toLowerCase, } from 'rrweb-snapshot'; import type { FontFaceSet } from 'css-font-loading-module'; import { @@ -309,13 +310,16 @@ function initMouseInteractionObserver({ disableMap[key] !== false, ) .forEach((eventKey: keyof typeof MouseInteractions) => { - let eventName = eventKey.toLowerCase(); + let eventName = toLowerCase(eventKey); const handler = getHandler(eventKey); if (window.PointerEvent) { switch (MouseInteractions[eventKey]) { case MouseInteractions.MouseDown: case MouseInteractions.MouseUp: - eventName = eventName.replace('mouse', 'pointer'); + eventName = eventName.replace( + 'mouse', + 'pointer', + ) as unknown as typeof eventName; break; case MouseInteractions.TouchStart: case MouseInteractions.TouchEnd: diff --git a/packages/rrweb/src/replay/index.ts b/packages/rrweb/src/replay/index.ts index 1bc9c6a6a1..aac84c2783 100644 --- a/packages/rrweb/src/replay/index.ts +++ b/packages/rrweb/src/replay/index.ts @@ -8,6 +8,7 @@ import { createMirror, attributes, serializedElementNodeWithId, + toLowerCase, } from 'rrweb-snapshot'; import { RRDocument, @@ -1120,7 +1121,7 @@ export class Replayer { if (d.id === -1) { break; } - const event = new Event(MouseInteractions[d.type].toLowerCase()); + const event = new Event(toLowerCase(MouseInteractions[d.type])); const target = this.mirror.getNode(d.id); if (!target) { return this.debugNodeNotFound(d, d.id);