Short version:

I don't want my users to have to code anything like Java.type(XXX), which they 
didn't need to do in Rhino and makes for some ugly code.   I want business 
people to be able to write scripts in most cases.  A proper script engine 
should be able to enable the developer to hide complexity from the script 
author/user, not the other way around, I'd think.

I need to be able to expose Java object(s) of a variety of types to the 
scripting environment and be able to intercept the following:

Object get(string)
put(string, Object)
Object get(int)
put(int, value)
Object[] ids() (for enumeration)
delete(string)
delete(i)

get methods should be able to return values or function references (which would 
of course implement a "call" method).

This is what Rhino allows, and it is powerful and elegant, and GREATLY 
simplifies the user's experience.


From: Jim Laskey (Oracle) [mailto:james.las...@oracle.com]
Sent: Tuesday, October 22, 2013 12:34 PM
To: Rick Bullotta
Cc: nashorn-dev@openjdk.java.net
Subject: Re: Docs/examples for JSAdapter

In Nashorn, there is no need to wrap classes/types in JavaScript objects.  You 
can work with them directly or extended them directly.  As an example,

jjs> var ArrayList = Java.type("java.util.ArrayList");  // or var ArrayList = 
java.util.ArrayList;
jjs> var Arrays = Java.type("java.util.Arrays");
jjs> var list = new ArrayList();
jjs> list.add("a");
true
jjs> list.add("b");
true
jjs> list.add("c");
true
jjs> list.addAll(Arrays.asList(["d", "e", "f"]));
true
jjs> list.addAll(Arrays.asList("g", "h", "i"));
true
jjs> for each(var e in list) print(e);
a
b
c
d
e
f
g
h
i

Is there a specific example of something you want to translate?  We can help 
you out.

Cheers,

-- Jim






On 2013-10-22, at 1:02 PM, Rick Bullotta 
<rick.bullo...@thingworx.com<mailto:rick.bullo...@thingworx.com>> 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<http://oracle.com>]
Sent: Tuesday, October 22, 2013 11:52 AM
To: Rick Bullotta
Cc: nashorn-dev@openjdk.java.net<mailto: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