diff options
-rw-r--r-- | src/qml/jsruntime/qv4qmlcontext.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlopenmetaobject.cpp | 18 | ||||
-rw-r--r-- | src/qml/qml/qqmlopenmetaobject_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 24 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache_p.h | 50 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertydata_p.h | 37 | ||||
-rw-r--r-- | src/qml/qml/qqmlproxymetaobject.cpp | 9 | ||||
-rw-r--r-- | src/qml/qml/qqmlproxymetaobject_p.h | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmltype.cpp | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype_p.h | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 41 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject_p.h | 4 | ||||
-rw-r--r-- | src/quick/designer/qqmldesignermetaobject.cpp | 38 | ||||
-rw-r--r-- | src/quick/designer/qqmldesignermetaobject_p.h | 5 |
16 files changed, 137 insertions, 116 deletions
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index 65481e4539..66693fb0d2 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -206,7 +206,10 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r // // Note: The scope object is only a QADMO for example when somebody registers a QQmlPropertyMap // sub-class as QML type and then instantiates it in .qml. - if (scopeObject && QQmlPropertyCache::isDynamicMetaObject(scopeObject->metaObject())) { + const QMetaObjectPrivate *metaObjectPrivate = scopeObject + ? reinterpret_cast<const QMetaObjectPrivate *>(scopeObject->metaObject()->d.data) + : nullptr; + if (metaObjectPrivate && metaObjectPrivate->flags & DynamicMetaObject) { // all bets are off, so don't try to optimize any lookups lookup = nullptr; if (performGobalLookUp()) diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 6383643ebb..bd49fc3b51 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1530,7 +1530,6 @@ QList<QQmlProxyMetaObject::ProxyData> QQmlMetaType::proxyData(const QMetaObject QMetaObjectBuilder builder; clone(builder, extMetaObject, superdataBaseMetaObject, baseMetaObject); - builder.setFlags(MetaObjectFlag::DynamicMetaObject); QMetaObject *mmo = builder.toMetaObject(); mmo->d.superdata = baseMetaObject; if (!metaObjects.isEmpty()) diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp index ec2d57013f..24aff03fca 100644 --- a/src/qml/qml/qqmlopenmetaobject.cpp +++ b/src/qml/qml/qqmlopenmetaobject.cpp @@ -99,11 +99,6 @@ QByteArray QQmlOpenMetaObjectType::propertyName(int idx) const return d->mob.property(idx).name(); } -QMetaObject *QQmlOpenMetaObjectType::metaObject() const -{ - return d->mem; -} - void QQmlOpenMetaObjectType::createProperties(const QVector<QByteArray> &names) { for (int i = 0; i < names.count(); ++i) { @@ -238,7 +233,7 @@ public: } QQmlOpenMetaObject *q; - QAbstractDynamicMetaObject *parent = nullptr; + QDynamicMetaObjectData *parent = nullptr; QVector<Property> data; QObject *object; QQmlRefPointer<QQmlOpenMetaObjectType> type; @@ -254,7 +249,7 @@ QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, const QMetaObject *base) d->type->d->referers.insert(this); QObjectPrivate *op = QObjectPrivate::get(obj); - d->parent = static_cast<QAbstractDynamicMetaObject *>(op->metaObject); + d->parent = op->metaObject; *static_cast<QMetaObject *>(this) = *d->type->d->mem; op->metaObject = this; } @@ -266,7 +261,7 @@ QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, QQmlOpenMetaObjectType *typ d->type->d->referers.insert(this); QObjectPrivate *op = QObjectPrivate::get(obj); - d->parent = static_cast<QAbstractDynamicMetaObject *>(op->metaObject); + d->parent = op->metaObject; *static_cast<QMetaObject *>(this) = *d->type->d->mem; op->metaObject = this; } @@ -292,6 +287,11 @@ void QQmlOpenMetaObject::emitPropertyNotification(const QByteArray &propertyName activate(d->object, *iter + d->type->d->signalOffset, nullptr); } +void QQmlOpenMetaObject::unparent() +{ + d->parent = nullptr; +} + int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void **a) { Q_ASSERT(d->object == o); @@ -319,7 +319,7 @@ int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void * } } -QAbstractDynamicMetaObject *QQmlOpenMetaObject::parent() const +QDynamicMetaObjectData *QQmlOpenMetaObject::parent() const { return d->parent; } diff --git a/src/qml/qml/qqmlopenmetaobject_p.h b/src/qml/qml/qqmlopenmetaobject_p.h index 47bba085b5..e455725bdf 100644 --- a/src/qml/qml/qqmlopenmetaobject_p.h +++ b/src/qml/qml/qqmlopenmetaobject_p.h @@ -78,7 +78,6 @@ public: int propertyCount() const; QByteArray propertyName(int) const; - QMetaObject *metaObject() const; protected: virtual void propertyCreated(int, QMetaPropertyBuilder &); @@ -121,6 +120,7 @@ public: QQmlOpenMetaObjectType *type() const; void emitPropertyNotification(const QByteArray &propertyName); + void unparent(); protected: int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override; @@ -132,7 +132,7 @@ protected: virtual void propertyWritten(int); virtual void propertyCreated(int, QMetaPropertyBuilder &); - QAbstractDynamicMetaObject *parent() const; + QDynamicMetaObjectData *parent() const; bool checkedSetValue(int index, const QVariant &value, bool force); diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 315f9f07fa..5ed63fb57c 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -342,7 +342,7 @@ const QMetaObject *QQmlPropertyCache::createMetaObject() QMetaObjectBuilder builder; toMetaObjectBuilder(builder); builder.setSuperClass(_parent->createMetaObject()); - _metaObject = RefCountedMetaObject(builder.toMetaObject(), RefCountedMetaObject::SharedMetaObject); + _metaObject = RefCountedMetaObject::createShared(builder.toMetaObject()); } return _metaObject; @@ -403,10 +403,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, QQmlPropertyData::Flags methodFlags, QQmlPropertyData::Flags signalFlags) { - _metaObject = RefCountedMetaObject(metaObject, RefCountedMetaObject::StaticMetaObject); - - bool dynamicMetaObject = isDynamicMetaObject(metaObject); - + _metaObject = RefCountedMetaObject::createStatic(metaObject); allowedRevisionCache.append(QTypeRevision::zero()); int methodCount = metaObject->methodCount(); @@ -557,8 +554,6 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, data->load(p); data->setTypeVersion(typeVersion); - data->m_flags.setIsDirect(!dynamicMetaObject); - Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX); data->setMetaObjectOffset(allowedRevisionCache.count() - 1); @@ -586,9 +581,8 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, isGadget = false; } - if (isGadget) // always dispatch over a 'normal' meta-call so the QQmlValueType can intercept - data->m_flags.setIsDirect(false); - else + // otherwise always dispatch over a 'normal' meta-call so the QQmlValueType can intercept + if (!isGadget) data->trySetStaticMetaCallFunction(metaObject->d.static_metacall, ii - propOffset); } } @@ -969,10 +963,7 @@ QQmlPropertyCache::property(QJSEngine *engine, QObject *obj, const QLatin1String return qQmlPropertyCacheProperty<const QLatin1String &>(engine, obj, name, context, local); } -// these two functions are copied from qmetaobject.cpp -static inline const QMetaObjectPrivate *priv(const uint* data) -{ return reinterpret_cast<const QMetaObjectPrivate*>(data); } - +// this function is copied from qmetaobject.cpp static inline const QByteArray stringData(const QMetaObject *mo, int index) { uint offset = mo->d.stringdata[2*index]; @@ -981,11 +972,6 @@ static inline const QByteArray stringData(const QMetaObject *mo, int index) return QByteArray::fromRawData(string, length); } -bool QQmlPropertyCache::isDynamicMetaObject(const QMetaObject *mo) -{ - return priv(mo->d.data)->flags & DynamicMetaObject; -} - const char *QQmlPropertyCache::className() const { if (_metaObject) diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 93e776527e..1db3f0f464 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -84,8 +84,14 @@ public: }; struct Data { - ~Data() { if (mode == SharedMetaObject) ::free(const_cast<QMetaObject *>(mo)); } - const QMetaObject *mo = nullptr; + ~Data() { + if (mode == SharedMetaObject) + ::free(sharedMetaObject); + } + union { + QMetaObject *sharedMetaObject = nullptr; + const QMetaObject *staticMetaObject; + }; int ref = 1; OwnershipMode mode; } *d; @@ -94,11 +100,24 @@ public: : d(nullptr) {} - RefCountedMetaObject(const QMetaObject *mo, OwnershipMode mode) - : d(new Data) { - d->mo = mo; - d->mode = mode; + static RefCountedMetaObject createShared(QMetaObject *mo) + { + RefCountedMetaObject result; + result.d = new Data(); + result.d->sharedMetaObject = mo; + result.d->mode = SharedMetaObject; + return result; + } + + static RefCountedMetaObject createStatic(const QMetaObject *mo) + { + RefCountedMetaObject result; + result.d = new Data(); + result.d->staticMetaObject = mo; + result.d->mode = StaticMetaObject; + return result; } + ~RefCountedMetaObject() { if (d && !--d->ref) delete d; @@ -120,8 +139,21 @@ public: ++d->ref; return *this; } - operator const QMetaObject *() const { return d ? d->mo : nullptr; } - const QMetaObject * operator ->() const { return d ? d->mo : nullptr; } + + const QMetaObject *constMetaObject() const + { + if (!d) + return nullptr; + return isShared() ? d->sharedMetaObject : d->staticMetaObject; + } + + QMetaObject *sharedMetaObject() const + { + return isShared() ? d->sharedMetaObject : nullptr; + } + + operator const QMetaObject *() const { return constMetaObject(); } + const QMetaObject * operator ->() const { return constMetaObject(); } bool isShared() const { return d && d->mode == SharedMetaObject; } }; @@ -206,8 +238,6 @@ public: inline int signalOffset() const; inline int qmlEnumCount() const; - static bool isDynamicMetaObject(const QMetaObject *); - void toMetaObjectBuilder(QMetaObjectBuilder &); inline bool callJSFactoryMethod(QObject *object, void **args) const; diff --git a/src/qml/qml/qqmlpropertydata_p.h b/src/qml/qml/qqmlpropertydata_p.h index edf777ff18..24e2204b71 100644 --- a/src/qml/qml/qqmlpropertydata_p.h +++ b/src/qml/qml/qqmlpropertydata_p.h @@ -104,7 +104,7 @@ public: // Lastly, isDirect and isOverridden apply to both functions and non-functions private: unsigned isConst : 1; // Property: has CONST flag/Method: is const - unsigned isDirectOrVMEFunction : 1; // Exists on a C++ QMetaOBject OR Function was added by QML + unsigned isVMEFunction : 1; // Function was added by QML unsigned isWritableORhasArguments : 1; // Has WRITE function OR Function takes arguments unsigned isResettableORisSignal : 1; // Has RESET function OR Function is a signal unsigned isAliasORisVMESignal : 1; // Is a QML alias to another property OR Signal was added by QML @@ -159,11 +159,6 @@ public: isConstructorORisBindable = b; } - void setIsDirect(bool b) { - Q_ASSERT(type != FunctionType); - isDirectOrVMEFunction = b; - } - void setIsRequired(bool b) { Q_ASSERT(type != FunctionType); isRequiredORisCloned = b; @@ -171,7 +166,7 @@ public: void setIsVMEFunction(bool b) { Q_ASSERT(type == FunctionType); - isDirectOrVMEFunction = b; + isVMEFunction = b; } void setHasArguments(bool b) { Q_ASSERT(type == FunctionType); @@ -233,7 +228,6 @@ public: bool isAlias() const { return !isFunction() && m_flags.isAliasORisVMESignal; } bool isFinal() const { return !isFunction() && m_flags.isFinalORisV4Function; } bool isOverridden() const { return m_flags.isOverridden; } - bool isDirect() const { return !isFunction() && m_flags.isDirectOrVMEFunction; } bool isRequired() const { return !isFunction() && m_flags.isRequiredORisCloned; } bool hasStaticMetaCallFunction() const { return staticMetaCallFunction() != nullptr; } bool isFunction() const { return m_flags.type == Flags::FunctionType; } @@ -244,7 +238,7 @@ public: bool isQJSValue() const { return m_flags.type == Flags::QJSValueType; } bool isVarProperty() const { return m_flags.type == Flags::VarPropertyType; } bool isQVariant() const { return m_flags.type == Flags::QVariantType; } - bool isVMEFunction() const { return isFunction() && m_flags.isDirectOrVMEFunction; } + bool isVMEFunction() const { return isFunction() && m_flags.isVMEFunction; } bool hasArguments() const { return isFunction() && m_flags.isWritableORhasArguments; } bool isSignal() const { return isFunction() && m_flags.isResettableORisSignal; } bool isVMESignal() const { return isFunction() && m_flags.isAliasORisVMESignal; } @@ -353,14 +347,23 @@ public: readPropertyWithArgs(target, args); } - inline void readPropertyWithArgs(QObject *target, void *args[]) const + // This is the same as QMetaObject::metacall(), but inlined here to avoid a function call. + // And we ignore the return value. + template<QMetaObject::Call call> + void doMetacall(QObject *object, int idx, void **argv) const + { + if (QDynamicMetaObjectData *dynamicMetaObject = QObjectPrivate::get(object)->metaObject) + dynamicMetaObject->metaCall(object, call, idx, argv); + else + object->qt_metacall(call, idx, argv); + } + + void readPropertyWithArgs(QObject *target, void *args[]) const { if (hasStaticMetaCallFunction()) staticMetaCallFunction()(target, QMetaObject::ReadProperty, relativePropertyIndex(), args); - else if (isDirect()) - target->qt_metacall(QMetaObject::ReadProperty, coreIndex(), args); else - QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex(), args); + doMetacall<QMetaObject::ReadProperty>(target, coreIndex(), args); } bool writeProperty(QObject *target, void *value, WriteFlags flags) const @@ -369,10 +372,8 @@ public: void *argv[] = { value, nullptr, &status, &flags }; if (flags.testFlag(BypassInterceptor) && hasStaticMetaCallFunction()) staticMetaCallFunction()(target, QMetaObject::WriteProperty, relativePropertyIndex(), argv); - else if (flags.testFlag(BypassInterceptor) && isDirect()) - target->qt_metacall(QMetaObject::WriteProperty, coreIndex(), argv); else - QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIndex(), argv); + doMetacall<QMetaObject::WriteProperty>(target, coreIndex(), argv); return true; } @@ -437,7 +438,7 @@ bool QQmlPropertyData::operator==(const QQmlPropertyData &other) const QQmlPropertyData::Flags::Flags() : otherBits(0) , isConst(false) - , isDirectOrVMEFunction(false) + , isVMEFunction(false) , isWritableORhasArguments(false) , isResettableORisSignal(false) , isAliasORisVMESignal(false) @@ -454,7 +455,7 @@ QQmlPropertyData::Flags::Flags() bool QQmlPropertyData::Flags::operator==(const QQmlPropertyData::Flags &other) const { return isConst == other.isConst && - isDirectOrVMEFunction == other.isDirectOrVMEFunction && + isVMEFunction == other.isVMEFunction && isWritableORhasArguments == other.isWritableORhasArguments && isResettableORisSignal == other.isResettableORisSignal && isAliasORisVMESignal == other.isAliasORisVMESignal && diff --git a/src/qml/qml/qqmlproxymetaobject.cpp b/src/qml/qml/qqmlproxymetaobject.cpp index 21d3c7ed05..33b216ee78 100644 --- a/src/qml/qml/qqmlproxymetaobject.cpp +++ b/src/qml/qml/qqmlproxymetaobject.cpp @@ -45,11 +45,11 @@ QT_BEGIN_NAMESPACE QQmlProxyMetaObject::QQmlProxyMetaObject(QObject *obj, QList<ProxyData> *mList) : metaObjects(mList), proxies(nullptr), parent(nullptr), object(obj) { - *static_cast<QMetaObject *>(this) = *metaObjects->constFirst().metaObject; + metaObject = metaObjects->constFirst().metaObject; QObjectPrivate *op = QObjectPrivate::get(obj); if (op->metaObject) - parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject); + parent = op->metaObject; op->metaObject = this; } @@ -145,4 +145,9 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void return object->qt_metacall(c, id, a); } +QMetaObject *QQmlProxyMetaObject::toDynamicMetaObject(QObject *) +{ + return metaObject; +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlproxymetaobject_p.h b/src/qml/qml/qqmlproxymetaobject_p.h index dfa5d44059..3eb25caa7b 100644 --- a/src/qml/qml/qqmlproxymetaobject_p.h +++ b/src/qml/qml/qqmlproxymetaobject_p.h @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE -class QQmlProxyMetaObject : public QAbstractDynamicMetaObject +class QQmlProxyMetaObject : public QDynamicMetaObjectData { public: struct ProxyData { @@ -78,6 +78,7 @@ public: protected: int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override; + QMetaObject *toDynamicMetaObject(QObject *) override; private: QObject *getProxy(int index); @@ -85,7 +86,8 @@ private: QList<ProxyData> *metaObjects; QObject **proxies; - QAbstractDynamicMetaObject *parent; + QDynamicMetaObjectData *parent; + QMetaObject *metaObject; QObject *object; }; diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index f9f40e7ec6..4b1e84f236 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -228,7 +228,6 @@ void QQmlTypePrivate::init() const // XXX - very inefficient QMetaObjectBuilder builder; QQmlMetaType::clone(builder, extMetaObject, extMetaObject, extMetaObject); - builder.setFlags(MetaObjectFlag::DynamicMetaObject); QMetaObject *mmo = builder.toMetaObject(); mmo->d.superdata = mo; QQmlProxyMetaObject::ProxyData data = { mmo, extFunc, 0, 0 }; diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index 7446322019..69baa03f74 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -52,7 +52,6 @@ QQmlValueType::QQmlValueType(QMetaType type, const QMetaObject *gadgetMetaObject { QMetaObjectBuilder builder(gadgetMetaObject); dynamicMetaObject = builder.toMetaObject(); - *static_cast<QMetaObject*>(this) = *dynamicMetaObject; } QQmlValueType::~QQmlValueType() @@ -113,7 +112,7 @@ void QQmlGadgetPtrWrapper::setValue(const QVariant &value) int QQmlGadgetPtrWrapper::metaCall(QMetaObject::Call type, int id, void **argv) { Q_ASSERT(m_gadgetPtr); - const QMetaObject *metaObject = valueType(); + const QMetaObject *metaObject = valueType()->metaObject(); QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &metaObject, &id); metaObject->d.static_metacall(static_cast<QObject *>(m_gadgetPtr), type, id, argv); return id; @@ -127,7 +126,7 @@ const QQmlValueType *QQmlGadgetPtrWrapper::valueType() const QMetaObject *QQmlValueType::toDynamicMetaObject(QObject *) { - return this; + return dynamicMetaObject; } void QQmlValueType::objectDestroyed(QObject *) diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h index b1e985ba7a..c8e2945413 100644 --- a/src/qml/qml/qqmlvaluetype_p.h +++ b/src/qml/qml/qqmlvaluetype_p.h @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE -class Q_QML_PRIVATE_EXPORT QQmlValueType : public QAbstractDynamicMetaObject +class Q_QML_PRIVATE_EXPORT QQmlValueType : public QDynamicMetaObjectData { public: QQmlValueType() : metaType(QMetaType::UnknownType) {} @@ -81,6 +81,7 @@ public: void destruct(void *gadgetPtr) const { metaType.destruct(gadgetPtr); } int metaTypeId() const { return metaType.id(); } + const QMetaObject *metaObject() const { return dynamicMetaObject; } // ---- dynamic meta object data interface QMetaObject *toDynamicMetaObject(QObject *) override; @@ -109,7 +110,7 @@ public: int metaTypeId() const { return valueType()->metaTypeId(); } int metaCall(QMetaObject::Call type, int id, void **argv); - QMetaProperty property(int index) { return valueType()->property(index); } + QMetaProperty property(int index) { return valueType()->metaObject()->property(index); } private: const QQmlValueType *valueType() const; diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 99663d9daa..ea4c9f6c6f 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -79,12 +79,13 @@ public: m_id = encodedIndex & ((quintptr(1) << (usableBits / 2)) - 1); // walk up to the correct meta object if necessary - auto mo = prop->object->metaObject(); + auto mo = static_cast<QQmlVMEMetaObject *>(QObjectPrivate::get(prop->object)->metaObject); while (inheritanceDepth--) - mo = mo->superClass(); - m_metaObject = static_cast<QQmlVMEMetaObject *>(const_cast<QMetaObject *>(mo)); + mo = mo->parentVMEMetaObject(); + m_metaObject = mo; Q_ASSERT(m_metaObject); - Q_ASSERT( ::strstr(m_metaObject->property(m_metaObject->propOffset() + m_id).typeName(), "QQmlListProperty") ); + Q_ASSERT(::strstr(m_metaObject->toDynamicMetaObject(prop->object)->property( + m_metaObject->propOffset() + m_id).typeName(), "QQmlListProperty") ); Q_ASSERT(m_metaObject->object == prop->object); // readPropertyAsList() with checks transformed into Q_ASSERT @@ -272,7 +273,7 @@ QQmlInterceptorMetaObject::QQmlInterceptorMetaObject(QObject *obj, const QQmlRef : object(obj), cache(cache), interceptors(nullptr), - hasAssignedMetaObjectData(false) + metaObject(nullptr) { QObjectPrivate *op = QObjectPrivate::get(obj); @@ -400,18 +401,13 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a) QMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObject *o) { - if (!hasAssignedMetaObjectData) { - *static_cast<QMetaObject *>(this) = *cache->createMetaObject(); - - if (parent.isT1()) - this->d.superdata = parent.asT1()->toDynamicMetaObject(o); - else - this->d.superdata = parent.asT2(); - - hasAssignedMetaObjectData = true; - } + Q_UNUSED(o); + if (!metaObject) + metaObject = cache->createMetaObject(); - return this; + // ### Qt7: The const_cast is only due to toDynamicMetaObject having the wrong return type. + // It should be const QMetaObject *. Fix this. + return const_cast<QMetaObject *>(metaObject); } QQmlVMEMetaObject::QQmlVMEMetaObject(QV4::ExecutionEngine *engine, @@ -777,10 +773,11 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * // To do this, we encode the hierarchy depth together with the id of the // property in a single quintptr, with the first half storing the depth // and the second half storing the property id - auto mo = object->metaObject(); + auto mo = static_cast<QQmlVMEMetaObject *>( + QObjectPrivate::get(object)->metaObject); quintptr inheritanceDepth = 0u; while (mo && mo != this) { - mo = mo->superClass(); + mo = mo->parentVMEMetaObject(); ++inheritanceDepth; } constexpr quintptr usableBits = sizeof(quintptr) * CHAR_BIT; @@ -996,10 +993,10 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * // are not rewritten correctly but this bug is deemed out-of-scope to fix for // performance reasons; see QTBUG-24064) and thus compilation will have failed. QQmlError e; - e.setDescription(QLatin1String("Exception occurred during compilation of " - "function: ") - + QString::fromUtf8(QMetaObject::method(_id) - .methodSignature())); + e.setDescription( + QStringLiteral( + "Exception occurred during compilation of function: ") + + QString::fromUtf8(metaObject->method(_id).methodSignature())); ep->warning(e); return -1; // The dynamic method with that id is not available. } diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 41b9a42b51..885efa01c5 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -89,7 +89,7 @@ public: }; -class Q_QML_PRIVATE_EXPORT QQmlInterceptorMetaObject : public QAbstractDynamicMetaObject +class Q_QML_PRIVATE_EXPORT QQmlInterceptorMetaObject : public QDynamicMetaObjectData { public: QQmlInterceptorMetaObject(QObject *obj, const QQmlRefPointer<QQmlPropertyCache> &cache); @@ -125,7 +125,7 @@ public: QBiPointer<QDynamicMetaObjectData, const QMetaObject> parent; QQmlPropertyValueInterceptor *interceptors; - bool hasAssignedMetaObjectData; + const QMetaObject *metaObject; }; inline QQmlInterceptorMetaObject *QQmlInterceptorMetaObject::get(QObject *obj) diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp index b005976387..33c161147b 100644 --- a/src/quick/designer/qqmldesignermetaobject.cpp +++ b/src/quick/designer/qqmldesignermetaobject.cpp @@ -110,8 +110,7 @@ QQmlDesignerMetaObject* QQmlDesignerMetaObject::getNodeInstanceMetaObject(QObjec void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine) { //Creating QQmlOpenMetaObjectType - m_type = new QQmlOpenMetaObjectType(metaObjectParent()); - m_type->addref(); + m_openMetaObject = std::make_unique<QQmlOpenMetaObject>(object, metaObjectParent()); //Assigning type to this copyTypeMetaObject(); @@ -119,10 +118,9 @@ void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine) QObjectPrivate *op = QObjectPrivate::get(object); op->metaObject = this; - cache = QQmlEnginePrivate::get(engine)->cache(this); + cache = QQmlEnginePrivate::get(engine)->cache(metaObject); nodeInstanceMetaObjectList.insert(this, true); - hasAssignedMetaObjectData = true; } QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine) @@ -136,7 +134,7 @@ QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engi //Assign cache to object if (ddata && ddata->propertyCache) { cache->setParent(ddata->propertyCache); - cache->invalidate(this); + cache->invalidate(metaObject); ddata->propertyCache->release(); ddata->propertyCache = cache.data(); ddata->propertyCache->addref(); @@ -146,23 +144,21 @@ QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engi QQmlDesignerMetaObject::~QQmlDesignerMetaObject() { - m_type->release(); - + // m_openMetaObject has this metaobject as its parent. + // We need to remove it in order to avoid a dtor recursion + m_openMetaObject->unparent(); nodeInstanceMetaObjectList.remove(this); } void QQmlDesignerMetaObject::createNewDynamicProperty(const QString &name) { - int id = m_type->createProperty(name.toUtf8()); + int id = type()->createProperty(name.toUtf8()); copyTypeMetaObject(); setValue(id, QVariant()); Q_ASSERT(id >= 0); - Q_UNUSED(id); //Updating cache - QQmlPropertyCache *oldParent = cache->parent(); - QQmlEnginePrivate::get(m_context->engine())->cache(this)->invalidate(this); - cache->setParent(oldParent); + cache->invalidate(metaObject); QQmlProperty property(myObject(), name, m_context); Q_ASSERT(property.isValid()); @@ -173,7 +169,7 @@ void QQmlDesignerMetaObject::setValue(int id, const QVariant &value) QPair<QVariant, bool> &prop = m_data->getDataRef(id); prop.first = propertyWriteValue(id, value); prop.second = true; - QMetaObject::activate(myObject(), id + m_type->signalOffset(), nullptr); + QMetaObject::activate(myObject(), id + type()->signalOffset(), nullptr); } QVariant QQmlDesignerMetaObject::propertyWriteValue(int, const QVariant &value) @@ -205,8 +201,8 @@ int QQmlDesignerMetaObject::propertyOffset() const int QQmlDesignerMetaObject::openMetaCall(QObject *o, QMetaObject::Call call, int id, void **a) { if ((call == QMetaObject::ReadProperty || call == QMetaObject::WriteProperty) - && id >= m_type->propertyOffset()) { - int propId = id - m_type->propertyOffset(); + && id >= type()->propertyOffset()) { + int propId = id - type()->propertyOffset(); if (call == QMetaObject::ReadProperty) { //propertyRead(propId); *reinterpret_cast<QVariant *>(a[0]) = m_data->getData(propId); @@ -217,7 +213,7 @@ int QQmlDesignerMetaObject::openMetaCall(QObject *o, QMetaObject::Call call, int prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0])); prop.second = true; //propertyWritten(propId); - activate(myObject(), m_type->signalOffset() + propId, nullptr); + activate(myObject(), type()->signalOffset() + propId, nullptr); } } return -1; @@ -236,7 +232,7 @@ int QQmlDesignerMetaObject::metaCall(QObject *o, QMetaObject::Call call, int id, int metaCallReturnValue = -1; - const QMetaProperty propertyById = QQmlVMEMetaObject::property(id); + const QMetaProperty propertyById = metaObject->property(id); if (call == QMetaObject::WriteProperty && propertyById.userType() == QMetaType::QVariant @@ -284,7 +280,7 @@ int QQmlDesignerMetaObject::metaCall(QObject *o, QMetaObject::Call call, int id, void QQmlDesignerMetaObject::notifyPropertyChange(int id) { - const QMetaProperty propertyById = property(id); + const QMetaProperty propertyById = metaObject->property(id); if (id < propertyOffset()) { if (notifyPropertyChangeCallBack) @@ -297,17 +293,17 @@ void QQmlDesignerMetaObject::notifyPropertyChange(int id) int QQmlDesignerMetaObject::count() const { - return m_type->propertyCount(); + return type()->propertyCount(); } QByteArray QQmlDesignerMetaObject::name(int idx) const { - return m_type->propertyName(idx); + return type()->propertyName(idx); } void QQmlDesignerMetaObject::copyTypeMetaObject() { - *static_cast<QMetaObject *>(this) = *m_type->metaObject(); + metaObject = m_openMetaObject.get(); } void QQmlDesignerMetaObject::registerNotifyPropertyChangeCallBack(void (*callback)(QObject *, const QQuickDesignerSupport::PropertyName &)) diff --git a/src/quick/designer/qqmldesignermetaobject_p.h b/src/quick/designer/qqmldesignermetaobject_p.h index cf91523ca3..08979b1492 100644 --- a/src/quick/designer/qqmldesignermetaobject_p.h +++ b/src/quick/designer/qqmldesignermetaobject_p.h @@ -58,6 +58,8 @@ #include <private/qqmlopenmetaobject_p.h> #include <private/qqmlvmemetaobject_p.h> +#include <memory> + QT_BEGIN_NAMESPACE struct MetaPropertyData; @@ -95,9 +97,10 @@ protected: private: QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine); void init(QObject *, QQmlEngine *engine); + QQmlOpenMetaObjectType *type() const { return m_openMetaObject->type(); } QPointer<QQmlContext> m_context; - QQmlOpenMetaObjectType *m_type; + std::unique_ptr<QQmlOpenMetaObject> m_openMetaObject; QScopedPointer<MetaPropertyData> m_data; //QAbstractDynamicMetaObject *m_parent; |