diff --git a/docs/migration/v8-to-v9.md b/docs/migration/v8-to-v9.md index 775ea5c8fc3a..f9950d161c0f 100644 --- a/docs/migration/v8-to-v9.md +++ b/docs/migration/v8-to-v9.md @@ -111,6 +111,7 @@ It will be removed in a future major version. - The `BAGGAGE_HEADER_NAME` export has been removed. Use `"baggage"` string constant directly instead. - The `flatten` export has been removed. There is no replacement. - The `urlEncode` method has been removed. There is no replacement. +- The `getDomElement` method has been removed. There is no replacement. ### `@sentry/nestjs` diff --git a/packages/browser/src/tracing/browserTracingIntegration.ts b/packages/browser/src/tracing/browserTracingIntegration.ts index 17030f2f4a43..85a9a0fa3616 100644 --- a/packages/browser/src/tracing/browserTracingIntegration.ts +++ b/packages/browser/src/tracing/browserTracingIntegration.ts @@ -21,7 +21,6 @@ import { getActiveSpan, getClient, getCurrentScope, - getDomElement, getDynamicSamplingContextFromSpan, getIsolationScope, getRootSpan, @@ -190,6 +189,12 @@ const DEFAULT_BROWSER_TRACING_OPTIONS: BrowserTracingOptions = { * We explicitly export the proper type here, as this has to be extended in some cases. */ export const browserTracingIntegration = ((_options: Partial = {}) => { + /** + * This is just a small wrapper that makes `document` optional. + * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up. + */ + const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined; + registerSpanErrorInstrumentation(); const { @@ -273,13 +278,13 @@ export const browserTracingIntegration = ((_options: Partial { + if (isPageloadTransaction && optionalWindowDocument) { + optionalWindowDocument.addEventListener('readystatechange', () => { emitFinish(); }); @@ -462,12 +467,14 @@ export function startBrowserTracingNavigationSpan(client: Client, spanOptions: S /** Returns the value of a meta tag */ export function getMetaContent(metaName: string): string | undefined { - // Can't specify generic to `getDomElement` because tracing can be used - // in a variety of environments, have to disable `no-unsafe-member-access` - // as a result. - const metaTag = getDomElement(`meta[name=${metaName}]`); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - return metaTag ? metaTag.getAttribute('content') : undefined; + /** + * This is just a small wrapper that makes `document` optional. + * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up. + */ + const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined; + + const metaTag = optionalWindowDocument && optionalWindowDocument.querySelector(`meta[name=${metaName}]`); + return (metaTag && metaTag.getAttribute('content')) || undefined; } /** Start listener for interaction transactions */ @@ -477,6 +484,12 @@ function registerInteractionListener( childSpanTimeout: BrowserTracingOptions['childSpanTimeout'], latestRoute: RouteInfo, ): void { + /** + * This is just a small wrapper that makes `document` optional. + * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up. + */ + const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined; + let inflightInteractionSpan: Span | undefined; const registerInteractionTransaction = (): void => { const op = 'ui.action.click'; @@ -519,7 +532,7 @@ function registerInteractionListener( ); }; - if (WINDOW.document) { + if (optionalWindowDocument) { addEventListener('click', registerInteractionTransaction, { once: false, capture: true }); } } diff --git a/packages/core/src/utils-hoist/browser.ts b/packages/core/src/utils-hoist/browser.ts index b3a5220e7c3c..96b779fecdb8 100644 --- a/packages/core/src/utils-hoist/browser.ts +++ b/packages/core/src/utils-hoist/browser.ts @@ -140,30 +140,6 @@ export function getLocationHref(): string { } } -/** - * Gets a DOM element by using document.querySelector. - * - * This wrapper will first check for the existence of the function before - * actually calling it so that we don't have to take care of this check, - * every time we want to access the DOM. - * - * Reason: DOM/querySelector is not available in all environments. - * - * We have to cast to any because utils can be consumed by a variety of environments, - * and we don't want to break TS users. If you know what element will be selected by - * `document.querySelector`, specify it as part of the generic call. For example, - * `const element = getDomElement('selector');` - * - * @param selector the selector string passed on to document.querySelector - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function getDomElement(selector: string): E | null { - if (WINDOW.document && WINDOW.document.querySelector) { - return WINDOW.document.querySelector(selector) as unknown as E; - } - return null; -} - /** * Given a DOM element, traverses up the tree until it finds the first ancestor node * that has the `data-sentry-component` or `data-sentry-element` attribute with `data-sentry-component` taking diff --git a/packages/core/src/utils-hoist/index.ts b/packages/core/src/utils-hoist/index.ts index fb47fb6ee75c..904dc1920629 100644 --- a/packages/core/src/utils-hoist/index.ts +++ b/packages/core/src/utils-hoist/index.ts @@ -1,6 +1,10 @@ export { applyAggregateErrorsToEvent } from './aggregate-errors'; export { getBreadcrumbLogLevelFromHttpStatusCode } from './breadcrumb-log-level'; -export { getComponentName, getDomElement, getLocationHref, htmlTreeAsString } from './browser'; +export { + getComponentName, + getLocationHref, + htmlTreeAsString, +} from './browser'; export { dsnFromString, dsnToString, makeDsn } from './dsn'; export { SentryError } from './error'; export { GLOBAL_OBJ } from './worldwide'; diff --git a/packages/core/test/utils-hoist/browser.test.ts b/packages/core/test/utils-hoist/browser.test.ts index c86570ee7fb0..01a0d5eee747 100644 --- a/packages/core/test/utils-hoist/browser.test.ts +++ b/packages/core/test/utils-hoist/browser.test.ts @@ -1,6 +1,6 @@ import { JSDOM } from 'jsdom'; -import { getDomElement, htmlTreeAsString } from '../../src/utils-hoist/browser'; +import { htmlTreeAsString } from '../../src/utils-hoist/browser'; beforeAll(() => { const dom = new JSDOM(); @@ -74,13 +74,3 @@ describe('htmlTreeAsString', () => { ); }); }); - -describe('getDomElement', () => { - it('returns the element for a given query selector', () => { - document.head.innerHTML = '
Hello
'; - const el = getDomElement('div#mydiv'); - expect(el).toBeDefined(); - expect(el?.tagName).toEqual('DIV'); - expect(el?.id).toEqual('mydiv'); - }); -}); diff --git a/packages/svelte/src/sdk.ts b/packages/svelte/src/sdk.ts index 1d21b72ef59d..52f8ef4c517b 100644 --- a/packages/svelte/src/sdk.ts +++ b/packages/svelte/src/sdk.ts @@ -1,7 +1,8 @@ import type { BrowserOptions } from '@sentry/browser'; +import { WINDOW } from '@sentry/browser'; import { addEventProcessor, init as browserInit } from '@sentry/browser'; import type { Client, EventProcessor } from '@sentry/core'; -import { applySdkMetadata, getDomElement } from '@sentry/core'; +import { applySdkMetadata } from '@sentry/core'; /** * Inits the Svelte SDK */ @@ -55,5 +56,5 @@ export function detectAndReportSvelteKit(): void { * @see https://github.com/sveltejs/kit/issues/307 for more information */ export function isSvelteKitApp(): boolean { - return getDomElement('div#svelte-announcer') !== null; + return !!WINDOW.document.querySelector('div#svelte-announcer'); } diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 5724c8e41213..33424bf8a8d0 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -67,7 +67,6 @@ import { getBreadcrumbLogLevelFromHttpStatusCode as getBreadcrumbLogLevelFromHttpStatusCode_imported, getComponentName as getComponentName_imported, getDebugImagesForResources as getDebugImagesForResources_imported, - getDomElement as getDomElement_imported, getEventDescription as getEventDescription_imported, getFilenameToDebugIdMap as getFilenameToDebugIdMap_imported, getFramesFromEvent as getFramesFromEvent_imported, @@ -542,9 +541,6 @@ export const resolve = resolve_imported; /** @deprecated Import from `@sentry/core` instead. */ export const getComponentName = getComponentName_imported; -/** @deprecated Import from `@sentry/core` instead. */ -export const getDomElement = getDomElement_imported; - /** @deprecated Import from `@sentry/core` instead. */ export const getLocationHref = getLocationHref_imported;