@@ -17,6 +17,11 @@ let totalAssetsToDownload = 0;
1717let loadBootResourceCallback : LoadBootResourceCallback | undefined = undefined ;
1818const loadedLazyAssemblies = new Set < string > ( ) ;
1919let mainWasmAsset : WasmAsset | null = null ;
20+ const allDownloadsQueuedPCS = createPromiseCompletionSource < void > ( ) ;
21+
22+ export function resolveAllDownloadsQueued ( ) : void {
23+ allDownloadsQueuedPCS . resolve ( ) ;
24+ }
2025
2126export function setLoadBootResourceCallback ( callback : LoadBootResourceCallback | undefined ) : void {
2227 loadBootResourceCallback = callback ;
@@ -332,7 +337,14 @@ export async function fetchNativeSymbols(asset: SymbolsAsset): Promise<void> {
332337
333338async function fetchBytes ( asset : AssetEntryInternal ) : Promise < Uint8Array | null > {
334339 dotnetAssert . check ( asset && asset . resolvedUrl , "Bad asset.resolvedUrl" ) ;
335- const response = await loadResource ( asset ) ;
340+ let response : Response ;
341+ try {
342+ response = await loadResource ( asset ) ;
343+ } catch ( err : any ) {
344+ // Strip .silent flag from download errors so they are properly reported via exit listeners
345+ const message = err instanceof Error ? err . message : String ( err ) ;
346+ throw new Error ( `Failed to load resource '${ asset . name } ' from '${ asset . resolvedUrl } ': ${ message } ` , { cause : err } ) ;
347+ }
336348 if ( ! response . ok ) {
337349 if ( asset . isOptional ) {
338350 dotnetLogger . warn ( `Optional resource '${ asset . name } ' failed to load from '${ asset . resolvedUrl } '. HTTP status: ${ response . status } ${ response . statusText } ` ) ;
@@ -346,7 +358,14 @@ async function fetchBytes(asset: AssetEntryInternal): Promise<Uint8Array | null>
346358
347359async function fetchText ( asset : AssetEntryInternal ) : Promise < string | null > {
348360 dotnetAssert . check ( asset && asset . resolvedUrl , "Bad asset.resolvedUrl" ) ;
349- const response = await loadResource ( asset ) ;
361+ let response : Response ;
362+ try {
363+ response = await loadResource ( asset ) ;
364+ } catch ( err : any ) {
365+ // Strip .silent flag from download errors so they are properly reported via exit listeners
366+ const message = err instanceof Error ? err . message : String ( err ) ;
367+ throw new Error ( `Failed to load resource '${ asset . name } ' from '${ asset . resolvedUrl } ': ${ message } ` , { cause : err } ) ;
368+ }
350369 if ( ! response . ok ) {
351370 if ( asset . isOptional ) {
352371 dotnetLogger . warn ( `Optional resource '${ asset . name } ' failed to load from '${ asset . resolvedUrl } '. HTTP status: ${ response . status } ${ response . statusText } ` ) ;
@@ -377,15 +396,19 @@ async function loadResourceRetry(asset: AssetEntryInternal): Promise<Response> {
377396 if ( response . ok || asset . isOptional || noRetryStatusCodes . has ( response . status ) ) {
378397 return response ;
379398 }
399+ // second attempt only after all first attempts are queued
400+ await allDownloadsQueuedPCS . promise ;
380401 if ( response . status === 429 ) {
381402 // Too Many Requests
382403 await delay ( 100 ) ;
383404 }
405+ dotnetLogger . debug ( `Retrying download '${ asset . name } '` ) ;
384406 response = await loadResourceAttempt ( ) ;
385407 if ( response . ok || noRetryStatusCodes . has ( response . status ) ) {
386408 return response ;
387409 }
388410 await delay ( 100 ) ; // wait 100ms before the last retry
411+ dotnetLogger . debug ( `Retrying download (2) '${ asset . name } ' after delay` ) ;
389412 response = await loadResourceAttempt ( ) ;
390413 if ( response . ok ) {
391414 return response ;
0 commit comments