@@ -27,6 +27,7 @@ const {
27
27
ArrayPrototypeShift,
28
28
ArrayPrototypeSlice,
29
29
ArrayPrototypeSplice,
30
+ ArrayPrototypeUnshift,
30
31
Boolean,
31
32
Error,
32
33
ErrorCaptureStackTrace,
@@ -42,6 +43,7 @@ const {
42
43
Promise,
43
44
PromiseReject,
44
45
PromiseResolve,
46
+ ReflectApply,
45
47
ReflectOwnKeys,
46
48
String,
47
49
StringPrototypeSplit,
@@ -59,6 +61,7 @@ const {
59
61
kEnhanceStackBeforeInspector,
60
62
codes : {
61
63
ERR_INVALID_ARG_TYPE ,
64
+ ERR_INVALID_THIS ,
62
65
ERR_OUT_OF_RANGE ,
63
66
ERR_UNHANDLED_ERROR
64
67
} ,
@@ -68,6 +71,7 @@ const {
68
71
validateAbortSignal,
69
72
validateBoolean,
70
73
validateFunction,
74
+ validateString,
71
75
} = require ( 'internal/validators' ) ;
72
76
73
77
const kCapture = Symbol ( 'kCapture' ) ;
@@ -76,6 +80,125 @@ const kMaxEventTargetListeners = Symbol('events.maxEventTargetListeners');
76
80
const kMaxEventTargetListenersWarned =
77
81
Symbol ( 'events.maxEventTargetListenersWarned' ) ;
78
82
83
+ let EventEmitterAsyncResource ;
84
+ // The EventEmitterAsyncResource has to be initialized lazily because event.js
85
+ // is loaded so early in the bootstrap process, before async_hooks is available.
86
+ //
87
+ // This implementation was adapted straight from addaleax's
88
+ // eventemitter-asyncresource MIT-licensed userland module.
89
+ // https://github.com/addaleax/eventemitter-asyncresource
90
+ function lazyEventEmitterAsyncResource ( ) {
91
+ if ( EventEmitterAsyncResource === undefined ) {
92
+ const {
93
+ AsyncResource
94
+ } = require ( 'async_hooks' ) ;
95
+
96
+ const kEventEmitter = Symbol ( 'kEventEmitter' ) ;
97
+ const kAsyncResource = Symbol ( 'kAsyncResource' ) ;
98
+ class EventEmitterReferencingAsyncResource extends AsyncResource {
99
+ /**
100
+ * @param {EventEmitter } ee
101
+ * @param {string } [type]
102
+ * @param {{
103
+ * triggerAsyncId?: number,
104
+ * requireManualDestroy?: boolean,
105
+ * }} [options]
106
+ */
107
+ constructor ( ee , type , options ) {
108
+ super ( type , options ) ;
109
+ this [ kEventEmitter ] = ee ;
110
+ }
111
+
112
+ /**
113
+ * @type {EventEmitter }
114
+ */
115
+ get eventEmitter ( ) {
116
+ if ( this [ kEventEmitter ] === undefined )
117
+ throw new ERR_INVALID_THIS ( 'EventEmitterReferencingAsyncResource' ) ;
118
+ return this [ kEventEmitter ] ;
119
+ }
120
+ }
121
+
122
+ EventEmitterAsyncResource =
123
+ class EventEmitterAsyncResource extends EventEmitter {
124
+ /**
125
+ * @param {{
126
+ * name?: string,
127
+ * triggerAsyncId?: number,
128
+ * requireManualDestroy?: boolean,
129
+ * }} [options]
130
+ */
131
+ constructor ( options = undefined ) {
132
+ let name ;
133
+ if ( typeof options === 'string' ) {
134
+ name = options ;
135
+ options = undefined ;
136
+ } else {
137
+ if ( new . target === EventEmitterAsyncResource ) {
138
+ validateString ( options ?. name , 'options.name' ) ;
139
+ }
140
+ name = options ?. name || new . target . name ;
141
+ }
142
+ super ( options ) ;
143
+
144
+ this [ kAsyncResource ] =
145
+ new EventEmitterReferencingAsyncResource ( this , name , options ) ;
146
+ }
147
+
148
+ /**
149
+ * @param {symbol,string } event
150
+ * @param {...any } args
151
+ * @returns {boolean }
152
+ */
153
+ emit ( event , ...args ) {
154
+ if ( this [ kAsyncResource ] === undefined )
155
+ throw new ERR_INVALID_THIS ( 'EventEmitterAsyncResource' ) ;
156
+ const { asyncResource } = this ;
157
+ ArrayPrototypeUnshift ( args , super . emit , this , event ) ;
158
+ return ReflectApply ( asyncResource . runInAsyncScope , asyncResource ,
159
+ args ) ;
160
+ }
161
+
162
+ /**
163
+ * @returns {void }
164
+ */
165
+ emitDestroy ( ) {
166
+ if ( this [ kAsyncResource ] === undefined )
167
+ throw new ERR_INVALID_THIS ( 'EventEmitterAsyncResource' ) ;
168
+ this . asyncResource . emitDestroy ( ) ;
169
+ }
170
+
171
+ /**
172
+ * @type {number }
173
+ */
174
+ get asyncId ( ) {
175
+ if ( this [ kAsyncResource ] === undefined )
176
+ throw new ERR_INVALID_THIS ( 'EventEmitterAsyncResource' ) ;
177
+ return this . asyncResource . asyncId ( ) ;
178
+ }
179
+
180
+ /**
181
+ * @type {number }
182
+ */
183
+ get triggerAsyncId ( ) {
184
+ if ( this [ kAsyncResource ] === undefined )
185
+ throw new ERR_INVALID_THIS ( 'EventEmitterAsyncResource' ) ;
186
+ return this . asyncResource . triggerAsyncId ( ) ;
187
+ }
188
+
189
+ /**
190
+ * @type {EventEmitterReferencingAsyncResource }
191
+ */
192
+ get asyncResource ( ) {
193
+ if ( this [ kAsyncResource ] === undefined )
194
+ throw new ERR_INVALID_THIS ( 'EventEmitterAsyncResource' ) ;
195
+ return this [ kAsyncResource ] ;
196
+ }
197
+ } ;
198
+ }
199
+ return EventEmitterAsyncResource ;
200
+ }
201
+
79
202
/**
80
203
* Creates a new `EventEmitter` instance.
81
204
* @param {{ captureRejections?: boolean; } } [opts]
@@ -106,6 +229,13 @@ ObjectDefineProperty(EventEmitter, 'captureRejections', {
106
229
enumerable : true
107
230
} ) ;
108
231
232
+ ObjectDefineProperty ( EventEmitter , 'EventEmitterAsyncResource' , {
233
+ enumerable : true ,
234
+ get : lazyEventEmitterAsyncResource ,
235
+ set : undefined ,
236
+ configurable : true ,
237
+ } ) ;
238
+
109
239
EventEmitter . errorMonitor = kErrorMonitor ;
110
240
111
241
// The default for captureRejections is false
0 commit comments