diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index f8a44275297ea..7d0b071551778 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -72,7 +72,7 @@ ifeq ($(ENABLE_METADATA_UPDATE),true) endif EMCC_DEBUG_FLAGS =-g -Os -s ASSERTIONS=1 -DDEBUG=1 -EMCC_RELEASE_FLAGS=-Oz --llvm-opts 2 +EMCC_RELEASE_FLAGS=-O3 --llvm-opts 3 ifeq ($(NOSTRIP),) STRIP_CMD=&& $(EMSDK_PATH)/upstream/bin/wasm-opt --strip-dwarf $(NATIVE_BIN_DIR)/dotnet.wasm -o $(NATIVE_BIN_DIR)/dotnet.wasm @@ -108,13 +108,13 @@ $(BUILDS_OBJ_DIR)/pinvoke-table.h: $(PINVOKE_TABLE) | $(BUILDS_OBJ_DIR) if cmp -s $(PINVOKE_TABLE) $$@ ; then : ; else cp $(PINVOKE_TABLE) $$@ ; fi $(BUILDS_OBJ_DIR)/driver.o: runtime/driver.c | $(BUILDS_OBJ_DIR) - $(EMCC) $(EMCC_FLAGS) $(1) -Oz -DCORE_BINDINGS -I$(BUILDS_OBJ_DIR) -I$(MONO_INCLUDE_DIR) runtime/driver.c -c -o $$@ + $(EMCC) $(EMCC_FLAGS) $(1) -O3 -DCORE_BINDINGS -I$(BUILDS_OBJ_DIR) -I$(MONO_INCLUDE_DIR) runtime/driver.c -c -o $$@ $(BUILDS_OBJ_DIR)/pinvoke.o: runtime/pinvoke.c runtime/pinvoke.h $(BUILDS_OBJ_DIR)/pinvoke-table.h | $(BUILDS_OBJ_DIR) - $(EMCC) $(EMCC_FLAGS) $(1) -Oz -DGEN_PINVOKE=1 -I$(BUILDS_OBJ_DIR) runtime/pinvoke.c -c -o $$@ + $(EMCC) $(EMCC_FLAGS) $(1) -O3 -DGEN_PINVOKE=1 -I$(BUILDS_OBJ_DIR) runtime/pinvoke.c -c -o $$@ $(BUILDS_OBJ_DIR)/corebindings.o: runtime/corebindings.c | $(BUILDS_OBJ_DIR) - $(EMCC) $(EMCC_FLAGS) $(1) -Oz -I$(MONO_INCLUDE_DIR) runtime/corebindings.c -c -o $$@ + $(EMCC) $(EMCC_FLAGS) $(1) -O3 -I$(MONO_INCLUDE_DIR) runtime/corebindings.c -c -o $$@ $(NATIVE_BIN_DIR)/src/emcc-flags.txt: | $(NATIVE_BIN_DIR)/src Makefile echo "$(call escape_quote,$(EMCC_FLAGS)) $(1)" > $$@ diff --git a/src/mono/wasm/runtime/binding_support.js b/src/mono/wasm/runtime/binding_support.js index 3938dc83041b6..8426d2154381b 100644 --- a/src/mono/wasm/runtime/binding_support.js +++ b/src/mono/wasm/runtime/binding_support.js @@ -541,6 +541,7 @@ var BindingSupportLib = { ((typeof js_obj === "object" || typeof js_obj === "function") && typeof js_obj.then === "function") } + var result; switch (true) { case js_obj === null: case typeof js_obj === "undefined": @@ -962,7 +963,7 @@ var BindingSupportLib = { var conv = primitiveConverters.get (key); if (!conv) - throw new Error ("Unknown parameter type " + type); + throw new Error ("Unknown parameter type " + key); var localStep = Object.create (conv.steps[0]); localStep.size = conv.size; @@ -1300,7 +1301,7 @@ var BindingSupportLib = { converter, buffer, resultRoot, exceptionRoot, argsRootBuffer, is_result_marshaled ) { this._handle_exception_for_call (converter, buffer, resultRoot, exceptionRoot, argsRootBuffer); - + var result; if (is_result_marshaled) result = this._unbox_mono_obj_root (resultRoot); else @@ -1443,7 +1444,7 @@ var BindingSupportLib = { "return result;" ); - bodyJs = body.join ("\r\n"); + var bodyJs = body.join ("\r\n"); if (friendly_name) { var escapeRE = /[^A-Za-z0-9_]/g; @@ -1699,7 +1700,6 @@ var BindingSupportLib = { var js_args = BINDING.mono_wasm_parse_args(args); - var res; try { var m = obj [js_name]; if (typeof m === "undefined") @@ -1731,7 +1731,6 @@ var BindingSupportLib = { return BINDING.js_string_to_mono_string ("Invalid property name object '" + js_name + "'"); } - var res; try { var m = obj [js_name]; if (m === Object(m) && obj.__is_mono_proxied__) diff --git a/src/mono/wasm/runtime/corebindings.c b/src/mono/wasm/runtime/corebindings.c index a0263c2a8ba9d..e386f84a9f31d 100644 --- a/src/mono/wasm/runtime/corebindings.c +++ b/src/mono/wasm/runtime/corebindings.c @@ -43,7 +43,7 @@ EM_JS(MonoObject*, compile_function, (int snippet_ptr, int len, int *is_exceptio } catch (e) { - res = e.toString (); + var res = e.toString (); setValue (is_exception, 1, "i32"); if (res === null || res === undefined) res = "unknown exception"; diff --git a/src/mono/wasm/runtime/dotnet_support.js b/src/mono/wasm/runtime/dotnet_support.js index 3272b714eca90..c9552c9a94b7c 100644 --- a/src/mono/wasm/runtime/dotnet_support.js +++ b/src/mono/wasm/runtime/dotnet_support.js @@ -46,7 +46,7 @@ var DotNetSupportLib = { var funcNameJsString = DOTNET.conv_string(functionName); var argsJsonJsString = argsJson && DOTNET.conv_string (argsJson); - var dotNetExports = globaThis.DotNet; + var dotNetExports = globalThis.DotNet; if (!dotNetExports) { throw new Error('The Microsoft.JSInterop.js library is not loaded.'); } diff --git a/src/mono/wasm/runtime/externs.js b/src/mono/wasm/runtime/externs.js new file mode 100644 index 0000000000000..571c4b39ef91f --- /dev/null +++ b/src/mono/wasm/runtime/externs.js @@ -0,0 +1,306 @@ +// @externs +/** + * @typedef WasmId + * @type {object} + * @property {string} idStr - full object id string + * @property {string} scheme - eg, object, valuetype, array .. + * @property {string} value - string part after `dotnet:scheme:` of the id string + * @property {object} o - value parsed as JSON + */ + +/** + * @typedef WasmRoot - a single address in the managed heap, visible to the GC + * @type {object} + * @property {ManagedPointer} value - pointer into the managed heap, stored in the root + * @property {function} get_address - retrieves address of the root in wasm memory + * @property {function} get - retrieves pointer value + * @property {function} set - updates the pointer + * @property {function} release - releases the root storage for future use + */ + +/** + * @typedef WasmRootBuffer - a collection of addresses in the managed heap, visible to the GC + * @type {object} + * @property {number} length - number of elements the root buffer can hold + * @property {function} get_address - retrieves address of an element in wasm memory, by index + * @property {function} get - retrieves an element by index + * @property {function} set - sets an element's value by index + * @property {function} release - releases the root storage for future use + */ + +/** + * @typedef ManagedPointer + * @type {number} - address in the managed heap + */ + +/** + * @typedef NativePointer + * @type {number} - address in wasm memory + */ + +/** + * @typedef Event + * @type {object} + * @property {string} eventName - name of the event being raised + * @property {object} eventArgs - arguments for the event itself + */ + +var ___cxa_is_pointer_type = function(type) {}; +var ___cxa_can_catch = function(caughtType, thrownType, exceptionThrowBuf) {}; +/** + * @suppress {duplicate} + */ +var addRunDependency = function(type) {}; +/** + * @suppress {duplicate} + */ +var removeRunDependency = function(type) {}; +/** + * @suppress {duplicate} + */ +var cwrap = function(ident, returnType, argTypes, opts) {}; +/** + * @suppress {duplicate} + */ +var converter = function() {}; +/** + * @suppress {duplicate} + */ +var this_arg = {}; +/** + * @suppress {duplicate} + */ +var WasmRoot = {}; +WasmRoot.value = 0; +WasmRoot.get_address = function() {}; +WasmRoot.get = function() {}; +WasmRoot.set = function() {}; +WasmRoot.release = function() {}; +/** + * @suppress {duplicate} + */ +var converter_so = {}; +converter_so.compiled_function = function() {}; +/** + * @const + * @suppress {duplicate} + */ +var Module = {}; +Module.FS_createDataFile = function(a,b,c,d,e,f) {}; +Module.FS_createDevice = function(a,b,c,d) {}; +Module.FS_createLazyFile = function(a,b,c,d,e) {}; +Module.FS_createPath = function(a,b) {}; +Module.FS_createPreloadedFile = function(a,b,c,d,e,f,g,h,r,q) {}; +Module.FS_unlink = function(a) {}; +Module.HEAP8 = {}; +Module.HEAP16 = {}; +Module.HEAP32 = {}; +Module.HEAPF32 = {}; +Module.HEAPF64 = {}; +Module.HEAPU8 = {}; +Module.HEAPU16 = {}; +Module.HEAPU32 = {} +Module.UTF8ArrayToString = function(a,b,c) {}; +Module.UTF8ToString = function(a,b) {}; +Module.addFunction = function(a,b) {}; +Module.addRunDependency = function() {}; +Module.asm = {}; +Module.ccall = function(a,b,c,d) {}; +Module.cwrap = function(a,b,c,d) {}; +Module.getValue = function(a,b) {}; +Module.instantiateWasm = function(e,t) {}; +Module.mono_bind_assembly_entry_point = function() {}; +Module.mono_bind_method = function() {}; +Module.mono_bind_static_method = function() {}; +Module.mono_bindings_init = function() {}; +Module.mono_call_assembly_entry_point = function() {}; +Module.mono_call_static_method = function() {}; +Module.mono_intern_string = function() {}; +Module.mono_load_runtime_and_bcl = function() {}; +Module.mono_load_runtime_and_bcl_args = function() {}; +Module.mono_method_get_call_signature = function() {}; +Module.mono_method_invoke = function() {}; +Module.mono_method_resolve = function() {}; +Module.mono_wasm_get_icudt_name = function() {}; +Module.mono_wasm_get_loaded_files = function() {}; +Module.mono_wasm_globalization_init = function() {}; +Module.mono_wasm_load_bytes_into_heap = function() {}; +Module.mono_wasm_load_icu_data = function() {}; +Module.mono_wasm_new_root = function() {}; +Module.mono_wasm_new_root_buffer = function() {}; +Module.mono_wasm_new_root_buffer_from_pointer = function() {}; +Module.mono_wasm_new_roots = function() {}; +Module.mono_wasm_release_roots = function() {}; +Module.postRun = []; +Module.preRun = []; +Module.preloadPlugins = []; +Module.preloadedAudios = {}; +Module.preloadedImages = {}; +Module.print = function() {}; +Module.printErr = function() {}; +Module.pump_message = function() {}; +Module.removeRunDependency = function() {}; +Module.run = function() {}; +Module.setValue = function(a,b,c) {}; +Module.stackAlloc = function() {}; +Module.stackRestore = function() {}; +Module.stackSave = function() {}; +Module.___errno_location = function() {}; +Module.___wasm_call_ctors = function() {}; +Module.__get_daylight = function() {}; +Module.__get_timezone = function() {}; +Module.__get_tzname = function() {}; +Module._free = function() {}; +Module._htons = function() {}; +Module._malloc = function() {}; +Module._memalign = function() {}; +Module._memset = function() {}; +Module._mono_background_exec = function() {}; +Module._mono_print_method_from_ip = function() {}; +Module._mono_set_timeout_exec = function() {}; +Module._mono_unbox_int = function() {}; +Module._mono_wasm_add_assembly = function() {}; +Module._mono_wasm_add_satellite_assembly = function() {}; +Module._mono_wasm_array_get = function() {}; +Module._mono_wasm_array_length = function() {}; +Module._mono_wasm_assembly_find_class = function() {}; +Module._mono_wasm_assembly_find_method = function() {}; +Module._mono_wasm_assembly_get_entry_point = function() {}; +Module._mono_wasm_assembly_load = function() {}; +Module._mono_wasm_box_primitive = function() {}; +Module._mono_wasm_clear_all_breakpoints = function() {}; +Module._mono_wasm_current_bp_id = function() {}; +Module._mono_wasm_deregister_root = function() {}; +Module._mono_wasm_enable_on_demand_gc = function() {}; +Module._mono_wasm_enum_frames = function() {}; +Module._mono_wasm_exec_regression = function() {}; +Module._mono_wasm_exit = function() {}; +Module._mono_wasm_find_corlib_class = function() {}; +Module._mono_wasm_get_array_values = function() {}; +Module._mono_wasm_get_delegate_invoke = function() {}; +Module._mono_wasm_get_deref_ptr_value = function() {}; +Module._mono_wasm_get_icudt_name = function() {}; +Module._mono_wasm_get_local_vars = function() {}; +Module._mono_wasm_get_obj_type = function() {}; +Module._mono_wasm_get_object_properties = function() {}; +Module._mono_wasm_intern_string = function() {}; +Module._mono_wasm_invoke_getter_on_object = function() {}; +Module._mono_wasm_invoke_getter_on_value = function() {}; +Module._mono_wasm_invoke_method = function() {}; +Module._mono_wasm_load_icu_data = function() {}; +Module._mono_wasm_load_runtime = function() {}; +Module._mono_wasm_obj_array_new = function() {}; +Module._mono_wasm_obj_array_set = function() {}; +Module._mono_wasm_parse_runtime_options = function() {}; +Module._mono_wasm_pause_on_exceptions = function() {}; +Module._mono_wasm_register_bundled_satellite_assemblies = function() {}; +Module._mono_wasm_register_root = function() {}; +Module._mono_wasm_remove_breakpoint = function() {}; +Module._mono_wasm_set_breakpoint = function() {}; +Module._mono_wasm_set_is_debugger_attached = function() {}; +Module._mono_wasm_set_main_args = function() {}; +Module._mono_wasm_set_value_on_object = function() {}; +Module._mono_wasm_set_variable_on_frame = function() {}; +Module._mono_wasm_setenv = function() {}; +Module._mono_wasm_setup_single_step = function() {}; +Module._mono_wasm_strdup = function() {}; +Module._mono_wasm_string_array_new = function() {}; +Module._mono_wasm_string_convert = function() {}; +Module._mono_wasm_string_from_js = function() {}; +Module._mono_wasm_string_from_utf16 = function() {}; +Module._mono_wasm_string_get_utf8 = function() {}; +Module._mono_wasm_try_unbox_primitive_and_get_type = function() {}; +Module._mono_wasm_typed_array_new = function() {}; +Module._mono_wasm_unbox_enum = function() {}; +Module._ntohs = function() {}; +Module._putchar = function() {}; +Module._setThrew = function() {}; +/** + * @const + * @suppress {duplicate} + */ +var MONO = {}; +MONO.mono_wasm_load_data_archive = function() {}; +MONO.mono_wasm_load_bytes_into_heap = function() {}; +MONO.mono_wasm_load_icu_data = function() {}; +MONO.mono_wasm_setenv = function() {}; +MONO.mono_wasm_runtime_ready = function() {}; +MONO.pump_message = function() {}; +MONO.mono_load_runtime_and_bcl = function() {}; +MONO.mono_load_runtime_and_bcl_args = function() {}; +MONO.mono_wasm_get_icudt_name = function() {}; +MONO.mono_wasm_globalization_init = function() {}; +MONO.mono_wasm_get_loaded_files = function() {}; +/** + * @param {number} capacity - the maximum number of elements the buffer can hold. + * @param {string} [msg] - a description of the root buffer (for debugging) + * @returns {WasmRootBuffer} + */ +MONO.mono_wasm_new_root_buffer = function(capacity, msg) {}; +/** + * @param {NativePointer} offset - the offset of the root buffer in the native heap. + * @param {number} capacity - the maximum number of elements the buffer can hold. + * @param {string} [msg] - a description of the root buffer (for debugging) + * @returns {WasmRootBuffer} + */ +MONO.mono_wasm_new_root_buffer_from_pointer = function(offset, capacity, msg) {}; +/** + * @param {ManagedPointer} [value] - an address in the managed heap to initialize the root with (or 0) + * @returns {WasmRoot} + */ +MONO.mono_wasm_new_root = function(value) {}; +/** + * @param {(number | ManagedPointer[])} count_or_values - either a number of roots or an array of pointers + * @returns {WasmRoot[]} + */ +MONO.mono_wasm_new_roots = function(count_or_values) {}; +/** + * @param {... WasmRoot} roots + */ +MONO.mono_wasm_release_roots = function() {}; +/** + * @const + * @suppress {duplicate} + */ +var BINDING = {}; +BINDING.mono_bindings_init = function() {}; +BINDING.mono_bind_method = function() {}; +BINDING.mono_method_invoke = function() {}; +BINDING.mono_method_get_call_signature = function() {}; +BINDING.mono_method_resolve = function() {}; +BINDING.mono_bind_static_method = function() {}; +BINDING.mono_call_static_method = function() {}; +BINDING.mono_bind_assembly_entry_point = function() {}; +BINDING.mono_call_assembly_entry_point = function() {}; +BINDING.mono_intern_string = function() {}; +BINDING.bind_static_method = function() {}; +BINDING.js_string_to_mono_string = function() {}; +BINDING.conv_string = function() {}; +BINDING.js_typed_array_to_array = function() {}; +BINDING.mono_array_to_js_array = function() {}; +BINDING.js_to_mono_obj = function() {}; +BINDING.mono_obj_array_new = function() {}; +BINDING.mono_obj_array_set = function() {}; +BINDING.js_typed_array_to_array = function() {}; +BINDING.unbox_mono_obj = function() {}; +/** + * @const + * @suppress {duplicate} + */ +var library_mono = {}; +/** + * @return {WasmRoot} + */ +library_mono.mono_wasm_new_root = function() {}; +/** + * @const + * @suppress {duplicate} + */ +var binding_support = {}; +binding_support._get_args_root_buffer_for_method_call = function() {}; +binding_support._get_buffer_for_method_call = function() {}; +binding_support.invoke_method = function() {}; +binding_support._handle_exception_for_call = function() {}; +binding_support.mono_wasm_try_unbox_primitive_and_get_type = function() {}; +binding_support.mono_wasm_try_unbox_primitive_and_get_type = function() {}; +binding_support._unbox_mono_obj_rooted_with_known_nonprimitive_type = function() {}; diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index 685aaaf375d85..a0041801660d7 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -2268,7 +2268,7 @@ var MonoSupportLib = { var manifest; try { - manifestContent = Module.UTF8ArrayToString(data, 8, manifestSize); + var manifestContent = Module.UTF8ArrayToString(data, 8, manifestSize); manifest = JSON.parse(manifestContent); if (!(manifest instanceof Array)) return false; @@ -2295,7 +2295,7 @@ var MonoSupportLib = { Module['FS_createPath'](prefix, folder, true, true); }); - for (row of manifest) { + for (var row of manifest) { var name = row[0]; var length = row[1]; var bytes = data.slice(0, length); diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index dda6fa29f6272..4b767236fbb43 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -119,12 +119,13 @@ --profiling-funcs -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s BINARYEN=1 -s ALIASING_FUNCTION_POINTERS=0 -s NO_EXIT_RUNTIME=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'FS_createPath', 'FS_createDataFile', 'cwrap', 'setValue', 'getValue', 'UTF8ToString', 'UTF8ArrayToString', 'addFunction']" -s "EXPORTED_FUNCTIONS=['_putchar']" --source-map-base http://example.com -emit-llvm -s FORCE_FILESYSTEM=1 -s USE_ZLIB=1 $(EmccFlags) -s MODULARIZE=1 -s EXPORT_ES6=1 -g -Os -s ASSERTIONS=1 -DENABLE_NETCORE=1 -DDEBUG=1 - -Oz --llvm-opts 2 -DENABLE_NETCORE=1 + -O3 --llvm-opts 3 -DENABLE_NETCORE=1 "$(EMSDK_PATH)/upstream/bin/wasm-opt" --strip-dwarf "$(NativeBinDir)/dotnet.wasm" -o "$(NativeBinDir)/dotnet.wasm" $(ArtifactsObjDir)wasm $(WasmObjDir)\emcc-version.txt $(MonoArtifactsPath)include/mono-2.0 $(RepoRoot)src\libraries\Native\Unix\System.Native + --externs runtime/externs.js - - @@ -152,12 +153,13 @@ DestinationFolder="$(MonoObjDir)" SkipUnchangedFiles="true" /> - - /dev/null 2>&1 && {Command}'"; } + if (ClosureArgs != null) + { + Environment.SetEnvironmentVariable("EMCC_CLOSURE_ARGS", ClosureArgs); + } + var workingDir = string.IsNullOrEmpty(WorkingDirectory) ? Directory.GetCurrentDirectory() : WorkingDirectory; Log.LogMessage(MessageImportance.Low, $"Working directory: {workingDir}"); Log.LogMessage(MessageImportance.Low, $"Using Command: {Command}");