6
6
using System . Collections . Generic ;
7
7
using System . Runtime . Serialization ;
8
8
using System . Text . Json ;
9
+ using System . Text . Json . Serialization ;
9
10
using ResourceHashesByNameDictionary = System . Collections . Generic . Dictionary < string , string > ;
10
11
11
12
// For test purposes only. Actual build time implementation lives in runtime repository with WasmSDK
@@ -41,7 +42,11 @@ public string entryAssembly
41
42
/// and values are SHA-256 hashes formatted in prefixed base-64 style (e.g., 'sha256-abcdefg...')
42
43
/// as used for subresource integrity checking.
43
44
/// </summary>
44
- public ResourcesData resources { get ; set ; } = new ResourcesData ( ) ;
45
+ [ JsonIgnore ]
46
+ public ResourcesData resources => ( ResourcesData ) resourcesRaw ;
47
+
48
+ [ JsonPropertyName ( "resources" ) ]
49
+ public object resourcesRaw { get ; set ; }
45
50
46
51
/// <summary>
47
52
/// Gets a value that determines whether to enable caching of the <see cref="resources"/>
@@ -148,6 +153,9 @@ public class ResourcesData
148
153
[ DataMember ( EmitDefaultValue = false ) ]
149
154
public ResourceHashesByNameDictionary jsModuleWorker { get ; set ; }
150
155
156
+ [ DataMember ( EmitDefaultValue = false ) ]
157
+ public ResourceHashesByNameDictionary jsModuleDiagnostics { get ; set ; }
158
+
151
159
[ DataMember ( EmitDefaultValue = false ) ]
152
160
public ResourceHashesByNameDictionary jsModuleNative { get ; set ; }
153
161
@@ -158,16 +166,21 @@ public class ResourcesData
158
166
public ResourceHashesByNameDictionary wasmNative { get ; set ; }
159
167
160
168
[ DataMember ( EmitDefaultValue = false ) ]
161
- public ResourceHashesByNameDictionary jsSymbols { get ; set ; }
169
+ public ResourceHashesByNameDictionary wasmSymbols { get ; set ; }
162
170
163
171
[ DataMember ( EmitDefaultValue = false ) ]
164
172
public ResourceHashesByNameDictionary icu { get ; set ; }
165
173
174
+ public ResourceHashesByNameDictionary coreAssembly { get ; set ; } = new ResourceHashesByNameDictionary ( ) ;
175
+
166
176
/// <summary>
167
177
/// "assembly" (.dll) resources
168
178
/// </summary>
169
179
public ResourceHashesByNameDictionary assembly { get ; set ; } = new ResourceHashesByNameDictionary ( ) ;
170
180
181
+ [ DataMember ( EmitDefaultValue = false ) ]
182
+ public ResourceHashesByNameDictionary corePdb { get ; set ; }
183
+
171
184
/// <summary>
172
185
/// "debug" (.pdb) resources
173
186
/// </summary>
@@ -212,13 +225,144 @@ public class ResourcesData
212
225
[ DataMember ( EmitDefaultValue = false ) ]
213
226
public Dictionary < string , AdditionalAsset > runtimeAssets { get ; set ; }
214
227
228
+ [ DataMember ( EmitDefaultValue = false ) ]
229
+ public Dictionary < string , ResourceHashesByNameDictionary > coreVfs { get ; set ; }
230
+
215
231
[ DataMember ( EmitDefaultValue = false ) ]
216
232
public Dictionary < string , ResourceHashesByNameDictionary > vfs { get ; set ; }
217
233
218
234
[ DataMember ( EmitDefaultValue = false ) ]
219
235
public List < string > remoteSources { get ; set ; }
220
236
}
221
237
238
+ public class AssetsData
239
+ {
240
+ /// <summary>
241
+ /// Gets a hash of all resources
242
+ /// </summary>
243
+ public string hash { get ; set ; }
244
+
245
+ [ DataMember ( EmitDefaultValue = false ) ]
246
+ public List < JsAsset > jsModuleWorker { get ; set ; }
247
+
248
+ [ DataMember ( EmitDefaultValue = false ) ]
249
+ public List < JsAsset > jsModuleDiagnostics { get ; set ; }
250
+
251
+ [ DataMember ( EmitDefaultValue = false ) ]
252
+ public List < JsAsset > jsModuleNative { get ; set ; }
253
+
254
+ [ DataMember ( EmitDefaultValue = false ) ]
255
+ public List < JsAsset > jsModuleRuntime { get ; set ; }
256
+
257
+ [ DataMember ( EmitDefaultValue = false ) ]
258
+ public List < WasmAsset > wasmNative { get ; set ; }
259
+
260
+ [ DataMember ( EmitDefaultValue = false ) ]
261
+ public List < SymbolsAsset > wasmSymbols { get ; set ; }
262
+
263
+ [ DataMember ( EmitDefaultValue = false ) ]
264
+ public List < GeneralAsset > icu { get ; set ; }
265
+
266
+ /// <summary>
267
+ /// "assembly" (.dll) resources needed to start MonoVM
268
+ /// </summary>
269
+ public List < GeneralAsset > coreAssembly { get ; set ; } = new ( ) ;
270
+
271
+ /// <summary>
272
+ /// "assembly" (.dll) resources
273
+ /// </summary>
274
+ public List < GeneralAsset > assembly { get ; set ; } = new ( ) ;
275
+
276
+ /// <summary>
277
+ /// "debug" (.pdb) resources needed to start MonoVM
278
+ /// </summary>
279
+ [ DataMember ( EmitDefaultValue = false ) ]
280
+ public List < GeneralAsset > corePdb { get ; set ; }
281
+
282
+ /// <summary>
283
+ /// "debug" (.pdb) resources
284
+ /// </summary>
285
+ [ DataMember ( EmitDefaultValue = false ) ]
286
+ public List < GeneralAsset > pdb { get ; set ; }
287
+
288
+ /// <summary>
289
+ /// localization (.satellite resx) resources
290
+ /// </summary>
291
+ [ DataMember ( EmitDefaultValue = false ) ]
292
+ public Dictionary < string , List < GeneralAsset > > satelliteResources { get ; set ; }
293
+
294
+ /// <summary>
295
+ /// Assembly (.dll) resources that are loaded lazily during runtime
296
+ /// </summary>
297
+ [ DataMember ( EmitDefaultValue = false ) ]
298
+ public List < GeneralAsset > lazyAssembly { get ; set ; }
299
+
300
+ /// <summary>
301
+ /// JavaScript module initializers that Blazor will be in charge of loading.
302
+ /// Used in .NET < 8
303
+ /// </summary>
304
+ [ DataMember ( EmitDefaultValue = false ) ]
305
+ public List < JsAsset > libraryInitializers { get ; set ; }
306
+
307
+ [ DataMember ( EmitDefaultValue = false ) ]
308
+ public List < JsAsset > modulesAfterConfigLoaded { get ; set ; }
309
+
310
+ [ DataMember ( EmitDefaultValue = false ) ]
311
+ public List < JsAsset > modulesAfterRuntimeReady { get ; set ; }
312
+
313
+ /// <summary>
314
+ /// Extensions created by users customizing the initialization process. The format of the file(s)
315
+ /// is up to the user.
316
+ /// </summary>
317
+ [ DataMember ( EmitDefaultValue = false ) ]
318
+ public Dictionary < string , ResourceHashesByNameDictionary > extensions { get ; set ; }
319
+
320
+ [ DataMember ( EmitDefaultValue = false ) ]
321
+ public List < VfsAsset > coreVfs { get ; set ; }
322
+
323
+ [ DataMember ( EmitDefaultValue = false ) ]
324
+ public List < VfsAsset > vfs { get ; set ; }
325
+ }
326
+
327
+ [ DataContract ]
328
+ public class JsAsset
329
+ {
330
+ public string name { get ; set ; }
331
+ public string moduleExports { get ; set ; }
332
+ }
333
+
334
+ [ DataContract ]
335
+ public class SymbolsAsset
336
+ {
337
+ public string name { get ; set ; }
338
+ }
339
+
340
+ [ DataContract ]
341
+ public class WasmAsset
342
+ {
343
+ public string name { get ; set ; }
344
+ public string integrity { get ; set ; }
345
+ public string resolvedUrl { get ; set ; }
346
+ }
347
+
348
+ [ DataContract ]
349
+ public class GeneralAsset
350
+ {
351
+ public string virtualPath { get ; set ; }
352
+ public string name { get ; set ; }
353
+ public string integrity { get ; set ; }
354
+ public string resolvedUrl { get ; set ; }
355
+ }
356
+
357
+ [ DataContract ]
358
+ public class VfsAsset
359
+ {
360
+ public string virtualPath { get ; set ; }
361
+ public string name { get ; set ; }
362
+ public string integrity { get ; set ; }
363
+ public string resolvedUrl { get ; set ; }
364
+ }
365
+
222
366
public enum GlobalizationMode : int
223
367
{
224
368
// Note that the numeric values are serialized and used in JS code, so don't change them without also updating the JS code
@@ -261,10 +405,65 @@ public class BootJsonDataLoader
261
405
public static BootJsonData ParseBootData ( string bootConfigPath )
262
406
{
263
407
string jsonContent = GetJsonContent ( bootConfigPath ) ;
264
- BootJsonData config = JsonSerializer . Deserialize < BootJsonData > ( jsonContent , new JsonSerializerOptions { PropertyNameCaseInsensitive = true } ) ;
408
+ var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true } ;
409
+ options . Converters . Add ( new ResourcesConverter ( ) ) ;
410
+ BootJsonData config = JsonSerializer . Deserialize < BootJsonData > ( jsonContent , options ) ;
411
+ if ( config . resourcesRaw is AssetsData assets )
412
+ {
413
+ config . resourcesRaw = ConvertAssetsToResources ( assets ) ;
414
+ }
415
+
265
416
return config ;
266
417
}
267
418
419
+ private static ResourcesData ConvertAssetsToResources ( AssetsData assets )
420
+ {
421
+ static Dictionary < string , ResourceHashesByNameDictionary > ConvertSatelliteResources ( Dictionary < string , List < GeneralAsset > > satelliteResources )
422
+ {
423
+ if ( satelliteResources == null )
424
+ return null ;
425
+
426
+ var result = new Dictionary < string , ResourceHashesByNameDictionary > ( ) ;
427
+ foreach ( var kvp in satelliteResources )
428
+ result [ kvp . Key ] = kvp . Value . ToDictionary ( a => a . name , a => a . integrity ) ;
429
+
430
+ return result ;
431
+ }
432
+
433
+ static Dictionary < string , ResourceHashesByNameDictionary > ConvertVfsAssets ( List < VfsAsset > vfsAssets )
434
+ {
435
+ return vfsAssets ? . ToDictionary ( a => a . virtualPath , a => new ResourceHashesByNameDictionary
436
+ {
437
+ { a . name , a . integrity }
438
+ } ) ;
439
+ }
440
+
441
+ var resources = new ResourcesData
442
+ {
443
+ hash = assets . hash ,
444
+ jsModuleWorker = assets . jsModuleWorker ? . ToDictionary ( a => a . name , a => ( string ) null ) ,
445
+ jsModuleDiagnostics = assets . jsModuleDiagnostics ? . ToDictionary ( a => a . name , a => ( string ) null ) ,
446
+ jsModuleNative = assets . jsModuleNative ? . ToDictionary ( a => a . name , a => ( string ) null ) ,
447
+ jsModuleRuntime = assets . jsModuleRuntime ? . ToDictionary ( a => a . name , a => ( string ) null ) ,
448
+ wasmNative = assets . wasmNative ? . ToDictionary ( a => a . name , a => a . integrity ) ,
449
+ wasmSymbols = assets . wasmSymbols ? . ToDictionary ( a => a . name , a => ( string ) null ) ,
450
+ icu = assets . icu ? . ToDictionary ( a => a . name , a => a . integrity ) ,
451
+ coreAssembly = assets . coreAssembly ? . ToDictionary ( a => a . name , a => a . integrity ) ,
452
+ assembly = assets . assembly ? . ToDictionary ( a => a . name , a => a . integrity ) ,
453
+ corePdb = assets . corePdb ? . ToDictionary ( a => a . name , a => a . integrity ) ,
454
+ pdb = assets . pdb ? . ToDictionary ( a => a . name , a => a . integrity ) ,
455
+ satelliteResources = ConvertSatelliteResources ( assets . satelliteResources ) ,
456
+ lazyAssembly = assets . lazyAssembly ? . ToDictionary ( a => a . name , a => a . integrity ) ,
457
+ libraryInitializers = assets . libraryInitializers ? . ToDictionary ( a => a . name , a => ( string ) null ) ,
458
+ modulesAfterConfigLoaded = assets . modulesAfterConfigLoaded ? . ToDictionary ( a => a . name , a => ( string ) null ) ,
459
+ modulesAfterRuntimeReady = assets . modulesAfterRuntimeReady ? . ToDictionary ( a => a . name , a => ( string ) null ) ,
460
+ extensions = assets . extensions ,
461
+ coreVfs = ConvertVfsAssets ( assets . coreVfs ) ,
462
+ vfs = ConvertVfsAssets ( assets . vfs )
463
+ } ;
464
+ return resources ;
465
+ }
466
+
268
467
public static string GetJsonContent ( string bootConfigPath )
269
468
{
270
469
string startComment = "/*json-start*/" ;
@@ -284,3 +483,32 @@ public static string GetJsonContent(string bootConfigPath)
284
483
return moduleContent ;
285
484
}
286
485
}
486
+
487
+ internal class ResourcesConverter : JsonConverter < object >
488
+ {
489
+ public override object Read ( ref Utf8JsonReader reader , Type typeToConvert , JsonSerializerOptions options )
490
+ {
491
+ var nestedOptions = new JsonSerializerOptions ( options ) ;
492
+ nestedOptions . Converters . Remove ( this ) ;
493
+
494
+ if ( reader . TokenType == JsonTokenType . StartObject )
495
+ {
496
+ try
497
+ {
498
+
499
+ return JsonSerializer . Deserialize < AssetsData > ( ref reader , nestedOptions ) ! ;
500
+ }
501
+ catch
502
+ {
503
+ return JsonSerializer . Deserialize < ResourcesData > ( ref reader , nestedOptions ) ! ;
504
+ }
505
+ }
506
+
507
+ return JsonSerializer . Deserialize < object > ( ref reader , nestedOptions ) ! ;
508
+ }
509
+
510
+ public override void Write ( Utf8JsonWriter writer , object value , JsonSerializerOptions options )
511
+ {
512
+ JsonSerializer . Serialize ( writer , value , value . GetType ( ) , options ) ;
513
+ }
514
+ }
0 commit comments