1
1
'use strict' ;
2
2
3
- const { JSON , Object } = primordials ;
3
+ const { Object } = primordials ;
4
4
5
5
const {
6
6
errnoException,
@@ -55,8 +55,6 @@ const {
55
55
56
56
const { SocketListSend, SocketListReceive } = SocketList ;
57
57
58
- // Lazy loaded for startup performance.
59
- let StringDecoder ;
60
58
// Lazy loaded for startup performance and to allow monkey patching of
61
59
// internalBinding('http_parser').HTTPParser.
62
60
let freeParser ;
@@ -343,6 +341,15 @@ ChildProcess.prototype.spawn = function(options) {
343
341
const ipcFd = stdio . ipcFd ;
344
342
stdio = options . stdio = stdio . stdio ;
345
343
344
+ if ( options . serialization !== undefined &&
345
+ options . serialization !== 'json' &&
346
+ options . serialization !== 'advanced' ) {
347
+ throw new ERR_INVALID_OPT_VALUE ( 'options.serialization' ,
348
+ options . serialization ) ;
349
+ }
350
+
351
+ const serialization = options . serialization || 'json' ;
352
+
346
353
if ( ipc !== undefined ) {
347
354
// Let child process know about opened IPC channel
348
355
if ( options . envPairs === undefined )
@@ -353,7 +360,8 @@ ChildProcess.prototype.spawn = function(options) {
353
360
options . envPairs ) ;
354
361
}
355
362
356
- options . envPairs . push ( 'NODE_CHANNEL_FD=' + ipcFd ) ;
363
+ options . envPairs . push ( `NODE_CHANNEL_FD=${ ipcFd } ` ) ;
364
+ options . envPairs . push ( `NODE_CHANNEL_SERIALIZATION_MODE=${ serialization } ` ) ;
357
365
}
358
366
359
367
validateString ( options . file , 'options.file' ) ;
@@ -446,7 +454,7 @@ ChildProcess.prototype.spawn = function(options) {
446
454
this . stdio . push ( stdio [ i ] . socket === undefined ? null : stdio [ i ] . socket ) ;
447
455
448
456
// Add .send() method and start listening for IPC data
449
- if ( ipc !== undefined ) setupChannel ( this , ipc ) ;
457
+ if ( ipc !== undefined ) setupChannel ( this , ipc , serialization ) ;
450
458
451
459
return err ;
452
460
} ;
@@ -516,7 +524,8 @@ class Control extends EventEmitter {
516
524
const channelDeprecationMsg = '_channel is deprecated. ' +
517
525
'Use ChildProcess.channel instead.' ;
518
526
519
- function setupChannel ( target , channel ) {
527
+ let serialization ;
528
+ function setupChannel ( target , channel , serializationMode ) {
520
529
target . channel = channel ;
521
530
522
531
Object . defineProperty ( target , '_channel' , {
@@ -535,12 +544,16 @@ function setupChannel(target, channel) {
535
544
536
545
const control = new Control ( channel ) ;
537
546
538
- if ( StringDecoder === undefined )
539
- StringDecoder = require ( 'string_decoder' ) . StringDecoder ;
540
- const decoder = new StringDecoder ( 'utf8' ) ;
541
- var jsonBuffer = '' ;
542
- var pendingHandle = null ;
543
- channel . buffering = false ;
547
+ if ( serialization === undefined )
548
+ serialization = require ( 'internal/child_process/serialization' ) ;
549
+ const {
550
+ initMessageChannel,
551
+ parseChannelMessages,
552
+ writeChannelMessage
553
+ } = serialization [ serializationMode ] ;
554
+
555
+ let pendingHandle = null ;
556
+ initMessageChannel ( channel ) ;
544
557
channel . pendingHandle = null ;
545
558
channel . onread = function ( arrayBuffer ) {
546
559
const recvHandle = channel . pendingHandle ;
@@ -552,21 +565,7 @@ function setupChannel(target, channel) {
552
565
if ( recvHandle )
553
566
pendingHandle = recvHandle ;
554
567
555
- // Linebreak is used as a message end sign
556
- var chunks = decoder . write ( pool ) . split ( '\n' ) ;
557
- var numCompleteChunks = chunks . length - 1 ;
558
- // Last line does not have trailing linebreak
559
- var incompleteChunk = chunks [ numCompleteChunks ] ;
560
- if ( numCompleteChunks === 0 ) {
561
- jsonBuffer += incompleteChunk ;
562
- this . buffering = jsonBuffer . length !== 0 ;
563
- return ;
564
- }
565
- chunks [ 0 ] = jsonBuffer + chunks [ 0 ] ;
566
-
567
- for ( var i = 0 ; i < numCompleteChunks ; i ++ ) {
568
- var message = JSON . parse ( chunks [ i ] ) ;
569
-
568
+ for ( const message of parseChannelMessages ( channel , pool ) ) {
570
569
// There will be at most one NODE_HANDLE message in every chunk we
571
570
// read because SCM_RIGHTS messages don't get coalesced. Make sure
572
571
// that we deliver the handle with the right message however.
@@ -581,9 +580,6 @@ function setupChannel(target, channel) {
581
580
handleMessage ( message , undefined , false ) ;
582
581
}
583
582
}
584
- jsonBuffer = incompleteChunk ;
585
- this . buffering = jsonBuffer . length !== 0 ;
586
-
587
583
} else {
588
584
this . buffering = false ;
589
585
target . disconnect ( ) ;
@@ -782,8 +778,7 @@ function setupChannel(target, channel) {
782
778
783
779
const req = new WriteWrap ( ) ;
784
780
785
- const string = JSON . stringify ( message ) + '\n' ;
786
- const err = channel . writeUtf8String ( req , string , handle ) ;
781
+ const err = writeChannelMessage ( channel , req , message , handle ) ;
787
782
const wasAsyncWrite = streamBaseState [ kLastWriteWasAsync ] ;
788
783
789
784
if ( err === 0 ) {
0 commit comments