Bug 32511 - Cannot use properties on JSValue objects passed as arguments to custom objects bound through IJSExport
Summary: Cannot use properties on JSValue objects passed as arguments to custom object...
Status: VERIFIED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: XI 8.10
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: (C7)
Assignee: Rolf Bjarne Kvinge [MSFT]
URL:
: 32982 ()
Depends on:
Blocks:
 
Reported: 2015-07-27 18:40 UTC by Christian
Modified: 2016-05-24 11:01 UTC (History)
7 users (show)

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


Attachments
Simple sample app to reproduce (9.41 KB, application/zip)
2015-07-27 18:40 UTC, Christian
Details


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 on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
VERIFIED FIXED

Description Christian 2015-07-27 18:40:59 UTC
Created attachment 12245 [details]
Simple sample app to reproduce

I have been trying to integrate JavaScriptCore with C#, now that the 8.10 version of Xamarin.iOS supports the IJSExport protocol, meaning that it should now be possible to call C# code from Javascript.

However, when calling methods on a C# class (exported via the IJSExport protocol) from Javascript, it seems the JSValue arguments in the C# methods are not correctly bound to their native object counterparts.

More precisely, when trying to use any of the members of the JSValue class, it reports various errors - selector not found / NotSupportedException etc.
When debugging, it seems the jsValue.Class.Name values at runtime of the JSValue objects verify that the native objects are indeed not JSValue objects, but __NSCFNumber and __NSDictionaryM (see attached example).


The attached example shows a test case which should reproduce the problem.

Any clues how to solve/work around this? This seems like a bug in the way the the Xamarin middleware wraps the calls.
By the way I created similar code in Swift which worked right out of the box.


####

This is how my custom object is implemented:

	[Protocol]
	interface IMyCustomObject : IJSExport
	{
		
		[Export ("Hello:")]
		void Hello(JSValue val);

		[Export ("CallMeBack:")]
		void CallMeBack (JSValue callbackFunc);

	}

	public class MyCustomObject : NSObject, IMyCustomObject
	{

		public void Hello (JSValue val)
		{
			//This will print out __NSCFNumber
			Debug.WriteLine ("Class of val: " + val.Class.Name);

			//This will fail, saying there is no selector isNumber

			if (val.IsNumber)
				Debug.WriteLine("Is a number");
			else
				Debug.WriteLine("Is not a number");
		}

		public void CallMeBack (JSValue callbackFunc)
		{
			//This will print out __NSDictionaryM
			Debug.WriteLine ("Class of callbackFunc: " + callbackFunc.Class.Name);

			callbackFunc.Call ();
		}

	}

