diff options
| author | Olivier De Cannière <olivier.decanniere@qt.io> | 2025-10-15 11:29:57 +0200 |
|---|---|---|
| committer | Olivier De Cannière <olivier.decanniere@qt.io> | 2025-11-13 09:00:54 +0100 |
| commit | 869bf6ffc03484ddf10ba405b7345120510d434c (patch) | |
| tree | 3a5961c60ccec2ba9d7d7ae63f61fae16d8a00e4 /src/qml/jsruntime/qv4referenceobject.cpp | |
| parent | 3793511dc797fc78262f26323a6e5e7ded13d53d (diff) | |
JSRuntime: Extract ReferenceObject::init lambdas into functions
Pick-to: 6.10
Change-Id: I489b515388f9aba9250bfb05687331c92578ca57
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4referenceobject.cpp')
| -rw-r--r-- | src/qml/jsruntime/qv4referenceobject.cpp | 64 |
1 files changed, 64 insertions, 0 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 |
