3

Given the following, running with Oracle JRE 6 gives the output boo, but OpenJDK 6 gives an exception

javax.script.ScriptException: sun.org.mozilla.javascript.EvaluatorException: The choice of Java
constructor replace matching JavaScript argument types (function,string) is ambiguous; candidate 
constructors are: 
    class java.lang.String replace(char,char)
    class java.lang.String replace(java.lang.CharSequence,java.lang.CharSequence) (<Unknown source>#1) 
in <Unknown source> at line number 1

That's presumably because with OpenJDK (presumably the rt.jar supplied with it) the function's getting a java.lang.String, but with Oracle's it's getting a JavaScript String (or something that can be implicitly coerced to one).

So which is more correct? The Javascript (in this case) is the API, so can we write the Java such that the API's the same for either implementation? (If the OpenJDK implementation is "more correct" (and so likely to be what everyone does in the future), then I guess changing the API (documentation, examples, tests) throwing in new String(...) as appropriate wouldn't be impossible, but I'd rather not uglify the API unless I'm more confident.)

import javax.script.*;

class st {
    public static void main(String[] args) {
        ScriptEngineManager mgr = new ScriptEngineManager();
        ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
        Bindings bindings = jsEngine.getBindings(ScriptContext.ENGINE_SCOPE);
        Foo foo = new Foo();
        bindings.put("v", foo);
        try {
            jsEngine.eval("v.run(function(a) {println(a.replace(/f/,\"b\"));})");
        } catch (ScriptException ex) {
            ex.printStackTrace();
        }    
    }
}

and

public class Foo {
    public void run(FooCB cb) {
        cb.run("foo");
    }
    public static interface FooCB {
        public void run(Object val);
    }
}
Bruce Stephens
  • 7,225
  • 1
  • 17
  • 7
  • Just out of curiosity, what do it do if the arguments passed in to `replace` are more than just one character in length? – laz May 10 '11 at 00:33
  • I'm not sure I understand the question. I happened to give an example with a single character regexp and a single character string, but longer arguments are possible and behave just as you'd expect (presuming you're familiar with something that supports regexps). – Bruce Stephens May 10 '11 at 21:31
  • Sure they're possible. I'm just wondering if it is coercing them into char since they are only one character long and wondering if longer strings are mapped to CharacterSequence. – laz May 10 '11 at 23:50
  • AFAIK the relevant things are Javascript `String` objects (and the regular expression is presumably a `RegExp` object) even if they happen to be only one character long. (However, I'm no Javascript expert so possibly I'm mistaken.) – Bruce Stephens May 11 '11 at 12:08

1 Answers1

3

The Java SE 6 spec (JSR 270) merely says:

There will be no requirement that any particular scripting language be supported by the platform; implementors may choose to include support for the scripting language(s) of their choice as they see fit.

To the best of my knowledge, there is no formal spec for how to integrate Java types into JavaScript. It's unfortunate, but there's no reason to expect 100% compatibility across implementations.

I believe both the Oracle JRE and OpenJDK ship with Rhino, but there's no guarantee about version level, patches, etc.

McDowell
  • 107,573
  • 31
  • 204
  • 267
  • I suspect you're right, and this is just unspecified. I guess it's not unsurprising, and it's not so horrible in this case: throwing in `new String(...)` in the right places in the Javascript isn't too bad. – Bruce Stephens May 13 '11 at 15:14