summaryrefslogtreecommitdiffstats
path: root/src/scxml/qscxmlcompiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/scxml/qscxmlcompiler.cpp')
-rw-r--r--src/scxml/qscxmlcompiler.cpp56
1 files changed, 29 insertions, 27 deletions
diff --git a/src/scxml/qscxmlcompiler.cpp b/src/scxml/qscxmlcompiler.cpp
index b9bd102..9ddb581 100644
--- a/src/scxml/qscxmlcompiler.cpp
+++ b/src/scxml/qscxmlcompiler.cpp
@@ -54,6 +54,14 @@
#include "qscxmltabledata_p.h"
#include <private/qmetaobjectbuilder_p.h>
+#if QT_CONFIG(scxml_ecmascriptdatamodel)
+// In Qt5 the ecmascript datamodel brings in QML dependency.
+// We use that to include the QML headers needed for invalidating
+// property cache, even though strictly speaking these are distinct
+// functionalities.
+#include <private/qqmldata_p.h>
+#include <private/qqmlpropertycache_p.h>
+#endif
#endif // BUILD_QSCXMLC
#include <functional>
@@ -485,31 +493,9 @@ private:
class DynamicStateMachinePrivate : public QScxmlStateMachinePrivate
{
- struct DynamicMetaObject : public QAbstractDynamicMetaObject
- {
- QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) override
- {
- return this;
- }
-
- int metaCall(QObject *o, QMetaObject::Call c, int id, void **a) override
- {
- return o->qt_metacall(c, id, a);
- }
- };
-
public:
DynamicStateMachinePrivate() :
- QScxmlStateMachinePrivate(&QScxmlStateMachine::staticMetaObject)
- {
- metaObject = new DynamicMetaObject;
- }
-
- void setDynamicMetaObject(const QMetaObject *m) {
- // Prevent the QML engine from creating a property cache for this thing.
- static_cast<DynamicMetaObject *>(metaObject)->d = m->d;
- m_metaObject = m;
- }
+ QScxmlStateMachinePrivate(&QScxmlStateMachine::staticMetaObject) {}
};
class DynamicStateMachine: public QScxmlStateMachine, public QScxmlInternal::GeneratedTableData
@@ -566,7 +552,7 @@ private:
b.setClassName("DynamicStateMachine");
b.setSuperClass(&QScxmlStateMachine::staticMetaObject);
b.setStaticMetacallFunction(qt_static_metacall);
- d->setDynamicMetaObject(b.toMetaObject());
+ d->m_metaObject = b.toMetaObject();
}
void initDynamicParts(const MetaDataInfo &info)
@@ -575,7 +561,7 @@ private:
// Release the temporary QMetaObject.
Q_ASSERT(d->m_metaObject != &QScxmlStateMachine::staticMetaObject);
free(const_cast<QMetaObject *>(d->m_metaObject));
- d->setDynamicMetaObject(&QScxmlStateMachine::staticMetaObject);
+ d->m_metaObject = &QScxmlStateMachine::staticMetaObject;
// Build the real one.
QMetaObjectBuilder b;
@@ -601,7 +587,7 @@ private:
}
// And we're done
- d->setDynamicMetaObject(b.toMetaObject());
+ d->m_metaObject = b.toMetaObject();
}
public:
@@ -609,8 +595,24 @@ public:
{
Q_D(DynamicStateMachine);
if (d->m_metaObject != &QScxmlStateMachine::staticMetaObject) {
+#if QT_CONFIG(scxml_ecmascriptdatamodel)
+ // Invalidate the QML property cache as we delete the dynamic
+ // metaobject, otherwise stale string accesses might occur.
+ // Important! This invalidation is a workaround and brittle at
+ // at best; while string cache will be cleared, the cache itself
+ // will not. Instead we rely on that the (only) user for the cache
+ // is gone as well. This workaround is specific to Qt5, in Qt6
+ // we are able to fix the issue more properly by marking the
+ // metaobject dynamic => QML property caching will not be done.
+ //
+ // All further interaction with this property cache must be
+ // avoided.
+ QQmlData *ddata = QQmlData::get(this, false);
+ if (ddata && ddata->propertyCache)
+ ddata->propertyCache->invalidate(d->m_metaObject);
+#endif
free(const_cast<QMetaObject *>(d->m_metaObject));
- d->setDynamicMetaObject(&QScxmlStateMachine::staticMetaObject);
+ d->m_metaObject = &QScxmlStateMachine::staticMetaObject;
}
}