QML: Add more safety to QQmlPropertyCache usages
We can almost always use QQmlPropertyCache::ConstPtr. The property cache creator needs mutable property caches for a while, but it can seal them when done. The designer integration does ugly stuff, but that should be limited to a specific environment. And the QQmlOpenMetaObject is rather wrong (again). This needs to be addresses in a later change. Task-number: QTBUG-73271 Change-Id: I1c31fd5936c745029d25b909c30b8d14a30f25d3 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
7b8e6714e1
commit
b5b5782088
|
@ -149,7 +149,7 @@ public:
|
|||
|
||||
// QML specific fields
|
||||
QQmlPropertyCacheVector propertyCaches;
|
||||
QQmlRefPointer<QQmlPropertyCache> rootPropertyCache() const { return propertyCaches.at(/*root object*/0); }
|
||||
QQmlPropertyCache::ConstPtr rootPropertyCache() const { return propertyCaches.at(/*root object*/0); }
|
||||
|
||||
QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ QQmlPropertyCache::ConstPtr ResolvedTypeReference::propertyCache() const
|
|||
/*!
|
||||
Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
|
||||
*/
|
||||
QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache()
|
||||
QQmlPropertyCache::ConstPtr ResolvedTypeReference::createPropertyCache()
|
||||
{
|
||||
if (m_typePropertyCache) {
|
||||
return m_typePropertyCache;
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
}
|
||||
|
||||
QQmlPropertyCache::ConstPtr propertyCache() const;
|
||||
QQmlRefPointer<QQmlPropertyCache> createPropertyCache();
|
||||
QQmlPropertyCache::ConstPtr createPropertyCache();
|
||||
bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums);
|
||||
|
||||
void doDynamicTypeCheck();
|
||||
|
@ -115,7 +115,7 @@ public:
|
|||
}
|
||||
|
||||
QQmlPropertyCache::ConstPtr typePropertyCache() const { return m_typePropertyCache; }
|
||||
void setTypePropertyCache(QQmlRefPointer<QQmlPropertyCache> cache)
|
||||
void setTypePropertyCache(QQmlPropertyCache::ConstPtr cache)
|
||||
{
|
||||
m_typePropertyCache = std::move(cache);
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ public:
|
|||
|
||||
private:
|
||||
QQmlType m_type;
|
||||
QQmlRefPointer<QQmlPropertyCache> m_typePropertyCache;
|
||||
QQmlPropertyCache::ConstPtr m_typePropertyCache;
|
||||
QV4::ExecutableCompilationUnit *m_compilationUnit = nullptr;
|
||||
|
||||
QTypeRevision m_version = QTypeRevision::zero();
|
||||
|
|
|
@ -1294,21 +1294,28 @@ Returns a QQmlPropertyCache for \a obj if one is available.
|
|||
If \a obj is null, being deleted or contains a dynamic meta object,
|
||||
nullptr is returned.
|
||||
*/
|
||||
QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::propertyCache(QObject *obj, QTypeRevision version)
|
||||
QQmlPropertyCache::ConstPtr QQmlMetaType::propertyCache(QObject *obj, QTypeRevision version)
|
||||
{
|
||||
if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
|
||||
return QQmlRefPointer<QQmlPropertyCache>();
|
||||
return QQmlPropertyCache::ConstPtr();
|
||||
return QQmlMetaType::propertyCache(obj->metaObject(), version);
|
||||
}
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::propertyCache(
|
||||
QQmlPropertyCache::ConstPtr QQmlMetaType::propertyCache(
|
||||
const QMetaObject *metaObject, QTypeRevision version)
|
||||
{
|
||||
QQmlMetaTypeDataPtr data; // not const: the cache is created on demand
|
||||
return data->propertyCache(metaObject, version);
|
||||
}
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::propertyCache(
|
||||
QQmlPropertyCache::Ptr QQmlMetaType::createPropertyCache(
|
||||
const QMetaObject *metaObject)
|
||||
{
|
||||
QQmlMetaTypeDataPtr data; // not const: the cache is created
|
||||
return data->createPropertyCache(metaObject);
|
||||
}
|
||||
|
||||
QQmlPropertyCache::ConstPtr QQmlMetaType::propertyCache(
|
||||
const QQmlType &type, QTypeRevision version)
|
||||
{
|
||||
QQmlMetaTypeDataPtr data; // not const: the cache is created on demand
|
||||
|
@ -1352,7 +1359,7 @@ QQmlMetaObject QQmlMetaType::metaObjectForType(QMetaType metaType)
|
|||
*
|
||||
* Look up by type's metaObject and version.
|
||||
*/
|
||||
QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::propertyCacheForType(QMetaType metaType)
|
||||
QQmlPropertyCache::ConstPtr QQmlMetaType::propertyCacheForType(QMetaType metaType)
|
||||
{
|
||||
QQmlMetaTypeDataPtr data;
|
||||
if (auto composite = data->findPropertyCacheInCompositeTypes(metaType))
|
||||
|
@ -1361,7 +1368,7 @@ QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::propertyCacheForType(QMetaType m
|
|||
const QQmlTypePrivate *type = data->idToType.value(metaType.id());
|
||||
return (type && type->typeId == metaType)
|
||||
? data->propertyCache(QQmlType(type).metaObject(), type->version)
|
||||
: QQmlRefPointer<QQmlPropertyCache>();
|
||||
: QQmlPropertyCache::ConstPtr();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1371,7 +1378,7 @@ QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::propertyCacheForType(QMetaType m
|
|||
* TODO: Is this correct? Passing a plain QTypeRevision() rather than QTypeRevision::zero() or
|
||||
* the actual type's version seems strange. The behavior has been in place for a while.
|
||||
*/
|
||||
QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::rawPropertyCacheForType(QMetaType metaType)
|
||||
QQmlPropertyCache::ConstPtr QQmlMetaType::rawPropertyCacheForType(QMetaType metaType)
|
||||
{
|
||||
QQmlMetaTypeDataPtr data;
|
||||
if (auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType))
|
||||
|
@ -1380,7 +1387,7 @@ QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::rawPropertyCacheForType(QMetaTyp
|
|||
const QQmlTypePrivate *type = data->idToType.value(metaType.id());
|
||||
return (type && type->typeId == metaType)
|
||||
? data->propertyCache(type->baseMetaObject, QTypeRevision())
|
||||
: QQmlRefPointer<QQmlPropertyCache>();
|
||||
: QQmlPropertyCache::ConstPtr();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1389,7 +1396,7 @@ QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::rawPropertyCacheForType(QMetaTyp
|
|||
* Look up by QQmlType and version. We only fall back to lookup by metaobject if the type
|
||||
* has no revisiononed attributes here. Unspecified versions are interpreted as "any".
|
||||
*/
|
||||
QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::rawPropertyCacheForType(
|
||||
QQmlPropertyCache::ConstPtr QQmlMetaType::rawPropertyCacheForType(
|
||||
QMetaType metaType, QTypeRevision version)
|
||||
{
|
||||
QQmlMetaTypeDataPtr data;
|
||||
|
@ -1398,7 +1405,7 @@ QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::rawPropertyCacheForType(
|
|||
|
||||
const QQmlTypePrivate *typePriv = data->idToType.value(metaType.id());
|
||||
if (!typePriv || typePriv->typeId != metaType)
|
||||
return QQmlRefPointer<QQmlPropertyCache>();
|
||||
return QQmlPropertyCache::ConstPtr();
|
||||
|
||||
const QQmlType type(typePriv);
|
||||
if (type.containsRevisionedAttributes())
|
||||
|
@ -1407,7 +1414,7 @@ QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::rawPropertyCacheForType(
|
|||
if (const QMetaObject *metaObject = type.metaObject())
|
||||
return data->propertyCache(metaObject, version);
|
||||
|
||||
return QQmlRefPointer<QQmlPropertyCache>();
|
||||
return QQmlPropertyCache::ConstPtr();
|
||||
}
|
||||
|
||||
void QQmlMetaType::unregisterType(int typeIndex)
|
||||
|
@ -1761,7 +1768,7 @@ QQmlValueType *QQmlMetaType::valueType(QMetaType type)
|
|||
return *data->metaTypeToValueType.insert(type.id(), nullptr);
|
||||
}
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::findPropertyCacheInCompositeTypes(QMetaType t)
|
||||
QQmlPropertyCache::ConstPtr QQmlMetaType::findPropertyCacheInCompositeTypes(QMetaType t)
|
||||
{
|
||||
const QQmlMetaTypeDataPtr data;
|
||||
return data->findPropertyCacheInCompositeTypes(t);
|
||||
|
|
|
@ -122,6 +122,8 @@ public:
|
|||
class Q_QML_PRIVATE_EXPORT QQmlMetaType
|
||||
{
|
||||
friend struct CompositeMetaTypeIds;
|
||||
friend class QQmlDesignerMetaObject;
|
||||
|
||||
static CompositeMetaTypeIds registerInternalCompositeType(const QByteArray &className);
|
||||
static void unregisterInternalCompositeType(const CompositeMetaTypeIds &typeIds);
|
||||
|
||||
|
@ -176,19 +178,34 @@ public:
|
|||
|
||||
static QQmlType qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports = false);
|
||||
|
||||
static QQmlRefPointer<QQmlPropertyCache> propertyCache(
|
||||
static QQmlPropertyCache::ConstPtr propertyCache(
|
||||
QObject *object, QTypeRevision version = QTypeRevision());
|
||||
static QQmlRefPointer<QQmlPropertyCache> propertyCache(
|
||||
static QQmlPropertyCache::ConstPtr propertyCache(
|
||||
const QMetaObject *metaObject, QTypeRevision version = QTypeRevision());
|
||||
static QQmlRefPointer<QQmlPropertyCache> propertyCache(
|
||||
static QQmlPropertyCache::ConstPtr propertyCache(
|
||||
const QQmlType &type, QTypeRevision version);
|
||||
|
||||
// This only works for a new metaObject that doesn't have an associated property cache, yet.
|
||||
// Do not call it more than once for the same metaObject!
|
||||
//
|
||||
// ------------------------------------------------------------------------------------
|
||||
// --> The caller has to uphold the immutability guarantees for the returned property cache <--
|
||||
// ------------------------------------------------------------------------------------
|
||||
//
|
||||
// This means: You cannot expose the metaObject, any objects created from it, or the property
|
||||
// cache to _anything_ that allows concurrent access before you are done changing the property
|
||||
// cache!
|
||||
//
|
||||
// In general, don't use this method. It's only for the designer integration. The designer
|
||||
// assumes that there is only one QML engine running in a single thread.
|
||||
static QQmlPropertyCache::Ptr createPropertyCache(const QMetaObject *metaObject);
|
||||
|
||||
// These methods may be called from the loader thread
|
||||
static QQmlMetaObject rawMetaObjectForType(QMetaType metaType);
|
||||
static QQmlMetaObject metaObjectForType(QMetaType metaType);
|
||||
static QQmlRefPointer<QQmlPropertyCache> propertyCacheForType(QMetaType metaType);
|
||||
static QQmlRefPointer<QQmlPropertyCache> rawPropertyCacheForType(QMetaType metaType);
|
||||
static QQmlRefPointer<QQmlPropertyCache> rawPropertyCacheForType(
|
||||
static QQmlPropertyCache::ConstPtr propertyCacheForType(QMetaType metaType);
|
||||
static QQmlPropertyCache::ConstPtr rawPropertyCacheForType(QMetaType metaType);
|
||||
static QQmlPropertyCache::ConstPtr rawPropertyCacheForType(
|
||||
QMetaType metaType, QTypeRevision version);
|
||||
|
||||
static void freeUnusedTypesAndCaches();
|
||||
|
@ -268,7 +285,7 @@ public:
|
|||
static QQmlValueType *valueType(QMetaType metaType);
|
||||
static const QMetaObject *metaObjectForValueType(QMetaType type);
|
||||
|
||||
static QQmlRefPointer<QQmlPropertyCache> findPropertyCacheInCompositeTypes(QMetaType t);
|
||||
static QQmlPropertyCache::ConstPtr findPropertyCacheInCompositeTypes(QMetaType t);
|
||||
static void registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
|
||||
static void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
|
||||
static QV4::ExecutableCompilationUnit *obtainExecutableCompilationUnit(QMetaType type);
|
||||
|
|
|
@ -119,16 +119,16 @@ bool QQmlMetaTypeData::registerModuleTypes(const QString &uri)
|
|||
return false;
|
||||
}
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::propertyCacheForVersion(
|
||||
QQmlPropertyCache::ConstPtr QQmlMetaTypeData::propertyCacheForVersion(
|
||||
int index, QTypeRevision version) const
|
||||
{
|
||||
return (index < typePropertyCaches.length())
|
||||
? typePropertyCaches.at(index).value(version)
|
||||
: QQmlRefPointer<QQmlPropertyCache>();
|
||||
: QQmlPropertyCache::ConstPtr();
|
||||
}
|
||||
|
||||
void QQmlMetaTypeData::setPropertyCacheForVersion(int index, QTypeRevision version,
|
||||
const QQmlRefPointer<QQmlPropertyCache> &cache)
|
||||
const QQmlPropertyCache::ConstPtr &cache)
|
||||
{
|
||||
if (index >= typePropertyCaches.length())
|
||||
typePropertyCaches.resize(index + 1);
|
||||
|
@ -141,13 +141,13 @@ void QQmlMetaTypeData::clearPropertyCachesForVersion(int index)
|
|||
typePropertyCaches[index].clear();
|
||||
}
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::propertyCache(
|
||||
QQmlPropertyCache::ConstPtr QQmlMetaTypeData::propertyCache(
|
||||
const QMetaObject *metaObject, QTypeRevision version)
|
||||
{
|
||||
if (QQmlRefPointer<QQmlPropertyCache> rv = propertyCaches.value(metaObject))
|
||||
if (QQmlPropertyCache::ConstPtr rv = propertyCaches.value(metaObject))
|
||||
return rv;
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> rv;
|
||||
QQmlPropertyCache::ConstPtr rv;
|
||||
if (const QMetaObject *superMeta = metaObject->superClass())
|
||||
rv = propertyCache(superMeta, version)->copyAndAppend(metaObject, version);
|
||||
else
|
||||
|
@ -160,7 +160,22 @@ QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::propertyCache(
|
|||
return rv;
|
||||
}
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::propertyCache(
|
||||
QQmlPropertyCache::Ptr QQmlMetaTypeData::createPropertyCache(const QMetaObject *metaObject)
|
||||
{
|
||||
QQmlPropertyCache::Ptr rv;
|
||||
if (const QMetaObject *superMeta = metaObject->superClass())
|
||||
rv = propertyCache(superMeta, QTypeRevision())->copyAndAppend(metaObject, QTypeRevision());
|
||||
else
|
||||
rv.adopt(new QQmlPropertyCache(metaObject));
|
||||
|
||||
const auto *mop = reinterpret_cast<const QMetaObjectPrivate *>(metaObject->d.data);
|
||||
if (!(mop->flags & DynamicMetaObject))
|
||||
propertyCaches.insert(metaObject, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
QQmlPropertyCache::ConstPtr QQmlMetaTypeData::propertyCache(
|
||||
const QQmlType &type, QTypeRevision version)
|
||||
{
|
||||
Q_ASSERT(type.isValid());
|
||||
|
@ -200,9 +215,8 @@ QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::propertyCache(
|
|||
return pc;
|
||||
}
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> raw = propertyCache(type.metaObject(), combinedVersion);
|
||||
|
||||
bool hasCopied = false;
|
||||
QQmlPropertyCache::ConstPtr raw = propertyCache(type.metaObject(), combinedVersion);
|
||||
QQmlPropertyCache::Ptr copied;
|
||||
|
||||
for (int ii = 0; ii < types.count(); ++ii) {
|
||||
const QQmlType ¤tType = types.at(ii);
|
||||
|
@ -213,14 +227,11 @@ QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::propertyCache(
|
|||
int moIndex = types.count() - 1 - ii;
|
||||
|
||||
if (raw->allowedRevision(moIndex) != rev) {
|
||||
if (!hasCopied) {
|
||||
// TODO: The copy should be mutable, and the original should be const
|
||||
// Considering this, the setAllowedRevision() below does not violate
|
||||
// the immutability of already published property caches.
|
||||
raw = raw->copy();
|
||||
hasCopied = true;
|
||||
if (copied.isNull()) {
|
||||
copied = raw->copy();
|
||||
raw = copied;
|
||||
}
|
||||
raw->setAllowedRevision(moIndex, rev);
|
||||
copied->setAllowedRevision(moIndex, rev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,7 +286,7 @@ QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::propertyCache(
|
|||
return raw;
|
||||
}
|
||||
|
||||
static QQmlRefPointer<QQmlPropertyCache> propertyCacheForPotentialInlineComponentType(
|
||||
static QQmlPropertyCache::ConstPtr propertyCacheForPotentialInlineComponentType(
|
||||
QMetaType t,
|
||||
const QHash<const QtPrivate::QMetaTypeInterface *,
|
||||
QV4::ExecutableCompilationUnit *>::const_iterator &iter) {
|
||||
|
@ -288,12 +299,11 @@ static QQmlRefPointer<QQmlPropertyCache> propertyCacheForPotentialInlineComponen
|
|||
return (*iter)->rootPropertyCache();
|
||||
}
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::findPropertyCacheInCompositeTypes(
|
||||
QMetaType t) const
|
||||
QQmlPropertyCache::ConstPtr QQmlMetaTypeData::findPropertyCacheInCompositeTypes(QMetaType t) const
|
||||
{
|
||||
auto iter = compositeTypes.constFind(t.iface());
|
||||
return (iter == compositeTypes.constEnd())
|
||||
? QQmlRefPointer<QQmlPropertyCache>()
|
||||
? QQmlPropertyCache::ConstPtr()
|
||||
: propertyCacheForPotentialInlineComponentType(t, iter);
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ struct QQmlMetaTypeData
|
|||
// a module via QQmlPrivate::RegisterCompositeType
|
||||
typedef QMultiHash<const QMetaObject *, QQmlTypePrivate *> MetaObjects;
|
||||
MetaObjects metaObjectToType;
|
||||
QVector<QHash<QTypeRevision, QQmlRefPointer<QQmlPropertyCache>>> typePropertyCaches;
|
||||
QVector<QHash<QTypeRevision, QQmlPropertyCache::ConstPtr>> typePropertyCaches;
|
||||
QHash<int, QQmlValueType *> metaTypeToValueType;
|
||||
QHash<const QtPrivate::QMetaTypeInterface *, QV4::ExecutableCompilationUnit *> compositeTypes;
|
||||
|
||||
|
@ -130,16 +130,18 @@ struct QQmlMetaTypeData
|
|||
QList<QQmlPrivate::AutoParentFunction> parentFunctions;
|
||||
QVector<QQmlPrivate::QmlUnitCacheLookupFunction> lookupCachedQmlUnit;
|
||||
|
||||
QHash<const QMetaObject *, QQmlRefPointer<QQmlPropertyCache>> propertyCaches;
|
||||
QHash<const QMetaObject *, QQmlPropertyCache::ConstPtr> propertyCaches;
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> propertyCacheForVersion(int index, QTypeRevision version) const;
|
||||
QQmlPropertyCache::ConstPtr propertyCacheForVersion(int index, QTypeRevision version) const;
|
||||
void setPropertyCacheForVersion(
|
||||
int index, QTypeRevision version, const QQmlRefPointer<QQmlPropertyCache> &cache);
|
||||
int index, QTypeRevision version, const QQmlPropertyCache::ConstPtr &cache);
|
||||
void clearPropertyCachesForVersion(int index);
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> propertyCache(const QMetaObject *metaObject, QTypeRevision version);
|
||||
QQmlRefPointer<QQmlPropertyCache> propertyCache(const QQmlType &type, QTypeRevision version);
|
||||
QQmlRefPointer<QQmlPropertyCache> findPropertyCacheInCompositeTypes(QMetaType t) const;
|
||||
QQmlPropertyCache::ConstPtr propertyCache(const QMetaObject *metaObject, QTypeRevision version);
|
||||
QQmlPropertyCache::ConstPtr propertyCache(const QQmlType &type, QTypeRevision version);
|
||||
QQmlPropertyCache::ConstPtr findPropertyCacheInCompositeTypes(QMetaType t) const;
|
||||
|
||||
QQmlPropertyCache::Ptr createPropertyCache(const QMetaObject *metaObject);
|
||||
|
||||
void setTypeRegistrationFailures(QStringList *failures)
|
||||
{
|
||||
|
|
|
@ -59,7 +59,13 @@ public:
|
|||
QHash<QByteArray, int> names;
|
||||
QMetaObjectBuilder mob;
|
||||
QMetaObject *mem;
|
||||
QQmlRefPointer<QQmlPropertyCache> cache;
|
||||
|
||||
// TODO: We need to make sure that this does not escape into other threads.
|
||||
// In particular, all its non-const uses are probably wrong. You should
|
||||
// only set the open metaobject to "cached" once it's not going to be
|
||||
// modified anymore.
|
||||
QQmlPropertyCache::Ptr cache;
|
||||
|
||||
QSet<QQmlOpenMetaObject*> referers;
|
||||
};
|
||||
|
||||
|
|
|
@ -139,8 +139,7 @@ bool QQmlBindingInstantiationContext::resolveInstantiatingProperty()
|
|||
return instantiatingProperty != nullptr;
|
||||
}
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache>
|
||||
QQmlBindingInstantiationContext::instantiatingPropertyCache() const
|
||||
QQmlPropertyCache::ConstPtr QQmlBindingInstantiationContext::instantiatingPropertyCache() const
|
||||
{
|
||||
if (instantiatingProperty) {
|
||||
if (instantiatingProperty->isQObject()) {
|
||||
|
@ -152,7 +151,7 @@ QQmlBindingInstantiationContext::instantiatingPropertyCache() const
|
|||
return QQmlMetaType::propertyCache(vtmo, instantiatingProperty->typeVersion());
|
||||
}
|
||||
}
|
||||
return QQmlRefPointer<QQmlPropertyCache>();
|
||||
return QQmlPropertyCache::ConstPtr();
|
||||
}
|
||||
|
||||
void QQmlPendingGroupPropertyBindings::resolveMissingPropertyCaches(
|
||||
|
|
|
@ -81,7 +81,7 @@ struct QQmlBindingInstantiationContext {
|
|||
const QQmlPropertyCache::ConstPtr &referencingObjectPropertyCache);
|
||||
|
||||
bool resolveInstantiatingProperty();
|
||||
QQmlRefPointer<QQmlPropertyCache> instantiatingPropertyCache() const;
|
||||
QQmlPropertyCache::ConstPtr instantiatingPropertyCache() const;
|
||||
|
||||
int referencingObjectIndex = -1;
|
||||
const QV4::CompiledData::Binding *instantiatingBinding = nullptr;
|
||||
|
@ -131,6 +131,7 @@ public:
|
|||
QQmlEnginePrivate *enginePrivate,
|
||||
const ObjectContainer *objectContainer, const QQmlImports *imports,
|
||||
const QByteArray &typeClassName);
|
||||
~QQmlPropertyCacheCreator() { propertyCaches->seal(); }
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -164,7 +165,7 @@ public:
|
|||
};
|
||||
protected:
|
||||
QQmlError buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context, VMEMetaObjectIsRequired isVMERequired);
|
||||
QQmlRefPointer<QQmlPropertyCache> propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const;
|
||||
QQmlPropertyCache::ConstPtr propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const;
|
||||
QQmlError createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache);
|
||||
|
||||
QMetaType metaTypeForParameter(const QV4::CompiledData::ParameterType ¶m, QString *customTypeName = nullptr);
|
||||
|
@ -324,7 +325,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecur
|
|||
}
|
||||
}
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> baseTypeCache;
|
||||
QQmlPropertyCache::ConstPtr baseTypeCache;
|
||||
{
|
||||
QQmlError error;
|
||||
baseTypeCache = propertyCacheForObject(obj, context, &error);
|
||||
|
@ -382,7 +383,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecur
|
|||
}
|
||||
|
||||
template <typename ObjectContainer>
|
||||
inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContainer>::propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const
|
||||
inline QQmlPropertyCache::ConstPtr QQmlPropertyCacheCreator<ObjectContainer>::propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const
|
||||
{
|
||||
if (context.instantiatingProperty) {
|
||||
return context.instantiatingPropertyCache();
|
||||
|
@ -456,7 +457,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(
|
|||
obj->signalCount() + obj->propertyCount() + obj->aliasCount(),
|
||||
obj->enumCount());
|
||||
|
||||
propertyCaches->set(objectIndex, cache);
|
||||
propertyCaches->setOwn(objectIndex, cache);
|
||||
propertyCaches->setNeedsVMEMetaObject(objectIndex);
|
||||
|
||||
QByteArray newClassName;
|
||||
|
@ -1030,7 +1031,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesTo
|
|||
if (!object.aliasCount())
|
||||
return QQmlError();
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> propertyCache = propertyCaches->at(objectIndex);
|
||||
QQmlPropertyCache::Ptr propertyCache = propertyCaches->ownAt(objectIndex);
|
||||
Q_ASSERT(propertyCache);
|
||||
|
||||
int effectiveSignalIndex = propertyCache->signalHandlerIndexCacheStart + propertyCache->propertyIndexCache.count();
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
//
|
||||
|
||||
#include <private/qqmlpropertycache_p.h>
|
||||
#include <private/qbipointer_p.h>
|
||||
|
||||
#include <QtCore/qtaggedpointer.h>
|
||||
|
||||
|
@ -60,11 +61,6 @@ QT_BEGIN_NAMESPACE
|
|||
class QQmlPropertyCacheVector
|
||||
{
|
||||
public:
|
||||
enum Tag {
|
||||
NoTag,
|
||||
CacheNeedsVMEMetaObject
|
||||
};
|
||||
|
||||
QQmlPropertyCacheVector() = default;
|
||||
QQmlPropertyCacheVector(QQmlPropertyCacheVector &&) = default;
|
||||
QQmlPropertyCacheVector &operator=(QQmlPropertyCacheVector &&) = default;
|
||||
|
@ -80,32 +76,85 @@ public:
|
|||
void clear()
|
||||
{
|
||||
for (int i = 0; i < data.count(); ++i) {
|
||||
if (QQmlPropertyCache *cache = data.at(i).data())
|
||||
cache->release();
|
||||
const auto &cache = data.at(i);
|
||||
if (cache.isT2()) {
|
||||
if (QQmlPropertyCache *data = cache.asT2())
|
||||
data->release();
|
||||
} else if (const QQmlPropertyCache *data = cache.asT1()) {
|
||||
data->release();
|
||||
}
|
||||
}
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void append(const QQmlRefPointer<QQmlPropertyCache> &cache) {
|
||||
void append(const QQmlPropertyCache::ConstPtr &cache) {
|
||||
cache->addref();
|
||||
data.append(QTaggedPointer<QQmlPropertyCache, Tag>(cache.data()));
|
||||
data.append(QBiPointer<const QQmlPropertyCache, QQmlPropertyCache>(cache.data()));
|
||||
Q_ASSERT(data.last().isT1());
|
||||
}
|
||||
QQmlRefPointer<QQmlPropertyCache> at(int index) const { return data.at(index).data(); }
|
||||
void set(int index, const QQmlRefPointer<QQmlPropertyCache> &replacement) {
|
||||
if (QQmlPropertyCache *oldCache = data.at(index).data()) {
|
||||
if (replacement.data() == oldCache)
|
||||
|
||||
void appendOwn(const QQmlPropertyCache::Ptr &cache) {
|
||||
cache->addref();
|
||||
data.append(QBiPointer<const QQmlPropertyCache, QQmlPropertyCache>(cache.data()));
|
||||
Q_ASSERT(data.last().isT2());
|
||||
}
|
||||
|
||||
QQmlPropertyCache::ConstPtr at(int index) const
|
||||
{
|
||||
const auto entry = data.at(index);
|
||||
if (entry.isT2())
|
||||
return entry.asT2();
|
||||
return entry.asT1();
|
||||
}
|
||||
|
||||
QQmlPropertyCache::Ptr ownAt(int index) const
|
||||
{
|
||||
const auto entry = data.at(index);
|
||||
if (entry.isT2())
|
||||
return entry.asT2();
|
||||
return QQmlPropertyCache::Ptr();
|
||||
}
|
||||
|
||||
void set(int index, const QQmlPropertyCache::ConstPtr &replacement) {
|
||||
if (QQmlPropertyCache::ConstPtr oldCache = at(index)) {
|
||||
// If it is our own, we keep it our own
|
||||
if (replacement.data() == oldCache.data())
|
||||
return;
|
||||
oldCache->release();
|
||||
}
|
||||
data[index] = replacement.data();
|
||||
replacement->addref();
|
||||
Q_ASSERT(data[index].isT1());
|
||||
}
|
||||
|
||||
void setOwn(int index, const QQmlPropertyCache::Ptr &replacement) {
|
||||
if (QQmlPropertyCache::ConstPtr oldCache = at(index)) {
|
||||
if (replacement.data() != oldCache.data()) {
|
||||
oldCache->release();
|
||||
replacement->addref();
|
||||
}
|
||||
} else {
|
||||
replacement->addref();
|
||||
}
|
||||
data[index] = replacement.data();
|
||||
Q_ASSERT(data[index].isT2());
|
||||
}
|
||||
|
||||
void setNeedsVMEMetaObject(int index) { data[index].setFlag(); }
|
||||
bool needsVMEMetaObject(int index) const { return data.at(index).flag(); }
|
||||
|
||||
void seal()
|
||||
{
|
||||
for (auto &entry: data) {
|
||||
if (entry.isT2())
|
||||
entry = static_cast<const QQmlPropertyCache *>(entry.asT2());
|
||||
Q_ASSERT(entry.isT1());
|
||||
}
|
||||
}
|
||||
|
||||
void setNeedsVMEMetaObject(int index) { data[index].setTag(CacheNeedsVMEMetaObject); }
|
||||
bool needsVMEMetaObject(int index) const { return data.at(index).tag() == CacheNeedsVMEMetaObject; }
|
||||
private:
|
||||
Q_DISABLE_COPY(QQmlPropertyCacheVector)
|
||||
QVector<QTaggedPointer<QQmlPropertyCache, Tag>> data;
|
||||
QVector<QBiPointer<const QQmlPropertyCache, QQmlPropertyCache>> data;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
@ -855,7 +855,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(
|
|||
qmlObjects->append(syntheticComponent);
|
||||
const int componentIndex = qmlObjects->count() - 1;
|
||||
// Keep property caches symmetric
|
||||
QQmlRefPointer<QQmlPropertyCache> componentCache
|
||||
QQmlPropertyCache::ConstPtr componentCache
|
||||
= QQmlMetaType::propertyCache(&QQmlComponent::staticMetaObject);
|
||||
propertyCaches.append(componentCache);
|
||||
|
||||
|
|
|
@ -245,11 +245,11 @@ void QQmlTypeData::createTypeAndPropertyCaches(
|
|||
setError(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QQmlPropertyCacheAliasCreator<QV4::ExecutableCompilationUnit> aliasCreator(
|
||||
&m_compiledData->propertyCaches, m_compiledData.data());
|
||||
aliasCreator.appendAliasPropertiesToMetaObjects(engine);
|
||||
QQmlPropertyCacheAliasCreator<QV4::ExecutableCompilationUnit> aliasCreator(
|
||||
&m_compiledData->propertyCaches, m_compiledData.data());
|
||||
aliasCreator.appendAliasPropertiesToMetaObjects(engine);
|
||||
}
|
||||
|
||||
pendingGroupPropertyBindings.resolveMissingPropertyCaches(&m_compiledData->propertyCaches);
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ void QQmlDesignerMetaObject::init(QObject *object)
|
|||
QObjectPrivate *op = QObjectPrivate::get(object);
|
||||
op->metaObject = this;
|
||||
|
||||
m_cache = QQmlMetaType::propertyCache(metaObject);
|
||||
m_cache = QQmlMetaType::createPropertyCache(metaObject);
|
||||
cache = m_cache;
|
||||
|
||||
nodeInstanceMetaObjectList.insert(this, true);
|
||||
|
|
Loading…
Reference in New Issue