44
55import { ChildProcessWithoutNullStreams , spawn } from 'child_process' ;
66import { inject , injectable } from 'inversify' ;
7- import split from 'split2' ;
8- import { Transform } from 'stream' ;
97import { EnvironmentVars } from '../../common/environmentVars' ;
108import { ILogger } from '../../common/logging' ;
9+ import { StreamSplitter } from '../../common/streamSplitter' ;
1110import * as urlUtils from '../../common/urlUtils' ;
1211import { INodeLaunchConfiguration , OutputSource } from '../../configuration' ;
1312import Dap from '../../dap/api' ;
1413import { ILaunchContext } from '../targets' ;
15- import { getNodeLaunchArgs , IProgramLauncher } from './processLauncher' ;
14+ import { IProgramLauncher , getNodeLaunchArgs } from './processLauncher' ;
1615import { SubprocessProgram } from './program' ;
1716
1817/**
@@ -64,12 +63,12 @@ export class SubprocessProgramLauncher implements IProgramLauncher {
6463 */
6564 private captureStdio ( dap : Dap . Api , child : ChildProcessWithoutNullStreams ) {
6665 child . stdout
67- . pipe ( EtxSplitter . stream ( ) )
68- . on ( 'data' , output => dap . output ( { category : 'stdout' , output } ) )
66+ . pipe ( new EtxSplitter ( ) )
67+ . on ( 'data' , output => dap . output ( { category : 'stdout' , output : output . toString ( ) } ) )
6968 . resume ( ) ;
7069 child . stderr
71- . pipe ( EtxSplitter . stream ( ) )
72- . on ( 'data' , output => dap . output ( { category : 'stderr' , output } ) )
70+ . pipe ( new EtxSplitter ( ) )
71+ . on ( 'data' , output => dap . output ( { category : 'stderr' , output : output . toString ( ) } ) )
7372 . resume ( ) ;
7473 }
7574
@@ -158,7 +157,7 @@ const formatArguments = (executable: string, args: ReadonlyArray<string>, cwd: s
158157} ;
159158
160159const enum Char {
161- ETX = '\u0003' ,
160+ ETX = 3 ,
162161}
163162
164163/**
@@ -168,22 +167,28 @@ const enum Char {
168167 * finds any, it will switch from splitting the stream on newlines to
169168 * splitting on ETX characters.
170169 */
171- export class EtxSplitter {
170+ export class EtxSplitter extends StreamSplitter {
172171 private etxSpotted = false ;
173172
174- public static stream ( ) : Transform {
175- return split ( new EtxSplitter ( ) ) ;
173+ constructor ( ) {
174+ super ( Char . ETX ) ;
175+ this . splitSuffix = Buffer . from ( '\n' ) ;
176176 }
177177
178- [ Symbol . split ] ( str : string ) {
179- this . etxSpotted ||= str . includes ( Char . ETX ) ;
180- if ( ! this . etxSpotted ) {
181- return [ str , '' ] ;
178+ override _transform (
179+ chunk : Buffer ,
180+ _encoding : string ,
181+ callback : ( error ?: Error | null | undefined , data ?: unknown ) => void ,
182+ ) : void {
183+ if ( ! this . etxSpotted && chunk . includes ( Char . ETX ) ) {
184+ this . etxSpotted = true ;
182185 }
183186
184- const split = str . split ( Char . ETX ) ;
187+ if ( ! this . etxSpotted ) {
188+ this . push ( chunk ) ;
189+ return callback ( ) ;
190+ }
185191
186- // restore or add new lines between each record for proper debug console display
187- return split . length > 1 ? split . map ( ( s , i ) => ( i < split . length - 1 ? `${ s } \n` : s ) ) : split ;
192+ return super . _transform ( chunk , _encoding , callback ) ;
188193 }
189194}
0 commit comments