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>
This commit is contained in:
parent
1ee2558b23
commit
c7443d2e11
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user