1

This is very similar to this other SO question about arrays.

If I evaluate:

y = {a: 1, b: 2, "momomomo": function() { return "hi"; }, zz: "wham"}

in a Javascript script instantiated via JSR223 (ScriptingEngine), I get a NativeObject of some sort (I see this in Eclipse's debugger) and have no idea how to access its properties. Furthermore I don't even know which .jar file, if any, I need to add to my build path to be able to work with the class in question, and if I find an approach that works in Rhino Javascript, it is useless for Jython.

Seems like JSR223 should have included language-agnostic access methods to ScriptingEngine to provide the ability to wrap a returned object as a List<Object> for arrays or a Map<String, Object> for associative arrays.

Any suggestions?

Community
  • 1
  • 1
Jason S
  • 184,598
  • 164
  • 608
  • 970
  • Have you checked Rhino documentation on how to access Java objects? http://www.mozilla.org/rhino/ScriptingJava.html – eee Apr 08 '11 at 21:13
  • yeah, but it kind of focuses more on how to access Java objects from Javascript. What I want to do is the opposite: access Javascript objects from Java. Also it's confusing because I'm not actually using Rhino's js.jar, I'm using the javax.script classes that are part of the SE 6 distribution, so I don't know how to get sun.org.mozilla.* into my build path or even whether I should be doing so. – Jason S Apr 08 '11 at 21:30
  • see Java array to JavaScript array mode: http://www.mozilla.org/rhino/faq.html – eee Apr 08 '11 at 21:45
  • But that's if I do it from within Javascript. (and it's maps not arrays) The point is, I have users who execute Javascript using my application. As the Java application programmer, I don't know what value is produced by the script, but I need to be able to analyze and/or manipulate that value *from within Java*. If it's an array, I may need to get the array length and the elements. I can't just tell my users "Don't use Javascript arrays, you're stuck using this weird syntax where you have to create the array using java.lang.reflect.Array.newInstance." They'll look at me like I have two heads. – Jason S Apr 08 '11 at 22:18

2 Answers2

0

I too am trying to embed different scripting languages with more features than jsr223 or bsf. For that i have had to define my own interfaces and implement thse around each different scripting engine.

One feature i wanted was the ability to pass a Function (java interface with a single method) to my scripting engine and have it just work when passed parameters. Each of my embedded scripting engines has a layer where i wrap/unwrap from/to java values from the scripting environment.

I would suggest the best way to solve the problem is for your wrapper around the scripting engine to provide a getValue( String name ) and have it fix up javascript arrays convertoing them to java Lists. Naturally the setValue(String, Object) would check if the value is a List and convert it back to a js array and so on. Its tedious :()

mP.
  • 18,002
  • 10
  • 71
  • 105
0

Convert it to a java object and return it. You can then work with the java object as you would normally.

The following is an example conversion function

function convertToJava(o) {
    var rval;
    if (Array.isArray(o)) {
        rval = new java.util.ArrayList();
        for (var key in o) {
            rval.add(convertToJava(o[key]));
        }
    } 
    else if (typeof o === 'object') {
        rval = new java.util.HashMap();
        for (var key in o) {
            rval.put(key, convertToJava(o[key]));
        }
    }
    else if (typeof o === 'function') {
        // skip
    }
    else if (typeof o === 'undefined') {
        // skip
    }
    else {
        rval = o;
    }
    return rval;
}
Tom Howard
  • 6,516
  • 35
  • 58