diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-12-04 10:16:54 +0100 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-12-08 08:47:48 +0100 |
commit | c7443d2e11c6558dc415d611d4d99e9286ddf0c0 (patch) | |
tree | b4962397a90f92dd093734c13bc8042c21d019d3 /src/corelib/kernel | |
parent | 1ee2558b23490efec117f2a3b94a970e5c9ebb89 (diff) |
QPropertyBindingPrivate: Enable QML engine error handling
The QPropertyBindingSourceLocation is only useful for C++ bindings; for
QML bindings we store the binding location in the V4 function. As the
QML binding needs to store some additional information for error
handling, we allow that memory to be reused by putting it into a union
with an array of byte.
Moreover, we use some of the space to store a callback pointer, which
gets called when an error occurs during binding evaluation. That
callback is only called when we know that the binding actually was set
up from the QML engine, in which case a bitflag is set.
Task-number: QTBUG-87733
Change-Id: I4387a4bd59d4d1ccfe75756ce81f4608319e0490
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qproperty.cpp | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty_p.h | 23 |
2 files changed, 25 insertions, 2 deletions
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index d2fd572b69..e2c5c7bff3 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -105,6 +105,8 @@ void QPropertyBindingPrivate::markDirtyAndNotifyObservers() dirty = true; if (eagerlyUpdating) { error = QPropertyBindingError(QPropertyBindingError::BindingLoop); + if (isQQmlPropertyBinding) + errorCallBack(this); return; } @@ -129,6 +131,8 @@ bool QPropertyBindingPrivate::evaluateIfDirtyAndReturnTrueIfValueChanged_helper( if (updating) { error = QPropertyBindingError(QPropertyBindingError::BindingLoop); + if (isQQmlPropertyBinding) + errorCallBack(this); return false; } diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h index e88547569e..d5feef1008 100644 --- a/src/corelib/kernel/qproperty_p.h +++ b/src/corelib/kernel/qproperty_p.h @@ -176,6 +176,7 @@ private: bool hasBindingWrapper:1; // used to detect binding loops for eagerly evaluated properties bool eagerlyUpdating:1; + bool isQQmlPropertyBinding:1; const QtPrivate::BindingFunctionVTable *vtable; @@ -190,7 +191,24 @@ private: QUntypedPropertyData *propertyDataPtr = nullptr; - QPropertyBindingSourceLocation location; + /* For bindings set up from C++, location stores where the binding was created in the C++ source + For QQmlPropertyBinding that information does not make sense, and the location in the QML file + is stored somewhere else. To make efficient use of the space, we instead provide a scratch space + for QQmlPropertyBinding (which stores further binding information there). + Anything stored in the union must be trivially destructible. + */ + static_assert(std::is_trivially_destructible_v<QPropertyBindingSourceLocation>); + static_assert(std::is_trivially_destructible_v<std::byte[sizeof(QPropertyBindingSourceLocation)]>); +protected: + using DeclarativeErrorCallback = void(*)(QPropertyBindingPrivate *); + union { + QPropertyBindingSourceLocation location; + struct { + std::byte declarativeExtraData[sizeof(QPropertyBindingSourceLocation) - sizeof(DeclarativeErrorCallback)]; + DeclarativeErrorCallback errorCallBack; + }; + }; +private: QPropertyBindingError error; QMetaType metaType; @@ -209,9 +227,10 @@ public: size_t dependencyObserverCount = 0; QPropertyBindingPrivate(QMetaType metaType, const QtPrivate::BindingFunctionVTable *vtable, - const QPropertyBindingSourceLocation &location) + const QPropertyBindingSourceLocation &location, bool isQQmlPropertyBinding=false) : hasBindingWrapper(false) , eagerlyUpdating(false) + , isQQmlPropertyBinding(isQQmlPropertyBinding) , vtable(vtable) , inlineDependencyObservers() // Explicit initialization required because of union , location(location) |