Passing common types between Java and (Rhino) Javascript
Asked Answered
O

3

8

I'm unclear on the rules for how types are converted between Javascript and Java when using (Mozilla) Rhino.

There's some specifics in the documentation about String:

It's important to keep in mind that Java strings and JavaScript strings are not the same […]Rhino provides some help in reducing the differences between the two types. First, you can pass a JavaScript string to a Java method that requires a Java string and Rhino will perform the conversion. We actually saw this feature in action on the call to the java.lang.String constructor in the preceding example. Rhino also makes the JavaScript methods available to Java strings if the java.lang.String class doesn't already define them

But what about others? If I pass a javascript Number to a Java method expecting int, double (or Integer or Double) will it get converted? What about long/Long? (which won't fit in a Double and so won't fit in a JS number?

What about Java methods returning these values?

Then there's Boolean/boolean. Are the JS constants true and false converted to and from the appropriate Java value? I've seen code like

java.lang.Boolean.TRUE.booleanValue()

used from JS, so at least some people think it isn't.

I have looked at the Mozilla Rhino documentation but do point out if I've missed something obvious.

Obstinate answered 18/7, 2011 at 7:57 Comment(1)
I'm passing a boolean from Java to Javascript compiled with Rhino to Java bytecode and as far as I can tell, it is handled as a Boolean in Javascript too. But that's just booleans.Psychologist
I
5

Here's how it converts JavaScript types to Java types: http://www-archive.mozilla.org/js/liveconnect/lc3_method_overloading.html#InvocationConversion.

Try it:

$ java -cp js.jar org.mozilla.javascript.tools.shell.Main

js> new java.lang.Integer(12345)
12345
js> new java.lang.Integer(12345) == 12345
true

js> new java.lang.Double(12345.12345)
12345.12345

js> new java.lang.Long(9223372036854775807)                 
js: Cannot convert 9223372036854776000 to java.lang.Long
js> 9223372036854775807
9223372036854776000
js> new java.lang.Long("9223372036854775807")
9223372036854775807
js> new java.lang.Long("-9223372036854775808")
-9223372036854775808

js> new java.lang.Boolean(true)
true
js> new java.lang.Boolean(true) == true
true
js> new java.lang.Boolean(true) == false
false
js> java.lang.Boolean.TRUE.booleanValue() == true
true
js> java.lang.Boolean.FALSE.booleanValue() == false
true

UPD

Unfortunately I can't find any docs about JavaScript-from-Java type mapping either. But the tutorial shows that JavaScript objects are inserted into and retrieved from context as Java Objects that actually can be Doubles, Booleans, Functions (for JavaScript functions; also implements Scriptable) or Scriptables (for objects).

Using this code snippet it's possibly to get JavaScript-Java type mapping reference:

https://gist.github.com/1089320#file_java_script_java_type_mapping.textile

As for LiveConnect compatibility. If you are referring to this footnote:

The ability to call Java from JavaScript was first implemented as part of a Netscape browser technology called LiveConnect. However, since that technology also encompassed communication with browser plugins, and since the way of calling JavaScript from Java in Rhino is entirely different, that term won't be used in this paper.

I think it's about using JavaScript from Java is different from LiveConnect specification. Using Java from JavaScript should be the same.

Impetuous answered 18/7, 2011 at 8:34 Comment(2)
Thanks. That's useful. But unless I'm missing something your transcript is more about how Javascript is handling Java types than what a Java method would see if passed a value for Javascript?Obstinate
Also, there's a comment about "Rhino compatibility" on the other LiveConnect oages on that site so the documentation may not fully apply to Rhino. Do you know how LC3 conversions (as documented there) and Rhino conversions are related? Are they known to be identical?Obstinate
B
2

Actually I had a problem even with the "automatic" conversion, ending up converting myself:

function javaToJavaScript(str)
{
    len = str.length();
    tmp = "";
    for (var i=0; i<len; i++)
        tmp += String.fromCharCode(str.charAt(i));
    return tmp;
}
Braunstein answered 5/8, 2013 at 1:48 Comment(4)
Never had an issue with String vs String. What were the problems you experienced?Obstinate
The called Java-function from JavaScript returned a Java-string. I wondered some time, why 'str.length' wasn't working as expected (returned a function, not integer as I thought).Braunstein
For me, the replace signatures were too different.Umpire
The following for me on Rhino 1.7.7: function javaToJS(str) { return ""+str;}Delight
B
0

This was solved by having the wrapper factory do the work for me in the situations where string doesn't implement all of the addons that js string has (like how string.length !== string.length() )

This can be set at the top level with:

context = Context.enter();

//This tells Rhino to convert String, Number, Boolean and Character into their JavaScript equivalents when returning from a Java function
context.getWrapFactory().setJavaPrimitiveWrap(false);

context.initStandardObjects();
Bridgework answered 22/8, 2019 at 19:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.