Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2cc5cd1
- better API and exit assert
pavelsavara Jan 29, 2024
f1cbff4
fix
pavelsavara Jan 29, 2024
0a633b3
Update src/mono/browser/runtime/dotnet.d.ts
pavelsavara Jan 30, 2024
0643bc0
Update src/mono/browser/runtime/dotnet.d.ts
pavelsavara Jan 30, 2024
0fa7ff3
Update src/mono/browser/runtime/dotnet.d.ts
pavelsavara Jan 30, 2024
1523802
Update src/mono/browser/runtime/dotnet.d.ts
pavelsavara Jan 30, 2024
6f9b4f1
Update src/mono/browser/runtime/dotnet.d.ts
pavelsavara Jan 30, 2024
692b1b3
Update src/mono/browser/runtime/dotnet.d.ts
pavelsavara Jan 30, 2024
deffd52
Update src/mono/browser/runtime/dotnet.d.ts
pavelsavara Jan 30, 2024
8b90dd7
Update src/mono/browser/runtime/dotnet.d.ts
pavelsavara Jan 30, 2024
d92d820
Update src/mono/browser/runtime/dotnet.d.ts
pavelsavara Jan 30, 2024
6cd8dd8
Update src/mono/browser/runtime/dotnet.d.ts
pavelsavara Jan 30, 2024
2fc30ac
Update src/mono/browser/runtime/loader/exit.ts
pavelsavara Jan 30, 2024
7e487d9
Update src/mono/browser/runtime/loader/exit.ts
pavelsavara Jan 30, 2024
ad07814
Update src/mono/browser/runtime/dotnet.d.ts
pavelsavara Jan 30, 2024
e3e516e
Update src/mono/browser/runtime/dotnet.d.ts
pavelsavara Jan 30, 2024
b80d4d1
Update src/mono/browser/runtime/types/index.ts
pavelsavara Jan 30, 2024
3e5b7a0
update
pavelsavara Jan 30, 2024
b293f86
WASM read/write
maraf Jan 30, 2024
7aade17
feedback from @maraf
pavelsavara Jan 30, 2024
787c1b2
fix
pavelsavara Jan 30, 2024
95e5437
fix
pavelsavara Jan 30, 2024
891ec7b
fix
pavelsavara Jan 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 196 additions & 3 deletions src/mono/browser/runtime/dotnet.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,26 +54,79 @@ type InstantiateWasmCallBack = (imports: WebAssembly.Imports, successCallback: I
declare type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array;

interface DotnetHostBuilder {
/**
* @param config default values for the runtime configuration. It will be merged with the default values.
* Note that if you provide resources and don't provide custom configSrc URL, the blazor.boot.json will be downloaded and applied by default.
*/
withConfig(config: MonoConfig): DotnetHostBuilder;
/**
* @param configSrc URL to the configuration file. ./blazor.boot.json is a default config file location.
*/
withConfigSrc(configSrc: string): DotnetHostBuilder;
/**
* "command line" arguments for the Main() method.
* @param args
*/
withApplicationArguments(...args: string[]): DotnetHostBuilder;
/**
* Sets the environment variable for the "process"
*/
withEnvironmentVariable(name: string, value: string): DotnetHostBuilder;
/**
* Sets the environment variables for the "process"
*/
withEnvironmentVariables(variables: {
[i: string]: string;
}): DotnetHostBuilder;
/**
* Sets the "current directory" for the "process" on the virtual file system.
*/
withVirtualWorkingDirectory(vfsPath: string): DotnetHostBuilder;
/**
* @param enabled if "true", writes diagnostic messages during runtime startup and execution to the browser console.
*/
withDiagnosticTracing(enabled: boolean): DotnetHostBuilder;
/**
* @param level
* level > 0 enables debugging and sets the logging level to debug
* level == 0 disables debugging and enables interpreter optimizations
* level < 0 enables debugging and disables debug logging.
*/
withDebugging(level: number): DotnetHostBuilder;
/**
* @param mainAssemblyName Sets the name of the assembly with the Main() method. Default is the same as the .csproj name.
*/
withMainAssembly(mainAssemblyName: string): DotnetHostBuilder;
/**
* Supply "command line" arguments for the Main() method from browser query arguments named "arg". Eg. `index.html?arg=A&arg=B&arg=C`.
* @param args
*/
withApplicationArgumentsFromQuery(): DotnetHostBuilder;
/**
* Sets application environment, such as "Development", "Staging", "Production", etc.
*/
withApplicationEnvironment(applicationEnvironment?: string): DotnetHostBuilder;
/**
* Sets application culture. This is a name specified in the BCP 47 format. See https://tools.ietf.org/html/bcp47
*/
withApplicationCulture(applicationCulture?: string): DotnetHostBuilder;
/**
* Overrides the built-in boot resource loading mechanism so that boot resources can be fetched
* from a custom source, such as an external CDN.
*/
withResourceLoader(loadBootResource?: LoadBootResourceCallback): DotnetHostBuilder;
/**
* Starts the runtime and returns promise of the API object.
*/
create(): Promise<RuntimeAPI>;
/**
* Runs the Main() method of the application and exits the runtime.
* You can provide "command line" arguments for the Main() method using
* - dotnet.withApplicationArguments(["A", "B", "C"])
* - dotnet.withApplicationArgumentsFromQuery()
* Note: after the runtime exits, it would reject all further calls to the API.
* You can use runMain() if you want to keep the runtime alive.
*/
run(): Promise<number>;
}
type MonoConfig = {
Expand Down Expand Up @@ -281,7 +334,7 @@ interface AssetEntry {
}
type SingleAssetBehaviors =
/**
* The binary of the dotnet runtime.
* The binary of the .NET runtime.
*/
"dotnetwasm"
/**
Expand Down Expand Up @@ -373,45 +426,179 @@ type DotnetModuleConfig = {
exports?: string[];
} & Partial<EmscriptenModule>;
type APIType = {
runMain: (mainAssemblyName: string, args?: string[]) => Promise<number>;
runMainAndExit: (mainAssemblyName: string, args?: string[]) => Promise<number>;
/**
* Runs the Main() method of the application.
* Note: this will keep the .NET runtime alive and the APIs will be available for further calls.
* @param mainAssemblyName name of the assembly with the Main() method. Optional. Default is the same as the .csproj name.
* @param args command line arguments for the Main() method. Optional.
* @returns exit code of the Main() method.
*/
runMain: (mainAssemblyName?: string, args?: string[]) => Promise<number>;
/**
* Runs the Main() method of the application and exits the runtime.
* Note: after the runtime exits, it would reject all further calls to the API.
* @param mainAssemblyName name of the assembly with the Main() method. Optional. Default is the same as the .csproj name.
* @param args command line arguments for the Main() method. Optional.
* @returns exit code of the Main() method.
*/
runMainAndExit: (mainAssemblyName?: string, args?: string[]) => Promise<number>;
/**
* Sets the environment variable for the "process"
* @param name
* @param value
*/
setEnvironmentVariable: (name: string, value: string) => void;
/**
* Returns the [JSExport] methods of the assembly with the given name
* @param assemblyName
*/
getAssemblyExports(assemblyName: string): Promise<any>;
/**
* Provides functions which could be imported by the managed code using [JSImport]
* @param moduleName maps to the second parameter of [JSImport]
* @param moduleImports object with functions which could be imported by the managed code. The keys map to the first parameter of [JSImport]
*/
setModuleImports(moduleName: string, moduleImports: any): void;
/**
* Returns the configuration object used to start the runtime.
*/
getConfig: () => MonoConfig;
/**
* Executes scripts which were loaded during runtime bootstrap.
* You can register the scripts using MonoConfig.resources.modulesAfterConfigLoaded and MonoConfig.resources.modulesAfterRuntimeReady.
*/
invokeLibraryInitializers: (functionName: string, args: any[]) => Promise<void>;
/**
* Writes to the WASM linear memory
*/
setHeapB32: (offset: NativePointer, value: number | boolean) => void;
/**
* Writes to the WASM linear memory
*/
setHeapU8: (offset: NativePointer, value: number) => void;
/**
* Writes to the WASM linear memory
*/
setHeapU16: (offset: NativePointer, value: number) => void;
/**
* Writes to the WASM linear memory
*/
setHeapU32: (offset: NativePointer, value: NativePointer | number) => void;
/**
* Writes to the WASM linear memory
*/
setHeapI8: (offset: NativePointer, value: number) => void;
/**
* Writes to the WASM linear memory
*/
setHeapI16: (offset: NativePointer, value: number) => void;
/**
* Writes to the WASM linear memory
*/
setHeapI32: (offset: NativePointer, value: number) => void;
/**
* Writes to the WASM linear memory
*/
setHeapI52: (offset: NativePointer, value: number) => void;
/**
* Writes to the WASM linear memory
*/
setHeapU52: (offset: NativePointer, value: number) => void;
/**
* Writes to the WASM linear memory
*/
setHeapI64Big: (offset: NativePointer, value: bigint) => void;
/**
* Writes to the WASM linear memory
*/
setHeapF32: (offset: NativePointer, value: number) => void;
/**
* Writes to the WASM linear memory
*/
setHeapF64: (offset: NativePointer, value: number) => void;
/**
* Reads from the WASM linear memory
*/
getHeapB32: (offset: NativePointer) => boolean;
/**
* Reads from the WASM linear memory
*/
getHeapU8: (offset: NativePointer) => number;
/**
* Reads from the WASM linear memory
*/
getHeapU16: (offset: NativePointer) => number;
/**
* Reads from the WASM linear memory
*/
getHeapU32: (offset: NativePointer) => number;
/**
* Reads from the WASM linear memory
*/
getHeapI8: (offset: NativePointer) => number;
/**
* Reads from the WASM linear memory
*/
getHeapI16: (offset: NativePointer) => number;
/**
* Reads from the WASM linear memory
*/
getHeapI32: (offset: NativePointer) => number;
/**
* Reads from the WASM linear memory
*/
getHeapI52: (offset: NativePointer) => number;
/**
* Reads from the WASM linear memory
*/
getHeapU52: (offset: NativePointer) => number;
/**
* Reads from the WASM linear memory
*/
getHeapI64Big: (offset: NativePointer) => bigint;
/**
* Reads from the WASM linear memory
*/
getHeapF32: (offset: NativePointer) => number;
/**
* Reads from the WASM linear memory
*/
getHeapF64: (offset: NativePointer) => number;
/**
* Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await.
*/
localHeapViewI8: () => Int8Array;
/**
* Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await.
*/
localHeapViewI16: () => Int16Array;
/**
* Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await.
*/
localHeapViewI32: () => Int32Array;
/**
* Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await.
*/
localHeapViewI64Big: () => BigInt64Array;
/**
* Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await.
*/
localHeapViewU8: () => Uint8Array;
/**
* Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await.
*/
localHeapViewU16: () => Uint16Array;
/**
* Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await.
*/
localHeapViewU32: () => Uint32Array;
/**
* Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await.
*/
localHeapViewF32: () => Float32Array;
/**
* Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await.
*/
localHeapViewF64: () => Float64Array;
};
type RuntimeAPI = {
Expand All @@ -425,7 +612,13 @@ type RuntimeAPI = {
};
} & APIType;
type ModuleAPI = {
/**
* The builder for the .NET runtime.
*/
dotnet: DotnetHostBuilder;
/**
* Terminates the runtime "process" and reject all further calls to the API.
*/
exit: (code: number, reason?: any) => void;
};
type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise<RuntimeAPI>;
Expand Down
2 changes: 1 addition & 1 deletion src/mono/browser/runtime/gc-handles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export function assert_not_disposed(result: any): GCHandle {
}

function _js_owned_object_finalized(gc_handle: GCHandle): void {
if (loaderHelpers.is_exited()) {
if (!loaderHelpers.is_runtime_running()) {
// We're shutting down, so don't bother doing anything else.
return;
}
Expand Down
2 changes: 2 additions & 0 deletions src/mono/browser/runtime/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import gitHash from "consts:gitHash";

import { RuntimeAPI } from "./types/index";
import type { GlobalObjects, EmscriptenInternals, RuntimeHelpers, LoaderHelpers, DotnetModuleInternal, PromiseAndController } from "./types/internal";
import { mono_log_error } from "./logging";

// these are our public API (except internal)
export let Module: DotnetModuleInternal;
Expand Down Expand Up @@ -104,5 +105,6 @@ export function mono_assert(condition: unknown, messageFactory: string | (() =>
? messageFactory()
: messageFactory);
const error = new Error(message);
mono_log_error(message, error);
runtimeHelpers.nativeAbort(error);
}
4 changes: 2 additions & 2 deletions src/mono/browser/runtime/loader/exit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export function is_runtime_running() {
}

export function assert_runtime_running() {
mono_assert(runtimeHelpers.runtimeReady, "mono runtime didn't start yet");
mono_assert(!loaderHelpers.assertAfterExit || !is_exited(), () => `mono runtime already exited with ${loaderHelpers.exitCode} ${loaderHelpers.exitReason}`);
mono_assert(runtimeHelpers.runtimeReady, ".NET runtime didn't start yet. Please call dotnet.create() first.");
mono_assert(!loaderHelpers.assertAfterExit || !is_exited(), () => `.NET runtime already exited with ${loaderHelpers.exitCode} ${loaderHelpers.exitReason}. You can use runtime.runMain() which doesn't exit the runtime.`);
}

export function register_exit_handlers() {
Expand Down
3 changes: 2 additions & 1 deletion src/mono/browser/runtime/loader/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type { MonoConfig, RuntimeAPI } from "../types";
import { assert_runtime_running, is_exited, is_runtime_running, mono_exit } from "./exit";
import { assertIsControllablePromise, createPromiseController, getPromiseController } from "./promise-controller";
import { mono_download_assets, resolve_single_asset_path, retrieve_asset_download } from "./assets";
import { mono_set_thread_name, setup_proxy_console } from "./logging";
import { mono_log_error, mono_set_thread_name, setup_proxy_console } from "./logging";
import { invokeLibraryInitializers } from "./libraryInitializers";
import { deep_merge_config, hasDebuggingEnabled } from "./config";
import { logDownloadStatsToConsole, purgeUnusedCacheEntriesAsync } from "./assetsCache";
Expand Down Expand Up @@ -139,5 +139,6 @@ export function mono_assert(condition: unknown, messageFactory: string | (() =>
? messageFactory()
: messageFactory);
const error = new Error(message);
mono_log_error(message, error);
runtimeHelpers.nativeAbort(error);
}
3 changes: 1 addition & 2 deletions src/mono/browser/runtime/loader/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,7 @@ export class HostBuilder implements DotnetHostBuilder {
if (!this.instance) {
await this.create();
}
mono_assert(emscriptenModule.config.mainAssemblyName, "Null moduleConfig.config.mainAssemblyName");
return this.instance!.runMainAndExit(emscriptenModule.config.mainAssemblyName);
return this.instance!.runMainAndExit();
} catch (err) {
mono_exit(1, err);
throw err;
Expand Down
2 changes: 2 additions & 0 deletions src/mono/browser/runtime/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ const typesConfig = {
],
external: externalDependencies,
plugins: [dts()],
onwarn: onwarn
};

let diagnosticMockTypesConfig = undefined;
Expand Down Expand Up @@ -239,6 +240,7 @@ if (isDebug) {
],
external: externalDependencies,
plugins: [dts()],
onwarn: onwarn
};
}

Expand Down
10 changes: 7 additions & 3 deletions src/mono/browser/runtime/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import MonoWasmThreads from "consts:monoWasmThreads";

import { ENVIRONMENT_IS_NODE, loaderHelpers, runtimeHelpers } from "./globals";
import { ENVIRONMENT_IS_NODE, loaderHelpers, mono_assert, runtimeHelpers } from "./globals";
import { mono_wasm_wait_for_debugger } from "./debug";
import { mono_wasm_set_main_args } from "./startup";
import cwraps from "./cwraps";
Expand All @@ -15,7 +15,7 @@ import { cancelThreads } from "./pthreads/browser";
/**
* Possible signatures are described here https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line
*/
export async function mono_run_main_and_exit(main_assembly_name: string, args?: string[]): Promise<number> {
export async function mono_run_main_and_exit(main_assembly_name?: string, args?: string[]): Promise<number> {
try {
const result = await mono_run_main(main_assembly_name, args);
loaderHelpers.mono_exit(result);
Expand All @@ -37,7 +37,11 @@ export async function mono_run_main_and_exit(main_assembly_name: string, args?:
/**
* Possible signatures are described here https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line
*/
export async function mono_run_main(main_assembly_name: string, args?: string[]): Promise<number> {
export async function mono_run_main(main_assembly_name?: string, args?: string[]): Promise<number> {
if (main_assembly_name === undefined || main_assembly_name === null || main_assembly_name === "") {
main_assembly_name = loaderHelpers.config.mainAssemblyName;
mono_assert(main_assembly_name, "Null or empty config.mainAssemblyName");
}
if (args === undefined || args === null) {
args = runtimeHelpers.config.applicationArguments;
}
Expand Down
Loading