Fix "for (... in ...)" loops for list properties.
authorMichael Brasser <michael.brasser@nokia.com>
Mon, 24 Oct 2011 22:52:01 +0000 (08:52 +1000)
committerQt by Nokia <qt-info@nokia.com>
Wed, 26 Oct 2011 00:11:24 +0000 (02:11 +0200)
Task-number: QTBUG-22276
Change-Id: Ibe5a1180044d8e4a6ca6458e8170dd027885ad10
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
src/declarative/qml/v8/qv8listwrapper.cpp
src/declarative/qml/v8/qv8listwrapper_p.h
tests/auto/declarative/qdeclarativeecmascript/data/forInLoop.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp

index 777ce78..9c1e320 100644 (file)
@@ -69,11 +69,11 @@ void QV8ListWrapper::init(QV8Engine *engine)
 {
     m_engine = engine;
     v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
-    ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
+    ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter, 0, 0, Enumerator);
     ft->InstanceTemplate()->SetIndexedPropertyHandler(IndexedGetter);
     ft->InstanceTemplate()->SetAccessor(v8::String::New("length"), LengthGetter, 0, 
                                         v8::Handle<v8::Value>(), v8::DEFAULT, 
-                                        v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
+                                        v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete | v8::DontEnum));
     ft->InstanceTemplate()->SetHasExternalResource(true);
     m_constructor = qPersistentNew<v8::Function>(ft->GetFunction());
 }
@@ -175,4 +175,20 @@ v8::Handle<v8::Value> QV8ListWrapper::LengthGetter(v8::Local<v8::String> propert
     return v8::Integer::NewFromUnsigned(count);
 }
 
+v8::Handle<v8::Array> QV8ListWrapper::Enumerator(const v8::AccessorInfo &info)
+{
+    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::Local<v8::Array> rv = v8::Array::New(count);
+
+    for (int ii = 0; ii < count; ++ii)
+        rv->Set(ii, v8::Number::New(ii));
+
+    return rv;
+}
+
 QT_END_NAMESPACE
index 8cbc7db..e18d1ee 100644 (file)
@@ -85,6 +85,7 @@ private:
                                                const v8::AccessorInfo &info);
     static v8::Handle<v8::Value> LengthGetter(v8::Local<v8::String> property, 
                                               const v8::AccessorInfo &info);
+    static v8::Handle<v8::Array> Enumerator(const v8::AccessorInfo &info);
 
     QV8Engine *m_engine;
     v8::Persistent<v8::Function> m_constructor;
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/forInLoop.qml b/tests/auto/declarative/qdeclarativeecmascript/data/forInLoop.qml
new file mode 100644 (file)
index 0000000..f14367f
--- /dev/null
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+QtObject {
+    property list<QtObject> objects
+    objects: [QtObject { objectName: "obj1" }, QtObject { objectName: "obj2" }, QtObject { objectName: "obj3" }]
+    property string listResult
+
+    function listProperty() {
+        for (var i in objects)
+            listResult += i + "=" + objects[i].objectName + "|"
+    }
+}
+
index 40072c9..33604dd 100644 (file)
@@ -207,6 +207,7 @@ private slots:
     void include();
     void signalHandlers();
     void doubleEvaluate();
+    void forInLoop();
 
     void callQtInvokables();
     void invokableObjectArg();
@@ -4780,6 +4781,25 @@ void tst_qdeclarativeecmascript::doubleEvaluate()
     delete object;
 }
 
+void tst_qdeclarativeecmascript::forInLoop()
+{
+    QDeclarativeComponent component(&engine, TEST_FILE("forInLoop.qml"));
+    QObject *object = component.create();
+    QVERIFY(object != 0);
+
+    QMetaObject::invokeMethod(object, "listProperty");
+
+    QStringList r = object->property("listResult").toString().split("|", QString::SkipEmptyParts);
+    QCOMPARE(r.size(), 3);
+    QCOMPARE(r[0],QLatin1String("0=obj1"));
+    QCOMPARE(r[1],QLatin1String("1=obj2"));
+    QCOMPARE(r[2],QLatin1String("2=obj3"));
+
+    //TODO: should test for in loop for other objects (such as QObjects) as well.
+
+    delete object;
+}
+
 QTEST_MAIN(tst_qdeclarativeecmascript)
 
 #include "tst_qdeclarativeecmascript.moc"