And this is how it's called:

	var jsContext = new JSContext ();
	var customObject = new MyCustomObject ();
	jsContext.GlobalObject.SetProperty (customObject, "customObject");

	jsContext.EvaluateScript (@"
  customObject.Hello(10);
  customObject.CallMeBack(function(){
    customObject.Hello(15);
  });
");
Comment 1 Brendan Zagaeski (Xamarin Team, assistant) 2015-07-29 18:39:40 UTC
To make a guess, I would not be too surprised if a corresponding Xcode app might hit the same problem. If any user seeing this issue would like to help investigate that possibility, you can attach a line-by-line port of the original test case into Objective-C (or Swift). That would improve the chances that the bug will receive additional attention soon. I will set the bug status to NEEDINFO to indicate that that additional test case would be helpful. Thanks!




## Possible workaround

In the mean time, my quick tests showed that the following change seemed to produce the desired outcome.


Replace:

> if (val.IsNumber)


With:

> if (JSValue.From(val, new JSContext()).IsNumber)
Comment 2 Rolf Bjarne Kvinge [MSFT] 2015-08-12 06:31:53 UTC
*** Bug 32982 has been marked as a duplicate of this bug. ***
Comment 3 Rolf Bjarne Kvinge [MSFT] 2015-08-12 07:08:36 UTC
This is a bug in our code (how we export protocols to ObjC).
Comment 4 Christian 2015-08-12 07:39:24 UTC
Thank you for the replies, Rolf and Brendan, and for the possible workaround. I will try that out.

Rolf does this mean you would like to see my port of this in Swift, or have you already found the cause of the bug?
Brendan, as I mentioned in the original post, I already tried implementing this in Swift, and it works as expected.

Is there any status on how soon this will be fixed?
Again, thank you for your help.
Comment 5 Rolf Bjarne Kvinge [MSFT] 2015-08-12 07:42:13 UTC
@Christian, I know what the problem is, no need for more information (for now at least).

Also note that another workaround is to use JSContext.CurrentArguments (see the test project in bug #32982 for an example for Xamarin.Mac, it should be trivially portable to Xamarin.iOS).

The current target to fix this is Xamarin.iOS 9.2 (that's several months away; it's not high priority since there's a workaround available).
Comment 6 Christian 2015-08-12 07:57:05 UTC
@Rolf, thank you very much for your quick reply.

Inspired by Brendan's comment, I just stumbled upon JSContext.CurrentArguments myself, so I was just about to post that workaround for anyone else to see. Good to know this is being addressed, and that there's a workaround I can use for now.

Thank you for your help.
Comment 7 Aaron Bockover [MSFT] 2015-08-12 07:59:33 UTC
Here's a direct link to the code in the test case I provided on the other bug so you don't need to download the whole project zip file:

https://gist.github.com/abock/30b40e937c9507ba2f59

Essentially just remove the parameters and adjust the export selector on your IJSExport methods, and access the JS invocation arguments via JSContext.CurrentArguments. You can similarly access the current "this" object and callee object, which can be especially useful.
Comment 8 Sebastien Pouliot 2015-09-04 11:45:12 UTC
re-numbering (target still C7)
Comment 10 Rolf Bjarne Kvinge [MSFT] 2016-01-04 11:53:07 UTC
Fixed.

maccore/master: f6846f1bbfb276f566ff0b497662427785996095
Comment 11 Akhilesh kumar 2016-05-20 15:03:01 UTC
I am successfully able to reproduce this issue with XI 8.10.3.2, on running the attached sample, it gives error "unrecognized selector sent to instance 0x796bbdd0" in application output.

However with C7 XI 9.8.0.318 this issue is working fine and on running attached sample, it does not give any error in Application output.

Screencast: http://www.screencast.com/t/AsZ8mkCvZ

So I am closing this issue.

xamarin.ios-9.8.0.318_efefc1edafbccb25395796b2a4f594c420f37bb3
Comment 12 liugx 2016-05-24 10:39:49 UTC
WEB JS: TypeError: customObject.Hello is not a function. (In 'customObject.Hello(10)', 'customObject.Hello' is undefined)


=== Xamarin Studio Business ===

Version 5.10.3 (build 51)
Installation UUID: 96790184-5699-4b29-a047-9f4c96df4250
Runtime:
	Mono 4.4.0 (mono-4.4.0-branch/0f5fdf2)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 404000168

=== Xamarin.Profiler ===

Not Installed

=== Apple Developer Tools ===

Xcode 7.3.1 (10188.1)
Build 7D1014

=== Xamarin.Mac ===

Version: 2.8.0.318 (Xamarin Business)

=== Xamarin.Android ===

Not Installed

=== Xamarin Android Player ===

Not Installed

=== Xamarin.iOS ===

Version: 9.8.0.318 (Xamarin Business)
Hash: efefc1e
Branch: cycle7
Build date: 2016-05-13 17:19:05-0400

=== Build Information ===

Release ID: 510030051
Git revision: f3c0d982165f785772d125f02668370d929014fb
Build date: 2016-03-24 18:51:31-04
Xamarin addins: ee5cfd3ecb6b20de47c1d25efb9a9abc101e8ce7
Build lane: monodevelop-lion-cycle6-c6sr3

=== Operating System ===

Mac OS X 10.11.1
Darwin sodsoftdeiMac-2.local 15.0.0 Darwin Kernel Version 15.0.0
    Sat Sep 19 15:53:46 PDT 2015
    root:xnu-3247.10.11~1/RELEASE_X86_64 x86_64
Comment 13 Rolf Bjarne Kvinge [MSFT] 2016-05-24 11:01:47 UTC
@liugx: please open a new bug report and attach a project we can use to reproduce any issues you're having.