diff options
author | Matthew Vogt <matthew.vogt@nokia.com> | 2012-07-18 10:16:12 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-07-20 05:35:13 +0200 |
commit | fa3dcc0efb2696612bf9db54a7ed4e26a2cf4765 (patch) | |
tree | 1a571292334edd0ea10fda559b8c84862a51b58b /src | |
parent | 9018c236c73884ea706ac1d04a306467454e6243 (diff) |
Update var property to null on object deletion
When a var property contains a pointer to a QObject-derived instance,
ensure that object deletion causes the property to be updated.
Task-number: QTBUG-26542
Change-Id: I67a59ffd7f09063328d45dc84889add55a5428e4
Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 53 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject_p.h | 10 |
2 files changed, 52 insertions, 11 deletions
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 5dcff3ea24..ce574875e3 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -57,8 +57,8 @@ Q_DECLARE_METATYPE(QJSValue); QT_BEGIN_NAMESPACE -QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr() - : QQmlGuard<QObject>(0), m_target(0), m_index(-1) +QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr(bool isVar) + : QQmlGuard<QObject>(0), m_target(0), m_isVar(isVar), m_index(-1) { } @@ -66,10 +66,16 @@ QQmlVMEVariantQObjectPtr::~QQmlVMEVariantQObjectPtr() { } -void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *) +void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *o) { - if (m_target && m_index >= 0) + if (m_target && m_index >= 0) { + if (m_isVar && m_target->varPropertiesInitialized && !m_target->varProperties.IsEmpty()) { + // Set the var property to NULL + m_target->varProperties->Set(m_index - m_target->firstVarPropertyIndex, v8::Null()); + } + m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0); + } } void QQmlVMEVariantQObjectPtr::setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index) @@ -336,7 +342,7 @@ void QQmlVMEVariant::setValue(QObject *v, QQmlVMEMetaObject *target, int index) if (type != QMetaType::QObjectStar) { cleanup(); type = QMetaType::QObjectStar; - new (dataPtr()) QQmlVMEVariantQObjectPtr; + new (dataPtr()) QQmlVMEVariantQObjectPtr(false); } reinterpret_cast<QQmlVMEVariantQObjectPtr*>(dataPtr())->setGuardedValue(v, target, index); } @@ -602,6 +608,8 @@ QQmlVMEMetaObject::~QQmlVMEMetaObject() if (metaData->varPropertyCount) qPersistentDispose(varProperties); // if not weak, will not have been cleaned up by the callback. + + qDeleteAll(varObjectGuards); } int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) @@ -1036,15 +1044,30 @@ void QQmlVMEMetaObject::writeVarProperty(int id, v8::Handle<v8::Value> value) } } - // And, if the new value is a scarce resource, we need to ensure that it does not get - // automatically released by the engine until no other references to it exist. + QObject *valueObject = 0; + QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id); + if (value->IsObject()) { - QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(v8::Handle<v8::Object>::Cast(value)); - if (r) { + // And, if the new value is a scarce resource, we need to ensure that it does not get + // automatically released by the engine until no other references to it exist. + if (QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(v8::Handle<v8::Object>::Cast(value))) { r->addVmePropertyReference(); + } else if (QV8QObjectResource *r = v8_resource_cast<QV8QObjectResource>(v8::Handle<v8::Object>::Cast(value))) { + // We need to track this QObject to signal its deletion + valueObject = r->object; + + // Do we already have a QObject guard for this property? + if (valueObject && !guard) { + guard = new QQmlVMEVariantQObjectPtr(true); + varObjectGuards.append(guard); + } } } + if (guard) { + guard->setGuardedValue(valueObject, this, id); + } + // Write the value and emit change signal as appropriate. varProperties->Set(id - firstVarPropertyIndex, value); activate(object, methodOffset() + id, 0); @@ -1367,4 +1390,16 @@ QQmlVMEMetaObject *QQmlVMEMetaObject::getForSignal(QObject *o, int coreIndex) return vme; } +QQmlVMEVariantQObjectPtr *QQmlVMEMetaObject::getQObjectGuardForProperty(int index) const +{ + QList<QQmlVMEVariantQObjectPtr *>::ConstIterator it = varObjectGuards.constBegin(), end = varObjectGuards.constEnd(); + for ( ; it != end; ++it) { + if ((*it)->m_index == index) { + return *it; + } + } + + return 0; +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 7a01b70b06..5751989b0c 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -141,13 +141,15 @@ class QQmlVMEMetaObject; class QQmlVMEVariantQObjectPtr : public QQmlGuard<QObject> { public: - inline QQmlVMEVariantQObjectPtr(); + inline QQmlVMEVariantQObjectPtr(bool isVar); inline ~QQmlVMEVariantQObjectPtr(); + inline void objectDestroyed(QObject *); inline void setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index); QQmlVMEMetaObject *m_target; - int m_index; + unsigned m_isVar : 1; + int m_index : 31; }; class QV8QObjectWrapper; @@ -238,6 +240,10 @@ public: void activate(QObject *, int, void **); + QList<QQmlVMEVariantQObjectPtr *> varObjectGuards; + + QQmlVMEVariantQObjectPtr *getQObjectGuardForProperty(int) const; + friend class QV8GCCallback; friend class QV8QObjectWrapper; }; |