aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp34
-rw-r--r--tests/auto/qml/qqmlecmascript/data/frozenQObject3.qml30
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp24
3 files changed, 85 insertions, 3 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index ad10053394..c01f6986be 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1328,9 +1328,37 @@ void Heap::QObjectWrapper::markObjects(Heap::Base *that, MarkStack *markStack)
QObjectWrapper *This = static_cast<QObjectWrapper *>(that);
if (QObject *o = This->object()) {
- QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
- if (vme)
- vme->mark(markStack);
+ if (QQmlData *ddata = QQmlData::get(o)) {
+ if (ddata->hasVMEMetaObject) {
+ if (QQmlVMEMetaObject *vme
+ = static_cast<QQmlVMEMetaObject *>(QObjectPrivate::get(o)->metaObject)) {
+ vme->mark(markStack);
+ }
+ }
+
+ if (ddata->hasConstWrapper) {
+ Scope scope(that->internalClass->engine);
+ Q_ASSERT(scope.engine->m_multiplyWrappedQObjects);
+
+ Scoped<QV4::QObjectWrapper> constWrapper(
+ scope,
+ scope.engine->m_multiplyWrappedQObjects->value(
+ static_cast<const QObject *>(o)));
+
+ Q_ASSERT(constWrapper);
+
+ if (This == constWrapper->d()) {
+ // We've got the const wrapper. Also mark the non-const one
+ if (ddata->jsEngineId == scope.engine->m_engineId)
+ ddata->jsWrapper.markOnce(markStack);
+ else
+ scope.engine->m_multiplyWrappedQObjects->mark(o, markStack);
+ } else {
+ // We've got the non-const wrapper. Also mark the const one.
+ constWrapper->mark(markStack);
+ }
+ }
+ }
// Children usually don't need to be marked, the gc keeps them alive.
// But in the rare case of a "floating" QObject without a parent that
diff --git a/tests/auto/qml/qqmlecmascript/data/frozenQObject3.qml b/tests/auto/qml/qqmlecmascript/data/frozenQObject3.qml
new file mode 100644
index 0000000000..51c321684e
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/frozenQObject3.qml
@@ -0,0 +1,30 @@
+import QtQml
+import test
+
+QtObject {
+ id: root
+
+ property FrozenObjects a: FrozenObjects { objectName: "a" }
+ property FrozenObjects b: FrozenObjects { objectName: "b" }
+
+ // Create wrappers and immediately discard them
+ objectName: a.getConst().objectName + "/" + b.getNonConst().objectName
+
+ // Create a non-const wrapper and retain it
+ property var objNonConst: a.getNonConst()
+
+ // Create a const wrapper and retain it
+ property var objConst: b.getConst()
+
+ property int gcs: 0
+
+ property Timer t: Timer {
+ interval: 1
+ running: true
+ repeat: true
+ onTriggered: {
+ gc();
+ ++root.gcs;
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index c6d73dabb0..788e78b0f1 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -10079,6 +10079,9 @@ public:
Q_INVOKABLE void triggerSignal() { emit fooMember2Emitted(&m_fooMember2); }
+ Q_INVOKABLE const FrozenFoo *getConst() { return createFloating(); }
+ Q_INVOKABLE FrozenFoo *getNonConst() { return createFloating(); }
+
FrozenFoo *fooMember() { return &m_fooMember; }
FrozenFoo *fooMember2() { return &m_fooMember2; }
@@ -10088,6 +10091,16 @@ signals:
private:
const FrozenFoo *fooMemberConst() const { return &m_fooMember; }
+ FrozenFoo *createFloating()
+ {
+ if (!m_floating) {
+ m_floating = new FrozenFoo;
+ m_floating->setObjectName(objectName());
+ }
+ return m_floating;
+ }
+
+ FrozenFoo *m_floating = nullptr;
FrozenFoo m_fooMember;
FrozenFoo m_fooMember2;
};
@@ -10110,6 +10123,17 @@ void tst_qqmlecmascript::frozenQObject()
QVERIFY(frozenObjects->property("caughtSignal").toBool());
QCOMPARE(frozenObjects->fooMember()->name(), QStringLiteral("Jane"));
QCOMPARE(frozenObjects->fooMember2()->name(), QStringLiteral("Jane"));
+
+ QQmlComponent component3(&engine, testFileUrl("frozenQObject3.qml"));
+ QScopedPointer<QObject> root3(component3.create());
+ QCOMPARE(root3->objectName(), QLatin1String("a/b"));
+ QVERIFY(root3->property("objConst").value<QObject *>());
+ QVERIFY(root3->property("objNonConst").value<QObject *>());
+
+ QTRY_VERIFY(root3->property("gcs").toInt() > 8);
+
+ QVERIFY(root3->property("objConst").value<QObject *>());
+ QVERIFY(root3->property("objNonConst").value<QObject *>());
}
struct ConstPointer : QObject