File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -44,6 +44,11 @@ export class StdioServerTransport implements Transport {
4444 // Ignore errors during close — we're already in an error path
4545 } ) ;
4646 } ;
47+ _onstdinclose = ( ) => {
48+ this . close ( ) . catch ( ( ) => {
49+ // Ignore errors during close — stdin pipe ended
50+ } ) ;
51+ } ;
4752
4853 /**
4954 * Starts listening for messages on `stdin`.
@@ -58,6 +63,7 @@ export class StdioServerTransport implements Transport {
5863 this . _started = true ;
5964 this . _stdin . on ( 'data' , this . _ondata ) ;
6065 this . _stdin . on ( 'error' , this . _onerror ) ;
66+ this . _stdin . on ( 'close' , this . _onstdinclose ) ;
6167 this . _stdout . on ( 'error' , this . _onstdouterror ) ;
6268 }
6369
@@ -85,6 +91,7 @@ export class StdioServerTransport implements Transport {
8591 // Remove our event listeners first
8692 this . _stdin . off ( 'data' , this . _ondata ) ;
8793 this . _stdin . off ( 'error' , this . _onerror ) ;
94+ this . _stdin . off ( 'close' , this . _onstdinclose ) ;
8895 this . _stdout . off ( 'error' , this . _onstdouterror ) ;
8996
9097 // Check if we were the only data listener
Original file line number Diff line number Diff line change @@ -179,3 +179,46 @@ test('should fire onerror before onclose on stdout error', async () => {
179179
180180 expect ( events ) . toEqual ( [ 'error' , 'close' ] ) ;
181181} ) ;
182+
183+ test ( 'should fire onclose when stdin emits close' , async ( ) => {
184+ const server = new StdioServerTransport ( input , output ) ;
185+ server . onerror = error => { throw error ; } ;
186+
187+ let closeCount = 0 ;
188+ server . onclose = ( ) => { closeCount ++ ; } ;
189+
190+ await server . start ( ) ;
191+ input . emit ( 'close' ) ;
192+
193+ expect ( closeCount ) . toBe ( 1 ) ;
194+ } ) ;
195+
196+ test ( 'should fire onclose when stdin emits end' , async ( ) => {
197+ const server = new StdioServerTransport ( input , output ) ;
198+ server . onerror = error => { throw error ; } ;
199+
200+ let closeCount = 0 ;
201+ server . onclose = ( ) => { closeCount ++ ; } ;
202+
203+ await server . start ( ) ;
204+ input . push ( null ) ; // signals end-of-stream
205+
206+ // Allow microtasks to flush
207+ await new Promise ( resolve => setTimeout ( resolve , 0 ) ) ;
208+
209+ expect ( closeCount ) . toBe ( 1 ) ;
210+ } ) ;
211+
212+ test ( 'should not fire onclose twice when close() called after stdin close' , async ( ) => {
213+ const server = new StdioServerTransport ( input , output ) ;
214+ server . onerror = ( ) => { } ;
215+
216+ let closeCount = 0 ;
217+ server . onclose = ( ) => { closeCount ++ ; } ;
218+
219+ await server . start ( ) ;
220+ input . emit ( 'close' ) ;
221+ await server . close ( ) ;
222+
223+ expect ( closeCount ) . toBe ( 1 ) ;
224+ } ) ;
You can’t perform that action at this time.
0 commit comments