Fixing bug 137181 so after delete arguments[i], arguments[i] and corresponding function parameter in activation are not shared:

The patch uses the special NOT_FOUND value to flag deleted indexes. It also
make sure that original array object passed to Function.call is not modified,
as all changes goes to cloned copy. It is not necessary for the fix, but it is
the only place in the current Rhino that can alter Object[] array passed to
Function.call and I think it is better to remove this exceptional case.
This commit is contained in:
igor%mir2.org 2002-04-16 07:28:40 +00:00
Родитель 4aafc80db4
Коммит 5427ff0d5c
1 изменённых файлов: 63 добавлений и 26 удалений

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

@ -20,6 +20,7 @@
* *
* Contributor(s): * Contributor(s):
* Norris Boyd * Norris Boyd
* Igor Bukanov
* *
* Alternatively, the contents of this file may be used under the * Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the * terms of the GNU Public License (the "GPL"), in which case the
@ -72,51 +73,83 @@ class Arguments extends IdScriptable {
} }
public boolean has(int index, Scriptable start) { public boolean has(int index, Scriptable start) {
Object[] args = activation.getOriginalArguments(); if (0 <= index && index < args.length) {
return (0 <= index && index < args.length) || super.has(index, start); if (args[index] != NOT_FOUND) {
return true;
}
}
return super.has(index, start);
} }
public Object get(int index, Scriptable start) { public Object get(int index, Scriptable start) {
if (0 <= index && index < args.length) { if (0 <= index && index < args.length) {
NativeFunction f = activation.funObj; Object value = args[index];
if (index < f.argCount) { if (value != NOT_FOUND) {
String argName = f.argNames[index]; if (sharedWithActivation(index)) {
for (int i=index+1; i < f.argNames.length; i++) { String argName = activation.funObj.argNames[index];
if (argName.equals(f.argNames[i])) { value = activation.get(argName, activation);
// duplicate parameter name, must use initial if (value == NOT_FOUND) Context.codeBug();
// parameter value
Object[] orig = activation.getOriginalArguments();
return index < orig.length ? orig[index]
: Undefined.instance;
} }
return value;
} }
return activation.get(f.argNames[index], activation);
}
return args[index];
} }
return super.get(index, start); return super.get(index, start);
} }
private boolean sharedWithActivation(int index) {
NativeFunction f = activation.funObj;
int definedCount = f.argCount;
if (index < definedCount) {
// Check if argument is not hidden by later argument with the same
// name as hidden arguments are not shared with activation
if (index < definedCount - 1) {
String argName = f.argNames[index];
for (int i = index + 1; i < definedCount; i++) {
if (argName.equals(f.argNames[i])) {
return false;
}
}
}
return true;
}
return false;
}
public void put(int index, Scriptable start, Object value) { public void put(int index, Scriptable start, Object value) {
if (0 <= index && index < args.length) { if (0 <= index && index < args.length) {
NativeFunction f = activation.funObj; if (args[index] != NOT_FOUND) {
if (index < f.argCount) if (sharedWithActivation(index)) {
activation.put(f.argNames[index], activation, value); String argName = activation.funObj.argNames[index];
else activation.put(argName, activation, value);
return;
}
synchronized (this) {
if (args[index] != NOT_FOUND) {
if (args == activation.getOriginalArguments()) {
args = (Object[])args.clone();
}
args[index] = value; args[index] = value;
return; return;
} }
}
}
}
super.put(index, start, value); super.put(index, start, value);
} }
public void delete(int index) { public void delete(int index) {
if (0 <= index && index < args.length) { if (0 <= index && index < args.length) {
NativeFunction f = activation.funObj; synchronized (this) {
if (index < f.argCount) if (args[index] != NOT_FOUND) {
activation.delete(f.argNames[index]); if (args == activation.getOriginalArguments()) {
else args = (Object[])args.clone();
args[index] = Undefined.instance;
} }
args[index] = NOT_FOUND;
return;
}
}
}
super.delete(index);
} }
protected int getIdDefaultAttributes(int id) { protected int getIdDefaultAttributes(int id) {
@ -228,5 +261,9 @@ class Arguments extends IdScriptable {
private Object lengthObj; private Object lengthObj;
private NativeCall activation; private NativeCall activation;
// Initially args holds activation.getOriginalArgs(), but any modification
// of its elements triggers creation of a copy. If its element holds NOT_FOUND,
// it indicates deleted index, in which case super class is queried.
private Object[] args; private Object[] args;
} }