Пример #1
0
bool
SetDenseElement(JSContext *cx, HandleObject obj, int32_t index, HandleValue value,
                bool strict)
{
    // This function is called from Ion code for StoreElementHole's OOL path.
    // In this case we know the object is native, has no indexed properties
    // and we can use setDenseElement instead of setDenseElementWithType.

    MOZ_ASSERT(obj->isNative());
    MOZ_ASSERT(!obj->isIndexed());

    JSObject::EnsureDenseResult result = JSObject::ED_SPARSE;
    do {
        if (index < 0)
            break;
        bool isArray = obj->is<ArrayObject>();
        if (isArray && !obj->as<ArrayObject>().lengthIsWritable())
            break;
        uint32_t idx = uint32_t(index);
        result = obj->ensureDenseElements(cx, idx, 1);
        if (result != JSObject::ED_OK)
            break;
        if (isArray) {
            ArrayObject &arr = obj->as<ArrayObject>();
            if (idx >= arr.length())
                arr.setLengthInt32(idx + 1);
        }
        obj->setDenseElement(idx, value);
        return true;
    } while (false);

    if (result == JSObject::ED_FAILED)
        return false;
    MOZ_ASSERT(result == JSObject::ED_SPARSE);

    RootedValue indexVal(cx, Int32Value(index));
    return SetObjectElement(cx, obj, indexVal, value, strict);
}
Пример #2
0
/* ES5 15.12.3 JA. */
static bool
JA(JSContext* cx, HandleObject obj, StringifyContext* scx)
{
    /*
     * This method implements the JA algorithm in ES5 15.12.3, but:
     *
     *   * The algorithm is somewhat reformulated to allow the final string to
     *     be streamed into a single buffer, rather than be created and copied
     *     into place incrementally as the ES5 algorithm specifies it.  This
     *     requires moving portions of the Str call in 8a into this algorithm
     *     (and in JO as well).
     */

    /* Steps 1-2, 11. */
    CycleDetector detect(scx, obj);
    if (!detect.foundCycle(cx))
        return false;

    if (!scx->sb.append('['))
        return false;

    /* Step 6. */
    uint32_t length;
    if (!GetLengthProperty(cx, obj, &length))
        return false;

    /* Steps 7-10. */
    if (length != 0) {
        /* Steps 4, 10b(i). */
        if (!WriteIndent(cx, scx, scx->depth))
            return false;

        /* Steps 7-10. */
        RootedValue outputValue(cx);
        for (uint32_t i = 0; i < length; i++) {
            if (!CheckForInterrupt(cx))
                return false;

            /*
             * Steps 8a-8c.  Again note how the call to the spec's Str method
             * is broken up into getting the property, running it past toJSON
             * and the replacer and maybe unboxing, and interpreting some
             * values as |null| in separate steps.
             */
#ifdef DEBUG
            if (scx->maybeSafely) {
                /*
                 * Trying to do a JS_AlreadyHasOwnElement runs the risk of
                 * hitting OOM on jsid creation.  Let's just assert sanity for
                 * small enough indices.
                 */
                MOZ_ASSERT(obj->is<ArrayObject>());
                MOZ_ASSERT(obj->is<NativeObject>());
                RootedNativeObject nativeObj(cx, &obj->as<NativeObject>());
                if (i <= JSID_INT_MAX) {
                    MOZ_ASSERT(nativeObj->containsDenseElement(i) != nativeObj->isIndexed(),
                               "the array must either be small enough to remain "
                               "fully dense (and otherwise un-indexed), *or* "
                               "all its initially-dense elements were sparsified "
                               "and the object is indexed");
                } else {
                    MOZ_ASSERT(obj->isIndexed());
                }
            }
#endif
            if (!GetElement(cx, obj, obj, i, &outputValue))
                return false;
            if (!PreprocessValue(cx, obj, i, &outputValue, scx))
                return false;
            if (IsFilteredValue(outputValue)) {
                if (!scx->sb.append("null"))
                    return false;
            } else {
                if (!Str(cx, outputValue, scx))
                    return false;
            }

            /* Steps 3, 4, 10b(i). */
            if (i < length - 1) {
                if (!scx->sb.append(','))
                    return false;
                if (!WriteIndent(cx, scx, scx->depth))
                    return false;
            }
        }

        /* Step 10(b)(iii). */
        if (!WriteIndent(cx, scx, scx->depth - 1))
            return false;
    }

    return scx->sb.append(']');
}