ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, const Value &index) { uint idx = index.asArrayIndex(); if (idx == UINT_MAX || !object.isObject()) return indexedGetterGeneric(l, object, index); Object *o = object.objectValue(); if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); if (idx < s->len) if (!s->data(idx).isEmpty()) return s->data(idx).asReturnedValue(); } return indexedGetterFallback(l, object, index); }
void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value &index, const Value &v) { uint idx = index.asArrayIndex(); if (idx == UINT_MAX || !object.isObject()) { indexedSetterGeneric(l, object, index, v); return; } Object *o = object.objectValue(); if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); if (idx < s->len) { s->data(idx) = v; return; } } indexedSetterFallback(l, object, index, v); }
void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value &index, const Value &value) { Scope scope(l->engine); ScopedObject o(scope, object.toObject(scope.engine)); if (scope.engine->hasException) return; uint idx = index.asArrayIndex(); if (idx < UINT_MAX) { if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); if (idx < s->len) { s->data(idx) = value; return; } } o->putIndexed(idx, value); return; } ScopedString name(scope, index.toString(scope.engine)); o->put(name, value); }
void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *pd, PropertyAttributes *attrs) { Object *o = static_cast<Object *>(m); name->setM(0); *index = UINT_MAX; if (o->arrayData()) { if (!it->arrayIndex) it->arrayNode = o->sparseBegin(); // sparse arrays if (it->arrayNode) { while (it->arrayNode != o->sparseEnd()) { int k = it->arrayNode->key(); uint pidx = it->arrayNode->value; Heap::SparseArrayData *sa = o->d()->arrayData.cast<Heap::SparseArrayData>(); const Property *p = reinterpret_cast<const Property *>(sa->values.data() + pidx); it->arrayNode = it->arrayNode->nextNode(); PropertyAttributes a = sa->attrs ? sa->attrs[pidx] : Attr_Data; if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) { it->arrayIndex = k + 1; *index = k; *attrs = a; pd->copy(p, a); return; } } it->arrayNode = 0; it->arrayIndex = UINT_MAX; } // dense arrays while (it->arrayIndex < o->d()->arrayData->values.size) { Heap::SimpleArrayData *sa = o->d()->arrayData.cast<Heap::SimpleArrayData>(); const Value &val = sa->data(it->arrayIndex); PropertyAttributes a = o->arrayData()->attributes(it->arrayIndex); ++it->arrayIndex; if (!val.isEmpty() && (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable())) { *index = it->arrayIndex - 1; *attrs = a; pd->value = val; return; } } } while (it->memberIndex < o->internalClass()->size) { Identifier *n = o->internalClass()->nameMap.at(it->memberIndex); if (!n) { // accessor properties have a dummy entry with n == 0 ++it->memberIndex; continue; } int idx = it->memberIndex; PropertyAttributes a = o->internalClass()->propertyData[it->memberIndex]; ++it->memberIndex; if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) { name->setM(o->engine()->identifierTable->stringFromIdentifier(n)); *attrs = a; pd->value = *o->propertyData(idx); if (a.isAccessor()) pd->set = *o->propertyData(idx + SetterOffset); return; } } *attrs = PropertyAttributes(); }