From b2a8a130a9129dd7bf0d708976cbe8332c939b49 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 2 Aug 2022 20:50:12 +0200 Subject: [PATCH 1/7] wip --- .../Web.JS/@types/dotnet/dotnet.d.ts | 388 +++++++++--------- .../Web.JS/src/Platform/BootConfig.ts | 9 +- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 111 +++-- 3 files changed, 253 insertions(+), 255 deletions(-) diff --git a/src/Components/Web.JS/@types/dotnet/dotnet.d.ts b/src/Components/Web.JS/@types/dotnet/dotnet.d.ts index 0e7590eadfdd..0d429f4dcd9a 100644 --- a/src/Components/Web.JS/@types/dotnet/dotnet.d.ts +++ b/src/Components/Web.JS/@types/dotnet/dotnet.d.ts @@ -3,7 +3,7 @@ //! //! This is generated file, see src/mono/wasm/runtime/rollup.config.js -//! This is not considered public API with backward compatibility guarantees. +//! This is not considered public API with backward compatibility guarantees. declare interface ManagedPointer { __brandManagedPointer: "ManagedPointer"; @@ -50,17 +50,19 @@ declare interface EmscriptenModule { stackRestore(stack: VoidPtr): void; stackAlloc(size: number): VoidPtr; ready: Promise; + instantiateWasm?: (imports: WebAssembly.Imports, successCallback: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void) => any; preInit?: (() => any)[]; preRun?: (() => any)[]; + onRuntimeInitialized?: () => any; postRun?: (() => any)[]; onAbort?: { (error: any): void; }; - onRuntimeInitialized?: () => any; - instantiateWasm: (imports: any, successCallback: Function) => any; } declare type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array; +declare function mono_wasm_runtime_ready(): void; + /** * 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. @@ -128,6 +130,47 @@ interface WasmRoot { toString(): string; } +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 { + /** + * copies elements from provided source to the wasm memory. + * target has to have the elements of the same type as the underlying C# array. + * same as TypedArray.set() + */ + set(source: TypedArray, targetOffset?: number): void; + /** + * copies elements from wasm memory to provided target. + * target has to have the elements of the same type as the underlying C# array. + */ + copyTo(target: TypedArray, sourceOffset?: number): void; + /** + * same as TypedArray.slice() + */ + slice(start?: number, end?: number): TypedArray; + get length(): number; + get byteLength(): number; +} + interface MonoObject extends ManagedPointer { __brandMonoObject: "MonoObject"; } @@ -141,20 +184,28 @@ interface MonoObjectRef extends ManagedPointer { __brandMonoObjectRef: "MonoObjectRef"; } declare type MonoConfig = { - isError: false; - assembly_root: string; - assets: AllAssetEntryTypes[]; + isError?: false; + assembly_root?: string; + assets?: AssetEntry[]; + /** + * Either this or enable_debugging needs to be set + * debug_level > 0 enables debugging and sets the debug log level to debug_level + * debug_level == 0 disables debugging and enables interpreter optimizations + * debug_level < 0 enabled debugging and disables debug logging. + */ debug_level?: number; enable_debugging?: number; - globalization_mode: GlobalizationMode; + globalization_mode?: GlobalizationMode; diagnostic_tracing?: boolean; remote_sources?: string[]; + max_parallel_downloads?: number; environment_variables?: { [i: string]: string; }; runtime_options?: string[]; aot_profiler_options?: AOTProfilerOptions; coverage_profiler_options?: CoverageProfilerOptions; + diagnostic_options?: DiagnosticOptions; ignore_pdb_load_errors?: boolean; wait_for_debugger?: number; }; @@ -163,43 +214,24 @@ declare type MonoConfigError = { message: string; error: any; }; -declare type AllAssetEntryTypes = AssetEntry | AssemblyEntry | SatelliteAssemblyEntry | VfsEntry | IcuData; -declare type AssetEntry = { +interface ResourceRequest { name: string; behavior: AssetBehaviours; + resolvedUrl?: string; + hash?: string; +} +interface AssetEntry extends ResourceRequest { virtual_path?: string; culture?: string; load_remote?: boolean; is_optional?: boolean; buffer?: ArrayBuffer; -}; -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; -} -declare const enum AssetBehaviours { - Resource = "resource", - Assembly = "assembly", - Heap = "heap", - ICU = "icu", - VFS = "vfs" -} -declare const enum GlobalizationMode { - ICU = "icu", - INVARIANT = "invariant", - AUTO = "auto" + pending?: LoadingResource; } +declare type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm" | "js-module-crypto" | "js-module-threads"; +declare type GlobalizationMode = "icu" | // load ICU globalization data from any runtime assets with behavior "icu". +"invariant" | // operate in invariant globalization mode. +"auto"; declare type AOTProfilerOptions = { write_at?: string; send_to?: string; @@ -208,18 +240,27 @@ declare type CoverageProfilerOptions = { write_at?: string; send_to?: string; }; +declare type DiagnosticOptions = { + sessions?: EventPipeSessionOptions[]; + server?: DiagnosticServerOptions; +}; interface EventPipeSessionOptions { collectRundownEvents?: boolean; providers: string; } +declare type DiagnosticServerOptions = { + connect_url: string; + suspend: string | boolean; +}; declare type DotnetModuleConfig = { disableDotnet6Compatibility?: boolean; - config?: MonoConfig | MonoConfigError; + config?: MonoConfig; configSrc?: string; - onConfigLoaded?: (config: MonoConfig) => Promise; - onDotnetReady?: () => void; + onConfigLoaded?: (config: MonoConfig) => void | Promise; + onDotnetReady?: () => void | Promise; imports?: DotnetModuleConfigImports; exports?: string[]; + downloadResource?: (request: ResourceRequest) => LoadingResource; } & Partial; declare type DotnetModuleConfigImports = { require?: (name: string) => any; @@ -242,14 +283,26 @@ declare type DotnetModuleConfigImports = { }; url?: any; }; - +interface LoadingResource { + name: string; + url: string; + response: Promise; +} declare type EventPipeSessionID = bigint; -interface EventPipeSession { - get sessionID(): EventPipeSessionID; - start(): void; - stop(): void; - getTraceBlob(): Blob; +interface DotnetPublicAPI { + MONO: MONOType; + BINDING: BINDINGType; + INTERNAL: any; + EXPORTS: any; + IMPORTS: any; + Module: EmscriptenModule; + RuntimeId: number; + RuntimeBuildInfo: { + ProductVersion: string; + Configuration: string; + }; } + declare const eventLevel: { readonly LogAlways: 0; readonly Critical: 1; @@ -280,59 +333,24 @@ declare class SessionOptionsBuilder { addSampleProfilerProvider(overrideOptions?: UnnamedProviderConfiguration): SessionOptionsBuilder; build(): EventPipeSessionOptions; } + +interface EventPipeSession { + get sessionID(): EventPipeSessionID; + start(): void; + stop(): void; + getTraceBlob(): Blob; +} + interface Diagnostics { EventLevel: EventLevel; SessionOptionsBuilder: typeof SessionOptionsBuilder; createEventPipeSession(options?: EventPipeSessionOptions): EventPipeSession | null; + getStartupSessions(): (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 function mono_wasm_get_assembly_exports(assembly: string): Promise; declare type _MemOffset = number | VoidPtr | NativePointer | ManagedPointer; declare type _NumberOrPointer = number | VoidPtr | NativePointer | ManagedPointer; @@ -372,54 +390,101 @@ 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_wasm_load_bytes_into_heap(bytes: Uint8Array): VoidPtr; 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; -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 { +declare function mono_wasm_setenv(name: string, value: string): void; +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; +/** +* @deprecated +*/ +declare function mono_load_runtime_and_bcl_args(cfg?: MonoConfig | MonoConfigError | undefined): Promise; + +/** + * @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; + +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; + +/** + * @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 mono_bind_static_method(fqn: string, signature?: string): Function; +declare function mono_call_assembly_entry_point(assembly: string, args?: any[], signature?: string): number; + +declare type BINDINGType = { + bind_static_method: typeof mono_bind_static_method; + call_assembly_entry_point: typeof mono_call_assembly_entry_point; /** - * copies elements from provided source to the wasm memory. - * target has to have the elements of the same type as the underlying C# array. - * same as TypedArray.set() + * @deprecated Not GC or thread safe */ - set(source: TypedArray, targetOffset?: number): void; + mono_obj_array_new: (size: number) => MonoArray; /** - * copies elements from wasm memory to provided target. - * target has to have the elements of the same type as the underlying C# array. + * @deprecated Not GC or thread safe */ - copyTo(target: TypedArray, sourceOffset?: number): void; + mono_obj_array_set: (array: MonoArray, idx: number, obj: MonoObject) => void; /** - * same as TypedArray.slice() + * @deprecated Not GC or thread safe */ - slice(start?: number, end?: number): TypedArray; - get length(): number; - get byteLength(): number; -} - -declare function mono_wasm_get_assembly_exports(assembly: string): Promise; - -declare const MONO: { + 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; + 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; +}; +declare type MONOType = { 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; @@ -464,69 +529,6 @@ declare const MONO: { 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; @@ -551,7 +553,7 @@ declare class Span implements IMemoryView, IDisposable { /** * 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. + * User could dispose it manually. */ declare class ArraySegment implements IMemoryView, IDisposable { dispose(): void; @@ -563,4 +565,4 @@ declare class ArraySegment implements IMemoryView, IDisposable { get byteLength(): number; } -export { ArraySegment, BINDINGType, CreateDotnetRuntimeType, DotnetModuleConfig, DotnetPublicAPI, EmscriptenModule, IMemoryView, MONOType, ManagedError, ManagedObject, MemoryViewType, MonoArray, MonoObject, MonoString, Span, VoidPtr, createDotnetRuntime as default }; +export { ArraySegment, AssetBehaviours, AssetEntry, BINDINGType, CreateDotnetRuntimeType, DotnetModuleConfig, DotnetPublicAPI, EmscriptenModule, IMemoryView, LoadingResource, MONOType, ManagedError, ManagedObject, MemoryViewType, MonoArray, MonoConfig, MonoObject, MonoString, ResourceRequest, Span, VoidPtr, createDotnetRuntime as default }; diff --git a/src/Components/Web.JS/src/Platform/BootConfig.ts b/src/Components/Web.JS/src/Platform/BootConfig.ts index 4f14e8fe3918..83f7ee65f5e6 100644 --- a/src/Components/Web.JS/src/Platform/BootConfig.ts +++ b/src/Components/Web.JS/src/Platform/BootConfig.ts @@ -33,7 +33,7 @@ export class BootConfigResult { return new BootConfigResult(bootConfig, applicationEnvironment); - function defaultLoadBlazorBootJson(url: string) : Promise { + function defaultLoadBlazorBootJson(url: string): Promise { return fetch(url, { method: 'GET', credentials: 'include', @@ -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 03c2a5d90f75..1fdae5fa14b3 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -12,7 +12,7 @@ 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 { DotnetPublicAPI, BINDINGType, CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, MONOType, AssetEntry, ResourceRequest } from 'dotnet'; // initially undefined and only fully initialized after createEmscriptenModuleInstance() export let BINDING: BINDINGType = undefined as any; @@ -20,7 +20,6 @@ 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 @@ -145,13 +144,13 @@ export const monoPlatform: Platform = { return ((baseAddress as any as number) + (fieldOffset || 0)) as any as T; }, - beginHeapLock: function() { + beginHeapLock: function () { assertHeapIsNotLocked(); currentHeapLock = new MonoHeapLock(); return currentHeapLock; }, - invokeWhenHeapUnlocked: function(callback) { + invokeWhenHeapUnlocked: function (callback) { // This is somewhat like a sync context. If we're not locked, just pass through the call directly. if (!currentHeapLock) { callback(); @@ -251,24 +250,52 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc (moduleConfig as any).preloadPlugins = []; let resourcesLoaded = 0; - function setProgress(){ - resourcesLoaded++; - const percentage = resourcesLoaded / totalResources.length * 100; - document.documentElement.style.setProperty('--blazor-load-percentage', `${percentage}%`); - document.documentElement.style.setProperty('--blazor-load-percentage-text', `"${Math.floor(percentage)}%"`); + function setProgress() { + resourcesLoaded++; + const percentage = resourcesLoaded / totalResources.length * 100; + document.documentElement.style.setProperty('--blazor-load-percentage', `${percentage}%`); + document.documentElement.style.setProperty('--blazor-load-percentage-text', `"${Math.floor(percentage)}%"`); + } + + const typesMap: { [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 = typesMap[request.behavior]; + if (type !== undefined) { + const loaded = resourceLoader.loadResource(request.name, request.resolvedUrl!, request.hash!, type); + loaded.url = toAbsoluteUrl(loaded.url); + return loaded; } + 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 assetsBeingLoaded = assets + .filter(asset => asset.behavior === 'dotnetwasm') + .map(asset => { + asset.pending = downloadResource(asset); + return asset.pending!; + }); // 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, assetsBeingLoaded); totalResources.forEach(loadingResource => loadingResource.response.then(_ => setProgress())); const dotnetTimeZoneResourceName = 'dotnet.timezones.blat'; @@ -307,22 +334,6 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc MONO = mono; IMPORTS = imports; - // Override the mechanism for fetching the main wasm file so we can connect it to our cache - const instantiateWasm = (wasmImports, successCallback) => { - (async () => { - let compiledInstance: WebAssembly.Instance; - try { - const dotnetWasmResource = await wasmBeingLoaded; - compiledInstance = await compileWasmModule(dotnetWasmResource, wasmImports); - } catch (ex) { - printErr((ex as Error).toString()); - throw ex; - } - successCallback(compiledInstance); - })(); - return []; // No exports - }; - const onRuntimeInitialized = () => { if (!icuDataResource) { // Use invariant culture if the app does not carry icu data. @@ -479,7 +490,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', ''); @@ -520,12 +531,16 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc const dotnetModuleConfig: DotnetModuleConfig = { ...moduleConfig, + config: { + assets, + debug_level: hasDebuggingEnabled() ? 1 : 0, + }, + downloadResource, disableDotnet6Compatibility: false, preRun: [preRun, ...existingPreRun], postRun: [postRun, ...existingPostRun], print, printErr, - instantiateWasm, onRuntimeInitialized, }; @@ -650,32 +665,6 @@ async function loadICUData(icuDataResource: LoadingResource): Promise { } Module.removeRunDependency(runDependencyId); } - -async function compileWasmModule(wasmResource: LoadingResource, imports: any): Promise { - const wasmResourceResponse = await wasmResource.response; - - // The instantiateStreaming spec explicitly requires the following exact MIME type (with no trailing parameters, etc.) - // https://webassembly.github.io/spec/web-api/#dom-webassembly-instantiatestreaming - const hasWasmContentType = wasmResourceResponse.headers?.get('content-type') === 'application/wasm'; - - if (hasWasmContentType && typeof WebAssembly.instantiateStreaming === 'function') { - // We can use streaming compilation. We know this shouldn't fail due to the content-type header being wrong, - // as we already just checked that. So if this fails for some other reason we'll treat it as fatal. - const streamingResult = await WebAssembly.instantiateStreaming(wasmResourceResponse, imports); - return streamingResult.instance; - } else { - if (!hasWasmContentType) { - // In most cases the developer should fix this. It's unusual enough that we don't mind logging a warning each time. - console.warn('WebAssembly resource does not have the expected content type "application/wasm", so falling back to slower ArrayBuffer instantiation.'); - } - - // Fall back on ArrayBuffer instantiation. - const arrayBuffer = await wasmResourceResponse.arrayBuffer(); - const arrayBufferResult = await WebAssembly.instantiate(arrayBuffer, imports); - return arrayBufferResult.instance; - } -} - function changeExtension(filename: string, newExtensionWithLeadingDot: string) { const lastDotIndex = filename.lastIndexOf('.'); if (lastDotIndex < 0) { From 8a9e7a4010a1153267cb9c1ebfb8d6d223857a0b Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 2 Aug 2022 22:24:08 +0200 Subject: [PATCH 2/7] wip --- src/Components/Web.JS/@types/dotnet/dotnet.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Components/Web.JS/@types/dotnet/dotnet.d.ts b/src/Components/Web.JS/@types/dotnet/dotnet.d.ts index 0d429f4dcd9a..ac068d05601c 100644 --- a/src/Components/Web.JS/@types/dotnet/dotnet.d.ts +++ b/src/Components/Web.JS/@types/dotnet/dotnet.d.ts @@ -3,7 +3,7 @@ //! //! This is generated file, see src/mono/wasm/runtime/rollup.config.js -//! This is not considered public API with backward compatibility guarantees. +//! This is not considered public API with backward compatibility guarantees. declare interface ManagedPointer { __brandManagedPointer: "ManagedPointer"; @@ -230,8 +230,8 @@ interface AssetEntry extends ResourceRequest { } declare type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm" | "js-module-crypto" | "js-module-threads"; declare type GlobalizationMode = "icu" | // load ICU globalization data from any runtime assets with behavior "icu". -"invariant" | // operate in invariant globalization mode. -"auto"; + "invariant" | // operate in invariant globalization mode. + "auto"; declare type AOTProfilerOptions = { write_at?: string; send_to?: string; @@ -260,7 +260,7 @@ declare type DotnetModuleConfig = { onDotnetReady?: () => void | Promise; imports?: DotnetModuleConfigImports; exports?: string[]; - downloadResource?: (request: ResourceRequest) => LoadingResource; + downloadResource?: (request: ResourceRequest) => LoadingResource | undefined; } & Partial; declare type DotnetModuleConfigImports = { require?: (name: string) => any; From fe06488e8ab4dbb617804465561125c92b12e414 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 3 Aug 2022 15:58:54 +0200 Subject: [PATCH 3/7] wip --- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 16 ++++------------ .../src/Platform/WebAssemblyResourceLoader.ts | 8 +++++++- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index 1fdae5fa14b3..c61db19c52b9 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -257,7 +257,7 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc document.documentElement.style.setProperty('--blazor-load-percentage-text', `"${Math.floor(percentage)}%"`); } - const typesMap: { [key: string]: WebAssemblyBootResourceType | undefined } = { + const monoToBlazorAssetTypeMap: { [key: string]: WebAssemblyBootResourceType | undefined } = { 'assembly': 'assembly', 'pdb': 'pdb', 'icu': 'globalization', @@ -266,11 +266,9 @@ 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 = typesMap[request.behavior]; + const type = monoToBlazorAssetTypeMap[request.behavior]; if (type !== undefined) { - const loaded = resourceLoader.loadResource(request.name, request.resolvedUrl!, request.hash!, type); - loaded.url = toAbsoluteUrl(loaded.url); - return loaded; + return resourceLoader.loadResource(request.name, request.resolvedUrl!, request.hash!, type); } return undefined; }; @@ -520,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; @@ -550,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/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 { From 3d41b13bd331489089bd5b3dbb2e22955e418fb2 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 3 Aug 2022 16:04:55 +0200 Subject: [PATCH 4/7] feedback --- src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index c61db19c52b9..3f68c885e26d 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -283,7 +283,7 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc }); // blazor could start downloading bit earlier than the runtime would - const assetsBeingLoaded = assets + const runtimeAssetsBeingLoaded = assets .filter(asset => asset.behavior === 'dotnetwasm') .map(asset => { asset.pending = downloadResource(asset); @@ -293,7 +293,7 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc // 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, assetsBeingLoaded); + const totalResources = assembliesBeingLoaded.concat(pdbsBeingLoaded, runtimeAssetsBeingLoaded); totalResources.forEach(loadingResource => loadingResource.response.then(_ => setProgress())); const dotnetTimeZoneResourceName = 'dotnet.timezones.blat'; From 4178c5a3a9907148e18cb70e882a51d1c796e9de Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 5 Aug 2022 13:49:12 +0200 Subject: [PATCH 5/7] updated MONO type definitions and JSImport usage --- .../Web.JS/@types/dotnet/dotnet-legacy.d.ts | 307 ++++++++++ .../Web.JS/@types/dotnet/dotnet.d.ts | 544 ++++-------------- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 23 +- .../Web.JS/src/Platform/Platform.ts | 2 +- .../src/Services/WebAssemblyConsoleLogger.cs | 2 +- 5 files changed, 438 insertions(+), 440 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..b09e8fe7d445 --- /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"; +} + +export interface MonoObject extends ManagedPointer { + __brandMonoObject: "MonoObject"; +} +export interface MonoString extends MonoObject { + __brand: "MonoString"; +} +export interface MonoArray extends MonoObject { + __brand: "MonoArray"; +} +export 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 }; diff --git a/src/Components/Web.JS/@types/dotnet/dotnet.d.ts b/src/Components/Web.JS/@types/dotnet/dotnet.d.ts index ac068d05601c..eacddc7a017b 100644 --- a/src/Components/Web.JS/@types/dotnet/dotnet.d.ts +++ b/src/Components/Web.JS/@types/dotnet/dotnet.d.ts @@ -3,11 +3,8 @@ //! //! This is generated file, see src/mono/wasm/runtime/rollup.config.js -//! This is not considered public API with backward compatibility guarantees. +//! This is not considered public API with backward compatibility guarantees. -declare interface ManagedPointer { - __brandManagedPointer: "ManagedPointer"; -} declare interface NativePointer { __brandNativePointer: "NativePointer"; } @@ -50,169 +47,40 @@ declare interface EmscriptenModule { stackRestore(stack: VoidPtr): void; stackAlloc(size: number): VoidPtr; ready: Promise; - instantiateWasm?: (imports: WebAssembly.Imports, successCallback: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void) => any; - preInit?: (() => any)[]; - preRun?: (() => any)[]; + instantiateWasm?: InstantiateWasmCallBack; + preInit?: (() => any)[] | (() => any); + preRun?: (() => any)[] | (() => any); onRuntimeInitialized?: () => any; - postRun?: (() => any)[]; + postRun?: (() => any)[] | (() => any); onAbort?: { (error: any): void; }; } +declare type InstantiateWasmSuccessCallback = (instance: WebAssembly.Instance, module: WebAssembly.Module) => void; +declare type InstantiateWasmCallBack = (imports: WebAssembly.Imports, successCallback: InstantiateWasmSuccessCallback) => any; declare type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array; -declare function mono_wasm_runtime_ready(): void; - -/** - * 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 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 { - /** - * copies elements from provided source to the wasm memory. - * target has to have the elements of the same type as the underlying C# array. - * same as TypedArray.set() - */ - set(source: TypedArray, targetOffset?: number): void; - /** - * copies elements from wasm memory to provided target. - * target has to have the elements of the same type as the underlying C# array. - */ - copyTo(target: TypedArray, sourceOffset?: number): void; - /** - * same as TypedArray.slice() - */ - slice(start?: number, end?: number): TypedArray; - get length(): number; - get byteLength(): number; -} - -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; + assemblyRootFolder?: string; assets?: AssetEntry[]; /** - * Either this or enable_debugging needs to be set - * debug_level > 0 enables debugging and sets the debug log level to debug_level - * debug_level == 0 disables debugging and enables interpreter optimizations - * debug_level < 0 enabled debugging and disables debug logging. + * 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. */ - debug_level?: number; - enable_debugging?: number; - globalization_mode?: GlobalizationMode; - diagnostic_tracing?: boolean; - remote_sources?: string[]; - max_parallel_downloads?: number; - environment_variables?: { + debugLevel?: number; + maxParallelDownloads?: number; + globalizationMode?: GlobalizationMode; + diagnosticTracing?: boolean; + remoteSources?: string[]; + environmentVariables?: { [i: string]: string; }; - runtime_options?: string[]; - aot_profiler_options?: AOTProfilerOptions; - coverage_profiler_options?: CoverageProfilerOptions; - diagnostic_options?: DiagnosticOptions; - ignore_pdb_load_errors?: boolean; - wait_for_debugger?: number; -}; -declare type MonoConfigError = { - isError: true; - message: string; - error: any; + runtimeOptions?: string[]; + aotProfilerOptions?: AOTProfilerOptions; + coverageProfilerOptions?: CoverageProfilerOptions; + ignorePdbLoadErrors?: boolean; + waitForDebugger?: number; }; interface ResourceRequest { name: string; @@ -221,36 +89,24 @@ interface ResourceRequest { hash?: string; } interface AssetEntry extends ResourceRequest { - virtual_path?: string; + virtualPath?: string; culture?: string; - load_remote?: boolean; - is_optional?: boolean; + loadRemote?: boolean; + isOptional?: boolean; buffer?: ArrayBuffer; pending?: LoadingResource; } declare type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm" | "js-module-crypto" | "js-module-threads"; declare type GlobalizationMode = "icu" | // load ICU globalization data from any runtime assets with behavior "icu". - "invariant" | // operate in invariant globalization mode. - "auto"; +"invariant" | // operate in invariant globalization mode. +"auto"; declare type AOTProfilerOptions = { - write_at?: string; - send_to?: string; + writeAt?: string; + sendTo?: string; }; declare type CoverageProfilerOptions = { - write_at?: string; - send_to?: string; -}; -declare type DiagnosticOptions = { - sessions?: EventPipeSessionOptions[]; - server?: DiagnosticServerOptions; -}; -interface EventPipeSessionOptions { - collectRundownEvents?: boolean; - providers: string; -} -declare type DiagnosticServerOptions = { - connect_url: string; - suspend: string | boolean; + writeAt?: string; + sendTo?: string; }; declare type DotnetModuleConfig = { disableDotnet6Compatibility?: boolean; @@ -258,277 +114,94 @@ declare type DotnetModuleConfig = { configSrc?: string; onConfigLoaded?: (config: MonoConfig) => void | Promise; onDotnetReady?: () => void | Promise; - imports?: DotnetModuleConfigImports; + 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; -}; interface LoadingResource { name: string; url: string; response: Promise; } -declare type EventPipeSessionID = bigint; -interface DotnetPublicAPI { - MONO: MONOType; - BINDING: BINDINGType; - INTERNAL: any; - EXPORTS: any; - IMPORTS: any; - Module: EmscriptenModule; - RuntimeId: number; - RuntimeBuildInfo: { - ProductVersion: string; - Configuration: string; - }; -} -declare const eventLevel: { - readonly LogAlways: 0; - readonly Critical: 1; - readonly Error: 2; - readonly Warning: 3; - readonly Informational: 4; - readonly Verbose: 5; +declare 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 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 EventPipeSession { - get sessionID(): EventPipeSessionID; - start(): void; - stop(): void; - getTraceBlob(): Blob; -} - -interface Diagnostics { - EventLevel: EventLevel; - SessionOptionsBuilder: typeof SessionOptionsBuilder; - createEventPipeSession(options?: EventPipeSessionOptions): EventPipeSession | null; - getStartupSessions(): (EventPipeSession | null)[]; -} - -declare function mono_wasm_load_icu_data(offset: VoidPtr): boolean; - -declare function mono_wasm_get_assembly_exports(assembly: string): Promise; - -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_wasm_load_bytes_into_heap(bytes: Uint8Array): VoidPtr; - -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 mono_wasm_setenv(name: string, value: string): void; -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; -/** -* @deprecated -*/ -declare function mono_load_runtime_and_bcl_args(cfg?: MonoConfig | MonoConfigError | undefined): Promise; - -/** - * @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; - -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; - -/** - * @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 mono_bind_static_method(fqn: string, signature?: string): Function; -declare function mono_call_assembly_entry_point(assembly: string, args?: any[], signature?: string): number; - -declare type BINDINGType = { - bind_static_method: typeof mono_bind_static_method; - call_assembly_entry_point: typeof mono_call_assembly_entry_point; +declare type DotnetPublicAPI = { /** - * @deprecated Not GC or thread safe + * @deprecated Please use API object instead. See also MONOType in dotnet-legacy.d.ts */ - mono_obj_array_new: (size: number) => MonoArray; + MONO: any; /** - * @deprecated Not GC or thread safe + * @deprecated Please use API object instead. See also BINDINGType in dotnet-legacy.d.ts */ - 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; + BINDING: any; + INTERNAL: any; + Module: EmscriptenModule; + runtimeId: number; + runtimeBuildInfo: { + productVersion: string; + buildConfiguration: string; + }; +} & APIType; + +interface IDisposable { + dispose(): void; + get isDisposed(): boolean; +} +declare const enum MemoryViewType { + Byte = 0, + Int32 = 1, + Double = 2 +} +interface IMemoryView { /** - * @deprecated Not GC or thread safe + * copies elements from provided source to the wasm memory. + * target has to have the elements of the same type as the underlying C# array. + * same as TypedArray.set() */ - js_to_mono_obj: typeof js_to_mono_obj; + set(source: TypedArray, targetOffset?: number): void; /** - * @deprecated Not GC or thread safe + * copies elements from wasm memory to provided target. + * target has to have the elements of the same type as the underlying C# array. */ - conv_string: typeof conv_string; + copyTo(target: TypedArray, sourceOffset?: number): void; /** - * @deprecated Not GC or thread safe + * same as TypedArray.slice() */ - unbox_mono_obj: typeof unbox_mono_obj; - 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; -}; -declare type MONOType = { - 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; -}; + slice(start?: number, end?: number): TypedArray; + get length(): number; + get byteLength(): number; +} declare function createDotnetRuntime(moduleFactory: DotnetModuleConfig | ((api: DotnetPublicAPI) => DotnetModuleConfig)): Promise; declare type CreateDotnetRuntimeType = typeof createDotnetRuntime; @@ -564,5 +237,22 @@ declare class ArraySegment implements IMemoryView, IDisposable { get length(): number; get byteLength(): number; } +/** + * Represents proxy to the System.Exception + */ +declare class ManagedError extends Error implements IDisposable { + get stack(): string | undefined; + dispose(): void; + get isDisposed(): boolean; + toString(): string; +} +/** + * Represents proxy to the System.Object + */ +declare class ManagedObject implements IDisposable { + dispose(): void; + get isDisposed(): boolean; + toString(): string; +} -export { ArraySegment, AssetBehaviours, AssetEntry, BINDINGType, CreateDotnetRuntimeType, DotnetModuleConfig, DotnetPublicAPI, EmscriptenModule, IMemoryView, LoadingResource, MONOType, ManagedError, ManagedObject, MemoryViewType, MonoArray, MonoConfig, MonoObject, MonoString, ResourceRequest, Span, VoidPtr, createDotnetRuntime as default }; +export { APIType, ArraySegment, AssetBehaviours, AssetEntry, CreateDotnetRuntimeType, DotnetModuleConfig, DotnetPublicAPI, EmscriptenModule, IMemoryView, LoadingResource, ManagedError, ManagedObject, MemoryViewType, MonoConfig, NativePointer, ResourceRequest, Span, createDotnetRuntime as default }; diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index 3f68c885e26d..e7e1b0b99f83 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -12,13 +12,13 @@ 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, AssetEntry, ResourceRequest } from 'dotnet'; +import { DotnetPublicAPI, 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 uint64HighOrderShift = Math.pow(2, 32); const maxSafeNumberHighPart = Math.pow(2, 21) - 1; // The high-order int32 from Number.MAX_SAFE_INTEGER @@ -144,13 +144,13 @@ export const monoPlatform: Platform = { return ((baseAddress as any as number) + (fieldOffset || 0)) as any as T; }, - beginHeapLock: function () { + beginHeapLock: function() { assertHeapIsNotLocked(); currentHeapLock = new MonoHeapLock(); return currentHeapLock; }, - invokeWhenHeapUnlocked: function (callback) { + invokeWhenHeapUnlocked: function(callback) { // This is somewhat like a sync context. If we're not locked, just pass through the call directly. if (!currentHeapLock) { callback(); @@ -245,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; @@ -326,11 +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, setModuleImports } = api; Module = module; BINDING = binding; MONO = mono; - IMPORTS = imports; const onRuntimeInitialized = () => { if (!icuDataResource) { @@ -497,8 +496,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 + setModuleImports('blazor-internal', { + Blazor: { _internal: Blazor._internal }, + }); attachInteropInvoker(); runtimeReadyResolve(api); @@ -531,7 +532,7 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc ...moduleConfig, config: { assets, - debug_level: hasDebuggingEnabled() ? 1 : 0, + debugLevel: hasDebuggingEnabled() ? 1 : 0, }, downloadResource, disableDotnet6Compatibility: false, 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/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 426cac08d435900dc1fa3d630794475bcbbc2cc5 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 10 Aug 2022 19:49:51 +0200 Subject: [PATCH 6/7] fix --- src/Components/Web.JS/@types/dotnet/dotnet-legacy.d.ts | 10 +++++----- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Components/Web.JS/@types/dotnet/dotnet-legacy.d.ts b/src/Components/Web.JS/@types/dotnet/dotnet-legacy.d.ts index b09e8fe7d445..6bfdd64e14bc 100644 --- a/src/Components/Web.JS/@types/dotnet/dotnet-legacy.d.ts +++ b/src/Components/Web.JS/@types/dotnet/dotnet-legacy.d.ts @@ -15,16 +15,16 @@ declare interface VoidPtr extends NativePointer { __brand: "VoidPtr"; } -export interface MonoObject extends ManagedPointer { +interface MonoObject extends ManagedPointer { __brandMonoObject: "MonoObject"; } -export interface MonoString extends MonoObject { +interface MonoString extends MonoObject { __brand: "MonoString"; } -export interface MonoArray extends MonoObject { +interface MonoArray extends MonoObject { __brand: "MonoArray"; } -export interface MonoObjectRef extends ManagedPointer { +interface MonoObjectRef extends ManagedPointer { __brandMonoObjectRef: "MonoObjectRef"; } declare type MemOffset = number | VoidPtr | NativePointer | ManagedPointer; @@ -304,4 +304,4 @@ declare type MONOType = { getF64: (offset: MemOffset) => number; }; -export { BINDINGType, MONOType }; +export { BINDINGType, MONOType, MonoArray, MonoObject, MonoString }; diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index e7e1b0b99f83..3cde73203eed 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -326,7 +326,7 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc const createDotnetRuntime = await dotnetJsBeingLoaded; await createDotnetRuntime((api) => { - const { MONO: mono, BINDING: binding, Module: module, setModuleImports } = api; + const { MONO: mono, BINDING: binding, Module: module } = api; Module = module; BINDING = binding; MONO = mono; @@ -497,7 +497,7 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc } // makes Blazor._internal visible to [JSImport] as "blazor-internal" module - setModuleImports('blazor-internal', { + api.setModuleImports('blazor-internal', { Blazor: { _internal: Blazor._internal }, }); From 514d5e1ea7d9acc959bbd11c31f96dccc936b508 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Thu, 11 Aug 2022 13:06:44 +0200 Subject: [PATCH 7/7] wip --- .../Web.JS/@types/dotnet/dotnet.d.ts | 32 +++++++++++++++---- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 4 +-- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/Components/Web.JS/@types/dotnet/dotnet.d.ts b/src/Components/Web.JS/@types/dotnet/dotnet.d.ts index eacddc7a017b..4d2208681b47 100644 --- a/src/Components/Web.JS/@types/dotnet/dotnet.d.ts +++ b/src/Components/Web.JS/@types/dotnet/dotnet.d.ts @@ -88,13 +88,38 @@ interface ResourceRequest { resolvedUrl?: string; hash?: string; } +interface LoadingResource { + name: string; + url: string; + response: Promise; +} 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; + /** + * 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; - pending?: LoadingResource; + /** + * 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; } declare type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm" | "js-module-crypto" | "js-module-threads"; declare type GlobalizationMode = "icu" | // load ICU globalization data from any runtime assets with behavior "icu". @@ -118,11 +143,6 @@ declare type DotnetModuleConfig = { exports?: string[]; downloadResource?: (request: ResourceRequest) => LoadingResource | undefined; } & Partial; -interface LoadingResource { - name: string; - url: string; - response: Promise; -} declare type APIType = { runMain: (mainAssemblyName: string, args: string[]) => Promise; diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index 3cde73203eed..e3dd7059bb00 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -286,8 +286,8 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc const runtimeAssetsBeingLoaded = assets .filter(asset => asset.behavior === 'dotnetwasm') .map(asset => { - asset.pending = downloadResource(asset); - return asset.pending!; + 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.