Interop with JS objects? (e.g. System.Runtime.InteropServices.JavaScript.JSObject) #508
-
Just playing with calling into C# from JS using the bootstrapper. If I pass a JS object from the JS side to a method accepting an Is there a supported ( or at least likely-to-work ) way to interact with these instances? Obviously I can pass structured objects using json, protobuf or similar, but if there is a more direct way I would prefer that :) |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
You would be interested in this discussion: #463 |
Beta Was this translation helpful? Give feedback.
-
I wish I had seen this post sooner cause you can use JSObject, at least in .NET 7(haven't tested in earlier versions), but it's just not really well documented. Maybe this will be helpful to others, but I never found any examples of JSObject being used in any meaningful way, and eventually worked out how to call instance methods on it. Because JSImport only works on static methods AFAIK, you need to declare static methods to act as proxies for instance methods, and take the JSObject as a reference. This is similar to approaches used by Uno types like RenderingLoopAnimator, where they take JSObjectHandle ID's as parameters to static methods imported with JSImport, and in the typescript/JS then call instance methods on the object. The difference being now we can use .NET runtime JSObject below instead of the Uno JSObjectHandle. (Personally, using InvokeJSWithInterop with an object implementing IJSObject feels alot more productive and natural because it doesn't require declaring static JS methods as proxies. This is what I do in my JQuery wrapper. Behind the scenes though, JSObject is more sophisticated and there are items open in .NET runtime repo to plan to expand its capabilities for calling methods, so hopefully it'll get easier in the future: dotnet/runtime#78906) Here's an example of two functions, one returning a JS object(in this case a reference to a DOM node), and another taking a JS object as a parameter and calling an instance method on it. Important! You must fully qualify JSObject or make sure you do not have a Map static JS methods to static C# methods: using System.Runtime.InteropServices.JavaScript;
public partial class JSObjectExample
{
[JSImport("globalThis.findElement")]
public static partial JSObject FindElement(string id);
[JSImport("globalThis.getClass")]
public static partial string GetClass(JSObject obj); From WASM project, use InvokeJS to declare the static JS methods (could have been a separate JS/typescript file). // findElement takes a string and returns an object
// getClass takes an object, calls an instance method on that object, and returns a string
WebAssemblyRuntime.InvokeJS("""
globalThis.findElement = function(id) { return document.getElementById(id); }
globalThis.getClass = function(obj) { return obj.getAttribute('class'); }
""");
// Call the static JS functions from C#
JSObject element = JSObjectExample.FindElement("uno-body");
// Pass the handle to another method
var elementClasses = JSObjectExample.GetClass(element);
Console.WriteLine("Class string: " + elementClasses); |
Beta Was this translation helpful? Give feedback.
You would be interested in this discussion: #463