I am going to try to mock up some kind of dependency injection based approach 
that works somewhat like the "wrapper" model on classes that extends JSObject.  
The primary change is that I'm going to have to implement the code that 
performs the "wrapping" each time I access an object or property/function - 
I'll have to figure out all the places it is needed.  That's the cool part 
about a wrap factory, which would be fairly easy to add to Nashorn.  Basically 
whenever an object is accessed, a check is made to see if it is one of the 
type(s) in the factory list, and if so, call the factory to let it create a 
wrapper object.  It allows this logic to be confined to one place instead of 
scattered around everywhere any of those types might be accessed via script.

Anyway, I think I know what I'm up against now.  That's a start. ;-)

-----Original Message-----
From: nashorn-dev-boun...@openjdk.java.net 
[mailto:nashorn-dev-boun...@openjdk.java.net] On Behalf Of Rick Bullotta
Sent: Tuesday, October 22, 2013 12:54 PM
To: Attila Szegedi
Cc: nashorn-dev@openjdk.java.net
Subject: RE: Docs/examples for JSAdapter

Cool.  Any examples out there in the ether?  

That said, I do think an interface-based approach would be more desirable since 
it does not force a specific class hierarchy (e.g. must extend JSObject), which 
could be very problematic in many cases (including ours).

-----Original Message-----
From: Attila Szegedi [mailto:attila.szeg...@oracle.com] 
Sent: Tuesday, October 22, 2013 12:51 PM
To: Rick Bullotta
Cc: A. Sundararajan; nashorn-dev@openjdk.java.net
Subject: Re: Docs/examples for JSAdapter

You should be able to use your own subclasses of 
jdk.nashorn.api.scripting.JSObject for this purpose.

Attila.

On Oct 22, 2013, at 6:46 PM, Rick Bullotta <rick.bullo...@thingworx.com> wrote:

