1 | ;
|
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 | */
|
17 | Object.defineProperty(exports, "__esModule", { value: true });
|
18 | exports.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
|
21 | const asyncHook = require("async_hooks");
|
22 | const shimmer = require("shimmer");
|
23 | const WRAPPED = Symbol('context_wrapped');
|
24 | /** A map of AsyncResource IDs to Context objects. */
|
25 | let contexts = new Map();
|
26 | let current = {};
|
27 | // Create the hook.
|
28 | asyncHook.createHook({ init, before, destroy }).enable();
|
29 | // A list of well-known EventEmitter methods that add event listeners.
|
30 | const EVENT_EMITTER_METHODS = [
|
31 | 'addListener',
|
32 | 'on',
|
33 | 'once',
|
34 | 'prependListener',
|
35 | 'prependOnceListener',
|
36 | ];
|
37 | class 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 | }
|
113 | const namespace = new AsyncHooksNamespace();
|
114 | // AsyncWrap Hooks
|
115 | /** init is called during object construction. */
|
116 | function init(uid, provider, parentUid, parentHandle) {
|
117 | contexts.set(uid, current);
|
118 | }
|
119 | /** before is called just before the resource's callback is called. */
|
120 | function 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 | */
|
130 | function destroy(uid) {
|
131 | contexts.delete(uid);
|
132 | }
|
133 | function createNamespace() {
|
134 | return namespace;
|
135 | }
|
136 | exports.createNamespace = createNamespace;
|
137 | function destroyNamespace() {
|
138 | current = {};
|
139 | contexts = new Map();
|
140 | }
|
141 | exports.destroyNamespace = destroyNamespace;
|
142 | function getNamespace() {
|
143 | return namespace;
|
144 | }
|
145 | exports.getNamespace = getNamespace;
|
146 | function reset() {
|
147 | throw new Error('Not implemented');
|
148 | }
|
149 | exports.reset = reset;
|
150 | //# sourceMappingURL=cls-ah.js.map |
\ | No newline at end of file |