{"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<string, WeakMap<ListenerFn, ListenerFn>>;\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<Context>();\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<A extends unknown[], F extends (...args: A) => ReturnType<F>>(\n    context: Context,\n    fn: F,\n    thisArg?: ThisParameterType<F>,\n    ...args: A\n  ): ReturnType<F> {\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<T>(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<T extends EventEmitter>(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<symbol, PatchMap>)[this._kOtListeners] = map;\n    return map;\n  }\n\n  private _getPatchMap(ee: EventEmitter): PatchMap | undefined {\n    return (ee as unknown as Record<symbol, PatchMap | undefined>)[this._kOtListeners];\n  }\n}\n"],"names":["AsyncLocalStorage","setIsSetup","ROOT_CONTEXT","buildContextWithSentryScopes","EventEmitter","SENTRY_SCOPES_CONTEXT_KEY"],"mappings":"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"}