aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmltooling/qmldbg_debugger
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qmltooling/qmldbg_debugger')
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro5
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp130
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h10
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp8
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp276
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h24
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp51
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h12
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp21
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp79
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.h16
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp292
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h38
14 files changed, 440 insertions, 524 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
index f3f8a21ff8..2d8f0ceda2 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
+++ b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
@@ -12,8 +12,6 @@ SOURCES += \
$$PWD/qv4debugjob.cpp
HEADERS += \
- $$PWD/../shared/qqmlconfigurabledebugservice.h \
- $$PWD/../shared/qqmldebugpacket.h \
$$PWD/qqmldebuggerservicefactory.h \
$$PWD/qqmlenginedebugservice.h \
$$PWD/qqmlwatcher.h \
@@ -23,9 +21,6 @@ HEADERS += \
$$PWD/qv4datacollector.h \
$$PWD/qv4debugjob.h
-INCLUDEPATH += $$PWD \
- $$PWD/../shared
-
OTHER_FILES += \
$$PWD/qqmldebuggerservice.json
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
index 9315adf4ce..3851cdc71f 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
@@ -52,7 +52,7 @@ QQmlDebugService *QQmlDebuggerServiceFactory::create(const QString &key)
if (key == QV4DebugServiceImpl::s_key)
return new QV4DebugServiceImpl(this);
- return 0;
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index f0bb4de016..4c104f01de 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -39,7 +39,6 @@
#include "qqmlenginedebugservice.h"
#include "qqmlwatcher.h"
-#include "qqmldebugpacket.h"
#include <private/qqmldebugstatesdelegate_p.h>
#include <private/qqmlboundsignal_p.h>
@@ -56,12 +55,52 @@
#include <QtCore/qdebug.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qfileinfo.h>
+#include <QtCore/qjsonvalue.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsondocument.h>
+
#include <private/qmetaobject_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qversionedpacket_p.h>
QT_BEGIN_NAMESPACE
+using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>;
+
+class NullDevice : public QIODevice
+{
+public:
+ NullDevice() { open(QIODevice::ReadWrite); }
+
+protected:
+ qint64 readData(char *data, qint64 maxlen) final;
+ qint64 writeData(const char *data, qint64 len) final;
+};
+
+qint64 NullDevice::readData(char *data, qint64 maxlen)
+{
+ Q_UNUSED(data);
+ return maxlen;
+}
+
+qint64 NullDevice::writeData(const char *data, qint64 len)
+{
+ Q_UNUSED(data);
+ return len;
+}
+
+// check whether the data can be saved
+// (otherwise we assert in QVariant::operator<< when actually saving it)
+static bool isSaveable(const QVariant &value)
+{
+ NullDevice nullDevice;
+ QDataStream fakeStream(&nullDevice);
+ return QMetaType::save(fakeStream, static_cast<int>(value.type()), value.constData());
+}
+
QQmlEngineDebugServiceImpl::QQmlEngineDebugServiceImpl(QObject *parent) :
- QQmlEngineDebugService(2, parent), m_watch(new QQmlWatcher(this)), m_statesDelegate(0)
+ QQmlEngineDebugService(2, parent), m_watch(new QQmlWatcher(this)), m_statesDelegate(nullptr)
{
connect(m_watch, &QQmlWatcher::propertyChanged,
this, &QQmlEngineDebugServiceImpl::propertyChanged);
@@ -98,13 +137,7 @@ QDataStream &operator<<(QDataStream &ds,
const QQmlEngineDebugServiceImpl::QQmlObjectProperty &data)
{
ds << (int)data.type << data.name;
- // check first whether the data can be saved
- // (otherwise we assert in QVariant::operator<<)
- QQmlDebugPacket fakeStream;
- if (QMetaType::save(fakeStream, data.value.type(), data.value.constData()))
- ds << data.value;
- else
- ds << QVariant();
+ ds << (isSaveable(data.value) ? data.value : QVariant());
ds << data.valueTypeName << data.binding << data.hasNotifySignal;
return ds;
}
@@ -208,21 +241,40 @@ QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const
return contents;
}
- if (QQmlValueTypeFactory::isValueType(userType)) {
- const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(userType);
- if (mo) {
- int toStringIndex = mo->indexOfMethod("toString");
- if (toStringIndex != -1) {
- QMetaMethod mm = mo->method(toStringIndex);
- QMetaType info(userType);
- QString s;
- if (info.flags() & QMetaType::IsGadget
- && mm.invokeOnGadget(value.data(), Q_RETURN_ARG(QString, s)))
- return s;
+ switch (userType) {
+ case QMetaType::QRect:
+ case QMetaType::QRectF:
+ case QMetaType::QPoint:
+ case QMetaType::QPointF:
+ case QMetaType::QSize:
+ case QMetaType::QSizeF:
+ case QMetaType::QFont:
+ // Don't call the toString() method on those. The stream operators are better.
+ return value;
+ case QMetaType::QJsonValue:
+ return value.toJsonValue().toVariant();
+ case QMetaType::QJsonObject:
+ return value.toJsonObject().toVariantMap();
+ case QMetaType::QJsonArray:
+ return value.toJsonArray().toVariantList();
+ case QMetaType::QJsonDocument:
+ return value.toJsonDocument().toVariant();
+ default:
+ if (QQmlValueTypeFactory::isValueType(userType)) {
+ const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(userType);
+ if (mo) {
+ int toStringIndex = mo->indexOfMethod("toString()");
+ if (toStringIndex != -1) {
+ QMetaMethod mm = mo->method(toStringIndex);
+ QString s;
+ if (mm.invokeOnGadget(value.data(), Q_RETURN_ARG(QString, s)))
+ return s;
+ }
}
- }
- return value;
+ if (isSaveable(value))
+ return value;
+ }
}
if (QQmlMetaType::isQObject(userType)) {
@@ -337,6 +389,9 @@ void QQmlEngineDebugServiceImpl::buildObjectList(QDataStream &message,
QQmlContext *ctxt,
const QList<QPointer<QObject> > &instances)
{
+ if (!ctxt->isValid())
+ return;
+
QQmlContextData *p = QQmlContextData::get(ctxt);
QString ctxtName = ctxt->objectName();
@@ -399,11 +454,8 @@ QQmlEngineDebugServiceImpl::objectData(QObject *object)
}
QQmlContext *context = qmlContext(object);
- if (context) {
- QQmlContextData *cdata = QQmlContextData::get(context);
- if (cdata)
- rv.idString = cdata->findObjectId(object);
- }
+ if (context && context->isValid())
+ rv.idString = QQmlContextData::get(context)->findObjectId(object);
rv.objectName = object->objectName();
rv.objectId = QQmlDebugService::idForObject(object);
@@ -564,14 +616,14 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
QObject *object = QQmlDebugService::objectForId(objectId);
QQmlContext *context = qmlContext(object);
- if (!context) {
+ if (!context || !context->isValid()) {
QQmlEngine *engine = qobject_cast<QQmlEngine *>(
QQmlDebugService::objectForId(engineId));
if (engine && m_engines.contains(engine))
context = engine->rootContext();
}
QVariant result;
- if (context) {
+ if (context && context->isValid()) {
QQmlExpression exprObj(context, object, expr);
bool undefined = false;
QVariant value = exprObj.evaluate(&undefined);
@@ -632,7 +684,7 @@ bool QQmlEngineDebugServiceImpl::setBinding(int objectId,
QObject *object = objectForId(objectId);
QQmlContext *context = qmlContext(object);
- if (object && context) {
+ if (object && context && context->isValid()) {
QQmlProperty property(object, propertyName, context);
if (property.isValid()) {
@@ -677,7 +729,7 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope
QObject *object = objectForId(objectId);
QQmlContext *context = qmlContext(object);
- if (object && context) {
+ if (object && context && context->isValid()) {
QStringRef parentPropertyRef(&propertyName);
const int idx = parentPropertyRef.indexOf(QLatin1Char('.'));
if (idx != -1)
@@ -695,8 +747,9 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope
property.reset();
} else {
// overwrite with default value
- if (QQmlType *objType = QQmlMetaType::qmlType(object->metaObject())) {
- if (QObject *emptyObject = objType->create()) {
+ QQmlType objType = QQmlMetaType::qmlType(object->metaObject());
+ if (objType.isValid()) {
+ if (QObject *emptyObject = objType.create()) {
if (emptyObject->property(parentProperty).isValid()) {
QVariant defaultValue = QQmlProperty(emptyObject, propertyName).read();
if (defaultValue.isValid()) {
@@ -712,7 +765,7 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope
if (hasValidSignal(object, propertyName)) {
QQmlProperty property(object, propertyName, context);
- QQmlPropertyPrivate::setSignalExpression(property, 0);
+ QQmlPropertyPrivate::setSignalExpression(property, nullptr);
return true;
}
@@ -731,11 +784,9 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth
{
QObject *object = objectForId(objectId);
QQmlContext *context = qmlContext(object);
- if (!object || !context || !context->engine())
+ if (!object || !context || !context->isValid())
return false;
QQmlContextData *contextData = QQmlContextData::get(context);
- if (!contextData)
- return false;
QQmlPropertyData dummy;
QQmlPropertyData *prop =
@@ -759,7 +810,7 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth
QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(qmlEngine(object)->handle());
+ QV4::ExecutionEngine *v4 = qmlEngine(object)->handle();
QV4::Scope scope(v4);
int lineNumber = 0;
@@ -800,7 +851,8 @@ void QQmlEngineDebugServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
void QQmlEngineDebugServiceImpl::objectCreated(QJSEngine *engine, QObject *object)
{
Q_ASSERT(engine);
- Q_ASSERT(m_engines.contains(engine));
+ if (!m_engines.contains(engine))
+ return;
int engineId = QQmlDebugService::idForObject(engine);
int objectId = QQmlDebugService::idForObject(object);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
index 2e40eb4de8..c0c24058eb 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
@@ -95,17 +95,17 @@ public:
bool hasNotifySignal;
};
- void engineAboutToBeAdded(QJSEngine *) Q_DECL_OVERRIDE;
- void engineAboutToBeRemoved(QJSEngine *) Q_DECL_OVERRIDE;
- void objectCreated(QJSEngine *, QObject *) Q_DECL_OVERRIDE;
+ void engineAboutToBeAdded(QJSEngine *) override;
+ void engineAboutToBeRemoved(QJSEngine *) override;
+ void objectCreated(QJSEngine *, QObject *) override;
- void setStatesDelegate(QQmlDebugStatesDelegate *) Q_DECL_OVERRIDE;
+ void setStatesDelegate(QQmlDebugStatesDelegate *) override;
signals:
void scheduleMessage(const QByteArray &);
protected:
- virtual void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
+ void messageReceived(const QByteArray &) override;
private:
friend class QQmlDebuggerServiceFactory;
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
index cbbbb2ceb7..86571e6cbe 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
@@ -61,12 +61,12 @@ public:
QObject *object,
int debugId,
const QMetaProperty &prop,
- QQmlWatcher *parent = 0);
+ QQmlWatcher *parent = nullptr);
QQmlWatchProxy(int id,
QQmlExpression *exp,
int debugId,
- QQmlWatcher *parent = 0);
+ QQmlWatcher *parent = nullptr);
public slots:
void notifyValueChanged(); // Needs to be a slot because of QQmlPropertyPrivate::connect()
@@ -86,7 +86,7 @@ QQmlWatchProxy::QQmlWatchProxy(int id,
QQmlExpression *exp,
int debugId,
QQmlWatcher *parent)
-: QObject(parent), m_id(id), m_watch(parent), m_object(0), m_debugId(debugId), m_expr(exp)
+: QObject(parent), m_id(id), m_watch(parent), m_object(nullptr), m_debugId(debugId), m_expr(exp)
{
QObject::connect(m_expr, &QQmlExpression::valueChanged,
this, &QQmlWatchProxy::notifyValueChanged);
@@ -97,7 +97,7 @@ QQmlWatchProxy::QQmlWatchProxy(int id,
int debugId,
const QMetaProperty &prop,
QQmlWatcher *parent)
-: QObject(parent), m_id(id), m_watch(parent), m_object(object), m_debugId(debugId), m_property(prop), m_expr(0)
+: QObject(parent), m_id(id), m_watch(parent), m_object(object), m_debugId(debugId), m_property(prop), m_expr(nullptr)
{
static int refreshIdx = -1;
if(refreshIdx == -1)
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
index e89b7a63d4..506ecb64bb 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -46,6 +46,7 @@
#include <private/qv4objectiterator_p.h>
#include <private/qv4identifier_p.h>
#include <private/qv4runtime_p.h>
+#include <private/qv4identifiertable_p.h>
#include <private/qqmlcontext_p.h>
#include <private/qqmlengine_p.h>
@@ -55,47 +56,39 @@
QT_BEGIN_NAMESPACE
-QV4::SimpleCallContext *QV4DataCollector::findContext(int frame)
+QV4::CppStackFrame *QV4DataCollector::findFrame(int frame)
{
- QV4::ExecutionContext *ctx = engine()->currentContext;
- while (ctx) {
- QV4::SimpleCallContext *cCtxt = ctx->asSimpleCallContext();
- if (cCtxt && cCtxt->d()->v4Function) {
- if (frame < 1)
- return cCtxt;
- --frame;
- }
- ctx = engine()->parentContext(ctx);
+ QV4::CppStackFrame *f = engine()->currentStackFrame;
+ while (f && frame) {
+ --frame;
+ f = f->parent;
}
-
- return 0;
+ return f;
}
-QV4::Heap::SimpleCallContext *QV4DataCollector::findScope(QV4::ExecutionContext *ctxt, int scope)
+QV4::Heap::ExecutionContext *QV4DataCollector::findContext(int frame)
{
- if (!ctxt)
- return 0;
+ QV4::CppStackFrame *f = findFrame(frame);
- QV4::Scope s(ctxt);
- QV4::ScopedContext ctx(s, ctxt);
+ return f ? f->context()->d() : nullptr;
+}
+
+QV4::Heap::ExecutionContext *QV4DataCollector::findScope(QV4::Heap::ExecutionContext *ctx, int scope)
+{
for (; scope > 0 && ctx; --scope)
- ctx = ctx->d()->outer;
+ ctx = ctx->outer;
- return (ctx && ctx->d()) ? ctx->asSimpleCallContext()->d() : 0;
+ return ctx;
}
QVector<QV4::Heap::ExecutionContext::ContextType> QV4DataCollector::getScopeTypes(int frame)
{
QVector<QV4::Heap::ExecutionContext::ContextType> types;
- QV4::Scope scope(engine());
- QV4::SimpleCallContext *sctxt = findContext(frame);
- if (!sctxt || sctxt->d()->type < QV4::Heap::ExecutionContext::Type_QmlContext)
- return types;
+ QV4::Heap::ExecutionContext *it = findFrame(frame)->context()->d();
- QV4::ScopedContext it(scope, sctxt);
- for (; it; it = it->d()->outer)
- types.append(QV4::Heap::ExecutionContext::ContextType(it->d()->type));
+ for (; it; it = it->outer)
+ types.append(QV4::Heap::ExecutionContext::ContextType(it->type));
return types;
}
@@ -104,58 +97,51 @@ int QV4DataCollector::encodeScopeType(QV4::Heap::ExecutionContext::ContextType s
{
switch (scopeType) {
case QV4::Heap::ExecutionContext::Type_GlobalContext:
- return 0;
- case QV4::Heap::ExecutionContext::Type_CatchContext:
- return 4;
+ break;
case QV4::Heap::ExecutionContext::Type_WithContext:
return 2;
- case QV4::Heap::ExecutionContext::Type_SimpleCallContext:
case QV4::Heap::ExecutionContext::Type_CallContext:
return 1;
case QV4::Heap::ExecutionContext::Type_QmlContext:
- default:
- return -1;
+ return 3;
+ case QV4::Heap::ExecutionContext::Type_BlockContext:
+ return 4;
}
+ return 0;
}
QV4DataCollector::QV4DataCollector(QV4::ExecutionEngine *engine)
- : m_engine(engine), m_namesAsObjects(true), m_redundantRefs(true)
+ : m_engine(engine)
{
m_values.set(engine, engine->newArrayObject());
}
-// TODO: Directly call addRef() once we don't need to support redundantRefs anymore
-QV4DataCollector::Ref QV4DataCollector::collect(const QV4::ScopedValue &value)
+QV4DataCollector::Ref QV4DataCollector::addValueRef(const QV4::ScopedValue &value)
{
- Ref ref = addRef(value);
- if (m_redundantRefs)
- m_collectedRefs.append(ref);
- return ref;
+ return addRef(value);
}
const QV4::Object *collectProperty(const QV4::ScopedValue &value, QV4::ExecutionEngine *engine,
QJsonObject &dict)
{
QV4::Scope scope(engine);
- QV4::ScopedValue typeString(scope, QV4::Runtime::method_typeofValue(engine, value));
+ QV4::ScopedValue typeString(scope, QV4::Runtime::TypeofValue::call(engine, value));
dict.insert(QStringLiteral("type"), typeString->toQStringNoThrow());
const QLatin1String valueKey("value");
switch (value->type()) {
case QV4::Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
- return 0;
+ return nullptr;
case QV4::Value::Undefined_Type:
dict.insert(valueKey, QJsonValue::Undefined);
- return 0;
+ return nullptr;
case QV4::Value::Null_Type:
- // "null" is not the correct type, but we leave this in until QtC can deal with "object"
- dict.insert(QStringLiteral("type"), QStringLiteral("null"));
dict.insert(valueKey, QJsonValue::Null);
- return 0;
+ return nullptr;
case QV4::Value::Boolean_Type:
dict.insert(valueKey, value->booleanValue());
- return 0;
+ return nullptr;
case QV4::Value::Managed_Type:
if (const QV4::String *s = value->as<QV4::String>()) {
dict.insert(valueKey, s->toQString());
@@ -168,25 +154,22 @@ const QV4::Object *collectProperty(const QV4::ScopedValue &value, QV4::Execution
int numProperties = 0;
QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
QV4::PropertyAttributes attrs;
- uint index;
- QV4::ScopedProperty p(scope);
- QV4::ScopedString name(scope);
+ QV4::ScopedPropertyKey name(scope);
while (true) {
- it.next(name.getRef(), &index, p, &attrs);
- if (attrs.isEmpty())
+ name = it.next(nullptr, &attrs);
+ if (!name->isValid())
break;
- else
- ++numProperties;
+ ++numProperties;
}
dict.insert(valueKey, numProperties);
return o;
} else {
Q_UNREACHABLE();
}
- return 0;
+ return nullptr;
case QV4::Value::Integer_Type:
dict.insert(valueKey, value->integerValue());
- return 0;
+ return nullptr;
default: {// double
const double val = value->doubleValue();
if (qIsFinite(val))
@@ -197,66 +180,26 @@ const QV4::Object *collectProperty(const QV4::ScopedValue &value, QV4::Execution
dict.insert(valueKey, QStringLiteral("-Infinity"));
else
dict.insert(valueKey, QStringLiteral("Infinity"));
- return 0;
+ return nullptr;
}
}
}
-QJsonObject QV4DataCollector::lookupRef(Ref ref, bool deep)
+QJsonObject QV4DataCollector::lookupRef(Ref ref)
{
QJsonObject dict;
- if (m_namesAsObjects) {
- if (lookupSpecialRef(ref, &dict))
- return dict;
- }
-
- if (m_redundantRefs)
- deep = true;
-
dict.insert(QStringLiteral("handle"), qint64(ref));
QV4::Scope scope(engine());
QV4::ScopedValue value(scope, getValue(ref));
const QV4::Object *object = collectProperty(value, engine(), dict);
- if (deep && object)
+ if (object)
dict.insert(QStringLiteral("properties"), collectProperties(object));
return dict;
}
-// TODO: Drop this method once we don't need to support namesAsObjects anymore
-QV4DataCollector::Ref QV4DataCollector::addFunctionRef(const QString &functionName)
-{
- Q_ASSERT(m_namesAsObjects);
- Ref ref = addRef(QV4::Primitive::emptyValue(), false);
-
- QJsonObject dict;
- dict.insert(QStringLiteral("handle"), qint64(ref));
- dict.insert(QStringLiteral("type"), QStringLiteral("function"));
- dict.insert(QStringLiteral("name"), functionName);
- m_specialRefs.insert(ref, dict);
- m_collectedRefs.append(ref);
-
- return ref;
-}
-
-// TODO: Drop this method once we don't need to support namesAsObjects anymore
-QV4DataCollector::Ref QV4DataCollector::addScriptRef(const QString &scriptName)
-{
- Q_ASSERT(m_namesAsObjects);
- Ref ref = addRef(QV4::Primitive::emptyValue(), false);
-
- QJsonObject dict;
- dict.insert(QStringLiteral("handle"), qint64(ref));
- dict.insert(QStringLiteral("type"), QStringLiteral("script"));
- dict.insert(QStringLiteral("name"), scriptName);
- m_specialRefs.insert(ref, dict);
- m_collectedRefs.append(ref);
-
- return ref;
-}
-
bool QV4DataCollector::isValidRef(QV4DataCollector::Ref ref) const
{
QV4::Scope scope(engine());
@@ -266,50 +209,35 @@ bool QV4DataCollector::isValidRef(QV4DataCollector::Ref ref) const
bool QV4DataCollector::collectScope(QJsonObject *dict, int frameNr, int scopeNr)
{
- QStringList names;
-
QV4::Scope scope(engine());
- QV4::Scoped<QV4::CallContext> ctxt(scope, findScope(findContext(frameNr), scopeNr));
+
+ QV4::Scoped<QV4::ExecutionContext> ctxt(scope, findScope(findContext(frameNr), scopeNr));
if (!ctxt)
return false;
- Refs collectedRefs;
- QV4::ScopedValue v(scope);
- int nFormals = ctxt->formalCount();
- for (unsigned i = 0, ei = nFormals; i != ei; ++i) {
- QString qName;
- if (QV4::Identifier *name = ctxt->formals()[nFormals - i - 1])
- qName = name->string;
- names.append(qName);
- v = ctxt->argument(i);
- collectedRefs.append(collect(v));
- }
-
- for (unsigned i = 0, ei = ctxt->variableCount(); i != ei; ++i) {
- QString qName;
- if (QV4::Identifier *name = ctxt->variables()[i])
- qName = name->string;
- names.append(qName);
- v = ctxt->d()->locals[i];
- collectedRefs.append(collect(v));
- }
-
QV4::ScopedObject scopeObject(scope, engine()->newObject());
+ if (ctxt->d()->type == QV4::Heap::ExecutionContext::Type_CallContext) {
+ QStringList names;
+ Refs collectedRefs;
+
+ QV4::ScopedValue v(scope);
+ QV4::Heap::InternalClass *ic = ctxt->internalClass();
+ for (uint i = 0; i < ic->size; ++i) {
+ QString name = ic->keyAt(i);
+ names.append(name);
+ v = static_cast<QV4::Heap::CallContext *>(ctxt->d())->locals[i];
+ collectedRefs.append(addValueRef(v));
+ }
- Q_ASSERT(names.size() == collectedRefs.size());
- QV4::ScopedString propName(scope);
- for (int i = 0, ei = collectedRefs.size(); i != ei; ++i) {
- propName = engine()->newString(names.at(i));
- scopeObject->put(propName, QV4::Value::fromReturnedValue(getValue(collectedRefs.at(i))));
+ Q_ASSERT(names.size() == collectedRefs.size());
+ QV4::ScopedString propName(scope);
+ for (int i = 0, ei = collectedRefs.size(); i != ei; ++i) {
+ propName = engine()->newString(names.at(i));
+ scopeObject->put(propName, (v = getValue(collectedRefs.at(i))));
+ }
}
- Ref scopeObjectRef = addRef(scopeObject);
- if (m_redundantRefs) {
- dict->insert(QStringLiteral("ref"), qint64(scopeObjectRef));
- m_collectedRefs.append(scopeObjectRef);
- } else {
- *dict = lookupRef(scopeObjectRef, true);
- }
+ *dict = lookupRef(addRef(scopeObject));
return true;
}
@@ -325,13 +253,8 @@ QJsonObject QV4DataCollector::buildFrame(const QV4::StackFrame &stackFrame, int
QJsonObject frame;
frame[QLatin1String("index")] = frameNr;
frame[QLatin1String("debuggerFrame")] = false;
- if (m_namesAsObjects) {
- frame[QLatin1String("func")] = toRef(addFunctionRef(stackFrame.function));
- frame[QLatin1String("script")] = toRef(addScriptRef(stackFrame.source));
- } else {
- frame[QLatin1String("func")] = stackFrame.function;
- frame[QLatin1String("script")] = stackFrame.source;
- }
+ frame[QLatin1String("func")] = stackFrame.function;
+ frame[QLatin1String("script")] = stackFrame.source;
frame[QLatin1String("line")] = stackFrame.line - 1;
if (stackFrame.column >= 0)
frame[QLatin1String("column")] = stackFrame.column;
@@ -340,7 +263,7 @@ QJsonObject QV4DataCollector::buildFrame(const QV4::StackFrame &stackFrame, int
QV4::Scope scope(engine());
QV4::ScopedContext ctxt(scope, findContext(frameNr));
while (ctxt) {
- if (QV4::SimpleCallContext *cCtxt = ctxt->asSimpleCallContext()) {
+ if (QV4::CallContext *cCtxt = ctxt->asCallContext()) {
if (cCtxt->d()->activation)
break;
}
@@ -348,8 +271,8 @@ QJsonObject QV4DataCollector::buildFrame(const QV4::StackFrame &stackFrame, int
}
if (ctxt) {
- QV4::ScopedValue o(scope, ctxt->asSimpleCallContext()->d()->activation);
- frame[QLatin1String("receiver")] = toRef(collect(o));
+ QV4::ScopedValue o(scope, ctxt->d()->activation);
+ frame[QLatin1String("receiver")] = toRef(addValueRef(o));
}
// Only type and index are used by Qt Creator, so we keep it easy:
@@ -370,30 +293,9 @@ QJsonObject QV4DataCollector::buildFrame(const QV4::StackFrame &stackFrame, int
return frame;
}
-// TODO: Drop this method once we don't need to support redundantRefs anymore
-QJsonArray QV4DataCollector::flushCollectedRefs()
-{
- Q_ASSERT(m_redundantRefs);
- QJsonArray refs;
- std::sort(m_collectedRefs.begin(), m_collectedRefs.end());
- for (int i = 0, ei = m_collectedRefs.size(); i != ei; ++i) {
- QV4DataCollector::Ref ref = m_collectedRefs.at(i);
- if (i > 0 && ref == m_collectedRefs.at(i - 1))
- continue;
- refs.append(lookupRef(ref, true));
- }
-
- m_collectedRefs.clear();
- return refs;
-}
-
void QV4DataCollector::clear()
{
m_values.set(engine(), engine()->newArrayObject());
- m_collectedRefs.clear();
- m_specialRefs.clear();
- m_namesAsObjects = true;
- m_redundantRefs = true;
}
QV4DataCollector::Ref QV4DataCollector::addRef(QV4::Value value, bool deduplicate)
@@ -413,18 +315,18 @@ QV4DataCollector::Ref QV4DataCollector::addRef(QV4::Value value, bool deduplicat
{ std::swap(*hasExceptionLoc, hadException); }
};
- // if we wouldn't do this, the putIndexed won't work.
+ // if we wouldn't do this, the put won't work.
ExceptionStateSaver resetExceptionState(engine());
QV4::Scope scope(engine());
QV4::ScopedObject array(scope, m_values.value());
if (deduplicate) {
for (Ref i = 0; i < array->getLength(); ++i) {
- if (array->getIndexed(i) == value.rawValue() && !m_specialRefs.contains(i))
+ if (array->get(i) == value.rawValue())
return i;
}
}
Ref ref = array->getLength();
- array->putIndexed(ref, value);
+ array->put(ref, value);
Q_ASSERT(array->getLength() - 1 == ref);
return ref;
}
@@ -434,23 +336,39 @@ QV4::ReturnedValue QV4DataCollector::getValue(Ref ref)
QV4::Scope scope(engine());
QV4::ScopedObject array(scope, m_values.value());
Q_ASSERT(ref < array->getLength());
- return array->getIndexed(ref, Q_NULLPTR);
+ return array->get(ref, nullptr);
}
-// TODO: Drop this method once we don't need to support namesAsObjects anymore
-bool QV4DataCollector::lookupSpecialRef(Ref ref, QJsonObject *dict)
+class CapturePreventer
{
- Q_ASSERT(m_namesAsObjects);
- SpecialRefs::const_iterator it = m_specialRefs.constFind(ref);
- if (it == m_specialRefs.cend())
- return false;
+public:
+ CapturePreventer(QV4::ExecutionEngine *engine)
+ {
+ if (QQmlEngine *e = engine->qmlEngine()) {
+ m_engine = QQmlEnginePrivate::get(e);
+ m_capture = m_engine->propertyCapture;
+ m_engine->propertyCapture = nullptr;
+ }
+ }
- *dict = it.value();
- return true;
-}
+ ~CapturePreventer()
+ {
+ if (m_engine && m_capture) {
+ Q_ASSERT(!m_engine->propertyCapture);
+ m_engine->propertyCapture = m_capture;
+ }
+ }
+
+private:
+ QQmlEnginePrivate *m_engine = nullptr;
+ QQmlPropertyCapture *m_capture = nullptr;
+};
QJsonArray QV4DataCollector::collectProperties(const QV4::Object *object)
{
+ CapturePreventer capturePreventer(engine());
+ Q_UNUSED(capturePreventer);
+
QJsonArray res;
QV4::Scope scope(engine());
@@ -478,8 +396,6 @@ QJsonObject QV4DataCollector::collectAsJson(const QString &name, const QV4::Scop
if (value->isManaged() && !value->isString()) {
Ref ref = addRef(value);
dict.insert(QStringLiteral("ref"), qint64(ref));
- if (m_redundantRefs)
- m_collectedRefs.append(ref);
}
collectProperty(value, engine(), dict);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
index de12e8d527..bc178fa2db 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
@@ -58,50 +58,36 @@ public:
typedef uint Ref;
typedef QVector<uint> Refs;
- static QV4::Heap::SimpleCallContext *findScope(QV4::ExecutionContext *ctxt, int scope);
+ static QV4::Heap::ExecutionContext *findScope(QV4::Heap::ExecutionContext *ctxt, int scope);
static int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType);
QVector<QV4::Heap::ExecutionContext::ContextType> getScopeTypes(int frame);
- QV4::SimpleCallContext *findContext(int frame);
+ QV4::Heap::ExecutionContext *findContext(int frame);
+ QV4::CppStackFrame *findFrame(int frame);
QV4DataCollector(QV4::ExecutionEngine *engine);
- Ref collect(const QV4::ScopedValue &value); // only for redundantRefs
- Ref addFunctionRef(const QString &functionName); // only for namesAsObjects
- Ref addScriptRef(const QString &scriptName); // only for namesAsObjects
-
- void setNamesAsObjects(bool namesAsObjects) { m_namesAsObjects = namesAsObjects; }
- bool namesAsObjects() const { return m_namesAsObjects; }
-
- void setRedundantRefs(bool redundantRefs) { m_redundantRefs = redundantRefs; }
- bool redundantRefs() const { return m_redundantRefs; }
+ Ref addValueRef(const QV4::ScopedValue &value);
bool isValidRef(Ref ref) const;
- QJsonObject lookupRef(Ref ref, bool deep);
+ QJsonObject lookupRef(Ref ref);
bool collectScope(QJsonObject *dict, int frameNr, int scopeNr);
QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr);
QV4::ExecutionEngine *engine() const { return m_engine; }
- QJsonArray flushCollectedRefs(); // only for redundantRefs
void clear();
private:
Ref addRef(QV4::Value value, bool deduplicate = true);
QV4::ReturnedValue getValue(Ref ref);
- bool lookupSpecialRef(Ref ref, QJsonObject *dict); // only for namesAsObjects
QJsonArray collectProperties(const QV4::Object *object);
QJsonObject collectAsJson(const QString &name, const QV4::ScopedValue &value);
void collectArgumentsInContext();
QV4::ExecutionEngine *m_engine;
- Refs m_collectedRefs; // only for redundantRefs
QV4::PersistentValue m_values;
- typedef QHash<Ref, QJsonObject> SpecialRefs; // only for namesAsObjects
- SpecialRefs m_specialRefs; // only for namesAsObjects
- bool m_namesAsObjects;
- bool m_redundantRefs;
};
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
index b82df9c6a9..5521e7628b 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
@@ -70,9 +70,9 @@ QV4Debugger::QV4Debugger(QV4::ExecutionEngine *engine)
, m_pauseRequested(false)
, m_haveBreakPoints(false)
, m_breakOnThrow(false)
- , m_returnedValue(engine, QV4::Primitive::undefinedValue())
- , m_gatherSources(0)
- , m_runningJob(0)
+ , m_returnedValue(engine, QV4::Value::undefinedValue())
+ , m_gatherSources(nullptr)
+ , m_runningJob(nullptr)
, m_collector(engine)
{
static int debuggerId = qRegisterMetaType<QV4Debugger*>();
@@ -115,7 +115,7 @@ void QV4Debugger::resume(Speed speed)
if (!m_returnedValue.isUndefined())
m_returnedValue.set(m_engine, QV4::Encode::undefined());
- m_currentContext.set(m_engine, *m_engine->currentContext);
+ m_currentFrame = m_engine->currentStackFrame;
m_stepping = speed;
m_runningCondition.wakeAll();
}
@@ -157,8 +157,8 @@ void QV4Debugger::clearPauseRequest()
QV4Debugger::ExecutionState QV4Debugger::currentExecutionState() const
{
ExecutionState state;
- state.fileName = getFunction()->sourceFile();
- state.lineNumber = engine()->current->lineNumber;
+ state.fileName = QUrl(getFunction()->sourceFile()).fileName();
+ state.lineNumber = engine()->currentStackFrame->lineNumber();
return state;
}
@@ -182,14 +182,14 @@ void QV4Debugger::maybeBreakAtInstruction()
if (m_gatherSources) {
m_gatherSources->run();
delete m_gatherSources;
- m_gatherSources = 0;
+ m_gatherSources = nullptr;
}
switch (m_stepping) {
case StepOver:
- if (m_currentContext.asManaged()->d() != m_engine->current)
+ if (m_currentFrame != m_engine->currentStackFrame)
break;
- // fall through
+ Q_FALLTHROUGH();
case StepIn:
pauseAndWait(Step);
return;
@@ -203,7 +203,8 @@ void QV4Debugger::maybeBreakAtInstruction()
pauseAndWait(PauseRequest);
} else if (m_haveBreakPoints) {
if (QV4::Function *f = getFunction()) {
- const int lineNumber = engine()->current->lineNumber;
+ // lineNumber will be negative for Ret instructions, so those won't match
+ const int lineNumber = engine()->currentStackFrame->lineNumber();
if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber))
pauseAndWait(BreakPointHit);
}
@@ -216,9 +217,8 @@ void QV4Debugger::enteringFunction()
return;
QMutexLocker locker(&m_lock);
- if (m_stepping == StepIn) {
- m_currentContext.set(m_engine, *m_engine->currentContext);
- }
+ if (m_stepping == StepIn)
+ m_currentFrame = m_engine->currentStackFrame;
}
void QV4Debugger::leavingFunction(const QV4::ReturnedValue &retVal)
@@ -229,13 +229,8 @@ void QV4Debugger::leavingFunction(const QV4::ReturnedValue &retVal)
QMutexLocker locker(&m_lock);
- if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->current) {
- if (QV4::ExecutionContext *parentContext
- = m_engine->parentContext(m_engine->currentContext)) {
- m_currentContext.set(m_engine, *parentContext);
- } else {
- m_currentContext.clear();
- }
+ if (m_stepping != NotStepping && m_currentFrame == m_engine->currentStackFrame) {
+ m_currentFrame = m_currentFrame->parent;
m_stepping = StepOver;
m_returnedValue.set(m_engine, retVal);
}
@@ -255,10 +250,8 @@ void QV4Debugger::aboutToThrow()
QV4::Function *QV4Debugger::getFunction() const
{
- QV4::Scope scope(m_engine);
- QV4::ExecutionContext *context = m_engine->currentContext;
- if (QV4::Function *function = context->getFunction())
- return function;
+ if (m_engine->currentStackFrame)
+ return m_engine->currentStackFrame->v4Function;
else
return m_engine->globalCode;
}
@@ -295,18 +288,18 @@ void QV4Debugger::pauseAndWait(PauseReason reason)
bool QV4Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
{
QHash<BreakPoint, QString>::iterator it = m_breakPoints.find(
- BreakPoint(filename.mid(filename.lastIndexOf('/') + 1), linenr));
+ BreakPoint(QUrl(filename).fileName(), linenr));
if (it == m_breakPoints.end())
return false;
QString condition = it.value();
if (condition.isEmpty())
return true;
- Q_ASSERT(m_runningJob == 0);
+ Q_ASSERT(m_runningJob == nullptr);
EvalJob evilJob(m_engine, condition);
m_runningJob = &evilJob;
m_runningJob->run();
- m_runningJob = 0;
+ m_runningJob = nullptr;
return evilJob.resultAsBoolean();
}
@@ -320,7 +313,7 @@ void QV4Debugger::runInEngine(QV4DebugJob *job)
void QV4Debugger::runInEngine_havingLock(QV4DebugJob *job)
{
Q_ASSERT(job);
- Q_ASSERT(m_runningJob == 0);
+ Q_ASSERT(m_runningJob == nullptr);
m_runningJob = job;
if (state() == Paused)
@@ -328,7 +321,7 @@ void QV4Debugger::runInEngine_havingLock(QV4DebugJob *job)
else
emit scheduleJob();
m_jobIsRunning.wait(&m_lock);
- m_runningJob = 0;
+ m_runningJob = nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h
index cd412e573d..4a755f2b72 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h
@@ -129,14 +129,14 @@ public:
void runInEngine(QV4DebugJob *job);
// compile-time interface
- void maybeBreakAtInstruction() Q_DECL_OVERRIDE;
+ void maybeBreakAtInstruction() override;
// execution hooks
- void enteringFunction() Q_DECL_OVERRIDE;
- void leavingFunction(const QV4::ReturnedValue &retVal) Q_DECL_OVERRIDE;
- void aboutToThrow() Q_DECL_OVERRIDE;
+ void enteringFunction() override;
+ void leavingFunction(const QV4::ReturnedValue &retVal) override;
+ void aboutToThrow() override;
- bool pauseAtNextOpportunity() const Q_DECL_OVERRIDE;
+ bool pauseAtNextOpportunity() const override;
signals:
void debuggerPaused(QV4Debugger *self, QV4Debugger::PauseReason reason);
@@ -150,7 +150,7 @@ private:
void runJobUnpaused();
QV4::ExecutionEngine *m_engine;
- QV4::PersistentValue m_currentContext;
+ QV4::CppStackFrame *m_currentFrame = 0;
QMutex m_lock;
QWaitCondition m_runningCondition;
State m_state;
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
index 9a34d5770a..71645579c5 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
@@ -56,13 +56,13 @@ QV4Debugger *QV4DebuggerAgent::pausedDebugger() const
if (debugger->state() == QV4Debugger::Paused)
return debugger;
}
- return 0;
+ return nullptr;
}
bool QV4DebuggerAgent::isRunning() const
{
// "running" means none of the engines are paused.
- return pausedDebugger() == 0;
+ return pausedDebugger() == nullptr;
}
void QV4DebuggerAgent::debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseReason reason)
@@ -79,20 +79,19 @@ void QV4DebuggerAgent::debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseR
case QV4Debugger::PauseRequest:
case QV4Debugger::BreakPointHit: {
event.insert(QStringLiteral("event"), QStringLiteral("break"));
- QVector<QV4::StackFrame> frames = debugger->stackTrace(1);
- if (frames.isEmpty())
+ QV4::CppStackFrame *frame = debugger->engine()->currentStackFrame;
+ if (!frame)
break;
- const QV4::StackFrame &topFrame = frames.first();
- body.insert(QStringLiteral("invocationText"), topFrame.function);
- body.insert(QStringLiteral("sourceLine"), topFrame.line - 1);
- if (topFrame.column > 0)
- body.insert(QStringLiteral("sourceColumn"), topFrame.column);
+ body.insert(QStringLiteral("invocationText"), frame->function());
+ body.insert(QStringLiteral("sourceLine"), qAbs(frame->lineNumber()) - 1);
+// if (frame->column > 0)
+// body.insert(QStringLiteral("sourceColumn"), frame->column);
QJsonArray breakPoints;
- foreach (int breakPointId, breakPointIds(topFrame.source, topFrame.line))
+ foreach (int breakPointId, breakPointIds(frame->source(), frame->lineNumber()))
breakPoints.push_back(breakPointId);
body.insert(QStringLiteral("breakpoints"), breakPoints);
- script.insert(QStringLiteral("name"), topFrame.source);
+ script.insert(QStringLiteral("name"), frame->source());
} break;
case QV4Debugger::Throwing:
// TODO: complete this!
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
index 107ec60943..b424ef9f6c 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
@@ -44,6 +44,7 @@
#include <private/qv4qmlcontext_p.h>
#include <private/qv4qobjectwrapper_p.h>
#include <private/qqmldebugservice_p.h>
+#include <private/qv4jscall_p.h>
#include <QtQml/qqmlengine.h>
@@ -63,26 +64,21 @@ void JavaScriptJob::run()
{
QV4::Scope scope(engine);
- QV4::ExecutionContextSaver saver(scope);
-
- QV4::ExecutionContext *ctx = engine->currentContext;
+ QV4::ScopedContext ctx(scope, engine->currentStackFrame ? engine->currentContext()
+ : engine->scriptContext());
QObject scopeObject;
- if (frameNr > 0) {
- for (int i = 0; i < frameNr; ++i) {
- ctx = engine->parentContext(ctx);
- }
- engine->pushContext(ctx);
- ctx = engine->currentContext;
- }
+ QV4::CppStackFrame *frame = engine->currentStackFrame;
+
+ for (int i = 0; frame && i < frameNr; ++i)
+ frame = frame->parent;
+ if (frameNr > 0 && frame)
+ ctx = static_cast<QV4::ExecutionContext *>(&frame->jsFrame->context);
if (context >= 0) {
QQmlContext *extraContext = qmlContext(QQmlDebugService::objectForId(context));
- if (extraContext) {
- engine->pushContext(QV4::QmlContext::create(ctx, QQmlContextData::get(extraContext),
- &scopeObject));
- ctx = engine->currentContext;
- }
+ if (extraContext)
+ ctx = QV4::QmlContext::create(ctx, QQmlContextData::get(extraContext), &scopeObject);
} else if (frameNr < 0) { // Use QML context if available
QQmlEngine *qmlEngine = engine->qmlEngine();
if (qmlEngine) {
@@ -102,25 +98,28 @@ void JavaScriptJob::run()
}
}
}
- if (!engine->qmlContext()) {
- engine->pushContext(QV4::QmlContext::create(ctx, QQmlContextData::get(qmlRootContext),
- &scopeObject));
- ctx = engine->currentContext;
- }
- engine->pushContext(ctx->newWithContext(withContext->toObject(engine)));
- ctx = engine->currentContext;
+ if (!engine->qmlContext())
+ ctx = QV4::QmlContext::create(ctx, QQmlContextData::get(qmlRootContext), &scopeObject);
}
}
- QV4::Script script(ctx, this->script);
- script.strictMode = ctx->d()->strictMode;
+ QV4::Script script(ctx, QV4::Compiler::ContextType::Eval, this->script);
+ if (const QV4::Function *function = frame ? frame->v4Function : engine->globalCode)
+ script.strictMode = function->isStrict();
+
// In order for property lookups in QML to work, we need to disable fast v4 lookups. That
// is a side-effect of inheritContext.
script.inheritContext = true;
script.parse();
QV4::ScopedValue result(scope);
- if (!scope.engine->hasException)
- result = script.run();
+ if (!scope.engine->hasException) {
+ if (frame) {
+ QV4::ScopedValue thisObject(scope, frame->thisObject());
+ result = script.run(thisObject);
+ } else {
+ result = script.run();
+ }
+ }
if (scope.engine->hasException) {
result = scope.engine->catchException();
resultIsException = true;
@@ -151,7 +150,6 @@ void BacktraceJob::run()
result.insert(QStringLiteral("toFrame"), fromFrame + frameArray.size());
result.insert(QStringLiteral("frames"), frameArray);
}
- flushRedundantRefs();
}
FrameJob::FrameJob(QV4DataCollector *collector, int frameNr) :
@@ -166,7 +164,6 @@ void FrameJob::run()
success = false;
} else {
result = collector->buildFrame(frames[frameNr], frameNr);
- flushRedundantRefs();
success = true;
}
}
@@ -196,7 +193,6 @@ void ScopeJob::run()
result[QLatin1String("index")] = scopeNr;
result[QLatin1String("frameIndex")] = frameNr;
result[QLatin1String("object")] = object;
- flushRedundantRefs();
}
bool ScopeJob::wasSuccessful() const
@@ -214,23 +210,23 @@ void ValueLookupJob::run()
// set if the engine is currently executing QML code.
QScopedPointer<QObject> scopeObject;
QV4::ExecutionEngine *engine = collector->engine();
+ QV4::Scope scope(engine);
+ QV4::Heap::ExecutionContext *qmlContext = nullptr;
if (engine->qmlEngine() && !engine->qmlContext()) {
scopeObject.reset(new QObject);
- engine->pushContext(QV4::QmlContext::create(engine->currentContext,
+ qmlContext = QV4::QmlContext::create(engine->currentContext(),
QQmlContextData::get(engine->qmlEngine()->rootContext()),
- scopeObject.data()));
+ scopeObject.data());
}
+ QV4::ScopedStackFrame frame(scope, qmlContext);
for (const QJsonValue &handle : handles) {
QV4DataCollector::Ref ref = handle.toInt();
if (!collector->isValidRef(ref)) {
exception = QString::fromLatin1("Invalid Ref: %1").arg(ref);
break;
}
- result[QString::number(ref)] = collector->lookupRef(ref, true);
+ result[QString::number(ref)] = collector->lookupRef(ref);
}
- flushRedundantRefs();
- if (scopeObject)
- engine->popContext();
}
const QString &ValueLookupJob::exceptionMessage() const
@@ -249,9 +245,7 @@ void ExpressionEvalJob::handleResult(QV4::ScopedValue &value)
{
if (hasExeption())
exception = value->toQStringNoThrow();
- result = collector->lookupRef(collector->collect(value), true);
- if (collector->redundantRefs())
- collectedRefs = collector->flushCollectedRefs();
+ result = collector->lookupRef(collector->addValueRef(value));
}
const QString &ExpressionEvalJob::exceptionMessage() const
@@ -264,20 +258,13 @@ const QJsonObject &ExpressionEvalJob::returnValue() const
return result;
}
-// TODO: Drop this method once we don't need to support redundantRefs anymore
-const QJsonArray &ExpressionEvalJob::refs() const
-{
- Q_ASSERT(collector->redundantRefs());
- return collectedRefs;
-}
-
GatherSourcesJob::GatherSourcesJob(QV4::ExecutionEngine *engine)
: engine(engine)
{}
void GatherSourcesJob::run()
{
- for (QV4::CompiledData::CompilationUnit *unit : qAsConst(engine->compilationUnits)) {
+ for (QV4::CompiledData::CompilationUnit *unit : engine->compilationUnits) {
QString fileName = unit->fileName();
if (!fileName.isEmpty())
sources.append(fileName);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.h
index eca8710e15..d1c7495863 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.h
@@ -78,24 +78,10 @@ class CollectJob : public QV4DebugJob
protected:
QV4DataCollector *collector;
QJsonObject result;
- QJsonArray collectedRefs; // only for redundantRefs
-
- void flushRedundantRefs()
- {
- if (collector->redundantRefs())
- collectedRefs = collector->flushCollectedRefs();
- }
public:
CollectJob(QV4DataCollector *collector) : collector(collector) {}
const QJsonObject &returnValue() const { return result; }
-
- // TODO: Drop this method once we don't need to support redundantRefs anymore
- const QJsonArray &refs() const
- {
- Q_ASSERT(collector->redundantRefs());
- return collectedRefs;
- }
};
class BacktraceJob: public CollectJob
@@ -146,7 +132,6 @@ class ExpressionEvalJob: public JavaScriptJob
QV4DataCollector *collector;
QString exception;
QJsonObject result;
- QJsonArray collectedRefs; // only for redundantRefs
public:
ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr, int context,
@@ -154,7 +139,6 @@ public:
void handleResult(QV4::ScopedValue &value) override;
const QString &exceptionMessage() const;
const QJsonObject &returnValue() const;
- const QJsonArray &refs() const; // only for redundantRefs
};
class GatherSourcesJob: public QV4DebugJob
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
index 168a08865c..5866163ca6 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
@@ -40,13 +40,12 @@
#include "qv4debugservice.h"
#include "qv4debugjob.h"
#include "qqmlengine.h"
-#include "qqmldebugpacket.h"
#include <private/qv4engine_p.h>
-#include <private/qv4isel_moth_p.h>
#include <private/qv4function_p.h>
#include <private/qqmldebugconnector_p.h>
#include <private/qv8engine_p.h>
+#include <private/qversionedpacket_p.h>
#include <QtCore/QJsonArray>
#include <QtCore/QJsonDocument>
@@ -68,19 +67,21 @@ const char *const V4_PAUSE = "interrupt";
QT_BEGIN_NAMESPACE
-class V8CommandHandler;
-class UnknownV8CommandHandler;
+class V4CommandHandler;
+class UnknownV4CommandHandler;
+
+using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>;
int QV4DebugServiceImpl::sequence = 0;
-class V8CommandHandler
+class V4CommandHandler
{
public:
- V8CommandHandler(const QString &command)
+ V4CommandHandler(const QString &command)
: cmd(command)
{}
- virtual ~V8CommandHandler()
+ virtual ~V4CommandHandler()
{}
QString command() const { return cmd; }
@@ -99,7 +100,7 @@ public:
debugService->send(response);
}
- debugService = 0;
+ debugService = nullptr;
seq = QJsonValue();
req = QJsonObject();
response = QJsonObject();
@@ -121,21 +122,6 @@ protected:
response.insert(QStringLiteral("running"), debugService->debuggerAgent.isRunning());
}
- QV4DataCollector *saneCollector(QV4Debugger *debugger)
- {
- QV4DataCollector *collector = debugger->collector();
- collector->setNamesAsObjects(debugService->clientRequiresNamesAsObjects());
- collector->setRedundantRefs(debugService->clientRequiresRedundantRefs());
- return collector;
- }
-
- // TODO: drop this method once we don't need to support redundantRefs anymore.
- void addRefs(const QJsonArray &refs)
- {
- Q_ASSERT(debugService->clientRequiresRedundantRefs());
- response.insert(QStringLiteral("refs"), refs);
- }
-
void createErrorResponse(const QString &msg)
{
QJsonValue command = req.value(QLatin1String("command"));
@@ -157,10 +143,10 @@ protected:
QJsonObject response;
};
-class UnknownV8CommandHandler: public V8CommandHandler
+class UnknownV4CommandHandler: public V4CommandHandler
{
public:
- UnknownV8CommandHandler(): V8CommandHandler(QString()) {}
+ UnknownV4CommandHandler(): V4CommandHandler(QString()) {}
void handleRequest() override
{
@@ -172,10 +158,10 @@ public:
};
namespace {
-class V8VersionRequest: public V8CommandHandler
+class V4VersionRequest: public V4CommandHandler
{
public:
- V8VersionRequest(): V8CommandHandler(QStringLiteral("version")) {}
+ V4VersionRequest(): V4CommandHandler(QStringLiteral("version")) {}
void handleRequest() override
{
@@ -188,98 +174,137 @@ public:
QLatin1String("this is not V8, this is V4 in Qt " QT_VERSION_STR));
body.insert(QStringLiteral("UnpausedEvaluate"), true);
body.insert(QStringLiteral("ContextEvaluate"), true);
+ body.insert(QStringLiteral("ChangeBreakpoint"), true);
addBody(body);
}
};
-class V8SetBreakPointRequest: public V8CommandHandler
+class V4BreakPointRequest: public V4CommandHandler
{
public:
- V8SetBreakPointRequest(): V8CommandHandler(QStringLiteral("setbreakpoint")) {}
+ V4BreakPointRequest(const QString &name): V4CommandHandler(name) {}
- void handleRequest() override
+ void handleRequest() final
{
+ // Other types are currently not supported
+ m_type = QStringLiteral("scriptRegExp");
+
// decypher the payload:
- QJsonObject args = req.value(QLatin1String("arguments")).toObject();
- if (args.isEmpty())
+ m_args = req.value(QLatin1String("arguments")).toObject();
+ if (m_args.isEmpty()) {
+ createErrorResponse(QStringLiteral("breakpoint request with empty arguments object"));
return;
+ }
+
+ const int id = handleBreakPointRequest();
+ if (id < 0) {
+ createErrorResponse(m_error);
+ } else {
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ QJsonObject body;
+ body.insert(QStringLiteral("type"), m_type);
+ body.insert(QStringLiteral("breakpoint"), id);
+ addBody(body);
+ }
+ }
+
+protected:
+ virtual int handleBreakPointRequest() = 0;
- QString type = args.value(QLatin1String("type")).toString();
+ QJsonObject m_args;
+ QString m_type;
+ QString m_error;
+};
+
+class V4SetBreakPointRequest: public V4BreakPointRequest
+{
+public:
+ V4SetBreakPointRequest(): V4BreakPointRequest(QStringLiteral("setbreakpoint")) {}
+
+ int handleBreakPointRequest() final
+ {
+ // decypher the payload:
+ const QString type = m_args.value(QLatin1String("type")).toString();
if (type != QLatin1String("scriptRegExp")) {
- createErrorResponse(QStringLiteral("breakpoint type \"%1\" is not implemented").arg(type));
- return;
+ m_error = QStringLiteral("breakpoint type \"%1\" is not implemented").arg(type);
+ return -1;
}
- QString fileName = args.value(QLatin1String("target")).toString();
+ const QString fileName = m_args.value(QLatin1String("target")).toString();
if (fileName.isEmpty()) {
- createErrorResponse(QStringLiteral("breakpoint has no file name"));
- return;
+ m_error = QStringLiteral("breakpoint has no file name");
+ return -1;
}
- int line = args.value(QLatin1String("line")).toInt(-1);
+
+ const int line = m_args.value(QLatin1String("line")).toInt(-1);
if (line < 0) {
- createErrorResponse(QStringLiteral("breakpoint has an invalid line number"));
- return;
+ m_error = QStringLiteral("breakpoint has an invalid line number");
+ return -1;
}
- bool enabled = args.value(QStringLiteral("enabled")).toBool(true);
- QString condition = args.value(QStringLiteral("condition")).toString();
+ const bool enabled = m_args.value(QStringLiteral("enabled")).toBool(true);
+ const QString condition = m_args.value(QStringLiteral("condition")).toString();
// set the break point:
- int id = debugService->debuggerAgent.addBreakPoint(fileName, line + 1, enabled, condition);
+ return debugService->debuggerAgent.addBreakPoint(fileName, line + 1, enabled, condition);
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("type"), type);
- body.insert(QStringLiteral("breakpoint"), id);
// It's undocumented, but V8 sends back an actual_locations array too. However, our
// Debugger currently doesn't tell us when it resolved a breakpoint, so we'll leave them
// pending until the breakpoint is hit for the first time.
- addBody(body);
}
};
-class V8ClearBreakPointRequest: public V8CommandHandler
+class V4ClearBreakPointRequest: public V4BreakPointRequest
{
public:
- V8ClearBreakPointRequest(): V8CommandHandler(QStringLiteral("clearbreakpoint")) {}
+ V4ClearBreakPointRequest(): V4BreakPointRequest(QStringLiteral("clearbreakpoint")) {}
- void handleRequest() override
+ int handleBreakPointRequest() final
{
- // decypher the payload:
- QJsonObject args = req.value(QLatin1String("arguments")).toObject();
- if (args.isEmpty())
- return;
+ const int id = m_args.value(QLatin1String("breakpoint")).toInt(-1);
+ if (id < 0)
+ m_error = QStringLiteral("breakpoint has an invalid number");
+ else // remove the break point:
+ debugService->debuggerAgent.removeBreakPoint(id);
- int id = args.value(QLatin1String("breakpoint")).toInt(-1);
+ return id;
+ }
+};
+
+class V4ChangeBreakPointRequest: public V4BreakPointRequest
+{
+public:
+ V4ChangeBreakPointRequest(): V4BreakPointRequest(QStringLiteral("changebreakpoint")) {}
+
+ int handleBreakPointRequest() final
+ {
+ const int id = m_args.value(QLatin1String("breakpoint")).toInt(-1);
if (id < 0) {
- createErrorResponse(QStringLiteral("breakpoint has an invalid number"));
- return;
+ m_error = QStringLiteral("breakpoint has an invalid number");
+ return id;
}
- // remove the break point:
- debugService->debuggerAgent.removeBreakPoint(id);
+ const QJsonValue enabled = m_args.value(QLatin1String("enabled"));
+ if (!enabled.isBool()) {
+ m_error = QStringLiteral("missing bool \"enabled\" in breakpoint change request");
+ return -1;
+ }
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("type"), QStringLiteral("scriptRegExp"));
- body.insert(QStringLiteral("breakpoint"), id);
- addBody(body);
+ // enable or disable the break point:
+ debugService->debuggerAgent.enableBreakPoint(id, enabled.toBool());
+ return id;
}
};
-class V8BacktraceRequest: public V8CommandHandler
+class V4BacktraceRequest: public V4CommandHandler
{
public:
- V8BacktraceRequest(): V8CommandHandler(QStringLiteral("backtrace")) {}
+ V4BacktraceRequest(): V4CommandHandler(QStringLiteral("backtrace")) {}
void handleRequest() override
{
@@ -296,7 +321,7 @@ public:
return;
}
- BacktraceJob job(saneCollector(debugger), fromFrame, toFrame);
+ BacktraceJob job(debugger->collector(), fromFrame, toFrame);
debugger->runInEngine(&job);
// response:
@@ -305,15 +330,13 @@ public:
addSuccess(true);
addRunning();
addBody(job.returnValue());
- if (debugService->clientRequiresRedundantRefs())
- addRefs(job.refs());
}
};
-class V8FrameRequest: public V8CommandHandler
+class V4FrameRequest: public V4CommandHandler
{
public:
- V8FrameRequest(): V8CommandHandler(QStringLiteral("frame")) {}
+ V4FrameRequest(): V4CommandHandler(QStringLiteral("frame")) {}
void handleRequest() override
{
@@ -333,7 +356,7 @@ public:
return;
}
- FrameJob job(saneCollector(debugger), frameNr);
+ FrameJob job(debugger->collector(), frameNr);
debugger->runInEngine(&job);
if (!job.wasSuccessful()) {
createErrorResponse(QStringLiteral("frame retrieval failed"));
@@ -348,15 +371,13 @@ public:
addSuccess(true);
addRunning();
addBody(job.returnValue());
- if (debugService->clientRequiresRedundantRefs())
- addRefs(job.refs());
}
};
-class V8ScopeRequest: public V8CommandHandler
+class V4ScopeRequest: public V4CommandHandler
{
public:
- V8ScopeRequest(): V8CommandHandler(QStringLiteral("scope")) {}
+ V4ScopeRequest(): V4CommandHandler(QStringLiteral("scope")) {}
void handleRequest() override
{
@@ -381,7 +402,7 @@ public:
return;
}
- ScopeJob job(saneCollector(debugger), frameNr, scopeNr);
+ ScopeJob job(debugger->collector(), frameNr, scopeNr);
debugger->runInEngine(&job);
if (!job.wasSuccessful()) {
createErrorResponse(QStringLiteral("scope retrieval failed"));
@@ -394,15 +415,13 @@ public:
addSuccess(true);
addRunning();
addBody(job.returnValue());
- if (debugService->clientRequiresRedundantRefs())
- addRefs(job.refs());
}
};
-class V8LookupRequest: public V8CommandHandler
+class V4LookupRequest: public V4CommandHandler
{
public:
- V8LookupRequest(): V8CommandHandler(QStringLiteral("lookup")) {}
+ V4LookupRequest(): V4CommandHandler(QStringLiteral("lookup")) {}
void handleRequest() override
{
@@ -423,7 +442,7 @@ public:
debugger = debuggers.first();
}
- ValueLookupJob job(handles, saneCollector(debugger));
+ ValueLookupJob job(handles, debugger->collector());
debugger->runInEngine(&job);
if (!job.exceptionMessage().isEmpty()) {
createErrorResponse(job.exceptionMessage());
@@ -434,16 +453,14 @@ public:
addSuccess(true);
addRunning();
addBody(job.returnValue());
- if (debugService->clientRequiresRedundantRefs())
- addRefs(job.refs());
}
}
};
-class V8ContinueRequest: public V8CommandHandler
+class V4ContinueRequest: public V4CommandHandler
{
public:
- V8ContinueRequest(): V8CommandHandler(QStringLiteral("continue")) {}
+ V4ContinueRequest(): V4CommandHandler(QStringLiteral("continue")) {}
void handleRequest() override
{
@@ -486,10 +503,10 @@ public:
}
};
-class V8DisconnectRequest: public V8CommandHandler
+class V4DisconnectRequest: public V4CommandHandler
{
public:
- V8DisconnectRequest(): V8CommandHandler(QStringLiteral("disconnect")) {}
+ V4DisconnectRequest(): V4CommandHandler(QStringLiteral("disconnect")) {}
void handleRequest() override
{
@@ -504,10 +521,10 @@ public:
}
};
-class V8SetExceptionBreakRequest: public V8CommandHandler
+class V4SetExceptionBreakRequest: public V4CommandHandler
{
public:
- V8SetExceptionBreakRequest(): V8CommandHandler(QStringLiteral("setexceptionbreak")) {}
+ V4SetExceptionBreakRequest(): V4CommandHandler(QStringLiteral("setexceptionbreak")) {}
void handleRequest() override
{
@@ -544,10 +561,10 @@ public:
}
};
-class V8ScriptsRequest: public V8CommandHandler
+class V4ScriptsRequest: public V4CommandHandler
{
public:
- V8ScriptsRequest(): V8CommandHandler(QStringLiteral("scripts")) {}
+ V4ScriptsRequest(): V4CommandHandler(QStringLiteral("scripts")) {}
void handleRequest() override
{
@@ -616,10 +633,10 @@ public:
// }
//
// The "value" key in "body" is the result of evaluating the expression in the request.
-class V8EvaluateRequest: public V8CommandHandler
+class V4EvaluateRequest: public V4CommandHandler
{
public:
- V8EvaluateRequest(): V8CommandHandler(QStringLiteral("evaluate")) {}
+ V4EvaluateRequest(): V4CommandHandler(QStringLiteral("evaluate")) {}
void handleRequest() override
{
@@ -644,7 +661,7 @@ public:
}
ExpressionEvalJob job(debugger->engine(), frame, context, expression,
- saneCollector(debugger));
+ debugger->collector());
debugger->runInEngine(&job);
if (job.hasExeption()) {
createErrorResponse(job.exceptionMessage());
@@ -654,44 +671,43 @@ public:
addSuccess(true);
addRunning();
addBody(job.returnValue());
- if (debugService->clientRequiresRedundantRefs())
- addRefs(job.refs());
}
}
};
} // anonymous namespace
-void QV4DebugServiceImpl::addHandler(V8CommandHandler* handler)
+void QV4DebugServiceImpl::addHandler(V4CommandHandler* handler)
{
handlers[handler->command()] = handler;
}
-V8CommandHandler *QV4DebugServiceImpl::v8CommandHandler(const QString &command) const
+V4CommandHandler *QV4DebugServiceImpl::v4CommandHandler(const QString &command) const
{
- V8CommandHandler *handler = handlers.value(command, 0);
+ V4CommandHandler *handler = handlers.value(command, 0);
if (handler)
return handler;
else
- return unknownV8CommandHandler.data();
+ return unknownV4CommandHandler.data();
}
QV4DebugServiceImpl::QV4DebugServiceImpl(QObject *parent) :
QQmlConfigurableDebugService<QV4DebugService>(1, parent),
- debuggerAgent(this), theSelectedFrame(0), redundantRefs(true), namesAsObjects(true),
- unknownV8CommandHandler(new UnknownV8CommandHandler)
+ debuggerAgent(this), theSelectedFrame(0),
+ unknownV4CommandHandler(new UnknownV4CommandHandler)
{
- addHandler(new V8VersionRequest);
- addHandler(new V8SetBreakPointRequest);
- addHandler(new V8ClearBreakPointRequest);
- addHandler(new V8BacktraceRequest);
- addHandler(new V8FrameRequest);
- addHandler(new V8ScopeRequest);
- addHandler(new V8LookupRequest);
- addHandler(new V8ContinueRequest);
- addHandler(new V8DisconnectRequest);
- addHandler(new V8SetExceptionBreakRequest);
- addHandler(new V8ScriptsRequest);
- addHandler(new V8EvaluateRequest);
+ addHandler(new V4VersionRequest);
+ addHandler(new V4SetBreakPointRequest);
+ addHandler(new V4ClearBreakPointRequest);
+ addHandler(new V4ChangeBreakPointRequest);
+ addHandler(new V4BacktraceRequest);
+ addHandler(new V4FrameRequest);
+ addHandler(new V4ScopeRequest);
+ addHandler(new V4LookupRequest);
+ addHandler(new V4ContinueRequest);
+ addHandler(new V4DisconnectRequest);
+ addHandler(new V4SetExceptionBreakRequest);
+ addHandler(new V4ScriptsRequest);
+ addHandler(new V4EvaluateRequest);
}
QV4DebugServiceImpl::~QV4DebugServiceImpl()
@@ -703,10 +719,9 @@ void QV4DebugServiceImpl::engineAdded(QJSEngine *engine)
{
QMutexLocker lock(&m_configMutex);
if (engine) {
- QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
+ QV4::ExecutionEngine *ee = engine->handle();
if (QQmlDebugConnector *server = QQmlDebugConnector::instance()) {
if (ee) {
- ee->iselFactory.reset(new QV4::Moth::ISelFactory);
QV4Debugger *debugger = new QV4Debugger(ee);
if (state() == Enabled)
ee->setDebugger(debugger);
@@ -722,7 +737,7 @@ void QV4DebugServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
{
QMutexLocker lock(&m_configMutex);
if (engine){
- const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
+ const QV4::ExecutionEngine *ee = engine->handle();
if (ee) {
QV4Debugger *debugger = qobject_cast<QV4Debugger *>(ee->debugger());
if (debugger)
@@ -782,12 +797,7 @@ void QV4DebugServiceImpl::messageReceived(const QByteArray &message)
if (type == V4_CONNECT) {
QJsonObject parameters = QJsonDocument::fromJson(payload).object();
- namesAsObjects = true;
- redundantRefs = true;
- if (parameters.contains("namesAsObjects"))
- namesAsObjects = parameters.value("namesAsObjects").toBool();
- if (parameters.contains("redundantRefs"))
- redundantRefs = parameters.value("redundantRefs").toBool();
+ Q_UNUSED(parameters); // For future protocol changes
emit messageToClient(name(), packMessage(type));
stopWaiting();
@@ -805,10 +815,10 @@ void QV4DebugServiceImpl::messageReceived(const QByteArray &message)
else
breakOnSignals.removeOne(signalName);
} else if (type == "v8request") {
- handleV8Request(payload);
+ handleV4Request(payload);
} else if (type == V4_DISCONNECT) {
TRACE_PROTOCOL(qDebug() << "... payload:" << payload.constData());
- handleV8Request(payload);
+ handleV4Request(payload);
} else {
sendSomethingToSomebody(type, 0);
}
@@ -823,7 +833,7 @@ void QV4DebugServiceImpl::sendSomethingToSomebody(const char *type, int magicNum
emit messageToClient(name(), packMessage(type, rs.data()));
}
-void QV4DebugServiceImpl::handleV8Request(const QByteArray &payload)
+void QV4DebugServiceImpl::handleV4Request(const QByteArray &payload)
{
TRACE_PROTOCOL(qDebug() << "v8request, payload:" << payload.constData());
@@ -832,7 +842,7 @@ void QV4DebugServiceImpl::handleV8Request(const QByteArray &payload)
QJsonValue type = o.value(QLatin1String("type"));
if (type.toString() == QLatin1String("request")) {
QJsonValue command = o.value(QLatin1String("command"));
- V8CommandHandler *h = v8CommandHandler(command.toString());
+ V4CommandHandler *h = v4CommandHandler(command.toString());
if (h)
h->handle(o, this);
}
@@ -846,11 +856,11 @@ QByteArray QV4DebugServiceImpl::packMessage(const QByteArray &command, const QBy
return rs.data();
}
-void QV4DebugServiceImpl::send(QJsonObject v8Payload)
+void QV4DebugServiceImpl::send(QJsonObject v4Payload)
{
- v8Payload[QLatin1String("seq")] = sequence++;
+ v4Payload[QLatin1String("seq")] = sequence++;
QJsonDocument doc;
- doc.setObject(v8Payload);
+ doc.setObject(v4Payload);
#ifdef NO_PROTOCOL_TRACING
QByteArray responseData = doc.toJson(QJsonDocument::Compact);
#else
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
index bb13890ae4..d0b104dfad 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
@@ -51,9 +51,9 @@
// We mean it.
//
-#include "qqmlconfigurabledebugservice.h"
#include "qv4debuggeragent.h"
#include "qv4datacollector.h"
+#include <private/qqmlconfigurabledebugservice_p.h>
#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qv4debugging_p.h>
@@ -64,56 +64,50 @@ QT_BEGIN_NAMESPACE
namespace QV4 { struct ExecutionEngine; }
class VariableCollector;
-class V8CommandHandler;
-class UnknownV8CommandHandler;
+class V4CommandHandler;
+class UnknownV4CommandHandler;
class QV4DebugServiceImpl;
class QV4DebugServiceImpl : public QQmlConfigurableDebugService<QV4DebugService>
{
Q_OBJECT
public:
- explicit QV4DebugServiceImpl(QObject *parent = 0);
- ~QV4DebugServiceImpl() Q_DECL_OVERRIDE;
+ explicit QV4DebugServiceImpl(QObject *parent = nullptr);
+ ~QV4DebugServiceImpl() override;
- void engineAdded(QJSEngine *engine) Q_DECL_OVERRIDE;
- void engineAboutToBeRemoved(QJSEngine *engine) Q_DECL_OVERRIDE;
+ void engineAdded(QJSEngine *engine) override;
+ void engineAboutToBeRemoved(QJSEngine *engine) override;
- void stateAboutToBeChanged(State state) Q_DECL_OVERRIDE;
+ void stateAboutToBeChanged(State state) override;
- void signalEmitted(const QString &signal) Q_DECL_OVERRIDE;
- void send(QJsonObject v8Payload);
+ void signalEmitted(const QString &signal) override;
+ void send(QJsonObject v4Payload);
int selectedFrame() const;
void selectFrame(int frameNr);
- bool clientRequiresRedundantRefs() const { return redundantRefs; }
- bool clientRequiresNamesAsObjects() const { return namesAsObjects; }
-
QV4DebuggerAgent debuggerAgent;
protected:
- void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
+ void messageReceived(const QByteArray &) override;
void sendSomethingToSomebody(const char *type, int magicNumber = 1);
private:
friend class QQmlDebuggerServiceFactory;
- void handleV8Request(const QByteArray &payload);
+ void handleV4Request(const QByteArray &payload);
static QByteArray packMessage(const QByteArray &command,
const QByteArray &message = QByteArray());
void processCommand(const QByteArray &command, const QByteArray &data);
- V8CommandHandler *v8CommandHandler(const QString &command) const;
+ V4CommandHandler *v4CommandHandler(const QString &command) const;
QStringList breakOnSignals;
static int sequence;
int theSelectedFrame;
- bool redundantRefs;
- bool namesAsObjects;
-
- void addHandler(V8CommandHandler* handler);
- QHash<QString, V8CommandHandler*> handlers;
- QScopedPointer<UnknownV8CommandHandler> unknownV8CommandHandler;
+ void addHandler(V4CommandHandler* handler);
+ QHash<QString, V4CommandHandler*> handlers;
+ QScopedPointer<UnknownV4CommandHandler> unknownV4CommandHandler;
};
QT_END_NAMESPACE