Also, we have to recall ConsString as optimization to represent JS
"string" primitive has caused lot of pain.. (internal type hiding,
conversion in places...). We fixed number of issues after introducing
ConsString. If we were to introduce JSNumber type, we may have to do
similar conversions (like what is being done for ConsString) everywhere
-- to hide and present Number to the java side...
I agree with Hannes that it is important to use java.lang.* primitive
wrappers being used to represent JS primitives for seamless integration.
-Sundar
On 1/12/2016 4:10 AM, Hannes Wallnoefer wrote:
Am 2016-01-11 um 19:45 schrieb Attila Szegedi:
Specifically in relation to the remark that JSType.isNumber check is
getting long… I think we could be even more conservative if we wished
to, namely only recognizing Integer and Double as wrapped numbers.
Within Nashorn, byte, short, float, and long don't occur naturally,
only int and double occur. Their wrappers (Byte, Short, etc.)
therefore also can’t appear. The only way to introduce them is
through POJO methods with such return types (e.g. Byte.valueOf()).
I’m not sure we’re under an obligation to consider those equivalent
to JS numbers. We could declare that Byte, Short, Float, and Long are
not numbers just host objects, albeit ones that JSType.toNumber
understands.
I guess we could do that, but we would (IMO) needlessly change the
rules we set up with Nashorn in JDK8. I think that making Java number
primitives equivalent to JS numbers is actually a nice feature.
Unfortunately it doesn't really work for longs because JS happens to
use double as its only number type, but I don't think that means we
should throw out the idea as a whole.
Also, an important point here is that we can't really safely
distinguish between primitive number types and object wrappers in
Nashorn. A java.lang.Short or java.lang.Float may just be a primitive
that happens to be handled in an object context.
Actually, I can take this train of thought in an even more drastic
direction. Consider this: we would be at liberty to internally box
numbers any way we want and not rely on java.lang.Double and friends
at all! It’s just convenient to box JS primitive number values (and
booleans, BTW) using readily available java.lang.* boxes, but we
could have a NashornNumber and NashornBoolean classes for internal
boxing of JS primitive numbers and booleans, when they need to be
boxed. Then we could even allow ourselves to not recognize any Java
primitive wrapper objects as special cases of JS primitive values at
all. The thought is actually not so far fetched in the sense that we
already have ConsString too, an alternative internal string
representation that is not a java.lang.String. We’d just have to take
care that such NashornNumber boxes are handled in all places where
ConsString is handled and converted into a Double when passing from
Nashorn to outside world.
That would provide a 100% consistent way of handling wrapper classes:
they’re all just POJOs at that point, no special treatment whatsoever.
I think what I wrote above also applies here - that seamlessness is
actually nice and that we don't really control whether a numeric value
from Java is handled as primitive or as wrapper object in Nashorn -
that may vary on how JavaScript code was used/optimized/compiled
before, what the code does with it, etc.
In Rhino, we had explicit wrapper classes for things to be treated as
objects (e.g. a java.lang.Double would be wrapped in a JavaObject
wrapper or whatever it was called). Since Nashorn does not use object
wrappers, I think it would be hard to distinguish between primitive
numbers and object wrappers in this way. It would als feel kind of
arbitrary to me.
Hannes
Attila.
On Jan 11, 2016, at 1:48 PM, Hannes Wallnoefer
<hannes.wallnoe...@oracle.com> wrote:
You are right of course, there needs to be consistency between
typeof operator and treatment as JS numbers.
This is in fact an unpleasant problem to solve. I've struggled
trying to fix this without breaking any existing code, but I've come
to the conclusion that it is not possible. Since we can't treat all
Java longs/Longs as JS numbers, we'd have to differentiate depending
on whether the value can be represented as double without losing
precision.
In a way we already do this with optimistic types, but I consider it
more a bug than a feature. It's weird (and error prone) if the
return value for a Java method returning long is reported as number
or object depending on the actual value.
So I think the right thing to do is draw a clear line between which
Java primitive/wrapper types represent JS numbers and which don't.
I've uploaded a new webrev that implements this:
http://cr.openjdk.java.net/~hannesw/8143896/webrev.01/
Note that the only types to be treated as JS numbers are the direct
wrapper classes for Java primitives that can be fully represented as
doubles. This means also things like AtomicInteger and DoubleAdder
will be reported and treated as objects. I think that's the correct
thing to do as they are not primitive numbers in the first place.
They are still converted to numbers when used in such a context in
JS. So I think the only place where this change is a actually
painful/surprising is longs.
Unfortunately the check for number type in JSType.isNumber gets a
bit long as we have to individually check for all primitive wrapper
classes. I've done extensive benchmarking and I don't think it has
an impact on performance. In any way, I wouldn't know how to handle
this differently.
Let me know what you think.
Hannes
Am 2016-01-04 um 05:00 schrieb Sundararajan Athijegannathan:
I think I already commented on this webrev -- that we need to cover
tests for BigInteger, BigDecimal.
Also, I'm not sure linking Double and Int by nashorn primitive
linkers is the right solution. AtomicInteger, DoubleAdder etc. are
all Number subtypes. We return "number" when typeof is used on any
Number subtype.
Now, that means JS code will see these as 'number' type objects --
yet Number.prototype methods won't work on those!! I know this is
hard problem -- we also have another (somewhat related) BigDecimal,
BigInteger toString / String conversion issue. We need to discuss
this.
-Sundar
On 1/2/2016 8:29 PM, Attila Szegedi wrote:
+1
On Dec 18, 2015, at 3:54 PM, Hannes Wallnoefer
<hannes.wallnoe...@oracle.com> wrote:
Please review JDK-8143896: java.lang.Long is implicitly converted
to double
http://cr.openjdk.java.net/~hannesw/8143896/webrev/
Thanks,
Hannes