Expose push pop in jsarray and add builtins (453734, r=mrbkap).
This commit is contained in:
@@ -2041,41 +2041,31 @@ array_sort(JSContext *cx, uintN argc, jsval *vp)
|
||||
/*
|
||||
* Perl-inspired push, pop, shift, unshift, and splice methods.
|
||||
*/
|
||||
static JSBool
|
||||
array_push_slowly(JSContext *cx, JSObject *obj, uintN argc, jsval *vp)
|
||||
JSBool
|
||||
js_array_push_slowly(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsuint length, newlength;
|
||||
|
||||
if (!js_GetLengthProperty(cx, obj, &length))
|
||||
return JS_FALSE;
|
||||
newlength = length + argc;
|
||||
if (!InitArrayElements(cx, obj, length, newlength, vp + 2))
|
||||
if (!InitArrayElements(cx, obj, length, newlength, argv))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Per ECMA-262, return the new array length. */
|
||||
if (!IndexToValue(cx, newlength, vp))
|
||||
if (!IndexToValue(cx, newlength, rval))
|
||||
return JS_FALSE;
|
||||
return js_SetLengthProperty(cx, obj, newlength);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
array_push(JSContext *cx, uintN argc, jsval *vp)
|
||||
JSBool
|
||||
js_array_push1_dense(JSContext* cx, JSObject* obj, jsval v, jsval *rval)
|
||||
{
|
||||
JSObject *obj;
|
||||
uint32 length;
|
||||
|
||||
/* Insist on one argument and obj of the expected class. */
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
if (argc != 1 || !OBJ_IS_DENSE_ARRAY(cx, obj))
|
||||
return array_push_slowly(cx, obj, argc, vp);
|
||||
|
||||
length = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
uint32 length = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
if (INDEX_TOO_SPARSE(obj, length)) {
|
||||
if (!js_MakeArraySlow(cx, obj))
|
||||
return JS_FALSE;
|
||||
return array_push_slowly(cx, obj, argc, vp);
|
||||
return js_array_push_slowly(cx, obj, 1, &v, rval);
|
||||
}
|
||||
|
||||
if (!EnsureLength(cx, obj, length + 1))
|
||||
@@ -2084,34 +2074,30 @@ array_push(JSContext *cx, uintN argc, jsval *vp)
|
||||
|
||||
JS_ASSERT(obj->dslots[length] == JSVAL_HOLE);
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]++;
|
||||
obj->dslots[length] = vp[2];
|
||||
return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp);
|
||||
obj->dslots[length] = v;
|
||||
return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], rval);
|
||||
}
|
||||
|
||||
JSBool
|
||||
array_pop(JSContext *cx, uintN argc, jsval *vp)
|
||||
js_array_push(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
jsuint index;
|
||||
JSBool hole;
|
||||
|
||||
/* Insist on one argument and obj of the expected class. */
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
|
||||
index = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
if (index == 0) {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
index--;
|
||||
if (!GetArrayElement(cx, obj, index, &hole, vp))
|
||||
return JS_FALSE;
|
||||
if (!hole && !DeleteArrayElement(cx, obj, index))
|
||||
return JS_FALSE;
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = index;
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (argc != 1 || !OBJ_IS_DENSE_ARRAY(cx, obj))
|
||||
return js_array_push_slowly(cx, obj, argc, vp + 2, vp);
|
||||
|
||||
return js_array_push1_dense(cx, obj, vp[2], vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_array_pop_slowly(JSContext *cx, JSObject* obj, jsval *vp)
|
||||
{
|
||||
jsuint index;
|
||||
JSBool hole;
|
||||
|
||||
if (!js_GetLengthProperty(cx, obj, &index))
|
||||
return JS_FALSE;
|
||||
@@ -2129,6 +2115,40 @@ array_pop(JSContext *cx, uintN argc, jsval *vp)
|
||||
return js_SetLengthProperty(cx, obj, index);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_array_pop_dense(JSContext *cx, JSObject* obj, jsval *vp)
|
||||
{
|
||||
jsuint index;
|
||||
JSBool hole;
|
||||
|
||||
index = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
if (index == 0) {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
index--;
|
||||
if (!GetArrayElement(cx, obj, index, &hole, vp))
|
||||
return JS_FALSE;
|
||||
if (!hole && !DeleteArrayElement(cx, obj, index))
|
||||
return JS_FALSE;
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = index;
|
||||
return JS_TRUE;
|
||||
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_array_pop(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
if (OBJ_IS_DENSE_ARRAY(cx, obj))
|
||||
return js_array_pop_dense(cx, obj, vp);
|
||||
return js_array_pop_slowly(cx, obj, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
array_shift(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
@@ -2884,8 +2904,8 @@ static JSFunctionSpec array_methods[] = {
|
||||
JS_FN("join", js_array_join, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("reverse", array_reverse, 0,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("sort", array_sort, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("push", array_push, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("pop", array_pop, 0,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("push", js_array_push, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("pop", js_array_pop, 0,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("shift", array_shift, 0,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("unshift", array_unshift, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("splice", array_splice, 2,JSFUN_GENERIC_NATIVE),
|
||||
|
||||
Reference in New Issue
Block a user