diff --git a/packages/core/src/tools/serialisation/sanitize.spec.ts b/packages/core/src/tools/serialisation/sanitize.spec.ts index 567bf89261..520190fc54 100644 --- a/packages/core/src/tools/serialisation/sanitize.spec.ts +++ b/packages/core/src/tools/serialisation/sanitize.spec.ts @@ -1,5 +1,5 @@ import { display } from '../display' -import { createNewEvent } from '../../../test' +import { registerCleanupTask } from '../../../test' import { sanitize } from './sanitize' describe('sanitize', () => { @@ -66,18 +66,34 @@ describe('sanitize', () => { expect(sanitize(node)).toBe('[HTMLDivElement]') }) - it('should serialize events', () => { - const event = createNewEvent('click') + it('should serialize events', (done) => { + const button = document.createElement('button') + document.body.appendChild(button) - expect(sanitize(event)).toEqual({ - isTrusted: false, + registerCleanupTask(() => { + document.body.removeChild(button) }) + + document.addEventListener( + 'click', + (event) => { + expect(sanitize(event)).toEqual({ + type: 'click', + isTrusted: false, + target: '[HTMLButtonElement]', + currentTarget: '[HTMLDocument]', + }) + done() + }, + { once: true } + ) + + button.click() }) it('should serialize errors as JSON.stringify does', () => { // Explicitely keep the previous behavior to avoid breaking changes in 4.x // Browsers have different behaviors: - // IE11 adds a description field // Safari IOS12 adds parts of the stack const error = new Error('My Error') expect(sanitize(error)).toEqual({ ...error }) @@ -114,6 +130,11 @@ describe('sanitize', () => { const obj = { a: null, b: undefined } expect(sanitize(obj)).toEqual({ a: null, b: undefined }) }) + + it('should handle regular expression', () => { + expect(sanitize(/[a-zA-Z0-9]+/g)).toEqual('[RegExp] /[a-zA-Z0-9]+/g') + expect(sanitize(new RegExp('[a-zA-Z0-9]+', 'g'))).toEqual('[RegExp] /[a-zA-Z0-9]+/g') + }) }) describe('arrays handling', () => { diff --git a/packages/core/src/tools/serialisation/sanitize.ts b/packages/core/src/tools/serialisation/sanitize.ts index a944b739f3..593ccb8c5a 100644 --- a/packages/core/src/tools/serialisation/sanitize.ts +++ b/packages/core/src/tools/serialisation/sanitize.ts @@ -16,6 +16,13 @@ type ContainerElementToProcess = { path: string } +type sanitizedEvent = { + type: string + isTrusted: boolean + currentTarget: string | null | undefined + target: string | null | undefined +} + // The maximum size of a single event is 256KiB. By default, we ensure that user-provided data // going through sanitize fits inside our events, while leaving room for other contexts, metadata, ... const SANITIZE_DEFAULT_MAX_CHARACTER_COUNT = 220 * ONE_KIBI_BYTE @@ -203,17 +210,15 @@ function sanitizePrimitivesAndFunctions(value: PrimitivesAndFunctions) { * LIMITATIONS * - If a class defines a toStringTag Symbol, it will fall in the catch-all method and prevent enumeration of properties. * To avoid this, a toJSON method can be defined. - * - IE11 does not return a distinct type for objects such as Map, WeakMap, ... These objects will pass through and their - * properties enumerated if any. - * */ -function sanitizeObjects(value: object) { +function sanitizeObjects(value: object): string | sanitizedEvent { try { - // Handle events - Keep a simple implementation to avoid breaking changes if (value instanceof Event) { - return { - isTrusted: value.isTrusted, - } + return sanitizeEvent(value) + } + + if (value instanceof RegExp) { + return `[RegExp] ${value.toString()}` } // Handle all remaining object types in a generic way @@ -229,6 +234,15 @@ function sanitizeObjects(value: object) { return '[Unserializable]' } +function sanitizeEvent(event: Event): sanitizedEvent { + return { + type: event.type, + isTrusted: event.isTrusted, + currentTarget: event.currentTarget ? (sanitizeObjects(event.currentTarget) as string) : null, + target: event.target ? (sanitizeObjects(event.target) as string) : null, + } +} + /** * Checks if a toJSON function exists and tries to execute it *