From cf801ca091d69295399561ff1472cf24f55c13b8 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Mon, 8 Mar 2021 19:11:45 -0600 Subject: [PATCH 1/2] Generalize the test runner a bit --- src/mono/sample/wasm/wasm.mk | 2 +- src/mono/wasm/runtime-test.js | 154 ++++++++++++----------- src/mono/wasm/runtime/binding_support.js | 3 +- src/mono/wasm/runtime/library_mono.js | 17 ++- 4 files changed, 95 insertions(+), 81 deletions(-) diff --git a/src/mono/sample/wasm/wasm.mk b/src/mono/sample/wasm/wasm.mk index 1858ca37911824..c62b67a1777119 100644 --- a/src/mono/sample/wasm/wasm.mk +++ b/src/mono/sample/wasm/wasm.mk @@ -23,7 +23,7 @@ run-browser: echo "The tool dotnet-serve could not be found. Install with: $(DOTNET) tool install --global dotnet-serve"; \ exit 1; \ else \ - $(DOTNET) serve -d bin/$(CONFIG)/AppBundle -p 8000; \ + $(DOTNET) serve -d=bin/$(CONFIG)/AppBundle -p 8000; \ fi run-console: diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js index 74aa1083c033d1..4a10be1e9220d1 100644 --- a/src/mono/wasm/runtime-test.js +++ b/src/mono/wasm/runtime-test.js @@ -4,29 +4,31 @@ // //glue code to deal with the differences between chrome, ch, d8, jsc and sm. -var is_browser = typeof window != "undefined"; +const is_browser = typeof window != "undefined"; +const is_node = !is_browser && typeof process != 'undefined'; // if the engine doesn't provide a console if (typeof (console) === "undefined") { - var console = { + console = { log: globalThis.print, clear: function () { } }; } + globalThis.testConsole = console; -function proxyMethod (prefix, func, asJson) { +function proxyMethod (prefix, proxyFunc, asJson) { return function() { var args = [...arguments]; if (asJson) { - func (JSON.stringify({ + proxyFunc (JSON.stringify({ method: prefix, payload: args[0], arguments: args })); } else { - func([prefix + args[0], ...args.slice(1)]); + proxyFunc([prefix + args[0], ...args.slice(1)]); } }; }; @@ -38,9 +40,9 @@ for (var m of methods) { } } -function proxyJson (func) { +function proxyJson (consoleFunc) { for (var m of ["log", ...methods]) - console[m] = proxyMethod(`console.${m}`,func, true); + console[m] = proxyMethod(`console.${m}`, consolefunc, true); } if (is_browser) { @@ -49,7 +51,7 @@ if (is_browser) { let consoleWebSocket = new WebSocket(consoleUrl); consoleWebSocket.onopen = function(event) { proxyJson(function (msg) { consoleWebSocket.send (msg); }); - globalThis.testConsole.log("browser: Console websocket connected."); + testConsole.log("browser: Console websocket connected."); }; consoleWebSocket.onerror = function(event) { console.log(`websocket error: ${event}`); @@ -64,6 +66,18 @@ if (is_browser) { } } } + +if (is_node) { + arguments = process.argv.slice (2); + var fs = require ('fs'); + function load (file) { + eval (fs.readFileSync(file).toString()); + }; + function read (path) { + return fs.readFileSync(path); + }; + const { performance, PerformanceObserver } = require("perf_hooks") +} //proxyJson(console.log); @@ -91,22 +105,20 @@ if (typeof performance == 'undefined') { } } -try { - if (typeof arguments == "undefined") - arguments = WScript.Arguments; - load = WScript.LoadScriptFile; - read = WScript.LoadBinaryFile; -} catch (e) { -} - try { if (typeof arguments == "undefined") { - if (typeof scriptArgs !== "undefined") + if (typeof (WScript) != "undefined") { + arguments = WScript.Arguments; + load = WScript.LoadScriptFile; + read = WScript.LoadBinaryFile; + } else if (typeof (scriptArgs) != "undefined") { arguments = scriptArgs; + } } } catch (e) { } + if (arguments === undefined) arguments = []; @@ -119,7 +131,7 @@ function test_exit (exit_code) { if (is_browser) { // Notify the selenium script Module.exit_code = exit_code; - Module.print ("WASM EXIT " + exit_code); + console.log ("WASM EXIT " + exit_code); var tests_done_elem = document.createElement ("label"); tests_done_elem.id = "tests_done"; tests_done_elem.innerHTML = exit_code.toString (); @@ -130,7 +142,7 @@ function test_exit (exit_code) { } function fail_exec (reason) { - Module.print (reason); + console.log (reason); test_exit (1); } @@ -144,8 +156,8 @@ function inspect_object (o) { } // Preprocess arguments -var args = testArguments; -console.info("Arguments: " + testArguments); +var args = [...testArguments]; +//console.info("Arguments: " + testArguments); profilers = []; setenv = {}; runtime_args = []; @@ -153,28 +165,29 @@ enable_gc = true; enable_zoneinfo = false; working_dir='/'; while (args !== undefined && args.length > 0) { - if (args [0].startsWith ("--profile=")) { - var arg = args [0].substring ("--profile=".length); + let currentArg = args [0].toString(); + if (currentArg.startsWith ("--profile=")) { + var arg = currentArg.substring ("--profile=".length); profilers.push (arg); args = args.slice (1); - } else if (args [0].startsWith ("--setenv=")) { - var arg = args [0].substring ("--setenv=".length); + } else if (currentArg.startsWith ("--setenv=")) { + var arg = currentArg.substring ("--setenv=".length); var parts = arg.split ('='); if (parts.length != 2) - fail_exec ("Error: malformed argument: '" + args [0]); + fail_exec ("Error: malformed argument: '" + currentArg); setenv [parts [0]] = parts [1]; args = args.slice (1); - } else if (args [0].startsWith ("--runtime-arg=")) { - var arg = args [0].substring ("--runtime-arg=".length); + } else if (currentArg.startsWith ("--runtime-arg=")) { + var arg = currentArg.substring ("--runtime-arg=".length); runtime_args.push (arg); args = args.slice (1); - } else if (args [0] == "--disable-on-demand-gc") { + } else if (currentArg == "--disable-on-demand-gc") { enable_gc = false; args = args.slice (1); - } else if (args [0].startsWith ("--working-dir=")) { - var arg = args [0].substring ("--working-dir=".length); + } else if (currentArg.startsWith ("--working-dir=")) { + var arg = currentArg.substring ("--working-dir=".length); working_dir = arg; args = args.slice (1); } else { @@ -186,44 +199,46 @@ testArguments = args; // cheap way to let the testing infrastructure know we're running in a browser context (or not) setenv["IsBrowserDomSupported"] = is_browser.toString().toLowerCase(); -function writeContentToFile(content, path) -{ +function writeContentToFile(content, path) { var stream = FS.open(path, 'w+'); FS.write(stream, content, 0, content.length, 0); FS.close(stream); } -function loadScript (url) -{ +function loadScript (url){ if (is_browser) { var script = document.createElement ("script"); script.src = url; document.head.appendChild (script); + } else if (is_node) { + return read (url).toString(); } else { load (url); } + return ""; } -loadScript ("mono-config.js"); - +eval (loadScript ("mono-config.js")); var Module = { mainScriptUrlOrBlob: "dotnet.js", - - print, - printErr, - + config, + setenv, + read, + arguments, onAbort: function(x) { - print ("ABORT: " + x); + console.log ("ABORT: " + x); var err = new Error(); - print ("Stacktrace: \n"); - print (err.stack); + console.log ("Stacktrace: \n"); + console.log (err.stack); test_exit (1); }, onRuntimeInitialized: function () { + try { + // Have to set env vars here to enable setting MONO_LOG_LEVEL etc. for (var variable in setenv) { - MONO.mono_wasm_setenv (variable, setenv [variable]); + Module._mono_wasm_setenv (variable, setenv [variable]); } if (!enable_gc) { @@ -241,7 +256,7 @@ var Module = { App.init (); }; config.fetch_file_cb = function (asset) { - // console.log("fetch_file_cb('" + asset + "')"); + //console.log("fetch_file_cb('" + asset + "')"); // for testing purposes add BCL assets to VFS until we special case File.Open // to identify when an assembly from the BCL is being open and resolve it correctly. /* @@ -261,30 +276,29 @@ var Module = { return new Promise ((resolve, reject) => { var bytes = null, error = null; try { - bytes = read (asset, 'binary'); + bytes = Module.read (asset, 'binary'); } catch (exc) { - error = exc; + reject (exc); } - var response = { ok: (bytes && !error), url: asset, - arrayBuffer: function () { - return new Promise ((resolve2, reject2) => { - if (error) - reject2 (error); - else - resolve2 (new Uint8Array (bytes)); - } - )} - } - resolve (response); - }) + resolve ({ + ok: (bytes && !error), + url: asset, + arrayBuffer: () => Promise.resolve (new Uint8Array (bytes)) + }); + }); } }; - MONO.mono_load_runtime_and_bcl_args (config); + Module.mono_load_runtime_and_bcl_args (config); + } catch (e) { + console.log (e); + } }, }; -loadScript ("dotnet.js"); +eval (loadScript ("dotnet.js")); +//var module = require ('./dotnet.js')(Module).then ((va) => console.log (va)); +//globalThis.Module = Module; const IGNORE_PARAM_COUNT = -1; @@ -314,10 +328,10 @@ var App = { var res = 0; try { res = exec_regression (10, args[1]); - Module.print ("REGRESSION RESULT: " + res); + console.log ("REGRESSION RESULT: " + res); } catch (e) { - Module.print ("ABORT: " + e); - print (e.stack); + console.log ("ABORT: " + e); + console.log (e.stack); res = 1; } @@ -352,9 +366,7 @@ var App = { wasm_set_main_args (main_argc, main_argv); // Automatic signature isn't working correctly - let result = Module.mono_call_assembly_entry_point (main_assembly_name, [app_args], "m"); - let onError = function (error) - { + let onError = function (error) { console.error (error); if (error.stack) console.error (error.stack); @@ -362,13 +374,15 @@ var App = { test_exit (1); } try { - result.then (test_exit).catch (onError); + Module.mono_call_assembly_entry_point (main_assembly_name, [app_args], "m") + .then (test_exit) + .catch (onError); } catch (error) { onError(error); } } else { - fail_exec ("Unhandled argument: " + args [0]); + fail_exec ("Unhandled argument: " + args[0]); } }, call_test_method: function (method_name, args, signature) { diff --git a/src/mono/wasm/runtime/binding_support.js b/src/mono/wasm/runtime/binding_support.js index 3938dc83041b64..a9fe4fbc8d6ca2 100644 --- a/src/mono/wasm/runtime/binding_support.js +++ b/src/mono/wasm/runtime/binding_support.js @@ -1016,7 +1016,7 @@ var BindingSupportLib = { // ensure the indirect values are 8-byte aligned so that aligned loads and stores will work var indirectBaseOffset = ((((args_marshal.length * 4) + 7) / 8) | 0) * 8; - var closure = {}; + var closure = { Module }; var indirectLocalOffset = 0; body.push ( @@ -1349,6 +1349,7 @@ var BindingSupportLib = { library_mono: MONO, binding_support: this, method: method, + Module: Module, this_arg: this_arg }; diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index 685aaaf375d85e..5a8bf50e988753 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -1759,9 +1759,9 @@ var MonoSupportLib = { try { load_runtime ("unused", args.debug_level); } catch (ex) { - print ("MONO_WASM: load_runtime () failed: " + ex); - print ("MONO_WASM: Stacktrace: \n"); - print (ex.stack); + Module.print ("MONO_WASM: load_runtime () failed: " + ex); + Module.print ("MONO_WASM: Stacktrace: \n"); + Module.print (ex.stack); var wasm_exit = Module.cwrap ('mono_wasm_exit', null, ['number']); wasm_exit (1); @@ -2454,6 +2454,8 @@ var MonoSupportLib = { ++MONO.pump_count; if (typeof globalThis.setTimeout === 'function') { globalThis.setTimeout (MONO.pump_message, 0); + } else { + Promise.resolve().then (MONO.pump_message); } }, @@ -2461,15 +2463,12 @@ var MonoSupportLib = { if (!this.mono_set_timeout_exec) this.mono_set_timeout_exec = Module.cwrap ("mono_set_timeout_exec", null, [ 'number' ]); + var timer = function () { this.mono_set_timeout_exec (id) }.bind (this); if (typeof globalThis.setTimeout === 'function') { - globalThis.setTimeout (function () { - this.mono_set_timeout_exec (id); - }, timeout); + globalThis.setTimeout (timer, timeout); } else { ++MONO.pump_count; - MONO.timeout_queue.push(function() { - this.mono_set_timeout_exec (id); - }) + MONO.timeout_queue.push(timer); } }, From ed4f9be7b9bba5e3e8e5d877ed32ccd0e38d3820 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Wed, 14 Apr 2021 19:23:53 -0500 Subject: [PATCH 2/2] checkpoint --- src/mono/wasm/runtime-test.js | 16 +++++++++++----- src/mono/wasm/runtime/library_mono.js | 8 ++------ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js index 4a10be1e9220d1..f91b8fe59ab6d9 100644 --- a/src/mono/wasm/runtime-test.js +++ b/src/mono/wasm/runtime-test.js @@ -210,15 +210,17 @@ function loadScript (url){ var script = document.createElement ("script"); script.src = url; document.head.appendChild (script); - } else if (is_node) { - return read (url).toString(); } else { load (url); } - return ""; } -eval (loadScript ("mono-config.js")); +if (is_node) { + eval (read ("mono-config.js").toString()); +} else { + loadScript("mono-config.js"); +} + var Module = { mainScriptUrlOrBlob: "dotnet.js", config, @@ -296,7 +298,11 @@ var Module = { }, }; -eval (loadScript ("dotnet.js")); +if (is_node) { + eval (read ("dotnet.js").toString()); +} else { + loadScript ("dotnet.js"); +} //var module = require ('./dotnet.js')(Module).then ((va) => console.log (va)); //globalThis.Module = Module; diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index 5a8bf50e988753..60de7ff8aa54f9 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -64,7 +64,7 @@ var MonoSupportLib = { this.mono_background_exec = Module.cwrap ("mono_background_exec", null); while (MONO.timeout_queue.length > 0) { --MONO.pump_count; - MONO.timeout_queue.shift()(); + Promise.resolve().then(MONO.timeout_queue.shift()()); } while (MONO.pump_count > 0) { --MONO.pump_count; @@ -2452,11 +2452,7 @@ var MonoSupportLib = { schedule_background_exec: function () { ++MONO.pump_count; - if (typeof globalThis.setTimeout === 'function') { - globalThis.setTimeout (MONO.pump_message, 0); - } else { - Promise.resolve().then (MONO.pump_message); - } + Promise.resolve().then (MONO.pump_message); }, mono_set_timeout: function (timeout, id) {