mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-01 14:08:24 +00:00
8023026: Array.prototype iterator functions like forEach, reduce should work for Java arrays, lists
Reviewed-by: jlaskey, lagergren
This commit is contained in:
parent
bf29c2ec49
commit
a28b8a61dc
@ -26,6 +26,7 @@
|
||||
package jdk.nashorn.internal.runtime.arrays;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import jdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||
import jdk.nashorn.internal.runtime.JSType;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
@ -49,7 +50,7 @@ abstract public class ArrayLikeIterator<T> implements Iterator<T> {
|
||||
*
|
||||
* @param includeUndefined should undefined elements be included in the iteration?
|
||||
*/
|
||||
protected ArrayLikeIterator(final boolean includeUndefined) {
|
||||
ArrayLikeIterator(final boolean includeUndefined) {
|
||||
this.includeUndefined = includeUndefined;
|
||||
this.index = 0;
|
||||
}
|
||||
@ -118,18 +119,26 @@ abstract public class ArrayLikeIterator<T> implements Iterator<T> {
|
||||
Object obj = object;
|
||||
|
||||
if (ScriptObject.isArray(obj)) {
|
||||
return new ArrayIterator((ScriptObject) obj, includeUndefined);
|
||||
return new ScriptArrayIterator((ScriptObject) obj, includeUndefined);
|
||||
}
|
||||
|
||||
obj = JSType.toScriptObject(obj);
|
||||
if (obj instanceof ScriptObject) {
|
||||
return new MapIterator((ScriptObject)obj, includeUndefined);
|
||||
return new ScriptObjectIterator((ScriptObject)obj, includeUndefined);
|
||||
}
|
||||
|
||||
if (obj instanceof ScriptObjectMirror) {
|
||||
return new ScriptObjectMirrorIterator((ScriptObjectMirror)obj, includeUndefined);
|
||||
}
|
||||
|
||||
if (obj instanceof List) {
|
||||
return new JavaListIterator((List)obj, includeUndefined);
|
||||
}
|
||||
|
||||
if (obj != null && obj.getClass().isArray()) {
|
||||
return new JavaArrayIterator(obj, includeUndefined);
|
||||
}
|
||||
|
||||
return new EmptyArrayLikeIterator();
|
||||
}
|
||||
|
||||
@ -143,19 +152,25 @@ abstract public class ArrayLikeIterator<T> implements Iterator<T> {
|
||||
Object obj = object;
|
||||
|
||||
if (ScriptObject.isArray(obj)) {
|
||||
return new ReverseArrayIterator((ScriptObject) obj, includeUndefined);
|
||||
return new ReverseScriptArrayIterator((ScriptObject) obj, includeUndefined);
|
||||
}
|
||||
|
||||
obj = JSType.toScriptObject(obj);
|
||||
if (obj instanceof ScriptObject) {
|
||||
return new ReverseMapIterator((ScriptObject)obj, includeUndefined);
|
||||
return new ReverseScriptObjectIterator((ScriptObject)obj, includeUndefined);
|
||||
}
|
||||
|
||||
if (obj instanceof ScriptObjectMirror) {
|
||||
return new ReverseScriptObjectMirrorIterator((ScriptObjectMirror)obj, includeUndefined);
|
||||
}
|
||||
|
||||
assert !obj.getClass().isArray();
|
||||
if (obj instanceof List) {
|
||||
return new ReverseJavaListIterator((List)obj, includeUndefined);
|
||||
}
|
||||
|
||||
if (obj != null && obj.getClass().isArray()) {
|
||||
return new ReverseJavaArrayIterator(obj, includeUndefined);
|
||||
}
|
||||
|
||||
return new EmptyArrayLikeIterator();
|
||||
}
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.runtime.arrays;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
/**
|
||||
* Iterator over a Java List.
|
||||
*/
|
||||
class JavaArrayIterator extends ArrayLikeIterator<Object> {
|
||||
|
||||
/** Array to iterate over */
|
||||
protected final Object array;
|
||||
|
||||
/** length of array */
|
||||
protected final long length;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param array array to iterate over
|
||||
* @param includeUndefined should undefined elements be included in iteration
|
||||
*/
|
||||
protected JavaArrayIterator(final Object array, final boolean includeUndefined) {
|
||||
super(includeUndefined);
|
||||
assert array.getClass().isArray() : "expecting Java array object";
|
||||
this.array = array;
|
||||
this.length = Array.getLength(array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the current index still inside the array
|
||||
* @return true if inside the array
|
||||
*/
|
||||
protected boolean indexInArray() {
|
||||
return index < length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next() {
|
||||
return Array.get(array, (int)bumpIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return indexInArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("remove");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.runtime.arrays;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Iterator over a Java List.
|
||||
*/
|
||||
class JavaListIterator extends ArrayLikeIterator<Object> {
|
||||
|
||||
/** {@link java.util.List} to iterate over */
|
||||
protected final List<?> list;
|
||||
|
||||
/** length of array */
|
||||
protected final long length;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param list list to iterate over
|
||||
* @param includeUndefined should undefined elements be included in iteration
|
||||
*/
|
||||
protected JavaListIterator(final List<?> list, final boolean includeUndefined) {
|
||||
super(includeUndefined);
|
||||
this.list = list;
|
||||
this.length = list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the current index still inside the array
|
||||
* @return true if inside the array
|
||||
*/
|
||||
protected boolean indexInArray() {
|
||||
return index < length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next() {
|
||||
return list.get((int)bumpIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return indexInArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
list.remove(index);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.runtime.arrays;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
/**
|
||||
* Reverse iterator over a array
|
||||
*/
|
||||
final class ReverseJavaArrayIterator extends JavaArrayIterator {
|
||||
/**
|
||||
* Constructor
|
||||
* @param array array to iterate over
|
||||
* @param includeUndefined should undefined elements be included in iteration
|
||||
*/
|
||||
public ReverseJavaArrayIterator(final Object array, final boolean includeUndefined) {
|
||||
super(array, includeUndefined);
|
||||
this.index = Array.getLength(array) - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReverse() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean indexInArray() {
|
||||
return index >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long bumpIndex() {
|
||||
return index--;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.runtime.arrays;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Reverse iterator over a List
|
||||
*/
|
||||
final class ReverseJavaListIterator extends JavaListIterator {
|
||||
/**
|
||||
* Constructor
|
||||
* @param list list to iterate over
|
||||
* @param includeUndefined should undefined elements be included in iteration
|
||||
*/
|
||||
public ReverseJavaListIterator(final List<?> list, final boolean includeUndefined) {
|
||||
super(list, includeUndefined);
|
||||
this.index = list.size() - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReverse() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean indexInArray() {
|
||||
return index >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long bumpIndex() {
|
||||
return index--;
|
||||
}
|
||||
}
|
||||
@ -30,14 +30,14 @@ import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
/**
|
||||
* Reverse iterator over a NativeArray
|
||||
*/
|
||||
final class ReverseArrayIterator extends ArrayIterator {
|
||||
final class ReverseScriptArrayIterator extends ScriptArrayIterator {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param array array to iterate over
|
||||
* @param includeUndefined should undefined elements be included in iteration
|
||||
*/
|
||||
public ReverseArrayIterator(final ScriptObject array, final boolean includeUndefined) {
|
||||
public ReverseScriptArrayIterator(final ScriptObject array, final boolean includeUndefined) {
|
||||
super(array, includeUndefined);
|
||||
this.index = array.getArray().length() - 1;
|
||||
}
|
||||
@ -31,9 +31,9 @@ import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
/**
|
||||
* Reverse iterator over a map
|
||||
*/
|
||||
final class ReverseMapIterator extends MapIterator {
|
||||
final class ReverseScriptObjectIterator extends ScriptObjectIterator {
|
||||
|
||||
ReverseMapIterator(final ScriptObject obj, final boolean includeUndefined) {
|
||||
ReverseScriptObjectIterator(final ScriptObject obj, final boolean includeUndefined) {
|
||||
super(obj, includeUndefined);
|
||||
this.index = JSType.toUint32(obj.getLength()) - 1;
|
||||
}
|
||||
@ -30,7 +30,7 @@ import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
/**
|
||||
* Iterator over a NativeArray
|
||||
*/
|
||||
class ArrayIterator extends ArrayLikeIterator<Object> {
|
||||
class ScriptArrayIterator extends ArrayLikeIterator<Object> {
|
||||
|
||||
/** Array {@link ScriptObject} to iterate over */
|
||||
protected final ScriptObject array;
|
||||
@ -43,7 +43,7 @@ class ArrayIterator extends ArrayLikeIterator<Object> {
|
||||
* @param array array to iterate over
|
||||
* @param includeUndefined should undefined elements be included in iteration
|
||||
*/
|
||||
protected ArrayIterator(final ScriptObject array, final boolean includeUndefined) {
|
||||
protected ScriptArrayIterator(final ScriptObject array, final boolean includeUndefined) {
|
||||
super(includeUndefined);
|
||||
this.array = array;
|
||||
this.length = array.getArray().length();
|
||||
@ -32,12 +32,12 @@ import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
/**
|
||||
* Iterator over a map
|
||||
*/
|
||||
class MapIterator extends ArrayLikeIterator<Object> {
|
||||
class ScriptObjectIterator extends ArrayLikeIterator<Object> {
|
||||
|
||||
protected final ScriptObject obj;
|
||||
private final long length;
|
||||
|
||||
MapIterator(final ScriptObject obj, final boolean includeUndefined) {
|
||||
ScriptObjectIterator(final ScriptObject obj, final boolean includeUndefined) {
|
||||
super(includeUndefined);
|
||||
this.obj = obj;
|
||||
this.length = JSType.toUint32(obj.getLength());
|
||||
71
nashorn/test/script/basic/JDK-8023026.js
Normal file
71
nashorn/test/script/basic/JDK-8023026.js
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8023026: Array.prototype iterator functions like forEach, reduce should work for Java arrays, lists
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
function checkIterations(obj) {
|
||||
if (typeof obj.getClass == 'function') {
|
||||
print("iterating on an object of " + obj.getClass());
|
||||
} else {
|
||||
print("iterating on " + String(obj));
|
||||
}
|
||||
|
||||
Array.prototype.forEach.call(obj,
|
||||
function(x) { print("forEach " + x); });
|
||||
|
||||
print("left sum " + Array.prototype.reduce.call(obj,
|
||||
function(x, y) { print("reduce", x, y); return x + y; }));
|
||||
|
||||
print("right sum " + Array.prototype.reduceRight.call(obj,
|
||||
function(x, y) { print("reduceRight", x, y); return x + y; }));
|
||||
|
||||
print("squared " + Array.prototype.map.call(obj,
|
||||
function(x) x*x));
|
||||
}
|
||||
|
||||
var array = new (Java.type("[I"))(4);
|
||||
for (var i in array) {
|
||||
array[i] = i;
|
||||
}
|
||||
|
||||
checkIterations(array);
|
||||
|
||||
var list = new java.util.ArrayList();
|
||||
list.add(1);
|
||||
list.add(3);
|
||||
list.add(5);
|
||||
list.add(7);
|
||||
|
||||
checkIterations(list);
|
||||
|
||||
var mirror = loadWithNewGlobal({
|
||||
name: "test",
|
||||
script: "[2, 4, 6, 8]"
|
||||
});
|
||||
|
||||
checkIterations(mirror);
|
||||
42
nashorn/test/script/basic/JDK-8023026.js.EXPECTED
Normal file
42
nashorn/test/script/basic/JDK-8023026.js.EXPECTED
Normal file
@ -0,0 +1,42 @@
|
||||
iterating on an object of class [I
|
||||
forEach 0
|
||||
forEach 1
|
||||
forEach 2
|
||||
forEach 3
|
||||
reduce 0 1
|
||||
reduce 1 2
|
||||
reduce 3 3
|
||||
left sum 6
|
||||
reduceRight 3 2
|
||||
reduceRight 5 1
|
||||
reduceRight 6 0
|
||||
right sum 6
|
||||
squared 0,1,4,9
|
||||
iterating on an object of class java.util.ArrayList
|
||||
forEach 1
|
||||
forEach 3
|
||||
forEach 5
|
||||
forEach 7
|
||||
reduce 1 3
|
||||
reduce 4 5
|
||||
reduce 9 7
|
||||
left sum 16
|
||||
reduceRight 7 5
|
||||
reduceRight 12 3
|
||||
reduceRight 15 1
|
||||
right sum 16
|
||||
squared 1,9,25,49
|
||||
iterating on [object Array]
|
||||
forEach 2
|
||||
forEach 4
|
||||
forEach 6
|
||||
forEach 8
|
||||
reduce 2 4
|
||||
reduce 6 6
|
||||
reduce 12 8
|
||||
left sum 20
|
||||
reduceRight 8 6
|
||||
reduceRight 14 4
|
||||
reduceRight 18 2
|
||||
right sum 20
|
||||
squared 4,16,36,64
|
||||
Loading…
x
Reference in New Issue
Block a user