Fix bug 414098 - Support for __define[GS]etter__ on array indexes

Patch from Matthieu Riou
This commit is contained in:
nboyd%atg.com 2008-02-05 18:37:47 +00:00
Родитель 7535fa175e
Коммит a4164076c6
3 изменённых файлов: 46 добавлений и 5 удалений

Просмотреть файл

@ -310,6 +310,8 @@ public class NativeArray extends IdScriptableObject
public synchronized Object get(int index, Scriptable start)
{
if (isGetterOrSetter(null, index, false))
return super.get(index, start);
if (dense != null && 0 <= index && index < dense.length)
return dense[index];
return super.get(index, start);
@ -317,6 +319,8 @@ public class NativeArray extends IdScriptableObject
public synchronized boolean has(int index, Scriptable start)
{
if (isGetterOrSetter(null, index, false))
return super.has(index, start);
if (dense != null && 0 <= index && index < dense.length)
return dense[index] != NOT_FOUND;
return super.has(index, start);
@ -372,6 +376,8 @@ public class NativeArray extends IdScriptableObject
public synchronized void put(int index, Scriptable start, Object value)
{
if (isGetterOrSetter(null, index, true))
super.put(index, start, value);
if (start == this && !isSealed() && dense != null && 0 <= index) {
if (index < dense.length) {
dense[index] = value;
@ -401,6 +407,8 @@ public class NativeArray extends IdScriptableObject
public synchronized void delete(int index)
{
if (isGetterOrSetter(null, index, true))
super.delete(index);
if (!isSealed() && dense != null && 0 <= index && index < dense.length)
{
dense[index] = NOT_FOUND;
@ -485,6 +493,21 @@ public class NativeArray extends IdScriptableObject
public long jsGet_length() {
return getLength();
}
/**
* Change the value of the internal flag that determines whether all
* storage is handed by a dense backing array rather than an associative
* store.
* @param denseOnly new value for denseOnly flag
* @throws IllegalArgumentException if an attempt is made to enable
* denseOnly after it was disabled; NativeArray code is not written
* to handle switching back to a dense representation
*/
void setDenseOnly(boolean denseOnly) {
if (denseOnly && !this.denseOnly)
throw new IllegalArgumentException();
this.denseOnly = denseOnly;
}
private synchronized void setLength(Object val) {
/* XXX do we satisfy this?
@ -1630,7 +1653,7 @@ public class NativeArray extends IdScriptableObject
// #/generated#
return id;
}
private static final int
Id_constructor = 1,
Id_toString = 2,

Просмотреть файл

@ -215,6 +215,8 @@ public class NativeObject extends IdScriptableObject
Callable getterOrSetter = (Callable)args[1];
boolean isSetter = (id == Id___defineSetter__);
so.setGetterOrSetter(name, index, getterOrSetter, isSetter);
if (so instanceof NativeArray)
((NativeArray)so).setDenseOnly(false);
}
return Undefined.instance;

Просмотреть файл

@ -582,6 +582,22 @@ public abstract class ScriptableObject implements Scriptable, Serializable,
return Undefined.instance;
}
/**
* Returns whether a property is a getter or a setter
* @param name property name
* @param index property index
* @param setter true to check for a setter, false for a getter
* @return whether the property is a getter or a setter
*/
protected boolean isGetterOrSetter(String name, int index, boolean setter) {
Slot slot = getSlot(name, index, SLOT_QUERY);
if (slot instanceof GetterSlot) {
if (setter && ((GetterSlot)slot).setter != null) return true;
if (!setter && ((GetterSlot)slot).getter != null) return true;
}
return false;
}
void addLazilyInitializedValue(String name, int index,
LazilyLoadedCtor init, int attributes)
{
@ -1963,9 +1979,9 @@ public abstract class ScriptableObject implements Scriptable, Serializable,
}
return nativeGetter.invoke(getterThis, args);
} else {
Callable f = (Callable)getterObj;
Function f = (Function)getterObj;
Context cx = Context.getContext();
return f.call(cx, ScriptRuntime.getTopCallScope(cx), start,
return f.call(cx, f.getParentScope(), start,
ScriptRuntime.emptyArgs);
}
}
@ -2046,8 +2062,8 @@ public abstract class ScriptableObject implements Scriptable, Serializable,
}
nativeSetter.invoke(setterThis, args);
} else {
Callable f = (Callable)setterObj;
f.call(cx, ScriptRuntime.getTopCallScope(cx), start,
Function f = (Function)setterObj;
f.call(cx, f.getParentScope(), start,
new Object[] { value });
}
return true;