@@ -14,18 +14,18 @@ const {
14
14
15
15
const { internalBinding } = require ( 'internal/bootstrap/loaders' ) ;
16
16
const { MessagePort, MessageChannel } = internalBinding ( 'messaging' ) ;
17
- const { handle_onclose } = internalBinding ( 'symbols' ) ;
17
+ const {
18
+ handle_onclose : handleOnCloseSymbol ,
19
+ oninit : onInitSymbol
20
+ } = internalBinding ( 'symbols' ) ;
18
21
const { clearAsyncIdStack } = require ( 'internal/async_hooks' ) ;
19
22
const { serializeError, deserializeError } = require ( 'internal/error-serdes' ) ;
20
23
const { pathToFileURL } = require ( 'url' ) ;
21
24
22
- util . inherits ( MessagePort , EventEmitter ) ;
23
-
24
25
const {
25
26
Worker : WorkerImpl ,
26
27
getEnvMessagePort,
27
- threadId,
28
- oninit : oninit_symbol
28
+ threadId
29
29
} = internalBinding ( 'worker' ) ;
30
30
31
31
const isMainThread = threadId === 0 ;
@@ -58,6 +58,23 @@ const messageTypes = {
58
58
LOAD_SCRIPT : 'loadScript'
59
59
} ;
60
60
61
+ // We have to mess with the MessagePort prototype a bit, so that a) we can make
62
+ // it inherit from EventEmitter, even though it is a C++ class, and b) we do
63
+ // not provide methods that are not present in the Browser and not documented
64
+ // on our side (e.g. hasRef).
65
+ // Save a copy of the original set of methods as a shallow clone.
66
+ const MessagePortPrototype = Object . create (
67
+ Object . getPrototypeOf ( MessagePort . prototype ) ,
68
+ Object . getOwnPropertyDescriptors ( MessagePort . prototype ) ) ;
69
+ // Set up the new inheritance chain.
70
+ Object . setPrototypeOf ( MessagePort , EventEmitter ) ;
71
+ Object . setPrototypeOf ( MessagePort . prototype , EventEmitter . prototype ) ;
72
+ // Finally, purge methods we don't want to be public.
73
+ delete MessagePort . prototype . stop ;
74
+ delete MessagePort . prototype . drain ;
75
+ delete MessagePort . prototype . hasRef ;
76
+ delete MessagePort . prototype . getAsyncId ;
77
+
61
78
// A communication channel consisting of a handle (that wraps around an
62
79
// uv_async_t) which can receive information from other threads and emits
63
80
// .onmessage events, and a function used for sending data to a MessagePort
@@ -81,10 +98,10 @@ Object.defineProperty(MessagePort.prototype, 'onmessage', {
81
98
this [ kOnMessageListener ] = value ;
82
99
if ( typeof value === 'function' ) {
83
100
this . ref ( ) ;
84
- this . start ( ) ;
101
+ MessagePortPrototype . start . call ( this ) ;
85
102
} else {
86
103
this . unref ( ) ;
87
- this . stop ( ) ;
104
+ MessagePortPrototype . stop . call ( this ) ;
88
105
}
89
106
}
90
107
} ) ;
@@ -94,7 +111,7 @@ function oninit() {
94
111
setupPortReferencing ( this , this , 'message' ) ;
95
112
}
96
113
97
- Object . defineProperty ( MessagePort . prototype , oninit_symbol , {
114
+ Object . defineProperty ( MessagePort . prototype , onInitSymbol , {
98
115
enumerable : true ,
99
116
writable : false ,
100
117
value : oninit
@@ -111,22 +128,18 @@ function onclose() {
111
128
this . emit ( 'close' ) ;
112
129
}
113
130
114
- Object . defineProperty ( MessagePort . prototype , handle_onclose , {
131
+ Object . defineProperty ( MessagePort . prototype , handleOnCloseSymbol , {
115
132
enumerable : false ,
116
133
writable : false ,
117
134
value : onclose
118
135
} ) ;
119
136
120
- const originalClose = MessagePort . prototype . close ;
121
137
MessagePort . prototype . close = function ( cb ) {
122
138
if ( typeof cb === 'function' )
123
139
this . once ( 'close' , cb ) ;
124
- originalClose . call ( this ) ;
140
+ MessagePortPrototype . close . call ( this ) ;
125
141
} ;
126
142
127
- const drainMessagePort = MessagePort . prototype . drain ;
128
- delete MessagePort . prototype . drain ;
129
-
130
143
Object . defineProperty ( MessagePort . prototype , util . inspect . custom , {
131
144
enumerable : false ,
132
145
writable : false ,
@@ -135,7 +148,7 @@ Object.defineProperty(MessagePort.prototype, util.inspect.custom, {
135
148
try {
136
149
// This may throw when `this` does not refer to a native object,
137
150
// e.g. when accessing the prototype directly.
138
- ref = this . hasRef ( ) ;
151
+ ref = MessagePortPrototype . hasRef . call ( this ) ;
139
152
} catch { return this ; }
140
153
return Object . assign ( Object . create ( MessagePort . prototype ) ,
141
154
ref === undefined ? {
@@ -157,12 +170,12 @@ function setupPortReferencing(port, eventEmitter, eventName) {
157
170
eventEmitter . on ( 'newListener' , ( name ) => {
158
171
if ( name === eventName && eventEmitter . listenerCount ( eventName ) === 0 ) {
159
172
port . ref ( ) ;
160
- port . start ( ) ;
173
+ MessagePortPrototype . start . call ( port ) ;
161
174
}
162
175
} ) ;
163
176
eventEmitter . on ( 'removeListener' , ( name ) => {
164
177
if ( name === eventName && eventEmitter . listenerCount ( eventName ) === 0 ) {
165
- port . stop ( ) ;
178
+ MessagePortPrototype . stop . call ( port ) ;
166
179
port . unref ( ) ;
167
180
}
168
181
} ) ;
@@ -304,7 +317,7 @@ class Worker extends EventEmitter {
304
317
305
318
[ kOnExit ] ( code ) {
306
319
debug ( `[${ threadId } ] hears end event for Worker ${ this . threadId } ` ) ;
307
- drainMessagePort . call ( this [ kPublicPort ] ) ;
320
+ MessagePortPrototype . drain . call ( this [ kPublicPort ] ) ;
308
321
this [ kDispose ] ( ) ;
309
322
this . emit ( 'exit' , code ) ;
310
323
this . removeAllListeners ( ) ;
0 commit comments