aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp24
-rw-r--r--tests/auto/qml/qqmlecmascript/data/accessUnregisteredQObjectProperty.qml19
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp78
3 files changed, 119 insertions, 2 deletions
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index ff711605be..535fb334c4 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -799,8 +799,30 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
data->propType = QMetaType::type(data->propTypeName);
- if (!data->isFunction())
+ if (!data->isFunction()) {
+ if (data->propType == QMetaType::UnknownType) {
+ const QMetaObject *mo = _metaObject;
+ QQmlPropertyCache *p = _parent;
+ while (p && (!mo || _ownMetaObject)) {
+ mo = p->_metaObject;
+ p = p->_parent;
+ }
+
+ int propOffset = mo->propertyOffset();
+ if (mo && data->coreIndex < propOffset + mo->propertyCount()) {
+ while (data->coreIndex < propOffset) {
+ mo = mo->superClass();
+ propOffset = mo->propertyOffset();
+ }
+
+ int registerResult = -1;
+ void *argv[] = { &registerResult };
+ mo->static_metacall(QMetaObject::RegisterPropertyMetaType, data->coreIndex - propOffset, argv);
+ data->propType = registerResult == -1 ? QMetaType::UnknownType : registerResult;
+ }
+ }
data->flags |= flagsForPropertyType(data->propType, engine);
+ }
data->flags &= ~QQmlPropertyData::NotFullyResolved;
}
diff --git a/tests/auto/qml/qqmlecmascript/data/accessUnregisteredQObjectProperty.qml b/tests/auto/qml/qqmlecmascript/data/accessUnregisteredQObjectProperty.qml
new file mode 100644
index 0000000000..f36bd87036
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/accessUnregisteredQObjectProperty.qml
@@ -0,0 +1,19 @@
+import QtQuick 2.4
+import Test 1.0
+
+Item {
+ property alias container: container
+
+ ObjectContainer {
+ id: container
+ }
+
+ function readProperty() {
+ var v = container.object1;
+ }
+
+ function writeProperty() {
+ container.object2 = null;
+ }
+}
+
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index c05ac7a052..e966052ce8 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -323,6 +323,8 @@ private slots:
void contextObjectOnLazyBindings();
void garbageCollectionDuringCreation();
void qtbug_39520();
+ void readUnregisteredQObjectProperty();
+ void writeUnregisteredQObjectProperty();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -5433,7 +5435,7 @@ void tst_qqmlecmascript::sequenceConversionWrite()
QVERIFY(seq != 0);
// we haven't registered QList<QPoint> as a sequence type, so writing shouldn't work.
- QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QJSValue to an unregistered type");
+ QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QJSValue to QList<QPoint>");
QTest::ignoreMessage(QtWarningMsg, warningOne.toLatin1().constData());
QMetaObject::invokeMethod(object, "performTest");
@@ -7767,6 +7769,80 @@ void tst_qqmlecmascript::qtbug_39520()
QCOMPARE(s.count('\n'), 1 * 1000 * 1000);
}
+class ContainedObject1 : public QObject
+{
+ Q_OBJECT
+};
+
+class ContainedObject2 : public QObject
+{
+ Q_OBJECT
+};
+
+class ObjectContainer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(ContainedObject1 *object1 READ object1 WRITE setObject1)
+ Q_PROPERTY(ContainedObject2 *object2 READ object2 WRITE setObject2)
+public:
+ explicit ObjectContainer(QObject *parent = 0) :
+ QObject(parent),
+ mGetterCalled(false),
+ mSetterCalled(false)
+ {
+ }
+
+ ContainedObject1 *object1()
+ {
+ mGetterCalled = true;
+ return 0;
+ }
+
+ void setObject1(ContainedObject1 *)
+ {
+ mSetterCalled = true;
+ }
+
+ ContainedObject2 *object2()
+ {
+ mGetterCalled = true;
+ return 0;
+ }
+
+ void setObject2(ContainedObject2 *)
+ {
+ mSetterCalled = true;
+ }
+
+public:
+ bool mGetterCalled;
+ bool mSetterCalled;
+};
+
+void tst_qqmlecmascript::readUnregisteredQObjectProperty()
+{
+ qmlRegisterType<ObjectContainer>("Test", 1, 0, "ObjectContainer");
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("accessUnregisteredQObjectProperty.qml"));
+ QObject *root = component.create();
+ QVERIFY(root);
+
+ QMetaObject::invokeMethod(root, "readProperty");
+ QCOMPARE(root->property("container").value<ObjectContainer*>()->mGetterCalled, true);
+}
+
+void tst_qqmlecmascript::writeUnregisteredQObjectProperty()
+{
+ qmlRegisterType<ObjectContainer>("Test", 1, 0, "ObjectContainer");
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("accessUnregisteredQObjectProperty.qml"));
+ QObject *root = component.create();
+ QVERIFY(root);
+
+ QMetaObject::invokeMethod(root, "writeProperty");
+ QCOMPARE(root->property("container").value<ObjectContainer*>()->mSetterCalled, true);
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"