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] preparation for module encapsulation #60928

Merged
merged 2 commits into from
Oct 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
425 changes: 209 additions & 216 deletions src/mono/wasm/runtime-test.js

Large diffs are not rendered by default.

42 changes: 1 addition & 41 deletions src/mono/wasm/runtime/corebindings.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,47 +30,7 @@ extern MonoObject* mono_wasm_web_socket_send (int webSocket_js_handle, void* buf
extern MonoObject* mono_wasm_web_socket_receive (int webSocket_js_handle, void* buffer_ptr, int offset, int length, void* response_ptr, int *thenable_js_handle, int *is_exception);
extern MonoObject* mono_wasm_web_socket_close (int webSocket_js_handle, int code, MonoString * reason, int wait_for_close_received, int *thenable_js_handle, int *is_exception);
extern MonoString* mono_wasm_web_socket_abort (int webSocket_js_handle, int *is_exception);

// Compiles a JavaScript function from the function data passed.
// Note: code snippet is not a function definition. Instead it must create and return a function instance.
EM_JS(MonoObject*, compile_function, (int snippet_ptr, int len, int *is_exception), {
try {
var data = INTERNAL.string_decoder.decode (snippet_ptr, snippet_ptr + len);
var wrapper = '(function () { ' + data + ' })';
var funcFactory = eval(wrapper);
var func = funcFactory();
if (typeof func !== 'function') {
throw new Error('Code must return an instance of a JavaScript function. '
+ 'Please use `return` statement to return a function.');
}
setValue (is_exception, 0, "i32");
return BINDING.js_to_mono_obj (func, true);
}
catch (e)
{
res = e.toString ();
setValue (is_exception, 1, "i32");
if (res === null || res === undefined)
res = "unknown exception";
return BINDING.js_to_mono_obj (res, true);
}
});

static MonoObject*
mono_wasm_compile_function (MonoString *str, int *is_exception)
{
if (str == NULL)
return NULL;
//char *native_val = mono_string_to_utf8 (str);
mono_unichar2 *native_val = mono_string_chars (str);
int native_len = mono_string_length (str) * 2;

MonoObject* native_res = compile_function((int)native_val, native_len, is_exception);
mono_free (native_val);
if (native_res == NULL)
return NULL;
return native_res;
}
extern MonoObject* mono_wasm_compile_function (MonoString *str, int *is_exception);

void core_initialize_internals ()
{
Expand Down
21 changes: 11 additions & 10 deletions src/mono/wasm/runtime/cs-to-js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

import { mono_wasm_new_root, WasmRoot } from "./roots";
import {
GCHandle, Int32Ptr, JSHandle, JSHandleDisposed, MonoArray,
MonoArrayNull, MonoObject, MonoObjectNull, MonoString, MonoClass,
MonoClassNull, MonoType, MonoTypeNull
GCHandle, Int32Ptr, JSHandleDisposed, MonoArray,
MonoArrayNull, MonoObject, MonoObjectNull, MonoString,
MonoType, MonoTypeNull
} from "./types";
import { Module, runtimeHelpers } from "./modules";
import { conv_string } from "./strings";
Expand Down Expand Up @@ -82,7 +82,8 @@ function _unbox_cs_owned_root_as_js_object(root: WasmRoot<any>) {
return js_obj;
}

function _unbox_mono_obj_root_with_known_nonprimitive_type_impl(root: WasmRoot<any>, type: MarshalType, typePtr: MonoType, unbox_buffer: VoidPtr) : any {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function _unbox_mono_obj_root_with_known_nonprimitive_type_impl(root: WasmRoot<any>, type: MarshalType, typePtr: MonoType, unbox_buffer: VoidPtr): any {
//See MARSHAL_TYPE_ defines in driver.c
switch (type) {
case MarshalType.INT64:
Expand Down Expand Up @@ -121,25 +122,25 @@ function _unbox_mono_obj_root_with_known_nonprimitive_type_impl(root: WasmRoot<a
case MarshalType.VOID:
return undefined;
default:
throw new Error(`no idea on how to unbox object of MarshalType ${type} at offset ${root.value} (root address is ${root.get_address()})`);
throw new Error(`no idea on how to unbox object of MarshalType ${type} at offset ${root.value} (root address is ${root.get_address()})`);
}
}

export function _unbox_mono_obj_root_with_known_nonprimitive_type(root: WasmRoot<any>, type: MarshalType, unbox_buffer: VoidPtr) : any {
export function _unbox_mono_obj_root_with_known_nonprimitive_type(root: WasmRoot<any>, type: MarshalType, unbox_buffer: VoidPtr): any {
if (type >= MarshalError.FIRST)
throw new Error(`Got marshaling error ${type} when attempting to unbox object at address ${root.value} (root located at ${root.get_address()})`);

let typePtr = MonoTypeNull;
if ((type === MarshalType.VT) || (type == MarshalType.OBJECT)) {
typePtr = <MonoType><any>Module.HEAPU32[<any>unbox_buffer >>> 2];
if (<number><any>typePtr < 1024)
throw new Error(`Got invalid MonoType ${typePtr} for object at address ${root.value} (root located at ${root.get_address()})`);
}

return _unbox_mono_obj_root_with_known_nonprimitive_type_impl(root, type, typePtr, unbox_buffer);
}

export function _unbox_mono_obj_root(root: WasmRoot<any>) : any {
export function _unbox_mono_obj_root(root: WasmRoot<any>): any {
if (root.value === 0)
return undefined;

Expand Down Expand Up @@ -350,7 +351,7 @@ function _unbox_task_root_as_promise(root: WasmRoot<MonoObject>) {
return result;
}

export function _unbox_ref_type_root_as_js_object(root: WasmRoot<MonoObject>) {
export function _unbox_ref_type_root_as_js_object(root: WasmRoot<MonoObject>): any {

if (root.value === MonoObjectNull)
return null;
Expand Down
16 changes: 8 additions & 8 deletions src/mono/wasm/runtime/cwraps.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import {
CharPtr, CharPtrPtr, Int32Ptr,
MonoArray, MonoAssembly, MonoClass,
MonoMethod, MonoObject, MonoString,
MonoType, VoidPtr
import {
CharPtr, CharPtrPtr, Int32Ptr,
MonoArray, MonoAssembly, MonoClass,
MonoMethod, MonoObject, MonoString,
MonoType, VoidPtr
} from "./types";
import { Module } from "./modules";

Expand Down Expand Up @@ -55,8 +55,8 @@ const fn_signatures: [ident: string, returnType: string | null, argTypes?: strin
["mono_wasm_typed_array_new", "number", ["number", "number", "number", "number"]],
["mono_wasm_class_get_type", "number", ["number"]],
["mono_wasm_type_get_class", "number", ["number"]],
["mono_wasm_get_type_name", 'string', ['number']],
["mono_wasm_get_type_aqn", 'string', ['number']],
["mono_wasm_get_type_name", "string", ["number"]],
["mono_wasm_get_type_aqn", "string", ["number"]],
["mono_wasm_unbox_rooted", "number", ["number"]],

//DOTNET
Expand Down Expand Up @@ -121,7 +121,7 @@ export interface t_Cwraps {

//DOTNET
mono_wasm_string_from_js(str: string): MonoString;

//INTERNAL
mono_wasm_exit(exit_code: number): number;
mono_wasm_enable_on_demand_gc(enable: number): void;
Expand Down
57 changes: 2 additions & 55 deletions src/mono/wasm/runtime/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@
void core_initialize_internals ();
#endif

extern MonoString* mono_wasm_invoke_js (MonoString *str, int *is_exception);

// Blazor specific custom routines - see dotnet_support.js for backing code
extern void* mono_wasm_invoke_js_blazor (MonoString **exceptionMessage, void *callInfo, void* arg0, void* arg1, void* arg2);
// The following two are for back-compat and will eventually be removed
extern void* mono_wasm_invoke_js_marshalled (MonoString **exceptionMessage, void *asyncHandleLongPtr, MonoString *funcName, MonoString *argsJson);
extern void* mono_wasm_invoke_js_unmarshalled (MonoString **exceptionMessage, MonoString *funcName, void* arg0, void* arg1, void* arg2);

void mono_wasm_enable_debugging (int);

Expand Down Expand Up @@ -137,55 +136,6 @@ static MonoDomain *root_domain;

#define RUNTIMECONFIG_BIN_FILE "runtimeconfig.bin"

static MonoString*
mono_wasm_invoke_js (MonoString *str, int *is_exception)
{
if (str == NULL)
return NULL;

int native_res_len = 0;
int *p_native_res_len = &native_res_len;

mono_unichar2 *native_res = (mono_unichar2*)EM_ASM_INT ({
var js_str = INTERNAL.string_decoder.copy ($0);

try {
var res = eval (js_str);
setValue ($2, 0, "i32");
if (res === null || res === undefined)
return 0;
else
res = res.toString ();
} catch (e) {
res = e.toString();
setValue ($2, 1, "i32");
if (res === null || res === undefined)
res = "unknown exception";

var stack = e.stack;
if (stack) {
// Some JS runtimes insert the error message at the top of the stack, some don't,
// so normalize it by using the stack as the result if it already contains the error
if (stack.startsWith(res))
res = stack;
else
res += "\n" + stack;
}
}
var buff = Module._malloc((res.length + 1) * 2);
stringToUTF16 (res, buff, (res.length + 1) * 2);
setValue ($1, res.length, "i32");
return buff;
}, (int)str, p_native_res_len, is_exception);

if (native_res == NULL)
return NULL;

MonoString *res = mono_string_new_utf16 (mono_domain_get (), native_res, native_res_len);
free (native_res);
return res;
}

static void
wasm_trace_logger (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data)
{
Expand Down Expand Up @@ -492,9 +442,6 @@ void mono_initialize_internals ()

// Blazor specific custom routines - see dotnet_support.js for backing code
mono_add_internal_call ("WebAssembly.JSInterop.InternalCalls::InvokeJS", mono_wasm_invoke_js_blazor);
// The following two are for back-compat and will eventually be removed
mono_add_internal_call ("WebAssembly.JSInterop.InternalCalls::InvokeJSMarshalled", mono_wasm_invoke_js_marshalled);
mono_add_internal_call ("WebAssembly.JSInterop.InternalCalls::InvokeJSUnmarshalled", mono_wasm_invoke_js_unmarshalled);

#ifdef CORE_BINDINGS
core_initialize_internals();
Expand Down
46 changes: 39 additions & 7 deletions src/mono/wasm/runtime/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
mono_load_runtime_and_bcl_args, mono_wasm_load_config,
mono_wasm_setenv, mono_wasm_set_runtime_options,
mono_wasm_load_data_archive, mono_wasm_asm_loaded,
mono_wasm_invoke_js_blazor, mono_wasm_invoke_js_marshalled, mono_wasm_invoke_js_unmarshalled, mono_wasm_set_main_args
mono_wasm_set_main_args
} from "./startup";
import { mono_set_timeout, schedule_background_exec } from "./scheduling";
import { mono_wasm_load_icu_data, mono_wasm_get_icudt_name } from "./icu";
Expand All @@ -39,7 +39,10 @@ import {
import {
call_static_method, mono_bind_static_method, mono_call_assembly_entry_point,
mono_method_resolve,
mono_wasm_compile_function,
mono_wasm_get_by_index, mono_wasm_get_global_object, mono_wasm_get_object_property,
mono_wasm_invoke_js,
mono_wasm_invoke_js_blazor,
mono_wasm_invoke_js_with_args, mono_wasm_set_by_index, mono_wasm_set_object_property,
_get_args_root_buffer_for_method_call, _get_buffer_for_method_call,
_handle_exception_for_call, _teardown_after_call
Expand All @@ -65,6 +68,10 @@ export const MONO: MONO = <any>{
mono_wasm_new_root,
mono_wasm_release_roots,

// for Blazor's future!
mono_wasm_add_assembly: cwraps.mono_wasm_add_assembly,
mono_wasm_load_runtime: cwraps.mono_wasm_load_runtime,

config: runtimeHelpers.config,
loaded_files: runtimeHelpers.loaded_files,

Expand Down Expand Up @@ -121,11 +128,32 @@ function export_to_emscripten(dotnet: any, mono: any, binding: any, internal: an

// here we expose objects used in tests to global namespace
if (!module.no_global_exports) {
(<any>globalThis).DOTNET = dotnet;
(<any>globalThis).MONO = mono;
(<any>globalThis).BINDING = binding;
(<any>globalThis).INTERNAL = internal;
(<any>globalThis).Module = module;
const warnWrap = (name: string, value: any) => {
if (typeof ((<any>globalThis)[name]) !== "undefined") {
// it already exists in the global namespace
return;
}
let warnOnce = true;
Object.defineProperty(globalThis, name, {
get: () => {
if (warnOnce) {
const stack = (new Error()).stack;
const nextLine = stack ? stack.substr(stack.indexOf("\n", 8) + 1) : "";
console.warn(`global ${name} is obsolete, please use Module.${name} instead ${nextLine}`);
warnOnce = false;
}
return value;
}
});
};
warnWrap("MONO", mono);
warnWrap("BINDING", binding);

// Blazor back compat
warnWrap("cwrap", Module.cwrap);
warnWrap("addRunDependency", Module.addRunDependency);
warnWrap("removeRunDependency", Module.removeRunDependency);
}
}

Expand All @@ -143,9 +171,8 @@ const linker_exports = {
schedule_background_exec,

// also keep in sync with driver.c
mono_wasm_invoke_js,
mono_wasm_invoke_js_blazor,
mono_wasm_invoke_js_marshalled,
mono_wasm_invoke_js_unmarshalled,

// also keep in sync with corebindings.c
mono_wasm_invoke_js_with_args,
Expand All @@ -168,6 +195,7 @@ const linker_exports = {
mono_wasm_web_socket_receive,
mono_wasm_web_socket_close,
mono_wasm_web_socket_abort,
mono_wasm_compile_function,

// also keep in sync with pal_icushim_static.c
mono_wasm_load_icu_data,
Expand Down Expand Up @@ -232,6 +260,10 @@ export interface MONO {
mono_wasm_new_root: typeof mono_wasm_new_root;
mono_wasm_release_roots: typeof mono_wasm_release_roots;

// for Blazor's future!
mono_wasm_add_assembly: typeof cwraps.mono_wasm_add_assembly,
mono_wasm_load_runtime: typeof cwraps.mono_wasm_load_runtime,

loaded_files: string[];
config: MonoConfig | MonoConfigError,
}
Expand Down
8 changes: 2 additions & 6 deletions src/mono/wasm/runtime/library-dotnet.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,9 @@
"use strict";

const DotNetSupportLib = {
// this will become globalThis.DOTNET
$DOTNET: {},
// this will become globalThis.MONO
$MONO: {},
// this will become globalThis.BINDING
$BINDING: {},
// this will become globalThis.INTERNAL
$INTERNAL: {},
// this line will be executed on runtime, populating the objects with methods
$DOTNET__postset: "__dotnet_runtime.INTERNAL.export_to_emscripten (DOTNET, MONO, BINDING, INTERNAL, Module);",
Expand All @@ -31,9 +27,8 @@ const linked_functions = [
"schedule_background_exec",

// driver.c
"mono_wasm_invoke_js",
"mono_wasm_invoke_js_blazor",
"mono_wasm_invoke_js_marshalled",
"mono_wasm_invoke_js_unmarshalled",

// corebindings.c
"mono_wasm_invoke_js_with_args",
Expand All @@ -56,6 +51,7 @@ const linked_functions = [
"mono_wasm_web_socket_receive",
"mono_wasm_web_socket_close",
"mono_wasm_web_socket_abort",
"mono_wasm_compile_function",

// pal_icushim_static.c
"mono_wasm_load_icu_data",
Expand Down
14 changes: 7 additions & 7 deletions src/mono/wasm/runtime/memory.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
import { Module, MONO } from './modules'
import { Module } from "./modules";

let _temp_mallocs : Array<Array<VoidPtr> | null> = [];
const _temp_mallocs: Array<Array<VoidPtr> | null> = [];

export function temp_malloc (size : number) : VoidPtr {
export function temp_malloc(size: number): VoidPtr {
if (!_temp_mallocs || !_temp_mallocs.length)
throw new Error("No temp frames have been created at this point");

const frame = _temp_mallocs[_temp_mallocs.length - 1] || [];
const result = Module._malloc(size);
frame.push(result);
_temp_mallocs[_temp_mallocs.length - 1] = frame;
return result;
}

export function _create_temp_frame () {
export function _create_temp_frame(): void {
_temp_mallocs.push(null);
}

export function _release_temp_frame () {
export function _release_temp_frame(): void {
if (!_temp_mallocs.length)
throw new Error("No temp frames have been created at this point");

const frame = _temp_mallocs.pop();
if (!frame)
return;

for (let i = 0, l = frame.length; i < l; i++)
Module._free(frame[i]);
}
Loading