aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlvmemetaobject.cpp
diff options
context:
space:
mode:
authorChris Adams <christopher.adams@nokia.com>2012-03-14 12:00:40 +1000
committerQt by Nokia <qt-info@nokia.com>2012-05-30 04:37:59 +0200
commit47eb68ab0b8d9ffd357cbad2f74b63ee2cf00dad (patch)
tree5159737869c7b8981003ed519b8cd8541799728e /src/qml/qml/qqmlvmemetaobject.cpp
parent7f8c243dec987018db47547c6ddea9cd8272e02a (diff)
Ensure that variant property references keep QObjects alive
Previously, only var property references could keep QObjects alive. This meant that the garbage collector would collect QObject data prematurely. This commit ensures that variant properties keep QObjects alive as required. Task-number: QTBUG-24767 Change-Id: Ic98a06863251a3e7d6384ba9256810a78fb23406 Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'src/qml/qml/qqmlvmemetaobject.cpp')
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp34
1 files changed, 31 insertions, 3 deletions
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 50fda6db39..2434ef0a2b 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -515,6 +515,9 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
aConnected.resize(metaData->aliasCount);
int list_type = qMetaTypeId<QQmlListProperty<QObject> >();
+ int qobject_type = qMetaTypeId<QObject*>();
+ int variant_type = qMetaTypeId<QVariant>();
+ bool needsGcCallback = (metaData->varPropertyCount > 0);
// ### Optimize
for (int ii = 0; ii < metaData->propertyCount - metaData->varPropertyCount; ++ii) {
@@ -522,12 +525,20 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
if (t == list_type) {
listProperties.append(List(methodOffset() + ii, this));
data[ii].setValue(listProperties.count() - 1);
- }
+ } else if (!needsGcCallback && (t == qobject_type || t == variant_type)) {
+ needsGcCallback = true;
+ }
}
firstVarPropertyIndex = metaData->propertyCount - metaData->varPropertyCount;
- if (metaData->varPropertyCount)
+
+ // both var properties and variant properties can keep references to
+ // other QObjects, and var properties can also keep references to
+ // JavaScript objects. If we have any properties, we need to hook
+ // the gc() to ensure that references keep objects alive as needed.
+ if (needsGcCallback) {
QV8GCCallback::addGcCallbackNode(this);
+ }
}
QQmlVMEMetaObject::~QQmlVMEMetaObject()
@@ -1121,9 +1132,26 @@ void QQmlVMEMetaObject::GcPrologueCallback(QV8GCCallback::Node *node)
{
QQmlVMEMetaObject *vmemo = static_cast<QQmlVMEMetaObject*>(node);
Q_ASSERT(vmemo);
- if (!vmemo->varPropertiesInitialized || vmemo->varProperties.IsEmpty() || !vmemo->ctxt || !vmemo->ctxt->engine)
+
+ if (!vmemo->ctxt || !vmemo->ctxt->engine)
return;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(vmemo->ctxt->engine);
+
+ // add references created by VMEVariant properties
+ int maxDataIdx = vmemo->metaData->propertyCount - vmemo->metaData->varPropertyCount;
+ for (int ii = 0; ii < maxDataIdx; ++ii) { // XXX TODO: optimise?
+ if (vmemo->data[ii].dataType() == QMetaType::QObjectStar) {
+ // possible QObject reference.
+ QObject *ref = vmemo->data[ii].asQObject();
+ if (ref) {
+ ep->v8engine()->addRelationshipForGC(vmemo->object, ref);
+ }
+ }
+ }
+
+ // add references created by var properties
+ if (!vmemo->varPropertiesInitialized || vmemo->varProperties.IsEmpty())
+ return;
ep->v8engine()->addRelationshipForGC(vmemo->object, vmemo->varProperties);
}