@@ -14,18 +14,18 @@ const {
1414
1515const { internalBinding } = require ( 'internal/bootstrap/loaders' ) ;
1616const { MessagePort, MessageChannel } = internalBinding ( 'messaging' ) ;
17- const { handle_onclose } = internalBinding ( 'symbols' ) ;
17+ const {
18+ handle_onclose : handleOnCloseSymbol ,
19+ oninit : onInitSymbol
20+ } = internalBinding ( 'symbols' ) ;
1821const { clearAsyncIdStack } = require ( 'internal/async_hooks' ) ;
1922const { serializeError, deserializeError } = require ( 'internal/error-serdes' ) ;
2023const { pathToFileURL } = require ( 'url' ) ;
2124
22- util . inherits ( MessagePort , EventEmitter ) ;
23-
2425const {
2526 Worker : WorkerImpl ,
2627 getEnvMessagePort,
27- threadId,
28- oninit : oninit_symbol
28+ threadId
2929} = internalBinding ( 'worker' ) ;
3030
3131const isMainThread = threadId === 0 ;
@@ -58,6 +58,23 @@ const messageTypes = {
5858 LOAD_SCRIPT : 'loadScript'
5959} ;
6060
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+
6178// A communication channel consisting of a handle (that wraps around an
6279// uv_async_t) which can receive information from other threads and emits
6380// .onmessage events, and a function used for sending data to a MessagePort
@@ -81,10 +98,10 @@ Object.defineProperty(MessagePort.prototype, 'onmessage', {
8198 this [ kOnMessageListener ] = value ;
8299 if ( typeof value === 'function' ) {
83100 this . ref ( ) ;
84- this . start ( ) ;
101+ MessagePortPrototype . start . call ( this ) ;
85102 } else {
86103 this . unref ( ) ;
87- this . stop ( ) ;
104+ MessagePortPrototype . stop . call ( this ) ;
88105 }
89106 }
90107} ) ;
@@ -94,7 +111,7 @@ function oninit() {
94111 setupPortReferencing ( this , this , 'message' ) ;
95112}
96113
97- Object . defineProperty ( MessagePort . prototype , oninit_symbol , {
114+ Object . defineProperty ( MessagePort . prototype , onInitSymbol , {
98115 enumerable : true ,
99116 writable : false ,
100117 value : oninit
@@ -111,22 +128,18 @@ function onclose() {
111128 this . emit ( 'close' ) ;
112129}
113130
114- Object . defineProperty ( MessagePort . prototype , handle_onclose , {
131+ Object . defineProperty ( MessagePort . prototype , handleOnCloseSymbol , {
115132 enumerable : false ,
116133 writable : false ,
117134 value : onclose
118135} ) ;
119136
120- const originalClose = MessagePort . prototype . close ;
121137MessagePort . prototype . close = function ( cb ) {
122138 if ( typeof cb === 'function' )
123139 this . once ( 'close' , cb ) ;
124- originalClose . call ( this ) ;
140+ MessagePortPrototype . close . call ( this ) ;
125141} ;
126142
127- const drainMessagePort = MessagePort . prototype . drain ;
128- delete MessagePort . prototype . drain ;
129-
130143Object . defineProperty ( MessagePort . prototype , util . inspect . custom , {
131144 enumerable : false ,
132145 writable : false ,
@@ -135,7 +148,7 @@ Object.defineProperty(MessagePort.prototype, util.inspect.custom, {
135148 try {
136149 // This may throw when `this` does not refer to a native object,
137150 // e.g. when accessing the prototype directly.
138- ref = this . hasRef ( ) ;
151+ ref = MessagePortPrototype . hasRef . call ( this ) ;
139152 } catch { return this ; }
140153 return Object . assign ( Object . create ( MessagePort . prototype ) ,
141154 ref === undefined ? {
@@ -157,12 +170,12 @@ function setupPortReferencing(port, eventEmitter, eventName) {
157170 eventEmitter . on ( 'newListener' , ( name ) => {
158171 if ( name === eventName && eventEmitter . listenerCount ( eventName ) === 0 ) {
159172 port . ref ( ) ;
160- port . start ( ) ;
173+ MessagePortPrototype . start . call ( port ) ;
161174 }
162175 } ) ;
163176 eventEmitter . on ( 'removeListener' , ( name ) => {
164177 if ( name === eventName && eventEmitter . listenerCount ( eventName ) === 0 ) {
165- port . stop ( ) ;
178+ MessagePortPrototype . stop . call ( port ) ;
166179 port . unref ( ) ;
167180 }
168181 } ) ;
@@ -304,7 +317,7 @@ class Worker extends EventEmitter {
304317
305318 [ kOnExit ] ( code ) {
306319 debug ( `[${ threadId } ] hears end event for Worker ${ this . threadId } ` ) ;
307- drainMessagePort . call ( this [ kPublicPort ] ) ;
320+ MessagePortPrototype . drain . call ( this [ kPublicPort ] ) ;
308321 this [ kDispose ] ( ) ;
309322 this . emit ( 'exit' , code ) ;
310323 this . removeAllListeners ( ) ;
0 commit comments