@@ -29,6 +29,19 @@ type PatchedEventEmitter = {
29
29
__ot_listeners ?: { [ name : string ] : WeakMap < Func < void > , Func < void > > } ;
30
30
} & EventEmitter ;
31
31
32
+ class Reference < T > {
33
+ constructor ( private _value : T ) { }
34
+
35
+ set ( value : T ) {
36
+ this . _value = value ;
37
+ return this ;
38
+ }
39
+
40
+ get ( ) {
41
+ return this . _value ;
42
+ }
43
+ }
44
+
32
45
const ADD_LISTENER_METHODS = [
33
46
'addListener' as 'addListener' ,
34
47
'on' as 'on' ,
@@ -39,9 +52,7 @@ const ADD_LISTENER_METHODS = [
39
52
40
53
export class AsyncHooksContextManager implements ContextManager {
41
54
private _asyncHook : asyncHooks . AsyncHook ;
42
- private _contexts : {
43
- [ uid : number ] : Context | undefined | null ;
44
- } = Object . create ( null ) ;
55
+ private _contextRefs : Map < number , Reference < Context > | undefined > = new Map ( ) ;
45
56
46
57
constructor ( ) {
47
58
this . _asyncHook = asyncHooks . createHook ( {
@@ -52,18 +63,24 @@ export class AsyncHooksContextManager implements ContextManager {
52
63
}
53
64
54
65
active ( ) : Context {
55
- return (
56
- this . _contexts [ asyncHooks . executionAsyncId ( ) ] || Context . ROOT_CONTEXT
57
- ) ;
66
+ const ref = this . _contextRefs . get ( asyncHooks . executionAsyncId ( ) ) ;
67
+ return ref === undefined ? Context . ROOT_CONTEXT : ref . get ( ) ;
58
68
}
59
69
60
70
with < T extends ( ...args : unknown [ ] ) => ReturnType < T > > (
61
71
context : Context ,
62
72
fn : T
63
73
) : ReturnType < T > {
64
74
const uid = asyncHooks . executionAsyncId ( ) ;
65
- const oldContext = this . _contexts [ uid ] ;
66
- this . _contexts [ uid ] = context ;
75
+ let ref = this . _contextRefs . get ( uid ) ;
76
+ let oldContext : Context | undefined = undefined ;
77
+ if ( ref === undefined ) {
78
+ ref = new Reference ( context ) ;
79
+ this . _contextRefs . set ( uid , ref ) ;
80
+ } else {
81
+ oldContext = ref . get ( ) ;
82
+ ref . set ( context ) ;
83
+ }
67
84
try {
68
85
return fn ( ) ;
69
86
} catch ( err ) {
@@ -72,7 +89,7 @@ export class AsyncHooksContextManager implements ContextManager {
72
89
if ( oldContext === undefined ) {
73
90
this . _destroy ( uid ) ;
74
91
} else {
75
- this . _contexts [ uid ] = oldContext ;
92
+ ref . set ( oldContext ) ;
76
93
}
77
94
}
78
95
}
@@ -82,8 +99,15 @@ export class AsyncHooksContextManager implements ContextManager {
82
99
fn : U
83
100
) : Promise < T > {
84
101
const uid = asyncHooks . executionAsyncId ( ) ;
85
- const oldContext = this . _contexts [ uid ] ;
86
- this . _contexts [ uid ] = context ;
102
+ let ref = this . _contextRefs . get ( uid ) ;
103
+ let oldContext : Context | undefined = undefined ;
104
+ if ( ref === undefined ) {
105
+ ref = new Reference ( context ) ;
106
+ this . _contextRefs . set ( uid , ref ) ;
107
+ } else {
108
+ oldContext = ref . get ( ) ;
109
+ ref . set ( context ) ;
110
+ }
87
111
try {
88
112
return await fn ( ) ;
89
113
} catch ( err ) {
@@ -92,7 +116,7 @@ export class AsyncHooksContextManager implements ContextManager {
92
116
if ( oldContext === undefined ) {
93
117
this . _destroy ( uid ) ;
94
118
} else {
95
- this . _contexts [ uid ] = oldContext ;
119
+ ref . set ( oldContext ) ;
96
120
}
97
121
}
98
122
}
@@ -117,7 +141,7 @@ export class AsyncHooksContextManager implements ContextManager {
117
141
118
142
disable ( ) : this {
119
143
this . _asyncHook . disable ( ) ;
120
- this . _contexts = { } ;
144
+ this . _contextRefs . clear ( ) ;
121
145
return this ;
122
146
}
123
147
@@ -252,7 +276,10 @@ export class AsyncHooksContextManager implements ContextManager {
252
276
* @param uid id of the async context
253
277
*/
254
278
private _init ( uid : number ) {
255
- this . _contexts [ uid ] = this . _contexts [ asyncHooks . executionAsyncId ( ) ] ;
279
+ this . _contextRefs . set (
280
+ uid ,
281
+ this . _contextRefs . get ( asyncHooks . executionAsyncId ( ) )
282
+ ) ;
256
283
}
257
284
258
285
/**
@@ -261,6 +288,6 @@ export class AsyncHooksContextManager implements ContextManager {
261
288
* @param uid uid of the async context
262
289
*/
263
290
private _destroy ( uid : number ) {
264
- delete this . _contexts [ uid ] ;
291
+ this . _contextRefs . delete ( uid ) ;
265
292
}
266
293
}
0 commit comments