From c952f068eeea83fda07e094aa531c8b0e4c09a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Thu, 4 Nov 2021 21:06:18 +0100 Subject: [PATCH 1/3] Revert back to eval in wasm InvokeJS with modularization support . Wrap code to evaluate in a function with MONO, BINDING, INTERNAL and module as local variables. Added tests for running js expressions. Co-authored-by: Pavel Savara --- .../InteropServices/JavaScript/MarshalTests.cs | 14 ++++++++++++++ src/mono/wasm/runtime/method-calls.ts | 12 ++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs index 101ce90eaa272..3b5b511f26c4f 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs @@ -871,5 +871,19 @@ public static void InternedStringReturnValuesWork() Assert.Equal("s: 1 length: 1", HelperMarshal._stringResource); Assert.Equal("1", HelperMarshal._stringResource2); } + + [Fact] + public static void InvokeJSExpression() + { + var result = Runtime.InvokeJS(@"1 + 2"); + Assert.Equal("3", result); + } + + [Fact] + public static void InvokeJSNullExpression() + { + var result = Runtime.InvokeJS(@"null"); + Assert.Null(result); + } } } diff --git a/src/mono/wasm/runtime/method-calls.ts b/src/mono/wasm/runtime/method-calls.ts index a2dd26d51f7e6..3328b2ebdc56b 100644 --- a/src/mono/wasm/runtime/method-calls.ts +++ b/src/mono/wasm/runtime/method-calls.ts @@ -541,18 +541,18 @@ export function mono_wasm_invoke_js(code: MonoString, is_exception: Int32Ptr): M if (code === MonoStringNull) return MonoStringNull; - const js_code = conv_string(code); + const js_code = conv_string(code)!; try { - const closure = { - Module, MONO, BINDING, INTERNAL + const closedEval = function (Module: EmscriptenModule, MONO: any, BINDING: any, INTERNAL: any, code: string) { + return eval(code); }; - const fn_body_template = `const {Module, MONO, BINDING, INTERNAL} = __closure; const __fn = function(){ ${js_code} }; return __fn.call(__closure);`; - const fn_defn = new Function("__closure", fn_body_template); - const res = fn_defn(closure); + let res = closedEval(Module, MONO, BINDING, INTERNAL, js_code); Module.setValue(is_exception, 0, "i32"); if (typeof res === "undefined" || res === null) return MonoStringNull; + + res = res.toString(); if (typeof res !== "string") return wrap_error(is_exception, `Return type of InvokeJS is string. Can't marshal response of type ${typeof res}.`); return js_string_to_mono_string(res); From f12a11aeca20bc66da9ac8503cc8ff40cf9966cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Thu, 4 Nov 2021 21:41:39 +0100 Subject: [PATCH 2/3] Add test for JS expression returning an "undefined". Add test ensuring global scope separation. --- .../InteropServices/JavaScript/MarshalTests.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs index 3b5b511f26c4f..fb52d1d58f4a7 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs @@ -885,5 +885,19 @@ public static void InvokeJSNullExpression() var result = Runtime.InvokeJS(@"null"); Assert.Null(result); } + + [Fact] + public static void InvokeJSUndefinedExpression() + { + var result = Runtime.InvokeJS(@"undefined"); + Assert.Null(result); + } + + [Fact] + public static void InvokeJSNotInGlobalScope() + { + var result = Runtime.InvokeJS(@"var test_local_variable_name = 5; globalThis.test_local_variable_name"); + Assert.Null(result); + } } } From 6cb4266bf1bafd00e2081e8e56731a7e72f431a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Fri, 5 Nov 2021 12:25:45 +0100 Subject: [PATCH 3/3] Drop test for result type after calling toString. --- src/mono/wasm/runtime/method-calls.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/mono/wasm/runtime/method-calls.ts b/src/mono/wasm/runtime/method-calls.ts index 3328b2ebdc56b..3567fc822d078 100644 --- a/src/mono/wasm/runtime/method-calls.ts +++ b/src/mono/wasm/runtime/method-calls.ts @@ -547,15 +547,12 @@ export function mono_wasm_invoke_js(code: MonoString, is_exception: Int32Ptr): M const closedEval = function (Module: EmscriptenModule, MONO: any, BINDING: any, INTERNAL: any, code: string) { return eval(code); }; - let res = closedEval(Module, MONO, BINDING, INTERNAL, js_code); + const res = closedEval(Module, MONO, BINDING, INTERNAL, js_code); Module.setValue(is_exception, 0, "i32"); if (typeof res === "undefined" || res === null) return MonoStringNull; - res = res.toString(); - if (typeof res !== "string") - return wrap_error(is_exception, `Return type of InvokeJS is string. Can't marshal response of type ${typeof res}.`); - return js_string_to_mono_string(res); + return js_string_to_mono_string(res.toString()); } catch (ex) { return wrap_error(is_exception, ex); }