зеркало из https://github.com/mozilla/pjs.git
bug 299738: Fix jsarray.c to not fill holes in arrays. r=brendan a=bsmedberg
This commit is contained in:
Родитель
6030986d21
Коммит
a23e65e0a2
138
js/src/jsarray.c
138
js/src/jsarray.c
|
@ -218,6 +218,23 @@ IndexToId(JSContext *cx, jsuint length, jsid *idp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
PropertyExists(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp)
|
||||
{
|
||||
JSObject *obj2;
|
||||
JSProperty *prop;
|
||||
|
||||
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
|
||||
return JS_FALSE;
|
||||
|
||||
*foundp = prop != NULL;
|
||||
if (*foundp) {
|
||||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_SetLengthProperty(JSContext *cx, JSObject *obj, jsuint length)
|
||||
{
|
||||
|
@ -602,6 +619,7 @@ array_reverse(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
jsuint len, half, i;
|
||||
jsid id, id2;
|
||||
jsval v, v2;
|
||||
JSBool idexists, id2exists;
|
||||
|
||||
if (!js_GetLengthProperty(cx, obj, &len))
|
||||
return JS_FALSE;
|
||||
|
@ -612,27 +630,31 @@ array_reverse(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
return JS_FALSE;
|
||||
if (!IndexToId(cx, len - i - 1, &id2))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, id2, &v2))
|
||||
return JS_FALSE;
|
||||
|
||||
#if JS_HAS_SPARSE_ARRAYS
|
||||
/* This part isn't done yet. */
|
||||
|
||||
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
|
||||
/* Check for holes to make sure they don't get filled. */
|
||||
if (!PropertyExists(cx, obj, id, &idexists) ||
|
||||
!PropertyExists(cx, obj, id2, &id2exists)) {
|
||||
return JS_FALSE;
|
||||
if (!prop) {
|
||||
OBJ_DELETE_PROPERTY(cx, obj, id2, &v); /* v is junk. */
|
||||
continue;
|
||||
}
|
||||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||
#endif
|
||||
|
||||
if (!OBJ_SET_PROPERTY(cx, obj, id, &v2))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_SET_PROPERTY(cx, obj, id2, &v))
|
||||
return JS_FALSE;
|
||||
if (idexists) {
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, id, &v) ||
|
||||
!OBJ_SET_PROPERTY(cx, obj, id2, &v)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
} else {
|
||||
if (!OBJ_DELETE_PROPERTY(cx, obj, id2, &v))
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (id2exists) {
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, id2, &v2) ||
|
||||
!OBJ_SET_PROPERTY(cx, obj, id, &v2)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
} else {
|
||||
if (!OBJ_DELETE_PROPERTY(cx, obj, id2, &v2))
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
|
@ -835,6 +857,7 @@ 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
|
||||
|
@ -887,19 +910,15 @@ array_sort(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
ca.status = IndexToId(cx, i, &id);
|
||||
if (!ca.status)
|
||||
goto out;
|
||||
{
|
||||
JSObject *obj2;
|
||||
JSProperty *prop;
|
||||
ca.status = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
|
||||
if (!ca.status)
|
||||
goto out;
|
||||
if (!prop) {
|
||||
vec[i] = JSVAL_HOLE;
|
||||
continue;
|
||||
}
|
||||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||
newlen++;
|
||||
|
||||
ca.status = PropertyExists(cx, obj, id, &idexists);
|
||||
if (!ca.status)
|
||||
goto out;
|
||||
if (!idexists) {
|
||||
vec[i] = JSVAL_HOLE;
|
||||
continue;
|
||||
}
|
||||
newlen++;
|
||||
|
||||
ca.status = OBJ_GET_PROPERTY(cx, obj, id, &vec[i]);
|
||||
if (!ca.status)
|
||||
|
@ -1048,10 +1067,7 @@ array_unshift(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
uintN i;
|
||||
jsid id, id2;
|
||||
jsval v;
|
||||
#if JS_HAS_SPARSE_ARRAYS
|
||||
JSObject *obj2;
|
||||
JSProperty *prop;
|
||||
#endif
|
||||
JSBool propExists;
|
||||
|
||||
if (!js_GetLengthProperty(cx, obj, &length))
|
||||
return JS_FALSE;
|
||||
|
@ -1064,15 +1080,12 @@ array_unshift(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
return JS_FALSE;
|
||||
if (!IndexToId(cx, last + argc, &id2))
|
||||
return JS_FALSE;
|
||||
#if JS_HAS_SPARSE_ARRAYS
|
||||
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
|
||||
if (!PropertyExists(cx, obj, id, &propExists))
|
||||
return JS_FALSE;
|
||||
if (!prop) {
|
||||
if (!propExists) {
|
||||
OBJ_DELETE_PROPERTY(cx, obj, id2, &v); /* v is junk. */
|
||||
continue;
|
||||
}
|
||||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||
#endif
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_SET_PROPERTY(cx, obj, id2, &v))
|
||||
|
@ -1105,6 +1118,7 @@ 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)
|
||||
|
@ -1182,11 +1196,18 @@ array_splice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
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;
|
||||
}
|
||||
|
||||
if (!js_SetLengthProperty(cx, obj2, end - begin))
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1201,10 +1222,17 @@ array_splice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return JS_FALSE;
|
||||
if (!IndexToId(cx, last + delta, &id2))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_SET_PROPERTY(cx, obj, id2, &v))
|
||||
if (!PropertyExists(cx, obj, id, &propExists))
|
||||
return JS_FALSE;
|
||||
if (propExists) {
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_SET_PROPERTY(cx, obj, id2, &v))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
if (!OBJ_DELETE_PROPERTY(cx, obj, id2, &v))
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
length += delta;
|
||||
} else if (argc < count) {
|
||||
|
@ -1214,10 +1242,17 @@ array_splice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return JS_FALSE;
|
||||
if (!IndexToId(cx, last - delta, &id2))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_SET_PROPERTY(cx, obj, id2, &v))
|
||||
if (!PropertyExists(cx, obj, id, &propExists))
|
||||
return JS_FALSE;
|
||||
if (propExists) {
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_SET_PROPERTY(cx, obj, id2, &v))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
if (!OBJ_DELETE_PROPERTY(cx, obj, id2, &v))
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
length -= delta;
|
||||
}
|
||||
|
@ -1274,23 +1309,21 @@ 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++) {
|
||||
JSProperty *prop;
|
||||
JSObject *obj2;
|
||||
JSBool propExists;
|
||||
|
||||
if (!IndexToId(cx, slot, &id))
|
||||
return JS_FALSE;
|
||||
if (!IndexToId(cx, length + slot, &id2))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_LOOKUP_PROPERTY(cx, aobj, id, &obj2, &prop))
|
||||
if (!PropertyExists(cx, aobj, id, &propExists))
|
||||
return JS_FALSE;
|
||||
if (!prop) {
|
||||
if (!propExists) {
|
||||
/*
|
||||
* Per ECMA 262, 15.4.4.4, step 9, ignore non-existent
|
||||
* properties.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||
if (!OBJ_GET_PROPERTY(cx, aobj, id, &v))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_SET_PROPERTY(cx, nobj, id2, &v))
|
||||
|
@ -1319,6 +1352,7 @@ 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)
|
||||
|
@ -1362,13 +1396,17 @@ array_slice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return JS_FALSE;
|
||||
if (!IndexToId(cx, slot - begin, &id2))
|
||||
return JS_FALSE;
|
||||
if (!PropertyExists(cx, obj, id, &propExists))
|
||||
return JS_FALSE;
|
||||
if (!propExists)
|
||||
continue;
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_SET_PROPERTY(cx, nobj, id2, &v))
|
||||
return JS_FALSE;
|
||||
}
|
||||
*rval = OBJECT_TO_JSVAL(nobj);
|
||||
return JS_TRUE;
|
||||
return js_SetLengthProperty(cx, nobj, end - begin);
|
||||
}
|
||||
#endif /* JS_HAS_SEQUENCE_OPS */
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче