Bug 17550 - JSValue.From() does not include overloads that accept Actions and Funcs
Summary: JSValue.From() does not include overloads that accept Actions and Funcs
Status: NEW
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: 7.0.6.x
Hardware: PC Mac OS
: --- enhancement
Target Milestone: Untriaged
Assignee: Bugzilla
Depends on:
Reported: 2014-02-02 19:18 UTC by Brendan Zagaeski (Xamarin Team, assistant)
Modified: 2015-08-24 18:31 UTC (History)
2 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report for Bug 17550 on Developer Community or GitHub if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: Developer Community HTML or GitHub Markdown
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:

Description Brendan Zagaeski (Xamarin Team, assistant) 2014-02-02 19:18:26 UTC
## Summary
The C# bindings for the JavaScriptCore library are missing `JSValue.From()` overloads that accept `Actions` and `Funcs`. Consequently, the bindings do not currently allow callbacks to C# methods from JavaScript.

## Complications

1. The Objective-C wrapper layer for JavaScriptCore only requires that the callback methods be of type `NSBlock` (a subclass of `NSObject`). Since the usual Xamarin binding mechanism for blocks requires a fixed delegate type signature, I suspect that it cannot accommodate this situation.

2. C# does not allow a parameter type of "any kind of delegate." Therefore, to expose functionality similar to the Objective-C version, I think the corresponding C# `JSValue.From()` overload would need either to:

A. Require the user to wrap up the callback delegate within a `void`, parameterless delegate (an `Action`).


B. Require the user to pass in a `MethodInfo` object rather than an `Action`. This option might not work: I'm not sure if `MethodInfo` contains all the necessary information.

## A little more background

The JavaScriptCore library allows the user to create a JavaScript function that calls a native C function [1]. In Objective-C, this feature is wrapped up in the `[JSObjCClassInfo wrapperForObject:]` method [2]. The C# bindings do not expose this feature. One problem is that `Actions` and `Funcs` are not subclasses of `NSObject`. Because of this, the `wrapperForObject:` method has no way to convert them to JavaScript objects.

> [1] See the JSObjectMakeFunctionWithCallback() function on:
> http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/API/JSObjectRef.cpp

> [2] See: http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/API/JSWrapperMap.mm
Note: the `wrapperForObject:` method is usually called indirectly as the result of a call to `[JSValue valueWithObject:inContext:]`, which is defined in:
> http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/API/JSValue.mm

## Possible solutions?

### Write a new JavaScriptCore binding that P/Invokes the C API

One way to work around the problem might be to re-write the Objective-C binding layer in C#. In this scenario, the C# binding would skip the Objective-C layer entirely. Instead it would directly P/Invoke the JavaScriptCore C API functions. Unfortunately, I think it would be necessary to recreate the whole Objective-C binding layer. One example that demonstrates this problem is that the Objective-C layer wraps the native C `JSValueRef` type into a `JSValue` Objective-C class. So the existing binding for `JSValue` would not be compatible with a `JSValue.From()` method that directly P/Invoked `JSObjectMakeFunctionWithCallback()`.

Maybe writing a P/Invoke, C API version of JavaScriptCore would be an interesting GSoC project?

### Create `NSBlocks` from C# `Actions` at runtime

Another solution might be to make the new `JSValue.From()` overload (that takes `Actions` or `MethodInfos`) include some fancy logic to create an intermediary callback `NSBlock` for _any_ input delegate at runtime. On the other hand, I think this might require creating new trampoline types at runtime, and I'm not sure that's technically possible considering that SRE is unavailable on iOS.

## Version information
Comment 1 David 2015-07-21 10:38:18 UTC
Any plans for adding this functionality?
Comment 2 Brendan Zagaeski (Xamarin Team, assistant) 2015-07-21 12:41:43 UTC
In case it's helpful for anyone looking for this feature, you can now (as of Xamarin.iOS 8.10 and higher) export entire C# objects to JavaScript using a different JavaScriptCore mechanism.

See Bug 23474, Comment 3 through Bug 23474, Comment 5 for more details about that.

That alternate strategy might be sufficient for many use cases.