diff options
Diffstat (limited to 'src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp')
-rw-r--r-- | src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp | 242 |
1 files changed, 93 insertions, 149 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp index 4c104f01de..f678eb905b 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qqmlenginedebugservice.h" #include "qqmlwatcher.h" @@ -51,6 +15,7 @@ #include <private/qqmlvaluetype_p.h> #include <private/qqmlvmemetaobject_p.h> #include <private/qqmlexpression_p.h> +#include <private/qqmlsignalnames_p.h> #include <QtCore/qdebug.h> #include <QtCore/qmetaobject.h> @@ -94,9 +59,12 @@ qint64 NullDevice::writeData(const char *data, qint64 len) // (otherwise we assert in QVariant::operator<< when actually saving it) static bool isSaveable(const QVariant &value) { + const int valType = static_cast<int>(value.userType()); + if (valType >= QMetaType::User) + return false; NullDevice nullDevice; QDataStream fakeStream(&nullDevice); - return QMetaType::save(fakeStream, static_cast<int>(value.type()), value.constData()); + return QMetaType(valType).save(fakeStream, value.constData()); } QQmlEngineDebugServiceImpl::QQmlEngineDebugServiceImpl(QObject *parent) : @@ -152,22 +120,14 @@ QDataStream &operator>>(QDataStream &ds, return ds; } -static inline bool isSignalPropertyName(const QString &signalName) -{ - // see QmlCompiler::isSignalPropertyName - return signalName.length() >= 3 && signalName.startsWith(QLatin1String("on")) && - signalName.at(2).isLetter() && signalName.at(2).isUpper(); -} - static bool hasValidSignal(QObject *object, const QString &propertyName) { - if (!isSignalPropertyName(propertyName)) + auto signalName = QQmlSignalNames::handlerNameToSignalName(propertyName); + if (!signalName) return false; - QString signalName = propertyName.mid(2); - signalName[0] = signalName.at(0).toLower(); - - int sigIdx = QQmlPropertyPrivate::findSignalByName(object->metaObject(), signalName.toLatin1()).methodIndex(); + int sigIdx = QQmlPropertyPrivate::findSignalByName(object->metaObject(), signalName->toLatin1()) + .methodIndex(); if (sigIdx == -1) return false; @@ -191,22 +151,18 @@ QQmlEngineDebugServiceImpl::propertyData(QObject *obj, int propIdx) if (binding) rv.binding = binding->expression(); - if (QQmlValueTypeFactory::isValueType(prop.userType())) { - rv.type = QQmlObjectProperty::Basic; - } else if (QQmlMetaType::isQObject(prop.userType())) { + rv.value = valueContents(prop.read(obj)); + + if (prop.metaType().flags().testFlag(QMetaType::PointerToQObject)) { rv.type = QQmlObjectProperty::Object; - } else if (QQmlMetaType::isList(prop.userType())) { + } else if (QQmlMetaType::isList(prop.metaType())) { rv.type = QQmlObjectProperty::List; } else if (prop.userType() == QMetaType::QVariant) { rv.type = QQmlObjectProperty::Variant; + } else if (rv.value.isValid()) { + rv.type = QQmlObjectProperty::Basic; } - QVariant value; - if (rv.type != QQmlObjectProperty::Unknown && prop.userType() != 0) { - value = prop.read(obj); - } - rv.value = valueContents(value); - return rv; } @@ -216,12 +172,13 @@ QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const // maps for serialization. if (value.userType() == qMetaTypeId<QJSValue>()) value = value.value<QJSValue>().toVariant(); - const int userType = value.userType(); + const QMetaType metaType = value.metaType(); + const int metaTypeId = metaType.id(); //QObject * is not streamable. //Convert all such instances to a String value - if (value.type() == QVariant::List) { + if (value.userType() == QMetaType::QVariantList) { QVariantList contents; QVariantList list = value.toList(); int count = list.size(); @@ -231,17 +188,15 @@ QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const return contents; } - if (value.type() == QVariant::Map) { + if (value.userType() == QMetaType::QVariantMap) { QVariantMap contents; - QMapIterator<QString, QVariant> i(value.toMap()); - while (i.hasNext()) { - i.next(); + const auto map = value.toMap(); + for (auto i = map.cbegin(), end = map.cend(); i != end; ++i) contents.insert(i.key(), valueContents(i.value())); - } return contents; } - switch (userType) { + switch (metaTypeId) { case QMetaType::QRect: case QMetaType::QRectF: case QMetaType::QPoint: @@ -260,8 +215,8 @@ QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const case QMetaType::QJsonDocument: return value.toJsonDocument().toVariant(); default: - if (QQmlValueTypeFactory::isValueType(userType)) { - const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(userType); + if (QQmlMetaType::isValueType(metaType)) { + const QMetaObject *mo = QQmlMetaType::metaObjectForValueType(metaType); if (mo) { int toStringIndex = mo->indexOfMethod("toString()"); if (toStringIndex != -1) { @@ -271,13 +226,13 @@ QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const return s; } } - - if (isSaveable(value)) - return value; } + + if (isSaveable(value)) + return value; } - if (QQmlMetaType::isQObject(userType)) { + if (metaType.flags().testFlag(QMetaType::PointerToQObject)) { QObject *o = QQmlMetaType::toQObject(value); if (o) { QString name = o->objectName(); @@ -297,8 +252,8 @@ void QQmlEngineDebugServiceImpl::buildObjectDump(QDataStream &message, QObjectList children = object->children(); - int childrenCount = children.count(); - for (int ii = 0; ii < children.count(); ++ii) { + int childrenCount = children.size(); + for (int ii = 0; ii < children.size(); ++ii) { if (qobject_cast<QQmlContext*>(children[ii])) --childrenCount; } @@ -307,7 +262,7 @@ void QQmlEngineDebugServiceImpl::buildObjectDump(QDataStream &message, QList<QQmlObjectProperty> fakeProperties; - for (int ii = 0; ii < children.count(); ++ii) { + for (int ii = 0; ii < children.size(); ++ii) { QObject *child = children.at(ii); if (qobject_cast<QQmlContext*>(child)) continue; @@ -343,10 +298,8 @@ void QQmlEngineDebugServiceImpl::buildObjectDump(QDataStream &message, if (scope) { const QByteArray methodName = QMetaObjectPrivate::signal(scope->metaObject(), signalHandler->signalIndex()).name(); - const QLatin1String methodNameStr(methodName); - if (methodNameStr.size() != 0) { - prop.name = QLatin1String("on") + QChar(methodNameStr.at(0)).toUpper() - + methodNameStr.mid(1); + if (!methodName.isEmpty()) { + prop.name = QQmlSignalNames::signalNameToHandlerName(methodName); } } } @@ -356,12 +309,12 @@ void QQmlEngineDebugServiceImpl::buildObjectDump(QDataStream &message, } } - message << propertyIndexes.size() + fakeProperties.count(); + message << int(propertyIndexes.size() + fakeProperties.size()); for (int ii = 0; ii < propertyIndexes.size(); ++ii) message << propertyData(object, propertyIndexes.at(ii)); - for (int ii = 0; ii < fakeProperties.count(); ++ii) + for (int ii = 0; ii < fakeProperties.size(); ++ii) message << fakeProperties[ii]; } @@ -370,7 +323,7 @@ void QQmlEngineDebugServiceImpl::prepareDeferredObjects(QObject *obj) qmlExecuteDeferred(obj); QObjectList children = obj->children(); - for (int ii = 0; ii < children.count(); ++ii) { + for (int ii = 0; ii < children.size(); ++ii) { QObject *child = children.at(ii); prepareDeferredObjects(child); } @@ -381,7 +334,7 @@ void QQmlEngineDebugServiceImpl::storeObjectIds(QObject *co) { QQmlDebugService::idForObject(co); QObjectList children = co->children(); - for (int ii = 0; ii < children.count(); ++ii) + for (int ii = 0; ii < children.size(); ++ii) storeObjectIds(children.at(ii)); } @@ -392,7 +345,7 @@ void QQmlEngineDebugServiceImpl::buildObjectList(QDataStream &message, if (!ctxt->isValid()) return; - QQmlContextData *p = QQmlContextData::get(ctxt); + QQmlRefPointer<QQmlContextData> p = QQmlContextData::get(ctxt); QString ctxtName = ctxt->objectName(); int ctxtId = QQmlDebugService::idForObject(ctxt); @@ -403,31 +356,31 @@ void QQmlEngineDebugServiceImpl::buildObjectList(QDataStream &message, int count = 0; - QQmlContextData *child = p->childContexts; + QQmlRefPointer<QQmlContextData> child = p->childContexts(); while (child) { ++count; - child = child->nextChild; + child = child->nextChild(); } message << count; - child = p->childContexts; + child = p->childContexts(); while (child) { buildObjectList(message, child->asQQmlContext(), instances); - child = child->nextChild; + child = child->nextChild(); } count = 0; - for (int ii = 0; ii < instances.count(); ++ii) { + for (int ii = 0; ii < instances.size(); ++ii) { QQmlData *data = QQmlData::get(instances.at(ii)); - if (data->context == p) + if (data->context == p.data()) count ++; } message << count; - for (int ii = 0; ii < instances.count(); ++ii) { + for (int ii = 0; ii < instances.size(); ++ii) { QQmlData *data = QQmlData::get(instances.at(ii)); - if (data->context == p) + if (data->context == p.data()) message << objectData(instances.at(ii)); } } @@ -435,8 +388,8 @@ void QQmlEngineDebugServiceImpl::buildObjectList(QDataStream &message, void QQmlEngineDebugServiceImpl::buildStatesList(bool cleanList, const QList<QPointer<QObject> > &instances) { - if (m_statesDelegate) - m_statesDelegate->buildStatesList(cleanList, instances); + if (auto delegate = statesDelegate()) + delegate->buildStatesList(cleanList, instances); } QQmlEngineDebugServiceImpl::QQmlObjectData @@ -496,26 +449,26 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) QQmlDebugPacket ds(message); QByteArray type; - int queryId; + qint32 queryId; ds >> type >> queryId; QQmlDebugPacket rs; if (type == "LIST_ENGINES") { rs << QByteArray("LIST_ENGINES_R"); - rs << queryId << m_engines.count(); + rs << queryId << int(m_engines.size()); - for (int ii = 0; ii < m_engines.count(); ++ii) { + for (int ii = 0; ii < m_engines.size(); ++ii) { QJSEngine *engine = m_engines.at(ii); QString engineName = engine->objectName(); - int engineId = QQmlDebugService::idForObject(engine); + qint32 engineId = QQmlDebugService::idForObject(engine); rs << engineName << engineId; } } else if (type == "LIST_OBJECTS") { - int engineId = -1; + qint32 engineId = -1; ds >> engineId; QQmlEngine *engine = @@ -525,20 +478,15 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) if (engine) { QQmlContext *rootContext = engine->rootContext(); - // Clean deleted objects QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(rootContext); - for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) { - if (!ctxtPriv->instances.at(ii)) { - ctxtPriv->instances.removeAt(ii); - --ii; - } - } - buildObjectList(rs, rootContext, ctxtPriv->instances); - buildStatesList(true, ctxtPriv->instances); + ctxtPriv->cleanInstances(); // Clean deleted objects + const QList<QPointer<QObject>> instances = ctxtPriv->instances(); + buildObjectList(rs, rootContext, instances); + buildStatesList(true, instances); } } else if (type == "FETCH_OBJECT") { - int objectId; + qint32 objectId; bool recurse; bool dumpProperties = true; @@ -556,8 +504,8 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) } else if (type == "FETCH_OBJECTS_FOR_LOCATION") { QString file; - int lineNumber; - int columnNumber; + qint32 lineNumber; + qint32 columnNumber; bool recurse; bool dumpProperties = true; @@ -566,7 +514,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) const QList<QObject*> objects = objectForLocationInfo(file, lineNumber, columnNumber); rs << QByteArray("FETCH_OBJECTS_FOR_LOCATION_R") << queryId - << objects.count(); + << int(objects.size()); for (QObject *object : objects) { if (recurse) @@ -575,7 +523,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) } } else if (type == "WATCH_OBJECT") { - int objectId; + qint32 objectId; ds >> objectId; bool ok = m_watch->addWatch(queryId, objectId); @@ -583,7 +531,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) rs << QByteArray("WATCH_OBJECT_R") << queryId << ok; } else if (type == "WATCH_PROPERTY") { - int objectId; + qint32 objectId; QByteArray property; ds >> objectId >> property; @@ -592,7 +540,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) rs << QByteArray("WATCH_PROPERTY_R") << queryId << ok; } else if (type == "WATCH_EXPR_OBJECT") { - int debugId; + qint32 debugId; QString expr; ds >> debugId >> expr; @@ -606,11 +554,11 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) rs << QByteArray("NO_WATCH_R") << queryId << ok; } else if (type == "EVAL_EXPRESSION") { - int objectId; + qint32 objectId; QString expr; ds >> objectId >> expr; - int engineId = -1; + qint32 engineId = -1; if (!ds.atEnd()) ds >> engineId; @@ -638,12 +586,12 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result; } else if (type == "SET_BINDING") { - int objectId; + qint32 objectId; QString propertyName; QVariant expr; bool isLiteralValue; QString filename; - int line; + qint32 line; ds >> objectId >> propertyName >> expr >> isLiteralValue >> filename >> line; bool ok = setBinding(objectId, propertyName, expr, isLiteralValue, @@ -652,7 +600,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) rs << QByteArray("SET_BINDING_R") << queryId << ok; } else if (type == "RESET_BINDING") { - int objectId; + qint32 objectId; QString propertyName; ds >> objectId >> propertyName; bool ok = resetBinding(objectId, propertyName); @@ -660,7 +608,7 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) rs << QByteArray("RESET_BINDING_R") << queryId << ok; } else if (type == "SET_METHOD_BODY") { - int objectId; + qint32 objectId; QString methodName; QString methodBody; ds >> objectId >> methodName >> methodBody; @@ -689,8 +637,8 @@ bool QQmlEngineDebugServiceImpl::setBinding(int objectId, if (property.isValid()) { bool inBaseState = true; - if (m_statesDelegate) { - m_statesDelegate->updateBinding(context, property, expression, isLiteralValue, + if (auto delegate = statesDelegate()) { + delegate->updateBinding(context, property, expression, isLiteralValue, filename, line, column, &inBaseState); } @@ -715,8 +663,8 @@ bool QQmlEngineDebugServiceImpl::setBinding(int objectId, } else { // not a valid property - if (m_statesDelegate) - ok = m_statesDelegate->setBindingForInvalidProperty(object, propertyName, expression, isLiteralValue); + if (auto delegate = statesDelegate()) + ok = delegate->setBindingForInvalidProperty(object, propertyName, expression, isLiteralValue); if (!ok) qWarning() << "QQmlEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object; } @@ -730,7 +678,7 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope QQmlContext *context = qmlContext(object); if (object && context && context->isValid()) { - QStringRef parentPropertyRef(&propertyName); + QStringView parentPropertyRef(propertyName); const int idx = parentPropertyRef.indexOf(QLatin1Char('.')); if (idx != -1) parentPropertyRef = parentPropertyRef.left(idx); @@ -769,8 +717,8 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope return true; } - if (m_statesDelegate) { - m_statesDelegate->resetBindingForInvalidProperty(object, propertyName); + if (auto delegate = statesDelegate()) { + delegate->resetBindingForInvalidProperty(object, propertyName); return true; } @@ -786,11 +734,10 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth QQmlContext *context = qmlContext(object); if (!object || !context || !context->isValid()) return false; - QQmlContextData *contextData = QQmlContextData::get(context); + QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context); QQmlPropertyData dummy; - QQmlPropertyData *prop = - QQmlPropertyCache::property(context->engine(), object, method, contextData, dummy); + const QQmlPropertyData *prop = QQmlPropertyCache::property(object, method, contextData, &dummy); if (!prop || !prop->isVMEFunction()) return false; @@ -799,7 +746,7 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth QList<QByteArray> paramNames = metaMethod.parameterNames(); QString paramStr; - for (int ii = 0; ii < paramNames.count(); ++ii) { + for (int ii = 0; ii < paramNames.size(); ++ii) { if (ii != 0) paramStr.append(QLatin1Char(',')); paramStr.append(QString::fromUtf8(paramNames.at(ii))); } @@ -814,16 +761,18 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth QV4::Scope scope(v4); int lineNumber = 0; - QV4::ScopedFunctionObject oldMethod(scope, vmeMetaObject->vmeMethod(prop->coreIndex())); - if (oldMethod && oldMethod->d()->function) { - lineNumber = oldMethod->d()->function->compiledFunction->location.line; - } + QV4::Scoped<QV4::JavaScriptFunctionObject> oldMethod( + scope, vmeMetaObject->vmeMethod(prop->coreIndex())); + if (oldMethod && oldMethod->d()->function) + lineNumber = oldMethod->d()->function->compiledFunction->location.line(); + QV4::ScopedValue v(scope, QQmlJavaScriptExpression::evalFunction(contextData, object, jsfunction, contextData->urlString(), lineNumber)); vmeMetaObject->setVmeMethod(prop->coreIndex(), v); return true; } -void QQmlEngineDebugServiceImpl::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value) +void QQmlEngineDebugServiceImpl::propertyChanged( + qint32 id, qint32 objectId, const QMetaProperty &property, const QVariant &value) { QQmlDebugPacket rs; rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value); @@ -854,22 +803,17 @@ void QQmlEngineDebugServiceImpl::objectCreated(QJSEngine *engine, QObject *objec if (!m_engines.contains(engine)) return; - int engineId = QQmlDebugService::idForObject(engine); - int objectId = QQmlDebugService::idForObject(object); - int parentId = QQmlDebugService::idForObject(object->parent()); + qint32 engineId = QQmlDebugService::idForObject(engine); + qint32 objectId = QQmlDebugService::idForObject(object); + qint32 parentId = QQmlDebugService::idForObject(object->parent()); QQmlDebugPacket rs; //unique queryId -1 - rs << QByteArray("OBJECT_CREATED") << -1 << engineId << objectId << parentId; + rs << QByteArray("OBJECT_CREATED") << qint32(-1) << engineId << objectId << parentId; emit messageToClient(name(), rs.data()); } -void QQmlEngineDebugServiceImpl::setStatesDelegate(QQmlDebugStatesDelegate *delegate) -{ - m_statesDelegate = delegate; -} - QT_END_NAMESPACE #include "moc_qqmlenginedebugservice.cpp" |