diff --git a/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs b/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs index 000dd103d2189..23067f81ea601 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs @@ -64,7 +64,11 @@ internal static unsafe partial class Runtime [MethodImpl(MethodImplOptions.InternalCall)] public static extern void CancelPromise(nint gcHandle); #endif - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern void SetEntryAssembly(Assembly assembly, int entryPointMetadataToken); + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern void AssemblyGetEntryPoint(IntPtr assemblyNamePtr, int auto_insert_breakpoint, void** monoMethodPtrPtr); + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern void BindAssemblyExports(IntPtr assemblyNamePtr); + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern void GetAssemblyExport(IntPtr assemblyNamePtr, IntPtr namespacePtr, IntPtr classnamePtr, IntPtr methodNamePtr, IntPtr* monoMethodPtrPtr); } } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/Resources/Strings.resx b/src/libraries/System.Runtime.InteropServices.JavaScript/src/Resources/Strings.resx index e77e419997996..9cb71cc66223a 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/Resources/Strings.resx +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/Resources/Strings.resx @@ -138,8 +138,8 @@ Managed entrypoint handle is not set. - - Cannot resolve managed entrypoint {0} in assembly {1}. + + Cannot resolve managed entrypoint handle. Return type '{0}' from main method in not supported. 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 9ec4a2400cd21..b244d69abdfb5 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 @@ -15,7 +15,7 @@ namespace System.Runtime.InteropServices.JavaScript internal static unsafe partial class JavaScriptExports { // the marshaled signature is: - // Task? CallEntrypoint(string mainAssemblyName, string[] args, bool waitForDebugger) + // Task? CallEntrypoint(char* assemblyNamePtr, string[] args) public static void CallEntrypoint(JSMarshalerArgument* arguments_buffer) { ref JSMarshalerArgument arg_exc = ref arguments_buffer[0]; // initialized by caller in alloc_stack_frame() @@ -30,11 +30,11 @@ public static void CallEntrypoint(JSMarshalerArgument* arguments_buffer) arg_exc.AssertCurrentThreadContext(); #endif - arg_1.ToManaged(out string? mainAssemblyName); + arg_1.ToManaged(out IntPtr assemblyNamePtr); arg_2.ToManaged(out string?[]? args); arg_3.ToManaged(out bool waitForDebugger); - Task? result = JSHostImplementation.CallEntrypoint(mainAssemblyName, args, waitForDebugger); + Task? result = JSHostImplementation.CallEntrypoint(assemblyNamePtr, args, waitForDebugger); arg_result.ToJS(result, (ref JSMarshalerArgument arg, int value) => { diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSHostImplementation.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSHostImplementation.cs index 7268951b68828..27a6d54886892 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSHostImplementation.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSHostImplementation.cs @@ -200,47 +200,19 @@ public static void LoadSatelliteAssembly(byte[] dllBytes) AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(dllBytes)); } - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Dynamic access from JavaScript")] - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Dynamic access from JavaScript")] - public static Task? CallEntrypoint(string? assemblyName, string?[]? args, bool waitForDebugger) + public static unsafe Task? CallEntrypoint(IntPtr assemblyNamePtr, string?[]? args, bool waitForDebugger) { try { - if (string.IsNullOrEmpty(assemblyName)) - { - throw new MissingMethodException(SR.MissingManagedEntrypointHandle); - } - if (!assemblyName.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase)) - { - assemblyName += ".dll"; - } - Assembly mainAssembly = Assembly.LoadFrom(assemblyName); - - MethodInfo? method = mainAssembly.EntryPoint; + void* ptr; + Interop.Runtime.AssemblyGetEntryPoint(assemblyNamePtr, waitForDebugger ? 1 : 0, &ptr); + RuntimeMethodHandle methodHandle = GetMethodHandleFromIntPtr((IntPtr)ptr); + // this would not work for generic types. But Main() could not be generic, so we are fine. + MethodInfo? method = MethodBase.GetMethodFromHandle(methodHandle) as MethodInfo; if (method == null) { - throw new InvalidOperationException(string.Format(SR.CannotResolveManagedEntrypoint, "Main", assemblyName)); + throw new InvalidOperationException(SR.CannotResolveManagedEntrypointHandle); } - if (method.IsSpecialName) - { - // we are looking for the original async method, rather than for the compiler generated wrapper like
- // because we need to yield to browser event loop - var type = method.DeclaringType!; - var name = method.Name; - var asyncName = name + "$"; - method = type.GetMethod(asyncName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); - if (method == null) - { - asyncName = name.Substring(1, name.Length - 2); - method = type.GetMethod(asyncName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); - } - if (method == null) - { - throw new InvalidOperationException(string.Format(SR.CannotResolveManagedEntrypoint, asyncName, assemblyName)); - } - } - - Interop.Runtime.SetEntryAssembly(mainAssembly, waitForDebugger ? method.MetadataToken : 0); object[] argsToPass = System.Array.Empty(); Task? result = null; @@ -293,75 +265,32 @@ public static void LoadSatelliteAssembly(byte[] dllBytes) } } - private static string GeneratedInitializerClassName = "System.Runtime.InteropServices.JavaScript.__GeneratedInitializer"; - private static string GeneratedInitializerMethodName = "__Register_"; - - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Dynamic access from JavaScript")] - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Dynamic access from JavaScript")] - public static Task BindAssemblyExports(string? assemblyName) + public static unsafe Task BindAssemblyExports(string? assemblyName) { - try - { - if (string.IsNullOrEmpty(assemblyName)) - { - throw new MissingMethodException("Missing assembly name"); - } - if (!assemblyName.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase)) - { - assemblyName += ".dll"; - } - - Assembly assembly = Assembly.LoadFrom(assemblyName); - Type? type = assembly.GetType(GeneratedInitializerClassName); - if (type == null) - { - foreach (var module in assembly.Modules) - { - RuntimeHelpers.RunModuleConstructor(module.ModuleHandle); - } - } - else - { - MethodInfo? methodInfo = type.GetMethod(GeneratedInitializerMethodName, BindingFlags.NonPublic | BindingFlags.Static); - methodInfo?.Invoke(null, []); - } - - return Task.CompletedTask; - } - catch (Exception ex) - { - if (ex is TargetInvocationException refEx && refEx.InnerException != null) - ex = refEx.InnerException; - return Task.FromException(ex); - } + Interop.Runtime.BindAssemblyExports(Marshal.StringToCoTaskMemUTF8(assemblyName)); + return Task.CompletedTask; } - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "TODO https://github.com/dotnet/runtime/issues/98366")] - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "TODO https://github.com/dotnet/runtime/issues/98366")] public static unsafe JSFunctionBinding BindManagedFunction(string fullyQualifiedName, int signatureHash, ReadOnlySpan signatures) { - if (string.IsNullOrEmpty(fullyQualifiedName)) - { - throw new ArgumentNullException(nameof(fullyQualifiedName)); - } + var (assemblyName, nameSpace, shortClassName, methodName) = ParseFQN(fullyQualifiedName); + var wrapper_name = $"__Wrapper_{methodName}_{signatureHash}"; + var dllName = assemblyName + ".dll"; - var signature = GetMethodSignature(signatures, null, null); - var (assemblyName, className, nameSpace, shortClassName, methodName) = ParseFQN(fullyQualifiedName); + IntPtr monoMethod; + Interop.Runtime.GetAssemblyExport( + Marshal.StringToCoTaskMemUTF8(dllName), + Marshal.StringToCoTaskMemUTF8(nameSpace), + Marshal.StringToCoTaskMemUTF8(shortClassName), + Marshal.StringToCoTaskMemUTF8(wrapper_name), + &monoMethod); - Assembly assembly = Assembly.LoadFrom(assemblyName + ".dll"); - Type? type = assembly.GetType(className); - if (type == null) + if (monoMethod == IntPtr.Zero) { - throw new InvalidOperationException("Class not found " + className); - } - var wrapper_name = $"__Wrapper_{methodName}_{signatureHash}"; - var methodInfo = type.GetMethod(wrapper_name, BindingFlags.NonPublic | BindingFlags.Static); - if (methodInfo == null) - { - throw new InvalidOperationException("Method not found " + wrapper_name); + Environment.FailFast($"Can't find {nameSpace}{shortClassName}{methodName} in {assemblyName}.dll"); } - var monoMethod = GetIntPtrFromMethodHandle(methodInfo.MethodHandle); + var signature = GetMethodSignature(signatures, null, null); JavaScriptImports.BindCSFunction(monoMethod, assemblyName, nameSpace, shortClassName, methodName, signatureHash, (IntPtr)signature.Header); @@ -381,14 +310,13 @@ public static void SetHasExternalEventLoop(Thread thread) #endif [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IntPtr GetIntPtrFromMethodHandle(RuntimeMethodHandle methodHandle) + public static RuntimeMethodHandle GetMethodHandleFromIntPtr(IntPtr ptr) { - var temp = new IntPtrAndHandle { methodHandle = methodHandle }; - return temp.ptr; + var temp = new IntPtrAndHandle { ptr = ptr }; + return temp.methodHandle; } - - public static (string assemblyName, string className, string nameSpace, string shortClassName, string methodName) ParseFQN(string fqn) + public static (string assemblyName, string nameSpace, string shortClassName, string methodName) ParseFQN(string fqn) { var assembly = fqn.Substring(fqn.IndexOf('[') + 1, fqn.IndexOf(']') - 1).Trim(); fqn = fqn.Substring(fqn.IndexOf(']') + 1).Trim(); @@ -410,7 +338,7 @@ public static (string assemblyName, string className, string nameSpace, string s throw new InvalidOperationException("No class name specified " + fqn); if (string.IsNullOrEmpty(methodName)) throw new InvalidOperationException("No method name specified " + fqn); - return (assembly, className, nameSpace, shortClassName, methodName); + return (assembly, nameSpace, shortClassName, methodName); } } } diff --git a/src/mono/browser/debugger/tests/debugger-test/debugger-main.js b/src/mono/browser/debugger/tests/debugger-test/debugger-main.js index 58688dfc8a470..f245ff64a33a2 100644 --- a/src/mono/browser/debugger/tests/debugger-test/debugger-main.js +++ b/src/mono/browser/debugger/tests/debugger-test/debugger-main.js @@ -44,7 +44,7 @@ try { try { const monoMethodPtr = App.exports.DebuggerTests.BindStaticMethod.GetMonoMethodPtr(method_name); // this is only implemented for void methods with no arguments - const invoker = runtime.Module.cwrap("mono_wasm_invoke_method", "number", ["number", "number", "number"]); + const invoker = runtime.Module.cwrap("mono_wasm_invoke_method", "void", ["number", "number"]); return function () { try { return invoker(monoMethodPtr, 0, 0); diff --git a/src/mono/browser/runtime/corebindings.c b/src/mono/browser/runtime/corebindings.c index 68e8c6c709766..978e7fd403830 100644 --- a/src/mono/browser/runtime/corebindings.c +++ b/src/mono/browser/runtime/corebindings.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "wasm-config.h" @@ -24,10 +25,15 @@ extern void mono_wasm_resolve_or_reject_promise (void *data); extern void mono_wasm_cancel_promise (int task_holder_gc_handle); extern void mono_wasm_console_clear (); extern void mono_wasm_set_entrypoint_breakpoint (int entry_point_metadata_token); +extern void mono_wasm_trace_logger (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data); + +extern int mono_runtime_run_module_cctor (MonoImage *image, MonoError *error); typedef void (*background_job_cb)(void); -void mono_wasm_set_entry_assembly (MonoReflectionAssembly* ref_assembly, int entry_point_metadata_token); +void mono_wasm_bind_assembly_exports (char *assembly_name); +void mono_wasm_assembly_get_entry_point (char *assembly_name, int auto_insert_breakpoint, MonoMethod **method_out); +void mono_wasm_get_assembly_export (char *assembly_name, char *namespace, char *classname, char *methodname, MonoMethod **method_out); #ifndef DISABLE_THREADS void mono_wasm_release_cs_owned_object_post (pthread_t target_tid, int js_handle); @@ -84,7 +90,9 @@ void bindings_initialize_internals (void) mono_add_internal_call ("Interop/Runtime::InvokeJSFunctionSend", mono_wasm_invoke_js_function_send); mono_add_internal_call ("Interop/Runtime::CancelPromise", mono_wasm_cancel_promise); mono_add_internal_call ("Interop/Runtime::CancelPromisePost", mono_wasm_cancel_promise_post); - mono_add_internal_call ("Interop/Runtime::SetEntryAssembly", mono_wasm_set_entry_assembly); + mono_add_internal_call ("Interop/Runtime::AssemblyGetEntryPoint", mono_wasm_assembly_get_entry_point); + mono_add_internal_call ("Interop/Runtime::BindAssemblyExports", mono_wasm_bind_assembly_exports); + mono_add_internal_call ("Interop/Runtime::GetAssemblyExport", mono_wasm_get_assembly_export); #else mono_add_internal_call ("Interop/Runtime::ReleaseCSOwnedObject", mono_wasm_release_cs_owned_object); mono_add_internal_call ("Interop/Runtime::ResolveOrRejectPromise", mono_wasm_resolve_or_reject_promise); @@ -92,7 +100,9 @@ void bindings_initialize_internals (void) mono_add_internal_call ("Interop/Runtime::InvokeJSImport", mono_wasm_invoke_js_import); mono_add_internal_call ("Interop/Runtime::InvokeJSFunction", mono_wasm_invoke_js_function); mono_add_internal_call ("Interop/Runtime::CancelPromise", mono_wasm_cancel_promise); - mono_add_internal_call ("Interop/Runtime::SetEntryAssembly", mono_wasm_set_entry_assembly); + mono_add_internal_call ("Interop/Runtime::AssemblyGetEntryPoint", mono_wasm_assembly_get_entry_point); + mono_add_internal_call ("Interop/Runtime::BindAssemblyExports", mono_wasm_bind_assembly_exports); + mono_add_internal_call ("Interop/Runtime::GetAssemblyExport", mono_wasm_get_assembly_export); #endif /* DISABLE_THREADS */ mono_add_internal_call ("Interop/JsGlobalization::ChangeCaseInvariant", mono_wasm_change_case_invariant); @@ -108,14 +118,145 @@ void bindings_initialize_internals (void) mono_add_internal_call ("System.ConsolePal::Clear", mono_wasm_console_clear); } -void mono_wasm_set_entry_assembly (MonoReflectionAssembly* ref_assembly, int entry_point_metadata_token) +static MonoAssembly* _mono_wasm_assembly_load (char *assembly_name) +{ + assert (assembly_name); + MonoImageOpenStatus status; + MonoAssemblyName* aname = mono_assembly_name_new (assembly_name); + assert (aname); + + MonoAssembly *res = mono_assembly_load (aname, NULL, &status); + mono_assembly_name_free (aname); + free (assembly_name); + + return res; +} + +void mono_wasm_assembly_get_entry_point (char *assembly_name, int auto_insert_breakpoint, MonoMethod **method_out) { - MonoAssembly *assembly = mono_reflection_assembly_get_assembly (ref_assembly); + assert (assembly_name); + *method_out = NULL; + MonoAssembly* assembly = _mono_wasm_assembly_load (assembly_name); + if(!assembly) + goto end; + + MonoImage *image; + MonoMethod *method = NULL; + + image = mono_assembly_get_image (assembly); + uint32_t entry = mono_image_get_entry_point (image); + if (!entry) + goto end; + mono_domain_ensure_entry_assembly (mono_get_root_domain (), assembly); - if (entry_point_metadata_token != 0) + method = mono_get_method (image, entry, NULL); + + /* + * If the entry point looks like a compiler generated wrapper around + * an async method in the form "" then try to look up the async methods + * "$" and "Name" it could be wrapping. We do this because the generated + * sync wrapper will call task.GetAwaiter().GetResult() when we actually want + * to yield to the host runtime. + */ + if (mono_method_get_flags (method, NULL) & 0x0800 /* METHOD_ATTRIBUTE_SPECIAL_NAME */) { + const char *name = mono_method_get_name (method); + int name_length = strlen (name); + + if ((*name != '<') || (name [name_length - 1] != '>')) + goto end; + + MonoClass *klass = mono_method_get_class (method); + assert(klass); + char *async_name = malloc (name_length + 2); + snprintf (async_name, name_length + 2, "%s$", name); + + // look for "$" + MonoMethodSignature *sig = mono_method_get_signature (method, image, mono_method_get_token (method)); + MonoMethod *async_method = mono_class_get_method_from_name (klass, async_name, mono_signature_get_param_count (sig)); + if (async_method != NULL) { + free (async_name); + method = async_method; + goto end; + } + + // look for "Name" by trimming the first and last character of "" + async_name [name_length - 1] = '\0'; + async_method = mono_class_get_method_from_name (klass, async_name + 1, mono_signature_get_param_count (sig)); + + free (async_name); + if (async_method != NULL) + method = async_method; + } + +end: + if (auto_insert_breakpoint && method) { - mono_wasm_set_entrypoint_breakpoint (entry_point_metadata_token); + mono_wasm_set_entrypoint_breakpoint(mono_method_get_token (method)); + } + *method_out = method; +} + +void mono_wasm_bind_assembly_exports (char *assembly_name) +{ + MonoError error; + MonoAssembly* assembly; + MonoImage *image; + MonoClass *klass; + MonoMethod *method; + PVOLATILE(MonoObject) temp_exc = NULL; + + assert (assembly_name); + assembly = _mono_wasm_assembly_load (assembly_name); + assert (assembly); + image = mono_assembly_get_image (assembly); + assert (image); + + klass = mono_class_from_name (image, "System.Runtime.InteropServices.JavaScript", "__GeneratedInitializer"); + if (klass) { + method = mono_class_get_method_from_name (klass, "__Register_", -1); + if (method) { + mono_runtime_invoke (method, NULL, NULL, (MonoObject **)&temp_exc); + if (temp_exc) { + PVOLATILE(MonoObject) exc2 = NULL; + store_volatile((MonoObject**)&temp_exc, (MonoObject*)mono_object_to_string ((MonoObject*)temp_exc, (MonoObject **)&exc2)); + if (exc2) { + mono_wasm_trace_logger ("jsinterop", "critical", "mono_wasm_bind_assembly_exports unexpected double fault", 1, NULL); + } else { + mono_wasm_trace_logger ("jsinterop", "critical", mono_string_to_utf8((MonoString*)temp_exc), 1, NULL); + } + abort (); + } + } } + else if (!mono_runtime_run_module_cctor(image, &error)) { + //g_print ("Failed to run module constructor due to %s\n", mono_error_get_message (error)); + } +} + +void mono_wasm_get_assembly_export (char *assembly_name, char *namespace, char *classname, char *methodname, MonoMethod **method_out) +{ + MonoError error; + MonoAssembly* assembly; + MonoImage *image; + MonoClass *klass; + MonoMethod *method=NULL; + *method_out = NULL; + + assert (assembly_name); + assembly = _mono_wasm_assembly_load (assembly_name); + assert (assembly); + image = mono_assembly_get_image (assembly); + assert (image); + + klass = mono_class_from_name (image, namespace, classname); + assert (klass); + method = mono_class_get_method_from_name (klass, methodname, -1); + assert (method); + + *method_out = method; + free (namespace); + free (classname); + free (methodname); } #ifndef DISABLE_THREADS diff --git a/src/mono/browser/runtime/driver.c b/src/mono/browser/runtime/driver.c index 3f47245a71efa..a9db7956feda4 100644 --- a/src/mono/browser/runtime/driver.c +++ b/src/mono/browser/runtime/driver.c @@ -242,7 +242,7 @@ mono_wasm_invoke_method (MonoMethod *method, void* args) // so, if that happens, we should abort the runtime if (temp_exc) { PVOLATILE(MonoObject) exc2 = NULL; - store_volatile((MonoObject**)temp_exc, (MonoObject*)mono_object_to_string ((MonoObject*)temp_exc, (MonoObject **)&exc2)); + store_volatile((MonoObject**)&temp_exc, (MonoObject*)mono_object_to_string ((MonoObject*)temp_exc, (MonoObject **)&exc2)); if (exc2) { mono_wasm_trace_logger ("jsinterop", "critical", "mono_wasm_invoke_method unexpected double fault", 1, NULL); } else { diff --git a/src/mono/browser/runtime/invoke-cs.ts b/src/mono/browser/runtime/invoke-cs.ts index 1b0338180ebff..5127ee0a4f3a4 100644 --- a/src/mono/browser/runtime/invoke-cs.ts +++ b/src/mono/browser/runtime/invoke-cs.ts @@ -11,19 +11,16 @@ import { get_sig, get_signature_argument_count, bound_cs_function_symbol, get_signature_version, alloc_stack_frame, get_signature_type, } from "./marshal"; -import { MonoMethod, JSFunctionSignature, BoundMarshalerToCs, BoundMarshalerToJs, MarshalerType, MonoAssembly } from "./types/internal"; -import cwraps from "./cwraps"; +import { MonoMethod, JSFunctionSignature, BoundMarshalerToCs, BoundMarshalerToJs, MarshalerType } from "./types/internal"; import { assert_js_interop } from "./invoke-js"; import { startMeasure, MeasuredBlock, endMeasure } from "./profiler"; import { bind_assembly_exports, invoke_sync_method } from "./managed-exports"; import { mono_log_debug } from "./logging"; -const _assembly_cache_by_name = new Map(); - export function mono_wasm_bind_cs_function(method: MonoMethod, assemblyName: string, namespaceName: string, shortClassName: string, methodName: string, signatureHash: number, signature: JSFunctionSignature): void { const fullyQualifiedName = `[${assemblyName}] ${namespaceName}.${shortClassName}:${methodName}`; const mark = startMeasure(); - mono_log_debug(`Binding [JSExport] ${assemblyName}.${shortClassName} from ${assemblyName} assembly`); + mono_log_debug(`Binding [JSExport] ${namespaceName}.${shortClassName}:${methodName} from ${assemblyName} assembly`); const version = get_signature_version(signature); mono_assert(version === 2, () => `Signature version ${version} mismatch.`); @@ -357,12 +354,3 @@ export async function mono_wasm_get_assembly_exports(assembly: string): Promise< return exportsByAssembly.get(assembly) || {}; } - -export function assembly_load(name: string): MonoAssembly { - if (_assembly_cache_by_name.has(name)) - return _assembly_cache_by_name.get(name); - - const result = cwraps.mono_wasm_assembly_load(name); - _assembly_cache_by_name.set(name, result); - return result; -} \ No newline at end of file diff --git a/src/mono/browser/runtime/managed-exports.ts b/src/mono/browser/runtime/managed-exports.ts index 9a140ac0f6c70..b41febf9c649f 100644 --- a/src/mono/browser/runtime/managed-exports.ts +++ b/src/mono/browser/runtime/managed-exports.ts @@ -7,12 +7,13 @@ import { GCHandle, GCHandleNull, JSMarshalerArguments, MarshalerToCs, MarshalerT import cwraps from "./cwraps"; import { runtimeHelpers, Module, loaderHelpers, mono_assert } from "./globals"; import { JavaScriptMarshalerArgSize, alloc_stack_frame, get_arg, get_arg_gc_handle, is_args_exception, set_arg_intptr, set_arg_type, set_gc_handle } from "./marshal"; -import { marshal_array_to_cs, marshal_array_to_cs_impl, marshal_bool_to_cs, marshal_exception_to_cs, marshal_string_to_cs } from "./marshal-to-cs"; +import { marshal_array_to_cs, marshal_array_to_cs_impl, marshal_bool_to_cs, marshal_exception_to_cs, marshal_intptr_to_cs, marshal_string_to_cs } from "./marshal-to-cs"; import { marshal_int32_to_js, end_marshal_task_to_js, marshal_string_to_js, begin_marshal_task_to_js, marshal_exception_to_js } from "./marshal-to-js"; import { do_not_force_dispose } from "./gc-handles"; import { assert_c_interop, assert_js_interop } from "./invoke-js"; import { mono_wasm_main_thread_ptr } from "./pthreads/shared"; import { _zero_region } from "./memory"; +import { stringToUTF8Ptr } from "./strings"; const managedExports: ManagedExports = {} as any; @@ -41,7 +42,7 @@ export function init_managed_exports(): void { managedExports.LoadLazyAssembly = get_method("LoadLazyAssembly"); } -// the marshaled signature is: Task? CallEntrypoint(string mainAssemblyName, string[] args) +// the marshaled signature is: Task? CallEntrypoint(char* mainAssemblyName, string[] args) export function call_entry_point(main_assembly_name: string, program_args: string[] | undefined, waitForDebugger: boolean): Promise { loaderHelpers.assert_runtime_running(); const sp = Module.stackSave(); @@ -51,7 +52,8 @@ export function call_entry_point(main_assembly_name: string, program_args: strin const arg1 = get_arg(args, 2); const arg2 = get_arg(args, 3); const arg3 = get_arg(args, 4); - marshal_string_to_cs(arg1, main_assembly_name); + const main_assembly_name_ptr = stringToUTF8Ptr(main_assembly_name); + marshal_intptr_to_cs(arg1, main_assembly_name_ptr); marshal_array_to_cs_impl(arg2, program_args && !program_args.length ? undefined : program_args, MarshalerType.String); marshal_bool_to_cs(arg3, waitForDebugger); diff --git a/src/mono/browser/runtime/marshal-to-js.ts b/src/mono/browser/runtime/marshal-to-js.ts index d3987586b01d4..b58201080b49e 100644 --- a/src/mono/browser/runtime/marshal-to-js.ts +++ b/src/mono/browser/runtime/marshal-to-js.ts @@ -59,7 +59,7 @@ export function initialize_marshalers_to_js(): void { } export function bind_arg_marshal_to_js(sig: JSMarshalerType, marshaler_type: MarshalerType, index: number): BoundMarshalerToJs | undefined { - if (marshaler_type === MarshalerType.None || marshaler_type === MarshalerType.Void) { + if (marshaler_type === MarshalerType.None || marshaler_type === MarshalerType.Void || marshaler_type === MarshalerType.Discard) { return undefined; } diff --git a/src/mono/browser/runtime/strings.ts b/src/mono/browser/runtime/strings.ts index ae73fe57ff50d..d6fbe3a12898a 100644 --- a/src/mono/browser/runtime/strings.ts +++ b/src/mono/browser/runtime/strings.ts @@ -5,7 +5,7 @@ import { mono_wasm_new_root, mono_wasm_new_root_buffer } from "./roots"; import { MonoString, MonoStringNull, WasmRoot, WasmRootBuffer } from "./types/internal"; import { Module } from "./globals"; import cwraps from "./cwraps"; -import { isSharedArrayBuffer, localHeapViewU8, getU32_local, setU16_local, localHeapViewU32, getU16_local, localHeapViewU16 } from "./memory"; +import { isSharedArrayBuffer, localHeapViewU8, getU32_local, setU16_local, localHeapViewU32, getU16_local, localHeapViewU16, _zero_region } from "./memory"; import { NativePointer, CharPtr } from "./types/emscripten"; export const interned_js_string_table = new Map(); @@ -44,6 +44,15 @@ export function stringToUTF8(str: string): Uint8Array { return _text_encoder_utf8.encode(str); } +export function stringToUTF8Ptr(str: string): CharPtr { + const bytes = str.length * 2; + const ptr = Module._malloc(bytes) as any; + _zero_region(ptr, str.length * 2); + const buffer = localHeapViewU8().subarray(ptr, ptr + bytes); + buffer.set(stringToUTF8(str)); + return ptr; +} + export function utf8ToStringRelaxed(buffer: Uint8Array): string { if (_text_decoder_utf8_relaxed === undefined) { return Module.UTF8ArrayToString(buffer, 0, buffer.byteLength); diff --git a/src/mono/wasi/mono-include/driver.h b/src/mono/wasi/mono-include/driver.h index 47c72f146f7c1..8931972755a6a 100644 --- a/src/mono/wasi/mono-include/driver.h +++ b/src/mono/wasi/mono-include/driver.h @@ -11,7 +11,6 @@ MonoAssembly* mono_wasm_assembly_load(const char *name); MonoMethod* mono_wasi_assembly_get_entry_point (MonoAssembly *assembly); MonoClass* mono_wasm_assembly_find_class (MonoAssembly *assembly, const char *namespace, const char *name); MonoMethod* mono_wasm_assembly_find_method (MonoClass *klass, const char *name, int arguments); -MonoObject* mono_wasm_invoke_method (MonoMethod *method, MonoObject *this_arg, void *params[], MonoObject **out_exc); int mono_unbox_int (MonoObject *obj); void add_assembly(const char* base_dir, const char *name);