* On backed storage being non-array. jdk.nashorn.internal.runtime.arrays.ArrayData is "backing store" impl for array storage - apart from Java array based impls there is on based on nio ByteBuffer. Not sure how feasible is to have one based on List. Also, even with one based on List, it would involve wrapping (ArrayData, NativeArray instance). But, right now dynalink's magic + nashorn runtime magic provides most of what JS Array offers on Java Lists - without wrapping as JS arrays.

* And btw, Array.prototype.forEach etc. do work on Java lists

var a = new java.util.ArrayList();
a.add("hello");
a.add("world");
Array.prototype.forEach.call(a, print);
print(Array.prototype.map.call(a, function(e) e.toUpperCase()));

-Sundar

Tim Fox wrote:
On 27/11/14 10:33, Attila Szegedi wrote:
Nashorn explicitly allows [] operator on java lists and it also supports for…in on them. ".length" is also supported since 8u20, see <https://bugs.openjdk.java.net/browse/JDK-8039387>.

We indeed don't implicitly convert Lists into JS Array objects in Nashorn. The reason is that JS Array has a Java array as backing storage; wrapping a large list would incur a lot of copying.

To avoid the copying, could the Nashorn JS Array implementation be changed so it backs either:

a) A Java Array (as it does currently) - this would the case if you created the JS array directly in JS code. b) A Java List - this would be the case if a List was passed from Java to JS, providing the user with a JS array

Then we can have our cake and eat it? I.e. we have a real JS Array object (not a half way house with some of the functions and properties but not all), and no copying overhead.

You can use "Java.from(someObject.provideList())" to explicitly convert a Java List to a JS array. We think it's better to provide an explicit conversion API than incur a linear conversion cost whenever a List object passes into the JS context. The Java.from created copy is shallow; if you have a List of Lists, the nested List objects are not converted.

Typically you'll want to create a real Array if you want to use Array functionality that points beyond [], .length, and for…in, e.g. JS Array comprehension operations (arguably, we *could* implement even those so that Array.prototype.forEach.call(javaList, ...) works as expected, but we aren't there yet.)

Attila.

On Nov 27, 2014, at 10:41 AM, Tim Fox <timvo...@gmail.com> wrote:

Hello again,

I am a bit confused about how Lists passed from Java into JS are converted.

I have a Java class as follows:

public class SomeClass {

   public List<String> provideList() {
     List<String> list = new ArrayList<>();
     list.add("foo");
     list.add("bar");
     return list;
   }
}

I call this from JavaScript:

var io = Packages.io;
var someObject = new io.vertx.scratchpad.SomeClass();

var arr = someObject.provideList();

console.log(arr[0]); // prints: foo
console.log(typeof arr.length); // undefined
console.log(arr instanceof Array); // false

I was under the impression that Nashorn automatically converted Java lists passed into JS into JS Arrays.

The object arr returned in some ways resembles a JavaScript array - the operators [] and []= work on it, however it doesn't have the array property "length" and it's not an instanceof Array.

Can anyone clarify to me what this object is? Any reason why Nashorn doesn't just wrap it as a real JS Array?

Cheers


Reply via email to