UNPKG

5.02 kBJavaScriptView Raw
1"use strict";
2/**
3 * Copyright 2018 Google LLC
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17Object.defineProperty(exports, "__esModule", { value: true });
18exports.reset = exports.getNamespace = exports.destroyNamespace = exports.createNamespace = void 0;
19// Original file from Stackdriver Trace Agent for Node.js
20// https://github.com/GoogleCloudPlatform/cloud-trace-nodejs
21const asyncHook = require("async_hooks");
22const shimmer = require("shimmer");
23const WRAPPED = Symbol('context_wrapped');
24/** A map of AsyncResource IDs to Context objects. */
25let contexts = new Map();
26let current = {};
27// Create the hook.
28asyncHook.createHook({ init, before, destroy }).enable();
29// A list of well-known EventEmitter methods that add event listeners.
30const EVENT_EMITTER_METHODS = [
31 'addListener',
32 'on',
33 'once',
34 'prependListener',
35 'prependOnceListener',
36];
37class AsyncHooksNamespace {
38 get name() {
39 throw new Error('Not implemented');
40 }
41 get active() {
42 return current;
43 }
44 createContext() {
45 throw new Error('Not implemented');
46 }
47 get(k) {
48 return current[k];
49 }
50 set(k, v) {
51 current[k] = v;
52 return v;
53 }
54 run(fn) {
55 this.runAndReturn(fn);
56 return current;
57 }
58 runAndReturn(fn) {
59 const oldContext = current;
60 current = {};
61 if (oldContext['current_tag_map']) {
62 current['current_tag_map'] = oldContext['current_tag_map'];
63 }
64 const res = fn();
65 current = oldContext;
66 return res;
67 }
68 bind(cb) {
69 // TODO(kjin): Monitor https://github.com/Microsoft/TypeScript/pull/15473.
70 // When it's landed and released, we can remove these `any` casts.
71 // tslint:disable-next-line:no-any
72 if (cb[WRAPPED] || !current) {
73 return cb;
74 }
75 const boundContext = current;
76 const contextWrapper = function () {
77 const oldContext = current;
78 current = boundContext;
79 // @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'IArguments' is not assignable to... Remove this comment to see the full error message
80 const res = cb.apply(this, arguments);
81 current = oldContext;
82 return res;
83 };
84 // tslint:disable-next-line:no-any
85 contextWrapper[WRAPPED] = true;
86 Object.defineProperty(contextWrapper, 'length', {
87 enumerable: false,
88 configurable: true,
89 writable: false,
90 value: cb.length,
91 });
92 return contextWrapper;
93 }
94 // This function is not technically needed and all tests currently pass
95 // without it (after removing call sites). While it is not a complete
96 // solution, restoring correct context before running every request/response
97 // event handler reduces the number of situations in which userspace queuing
98 // will cause us to lose context.
99 bindEmitter(ee) {
100 const ns = this;
101 EVENT_EMITTER_METHODS.forEach(method => {
102 if (ee[method]) {
103 shimmer.wrap(ee, method, oldMethod => {
104 return function (event, cb) {
105 // @ts-expect-error ts-migrate(2684) FIXME: The 'this' context of type '((event: string | symb... Remove this comment to see the full error message
106 return oldMethod.call(this, event, ns.bind(cb));
107 };
108 });
109 }
110 });
111 }
112}
113const namespace = new AsyncHooksNamespace();
114// AsyncWrap Hooks
115/** init is called during object construction. */
116function init(uid, provider, parentUid, parentHandle) {
117 contexts.set(uid, current);
118}
119/** before is called just before the resource's callback is called. */
120function before(uid) {
121 const maybeCurrent = contexts.get(uid);
122 if (maybeCurrent !== undefined) {
123 current = maybeCurrent;
124 }
125}
126/**
127 * destroy is called when the object is no longer used, so also delete
128 * its entry in the map.
129 */
130function destroy(uid) {
131 contexts.delete(uid);
132}
133function createNamespace() {
134 return namespace;
135}
136exports.createNamespace = createNamespace;
137function destroyNamespace() {
138 current = {};
139 contexts = new Map();
140}
141exports.destroyNamespace = destroyNamespace;
142function getNamespace() {
143 return namespace;
144}
145exports.getNamespace = getNamespace;
146function reset() {
147 throw new Error('Not implemented');
148}
149exports.reset = reset;
150//# sourceMappingURL=cls-ah.js.map
\No newline at end of file