QmlPuppet: add workaround for reading list<> property crash

it skips the problematic QQmlProperty::read() calls

Pick-to: qds/4.7
Change-Id: Ic28e0de2143c4543c0815eda27d3886af1524f80
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Tim Jenssen
2025-05-12 21:26:15 +02:00
parent 78707dd625
commit 9162f29e9e
3 changed files with 56 additions and 4 deletions

View File

@@ -347,6 +347,7 @@ void DesignerCustomObjectDataFork::populateResetHashes()
if (binding) {
m_resetBindingHash.insert(propertyName, binding);
} else if (property.isWritable()) {
if (!QmlPrivateGate::useCrashQTBUG136735Workaround(property, Q_FUNC_INFO))
m_resetValueHash.insert(propertyName, property.read());
}
}
@@ -994,6 +995,53 @@ void registerFixResourcePathsForObjectCallBack()
s_qrcEngineHandler = new QrcEngineHandler();
}
bool useCrashQTBUG136735Workaround(const QQmlProperty &property, const char *callerInfo)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 4)
Q_UNUSED(property)
Q_UNUSED(callerInfo)
return false; // fixed in Qt
#else
if (!property.isValid())
return false;
auto coreMetaType = property.propertyMetaType();
// property.propertyTypeCategory() == QQmlProperty::PropertyTypeCategory::List
// for unknown reason the simple check is sometimes not working in the editor QMLPuppet
const bool listLike = coreMetaType.id() == QMetaType::QStringList
|| coreMetaType.id() == QMetaType::QVariantList
|| QtPrivate::hasRegisteredConverterFunctionToIterableMetaSequence(
coreMetaType);
if (!listLike)
return false;
const QMetaObject *metaObject = property.object()->metaObject();
QString ownerClassName;
do {
bool isDirectProperty = property.property().enclosingMetaObject() == metaObject;
if (isDirectProperty) {
ownerClassName = QString::fromLatin1(metaObject->className());
break;
}
} while ((metaObject = metaObject->superClass()));
// is generated QML type
static const QRegularExpression
re(QStringLiteral(R"(_QML(?:TYPE)?_\d+$)"), QRegularExpression::CaseInsensitiveOption);
if (!re.match(ownerClassName).hasMatch())
return false;
QString debugString("skipped read() on %1::%2 (direct owned list<T> property, QTBUG-136735)");
qWarning().noquote() << callerInfo
<< qPrintable(debugString.arg(ownerClassName, property.name()))
<< QString("propertyCategory(%3)").arg(property.propertyTypeCategory());
return true;
#endif
}
} // namespace QmlPrivateGate
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -24,6 +24,8 @@ typedef QWeakPointer<ObjectNodeInstance> ObjectNodeInstanceWeakPointer;
namespace QmlPrivateGate {
bool useCrashQTBUG136735Workaround(const QQmlProperty &property, const char *callerInfo);
class ComponentCompleteDisabler
{
public:

View File

@@ -623,14 +623,16 @@ static bool isPropertyBlackListed(const PropertyName &propertyName)
QVariant ObjectNodeInstance::property(const PropertyName &name) const
{
if (ignoredProperties().contains(name))
return QVariant();
return {};
// TODO: handle model nodes
if (isPropertyBlackListed(name))
return QVariant();
return {};
QQmlProperty property(object(), QString::fromUtf8(name), context());
if (QmlPrivateGate::useCrashQTBUG136735Workaround(property, Q_FUNC_INFO))
return {};
if (property.property().isEnumType()) {
QVariant value = property.read();
QMetaEnum me = property.property().enumerator();
@@ -640,7 +642,7 @@ QVariant ObjectNodeInstance::property(const PropertyName &name) const
if (property.propertyType() == QMetaType::QUrl) {
QUrl url = property.read().toUrl();
if (url.isEmpty())
return QVariant();
return {};
if (url.scheme() == "file") {
QFileInfo fi{nodeInstanceServer()->fileUrl().toLocalFile()};