{"version":3,"file":"utils.cjs","sources":["../src/index.ts"],"sourcesContent":["type PrototypeOwner = Node | ShadowRoot | MutationObserver | Element;\ntype TypeofPrototypeOwner =\n  | typeof Node\n  | typeof ShadowRoot\n  | typeof MutationObserver\n  | typeof Element;\n\ntype BasePrototypeCache = {\n  Node: typeof Node.prototype;\n  ShadowRoot: typeof ShadowRoot.prototype;\n  MutationObserver: typeof MutationObserver.prototype;\n  Element: typeof Element.prototype;\n};\n\nconst testableAccessors = {\n  Node: [\n    'childNodes',\n    'parentNode',\n    'parentElement',\n    'textContent',\n    'ownerDocument',\n  ] as const,\n  ShadowRoot: ['host', 'styleSheets'] as const,\n  Element: ['shadowRoot', 'querySelector', 'querySelectorAll'] as const,\n  MutationObserver: [] as const,\n} as const;\n\nconst testableMethods = {\n  Node: ['contains', 'getRootNode'] as const,\n  ShadowRoot: ['getSelection'],\n  Element: [],\n  MutationObserver: ['constructor'],\n} as const;\n\nconst untaintedBasePrototype: Partial<BasePrototypeCache> = {};\n\n/*\n When angular patches things - particularly the MutationObserver -\n they pass the `isNativeFunction` check\n That then causes performance issues\n because Angular's change detection\n doesn't like sharing a mutation observer\n Checking for the presence of the Zone object\n on global is a good-enough proxy for Angular\n to cover most cases\n (you can configure zone.js to have a different name\n  on the global object and should then manually run rrweb\n  outside the Zone)\n */\nexport const isAngularZonePresent = (): boolean => {\n  return !!(globalThis as { Zone?: unknown }).Zone;\n};\n\nexport function getUntaintedPrototype<T extends keyof BasePrototypeCache>(\n  key: T,\n): BasePrototypeCache[T] {\n  if (untaintedBasePrototype[key])\n    return untaintedBasePrototype[key] as BasePrototypeCache[T];\n\n  const defaultObj = globalThis[key] as TypeofPrototypeOwner;\n  const defaultPrototype = defaultObj.prototype as BasePrototypeCache[T];\n\n  // use list of testable accessors to check if the prototype is tainted\n  const accessorNames =\n    key in testableAccessors ? testableAccessors[key] : undefined;\n  const isUntaintedAccessors = Boolean(\n    accessorNames &&\n      // @ts-expect-error 2345\n      accessorNames.every((accessor: keyof typeof defaultPrototype) =>\n        Boolean(\n          Object.getOwnPropertyDescriptor(defaultPrototype, accessor)\n            ?.get?.toString()\n            .includes('[native code]'),\n        ),\n      ),\n  );\n\n  const methodNames = key in testableMethods ? testableMethods[key] : undefined;\n  const isUntaintedMethods = Boolean(\n    methodNames &&\n      methodNames.every(\n        // @ts-expect-error 2345\n        (method: keyof typeof defaultPrototype) =>\n          typeof defaultPrototype[method] === 'function' &&\n          defaultPrototype[method]?.toString().includes('[native code]'),\n      ),\n  );\n\n  if (isUntaintedAccessors && isUntaintedMethods && !isAngularZonePresent()) {\n    untaintedBasePrototype[key] = defaultObj.prototype as BasePrototypeCache[T];\n    return defaultObj.prototype as BasePrototypeCache[T];\n  }\n\n  try {\n    const iframeEl = document.createElement('iframe');\n    document.body.appendChild(iframeEl);\n    const win = iframeEl.contentWindow;\n    if (!win) return defaultObj.prototype as BasePrototypeCache[T];\n\n    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n    const untaintedObject = (win as any)[key]\n      .prototype as BasePrototypeCache[T];\n    // cleanup\n    document.body.removeChild(iframeEl);\n\n    if (!untaintedObject) return defaultPrototype;\n\n    return (untaintedBasePrototype[key] = untaintedObject);\n  } catch {\n    return defaultPrototype;\n  }\n}\n\nconst untaintedAccessorCache: Record<\n  string,\n  (this: PrototypeOwner, ...args: unknown[]) => unknown\n> = {};\n\nexport function getUntaintedAccessor<\n  K extends keyof BasePrototypeCache,\n  T extends keyof BasePrototypeCache[K],\n>(\n  key: K,\n  instance: BasePrototypeCache[K],\n  accessor: T,\n): BasePrototypeCache[K][T] {\n  const cacheKey = `${key}.${String(accessor)}`;\n  if (untaintedAccessorCache[cacheKey])\n    return untaintedAccessorCache[cacheKey].call(\n      instance,\n    ) as BasePrototypeCache[K][T];\n\n  const untaintedPrototype = getUntaintedPrototype(key);\n  // eslint-disable-next-line @typescript-eslint/unbound-method\n  const untaintedAccessor = Object.getOwnPropertyDescriptor(\n    untaintedPrototype,\n    accessor,\n  )?.get;\n\n  if (!untaintedAccessor) return instance[accessor];\n\n  untaintedAccessorCache[cacheKey] = untaintedAccessor;\n\n  return untaintedAccessor.call(instance) as BasePrototypeCache[K][T];\n}\n\ntype BaseMethod<K extends keyof BasePrototypeCache> = (\n  this: BasePrototypeCache[K],\n  ...args: unknown[]\n) => unknown;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst untaintedMethodCache: Record<string, BaseMethod<any>> = {};\nexport function getUntaintedMethod<\n  K extends keyof BasePrototypeCache,\n  T extends keyof BasePrototypeCache[K],\n>(\n  key: K,\n  instance: BasePrototypeCache[K],\n  method: T,\n): BasePrototypeCache[K][T] {\n  const cacheKey = `${key}.${String(method)}`;\n  if (untaintedMethodCache[cacheKey])\n    return untaintedMethodCache[cacheKey].bind(\n      instance,\n    ) as BasePrototypeCache[K][T];\n\n  const untaintedPrototype = getUntaintedPrototype(key);\n  const untaintedMethod = untaintedPrototype[method];\n\n  if (typeof untaintedMethod !== 'function') return instance[method];\n\n  untaintedMethodCache[cacheKey] = untaintedMethod as BaseMethod<K>;\n\n  return untaintedMethod.bind(instance) as BasePrototypeCache[K][T];\n}\n\nexport function ownerDocument(n: Node): Document | null {\n  return getUntaintedAccessor('Node', n, 'ownerDocument');\n}\n\nexport function childNodes(n: Node): NodeListOf<Node> {\n  return getUntaintedAccessor('Node', n, 'childNodes');\n}\n\nexport function parentNode(n: Node): ParentNode | null {\n  return getUntaintedAccessor('Node', n, 'parentNode');\n}\n\nexport function parentElement(n: Node): HTMLElement | null {\n  return getUntaintedAccessor('Node', n, 'parentElement');\n}\n\nexport function textContent(n: Node): string | null {\n  return getUntaintedAccessor('Node', n, 'textContent');\n}\n\nexport function contains(n: Node, other: Node): boolean {\n  return getUntaintedMethod('Node', n, 'contains')(other);\n}\n\nexport function getRootNode(n: Node): Node {\n  return getUntaintedMethod('Node', n, 'getRootNode')();\n}\n\nexport function host(n: ShadowRoot): Element | null {\n  if (!n || !('host' in n)) return null;\n  return getUntaintedAccessor('ShadowRoot', n, 'host');\n}\n\nexport function styleSheets(n: ShadowRoot): StyleSheetList {\n  return n.styleSheets;\n}\n\nexport function shadowRoot(n: Node): ShadowRoot | null {\n  if (!n || !('shadowRoot' in n)) return null;\n  return getUntaintedAccessor('Element', n as Element, 'shadowRoot');\n}\n\nexport function querySelector(n: Element, selectors: string): Element | null {\n  return getUntaintedAccessor('Element', n, 'querySelector')(selectors);\n}\n\nexport function querySelectorAll(\n  n: Element,\n  selectors: string,\n): NodeListOf<Element> {\n  return getUntaintedAccessor('Element', n, 'querySelectorAll')(selectors);\n}\n\nexport function mutationObserverCtor(): (typeof MutationObserver)['prototype']['constructor'] {\n  return getUntaintedPrototype('MutationObserver').constructor;\n}\n\n// copy from https://github.com/getsentry/sentry-javascript/blob/b2109071975af8bf0316d3b5b38f519bdaf5dc15/packages/utils/src/object.ts\nexport function patch(\n  source: { [key: string]: any },\n  name: string,\n  replacement: (...args: unknown[]) => unknown,\n): () => void {\n  try {\n    if (!(name in source)) {\n      return () => {\n        //\n      };\n    }\n\n    const original = source[name] as () => unknown;\n    const wrapped = replacement(original);\n\n    // Make sure it's a function first, as we need to attach an empty prototype for `defineProperties` to work\n    // otherwise it'll throw \"TypeError: Object.defineProperties called on non-object\"\n    if (typeof wrapped === 'function') {\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n      wrapped.prototype = wrapped.prototype || {};\n      Object.defineProperties(wrapped, {\n        __rrweb_original__: {\n          enumerable: false,\n          value: original,\n        },\n      });\n    }\n\n    source[name] = wrapped;\n\n    return () => {\n      source[name] = original;\n    };\n  } catch {\n    return () => {\n      //\n    };\n    // This can throw if multiple fill happens on a global object like XMLHttpRequest\n    // Fixes https://github.com/getsentry/sentry-javascript/issues/2043\n  }\n}\n\nexport default {\n  ownerDocument,\n  childNodes,\n  parentNode,\n  parentElement,\n  textContent,\n  contains,\n  getRootNode,\n  host,\n  styleSheets,\n  shadowRoot,\n  querySelector,\n  querySelectorAll,\n  mutationObserver: mutationObserverCtor,\n  patch,\n};\n"],"names":[],"mappings":"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"}