diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/qml/jsruntime/qv4referenceobject.cpp | 64 | ||||
| -rw-r--r-- | src/qml/jsruntime/qv4referenceobject_p.h | 67 |
2 files changed, 67 insertions, 64 deletions
diff --git a/src/qml/jsruntime/qv4referenceobject.cpp b/src/qml/jsruntime/qv4referenceobject.cpp index 7493ed5714..336b715ca0 100644 --- a/src/qml/jsruntime/qv4referenceobject.cpp +++ b/src/qml/jsruntime/qv4referenceobject.cpp @@ -488,4 +488,68 @@ void QQmlDirtyReferenceObject_callback(QQmlNotifierEndpoint *e, void **) { static_cast<QV4::Heap::ReferenceObjectEndpoint*>(e)->reference->setDirty(true); } +namespace QV4 { + +void Heap::ReferenceObject::connectToNotifySignal(QObject *obj, int property, QQmlEngine *engine) +{ + Q_ASSERT(obj); + Q_ASSERT(engine); + + Q_ASSERT(!referenceEndpoint); + Q_ASSERT(!bindableNotifier); + + referenceEndpoint = new ReferenceObjectEndpoint(this); + + // Connect and signal emission work on "signal indexes". Those are different from "method + // indexes". + // The public MetaObject interface can, generally, give us the "method index" of the notify + // signal. + // Quite unintuitively, this is true for "notifySignalIndex". As the "method index" and the + // "signal index" can be different, connecting the "method index" of the notify signal can + // incur in issues when the signal is being emitted and checking for connected endpoints. + // For example, we might be connected to the "method index" of the notify signal for the + // property and end up checking for the subscribers of a different signal when the notify + // signal is emitted, due to the different meaning of the same index. + // Thus we pass by the private interface to ensure that we are connecting based on the "signal + // index" instead. + const int index = QMetaObjectPrivate::signalIndex(obj->metaObject()->property(property) + .notifySignal()); + referenceEndpoint->connect(obj, index, engine); + + // When the object that is being referenced is destroyed, we + // need to ensure that one additional read is performed to + // invalidate the data we hold. + // As the object might be destroyed in a way that doesn't + // trigger the notify signal for the relevant property, we react + // directly to the destruction itself. + // We use a plain connection instead of a QQmlNotifierEndpoint + // based connection as, currently, declarative-side signals are + // always discarded during destruction (see + // QQmlData::signalEmitted). + // In theory it should be possible to relax that condition for + // the destroy signal specifically, which should allow a more + // optimized way of connecting. + // Nonetheless this seems to be the only place where we have + // this kind of need, and thus go for the simpler solution, + // which can be changed later if the need arises. + new (onDelete) QMetaObject::Connection( + QObject::connect(obj, &QObject::destroyed, [this](){ setDirty(true); })); +} + +void Heap::ReferenceObject::connectToBindable(QObject *obj, int property, QQmlEngine *engine) +{ + Q_ASSERT(obj); + Q_ASSERT(engine); + + Q_ASSERT(!referenceEndpoint); + Q_ASSERT(!bindableNotifier); + + bindableNotifier = new QPropertyNotifier(obj->metaObject()->property(property).bindable(obj) + .addNotifier([this](){ setDirty(true); })); + new (onDelete) QMetaObject::Connection( + QObject::connect(obj, &QObject::destroyed, [this]() { setDirty(true); })); +} + +} // namespace QV4 + QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4referenceobject_p.h b/src/qml/jsruntime/qv4referenceobject_p.h index 0e7219ef92..c179e83363 100644 --- a/src/qml/jsruntime/qv4referenceobject_p.h +++ b/src/qml/jsruntime/qv4referenceobject_p.h @@ -53,70 +53,6 @@ DECLARE_HEAP_OBJECT(ReferenceObject, Object) { void init(Object *object, int property, Flags flags) { - auto connectToNotifySignal = [this](QObject* obj, int property, QQmlEngine* engine) { - Q_ASSERT(obj); - Q_ASSERT(engine); - - Q_ASSERT(!referenceEndpoint); - Q_ASSERT(!bindableNotifier); - - referenceEndpoint = new ReferenceObjectEndpoint(this); - referenceEndpoint->connect( - obj, - // Connect and signal emission work on "signal - // indexes". Those are different from "method - // indexes". - // The public MetaObject interface can, generally, - // give us the "method index" of the notify - // signal. - // Quite unintuitively, this is true for - // "notifySignalIndex". - // As the "method index" and the "signal index" - // can be different, connecting the "method index" - // of the notify signal can incur in issues when - // the signal is being emitted and checking for - // connected endpoints. - // For example, we might be connected to the - // "method index" of the notify signal for the - // property and end up checking for the - // subscribers of a different signal when the - // notify signal is emitted, due to the different - // meaning of the same index. - // Thus we pass by the private interface to ensure - // that we are connecting based on the "signal - // index" instead. - QMetaObjectPrivate::signalIndex(obj->metaObject()->property(property).notifySignal()), - engine); - // When the object that is being referenced is destroyed, we - // need to ensure that one additional read is performed to - // invalidate the data we hold. - // As the object might be destroyed in a way that doesn't - // trigger the notify signal for the relevant property, we react - // directly to the destruction itself. - // We use a plain connection instead of a QQmlNotifierEndpoint - // based connection as, currently, declarative-side signals are - // always discarded during destruction (see - // QQmlData::signalEmitted). - // In theory it should be possible to relax that condition for - // the destroy signal specifically, which should allow a more - // optimized way of connecting. - // Nonetheless this seems to be the only place where we have - // this kind of need, and thus go for the simpler solution, - // which can be changed later if the need arises. - new(onDelete) QMetaObject::Connection(QObject::connect(obj, &QObject::destroyed, [this](){ setDirty(true); })); - }; - - auto connectToBindable = [this](QObject* obj, int property, QQmlEngine* engine) { - Q_ASSERT(obj); - Q_ASSERT(engine); - - Q_ASSERT(!referenceEndpoint); - Q_ASSERT(!bindableNotifier); - - bindableNotifier = new QPropertyNotifier(obj->metaObject()->property(property).bindable(obj).addNotifier([this](){ setDirty(true); })); - new(onDelete) QMetaObject::Connection(QObject::connect(obj, &QObject::destroyed, [this](){ setDirty(true); })); - }; - setObject(object); m_property = property; m_flags = flags; @@ -227,6 +163,9 @@ DECLARE_HEAP_OBJECT(ReferenceObject, Object) { delete bindableNotifier; } + void connectToNotifySignal(QObject *obj, int property, QQmlEngine *engine); + void connectToBindable(QObject *obj, int property, QQmlEngine *engine); + private: bool hasFlag(Flag flag) const |
