Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Rhino: passing java.lang.Boolean as a parameter to java method

138 views
Skip to first unread message

almo

unread,
Oct 30, 2006, 6:12:43 AM10/30/06
to
It was initially posted to netscape.public.mozilla.jseng, but no reply
there, so I reposted it here.

I've got a problem when passing Boolean taken from java object to java
method with declared 'boolean' parameter.
Please, consider the following short example code.
Java:
class C
{
public boolean negate( boolean b ){ return !b; }
public Boolean getB(){ return Boolean.TRUE; }
}

JavaScript ('c' is a global variable of java type C ):
c.negate( c.b )

Rhino's output is:
org.mozilla.javascript.EvaluatorException: Can't find method
C.negate(java.lang.Boolean). (<cmd>#1)

But if an analogous example with int and Integer is written, everything
is ok.

Will anyone be so kind to tell me what's the problem is in the first
example? ;)

p.s.I'm using cvs branch 1.6RC4.

Attila Szegedi

unread,
Oct 30, 2006, 7:38:38 AM10/30/06
to almo, dev-tech-...@lists.mozilla.org
Indeed... I'm trying to track down why does it behave this way, in the
meantime, you can call

cx.getWrapFactory().setJavaPrimitiveWrap(false);

on your Context object -- it'll fix the problem for now.

Attila.

> _______________________________________________
> dev-tech-js-engine mailing list
> dev-tech-...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-tech-js-engine
>

Attila Szegedi

unread,
Oct 30, 2006, 9:31:27 AM10/30/06
to almo, dev-tech-...@lists.mozilla.org, Scott Furman
Ok, the culprit is line 354 in NativeJavaObject that figures out whether
it is possible to convert argument types. When passed
(NativeJavaObject(Boolean.TRUE), Boolean.TYPE), it'll return
CONVERSION_NONE, since line 354 says

else if (to.isPrimitive() && to != Boolean.TYPE) {
...
}

that is, Boolean.TYPE is explicitly excluded. Now, Rhino follows the
Netscape LiveConnect 3 (LC3) specification for conversions between JS and
Java, it is documented here:

<http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html>

I checked whether exclusion of Boolean.TYPE is according to LC3 spec, and
here's what I found:

1) If Rhino is wrapping Java primitive types (default behaviour,
corresponds to WrapFactory.setJavaPrimitiveWrap(true), then the Boolean
returned from getB() is wrapped as JavaNativeObject, and falls under
section 3.3.6.1 of the above referenced LC3 spec, and it specifically
excludes conversion to primitive boolean -- in the last line of the
conversion table for 3.3.6.1 it says "loat, double, byte, char, short,
int, long".

2) If Rhino is *not* wrapping Java primitive types
(WrapFactory.setJavaPrimitiveWrap(false)), then the Boolean returned from
getB() is treated as native JS boolean, and falls under section 3.3.2 of
the LC3 specification, thus gets converted to Java boolean, since that
section allows this conversion.

So, Rhino definitely operates according to LC3 spec. Whether the spec
makes sense is another matter - I don't know the rationale behind
prohibiting wrapper for a Boolean from being coerced to boolean
automatically...

I'm CC-ing the e-mail address featured as the author of the spec, maybe
he'll care to comment.

Attila.


On Mon, 30 Oct 2006 13:38:38 +0100, Attila Szegedi <szeg...@freemail.hu>
wrote:

> Indeed... I'm trying to track down why does it behave this way, in the
> meantime, you can call
>
> cx.getWrapFactory().setJavaPrimitiveWrap(false);
>
> on your Context object -- it'll fix the problem for now.
>
> Attila.
>
> On Mon, 30 Oct 2006 13:12:43 +0200, almo <al...@mail.ru> wrote:
>

almo

unread,
Oct 31, 2006, 1:57:17 PM10/31/06
to
Thanks for thorough investigation.
setJavaPrimitiveWrap( false ) really helped.
Explicit Boolean case exclusion seems really strange.
I hope spec author will answer, it would interesting to figure out the
rationale

Attila Szegedi

unread,
Nov 8, 2006, 4:45:32 AM11/8/06
to dev-tech-...@lists.mozilla.org
We didn't get back any feedback on this, and frankly, it is not the first
time we got a bug report regarding this "feature". Pending anyone
explaining why Boolean --> boolean conversion is not allowed while all
other java.lang.* primitve wrapper objects --> primitive conversions are,
I'm inclined to simply go beyond LC3, and add support for this in next
Rhino release.

There is a separate matter of not being able to pass a NativeObject to a
method that declares an argument to be a ScriptableObject. The reason for
this is in NativeJavaObject.getConversionWeight() that does this:

case JSTYPE_OBJECT:
// Other objects takes #1-#3 spots
if (to == fromObj.getClass()) {
// No conversion required
return 1;
}

while I believe it would instead have to use "to.isInstance(fromObj)" in
the if clause.

Pending anyone objecting, these changes will go in the CVS HEAD.

Attila.

0 new messages