> Yuck.  Looks like we'll be sticking with Rhino for a while then. 
> 
> I would STRONGLY recommend adding the ability of a Java class developer to 
> implement an interface that provides the functionality I described in my 
> response to Jim.  It is just plain wrong to push complexity to the end user 
> when it can easily be solved in the framework/platform.  To implement that 
> should be rather trivial, to be honest.
> 
> 
> -----Original Message-----
> From: nashorn-dev-boun...@openjdk.java.net 
> [mailto:nashorn-dev-boun...@openjdk.java.net] On Behalf Of A. Sundararajan
> Sent: Tuesday, October 22, 2013 12:33 PM
> To: nashorn-dev@openjdk.java.net
> Subject: Re: Docs/examples for JSAdapter
> 
> No. Nashorn uses wrapperless Java objects. Java objects are exposed to 
> scripts "as is" - no wrapping as 'script objects' as in Rhino.
> 
> It is possible to implement Java interfaces in script (just like it was in 
> Rhino).
> 
> -Sundar
> 
> On Tuesday 22 October 2013 09:32 PM, Rick Bullotta wrote:
>> In Rhino, you register custom adapters in a "wrap factory" that tells the 
>> script engine to use these adapters for accessing instances of those 
>> classes/types.  What's the analog in Nashorn?  Can custom types implement 
>> interfaces that Nashorn will use?
>> 
>> From: Jim Laskey (Oracle) [mailto:james.las...@oracle.com]
>> Sent: Tuesday, October 22, 2013 11:52 AM
>> To: Rick Bullotta
>> Cc: nashorn-dev@openjdk.java.net
>> Subject: Re: Docs/examples for JSAdapter
>> 
>> In general the Nashorn docs start here. 
>> https://wiki.openjdk.java.net/display/Nashorn/Nashorn+Documentation, but as 
>> you point out, we seem to be lacking JSAdapter details.  I should start an 
>> FAQ.
>> 
>>> From the javadoc (cd make; ant javadoc # ./dist/javadoc/index.html)
>> 
>> 
>> *         public final class NativeJSAdapter
>> 
>> *         extends 
>> ScriptObject<file:///\\Volumes\Elephant\Projects\nashorn~jdk8\nashorn\dist\javadoc\jdk\nashorn\internal\runtime\ScriptObject.html>
>> This class is the implementation of the Nashorn-specific global object named 
>> JSAdapter. It can be thought of as the 
>> Proxy<http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html?is-external=true>
>>  equivalent for JavaScript. NativeJSAdapter calls specially named JavaScript 
>> methods on an adaptee object when property access/update/call/new/delete is 
>> attempted on it. Example:
>> 
>>     var y = {
>> 
>>                 __get__    : function (name) { ... }
>> 
>>                 __has__    : function (name) { ... }
>> 
>>                 __put__    : function (name, value) {...}
>> 
>>                 __call__   : function (name, arg1, arg2) {...}
>> 
>>                 __new__    : function (arg1, arg2) {...}
>> 
>>                 __delete__ : function (name) { ... }
>> 
>>                 __getIds__ : function () { ... }
>> 
>>             };
>> 
>> 
>> 
>>     var x = new JSAdapter(y);
>> 
>> 
>> 
>>     x.i;                        // calls y.__get__
>> 
>>     x.foo();                    // calls y.__call__
>> 
>>     new x();                    // calls y.__new__
>> 
>>     i in x;                     // calls y.__has__
>> 
>>     x.p = 10;                   // calls y.__put__
>> 
>>     delete x.p;                 // calls y.__delete__
>> 
>>     for (i in x) { print(i); }  // calls y.__getIds__
>> 
>> 
>> 
>> JavaScript caller of adapter object is isolated from the fact that the 
>> property access/mutation/deletion are really calls to JavaScript methods on 
>> adaptee.
>> 
>> JSAdapter constructor can optionally receive an "overrides" object. 
>> Properties of overrides object is copied to JSAdapter instance. When user 
>> accessed property is one of these, then adaptee's methods like __get__, 
>> __put__ etc. are not called for those. This can be used to make certain 
>> "preferred" properties that can be accessed in the usual/faster way avoiding 
>> proxy mechanism. Example:
>> 
>>      var x = new JSAdapter({ foo: 444, bar: 6546 }) {
>> 
>>           __get__: function(name) { return name; }
>> 
>>       };
>> 
>> 
>> 
>>      x.foo;           // 444 directly retrieved without __get__ call
>> 
>>      x.bar = 'hello'; // "bar" directly set without __put__ call
>> 
>>      x.prop           // calls __get__("prop") as 'prop' is not overridden
>> 
>> 
>> It is possible to pass a specific prototype for JSAdapter instance by 
>> passing three arguments to JSAdapter constructor. So exact signature of 
>> JSAdapter constructor is as follows:
>> 
>>      JSAdapter([proto], [overrides], adaptee);
>> 
>> 
>> Both proto and overrides are optional - but adaptee is not. When proto is 
>> not passed JSAdapter.prototype is used.
>> *
>> As well as the test ./test/script/basic/jsadapter.js
>> 
>> var obj = new JSAdapter() {
>>     __get__: function(name) {
>>         print("getter called for '" + name + "'"); return name;
>>     },
>> 
>>     __put__: function(name, value) {
>>         print("setter called for '" + name + "' with " + value);
>>     },
>> 
>>     __call__: function(name, arg1, arg2) {
>>         print("method '" + name + "' called with " + arg1 + ", " + arg2);
>>     },
>> 
>>     __new__: function(arg1, arg2) {
>>         print("new with " + arg1 + ", " + arg2);
>>     },
>> 
>>     __getIds__: function() {
>>         print("__getIds__ called");
>>         return [ "foo", "bar" ];
>>     },
>> 
>>     __getValues__: function() {
>>         print("__getValues__ called");
>>         return [ "fooval", "barval" ];
>>     },
>> 
>>     __has__: function(name) {
>>         print("__has__ called with '" + name + "'");
>>         return name == "js";
>>     },
>> 
>>     __delete__: function(name) {
>>         print("__delete__ called with '" + name + "'");
>>         return true;
>>     }
>> };
>> 
>> // calls __get__
>> print(obj.foo);
>> 
>> // calls __put__
>> obj.foo = 33;
>> 
>> // calls __call__
>> obj.func("hello", "world");
>> 
>> // calls __new__
>> new obj("hey!", "it works!");
>> 
>> for (i in obj) {
>>     print(i);
>> }
>> 
>> for each (i in obj) {
>>     print(i);
>> }
>> 
>> var x = "foo" in obj;
>> print(x);
>> 
>> var y = "js" in obj;
>> print(y);
>> 
>> print(delete obj.prop);
>> 
>> print(obj["js"]);
>> obj["js"] = "javascript";
>> print(obj["javascript"]);
>> Hope that helps.  Is there a specific question?
>> 
>> Cheers,
>> 
>> -- Jim
>> 
>> On 2013-10-22, at 11:50 AM, Rick Bullotta 
>> <rick.bullo...@thingworx.com<mailto:rick.bullo...@thingworx.com>> wrote:
>> 
>> 
>> Hi, all.
>> 
>> I've been searching everywhere for any form of documentation or substantive 
>> examples as to how JSAdapter works in Nashorn, as it is an essential piece 
>> of the puzzle for many of us who will naturally be migrating from Rhino.
>> 
>> Can anyone provide and additional info?
>> 
>> Thanks,
>> 
>> Rick
>> ThingWorx
>> 
> 

Reply via email to