aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-06-10 17:11:52 +0200
committerLars Knoll <lars.knoll@digia.com>2013-06-11 16:00:28 +0200
commit83ede4249bf24b8a88db0ce957de27052b7aba7c (patch)
treefb9111175436970caba292b6feaeb4842e3d6768 /src/qml/qml
parenta5d8e134b201a27cdeec7faf2529d69343406405 (diff)
Implement objectiterator on top of an iterator method in the vtbl
This makes it easier to implement the array-like wrapper classes for qml lists and qt lists. Change-Id: I169025a3e9c76951c0778bcda4bbb1f9a8afc8a0 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp34
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h1
-rw-r--r--src/qml/qml/v4/qv4managed.cpp2
-rw-r--r--src/qml/qml/v4/qv4managed_p.h7
-rw-r--r--src/qml/qml/v4/qv4object.cpp61
-rw-r--r--src/qml/qml/v4/qv4object_p.h2
-rw-r--r--src/qml/qml/v4/qv4objectiterator.cpp118
-rw-r--r--src/qml/qml/v4/qv4objectiterator_p.h3
-rw-r--r--src/qml/qml/v4/qv4regexp.cpp5
-rw-r--r--src/qml/qml/v4/qv4regexp_p.h2
-rw-r--r--src/qml/qml/v4/qv4sequenceobject.cpp46
-rw-r--r--src/qml/qml/v4/qv4string.cpp1
-rw-r--r--src/qml/qml/v4/qv4stringobject.cpp21
-rw-r--r--src/qml/qml/v4/qv4stringobject_p.h1
14 files changed, 163 insertions, 141 deletions
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index ec34905ca3..719119cc05 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -108,6 +108,10 @@ Value QmlListWrapper::get(Managed *m, ExecutionContext *ctx, String *name, bool
return Value::fromUInt32(count);
}
+ uint idx = name->asArrayIndex();
+ if (idx != UINT_MAX)
+ return getIndexed(m, ctx, idx, hasProperty);
+
return Value::undefinedValue();
}
@@ -139,23 +143,21 @@ void QmlListWrapper::destroy(Managed *that)
w->~QmlListWrapper();
}
-#if 0
-// ### does this need porting?
-v8::Handle<v8::Array> QV8ListWrapper::Enumerator(const v8::AccessorInfo &info)
+Property *QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs)
{
- QV8ListResource *resource = v8_resource_cast<QV8ListResource>(info.This());
-
- if (!resource || resource->object.isNull()) return v8::Array::New();
-
- quint32 count = resource->property.count?resource->property.count(&resource->property):0;
-
- v8::Handle<v8::Array> rv = v8::Array::New(count);
-
- for (uint ii = 0; ii < count; ++ii)
- rv->Set(ii, Value::fromDouble(ii));
-
- return rv;
+ *name = 0;
+ *index = UINT_MAX;
+ QmlListWrapper *w = m->as<QmlListWrapper>();
+ quint32 count = w->property.count ? w->property.count(&w->property) : 0;
+ if (it->arrayIndex < count) {
+ if (attrs)
+ *attrs = QV4::Attr_Data;
+ *index = it->arrayIndex;
+ ++it->arrayIndex;
+ it->tmpDynamicProperty.value = QV4::QObjectWrapper::wrap(w->engine(), w->property.at(&w->property, *index));
+ return &it->tmpDynamicProperty;
+ }
+ return QV4::Object::advanceIterator(m, it, name, index, attrs);
}
-#endif
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index 5e8a84b87a..de2a0470d8 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -83,6 +83,7 @@ public:
static Value get(Managed *m, ExecutionContext *ctx, String *name, bool *hasProperty);
static Value getIndexed(Managed *m, ExecutionContext *ctx, uint index, bool *hasProperty);
static void put(Managed *m, ExecutionContext *ctx, String *name, const Value &value);
+ static Property *advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes);
static void destroy(Managed *that);
private:
diff --git a/src/qml/qml/v4/qv4managed.cpp b/src/qml/qml/v4/qv4managed.cpp
index 1adf310858..efba827c21 100644
--- a/src/qml/qml/v4/qv4managed.cpp
+++ b/src/qml/qml/v4/qv4managed.cpp
@@ -63,6 +63,7 @@ const ManagedVTable Managed::static_vtbl =
0,
0,
isEqualTo,
+ 0,
"Managed",
};
@@ -199,7 +200,6 @@ bool Managed::isEqualTo(Managed *, Managed *)
return false;
}
-
Value Managed::get(ExecutionContext *ctx, String *name, bool *hasProperty)
{
return vtbl->get(this, ctx, name, hasProperty);
diff --git a/src/qml/qml/v4/qv4managed_p.h b/src/qml/qml/v4/qv4managed_p.h
index 3b1d4d0c95..ab7d9024a9 100644
--- a/src/qml/qml/v4/qv4managed_p.h
+++ b/src/qml/qml/v4/qv4managed_p.h
@@ -54,9 +54,11 @@ class MemoryManager;
struct String;
struct Object;
struct ObjectPrototype;
+struct ObjectIterator;
struct ExecutionContext;
struct ScriptFunction;
struct InternalClass;
+struct Property;
struct BooleanObject;
struct NumberObject;
@@ -106,6 +108,7 @@ struct ManagedVTable
void (*getLookup)(Managed *m, ExecutionContext *ctx, Lookup *l, Value *result);
void (*setLookup)(Managed *m, ExecutionContext *ctx, Lookup *l, const Value &v);
bool (*isEqualTo)(Managed *m, Managed *other);
+ Property *(*advanceIterator)(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes);
const char *className;
};
@@ -128,6 +131,7 @@ const QV4::ManagedVTable classname::static_vtbl = \
getLookup, \
setLookup, \
isEqualTo, \
+ advanceIterator, \
#classname \
}
@@ -248,6 +252,8 @@ public:
bool isEqualTo(Managed *other)
{ return vtbl->isEqualTo(this, other); }
+ Property *advanceIterator(ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes)
+ { return vtbl->advanceIterator(this, it, name, index, attributes); }
static void destroy(Managed *that) { that->_data = 0; }
static bool hasInstance(Managed *that, ExecutionContext *ctx, const Value &value);
@@ -290,6 +296,7 @@ public:
private:
friend class MemoryManager;
friend struct Identifiers;
+ friend struct ObjectIterator;
};
}
diff --git a/src/qml/qml/v4/qv4object.cpp b/src/qml/qml/v4/qv4object.cpp
index 89b8575c58..e8cf23db45 100644
--- a/src/qml/qml/v4/qv4object.cpp
+++ b/src/qml/qml/v4/qv4object.cpp
@@ -516,6 +516,67 @@ void Object::setLookup(Managed *m, ExecutionContext *ctx, Lookup *l, const Value
o->put(ctx, l->name, value);
}
+Property *Object::advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs)
+{
+ Object *o = static_cast<Object *>(m);
+ *name = 0;
+ *index = UINT_MAX;
+
+ if (!it->arrayIndex)
+ it->arrayNode = o->sparseArrayBegin();
+
+ // sparse arrays
+ if (it->arrayNode) {
+ while (it->arrayNode != o->sparseArrayEnd()) {
+ int k = it->arrayNode->key();
+ uint pidx = it->arrayNode->value;
+ Property *p = o->arrayData + pidx;
+ it->arrayNode = it->arrayNode->nextNode();
+ PropertyAttributes a = o->arrayAttributes ? o->arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
+ if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
+ it->arrayIndex = k + 1;
+ *index = k;
+ if (attrs)
+ *attrs = a;
+ return p;
+ }
+ }
+ it->arrayNode = 0;
+ it->arrayIndex = UINT_MAX;
+ }
+ // dense arrays
+ while (it->arrayIndex < o->arrayDataLen) {
+ uint pidx = o->propertyIndexFromArrayIndex(it->arrayIndex);
+ Property *p = o->arrayData + pidx;
+ PropertyAttributes a = o->arrayAttributes ? o->arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
+ ++it->arrayIndex;
+ if ((!o->arrayAttributes || !o->arrayAttributes[pidx].isGeneric())
+ && (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable())) {
+ *index = it->arrayIndex - 1;
+ if (attrs)
+ *attrs = a;
+ return p;
+ }
+ }
+
+ while (it->memberIndex < o->internalClass->size) {
+ String *n = o->internalClass->nameMap.at(it->memberIndex);
+ assert(n);
+ // ### check that it's not a repeated attribute
+
+ Property *p = o->memberData + it->memberIndex;
+ PropertyAttributes a = o->internalClass->propertyData[it->memberIndex];
+ ++it->memberIndex;
+ if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
+ *name = n;
+ if (attrs)
+ *attrs = a;
+ return p;
+ }
+ }
+
+ return 0;
+}
// Section 8.12.3
Value Object::internalGet(ExecutionContext *ctx, String *name, bool *hasProperty)
diff --git a/src/qml/qml/v4/qv4object_p.h b/src/qml/qml/v4/qv4object_p.h
index 98bb2186dd..d21f33de85 100644
--- a/src/qml/qml/v4/qv4object_p.h
+++ b/src/qml/qml/v4/qv4object_p.h
@@ -345,6 +345,7 @@ public:
using Managed::deleteIndexedProperty;
using Managed::getLookup;
using Managed::setLookup;
+ using Managed::advanceIterator;
protected:
static const ManagedVTable static_vtbl;
static void destroy(Managed *that);
@@ -359,6 +360,7 @@ protected:
static bool deleteIndexedProperty(Managed *m, ExecutionContext *ctx, uint index);
static void getLookup(Managed *m, ExecutionContext *ctx, Lookup *l, Value *result);
static void setLookup(Managed *m, ExecutionContext *ctx, Lookup *l, const Value &v);
+ static Property *advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes);
private:
diff --git a/src/qml/qml/v4/qv4objectiterator.cpp b/src/qml/qml/v4/qv4objectiterator.cpp
index 446b79e0ce..9c48ec7172 100644
--- a/src/qml/qml/v4/qv4objectiterator.cpp
+++ b/src/qml/qml/v4/qv4objectiterator.cpp
@@ -47,24 +47,13 @@ using namespace QV4;
ObjectIterator::ObjectIterator(Object *o, uint flags)
: object(o)
- , internalClass(o ? o->internalClass : 0)
, current(o)
, arrayNode(0)
, arrayIndex(0)
, memberIndex(0)
, flags(flags)
- , wrappedListLength(0)
{
tmpDynamicProperty.value = Value::undefinedValue();
- if (current) {
- if (current->asStringObject())
- this->flags |= CurrentIsString;
-
- if (current->isListType()) {
- wrappedListLength = current->get(o->engine()->id_length).toUInt32();
- assert(current->arrayDataLen == 0);
- }
- }
}
Property *ObjectIterator::next(String **name, uint *index, PropertyAttributes *attrs)
@@ -76,106 +65,17 @@ Property *ObjectIterator::next(String **name, uint *index, PropertyAttributes *a
if (!current)
break;
- if (flags & CurrentIsString) {
- StringObject *s = static_cast<StringObject *>(current);
- uint slen = s->value.stringValue()->toQString().length();
- while (arrayIndex < slen) {
- *index = arrayIndex;
- ++arrayIndex;
- if (attrs)
- *attrs = s->arrayAttributes ? s->arrayAttributes[arrayIndex] : PropertyAttributes(Attr_NotWritable|Attr_NotConfigurable);
- return s->__getOwnProperty__(*index);
- }
- flags &= ~CurrentIsString;
- arrayNode = current->sparseArrayBegin();
- // iterate until we're past the end of the string
- while (arrayNode && arrayNode->key() < slen)
- arrayNode = arrayNode->nextNode();
- }
-
- if (!arrayIndex)
- arrayNode = current->sparseArrayBegin();
-
- // sparse arrays
- if (arrayNode) {
- while (arrayNode != current->sparseArrayEnd()) {
- int k = arrayNode->key();
- uint pidx = arrayNode->value;
- p = current->arrayData + pidx;
- arrayNode = arrayNode->nextNode();
- PropertyAttributes a = current->arrayAttributes ? current->arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
- if (!(flags & EnumerableOnly) || a.isEnumerable()) {
- arrayIndex = k + 1;
- *index = k;
- if (attrs)
- *attrs = a;
- return p;
- }
- }
- arrayNode = 0;
- arrayIndex = UINT_MAX;
- }
- // dense arrays
- while (arrayIndex < current->arrayDataLen) {
- uint pidx = current->propertyIndexFromArrayIndex(arrayIndex);
- p = current->arrayData + pidx;
- PropertyAttributes a = current->arrayAttributes ? current->arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
- ++arrayIndex;
- if ((!current->arrayAttributes || !current->arrayAttributes[pidx].isGeneric())
- && (!(flags & EnumerableOnly) || a.isEnumerable())) {
- *index = arrayIndex - 1;
- if (attrs)
- *attrs = a;
- return p;
- }
- }
-
- while (arrayIndex < wrappedListLength) {
- PropertyAttributes a = current->queryIndexed(arrayIndex);
- ++arrayIndex;
- if (!(flags & EnumerableOnly) || a.isEnumerable()) {
- *index = arrayIndex - 1;
- if (attrs)
- *attrs = a;
- tmpDynamicProperty.value = current->getIndexed(*index);
- return &tmpDynamicProperty;
- }
- }
-
- if (memberIndex == internalClass->size) {
- if (flags & WithProtoChain)
- current = current->prototype;
- else
- current = 0;
- if (current && current->asStringObject())
- flags |= CurrentIsString;
- else
- flags &= ~CurrentIsString;
-
- internalClass = current ? current->internalClass : 0;
-
- arrayIndex = 0;
- memberIndex = 0;
+ p = current->advanceIterator(this, name, index, attrs);
+ if (p)
+ return p;
- if (current && current->isListType()) {
- wrappedListLength = current->get(current->engine()->id_length).toUInt32();
- assert(current->arrayDataLen == 0);
- }
- continue;
- }
- String *n = internalClass->nameMap.at(memberIndex);
- assert(n);
- // ### check that it's not a repeated attribute
+ if (flags & WithProtoChain)
+ current = current->prototype;
+ else
+ current = 0;
- p = current->memberData + memberIndex;
- PropertyAttributes a = internalClass->propertyData[memberIndex];
- ++memberIndex;
- if (!(flags & EnumerableOnly) || a.isEnumerable()) {
- *name = n;
- if (attrs)
- *attrs = a;
- return p;
- }
+ arrayIndex = 0;
+ memberIndex = 0;
}
return 0;
}
diff --git a/src/qml/qml/v4/qv4objectiterator_p.h b/src/qml/qml/v4/qv4objectiterator_p.h
index a481a75d17..6a29dd97fa 100644
--- a/src/qml/qml/v4/qv4objectiterator_p.h
+++ b/src/qml/qml/v4/qv4objectiterator_p.h
@@ -64,11 +64,9 @@ struct Q_QML_EXPORT ObjectIterator
NoFlags = 0,
EnumerableOnly = 0x1,
WithProtoChain = 0x2,
- CurrentIsString = 0x4
};
Object *object;
- InternalClass *internalClass;
Object *current;
SparseArrayNode *arrayNode;
uint arrayIndex;
@@ -76,7 +74,6 @@ struct Q_QML_EXPORT ObjectIterator
uint flags;
Property tmpDynamicProperty;
- uint wrappedListLength;
ObjectIterator(Object *o, uint flags);
Property *next(String **name, uint *index, PropertyAttributes *attributes = 0);
diff --git a/src/qml/qml/v4/qv4regexp.cpp b/src/qml/qml/v4/qv4regexp.cpp
index 1c059d22be..aa207515d7 100644
--- a/src/qml/qml/v4/qv4regexp.cpp
+++ b/src/qml/qml/v4/qv4regexp.cpp
@@ -173,3 +173,8 @@ bool RegExp::deleteIndexedProperty(Managed *m, ExecutionContext *ctx, uint index
{
return false;
}
+
+Property *RegExp::advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes)
+{
+ return 0;
+}
diff --git a/src/qml/qml/v4/qv4regexp_p.h b/src/qml/qml/v4/qv4regexp_p.h
index b850599ad1..4fb075eec1 100644
--- a/src/qml/qml/v4/qv4regexp_p.h
+++ b/src/qml/qml/v4/qv4regexp_p.h
@@ -119,7 +119,7 @@ protected:
static PropertyAttributes queryIndexed(const Managed *m, uint index);
static bool deleteProperty(Managed *m, ExecutionContext *ctx, String *name);
static bool deleteIndexedProperty(Managed *m, ExecutionContext *ctx, uint index);
-
+ static Property *advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes);
private:
friend class RegExpCache;
diff --git a/src/qml/qml/v4/qv4sequenceobject.cpp b/src/qml/qml/v4/qv4sequenceobject.cpp
index 1c386d7e64..be9bbfc364 100644
--- a/src/qml/qml/v4/qv4sequenceobject.cpp
+++ b/src/qml/qml/v4/qv4sequenceobject.cpp
@@ -76,27 +76,27 @@ static void generateWarning(QV4::ExecutionContext *ctx, const QString& descripti
F(QString, QString, QStringList, QString()) \
F(QUrl, Url, QList<QUrl>, QUrl())
-static QV4::Value convertElementToValue(QV4::ExecutionContext *ctx, const QString &element)
+static QV4::Value convertElementToValue(QV4::ExecutionEngine *engine, const QString &element)
{
- return QV4::Value::fromString(ctx, element);
+ return QV4::Value::fromString(engine, element);
}
-static QV4::Value convertElementToValue(QV4::ExecutionContext *ctx, int element)
+static QV4::Value convertElementToValue(QV4::ExecutionEngine *, int element)
{
return QV4::Value::fromInt32(element);
}
-static QV4::Value convertElementToValue(QV4::ExecutionContext *ctx, const QUrl &element)
+static QV4::Value convertElementToValue(QV4::ExecutionEngine *engine, const QUrl &element)
{
- return QV4::Value::fromString(ctx, element.toString());
+ return QV4::Value::fromString(engine, element.toString());
}
-static QV4::Value convertElementToValue(QV4::ExecutionContext *ctx, qreal element)
+static QV4::Value convertElementToValue(QV4::ExecutionEngine *, qreal element)
{
return QV4::Value::fromDouble(element);
}
-static QV4::Value convertElementToValue(QV4::ExecutionContext *ctx, bool element)
+static QV4::Value convertElementToValue(QV4::ExecutionEngine *, bool element)
{
return QV4::Value::fromBoolean(element);
}
@@ -210,7 +210,7 @@ public:
if (signedIdx < m_container.count()) {
if (hasProperty)
*hasProperty = true;
- return convertElementToValue(ctx, m_container.at(signedIdx));
+ return convertElementToValue(ctx->engine, m_container.at(signedIdx));
}
if (hasProperty)
*hasProperty = false;
@@ -268,7 +268,29 @@ public:
loadReference();
}
qint32 signedIdx = static_cast<qint32>(index);
- return (index < m_container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
+ return (signedIdx < m_container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
+ }
+
+ Property *containerAdvanceIterator(ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs)
+ {
+ *name = 0;
+ *index = UINT_MAX;
+
+ if (m_isReference) {
+ if (!m_object)
+ return QQmlSequenceBase::advanceIterator(this, it, name, index, attrs);
+ loadReference();
+ }
+
+ if (it->arrayIndex < m_container.count()) {
+ if (attrs)
+ *attrs = QV4::Attr_Data;
+ *index = it->arrayIndex;
+ ++it->arrayIndex;
+ it->tmpDynamicProperty.value = convertElementToValue(engine(), m_container.at(*index));
+ return &it->tmpDynamicProperty;
+ }
+ return QQmlSequenceBase::advanceIterator(this, it, name, index, attrs);
}
bool containerDeleteIndexedProperty(QV4::ExecutionContext *ctx, uint index)
@@ -335,8 +357,8 @@ public:
{
QV4::Managed *fun = this->m_compareFn.asManaged();
QV4::Value argv[2] = {
- convertElementToValue(this->m_ctx, lhs),
- convertElementToValue(this->m_ctx, rhs)
+ convertElementToValue(this->m_ctx->engine, lhs),
+ convertElementToValue(this->m_ctx->engine, rhs)
};
QV4::Value result = fun->call(this->m_ctx, QV4::Value::fromObject(this->m_ctx->engine->globalObject), argv, 2);
return result.toNumber() < 0;
@@ -458,6 +480,8 @@ private:
{ return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(ctx, index); }
static bool isEqualTo(Managed *that, Managed *other)
{ return static_cast<QQmlSequence<Container> *>(that)->containerIsEqualTo(other); }
+ static Property *advanceIterator(Managed *that, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs)
+ { return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, attrs); }
static void destroy(Managed *that)
{
diff --git a/src/qml/qml/v4/qv4string.cpp b/src/qml/qml/v4/qv4string.cpp
index a310fbe234..52e9949afb 100644
--- a/src/qml/qml/v4/qv4string.cpp
+++ b/src/qml/qml/v4/qv4string.cpp
@@ -92,6 +92,7 @@ const ManagedVTable String::static_vtbl =
0 /*getLookup*/,
0 /*setLookup*/,
Managed::isEqualTo,
+ 0 /*advanceIterator*/,
"String",
};
diff --git a/src/qml/qml/v4/qv4stringobject.cpp b/src/qml/qml/v4/qv4stringobject.cpp
index 0b8598fdb1..912db7d81c 100644
--- a/src/qml/qml/v4/qv4stringobject.cpp
+++ b/src/qml/qml/v4/qv4stringobject.cpp
@@ -99,6 +99,27 @@ Property *StringObject::getIndex(uint index) const
return &tmpProperty;
}
+Property *StringObject::advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs)
+{
+ StringObject *s = static_cast<StringObject *>(m);
+ uint slen = s->value.stringValue()->toQString().length();
+ if (it->arrayIndex < slen) {
+ while (it->arrayIndex < slen) {
+ *index = it->arrayIndex;
+ ++it->arrayIndex;
+ if (attrs)
+ *attrs = s->arrayAttributes ? s->arrayAttributes[it->arrayIndex] : PropertyAttributes(Attr_NotWritable|Attr_NotConfigurable);
+ return s->__getOwnProperty__(*index);
+ }
+ it->arrayNode = s->sparseArrayBegin();
+ // iterate until we're past the end of the string
+ while (it->arrayNode && it->arrayNode->key() < slen)
+ it->arrayNode = it->arrayNode->nextNode();
+ }
+
+ return Object::advanceIterator(m, it, name, index, attrs);
+}
+
void StringObject::markObjects(Managed *that)
{
StringObject *o = static_cast<StringObject *>(that);
diff --git a/src/qml/qml/v4/qv4stringobject_p.h b/src/qml/qml/v4/qv4stringobject_p.h
index 7bd08fae39..cbd7fef839 100644
--- a/src/qml/qml/v4/qv4stringobject_p.h
+++ b/src/qml/qml/v4/qv4stringobject_p.h
@@ -57,6 +57,7 @@ struct StringObject: Object {
Property *getIndex(uint index) const;
protected:
+ static Property *advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs);
static const ManagedVTable static_vtbl;
static void markObjects(Managed *that);
};