From d864684c7d6c89d8389d4ed567e43540f32a070a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Og=C3=B3rek?= Date: Sun, 21 Mar 2021 18:40:54 +0100 Subject: [PATCH 1/2] ref: Add fast-path to fetchImpl --- packages/browser/src/transports/fetch.ts | 9 +++++++-- packages/utils/src/supports.ts | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/browser/src/transports/fetch.ts b/packages/browser/src/transports/fetch.ts index c16ab3a4a588..db7011018d64 100644 --- a/packages/browser/src/transports/fetch.ts +++ b/packages/browser/src/transports/fetch.ts @@ -1,6 +1,6 @@ import { eventToSentryRequest, sessionToSentryRequest } from '@sentry/core'; import { Event, Response, SentryRequest, Session, TransportOptions } from '@sentry/types'; -import { getGlobalObject, logger, supportsReferrerPolicy, SyncPromise } from '@sentry/utils'; +import { getGlobalObject, isNativeFetch, logger, supportsReferrerPolicy, SyncPromise } from '@sentry/utils'; import { BaseTransport } from './base'; @@ -45,8 +45,13 @@ type FetchImpl = typeof fetch; * Safari: resource blocked by content blocker */ function getNativeFetchImplementation(): FetchImpl { - // Make sure that the fetch we use is always the native one. + // Fast path to avoid DOM I/O const global = getGlobalObject(); + // eslint-disable-next-line @typescript-eslint/unbound-method + if (isNativeFetch(global.fetch)) { + return global.fetch.bind(global); + } + const document = global.document; // eslint-disable-next-line deprecation/deprecation if (typeof document?.createElement === `function`) { diff --git a/packages/utils/src/supports.ts b/packages/utils/src/supports.ts index a7c98f1bb5ab..88e519b77a24 100644 --- a/packages/utils/src/supports.ts +++ b/packages/utils/src/supports.ts @@ -73,7 +73,7 @@ export function supportsFetch(): boolean { * isNativeFetch checks if the given function is a native implementation of fetch() */ // eslint-disable-next-line @typescript-eslint/ban-types -function isNativeFetch(func: Function): boolean { +export function isNativeFetch(func: Function): boolean { return func && /^function fetch\(\)\s+\{\s+\[native code\]\s+\}$/.test(func.toString()); } From f5b6abd31a3b4531656c86188378515cb6fc17cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Og=C3=B3rek?= Date: Mon, 22 Mar 2021 12:32:10 +0100 Subject: [PATCH 2/2] fix: Cleanup after fetch impl detection --- packages/browser/src/transports/fetch.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/browser/src/transports/fetch.ts b/packages/browser/src/transports/fetch.ts index db7011018d64..f0bd608eeb43 100644 --- a/packages/browser/src/transports/fetch.ts +++ b/packages/browser/src/transports/fetch.ts @@ -45,14 +45,16 @@ type FetchImpl = typeof fetch; * Safari: resource blocked by content blocker */ function getNativeFetchImplementation(): FetchImpl { + /* eslint-disable @typescript-eslint/unbound-method */ + // Fast path to avoid DOM I/O const global = getGlobalObject(); - // eslint-disable-next-line @typescript-eslint/unbound-method if (isNativeFetch(global.fetch)) { return global.fetch.bind(global); } const document = global.document; + let fetchImpl = global.fetch; // eslint-disable-next-line deprecation/deprecation if (typeof document?.createElement === `function`) { try { @@ -60,14 +62,16 @@ function getNativeFetchImplementation(): FetchImpl { sandbox.hidden = true; document.head.appendChild(sandbox); if (sandbox.contentWindow?.fetch) { - return sandbox.contentWindow.fetch.bind(global); + fetchImpl = sandbox.contentWindow.fetch; } document.head.removeChild(sandbox); } catch (e) { logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', e); } } - return global.fetch.bind(global); + + return fetchImpl.bind(global); + /* eslint-enable @typescript-eslint/unbound-method */ } /** `fetch` based transport */