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 >