зеркало из https://github.com/mozilla/pjs.git
I've made changes to Rhino such that its default behavior is now only to treat
Iterables or Iterators specially when they are arguments to the new Iterator constructor: js> m = new java.util.HashMap() {} js> m.put("a",1) null js> m.put("b",2) null js> m {a=1.0, b=2.0} js> for (i in m.values()) print(i) notifyAll removeAll containsAll contains empty equals notify class isEmpty add size iterator clear wait retainAll toString hashCode toArray addAll getClass remove js> for (i in Iterator(m.values())) print(i) 1.0 2.0 js> for (i in Iterator(m.values().iterator())) print(i) 1.0 2.0 js> Since Iterator is a new addition for 1.7, there are no issues for backwards compatibility. This still leaves open the possibility of top-level functions to wrap Maps and Lists as JavaScript Objects and Arrays.
This commit is contained in:
Родитель
a1eb01d71b
Коммит
25a7cab519
|
@ -640,20 +640,6 @@ class JavaMembers
|
|||
}
|
||||
}
|
||||
|
||||
// For objects that implement java.lang.Iterable, provide a
|
||||
// __iterator__ property
|
||||
if (iterableClass != null && iterableClass.isAssignableFrom(cl) &&
|
||||
members.get(NativeIterator.ITERATOR_PROPERTY_NAME) == null &&
|
||||
staticMembers.get(NativeIterator.ITERATOR_PROPERTY_NAME) == null)
|
||||
{
|
||||
Method m = VMBridge.instance.getIteratorMethod();
|
||||
if (m != null) {
|
||||
members.put(NativeIterator.ITERATOR_PROPERTY_NAME,
|
||||
new FunctionObject(NativeIterator.ITERATOR_PROPERTY_NAME,
|
||||
m, scope));
|
||||
}
|
||||
}
|
||||
|
||||
// Reflect constructors
|
||||
Constructor[] constructors = getAccessibleConstructors();
|
||||
ctors = new MemberBox[constructors.length];
|
||||
|
@ -874,7 +860,6 @@ class JavaMembers
|
|||
private Hashtable staticFieldAndMethods;
|
||||
MemberBox[] ctors;
|
||||
private boolean includePrivate;
|
||||
private static Class iterableClass = Kit.classOrNull("java.lang.Iterable");
|
||||
}
|
||||
|
||||
class BeanProperty
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* This class implements iterator objects. See
|
||||
* http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7#Iterators
|
||||
|
@ -161,10 +163,24 @@ public final class NativeIterator extends IdScriptableObject {
|
|||
boolean keyOnly = args.length > 1 && ScriptRuntime.toBoolean(args[1]);
|
||||
if (thisObj != null) {
|
||||
// Called as a function. Convert to iterator if possible.
|
||||
Scriptable iterator = ScriptRuntime.toIterator(cx, scope, obj,
|
||||
keyOnly);
|
||||
|
||||
// For objects that implement java.lang.Iterable or
|
||||
// java.util.Iterator, have JavaScript Iterator call the underlying
|
||||
// iteration methods
|
||||
Iterator iterator =
|
||||
VMBridge.instance.getJavaIterator(cx, scope, obj);
|
||||
if (iterator != null) {
|
||||
return iterator;
|
||||
scope = ScriptableObject.getTopLevelScope(scope);
|
||||
return cx.getWrapFactory().wrap(cx, scope,
|
||||
new WrappedJavaIterator(iterator, scope),
|
||||
WrappedJavaIterator.class);
|
||||
}
|
||||
|
||||
// Otherwise, just call the runtime routine
|
||||
Scriptable jsIterator = ScriptRuntime.toIterator(cx, scope, obj,
|
||||
keyOnly);
|
||||
if (jsIterator != null) {
|
||||
return jsIterator;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,6 +210,30 @@ public final class NativeIterator extends IdScriptableObject {
|
|||
return cx.newArray(scope, elements);
|
||||
}
|
||||
|
||||
static public class WrappedJavaIterator
|
||||
{
|
||||
WrappedJavaIterator(Iterator iterator, Scriptable scope) {
|
||||
this.iterator = iterator;
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
if (!iterator.hasNext()) {
|
||||
// Out of values. Throw StopIteration.
|
||||
throw new JavaScriptException(
|
||||
NativeIterator.getStopIterationObject(scope), null, 0);
|
||||
}
|
||||
return iterator.next();
|
||||
}
|
||||
|
||||
public Object __iterator__(boolean b) {
|
||||
return this;
|
||||
}
|
||||
|
||||
private Iterator iterator;
|
||||
private Scriptable scope;
|
||||
}
|
||||
|
||||
// #string_id_map#
|
||||
|
||||
protected int findPrototypeId(String s) {
|
||||
|
|
|
@ -41,6 +41,7 @@ package org.mozilla.javascript;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Member;
|
||||
import java.util.Iterator;
|
||||
|
||||
public abstract class VMBridge
|
||||
{
|
||||
|
@ -165,10 +166,18 @@ public abstract class VMBridge
|
|||
protected abstract boolean isVarArgs(Member member);
|
||||
|
||||
/**
|
||||
* return method corresponding to __iterator__ for treating a
|
||||
* java.lang.Iterable as a JavaScript Iterator
|
||||
* If "obj" is a java.util.Iterator or a java.lang.Iterable, return a
|
||||
* wrapping as a JavaScript Iterator. Otherwise, return null.
|
||||
* This method is in VMBridge since Iterable is a JDK 1.5 addition.
|
||||
*/
|
||||
public Method getIteratorMethod() {
|
||||
public Iterator getJavaIterator(Context cx, Scriptable scope, Object obj) {
|
||||
if (obj instanceof Wrapper) {
|
||||
Object unwrapped = ((Wrapper) obj).unwrap();
|
||||
Iterator iterator = null;
|
||||
if (unwrapped instanceof Iterator)
|
||||
iterator = (Iterator) unwrapped;
|
||||
return iterator;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public class VMBridge_jdk15 extends org.mozilla.javascript.jdk13.VMBridge_jdk13
|
|||
// so that we can load a bridge to an older JDK instead.
|
||||
Method.class.getMethod("isVarArgs", (Class[]) null);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// Throw a fittitng exception that is handled by
|
||||
// Throw a fitting exception that is handled by
|
||||
// org.mozilla.javascript.Kit.newInstanceOrNull:
|
||||
throw new InstantiationException(e.getMessage());
|
||||
}
|
||||
|
@ -67,55 +67,21 @@ public class VMBridge_jdk15 extends org.mozilla.javascript.jdk13.VMBridge_jdk13
|
|||
return false;
|
||||
}
|
||||
|
||||
public Method getIteratorMethod() {
|
||||
try {
|
||||
Class[] sig = { Context.class, Scriptable.class,
|
||||
ScriptRuntime.emptyArgs.getClass(),
|
||||
Function.class };
|
||||
return VMBridge_jdk15.class.getMethod("__iterator__", sig);
|
||||
} catch (NoSuchMethodException e) {
|
||||
/**
|
||||
* If "obj" is a java.util.Iterator or a java.lang.Iterable, return a
|
||||
* wrapping as a JavaScript Iterator. Otherwise, return null.
|
||||
* This method is in VMBridge since Iterable is a JDK 1.5 addition.
|
||||
*/
|
||||
public Iterator getJavaIterator(Context cx, Scriptable scope, Object obj) {
|
||||
if (obj instanceof Wrapper) {
|
||||
Object unwrapped = ((Wrapper) obj).unwrap();
|
||||
Iterator iterator = null;
|
||||
if (unwrapped instanceof Iterator)
|
||||
iterator = (Iterator) unwrapped;
|
||||
if (unwrapped instanceof Iterable)
|
||||
iterator = ((Iterable)unwrapped).iterator();
|
||||
return iterator;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object __iterator__(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
if (thisObj instanceof Wrapper) {
|
||||
Object obj = ((Wrapper) thisObj).unwrap();
|
||||
if (obj instanceof Iterable) {
|
||||
Scriptable scope = ScriptableObject.getTopLevelScope(funObj);
|
||||
return cx.getWrapFactory().wrap(cx, scope,
|
||||
new WrappedJavaIterator((Iterable) obj, scope),
|
||||
WrappedJavaIterator.class);
|
||||
}
|
||||
}
|
||||
throw ScriptRuntime.typeError1("msg.incompat.call",
|
||||
NativeIterator.ITERATOR_PROPERTY_NAME);
|
||||
}
|
||||
|
||||
static public class WrappedJavaIterator
|
||||
{
|
||||
WrappedJavaIterator(Iterable iterable, Scriptable scope) {
|
||||
this.iterator = iterable.iterator();
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
if (!iterator.hasNext()) {
|
||||
// Out of values. Throw StopIteration.
|
||||
throw new JavaScriptException(
|
||||
NativeIterator.getStopIterationObject(scope), null, 0);
|
||||
}
|
||||
return iterator.next();
|
||||
}
|
||||
|
||||
public Object __iterator__() {
|
||||
return this;
|
||||
}
|
||||
|
||||
private Iterator iterator;
|
||||
private Scriptable scope;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче