From 65934817f508e4e0785af803dc03d50c8a3fa9f5 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 16 Dec 2022 16:58:59 +0100 Subject: [PATCH 1/5] unify startup bit more --- .../Web.JS/@types/dotnet/dotnet-legacy.d.ts | 307 +++++++++ .../Web.JS/@types/dotnet/dotnet.d.ts | 633 +++++------------- .../Web.JS/src/Platform/BootConfig.ts | 7 + .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 89 ++- .../Web.JS/src/Platform/Platform.ts | 2 +- .../src/Platform/WebAssemblyResourceLoader.ts | 8 +- .../src/Services/WebAssemblyConsoleLogger.cs | 2 +- 7 files changed, 545 insertions(+), 503 deletions(-) create mode 100644 src/Components/Web.JS/@types/dotnet/dotnet-legacy.d.ts diff --git a/src/Components/Web.JS/@types/dotnet/dotnet-legacy.d.ts b/src/Components/Web.JS/@types/dotnet/dotnet-legacy.d.ts new file mode 100644 index 000000000000..ffd576f3ede1 --- /dev/null +++ b/src/Components/Web.JS/@types/dotnet/dotnet-legacy.d.ts @@ -0,0 +1,307 @@ +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. +//! +//! This is generated file, see src/mono/wasm/runtime/rollup.config.js + +//! This is not considered public API with backward compatibility guarantees. + +declare interface ManagedPointer { + __brandManagedPointer: "ManagedPointer"; +} +declare interface NativePointer { + __brandNativePointer: "NativePointer"; +} +declare interface VoidPtr extends NativePointer { + __brand: "VoidPtr"; +} + +interface MonoObject extends ManagedPointer { + __brandMonoObject: "MonoObject"; +} +interface MonoString extends MonoObject { + __brand: "MonoString"; +} +interface MonoArray extends MonoObject { + __brand: "MonoArray"; +} +interface MonoObjectRef extends ManagedPointer { + __brandMonoObjectRef: "MonoObjectRef"; +} +declare type MemOffset = number | VoidPtr | NativePointer | ManagedPointer; +declare type NumberOrPointer = number | VoidPtr | NativePointer | ManagedPointer; +interface WasmRoot { + get_address(): MonoObjectRef; + get_address_32(): number; + get address(): MonoObjectRef; + get(): T; + set(value: T): T; + get value(): T; + set value(value: T); + copy_from_address(source: MonoObjectRef): void; + copy_to_address(destination: MonoObjectRef): void; + copy_from(source: WasmRoot): void; + copy_to(destination: WasmRoot): void; + valueOf(): T; + clear(): void; + release(): void; + toString(): string; +} +interface WasmRootBuffer { + get_address(index: number): MonoObjectRef; + get_address_32(index: number): number; + get(index: number): ManagedPointer; + set(index: number, value: ManagedPointer): ManagedPointer; + copy_value_from_address(index: number, sourceAddress: MonoObjectRef): void; + clear(): void; + release(): void; + toString(): string; +} + +/** + * @deprecated Please use methods in top level API object instead + */ +declare type BINDINGType = { + /** + * @deprecated Please use [JSExportAttribute] instead + */ + bind_static_method: (fqn: string, signature?: string) => Function; + /** + * @deprecated Please use runMain() instead + */ + call_assembly_entry_point: (assembly: string, args?: any[], signature?: string) => number; + /** + * @deprecated Not GC or thread safe + */ + mono_obj_array_new: (size: number) => MonoArray; + /** + * @deprecated Not GC or thread safe + */ + mono_obj_array_set: (array: MonoArray, idx: number, obj: MonoObject) => void; + /** + * @deprecated Not GC or thread safe + */ + js_string_to_mono_string: (string: string) => MonoString; + /** + * @deprecated Not GC or thread safe + */ + js_typed_array_to_array: (js_obj: any) => MonoArray; + /** + * @deprecated Not GC or thread safe + */ + mono_array_to_js_array: (mono_array: MonoArray) => any[] | null; + /** + * @deprecated Not GC or thread safe + */ + js_to_mono_obj: (js_obj: any) => MonoObject; + /** + * @deprecated Not GC or thread safe + */ + conv_string: (mono_obj: MonoString) => string | null; + /** + * @deprecated Not GC or thread safe + */ + unbox_mono_obj: (mono_obj: MonoObject) => any; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_obj_array_new_ref: (size: number, result: MonoObjectRef) => void; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_obj_array_set_ref: (array: MonoObjectRef, idx: number, obj: MonoObjectRef) => void; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + js_string_to_mono_string_root: (string: string, result: WasmRoot) => void; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + js_typed_array_to_array_root: (js_obj: any, result: WasmRoot) => void; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + js_to_mono_obj_root: (js_obj: any, result: WasmRoot, should_add_in_flight: boolean) => void; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + conv_string_root: (root: WasmRoot) => string | null; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + unbox_mono_obj_root: (root: WasmRoot) => any; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_array_root_to_js_array: (arrayRoot: WasmRoot) => any[] | null; +}; +/** + * @deprecated Please use methods in top level API object instead + */ +declare type MONOType = { + /** + * @deprecated Please use setEnvironmentVariable() instead + */ + mono_wasm_setenv: (name: string, value: string) => void; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_load_bytes_into_heap: (bytes: Uint8Array) => VoidPtr; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_load_icu_data: (offset: VoidPtr) => boolean; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_runtime_ready: () => void; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_load_data_archive: (data: Uint8Array, prefix: string) => boolean; + /** + * @deprecated Please use configSrc instead + */ + mono_wasm_load_config: (configFilePath: string) => Promise; + /** + * @deprecated Please use runMain instead + */ + mono_load_runtime_and_bcl_args: Function; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_wasm_new_root_buffer: (capacity: number, name?: string) => WasmRootBuffer; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_wasm_new_root: (value?: T | undefined) => WasmRoot; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_wasm_new_external_root: (address: VoidPtr | MonoObjectRef) => WasmRoot; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_wasm_release_roots: (...args: WasmRoot[]) => void; + /** + * @deprecated Please use runMain instead + */ + mono_run_main: (main_assembly_name: string, args: string[]) => Promise; + /** + * @deprecated Please use runMainAndExit instead + */ + mono_run_main_and_exit: (main_assembly_name: string, args: string[]) => Promise; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_add_assembly: (name: string, data: VoidPtr, size: number) => number; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_load_runtime: (unused: string, debugLevel: number) => void; + /** + * @deprecated Please use getConfig() instead + */ + config: any; + /** + * @deprecated Please use config.assets instead + */ + loaded_files: string[]; + /** + * @deprecated Please use setHeapB32 + */ + setB32: (offset: MemOffset, value: number | boolean) => void; + /** + * @deprecated Please use setHeapI8 + */ + setI8: (offset: MemOffset, value: number) => void; + /** + * @deprecated Please use setHeapI16 + */ + setI16: (offset: MemOffset, value: number) => void; + /** + * @deprecated Please use setHeapI32 + */ + setI32: (offset: MemOffset, value: number) => void; + /** + * @deprecated Please use setHeapI52 + */ + setI52: (offset: MemOffset, value: number) => void; + /** + * @deprecated Please use setHeapU52 + */ + setU52: (offset: MemOffset, value: number) => void; + /** + * @deprecated Please use setHeapI64Big + */ + setI64Big: (offset: MemOffset, value: bigint) => void; + /** + * @deprecated Please use setHeapU8 + */ + setU8: (offset: MemOffset, value: number) => void; + /** + * @deprecated Please use setHeapU16 + */ + setU16: (offset: MemOffset, value: number) => void; + /** + * @deprecated Please use setHeapU32 + */ + setU32: (offset: MemOffset, value: NumberOrPointer) => void; + /** + * @deprecated Please use setHeapF32 + */ + setF32: (offset: MemOffset, value: number) => void; + /** + * @deprecated Please use setHeapF64 + */ + setF64: (offset: MemOffset, value: number) => void; + /** + * @deprecated Please use getHeapB32 + */ + getB32: (offset: MemOffset) => boolean; + /** + * @deprecated Please use getHeapI8 + */ + getI8: (offset: MemOffset) => number; + /** + * @deprecated Please use getHeapI16 + */ + getI16: (offset: MemOffset) => number; + /** + * @deprecated Please use getHeapI32 + */ + getI32: (offset: MemOffset) => number; + /** + * @deprecated Please use getHeapI52 + */ + getI52: (offset: MemOffset) => number; + /** + * @deprecated Please use getHeapU52 + */ + getU52: (offset: MemOffset) => number; + /** + * @deprecated Please use getHeapI64Big + */ + getI64Big: (offset: MemOffset) => bigint; + /** + * @deprecated Please use getHeapU8 + */ + getU8: (offset: MemOffset) => number; + /** + * @deprecated Please use getHeapU16 + */ + getU16: (offset: MemOffset) => number; + /** + * @deprecated Please use getHeapU32 + */ + getU32: (offset: MemOffset) => number; + /** + * @deprecated Please use getHeapF32 + */ + getF32: (offset: MemOffset) => number; + /** + * @deprecated Please use getHeapF64 + */ + getF64: (offset: MemOffset) => number; +}; + +export { BINDINGType, MONOType, MonoArray, MonoObject, MonoString }; diff --git a/src/Components/Web.JS/@types/dotnet/dotnet.d.ts b/src/Components/Web.JS/@types/dotnet/dotnet.d.ts index 71be4d4b3e5b..795b52f709a5 100644 --- a/src/Components/Web.JS/@types/dotnet/dotnet.d.ts +++ b/src/Components/Web.JS/@types/dotnet/dotnet.d.ts @@ -5,9 +5,23 @@ //! This is not considered public API with backward compatibility guarantees. -declare interface ManagedPointer { - __brandManagedPointer: "ManagedPointer"; +interface DotnetHostBuilder { + withConfig(config: MonoConfig): DotnetHostBuilder; + withConfigSrc(configSrc: string): DotnetHostBuilder; + withApplicationArguments(...args: string[]): DotnetHostBuilder; + withEnvironmentVariable(name: string, value: string): DotnetHostBuilder; + withEnvironmentVariables(variables: { + [i: string]: string; + }): DotnetHostBuilder; + withVirtualWorkingDirectory(vfsPath: string): DotnetHostBuilder; + withDiagnosticTracing(enabled: boolean): DotnetHostBuilder; + withDebugging(level: number): DotnetHostBuilder; + withMainAssembly(mainAssemblyName: string): DotnetHostBuilder; + withApplicationArgumentsFromQuery(): DotnetHostBuilder; + create(): Promise; + run(): Promise; } + declare interface NativePointer { __brandNativePointer: "NativePointer"; } @@ -46,358 +60,190 @@ declare interface EmscriptenModule { FS_readFile(filename: string, opts: any): any; removeRunDependency(id: string): void; addRunDependency(id: string): void; + addFunction(fn: Function, signature: string): number; + getWasmTableEntry(index: number): any; stackSave(): VoidPtr; stackRestore(stack: VoidPtr): void; stackAlloc(size: number): VoidPtr; ready: Promise; - preInit?: (() => any)[]; - preRun?: (() => any)[]; - postRun?: (() => any)[]; + instantiateWasm?: InstantiateWasmCallBack; + preInit?: (() => any)[] | (() => any); + preRun?: (() => any)[] | (() => any); + onRuntimeInitialized?: () => any; + postRun?: (() => any)[] | (() => any); onAbort?: { (error: any): void; }; - onRuntimeInitialized?: () => any; - instantiateWasm: (imports: any, successCallback: Function) => any; } +type InstantiateWasmSuccessCallback = (instance: WebAssembly.Instance, module: WebAssembly.Module) => void; +type InstantiateWasmCallBack = (imports: WebAssembly.Imports, successCallback: InstantiateWasmSuccessCallback) => any; declare type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array; -/** - * Allocates a block of memory that can safely contain pointers into the managed heap. - * The result object has get(index) and set(index, value) methods that can be used to retrieve and store managed pointers. - * Once you are done using the root buffer, you must call its release() method. - * For small numbers of roots, it is preferable to use the mono_wasm_new_root and mono_wasm_new_roots APIs instead. - */ -declare function mono_wasm_new_root_buffer(capacity: number, name?: string): WasmRootBuffer; -/** - * Allocates a WasmRoot pointing to a root provided and controlled by external code. Typicaly on managed stack. - * Releasing this root will not de-allocate the root space. You still need to call .release(). - */ -declare function mono_wasm_new_external_root(address: VoidPtr | MonoObjectRef): WasmRoot; -/** - * Allocates temporary storage for a pointer into the managed heap. - * Pointers stored here will be visible to the GC, ensuring that the object they point to aren't moved or collected. - * If you already have a managed pointer you can pass it as an argument to initialize the temporary storage. - * The result object has get() and set(value) methods, along with a .value property. - * When you are done using the root you must call its .release() method. - */ -declare function mono_wasm_new_root(value?: T | undefined): WasmRoot; -/** - * Releases 1 or more root or root buffer objects. - * Multiple objects may be passed on the argument list. - * 'undefined' may be passed as an argument so it is safe to call this method from finally blocks - * even if you are not sure all of your roots have been created yet. - * @param {... WasmRoot} roots - */ -declare function mono_wasm_release_roots(...args: WasmRoot[]): void; -declare class WasmRootBuffer { - private __count; - private length; - private __offset; - private __offset32; - private __handle; - private __ownsAllocation; - constructor(offset: VoidPtr, capacity: number, ownsAllocation: boolean, name?: string); - _throw_index_out_of_range(): void; - _check_in_range(index: number): void; - get_address(index: number): MonoObjectRef; - get_address_32(index: number): number; - get(index: number): ManagedPointer; - set(index: number, value: ManagedPointer): ManagedPointer; - copy_value_from_address(index: number, sourceAddress: MonoObjectRef): void; - _unsafe_get(index: number): number; - _unsafe_set(index: number, value: ManagedPointer | NativePointer): void; - clear(): void; - release(): void; - toString(): string; -} -interface WasmRoot { - get_address(): MonoObjectRef; - get_address_32(): number; - get address(): MonoObjectRef; - get(): T; - set(value: T): T; - get value(): T; - set value(value: T); - copy_from_address(source: MonoObjectRef): void; - copy_to_address(destination: MonoObjectRef): void; - copy_from(source: WasmRoot): void; - copy_to(destination: WasmRoot): void; - valueOf(): T; - clear(): void; - release(): void; - toString(): string; -} - -interface MonoObject extends ManagedPointer { - __brandMonoObject: "MonoObject"; -} -interface MonoString extends MonoObject { - __brand: "MonoString"; -} -interface MonoArray extends MonoObject { - __brand: "MonoArray"; -} -interface MonoObjectRef extends ManagedPointer { - __brandMonoObjectRef: "MonoObjectRef"; -} -declare type MonoConfig = { - isError: false; - assembly_root: string; - assets: AllAssetEntryTypes[]; - debug_level?: number; - enable_debugging?: number; - globalization_mode: GlobalizationMode; - diagnostic_tracing?: boolean; - remote_sources?: string[]; - environment_variables?: { +type MonoConfig = { + /** + * The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script. + */ + assemblyRootFolder?: string; + /** + * A list of assets to load along with the runtime. + */ + assets?: AssetEntry[]; + /** + * Additional search locations for assets. + */ + remoteSources?: string[]; + /** + * It will not fail the startup is .pdb files can't be downloaded + */ + ignorePdbLoadErrors?: boolean; + /** + * We are throttling parallel downloads in order to avoid net::ERR_INSUFFICIENT_RESOURCES on chrome. The default value is 16. + */ + maxParallelDownloads?: number; + /** + * Name of the assembly with main entrypoint + */ + mainAssemblyName?: string; + /** + * Configures the runtime's globalization mode + */ + globalizationMode?: GlobalizationMode; + /** + * debugLevel > 0 enables debugging and sets the debug log level to debugLevel + * debugLevel == 0 disables debugging and enables interpreter optimizations + * debugLevel < 0 enabled debugging and disables debug logging. + */ + debugLevel?: number; + /** + * Enables diagnostic log messages during startup + */ + diagnosticTracing?: boolean; + /** + * Dictionary-style Object containing environment variables + */ + environmentVariables?: { [i: string]: string; }; - runtime_options?: string[]; - aot_profiler_options?: AOTProfilerOptions; - coverage_profiler_options?: CoverageProfilerOptions; - ignore_pdb_load_errors?: boolean; - wait_for_debugger?: number; -}; -declare type MonoConfigError = { - isError: true; - message: string; - error: any; + /** + * initial number of workers to add to the emscripten pthread pool + */ + pthreadPoolSize?: number; }; +interface ResourceRequest { + name: string; + behavior: AssetBehaviours; + resolvedUrl?: string; + hash?: string; +} interface LoadingResource { name: string; url: string; response: Promise; } -declare type AllAssetEntryTypes = AssetEntry | AssemblyEntry | SatelliteAssemblyEntry | VfsEntry | IcuData; -declare type AssetEntry = { - name: string; - behavior: AssetBehaviours; - virtual_path?: string; +interface AssetEntry extends ResourceRequest { + /** + * If specified, overrides the path of the asset in the virtual filesystem and similar data structures once downloaded. + */ + virtualPath?: string; + /** + * Culture code + */ culture?: string; - load_remote?: boolean; - is_optional?: boolean; + /** + * If true, an attempt will be made to load the asset from each location in MonoConfig.remoteSources. + */ + loadRemote?: boolean; + /** + * If true, the runtime startup would not fail if the asset download was not successful. + */ + isOptional?: boolean; + /** + * If provided, runtime doesn't have to fetch the data. + * Runtime would set the buffer to null after instantiation to free the memory. + */ buffer?: ArrayBuffer; + /** + * It's metadata + fetch-like Promise + * If provided, the runtime doesn't have to initiate the download. It would just await the response. + */ pendingDownload?: LoadingResource; -}; -interface AssemblyEntry extends AssetEntry { - name: "assembly"; -} -interface SatelliteAssemblyEntry extends AssetEntry { - name: "resource"; - culture: string; -} -interface VfsEntry extends AssetEntry { - name: "vfs"; - virtual_path: string; -} -interface IcuData extends AssetEntry { - name: "icu"; - load_remote: boolean; } type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm" | "js-module-threads"; -declare const enum GlobalizationMode { - ICU = "icu", - INVARIANT = "invariant", - AUTO = "auto" -} -declare type AOTProfilerOptions = { - write_at?: string; - send_to?: string; -}; -declare type CoverageProfilerOptions = { - write_at?: string; - send_to?: string; -}; -interface EventPipeSessionOptions { - collectRundownEvents?: boolean; - providers: string; -} -declare type DotnetModuleConfig = { +type GlobalizationMode = "icu" | // load ICU globalization data from any runtime assets with behavior "icu". + "invariant" | // operate in invariant globalization mode. + "auto"; +type DotnetModuleConfig = { disableDotnet6Compatibility?: boolean; - config?: MonoConfig | MonoConfigError; + config?: MonoConfig; configSrc?: string; - onConfigLoaded?: (config: MonoConfig) => Promise; - onDotnetReady?: () => void; - imports?: DotnetModuleConfigImports; + onConfigLoaded?: (config: MonoConfig) => void | Promise; + onDotnetReady?: () => void | Promise; + imports?: any; exports?: string[]; + downloadResource?: (request: ResourceRequest) => LoadingResource | undefined; } & Partial; -declare type DotnetModuleConfigImports = { - require?: (name: string) => any; - fetch?: (url: string) => Promise; - fs?: { - promises?: { - readFile?: (path: string) => Promise; - }; - readFileSync?: (path: string, options: any | undefined) => string; - }; - crypto?: { - randomBytes?: (size: number) => Buffer; - }; - ws?: WebSocket & { - Server: any; - }; - path?: { - normalize?: (path: string) => string; - dirname?: (path: string) => string; - }; - url?: any; +type APIType = { + runMain: (mainAssemblyName: string, args: string[]) => Promise; + runMainAndExit: (mainAssemblyName: string, args: string[]) => Promise; + setEnvironmentVariable: (name: string, value: string) => void; + getAssemblyExports(assemblyName: string): Promise; + setModuleImports(moduleName: string, moduleImports: any): void; + getConfig: () => MonoConfig; + setHeapB32: (offset: NativePointer, value: number | boolean) => void; + setHeapU8: (offset: NativePointer, value: number) => void; + setHeapU16: (offset: NativePointer, value: number) => void; + setHeapU32: (offset: NativePointer, value: NativePointer | number) => void; + setHeapI8: (offset: NativePointer, value: number) => void; + setHeapI16: (offset: NativePointer, value: number) => void; + setHeapI32: (offset: NativePointer, value: number) => void; + setHeapI52: (offset: NativePointer, value: number) => void; + setHeapU52: (offset: NativePointer, value: number) => void; + setHeapI64Big: (offset: NativePointer, value: bigint) => void; + setHeapF32: (offset: NativePointer, value: number) => void; + setHeapF64: (offset: NativePointer, value: number) => void; + getHeapB32: (offset: NativePointer) => boolean; + getHeapU8: (offset: NativePointer) => number; + getHeapU16: (offset: NativePointer) => number; + getHeapU32: (offset: NativePointer) => number; + getHeapI8: (offset: NativePointer) => number; + getHeapI16: (offset: NativePointer) => number; + getHeapI32: (offset: NativePointer) => number; + getHeapI52: (offset: NativePointer) => number; + getHeapU52: (offset: NativePointer) => number; + getHeapI64Big: (offset: NativePointer) => bigint; + getHeapF32: (offset: NativePointer) => number; + getHeapF64: (offset: NativePointer) => number; }; - -declare type EventPipeSessionID = bigint; -interface EventPipeSession { - get sessionID(): EventPipeSessionID; - start(): void; - stop(): void; - getTraceBlob(): Blob; -} -declare const eventLevel: { - readonly LogAlways: 0; - readonly Critical: 1; - readonly Error: 2; - readonly Warning: 3; - readonly Informational: 4; - readonly Verbose: 5; +type RuntimeAPI = { + /** + * @deprecated Please use API object instead. See also MONOType in dotnet-legacy.d.ts + */ + MONO: any; + /** + * @deprecated Please use API object instead. See also BINDINGType in dotnet-legacy.d.ts + */ + BINDING: any; + INTERNAL: any; + Module: EmscriptenModule; + runtimeId: number; + runtimeBuildInfo: { + productVersion: string; + gitHash: string; + buildConfiguration: string; + }; +} & APIType; +type ModuleAPI = { + dotnet: DotnetHostBuilder; + exit: (code: number, reason?: any) => void; }; -declare type EventLevel = typeof eventLevel; -declare type UnnamedProviderConfiguration = Partial<{ - keyword_mask: string | 0; - level: number; - args: string; -}>; -interface ProviderConfiguration extends UnnamedProviderConfiguration { - name: string; -} -declare class SessionOptionsBuilder { - private _rundown?; - private _providers; - constructor(); - static get Empty(): SessionOptionsBuilder; - static get DefaultProviders(): SessionOptionsBuilder; - setRundownEnabled(enabled: boolean): SessionOptionsBuilder; - addProvider(provider: ProviderConfiguration): SessionOptionsBuilder; - addRuntimeProvider(overrideOptions?: UnnamedProviderConfiguration): SessionOptionsBuilder; - addRuntimePrivateProvider(overrideOptions?: UnnamedProviderConfiguration): SessionOptionsBuilder; - addSampleProfilerProvider(overrideOptions?: UnnamedProviderConfiguration): SessionOptionsBuilder; - build(): EventPipeSessionOptions; -} -interface Diagnostics { - EventLevel: EventLevel; - SessionOptionsBuilder: typeof SessionOptionsBuilder; - createEventPipeSession(options?: EventPipeSessionOptions): EventPipeSession | null; -} - -declare function mono_wasm_runtime_ready(): void; - -declare function mono_wasm_setenv(name: string, value: string): void; -declare function mono_load_runtime_and_bcl_args(config: MonoConfig | MonoConfigError | undefined): Promise; -declare function mono_wasm_load_data_archive(data: Uint8Array, prefix: string): boolean; -/** - * Loads the mono config file (typically called mono-config.json) asynchroniously - * Note: the run dependencies are so emsdk actually awaits it in order. - * - * @param {string} configFilePath - relative path to the config file - * @throws Will throw an error if the config file loading fails - */ -declare function mono_wasm_load_config(configFilePath: string): Promise; - -declare function mono_wasm_load_icu_data(offset: VoidPtr): boolean; - -/** - * @deprecated Not GC or thread safe - */ -declare function conv_string(mono_obj: MonoString): string | null; -declare function conv_string_root(root: WasmRoot): string | null; -declare function js_string_to_mono_string_root(string: string, result: WasmRoot): void; -/** - * @deprecated Not GC or thread safe - */ -declare function js_string_to_mono_string(string: string): MonoString; - -/** - * @deprecated Not GC or thread safe. For blazor use only - */ -declare function js_to_mono_obj(js_obj: any): MonoObject; -declare function js_to_mono_obj_root(js_obj: any, result: WasmRoot, should_add_in_flight: boolean): void; -declare function js_typed_array_to_array_root(js_obj: any, result: WasmRoot): void; -/** - * @deprecated Not GC or thread safe - */ -declare function js_typed_array_to_array(js_obj: any): MonoArray; - -declare function unbox_mono_obj(mono_obj: MonoObject): any; -declare function unbox_mono_obj_root(root: WasmRoot): any; -declare function mono_array_to_js_array(mono_array: MonoArray): any[] | null; -declare function mono_array_root_to_js_array(arrayRoot: WasmRoot): any[] | null; - -declare function mono_bind_static_method(fqn: string, signature?: string): Function; -declare function mono_call_assembly_entry_point(assembly: string, args?: any[], signature?: string): number; - -declare function mono_wasm_load_bytes_into_heap(bytes: Uint8Array): VoidPtr; - -declare type _MemOffset = number | VoidPtr | NativePointer | ManagedPointer; -declare type _NumberOrPointer = number | VoidPtr | NativePointer | ManagedPointer; -declare function setB32(offset: _MemOffset, value: number | boolean): void; -declare function setU8(offset: _MemOffset, value: number): void; -declare function setU16(offset: _MemOffset, value: number): void; -declare function setU32(offset: _MemOffset, value: _NumberOrPointer): void; -declare function setI8(offset: _MemOffset, value: number): void; -declare function setI16(offset: _MemOffset, value: number): void; -declare function setI32(offset: _MemOffset, value: number): void; -/** - * Throws for values which are not 52 bit integer. See Number.isSafeInteger() - */ -declare function setI52(offset: _MemOffset, value: number): void; -/** - * Throws for values which are not 52 bit integer or are negative. See Number.isSafeInteger(). - */ -declare function setU52(offset: _MemOffset, value: number): void; -declare function setI64Big(offset: _MemOffset, value: bigint): void; -declare function setF32(offset: _MemOffset, value: number): void; -declare function setF64(offset: _MemOffset, value: number): void; -declare function getB32(offset: _MemOffset): boolean; -declare function getU8(offset: _MemOffset): number; -declare function getU16(offset: _MemOffset): number; -declare function getU32(offset: _MemOffset): number; -declare function getI8(offset: _MemOffset): number; -declare function getI16(offset: _MemOffset): number; -declare function getI32(offset: _MemOffset): number; -/** - * Throws for Number.MIN_SAFE_INTEGER > value > Number.MAX_SAFE_INTEGER - */ -declare function getI52(offset: _MemOffset): number; -/** - * Throws for 0 > value > Number.MAX_SAFE_INTEGER - */ -declare function getU52(offset: _MemOffset): number; -declare function getI64Big(offset: _MemOffset): bigint; -declare function getF32(offset: _MemOffset): number; -declare function getF64(offset: _MemOffset): number; - -declare function mono_run_main_and_exit(main_assembly_name: string, args: string[]): Promise; -declare function mono_run_main(main_assembly_name: string, args: string[]): Promise; +declare function createDotnetRuntime(moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): Promise; +type CreateDotnetRuntimeType = typeof createDotnetRuntime; interface IDisposable { dispose(): void; get isDisposed(): boolean; } -declare class ManagedObject implements IDisposable { - dispose(): void; - get isDisposed(): boolean; - toString(): string; -} -declare class ManagedError extends Error implements IDisposable { - constructor(message: string); - get stack(): string | undefined; - dispose(): void; - get isDisposed(): boolean; - toString(): string; -} -declare const enum MemoryViewType { - Byte = 0, - Int32 = 1, - Double = 2 -} -interface IMemoryView { +interface IMemoryView extends IDisposable { /** * copies elements from provided source to the wasm memory. * target has to have the elements of the same type as the underlying C# array. @@ -417,150 +263,11 @@ interface IMemoryView { get byteLength(): number; } -declare function mono_wasm_get_assembly_exports(assembly: string): Promise; - -declare const MONO: { - mono_wasm_setenv: typeof mono_wasm_setenv; - mono_wasm_load_bytes_into_heap: typeof mono_wasm_load_bytes_into_heap; - mono_wasm_load_icu_data: typeof mono_wasm_load_icu_data; - mono_wasm_runtime_ready: typeof mono_wasm_runtime_ready; - mono_wasm_load_data_archive: typeof mono_wasm_load_data_archive; - mono_wasm_load_config: typeof mono_wasm_load_config; - mono_load_runtime_and_bcl_args: typeof mono_load_runtime_and_bcl_args; - mono_wasm_new_root_buffer: typeof mono_wasm_new_root_buffer; - mono_wasm_new_root: typeof mono_wasm_new_root; - mono_wasm_new_external_root: typeof mono_wasm_new_external_root; - mono_wasm_release_roots: typeof mono_wasm_release_roots; - mono_run_main: typeof mono_run_main; - mono_run_main_and_exit: typeof mono_run_main_and_exit; - mono_wasm_get_assembly_exports: typeof mono_wasm_get_assembly_exports; - mono_wasm_add_assembly: (name: string, data: VoidPtr, size: number) => number; - mono_wasm_load_runtime: (unused: string, debug_level: number) => void; - config: MonoConfig | MonoConfigError; - loaded_files: string[]; - setB32: typeof setB32; - setI8: typeof setI8; - setI16: typeof setI16; - setI32: typeof setI32; - setI52: typeof setI52; - setU52: typeof setU52; - setI64Big: typeof setI64Big; - setU8: typeof setU8; - setU16: typeof setU16; - setU32: typeof setU32; - setF32: typeof setF32; - setF64: typeof setF64; - getB32: typeof getB32; - getI8: typeof getI8; - getI16: typeof getI16; - getI32: typeof getI32; - getI52: typeof getI52; - getU52: typeof getU52; - getI64Big: typeof getI64Big; - getU8: typeof getU8; - getU16: typeof getU16; - getU32: typeof getU32; - getF32: typeof getF32; - getF64: typeof getF64; - diagnostics: Diagnostics; -}; -declare type MONOType = typeof MONO; -declare const BINDING: { - /** - * @deprecated Not GC or thread safe - */ - mono_obj_array_new: (size: number) => MonoArray; - /** - * @deprecated Not GC or thread safe - */ - mono_obj_array_set: (array: MonoArray, idx: number, obj: MonoObject) => void; - /** - * @deprecated Not GC or thread safe - */ - js_string_to_mono_string: typeof js_string_to_mono_string; - /** - * @deprecated Not GC or thread safe - */ - js_typed_array_to_array: typeof js_typed_array_to_array; - /** - * @deprecated Not GC or thread safe - */ - mono_array_to_js_array: typeof mono_array_to_js_array; - /** - * @deprecated Not GC or thread safe - */ - js_to_mono_obj: typeof js_to_mono_obj; - /** - * @deprecated Not GC or thread safe - */ - conv_string: typeof conv_string; - /** - * @deprecated Not GC or thread safe - */ - unbox_mono_obj: typeof unbox_mono_obj; - /** - * @deprecated Renamed to conv_string_root - */ - conv_string_rooted: typeof conv_string_root; - mono_obj_array_new_ref: (size: number, result: MonoObjectRef) => void; - mono_obj_array_set_ref: (array: MonoObjectRef, idx: number, obj: MonoObjectRef) => void; - js_string_to_mono_string_root: typeof js_string_to_mono_string_root; - js_typed_array_to_array_root: typeof js_typed_array_to_array_root; - js_to_mono_obj_root: typeof js_to_mono_obj_root; - conv_string_root: typeof conv_string_root; - unbox_mono_obj_root: typeof unbox_mono_obj_root; - mono_array_root_to_js_array: typeof mono_array_root_to_js_array; - bind_static_method: typeof mono_bind_static_method; - call_assembly_entry_point: typeof mono_call_assembly_entry_point; -}; -declare type BINDINGType = typeof BINDING; -interface DotnetPublicAPI { - MONO: typeof MONO; - BINDING: typeof BINDING; - INTERNAL: any; - EXPORTS: any; - IMPORTS: any; - Module: EmscriptenModule; - RuntimeId: number; - RuntimeBuildInfo: { - ProductVersion: string; - Configuration: string; - }; -} - -declare function createDotnetRuntime(moduleFactory: DotnetModuleConfig | ((api: DotnetPublicAPI) => DotnetModuleConfig)): Promise; -declare type CreateDotnetRuntimeType = typeof createDotnetRuntime; declare global { - function getDotnetRuntime(runtimeId: number): DotnetPublicAPI | undefined; + function getDotnetRuntime(runtimeId: number): RuntimeAPI | undefined; } -/** - * Span class is JS wrapper for System.Span. This view doesn't own the memory, nor pin the underlying array. - * It's ideal to be used on call from C# with the buffer pinned there or with unmanaged memory. - * It is disposed at the end of the call to JS. - */ -declare class Span implements IMemoryView, IDisposable { - dispose(): void; - get isDisposed(): boolean; - set(source: TypedArray, targetOffset?: number | undefined): void; - copyTo(target: TypedArray, sourceOffset?: number | undefined): void; - slice(start?: number | undefined, end?: number | undefined): TypedArray; - get length(): number; - get byteLength(): number; -} -/** - * ArraySegment class is JS wrapper for System.ArraySegment. - * This wrapper would also pin the underlying array and hold GCHandleType.Pinned until this JS instance is collected. - * User could dispose it manualy. - */ -declare class ArraySegment implements IMemoryView, IDisposable { - dispose(): void; - get isDisposed(): boolean; - set(source: TypedArray, targetOffset?: number | undefined): void; - copyTo(target: TypedArray, sourceOffset?: number | undefined): void; - slice(start?: number | undefined, end?: number | undefined): TypedArray; - get length(): number; - get byteLength(): number; -} +declare const dotnet: ModuleAPI["dotnet"]; +declare const exit: ModuleAPI["exit"]; -export { ArraySegment, BINDINGType, CreateDotnetRuntimeType, DotnetModuleConfig, DotnetPublicAPI, EmscriptenModule, IMemoryView, MONOType, ManagedError, ManagedObject, MemoryViewType, MonoArray, MonoObject, MonoString, Span, VoidPtr, createDotnetRuntime as default }; +export { CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, IMemoryView, ModuleAPI, MonoConfig, RuntimeAPI, createDotnetRuntime as default, dotnet, exit }; diff --git a/src/Components/Web.JS/src/Platform/BootConfig.ts b/src/Components/Web.JS/src/Platform/BootConfig.ts index 4f14e8fe3918..ba3585f1e924 100644 --- a/src/Components/Web.JS/src/Platform/BootConfig.ts +++ b/src/Components/Web.JS/src/Platform/BootConfig.ts @@ -69,9 +69,16 @@ export interface ResourceGroups { readonly satelliteResources?: { [cultureName: string]: ResourceList }; readonly libraryInitializers?: ResourceList, readonly extensions?: BootJsonDataExtension + readonly runtimeAssets: ExtendedResourceList; } export type ResourceList = { [name: string]: string }; +export type ExtendedResourceList = { + [name: string]: { + hash: string, + behavior: string + } +}; export enum ICUDataMode { Sharded, diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index b25e7336de22..ee152dde03f2 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -12,15 +12,14 @@ import { Platform, System_Array, Pointer, System_Object, System_String, HeapLock import { WebAssemblyBootResourceType } from '../WebAssemblyStartOptions'; import { BootJsonData, ICUDataMode } from '../BootConfig'; import { Blazor } from '../../GlobalExports'; -import { DotnetPublicAPI, BINDINGType, CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, MONOType } from 'dotnet'; +import { RuntimeAPI, CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, AssetEntry, ResourceRequest } from 'dotnet'; +import { BINDINGType, MONOType } from 'dotnet/dotnet-legacy'; // initially undefined and only fully initialized after createEmscriptenModuleInstance() export let BINDING: BINDINGType = undefined as any; export let MONO: MONOType = undefined as any; export let Module: DotnetModuleConfig & EmscriptenModule = undefined as any; -export let IMPORTS: any = undefined as any; -const appBinDirName = 'appBinDir'; const uint64HighOrderShift = Math.pow(2, 32); const maxSafeNumberHighPart = Math.pow(2, 21) - 1; // The high-order int32 from Number.MAX_SAFE_INTEGER @@ -224,10 +223,10 @@ async function importDotnetJs(resourceLoader: WebAssemblyResourceLoader): Promis return await cjsExport; } -async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoader): Promise { - let runtimeReadyResolve: (data: DotnetPublicAPI) => void = undefined as any; +async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoader): Promise { + let runtimeReadyResolve: (data: RuntimeAPI) => void = undefined as any; let runtimeReadyReject: (reason?: any) => void = undefined as any; - const runtimeReady = new Promise((resolve, reject) => { + const runtimeReady = new Promise((resolve, reject) => { runtimeReadyResolve = resolve; runtimeReadyReject = reject; }); @@ -246,8 +245,8 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc console.error(line); showErrorNotification(); }; - const existingPreRun = moduleConfig.preRun || []; - const existingPostRun = moduleConfig.postRun || []; + const existingPreRun = moduleConfig.preRun || [] as any; + const existingPostRun = moduleConfig.postRun || [] as any; (moduleConfig as any).preloadPlugins = []; let resourcesLoaded = 0; @@ -258,17 +257,43 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc document.documentElement.style.setProperty('--blazor-load-percentage-text', `"${Math.floor(percentage)}%"`); } + const monoToBlazorAssetTypeMap: { [key: string]: WebAssemblyBootResourceType | undefined } = { + 'assembly': 'assembly', + 'pdb': 'pdb', + 'icu': 'globalization', + 'dotnetwasm': 'dotnetwasm', + }; + + // it would not `loadResource` on types for which there is no typesMap mapping + const downloadResource = (request: ResourceRequest): LoadingResource | undefined => { + const type = monoToBlazorAssetTypeMap[request.behavior]; + if (type !== undefined) { + return resourceLoader.loadResource(request.name, request.resolvedUrl!, request.hash!, type); + } + return undefined; + }; + + const runtimeAssets = resourceLoader.bootConfig.resources.runtimeAssets; + // pass part of responsibility for asset loading to runtime + const assets: AssetEntry[] = Object.keys(runtimeAssets).map(name => { + const asset = runtimeAssets[name] as AssetEntry; + asset.name = name; + asset.resolvedUrl = `_framework/${name}`; + return asset; + }); + + // blazor could start downloading bit earlier than the runtime would + const runtimeAssetsBeingLoaded = assets + .filter(asset => asset.behavior === 'dotnetwasm') + .map(asset => { + asset.pendingDownload = downloadResource(asset); + return asset.pendingDownload!; + }); + // Begin loading the .dll/.pdb/.wasm files, but don't block here. Let other loading processes run in parallel. - const dotnetWasmResourceName = 'dotnet.wasm'; const assembliesBeingLoaded = resourceLoader.loadResources(resources.assembly, filename => `_framework/${filename}`, 'assembly'); const pdbsBeingLoaded = resourceLoader.loadResources(resources.pdb || {}, filename => `_framework/${filename}`, 'pdb'); - const wasmBeingLoaded = resourceLoader.loadResource( - /* name */ dotnetWasmResourceName, - /* url */ `_framework/${dotnetWasmResourceName}`, - /* hash */ resourceLoader.bootConfig.resources.runtime[dotnetWasmResourceName], - /* type */ 'dotnetwasm' - ); - const totalResources = assembliesBeingLoaded.concat(pdbsBeingLoaded, wasmBeingLoaded); + const totalResources = assembliesBeingLoaded.concat(pdbsBeingLoaded, runtimeAssetsBeingLoaded); totalResources.forEach(loadingResource => loadingResource.response.then(_ => setProgress())); const dotnetTimeZoneResourceName = 'dotnet.timezones.blat'; @@ -301,12 +326,10 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc const createDotnetRuntime = await dotnetJsBeingLoaded; await createDotnetRuntime((api) => { - const { MONO: mono, BINDING: binding, Module: module, IMPORTS: imports } = api; + const { MONO: mono, BINDING: binding, Module: module } = api; Module = module; BINDING = binding; MONO = mono; - IMPORTS = imports; - const onRuntimeInitialized = () => { if (!icuDataResource) { // Use invariant culture if the app does not carry icu data. @@ -463,7 +486,7 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc } // -1 enables debugging with logging disabled. 0 disables debugging entirely. - MONO.mono_wasm_load_runtime(appBinDirName, hasDebuggingEnabled() ? -1 : 0); + MONO.mono_wasm_load_runtime('unused', hasDebuggingEnabled() ? -1 : 0); MONO.mono_wasm_runtime_ready(); try { BINDING.bind_static_method('invalid-fqn', ''); @@ -472,8 +495,10 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc // this would always throw, but it will initialize runtime interop as side-effect } - // makes Blazor._internal visible to [JSImport] - IMPORTS.Blazor = { _internal: Blazor._internal }; + // makes Blazor._internal visible to [JSImport] as "blazor-internal" module + api.setModuleImports('blazor-internal', { + Blazor: { _internal: Blazor._internal }, + }); attachInteropInvoker(); runtimeReadyResolve(api); @@ -493,7 +518,7 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc const heapMemory = new Uint8Array(Module.HEAPU8.buffer, heapAddress as any, data.length); heapMemory.set(data); MONO.mono_wasm_add_assembly(loadAsName, heapAddress, data.length); - MONO.loaded_files.push(toAbsoluteUrl(dependency.url)); + MONO.loaded_files.push(dependency.url); } catch (errorInfo) { runtimeReadyReject(errorInfo); return; @@ -505,14 +530,10 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc const dotnetModuleConfig: DotnetModuleConfig = { ...moduleConfig, config: { - assets: [ - { - behavior: 'dotnetwasm', - name: 'dotnet.wasm', - pendingDownload: wasmBeingLoaded, - }, - ], - } as any, + assets, + debugLevel: hasDebuggingEnabled() ? -1 : 0, + }, + downloadResource, disableDotnet6Compatibility: false, preRun: [preRun, ...existingPreRun], postRun: [postRun, ...existingPostRun], @@ -527,12 +548,6 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc return await runtimeReady; } -const anchorTagForAbsoluteUrlConversions = document.createElement('a'); -function toAbsoluteUrl(possiblyRelativeUrl: string) { - anchorTagForAbsoluteUrlConversions.href = possiblyRelativeUrl; - return anchorTagForAbsoluteUrlConversions.href; -} - function getArrayDataPointer(array: System_Array): number { return array + 12; // First byte from here is length, then following bytes are entries } diff --git a/src/Components/Web.JS/src/Platform/Platform.ts b/src/Components/Web.JS/src/Platform/Platform.ts index 685fda4559f8..e7584e1706bc 100644 --- a/src/Components/Web.JS/src/Platform/Platform.ts +++ b/src/Components/Web.JS/src/Platform/Platform.ts @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { MonoObject, MonoString, MonoArray } from 'dotnet'; +import { MonoObject, MonoString, MonoArray } from 'dotnet/dotnet-legacy'; import { WebAssemblyResourceLoader } from './WebAssemblyResourceLoader'; export interface Platform { diff --git a/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts b/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts index f286d79517e2..6d3c176c711e 100644 --- a/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts +++ b/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts @@ -6,6 +6,12 @@ import { BootJsonData, ResourceList } from './BootConfig'; import { WebAssemblyStartOptions, WebAssemblyBootResourceType } from './WebAssemblyStartOptions'; const networkFetchCacheMode = 'no-cache'; +const anchorTagForAbsoluteUrlConversions = document.createElement('a'); +function toAbsoluteUrl(possiblyRelativeUrl: string) { + anchorTagForAbsoluteUrlConversions.href = possiblyRelativeUrl; + return anchorTagForAbsoluteUrlConversions.href; +} + export class WebAssemblyResourceLoader { private usedCacheKeys: { [key: string]: boolean } = {}; @@ -31,7 +37,7 @@ export class WebAssemblyResourceLoader { ? this.loadResourceWithCaching(this.cacheIfUsed, name, url, contentHash, resourceType) : this.loadResourceWithoutCaching(name, url, contentHash, resourceType); - return { name, url, response }; + return { name, url: toAbsoluteUrl(url), response }; } logToConsole(): void { diff --git a/src/Components/WebAssembly/WebAssembly/src/Services/WebAssemblyConsoleLogger.cs b/src/Components/WebAssembly/WebAssembly/src/Services/WebAssemblyConsoleLogger.cs index c5a658be60cf..073ed5f7675a 100644 --- a/src/Components/WebAssembly/WebAssembly/src/Services/WebAssemblyConsoleLogger.cs +++ b/src/Components/WebAssembly/WebAssembly/src/Services/WebAssemblyConsoleLogger.cs @@ -177,6 +177,6 @@ internal static partial class ConsoleLoggerInterop public static partial void ConsoleWarn(string message); [JSImport("globalThis.console.error")] public static partial void ConsoleError(string message); - [JSImport("Blazor._internal.dotNetCriticalError")] + [JSImport("Blazor._internal.dotNetCriticalError", "blazor-internal")] public static partial void DotNetCriticalError(string message); } From b6438efe5d2a6207d2674cebd4494657a195967e Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 16 Dec 2022 17:09:07 +0100 Subject: [PATCH 2/5] more cleanup --- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index ee152dde03f2..f9d7178e7047 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -201,26 +201,9 @@ async function importDotnetJs(resourceLoader: WebAssemblyResourceLoader): Promis document.head.appendChild(scriptElem); } - // GOTCHA: remove this once runtime switched to ES6 - // this is capturing the export via callback we have in CJS version of the runtime - let cjsExportResolve: (data: CreateDotnetRuntimeType) => void = undefined as any; - const cjsExport = new Promise((resolve) => { - cjsExportResolve = resolve; - }); - globalThis.__onDotnetRuntimeLoaded = (createDotnetRuntime) => { - delete globalThis.__onDotnetRuntimeLoaded; - cjsExportResolve(createDotnetRuntime); - }; - const absoluteSrc = (new URL(src, document.baseURI)).toString(); const { default: createDotnetRuntime } = await import(/* webpackIgnore: true */ absoluteSrc); - if (createDotnetRuntime) { - // this runs when loaded module was ES6 - delete globalThis.__onDotnetRuntimeLoaded; - return createDotnetRuntime; - } - - return await cjsExport; + return await createDotnetRuntime; } async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoader): Promise { From 6c6986dedc37a1ed56eba41a2625fc2e16527d82 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 19 Dec 2022 15:57:37 +0100 Subject: [PATCH 3/5] fix --- src/Components/Web.JS/@types/dotnet/dotnet.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Web.JS/@types/dotnet/dotnet.d.ts b/src/Components/Web.JS/@types/dotnet/dotnet.d.ts index 795b52f709a5..01e2a72eee6f 100644 --- a/src/Components/Web.JS/@types/dotnet/dotnet.d.ts +++ b/src/Components/Web.JS/@types/dotnet/dotnet.d.ts @@ -270,4 +270,4 @@ declare global { declare const dotnet: ModuleAPI["dotnet"]; declare const exit: ModuleAPI["exit"]; -export { CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, IMemoryView, ModuleAPI, MonoConfig, RuntimeAPI, createDotnetRuntime as default, dotnet, exit }; +export { CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, IMemoryView, ModuleAPI, MonoConfig, RuntimeAPI, AssetEntry, ResourceRequest, createDotnetRuntime as default, dotnet, exit }; From bd6532ff4988b38c35551a0fd44da18082e35aad Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 19 Dec 2022 18:19:13 +0100 Subject: [PATCH 4/5] fix --- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index f9d7178e7047..741ecf3c36e0 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -248,10 +248,15 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc }; // it would not `loadResource` on types for which there is no typesMap mapping - const downloadResource = (request: ResourceRequest): LoadingResource | undefined => { - const type = monoToBlazorAssetTypeMap[request.behavior]; + const downloadResource = (asset: AssetEntry): LoadingResource | undefined => { + // this whole condition could be removed after the resourceLoader could cache in-flight requests + if (asset.behavior === 'dotnetwasm') { + return runtimeAssetsBeingLoaded + .filter(request => request.name === asset.name)[0]; + } + const type = monoToBlazorAssetTypeMap[asset.behavior]; if (type !== undefined) { - return resourceLoader.loadResource(request.name, request.resolvedUrl!, request.hash!, type); + return resourceLoader.loadResource(asset.name, asset.resolvedUrl!, asset.hash!, type); } return undefined; }; @@ -268,16 +273,12 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc // blazor could start downloading bit earlier than the runtime would const runtimeAssetsBeingLoaded = assets .filter(asset => asset.behavior === 'dotnetwasm') - .map(asset => { - asset.pendingDownload = downloadResource(asset); - return asset.pendingDownload!; - }); + .map(asset => resourceLoader.loadResource(asset.name, asset.resolvedUrl!, asset.hash!, 'dotnetwasm')); // Begin loading the .dll/.pdb/.wasm files, but don't block here. Let other loading processes run in parallel. const assembliesBeingLoaded = resourceLoader.loadResources(resources.assembly, filename => `_framework/${filename}`, 'assembly'); const pdbsBeingLoaded = resourceLoader.loadResources(resources.pdb || {}, filename => `_framework/${filename}`, 'pdb'); const totalResources = assembliesBeingLoaded.concat(pdbsBeingLoaded, runtimeAssetsBeingLoaded); - totalResources.forEach(loadingResource => loadingResource.response.then(_ => setProgress())); const dotnetTimeZoneResourceName = 'dotnet.timezones.blat'; let timeZoneResource: LoadingResource | undefined; @@ -306,6 +307,7 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc icuDataResource.response.then(_ => setProgress()); } + totalResources.forEach(loadingResource => loadingResource.response.then(_ => setProgress())); const createDotnetRuntime = await dotnetJsBeingLoaded; await createDotnetRuntime((api) => { From d1e0e346c52013267ff2b825d8dae3da27d95cbe Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 21 Dec 2022 16:30:12 +0100 Subject: [PATCH 5/5] prep for pendingDownload --- src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index 741ecf3c36e0..be4fecb69f7b 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -273,7 +273,10 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc // blazor could start downloading bit earlier than the runtime would const runtimeAssetsBeingLoaded = assets .filter(asset => asset.behavior === 'dotnetwasm') - .map(asset => resourceLoader.loadResource(asset.name, asset.resolvedUrl!, asset.hash!, 'dotnetwasm')); + .map(asset => { + asset.pendingDownload = resourceLoader.loadResource(asset.name, asset.resolvedUrl!, asset.hash!, 'dotnetwasm'); + return asset.pendingDownload; + }); // Begin loading the .dll/.pdb/.wasm files, but don't block here. Let other loading processes run in parallel. const assembliesBeingLoaded = resourceLoader.loadResources(resources.assembly, filename => `_framework/${filename}`, 'assembly');