From 0d80733c267e5d19f78422b339b32923f0aa91c5 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Thu, 4 Aug 2022 08:19:50 +0200 Subject: [PATCH] [wasm] deprecate legacy JS API and propose new (#73068) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added new API methods to top level next to MONO and BINDING namespaces - marked MONO and BINDING namespaces obsolete - separated legacy API into dotnet-legacy.d.ts - renamed snake_case to camelCase names Co-authored-by: Marek FiĊĦera Co-authored-by: Ankit Jain --- .gitattributes | 1 + .gitignore | 2 + eng/liveBuilds.targets | 1 + .../Directory.Build.props | 1 + .../InteropServices/JavaScript/MemoryTests.cs | 18 +- .../JavaScript/Interop/JavaScriptExports.cs | 4 +- .../JavaScript/JSImportAttribute.cs | 8 +- .../JavaScript/JavaScriptTestHelper.cs | 4 + .../JavaScript/JavaScriptTestHelper.mjs | 14 +- src/mono/sample/mbr/browser/main.js | 4 +- .../sample/wasm/browser-bench/frame-main.js | 29 +- src/mono/sample/wasm/browser-bench/main.js | 8 +- .../Wasm.Browser.EventPipe.Sample.csproj | 12 +- .../Wasm.Browser.ThreadsEP.Sample.csproj | 2 +- .../sample/wasm/browser-mt-eventpipe/main.js | 4 +- .../sample/wasm/browser-profile/README.md | 10 +- .../Wasm.BrowserProfile.Sample.csproj | 2 +- src/mono/sample/wasm/browser-profile/main.js | 22 +- .../Wasm.Browser.WebPack.Sample.csproj | 2 + src/mono/sample/wasm/browser/Program.cs | 4 +- src/mono/sample/wasm/browser/main.js | 52 +- .../sample/wasm/console-node-es6/main.mjs | 12 +- .../Wasm.Console.Node.TS.Sample.csproj | 2 + src/mono/sample/wasm/console-v8-es6/main.mjs | 4 +- .../sample/wasm/console-v8-es6/v8shim.cjs | 11 - .../Wasm.Node.WebPack.Sample.csproj | 2 + src/mono/wasm/build/WasmApp.targets | 4 +- .../tests/debugger-test/debugger-driver.html | 20 +- .../tests/debugger-test/debugger-main.js | 12 +- .../wasm-page-without-assets.html | 19 +- src/mono/wasm/runtime/cjs/dotnet.cjs.lib.js | 117 ---- src/mono/wasm/runtime/cwraps.ts | 7 +- src/mono/wasm/runtime/debug.ts | 6 +- src/mono/wasm/runtime/diagnostics/README.md | 4 +- .../browser/session-options-builder.ts | 18 +- src/mono/wasm/runtime/diagnostics/index.ts | 10 +- src/mono/wasm/runtime/dotnet-legacy.d.ts | 439 +++++++++++++ src/mono/wasm/runtime/dotnet.d.ts | 578 ++++-------------- src/mono/wasm/runtime/es6/dotnet.es6.lib.js | 2 +- src/mono/wasm/runtime/es6/dotnet.es6.pre.js | 4 +- src/mono/wasm/runtime/export-api.ts | 46 ++ src/mono/wasm/runtime/export-types.ts | 33 +- src/mono/wasm/runtime/exports.ts | 78 ++- src/mono/wasm/runtime/icu.ts | 14 +- src/mono/wasm/runtime/imports.ts | 9 +- src/mono/wasm/runtime/invoke-cs.ts | 31 +- src/mono/wasm/runtime/invoke-js.ts | 16 +- src/mono/wasm/runtime/managed-exports.ts | 18 +- src/mono/wasm/runtime/marshal-to-cs.ts | 6 +- src/mono/wasm/runtime/marshal-to-js.ts | 4 +- src/mono/wasm/runtime/marshal.ts | 23 +- src/mono/wasm/runtime/modularize-dotnet.md | 41 +- .../wasm/runtime/net6-legacy/export-types.ts | 265 ++++++++ .../runtime/net6-legacy/exports-legacy.ts | 106 +--- .../wasm/runtime/net6-legacy/method-calls.ts | 2 +- src/mono/wasm/runtime/polyfills.ts | 2 +- src/mono/wasm/runtime/profiler.ts | 34 +- src/mono/wasm/runtime/rollup.config.js | 21 +- src/mono/wasm/runtime/run.ts | 4 +- src/mono/wasm/runtime/startup.ts | 148 +++-- src/mono/wasm/runtime/tsconfig.shared.json | 4 +- src/mono/wasm/runtime/types.ts | 115 ++-- src/mono/wasm/runtime/types/emscripten.ts | 6 +- src/mono/wasm/runtime/types/node.d.ts | 3 +- src/mono/wasm/runtime/web-socket.ts | 2 +- .../templates/templates/browser/Program.cs | 2 +- .../templates/browser/app-support.js | 140 +++-- .../wasm/templates/templates/browser/main.js | 19 +- .../templates/templates/console/Program.cs | 2 +- .../templates/console/app-support.mjs | 147 +++-- .../wasm/templates/templates/console/main.mjs | 19 +- src/mono/wasm/test-main.js | 193 +++--- src/mono/wasm/wasm.proj | 3 +- src/tasks/WasmAppBuilder/WasmAppBuilder.cs | 12 +- .../WebAssembly/Browser/HotReload/main.js | 2 +- 75 files changed, 1660 insertions(+), 1385 deletions(-) delete mode 100644 src/mono/wasm/runtime/cjs/dotnet.cjs.lib.js create mode 100644 src/mono/wasm/runtime/dotnet-legacy.d.ts create mode 100644 src/mono/wasm/runtime/export-api.ts create mode 100644 src/mono/wasm/runtime/net6-legacy/export-types.ts diff --git a/.gitattributes b/.gitattributes index a25b1f94d6e5..a3a9aba9074c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -76,3 +76,4 @@ src/tests/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp- src/tests/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/knucleotide-input.txt text eol=lf src/tests/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/knucleotide-input-big.txt text eol=lf src/mono/wasm/runtime/dotnet.d.ts text eol=lf +src/mono/wasm/runtime/dotnet-legacy.d.ts text eol=lf diff --git a/.gitignore b/.gitignore index 28326fe3f5e6..7317c06261a7 100644 --- a/.gitignore +++ b/.gitignore @@ -188,6 +188,8 @@ node_modules/ *.metaproj.tmp bin.localpkg/ src/mono/wasm/runtime/dotnet.d.ts.sha256 +src/mono/wasm/runtime/dotnet-legacy.d.ts.sha256 + src/mono/sample/wasm/browser-nextjs/public/ # RIA/Silverlight projects diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets index 44a60fce233c..0da788b3c272 100644 --- a/eng/liveBuilds.targets +++ b/eng/liveBuilds.targets @@ -181,6 +181,7 @@ $(LibrariesNativeArtifactsPath)dotnet.js; $(LibrariesNativeArtifactsPath)src\dotnet-crypto-worker.js; $(LibrariesNativeArtifactsPath)dotnet.d.ts; + $(LibrariesNativeArtifactsPath)dotnet-legacy.d.ts; $(LibrariesNativeArtifactsPath)package.json; $(LibrariesNativeArtifactsPath)dotnet.wasm; $(LibrariesNativeArtifactsPath)dotnet.js.symbols; diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index 42c107d012cb..b9cc3a522b42 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -218,6 +218,7 @@ + diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MemoryTests.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MemoryTests.cs index d7027fe0b958..70eb88b1a55c 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MemoryTests.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MemoryTests.cs @@ -26,8 +26,8 @@ namespace System.Runtime.InteropServices.JavaScript.Tests long dummy = 0xA6A6A6A6L; long actual2 = dummy; var bagFn = new Function("ptr", "ptr2", @" - const value=globalThis.App.MONO.getI52(ptr); - globalThis.App.MONO.setI52(ptr2, value); + const value=globalThis.App.runtime.getHeapI52(ptr); + globalThis.App.runtime.setHeapI52(ptr2, value); return ''+value;"); uint ptr = (uint)Unsafe.AsPointer(ref expected); @@ -53,8 +53,8 @@ namespace System.Runtime.InteropServices.JavaScript.Tests ulong dummy = 0xA6A6A6A6UL; ulong actual2 = dummy; var bagFn = new Function("ptr", "ptr2", @" - const value=globalThis.App.MONO.getI52(ptr); - globalThis.App.MONO.setU52(ptr2, value); + const value=globalThis.App.runtime.getHeapI52(ptr); + globalThis.App.runtime.setHeapU52(ptr2, value); return ''+value;"); uint ptr = (uint)Unsafe.AsPointer(ref expected); @@ -99,14 +99,14 @@ namespace System.Runtime.InteropServices.JavaScript.Tests long actual = 0; uint ptr = (uint)Unsafe.AsPointer(ref actual); var bagFn = new Function("ptr", "value", @" - globalThis.App.MONO.setI52(ptr, value);"); + globalThis.App.runtime.setHeapI52(ptr, value);"); var ex=Assert.Throws(() => bagFn.Call(null, ptr, value)); Assert.Contains("Value is not a safe integer", ex.Message); double expectedD = value; uint ptrD = (uint)Unsafe.AsPointer(ref expectedD); var bagFnD = new Function("ptr", "value", @" - globalThis.App.MONO.getI52(ptr);"); + globalThis.App.runtime.getHeapI52(ptr);"); var exD = Assert.Throws(() => bagFn.Call(null, ptr, value)); Assert.Contains("Value is not a safe integer", ex.Message); } @@ -118,14 +118,14 @@ namespace System.Runtime.InteropServices.JavaScript.Tests long actual = 0; uint ptr = (uint)Unsafe.AsPointer(ref actual); var bagFn = new Function("ptr", "value", @" - globalThis.App.MONO.setU52(ptr, value);"); + globalThis.App.runtime.setHeapU52(ptr, value);"); var ex=Assert.Throws(() => bagFn.Call(null, ptr, value)); Assert.Contains("Can't convert negative Number into UInt64", ex.Message); double expectedD = value; uint ptrD = (uint)Unsafe.AsPointer(ref expectedD); var bagFnD = new Function("ptr", "value", @" - globalThis.App.MONO.getU52(ptr);"); + globalThis.App.runtime.getHeapU52(ptr);"); var exD = Assert.Throws(() => bagFn.Call(null, ptr, value)); Assert.Contains("Can't convert negative Number into UInt64", ex.Message); } @@ -136,7 +136,7 @@ namespace System.Runtime.InteropServices.JavaScript.Tests long actual = 0; uint ptr = (uint)Unsafe.AsPointer(ref actual); var bagFn = new Function("ptr", "value", @" - globalThis.App.MONO.setI52(ptr, value);"); + globalThis.App.runtime.setHeapI52(ptr, value);"); var ex=Assert.Throws(() => bagFn.Call(null, ptr, double.NaN)); Assert.Contains("Value is not a safe integer: NaN (number)", ex.Message); } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs index c0aa35fed876..d2916b4e9c74 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs @@ -117,7 +117,7 @@ namespace System.Runtime.InteropServices.JavaScript { } - // Called by the AOT profiler to save profile data into INTERNAL.aot_profile_data + // Called by the AOT profiler to save profile data into INTERNAL.aotProfileData [MethodImpl(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425 public static unsafe void DumpAotProfileData(ref byte buf, int len, string extraArg) { @@ -133,7 +133,7 @@ namespace System.Runtime.InteropServices.JavaScript if (module == null) throw new InvalidOperationException(); - module.SetProperty("aot_profile_data", span.ToArray()); + module.SetProperty("aotProfileData", span.ToArray()); } } } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSImportAttribute.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSImportAttribute.cs index 05704d604995..2fe067921fb7 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSImportAttribute.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSImportAttribute.cs @@ -20,8 +20,6 @@ namespace System.Runtime.InteropServices.JavaScript /// public static partial int librarySum(int a, int b); /// [JSImport("Math.sum", "my-math-helper")] /// public static partial int libraryNamespaceSum(int a, int b); - /// [JSImport("IMPORTS.sum")] - /// public static partial int runtimeImportsSum(int a, int b); /// [JSImport("globalThis.Math.sum")] /// public static partial int globalSum(int a, int b); /// @@ -31,7 +29,7 @@ namespace System.Runtime.InteropServices.JavaScript public sealed class JSImportAttribute : Attribute { /// - /// The name of the target JavaScript function. This name will be used as a key to locate the function in the IMPORTS JavaScript object owned by the runtime. + /// The name of the target JavaScript function. This name will be used as a key to locate the function in the module. /// Functions nested inside of objects can be referred to by using the dot operator to connect one or more names. /// public string FunctionName { get; } @@ -44,7 +42,7 @@ namespace System.Runtime.InteropServices.JavaScript /// /// Initializes a new instance of the . /// - /// Name of the function to be bound in the IMPORTS object of the runtime instance in the JavaScript page. It allows dots for nested objects. + /// Name of the function to be bound in the module. It allows dots for nested objects. public JSImportAttribute(string functionName) { FunctionName = functionName; @@ -54,7 +52,7 @@ namespace System.Runtime.InteropServices.JavaScript /// Initializes a new instance of the . /// /// - /// The name of the target JavaScript function. This name will be used as a key to locate the function in the IMPORTS JavaScript object owned by the runtime. + /// The name of the target JavaScript function. This name will be used as a key to locate the function in the module. /// Functions nested inside of objects can be referred to by using the dot operator to connect one or more names. /// /// diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs index 47501520abc7..aaa5d16c2b8c 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs @@ -918,6 +918,9 @@ namespace System.Runtime.InteropServices.JavaScript.Tests } #endregion JSObject + [JSImport("setup", "JavaScriptTestHelper")] + internal static partial Task Setup(); + static JSObject _module; public static async Task InitializeAsync() { @@ -925,6 +928,7 @@ namespace System.Runtime.InteropServices.JavaScript.Tests { // Log("JavaScriptTestHelper.mjs importing"); _module = await JSHost.ImportAsync("JavaScriptTestHelper", "./JavaScriptTestHelper.mjs"); + await Setup(); // Log("JavaScriptTestHelper.mjs imported"); } } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs index c6494638b678..c3cc24ed7397 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs @@ -5,8 +5,8 @@ class JSData { constructor(name) { this.name = name; } - echoMemberMethod(arg1){ - return arg1 + "-w-i-t-h-"+ this.name; + echoMemberMethod(arg1) { + return arg1 + "-w-i-t-h-" + this.name; } toString() { return `JSData("${this.name}")`; @@ -146,14 +146,14 @@ export function getClass1() { // console.log(`getClass1(arg1:${cname !== null ? cname : ''})`) return cname; } - +let dllExports; export function invoke1(arg1, name) { if (globalThis.gc) { // console.log('globalThis.gc'); globalThis.gc(); } // console.log(`invoke1: ${name}(arg1:${arg1 !== null ? typeof arg1 : ''})`) - const JavaScriptTestHelper = globalThis.App.EXPORTS.System.Runtime.InteropServices.JavaScript.Tests.JavaScriptTestHelper + const JavaScriptTestHelper = dllExports.System.Runtime.InteropServices.JavaScript.Tests.JavaScriptTestHelper; const fn = JavaScriptTestHelper[name]; // console.log("invoke1:" + typeof fn); @@ -164,8 +164,7 @@ export function invoke1(arg1, name) { } export function invoke2(arg1, name) { - const JavaScriptTestHelperNoNamespace = globalThis.App.EXPORTS.JavaScriptTestHelperNoNamespace - const fn = JavaScriptTestHelperNoNamespace[name]; + const fn = dllExports.JavaScriptTestHelperNoNamespace[name]; //console.log("invoke1:" + fn.toString()); const res = fn(arg1); // console.log(`invoke1: res ${res !== null ? typeof res : ''}`) @@ -272,5 +271,8 @@ globalThis.rebound = { echoMemberMethod: globalThis.data.echoMemberMethod.bind(globalThis.data) } +export async function setup() { + dllExports = await App.runtime.getAssemblyExports("System.Runtime.InteropServices.JavaScript.Tests.dll"); +} // console.log('JavaScriptTestHelper:' Object.keys(globalThis.JavaScriptTestHelper)); diff --git a/src/mono/sample/mbr/browser/main.js b/src/mono/sample/mbr/browser/main.js index 4ea890233350..11d83de7f5d8 100644 --- a/src/mono/sample/mbr/browser/main.js +++ b/src/mono/sample/mbr/browser/main.js @@ -3,8 +3,8 @@ import createDotnetRuntime from './dotnet.js' try { const { BINDING } = await createDotnetRuntime(({ MONO }) => ({ configSrc: "./mono-config.json", - onConfigLoaded: () => { - MONO.config.environment_variables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug"; + onConfigLoaded: (config) => { + config.environmentVariables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug"; }, })); const update = BINDING.bind_static_method("[WasmDelta] Sample.Test:Update"); diff --git a/src/mono/sample/wasm/browser-bench/frame-main.js b/src/mono/sample/wasm/browser-bench/frame-main.js index 0d189ff66a89..bf767c9e7ebc 100644 --- a/src/mono/sample/wasm/browser-bench/frame-main.js +++ b/src/mono/sample/wasm/browser-bench/frame-main.js @@ -6,28 +6,31 @@ import createDotnetRuntime from './dotnet.js' class FrameApp { - async init({ MONO }) { - const exports = await MONO.mono_wasm_get_assembly_exports("Wasm.Browser.Bench.Sample.dll"); + async init({ getAssemblyExports }) { + const exports = await getAssemblyExports("Wasm.Browser.Bench.Sample.dll"); exports.Sample.AppStartTask.FrameApp.ReachedManaged(); } reachedCallback() { - window.parent.resolveAppStartEvent("reached"); + if (window.parent != window) { + window.parent.resolveAppStartEvent("reached"); + } } } +let mute = false; try { globalThis.frameApp = new FrameApp(); globalThis.frameApp.ReachedCallback = globalThis.frameApp.reachedCallback.bind(globalThis.frameApp); - - let mute = false; - window.addEventListener("pageshow", event => { window.parent.resolveAppStartEvent("pageshow"); }) + if (window.parent != window) { + window.addEventListener("pageshow", event => { window.parent.resolveAppStartEvent("pageshow"); }) + } window.muteErrors = () => { mute = true; } - const { MONO } = await createDotnetRuntime(() => ({ + const runtime = await createDotnetRuntime(() => ({ disableDotnet6Compatibility: true, configSrc: "./mono-config.json", printErr: function () { @@ -36,16 +39,20 @@ try { } }, onConfigLoaded: () => { - window.parent.resolveAppStartEvent("onConfigLoaded"); - // Module.config.diagnostic_tracing = true; + if (window.parent != window) { + window.parent.resolveAppStartEvent("onConfigLoaded"); + } + // Module.config.diagnosticTracing = true; }, onAbort: (error) => { wasm_exit(1, error); }, })); - window.parent.resolveAppStartEvent("onDotnetReady"); - await frameApp.init({ MONO }); + if (window.parent != window) { + window.parent.resolveAppStartEvent("onDotnetReady"); + } + await frameApp.init(runtime); } catch (err) { if (!mute) { diff --git a/src/mono/sample/wasm/browser-bench/main.js b/src/mono/sample/wasm/browser-bench/main.js index f76e7bb6d5a4..d45c4e7aa510 100644 --- a/src/mono/sample/wasm/browser-bench/main.js +++ b/src/mono/sample/wasm/browser-bench/main.js @@ -10,8 +10,8 @@ let setTasks; let getFullJsonResults; class MainApp { - async init({ MONO }) { - const exports = await MONO.mono_wasm_get_assembly_exports("Wasm.Browser.Bench.Sample.dll"); + async init({ getAssemblyExports }) { + const exports = await getAssemblyExports("Wasm.Browser.Bench.Sample.dll"); runBenchmark = exports.Sample.Test.RunBenchmark; setTasks = exports.Sample.Test.SetTasks; getFullJsonResults = exports.Sample.Test.GetFullJsonResults; @@ -94,14 +94,14 @@ try { globalThis.mainApp.FrameReachedManaged = globalThis.mainApp.frameReachedManaged.bind(globalThis.mainApp); globalThis.mainApp.PageShow = globalThis.mainApp.pageShow.bind(globalThis.mainApp); - const { MONO } = await createDotnetRuntime(() => ({ + const runtime = await createDotnetRuntime(() => ({ disableDotnet6Compatibility: true, configSrc: "./mono-config.json", onAbort: (error) => { wasm_exit(1, error); } })); - await mainApp.init({ MONO }); + await mainApp.init(runtime); } catch (err) { wasm_exit(1, err); diff --git a/src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj b/src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj index 49f5718f1297..f3feef21cce3 100644 --- a/src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj +++ b/src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj @@ -20,23 +20,23 @@ - - - - diff --git a/src/mono/sample/wasm/browser-mt-eventpipe/Wasm.Browser.ThreadsEP.Sample.csproj b/src/mono/sample/wasm/browser-mt-eventpipe/Wasm.Browser.ThreadsEP.Sample.csproj index 4e097628df99..514d8ca176e9 100644 --- a/src/mono/sample/wasm/browser-mt-eventpipe/Wasm.Browser.ThreadsEP.Sample.csproj +++ b/src/mono/sample/wasm/browser-mt-eventpipe/Wasm.Browser.ThreadsEP.Sample.csproj @@ -13,7 +13,7 @@ - { + const { MONO, BINDING, Module, runtimeBuildInfo } = await createDotnetRuntime(() => { console.log('user code in createDotnetRuntime') return { disableDotnet6Compatibility: true, @@ -40,7 +40,7 @@ async function main() { try { const testMeaning = BINDING.bind_static_method("[Wasm.Browser.ThreadsEP.Sample] Sample.Test:TestMeaning"); const ret = testMeaning(); - document.getElementById("out").innerHTML = `${ret} as computed on dotnet ver ${RuntimeBuildInfo.ProductVersion}`; + document.getElementById("out").innerHTML = `${ret} as computed on dotnet ver ${runtimeBuildInfo.productVersion}`; console.debug(`ret: ${ret}`); diff --git a/src/mono/sample/wasm/browser-profile/README.md b/src/mono/sample/wasm/browser-profile/README.md index 08bedff4756a..9d7327a63087 100644 --- a/src/mono/sample/wasm/browser-profile/README.md +++ b/src/mono/sample/wasm/browser-profile/README.md @@ -14,8 +14,8 @@ ``` await createDotnetRuntime(() => ({ onConfigLoaded: () => { - if (config.enable_profiler) { - config.aot_profiler_options = { + if (config.enableProfiler) { + config.aotProfilerOptions = { write_at: "", send_to: "System.Runtime.InteropServices.JavaScript.JavaScriptExports::DumpAotProfileData" } @@ -28,14 +28,14 @@ await createDotnetRuntime(() => ({ `BINDING.bind_static_method("<[ProjectName] Namespace.Class::StopProfile">)();` -When the `write_at` method is called, the `send_to` method `DumpAotProfileData` stores the profile data into `INTERNAL.aot_profile_data` +When the `write_at` method is called, the `send_to` method `DumpAotProfileData` stores the profile data into `INTERNAL.aotProfileData` -4. Download `INTERNAL.aot_profile_data` in JS, using something similar to: +4. Download `INTERNAL.aotProfileData` in JS, using something similar to: ``` function saveProfile() { var a = document.createElement('a'); - var blob = new Blob([INTERNAL.aot_profile_data]); + var blob = new Blob([INTERNAL.aotProfileData]); a.href = URL.createObjectURL(blob); a.download = "data.aotprofile"; // Append anchor to body. diff --git a/src/mono/sample/wasm/browser-profile/Wasm.BrowserProfile.Sample.csproj b/src/mono/sample/wasm/browser-profile/Wasm.BrowserProfile.Sample.csproj index b78cf6931419..f6508c948e44 100644 --- a/src/mono/sample/wasm/browser-profile/Wasm.BrowserProfile.Sample.csproj +++ b/src/mono/sample/wasm/browser-profile/Wasm.BrowserProfile.Sample.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/mono/sample/wasm/browser-profile/main.js b/src/mono/sample/wasm/browser-profile/main.js index 6431b3628a6a..29e6be1e3af4 100644 --- a/src/mono/sample/wasm/browser-profile/main.js +++ b/src/mono/sample/wasm/browser-profile/main.js @@ -12,12 +12,12 @@ function wasm_exit(exit_code, reason) { console.log(`WASM EXIT ${exit_code}`); } -function saveProfile(aot_profile_data) { - if (!aot_profile_data) { - throw new Error("aot_profile_data not set") +function saveProfile(aotProfileData) { + if (!aotProfileData) { + throw new Error("aotProfileData not set") } const a = document.createElement('a'); - const blob = new Blob([aot_profile_data]); + const blob = new Blob([aotProfileData]); a.href = URL.createObjectURL(blob); a.download = "data.aotprofile"; // Append anchor to body. @@ -32,11 +32,11 @@ try { const { MONO, BINDING, INTERNAL } = await createDotnetRuntime(({ MONO }) => ({ configSrc: "./mono-config.json", disableDotnet6Compatibility: true, - onConfigLoaded: () => { - if (MONO.config.enable_profiler) { - MONO.config.aot_profiler_options = { - write_at: "Sample.Test::StopProfile", - send_to: "System.Runtime.InteropServices.JavaScript.JavaScriptExports::DumpAotProfileData" + onConfigLoaded: (config) => { + if (config.enableProfiler) { + config.aotProfilerOptions = { + writeAt: "Sample.Test::StopProfile", + sendTo: "System.Runtime.InteropServices.JavaScript.JavaScriptExports::DumpAotProfileData" } } }, @@ -49,9 +49,9 @@ try { document.getElementById("out").innerHTML = ret; console.debug(`ret: ${ret}`); - if (MONO.config.enable_profiler) { + if (MONO.config.enableProfiler) { stopProfile(); - saveProfile(INTERNAL.aot_profile_data); + saveProfile(INTERNAL.aotProfileData); } let exit_code = ret == 42 ? 0 : 1; diff --git a/src/mono/sample/wasm/browser-webpack/Wasm.Browser.WebPack.Sample.csproj b/src/mono/sample/wasm/browser-webpack/Wasm.Browser.WebPack.Sample.csproj index 7c9c4da09e10..7eb6e7ac4f8c 100644 --- a/src/mono/sample/wasm/browser-webpack/Wasm.Browser.WebPack.Sample.csproj +++ b/src/mono/sample/wasm/browser-webpack/Wasm.Browser.WebPack.Sample.csproj @@ -12,11 +12,13 @@ + diff --git a/src/mono/sample/wasm/browser/Program.cs b/src/mono/sample/wasm/browser/Program.cs index eb2506e0f213..2f8cabacea1d 100644 --- a/src/mono/sample/wasm/browser/Program.cs +++ b/src/mono/sample/wasm/browser/Program.cs @@ -15,10 +15,10 @@ namespace Sample return 0; } - [JSImport("Sample.Test.add")] + [JSImport("Sample.Test.add", "main.js")] internal static partial int Add(int a, int b); - [JSImport("Sample.Test.sub")] + [JSImport("Sample.Test.sub", "main.js")] internal static partial int Sub(int a, int b); [JSExport] diff --git a/src/mono/sample/wasm/browser/main.js b/src/mono/sample/wasm/browser/main.js index 4945a5cb67f5..82561c74e223 100644 --- a/src/mono/sample/wasm/browser/main.js +++ b/src/mono/sample/wasm/browser/main.js @@ -12,6 +12,11 @@ function wasm_exit(exit_code, reason) { console.log(`WASM EXIT ${exit_code}`); } +/** + * @type {import('../../../wasm/runtime/dotnet').CreateDotnetRuntimeType} + */ +const createDotnetRuntimeTyped = createDotnetRuntime; + function add(a, b) { return a + b; } @@ -19,36 +24,55 @@ function add(a, b) { function sub(a, b) { return a - b; } - try { - const { MONO, RuntimeBuildInfo, IMPORTS } = await createDotnetRuntime(() => { - console.log('user code in createDotnetRuntime callback'); + const { runtimeBuildInfo, setModuleImports, getAssemblyExports, runMain } = await createDotnetRuntimeTyped(() => { + // this callback usually needs no statements, the API objects are only empty shells here and are populated later return { configSrc: "./mono-config.json", + onConfigLoaded: (config) => { + // This is called during emscripten `dotnet.wasm` instantiation, after we fetched config. + console.log('user code Module.onConfigLoaded'); + // config is loaded and could be tweaked before the rest of the runtime startup sequence + config.environmentVariables["MONO_LOG_LEVEL"] = "debug" + }, preInit: () => { console.log('user code Module.preInit'); }, preRun: () => { console.log('user code Module.preRun'); }, - onRuntimeInitialized: () => { console.log('user code Module.onRuntimeInitialized'); }, + onRuntimeInitialized: () => { + console.log('user code Module.onRuntimeInitialized'); + // here we could use API passed into this callback + // Module.FS.chdir("/"); + }, + onDotnetReady: () => { + // This is called after all assets are loaded. + console.log('user code Module.onDotnetReady'); + }, postRun: () => { console.log('user code Module.postRun'); }, } }); + // at this point both emscripten and monoVM are fully initialized. + // we could use the APIs returned and resolved from createDotnetRuntime promise + // both exports are receiving the same object instances console.log('user code after createDotnetRuntime()'); - IMPORTS.Sample = { - Test: { - add, - sub + setModuleImports("main.js", { + Sample: { + Test: { + add, + sub + } } - }; + }); - const exports = await MONO.mono_wasm_get_assembly_exports("Wasm.Browser.Sample.dll"); + const exports = await getAssemblyExports("Wasm.Browser.Sample.dll"); const meaning = exports.Sample.Test.TestMeaning(); console.debug(`meaning: ${meaning}`); if (!exports.Sample.Test.IsPrime(meaning)) { - document.getElementById("out").innerHTML = `${meaning} as computed on dotnet ver ${RuntimeBuildInfo.ProductVersion}`; + document.getElementById("out").innerHTML = `${meaning} as computed on dotnet ver ${runtimeBuildInfo.productVersion}`; console.debug(`ret: ${meaning}`); } - let exit_code = await MONO.mono_run_main("Wasm.Browser.Sample.dll", []); + let exit_code = await runMain("Wasm.Browser.Sample.dll", []); wasm_exit(exit_code); -} catch (err) { - wasm_exit(2, err); } +catch (err) { + wasm_exit(2, err); +} \ No newline at end of file diff --git a/src/mono/sample/wasm/console-node-es6/main.mjs b/src/mono/sample/wasm/console-node-es6/main.mjs index 3cd0598af62c..4f29df3284a6 100644 --- a/src/mono/sample/wasm/console-node-es6/main.mjs +++ b/src/mono/sample/wasm/console-node-es6/main.mjs @@ -1,10 +1,18 @@ +// @ts-check +// @ts-ignore import createDotnetRuntime from './dotnet.js' +import process from 'process' -const { MONO } = await createDotnetRuntime(() => ({ +/** + * @type {import('../../../wasm/runtime/dotnet').CreateDotnetRuntimeType} + */ +const createDotnetRuntimeTyped = createDotnetRuntime; + +const { runMainAndExit } = await createDotnetRuntimeTyped(() => ({ disableDotnet6Compatibility: true, configSrc: "./mono-config.json", })); const app_args = process.argv.slice(2); const dllName = "Wasm.Console.Node.Sample.dll"; -await MONO.mono_run_main_and_exit(dllName, app_args); +await runMainAndExit(dllName, app_args); diff --git a/src/mono/sample/wasm/console-node-ts/Wasm.Console.Node.TS.Sample.csproj b/src/mono/sample/wasm/console-node-ts/Wasm.Console.Node.TS.Sample.csproj index 842dc7ddecb5..10369cb62c1b 100644 --- a/src/mono/sample/wasm/console-node-ts/Wasm.Console.Node.TS.Sample.csproj +++ b/src/mono/sample/wasm/console-node-ts/Wasm.Console.Node.TS.Sample.csproj @@ -10,9 +10,11 @@ --> + diff --git a/src/mono/sample/wasm/console-v8-es6/main.mjs b/src/mono/sample/wasm/console-v8-es6/main.mjs index 11d9ce8f19b1..3283d9bc4218 100644 --- a/src/mono/sample/wasm/console-v8-es6/main.mjs +++ b/src/mono/sample/wasm/console-v8-es6/main.mjs @@ -4,8 +4,8 @@ const dllName = "Wasm.Console.V8.Sample.dll"; const app_args = Array.from(arguments); async function main() { - const { MONO } = await createDotnetRuntime(); - await MONO.mono_run_main_and_exit(dllName, app_args); + const { runMainAndExit } = await createDotnetRuntime(); + await runMainAndExit(dllName, app_args); } main(); \ No newline at end of file diff --git a/src/mono/sample/wasm/console-v8-es6/v8shim.cjs b/src/mono/sample/wasm/console-v8-es6/v8shim.cjs index f8c2a61fe87f..81f6fd127535 100644 --- a/src/mono/sample/wasm/console-v8-es6/v8shim.cjs +++ b/src/mono/sample/wasm/console-v8-es6/v8shim.cjs @@ -1,14 +1,3 @@ -if (typeof globalThis.URL === 'undefined') { - globalThis.URL = class URL { - constructor(url) { - this.url = url; - } - toString() { - return this.url; - } - }; -} - import('./main.mjs').catch(err => { console.log(err); console.log(err.stack); diff --git a/src/mono/sample/wasm/node-webpack/Wasm.Node.WebPack.Sample.csproj b/src/mono/sample/wasm/node-webpack/Wasm.Node.WebPack.Sample.csproj index 7c0c3da238ec..c8e021906c4e 100644 --- a/src/mono/sample/wasm/node-webpack/Wasm.Node.WebPack.Sample.csproj +++ b/src/mono/sample/wasm/node-webpack/Wasm.Node.WebPack.Sample.csproj @@ -7,11 +7,13 @@ + diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 0a03189f69ec..d9a5f1f06ed7 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -17,7 +17,7 @@ - $(RunAOTCompilation) - Defaults to false. - $(WasmDebugLevel) - > 0 enables debugging and sets the debug log level to debug_level + > 0 enables debugging and sets the debug log level to debugLevel == 0 disables debugging and enables interpreter optimizations < 0 enabled debugging and disables debug logging. @@ -75,7 +75,7 @@ - @(WasmNativeAsset) - Native files to be added to `NativeAssets` in the bundle. - @(WasmExtraConfig) - json elements to add to `mono-config.json` - Eg. + Eg. - Value attribute can have a number, bool, quoted string, or json string diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html b/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html index 5c6917121db2..33c6f7e01db2 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html @@ -7,14 +7,14 @@ var App = { static_method_table: {}, init: function () { - this.int_add = App.BINDING.bind_static_method("[debugger-test] Math:IntAdd"); - this.use_complex = App.BINDING.bind_static_method("[debugger-test] Math:UseComplex"); - this.delegates_test = App.BINDING.bind_static_method("[debugger-test] Math:DelegatesTest"); - this.generic_types_test = App.BINDING.bind_static_method("[debugger-test] Math:GenericTypesTest"); - this.outer_method = App.BINDING.bind_static_method("[debugger-test] Math:OuterMethod"); - this.async_method = App.BINDING.bind_static_method("[debugger-test] Math/NestedInMath:AsyncTest"); - this.method_with_structs = App.BINDING.bind_static_method("[debugger-test] DebuggerTests.ValueTypesTest:MethodWithLocalStructs"); - this.run_all = App.BINDING.bind_static_method("[debugger-test] DebuggerTest:run_all"); + this.int_add = App.runtime.BINDING.bind_static_method("[debugger-test] Math:IntAdd"); + this.use_complex = App.runtime.BINDING.bind_static_method("[debugger-test] Math:UseComplex"); + this.delegates_test = App.runtime.BINDING.bind_static_method("[debugger-test] Math:DelegatesTest"); + this.generic_types_test = App.runtime.BINDING.bind_static_method("[debugger-test] Math:GenericTypesTest"); + this.outer_method = App.runtime.BINDING.bind_static_method("[debugger-test] Math:OuterMethod"); + this.async_method = App.runtime.BINDING.bind_static_method("[debugger-test] Math/NestedInMath:AsyncTest"); + this.method_with_structs = App.runtime.BINDING.bind_static_method("[debugger-test] DebuggerTests.ValueTypesTest:MethodWithLocalStructs"); + this.run_all = App.runtime.BINDING.bind_static_method("[debugger-test] DebuggerTest:run_all"); this.static_method_table = {}; console.log ("ready"); }, @@ -22,7 +22,7 @@ function invoke_static_method (method_name, ...args) { var method = App.static_method_table [method_name]; if (method == undefined) - method = App.static_method_table[method_name] = App.BINDING.bind_static_method(method_name); + method = App.static_method_table[method_name] = App.runtime.BINDING.bind_static_method(method_name); return method (...args); } @@ -30,7 +30,7 @@ async function invoke_static_method_async (method_name, ...args) { var method = App.static_method_table [method_name]; if (method == undefined) { - method = App.static_method_table[method_name] = App.BINDING.bind_static_method(method_name); + method = App.static_method_table[method_name] = App.runtime.BINDING.bind_static_method(method_name); } return await method (...args); diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-main.js b/src/mono/wasm/debugger/tests/debugger-test/debugger-main.js index 19dc0175e269..29b23b79e2d9 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-main.js +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-main.js @@ -6,14 +6,14 @@ import createDotnetRuntime from './dotnet.js' try { - const { BINDING } = await createDotnetRuntime(({ INTERNAL }) => ({ + const runtime = await createDotnetRuntime(({ INTERNAL }) => ({ configSrc: "./mono-config.json", onConfigLoaded: (config) => { - config.environment_variables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug"; + config.environmentVariables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug"; /* For custom logging patch the functions below - config.diagnostic_tracing = true; - config.environment_variables["MONO_LOG_LEVEL"] = "debug"; - config.environment_variables["MONO_LOG_MASK"] = "all"; + config.diagnosticTracing = true; + config.environmentVariables["MONO_LOG_LEVEL"] = "debug"; + config.environmentVariables["MONO_LOG_MASK"] = "all"; INTERNAL.logging = { trace: (domain, log_level, message, isFatal, dataPtr) => console.log({ domain, log_level, message, isFatal, dataPtr }), debugger: (level, message) => console.log({ level, message }), @@ -21,7 +21,7 @@ try { */ }, })); - App.BINDING = BINDING; + App.runtime = runtime; App.init() } catch (err) { console.log(`WASM ERROR ${err}`); diff --git a/src/mono/wasm/debugger/tests/debugger-test/wasm-page-without-assets.html b/src/mono/wasm/debugger/tests/debugger-test/wasm-page-without-assets.html index 992e9bac68a7..9e62a550b22e 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/wasm-page-without-assets.html +++ b/src/mono/wasm/debugger/tests/debugger-test/wasm-page-without-assets.html @@ -1,15 +1,15 @@ - - - + + + + + @@ -17,5 +17,6 @@ Stuff goes here - - + + + \ No newline at end of file diff --git a/src/mono/wasm/runtime/cjs/dotnet.cjs.lib.js b/src/mono/wasm/runtime/cjs/dotnet.cjs.lib.js deleted file mode 100644 index 2c815a38facb..000000000000 --- a/src/mono/wasm/runtime/cjs/dotnet.cjs.lib.js +++ /dev/null @@ -1,117 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -/* eslint-disable no-undef */ - -"use strict"; - -#if USE_PTHREADS -const usePThreads = `true`; -const isPThread = `ENVIRONMENT_IS_PTHREAD`; -#else -const usePThreads = `false`; -const isPThread = `false`; -#endif - -const DotnetSupportLib = { - $DOTNET: {}, - // these lines will be placed early on emscripten runtime creation, passing import and export objects into __dotnet_runtime IFFE - // we replace implementation of fetch - // replacement of require is there for consistency with ES6 code - $DOTNET__postset: ` -let __dotnet_replacement_PThread = ${usePThreads} ? {} : undefined; -if (${usePThreads}) { - __dotnet_replacement_PThread.loadWasmModuleToWorker = PThread.loadWasmModuleToWorker; - __dotnet_replacement_PThread.threadInitTLS = PThread.threadInitTLS; -} -let __dotnet_replacements = {scriptUrl: undefined, fetch: globalThis.fetch, require, updateGlobalBufferAndViews, pthreadReplacements: __dotnet_replacement_PThread}; -if (ENVIRONMENT_IS_NODE) { - __dotnet_replacements.requirePromise = Promise.resolve(require); -} -let __dotnet_exportedAPI = __dotnet_runtime.__initializeImportsAndExports( - { isESM:false, isGlobal:ENVIRONMENT_IS_GLOBAL, isNode:ENVIRONMENT_IS_NODE, isWorker:ENVIRONMENT_IS_WORKER, isShell:ENVIRONMENT_IS_SHELL, isWeb:ENVIRONMENT_IS_WEB, isPThread:${isPThread}, quit_, ExitStatus, requirePromise:Promise.resolve(require)}, - { mono:MONO, binding:BINDING, internal:INTERNAL, module:Module, marshaled_exports: EXPORTS, marshaled_imports: IMPORTS }, - __dotnet_replacements); -updateGlobalBufferAndViews = __dotnet_replacements.updateGlobalBufferAndViews; -var fetch = __dotnet_replacements.fetch; -_scriptDir = __dirname = scriptDirectory = __dotnet_replacements.scriptDirectory; -if (ENVIRONMENT_IS_NODE) { - __dotnet_replacements.requirePromise.then(someRequire => { - require = someRequire; - }); -} -var noExitRuntime = __dotnet_replacements.noExitRuntime; -if (${usePThreads}) { - PThread.loadWasmModuleToWorker = __dotnet_replacements.pthreadReplacements.loadWasmModuleToWorker; - PThread.threadInitTLS = __dotnet_replacements.pthreadReplacements.threadInitTS; -} -`, -}; - -// the methods would be visible to EMCC linker -// --- keep in sync with exports.ts --- -const linked_functions = [ - // mini-wasm.c - "mono_set_timeout", - - // mini-wasm-debugger.c - "mono_wasm_asm_loaded", - "mono_wasm_fire_debugger_agent_message", - "mono_wasm_debugger_log", - "mono_wasm_add_dbg_command_received", - - // mono-threads-wasm.c - "schedule_background_exec", - - // driver.c - "mono_wasm_invoke_js_blazor", - "mono_wasm_trace_logger", - "mono_wasm_set_entrypoint_breakpoint", - "mono_wasm_event_pipe_early_startup_callback", - - // corebindings.c - "mono_wasm_invoke_js_with_args_ref", - "mono_wasm_get_object_property_ref", - "mono_wasm_set_object_property_ref", - "mono_wasm_get_by_index_ref", - "mono_wasm_set_by_index_ref", - "mono_wasm_get_global_object_ref", - "mono_wasm_create_cs_owned_object_ref", - "mono_wasm_release_cs_owned_object", - "mono_wasm_typed_array_to_array_ref", - "mono_wasm_typed_array_from_ref", - "mono_wasm_compile_function_ref", - "mono_wasm_bind_js_function", - "mono_wasm_invoke_bound_function", - "mono_wasm_bind_cs_function", - "mono_wasm_marshal_promise", - - // pal_icushim_static.c - "mono_wasm_load_icu_data", - "mono_wasm_get_icudt_name", - - // pal_crypto_webworker.c - "dotnet_browser_can_use_subtle_crypto_impl", - "dotnet_browser_simple_digest_hash", - "dotnet_browser_sign", - "dotnet_browser_encrypt_decrypt", - "dotnet_browser_derive_bits", - - #if USE_PTHREADS - /// mono-threads-wasm.c - "mono_wasm_pthread_on_pthread_attached", - /// diagnostics_server.c - "mono_wasm_diagnostic_server_on_server_thread_created", - "mono_wasm_diagnostic_server_on_runtime_server_init", - "mono_wasm_diagnostic_server_stream_signal_work_available", - #endif -]; - -// -- this javascript file is evaluated by emcc during compilation! -- -// we generate simple proxy for each exported function so that emcc will include them in the final output -for (let linked_function of linked_functions) { - const fn_template = `return __dotnet_runtime.__linker_exports.${linked_function}.apply(__dotnet_runtime, arguments)`; - DotnetSupportLib[linked_function] = new Function(fn_template); -} - -autoAddDeps(DotnetSupportLib, "$DOTNET"); -mergeInto(LibraryManager.library, DotnetSupportLib); diff --git a/src/mono/wasm/runtime/cwraps.ts b/src/mono/wasm/runtime/cwraps.ts index 02e35cee24c7..af1231edacbc 100644 --- a/src/mono/wasm/runtime/cwraps.ts +++ b/src/mono/wasm/runtime/cwraps.ts @@ -4,10 +4,9 @@ import { MonoArray, MonoAssembly, MonoClass, MonoMethod, MonoObject, MonoString, - MonoType, MonoObjectRef, MonoStringRef + MonoType, MonoObjectRef, MonoStringRef, JSMarshalerArguments } from "./types"; import { ENVIRONMENT_IS_PTHREAD, Module } from "./imports"; -import { JSMarshalerArguments } from "./marshal"; import { VoidPtr, CharPtrPtr, Int32Ptr, CharPtr, ManagedPointer } from "./types/emscripten"; type SigLine = [lazy: boolean, name: string, returnType: string | null, argTypes?: string[], opts?: any]; @@ -112,7 +111,7 @@ export interface t_Cwraps { mono_wasm_get_icudt_name(name: string): string; mono_wasm_add_assembly(name: string, data: VoidPtr, size: number): number; mono_wasm_add_satellite_assembly(name: string, culture: string, data: VoidPtr, size: number): void; - mono_wasm_load_runtime(unused: string, debug_level: number): void; + mono_wasm_load_runtime(unused: string, debugLevel: number): void; mono_wasm_change_debugger_log_level(value: number): void; /** @@ -233,4 +232,4 @@ export function init_c_exports(): void { wf[name] = fce; } } -} +} \ No newline at end of file diff --git a/src/mono/wasm/runtime/debug.ts b/src/mono/wasm/runtime/debug.ts index 40ab3a420174..48894c6327c2 100644 --- a/src/mono/wasm/runtime/debug.ts +++ b/src/mono/wasm/runtime/debug.ts @@ -150,7 +150,7 @@ export function mono_wasm_get_loaded_files(): string[] { export function mono_wasm_wait_for_debugger(): Promise { return new Promise((resolve) => { const interval = setInterval(() => { - if (runtimeHelpers.wait_for_debugger != 1) { + if (runtimeHelpers.waitForDebugger != 1) { return; } clearInterval(interval); @@ -160,8 +160,8 @@ export function mono_wasm_wait_for_debugger(): Promise { } export function mono_wasm_debugger_attached(): void { - if (runtimeHelpers.wait_for_debugger == -1) - runtimeHelpers.wait_for_debugger = 1; + if (runtimeHelpers.waitForDebugger == -1) + runtimeHelpers.waitForDebugger = 1; cwraps.mono_wasm_set_is_debugger_attached(true); } diff --git a/src/mono/wasm/runtime/diagnostics/README.md b/src/mono/wasm/runtime/diagnostics/README.md index 50da1337c4fc..52995f389557 100644 --- a/src/mono/wasm/runtime/diagnostics/README.md +++ b/src/mono/wasm/runtime/diagnostics/README.md @@ -27,9 +27,9 @@ To use mocking: 3. configure the diagnostics server with a `mock:relative_url_of/mock.js` ```xml - ``` diff --git a/src/mono/wasm/runtime/diagnostics/browser/session-options-builder.ts b/src/mono/wasm/runtime/diagnostics/browser/session-options-builder.ts index 079e26e48d82..5aa76b04ae6e 100644 --- a/src/mono/wasm/runtime/diagnostics/browser/session-options-builder.ts +++ b/src/mono/wasm/runtime/diagnostics/browser/session-options-builder.ts @@ -15,7 +15,7 @@ export const eventLevel = { export type EventLevel = typeof eventLevel; type UnnamedProviderConfiguration = Partial<{ - keyword_mask: string | 0; + keywordMask: string | 0; level: number; args: string; }> @@ -40,19 +40,19 @@ const sampleProfilerProviderName = "Microsoft-DotNETCore-SampleProfiler"; const runtimeProviderDefault: ProviderConfiguration = { name: runtimeProviderName, - keyword_mask: "4c14fccbd", + keywordMask: "4c14fccbd", level: eventLevel.Verbose, }; const runtimePrivateProviderDefault: ProviderConfiguration = { name: runtimePrivateProviderName, - keyword_mask: "4002000b", + keywordMask: "4002000b", level: eventLevel.Verbose, }; const sampleProfilerProviderDefault: ProviderConfiguration = { name: sampleProfilerProviderName, - keyword_mask: "0", + keywordMask: "0", level: eventLevel.Verbose, }; @@ -83,21 +83,21 @@ export class SessionOptionsBuilder { return this; } /// Add the Microsoft-Windows-DotNETRuntime provider. Use override options to change the event level or keyword mask. - /// The default is { keyword_mask: "4c14fccbd", level: eventLevel.Verbose } + /// The default is { keywordMask: "4c14fccbd", level: eventLevel.Verbose } addRuntimeProvider(overrideOptions?: UnnamedProviderConfiguration): SessionOptionsBuilder { const options = { ...runtimeProviderDefault, ...overrideOptions }; this._providers.push(options); return this; } /// Add the Microsoft-Windows-DotNETRuntimePrivate provider. Use override options to change the event level or keyword mask. - /// The default is { keyword_mask: "4002000b", level: eventLevel.Verbose} + /// The default is { keywordMask: "4002000b", level: eventLevel.Verbose} addRuntimePrivateProvider(overrideOptions?: UnnamedProviderConfiguration): SessionOptionsBuilder { const options = { ...runtimePrivateProviderDefault, ...overrideOptions }; this._providers.push(options); return this; } /// Add the Microsoft-DotNETCore-SampleProfiler. Use override options to change the event level or keyword mask. - // The default is { keyword_mask: 0, level: eventLevel.Verbose } + // The default is { keywordMask: 0, level: eventLevel.Verbose } addSampleProfilerProvider(overrideOptions?: UnnamedProviderConfiguration): SessionOptionsBuilder { const options = { ...sampleProfilerProviderDefault, ...overrideOptions }; this._providers.push(options); @@ -107,11 +107,11 @@ export class SessionOptionsBuilder { build(): EventPipeSessionOptions { const providers = this._providers.map(p => { const name = p.name; - const keyword_mask = "" + (p?.keyword_mask ?? ""); + const keywordMask = "" + (p?.keywordMask ?? ""); const level = p?.level ?? eventLevel.Verbose; const args = p?.args ?? ""; const maybeArgs = args != "" ? `:${args}` : ""; - return `${name}:${keyword_mask}:${level}${maybeArgs}`; + return `${name}:${keywordMask}:${level}${maybeArgs}`; }); return { collectRundownEvents: this._rundown, diff --git a/src/mono/wasm/runtime/diagnostics/index.ts b/src/mono/wasm/runtime/diagnostics/index.ts index c42a87150227..203000489311 100644 --- a/src/mono/wasm/runtime/diagnostics/index.ts +++ b/src/mono/wasm/runtime/diagnostics/index.ts @@ -19,7 +19,7 @@ import { import { EventPipeSession, makeEventPipeSession } from "./browser/file-session"; export interface Diagnostics { - EventLevel: EventLevel; + eventLevel: EventLevel; SessionOptionsBuilder: typeof SessionOptionsBuilder; createEventPipeSession(options?: EventPipeSessionOptions): EventPipeSession | null; @@ -62,7 +62,7 @@ function getDiagnostics(): Diagnostics { /// Warning: 3, /// Informational: 4, /// Verbose: 5, - EventLevel: eventLevel, + eventLevel: eventLevel, /// A builder for creating an EventPipeSessionOptions instance. SessionOptionsBuilder: SessionOptionsBuilder, /// Creates a new EventPipe session that will collect trace events from the runtime and managed libraries. @@ -100,10 +100,10 @@ export async function mono_wasm_init_diagnostics(options: DiagnosticOptions): Pr return; } else { if (!is_nullish(options.server)) { - if (options.server.connect_url === undefined || typeof (options.server.connect_url) !== "string") { - throw new Error("server.connect_url must be a string"); + if (options.server.connectUrl === undefined || typeof (options.server.connectUrl) !== "string") { + throw new Error("server.connectUrl must be a string"); } - const url = options.server.connect_url; + const url = options.server.connectUrl; const suspend = boolsyOption(options.server.suspend); const controller = await startDiagnosticServer(url); if (controller) { diff --git a/src/mono/wasm/runtime/dotnet-legacy.d.ts b/src/mono/wasm/runtime/dotnet-legacy.d.ts new file mode 100644 index 000000000000..476c0031b7dd --- /dev/null +++ b/src/mono/wasm/runtime/dotnet-legacy.d.ts @@ -0,0 +1,439 @@ +//! 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"; +} + +declare function mono_wasm_runtime_ready(): void; + +declare function mono_wasm_load_icu_data(offset: VoidPtr): boolean; + +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 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; + +/** + * 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; +} + +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 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; + +/** + * @deprecated Please use methods in top level API object instead + */ +declare type BINDINGType = { + /** + * @deprecated Please use [JSExportAttribute] instead + */ + bind_static_method: typeof mono_bind_static_method; + /** + * @deprecated Please use runMain() instead + */ + call_assembly_entry_point: typeof mono_call_assembly_entry_point; + /** + * @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 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: typeof js_string_to_mono_string_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + js_typed_array_to_array_root: typeof js_typed_array_to_array_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + js_to_mono_obj_root: typeof js_to_mono_obj_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + conv_string_root: typeof conv_string_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + unbox_mono_obj_root: typeof unbox_mono_obj_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_array_root_to_js_array: typeof mono_array_root_to_js_array; +}; +/** + * @deprecated Please use methods in top level API object instead + */ +declare type MONOType = { + /** + * @deprecated Please use setEnvironmentVariable() instead + */ + mono_wasm_setenv: typeof mono_wasm_setenv; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_load_bytes_into_heap: typeof mono_wasm_load_bytes_into_heap; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_load_icu_data: typeof mono_wasm_load_icu_data; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_runtime_ready: typeof mono_wasm_runtime_ready; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_load_data_archive: typeof mono_wasm_load_data_archive; + /** + * @deprecated Please use configSrc instead + */ + mono_wasm_load_config: typeof mono_wasm_load_config; + /** + * @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: typeof mono_wasm_new_root_buffer; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_wasm_new_root: typeof mono_wasm_new_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_wasm_new_external_root: typeof mono_wasm_new_external_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_wasm_release_roots: typeof mono_wasm_release_roots; + /** + * @deprecated Please use runMain instead + */ + mono_run_main: typeof mono_run_main; + /** + * @deprecated Please use runMainAndExit instead + */ + mono_run_main_and_exit: typeof mono_run_main_and_exit; + /** + * @deprecated Please use getAssemblyExports instead + */ + mono_wasm_get_assembly_exports: typeof mono_wasm_get_assembly_exports; + /** + * @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: typeof setB32; + /** + * @deprecated Please use setHeapI8 + */ + setI8: typeof setI8; + /** + * @deprecated Please use setHeapI16 + */ + setI16: typeof setI16; + /** + * @deprecated Please use setHeapI32 + */ + setI32: typeof setI32; + /** + * @deprecated Please use setHeapI52 + */ + setI52: typeof setI52; + /** + * @deprecated Please use setHeapU52 + */ + setU52: typeof setU52; + /** + * @deprecated Please use setHeapI64Big + */ + setI64Big: typeof setI64Big; + /** + * @deprecated Please use setHeapU8 + */ + setU8: typeof setU8; + /** + * @deprecated Please use setHeapU16 + */ + setU16: typeof setU16; + /** + * @deprecated Please use setHeapU32 + */ + setU32: typeof setU32; + /** + * @deprecated Please use setHeapF32 + */ + setF32: typeof setF32; + /** + * @deprecated Please use setHeapF64 + */ + setF64: typeof setF64; + /** + * @deprecated Please use getHeapB32 + */ + getB32: typeof getB32; + /** + * @deprecated Please use getHeapI8 + */ + getI8: typeof getI8; + /** + * @deprecated Please use getHeapI16 + */ + getI16: typeof getI16; + /** + * @deprecated Please use getHeapI32 + */ + getI32: typeof getI32; + /** + * @deprecated Please use getHeapI52 + */ + getI52: typeof getI52; + /** + * @deprecated Please use getHeapU52 + */ + getU52: typeof getU52; + /** + * @deprecated Please use getHeapI64Big + */ + getI64Big: typeof getI64Big; + /** + * @deprecated Please use getHeapU8 + */ + getU8: typeof getU8; + /** + * @deprecated Please use getHeapU16 + */ + getU16: typeof getU16; + /** + * @deprecated Please use getHeapU32 + */ + getU32: typeof getU32; + /** + * @deprecated Please use getHeapF32 + */ + getF32: typeof getF32; + /** + * @deprecated Please use getHeapF64 + */ + getF64: typeof getF64; +}; + +export { BINDINGType, MONOType }; diff --git a/src/mono/wasm/runtime/dotnet.d.ts b/src/mono/wasm/runtime/dotnet.d.ts index bc597e85463e..7208e1d9e3d7 100644 --- a/src/mono/wasm/runtime/dotnet.d.ts +++ b/src/mono/wasm/runtime/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"; } @@ -51,101 +48,134 @@ declare interface EmscriptenModule { stackAlloc(size: number): VoidPtr; ready: Promise; instantiateWasm?: (imports: WebAssembly.Imports, successCallback: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void) => any; - preInit?: (() => any)[]; - preRun?: (() => any)[]; + preInit?: (() => any)[] | (() => any); + preRun?: (() => any)[] | (() => any); onRuntimeInitialized?: () => any; - postRun?: (() => any)[]; + postRun?: (() => any)[] | (() => any); onAbort?: { (error: any): void; }; } declare type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array; -declare function mono_wasm_runtime_ready(): void; +declare type MonoConfig = { + assemblyRootFolder?: string; + assets?: AssetEntry[]; + /** + * debugLevel > 0 enables debugging and sets the debug log level to debugLevel + * debugLevel == 0 disables debugging and enables interpreter optimizations + * debugLevel < 0 enabled debugging and disables debug logging. + */ + debugLevel?: number; + maxParallelDownloads?: number; + globalizationMode?: GlobalizationMode; + diagnosticTracing?: boolean; + remoteSources?: string[]; + environmentVariables?: { + [i: string]: string; + }; + runtimeOptions?: string[]; + aotProfilerOptions?: AOTProfilerOptions; + coverageProfilerOptions?: CoverageProfilerOptions; + ignorePdbLoadErrors?: boolean; + waitForDebugger?: number; +}; +interface ResourceRequest { + name: string; + behavior: AssetBehaviours; + resolvedUrl?: string; + hash?: string; +} +interface AssetEntry extends ResourceRequest { + virtualPath?: string; + culture?: string; + loadRemote?: boolean; + isOptional?: boolean; + buffer?: ArrayBuffer; + pending?: LoadingResource; +} +declare type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm"; +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 = { + writeAt?: string; + sendTo?: string; +}; +declare type CoverageProfilerOptions = { + writeAt?: string; + sendTo?: string; +}; +declare type DotnetModuleConfig = { + disableDotnet6Compatibility?: boolean; + config?: MonoConfig; + configSrc?: string; + onConfigLoaded?: (config: MonoConfig) => void | Promise; + onDotnetReady?: () => void | Promise; + imports?: any; + exports?: string[]; + downloadResource?: (request: ResourceRequest) => LoadingResource | undefined; +} & Partial; +interface LoadingResource { + name: string; + url: string; + response: Promise; +} -/** - * 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 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 DotnetPublicAPI = { + /** + * @deprecated Please use API object instead. See also MONOType in dotnet-legacy.d.ts + */ + MONO: any; + /** + * @deprecated Please use API object instead. See also BINDINGType in dotnet-legacy.d.ts + */ + BINDING: any; + INTERNAL: any; + Module: EmscriptenModule; + runtimeId: number; + runtimeBuildInfo: { + productVersion: string; + buildConfiguration: string; + } & APIType; +}; 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, @@ -171,365 +201,6 @@ interface IMemoryView { 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; - 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; - 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; -}; -declare type MonoConfigError = { - isError: true; - message: string; - error: any; -}; -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; - pending?: LoadingResource; -} -declare type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm"; -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; -}; -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; - configSrc?: string; - onConfigLoaded?: (config: MonoConfig) => void | Promise; - onDotnetReady?: () => void | Promise; - imports?: DotnetModuleConfigImports; - exports?: string[]; - downloadResource?: (request: ResourceRequest) => LoadingResource; -} & 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 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; - /** - * @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; - 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; -}; - declare function createDotnetRuntime(moduleFactory: DotnetModuleConfig | ((api: DotnetPublicAPI) => DotnetModuleConfig)): Promise; declare type CreateDotnetRuntimeType = typeof createDotnetRuntime; declare global { @@ -564,5 +235,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/mono/wasm/runtime/es6/dotnet.es6.lib.js b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js index 82fd6abba1b9..c6c554d2112c 100644 --- a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js +++ b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js @@ -33,7 +33,7 @@ if (ENVIRONMENT_IS_NODE) { } let __dotnet_exportedAPI = __dotnet_runtime.__initializeImportsAndExports( { isGlobal:false, isNode:ENVIRONMENT_IS_NODE, isWorker:ENVIRONMENT_IS_WORKER, isShell:ENVIRONMENT_IS_SHELL, isWeb:ENVIRONMENT_IS_WEB, isPThread:${isPThread}, quit_, ExitStatus, requirePromise:__dotnet_replacements.requirePromise }, - { mono:MONO, binding:BINDING, internal:INTERNAL, module:Module, marshaled_exports: EXPORTS, marshaled_imports: IMPORTS }, + { mono:MONO, binding:BINDING, internal:INTERNAL, module:Module, marshaled_imports: IMPORTS }, __dotnet_replacements); updateGlobalBufferAndViews = __dotnet_replacements.updateGlobalBufferAndViews; var fetch = __dotnet_replacements.fetch; diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.pre.js b/src/mono/wasm/runtime/es6/dotnet.es6.pre.js index 51648406a655..ea93a4052671 100644 --- a/src/mono/wasm/runtime/es6/dotnet.es6.pre.js +++ b/src/mono/wasm/runtime/es6/dotnet.es6.pre.js @@ -1,10 +1,10 @@ -const MONO = {}, BINDING = {}, INTERNAL = {}, IMPORTS = {}, EXPORTS = {}; +const MONO = {}, BINDING = {}, INTERNAL = {}, IMPORTS = {}; let ENVIRONMENT_IS_GLOBAL = false; var require = require || undefined; var __dirname = __dirname || ''; if (typeof createDotnetRuntime === "function") { Module = { ready: Module.ready }; - const extension = createDotnetRuntime({ MONO, BINDING, INTERNAL, IMPORTS, EXPORTS, Module }) + const extension = createDotnetRuntime({ MONO, BINDING, INTERNAL, Module, IMPORTS }) if (extension.ready) { throw new Error("MONO_WASM: Module.ready couldn't be redefined.") } diff --git a/src/mono/wasm/runtime/export-api.ts b/src/mono/wasm/runtime/export-api.ts new file mode 100644 index 000000000000..85ffc480300a --- /dev/null +++ b/src/mono/wasm/runtime/export-api.ts @@ -0,0 +1,46 @@ +import { APIType } from "./exports"; +import { runtimeHelpers } from "./imports"; +import { mono_wasm_get_assembly_exports } from "./invoke-cs"; +import { mono_wasm_set_module_imports } from "./invoke-js"; +import { getB32, getF32, getF64, getI16, getI32, getI52, getI64Big, getI8, getU16, getU32, getU52, getU8, setB32, setF32, setF64, setI16, setI32, setI52, setI64Big, setI8, setU16, setU32, setU52, setU8 } from "./memory"; +import { mono_run_main, mono_run_main_and_exit } from "./run"; +import { mono_wasm_setenv } from "./startup"; +import { MonoConfig } from "./types"; + +export function export_api(): any { + const api: APIType = { + runMain: mono_run_main, + runMainAndExit: mono_run_main_and_exit, + setEnvironmentVariable: mono_wasm_setenv, + getAssemblyExports: mono_wasm_get_assembly_exports, + setModuleImports: mono_wasm_set_module_imports, + getConfig: (): MonoConfig => { + return runtimeHelpers.config; + }, + setHeapB32: setB32, + setHeapU8: setU8, + setHeapU16: setU16, + setHeapU32: setU32, + setHeapI8: setI8, + setHeapI16: setI16, + setHeapI32: setI32, + setHeapI52: setI52, + setHeapU52: setU52, + setHeapI64Big: setI64Big, + setHeapF32: setF32, + setHeapF64: setF64, + getHeapB32: getB32, + getHeapU8: getU8, + getHeapU16: getU16, + getHeapU32: getU32, + getHeapI8: getI8, + getHeapI16: getI16, + getHeapI32: getI32, + getHeapI52: getI52, + getHeapU52: getU52, + getHeapI64Big: getI64Big, + getHeapF32: getF32, + getHeapF64: getF64, + }; + return api; +} \ No newline at end of file diff --git a/src/mono/wasm/runtime/export-types.ts b/src/mono/wasm/runtime/export-types.ts index 15b1ec3869d7..946d3f9fc6f6 100644 --- a/src/mono/wasm/runtime/export-types.ts +++ b/src/mono/wasm/runtime/export-types.ts @@ -1,10 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { BINDINGType, MONOType } from "./net6-legacy/exports-legacy"; -import { IDisposable, IMemoryView, ManagedError, ManagedObject, MemoryViewType } from "./marshal"; -import { AssetBehaviours, AssetEntry, DotnetModuleConfig, DotnetPublicAPI, LoadingResource, MonoArray, MonoConfig, MonoObject, MonoString, ResourceRequest } from "./types"; -import { EmscriptenModule, TypedArray, VoidPtr } from "./types/emscripten"; +import { APIType, DotnetPublicAPI } from "./exports"; +import { IDisposable, IMemoryView, MemoryViewType } from "./marshal"; +import { AssetBehaviours, AssetEntry, DotnetModuleConfig, LoadingResource, MonoConfig, ResourceRequest } from "./types"; +import { EmscriptenModule, NativePointer, TypedArray } from "./types/emscripten"; // ----------------------------------------------------------- // this files has all public exports from the dotnet.js module @@ -51,11 +51,28 @@ declare class ArraySegment implements IMemoryView, IDisposable { 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 { - VoidPtr, - MonoObject, MonoString, MonoArray, - BINDINGType, MONOType, EmscriptenModule, - DotnetPublicAPI, DotnetModuleConfig, CreateDotnetRuntimeType, MonoConfig, + EmscriptenModule, NativePointer, + DotnetPublicAPI, APIType, DotnetModuleConfig, CreateDotnetRuntimeType, MonoConfig, AssetEntry, ResourceRequest, LoadingResource, AssetBehaviours, IMemoryView, MemoryViewType, ManagedObject, ManagedError, Span, ArraySegment }; diff --git a/src/mono/wasm/runtime/exports.ts b/src/mono/wasm/runtime/exports.ts index 47628879641e..cfbd03fc68f7 100644 --- a/src/mono/wasm/runtime/exports.ts +++ b/src/mono/wasm/runtime/exports.ts @@ -2,11 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. import ProductVersion from "consts:productVersion"; -import Configuration from "consts:configuration"; +import BuildConfiguration from "consts:configuration"; import MonoWasmThreads from "consts:monoWasmThreads"; import { ENVIRONMENT_IS_PTHREAD, set_imports_exports } from "./imports"; -import { DotnetModule, is_nullish, DotnetPublicAPI, EarlyImports, EarlyExports, EarlyReplacements } from "./types"; +import { DotnetModule, is_nullish, EarlyImports, EarlyExports, EarlyReplacements, MonoConfig } from "./types"; import { configure_emscripten_startup, mono_wasm_pthread_worker_init } from "./startup"; import { mono_bind_static_method } from "./net6-legacy/method-calls"; @@ -15,6 +15,8 @@ import { export_binding_api, export_mono_api } from "./net6-legacy/exports-legac import { export_internal } from "./exports-internal"; import { export_linker } from "./exports-linker"; import { init_polyfills } from "./polyfills"; +import { EmscriptenModule, NativePointer } from "./types/emscripten"; +import { export_api } from "./export-api"; export const __initializeImportsAndExports: any = initializeImportsAndExports; // don't want to export the type export let __linker_exports: any = null; @@ -41,19 +43,20 @@ function initializeImportsAndExports( Object.assign(exports.mono, export_mono_api()); Object.assign(exports.binding, export_binding_api()); Object.assign(exports.internal, export_internal()); + const API = export_api(); __linker_exports = export_linker(); exportedAPI = { MONO: exports.mono, BINDING: exports.binding, INTERNAL: exports.internal, - EXPORTS: exports.marshaled_exports, IMPORTS: exports.marshaled_imports, Module: module, - RuntimeBuildInfo: { - ProductVersion, - Configuration - } + runtimeBuildInfo: { + productVersion: ProductVersion, + buildConfiguration: BuildConfiguration + }, + ...API, }; if (exports.module.__undefinedConfig) { module.disableDotnet6Compatibility = true; @@ -78,7 +81,7 @@ function initializeImportsAndExports( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore module.mono_bind_static_method = (fqn: string, signature: string/*ArgsMarshalString*/): Function => { - console.warn("MONO_WASM: Module.mono_bind_static_method is obsolete, please use BINDING.bind_static_method instead"); + console.warn("MONO_WASM: Module.mono_bind_static_method is obsolete, please use [JSExportAttribute] interop instead"); return mono_bind_static_method(fqn, signature); }; @@ -150,9 +153,9 @@ class RuntimeList { private list: { [runtimeId: number]: WeakRef } = {}; public registerRuntime(api: DotnetPublicAPI): number { - api.RuntimeId = Object.keys(this.list).length; - this.list[api.RuntimeId] = create_weak_ref(api); - return api.RuntimeId; + api.runtimeId = Object.keys(this.list).length; + this.list[api.runtimeId] = create_weak_ref(api); + return api.runtimeId; } public getRuntime(runtimeId: number): DotnetPublicAPI | undefined { @@ -164,3 +167,56 @@ class RuntimeList { export function get_dotnet_instance(): DotnetPublicAPI { return exportedAPI; } + +export interface 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, +} + +// this represents visibility in the javascript +// like https://github.com/dotnet/aspnetcore/blob/main/src/Components/Web.JS/src/Platform/Mono/MonoTypes.ts +export type DotnetPublicAPI = { + /** + * @deprecated Please use API object instead. See also MONOType in dotnet-legacy.d.ts + */ + MONO: any, + /** + * @deprecated Please use API object instead. See also BINDINGType in dotnet-legacy.d.ts + */ + BINDING: any, + INTERNAL: any, + Module: EmscriptenModule, + runtimeId: number, + runtimeBuildInfo: { + productVersion: string, + buildConfiguration: string, + } & APIType +} \ No newline at end of file diff --git a/src/mono/wasm/runtime/icu.ts b/src/mono/wasm/runtime/icu.ts index 551d0d92d70a..93ea54d9d9fa 100644 --- a/src/mono/wasm/runtime/icu.ts +++ b/src/mono/wasm/runtime/icu.ts @@ -26,24 +26,24 @@ export function mono_wasm_get_icudt_name(culture: string): string { } // Performs setup for globalization. -// @globalization_mode is one of "icu", "invariant", or "auto". +// @globalizationMode is one of "icu", "invariant", or "auto". // "auto" will use "icu" if any ICU data archives have been loaded, // otherwise "invariant". export function mono_wasm_globalization_init(): void { const config = Module.config as MonoConfig; let invariantMode = false; - if (!config.globalization_mode) - config.globalization_mode = "auto"; - if (config.globalization_mode === "invariant") + if (!config.globalizationMode) + config.globalizationMode = "auto"; + if (config.globalizationMode === "invariant") invariantMode = true; if (!invariantMode) { if (num_icu_assets_loaded_successfully > 0) { - if (runtimeHelpers.diagnostic_tracing) { + if (runtimeHelpers.diagnosticTracing) { console.debug("MONO_WASM: ICU data archive(s) loaded, disabling invariant mode"); } - } else if (config.globalization_mode !== "icu") { - if (runtimeHelpers.diagnostic_tracing) { + } else if (config.globalizationMode !== "icu") { + if (runtimeHelpers.diagnosticTracing) { console.debug("MONO_WASM: ICU data archive(s) not loaded, using invariant globalization mode"); } invariantMode = true; diff --git a/src/mono/wasm/runtime/imports.ts b/src/mono/wasm/runtime/imports.ts index a5d62e93be49..fcd7760795e8 100644 --- a/src/mono/wasm/runtime/imports.ts +++ b/src/mono/wasm/runtime/imports.ts @@ -4,7 +4,7 @@ /* eslint-disable @typescript-eslint/triple-slash-reference */ /// -import { BINDINGType, MONOType } from "./net6-legacy/exports-legacy"; +import { BINDINGType, MONOType } from "./net6-legacy/export-types"; import { DotnetModule, EarlyExports, EarlyImports, MonoConfig, RuntimeHelpers } from "./types"; import { EmscriptenModule } from "./types/emscripten"; @@ -13,7 +13,6 @@ export let Module: EmscriptenModule & DotnetModule; export let MONO: MONOType; export let BINDING: BINDINGType; export let INTERNAL: any; -export let EXPORTS: any; export let IMPORTS: any; // these are imported and re-exported from emscripten internals @@ -33,9 +32,6 @@ export function set_imports_exports( INTERNAL = exports.internal; Module = exports.module; - EXPORTS = exports.marshaled_exports; // [JSExport] - IMPORTS = exports.marshaled_imports; // [JSImport] - ENVIRONMENT_IS_NODE = imports.isNode; ENVIRONMENT_IS_SHELL = imports.isShell; ENVIRONMENT_IS_WEB = imports.isWeb; @@ -69,7 +65,6 @@ export const runtimeHelpers: RuntimeHelpers = { MONO.config = value; Module.config = value; }, - diagnostic_tracing: false, - enable_debugging: false, + diagnosticTracing: false, fetch: null }; diff --git a/src/mono/wasm/runtime/invoke-cs.ts b/src/mono/wasm/runtime/invoke-cs.ts index d4e91aaeb65d..8272f49f62c2 100644 --- a/src/mono/wasm/runtime/invoke-cs.ts +++ b/src/mono/wasm/runtime/invoke-cs.ts @@ -1,18 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { EXPORTS, Module, runtimeHelpers } from "./imports"; +import { Module, runtimeHelpers } from "./imports"; import { generate_arg_marshal_to_cs } from "./marshal-to-cs"; import { marshal_exception_to_js, generate_arg_marshal_to_js } from "./marshal-to-js"; import { - JSMarshalerArguments, JavaScriptMarshalerArgSize, JSFunctionSignature, + JavaScriptMarshalerArgSize, JSMarshalerTypeSize, JSMarshalerSignatureHeaderSize, get_arg, get_sig, get_signature_argument_count, is_args_exception, bound_cs_function_symbol, get_signature_version, MarshalerType, alloc_stack_frame, } from "./marshal"; import { mono_wasm_new_external_root } from "./roots"; import { conv_string, conv_string_root } from "./strings"; -import { mono_assert, MonoObjectRef, MonoStringRef, MonoString, MonoObject, MonoMethod } from "./types"; +import { mono_assert, MonoObjectRef, MonoStringRef, MonoString, MonoObject, MonoMethod, JSMarshalerArguments, JSFunctionSignature } from "./types"; import { Int32Ptr } from "./types/emscripten"; import cwraps from "./cwraps"; import { assembly_load } from "./class-loader"; @@ -31,7 +31,7 @@ export function mono_wasm_bind_cs_function(fully_qualified_name: MonoStringRef, const js_fqn = conv_string_root(fqn_root)!; mono_assert(js_fqn, "fully_qualified_name must be string"); - if (runtimeHelpers.diagnostic_tracing) { + if (runtimeHelpers.diagnosticTracing) { console.debug(`MONO_WASM: Binding [JSExport] ${js_fqn}`); } @@ -119,30 +119,9 @@ export function invoke_method_and_handle_exception(method: MonoMethod, args: JSM } export const exportsByAssembly: Map = new Map(); - function _walk_exports_to_set_function(assembly: string, namespace: string, classname: string, methodname: string, signature_hash: number, fn: Function): void { - let scope: any = EXPORTS; const parts = `${namespace}.${classname}`.replace(/\//g, ".").split("."); - - for (let i = 0; i < parts.length; i++) { - const part = parts[i]; - if (part != "") { - let newscope = scope[part]; - if (typeof newscope === "undefined") { - newscope = {}; - scope[part] = newscope; - } - mono_assert(newscope, () => `${part} not found while looking up ${classname}`); - scope = newscope; - } - } - - if (!scope[methodname]) { - scope[methodname] = fn; - } - scope[`${methodname}.${signature_hash}`] = fn; - - // do it again for per assemly scope + let scope: any = undefined; let assemblyScope = exportsByAssembly.get(assembly); if (!assemblyScope) { assemblyScope = {}; diff --git a/src/mono/wasm/runtime/invoke-js.ts b/src/mono/wasm/runtime/invoke-js.ts index 21c5bfa14150..1482b3f4383c 100644 --- a/src/mono/wasm/runtime/invoke-js.ts +++ b/src/mono/wasm/runtime/invoke-js.ts @@ -3,10 +3,10 @@ import { mono_wasm_get_jsobj_from_js_handle, mono_wasm_get_js_handle } from "./gc-handles"; import { marshal_exception_to_cs, generate_arg_marshal_to_cs } from "./marshal-to-cs"; -import { get_signature_argument_count, JSMarshalerArguments as JSMarshalerArguments, JavaScriptMarshalerArgSize, JSFunctionSignature as JSFunctionSignature, bound_js_function_symbol, JSMarshalerTypeSize, get_sig, JSMarshalerSignatureHeaderSize, get_signature_version, MarshalerType, get_signature_type } from "./marshal"; +import { get_signature_argument_count, JavaScriptMarshalerArgSize, bound_js_function_symbol, JSMarshalerTypeSize, get_sig, JSMarshalerSignatureHeaderSize, get_signature_version, MarshalerType, get_signature_type } from "./marshal"; import { setI32 } from "./memory"; import { conv_string_root, js_string_to_mono_string_root } from "./strings"; -import { mono_assert, JSHandle, MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "./types"; +import { mono_assert, JSHandle, MonoObject, MonoObjectRef, MonoString, MonoStringRef, JSFunctionSignature, JSMarshalerArguments } from "./types"; import { Int32Ptr } from "./types/emscripten"; import { IMPORTS, INTERNAL, Module, runtimeHelpers } from "./imports"; import { generate_arg_marshal_to_js } from "./marshal-to-js"; @@ -23,7 +23,7 @@ export function mono_wasm_bind_js_function(function_name: MonoStringRef, module_ const js_function_name = conv_string_root(function_name_root)!; const js_module_name = conv_string_root(module_name_root)!; - if (runtimeHelpers.diagnostic_tracing) { + if (runtimeHelpers.diagnosticTracing) { console.debug(`MONO_WASM: Binding [JSImport] ${js_function_name} from ${js_module_name}`); } const fn = mono_wasm_lookup_function(js_function_name, js_module_name); @@ -103,6 +103,12 @@ export function mono_wasm_invoke_bound_function(bound_function_js_handle: JSHand bound_fn(args); } +export function mono_wasm_set_module_imports(module_name: string, moduleImports: any) { + importedModules.set(module_name, moduleImports); + if (runtimeHelpers.diagnosticTracing) + console.debug(`MONO_WASM: added module imports '${module_name}'`); +} + function mono_wasm_lookup_function(function_name: string, js_module_name: string): Function { mono_assert(function_name && typeof function_name === "string", "function_name must be string"); @@ -174,7 +180,7 @@ export async function dynamic_import(module_name: string, module_url: string): P let promise = importedModulesPromises.get(module_name); const newPromise = !promise; if (newPromise) { - if (runtimeHelpers.diagnostic_tracing) + if (runtimeHelpers.diagnosticTracing) console.debug(`MONO_WASM: importing ES6 module '${module_name}' from '${module_url}'`); promise = import(/* webpackIgnore: true */module_url); importedModulesPromises.set(module_name, promise); @@ -182,7 +188,7 @@ export async function dynamic_import(module_name: string, module_url: string): P const module = await promise; if (newPromise) { importedModules.set(module_name, module); - if (runtimeHelpers.diagnostic_tracing) + if (runtimeHelpers.diagnosticTracing) console.debug(`MONO_WASM: imported ES6 module '${module_name}' from '${module_url}'`); } return module; diff --git a/src/mono/wasm/runtime/managed-exports.ts b/src/mono/wasm/runtime/managed-exports.ts index 7b6e21ffe7e7..4966c54089ad 100644 --- a/src/mono/wasm/runtime/managed-exports.ts +++ b/src/mono/wasm/runtime/managed-exports.ts @@ -1,27 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { GCHandle, MonoMethod, mono_assert } from "./types"; +import { GCHandle, MarshalerToCs, MarshalerToJs, MonoMethod, mono_assert } from "./types"; import cwraps from "./cwraps"; import { Module, runtimeHelpers } from "./imports"; -import { alloc_stack_frame, get_arg, get_arg_gc_handle, MarshalerToCs, MarshalerToJs, MarshalerType, set_arg_type, set_gc_handle } from "./marshal"; +import { alloc_stack_frame, get_arg, get_arg_gc_handle, MarshalerType, set_arg_type, set_gc_handle } from "./marshal"; import { invoke_method_and_handle_exception } from "./invoke-cs"; import { marshal_exception_to_cs } from "./marshal-to-cs"; -// in all the exported internals methods, we use the same data structures for stack frame as normal full blow interop -// see src\libraries\System.Runtime.InteropServices.JavaScript\src\System\Runtime\InteropServices\JavaScript\Interop\JavaScriptExports.cs -export interface JavaScriptExports { - // the marshaled signature is: void ReleaseJSOwnedObjectByGCHandle(GCHandle gcHandle) - _release_js_owned_object_by_gc_handle(gc_handle: GCHandle): void; - // the marshaled signature is: GCHandle CreateTaskCallback() - _create_task_callback(): GCHandle; - // the marshaled signature is: void CompleteTask(GCHandle holder, Exception? exceptionResult, T? result) - _complete_task(holder_gc_handle: GCHandle, error?: any, data?: any, res_converter?: MarshalerToCs): void; - // the marshaled signature is: TRes? CallDelegate(GCHandle callback, T1? arg1, T2? arg2, T3? arg3) - _call_delegate(callback_gc_handle: GCHandle, arg1_js: any, arg2_js: any, arg3_js: any, - res_converter?: MarshalerToJs, arg1_converter?: MarshalerToCs, arg2_converter?: MarshalerToCs, arg3_converter?: MarshalerToCs): any; -} - export function init_managed_exports(): void { const anyModule = Module as any; const exports_fqn_asm = "System.Runtime.InteropServices.JavaScript"; diff --git a/src/mono/wasm/runtime/marshal-to-cs.ts b/src/mono/wasm/runtime/marshal-to-cs.ts index ae2019fb5741..2a29abde9f93 100644 --- a/src/mono/wasm/runtime/marshal-to-cs.ts +++ b/src/mono/wasm/runtime/marshal-to-cs.ts @@ -6,16 +6,16 @@ import cwraps from "./cwraps"; import { assert_not_disposed, cs_owned_js_handle_symbol, js_owned_gc_handle_symbol, mono_wasm_get_js_handle, setup_managed_proxy, teardown_managed_proxy } from "./gc-handles"; import { Module, runtimeHelpers } from "./imports"; import { - JSMarshalerArgument, ManagedError, + ManagedError, set_gc_handle, set_js_handle, set_arg_type, set_arg_i32, set_arg_f64, set_arg_i52, set_arg_f32, set_arg_i16, set_arg_u8, set_arg_b8, set_arg_date, set_arg_length, get_arg, get_signature_type, get_signature_arg1_type, get_signature_arg2_type, cs_to_js_marshalers, js_to_cs_marshalers, - MarshalerToCs, MarshalerToJs, get_signature_res_type, JSMarshalerArguments, bound_js_function_symbol, set_arg_u16, JSMarshalerType, array_element_size, + get_signature_res_type, bound_js_function_symbol, set_arg_u16, array_element_size, get_string_root, Span, ArraySegment, MemoryViewType, get_signature_arg3_type, MarshalerType, set_arg_i64_big, set_arg_intptr, IDisposable, set_arg_element_type, ManagedObject } from "./marshal"; import { _zero_region } from "./memory"; import { js_string_to_mono_string_root } from "./strings"; -import { mono_assert, GCHandle, GCHandleNull } from "./types"; +import { mono_assert, GCHandle, GCHandleNull, JSMarshalerArgument, JSMarshalerArguments, JSMarshalerType, MarshalerToCs, MarshalerToJs } from "./types"; import { TypedArray } from "./types/emscripten"; export function initialize_marshalers_to_cs(): void { diff --git a/src/mono/wasm/runtime/marshal-to-js.ts b/src/mono/wasm/runtime/marshal-to-js.ts index 7555fdbff6cf..4151cf5b19a4 100644 --- a/src/mono/wasm/runtime/marshal-to-js.ts +++ b/src/mono/wasm/runtime/marshal-to-js.ts @@ -6,7 +6,7 @@ import cwraps from "./cwraps"; import { _lookup_js_owned_object, mono_wasm_get_jsobj_from_js_handle, mono_wasm_get_js_handle, setup_managed_proxy } from "./gc-handles"; import { Module, runtimeHelpers } from "./imports"; import { - ManagedObject, JSMarshalerArgument, ManagedError, JSMarshalerArguments, MarshalerToCs, MarshalerToJs, JSMarshalerType, + ManagedObject, ManagedError, get_arg_gc_handle, get_arg_js_handle, get_arg_type, get_arg_i32, get_arg_f64, get_arg_i52, get_arg_i16, get_arg_u8, get_arg_f32, get_arg_b8, get_arg_date, get_arg_length, set_js_handle, get_arg, set_arg_type, get_signature_arg2_type, get_signature_arg1_type, get_signature_type, cs_to_js_marshalers, js_to_cs_marshalers, @@ -14,7 +14,7 @@ import { ArraySegment, Span, MemoryViewType, get_signature_arg3_type, MarshalerType, get_arg_i64_big, get_arg_intptr, get_arg_element_type } from "./marshal"; import { conv_string_root } from "./strings"; -import { mono_assert, JSHandleNull, GCHandleNull } from "./types"; +import { mono_assert, JSHandleNull, GCHandleNull, JSMarshalerArgument, JSMarshalerArguments, JSMarshalerType, MarshalerToCs, MarshalerToJs } from "./types"; import { TypedArray } from "./types/emscripten"; export function initialize_marshalers_to_js(): void { diff --git a/src/mono/wasm/runtime/marshal.ts b/src/mono/wasm/runtime/marshal.ts index f62415ec934d..4b0700714c39 100644 --- a/src/mono/wasm/runtime/marshal.ts +++ b/src/mono/wasm/runtime/marshal.ts @@ -5,8 +5,8 @@ import { js_owned_gc_handle_symbol, teardown_managed_proxy } from "./gc-handles" import { Module } from "./imports"; import { getF32, getF64, getI16, getI32, getI64Big, getU16, getU32, getU8, setF32, setF64, setI16, setI32, setI64Big, setU16, setU32, setU8 } from "./memory"; import { mono_wasm_new_external_root, WasmRoot } from "./roots"; -import { mono_assert, GCHandle, JSHandle, MonoObject, MonoString, GCHandleNull } from "./types"; -import { CharPtr, NativePointer, TypedArray, VoidPtr } from "./types/emscripten"; +import { mono_assert, GCHandle, JSHandle, MonoObject, MonoString, GCHandleNull, JSMarshalerArguments, JSFunctionSignature, JSMarshalerType, JSMarshalerArgument, MarshalerToJs, MarshalerToCs } from "./types"; +import { CharPtr, TypedArray, VoidPtr } from "./types/emscripten"; export const cs_to_js_marshalers = new Map(); export const js_to_cs_marshalers = new Map(); @@ -39,22 +39,6 @@ export const JavaScriptMarshalerArgSize = 16; export const JSMarshalerTypeSize = 32; export const JSMarshalerSignatureHeaderSize = 4 + 4; // without Exception and Result -export interface JSMarshalerArguments extends NativePointer { - __brand: "JSMarshalerArguments" -} - -export interface JSFunctionSignature extends NativePointer { - __brand: "JSFunctionSignatures" -} - -export interface JSMarshalerType extends NativePointer { - __brand: "JSMarshalerType" -} - -export interface JSMarshalerArgument extends NativePointer { - __brand: "JSMarshalerArgument" -} - export function alloc_stack_frame(size: number): JSMarshalerArguments { const anyModule = Module as any; const args = anyModule.stackAlloc(JavaScriptMarshalerArgSize * size); @@ -354,9 +338,6 @@ export class ManagedError extends Error implements IDisposable { } } -export type MarshalerToJs = (arg: JSMarshalerArgument, sig?: JSMarshalerType, res_converter?: MarshalerToJs, arg1_converter?: MarshalerToCs, arg2_converter?: MarshalerToCs) => any; -export type MarshalerToCs = (arg: JSMarshalerArgument, value: any, sig?: JSMarshalerType, res_converter?: MarshalerToCs, arg1_converter?: MarshalerToJs, arg2_converter?: MarshalerToJs) => void; - export function get_signature_marshaler(signature: JSFunctionSignature, index: number): JSHandle { mono_assert(signature, "Null signatures"); const sig = get_sig(signature, index); diff --git a/src/mono/wasm/runtime/modularize-dotnet.md b/src/mono/wasm/runtime/modularize-dotnet.md index b2f2e2afd102..39668cc03c94 100644 --- a/src/mono/wasm/runtime/modularize-dotnet.md +++ b/src/mono/wasm/runtime/modularize-dotnet.md @@ -38,43 +38,4 @@ await createDotnetRuntime(() => ({ })); ``` -More complex scenario with using APIs, commented -``` -import createDotnetRuntime from './dotnet.js' - -export const { MONO, BINDING } = await createDotnetRuntime(({ MONO, BINDING, Module }) => -// this is callback with no statement, the APIs are only empty shells here and are populated later. -({ - disableDotnet6Compatibility: true, - configSrc: "./mono-config.json", - onConfigLoaded: () => { - // This is called during emscripten `preInit` event, after we fetched config. - - // Module.config is loaded and could be tweaked before application - Module.config.environment_variables["MONO_LOG_LEVEL"]="debug" - - // here we could use API passed into this callback - // call some early available functions - MONO.mono_wasm_setenv("HELLO", "WORLD); - } - onDotnetReady: () => { - // Only when there is no `onRuntimeInitialized` override. - // This is called after all assets are loaded. - // It happens during emscripten `onRuntimeInitialized` after monoVm init + globalization + assemblies. - // This also matches when the top level promise is resolved. - // The original emscripten `Module.ready` promise is replaced with this. - - // at this point both emscripten and monoVM are fully initialized. - Module.FS.chdir(processedArguments.working_dir); - }, - onAbort: (error) => { - set_exit_code(1, error); - }, -})); - -// at this point both emscripten and monoVM are fully initialized. -// we could use the APIs returned and resolved from createDotnetRuntime promise -// both API exports are receiving the same API object instances, i.e. same `MONO` instance. -const run_all = BINDING.bind_static_method ("[debugger-test] DebuggerTest:run_all"); -run_all(); -``` +For more complex scenario with using APIs see `src\mono\sample\wasm` diff --git a/src/mono/wasm/runtime/net6-legacy/export-types.ts b/src/mono/wasm/runtime/net6-legacy/export-types.ts new file mode 100644 index 000000000000..c2f9022c377b --- /dev/null +++ b/src/mono/wasm/runtime/net6-legacy/export-types.ts @@ -0,0 +1,265 @@ +import { mono_wasm_runtime_ready } from "../debug"; +import { mono_wasm_load_icu_data } from "../icu"; +import { mono_wasm_get_assembly_exports } from "../invoke-cs"; +import { mono_wasm_load_bytes_into_heap, setB32, setI8, setI16, setI32, setI52, setU52, setI64Big, setU8, setU16, setU32, setF32, setF64, getB32, getI8, getI16, getI32, getI52, getU52, getI64Big, getU8, getU16, getU32, getF32, getF64 } from "../memory"; +import { mono_wasm_new_root_buffer, mono_wasm_new_root, mono_wasm_new_external_root, mono_wasm_release_roots } from "../roots"; +import { mono_run_main, mono_run_main_and_exit } from "../run"; +import { mono_wasm_setenv, mono_wasm_load_data_archive, mono_wasm_load_config } from "../startup"; +import { js_string_to_mono_string, conv_string, js_string_to_mono_string_root, conv_string_root } from "../strings"; +import { MonoArray, MonoObject, MonoObjectRef } from "../types"; +import { VoidPtr } from "../types/emscripten"; +import { mono_array_to_js_array, unbox_mono_obj, unbox_mono_obj_root, mono_array_root_to_js_array } from "./cs-to-js"; +import { js_typed_array_to_array, js_to_mono_obj, js_typed_array_to_array_root, js_to_mono_obj_root } from "./js-to-cs"; +import { mono_bind_static_method, mono_call_assembly_entry_point } from "./method-calls"; + +/** + * @deprecated Please use methods in top level API object instead + */ +export type BINDINGType = { + /** + * @deprecated Please use [JSExportAttribute] instead + */ + bind_static_method: typeof mono_bind_static_method; + /** + * @deprecated Please use runMain() instead + */ + call_assembly_entry_point: typeof mono_call_assembly_entry_point; + /** + * @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 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: typeof js_string_to_mono_string_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + js_typed_array_to_array_root: typeof js_typed_array_to_array_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + js_to_mono_obj_root: typeof js_to_mono_obj_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + conv_string_root: typeof conv_string_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + unbox_mono_obj_root: typeof unbox_mono_obj_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_array_root_to_js_array: typeof mono_array_root_to_js_array; +} + +/** + * @deprecated Please use methods in top level API object instead + */ +export type MONOType = { + /** + * @deprecated Please use setEnvironmentVariable() instead + */ + mono_wasm_setenv: typeof mono_wasm_setenv; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_load_bytes_into_heap: typeof mono_wasm_load_bytes_into_heap; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_load_icu_data: typeof mono_wasm_load_icu_data; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_runtime_ready: typeof mono_wasm_runtime_ready; + /** + * @deprecated Please use config.assets instead + */ + mono_wasm_load_data_archive: typeof mono_wasm_load_data_archive; + /** + * @deprecated Please use configSrc instead + */ + mono_wasm_load_config: typeof mono_wasm_load_config; + /** + * @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: typeof mono_wasm_new_root_buffer; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_wasm_new_root: typeof mono_wasm_new_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_wasm_new_external_root: typeof mono_wasm_new_external_root; + /** + * @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead. + */ + mono_wasm_release_roots: typeof mono_wasm_release_roots; + /** + * @deprecated Please use runMain instead + */ + mono_run_main: typeof mono_run_main; + /** + * @deprecated Please use runMainAndExit instead + */ + mono_run_main_and_exit: typeof mono_run_main_and_exit; + /** + * @deprecated Please use getAssemblyExports instead + */ + mono_wasm_get_assembly_exports: typeof mono_wasm_get_assembly_exports; + /** + * @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: typeof setB32; + /** + * @deprecated Please use setHeapI8 + */ + setI8: typeof setI8; + /** + * @deprecated Please use setHeapI16 + */ + setI16: typeof setI16; + /** + * @deprecated Please use setHeapI32 + */ + setI32: typeof setI32; + /** + * @deprecated Please use setHeapI52 + */ + setI52: typeof setI52; + /** + * @deprecated Please use setHeapU52 + */ + setU52: typeof setU52; + /** + * @deprecated Please use setHeapI64Big + */ + setI64Big: typeof setI64Big; + /** + * @deprecated Please use setHeapU8 + */ + setU8: typeof setU8; + /** + * @deprecated Please use setHeapU16 + */ + setU16: typeof setU16; + /** + * @deprecated Please use setHeapU32 + */ + setU32: typeof setU32; + /** + * @deprecated Please use setHeapF32 + */ + setF32: typeof setF32; + /** + * @deprecated Please use setHeapF64 + */ + setF64: typeof setF64; + /** + * @deprecated Please use getHeapB32 + */ + getB32: typeof getB32; + /** + * @deprecated Please use getHeapI8 + */ + getI8: typeof getI8; + /** + * @deprecated Please use getHeapI16 + */ + getI16: typeof getI16; + /** + * @deprecated Please use getHeapI32 + */ + getI32: typeof getI32; + /** + * @deprecated Please use getHeapI52 + */ + getI52: typeof getI52; + /** + * @deprecated Please use getHeapU52 + */ + getU52: typeof getU52; + /** + * @deprecated Please use getHeapI64Big + */ + getI64Big: typeof getI64Big; + /** + * @deprecated Please use getHeapU8 + */ + getU8: typeof getU8; + /** + * @deprecated Please use getHeapU16 + */ + getU16: typeof getU16; + /** + * @deprecated Please use getHeapU32 + */ + getU32: typeof getU32; + /** + * @deprecated Please use getHeapF32 + */ + getF32: typeof getF32; + /** + * @deprecated Please use getHeapF64 + */ + getF64: typeof getF64; +} \ No newline at end of file diff --git a/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts b/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts index 93b26e6f1e14..7dd9f494aa42 100644 --- a/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts +++ b/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts @@ -1,6 +1,5 @@ import cwraps from "../cwraps"; import { mono_wasm_runtime_ready } from "../debug"; -import diagnostics, { Diagnostics } from "../diagnostics"; import { mono_wasm_load_icu_data } from "../icu"; import { runtimeHelpers } from "../imports"; import { mono_wasm_get_assembly_exports } from "../invoke-cs"; @@ -9,16 +8,16 @@ import { mono_wasm_new_root_buffer, mono_wasm_new_root, mono_wasm_new_external_r import { mono_run_main, mono_run_main_and_exit } from "../run"; import { mono_wasm_setenv, mono_wasm_load_data_archive, mono_wasm_load_config, mono_load_runtime_and_bcl_args } from "../startup"; import { js_string_to_mono_string, conv_string, js_string_to_mono_string_root, conv_string_root } from "../strings"; -import { MonoArray, MonoConfig, MonoConfigError, MonoObject, MonoObjectRef } from "../types"; -import { VoidPtr } from "../types/emscripten"; +import { MonoConfig, MonoConfigError } from "../types"; import { mono_array_to_js_array, unbox_mono_obj, unbox_mono_obj_root, mono_array_root_to_js_array } from "./cs-to-js"; import { js_typed_array_to_array, js_to_mono_obj, js_typed_array_to_array_root, js_to_mono_obj_root } from "./js-to-cs"; import { mono_bind_static_method, mono_call_assembly_entry_point } from "./method-calls"; import { mono_wasm_load_runtime } from "../startup"; +import { BINDINGType, MONOType } from "./export-types"; export function export_mono_api(): MONOType { return { - // current "public" MONO API + // legacy MONO API mono_wasm_setenv, mono_wasm_load_bytes_into_heap, mono_wasm_load_icu_data, @@ -66,9 +65,6 @@ export function export_mono_api(): MONOType { getU32, getF32, getF64, - - // Diagnostics - diagnostics }; } @@ -80,7 +76,7 @@ export function cwraps_mono_api(mono: MONOType): void { export function export_binding_api(): BINDINGType { return { - //current "public" BINDING API + // legacy BINDING API bind_static_method: mono_bind_static_method, call_assembly_entry_point: mono_call_assembly_entry_point, mono_obj_array_new: null, @@ -111,97 +107,3 @@ export function cwraps_binding_api(binding: BINDINGType): void { mono_obj_array_set_ref: cwraps.mono_wasm_obj_array_set_ref, }); } - -export type BINDINGType = { - bind_static_method: typeof mono_bind_static_method; - call_assembly_entry_point: typeof mono_call_assembly_entry_point; - /** - * @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; - - // do we really want to advertize add these below ? - 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; -} - -export 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; - -} \ No newline at end of file diff --git a/src/mono/wasm/runtime/net6-legacy/method-calls.ts b/src/mono/wasm/runtime/net6-legacy/method-calls.ts index af7c17b80c86..830410844253 100644 --- a/src/mono/wasm/runtime/net6-legacy/method-calls.ts +++ b/src/mono/wasm/runtime/net6-legacy/method-calls.ts @@ -75,7 +75,7 @@ export function mono_bind_assembly_entry_point(assembly: string, signature?: str throw new Error("Could not find assembly: " + assembly); let auto_set_breakpoint = 0; - if (runtimeHelpers.wait_for_debugger == 1) + if (runtimeHelpers.waitForDebugger == 1) auto_set_breakpoint = 1; const method = cwraps.mono_wasm_assembly_get_entry_point(asm, auto_set_breakpoint); diff --git a/src/mono/wasm/runtime/polyfills.ts b/src/mono/wasm/runtime/polyfills.ts index 92078609d5e8..1e56ac4e813a 100644 --- a/src/mono/wasm/runtime/polyfills.ts +++ b/src/mono/wasm/runtime/polyfills.ts @@ -120,7 +120,7 @@ export function init_polyfills(replacements: EarlyReplacements): void { } // require replacement - const imports = anyModule.imports = Module.imports || {}; + const imports = anyModule.imports = (Module.imports || {}) as DotnetModuleConfigImports; const requireWrapper = (wrappedRequire: Function) => (name: string) => { const resolved = (Module.imports)[name]; if (resolved) { diff --git a/src/mono/wasm/runtime/profiler.ts b/src/mono/wasm/runtime/profiler.ts index 92dc91a66d11..45845417e83e 100644 --- a/src/mono/wasm/runtime/profiler.ts +++ b/src/mono/wasm/runtime/profiler.ts @@ -6,35 +6,35 @@ import { AOTProfilerOptions, CoverageProfilerOptions } from "./types"; // Initialize the AOT profiler with OPTIONS. // Requires the AOT profiler to be linked into the app. -// options = { write_at: "", send_to: "" } +// options = { writeAt: "", sendTo: "" } // should be in the format ::. -// write_at defaults to 'WebAssembly.Runtime::StopProfile'. -// send_to defaults to 'WebAssembly.Runtime::DumpAotProfileData'. -// DumpAotProfileData stores the data into INTERNAL.aot_profile_data. +// writeAt defaults to 'WebAssembly.Runtime::StopProfile'. +// sendTo defaults to 'WebAssembly.Runtime::DumpAotProfileData'. +// DumpAotProfileData stores the data into INTERNAL.aotProfileData. // export function mono_wasm_init_aot_profiler(options: AOTProfilerOptions): void { if (options == null) options = {}; - if (!("write_at" in options)) - options.write_at = "System.Runtime.InteropServices.JavaScript.JavaScriptExports::StopProfile"; - if (!("send_to" in options)) - options.send_to = "Interop/Runtime::DumpAotProfileData"; - const arg = "aot:write-at-method=" + options.write_at + ",send-to-method=" + options.send_to; + if (!("writeAt" in options)) + options.writeAt = "System.Runtime.InteropServices.JavaScript.JavaScriptExports::StopProfile"; + if (!("sendTo" in options)) + options.sendTo = "Interop/Runtime::DumpAotProfileData"; + const arg = "aot:write-at-method=" + options.writeAt + ",send-to-method=" + options.sendTo; Module.ccall("mono_wasm_load_profiler_aot", null, ["string"], [arg]); } -// options = { write_at: "", send_to: "" } +// options = { writeAt: "", sendTo: "" } // should be in the format ::. -// write_at defaults to 'WebAssembly.Runtime::StopProfile'. -// send_to defaults to 'WebAssembly.Runtime::DumpCoverageProfileData'. +// writeAt defaults to 'WebAssembly.Runtime::StopProfile'. +// sendTo defaults to 'WebAssembly.Runtime::DumpCoverageProfileData'. // DumpCoverageProfileData stores the data into INTERNAL.coverage_profile_data. export function mono_wasm_init_coverage_profiler(options: CoverageProfilerOptions): void { if (options == null) options = {}; - if (!("write_at" in options)) - options.write_at = "WebAssembly.Runtime::StopProfile"; - if (!("send_to" in options)) - options.send_to = "WebAssembly.Runtime::DumpCoverageProfileData"; - const arg = "coverage:write-at-method=" + options.write_at + ",send-to-method=" + options.send_to; + if (!("writeAt" in options)) + options.writeAt = "WebAssembly.Runtime::StopProfile"; + if (!("sendTo" in options)) + options.sendTo = "WebAssembly.Runtime::DumpCoverageProfileData"; + const arg = "coverage:write-at-method=" + options.writeAt + ",send-to-method=" + options.sendTo; Module.ccall("mono_wasm_load_profiler_coverage", null, ["string"], [arg]); } diff --git a/src/mono/wasm/runtime/rollup.config.js b/src/mono/wasm/runtime/rollup.config.js index 9c6137ec5127..d445f52f34b7 100644 --- a/src/mono/wasm/runtime/rollup.config.js +++ b/src/mono/wasm/runtime/rollup.config.js @@ -66,7 +66,6 @@ const inlineAssert = [ const outputCodePlugins = [regexReplace(inlineAssert), consts({ productVersion, configuration, monoWasmThreads, monoDiagnosticsMock }), typescript()]; const externalDependencies = [ - "node/buffer" ]; const iffeConfig = { @@ -97,6 +96,19 @@ const typesConfig = { external: externalDependencies, plugins: [dts()], }; +const legacyConfig = { + input: "./net6-legacy/export-types.ts", + output: [ + { + format: "es", + file: nativeBinDir + "/dotnet-legacy.d.ts", + banner: banner_dts, + plugins: [writeOnChangePlugin()], + } + ], + external: externalDependencies, + plugins: [dts()], +}; let diagnosticMockTypesConfig = undefined; @@ -110,6 +122,12 @@ if (isDebug) { banner: banner_dts, plugins: [alwaysLF(), writeOnChangePlugin()], }); + legacyConfig.output.push({ + format: "es", + file: "./dotnet-legacy.d.ts", + banner: banner_dts, + plugins: [alwaysLF(), writeOnChangePlugin()], + }); // export types into the source code and commit to git diagnosticMockTypesConfig = { @@ -150,6 +168,7 @@ const workerConfigs = findWebWorkerInputs("./workers").map((workerInput) => make const allConfigs = [ iffeConfig, typesConfig, + legacyConfig, ].concat(workerConfigs) .concat(diagnosticMockTypesConfig ? [diagnosticMockTypesConfig] : []); export default defineConfig(allConfigs); diff --git a/src/mono/wasm/runtime/run.ts b/src/mono/wasm/runtime/run.ts index fcf1c78664c0..7958595c14cd 100644 --- a/src/mono/wasm/runtime/run.ts +++ b/src/mono/wasm/runtime/run.ts @@ -9,7 +9,7 @@ export async function mono_run_main_and_exit(main_assembly_name: string, args: s set_exit_code(result); } catch (error) { if (error instanceof runtimeHelpers.ExitStatus) { - return; + return;// FIXME: should this be re-throw ? } set_exit_code(1, error); } @@ -17,7 +17,7 @@ export async function mono_run_main_and_exit(main_assembly_name: string, args: s export async function mono_run_main(main_assembly_name: string, args: string[]): Promise { mono_wasm_set_main_args(main_assembly_name, args); - if (runtimeHelpers.wait_for_debugger == -1) { + if (runtimeHelpers.waitForDebugger == -1) { console.log("MONO_WASM: waiting for debugger..."); return await mono_wasm_wait_for_debugger().then(() => mono_call_assembly_entry_point(main_assembly_name, [args], "m")); } diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index bef45d27fed6..0093ee5d3db1 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.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 { mono_assert, CharPtrNull, DotnetModule, MonoConfig, wasm_type_symbol, MonoObject, MonoConfigError, LoadingResource, AssetEntry, ResourceRequest, DotnetPublicAPI } from "./types"; +import { mono_assert, CharPtrNull, DotnetModule, MonoConfig, wasm_type_symbol, MonoObject, MonoConfigError, LoadingResource, AssetEntry, ResourceRequest } from "./types"; import { BINDING, ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, INTERNAL, Module, MONO, runtimeHelpers } from "./imports"; import cwraps, { init_c_exports } from "./cwraps"; import { mono_wasm_raise_debug_event, mono_wasm_runtime_ready } from "./debug"; @@ -19,13 +19,13 @@ import { init_polyfills_async } from "./polyfills"; import * as pthreads_worker from "./pthreads/worker"; import { createPromiseController, PromiseAndController } from "./promise-controller"; import { string_decoder } from "./strings"; -import { mono_wasm_init_diagnostics } from "./diagnostics/index"; import { delay } from "./promise-utils"; import { init_managed_exports } from "./managed-exports"; import { init_legacy_exports } from "./net6-legacy/corebindings"; import { mono_wasm_load_bytes_into_heap } from "./memory"; import { cwraps_internal } from "./exports-internal"; import { cwraps_binding_api, cwraps_mono_api } from "./net6-legacy/exports-legacy"; +import { DotnetPublicAPI } from "./exports"; let all_assets_loaded_in_memory: Promise | null = null; const loaded_files: { url: string, file: string }[] = []; @@ -99,8 +99,7 @@ function instantiateWasm( } else { config = runtimeHelpers.config = Module.config = {} as any; } - runtimeHelpers.diagnostic_tracing = !!config.diagnostic_tracing; - runtimeHelpers.enable_debugging = config.enable_debugging ? config.enable_debugging : 0; + runtimeHelpers.diagnosticTracing = !!config.diagnosticTracing; if (!config.assets) { config.assets = []; } @@ -115,7 +114,7 @@ function instantiateWasm( wasm_module_imports = imports; wasm_success_callback = successCallback; - _instantiate_wasm_module(); + instantiate_wasm_module(); return []; // No exports } @@ -123,7 +122,7 @@ function preInit(isCustomStartup: boolean, userPreInit: (() => void)[]) { Module.addRunDependency("mono_pre_init"); try { mono_wasm_pre_init_essential(); - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: preInit"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: preInit"); beforePreInit.promise_control.resolve(); // all user Module.preInit callbacks userPreInit.forEach(fn => fn()); @@ -158,7 +157,7 @@ async function preRunAsync(userPreRun: (() => void)[]) { // wait for previous stages await afterInstantiateWasm.promise; await afterPreInit.promise; - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: preRunAsync"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: preRunAsync"); try { // all user Module.preRun callbacks userPreRun.map(fn => fn()); @@ -175,7 +174,7 @@ async function preRunAsync(userPreRun: (() => void)[]) { async function onRuntimeInitializedAsync(isCustomStartup: boolean, userOnRuntimeInitialized: () => void) { // wait for previous stage await afterPreRun.promise; - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: onRuntimeInitialized"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: onRuntimeInitialized"); // signal this stage, this will allow pending assets to allocate memory beforeOnRuntimeInitialized.promise_control.resolve(); try { @@ -185,7 +184,7 @@ async function onRuntimeInitializedAsync(isCustomStartup: boolean, userOnRuntime const expected_asset_count = config.assets ? config.assets.length : 0; mono_assert(downloded_assets_count == expected_asset_count, "Expected assets to be downloaded"); mono_assert(instantiated_assets_count == expected_asset_count, "Expected assets to be in memory"); - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: all assets are loaded in wasm memory"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: all assets are loaded in wasm memory"); // load runtime await mono_wasm_before_user_runtime_initialized(); @@ -212,7 +211,7 @@ async function onRuntimeInitializedAsync(isCustomStartup: boolean, userOnRuntime async function postRunAsync(userpostRun: (() => void)[]) { // wait for previous stage await afterOnRuntimeInitialized.promise; - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: postRunAsync"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: postRunAsync"); try { // all user Module.postRun callbacks userpostRun.map(fn => fn()); @@ -227,7 +226,7 @@ async function postRunAsync(userpostRun: (() => void)[]) { // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function abort_startup(reason: any, should_exit: boolean): void { - if (runtimeHelpers.diagnostic_tracing) console.trace("MONO_WASM: abort_startup"); + if (runtimeHelpers.diagnosticTracing) console.trace("MONO_WASM: abort_startup"); afterInstantiateWasm.promise_control.reject(reason); beforePreInit.promise_control.reject(reason); afterPreInit.promise_control.reject(reason); @@ -243,7 +242,7 @@ export function abort_startup(reason: any, should_exit: boolean): void { // runs in both blazor and non-blazor function mono_wasm_pre_init_essential(): void { Module.addRunDependency("mono_wasm_pre_init_essential"); - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: mono_wasm_pre_init_essential"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_wasm_pre_init_essential"); // init_polyfills() is already called from export.ts init_crypto(); @@ -257,7 +256,7 @@ function mono_wasm_pre_init_essential(): void { // runs in both blazor and non-blazor async function mono_wasm_pre_init_essential_async(): Promise { - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: mono_wasm_pre_init_essential_async"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_wasm_pre_init_essential_async"); Module.addRunDependency("mono_wasm_pre_init_essential_async"); await init_polyfills_async(); @@ -267,7 +266,7 @@ async function mono_wasm_pre_init_essential_async(): Promise { // runs just in non-blazor async function mono_wasm_pre_init_full(): Promise { - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: mono_wasm_pre_init_full"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_wasm_pre_init_full"); Module.addRunDependency("mono_wasm_pre_init_full"); if (Module.configSrc) { @@ -280,9 +279,9 @@ async function mono_wasm_pre_init_full(): Promise { // runs just in non-blazor async function mono_wasm_before_user_runtime_initialized(): Promise { - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: mono_wasm_before_user_runtime_initialized"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_wasm_before_user_runtime_initialized"); - if (!Module.config || Module.config.isError) { + if (!Module.config) { return; } @@ -295,7 +294,7 @@ async function mono_wasm_before_user_runtime_initialized(): Promise { await _apply_configuration_from_args(); mono_wasm_globalization_init(); - if (!runtimeHelpers.mono_wasm_load_runtime_done) mono_wasm_load_runtime("unused", config.debug_level || 0); + if (!runtimeHelpers.mono_wasm_load_runtime_done) mono_wasm_load_runtime("unused", config.debugLevel || 0); if (!runtimeHelpers.mono_wasm_runtime_is_ready) mono_wasm_runtime_ready(); setTimeout(() => { // when there are free CPU cycles @@ -309,7 +308,7 @@ async function mono_wasm_before_user_runtime_initialized(): Promise { // runs in both blazor and non-blazor async function mono_wasm_after_user_runtime_initialized(): Promise { - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: mono_wasm_after_user_runtime_initialized"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_wasm_after_user_runtime_initialized"); try { if (!Module.disableDotnet6Compatibility && Module.exports) { // Export emscripten defined in module through EXPORTED_RUNTIME_METHODS @@ -329,7 +328,7 @@ async function mono_wasm_after_user_runtime_initialized(): Promise { } } - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: Initializing mono runtime"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: Initializing mono runtime"); if (Module.onDotnetReady) { try { @@ -363,14 +362,14 @@ export function mono_wasm_setenv(name: string, value: string): void { export function mono_wasm_set_runtime_options(options: string[]): void { if (!Array.isArray(options)) - throw new Error("Expected runtime_options to be an array of strings"); + throw new Error("Expected runtimeOptions to be an array of strings"); const argv = Module._malloc(options.length * 4); let aindex = 0; for (let i = 0; i < options.length; ++i) { const option = options[i]; if (typeof (option) !== "string") - throw new Error("Expected runtime_options to be an array of strings"); + throw new Error("Expected runtimeOptions to be an array of strings"); Module.setValue(argv + (aindex * 4), cwraps.mono_wasm_strdup(option), "i32"); aindex += 1; } @@ -378,14 +377,14 @@ export function mono_wasm_set_runtime_options(options: string[]): void { } -async function _instantiate_wasm_module(): Promise { +async function instantiate_wasm_module(): Promise { // this is called so early that even Module exports like addRunDependency don't exist yet try { if (!config.assets && Module.configSrc) { // when we are starting with mono-config,json, it could have dotnet.wasm location in it, we have to wait for it await mono_wasm_load_config(Module.configSrc); } - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: instantiateWasm"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: instantiate_wasm_module"); let assetToLoad: AssetEntry = { name: "dotnet.wasm", behavior: "dotnetwasm" @@ -399,7 +398,7 @@ async function _instantiate_wasm_module(): Promise { const pendingAsset = await start_asset_download(assetToLoad); await beforePreInit.promise; - Module.addRunDependency("_instantiate_wasm_module"); + Module.addRunDependency("instantiate_wasm_module"); mono_assert(pendingAsset && pendingAsset.pending, () => `Can't load ${assetToLoad.name}`); const response = await pendingAsset.pending.response; @@ -407,20 +406,20 @@ async function _instantiate_wasm_module(): Promise { let compiledInstance: WebAssembly.Instance; let compiledModule: WebAssembly.Module; if (typeof WebAssembly.instantiateStreaming === "function" && contentType === "application/wasm") { - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: mono_wasm_after_user_runtime_initialized streaming"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: instantiate_wasm_module streaming"); const streamingResult = await WebAssembly.instantiateStreaming(response, wasm_module_imports!); compiledInstance = streamingResult.instance; compiledModule = streamingResult.module; } else { const arrayBuffer = await response.arrayBuffer(); - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: mono_wasm_after_user_runtime_initialized streaming"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: instantiate_wasm_module buffered"); const arrayBufferResult = await WebAssembly.instantiate(arrayBuffer, wasm_module_imports!); compiledInstance = arrayBufferResult.instance; compiledModule = arrayBufferResult.module; } ++instantiated_assets_count; wasm_success_callback!(compiledInstance, compiledModule); - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: instantiateWasm done"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: instantiate_wasm_module done"); afterInstantiateWasm.promise_control.resolve(); wasm_success_callback = null; wasm_module_imports = null; @@ -429,16 +428,16 @@ async function _instantiate_wasm_module(): Promise { abort_startup(err, true); throw err; } - Module.removeRunDependency("_instantiate_wasm_module"); + Module.removeRunDependency("instantiate_wasm_module"); } // this need to be run only after onRuntimeInitialized event, when the memory is ready function _instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array) { - if (runtimeHelpers.diagnostic_tracing) + if (runtimeHelpers.diagnosticTracing) console.debug(`MONO_WASM: Loaded:${asset.name} as ${asset.behavior} size ${bytes.length} from ${url}`); - const virtualName: string = typeof (asset.virtual_path) === "string" - ? asset.virtual_path + const virtualName: string = typeof (asset.virtualPath) === "string" + ? asset.virtualPath : asset.name; let offset: VoidPtr | null = null; @@ -466,7 +465,7 @@ function _instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array) { if (fileName.startsWith("/")) fileName = fileName.substr(1); if (parentDirectory) { - if (runtimeHelpers.diagnostic_tracing) + if (runtimeHelpers.diagnosticTracing) console.debug(`MONO_WASM: Creating directory '${parentDirectory}'`); Module.FS_createPath( @@ -476,7 +475,7 @@ function _instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array) { parentDirectory = "/"; } - if (runtimeHelpers.diagnostic_tracing) + if (runtimeHelpers.diagnosticTracing) console.debug(`MONO_WASM: Creating file '${fileName}' in directory '${parentDirectory}'`); if (!mono_wasm_load_data_archive(bytes, parentDirectory)) { @@ -518,43 +517,41 @@ async function _apply_configuration_from_args() { mono_wasm_setenv("TZ", "UTC"); } - for (const k in config.environment_variables) { - const v = config.environment_variables![k]; + for (const k in config.environmentVariables) { + const v = config.environmentVariables![k]; if (typeof (v) === "string") mono_wasm_setenv(k, v); else throw new Error(`Expected environment variable '${k}' to be a string but it was ${typeof v}: '${v}'`); } - if (config.runtime_options) - mono_wasm_set_runtime_options(config.runtime_options); + if (config.runtimeOptions) + mono_wasm_set_runtime_options(config.runtimeOptions); - if (config.aot_profiler_options) - mono_wasm_init_aot_profiler(config.aot_profiler_options); + if (config.aotProfilerOptions) + mono_wasm_init_aot_profiler(config.aotProfilerOptions); - if (config.coverage_profiler_options) - mono_wasm_init_coverage_profiler(config.coverage_profiler_options); + if (config.coverageProfilerOptions) + mono_wasm_init_coverage_profiler(config.coverageProfilerOptions); - if (config.diagnostic_options) { - await mono_wasm_init_diagnostics(config.diagnostic_options); - } + // FIXME await mono_wasm_init_diagnostics(config.diagnosticOptions); } -export function mono_wasm_load_runtime(unused?: string, debug_level?: number): void { - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: mono_wasm_load_runtime"); +export function mono_wasm_load_runtime(unused?: string, debugLevel?: number): void { + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_wasm_load_runtime"); if (runtimeHelpers.mono_wasm_load_runtime_done) { return; } runtimeHelpers.mono_wasm_load_runtime_done = true; try { - if (debug_level == undefined) { - debug_level = 0; - if (config && config.debug_level) { - debug_level = 0 + debug_level; + if (debugLevel == undefined) { + debugLevel = 0; + if (config && config.debugLevel) { + debugLevel = 0 + debugLevel; } } - cwraps.mono_wasm_load_runtime(unused || "unused", debug_level); - runtimeHelpers.wait_for_debugger = config.wait_for_debugger; + cwraps.mono_wasm_load_runtime(unused || "unused", debugLevel); + runtimeHelpers.waitForDebugger = config.waitForDebugger; if (!runtimeHelpers.mono_wasm_bindings_is_ready) bindings_init(); } catch (err: any) { @@ -570,7 +567,7 @@ export function mono_wasm_load_runtime(unused?: string, debug_level?: number): v } export function bindings_init(): void { - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: bindings_init"); + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: bindings_init"); if (runtimeHelpers.mono_wasm_bindings_is_ready) { return; } @@ -610,7 +607,8 @@ export function bindings_init(): void { function downloadResource(request: ResourceRequest): LoadingResource { if (typeof Module.downloadResource === "function") { - return Module.downloadResource(request); + const loading = Module.downloadResource(request); + if (loading) return loading; } const options: any = {}; if (request.hash) { @@ -643,7 +641,7 @@ async function start_asset_download_sources(asset: AssetEntry): Promise(); } return await start_asset_download_sources(asset); } catch (response: any) { - const isOkToFail = asset.is_optional || (asset.name.match(/\.pdb$/) && config.ignore_pdb_load_errors); + const isOkToFail = asset.isOptional || (asset.name.match(/\.pdb$/) && config.ignorePdbLoadErrors); if (!isOkToFail) { const err: any = new Error(`MONO_WASM: download '${response.url}' for ${asset.name} failed ${response.status} ${response.statusText}`); err.status = response.status; @@ -724,8 +723,8 @@ async function start_asset_download_throttle(asset: AssetEntry): Promise(); async function mono_download_assets(): Promise { - if (runtimeHelpers.diagnostic_tracing) console.debug("MONO_WASM: mono_download_assets"); - runtimeHelpers.max_parallel_downloads = runtimeHelpers.config.max_parallel_downloads || runtimeHelpers.max_parallel_downloads; + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_download_assets"); + runtimeHelpers.maxParallelDownloads = runtimeHelpers.config.maxParallelDownloads || runtimeHelpers.maxParallelDownloads; try { const download_promises: Promise[] = []; // start fetching and instantiating all assets in parallel @@ -862,7 +861,7 @@ export async function mono_wasm_load_config(configFilePath: string): Promise(ptr: T | nu } export type MonoConfig = { - isError?: false, - assembly_root?: string, // the subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script. + assemblyRootFolder?: string, // the subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script. assets?: AssetEntry[], // a list of assets to load along with the runtime. each asset is a dictionary-style Object with the following properties: /** - * 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, // Either this or debug_level needs to be set - globalization_mode?: GlobalizationMode, // configures the runtime's globalization mode - diagnostic_tracing?: boolean // enables diagnostic log messages during startup - remote_sources?: string[], // additional search locations for assets. Sources will be checked in sequential order until the asset is found. The string "./" indicates to load from the application directory (as with the files in assembly_list), and a fully-qualified URL like "https://example.com/" indicates that asset loads can be attempted from a remote server. Sources must end with a "/". - max_parallel_downloads?: number, // we are throttling parallel downloads in order to avoid net::ERR_INSUFFICIENT_RESOURCES on chrome - environment_variables?: { + debugLevel?: number, + maxParallelDownloads?: number, // we are throttling parallel downloads in order to avoid net::ERR_INSUFFICIENT_RESOURCES on chrome + globalizationMode?: GlobalizationMode, // configures the runtime's globalization mode + diagnosticTracing?: boolean // enables diagnostic log messages during startup + remoteSources?: string[], // additional search locations for assets. Sources will be checked in sequential order until the asset is found. The string "./" indicates to load from the application directory (as with the files in assembly_list), and a fully-qualified URL like "https://example.com/" indicates that asset loads can be attempted from a remote server. Sources must end with a "/". + environmentVariables?: { [i: string]: string; }, // dictionary-style Object containing environment variables - runtime_options?: string[], // array of runtime options as strings - aot_profiler_options?: AOTProfilerOptions, // dictionary-style Object. If omitted, aot profiler will not be initialized. - coverage_profiler_options?: CoverageProfilerOptions, // dictionary-style Object. If omitted, coverage profiler will not be initialized. - diagnostic_options?: DiagnosticOptions, // dictionary-style Object. If omitted, diagnostics will not be initialized. - ignore_pdb_load_errors?: boolean, - wait_for_debugger?: number + runtimeOptions?: string[], // array of runtime options as strings + aotProfilerOptions?: AOTProfilerOptions, // dictionary-style Object. If omitted, aot profiler will not be initialized. + coverageProfilerOptions?: CoverageProfilerOptions, // dictionary-style Object. If omitted, coverage profiler will not be initialized. + ignorePdbLoadErrors?: boolean, + waitForDebugger?: number }; export type MonoConfigError = { @@ -108,10 +101,10 @@ export interface ResourceRequest { // Types of assets that can be in the mono-config.js/mono-config.json file (taken from /src/tasks/WasmAppBuilder/WasmAppBuilder.cs) export interface AssetEntry extends ResourceRequest { - virtual_path?: string, // if specified, overrides the path of the asset in the virtual filesystem and similar data structures once loaded. + virtualPath?: string, // if specified, overrides the path of the asset in the virtual filesystem and similar data structures once loaded. culture?: string, - load_remote?: boolean, // if true, an attempt will be made to load the asset from each location in @args.remote_sources. - is_optional?: boolean // if true, any failure to load this asset will be ignored. + loadRemote?: boolean, // if true, an attempt will be made to load the asset from each location in @args.remoteSources. + isOptional?: boolean // if true, any failure to load this asset will be ignored. buffer?: ArrayBuffer // if provided, we don't have to fetch it pending?: LoadingResource // if provided, we don't have to start fetching it } @@ -155,11 +148,10 @@ export type RuntimeHelpers = { mono_wasm_bindings_is_ready: boolean; loaded_files: string[]; - max_parallel_downloads: number; + maxParallelDownloads: number; config: MonoConfig; - diagnostic_tracing: boolean; - enable_debugging: number; - wait_for_debugger?: number; + diagnosticTracing: boolean; + waitForDebugger?: number; fetch_like: (url: string, init?: RequestInit) => Promise; scriptDirectory?: string requirePromise: Promise @@ -178,13 +170,13 @@ export type GlobalizationMode = export type AOTProfilerOptions = { - write_at?: string, // should be in the format ::, default: 'WebAssembly.Runtime::StopProfile' - send_to?: string // should be in the format ::, default: 'WebAssembly.Runtime::DumpAotProfileData' (DumpAotProfileData stores the data into INTERNAL.aot_profile_data.) + writeAt?: string, // should be in the format ::, default: 'WebAssembly.Runtime::StopProfile' + sendTo?: string // should be in the format ::, default: 'WebAssembly.Runtime::DumpAotProfileData' (DumpAotProfileData stores the data into INTERNAL.aotProfileData.) } export type CoverageProfilerOptions = { - write_at?: string, // should be in the format ::, default: 'WebAssembly.Runtime::StopProfile' - send_to?: string // should be in the format ::, default: 'WebAssembly.Runtime::DumpCoverageProfileData' (DumpCoverageProfileData stores the data into INTERNAL.coverage_profile_data.) + writeAt?: string, // should be in the format ::, default: 'WebAssembly.Runtime::StopProfile' + sendTo?: string // should be in the format ::, default: 'WebAssembly.Runtime::DumpCoverageProfileData' (DumpCoverageProfileData stores the data into INTERNAL.coverage_profile_data.) } /// Options to configure EventPipe sessions that will be created and started at runtime startup @@ -208,7 +200,7 @@ export interface EventPipeSessionOptions { /// Options to configure the diagnostic server export type DiagnosticServerOptions = { - connect_url: string, // websocket URL to connect to. + connectUrl: string, // websocket URL to connect to. suspend: string | boolean, // if true, the server will suspend the app when it starts until a diagnostic tool tells the runtime to resume. } // how we extended emscripten Module @@ -222,9 +214,9 @@ export type DotnetModuleConfig = { onConfigLoaded?: (config: MonoConfig) => void | Promise; onDotnetReady?: () => void | Promise; - imports?: DotnetModuleConfigImports; + imports?: any; exports?: string[]; - downloadResource?: (request: ResourceRequest) => LoadingResource + downloadResource?: (request: ResourceRequest) => LoadingResource | undefined } & Partial export type DotnetModuleConfigImports = { @@ -331,8 +323,7 @@ export type EarlyExports = { binding: any, internal: any, module: any, - marshaled_exports: any, - marshaled_imports: any + marshaled_imports: any, }; export type EarlyReplacements = { fetch: any, @@ -369,18 +360,36 @@ export function notThenable(x: T | PromiseLike): x is T { /// Primarily intended for debugging purposes. export type EventPipeSessionID = bigint; -// this represents visibility in the javascript -// like https://github.com/dotnet/aspnetcore/blob/main/src/Components/Web.JS/src/Platform/Mono/MonoTypes.ts -export interface DotnetPublicAPI { - MONO: MONOType, - BINDING: BINDINGType, - INTERNAL: any, - EXPORTS: any, - IMPORTS: any, - Module: EmscriptenModule, - RuntimeId: number, - RuntimeBuildInfo: { - ProductVersion: string, - Configuration: string, - } -} \ No newline at end of file +// in all the exported internals methods, we use the same data structures for stack frame as normal full blow interop +// see src\libraries\System.Runtime.InteropServices.JavaScript\src\System\Runtime\InteropServices\JavaScript\Interop\JavaScriptExports.cs +export interface JavaScriptExports { + // the marshaled signature is: void ReleaseJSOwnedObjectByGCHandle(GCHandle gcHandle) + _release_js_owned_object_by_gc_handle(gc_handle: GCHandle): void; + // the marshaled signature is: GCHandle CreateTaskCallback() + _create_task_callback(): GCHandle; + // the marshaled signature is: void CompleteTask(GCHandle holder, Exception? exceptionResult, T? result) + _complete_task(holder_gc_handle: GCHandle, error?: any, data?: any, res_converter?: MarshalerToCs): void; + // the marshaled signature is: TRes? CallDelegate(GCHandle callback, T1? arg1, T2? arg2, T3? arg3) + _call_delegate(callback_gc_handle: GCHandle, arg1_js: any, arg2_js: any, arg3_js: any, + res_converter?: MarshalerToJs, arg1_converter?: MarshalerToCs, arg2_converter?: MarshalerToCs, arg3_converter?: MarshalerToCs): any; +} + +export type MarshalerToJs = (arg: JSMarshalerArgument, sig?: JSMarshalerType, res_converter?: MarshalerToJs, arg1_converter?: MarshalerToCs, arg2_converter?: MarshalerToCs) => any; +export type MarshalerToCs = (arg: JSMarshalerArgument, value: any, sig?: JSMarshalerType, res_converter?: MarshalerToCs, arg1_converter?: MarshalerToJs, arg2_converter?: MarshalerToJs) => void; + +export interface JSMarshalerArguments extends NativePointer { + __brand: "JSMarshalerArguments" +} + +export interface JSFunctionSignature extends NativePointer { + __brand: "JSFunctionSignatures" +} + +export interface JSMarshalerType extends NativePointer { + __brand: "JSMarshalerType" +} + +export interface JSMarshalerArgument extends NativePointer { + __brand: "JSMarshalerArgument" +} + diff --git a/src/mono/wasm/runtime/types/emscripten.ts b/src/mono/wasm/runtime/types/emscripten.ts index 1b503808774e..3c90efaac757 100644 --- a/src/mono/wasm/runtime/types/emscripten.ts +++ b/src/mono/wasm/runtime/types/emscripten.ts @@ -59,10 +59,10 @@ export declare interface EmscriptenModule { ready: Promise; instantiateWasm?: (imports: WebAssembly.Imports, successCallback: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void) => any; - preInit?: (() => any)[]; - preRun?: (() => any)[]; + preInit?: (() => any)[] | (() => any); + preRun?: (() => any)[] | (() => any); onRuntimeInitialized?: () => any; - postRun?: (() => any)[]; + postRun?: (() => any)[] | (() => any); onAbort?: { (error: any): void }; } diff --git a/src/mono/wasm/runtime/types/node.d.ts b/src/mono/wasm/runtime/types/node.d.ts index 1c3f1daa2057..e67c742c68d6 100644 --- a/src/mono/wasm/runtime/types/node.d.ts +++ b/src/mono/wasm/runtime/types/node.d.ts @@ -1,3 +1,4 @@ // only when script loaded as CJS declare const __filename: string; -declare const __dirname: string; \ No newline at end of file +declare const __dirname: string; +declare type Buffer = {} \ No newline at end of file diff --git a/src/mono/wasm/runtime/web-socket.ts b/src/mono/wasm/runtime/web-socket.ts index cfc0b303b230..ea9dc2a89228 100644 --- a/src/mono/wasm/runtime/web-socket.ts +++ b/src/mono/wasm/runtime/web-socket.ts @@ -5,9 +5,9 @@ import { prevent_timer_throttling } from "./scheduling"; import { Queue } from "./queue"; import { PromiseController, createPromiseController } from "./promise-controller"; import { mono_assert } from "./types"; -import { VoidPtr } from "./export-types"; import { Module } from "./imports"; import { setI32 } from "./memory"; +import { VoidPtr } from "./types/emscripten"; const wasm_ws_pending_send_buffer = Symbol.for("wasm ws_pending_send_buffer"); const wasm_ws_pending_send_buffer_offset = Symbol.for("wasm ws_pending_send_buffer_offset"); diff --git a/src/mono/wasm/templates/templates/browser/Program.cs b/src/mono/wasm/templates/templates/browser/Program.cs index 6596348a72cd..ecf115b0e712 100644 --- a/src/mono/wasm/templates/templates/browser/Program.cs +++ b/src/mono/wasm/templates/templates/browser/Program.cs @@ -13,6 +13,6 @@ public partial class MyClass return text; } - [JSImport("window.location.href")] + [JSImport("window.location.href", "main.js")] internal static partial string GetHRef(); } diff --git a/src/mono/wasm/templates/templates/browser/app-support.js b/src/mono/wasm/templates/templates/browser/app-support.js index 0588becc7fb9..f90ccea9134c 100644 --- a/src/mono/wasm/templates/templates/browser/app-support.js +++ b/src/mono/wasm/templates/templates/browser/app-support.js @@ -55,6 +55,9 @@ function set_exit_code(exit_code, reason) { console.error(reason); else console.error(JSON.stringify(reason)); + + if (is_browser && document.getElementById("out")) + document.getElementById("out").innerHTML = `error: ${reason}`; } if (runArgs && runArgs.forwardConsole) { @@ -79,8 +82,8 @@ function stringify_as_error_with_stack(err) { return ""; // FIXME: - if (App && App.INTERNAL) - return App.INTERNAL.mono_wasm_stringify_as_error_with_stack(err); + if (App && App.runtime && App.runtime.INTERNAL) + return App.runtime.INTERNAL.mono_wasm_stringify_as_error_with_stack(err); if (err.stack) return err.stack; @@ -142,73 +145,68 @@ function applyArguments() { } } -try { - const argsResponse = await fetch('./runArgs.json') - if (!argsResponse.ok) { - console.debug(`could not load ./runArgs.json: ${argsResponse.status}. Ignoring`); - } else { - runArgs = await argsResponse.json(); - console.debug(`runArgs: ${JSON.stringify(runArgs)}`); +App.run = async function run(main) { + try { + const argsResponse = await fetch('./runArgs.json') + if (!argsResponse.ok) { + console.debug(`could not load ./runArgs.json: ${argsResponse.status}. Ignoring`); + } else { + runArgs = await argsResponse.json(); + console.debug(`runArgs: ${JSON.stringify(runArgs)}`); + } + initRunArgs(); + applyArguments(); + + const runtime = await createDotnetRuntime(({ Module, INTERNAL }) => ({ + disableDotnet6Compatibility: true, + config: null, + configSrc: "./mono-config.json", + onConfigLoaded: (config) => { + if (!config) { + const err = new Error("Could not find ./mono-config.json. Cancelling run"); + set_exit_code(1); + throw err; + } + // Have to set env vars here to enable setting MONO_LOG_LEVEL etc. + for (let variable in runArgs.environmentVariables) { + config.environmentVariables[variable] = runArgs.environmentVariables[variable]; + } + config.diagnosticTracing = !!runArgs.diagnosticTracing; + if (!!runArgs.debugging) { + if (config.debugLevel == 0) + config.debugLevel = -1; + + config.waitForDebugger = -1; + } + }, + onDotnetReady: async () => { + let wds = Module.FS.stat(runArgs.workingDirectory); + if (wds === undefined || !Module.FS.isDir(wds.mode)) { + set_exit_code(1, `Could not find working directory ${runArgs.working_dir}`); + return; + } + + Module.FS.chdir(runArgs.workingDirectory); + + if (runArgs.runtimeArgs.length > 0) + INTERNAL.mono_wasm_set_runtime_options(runArgs.runtimeArgs); + }, + onAbort: (error) => { + set_exit_code(1, error); + }, + })); + App.runtime = runtime; + App.runArgs = runArgs; + App.main = main; + if (App.main) { + let exit_code = await App.main(runArgs.applicationArguments); + set_exit_code(exit_code ?? 0); + } + else { + set_exit_code(1, "WASM ERROR: no App.main defined"); + } } - initRunArgs(); - applyArguments(); - - createDotnetRuntime(({ MONO, INTERNAL, BINDING, IMPORTS, Module }) => ({ - disableDotnet6Compatibility: true, - config: null, - configSrc: "./mono-config.json", - onConfigLoaded: (config) => { - if (!Module.config) { - const err = new Error("Could not find ./mono-config.json. Cancelling run"); - set_exit_code(1); - throw err; - } - // Have to set env vars here to enable setting MONO_LOG_LEVEL etc. - for (let variable in runArgs.environmentVariables) { - config.environment_variables[variable] = runArgs.environmentVariables[variable]; - } - config.diagnostic_tracing = !!runArgs.diagnosticTracing; - if (!!runArgs.debugging) { - if (config.debug_level == 0) - config.debug_level = -1; - - config.wait_for_debugger = -1; - } - }, - onDotnetReady: async () => { - let wds = Module.FS.stat(runArgs.workingDirectory); - if (wds === undefined || !Module.FS.isDir(wds.mode)) { - set_exit_code(1, `Could not find working directory ${runArgs.working_dir}`); - return; - } - - Module.FS.chdir(runArgs.workingDirectory); - - if (runArgs.runtimeArgs.length > 0) - INTERNAL.mono_wasm_set_runtime_options(runArgs.runtimeArgs); - - Object.assign(App, { MONO, BINDING, IMPORTS, Module, runArgs }); - - try { - if (App.main) { - let exit_code = await App.main(runArgs.applicationArguments); - set_exit_code(exit_code ?? 0); - } - else { - set_exit_code(1, "WASM ERROR: no App.main defined"); - } - } catch (err) { - if (is_browser && document.getElementById("out")) - document.getElementById("out").innerHTML = `error: ${err}`; - set_exit_code(1, err); - } - }, - onAbort: (error) => { - set_exit_code(1, error); - }, - })); -} -catch (err) { - set_exit_code(2, err); -} - + catch (err) { + set_exit_code(2, err); + } +} \ No newline at end of file diff --git a/src/mono/wasm/templates/templates/browser/main.js b/src/mono/wasm/templates/templates/browser/main.js index 9048c9cb6129..8c199c8c3340 100644 --- a/src/mono/wasm/templates/templates/browser/main.js +++ b/src/mono/wasm/templates/templates/browser/main.js @@ -1,15 +1,18 @@ import { App } from './app-support.js' -App.main = async function (applicationArguments) { - App.IMPORTS.window = { - location: { - href: () => globalThis.window.location.href +async function main(applicationArguments) { + App.runtime.setModuleImports("main.js", { + window: { + location: { + href: () => globalThis.window.location.href + } } - }; - - const exports = await App.MONO.mono_wasm_get_assembly_exports("browser.0.dll"); + }); + const exports = await App.runtime.getAssemblyExports("browser.0.dll"); const text = exports.MyClass.Greeting(); document.getElementById("out").innerHTML = `${text}`; - await App.MONO.mono_run_main("browser.0.dll", applicationArguments); + await App.runtime.runMain("browser.0.dll", applicationArguments); } + +App.run(main); \ No newline at end of file diff --git a/src/mono/wasm/templates/templates/console/Program.cs b/src/mono/wasm/templates/templates/console/Program.cs index 39e2e566379c..953d33702172 100644 --- a/src/mono/wasm/templates/templates/console/Program.cs +++ b/src/mono/wasm/templates/templates/console/Program.cs @@ -14,6 +14,6 @@ public partial class MyClass return text; } - [JSImport("node.process.version")] + [JSImport("node.process.version", "main.mjs")] internal static partial string GetNodeVersion(); } diff --git a/src/mono/wasm/templates/templates/console/app-support.mjs b/src/mono/wasm/templates/templates/console/app-support.mjs index 573a2fc14f31..88d1505136a9 100644 --- a/src/mono/wasm/templates/templates/console/app-support.mjs +++ b/src/mono/wasm/templates/templates/console/app-support.mjs @@ -24,8 +24,8 @@ function stringify_as_error_with_stack(err) { return ""; // FIXME: - if (App && App.INTERNAL) - return App.INTERNAL.mono_wasm_stringify_as_error_with_stack(err); + if (App && App.runtime.INTERNAL) + return App.runtime.INTERNAL.mono_wasm_stringify_as_error_with_stack(err); if (err.stack) return err.stack; @@ -46,7 +46,7 @@ function set_exit_code(exit_code, reason) { console.error(JSON.stringify(reason)); } - if (App && App.INTERNAL) { + if (App && App.runtime && App.runtime.INTERNAL) { let _flush = function (_stream) { return new Promise((resolve, reject) => { _stream.on('error', (error) => reject(error)); @@ -58,10 +58,10 @@ function set_exit_code(exit_code, reason) { Promise.all([stdoutFlushed, stderrFlushed]) .then( - () => App.INTERNAL.mono_wasm_exit(exit_code), + () => App.runtime.INTERNAL.mono_wasm_exit(exit_code), reason => { console.error(`flushing std* streams failed: ${reason}`); - App.INTERNAL.mono_wasm_exit(123456); + App.runtime.INTERNAL.mono_wasm_exit(123456); }); } } @@ -94,7 +94,7 @@ function mergeArguments() { } else if (currentArg.startsWith("--runtime-arg=")) { const arg = currentArg.substring("--runtime-arg=".length); runArgs.runtimeArgs.push(arg); - } else if (currentArg == "--diagnostic_tracing") { + } else if (currentArg == "--diagnostic-tracing") { runArgs.diagnosticTracing = true; } else if (currentArg.startsWith("--working-dir=")) { const arg = currentArg.substring("--working-dir=".length); @@ -111,75 +111,72 @@ function mergeArguments() { is_debugging = runArgs.debugging === true; } - -try { +App.run = async function run(main) { try { - if (await stat('./runArgs.json')) { - const argsJson = await readFile('./runArgs.json', { encoding: "utf8" }); - runArgs = JSON.parse(argsJson); - console.debug(`runArgs: ${JSON.stringify(runArgs)}`); + try { + if (await stat('./runArgs.json')) { + const argsJson = await readFile('./runArgs.json', { encoding: "utf8" }); + runArgs = JSON.parse(argsJson); + console.debug(`runArgs: ${JSON.stringify(runArgs)}`); + } + } catch (err) { + console.debug(`could not load ./runArgs.json: ${err}. Ignoring`); + } + initRunArgs(); + mergeArguments(); + + const runtime = await createDotnetRuntime(({ Module, INTERNAL }) => ({ + disableDotnet6Compatibility: true, + config: null, + configSrc: "./mono-config.json", + onConfigLoaded: (config) => { + if (!config) { + const err = new Error("Could not find ./mono-config.json. Cancelling run"); + set_exit_code(1); + throw err; + } + // Have to set env vars here to enable setting MONO_LOG_LEVEL etc. + for (let variable in runArgs.environmentVariables) { + config.environmentVariables[variable] = runArgs.environmentVariables[variable]; + } + config.diagnosticTracing = !!runArgs.diagnosticTracing; + if (is_debugging) { + if (config.debugLevel == 0) + config.debugLevel = -1; + + config.waitForDebugger = -1; + } + }, + onDotnetReady: async () => { + let wds = Module.FS.stat(runArgs.workingDirectory); + if (wds === undefined || !Module.FS.isDir(wds.mode)) { + set_exit_code(1, `Could not find working directory ${runArgs.working_dir}`); + return; + } + + Module.FS.chdir(runArgs.workingDirectory); + + if (runArgs.runtimeArgs.length > 0) + INTERNAL.mono_wasm_set_runtime_options(runArgs.runtimeArgs); + + }, + onAbort: (error) => { + set_exit_code(1, error); + }, + })); + App.runtime = runtime; + App.runArgs = runArgs; + App.main = main; + + if (App.main) { + let exit_code = await App.main(runArgs.applicationArguments); + set_exit_code(exit_code ?? 0); + } + else { + set_exit_code(1, "WASM ERROR: no App.main defined"); } - } catch (err) { - console.debug(`could not load ./runArgs.json: ${err}. Ignoring`); } - initRunArgs(); - mergeArguments(); - - createDotnetRuntime(({ MONO, INTERNAL, BINDING, IMPORTS, Module }) => ({ - disableDotnet6Compatibility: true, - config: null, - configSrc: "./mono-config.json", - onConfigLoaded: (config) => { - if (!Module.config) { - const err = new Error("Could not find ./mono-config.json. Cancelling run"); - set_exit_code(1); - throw err; - } - // Have to set env vars here to enable setting MONO_LOG_LEVEL etc. - for (let variable in runArgs.environmentVariables) { - config.environment_variables[variable] = runArgs.environmentVariables[variable]; - } - config.diagnostic_tracing = !!runArgs.diagnosticTracing; - if (is_debugging) { - if (config.debug_level == 0) - config.debug_level = -1; - - config.wait_for_debugger = -1; - } - }, - onDotnetReady: async () => { - let wds = Module.FS.stat(runArgs.workingDirectory); - if (wds === undefined || !Module.FS.isDir(wds.mode)) { - set_exit_code(1, `Could not find working directory ${runArgs.working_dir}`); - return; - } - - Module.FS.chdir(runArgs.workingDirectory); - - if (runArgs.runtimeArgs.length > 0) - INTERNAL.mono_wasm_set_runtime_options(runArgs.runtimeArgs); - - Object.assign(App, { MONO, INTERNAL, BINDING, IMPORTS, Module, runArgs }); - - try { - if (App.main) { - let exit_code = await App.main(runArgs.applicationArguments); - set_exit_code(exit_code ?? 0); - } - else { - set_exit_code(1, "WASM ERROR: no App.main defined"); - } - } catch (err) { - if (is_browser && document.getElementById("out")) - document.getElementById("out").innerHTML = `error: ${err}`; - set_exit_code(1, err); - } - }, - onAbort: (error) => { - set_exit_code(1, error); - }, - })); -} -catch (err) { - set_exit_code(2, err); -} + catch (err) { + set_exit_code(2, err); + } +} \ No newline at end of file diff --git a/src/mono/wasm/templates/templates/console/main.mjs b/src/mono/wasm/templates/templates/console/main.mjs index 7ed16057db0e..7ff6690f5bc4 100644 --- a/src/mono/wasm/templates/templates/console/main.mjs +++ b/src/mono/wasm/templates/templates/console/main.mjs @@ -1,16 +1,19 @@ import { App } from './app-support.mjs' -App.main = async function (applicationArguments) { - - App.IMPORTS.node = { - process : { - version: () => globalThis.process.version +async function main(applicationArguments) { + App.runtime.setModuleImports("main.mjs", { + node: { + process: { + version: () => globalThis.process.version + } } - }; + }); - const exports = await App.MONO.mono_wasm_get_assembly_exports("console.0.dll"); + const exports = await App.runtime.getAssemblyExports("console.0.dll"); const text = exports.MyClass.Greeting(); console.log(text); - return await App.MONO.mono_run_main("console.0.dll", applicationArguments); + return await App.runtime.runMain("console.0.dll", applicationArguments); } + +App.run(main); \ No newline at end of file diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index d327e811252d..ac8dd0016a11 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -84,9 +84,9 @@ function set_exit_code(exit_code, reason) { } if (is_browser) { - if (App.Module) { + if (App.runtime && App.runtime.Module) { // Notify the selenium script - App.Module.exit_code = exit_code; + App.runtime.Module.exit_code = exit_code; } //Tell xharness WasmBrowserTestRunner what was the exit code @@ -112,7 +112,7 @@ function set_exit_code(exit_code, reason) { console.log("WASM EXIT " + exit_code); } - } else if (App && App.INTERNAL) { + } else if (App && App.runtime && App.runtime.INTERNAL) { if (is_node) { // NodeJS is lazy with flushing of console stream. // We need all of the output, so we force it to flush. @@ -128,13 +128,13 @@ function set_exit_code(exit_code, reason) { Promise.all([stdoutFlushed, stderrFlushed]) .then( - () => App.INTERNAL.mono_wasm_exit(exit_code), + () => App.runtime.INTERNAL.mono_wasm_exit(exit_code), reason => { console.error(`flushing std* streams failed: ${reason}`); - App.INTERNAL.mono_wasm_exit(123456); + App.runtime.INTERNAL.mono_wasm_exit(123456); }); } else { - App.INTERNAL.mono_wasm_exit(exit_code); + App.runtime.INTERNAL.mono_wasm_exit(exit_code); } } } @@ -144,8 +144,8 @@ function stringify_as_error_with_stack(err) { return ""; // FIXME: - if (App && App.INTERNAL) - return App.INTERNAL.mono_wasm_stringify_as_error_with_stack(err); + if (App && App.runtime && App.runtime.INTERNAL) + return App.runtime.INTERNAL.mono_wasm_stringify_as_error_with_stack(err); if (err.stack) return err.stack; @@ -191,7 +191,7 @@ function processQueryArguments(incomingArguments) { runArgs.runtimeArgs.push(arg); } else if (currentArg == "--disable-on-demand-gc") { runArgs.enableGC = false; - } else if (currentArg == "--diagnostic_tracing") { + } else if (currentArg == "--diagnostic-tracing") { runArgs.diagnosticTracing = true; } else if (currentArg.startsWith("--working-dir=")) { const arg = currentArg.substring("--working-dir=".length); @@ -340,95 +340,98 @@ if (typeof globalThis.crypto === 'undefined') { } } -Promise.all([argsPromise, loadDotnetPromise]).then(async ([_, createDotnetRuntime]) => { +Promise.all([argsPromise, loadDotnetPromise]).then(async ([runArgs, createDotnetRuntime]) => { applyArguments(); - return createDotnetRuntime(({ MONO, INTERNAL, BINDING, IMPORTS, EXPORTS, Module }) => ({ - disableDotnet6Compatibility: true, - config: null, - configSrc: runArgs.configSrc || "./mono-config.json", - onConfigLoaded: (config) => { - if (!Module.config) { - const err = new Error("Could not find ./mono-config.json. Cancelling run"); - set_exit_code(1); - throw err; - } - // Have to set env vars here to enable setting MONO_LOG_LEVEL etc. - for (let variable in runArgs.environmentVariables) { - config.environment_variables[variable] = runArgs.environmentVariables[variable]; - } - config.diagnostic_tracing = !!runArgs.diagnosticTracing; - if (!!runArgs.debugging) { - if (config.debug_level == 0) - config.debug_level = -1; - - config.wait_for_debugger = -1; - } - - if (is_node) { - // we may have dependencies on NPM packages, depending on the test case - // some of them polyfill for browser built-in stuff - const modulesToLoad = runArgs.environmentVariables["NPM_MODULES"]; - if (modulesToLoad) { - modulesToLoad.split(',').forEach(module => { - const { 0: moduleName, 1: globalAlias } = module.split(':'); - - let message = `Loading npm '${moduleName}'`; - let moduleExport = INTERNAL.require(moduleName); - - if (globalAlias) { - message += ` and attaching to global as '${globalAlias}'`; - globalThis[globalAlias] = moduleExport; - } else if (moduleName == "node-fetch") { - message += ' and attaching to global'; - globalThis.fetch = moduleExport.default; - globalThis.Headers = moduleExport.Headers; - globalThis.Request = moduleExport.Request; - globalThis.Response = moduleExport.Response; - } else if (moduleName == "node-abort-controller") { - message += ' and attaching to global'; - globalThis.AbortController = moduleExport.AbortController; - } - - console.log(message); - }); + const runtime = await createDotnetRuntime(({ INTERNAL, Module }) => { + return ({ + disableDotnet6Compatibility: true, + config: null, + configSrc: runArgs.configSrc || "./mono-config.json", + onConfigLoaded: (config) => { + if (!config) { + const err = new Error("Could not find ./mono-config.json. Cancelling run"); + set_exit_code(1); + throw err; } - } + // Have to set env vars here to enable setting MONO_LOG_LEVEL etc. + for (let variable in runArgs.environmentVariables) { + config.environmentVariables[variable] = runArgs.environmentVariables[variable]; + } + config.diagnosticTracing = !!runArgs.diagnosticTracing; + if (!!runArgs.debugging) { + if (config.debugLevel == 0) + config.debugLevel = -1; - // Must be after loading npm modules. - config.environment_variables["IsWebSocketSupported"] = ("WebSocket" in globalThis).toString().toLowerCase(); - }, - preRun: () => { - if (!runArgs.enableGC) { - INTERNAL.mono_wasm_enable_on_demand_gc(0); - } - }, - onDotnetReady: () => { - let wds = Module.FS.stat(runArgs.workingDirectory); - if (wds === undefined || !Module.FS.isDir(wds.mode)) { - set_exit_code(1, `Could not find working directory ${runArgs.workingDirectory}`); - return; - } + config.waitForDebugger = -1; + } - Module.FS.chdir(runArgs.workingDirectory); + if (is_node) { + // we may have dependencies on NPM packages, depending on the test case + // some of them polyfill for browser built-in stuff + const modulesToLoad = runArgs.environmentVariables["NPM_MODULES"]; + if (modulesToLoad) { + modulesToLoad.split(',').forEach(module => { + const { 0: moduleName, 1: globalAlias } = module.split(':'); + + let message = `Loading npm '${moduleName}'`; + let moduleExport = INTERNAL.require(moduleName); + + if (globalAlias) { + message += ` and attaching to global as '${globalAlias}'`; + globalThis[globalAlias] = moduleExport; + } else if (moduleName == "node-fetch") { + message += ' and attaching to global'; + globalThis.fetch = moduleExport.default; + globalThis.Headers = moduleExport.Headers; + globalThis.Request = moduleExport.Request; + globalThis.Response = moduleExport.Response; + } else if (moduleName == "node-abort-controller") { + message += ' and attaching to global'; + globalThis.AbortController = moduleExport.AbortController; + } + + console.log(message); + }); + } + } + + // Must be after loading npm modules. + config.environmentVariables["IsWebSocketSupported"] = ("WebSocket" in globalThis).toString().toLowerCase(); + }, + preRun: () => { + if (!runArgs.enableGC) { + INTERNAL.mono_wasm_enable_on_demand_gc(0); + } + }, + onDotnetReady: () => { + let wds = Module.FS.stat(runArgs.workingDirectory); + if (wds === undefined || !Module.FS.isDir(wds.mode)) { + set_exit_code(1, `Could not find working directory ${runArgs.workingDirectory}`); + return; + } + + Module.FS.chdir(runArgs.workingDirectory); + }, + onAbort: (error) => { + set_exit_code(1, stringify_as_error_with_stack(new Error())); + }, + }) + }); + App.runtime = runtime + App.runArgs = runArgs + App.init(); - App.init({ MONO, INTERNAL, BINDING, IMPORTS, EXPORTS, Module, runArgs }); - }, - onAbort: (error) => { - set_exit_code(1, stringify_as_error_with_stack(new Error())); - }, - })); }).catch(function (err) { set_exit_code(1, "failed to load the dotnet.js file.\n" + stringify_as_error_with_stack(err)); }); const App = { - init: async function ({ MONO, INTERNAL, BINDING, IMPORTS, EXPORTS, Module, runArgs }) { - Object.assign(App, { MONO, INTERNAL, BINDING, IMPORTS, EXPORTS, Module, runArgs }); + init: async function () { console.info("Initializing....."); for (let i = 0; i < runArgs.profilers.length; ++i) { - const init = Module.cwrap('mono_wasm_load_profiler_' + runArgs.profilers[i], 'void', ['string']); + const init = App.runtime.Module.cwrap('mono_wasm_load_profiler_' + runArgs.profilers[i], 'void', ['string']); init(""); } @@ -438,7 +441,7 @@ const App = { } if (runArgs.applicationArguments[0] == "--regression") { - const exec_regression = Module.cwrap('mono_wasm_exec_regression', 'number', ['number', 'string']); + const exec_regression = App.runtime.Module.cwrap('mono_wasm_exec_regression', 'number', ['number', 'string']); let res = 0; try { @@ -457,7 +460,7 @@ const App = { } if (runArgs.runtimeArgs.length > 0) - INTERNAL.mono_wasm_set_runtime_options(runArgs.runtimeArgs); + App.runtime.INTERNAL.mono_wasm_set_runtime_options(runArgs.runtimeArgs); if (runArgs.applicationArguments[0] == "--run") { // Run an exe @@ -468,7 +471,7 @@ const App = { try { const main_assembly_name = runArgs.applicationArguments[1]; const app_args = runArgs.applicationArguments.slice(2); - const result = await App.MONO.mono_run_main(main_assembly_name, app_args); + const result = await App.runtime.runMain(main_assembly_name, app_args); set_exit_code(result); } catch (error) { if (error.name != "ExitStatus") { @@ -480,7 +483,7 @@ const App = { } }, - /** Runs a particular test + /** Runs a particular test in legacy interop tests * @type {(method_name: string, args: any[]=, signature: any=) => return number} */ call_test_method: function (method_name, args, signature) { @@ -490,7 +493,7 @@ const App = { const fqn = "[System.Private.Runtime.InteropServices.JavaScript.Tests]System.Runtime.InteropServices.JavaScript.Tests.HelperMarshal:" + method_name; try { - const method = App.BINDING.bind_static_method(fqn, signature); + const method = App.runtime.BINDING.bind_static_method(fqn, signature); return method.apply(null, args || []); } catch (exc) { console.error("exception thrown in", fqn); @@ -504,16 +507,12 @@ const App = { args.push("MONO"); args.push("BINDING"); args.push("INTERNAL"); - args.push("IMPORTS"); - args.push("EXPORTS"); const userFunction = new Function(...args, code); return function (...args) { - args[arg_count + 0] = globalThis.App.MONO; - args[arg_count + 1] = globalThis.App.BINDING; - args[arg_count + 2] = globalThis.App.INTERNAL; - args[arg_count + 3] = globalThis.App.IMPORTS; - args[arg_count + 4] = globalThis.App.EXPORTS; + args[arg_count + 0] = globalThis.App.runtime.MONO; + args[arg_count + 1] = globalThis.App.runtime.BINDING; + args[arg_count + 2] = globalThis.App.runtime.INTERNAL; return userFunction(...args); }; }, @@ -521,7 +520,7 @@ const App = { const closedEval = function (Module, MONO, BINDING, INTERNAL, code) { return eval(code); }; - const res = closedEval(globalThis.App.Module, globalThis.App.MONO, globalThis.App.BINDING, globalThis.App.INTERNAL, js_code); + const res = closedEval(globalThis.App.runtime.Module, globalThis.App.runtime.MONO, globalThis.App.runtime.BINDING, globalThis.App.runtime.INTERNAL, js_code); return (res === undefined || res === null || typeof res === "string") ? null : res.toString(); diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 8af7a20ed70b..5d7f1facca07 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -291,6 +291,7 @@ + Exclude="$(MonoProjectRoot)wasm/runtime/dotnet.d.ts;$(MonoProjectRoot)wasm/runtime/dotnet-legacy.d.ts;$(MonoProjectRoot)wasm/runtime/diagnostics-mock.d.ts;$(MonoProjectRoot)wasm/runtime/node_modules/**/*.ts" /> <_RollupInputs Include="$(MonoProjectRoot)wasm/runtime/**/tsconfig.*" Exclude="$(MonoProjectRoot)wasm/runtime/node_modules/**/tsconfig.*" /> <_RollupInputs Include="$(MonoProjectRoot)wasm/runtime/workers/**/*.js"/> diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs index 38cf0e1a2e7f..de25059d66d0 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs @@ -54,7 +54,7 @@ public class WasmAppBuilder : Task // - Value: can be a number, bool, quoted string, or json string // // Examples: - // + // // // // @@ -73,13 +73,13 @@ public class WasmAppBuilder : Task private sealed class WasmAppConfig { - [JsonPropertyName("assembly_root")] + [JsonPropertyName("assemblyRootFolder")] public string AssemblyRoot { get; set; } = "managed"; - [JsonPropertyName("debug_level")] + [JsonPropertyName("debugLevel")] public int DebugLevel { get; set; } = 0; [JsonPropertyName("assets")] public List Assets { get; } = new List(); - [JsonPropertyName("remote_sources")] + [JsonPropertyName("remoteSources")] public List RemoteSources { get; set; } = new List(); [JsonExtensionData] public Dictionary Extra { get; set; } = new(); @@ -117,14 +117,14 @@ public class WasmAppBuilder : Task private sealed class VfsEntry : AssetEntry { public VfsEntry(string name) : base(name, "vfs") {} - [JsonPropertyName("virtual_path")] + [JsonPropertyName("virtualPath")] public string? VirtualPath { get; set; } } private sealed class IcuData : AssetEntry { public IcuData(string name) : base(name, "icu") {} - [JsonPropertyName("load_remote")] + [JsonPropertyName("loadRemote")] public bool LoadRemote { get; set; } } diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/main.js b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/main.js index 1fa6a59663c5..6098f1cd960a 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/main.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/main.js @@ -13,7 +13,7 @@ try { const { BINDING } = await createDotnetRuntime(({ MONO }) => ({ configSrc: "./mono-config.json", onConfigLoaded: () => { - MONO.config.environment_variables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug"; + MONO.config.environmentVariables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug"; }, })); const testMeaning = BINDING.bind_static_method("[WebAssembly.Browser.HotReload.Test] Sample.Test:TestMeaning");