diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 40592146ada6de..120b81c37dc9e1 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -13,6 +13,7 @@ const { StringPrototypeSlice, Symbol, Uint8Array, + SafeSet, } = primordials; const { @@ -81,6 +82,7 @@ let HTTPParser; const MAX_HANDLE_RETRANSMISSIONS = 3; const kChannelHandle = Symbol('kChannelHandle'); const kIsUsedAsStdio = Symbol('kIsUsedAsStdio'); +const kPendingMessages = Symbol('pendingMessages'); // This object contain function to convert TCP objects to native handle objects // and back again. @@ -526,6 +528,7 @@ class Control extends EventEmitter { constructor(channel) { super(); this.#channel = channel; + this[kPendingMessages] = new SafeSet(); } // The methods keeping track of the counter are being used to track the @@ -699,6 +702,19 @@ function setupChannel(target, channel, serializationMode) { }); }); + target.on('newListener', function () { + if(!target.channel) return; + + const messages = target.channel[kPendingMessages]; + if (!messages.size) return; + + for (const messageParams of messages) { + process.nextTick(() => ReflectApply(target.emit, target, messageParams)); + } + + messages.clear(); + }); + target.send = function(message, handle, options, callback) { if (typeof handle === 'function') { callback = handle; @@ -912,7 +928,15 @@ function setupChannel(target, channel, serializationMode) { }; function emit(event, message, handle) { - target.emit(event, message, handle); + const args = [event, message, handle]; + const isInternalMessage = "internalMessage" === event; + const hasListenersInstalled = target.listenerCount('message'); + if (hasListenersInstalled || isInternalMessage) { + target.emit(event, message, handle); + return; + } + + target.channel[kPendingMessages].add(args); } function handleMessage(message, handle, internal) {