{"version":3,"file":"index.js","sources":["../../src/asyncLocalStorageContextManager.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * NOTICE from the Sentry authors:\n * This implementation follows the behavior of OpenTelemetry’s `@opentelemetry/context-async-hooks`\n * package, combining logic that upstream splits across:\n * - https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-context-async-hooks/src/AbstractAsyncHooksContextManager.ts\n * - https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-context-async-hooks/src/AsyncLocalStorageContextManager.ts\n * It is a single-class re-implementation for Sentry (not a verbatim copy of those files).\n */\n\nimport type { Context, ContextManager } from '@opentelemetry/api';\nimport { ROOT_CONTEXT } from '@opentelemetry/api';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { EventEmitter } from 'node:events';\nimport { SENTRY_SCOPES_CONTEXT_KEY } from './constants';\nimport type { AsyncLocalStorageLookup } from './contextManager';\nimport { buildContextWithSentryScopes } from './utils/buildContextWithSentryScopes';\nimport { setIsSetup } from './utils/setupCheck';\n\ntype ListenerFn = (...args: unknown[]) => unknown;\n\n/**\n * Per-event map from user listeners to context-bound listeners.\n */\ntype PatchMap = Record>;\n\nconst ADD_LISTENER_METHODS = ['addListener', 'on', 'once', 'prependListener', 'prependOnceListener'] as const;\n\n/**\n * OpenTelemetry-compatible context manager using Node.js `AsyncLocalStorage`.\n * Semantics match `@opentelemetry/context-async-hooks` (function `bind` + `EventEmitter` patching).\n */\nexport class SentryAsyncLocalStorageContextManager implements ContextManager {\n protected readonly _asyncLocalStorage = new AsyncLocalStorage();\n\n private readonly _kOtListeners = Symbol('OtListeners');\n private _wrapped = false;\n\n public constructor() {\n setIsSetup('SentryContextManager');\n }\n\n public active(): Context {\n return this._asyncLocalStorage.getStore() ?? ROOT_CONTEXT;\n }\n\n public with ReturnType>(\n context: Context,\n fn: F,\n thisArg?: ThisParameterType,\n ...args: A\n ): ReturnType {\n const ctx2 = buildContextWithSentryScopes(context, this.active());\n const cb = thisArg == null ? fn : fn.bind(thisArg);\n return this._asyncLocalStorage.run(ctx2, cb as never, ...args);\n }\n\n public enable(): this {\n return this;\n }\n\n public disable(): this {\n this._asyncLocalStorage.disable();\n return this;\n }\n\n public bind(context: Context, target: T): T {\n if (target instanceof EventEmitter) {\n return this._bindEventEmitter(context, target);\n }\n if (typeof target === 'function') {\n return this._bindFunction(context, target as unknown as ListenerFn) as T;\n }\n return target;\n }\n\n /**\n * Gets underlying AsyncLocalStorage and symbol to allow lookup of scope.\n * This is Sentry-specific.\n */\n public getAsyncLocalStorageLookup(): AsyncLocalStorageLookup {\n return {\n asyncLocalStorage: this._asyncLocalStorage,\n contextSymbol: SENTRY_SCOPES_CONTEXT_KEY,\n };\n }\n\n private _bindFunction(context: Context, target: ListenerFn): ListenerFn {\n const managerWith = this.with.bind(this);\n const contextWrapper = function (this: never, ...args: unknown[]) {\n return managerWith(context, () => target.apply(this, args));\n };\n Object.defineProperty(contextWrapper, 'length', {\n enumerable: false,\n configurable: true,\n writable: false,\n value: target.length,\n });\n return contextWrapper;\n }\n\n private _bindEventEmitter(context: Context, ee: T): T {\n if (this._getPatchMap(ee) !== undefined) {\n return ee;\n }\n this._createPatchMap(ee);\n\n for (const methodName of ADD_LISTENER_METHODS) {\n if (ee[methodName] === undefined) continue;\n ee[methodName] = this._patchAddListener(\n ee,\n ee[methodName] as unknown as (...args: unknown[]) => unknown,\n context,\n );\n }\n if (typeof ee.removeListener === 'function') {\n // oxlint-disable-next-line @typescript-eslint/unbound-method -- patched like upstream OTel context manager\n ee.removeListener = this._patchRemoveListener(ee, ee.removeListener as (...args: unknown[]) => unknown);\n }\n if (typeof ee.off === 'function') {\n // oxlint-disable-next-line @typescript-eslint/unbound-method\n ee.off = this._patchRemoveListener(ee, ee.off as (...args: unknown[]) => unknown);\n }\n if (typeof ee.removeAllListeners === 'function') {\n ee.removeAllListeners = this._patchRemoveAllListeners(\n ee,\n // oxlint-disable-next-line @typescript-eslint/unbound-method\n ee.removeAllListeners as (...args: unknown[]) => unknown,\n );\n }\n return ee;\n }\n\n private _patchRemoveListener(ee: EventEmitter, original: (...args: unknown[]) => unknown) {\n // oxlint-disable-next-line @typescript-eslint/no-this-alias\n const contextManager = this;\n return function (this: unknown, event: string, listener: ListenerFn) {\n const events = contextManager._getPatchMap(ee)?.[event];\n if (events === undefined) {\n return original.call(this, event, listener);\n }\n const patchedListener = events.get(listener);\n return original.call(this, event, patchedListener || listener);\n };\n }\n\n private _patchRemoveAllListeners(ee: EventEmitter, original: (...args: unknown[]) => unknown) {\n // oxlint-disable-next-line @typescript-eslint/no-this-alias\n const contextManager = this;\n return function (this: unknown, event?: string) {\n const map = contextManager._getPatchMap(ee);\n if (map !== undefined) {\n if (arguments.length === 0) {\n contextManager._createPatchMap(ee);\n } else if (event !== undefined && map[event] !== undefined) {\n // oxlint-disable-next-line @typescript-eslint/no-dynamic-delete -- event-keyed listener map\n delete map[event];\n }\n }\n return original.apply(this, arguments);\n };\n }\n\n private _patchAddListener(ee: EventEmitter, original: (...args: unknown[]) => unknown, context: Context) {\n // oxlint-disable-next-line @typescript-eslint/no-this-alias\n const contextManager = this;\n return function (this: unknown, event: string, listener: ListenerFn) {\n if (contextManager._wrapped) {\n return original.call(this, event, listener);\n }\n let map = contextManager._getPatchMap(ee);\n if (map === undefined) {\n map = contextManager._createPatchMap(ee);\n }\n let listeners = map[event];\n if (listeners === undefined) {\n listeners = new WeakMap();\n map[event] = listeners;\n }\n const patchedListener = contextManager.bind(context, listener);\n listeners.set(listener, patchedListener);\n\n contextManager._wrapped = true;\n try {\n return original.call(this, event, patchedListener);\n } finally {\n contextManager._wrapped = false;\n }\n };\n }\n\n private _createPatchMap(ee: EventEmitter): PatchMap {\n const map = Object.create(null) as PatchMap;\n (ee as unknown as Record)[this._kOtListeners] = map;\n return map;\n }\n\n private _getPatchMap(ee: EventEmitter): PatchMap | undefined {\n return (ee as unknown as Record)[this._kOtListeners];\n }\n}\n"],"names":[],"mappings":"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"}