summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2020-12-04 10:16:54 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2020-12-08 08:47:48 +0100
commitc7443d2e11c6558dc415d611d4d99e9286ddf0c0 (patch)
treeb4962397a90f92dd093734c13bc8042c21d019d3 /src/corelib/kernel
parent1ee2558b23490efec117f2a3b94a970e5c9ebb89 (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.cpp4
-rw-r--r--src/corelib/kernel/qproperty_p.h23
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)