ClearScript icon indicating copy to clipboard operation
ClearScript copied to clipboard

Support a custom converter to wrap / unwrap objects before passing to v8

Open viceice opened this issue 3 years ago • 9 comments

I like to have an option to use Newtonsoft.JSON like JsonConverterAttribute (optionally added via CustomAttributeLoader when i can add atttribute to external objects), so clearscript calls my converter when passing objects between v8 and managed code.

EG: i like to wrap all Managed Guid to my JsUuid struct when passing to v8 and unwrap when calling managed code from v8 again.

This is highly related to #396


  • #395
  • #396

viceice avatar Jul 01 '22 08:07 viceice

Hi @viceice,

One of ClearScript's main goals is to allow script code to use .NET objects without conversion.

There are exceptions, of course. Without automatic conversion of fundamental values – numbers, strings, Booleans, etc. – using ClearScript would be very painful, and automatic conversion of some common objects – e.g., timestamps and async primitives – is too convenient to do without, at least on an opt-in basis.

Can you say more about the scenario(s) you have in mind? Why do you believe that arbitrary custom conversion – especially from one managed type to another – would be a broadly useful addition to ClearScript?

Thanks!

ClearScriptLib avatar Jul 06 '22 03:07 ClearScriptLib

I've an API which uses Dictionary like types, so it has a string / object indexer like this

public interface IDataObject {
  object this[string key] { get; set; }
}

And i like to create some handler / converter, which can be applied to that indexer and is called by clearscript when interop between js / cs.

Currently my workaround is to add a static global class to js where i do the conversion. As a sample it converts anonymous javascript objects (ScriptObject) to a dotnet JSON like object, which can be again used by our other API's.

So my use-case is just to remove the extra object to js and use some kind of attribute based type converter. We don't want to make our whole API aware of the native js objects.

viceice avatar Jul 11 '22 09:07 viceice

Hi @viceice,

Sorry, please clarify. Why is conversion necessary? In other words, why can't the script code use your .NET objects "as is"?

Thanks!

ClearScriptLib avatar Jul 11 '22 15:07 ClearScriptLib

because sometimes i need to merge parts of dotnet object to js objects (not a big issue) but i also need to allow generating some js object which needs to be converted to dotnet when passing to certain functions. it's some complicated API and not easy to solve.

The other solution will be to create a wrapper object wich will do the comversion for our API objects, but that will be a lot of work. We've a big inheritance hierachy. so the wrapper needs to understand a lot more different types, so effectively duplicating our whole api.

viceice avatar Jul 11 '22 20:07 viceice

i also need to allow generating some js object which needs to be converted to dotnet when passing to certain functions

If we understand correctly, you have a large, complex .NET API, and you believe that exporting it "as is" would result in a suboptimal JavaScript experience, so you'd like to transform some elements on the fly to make them more JavaScript-friendly. Is that correct?

ClearScriptLib avatar Jul 12 '22 01:07 ClearScriptLib

yes. i currently get it working without but handling in Javascript isn't that nice because of additional helper methods on separate global object to handle the conversion

viceice avatar Jul 12 '22 05:07 viceice

Hi @viceice,

i currently get it working without but handling in Javascript isn't that nice

It's great to hear that you found a temporary solution, but yes, we can see how customization at the host-script boundary could improve things further. In truth, requests for this kind of capability have been popping up sporadically for a long time.

Our main concern is that marshaling in ClearScript is a complicated affair with lots of subtlety and a vast number of edge cases, and this new feature would have to be closely tied in with it. The trick will be to design something that's generally useful and provides the necessary hooks without breaking existing functionality or incurring significant overhead.

Could you take us through your vision for this feature step by step? You mentioned something about an attribute similar to JsonConverter, but the scenario here is more complicated.

For one thing, ClearScript marshals values and objects mostly by reference; we aren't talking about serialization a-la JSON.

Also, the type of a marshaled item isn't always its actual type; the item could be type restricted, meaning that it exposes only the members of a base class or interface. For example, an integer could be marshaled as IConvertible. The bottom line is that an item's type is probably not the right way to acquire a converter in all cases.

Another issue is that script objects are mostly all of the same type on the managed side, so there can be no type-based converter lookup for them.

Finally, ClearScript passes more than just .NET values and objects to the script engine. There are also host types, "tear off" methods and indexers, host variables, etc. Whatever facility we come up with must be able to handle all these cases.

Please send us your opinions and ideas. Thanks!

ClearScriptLib avatar Jul 12 '22 16:07 ClearScriptLib

Ok, will try to make a mockup in next days

viceice avatar Jul 13 '22 06:07 viceice

Ok, will try to make a mockup in next days

Thanks, that would be great. And if you could share a minimal example of a C# API that just doesn't work well when used directly from JavaScript, that would be very helpful too.

ClearScriptLib avatar Jul 13 '22 13:07 ClearScriptLib

Hi @viceice,

Please feel free to reopen this issue if you're still interested in a general conversion facility in ClearScript.

Thanks!

ClearScriptLib avatar Aug 29 '22 15:08 ClearScriptLib

thanks, had no time to work in this yet.

viceice avatar Aug 29 '22 17:08 viceice