diff options
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 24 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/accessUnregisteredQObjectProperty.qml | 19 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 78 |
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[] = { ®isterResult }; + 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" |