{"version":3,"file":"AbstractAsyncHooksContextManager.js","sourceRoot":"","sources":["../../src/AbstractAsyncHooksContextManager.ts"],"names":[],"mappings":"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","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\nimport { ContextManager, Context } from '@opentelemetry/api';\nimport { EventEmitter } from 'events';\n\ntype Func = (...args: unknown[]) => T;\n\n/**\n * Store a map for each event of all original listeners and their \"patched\"\n * version. So when a listener is removed by the user, the corresponding\n * patched function will be also removed.\n */\ninterface PatchMap {\n [name: string]: WeakMap, Func>;\n}\n\nconst ADD_LISTENER_METHODS = [\n 'addListener' as const,\n 'on' as const,\n 'once' as const,\n 'prependListener' as const,\n 'prependOnceListener' as const,\n];\n\nexport abstract class AbstractAsyncHooksContextManager\n implements ContextManager\n{\n abstract active(): Context;\n\n abstract with ReturnType>(\n context: Context,\n fn: F,\n thisArg?: ThisParameterType,\n ...args: A\n ): ReturnType;\n\n abstract enable(): this;\n\n abstract disable(): this;\n\n /**\n * Binds a the certain context or the active one to the target function and then returns the target\n * @param context A context (span) to be bind to target\n * @param target a function or event emitter. When target or one of its callbacks is called,\n * the provided context will be used as the active context for the duration of the call.\n */\n bind(context: Context, target: T): T {\n if (target instanceof EventEmitter) {\n return this._bindEventEmitter(context, target);\n }\n\n if (typeof target === 'function') {\n return this._bindFunction(context, target);\n }\n return target;\n }\n\n private _bindFunction(context: Context, target: T): T {\n const manager = this;\n const contextWrapper = function (this: never, ...args: unknown[]) {\n return manager.with(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 /**\n * It isn't possible to tell Typescript that contextWrapper is the same as T\n * so we forced to cast as any here.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return contextWrapper as any;\n }\n\n /**\n * By default, EventEmitter call their callback with their context, which we do\n * not want, instead we will bind a specific context to all callbacks that\n * go through it.\n * @param context the context we want to bind\n * @param ee EventEmitter an instance of EventEmitter to patch\n */\n private _bindEventEmitter(\n context: Context,\n ee: T\n ): T {\n const map = this._getPatchMap(ee);\n if (map !== undefined) return ee;\n this._createPatchMap(ee);\n\n // patch methods that add a listener to propagate context\n ADD_LISTENER_METHODS.forEach(methodName => {\n if (ee[methodName] === undefined) return;\n ee[methodName] = this._patchAddListener(ee, ee[methodName], context);\n });\n // patch methods that remove a listener\n if (typeof ee.removeListener === 'function') {\n ee.removeListener = this._patchRemoveListener(ee, ee.removeListener);\n }\n if (typeof ee.off === 'function') {\n ee.off = this._patchRemoveListener(ee, ee.off);\n }\n // patch method that remove all listeners\n if (typeof ee.removeAllListeners === 'function') {\n ee.removeAllListeners = this._patchRemoveAllListeners(\n ee,\n ee.removeAllListeners\n );\n }\n return ee;\n }\n\n /**\n * Patch methods that remove a given listener so that we match the \"patched\"\n * version of that listener (the one that propagate context).\n * @param ee EventEmitter instance\n * @param original reference to the patched method\n */\n private _patchRemoveListener(ee: EventEmitter, original: Function) {\n const contextManager = this;\n return function (this: never, event: string, listener: Func) {\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 /**\n * Patch methods that remove all listeners so we remove our\n * internal references for a given event.\n * @param ee EventEmitter instance\n * @param original reference to the patched method\n */\n private _patchRemoveAllListeners(ee: EventEmitter, original: Function) {\n const contextManager = this;\n return function (this: never, event: string) {\n const map = contextManager._getPatchMap(ee);\n if (map !== undefined) {\n if (arguments.length === 0) {\n contextManager._createPatchMap(ee);\n } else if (map[event] !== undefined) {\n delete map[event];\n }\n }\n return original.apply(this, arguments);\n };\n }\n\n /**\n * Patch methods on an event emitter instance that can add listeners so we\n * can force them to propagate a given context.\n * @param ee EventEmitter instance\n * @param original reference to the patched method\n * @param [context] context to propagate when calling listeners\n */\n private _patchAddListener(\n ee: EventEmitter,\n original: Function,\n context: Context\n ) {\n const contextManager = this;\n return function (this: never, event: string, listener: Func) {\n /**\n * This check is required to prevent double-wrapping the listener.\n * The implementation for ee.once wraps the listener and calls ee.on.\n * Without this check, we would wrap that wrapped listener.\n * This causes an issue because ee.removeListener depends on the onceWrapper\n * to properly remove the listener. If we wrap their wrapper, we break\n * that detection.\n */\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 // store a weak reference of the user listener to ours\n listeners.set(listener, patchedListener);\n\n /**\n * See comment at the start of this function for the explanation of this property.\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);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (ee as any)[this._kOtListeners] = map;\n return map;\n }\n private _getPatchMap(ee: EventEmitter): PatchMap | undefined {\n return (ee as never)[this._kOtListeners];\n }\n\n private readonly _kOtListeners = Symbol('OtListeners');\n private _wrapped = false;\n}\n"]}