Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wasm] improve startup #72275

Merged
merged 19 commits into from
Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

export function log(message) {
// uncomment for debugging
console.log(message);
// console.log(message);
}

export function install() {
Expand Down
2 changes: 1 addition & 1 deletion src/mono/sample/wasm/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<Exec Command="dotnet tool install -g dotnet-serve" IgnoreExitCode="true" />
</Target>
<Target Name="RunSampleWithBrowser" DependsOnTargets="BuildSampleInTree;CheckServe">
<Exec Command="$(_Dotnet) serve -o -d:bin/$(Configuration)/AppBundle -p:8000 --mime .mjs=text/javascript --mime .js=text/javascript --mime .cjs=text/javascript" IgnoreExitCode="true" YieldDuringToolExecution="true" />
<Exec Command="$(_Dotnet) serve -o -d:bin/$(Configuration)/AppBundle -p:8000 --mime .mjs=text/javascript --mime .js=text/javascript --mime .cjs=text/javascript -h Cross-Origin-Opener-Policy:same-origin -h Cross-Origin-Embedder-Policy:require-corp " IgnoreExitCode="true" YieldDuringToolExecution="true" />
</Target>
<Target Name="RunSampleWithBrowserAndSimpleServer" DependsOnTargets="BuildSampleInTree">
<Exec Command="$(_Dotnet) build -c $(Configuration) ..\simple-server\HttpServer.csproj" />
Expand Down
1 change: 0 additions & 1 deletion src/mono/sample/wasm/browser-eventpipe/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ <h3 id="header">Wasm Browser EventPipe profiling Sample</h3>
<label for="inputN">N:</label> <input type="number" id="inputN" value="10"/>
</div>
<div>Computing Fib(N) repeatedly: <span id="out"></span>
<script type="module" src="./dotnet.worker.js"></script>
<script type="module" src="./main.js"></script>
</body>

Expand Down
4 changes: 2 additions & 2 deletions src/mono/sample/wasm/browser/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function sub(a, b) {

try {
const { MONO, RuntimeBuildInfo, IMPORTS } = await createDotnetRuntime(() => {
console.log('user code in createDotnetRuntime');
console.log('user code in createDotnetRuntime callback');
return {
configSrc: "./mono-config.json",
preInit: () => { console.log('user code Module.preInit'); },
Expand All @@ -31,7 +31,7 @@ try {
postRun: () => { console.log('user code Module.postRun'); },
}
});
console.log('after createDotnetRuntime');
console.log('user code after createDotnetRuntime()');
IMPORTS.Sample = {
Test: {
add,
Expand Down
20 changes: 10 additions & 10 deletions src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,30 @@
var App = {
static_method_table: {},
init: function () {
this.int_add = getDotnetRuntime(0).INTERNAL.mono_bind_static_method ("[debugger-test] Math:IntAdd");
this.use_complex = getDotnetRuntime(0).INTERNAL.mono_bind_static_method ("[debugger-test] Math:UseComplex");
this.delegates_test = getDotnetRuntime(0).INTERNAL.mono_bind_static_method ("[debugger-test] Math:DelegatesTest");
this.generic_types_test = getDotnetRuntime(0).INTERNAL.mono_bind_static_method ("[debugger-test] Math:GenericTypesTest");
this.outer_method = getDotnetRuntime(0).INTERNAL.mono_bind_static_method ("[debugger-test] Math:OuterMethod");
this.async_method = getDotnetRuntime(0).INTERNAL.mono_bind_static_method ("[debugger-test] Math/NestedInMath:AsyncTest");
this.method_with_structs = getDotnetRuntime(0).INTERNAL.mono_bind_static_method ("[debugger-test] DebuggerTests.ValueTypesTest:MethodWithLocalStructs");
this.run_all = getDotnetRuntime(0).INTERNAL.mono_bind_static_method ("[debugger-test] DebuggerTest:run_all");
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.static_method_table = {};
console.log ("ready");
},
};
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] = getDotnetRuntime(0).INTERNAL.mono_bind_static_method (method_name);
method = App.static_method_table[method_name] = App.BINDING.bind_static_method(method_name);

return method (...args);
}

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] = getDotnetRuntime(0).INTERNAL.mono_bind_static_method (method_name);
method = App.static_method_table[method_name] = App.BINDING.bind_static_method(method_name);
}

return await method (...args);
Expand Down
9 changes: 5 additions & 4 deletions src/mono/wasm/debugger/tests/debugger-test/debugger-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import createDotnetRuntime from './dotnet.js'

try {
const { BINDING, INTERNAL } = await createDotnetRuntime(() => ({
const { BINDING } = await createDotnetRuntime(({ INTERNAL }) => ({
configSrc: "./mono-config.json",
onConfigLoaded: (config) => {
config.environment_variables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug";
Expand All @@ -15,13 +15,14 @@ try {
config.environment_variables["MONO_LOG_LEVEL"] = "debug";
config.environment_variables["MONO_LOG_MASK"] = "all";
INTERNAL.logging = {
trace: function (domain, log_level, message, isFatal, dataPtr) { },
debugger: function (level, message) { }
trace: (domain, log_level, message, isFatal, dataPtr) => console.log({ domain, log_level, message, isFatal, dataPtr }),
debugger: (level, message) => console.log({ level, message }),
};
*/
},
}));
App.init({ BINDING, INTERNAL })
App.BINDING = BINDING;
App.init()
} catch (err) {
console.log(`WASM ERROR ${err}`);
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<EnableDefaultWasmAssembliesToBundle>false</EnableDefaultWasmAssembliesToBundle>
<WasmAppDir>$(AppDir)</WasmAppDir>
<WasmMainJSPath>debugger-main.js</WasmMainJSPath>
<!-- like is used on blazor -->
<!-- -1 enabled debugging and disables debug logging. -->
<WasmDebugLevel Condition="'$(WasmDebugLevel)'==''">-1</WasmDebugLevel>

<WasmResolveAssembliesBeforeBuild>true</WasmResolveAssembliesBeforeBuild>
Expand Down
17 changes: 12 additions & 5 deletions src/mono/wasm/runtime/cjs/dotnet.cjs.lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,30 @@ const isPThread = `false`;
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 readAsync and fetch
// 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 = {readAsync, fetch: globalThis.fetch, require, updateGlobalBufferAndViews, pthreadReplacements: __dotnet_replacement_PThread};
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}, locateFile, quit_, ExitStatus, requirePromise:Promise.resolve(require)},
{ 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;
readAsync = __dotnet_replacements.readAsync;
var fetch = __dotnet_replacements.fetch;
require = __dotnet_replacements.requireOut;
_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;
Expand Down
5 changes: 5 additions & 0 deletions src/mono/wasm/runtime/cjs/dotnet.cjs.pre.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ if (ENVIRONMENT_IS_GLOBAL) {
}
globalThis.Module.ready = Module.ready;
Module = createDotnetRuntime = globalThis.Module;
if (!createDotnetRuntime.locateFile) createDotnetRuntime.locateFile = createDotnetRuntime.__locateFile = (path) => scriptDirectory + path;
}
else if (typeof createDotnetRuntime === "object") {
Module = { ready: Module.ready, __undefinedConfig: Object.keys(createDotnetRuntime).length === 1 };
Object.assign(Module, createDotnetRuntime);
createDotnetRuntime = Module;
if (!createDotnetRuntime.locateFile) createDotnetRuntime.locateFile = createDotnetRuntime.__locateFile = (path) => scriptDirectory + path;
}
else if (typeof createDotnetRuntime === "function") {
Module = { ready: Module.ready };
Expand All @@ -19,7 +21,10 @@ else if (typeof createDotnetRuntime === "function") {
}
Object.assign(Module, extension);
createDotnetRuntime = Module;
if (!createDotnetRuntime.locateFile) createDotnetRuntime.locateFile = createDotnetRuntime.__locateFile = (path) => scriptDirectory + path;
}
else {
throw new Error("MONO_WASM: Can't locate global Module object or moduleFactory callback of createDotnetRuntime function.")
}
var require = require || undefined;
var __dirname = __dirname || '';
29 changes: 14 additions & 15 deletions src/mono/wasm/runtime/crypto-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export function dotnet_browser_encrypt_decrypt(isEncrypting: boolean, key_buffer
}

if (result.length > output_len) {
console.error(`ENCRYPT DECRYPT: Encrypt/Decrypt length exceeds output length: ${result.length} > ${output_len}`);
console.error(`MONO_WASM_ENCRYPT_DECRYPT: Encrypt/Decrypt length exceeds output length: ${result.length} > ${output_len}`);
return ERR_ARGS;
}

Expand Down Expand Up @@ -91,7 +91,7 @@ function _send_simple_msg(msg: any, prefix: string, output_buffer: number, outpu
}

if (result.length > output_len) {
console.error(`${prefix}: Result length exceeds output length: ${result.length} > ${output_len}`);
console.error(`MONO_WASM_ENCRYPT_DECRYPT: ${prefix}: Result length exceeds output length: ${result.length} > ${output_len}`);
return ERR_ARGS;
}

Expand Down Expand Up @@ -132,7 +132,7 @@ function _send_msg_worker(msg: any): number | any {
const responseJson = JSON.parse(response);

if (responseJson.error !== undefined) {
console.error(`Worker failed with: ${responseJson.error}`);
console.error(`MONO_WASM_ENCRYPT_DECRYPT: Worker failed with: ${responseJson.error}`);
if (responseJson.error_type == "ArgumentsError")
return ERR_ARGS;
if (responseJson.error_type == "WorkerFailedError")
Expand All @@ -144,9 +144,9 @@ function _send_msg_worker(msg: any): number | any {
return responseJson.result;
} catch (err) {
if (err instanceof Error && err.stack !== undefined)
console.error(`${err.stack}`);
console.error(`MONO_WASM_ENCRYPT_DECRYPT: ${err.stack}`);
else
console.error(`_send_msg_worker failed: ${err}`);
console.error(`MONO_WASM_ENCRYPT_DECRYPT: _send_msg_worker failed: ${err}`);
return ERR_OP_FAILED;
}
}
Expand Down Expand Up @@ -202,10 +202,9 @@ class LibraryChannel {

public send_msg(msg: string): string {
try {
let state = Atomics.load(this.comm, this.STATE_IDX);
if (state !== this.STATE_IDLE)
console.log(`send_msg, waiting for idle now, ${state}`);
state = this.wait_for_state(pstate => pstate == this.STATE_IDLE, "waiting");
// const state = Atomics.load(this.comm, this.STATE_IDX);
// if (state !== this.STATE_IDLE) console.debug(`MONO_WASM_ENCRYPT_DECRYPT: send_msg, waiting for idle now, ${state}`);
this.wait_for_state(pstate => pstate == this.STATE_IDLE, "waiting");

this.send_request(msg);
return this.read_response();
Expand All @@ -214,14 +213,13 @@ class LibraryChannel {
throw err;
}
finally {
const state = Atomics.load(this.comm, this.STATE_IDX);
if (state !== this.STATE_IDLE)
console.log(`state at end of send_msg: ${state}`);
// const state = Atomics.load(this.comm, this.STATE_IDX);
// if (state !== this.STATE_IDLE) console.debug(`MONO_WASM_ENCRYPT_DECRYPT: state at end of send_msg: ${state}`);
}
}

public shutdown(): void {
console.debug("Shutting down crypto");
// console.debug("MONO_WASM_ENCRYPT_DECRYPT: Shutting down crypto");
const state = Atomics.load(this.comm, this.STATE_IDX);
if (state !== this.STATE_IDLE)
throw new Error(`OWNER: Invalid sync communication channel state: ${state}`);
Expand All @@ -232,14 +230,15 @@ class LibraryChannel {
Atomics.notify(this.comm, this.STATE_IDX);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
private reset(reason: string): void {
console.debug(`reset: ${reason}`);
// console.debug(`MONO_WASM_ENCRYPT_DECRYPT: reset: ${reason}`);
const state = Atomics.load(this.comm, this.STATE_IDX);
if (state === this.STATE_SHUTDOWN)
return;

if (state === this.STATE_RESET || state === this.STATE_IDLE) {
console.debug(`state is already RESET or idle: ${state}`);
// console.debug(`MONO_WASM_ENCRYPT_DECRYPT: state is already RESET or idle: ${state}`);
return;
}

Expand Down
40 changes: 22 additions & 18 deletions src/mono/wasm/runtime/debug.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import Configuration from "consts:configuration";
import { INTERNAL, Module, MONO, runtimeHelpers } from "./imports";
import { toBase64StringImpl } from "./base64";
import cwraps from "./cwraps";
import { VoidPtr, CharPtr } from "./types/emscripten";
const commands_received : any = new Map<number, CommandResponse>();
const commands_received: any = new Map<number, CommandResponse>();
const wasm_func_map = new Map<number, string>();
commands_received.remove = function (key: number) : CommandResponse { const value = this.get(key); this.delete(key); return value;};
commands_received.remove = function (key: number): CommandResponse { const value = this.get(key); this.delete(key); return value; };
let _call_function_res_cache: any = {};
let _next_call_function_res_id = 0;
let _debugger_buffer_len = -1;
let _debugger_buffer: VoidPtr;
let _assembly_name_str: string; //keep this variable, it's used by BrowserDebugProxy
let _entrypoint_method_token: number; //keep this variable, it's used by BrowserDebugProxy

const regexes:any[] = [];
const regexes: any[] = [];

// V8
// at <anonymous>:wasm-function[1900]:0x83f63
Expand Down Expand Up @@ -66,7 +67,7 @@ export function mono_wasm_add_dbg_command_received(res_ok: boolean, id: number,
}
};
if (commands_received.has(id))
console.warn("Addind an id that already exists in commands_received");
console.warn(`MONO_WASM: Adding an id (${id}) that already exists in commands_received`);
commands_received.set(id, buffer_obj);
}

Expand Down Expand Up @@ -178,7 +179,7 @@ function _create_proxy_from_object_id(objectId: string, details: any) {
if (objectId.startsWith("dotnet:array:")) {
let ret: Array<any>;
if (details.items === undefined) {
ret = details.map ((p: any) => p.value);
ret = details.map((p: any) => p.value);
return ret;
}
if (details.dimensionsDetails === undefined || details.dimensionsDetails.length === 1) {
Expand Down Expand Up @@ -363,27 +364,31 @@ export function mono_wasm_debugger_log(level: number, message_ptr: CharPtr): voi
return;
}

console.debug(`Debugger.Debug: ${message}`);
if (Configuration === "Debug") {
pavelsavara marked this conversation as resolved.
Show resolved Hide resolved
console.debug(`MONO_WASM: Debugger.Debug: ${message}`);
}
}

function _readSymbolMapFile(filename: string): void {
try {
const res = Module.FS_readFile(filename, {flags: "r", encoding: "utf8"});
const res = Module.FS_readFile(filename, { flags: "r", encoding: "utf8" });
res.split(/[\r\n]/).forEach((line: string) => {
const parts:string[] = line.split(/:/);
const parts: string[] = line.split(/:/);
if (parts.length < 2)
return;

parts[1] = parts.splice(1).join(":");
wasm_func_map.set(Number(parts[0]), parts[1]);
});

console.debug(`Loaded ${wasm_func_map.size} symbols`);
} catch (error:any) {
console.debug(`MONO_WASM: Loaded ${wasm_func_map.size} symbols`);
} catch (error: any) {
if (error.errno == 44) // NOENT
console.debug(`Could not find symbols file ${filename}. Ignoring.`);
else
console.log(`Error loading symbol file ${filename}: ${JSON.stringify(error)}`);
if (Configuration === "Debug") {
console.debug(`MONO_WASM: Could not find symbols file ${filename}. Ignoring.`);
}
else
console.log(`MONO_WASM: Error loading symbol file ${filename}: ${JSON.stringify(error)}`);
pavelsavara marked this conversation as resolved.
Show resolved Hide resolved
return;
}
}
Expand All @@ -395,11 +400,10 @@ export function mono_wasm_symbolicate_string(message: string): string {

const origMessage = message;

for (let i = 0; i < regexes.length; i ++)
{
for (let i = 0; i < regexes.length; i++) {
const newRaw = message.replace(new RegExp(regexes[i], "g"), (substring, ...args) => {
const groups = args.find(arg => {
return typeof(arg) == "object" && arg.replaceSection !== undefined;
return typeof (arg) == "object" && arg.replaceSection !== undefined;
});

if (groups === undefined)
Expand All @@ -421,7 +425,7 @@ export function mono_wasm_symbolicate_string(message: string): string {

return origMessage;
} catch (error) {
console.debug(`failed to symbolicate: ${error}`);
console.debug(`MONO_WASM: failed to symbolicate: ${error}`);
return message;
}
}
Expand Down Expand Up @@ -506,7 +510,7 @@ export function setup_proxy_console(id: string, originalConsole: Console, origin
};
}

const originalConsoleObj : any = originalConsole;
const originalConsoleObj: any = originalConsole;
const methods = ["debug", "trace", "warn", "info", "error"];
for (const m of methods) {
if (typeof (originalConsoleObj[m]) !== "function") {
Expand Down