@@ -44,6 +44,7 @@ const waitForExit = async (
4444const waitForText = async (
4545 stream : ReadableStream < Uint8Array > | null ,
4646 expected : string ,
47+ timeoutMs : number ,
4748) : Promise < {
4849 seen : string ;
4950 remainder : Promise < string > ;
@@ -54,14 +55,27 @@ const waitForText = async (
5455 const reader = stream . getReader ( ) ;
5556 const decoder = new TextDecoder ( ) ;
5657 let seen = "" ;
58+ let timeoutId : ReturnType < typeof setTimeout > | undefined ;
5759
5860 try {
59- while ( ! seen . includes ( expected ) ) {
60- const { value, done } = await reader . read ( ) ;
61- if ( done ) break ;
62- if ( ! value ) continue ;
63- seen += decoder . decode ( value , { stream : true } ) ;
64- }
61+ await Promise . race ( [
62+ ( async ( ) => {
63+ while ( ! seen . includes ( expected ) ) {
64+ const { value, done } = await reader . read ( ) ;
65+ if ( done ) break ;
66+ if ( ! value ) continue ;
67+ seen += decoder . decode ( value , { stream : true } ) ;
68+ }
69+ } ) ( ) ,
70+ new Promise < never > ( ( _ , reject ) => {
71+ timeoutId = setTimeout ( ( ) => {
72+ void reader . cancel ( ) ;
73+ reject (
74+ new Error ( `timed out waiting for ${ JSON . stringify ( expected ) } ` ) ,
75+ ) ;
76+ } , timeoutMs ) ;
77+ } ) ,
78+ ] ) ;
6579 seen += decoder . decode ( ) ;
6680
6781 const remainder = ( async ( ) => {
@@ -84,6 +98,8 @@ const waitForText = async (
8498 } catch ( error ) {
8599 reader . releaseLock ( ) ;
86100 throw error ;
101+ } finally {
102+ if ( timeoutId !== undefined ) clearTimeout ( timeoutId ) ;
87103 }
88104} ;
89105
@@ -99,7 +115,7 @@ Deno.test({
99115 stderr : "piped" ,
100116 } ) . spawn ( ) ;
101117
102- const stdoutState = await waitForText ( child . stdout , "ready\n" ) ;
118+ const stdoutState = await waitForText ( child . stdout , "ready\n" , 2_000 ) ;
103119 const stderrPromise = new Response ( child . stderr ) . text ( ) ;
104120
105121 child . kill ( "SIGINT" ) ;
0 commit comments