зеркало из https://github.com/mozilla/pjs.git
Patch from Igor:
I suggest to move the code in ScriptableObject.get/put that deals with getter/setter into separated methods so it would be easy to follow the code and the attached patch does just that.
This commit is contained in:
Родитель
209698adb6
Коммит
2d22ea1689
|
@ -144,38 +144,19 @@ public abstract class ScriptableObject implements Scriptable, Serializable {
|
||||||
public Object get(String name, Scriptable start) {
|
public Object get(String name, Scriptable start) {
|
||||||
Slot slot = lastAccess; // Get local copy
|
Slot slot = lastAccess; // Get local copy
|
||||||
if (name == slot.stringKey) {
|
if (name == slot.stringKey) {
|
||||||
|
// Cache match, check if it was not deleted
|
||||||
if (slot.wasDeleted == 0) { return slot.value; }
|
if (slot.wasDeleted == 0) { return slot.value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
int hashCode = name.hashCode();
|
int hashCode = name.hashCode();
|
||||||
slot = getSlot(name, hashCode, false);
|
slot = getSlot(name, hashCode, false);
|
||||||
if (slot == null)
|
if (slot == null) {
|
||||||
return Scriptable.NOT_FOUND;
|
return Scriptable.NOT_FOUND;
|
||||||
if ((slot.flags & Slot.HAS_GETTER) != 0) {
|
|
||||||
GetterSlot getterSlot = (GetterSlot) slot;
|
|
||||||
try {
|
|
||||||
if (getterSlot.delegateTo == null) {
|
|
||||||
// Walk the prototype chain to find an appropriate
|
|
||||||
// object to invoke the getter on.
|
|
||||||
Class clazz = getterSlot.getter.getDeclaringClass();
|
|
||||||
while (!clazz.isInstance(start)) {
|
|
||||||
start = start.getPrototype();
|
|
||||||
if (start == null) {
|
|
||||||
start = this;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return getterSlot.getter.invoke(start, ScriptRuntime.emptyArgs);
|
|
||||||
}
|
|
||||||
Object[] args = { this };
|
|
||||||
return getterSlot.getter.invoke(getterSlot.delegateTo, args);
|
|
||||||
}
|
|
||||||
catch (InvocationTargetException e) {
|
|
||||||
throw WrappedException.wrapException(e);
|
|
||||||
}
|
|
||||||
catch (IllegalAccessException e) {
|
|
||||||
throw WrappedException.wrapException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if ((slot.flags & Slot.HAS_GETTER) != 0) {
|
||||||
|
return getByGetter((GetterSlot) slot, name, start);
|
||||||
|
}
|
||||||
|
|
||||||
// Here stringKey.equals(name) holds, but it can be that
|
// Here stringKey.equals(name) holds, but it can be that
|
||||||
// slot.stringKey != name. To make last name cache work, need
|
// slot.stringKey != name. To make last name cache work, need
|
||||||
// to change the key
|
// to change the key
|
||||||
|
@ -186,6 +167,35 @@ public abstract class ScriptableObject implements Scriptable, Serializable {
|
||||||
return slot.value;
|
return slot.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object getByGetter(GetterSlot slot,
|
||||||
|
String name, Scriptable start)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (slot.delegateTo == null) {
|
||||||
|
// Walk the prototype chain to find an appropriate
|
||||||
|
// object to invoke the getter on.
|
||||||
|
Class clazz = slot.getter.getDeclaringClass();
|
||||||
|
while (!clazz.isInstance(start)) {
|
||||||
|
start = start.getPrototype();
|
||||||
|
if (start == null) {
|
||||||
|
start = this;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return slot.getter.invoke(start, ScriptRuntime.emptyArgs);
|
||||||
|
}
|
||||||
|
Object[] args = { this };
|
||||||
|
return slot.getter.invoke(slot.delegateTo, args);
|
||||||
|
}
|
||||||
|
catch (InvocationTargetException e) {
|
||||||
|
throw WrappedException.wrapException(e);
|
||||||
|
}
|
||||||
|
catch (IllegalAccessException e) {
|
||||||
|
throw WrappedException.wrapException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of the indexed property or NOT_FOUND.
|
* Returns the value of the indexed property or NOT_FOUND.
|
||||||
*
|
*
|
||||||
|
@ -228,50 +238,12 @@ public abstract class ScriptableObject implements Scriptable, Serializable {
|
||||||
slot = getSlotToSet(name, hash);
|
slot = getSlotToSet(name, hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((slot.attributes & ScriptableObject.READONLY) != 0)
|
if ((slot.attributes & ScriptableObject.READONLY) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ((slot.flags & Slot.HAS_SETTER) != 0) {
|
||||||
|
setBySetter((GetterSlot)slot, name, start, value);
|
||||||
return;
|
return;
|
||||||
if ((slot.flags & Slot.HAS_SETTER) != 0) {
|
|
||||||
GetterSlot getterSlot = (GetterSlot) slot;
|
|
||||||
try {
|
|
||||||
Class pTypes[] = getterSlot.setter.getParameterTypes();
|
|
||||||
Class desired = pTypes[pTypes.length - 1];
|
|
||||||
Object actualArg
|
|
||||||
= FunctionObject.convertArg(start, value, desired);
|
|
||||||
if (getterSlot.delegateTo == null) {
|
|
||||||
// Walk the prototype chain to find an appropriate
|
|
||||||
// object to invoke the setter on.
|
|
||||||
Object[] arg = { actualArg };
|
|
||||||
Class clazz = getterSlot.setter.getDeclaringClass();
|
|
||||||
while (!clazz.isInstance(start)) {
|
|
||||||
start = start.getPrototype();
|
|
||||||
if (start == null) {
|
|
||||||
start = this;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Object v = getterSlot.setter.invoke(start, arg);
|
|
||||||
if (getterSlot.setterReturnsValue) {
|
|
||||||
slot.value = v;
|
|
||||||
if (!(v instanceof Method))
|
|
||||||
slot.flags = 0;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Object[] args = { this, actualArg };
|
|
||||||
Object v = getterSlot.setter.invoke(getterSlot.delegateTo, args);
|
|
||||||
if (getterSlot.setterReturnsValue) {
|
|
||||||
slot.value = v;
|
|
||||||
if (!(v instanceof Method))
|
|
||||||
slot.flags = 0;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (InvocationTargetException e) {
|
|
||||||
throw WrappedException.wrapException(e);
|
|
||||||
}
|
|
||||||
catch (IllegalAccessException e) {
|
|
||||||
throw WrappedException.wrapException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (this == start) {
|
if (this == start) {
|
||||||
slot.value = value;
|
slot.value = value;
|
||||||
|
@ -283,6 +255,50 @@ public abstract class ScriptableObject implements Scriptable, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setBySetter(GetterSlot slot,
|
||||||
|
String name, Scriptable start, Object value)
|
||||||
|
{
|
||||||
|
Object setterResult;
|
||||||
|
try {
|
||||||
|
Class pTypes[] = slot.setter.getParameterTypes();
|
||||||
|
Class desired = pTypes[pTypes.length - 1];
|
||||||
|
Object actualArg
|
||||||
|
= FunctionObject.convertArg(start, value, desired);
|
||||||
|
if (slot.delegateTo == null) {
|
||||||
|
// Walk the prototype chain to find an appropriate
|
||||||
|
// object to invoke the setter on.
|
||||||
|
Object[] arg = { actualArg };
|
||||||
|
Class clazz = slot.setter.getDeclaringClass();
|
||||||
|
while (!clazz.isInstance(start)) {
|
||||||
|
start = start.getPrototype();
|
||||||
|
if (start == null) {
|
||||||
|
start = this;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setterResult = slot.setter.invoke(start, arg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Object[] args = { this, actualArg };
|
||||||
|
setterResult = slot.setter.invoke(slot.delegateTo, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InvocationTargetException e) {
|
||||||
|
throw WrappedException.wrapException(e);
|
||||||
|
}
|
||||||
|
catch (IllegalAccessException e) {
|
||||||
|
throw WrappedException.wrapException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot.setterReturnsValue) {
|
||||||
|
slot.value = setterResult;
|
||||||
|
if (!(setterResult instanceof Method)) {
|
||||||
|
slot.flags = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value of the indexed property, creating it if need be.
|
* Sets the value of the indexed property, creating it if need be.
|
||||||
*
|
*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче