diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2014-02-06 12:47:43 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-07 06:04:26 +0100 |
commit | 1298960aaa18217df44458312a8580a4d97b76e2 (patch) | |
tree | 19d9e0d81a1e2bd85cfb263fd7e8b8e236fc35be /src/qml | |
parent | edcdec4b5d23a04e727134723875ae40e0af6d1e (diff) |
Fix memory management issue with accessors
The earlier pattern of
Property p;
p.setSetter(new (mm) setterFunction);
p.setGetter(new (mm) getterFunction);
carries the risk of the second allocation garbage collecting the first one.
Consequently we need to put these values onto the JS stack, using a simple
ScopedProperty wrapper.
Change-Id: Ib29ea3b1eab95595dd6dfbb86fea282d23e3d899
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 7 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4scopedvalue_p.h | 12 | ||||
-rw-r--r-- | src/qml/types/qqmldelegatemodel.cpp | 28 | ||||
-rw-r--r-- | src/qml/util/qqmladaptormodel.cpp | 6 |
4 files changed, 33 insertions, 20 deletions
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index e9775cc1ed..de84747221 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -198,9 +198,10 @@ void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter) void Object::defineAccessorProperty(const StringRef name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *)) { ExecutionEngine *v4 = engine(); - Property p; - p.setGetter(getter ? v4->newBuiltinFunction(v4->rootContext, name, getter)->getPointer() : 0); - p.setSetter(setter ? v4->newBuiltinFunction(v4->rootContext, name, setter)->getPointer() : 0); + QV4::Scope scope(v4); + ScopedProperty p(scope); + p->setGetter(getter ? v4->newBuiltinFunction(v4->rootContext, name, getter)->getPointer() : 0); + p->setSetter(setter ? v4->newBuiltinFunction(v4->rootContext, name, setter)->getPointer() : 0); insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); } diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 34fb05835f..deb52c3605 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -658,6 +658,18 @@ inline ValueRef &ValueRef::operator=(const ScopedValue &o) return *this; } +struct ScopedProperty +{ + ScopedProperty(Scope &scope) + { + property = reinterpret_cast<Property*>(scope.alloc(sizeof(Property) / sizeof(Value))); + } + + Property *operator->() { return property; } + operator const Property &() { return *property; } + + Property *property; +}; } diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 5f0d26725c..3b02e1850b 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -1629,45 +1629,45 @@ void QQmlDelegateModelItemMetaType::initializePrototype() proto->defineAccessorProperty(QStringLiteral("model"), QQmlDelegateModelItem::get_model, 0); proto->defineAccessorProperty(QStringLiteral("groups"), QQmlDelegateModelItem::get_groups, QQmlDelegateModelItem::set_groups); QV4::ScopedString s(scope); - QV4::Property p; + QV4::ScopedProperty p(scope); s = v4->newString(QStringLiteral("isUnresolved")); - p.setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, 30, QQmlDelegateModelItem::get_member)); - p.setSetter(0); + p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, 30, QQmlDelegateModelItem::get_member)); + p->setSetter(0); proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); s = v4->newString(QStringLiteral("inItems")); - p.setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::get_member)); - p.setSetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::set_member)); + p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::get_member)); + p->setSetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::set_member)); proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); s = v4->newString(QStringLiteral("inPersistedItems")); - p.setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_member)); - p.setSetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::set_member)); + p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_member)); + p->setSetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::set_member)); proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); s = v4->newString(QStringLiteral("itemsIndex")); - p.setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::get_index)); + p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::get_index)); proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); s = v4->newString(QStringLiteral("persistedItemsIndex")); - p.setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_index)); - p.setSetter(0); + p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_index)); + p->setSetter(0); proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); for (int i = 2; i < groupNames.count(); ++i) { QString propertyName = QStringLiteral("in") + groupNames.at(i); propertyName.replace(2, 1, propertyName.at(2).toUpper()); s = v4->newString(propertyName); - p.setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::get_member)); - p.setSetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::set_member)); + p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::get_member)); + p->setSetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::set_member)); proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); } for (int i = 2; i < groupNames.count(); ++i) { const QString propertyName = groupNames.at(i) + QStringLiteral("Index"); s = v4->newString(propertyName); - p.setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::get_index)); - p.setSetter(0); + p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::get_index)); + p->setSetter(0); proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); } modelItemProto = proto; diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp index 8b79e33cc7..d38e5ac3df 100644 --- a/src/qml/util/qqmladaptormodel.cpp +++ b/src/qml/util/qqmladaptormodel.cpp @@ -219,6 +219,7 @@ public: QV4::Scoped<QV4::Object> proto(scope, v4->newObject()); proto->defineAccessorProperty(QStringLiteral("index"), get_index, 0); proto->defineAccessorProperty(QStringLiteral("hasModelChildren"), get_hasModelChildren, 0); + QV4::ScopedProperty p(scope); typedef QHash<QByteArray, int>::const_iterator iterator; for (iterator it = roleNames.constBegin(), end = roleNames.constEnd(); it != end; ++it) { @@ -226,9 +227,8 @@ public: const QByteArray &propertyName = it.key(); QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName))); - QV4::Property p; - p.setGetter(new (v4->memoryManager) QV4::IndexedBuiltinFunction(v4->rootContext, propertyId, QQmlDMCachedModelData::get_property)); - p.setSetter(new (v4->memoryManager) QV4::IndexedBuiltinFunction(v4->rootContext, propertyId, QQmlDMCachedModelData::set_property)); + p->setGetter(new (v4->memoryManager) QV4::IndexedBuiltinFunction(v4->rootContext, propertyId, QQmlDMCachedModelData::get_property)); + p->setSetter(new (v4->memoryManager) QV4::IndexedBuiltinFunction(v4->rootContext, propertyId, QQmlDMCachedModelData::set_property)); proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable); } prototype = proto; |