{"version":3,"file":"view-hierarchy.js","sources":["../../../../../src/integrations/view-hierarchy.ts"],"sourcesContent":["import type { Attachment, Event, EventHint, ViewHierarchyData, ViewHierarchyWindow } from '@sentry/core/browser';\nimport { defineIntegration, getComponentName } from '@sentry/core/browser';\nimport { WINDOW } from '../helpers';\n\ninterface OnElementArgs {\n /**\n * The element being processed.\n */\n element: HTMLElement;\n /**\n * Lowercase tag name of the element.\n */\n tagName: string;\n /**\n * The component name of the element.\n */\n componentName?: string;\n\n /**\n * The current depth of the element in the view hierarchy. The root element will have a depth of 0.\n *\n * This allows you to limit the traversal depth for large DOM trees.\n */\n depth?: number;\n}\n\ninterface Options {\n /**\n * Whether to attach the view hierarchy to the event.\n *\n * Default: Always attach.\n */\n shouldAttach?: (event: Event, hint: EventHint) => boolean;\n\n /**\n * A function that returns the root element to start walking the DOM from.\n *\n * Default: `window.document.body`\n */\n rootElement?: () => HTMLElement | undefined;\n\n /**\n * Called for each HTMLElement as we walk the DOM.\n *\n * Return an object to include the element with any additional properties.\n * Return `skip` to exclude the element and its children.\n * Return `children` to skip the element but include its children.\n */\n onElement?: (prop: OnElementArgs) => Record | 'skip' | 'children';\n}\n\n/**\n * An integration to include a view hierarchy attachment which contains the DOM.\n */\nexport const viewHierarchyIntegration = defineIntegration((options: Options = {}) => {\n const skipHtmlTags = ['script'];\n\n /** Walk an element */\n function walk(element: HTMLElement, windows: ViewHierarchyWindow[], depth = 0): void {\n if (!element) {\n return;\n }\n\n // With Web Components, we need to walk into shadow DOMs\n const children = 'shadowRoot' in element && element.shadowRoot ? element.shadowRoot.children : element.children;\n\n for (const child of children) {\n if (!(child instanceof HTMLElement)) {\n continue;\n }\n\n const componentName = getComponentName(child, 1) || undefined;\n const tagName = child.tagName.toLowerCase();\n\n if (skipHtmlTags.includes(tagName)) {\n continue;\n }\n\n const result = options.onElement?.({ element: child, componentName, tagName, depth }) || {};\n\n if (result === 'skip') {\n continue;\n }\n\n // Skip this element but include its children\n if (result === 'children') {\n walk(child, windows, depth + 1);\n continue;\n }\n\n const { x, y, width, height } = child.getBoundingClientRect();\n\n const window: ViewHierarchyWindow = {\n identifier: (child.id || undefined) as string,\n type: componentName || tagName,\n visible: true,\n alpha: 1,\n height,\n width,\n x,\n y,\n ...result,\n };\n\n const children: ViewHierarchyWindow[] = [];\n window.children = children;\n\n // Recursively walk the children\n walk(child, window.children, depth + 1);\n\n windows.push(window);\n }\n }\n\n return {\n name: 'ViewHierarchy',\n processEvent: (event, hint) => {\n // only capture for error events\n if (event.type !== undefined || options.shouldAttach?.(event, hint) === false) {\n return event;\n }\n\n const root: ViewHierarchyData = {\n rendering_system: 'DOM',\n positioning: 'absolute',\n windows: [],\n };\n\n walk(options.rootElement?.() || WINDOW.document.body, root.windows);\n\n const attachment: Attachment = {\n filename: 'view-hierarchy.json',\n attachmentType: 'event.view_hierarchy',\n contentType: 'application/json',\n data: JSON.stringify(root),\n };\n\n hint.attachments = hint.attachments || [];\n hint.attachments.push(attachment);\n\n return event;\n },\n };\n});\n"],"names":["defineIntegration","getComponentName","children","WINDOW"],"mappings":"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"}