Modify JS Object to QVariant conversion
authorChris Adams <christopher.adams@nokia.com>
Mon, 26 Sep 2011 04:25:36 +0000 (14:25 +1000)
committerQt by Nokia <qt-info@nokia.com>
Fri, 30 Sep 2011 08:37:05 +0000 (10:37 +0200)
Previously, JS Objects would be converted to a QVariantMap where
each value in the map was a QVariant from toVariant(propertyValue).
Unfortunately, this would result in a crash if the object had a
reference to another object which had a reference to the original
object, due to the circular reference.

This commit changes the conversion code to use
QV8Engine::variantMapFromJS() instead, which avoids cyclic references.

Task-number: QTBUG-21626
Change-Id: I129048c8704ae0d1095a02d0ce4c0fe5850b1b20
Reviewed-on: http://codereview.qt-project.org/5490
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>

src/declarative/qml/v8/qv8engine.cpp
tests/auto/declarative/qdeclarativeecmascript/data/objectConversion.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp

index 2108480..33c87b7 100644 (file)
@@ -460,13 +460,7 @@ QVariant QV8Engine::toBasicVariant(v8::Handle<v8::Value> value)
         int length = properties->Length();
         if (length == 0)
             return QVariant();
-
-        QVariantMap map; 
-        for (int ii = 0; ii < length; ++ii) {
-            v8::Handle<v8::Value> property = properties->Get(ii);
-            map.insert(toString(property), toVariant(object->Get(property), -1));
-        }
-        return map;
+        return variantMapFromJS(object);
     }
 
     return QVariant();
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/objectConversion.qml b/tests/auto/declarative/qdeclarativeecmascript/data/objectConversion.qml
new file mode 100644 (file)
index 0000000..67fc342
--- /dev/null
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+Rectangle {
+    width: 360
+    height: 360
+
+    function circularObject() {
+        var a = {}
+        var b = {}
+
+        a.test = 100;
+        a.c = b;
+        b.c = a;
+        return a;
+    }
+}
index 537965c..9200e0f 100644 (file)
@@ -152,6 +152,7 @@ private slots:
     void propertyChangeSlots();
     void elementAssign();
     void objectPassThroughSignals();
+    void objectConversion();
     void booleanConversion();
     void handleReferenceManagement();
     void stringArg();
@@ -3314,6 +3315,21 @@ void tst_qdeclarativeecmascript::objectPassThroughSignals()
     delete object;
 }
 
+// QTBUG-21626
+void tst_qdeclarativeecmascript::objectConversion()
+{
+    QDeclarativeComponent component(&engine, TEST_FILE("objectConversion.qml"));
+
+    QObject *object = component.create();
+    QVERIFY(object != 0);
+    QVariant retn;
+    QMetaObject::invokeMethod(object, "circularObject", Q_RETURN_ARG(QVariant, retn));
+    QCOMPARE(retn.value<QVariantMap>().value("test"), QVariant(100));
+
+    delete object;
+}
+
+
 // QTBUG-20242
 void tst_qdeclarativeecmascript::booleanConversion()
 {