2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
4
import { INTERNAL , Module , MONO , runtimeHelpers } from "./modules" ;
5
- import { AssetEntry , CharPtr , CharPtrNull , EmscriptenModuleMono , GlobalizationMode , MonoConfig , TypedArray , VoidPtr , wasm_type_symbol } from "./types" ;
5
+ import { AllAssetEntryTypes , AssetEntry , CharPtr , CharPtrNull , EmscriptenModuleMono , GlobalizationMode , MonoConfig , TypedArray , VoidPtr , wasm_type_symbol } from "./types" ;
6
6
import cwraps from "./cwraps" ;
7
7
import { mono_wasm_raise_debug_event , mono_wasm_runtime_ready } from "./debug" ;
8
8
import { mono_wasm_globalization_init , mono_wasm_load_icu_data } from "./icu" ;
@@ -56,7 +56,7 @@ export function mono_wasm_set_runtime_options(options: string[]): void {
56
56
cwraps . mono_wasm_parse_runtime_options ( options . length , argv ) ;
57
57
}
58
58
59
- function _handle_loaded_asset ( ctx : MonoInitContext , asset : AssetEntry , url : string , blob : ArrayBuffer ) {
59
+ function _handle_fetched_asset ( ctx : MonoInitContext , asset : AssetEntry , url : string , blob : ArrayBuffer ) {
60
60
const bytes = new Uint8Array ( blob ) ;
61
61
if ( ctx . tracing )
62
62
console . log ( `MONO_WASM: Loaded:${ asset . name } as ${ asset . behavior } size ${ bytes . length } from ${ url } ` ) ;
@@ -129,16 +129,6 @@ function _handle_loaded_asset(ctx: MonoInitContext, asset: AssetEntry, url: stri
129
129
}
130
130
}
131
131
132
- // Initializes the runtime and loads assemblies, debug information, and other files.
133
- export function mono_load_runtime_and_bcl_args ( args : MonoConfig ) : void {
134
- try {
135
- return _load_assets_and_runtime ( args ) ;
136
- } catch ( exc : any ) {
137
- console . error ( "MONO_WASM: Error in mono_load_runtime_and_bcl_args:" , exc ) ;
138
- throw exc ;
139
- }
140
- }
141
-
142
132
function _apply_configuration_from_args ( args : MonoConfig ) {
143
133
for ( const k in ( args . environment_variables || { } ) )
144
134
mono_wasm_setenv ( k , args . environment_variables ! [ k ] ) ;
@@ -153,7 +143,7 @@ function _apply_configuration_from_args(args: MonoConfig) {
153
143
mono_wasm_init_coverage_profiler ( args . coverage_profiler_options ) ;
154
144
}
155
145
156
- function _get_fetch_file_cb_from_args ( args : MonoConfig ) : ( asset : string ) => Promise < Response > {
146
+ function _get_fetch_implementation ( args : MonoConfig ) : ( asset : string ) => Promise < Response > {
157
147
if ( typeof ( args . fetch_file_cb ) === "function" )
158
148
return args . fetch_file_cb ;
159
149
@@ -307,136 +297,101 @@ export function bindings_lazy_init(): void {
307
297
308
298
_create_primitive_converters ( ) ;
309
299
}
310
- function _load_assets_and_runtime ( args : MonoConfig ) {
311
- if ( args . enable_debugging )
312
- args . debug_level = args . enable_debugging ;
313
-
314
- const ctx : MonoInitContext = {
315
- tracing : args . diagnostic_tracing || false ,
316
- pending_count : args . assets . length ,
317
- loaded_assets : Object . create ( null ) ,
318
- // dlls and pdbs, used by blazor and the debugger
319
- loaded_files : [ ] ,
320
- createPath : Module . FS_createPath ,
321
- createDataFile : Module . FS_createDataFile
322
- } ;
323
-
324
- if ( ctx . tracing )
325
- console . log ( "MONO_WASM: mono_wasm_load_runtime_with_args" , JSON . stringify ( args ) ) ;
326
-
327
- _apply_configuration_from_args ( args ) ;
328
300
329
- const fetch_file_cb = _get_fetch_file_cb_from_args ( args ) ;
330
-
331
- const onPendingRequestComplete = function ( ) {
332
- -- ctx . pending_count ;
333
-
334
- if ( ctx . pending_count === 0 ) {
335
- try {
336
- _finalize_startup ( args , ctx ) ;
337
- } catch ( exc : any ) {
338
- console . error ( "MONO_WASM: Unhandled exception in _finalize_startup" , exc ) ;
339
- console . error ( exc . stack ) ;
340
- throw exc ;
341
- }
342
- }
343
- } ;
301
+ // Initializes the runtime and loads assemblies, debug information, and other files.
302
+ export async function mono_load_runtime_and_bcl_args ( args : MonoConfig ) : Promise < void > {
303
+ try {
304
+ if ( args . enable_debugging )
305
+ args . debug_level = args . enable_debugging ;
306
+
307
+ const ctx : MonoInitContext = {
308
+ tracing : args . diagnostic_tracing || false ,
309
+ pending_count : args . assets . length ,
310
+ loaded_assets : Object . create ( null ) ,
311
+ // dlls and pdbs, used by blazor and the debugger
312
+ loaded_files : [ ] ,
313
+ createPath : Module . FS_createPath ,
314
+ createDataFile : Module . FS_createDataFile
315
+ } ;
344
316
345
- const processFetchResponseBuffer = function ( asset : AssetEntry , url : string , buffer : ArrayBuffer ) {
346
- try {
347
- _handle_loaded_asset ( ctx , asset , url , buffer ) ;
348
- } catch ( exc ) {
349
- console . error ( `MONO_WASM: Unhandled exception in processFetchResponseBuffer ${ url } ${ exc } ` ) ;
350
- throw exc ;
351
- } finally {
352
- onPendingRequestComplete ( ) ;
353
- }
354
- } ;
317
+ _apply_configuration_from_args ( args ) ;
355
318
356
- args . assets . forEach ( function ( asset : AssetEntry ) {
357
- let sourceIndex = 0 ;
358
- const sourcesList = asset . load_remote ? args . remote_sources ! : [ "" ] ;
319
+ const local_fetch = _get_fetch_implementation ( args ) ;
359
320
360
- const handleFetchResponse = function ( response : Response ) {
361
- if ( ! response . ok ) {
362
- try {
363
- attemptNextSource ( ) ;
364
- return ;
365
- } catch ( exc ) {
366
- console . error ( `MONO_WASM: Unhandled exception in handleFetchResponse attemptNextSource for asset ${ asset . name } ${ exc } ` ) ;
367
- throw exc ;
368
- }
369
- }
321
+ const load_asset = async ( asset : AllAssetEntryTypes ) : Promise < void > => {
322
+ //TODO we could do module.addRunDependency(asset.name) and delay emscripten run() after all assets are loaded
370
323
371
- try {
372
- const bufferPromise = response . arrayBuffer ( ) ;
373
- bufferPromise . then ( ( data ) => processFetchResponseBuffer ( asset , response . url , data ) ) ;
374
- } catch ( exc ) {
375
- console . error ( `MONO_WASM: Unhandled exception in handleFetchResponse for asset ${ asset . name } ${ exc } ` ) ;
376
- attemptNextSource ( ) ;
377
- }
378
- } ;
324
+ const sourcesList = asset . load_remote ? args . remote_sources ! : [ "" ] ;
325
+ let error = undefined ;
326
+ for ( let sourcePrefix of sourcesList ) {
327
+ // HACK: Special-case because MSBuild doesn't allow "" as an attribute
328
+ if ( sourcePrefix === "./" )
329
+ sourcePrefix = "" ;
379
330
380
- const attemptNextSource = function ( ) {
381
- if ( sourceIndex >= sourcesList . length ) {
382
- const msg = `MONO_WASM: Failed to load ${ asset . name } ` ;
383
- try {
384
- const isOk = asset . is_optional ||
385
- ( asset . name . match ( / \. p d b $ / ) && args . ignore_pdb_load_errors ) ;
386
-
387
- if ( isOk )
388
- console . debug ( msg ) ;
389
- else {
390
- console . error ( msg ) ;
391
- throw new Error ( msg ) ;
331
+ let attemptUrl ;
332
+ if ( sourcePrefix . trim ( ) === "" ) {
333
+ if ( asset . behavior === "assembly" )
334
+ attemptUrl = locateFile ( args . assembly_root + "/" + asset . name ) ;
335
+ else if ( asset . behavior === "resource" ) {
336
+ const path = asset . culture !== "" ? `${ asset . culture } /${ asset . name } ` : asset . name ;
337
+ attemptUrl = locateFile ( args . assembly_root + "/" + path ) ;
392
338
}
393
- } finally {
394
- onPendingRequestComplete ( ) ;
395
- }
396
- }
397
-
398
- let sourcePrefix = sourcesList [ sourceIndex ] ;
399
- sourceIndex ++ ;
400
-
401
- // HACK: Special-case because MSBuild doesn't allow "" as an attribute
402
- if ( sourcePrefix === "./" )
403
- sourcePrefix = "" ;
404
-
405
- let attemptUrl ;
406
- if ( sourcePrefix . trim ( ) === "" ) {
407
- if ( asset . behavior === "assembly" )
408
- attemptUrl = locateFile ( args . assembly_root + "/" + asset . name ) ;
409
- else if ( asset . behavior === "resource" ) {
410
- const path = asset . culture !== "" ? `${ asset . culture } /${ asset . name } ` : asset . name ;
411
- attemptUrl = locateFile ( args . assembly_root + "/" + path ) ;
339
+ else
340
+ attemptUrl = asset . name ;
341
+ } else {
342
+ attemptUrl = sourcePrefix + asset . name ;
412
343
}
413
- else
414
- attemptUrl = asset . name ;
415
- } else {
416
- attemptUrl = sourcePrefix + asset . name ;
417
- }
418
-
419
- try {
420
344
if ( asset . name === attemptUrl ) {
421
345
if ( ctx . tracing )
422
346
console . log ( `MONO_WASM: Attempting to fetch '${ attemptUrl } '` ) ;
423
347
} else {
424
348
if ( ctx . tracing )
425
349
console . log ( `MONO_WASM: Attempting to fetch '${ attemptUrl } ' for ${ asset . name } ` ) ;
426
350
}
427
- const fetch_promise = fetch_file_cb ( attemptUrl ) ;
428
- fetch_promise . then ( handleFetchResponse ) ;
429
- } catch ( exc ) {
430
- console . error ( `MONO_WASM: Error fetching ${ attemptUrl } ${ exc } ` ) ;
431
- attemptNextSource ( ) ;
351
+ try {
352
+ const response = await local_fetch ( attemptUrl ) ;
353
+ if ( ! response . ok ) {
354
+ error = new Error ( `MONO_WASM: Fetch '${ attemptUrl } ' for ${ asset . name } failed ${ response . status } ${ response . statusText } ` ) ;
355
+ continue ; // next source
356
+ }
357
+
358
+ const buffer = await response . arrayBuffer ( ) ;
359
+ _handle_fetched_asset ( ctx , asset , attemptUrl , buffer ) ;
360
+ -- ctx . pending_count ;
361
+ error = undefined ;
362
+ }
363
+ catch ( err ) {
364
+ error = new Error ( `MONO_WASM: Fetch '${ attemptUrl } ' for ${ asset . name } failed ${ err } ` ) ;
365
+ continue ; //next source
366
+ }
367
+
368
+ if ( ! error ) {
369
+ //TODO Module.removeRunDependency(configFilePath);
370
+ break ; // this source worked, stop searching
371
+ }
372
+ }
373
+ if ( error ) {
374
+ const isOkToFail = asset . is_optional || ( asset . name . match ( / \. p d b $ / ) && args . ignore_pdb_load_errors ) ;
375
+ if ( ! isOkToFail )
376
+ throw error ;
432
377
}
433
378
} ;
379
+ const fetch_promises : Promise < void > [ ] = [ ] ;
380
+ // start fetching all assets in parallel
381
+ for ( const asset of args . assets ) {
382
+ fetch_promises . push ( load_asset ( asset ) ) ;
383
+ }
434
384
435
- attemptNextSource ( ) ;
436
- } ) ;
385
+ await Promise . all ( fetch_promises ) ;
386
+
387
+ _finalize_startup ( args , ctx ) ;
388
+ } catch ( exc : any ) {
389
+ console . error ( "MONO_WASM: Error in mono_load_runtime_and_bcl_args:" , exc ) ;
390
+ throw exc ;
391
+ }
437
392
}
438
393
439
- // used from ASP.NET
394
+ // used from Blazor
440
395
export function mono_wasm_load_data_archive ( data : TypedArray , prefix : string ) : boolean {
441
396
if ( data . length < 8 )
442
397
return false ;
0 commit comments