Fix bug 310323: implement new array extras (forEach, indexOf, filter, map,

some, every)
This commit is contained in:
nboyd%atg.com 2005-09-28 16:13:27 +00:00
Родитель abe8b3971a
Коммит cfae79c4c1
1 изменённых файлов: 148 добавлений и 12 удалений

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

@ -64,6 +64,7 @@ public class NativeArray extends IdScriptableObject
*/
private static final Object ARRAY_TAG = new Object();
private static final Integer NEGATIVE_ONE = new Integer(-1);
static void init(Scriptable scope, boolean sealed)
{
@ -162,6 +163,13 @@ public class NativeArray extends IdScriptableObject
case Id_splice: arity=1; s="splice"; break;
case Id_concat: arity=1; s="concat"; break;
case Id_slice: arity=1; s="slice"; break;
case Id_indexOf: arity=1; s="indexOf"; break;
case Id_lastIndexOf: arity=1; s="lastIndexOf"; break;
case Id_every: arity=1; s="every"; break;
case Id_filter: arity=1; s="filter"; break;
case Id_forEach: arity=1; s="forEach"; break;
case Id_map: arity=1; s="map"; break;
case Id_some: arity=1; s="some"; break;
default: throw new IllegalArgumentException(String.valueOf(id));
}
initPrototypeMethod(ARRAY_TAG, id, s, arity);
@ -223,6 +231,19 @@ public class NativeArray extends IdScriptableObject
case Id_slice:
return js_slice(cx, thisObj, args);
case Id_indexOf:
return indexOfHelper(cx, thisObj, args, false);
case Id_lastIndexOf:
return indexOfHelper(cx, thisObj, args, true);
case Id_every:
case Id_filter:
case Id_forEach:
case Id_map:
case Id_some:
return iterativeMethod(cx, id, scope, thisObj, args);
}
throw new IllegalArgumentException(String.valueOf(id));
}
@ -1133,38 +1154,146 @@ public class NativeArray extends IdScriptableObject
return result;
}
/**
* Implements the methods "indexOf" and "lastIndexOf".
*/
private Object indexOfHelper(Context cx, Scriptable thisObj,
Object[] args, boolean isLast)
{
Object compareTo = args.length > 0 ? args[0] : Undefined.instance;
long length = getLengthProperty(cx, thisObj);
long start = args.length > 1
? ScriptRuntime.toInt32(ScriptRuntime.toNumber(args[1]))
: (isLast ? length : 0);
if (start < 0) {
start += length;
if (start < 0)
start = 0;
}
if (isLast) {
for (long i=start; i >= 0 ; i--) {
if (ScriptRuntime.shallowEq(getElem(cx, thisObj, i), compareTo)) {
return new Long(i);
}
}
} else {
for (long i=start; i < length; i++) {
if (ScriptRuntime.shallowEq(getElem(cx, thisObj, i), compareTo)) {
return new Long(i);
}
}
}
return NEGATIVE_ONE;
}
/**
* Implements the methods "every", "filter", "forEach", "map", and "some".
*/
private Object iterativeMethod(Context cx, int id, Scriptable scope,
Scriptable thisObj, Object[] args)
{
Object callbackArg = args.length > 0 ? args[0] : Undefined.instance;
if (callbackArg == null || !(callbackArg instanceof Function)) {
throw ScriptRuntime.notFunctionError(
ScriptRuntime.toString(callbackArg));
}
Function f = (Function) callbackArg;
Scriptable parent = ScriptableObject.getTopLevelScope(f);
Scriptable thisArg = args.length > 1 && args[1] instanceof Scriptable
? (Scriptable) args[1]
: parent;
long length = getLengthProperty(cx, thisObj);
Scriptable array = null;
if (id == Id_filter) {
array = ScriptRuntime.newObject(cx, scope, "Array", null);
} else if (id == Id_map) {
// allocate dense array for efficiency
Object[] ctorArgs = { new Long(length) };
array = ScriptRuntime.newObject(cx, scope, "Array", ctorArgs);
}
Object[] innerArgs = new Object[3];
long j=0;
for (long i=0; i < length; i++) {
innerArgs[0] = getElem(cx, thisObj, i);
innerArgs[1] = new Long(i);
innerArgs[2] = thisObj;
Object result = f.call(cx, parent, thisArg, innerArgs);
switch (id) {
case Id_every:
if (!ScriptRuntime.toBoolean(result))
return Boolean.FALSE;
break;
case Id_filter:
if (ScriptRuntime.toBoolean(result))
setElem(cx, array, j++, innerArgs[0]);
break;
case Id_forEach:
break;
case Id_map:
setElem(cx, array, j++, result);
break;
case Id_some:
if (ScriptRuntime.toBoolean(result))
return Boolean.TRUE;
break;
}
}
switch (id) {
case Id_every:
return Boolean.TRUE;
case Id_filter:
case Id_map:
return array;
case Id_some:
return Boolean.FALSE;
case Id_forEach:
default:
return Undefined.instance;
}
}
// #string_id_map#
protected int findPrototypeId(String s)
{
int id;
// #generated# Last update: 2004-03-17 13:17:02 CET
// #generated# Last update: 2005-09-26 15:47:42 EDT
L0: { id = 0; String X = null; int c;
L: switch (s.length()) {
case 3: X="pop";id=Id_pop; break L;
case 4: c=s.charAt(0);
if (c=='j') { X="join";id=Id_join; }
else if (c=='p') { X="push";id=Id_push; }
else if (c=='s') { X="sort";id=Id_sort; }
case 3: c=s.charAt(0);
if (c=='m') { if (s.charAt(2)=='p' && s.charAt(1)=='a') {id=Id_map; break L0;} }
else if (c=='p') { if (s.charAt(2)=='p' && s.charAt(1)=='o') {id=Id_pop; break L0;} }
break L;
case 4: switch (s.charAt(2)) {
case 'i': X="join";id=Id_join; break L;
case 'm': X="some";id=Id_some; break L;
case 'r': X="sort";id=Id_sort; break L;
case 's': X="push";id=Id_push; break L;
} break L;
case 5: c=s.charAt(1);
if (c=='h') { X="shift";id=Id_shift; }
else if (c=='l') { X="slice";id=Id_slice; }
else if (c=='v') { X="every";id=Id_every; }
break L;
case 6: c=s.charAt(0);
if (c=='c') { X="concat";id=Id_concat; }
else if (c=='f') { X="filter";id=Id_filter; }
else if (c=='s') { X="splice";id=Id_splice; }
break L;
case 7: c=s.charAt(0);
if (c=='r') { X="reverse";id=Id_reverse; }
else if (c=='u') { X="unshift";id=Id_unshift; }
break L;
case 7: switch (s.charAt(0)) {
case 'f': X="forEach";id=Id_forEach; break L;
case 'i': X="indexOf";id=Id_indexOf; break L;
case 'r': X="reverse";id=Id_reverse; break L;
case 'u': X="unshift";id=Id_unshift; break L;
} break L;
case 8: c=s.charAt(3);
if (c=='o') { X="toSource";id=Id_toSource; }
else if (c=='t') { X="toString";id=Id_toString; }
break L;
case 11: X="constructor";id=Id_constructor; break L;
case 11: c=s.charAt(0);
if (c=='c') { X="constructor";id=Id_constructor; }
else if (c=='l') { X="lastIndexOf";id=Id_lastIndexOf; }
break L;
case 14: X="toLocaleString";id=Id_toLocaleString; break L;
}
if (X!=null && X!=s && !X.equals(s)) id = 0;
@ -1188,8 +1317,15 @@ public class NativeArray extends IdScriptableObject
Id_splice = 12,
Id_concat = 13,
Id_slice = 14,
Id_indexOf = 15,
Id_lastIndexOf = 16,
Id_every = 17,
Id_filter = 18,
Id_forEach = 19,
Id_map = 20,
Id_some = 21,
MAX_PROTOTYPE_ID = 14;
MAX_PROTOTYPE_ID = 21;
// #/string_id_map#