// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Threading.Tasks;
public class Test
{
- public static void Main (string[] args)
+
+ public static async Task<int> Main(string[] args)
{
- Console.WriteLine ("Hello, World!");
+ await Task.Delay(1);
+ Console.WriteLine("Hello World!");
+ for (int i = 0; i < args.Length; i++) {
+ Console.WriteLine($"args[{i}] = {args[i]}");
+ }
+ return args.Length;
}
-}
+}
\ No newline at end of file
fail_exec ("Error: Missing main executable argument.");
return;
}
- main_assembly = assembly_load (args[1]);
- if (main_assembly == 0) {
- fail_exec ("Error: Unable to load main executable '" + args[1] + "'");
- return;
- }
- main_method = assembly_get_entry_point (main_assembly);
- if (main_method == 0) {
- fail_exec ("Error: Main (string[]) method not found.");
- return;
- }
+ main_assembly_name = args[1];
var app_args = string_array_new (args.length - 2);
for (var i = 2; i < args.length; ++i) {
obj_array_set (app_args, i - 2, string_from_js (args [i]));
}
wasm_set_main_args (main_argc, main_argv);
+ function isThenable (js_obj) {
+ // When using an external Promise library the Promise.resolve may not be sufficient
+ // to identify the object as a Promise.
+ return Promise.resolve (js_obj) === js_obj ||
+ ((typeof js_obj === "object" || typeof js_obj === "function") && typeof js_obj.then === "function")
+ }
+
try {
- var invoke_args = Module._malloc (4);
- Module.setValue (invoke_args, app_args, "i32");
- var eh_exc = Module._malloc (4);
- Module.setValue (eh_exc, 0, "i32");
- var res = runtime_invoke (main_method, 0, invoke_args, eh_exc);
- var eh_res = Module.getValue (eh_exc, "i32");
- if (eh_res != 0) {
- print ("Exception:" + string_get_utf8 (res));
- test_exit (1);
+ // Automatic signature isn't working correctly
+ let exit_code = Module.mono_call_assembly_entry_point (main_assembly_name, [app_args], "m");
+
+ if (isThenable (exit_code))
+ {
+ exit_code.then (
+ (result) => {
+ test_exit (result);
+ },
+ (reason) => {
+ console.error (reason);
+ test_exit (1);
+ });
+ } else {
+ test_exit (exit_code);
return;
}
- var exit_code = unbox_int (res);
- test_exit (exit_code);
} catch (ex) {
print ("JS exception: " + ex);
print (ex.stack);
test_exit (1);
return;
}
-
-/*
- // For testing tp/timers etc.
- while (true) {
- // Sleep by busy waiting
- var start = performance.now ();
- useconds = 1e6 / 10;
- while (performance.now() - start < useconds / 1000) {
- // Do nothing.
- }
-
- Module.pump_message ();
- }
-*/
-
- return;
} else {
fail_exec ("Unhandled argument: " + args [0]);
}
return NULL;
mono_domain_ensure_entry_assembly (root_domain, assembly);
+ method = mono_get_method (image, entry, NULL);
- return mono_get_method (image, entry, NULL);
+ /*
+ * If the entry point looks like a compiler generated wrapper around
+ * an async method in the form "<Name>" then try to look up the async method
+ * "Name" it is 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] != '>'))
+ return method;
+
+ MonoClass *klass = mono_method_get_class (method);
+ char *async_name = strdup (name);
+
+ async_name [name_length - 1] = '\0';
+
+ 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 + 1, mono_signature_get_param_count (sig));
+ free (async_name);
+ if (async_method != NULL)
+ return async_method;
+ }
+ return method;
}
EMSCRIPTEN_KEEPALIVE char *