From 39d1e93b675cc94708e5f727699fc6b3a290bda8 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 1 Dec 2015 15:50:15 +0100 Subject: V4 Debugger: If no context is given inject the QML context The user generally expects QML "root" objects to be in a "global" scope. Or at least that makes debugging a lot easier. By opening a WithContext with the relevant objects we can simulate that. Task-number: QTCREATORBUG-14931 Change-Id: I89af0560803b2c54a35f08e9fd659e65fb937cb9 Reviewed-by: Simon Hausmann --- .../qmldbg_debugger/qv4datacollector.cpp | 16 ++++++++++ .../qmltooling/qmldbg_debugger/qv4debugger.cpp | 37 +++++++++++++++++++--- .../qmltooling/qmldbg_debugger/qv4debugservice.cpp | 11 ++++--- 3 files changed, 55 insertions(+), 9 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp index ac46905f1c..78cb2be8d3 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp @@ -39,6 +39,9 @@ #include #include +#include +#include + #include #include @@ -352,6 +355,17 @@ QJsonObject QV4DataCollector::collectAsJson(const QString &name, const QV4::Scop void ValueLookupJob::run() { + // Open a QML context if we don't have one, yet. We might run into QML objects when looking up + // refs and that will crash without a valid QML context. Mind that engine->qmlContext() is only + // set if the engine is currently executing QML code. + QScopedPointer scopeObject; + QV4::ExecutionEngine *engine = collector->engine(); + if (engine->qmlEngine() && !engine->qmlContext()) { + scopeObject.reset(new QObject); + engine->pushContext(engine->currentContext->newQmlContext( + QQmlContextData::get(engine->qmlEngine()->rootContext()), + scopeObject.data())); + } foreach (const QJsonValue &handle, handles) { QV4DataCollector::Ref ref = handle.toInt(); if (!collector->isValidRef(ref)) { @@ -361,6 +375,8 @@ void ValueLookupJob::run() result[QString::number(ref)] = collector->lookupRef(ref); } collectedRefs = collector->flushCollectedRefs(); + if (scopeObject) + engine->popContext(); } const QString &ValueLookupJob::exceptionMessage() const diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp index a7ef1ede6b..b7c310edd8 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp @@ -36,6 +36,8 @@ #include #include +#include +#include QT_BEGIN_NAMESPACE @@ -69,11 +71,38 @@ void QV4Debugger::JavaScriptJob::run() QV4::ExecutionContextSaver saver(scope); QV4::ExecutionContext *ctx = engine->currentContext; - if (frameNr > 0) { - for (int i = 0; i < frameNr; ++i) { - ctx = engine->parentContext(ctx); + QObject scopeObject; + if (frameNr < 0) { // Use QML context if available + QQmlEngine *qmlEngine = engine->qmlEngine(); + if (qmlEngine) { + QQmlContext *qmlRootContext = qmlEngine->rootContext(); + QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(qmlRootContext); + + QV4::ScopedObject withContext(scope, engine->newObject()); + for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) { + QObject *object = ctxtPriv->instances.at(ii); + if (QQmlContext *context = qmlContext(object)) { + if (QQmlContextData *cdata = QQmlContextData::get(context)) { + QV4::ScopedValue v(scope, QV4::QObjectWrapper::wrap(engine, object)); + withContext->put(engine, cdata->findObjectId(object), v); + } + } + } + if (!engine->qmlContext()) { + engine->pushContext(ctx->newQmlContext(QQmlContextData::get(qmlRootContext), + &scopeObject)); + ctx = engine->currentContext; + } + engine->pushContext(ctx->newWithContext(withContext->toObject(engine))); + ctx = engine->currentContext; + } + } else { + if (frameNr > 0) { + for (int i = 0; i < frameNr; ++i) { + ctx = engine->parentContext(ctx); + } + engine->pushContext(ctx); } - engine->pushContext(ctx); } QV4::Script script(ctx, this->script); diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp index 6524a1ff28..dcf1fe8335 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp @@ -602,8 +602,11 @@ public: virtual void handleRequest() { - QV4Debugger *debugger = debugService->debuggerAgent.pausedDebugger(); + QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject(); + QString expression = arguments.value(QStringLiteral("expression")).toString(); + int frame = -1; + QV4Debugger *debugger = debugService->debuggerAgent.pausedDebugger(); if (!debugger) { const QList &debuggers = debugService->debuggerAgent.debuggers(); if (debuggers.count() > 1) { @@ -614,12 +617,10 @@ public: return; } debugger = debuggers.first(); + } else { + frame = arguments.value(QStringLiteral("frame")).toInt(0); } - QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject(); - QString expression = arguments.value(QStringLiteral("expression")).toString(); - const int frame = arguments.value(QStringLiteral("frame")).toInt(0); - ExpressionEvalJob job(debugger->engine(), frame, expression, debugger->collector()); debugger->runInEngine(&job); if (job.hasExeption()) { -- cgit v1.2.3