diff options
-rw-r--r-- | src/qml/compiler/qqmlpropertycachecreator.cpp | 2 | ||||
-rw-r--r-- | src/qml/compiler/qqmlpropertycachecreator_p.h | 19 | ||||
-rw-r--r-- | src/qml/compiler/qqmlpropertyvalidator.cpp | 5 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 8 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache_p.h | 41 | ||||
-rw-r--r-- | tests/auto/qml/qqmlengine/data/GroupedPropertiesRevisionComponent1.qml | 10 | ||||
-rw-r--r-- | tests/auto/qml/qqmlengine/data/GroupedPropertiesRevisionComponent2.qml | 10 | ||||
-rw-r--r-- | tests/auto/qml/qqmlengine/data/testGroupedPropertiesRevision.1.qml | 7 | ||||
-rw-r--r-- | tests/auto/qml/qqmlengine/data/testGroupedPropertiesRevision.2.qml | 7 | ||||
-rw-r--r-- | tests/auto/qml/qqmlengine/tst_qqmlengine.cpp | 12 |
13 files changed, 106 insertions, 22 deletions
diff --git a/src/qml/compiler/qqmlpropertycachecreator.cpp b/src/qml/compiler/qqmlpropertycachecreator.cpp index f8d63ec634..4f8b48f52e 100644 --- a/src/qml/compiler/qqmlpropertycachecreator.cpp +++ b/src/qml/compiler/qqmlpropertycachecreator.cpp @@ -64,7 +64,7 @@ QQmlBindingInstantiationContext::QQmlBindingInstantiationContext(int referencing Q_ASSERT(instantiatingBinding->propertyNameIndex != 0); bool notInRevision = false; - instantiatingProperty = QmlIR::PropertyResolver(referencingObjectPropertyCache).property(instantiatingPropertyName, ¬InRevision); + instantiatingProperty = QmlIR::PropertyResolver(referencingObjectPropertyCache).property(instantiatingPropertyName, ¬InRevision, QmlIR::PropertyResolver::IgnoreRevision); } } diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h index 5d6a5c177a..0a525e418c 100644 --- a/src/qml/compiler/qqmlpropertycachecreator_p.h +++ b/src/qml/compiler/qqmlpropertycachecreator_p.h @@ -184,7 +184,7 @@ inline QQmlPropertyCache *QQmlPropertyCacheCreator<ObjectContainer>::propertyCac { if (context.instantiatingProperty) { if (context.instantiatingProperty->isQObject()) { - return enginePrivate->rawPropertyCacheForType(context.instantiatingProperty->propType()); + return enginePrivate->rawPropertyCacheForType(context.instantiatingProperty->propType(), context.instantiatingProperty->typeMinorVersion()); } else if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(context.instantiatingProperty->propType())) { return enginePrivate->cache(vtmo); } @@ -476,6 +476,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj pend = obj->propertiesEnd(); for ( ; p != pend; ++p, ++propertyIdx) { int propertyType = 0; + int propertTypeMinorVersion = 0; QQmlPropertyData::Flags propertyFlags; if (p->type == QV4::CompiledData::Property::Var) { @@ -513,6 +514,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj } else { if (p->type == QV4::CompiledData::Property::Custom) { propertyType = qmltype.typeId(); + propertTypeMinorVersion = qmltype.minorVersion(); } else { propertyType = qmltype.qListTypeId(); } @@ -532,7 +534,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj if (!obj->defaultPropertyIsAlias && propertyIdx == obj->indexOfDefaultPropertyOrAlias) cache->_defaultPropertyName = propertyName; cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++, - propertyType, effectiveSignalIndex); + propertyType, propertTypeMinorVersion, effectiveSignalIndex); effectiveSignalIndex++; } @@ -555,7 +557,7 @@ public: private: void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex); - void propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, QQmlPropertyRawData::Flags *propertyFlags); + void propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyRawData::Flags *propertyFlags); void collectObjectsWithAliasesRecursively(int objectIndex, QVector<int> *objectsWithAliases) const; @@ -667,7 +669,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::collectObjectsWithAl template <typename ObjectContainer> inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias( - const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, + const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion, QQmlPropertyData::Flags *propertyFlags) { const int targetObjectIndex = objectForId(component, alias.targetObjectId); @@ -685,7 +687,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias auto targetAlias = targetObject.aliasesBegin(); for (uint i = 0; i < alias.localAliasIndex; ++i) ++targetAlias; - propertyDataForAlias(component, *targetAlias, type, propertyFlags); + propertyDataForAlias(component, *targetAlias, type, minorVersion, propertyFlags); return; } else if (alias.encodedMetaPropertyIndex == -1) { Q_ASSERT(alias.flags & QV4::CompiledData::Alias::AliasPointsToPointerObject); @@ -697,6 +699,8 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias else *type = typeRef->compilationUnit->metaTypeId; + *minorVersion = typeRef->minorVersion; + propertyFlags->type = QQmlPropertyData::Flags::QObjectDerivedType; } else { int coreIndex = QQmlPropertyIndex::fromEncoded(alias.encodedMetaPropertyIndex).coreIndex(); @@ -756,8 +760,9 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesToPrope Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved); int type = 0; + int minorVersion = 0; QQmlPropertyData::Flags propertyFlags; - propertyDataForAlias(component, *alias, &type, &propertyFlags); + propertyDataForAlias(component, *alias, &type, &minorVersion, &propertyFlags); const QString propertyName = objectContainer->stringAt(alias->nameIndex); @@ -765,7 +770,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesToPrope propertyCache->_defaultPropertyName = propertyName; propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++, - type, effectiveSignalIndex++); + type, minorVersion, effectiveSignalIndex++); } } diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp index 7ea89b378d..9fde6848bb 100644 --- a/src/qml/compiler/qqmlpropertyvalidator.cpp +++ b/src/qml/compiler/qqmlpropertyvalidator.cpp @@ -665,10 +665,11 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData * } else if (property->propType() == qMetaTypeId<QQmlScriptString>()) { return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: script expected")); } else { - // We want to raw metaObject here as the raw metaobject is the + // We want to use the raw metaObject here as the raw metaobject is the // actual property type before we applied any extensions that might // effect the properties on the type, but don't effect assignability - QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType()); + // Using -1 for the minor version ensures that we get the raw metaObject. + QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType(), -1); // Will be true if the assgned type inherits propertyMetaObject bool isAssignable = false; diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 97ca597953..836aa8c416 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -823,7 +823,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI if (!pd || !pd->isQObject()) continue; - QQmlPropertyCache *pc = enginePrivate->rawPropertyCacheForType(pd->propType()); + QQmlPropertyCache *pc = enginePrivate->rawPropertyCacheForType(pd->propType(), pd->typeMinorVersion()); const QMetaObject *mo = pc ? pc->firstCppMetaObject() : 0; while (mo) { if (mo == &QQmlComponent::staticMetaObject) diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index c47d8a0a81..a66bcaa9bd 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -2342,7 +2342,7 @@ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t) } } -QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t) +QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t, int minorVersion) { Locker locker(this); auto iter = m_compositeTypes.constFind(t); @@ -2351,7 +2351,11 @@ QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t) } else { QQmlType type = QQmlMetaType::qmlType(t); locker.unlock(); - return type.isValid() ? cache(type.baseMetaObject()) : 0; + + if (minorVersion >= 0) + return type.isValid() ? cache(type, minorVersion) : 0; + else + return type.isValid() ? cache(type.baseMetaObject()) : 0; } } diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 791660cac7..74e232fd84 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -220,7 +220,7 @@ public: QQmlMetaObject rawMetaObjectForType(int) const; QQmlMetaObject metaObjectForType(int) const; QQmlPropertyCache *propertyCacheForType(int); - QQmlPropertyCache *rawPropertyCacheForType(int); + QQmlPropertyCache *rawPropertyCacheForType(int, int minorVersion = -1); void registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit); void unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit); diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 7178dffa8b..bce81c1504 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -321,13 +321,14 @@ QQmlPropertyCache *QQmlPropertyCache::copyAndReserve(int propertyCount, int meth This is different from QMetaMethod::methodIndex(). */ void QQmlPropertyCache::appendProperty(const QString &name, QQmlPropertyData::Flags flags, - int coreIndex, int propType, int notifyIndex) + int coreIndex, int propType, int minorVersion, int notifyIndex) { QQmlPropertyData data; data.setPropType(propType); data.setCoreIndex(coreIndex); data.setNotifyIndex(notifyIndex); data.setFlags(flags); + data.setTypeMinorVersion(minorVersion); QQmlPropertyData *old = findNamedProperty(name); if (old) diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 6cdb82bd46..e032d4f4c7 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -218,12 +218,38 @@ public: _coreIndex = qint16(idx); } - int revision() const { return _revision; } - void setRevision(int rev) + quint8 revision() const { return _revision; } + void setRevision(quint8 rev) { - Q_ASSERT(rev >= std::numeric_limits<qint16>::min()); - Q_ASSERT(rev <= std::numeric_limits<qint16>::max()); - _revision = qint16(rev); + Q_ASSERT(rev >= std::numeric_limits<quint8>::min()); + Q_ASSERT(rev <= std::numeric_limits<quint8>::max()); + _revision = quint8(rev); + } + + /* If a property is a C++ type, then we store the minor + * version of this type. + * This is required to resolve property or signal revisions + * if this property is used as a grouped property. + * + * Test.qml + * property TextEdit someTextEdit: TextEdit {} + * + * Test { + * someTextEdit.preeditText: "test" //revision 7 + * someTextEdit.onEditingFinished: console.log("test") //revision 6 + * } + * + * To determine if these properties with revisions are available we need + * the minor version of TextEdit as imported in Test.qml. + * + */ + + quint8 typeMinorVersion() const { return _typeMinorVersion; } + void setTypeMinorVersion(quint8 rev) + { + Q_ASSERT(rev >= std::numeric_limits<quint8>::min()); + Q_ASSERT(rev <= std::numeric_limits<quint8>::max()); + _typeMinorVersion = quint8(rev); } QQmlPropertyCacheMethodArguments *arguments() const { return _arguments; } @@ -257,7 +283,8 @@ private: qint16 _notifyIndex; qint16 _overrideIndex; - qint16 _revision; + quint8 _revision; + quint8 _typeMinorVersion; qint16 _metaObjectOffset; QQmlPropertyCacheMethodArguments *_arguments; @@ -390,7 +417,7 @@ public: QQmlPropertyCache *copyAndReserve(int propertyCount, int methodCount, int signalCount, int enumCount); void appendProperty(const QString &, QQmlPropertyRawData::Flags flags, int coreIndex, - int propType, int notifyIndex); + int propType, int revision, int notifyIndex); void appendSignal(const QString &, QQmlPropertyRawData::Flags, int coreIndex, const int *types = 0, const QList<QByteArray> &names = QList<QByteArray>()); void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex, diff --git a/tests/auto/qml/qqmlengine/data/GroupedPropertiesRevisionComponent1.qml b/tests/auto/qml/qqmlengine/data/GroupedPropertiesRevisionComponent1.qml new file mode 100644 index 0000000000..1047926750 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/GroupedPropertiesRevisionComponent1.qml @@ -0,0 +1,10 @@ +import QtQuick 2.8 + +Item { + property alias textEdit: textEdit + + TextEdit { + id: textEdit + + } +} diff --git a/tests/auto/qml/qqmlengine/data/GroupedPropertiesRevisionComponent2.qml b/tests/auto/qml/qqmlengine/data/GroupedPropertiesRevisionComponent2.qml new file mode 100644 index 0000000000..552c6c3791 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/GroupedPropertiesRevisionComponent2.qml @@ -0,0 +1,10 @@ +import QtQuick 2.0 + +Item { + property alias textEdit: textEdit + + TextEdit { + id: textEdit + + } +} diff --git a/tests/auto/qml/qqmlengine/data/testGroupedPropertiesRevision.1.qml b/tests/auto/qml/qqmlengine/data/testGroupedPropertiesRevision.1.qml new file mode 100644 index 0000000000..39bd01fe40 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/testGroupedPropertiesRevision.1.qml @@ -0,0 +1,7 @@ +import QtQuick 2.8 + +Item { + GroupedPropertiesRevisionComponent1 { + textEdit.onEditingFinished: console.log("test") + } +} diff --git a/tests/auto/qml/qqmlengine/data/testGroupedPropertiesRevision.2.qml b/tests/auto/qml/qqmlengine/data/testGroupedPropertiesRevision.2.qml new file mode 100644 index 0000000000..bb9ba79b01 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/testGroupedPropertiesRevision.2.qml @@ -0,0 +1,7 @@ +import QtQuick 2.8 + +Item { + GroupedPropertiesRevisionComponent2 { + textEdit.onEditingFinished: console.log("test") + } +} diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index b332ab2194..d6d7506c48 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -75,6 +75,7 @@ private slots: void urlInterceptor(); void qmlContextProperties(); void testGCCorruption(); + void testGroupedPropertyRevisions(); public slots: QObject *createAQObjectForOwnershipTest () @@ -873,6 +874,17 @@ void tst_qqmlengine::testGCCorruption() QVERIFY2(o, qPrintable(c.errorString())); } +void tst_qqmlengine::testGroupedPropertyRevisions() +{ + QQmlEngine e; + + QQmlComponent c(&e, testFileUrl("testGroupedPropertiesRevision.1.qml")); + QScopedPointer<QObject> object(c.create()); + QVERIFY2(object.data(), qPrintable(c.errorString())); + QQmlComponent c2(&e, testFileUrl("testGroupedPropertiesRevision.2.qml")); + QVERIFY(!c2.errorString().isEmpty()); +} + QTEST_MAIN(tst_qqmlengine) #include "tst_qqmlengine.moc" |