Exemple #1
0
static JSBool
array_slice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    JSObject *nobj;
    jsuint length, begin, end, slot;
    jsdouble d;
    jsid id, id2;
    jsval v;

    nobj = js_NewArrayObject(cx, 0, NULL);
    if (!nobj)
        return JS_FALSE;

    if (!js_GetLengthProperty(cx, obj, &length))
        return JS_FALSE;
    begin = 0;
    end = length;

    if (argc > 0) {
        if (!js_ValueToNumber(cx, argv[0], &d))
            return JS_FALSE;
        d = js_DoubleToInteger(d);
        if (d < 0) {
            d += length;
            if (d < 0)
                d = 0;
        } else if (d > length) {
            d = length;
        }
        begin = (jsuint)d;

        if (argc > 1) {
            if (!js_ValueToNumber(cx, argv[1], &d))
                return JS_FALSE;
            d = js_DoubleToInteger(d);
            if (d < 0) {
                d += length;
                if (d < 0)
                    d = 0;
            } else if (d > length) {
                d = length;
            }
            end = (jsuint)d;
        }
    }

    for (slot = begin; slot < end; slot++) {
        if (!IndexToId(cx, slot, &id))
            return JS_FALSE;
        if (!IndexToId(cx, slot - begin, &id2))
            return JS_FALSE;
        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;
}
Exemple #2
0
/*
 * Python-esque sequence operations.
 */
