44 JSONParse,
55 JSONStringify,
66 StringPrototypeSplit,
7+ ArrayPrototypePush,
8+ ReflectApply,
79 Symbol,
810 TypedArrayPrototypeSubarray,
911} = primordials ;
@@ -13,8 +15,10 @@ const v8 = require('v8');
1315const { isArrayBufferView } = require ( 'internal/util/types' ) ;
1416const assert = require ( 'internal/assert' ) ;
1517const { streamBaseState, kLastWriteWasAsync } = internalBinding ( 'stream_wrap' ) ;
18+ const { readUInt32BE } = require ( 'internal/buffer' ) ;
1619
1720const kMessageBuffer = Symbol ( 'kMessageBuffer' ) ;
21+ const kMessageBufferSize = Symbol ( 'kMessageBufferSize' ) ;
1822const kJSONBuffer = Symbol ( 'kJSONBuffer' ) ;
1923const kStringDecoder = Symbol ( 'kStringDecoder' ) ;
2024
@@ -51,29 +55,47 @@ class ChildProcessDeserializer extends v8.DefaultDeserializer {
5155// (aka 'advanced')
5256const advanced = {
5357 initMessageChannel ( channel ) {
54- channel [ kMessageBuffer ] = Buffer . alloc ( 0 ) ;
58+ channel [ kMessageBuffer ] = [ ] ;
59+ channel [ kMessageBufferSize ] = 0 ;
5560 channel . buffering = false ;
5661 } ,
5762
5863 * parseChannelMessages ( channel , readData ) {
5964 if ( readData . length === 0 ) return ;
6065
61- let messageBuffer = Buffer . concat ( [ channel [ kMessageBuffer ] , readData ] ) ;
62- while ( messageBuffer . length > 4 ) {
63- const size = messageBuffer . readUInt32BE ( ) ;
64- if ( messageBuffer . length < 4 + size ) {
65- break ;
66- }
66+ ArrayPrototypePush ( channel [ kMessageBuffer ] , readData ) ;
67+ channel [ kMessageBufferSize ] += readData . length ;
68+
69+ // Index 0 should always be present because we just pushed data into it.
70+ let messageBufferHead = channel [ kMessageBuffer ] [ 0 ] ;
71+ while ( messageBufferHead . length >= 4 ) {
72+ // We call `readUInt32BE` manually here, because this is faster than first converting
73+ // it to a buffer and using `readUInt32BE` on that.
74+ const fullMessageSize = ReflectApply ( readUInt32BE , messageBufferHead , [ 0 ] ) + 4 ;
75+
76+ if ( channel [ kMessageBufferSize ] < fullMessageSize ) break ;
77+
78+ const concatenatedBuffer = channel [ kMessageBuffer ] . length === 1 ?
79+ channel [ kMessageBuffer ] [ 0 ] :
80+ Buffer . concat (
81+ channel [ kMessageBuffer ] ,
82+ channel [ kMessageBufferSize ]
83+ ) ;
6784
6885 const deserializer = new ChildProcessDeserializer (
69- TypedArrayPrototypeSubarray ( messageBuffer , 4 , 4 + size ) ) ;
70- messageBuffer = TypedArrayPrototypeSubarray ( messageBuffer , 4 + size ) ;
86+ TypedArrayPrototypeSubarray ( concatenatedBuffer , 4 , fullMessageSize )
87+ ) ;
88+
89+ messageBufferHead = TypedArrayPrototypeSubarray ( concatenatedBuffer , fullMessageSize ) ;
90+ channel [ kMessageBufferSize ] = messageBufferHead . length ;
91+ channel [ kMessageBuffer ] =
92+ channel [ kMessageBufferSize ] !== 0 ? [ messageBufferHead ] : [ ] ;
7193
7294 deserializer . readHeader ( ) ;
7395 yield deserializer . readValue ( ) ;
7496 }
75- channel [ kMessageBuffer ] = messageBuffer ;
76- channel . buffering = messageBuffer . length > 0 ;
97+
98+ channel . buffering = channel [ kMessageBufferSize ] > 0 ;
7799 } ,
78100
79101 writeChannelMessage ( channel , req , message , handle ) {
0 commit comments