@@ -1129,6 +1129,55 @@ describe("downloadToTemp atomic publication and bounded retry", () => {
11291129 expect ( temporaryDownloadEntries ( dir ) ) . toEqual ( [ ] ) ;
11301130 } ) ;
11311131
1132+ it ( "keeps the deadline active when a stalled body never observes the abort" , async ( ) => {
1133+ // Bun 1.3.9's Readable.fromWeb can stop reading mid-body; the fetch abort then never
1134+ // reaches the pipeline. Model that with a body that neither ends nor errors on abort.
1135+ const fetchMock = vi
1136+ . fn ( )
1137+ . mockImplementationOnce ( async ( ) => {
1138+ const stalledBody = new ReadableStream < Uint8Array > ( {
1139+ start ( controller ) {
1140+ controller . enqueue ( new TextEncoder ( ) . encode ( "partial" ) ) ;
1141+ } ,
1142+ } ) ;
1143+ return new Response ( stalledBody ) ;
1144+ } )
1145+ . mockResolvedValueOnce ( new Response ( "complete" ) ) ;
1146+ vi . stubGlobal ( "fetch" , fetchMock ) ;
1147+ const dir = makeTempDir ( ) ;
1148+
1149+ const path = await downloadToTemp ( "https://cdn.example/unresponsive-body.mp4" , dir , 20 ) ;
1150+
1151+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 2 ) ;
1152+ expect ( readFileSync ( path , "utf8" ) ) . toBe ( "complete" ) ;
1153+ expect ( temporaryDownloadEntries ( dir ) ) . toEqual ( [ ] ) ;
1154+ } ) ;
1155+
1156+ it ( "does not publish a chunked body that ended because the deadline aborted it" , async ( ) => {
1157+ // Bun 1.4.2 ends an aborted fetch body as if it were complete. With no Content-Length
1158+ // there is no length check to catch the truncation.
1159+ const fetchMock = vi
1160+ . fn ( )
1161+ . mockImplementationOnce ( async ( _url : string , init : RequestInit ) => {
1162+ const truncatedBody = new ReadableStream < Uint8Array > ( {
1163+ start ( controller ) {
1164+ controller . enqueue ( new TextEncoder ( ) . encode ( "partial" ) ) ;
1165+ init . signal ?. addEventListener ( "abort" , ( ) => controller . close ( ) , { once : true } ) ;
1166+ } ,
1167+ } ) ;
1168+ return new Response ( truncatedBody ) ;
1169+ } )
1170+ . mockResolvedValueOnce ( new Response ( "complete" ) ) ;
1171+ vi . stubGlobal ( "fetch" , fetchMock ) ;
1172+ const dir = makeTempDir ( ) ;
1173+
1174+ const path = await downloadToTemp ( "https://cdn.example/aborted-chunked-body.mp4" , dir , 20 ) ;
1175+
1176+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 2 ) ;
1177+ expect ( readFileSync ( path , "utf8" ) ) . toBe ( "complete" ) ;
1178+ expect ( temporaryDownloadEntries ( dir ) ) . toEqual ( [ ] ) ;
1179+ } ) ;
1180+
11321181 it ( "retries a zero-byte 200 response without publishing it" , async ( ) => {
11331182 const fetchMock = vi
11341183 . fn ( )
0 commit comments