Move propertyCache- and metaObject-related functions into QQmlMetaType

That's where the data resides. This allows us to lock the mutex only
once for all those methods, and it makes a large number of engine
pointers unnecessary.

Finally, we can now find the element type of a QQmlListProperty without
supplying an engine.

Change-Id: If1ae8eafe8762a112d1ca06f9c92ab8a727d1bda
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Ulf Hermann 2021-12-03 01:11:42 +01:00
parent 26a97ace7c
commit 5f76fabd06
24 changed files with 212 additions and 230 deletions

View File

@ -2050,9 +2050,6 @@ bool CallArgument::fromValue(
qvariantPtr = new (&allocData) QVariant();
type = QVariantWrappedType;
const QQmlEnginePrivate *ep = engine->qmlEngine()
? QQmlEnginePrivate::get(engine->qmlEngine())
: nullptr;
QVariant v = engine->toVariant(value, metaType);
if (v.metaType() == metaType) {
@ -2066,7 +2063,7 @@ bool CallArgument::fromValue(
return true;
}
const QQmlMetaObject mo = ep ? ep->rawMetaObjectForType(metaType) : QQmlMetaObject();
const QQmlMetaObject mo = QQmlMetaType::rawMetaObjectForType(metaType);
if (!mo.isNull()) {
QObject *obj = QQmlMetaType::toQObject(v);

View File

@ -869,12 +869,8 @@ static bool initObjectLookup(
const QMetaObject *typeMetaObject = type.metaObject();
const QMetaObject *foundMetaObject = propType.metaObject();
if (!foundMetaObject) {
if (QQmlEngine *engine = aotContext->qmlEngine()) {
foundMetaObject = QQmlEnginePrivate::get(engine)->metaObjectForType(
propType).metaObject();
}
}
if (!foundMetaObject)
foundMetaObject = QQmlMetaType::metaObjectForType(propType).metaObject();
while (foundMetaObject) {
if (foundMetaObject == typeMetaObject)
@ -1318,7 +1314,8 @@ bool AOTCompiledContext::loadTypeLookup(uint index, void *target) const
->compilationUnit()->typeIds.id;
}
*static_cast<const QMetaObject **>(target) = ep->metaObjectForType(metaType).metaObject();
*static_cast<const QMetaObject **>(target)
= QQmlMetaType::metaObjectForType(metaType).metaObject();
return true;
}

View File

@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE
QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QQmlScriptString &script, QObject *obj, QQmlContext *ctxt)
{
QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
QQmlBinding *b = newBinding(property);
if (ctxt && !ctxt->isValid())
return b;
@ -125,7 +125,7 @@ QQmlBinding *QQmlBinding::create(
const QQmlPropertyData *property, const QString &str, QObject *obj,
const QQmlRefPointer<QQmlContextData> &ctxt, const QString &url, quint16 lineNumber)
{
QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
QQmlBinding *b = newBinding(property);
b->setNotifyOnValueChanged(true);
b->QQmlJavaScriptExpression::setContext(ctxt);
@ -147,7 +147,7 @@ QQmlBinding *QQmlBinding::create(QMetaType propertyType, QV4::Function *function
const QQmlRefPointer<QQmlContextData> &ctxt,
QV4::ExecutionContext *scope)
{
QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), propertyType);
QQmlBinding *b = newBinding(propertyType);
b->setNotifyOnValueChanged(true);
b->QQmlJavaScriptExpression::setContext(ctxt);
@ -603,8 +603,7 @@ void QQmlBinding::handleWriteError(const void *result, QMetaType resultType, QMe
if (resultType.flags() & QMetaType::PointerToQObject) {
if (QObject *o = *(QObject *const *)result) {
valueType = o->metaObject()->className();
QQmlMetaObject propertyMetaObject = QQmlPropertyPrivate::rawMetaObjectForType(
QQmlEnginePrivate::get(engine()), metaType);
QQmlMetaObject propertyMetaObject = QQmlPropertyPrivate::rawMetaObjectForType(metaType);
if (!propertyMetaObject.isNull())
propertyType = propertyMetaObject.className();
}
@ -801,8 +800,8 @@ class QObjectPointerBinding: public QQmlNonbindingBinding
QQmlMetaObject targetMetaObject;
public:
QObjectPointerBinding(QQmlEnginePrivate *engine, QMetaType propertyType)
: targetMetaObject(QQmlPropertyPrivate::rawMetaObjectForType(engine, propertyType))
QObjectPointerBinding(QMetaType propertyType)
: targetMetaObject(QQmlPropertyPrivate::rawMetaObjectForType(propertyType))
{}
protected:
@ -831,11 +830,8 @@ protected:
if (resultMo.isNull())
resultMo = resultObject->metaObject();
} else if (type == QMetaType::fromType<QVariant>()) {
QVariant value = *static_cast<QVariant *>(result);
QQmlEngine *qmlEngine = engine();
Q_ASSERT(qmlEngine);
resultMo = QQmlPropertyPrivate::rawMetaObjectForType(
QQmlEnginePrivate::get(qmlEngine), value.metaType());
const QVariant value = *static_cast<QVariant *>(result);
resultMo = QQmlPropertyPrivate::rawMetaObjectForType(value.metaType());
if (resultMo.isNull())
return slowWrite(*pd, vtpd, result, type, isUndefined, flags);
resultObject = *static_cast<QObject *const *>(value.constData());
@ -873,11 +869,8 @@ protected:
resultMo = resultObject->metaObject();
}
} else if (auto variant = result.as<QV4::VariantObject>()) {
QVariant value = variant->d()->data();
QQmlEngine *qmlEngine = engine();
Q_ASSERT(qmlEngine);
resultMo = QQmlPropertyPrivate::rawMetaObjectForType(
QQmlEnginePrivate::get(qmlEngine), value.metaType());
const QVariant value = variant->d()->data();
resultMo = QQmlPropertyPrivate::rawMetaObjectForType(value.metaType());
if (resultMo.isNull())
return slowWrite(*pd, vtpd, result, isUndefined, flags);
resultObject = *static_cast<QObject *const *>(value.constData());
@ -910,15 +903,15 @@ private:
}
};
QQmlBinding *QQmlBinding::newBinding(QQmlEnginePrivate *engine, const QQmlPropertyData *property)
QQmlBinding *QQmlBinding::newBinding(const QQmlPropertyData *property)
{
return newBinding(engine, property ? property->propType() : QMetaType());
return newBinding(property ? property->propType() : QMetaType());
}
QQmlBinding *QQmlBinding::newBinding(QQmlEnginePrivate *engine, QMetaType propertyType)
QQmlBinding *QQmlBinding::newBinding(QMetaType propertyType)
{
if (propertyType.flags() & QMetaType::PointerToQObject)
return new QObjectPointerBinding(engine, propertyType);
return new QObjectPointerBinding(propertyType);
if (propertyType == QMetaType::fromType<QQmlBinding *>())
return new QQmlBindingBinding;

View File

@ -161,8 +161,8 @@ private:
inline bool enabledFlag() const;
inline void setEnabledFlag(bool);
static QQmlBinding *newBinding(QQmlEnginePrivate *engine, const QQmlPropertyData *property);
static QQmlBinding *newBinding(QQmlEnginePrivate *engine, QMetaType propertyType);
static QQmlBinding *newBinding(const QQmlPropertyData *property);
static QQmlBinding *newBinding(QMetaType propertyType);
QQmlSourceLocation *m_sourceLocation = nullptr; // used for Qt.binding() created functions
QV4::PersistentValue m_boundFunction; // used for Qt.binding() that are created from a bound function object

View File

@ -1694,91 +1694,6 @@ QString QQmlEnginePrivate::offlineStorageDatabaseDirectory() const
return q->offlineStoragePath() + QDir::separator() + QLatin1String("Databases") + QDir::separator();
}
/*!
* \internal
*
* Look up by type's baseMetaObject.
*/
QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(QMetaType metaType) const
{
if (auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType))
return QQmlMetaObject(composite);
return QQmlMetaObject(QQmlMetaType::qmlType(metaType).baseMetaObject());
}
/*!
* \internal
*
* Look up by type's metaObject.
*/
QQmlMetaObject QQmlEnginePrivate::metaObjectForType(QMetaType metaType) const
{
if (auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType))
return QQmlMetaObject(composite);
return QQmlMetaObject(QQmlMetaType::qmlType(metaType).metaObject());
}
/*!
* \internal
*
* Look up by type's metaObject and version.
*/
QQmlRefPointer<QQmlPropertyCache> QQmlEnginePrivate::propertyCacheForType(QMetaType metaType)
{
if (auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType))
return composite;
const QQmlType type = QQmlMetaType::qmlType(metaType);
return type.isValid()
? QQmlMetaType::propertyCache(type.metaObject(), type.version())
: QQmlRefPointer<QQmlPropertyCache>();
}
/*!
* \internal
*
* Look up by type's baseMetaObject and unspecified/any version.
* 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> QQmlEnginePrivate::rawPropertyCacheForType(QMetaType metaType)
{
if (auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType))
return composite;
const QQmlType type = QQmlMetaType::qmlType(metaType);
return type.isValid()
? QQmlMetaType::propertyCache(type.baseMetaObject(), QTypeRevision())
: QQmlRefPointer<QQmlPropertyCache>();
}
/*!
* \internal
*
* 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> QQmlEnginePrivate::rawPropertyCacheForType(
QMetaType metaType, QTypeRevision version)
{
if (auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType))
return composite;
const QQmlType type = QQmlMetaType::qmlType(metaType);
if (!type.isValid())
return QQmlRefPointer<QQmlPropertyCache>();
if (type.containsRevisionedAttributes())
return QQmlMetaType::propertyCache(type, version);
if (const QMetaObject *metaObject = type.metaObject())
return QQmlMetaType::propertyCache(metaObject, version);
return QQmlRefPointer<QQmlPropertyCache>();
}
template<>
QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type)
{

View File

@ -208,14 +208,6 @@ public:
// These methods may be called from any thread
QString offlineStorageDatabaseDirectory() const;
// These methods may be called from the loader thread
QQmlMetaObject rawMetaObjectForType(QMetaType metaType) const;
QQmlMetaObject metaObjectForType(QMetaType metaType) const;
QQmlRefPointer<QQmlPropertyCache> propertyCacheForType(QMetaType metaType);
QQmlRefPointer<QQmlPropertyCache> rawPropertyCacheForType(QMetaType metaType);
QQmlRefPointer<QQmlPropertyCache> rawPropertyCacheForType(
QMetaType metaType, QTypeRevision version);
bool isTypeLoaded(const QUrl &url) const;
bool isScriptLoaded(const QUrl &url) const;

View File

@ -59,7 +59,8 @@ QQmlListReferencePrivate::QQmlListReferencePrivate()
{
}
QQmlListReference QQmlListReferencePrivate::init(const QQmlListProperty<QObject> &prop, QMetaType propType, QQmlEngine *engine)
QQmlListReference QQmlListReferencePrivate::init(
const QQmlListProperty<QObject> &prop, QMetaType propType)
{
QQmlListReference rv;
@ -67,7 +68,6 @@ QQmlListReference QQmlListReferencePrivate::init(const QQmlListProperty<QObject>
rv.d = new QQmlListReferencePrivate;
rv.d->object = prop.object;
rv.d->setEngine(engine);
rv.d->property = prop;
rv.d->propertyType = propType;
@ -132,12 +132,8 @@ Constructs a QQmlListReference from a QVariant \a variant containing a QQmlListP
owning the list property is destroyed after the reference is constructed, it will automatically
become invalid. That is, it is safe to hold QQmlListReference instances even after the object is
deleted.
The \a engine is required to look up the element type, which may be a dynamically created QML type.
If it's omitted, only pre-registered types are available. The element type is needed when inserting
values into the list and when the value meta type is explicitly retrieved.
*/
QQmlListReference::QQmlListReference(const QVariant &variant, QQmlEngine *engine)
QQmlListReference::QQmlListReference(const QVariant &variant)
: d(nullptr)
{
const QMetaType t = variant.metaType();
@ -146,7 +142,6 @@ QQmlListReference::QQmlListReference(const QVariant &variant, QQmlEngine *engine
d = new QQmlListReferencePrivate;
d->propertyType = t;
d->setEngine(engine);
d->property.~QQmlListProperty();
t.construct(&d->property, variant.constData());
@ -159,13 +154,9 @@ Constructs a QQmlListReference for \a object's \a property. If \a property is n
property, an invalid QQmlListReference is created. If \a object is destroyed after
the reference is constructed, it will automatically become invalid. That is, it is safe to hold
QQmlListReference instances even after \a object is deleted.
The \a engine is required to look up the element type, which may be a dynamically created QML type.
If it's omitted, only pre-registered types are available. The element type is needed when inserting
values into the list and when the value meta type is explicitly retrieved.
*/
QQmlListReference::QQmlListReference(QObject *object, const char *property, QQmlEngine *engine)
: d(nullptr)
QQmlListReference::QQmlListReference(QObject *object, const char *property)
: d(nullptr)
{
if (!object || !property) return;
@ -178,7 +169,6 @@ QQmlListReference::QQmlListReference(QObject *object, const char *property, QQml
d = new QQmlListReferencePrivate;
d->object = object;
d->propertyType = data->propType();
d->setEngine(engine);
void *args[] = { &d->property, nullptr };
QMetaObject::metacall(object, QMetaObject::ReadProperty, data->coreIndex(), args);

View File

@ -197,8 +197,19 @@ class Q_QML_EXPORT QQmlListReference
{
public:
QQmlListReference();
explicit QQmlListReference(const QVariant &variant, QQmlEngine *engine = nullptr);
QQmlListReference(QObject *, const char *property, QQmlEngine * = nullptr);
#if QT_DEPRECATED_SINCE(6, 3)
QT_DEPRECATED_X("Drop the QQmlEngine* argument")
QQmlListReference(const QVariant &variant, QQmlEngine *)
: QQmlListReference(variant) {}
QT_DEPRECATED_X("Drop the QQmlEngine* argument")
QQmlListReference(QObject *o, const char *property, QQmlEngine *)
: QQmlListReference(o, property) {}
#endif
explicit QQmlListReference(const QVariant &variant);
QQmlListReference(QObject *o, const char *property);
QQmlListReference(const QQmlListReference &);
QQmlListReference &operator=(const QQmlListReference &);
~QQmlListReference();

View File

@ -64,7 +64,7 @@ class QQmlListReferencePrivate
public:
QQmlListReferencePrivate();
static QQmlListReference init(const QQmlListProperty<QObject> &, QMetaType, QQmlEngine *);
static QQmlListReference init(const QQmlListProperty<QObject> &, QMetaType);
QPointer<QObject> object;
QQmlListProperty<QObject> property;
@ -78,26 +78,18 @@ public:
return ref->d;
}
void setEngine(QQmlEngine *engine)
{
m_elementTypeOrEngine = engine;
}
const QMetaObject *elementType()
{
if (m_elementTypeOrEngine.isT2()) {
const QMetaType listType = QQmlMetaType::listType(propertyType);
const QQmlEngine *engine = m_elementTypeOrEngine.asT2();
const QQmlEnginePrivate *p = engine ? QQmlEnginePrivate::get(engine) : nullptr;
m_elementTypeOrEngine = p ? p->rawMetaObjectForType(listType).metaObject()
: QQmlMetaType::qmlType(listType).baseMetaObject();
if (!m_elementType) {
m_elementType = QQmlMetaType::rawMetaObjectForType(
QQmlMetaType::listType(propertyType)).metaObject();
}
return m_elementTypeOrEngine.asT1();
return m_elementType;
}
private:
QBiPointer<const QMetaObject, QQmlEngine> m_elementTypeOrEngine;
const QMetaObject *m_elementType = nullptr;
};

View File

@ -103,8 +103,7 @@ QVariant QmlListWrapper::toVariant() const
QQmlListReference QmlListWrapper::toListReference() const
{
Heap::QmlListWrapper *wrapper = d();
return QQmlListReferencePrivate::init(
wrapper->property(), QMetaType(wrapper->propertyType), engine()->qmlEngine());
return QQmlListReferencePrivate::init(wrapper->property(), QMetaType(wrapper->propertyType));
}

View File

@ -1306,6 +1306,101 @@ QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::propertyCache(
return data->propertyCache(type, version);
}
/*!
* \internal
*
* Look up by type's baseMetaObject.
*/
QQmlMetaObject QQmlMetaType::rawMetaObjectForType(QMetaType metaType)
{
const QQmlMetaTypeDataPtr data;
if (auto composite = data->findPropertyCacheInCompositeTypes(metaType))
return QQmlMetaObject(composite);
const QQmlTypePrivate *type = data->idToType.value(metaType.id());
return (type && type->typeId == metaType) ? type->baseMetaObject : nullptr;
}
/*!
* \internal
*
* Look up by type's metaObject.
*/
QQmlMetaObject QQmlMetaType::metaObjectForType(QMetaType metaType)
{
const QQmlMetaTypeDataPtr data;
if (auto composite = data->findPropertyCacheInCompositeTypes(metaType))
return QQmlMetaObject(composite);
const QQmlTypePrivate *type = data->idToType.value(metaType.id());
return (type && type->typeId == metaType)
? QQmlType(type).metaObject()
: nullptr;
}
/*!
* \internal
*
* Look up by type's metaObject and version.
*/
QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::propertyCacheForType(QMetaType metaType)
{
QQmlMetaTypeDataPtr data;
if (auto composite = data->findPropertyCacheInCompositeTypes(metaType))
return composite;
const QQmlTypePrivate *type = data->idToType.value(metaType.id());
return (type && type->typeId == metaType)
? data->propertyCache(QQmlType(type).metaObject(), type->version)
: QQmlRefPointer<QQmlPropertyCache>();
}
/*!
* \internal
*
* Look up by type's baseMetaObject and unspecified/any version.
* 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)
{
QQmlMetaTypeDataPtr data;
if (auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType))
return composite;
const QQmlTypePrivate *type = data->idToType.value(metaType.id());
return (type && type->typeId == metaType)
? data->propertyCache(type->baseMetaObject, QTypeRevision())
: QQmlRefPointer<QQmlPropertyCache>();
}
/*!
* \internal
*
* 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(
QMetaType metaType, QTypeRevision version)
{
QQmlMetaTypeDataPtr data;
if (auto composite = data->findPropertyCacheInCompositeTypes(metaType))
return composite;
const QQmlTypePrivate *typePriv = data->idToType.value(metaType.id());
if (!typePriv || typePriv->typeId != metaType)
return QQmlRefPointer<QQmlPropertyCache>();
const QQmlType type(typePriv);
if (type.containsRevisionedAttributes())
return data->propertyCache(type, version);
if (const QMetaObject *metaObject = type.metaObject())
return data->propertyCache(metaObject, version);
return QQmlRefPointer<QQmlPropertyCache>();
}
void QQmlMetaType::unregisterType(int typeIndex)
{
QQmlMetaTypeDataPtr data;
@ -1667,26 +1762,10 @@ QQmlValueType *QQmlMetaType::valueType(QMetaType type)
return *data->metaTypeToValueType.insert(type.id(), nullptr);
}
static QQmlRefPointer<QQmlPropertyCache> propertyCacheForPotentialInlineComponentType(
QMetaType t, const QHash<const QtPrivate::QMetaTypeInterface *,
QV4::ExecutableCompilationUnit *>::const_iterator &iter) {
if (t != (*iter)->typeIds.id) {
// this is an inline component, and what we have in the iterator is currently the parent compilation unit
for (auto &&icDatum: (*iter)->inlineComponentData)
if (icDatum.typeIds.id == t)
return (*iter)->propertyCaches.at(icDatum.objectIndex);
}
return (*iter)->rootPropertyCache();
}
QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::findPropertyCacheInCompositeTypes(QMetaType t)
{
const QQmlMetaTypeDataPtr data;
auto iter = data->compositeTypes.constFind(t.iface());
return (iter == data->compositeTypes.constEnd())
? QQmlRefPointer<QQmlPropertyCache>()
: propertyCacheForPotentialInlineComponentType(t, iter);
return data->findPropertyCacheInCompositeTypes(t);
}
void QQmlMetaType::registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit)

View File

@ -62,6 +62,7 @@ class QQmlTypeModule;
class QRecursiveMutex;
class QQmlError;
class QQmlValueType;
class QQmlMetaObject;
namespace QV4 { class ExecutableCompilationUnit; }
@ -180,6 +181,14 @@ public:
static QQmlRefPointer<QQmlPropertyCache> propertyCache(
const QQmlType &type, QTypeRevision version);
// 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(
QMetaType metaType, QTypeRevision version);
static void freeUnusedTypesAndCaches();
static QMetaProperty defaultProperty(const QMetaObject *);

View File

@ -141,7 +141,8 @@ void QQmlMetaTypeData::clearPropertyCachesForVersion(int index)
typePropertyCaches[index].clear();
}
QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, QTypeRevision version)
QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::propertyCache(
const QMetaObject *metaObject, QTypeRevision version)
{
if (QQmlRefPointer<QQmlPropertyCache> rv = propertyCaches.value(metaObject))
return rv;
@ -274,4 +275,26 @@ QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::propertyCache(
return raw;
}
static QQmlRefPointer<QQmlPropertyCache> propertyCacheForPotentialInlineComponentType(
QMetaType t,
const QHash<const QtPrivate::QMetaTypeInterface *,
QV4::ExecutableCompilationUnit *>::const_iterator &iter) {
if (t != (*iter)->typeIds.id) {
// this is an inline component, and what we have in the iterator is currently the parent compilation unit
for (auto &&icDatum: (*iter)->inlineComponentData)
if (icDatum.typeIds.id == t)
return (*iter)->propertyCaches.at(icDatum.objectIndex);
}
return (*iter)->rootPropertyCache();
}
QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::findPropertyCacheInCompositeTypes(
QMetaType t) const
{
auto iter = compositeTypes.constFind(t.iface());
return (iter == compositeTypes.constEnd())
? QQmlRefPointer<QQmlPropertyCache>()
: propertyCacheForPotentialInlineComponentType(t, iter);
}
QT_END_NAMESPACE

View File

@ -139,6 +139,7 @@ struct QQmlMetaTypeData
QQmlRefPointer<QQmlPropertyCache> propertyCache(const QMetaObject *metaObject, QTypeRevision version);
QQmlRefPointer<QQmlPropertyCache> propertyCache(const QQmlType &type, QTypeRevision version);
QQmlRefPointer<QQmlPropertyCache> findPropertyCacheInCompositeTypes(QMetaType t) const;
void setTypeRegistrationFailures(QStringList *failures)
{

View File

@ -1182,7 +1182,7 @@ QVariant QQmlPropertyPrivate::readValueProperty()
QQmlListProperty<QObject> prop;
core.readProperty(object, &prop);
return QVariant::fromValue(QQmlListReferencePrivate::init(prop, core.propType(), engine));
return QVariant::fromValue(QQmlListReferencePrivate::init(prop, core.propType()));
} else if (core.isQObject()) {
@ -1383,11 +1383,11 @@ bool QQmlPropertyPrivate::write(
} else {
varType = variantMetaType;
}
QQmlMetaObject valMo = rawMetaObjectForType(enginePriv, varType);
QQmlMetaObject valMo = rawMetaObjectForType(varType);
if (valMo.isNull() || !varType.flags().testFlag(QMetaType::PointerToQObject))
return false;
QObject *o = *static_cast<QObject *const *>(val.constData());
QQmlMetaObject propMo = rawMetaObjectForType(enginePriv, propertyMetaType);
QQmlMetaObject propMo = rawMetaObjectForType(propertyMetaType);
if (o)
valMo = o;
@ -1458,14 +1458,7 @@ bool QQmlPropertyPrivate::write(
} else if (property.isQList()) {
QQmlMetaObject listType;
if (enginePriv) {
listType = enginePriv->rawMetaObjectForType(QQmlMetaType::listType(propertyMetaType));
} else {
const QQmlType type = QQmlMetaType::qmlType(QQmlMetaType::listType(propertyMetaType));
if (!type.isValid())
return false;
listType = type.baseMetaObject();
}
listType = QQmlMetaType::rawMetaObjectForType(QQmlMetaType::listType(propertyMetaType));
if (listType.isNull())
return false;
@ -1592,19 +1585,13 @@ bool QQmlPropertyPrivate::write(
return true;
}
QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(
QQmlEnginePrivate *engine, QMetaType metaType)
QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QMetaType metaType)
{
if (metaType.flags() & QMetaType::PointerToQObject) {
if (const QMetaObject *metaObject = metaType.metaObject())
return metaObject;
}
if (engine)
return engine->rawMetaObjectForType(metaType);
const QQmlType type = QQmlMetaType::qmlType(metaType);
if (type.isValid())
return QQmlMetaObject(type.baseMetaObject());
return QQmlMetaObject();
return QQmlMetaType::rawMetaObjectForType(metaType);
}
/*!

View File

@ -113,7 +113,7 @@ public:
QVariant readValueProperty();
bool writeValueProperty(const QVariant &, QQmlPropertyData::WriteFlags);
static QQmlMetaObject rawMetaObjectForType(QQmlEnginePrivate *, QMetaType metaType);
static QQmlMetaObject rawMetaObjectForType(QMetaType metaType);
static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object,
const QVariant &value, int flags);
static bool writeValueProperty(QObject *,

View File

@ -127,14 +127,15 @@ bool QQmlBindingInstantiationContext::resolveInstantiatingProperty()
return instantiatingProperty != nullptr;
}
QQmlRefPointer<QQmlPropertyCache> QQmlBindingInstantiationContext::instantiatingPropertyCache(QQmlEnginePrivate *enginePrivate) const
QQmlRefPointer<QQmlPropertyCache>
QQmlBindingInstantiationContext::instantiatingPropertyCache() const
{
if (instantiatingProperty) {
if (instantiatingProperty->isQObject()) {
// rawPropertyCacheForType assumes a given unspecified version means "any version".
// There is another overload that takes no version, which we shall not use here.
return enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType(),
instantiatingProperty->typeVersion());
return QQmlMetaType::rawPropertyCacheForType(instantiatingProperty->propType(),
instantiatingProperty->typeVersion());
} else if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForValueType(instantiatingProperty->propType())) {
return QQmlMetaType::propertyCache(vtmo, instantiatingProperty->typeVersion());
}
@ -142,7 +143,8 @@ QQmlRefPointer<QQmlPropertyCache> QQmlBindingInstantiationContext::instantiating
return QQmlRefPointer<QQmlPropertyCache>();
}
void QQmlPendingGroupPropertyBindings::resolveMissingPropertyCaches(QQmlEnginePrivate *enginePrivate, QQmlPropertyCacheVector *propertyCaches) const
void QQmlPendingGroupPropertyBindings::resolveMissingPropertyCaches(
QQmlPropertyCacheVector *propertyCaches) const
{
for (QQmlBindingInstantiationContext pendingBinding: *this) {
const int groupPropertyObjectIndex = pendingBinding.instantiatingBinding->value.objectIndex;
@ -153,7 +155,7 @@ void QQmlPendingGroupPropertyBindings::resolveMissingPropertyCaches(QQmlEnginePr
if (pendingBinding.referencingObjectPropertyCache) {
if (!pendingBinding.resolveInstantiatingProperty())
continue;
auto cache = pendingBinding.instantiatingPropertyCache(enginePrivate);
auto cache = pendingBinding.instantiatingPropertyCache();
propertyCaches->set(groupPropertyObjectIndex, cache);
} else {
auto cache = propertyCaches->at(pendingBinding.referencingObjectIndex);

View File

@ -81,7 +81,7 @@ struct QQmlBindingInstantiationContext {
const QQmlRefPointer<QQmlPropertyCache> &referencingObjectPropertyCache);
bool resolveInstantiatingProperty();
QQmlRefPointer<QQmlPropertyCache> instantiatingPropertyCache(QQmlEnginePrivate *enginePrivate) const;
QQmlRefPointer<QQmlPropertyCache> instantiatingPropertyCache() const;
int referencingObjectIndex = -1;
const QV4::CompiledData::Binding *instantiatingBinding = nullptr;
@ -92,7 +92,7 @@ struct QQmlBindingInstantiationContext {
struct QQmlPendingGroupPropertyBindings : public QVector<QQmlBindingInstantiationContext>
{
void resolveMissingPropertyCaches(QQmlEnginePrivate *enginePrivate, QQmlPropertyCacheVector *propertyCaches) const;
void resolveMissingPropertyCaches(QQmlPropertyCacheVector *propertyCaches) const;
};
struct QQmlPropertyCacheCreatorBase
@ -383,7 +383,7 @@ template <typename ObjectContainer>
inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContainer>::propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const
{
if (context.instantiatingProperty) {
return context.instantiatingPropertyCache(enginePrivate);
return context.instantiatingPropertyCache();
} else if (obj->inheritedTypeNameIndex != 0) {
auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
@ -967,7 +967,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
if (!QQmlMetaType::isValueType(targetProperty->propType()) && valueTypeIndex != -1) {
// deep alias property
*type = targetProperty->propType();
QQmlRefPointer<QQmlPropertyCache> typeCache = enginePriv->propertyCacheForType(*type);
QQmlRefPointer<QQmlPropertyCache> typeCache = QQmlMetaType::propertyCacheForType(*type);
Q_ASSERT(typeCache);
QQmlPropertyData *typeProperty = typeCache->property(valueTypeIndex);

View File

@ -329,7 +329,7 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject(
);
}
if (!enginePrivate->propertyCacheForType(type)) {
if (!QQmlMetaType::propertyCacheForType(type)) {
return recordError(binding->location,
tr("Invalid grouped property access: Property \"%1\" with type \"%2\", which is not a value type")
.arg(name)
@ -661,7 +661,7 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding(
*/
bool QQmlPropertyValidator::canCoerce(QMetaType to, QQmlRefPointer<QQmlPropertyCache> fromMo) const
{
QQmlRefPointer<QQmlPropertyCache> toMo = enginePrivate->rawPropertyCacheForType(to);
QQmlRefPointer<QQmlPropertyCache> toMo = QQmlMetaType::rawPropertyCacheForType(to);
if (toMo.isNull()) {
// if we have an inline component from the current file,
@ -772,7 +772,7 @@ QQmlError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *propert
// effect the properties on the type, but don't effect assignability
// Not passing a version ensures that we get the raw metaObject.
QQmlRefPointer<QQmlPropertyCache> propertyMetaObject
= enginePrivate->rawPropertyCacheForType(propType);
= QQmlMetaType::rawPropertyCacheForType(propType);
if (!propertyMetaObject) {
// if we have an inline component from the current file,
// it is not properly registered at this point, as registration

View File

@ -100,7 +100,7 @@ QQmlRefPointer<QV4::ExecutableCompilationUnit> QQmlTypeCompiler::compile()
QQmlComponentAndAliasResolver resolver(this);
if (!resolver.resolve(result.processedRoot))
return nullptr;
pendingGroupPropertyBindings.resolveMissingPropertyCaches(engine, &m_propertyCaches);
pendingGroupPropertyBindings.resolveMissingPropertyCaches(&m_propertyCaches);
pendingGroupPropertyBindings.clear(); // anything that can be processed is now processed
}
} while (result.canResume);
@ -817,8 +817,8 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(
// Otherwise, make sure we look up by metaobject.
// TODO: Is this correct?
QQmlRefPointer<QQmlPropertyCache> pc = pd->typeVersion().hasMinorVersion()
? enginePrivate->rawPropertyCacheForType(pd->propType(), pd->typeVersion())
: enginePrivate->rawPropertyCacheForType(pd->propType());
? QQmlMetaType::rawPropertyCacheForType(pd->propType(), pd->typeVersion())
: QQmlMetaType::rawPropertyCacheForType(pd->propType());
const QMetaObject *mo = pc ? pc->firstCppMetaObject() : nullptr;
while (mo) {
if (mo == &QQmlComponent::staticMetaObject)

View File

@ -249,7 +249,7 @@ void QQmlTypeData::createTypeAndPropertyCaches(
&m_compiledData->propertyCaches, m_compiledData.data());
aliasCreator.appendAliasPropertiesToMetaObjects(engine);
pendingGroupPropertyBindings.resolveMissingPropertyCaches(engine, &m_compiledData->propertyCaches);
pendingGroupPropertyBindings.resolveMissingPropertyCaches(&m_compiledData->propertyCaches);
}
static bool addTypeReferenceChecksumsToHash(
@ -899,8 +899,6 @@ QQmlError QQmlTypeData::buildTypeResolutionCaches(
m_importCache.populateCache(typeNameCache->data());
QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
for (auto resolvedType = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd(); resolvedType != end; ++resolvedType) {
QScopedPointer<QV4::ResolvedTypeReference> ref(new QV4::ResolvedTypeReference);
QQmlType qmlType = resolvedType->type;
@ -933,7 +931,7 @@ QQmlError QQmlTypeData::buildTypeResolutionCaches(
auto exUnit = QQmlMetaType::obtainExecutableCompilationUnit(type);
if (exUnit) {
ref->setCompilationUnit(exUnit);
ref->setTypePropertyCache(engine->propertyCacheForType(type));
ref->setTypePropertyCache(QQmlMetaType::propertyCacheForType(type));
}
}
} else {

View File

@ -389,14 +389,13 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const
{
Q_ASSERT(typeObject->as<QV4::QQmlTypeWrapper>());
const QV4::QQmlTypeWrapper *typeWrapper = static_cast<const QV4::QQmlTypeWrapper *>(typeObject);
QV4::ExecutionEngine *engine = typeObject->internalClass()->engine;
QQmlEnginePrivate *qenginepriv = QQmlEnginePrivate::get(engine->qmlEngine());
// can only compare a QObject* against a QML type
const QObjectWrapper *wrapper = var.as<QObjectWrapper>();
if (!wrapper)
return QV4::Encode(false);
QV4::ExecutionEngine *engine = typeObject->internalClass()->engine;
// in case the wrapper outlived the QObject*
const QObject *wrapperObject = wrapper->object();
if (!wrapperObject)
@ -413,13 +412,14 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const
if (!theirDData->compilationUnit)
return Encode(false);
QQmlEnginePrivate *qenginepriv = QQmlEnginePrivate::get(engine->qmlEngine());
QQmlRefPointer<QQmlTypeData> td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl());
if (ExecutableCompilationUnit *cu = td->compilationUnit())
myQmlType = qenginepriv->metaObjectForType(cu->typeIds.id);
myQmlType = QQmlMetaType::metaObjectForType(cu->typeIds.id);
else
return Encode(false); // It seems myQmlType has some errors, so we could not compile it.
} else {
myQmlType = qenginepriv->metaObjectForType(myTypeId);
myQmlType = QQmlMetaType::metaObjectForType(myTypeId);
}
const QMetaObject *theirType = wrapperObject->metaObject();

View File

@ -250,9 +250,8 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
if (pd && valueTypeIndex != -1 && !QQmlMetaType::valueType(pd->propType())) {
// deep alias
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(metaObject->compilationUnit->engine->qmlEngine());
const QQmlRefPointer<QQmlPropertyCache> newPropertyCache
= enginePriv->propertyCacheForType(pd->propType());
= QQmlMetaType::propertyCacheForType(pd->propType());
void *argv[1] = { &target };
QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex, argv);
Q_ASSERT(newPropertyCache);

View File

@ -880,15 +880,13 @@ void tst_qqmllistreference::compositeListProperty()
QVERIFY(!i1.isNull());
QVERIFY(!i2.isNull());
// Without engine
// Without engine: We know the element type now.
QQmlListReference list1(object.data(), "items");
QCOMPARE(list1.listElementType(), nullptr);
QVERIFY(list1.listElementType() != nullptr);
QVERIFY(list1.append(i1.data()));
QVERIFY(list1.replace(0, i2.data()));
// Doesn't work because element type is unknown.
QVERIFY(!list1.append(i1.data()));
QVERIFY(!list1.replace(0, i2.data()));
// With engine
// With engine: same
QQmlListReference list2(object.data(), "items", &engine);
QVERIFY(list2.listElementType() != nullptr);
QVERIFY(list2.append(i1.data()));