static JSBool
array_concat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    JSObject *nobj, *aobj;
    jsuint length, alength, slot;
    uintN i;
    jsval v;
    jsid id, id2;

    /* Treat obj as the first argument; see ECMA 15.4.4.4. */
    --argv;
    JS_ASSERT(obj == JSVAL_TO_OBJECT(argv[0]));

    /* Create a new Array object and store it in the rval local root. */
    nobj = js_NewArrayObject(cx, 0, NULL);
    if (!nobj)
        return JS_FALSE;
    *rval = OBJECT_TO_JSVAL(nobj);

    /* Loop over [0, argc] to concat args into nobj, expanding all Arrays. */
    length = 0;
    for (i = 0; i <= argc; i++) {
        v = argv[i];
        if (JSVAL_IS_OBJECT(v)) {
            aobj = JSVAL_TO_OBJECT(v);
            if (aobj && OBJ_GET_CLASS(cx, aobj) == &js_ArrayClass) {
                if (!OBJ_GET_PROPERTY(cx, aobj,
                                      (jsid)cx->runtime->atomState.lengthAtom,
                                      &v)) {
                    return JS_FALSE;
                }
                if (!ValueIsLength(cx, v, &alength))
                    return JS_FALSE;
                for (slot = 0; slot < alength; slot++) {
                    if (!IndexToId(cx, slot, &id))
                        return JS_FALSE;
                    if (!IndexToId(cx, length + slot, &id2))
                        return JS_FALSE;
                    if (!OBJ_GET_PROPERTY(cx, aobj, id, &v))
                        return JS_FALSE;
                    if (!OBJ_SET_PROPERTY(cx, nobj, id2, &v))
                        return JS_FALSE;
                }
                length += alength;
                continue;
            }
        }

        if (!IndexToId(cx, length, &id))
            return JS_FALSE;
        if (!OBJ_SET_PROPERTY(cx, nobj, id, &v))
            return JS_FALSE;
        length++;
    }

    return JS_TRUE;
}
Exemple #3
0
static JSBool
OpenArray(JSContext *cx, JSONParser *jp)
{
    // Add an array to an existing array or object
    JSObject *arr = js_NewArrayObject(cx, 0, NULL);
    if (!arr)
        return JS_FALSE;

    return PushObject(cx, jp, arr);
}
Exemple #4
0
static JSBool
NewKeyValuePair(JSContext *cx, jsid key, jsval val, jsval *rval)
{
    jsval vec[2];
    JSTempValueRooter tvr;
    JSObject *aobj;

    vec[0] = ID_TO_VALUE(key);
    vec[1] = val;

    JS_PUSH_TEMP_ROOT(cx, 2, vec, &tvr);
    aobj = js_NewArrayObject(cx, 2, vec);
    *rval = OBJECT_TO_JSVAL(aobj);
    JS_POP_TEMP_ROOT(cx, &tvr);

    return aobj != NULL;
}
Exemple #5
0
JSONParser *
js_BeginJSONParse(JSContext *cx, jsval *rootVal)
{
    if (!cx)
        return NULL;

    JSObject *arr = js_NewArrayObject(cx, 0, NULL);
    if (!arr)
        return NULL;

    JSONParser *jp = (JSONParser*) JS_malloc(cx, sizeof(JSONParser));
    if (!jp)
        return NULL;
    jp->buffer = NULL;

    jp->objectStack = arr;
    if (!js_AddRoot(cx, &jp->objectStack, "JSON parse stack"))
        goto bad;

    jp->hexChar = 0;
    jp->numHex = 0;
    jp->statep = jp->stateStack;
    *jp->statep = JSON_PARSE_STATE_INIT;
    jp->rootVal = rootVal;

    jp->objectKey = (JSStringBuffer*) JS_malloc(cx, sizeof(JSStringBuffer));
    if (!jp->objectKey)
        goto bad;
    js_InitStringBuffer(jp->objectKey);
    
    jp->buffer = (JSStringBuffer*) JS_malloc(cx, sizeof(JSStringBuffer));
    if (!jp->buffer)
        goto bad;
    js_InitStringBuffer(jp->buffer);

    return jp;
bad:
    JS_free(cx, jp->buffer);
    JS_free(cx, jp);
    return NULL;
}
Exemple #6
0
static JSBool
array_splice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsuint length, begin, end, count, delta, last;
    uintN i;
    jsdouble d;
    jsid id, id2;
    jsval v;
    JSObject *obj2;

    /* Nothing to do if no args.  Otherwise lock and load length. */
    if (argc == 0)
        return JS_TRUE;
    if (!js_GetLengthProperty(cx, obj, &length))
        return JS_FALSE;

    /* Convert the first argument into a starting index. */
    if (!js_ValueToNumber(cx, *argv, &d))
        return JS_FALSE;
    d = js_DoubleToInteger(d);
    if (d < 0) {
        d += length;
        if (d < 0)
            d = 0;
    } else if (d > length) {
        d = length;
    }
    begin = (jsuint)d; /* d has been clamped to uint32 */
    argc--;
    argv++;

    /* Convert the second argument from a count into a fencepost index. */
    delta = length - begin;
    if (argc == 0) {
        count = delta;
        end = length;
    } else {
        if (!js_ValueToNumber(cx, *argv, &d))
            return JS_FALSE;
        d = js_DoubleToInteger(d);
        if (d < 0)
            d = 0;
        else if (d > delta)
            d = delta;
        count = (jsuint)d;
        end = begin + count;
        argc--;
        argv++;
    }

    if (count == 1 && cx->version == JSVERSION_1_2) {
        /*
         * JS lacks "list context", whereby in Perl one turns the single
         * scalar that's spliced out into an array just by assigning it to
         * @single instead of $single, or by using it as Perl push's first
         * argument, for instance.
         *
         * JS1.2 emulated Perl too closely and returned a non-Array for
         * the single-splice-out case, requiring callers to test and wrap
         * in [] if necessary.  So JS1.3, default, and other versions all
         * return an array of length 1 for uniformity.
         */
        if (!IndexToId(cx, begin, &id))
            return JS_FALSE;
        if (!OBJ_GET_PROPERTY(cx, obj, id, rval))
            return JS_FALSE;
    } else {
        if (cx->version != JSVERSION_1_2 || count > 0) {
            /*
             * Create a new array value to return.  Our ECMA v2 proposal specs
             * that splice always returns an array value, even when given no
             * arguments.  We think this is best because it eliminates the need
             * for callers to do an extra test to handle the empty splice case.
             */
            obj2 = js_NewArrayObject(cx, 0, NULL);
            if (!obj2)
                return JS_FALSE;
            *rval = OBJECT_TO_JSVAL(obj2);

            /* 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))
                        return JS_FALSE;
                    if (!IndexToId(cx, last - begin, &id2))
                        return JS_FALSE;
                    if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
                        return JS_FALSE;
                    if (!OBJ_SET_PROPERTY(cx, obj2, id2, &v))
                        return JS_FALSE;
                }
            }
        }
    }

    /* Find the direction (up or down) to copy and make way for argv. */
    if (argc > count) {
        delta = (jsuint)argc - count;
        last = length;
        /* (uint) end could be 0, so can't use vanilla >= test */
        while (last-- > end) {
            if (!IndexToId(cx, last, &id))
                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))
                return JS_FALSE;
        }
        length += delta;
    } else if (argc < count) {
        delta = count - (jsuint)argc;
        for (last = end; last < length; last++) {
            if (!IndexToId(cx, last, &id))
                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))
                return JS_FALSE;
        }
        length -= delta;
    }

    /* Copy from argv into the hole to complete the splice. */
    for (i = 0; i < argc; i++) {
        if (!IndexToId(cx, begin + i, &id))
            return JS_FALSE;
        if (!OBJ_SET_PROPERTY(cx, obj, id, &argv[i]))
            return JS_FALSE;
    }

    /* Update length in case we deleted elements from the end. */
    return js_SetLengthProperty(cx, obj, length);
}