1.8 branch landing of bug 310425 patch (a=mscott).

git-svn-id: svn://10.0.0.236/branches/MOZILLA_1_8_BRANCH@181459 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
brendan%mozilla.org
2005-10-03 03:07:23 +00:00
parent 9ae86c831c
commit 8abe73e967

View File

@@ -188,25 +188,25 @@ js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
}
static JSBool
IndexToValue(JSContext *cx, jsuint length, jsval *vp)
IndexToValue(JSContext *cx, jsuint index, jsval *vp)
{
if (length <= JSVAL_INT_MAX) {
*vp = INT_TO_JSVAL(length);
if (index <= JSVAL_INT_MAX) {
*vp = INT_TO_JSVAL(index);
return JS_TRUE;
}
return js_NewDoubleValue(cx, (jsdouble)length, vp);
return js_NewDoubleValue(cx, (jsdouble)index, vp);
}
static JSBool
IndexToId(JSContext *cx, jsuint length, jsid *idp)
IndexToId(JSContext *cx, jsuint index, jsid *idp)
{
JSString *str;
JSAtom *atom;
if (length <= JSVAL_INT_MAX) {
*idp = INT_TO_JSID(length);
if (index <= JSVAL_INT_MAX) {
*idp = INT_TO_JSID(index);
} else {
str = js_NumberToString(cx, (jsdouble)length);
str = js_NumberToString(cx, (jsdouble)index);
if (!str)
return JS_FALSE;
atom = js_AtomizeString(cx, str, 0);
@@ -235,6 +235,22 @@ PropertyExists(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp)
return JS_TRUE;
}
#define JSID_HOLE JSVAL_NULL
static JSBool
IndexToExistingId(JSContext *cx, JSObject *obj, jsuint index, jsid *idp)
{
JSBool exists;
if (!IndexToId(cx, index, idp))
return JS_FALSE;
if (!PropertyExists(cx, obj, *idp, &exists))
return JS_FALSE;
if (!exists)
*idp = JSID_HOLE;
return JS_TRUE;
}
JSBool
js_SetLengthProperty(JSContext *cx, JSObject *obj, jsuint length)
{
@@ -637,7 +653,7 @@ array_reverse(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return JS_FALSE;
}
/*
/*
* Get both of the values now. Note that we don't use v, or v2 based on
* idexists and id2exists.
*/
@@ -654,7 +670,7 @@ array_reverse(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return JS_FALSE;
}
if (id2exists) {
if (!OBJ_SET_PROPERTY(cx, obj, id, &v2))
if (!OBJ_SET_PROPERTY(cx, obj, id, &v2))
return JS_FALSE;
} else {
if (!OBJ_DELETE_PROPERTY(cx, obj, id, &v2))
@@ -791,7 +807,7 @@ sort_compare(const void *a, const void *b, void *arg)
fval = ca->fval;
/*
/*
* By ECMA 262, 15.4.4.11, existence of the property with value undefined
* takes precedence over an undefined property (which we call a "hole").
*/
@@ -876,7 +892,6 @@ array_sort(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
JSStackFrame *fp;
jsid id;
size_t nbytes;
JSBool idexists;
/*
* Optimize the default compare function case if all of obj's elements
@@ -926,14 +941,11 @@ array_sort(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
fp->nvars = len;
for (i = 0; i < len; i++) {
ca.status = IndexToId(cx, i, &id);
ca.status = IndexToExistingId(cx, obj, i, &id);
if (!ca.status)
goto out;
ca.status = PropertyExists(cx, obj, id, &idexists);
if (!ca.status)
goto out;
if (!idexists) {
if (id == JSID_HOLE) {
vec[i] = JSVAL_HOLE;
all_strings = JS_FALSE;
continue;
@@ -1088,7 +1100,6 @@ array_unshift(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
uintN i;
jsid id, id2;
jsval v;
JSBool propExists;
if (!js_GetLengthProperty(cx, obj, &length))
return JS_FALSE;
@@ -1097,18 +1108,16 @@ array_unshift(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
if (length > 0) {
last = length;
while (last--) {
if (!IndexToId(cx, last, &id))
if (!IndexToExistingId(cx, obj, last, &id))
return JS_FALSE;
if (!IndexToId(cx, last + argc, &id2))
return JS_FALSE;
if (!PropertyExists(cx, obj, id, &propExists))
return JS_FALSE;
if (!propExists) {
if (id == JSID_HOLE) {
OBJ_DELETE_PROPERTY(cx, obj, id2, &v); /* v is junk. */
continue;
}
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
return JS_FALSE;
if (!IndexToId(cx, last + argc, &id2))
return JS_FALSE;
if (!OBJ_SET_PROPERTY(cx, obj, id2, &v))
return JS_FALSE;
}
@@ -1139,7 +1148,6 @@ array_splice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsid id, id2;
jsval v;
JSObject *obj2;
JSBool propExists;
/* Nothing to do if no args. Otherwise lock and load length. */
if (argc == 0)
@@ -1213,16 +1221,14 @@ array_splice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
/* If there are elements to remove, put them into the return value. */
if (count > 0) {
for (last = begin; last < end; last++) {
if (!IndexToId(cx, last, &id))
if (!IndexToExistingId(cx, obj, last, &id))
return JS_FALSE;
if (id == JSID_HOLE)
continue; /* don't fill holes in the new array */
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
return JS_FALSE;
if (!IndexToId(cx, last - begin, &id2))
return JS_FALSE;
if (!PropertyExists(cx, obj, id, &propExists))
return JS_FALSE;
if (!propExists)
continue; /* Don't fill holes in the new array */
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
return JS_FALSE;
if (!OBJ_SET_PROPERTY(cx, obj2, id2, &v))
return JS_FALSE;
}
@@ -1239,13 +1245,11 @@ array_splice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
last = length;
/* (uint) end could be 0, so can't use vanilla >= test */
while (last-- > end) {
if (!IndexToId(cx, last, &id))
if (!IndexToExistingId(cx, obj, last, &id))
return JS_FALSE;
if (!IndexToId(cx, last + delta, &id2))
return JS_FALSE;
if (!PropertyExists(cx, obj, id, &propExists))
return JS_FALSE;
if (propExists) {
if (id != JSID_HOLE) {
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
return JS_FALSE;
if (!OBJ_SET_PROPERTY(cx, obj, id2, &v))
@@ -1259,13 +1263,11 @@ array_splice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
} else if (argc < count) {
delta = count - (jsuint)argc;
for (last = end; last < length; last++) {
if (!IndexToId(cx, last, &id))
if (!IndexToExistingId(cx, obj, last, &id))
return JS_FALSE;
if (!IndexToId(cx, last - delta, &id2))
return JS_FALSE;
if (!PropertyExists(cx, obj, id, &propExists))
return JS_FALSE;
if (propExists) {
if (id != JSID_HOLE) {
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
return JS_FALSE;
if (!OBJ_SET_PROPERTY(cx, obj, id2, &v))
@@ -1330,16 +1332,10 @@ array_concat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
if (!ValueIsLength(cx, v, &alength))
return JS_FALSE;
for (slot = 0; slot < alength; slot++) {
JSBool propExists;
if (!IndexToId(cx, slot, &id))
if (!IndexToExistingId(cx, aobj, slot, &id))
return JS_FALSE;
if (!IndexToId(cx, length + slot, &id2))
return JS_FALSE;
if (!PropertyExists(cx, aobj, id, &propExists))
return JS_FALSE;
if (!propExists) {
/*
if (id == JSID_HOLE) {
/*
* Per ECMA 262, 15.4.4.4, step 9, ignore non-existent
* properties.
*/
@@ -1347,6 +1343,8 @@ array_concat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
}
if (!OBJ_GET_PROPERTY(cx, aobj, id, &v))
return JS_FALSE;
if (!IndexToId(cx, length + slot, &id2))
return JS_FALSE;
if (!OBJ_SET_PROPERTY(cx, nobj, id2, &v))
return JS_FALSE;
}
@@ -1373,7 +1371,6 @@ array_slice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble d;
jsid id, id2;
jsval v;
JSBool propExists;
nobj = js_NewArrayObject(cx, 0, NULL);
if (!nobj)
@@ -1416,16 +1413,14 @@ array_slice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
begin = end;
for (slot = begin; slot < end; slot++) {
if (!IndexToId(cx, slot, &id))
if (!IndexToExistingId(cx, obj, slot, &id))
return JS_FALSE;
if (!IndexToId(cx, slot - begin, &id2))
return JS_FALSE;
if (!PropertyExists(cx, obj, id, &propExists))
return JS_FALSE;
if (!propExists)
if (id == JSID_HOLE)
continue;
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
return JS_FALSE;
if (!IndexToId(cx, slot - begin, &id2))
return JS_FALSE;
if (!OBJ_SET_PROPERTY(cx, nobj, id2, &v))
return JS_FALSE;
}
@@ -1435,94 +1430,80 @@ array_slice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
#endif /* JS_HAS_SEQUENCE_OPS */
#if JS_HAS_ARRAY_EXTRAS
static JSBool
array_indexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
array_indexOfHelper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval, JSBool isLast)
{
jsuint length, i;
jsint index;
jsdouble start;
jsuint length, i, stop;
jsint direction;
if (!js_GetLengthProperty(cx, obj, &length))
return JS_FALSE;
start = 0;
if (argc > 1) {
if (length == 0)
goto not_found;
if (argc <= 1) {
i = isLast ? length - 1 : 0;
} else {
jsdouble start;
if (!js_ValueToNumber(cx, argv[1], &start))
return JS_FALSE;
start = js_DoubleToInteger(start);
if (start < 0) {
start += length;
if (start < 0)
start = 0;
} else if (start > length) {
start = length;
i = (start < 0) ? 0 : (jsuint)start;
} else if (start >= length) {
i = length - 1;
} else {
i = (jsuint)start;
}
}
index = -1;
for (i = (jsuint)start; i < length; i++) {
if (isLast) {
stop = 0;
direction = -1;
} else {
stop = length - 1;
direction = 1;
}
for (; ; i += direction) {
jsid id;
jsval v;
if (!IndexToId(cx, i, &id) ||
!OBJ_GET_PROPERTY(cx, obj, id, &v)) {
if (!IndexToExistingId(cx, obj, (jsuint)i, &id))
return JS_FALSE;
}
if (id == JSID_HOLE)
continue;
if (js_StrictlyEqual(v, argv[0])) {
index = i;
break;
}
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
return JS_FALSE;
if (js_StrictlyEqual(v, argv[0]))
return js_NewNumberValue(cx, i, rval);
if (i == stop)
goto not_found;
}
*rval = INT_TO_JSVAL(index);
not_found:
*rval = INT_TO_JSVAL(-1);
return JS_TRUE;
}
static JSBool
array_indexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
return array_indexOfHelper(cx, obj, argc, argv, rval, JS_FALSE);
}
static JSBool
array_lastIndexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
jsuint length;
jsint i, index;
jsdouble start;
if (!js_GetLengthProperty(cx, obj, &length))
return JS_FALSE;
start = length - 1;
if (argc > 1) {
if (!js_ValueToNumber(cx, argv[1], &start))
return JS_FALSE;
start = js_DoubleToInteger(start);
if (start < 0) {
start += length ;
if (start < 0)
start = 0;
} else if (start >= length) {
start = length - 1;
}
}
index = -1;
for (i = (jsint)start; i >= 0; i--) {
jsid id;
jsval v;
if (!IndexToId(cx, (jsuint)i, &id) ||
!OBJ_GET_PROPERTY(cx, obj, id, &v)) {
return JS_FALSE;
}
if (js_StrictlyEqual(v, argv[0])) {
index = i;
break;
}
}
*rval = INT_TO_JSVAL(index);
return JS_TRUE;
return array_indexOfHelper(cx, obj, argc, argv, rval, JS_TRUE);
}
/* Order is important; extras that use a caller's predicate must follow MAP. */
@@ -1544,7 +1525,7 @@ array_extra(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval,
void *mark;
JSStackFrame *fp;
JSBool ok, b;
if (!js_GetLengthProperty(cx, obj, &length))
return JS_FALSE;
@@ -1587,7 +1568,7 @@ array_extra(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval,
if (length == 0)
return JS_TRUE;
if (argc > 1) {
if (!js_ValueToObject(cx, argv[1], &thisp))
return JS_FALSE;
@@ -1612,9 +1593,11 @@ array_extra(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval,
jsid id;
jsval v, rval2;
ok = IndexToId(cx, i, &id);
ok = IndexToExistingId(cx, obj, i, &id);
if (!ok)
break;
if (id == JSID_HOLE)
continue;
ok = OBJ_GET_PROPERTY(cx, obj, id, &v);
if (!ok)
break;