Remove old marshalled-interop API and update MonoSanity sample to use newer API
This commit is contained in:
parent
99a08da321
commit
09eccb52c5
|
|
@ -104,6 +104,19 @@
|
|||
function triggerJsException() {
|
||||
throw new Error('This is a JavaScript exception.');
|
||||
}
|
||||
|
||||
// Normally, applications would use the higher-level APIs for registering invocable
|
||||
// functions, and for invoking them with automatic argument/result marshalling.
|
||||
// But since this project is trying to test low-level Mono runtime capabilities,
|
||||
// we implement our own marshalling here.
|
||||
window.__blazorRegisteredFunctions = {
|
||||
evaluateJsExpression: function (dotNetStringExpression) {
|
||||
var result = eval(dotnetStringToJavaScriptString(dotNetStringExpression));
|
||||
return result === null || result === undefined
|
||||
? result // Pass through null/undefined so we can verify this is handled upstream
|
||||
: javaScriptStringToDotNetString(result.toString());
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -43,6 +43,21 @@
|
|||
}
|
||||
};
|
||||
|
||||
window.dotnetStringToJavaScriptString = function dotnetStringToJavaScriptString(mono_obj) {
|
||||
if (mono_obj === 0)
|
||||
return null;
|
||||
var mono_string_get_utf8 = Module.cwrap('mono_wasm_string_get_utf8', 'number', ['number']);
|
||||
var raw = mono_string_get_utf8(mono_obj);
|
||||
var res = Module.UTF8ToString(raw);
|
||||
Module._free(raw);
|
||||
return res;
|
||||
};
|
||||
|
||||
window.javaScriptStringToDotNetString = function dotnetStringToJavaScriptString(javaScriptString) {
|
||||
var mono_string = Module.cwrap('mono_wasm_string_from_js', 'number', ['string']);
|
||||
return mono_string(javaScriptString);
|
||||
};
|
||||
|
||||
function preloadAssemblies(loadAssemblyUrls) {
|
||||
var loadBclAssemblies = [
|
||||
'mscorlib',
|
||||
|
|
@ -77,21 +92,10 @@
|
|||
xhr.onerror = onerror;
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
function dotnetStringToJavaScriptString(mono_obj) {
|
||||
if (mono_obj === 0)
|
||||
return null;
|
||||
var mono_string_get_utf8 = Module.cwrap('mono_wasm_string_get_utf8', 'number', ['number']);
|
||||
var raw = mono_string_get_utf8(mono_obj);
|
||||
var res = Module.UTF8ToString(raw);
|
||||
Module._free(raw);
|
||||
return res;
|
||||
}
|
||||
|
||||
function callMethod(method, target, args) {
|
||||
var stack = Module.Runtime.stackSave();
|
||||
var invoke_method = Module.cwrap('mono_wasm_invoke_method', 'number', ['number', 'number', 'number']);
|
||||
var mono_string = Module.cwrap('mono_wasm_string_from_js', 'number', ['string']);
|
||||
|
||||
try {
|
||||
var argsBuffer = Module.Runtime.stackAlloc(args.length);
|
||||
|
|
@ -103,7 +107,7 @@
|
|||
Module.setValue(managedInt, argVal, 'i32');
|
||||
Module.setValue(argsBuffer + i * 4, managedInt, 'i32');
|
||||
} else if (typeof argVal === 'string') {
|
||||
var managedString = mono_string(argVal);
|
||||
var managedString = javaScriptStringToDotNetString(argVal);
|
||||
Module.setValue(argsBuffer + i * 4, managedString, 'i32');
|
||||
} else {
|
||||
throw new Error('Unsupported arg type: ' + typeof argVal);
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@ namespace MonoSanityClient
|
|||
|
||||
public static string EvaluateJavaScript(string expression)
|
||||
{
|
||||
var result = Runtime.InvokeJS(expression, out var resultIsException);
|
||||
if (resultIsException != 0)
|
||||
var result = Runtime.InvokeJS<string, object, object, string>(out var exceptionMessage, "evaluateJsExpression", expression, null, null);
|
||||
if (exceptionMessage != null)
|
||||
{
|
||||
return $".NET got exception: {result}";
|
||||
return $".NET got exception: {exceptionMessage}";
|
||||
}
|
||||
|
||||
return $".NET received: {(result ?? "(NULL)")}";
|
||||
|
|
|
|||
|
|
@ -7,4 +7,9 @@
|
|||
<!-- Local alternative to <PackageReference Include="Microsoft.Blazor.Build" /> -->
|
||||
<Import Project="..\..\src\Microsoft.Blazor.Build\ReferenceFromSource.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Share the WebAssembly.Runtime.cs source here so we get access to the same interop externs -->
|
||||
<Compile Include="..\..\src\Microsoft.Blazor.Browser\Interop\WebAssembly.Runtime.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace WebAssembly
|
||||
{
|
||||
internal static class Runtime
|
||||
{
|
||||
// The exact namespace, type, and method name must match the corresponding entry in
|
||||
// driver.c in the Mono distribution
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public static extern string InvokeJS(string str, out int resultIsException);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using WebAssembly;
|
||||
|
||||
namespace Microsoft.Blazor.Browser.Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods for invoking preregistered JavaScript functions from .NET code.
|
||||
/// </summary>
|
||||
public static class RegisteredFunction
|
||||
{
|
||||
/// <summary>
|
||||
/// Invokes the JavaScript function registered with the specified identifier.
|
||||
///
|
||||
/// When using this overload, all arguments will be supplied as <see cref="System.Object" />
|
||||
/// references, meaning that any reference types will be boxed. If you are passing
|
||||
/// 3 or fewer arguments, it is preferable to instead call the overload that
|
||||
/// specifies generic type arguments for each argument.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
|
||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||
/// <param name="args">The arguments to pass, each of which will be supplied as a <see cref="System.Object" /> instance.</param>
|
||||
/// <returns>The result of the function invocation.</returns>
|
||||
public static TRes Invoke<TRes>(string identifier, params object[] args)
|
||||
{
|
||||
var result = Runtime.InvokeJSArray<TRes>(out var exception, identifier, args);
|
||||
return exception != null
|
||||
? throw new JavaScriptException(exception)
|
||||
: result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the JavaScript function registered with the specified identifier.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
|
||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||
/// <returns>The result of the function invocation.</returns>
|
||||
public static TRes Invoke<T0, TRes>(string identifier)
|
||||
{
|
||||
var result = Runtime.InvokeJS<object, object, object, TRes>(out var exception, identifier, null, null, null);
|
||||
return exception != null
|
||||
? throw new JavaScriptException(exception)
|
||||
: result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the JavaScript function registered with the specified identifier.
|
||||
/// </summary>
|
||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
||||
/// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
|
||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||
/// <param name="arg0">The first argument.</param>
|
||||
/// <returns>The result of the function invocation.</returns>
|
||||
public static TRes Invoke<T0, TRes>(string identifier, T0 arg0)
|
||||
{
|
||||
var result = Runtime.InvokeJS<T0, object, object, TRes>(out var exception, identifier, arg0, null, null);
|
||||
return exception != null
|
||||
? throw new JavaScriptException(exception)
|
||||
: result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the JavaScript function registered with the specified identifier.
|
||||
/// </summary>
|
||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
||||
/// <typeparam name="T1">The type of the second argument.</typeparam>
|
||||
/// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
|
||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||
/// <param name="arg0">The first argument.</param>
|
||||
/// <param name="arg1">The second argument.</param>
|
||||
/// <returns>The result of the function invocation.</returns>
|
||||
public static TRes Invoke<T0, T1, TRes>(string identifier, T0 arg0, T1 arg1)
|
||||
{
|
||||
var result = Runtime.InvokeJS<T0, T1, object, TRes>(out var exception, identifier, arg0, arg1, null);
|
||||
return exception != null
|
||||
? throw new JavaScriptException(exception)
|
||||
: result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the JavaScript function registered with the specified identifier.
|
||||
/// </summary>
|
||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
||||
/// <typeparam name="T1">The type of the second argument.</typeparam>
|
||||
/// <typeparam name="T2">The type of the third argument.</typeparam>
|
||||
/// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
|
||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||
/// <param name="arg0">The first argument.</param>
|
||||
/// <param name="arg1">The second argument.</param>
|
||||
/// <param name="arg2">The third argument.</param>
|
||||
/// <returns>The result of the function invocation.</returns>
|
||||
public static TRes Invoke<T0, T1, T2, TRes>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
||||
{
|
||||
var result = Runtime.InvokeJS<T0, T1, T2, TRes>(out var exception, identifier, arg0, arg1, arg2);
|
||||
return exception != null
|
||||
? throw new JavaScriptException(exception)
|
||||
: result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +1,19 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Blazor.Browser.Interop;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace WebAssembly
|
||||
{
|
||||
internal static class Runtime
|
||||
{
|
||||
public static string EvaluateJavaScript(string expression)
|
||||
{
|
||||
var result = InvokeJS(expression, out var resultIsException);
|
||||
|
||||
if (resultIsException != 0)
|
||||
{
|
||||
throw new JavaScriptException(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// The exact namespace, type, and method name must match the corresponding entry in
|
||||
// The exact namespace, type, and method names must match the corresponding entry in
|
||||
// driver.c in the Mono distribution
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
static extern string InvokeJS(string str, out int resultIsException);
|
||||
|
||||
// The exact namespace, type, and method name must match the corresponding entry in
|
||||
// driver.c in the Mono distribution
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public static extern object InvokeJSUnmarshalled(string funcExpression, object[] args, out int resultIsException);
|
||||
public static extern TRes InvokeJS<T0, T1, T2, TRes>(out string exception, string funcName, T0 arg0, T1 arg1, T2 arg2);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public static extern TRes InvokeJSArray<TRes>(out string exception, string funcName, object[] args);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ namespace Microsoft.Blazor.Browser
|
|||
{
|
||||
public Renderer()
|
||||
{
|
||||
WebAssembly.Runtime.EvaluateJavaScript("console.log('Renderer')");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ namespace Microsoft.Blazor.E2ETest.Tests
|
|||
SetValue(Browser, "callJsEvalExpression", "triggerJsException()");
|
||||
Browser.FindElement(By.CssSelector("#callJs button")).Click();
|
||||
var result = GetValue(Browser, "callJsResult");
|
||||
Assert.StartsWith(".NET got exception: Error: This is a JavaScript exception.", result);
|
||||
Assert.StartsWith(".NET got exception: This is a JavaScript exception.", result);
|
||||
|
||||
// Also verify we got a stack trace
|
||||
Assert.Contains("at triggerJsException", result);
|
||||
|
|
|
|||
Loading…
Reference in New Issue