diff --git a/packages/browser-utils/src/getLocationHref.ts b/packages/browser-utils/src/getLocationHref.ts new file mode 100644 index 000000000000..75675a727e25 --- /dev/null +++ b/packages/browser-utils/src/getLocationHref.ts @@ -0,0 +1,12 @@ +import { WINDOW } from './types'; + +/** + * A safe form of location.href. + */ +export function getLocationHref(): string { + try { + return WINDOW.document?.location.href ?? ''; + } catch { + return ''; + } +} diff --git a/packages/browser-utils/src/index.ts b/packages/browser-utils/src/index.ts index ca86c78052f0..327d78aca1a1 100644 --- a/packages/browser-utils/src/index.ts +++ b/packages/browser-utils/src/index.ts @@ -22,6 +22,8 @@ export { interactionsIntegration } from './performance/interactions'; export { isBotUserAgent } from './isBotUserAgent'; +export { getLocationHref } from './getLocationHref'; + export { userTimingIntegration } from './performance/userTiming'; export { extractNetworkProtocol } from './performance/utils'; diff --git a/packages/browser/src/helpers.ts b/packages/browser/src/helpers.ts index 5e31528b6dea..32007ad33954 100644 --- a/packages/browser/src/helpers.ts +++ b/packages/browser/src/helpers.ts @@ -4,12 +4,12 @@ import { addExceptionTypeValue, addNonEnumerableProperty, captureException, - getLocationHref, getOriginalFunction, GLOBAL_OBJ, markFunctionWrapped, withScope, } from '@sentry/core/browser'; +import { getLocationHref } from '@sentry/browser-utils'; export const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window; diff --git a/packages/browser/src/integrations/globalhandlers.ts b/packages/browser/src/integrations/globalhandlers.ts index a99c648f0583..106f859326bf 100644 --- a/packages/browser/src/integrations/globalhandlers.ts +++ b/packages/browser/src/integrations/globalhandlers.ts @@ -6,7 +6,6 @@ import { debug, defineIntegration, getClient, - getLocationHref, isPrimitive, isString, stripDataUrlContent, @@ -14,6 +13,7 @@ import { } from '@sentry/core/browser'; import type { BrowserClient } from '../client'; import { DEBUG_BUILD } from '../debug-build'; +import { getLocationHref } from '@sentry/browser-utils'; import { eventFromUnknownInput } from '../eventbuilder'; import { shouldIgnoreOnError } from '../helpers'; diff --git a/packages/browser/src/tracing/browserTracingIntegration.ts b/packages/browser/src/tracing/browserTracingIntegration.ts index 68feaac0190f..fcfeec85a5f4 100644 --- a/packages/browser/src/tracing/browserTracingIntegration.ts +++ b/packages/browser/src/tracing/browserTracingIntegration.ts @@ -18,7 +18,6 @@ import { getClient, getCurrentScope, getDynamicSamplingContextFromSpan, - getLocationHref, GLOBAL_OBJ, hasSpansEnabled, hasSpanStreamingEnabled, @@ -41,6 +40,7 @@ import { import { addHistoryInstrumentationHandler, addPerformanceEntries, + getLocationHref, isBotUserAgent, startTrackingLongAnimationFrames, startTrackingLongTasks, diff --git a/packages/browser/src/tracing/request.ts b/packages/browser/src/tracing/request.ts index 5ab075ca0620..7333f7cf336e 100644 --- a/packages/browser/src/tracing/request.ts +++ b/packages/browser/src/tracing/request.ts @@ -12,7 +12,6 @@ import { addFetchInstrumentationHandler, getActiveSpan, getClient, - getLocationHref, getTraceData, getUrlFragment, getUrlQuery, @@ -37,6 +36,7 @@ import { filterCollectedUrl, filterCollectedUrlQuery } from '@sentry/core'; import { addPerformanceInstrumentationHandler, addXhrInstrumentationHandler, + getLocationHref, parseXhrResponseHeaders, resourceTimingToSpanAttributes, SENTRY_XHR_DATA_KEY, diff --git a/packages/browser/src/utils/detectBrowserExtension.ts b/packages/browser/src/utils/detectBrowserExtension.ts index 86ba33ba7727..9851adc2225a 100644 --- a/packages/browser/src/utils/detectBrowserExtension.ts +++ b/packages/browser/src/utils/detectBrowserExtension.ts @@ -1,4 +1,5 @@ -import { consoleSandbox, getLocationHref } from '@sentry/core/browser'; +import { getLocationHref } from '@sentry/browser-utils'; +import { consoleSandbox } from '@sentry/core/browser'; import { DEBUG_BUILD } from '../debug-build'; import { WINDOW } from '../helpers'; diff --git a/packages/browser/test/sdk.test.ts b/packages/browser/test/sdk.test.ts index 3d84da69e565..7834285dd2e4 100644 --- a/packages/browser/test/sdk.test.ts +++ b/packages/browser/test/sdk.test.ts @@ -11,6 +11,7 @@ import { afterEach, describe, expect, it, test, vi } from 'vitest'; import type { BrowserOptions } from '../src'; import { WINDOW } from '../src'; import { init } from '../src/sdk'; +import * as browserUtils from '@sentry/browser-utils'; const PUBLIC_DSN = 'https://username@domain/123'; @@ -168,7 +169,7 @@ describe('init', () => { const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); const locationHrefSpy = vi - .spyOn(SentryCore, 'getLocationHref') + .spyOn(browserUtils, 'getLocationHref') .mockImplementation(() => `${extensionProtocol}://mock-extension-id/dedicated-page.html`); Object.defineProperty(WINDOW, 'browser', { value: { runtime: { id: 'mock-extension-id' } }, writable: true }); diff --git a/packages/browser/test/tracing/request.test.ts b/packages/browser/test/tracing/request.test.ts index f3cd82b86aea..c75fccebb6a1 100644 --- a/packages/browser/test/tracing/request.test.ts +++ b/packages/browser/test/tracing/request.test.ts @@ -193,7 +193,7 @@ describe('shouldAttachHeaders', () => { let locationHrefSpy: MockInstance; beforeEach(() => { - locationHrefSpy = vi.spyOn(utils, 'getLocationHref').mockImplementation(() => 'https://my-origin.com'); + locationHrefSpy = vi.spyOn(browserUtils, 'getLocationHref').mockImplementation(() => 'https://my-origin.com'); }); afterEach(() => { @@ -232,7 +232,7 @@ describe('shouldAttachHeaders', () => { beforeEach(() => { locationHrefSpy = vi - .spyOn(utils, 'getLocationHref') + .spyOn(browserUtils, 'getLocationHref') .mockImplementation(() => 'https://my-origin.com/api/my-route'); }); @@ -364,7 +364,7 @@ describe('shouldAttachHeaders', () => { let locationHrefSpy: MockInstance; beforeEach(() => { - locationHrefSpy = vi.spyOn(utils, 'getLocationHref').mockImplementation(() => ''); + locationHrefSpy = vi.spyOn(browserUtils, 'getLocationHref').mockImplementation(() => ''); }); afterEach(() => { diff --git a/packages/core/src/browser-exports.ts b/packages/core/src/browser-exports.ts index 639ba3b90b39..a5722843187d 100644 --- a/packages/core/src/browser-exports.ts +++ b/packages/core/src/browser-exports.ts @@ -15,7 +15,6 @@ export { startIdleSpan } from './tracing/idleSpan'; export { spanStreamingIntegration } from './integrations/browserSpanStreaming'; -export { getLocationHref } from './utils/browser'; export { supportsDOMError, supportsHistory, supportsNativeFetch, supportsReportingObserver } from './utils/supports'; export type { XhrBreadcrumbData, XhrBreadcrumbHint } from './types/breadcrumb'; export type { diff --git a/packages/feedback/src/core/sendFeedback.ts b/packages/feedback/src/core/sendFeedback.ts index 35c829ab0869..3c1d2c97c9fc 100644 --- a/packages/feedback/src/core/sendFeedback.ts +++ b/packages/feedback/src/core/sendFeedback.ts @@ -6,8 +6,8 @@ import type { SendFeedbackParams, TransportMakeRequestResponse, } from '@sentry/core'; -import { captureFeedback, getClient, getCurrentScope, getLocationHref } from '@sentry/core'; -import { FEEDBACK_API_SOURCE } from '../constants'; +import { captureFeedback, getClient, getCurrentScope } from '@sentry/core'; +import { FEEDBACK_API_SOURCE, WINDOW } from '../constants'; import { createFeedbackError } from '../util/createFeedbackError'; /** @@ -36,7 +36,7 @@ export const sendFeedback: SendFeedback = ( const eventId = captureFeedback( { source: FEEDBACK_API_SOURCE, - url: getLocationHref(), + url: _getLocationHref(), ...params, }, hint, @@ -113,3 +113,14 @@ export const sendFeedback: SendFeedback = ( * }, * } */ + +/** + * A safe form of location.href. + */ +function _getLocationHref(): string { + try { + return WINDOW.document.location.href; + } catch { + return ''; + } +} diff --git a/packages/replay-internal/src/coreHandlers/handleBeforeSendEvent.ts b/packages/replay-internal/src/coreHandlers/handleBeforeSendEvent.ts index d529bf425ce7..02dbecb755d2 100644 --- a/packages/replay-internal/src/coreHandlers/handleBeforeSendEvent.ts +++ b/packages/replay-internal/src/coreHandlers/handleBeforeSendEvent.ts @@ -1,5 +1,5 @@ +import { getLocationHref } from '@sentry/browser-utils'; import type { ErrorEvent, Event } from '@sentry/core'; -import { getLocationHref } from '@sentry/core'; import type { ReplayContainer } from '../types'; import { createBreadcrumb } from '../util/createBreadcrumb'; import { isErrorEvent } from '../util/eventUtils';