Пример #1
0
static inline PropertyIteratorObject*
NewPropertyIteratorObject(JSContext* cx)
{
    RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &PropertyIteratorObject::class_,
                                                             TaggedProto(nullptr)));
    if (!group)
        return nullptr;

    const Class* clasp = &PropertyIteratorObject::class_;
    RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, TaggedProto(nullptr),
                                                      ITERATOR_FINALIZE_KIND));
    if (!shape)
        return nullptr;

    JSObject* obj;
    JS_TRY_VAR_OR_RETURN_NULL(cx, obj, NativeObject::create(cx, ITERATOR_FINALIZE_KIND,
                                                            GetInitialHeap(GenericObject, clasp),
                                                            shape, group));

    PropertyIteratorObject* res = &obj->as<PropertyIteratorObject>();

    // CodeGenerator::visitIteratorStartO assumes the iterator object is not
    // inside the nursery when deciding whether a barrier is necessary.
    MOZ_ASSERT(!js::gc::IsInsideNursery(res));

    MOZ_ASSERT(res->numFixedSlots() == JSObject::ITER_CLASS_NFIXED_SLOTS);
    return res;
}
Пример #2
0
static bool
Reify(JSContext *cx, JSCompartment *origin, Value *vp)
{
    PropertyIteratorObject *iterObj = &vp->toObject().asPropertyIterator();
    NativeIterator *ni = iterObj->getNativeIterator();

    AutoCloseIterator close(cx, iterObj);

    /* Wrap the iteratee. */
    RootedObject obj(cx, ni->obj);
    if (!origin->wrap(cx, obj.address()))
        return false;

    /*
     * Wrap the elements in the iterator's snapshot.
     * N.B. the order of closing/creating iterators is important due to the
     * implicit cx->enumerators state.
     */
    size_t length = ni->numKeys();
    bool isKeyIter = ni->isKeyIter();
    AutoIdVector keys(cx);
    if (length > 0) {
        if (!keys.reserve(length))
            return false;
        for (size_t i = 0; i < length; ++i) {
            jsid id;
            if (!ValueToId(cx, StringValue(ni->begin()[i]), &id))
                return false;
            keys.infallibleAppend(id);
            if (!origin->wrapId(cx, &keys[i]))
                return false;
        }
    }

    close.clear();
    if (!CloseIterator(cx, iterObj))
        return false;

    if (isKeyIter)
        return VectorToKeyIterator(cx, obj, ni->flags, keys, vp);
    return VectorToValueIterator(cx, obj, ni->flags, keys, vp);
}
Пример #3
0
static MOZ_ALWAYS_INLINE PropertyIteratorObject*
LookupInIteratorCache(JSContext* cx, JSObject* obj, uint32_t* numGuards)
{
    MOZ_ASSERT(*numGuards == 0);

    ReceiverGuardVector guards(cx);
    uint32_t key = 0;
    JSObject* pobj = obj;
    do {
        if (!CanCompareIterableObjectToCache(pobj))
            return nullptr;

        ReceiverGuard guard(pobj);
        key = mozilla::AddToHash(key, guard.hash());

        if (MOZ_UNLIKELY(!guards.append(guard))) {
            cx->recoverFromOutOfMemory();
            return nullptr;
        }

        pobj = pobj->staticPrototype();
    } while (pobj);

    MOZ_ASSERT(!guards.empty());
    *numGuards = guards.length();

    IteratorHashPolicy::Lookup lookup(guards.begin(), guards.length(), key);
    auto p = cx->compartment()->iteratorCache.lookup(lookup);
    if (!p)
        return nullptr;

    PropertyIteratorObject* iterobj = *p;
    MOZ_ASSERT(iterobj->compartment() == cx->compartment());

    NativeIterator* ni = iterobj->getNativeIterator();
    if (ni->flags & (JSITER_ACTIVE|JSITER_UNREUSABLE))
        return nullptr;

    return iterobj;
}