From bd9eb70629aeb5970f6188025f184ff4b0d5dcd4 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Fri, 6 Dec 2024 09:50:53 +0100 Subject: [PATCH] fix: angular wrapped mutationobserver detection (#1597) * fix: angular wrapped mutationobserver detection * add change set * fix * prettier * following posthog prod * manually prettier * Update .changeset/moody-experts-build.md Co-authored-by: Justin Halsall --------- Co-authored-by: Justin Halsall --- .changeset/moody-experts-build.md | 5 +++++ packages/utils/src/index.ts | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 .changeset/moody-experts-build.md diff --git a/.changeset/moody-experts-build.md b/.changeset/moody-experts-build.md new file mode 100644 index 00000000..fb2c399a --- /dev/null +++ b/.changeset/moody-experts-build.md @@ -0,0 +1,5 @@ +--- +"@rrweb/record": patch +--- + +Correctly detect when angular has wrapped mutation observer diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index b88d7f45..1cd267c0 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -28,6 +28,23 @@ const testableMethods = { const untaintedBasePrototype: Partial = {}; +/* + When angular patches things - particularly the MutationObserver - + they pass the `isNativeFunction` check + That then causes performance issues + because Angular's change detection + doesn't like sharing a mutation observer + Checking for the presence of the Zone object + on global is a good-enough proxy for Angular + to cover most cases + (you can configure zone.js to have a different name + on the global object and should then manually run rrweb + outside the Zone) + */ +export const isAngularZonePresent = (): boolean => { + return !!(globalThis as { Zone?: unknown }).Zone; +}; + export function getUntaintedPrototype( key: T, ): BasePrototypeCache[T] { @@ -63,7 +80,7 @@ export function getUntaintedPrototype( ), ); - if (isUntaintedAccessors && isUntaintedMethods) { + if (isUntaintedAccessors && isUntaintedMethods && !isAngularZonePresent()) { untaintedBasePrototype[key] = defaultObj.prototype as BasePrototypeCache[T]; return defaultObj.prototype as BasePrototypeCache[T]; }