From 2951c124d3ff58abe1f84175e512ba26977f13d8 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 14 Jan 2021 16:50:39 +0100 Subject: Mark dynamic state machines' metaobjects as fully dynamic The memory is allocated using malloc() and will be free()'d eventually. Client code cannot expect to keep string data from those metaobjects around. The QML engine will avoid the creation of property caches (which hold string data from the metaobject) if the metaobject is fully dynamic. Therefore, just create a QAbstractDynamicMetaObject that wraps the original metaobject and pass that to QObjectPrivate in order to signal the fully dynamic nature of the metaobject to QML. Fixes: QTBUG-89521 Change-Id: I349dcb689be5674679237a551ed8595bd6b5b672 Reviewed-by: Fabian Kosmale (cherry picked from commit 0e4c91654abff279b51238b46f880dd624ab9ec8) Reviewed-by: Qt Cherry-pick Bot --- src/scxml/qscxmlcompiler.cpp | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/scxml/qscxmlcompiler.cpp b/src/scxml/qscxmlcompiler.cpp index 8583233..9bf3a92 100644 --- a/src/scxml/qscxmlcompiler.cpp +++ b/src/scxml/qscxmlcompiler.cpp @@ -485,9 +485,31 @@ 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) {} + 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(metaObject)->d = m->d; + m_metaObject = m; + } }; class DynamicStateMachine: public QScxmlStateMachine, public QScxmlInternal::GeneratedTableData @@ -544,7 +566,7 @@ private: b.setClassName("DynamicStateMachine"); b.setSuperClass(&QScxmlStateMachine::staticMetaObject); b.setStaticMetacallFunction(qt_static_metacall); - d->m_metaObject = b.toMetaObject(); + d->setDynamicMetaObject(b.toMetaObject()); } void initDynamicParts(const MetaDataInfo &info) @@ -553,7 +575,7 @@ private: // Release the temporary QMetaObject. Q_ASSERT(d->m_metaObject != &QScxmlStateMachine::staticMetaObject); free(const_cast(d->m_metaObject)); - d->m_metaObject = &QScxmlStateMachine::staticMetaObject; + d->setDynamicMetaObject(&QScxmlStateMachine::staticMetaObject); // Build the real one. QMetaObjectBuilder b; @@ -579,7 +601,7 @@ private: } // And we're done - d->m_metaObject = b.toMetaObject(); + d->setDynamicMetaObject(b.toMetaObject()); } public: @@ -588,7 +610,7 @@ public: Q_D(DynamicStateMachine); if (d->m_metaObject != &QScxmlStateMachine::staticMetaObject) { free(const_cast(d->m_metaObject)); - d->m_metaObject = &QScxmlStateMachine::staticMetaObject; + d->setDynamicMetaObject(&QScxmlStateMachine::staticMetaObject); } } -- cgit v1.2.3