diff --git a/src/plugins/debugger/qml/qmladapter.cpp b/src/plugins/debugger/qml/qmladapter.cpp index ff721970949282e58f887750a9269cb340a32f9a..e649a794f6a4d51b0424f90bf4dac1e119337edf 100644 --- a/src/plugins/debugger/qml/qmladapter.cpp +++ b/src/plugins/debugger/qml/qmladapter.cpp @@ -158,7 +158,6 @@ void QmlAdapter::clientStatusChanged(QDeclarativeDebugClient::Status status) if (status == QDeclarativeDebugClient::Enabled) { d->m_qmlClient = d->debugClients.value(serviceName); - d->m_qmlClient->flushSendBuffer(); d->m_qmlClient->startSession(); } } diff --git a/src/plugins/debugger/qml/qmldebuggerclient.cpp b/src/plugins/debugger/qml/qmldebuggerclient.cpp index c1e6144df481b230b853934b5e232f92d86760b2..13cfd6c5db0628ae889d25f126703cbcdc36afd9 100644 --- a/src/plugins/debugger/qml/qmldebuggerclient.cpp +++ b/src/plugins/debugger/qml/qmldebuggerclient.cpp @@ -82,5 +82,17 @@ void QmlDebuggerClient::flushSendBuffer() d->sendBuffer.clear(); } +//TODO:: remove this method +QList<QByteArray> QmlDebuggerClient::cachedMessages() +{ + return d->sendBuffer; +} + +//TODO:: remove this method +void QmlDebuggerClient::clearCachedMessages() +{ + d->sendBuffer.clear(); +} + } // Internal } // Debugger diff --git a/src/plugins/debugger/qml/qmldebuggerclient.h b/src/plugins/debugger/qml/qmldebuggerclient.h index e190ce3a78c36fd1d730d54cd3e6e9b37690b53b..8b92d17d396d0ce4c59618316b7b8796647098f2 100644 --- a/src/plugins/debugger/qml/qmldebuggerclient.h +++ b/src/plugins/debugger/qml/qmldebuggerclient.h @@ -92,6 +92,9 @@ protected: virtual void statusChanged(Status status); void sendMessage(const QByteArray &msg); + QList<QByteArray> cachedMessages(); + void clearCachedMessages(); + private: QmlDebuggerClientPrivate *d; friend class QmlDebuggerClientPrivate; diff --git a/src/plugins/debugger/qml/qmlv8debuggerclient.cpp b/src/plugins/debugger/qml/qmlv8debuggerclient.cpp index c6bfc61896b47cd4e8a54b1fc72569d933755ff7..42dcfc741180757a3997dd80db12a695c1c2de42 100644 --- a/src/plugins/debugger/qml/qmlv8debuggerclient.cpp +++ b/src/plugins/debugger/qml/qmlv8debuggerclient.cpp @@ -80,9 +80,7 @@ public: q(q), sequence(-1), engine(0), - debugServiceState(QmlV8DebuggerClient::RunningState), - requestListBreakpoints(false), - requestBacktrace(true) + isOldService(false) { parser = m_scriptEngine.evaluate(_("JSON.parse")); stringifier = m_scriptEngine.evaluate(_("JSON.stringify")); @@ -125,8 +123,11 @@ public: void logSendMessage(const QString &msg) const; void logReceiveMessage(const QString &msg) const; + //TODO:: remove this method + void reformatRequest(QByteArray &request); + private: - QByteArray packMessage(const QByteArray &message); + QByteArray packMessage(const QByteArray &type, const QByteArray &message = QByteArray()); QScriptValue initObject(); @@ -141,24 +142,15 @@ public: QScriptValue parser; QScriptValue stringifier; - //State Information - QmlV8DebuggerClient::V8DebugServiceStates debugServiceState; - int currentFrameIndex; - QStringList watchedExpressions; - - //Flags - bool requestListBreakpoints; - bool requestBacktrace; + QHash<int, QString> evaluatingExpression; + QHash<int, QByteArray> localsAndWatchers; //Cache - QHash<int, QByteArray> localsAndWatchers; - QHash<int, QString> evaluatingWatches; - QStack<QString> watchesToEvaluate; - QStack<int> currentFrameScopes; - QList<WatchData> localDataList; + QStringList watchedExpressions; QVariant refsVal; - QHash<int, QString> evaluatingExpression; - QQueue<QByteArray> requestQueue; + + //TODO: remove this flag + bool isOldService; private: QScriptEngine m_scriptEngine; }; @@ -171,16 +163,19 @@ private: void QmlV8DebuggerClientPrivate::connect() { - // { "seq" : <number>, - // "type" : "request", - // "command" : "connect", - // } - QScriptValue jsonVal = initObject(); - jsonVal.setProperty(_(COMMAND), QScriptValue(_(CONNECT))); - - const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), _(CONNECT))); + if (isOldService) { + // { "seq" : <number>, + // "type" : "request", + // "command" : "connect", + // } + QScriptValue jsonVal = initObject(); + jsonVal.setProperty(_(COMMAND), QScriptValue(_(CONNECT))); + const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); + q->sendMessage(packMessage(QByteArray(), jsonMessage.toString().toUtf8())); + } else { + q->sendMessage(packMessage(CONNECT)); + } } void QmlV8DebuggerClientPrivate::disconnect() @@ -194,29 +189,30 @@ void QmlV8DebuggerClientPrivate::disconnect() const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + q->sendMessage(packMessage(DISCONNECT, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::interrupt() { - // { "seq" : <number>, - // "type" : "request", - // "command" : "interrupt", - // } - QScriptValue jsonVal = initObject(); - jsonVal.setProperty(_(COMMAND), QScriptValue(_(INTERRUPT))); + logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), _(INTERRUPT))); + if (isOldService) { + // { "seq" : <number>, + // "type" : "request", + // "command" : "interrupt", + // } + QScriptValue jsonVal = initObject(); + jsonVal.setProperty(_(COMMAND), QScriptValue(_(INTERRUPT))); + const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); + q->sendMessage(packMessage(QByteArray(), jsonMessage.toString().toUtf8())); - const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + } else { + q->sendMessage(packMessage(INTERRUPT)); + } } void QmlV8DebuggerClientPrivate::continueDebugging(QmlV8DebuggerClient::StepAction action, int count) { - //First reset - q->resetDebugger(); - // { "seq" : <number>, // "type" : "request", // "command" : "continue", @@ -248,8 +244,8 @@ void QmlV8DebuggerClientPrivate::continueDebugging(QmlV8DebuggerClient::StepActi } const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::evaluate(const QString expr, bool global, @@ -306,8 +302,8 @@ void QmlV8DebuggerClientPrivate::evaluate(const QString expr, bool global, jsonVal.setProperty(_(ARGUMENTS), args); const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::lookup(QList<int> handles, bool includeSource) @@ -339,8 +335,8 @@ void QmlV8DebuggerClientPrivate::lookup(QList<int> handles, bool includeSource) jsonVal.setProperty(_(ARGUMENTS), args); const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::backtrace(int fromFrame, int toFrame, bool bottom) @@ -371,8 +367,8 @@ void QmlV8DebuggerClientPrivate::backtrace(int fromFrame, int toFrame, bool bott jsonVal.setProperty(_(ARGUMENTS), args); const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::frame(int number) @@ -394,8 +390,8 @@ void QmlV8DebuggerClientPrivate::frame(int number) } const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::scope(int number, int frameNumber) @@ -422,8 +418,8 @@ void QmlV8DebuggerClientPrivate::scope(int number, int frameNumber) } const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::scopes(int frameNumber) @@ -446,8 +442,8 @@ void QmlV8DebuggerClientPrivate::scopes(int frameNumber) } const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::scripts(int types, const QList<int> ids, bool includeSource, @@ -489,8 +485,8 @@ void QmlV8DebuggerClientPrivate::scripts(int types, const QList<int> ids, bool i jsonVal.setProperty(_(ARGUMENTS), args); const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::source(int frame, int fromLine, int toLine) @@ -521,8 +517,8 @@ void QmlV8DebuggerClientPrivate::source(int frame, int fromLine, int toLine) jsonVal.setProperty(_(ARGUMENTS), args); const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::setBreakpoint(const QString type, const QString target, @@ -541,33 +537,42 @@ void QmlV8DebuggerClientPrivate::setBreakpoint(const QString type, const QString // "ignoreCount" : <number specifying the number of break point hits to ignore, default value is 0> // } // } - QScriptValue jsonVal = initObject(); - jsonVal.setProperty(_(COMMAND), QScriptValue(_(SETBREAKPOINT))); + if (type == _(EVENT) && !isOldService) { + QByteArray params; + QDataStream rs(¶ms, QIODevice::WriteOnly); + rs << target.toUtf8() << enabled; + logSendMessage(QString(_("%1 %2 %3 %4")).arg(_(V8DEBUG), _(SIGNALHANDLER), target, enabled?_("enabled"):_("disabled"))); + q->sendMessage(packMessage(SIGNALHANDLER, params)); - QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT))); + } else { + QScriptValue jsonVal = initObject(); + jsonVal.setProperty(_(COMMAND), QScriptValue(_(SETBREAKPOINT))); - args.setProperty(_(TYPE), QScriptValue(type)); - args.setProperty(_(TARGET), QScriptValue(target)); + QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT))); - if (line != -1) - args.setProperty(_(LINE), QScriptValue(line)); + args.setProperty(_(TYPE), QScriptValue(type)); + args.setProperty(_(TARGET), QScriptValue(target)); - if (column != -1) - args.setProperty(_(COLUMN), QScriptValue(column)); + if (line != -1) + args.setProperty(_(LINE), QScriptValue(line)); - args.setProperty(_(ENABLED), QScriptValue(enabled)); + if (column != -1) + args.setProperty(_(COLUMN), QScriptValue(column)); - if (!condition.isEmpty()) - args.setProperty(_(CONDITION), QScriptValue(condition)); + args.setProperty(_(ENABLED), QScriptValue(enabled)); - if (ignoreCount != -1) - args.setProperty(_(IGNORECOUNT), QScriptValue(ignoreCount)); + if (!condition.isEmpty()) + args.setProperty(_(CONDITION), QScriptValue(condition)); - jsonVal.setProperty(_(ARGUMENTS), args); + if (ignoreCount != -1) + args.setProperty(_(IGNORECOUNT), QScriptValue(ignoreCount)); - const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + jsonVal.setProperty(_(ARGUMENTS), args); + + const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); + } } void QmlV8DebuggerClientPrivate::changeBreakpoint(int breakpoint, bool enabled, @@ -601,8 +606,8 @@ void QmlV8DebuggerClientPrivate::changeBreakpoint(int breakpoint, bool enabled, jsonVal.setProperty(_(ARGUMENTS), args); const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::clearBreakpoint(int breakpoint) @@ -624,8 +629,8 @@ void QmlV8DebuggerClientPrivate::clearBreakpoint(int breakpoint) jsonVal.setProperty(_(ARGUMENTS), args); const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::setExceptionBreak(QmlV8DebuggerClient::Exceptions type, @@ -657,8 +662,8 @@ void QmlV8DebuggerClientPrivate::setExceptionBreak(QmlV8DebuggerClient::Exceptio const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::listBreakpoints() @@ -672,8 +677,8 @@ void QmlV8DebuggerClientPrivate::listBreakpoints() QScriptValue(_(LISTBREAKPOINTS))); const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::v8flags(const QString flags) @@ -695,8 +700,8 @@ void QmlV8DebuggerClientPrivate::v8flags(const QString flags) jsonVal.setProperty(_(ARGUMENTS), args); const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } void QmlV8DebuggerClientPrivate::version() @@ -709,8 +714,8 @@ void QmlV8DebuggerClientPrivate::version() jsonVal.setProperty(_(COMMAND), QScriptValue(_(VERSION))); const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } //void QmlV8DebuggerClientPrivate::profile(ProfileCommand command) @@ -734,8 +739,8 @@ void QmlV8DebuggerClientPrivate::version() // jsonVal.setProperty(_(ARGUMENTS), args); // const QScriptValue jsonMessage = m_stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); -// logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); -// q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); +// logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); +// q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); //} void QmlV8DebuggerClientPrivate::gc() @@ -757,8 +762,8 @@ void QmlV8DebuggerClientPrivate::gc() jsonVal.setProperty(_(ARGUMENTS), args); const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal); - logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString())); - q->sendMessage(packMessage(jsonMessage.toString().toUtf8())); + logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString())); + q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8())); } QmlV8ObjectData QmlV8DebuggerClientPrivate::extractData(const QVariant &data) @@ -858,22 +863,21 @@ QmlV8ObjectData QmlV8DebuggerClientPrivate::extractData(const QVariant &data) void QmlV8DebuggerClientPrivate::clearCache() { - localsAndWatchers.clear(); - evaluatingWatches.clear(); - watchesToEvaluate.clear(); - currentFrameScopes.clear(); - localDataList.clear(); + watchedExpressions.clear(); refsVal.clear(); } -QByteArray QmlV8DebuggerClientPrivate::packMessage(const QByteArray &message) +QByteArray QmlV8DebuggerClientPrivate::packMessage(const QByteArray &type, const QByteArray &message) { SDEBUG(message); - QByteArray reply; - QDataStream rs(&reply, QIODevice::WriteOnly); + QByteArray request; + QDataStream rs(&request, QIODevice::WriteOnly); QByteArray cmd = V8DEBUG; - rs << cmd << message; - return reply; + rs << cmd; + if (!isOldService) + rs << type; + rs << message; + return request; } QScriptValue QmlV8DebuggerClientPrivate::initObject() @@ -897,6 +901,47 @@ void QmlV8DebuggerClientPrivate::logReceiveMessage(const QString &msg) const engine->logMessage("V8DebuggerClient", QmlEngine::LogReceive, msg); } +//TODO::remove this method +void QmlV8DebuggerClientPrivate::reformatRequest(QByteArray &request) +{ + QDataStream ds(request); + QByteArray header; + ds >> header; + + if (header == "V8DEBUG") { + QByteArray command; + QByteArray data; + ds >> command >> data; + + if (command == INTERRUPT) { + interrupt(); + + } else if (command == V8REQUEST) { + QString requestString(data); + const QVariantMap reqMap = parser.call(QScriptValue(), + QScriptValueList() << + QScriptValue(requestString)).toVariant().toMap(); + const QString debugCommand(reqMap.value(_(COMMAND)).toString()); + if (debugCommand == _(SETBREAKPOINT)) { + QVariantMap arguments = reqMap.value(_(ARGUMENTS)).toMap(); + QString type(arguments.value(_(TYPE)).toString()); + if (type == _(SCRIPTREGEXP)) { + data.replace(SCRIPTREGEXP, SCRIPT); + } + } + q->sendMessage(packMessage(QByteArray(), data)); + + } else if (command == SIGNALHANDLER) { + QDataStream rs(data); + QByteArray signalHandler; + bool enabled; + rs >> signalHandler >> enabled; + + setBreakpoint(_(EVENT), QString::fromUtf8(signalHandler), -1, -1, enabled); + } + } +} + /////////////////////////////////////////////////////////////////////// // // QmlV8DebuggerClient @@ -907,7 +952,6 @@ QmlV8DebuggerClient::QmlV8DebuggerClient(QmlJsDebugClient::QDeclarativeDebugConn : QmlDebuggerClient(client, QLatin1String("V8Debugger")), d(new QmlV8DebuggerClientPrivate(this)) { - resetDebugger(); } QmlV8DebuggerClient::~QmlV8DebuggerClient() @@ -917,8 +961,18 @@ QmlV8DebuggerClient::~QmlV8DebuggerClient() void QmlV8DebuggerClient::startSession() { - resetDebugger(); - d->debugServiceState = QmlV8DebuggerClient::RunningState; + //TODO:: remove this check. + //Modify messages to align with the older protocol + if (serviceVersion() < CURRENT_SUPPORTED_VERSION) { + d->isOldService = true; + //Modify cached messages + QList<QByteArray> buffer = cachedMessages(); + clearCachedMessages(); + foreach (QByteArray msg, buffer) { + d->reformatRequest(msg); + } + } + flushSendBuffer(); d->connect(); } @@ -929,26 +983,31 @@ void QmlV8DebuggerClient::endSession() void QmlV8DebuggerClient::executeStep() { + clearExceptionSelection(); d->continueDebugging(In); } void QmlV8DebuggerClient::executeStepOut() { + clearExceptionSelection(); d->continueDebugging(Out); } void QmlV8DebuggerClient::executeNext() { + clearExceptionSelection(); d->continueDebugging(Next); } void QmlV8DebuggerClient::executeStepI() { + clearExceptionSelection(); d->continueDebugging(In); } void QmlV8DebuggerClient::continueInferior() { + clearExceptionSelection(); d->continueDebugging(Continue); } @@ -959,7 +1018,8 @@ void QmlV8DebuggerClient::interruptInferior() void QmlV8DebuggerClient::activateFrame(int index) { - d->backtrace(index); + if (index != d->engine->stackHandler()->currentIndex()) + d->frame(index); } bool QmlV8DebuggerClient::acceptsBreakpoint(const BreakpointModelId &id) @@ -967,6 +1027,7 @@ bool QmlV8DebuggerClient::acceptsBreakpoint(const BreakpointModelId &id) BreakpointType type = d->engine->breakHandler()->breakpointData(id).type; return (type == BreakpointOnQmlSignalHandler || type == BreakpointByFunction + || type == BreakpointByFileAndLine || type == BreakpointAtJavaScriptThrow); } @@ -980,9 +1041,15 @@ void QmlV8DebuggerClient::insertBreakpoint(const BreakpointModelId &id) d->setExceptionBreak(AllExceptions, params.enabled); } else if (params.type == BreakpointByFileAndLine) { - d->setBreakpoint(QString(_(SCRIPT)), QFileInfo(params.fileName).fileName(), - params.lineNumber - 1, -1, params.enabled, - QString(params.condition), params.ignoreCount); + if (d->isOldService) { + d->setBreakpoint(QString(_(SCRIPT)), QFileInfo(params.fileName).fileName(), + params.lineNumber - 1, -1, params.enabled, + QString(params.condition), params.ignoreCount); + } else { + d->setBreakpoint(QString(_(SCRIPTREGEXP)), QFileInfo(params.fileName).fileName(), + params.lineNumber - 1, -1, params.enabled, + QString(params.condition), params.ignoreCount); + } } else if (params.type == BreakpointByFunction) { d->setBreakpoint(QString(_(FUNCTION)), params.functionName, @@ -992,6 +1059,7 @@ void QmlV8DebuggerClient::insertBreakpoint(const BreakpointModelId &id) } else if (params.type == BreakpointOnQmlSignalHandler) { d->setBreakpoint(QString(_(EVENT)), params.functionName, -1, -1, params.enabled); + d->engine->breakHandler()->notifyBreakpointInsertOk(id); } d->breakpointsSync.insert(d->sequence, id); @@ -1006,6 +1074,11 @@ void QmlV8DebuggerClient::removeBreakpoint(const BreakpointModelId &id) if (handler->breakpointData(id).type == BreakpointAtJavaScriptThrow) { d->setExceptionBreak(AllExceptions); + + } else if (handler->breakpointData(id).type == BreakpointOnQmlSignalHandler) { + d->setBreakpoint(QString(_(EVENT)), handler->breakpointData(id).functionName, + -1, -1, false); + } else { d->clearBreakpoint(breakpoint); } @@ -1018,11 +1091,16 @@ void QmlV8DebuggerClient::changeBreakpoint(const BreakpointModelId &id) if (params.type == BreakpointAtJavaScriptThrow) { d->setExceptionBreak(AllExceptions, params.enabled); - } - int breakpoint = d->breakpoints.value(id); - d->changeBreakpoint(breakpoint, params.enabled, QString(params.condition), - params.ignoreCount); + } else if (handler->breakpointData(id).type == BreakpointOnQmlSignalHandler) { + d->setBreakpoint(QString(_(EVENT)), params.functionName, + -1, -1, params.enabled); + + } else { + int breakpoint = d->breakpoints.value(id); + d->changeBreakpoint(breakpoint, params.enabled, QString(params.condition), + params.ignoreCount); + } BreakpointResponse br = handler->response(id); br.enabled = params.enabled; @@ -1042,26 +1120,20 @@ void QmlV8DebuggerClient::assignValueInDebugger(const QByteArray /*expr*/, const StackHandler *stackHandler = d->engine->stackHandler(); QString expression = QString(_("%1 = %2;")).arg(property).arg(value); if (stackHandler->isContentsValid()) { - d->evaluate(expression, false, false, stackHandler->currentIndex()); + d->evaluate(expression/*, false, false, stackHandler->currentIndex()*/); } } -void QmlV8DebuggerClient::updateWatchData(const WatchData &data) +void QmlV8DebuggerClient::updateWatchData(const WatchData &/*data*/) { - if (data.isWatcher()) { - QString exp(data.exp); - if (!d->watchedExpressions.contains(exp)) { - //Push new expression to the stack - d->watchesToEvaluate.push(exp); - } - } + //NOT USED } void QmlV8DebuggerClient::executeDebuggerCommand(const QString &command) { StackHandler *stackHandler = d->engine->stackHandler(); if (stackHandler->isContentsValid()) { - d->evaluate(command, false, false, stackHandler->currentIndex()); + d->evaluate(command/*, false, false, stackHandler->currentIndex()*/); d->evaluatingExpression.insert(d->sequence, command); } else { //Currently cannot evaluate if not in a javascript break @@ -1073,29 +1145,18 @@ void QmlV8DebuggerClient::executeDebuggerCommand(const QString &command) void QmlV8DebuggerClient::synchronizeWatchers(const QStringList &watchers) { SDEBUG(watchers); - //Cache the watched expression List - d->watchedExpressions = watchers; - //Evaluate new expressions one at a time. - if (!d->watchesToEvaluate.isEmpty()) { - StackHandler *stackHandler = d->engine->stackHandler(); - const QString exp = d->watchesToEvaluate.pop(); - if (stackHandler->isContentsValid()) { - d->evaluate(exp, false, false, stackHandler->currentIndex()); - } else { - d->evaluate(exp); + foreach (const QString &exp, watchers) { + if (!d->watchedExpressions.contains(exp)) { + d->watchedExpressions << exp; + executeDebuggerCommand(exp); } - d->evaluatingWatches.insert(d->sequence, exp); } } void QmlV8DebuggerClient::expandObject(const QByteArray &iname, quint64 objectId) { - if (d->debugServiceState != QmlV8DebuggerClient::RunningState) { - if (!d->localsAndWatchers.contains(objectId)) { - d->lookup(QList<int>() << objectId); - d->localsAndWatchers.insert(objectId, iname); - } - } + d->localsAndWatchers.insert(objectId, iname); + d->lookup(QList<int>() << objectId); } void QmlV8DebuggerClient::setEngine(QmlEngine *engine) @@ -1110,228 +1171,192 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data) ds >> command; if (command == V8DEBUG) { + QByteArray type; QByteArray response; - ds >> response; - QString responseString(response); - - SDEBUG(responseString); - d->logReceiveMessage(QString(_("%1 %2")).arg(_(V8DEBUG), responseString)); + ds >> type >> response; - const QVariantMap resp = d->parser.call(QScriptValue(), - QScriptValueList() << - QScriptValue(responseString)).toVariant().toMap(); - bool isV8Running = resp.value(_("running")).toBool(); - const QString type(resp.value(_(TYPE)).toString()); - - if (type == _("response")) { + if (d->isOldService) { + response = type; + type = QByteArray(V8MESSAGE); + } - bool success = resp.value(_("success")).toBool(); - if (!success) { - SDEBUG("Request was unsuccessful"); - } + d->logReceiveMessage(QString(_("%1 %2")).arg(_(V8DEBUG), QString(type))); + if (type == CONNECT) { + //debugging session started - const QString debugCommand(resp.value(_(COMMAND)).toString()); + } else if (type == INTERRUPT) { + //debug break requested - if (debugCommand == _(CONNECT)) { - //debugging session started + } else if (type == SIGNALHANDLER) { + //break on signal handler requested - } else if (debugCommand == _(DISCONNECT)) { - //debugging session ended + } else if (type == V8MESSAGE) { + QString responseString(response); + SDEBUG(responseString); + d->logReceiveMessage(QString(_("%1 %2")).arg(_(V8MESSAGE), responseString)); - } else if (debugCommand == _(CONTINEDEBUGGING)) { - d->requestBacktrace = true; + const QVariantMap resp = d->parser.call(QScriptValue(), + QScriptValueList() << + QScriptValue(responseString)).toVariant().toMap(); + const QString type(resp.value(_(TYPE)).toString()); - } else if (debugCommand == _(BACKTRACE)) { - if (success && d->debugServiceState != QmlV8DebuggerClient::RunningState) { - updateStack(resp.value(_(BODY)), resp.value(_(REFS))); - } + if (type == _("response")) { - } else if (debugCommand == _(LOOKUP)) { - if (success && d->debugServiceState != QmlV8DebuggerClient::RunningState) { - expandLocalsAndWatchers(resp.value(_(BODY)), resp.value(_(REFS))); + bool success = resp.value(_("success")).toBool(); + if (!success) { + SDEBUG("Request was unsuccessful"); } - } else if (debugCommand == _(EVALUATE)) { - int seq = resp.value(_("request_seq")).toInt(); - if (success) { - d->requestBacktrace = true; - updateEvaluationResult(seq, success, resp.value(_(BODY)), resp.value(_(REFS))); + const QString debugCommand(resp.value(_(COMMAND)).toString()); + + if (debugCommand == _(DISCONNECT)) { + //debugging session ended + + } else if (debugCommand == _(CONTINEDEBUGGING)) { + //do nothing, wait for next break + + } else if (debugCommand == _(BACKTRACE)) { + if (success) { + updateStack(resp.value(_(BODY)), resp.value(_(REFS))); + } + + } else if (debugCommand == _(LOOKUP)) { + if (success) { + expandLocalsAndWatchers(resp.value(_(BODY)), resp.value(_(REFS))); + } + + } else if (debugCommand == _(EVALUATE)) { + int seq = resp.value(_("request_seq")).toInt(); + if (success) { + updateEvaluationResult(seq, success, resp.value(_(BODY)), resp.value(_(REFS))); + } else { + QVariantMap map; + map.insert(_(TYPE), QVariant(_("string"))); + map.insert(_(VALUE), resp.value(_("message"))); + updateEvaluationResult(seq, success, QVariant(map), QVariant()); + } + + } else if (debugCommand == _(LISTBREAKPOINTS)) { + if (success) { + updateBreakpoints(resp.value(_(BODY))); + } + + } else if (debugCommand == _(SETBREAKPOINT)) { + // { "seq" : <number>, + // "type" : "response", + // "request_seq" : <number>, + // "command" : "setbreakpoint", + // "body" : { "type" : <"function" or "script"> + // "breakpoint" : <break point number of the new break point> + // } + // "running" : <is the VM running after sending this response> + // "success" : true + // } + + int seq = resp.value(_("request_seq")).toInt(); + const QVariantMap breakpointData = resp.value(_(BODY)).toMap(); + int index = breakpointData.value(_("breakpoint")).toInt(); + + BreakpointModelId id = d->breakpointsSync.take(seq); + d->breakpoints.insert(id, index); + + if (d->engine->breakHandler()->state(id) != BreakpointInserted) + d->engine->breakHandler()->notifyBreakpointInsertOk(id); + + + } else if (debugCommand == _(CHANGEBREAKPOINT)) { + // DO NOTHING + + } else if (debugCommand == _(CLEARBREAKPOINT)) { + // DO NOTHING + + } else if (debugCommand == _(SETEXCEPTIONBREAK)) { + // { "seq" : <number>, + // "type" : "response", + // "request_seq" : <number>, + // "command" : "setexceptionbreak", + // “body†: { "type" : <string: "all" or "uncaught" corresponding to the request.>, + // "enabled" : <bool: true if the break type is currently enabled as a result of the request> + // } + // "running" : true + // "success" : true + // } + + + } else if (debugCommand == _(FRAME)) { + if (success) { + setCurrentFrameDetails(resp.value(_(BODY)), resp.value(_(REFS))); + } + + } else if (debugCommand == _(SCOPE)) { + if (success) { + updateScope(resp.value(_(BODY)), resp.value(_(REFS))); + } + + } else if (debugCommand == _(SCOPES)) { + } else if (debugCommand == _(SOURCE)) { + } else if (debugCommand == _(SCRIPTS)) { + } else if (debugCommand == _(VERSION)) { + } else if (debugCommand == _(V8FLAGS)) { + } else if (debugCommand == _(GARBAGECOLLECTOR)) { } else { - QVariantMap map; - map.insert(_(TYPE), QVariant(_("string"))); - map.insert(_(VALUE), resp.value(_("message"))); - updateEvaluationResult(seq, success, QVariant(map), QVariant()); + // DO NOTHING } - } else if (debugCommand == _(LISTBREAKPOINTS)) { - if (success && d->debugServiceState != QmlV8DebuggerClient::RunningState) { - updateBreakpoints(resp.value(_(BODY))); - } - - } else if (debugCommand == _(SETBREAKPOINT)) { - // { "seq" : <number>, - // "type" : "response", - // "request_seq" : <number>, - // "command" : "setbreakpoint", - // "body" : { "type" : <"function" or "script"> - // "breakpoint" : <break point number of the new break point> - // } - // "running" : <is the VM running after sending this response> - // "success" : true - // } - - int seq = resp.value(_("request_seq")).toInt(); - const QVariantMap breakpointData = resp.value(_(BODY)).toMap(); - int index = breakpointData.value(_("breakpoint")).toInt(); - - BreakpointModelId id = d->breakpointsSync.take(seq); - d->breakpoints.insert(id, index); - - d->engine->breakHandler()->notifyBreakpointInsertOk(id); - - - } else if (debugCommand == _(CHANGEBREAKPOINT)) { - // DO NOTHING - - } else if (debugCommand == _(CLEARBREAKPOINT)) { - // DO NOTHING - - } else if (debugCommand == _(SETEXCEPTIONBREAK)) { - // { "seq" : <number>, - // "type" : "response", - // "request_seq" : <number>, - // "command" : "setexceptionbreak", - // "body" : { "type" : <string: "all" or "uncaught" corresponding to the request.>, - // "enabled" : <bool: true if the break type is currently enabled as a result of the request> - // } - // "running" : true - // "success" : true - // } - //TODO:: - - } else if (debugCommand == _(FRAME)) { - if (success && d->debugServiceState != QmlV8DebuggerClient::RunningState) { - const QVariant body = resp.value(_(BODY)); - const QVariant refs = resp.value(_(REFS)); - const QVariant locals = body.toMap().value(_("locals")); - StackFrame frame = createStackFrame(body, refs); - updateLocals(locals, refs); - d->engine->stackHandler()->setCurrentIndex(frame.level); - } - - } else if (debugCommand == _(SCOPE)) { - if (success && d->debugServiceState != QmlV8DebuggerClient::RunningState) { - const QVariant body = resp.value(_(BODY)).toMap().value(_("object")); - const QVariant refs = resp.value(_(REFS)); - updateScope(body, refs); - } - - } else if (debugCommand == _(SCOPES)) { - } else if (debugCommand == _(SOURCE)) { - } else if (debugCommand == _(SCRIPTS)) { - } else if (debugCommand == _(VERSION)) { - } else if (debugCommand == _(V8FLAGS)) { - } else if (debugCommand == _(GARBAGECOLLECTOR)) { - } else { - // DO NOTHING - } - - if (!isV8Running - && d->debugServiceState == QmlV8DebuggerClient::ProcessingRequestState) - d->debugServiceState = QmlV8DebuggerClient::WaitingForRequestState; + } else if (type == _(EVENT)) { + const QString eventType(resp.value(_(EVENT)).toString()); - } else if (type == _(EVENT)) { - const QString eventType(resp.value(_(EVENT)).toString()); + if (eventType == _("break")) { + if (d->engine->state() == InferiorRunOk) { + d->engine->inferiorSpontaneousStop(); + d->backtrace(); + } - if (eventType == _("break")) { - if (d->engine->state() == InferiorRunOk) - d->engine->inferiorSpontaneousStop(); - isV8Running = false; + } else if (eventType == _("exception")) { + const QVariantMap body = resp.value(_(BODY)).toMap(); + int lineNumber = body.value(_("sourceLine")).toInt() + 1; - } else if (eventType == _("exception")) { - const QVariantMap body = resp.value(_(BODY)).toMap(); - int lineNumber = body.value(_("sourceLine")).toInt() + 1; - - const QVariantMap script = body.value(_("script")).toMap(); - QUrl fileUrl(script.value(_(NAME)).toString()); - QString filePath = d->engine->toFileInProject(fileUrl); - - const QVariantMap exception = body.value(_("exception")).toMap(); - QString errorMessage = exception.value(_("text")).toString(); - - highlightExceptionCode(lineNumber, filePath, errorMessage); - - if (d->engine->state() == InferiorRunOk) - d->engine->inferiorSpontaneousStop(); - isV8Running = false; - d->requestBacktrace = true; - - } else if (eventType == _("afterCompile")) { - d->requestListBreakpoints = true; - } - - //Sometimes we do not get event type! - //This is most probably due to a wrong eval expression. - //Redirect output to console. - if (eventType.isEmpty()) { - bool success = resp.value(_("success")).toBool(); - QVariantMap map; - map.insert(_(TYPE), QVariant(_("string"))); - map.insert(_(VALUE), resp.value(_("message"))); - //Since there is no sequence value, best estimate is - //last sequence value - updateEvaluationResult(d->sequence, success, QVariant(map), QVariant()); - if (!isV8Running - && d->debugServiceState == QmlV8DebuggerClient::ProcessingRequestState) - d->debugServiceState = QmlV8DebuggerClient::WaitingForRequestState; - } + const QVariantMap script = body.value(_("script")).toMap(); + QUrl fileUrl(script.value(_(NAME)).toString()); + QString filePath = d->engine->toFileInProject(fileUrl); - if (!isV8Running - && d->debugServiceState == QmlV8DebuggerClient::RunningState) - d->debugServiceState = QmlV8DebuggerClient::WaitingForRequestState; - } + const QVariantMap exception = body.value(_("exception")).toMap(); + QString errorMessage = exception.value(_("text")).toString(); - if (isV8Running) { - resetDebugger(); - d->debugServiceState = QmlV8DebuggerClient::RunningState; + highlightExceptionCode(lineNumber, filePath, errorMessage); - } else { - if (d->requestListBreakpoints) { - d->listBreakpoints(); - d->requestListBreakpoints = false; - } + if (d->engine->state() == InferiorRunOk) { + d->engine->inferiorSpontaneousStop(); + d->backtrace(); + } - if (d->requestBacktrace) { - d->backtrace(d->currentFrameIndex); - d->requestBacktrace = false; - } + } else if (eventType == _("afterCompile")) { + //Currently break point relocation is disabled. + //Uncomment the line below when it will be enabled. +// d->listBreakpoints(); + } - if (d->debugServiceState == QmlV8DebuggerClient::WaitingForRequestState - && !d->requestQueue.isEmpty()) { - QmlDebuggerClient::sendMessage(d->requestQueue.dequeue()); - d->debugServiceState = QmlV8DebuggerClient::ProcessingRequestState; - } + //Sometimes we do not get event type! + //This is most probably due to a wrong eval expression. + //Redirect output to console. + if (eventType.isEmpty()) { + bool success = resp.value(_("success")).toBool(); + QVariantMap map; + map.insert(_(TYPE), QVariant(_("string"))); + map.insert(_(VALUE), resp.value(_("message"))); + //Since there is no sequence value, best estimate is + //last sequence value + updateEvaluationResult(d->sequence, success, QVariant(map), QVariant()); + } - } + } //EVENT + } //V8MESSAGE } else { //DO NOTHING } - SDEBUG(QString(_("State: %1")).arg(d->debugServiceState)); } -void QmlV8DebuggerClient::sendMessage(const QByteArray &msg) -{ - if (d->debugServiceState == QmlV8DebuggerClient::RunningState) { - QmlDebuggerClient::sendMessage(msg); - } else if (d->debugServiceState == QmlV8DebuggerClient::WaitingForRequestState) { - QmlDebuggerClient::sendMessage(msg); - d->debugServiceState = QmlV8DebuggerClient::ProcessingRequestState; - } else { - d->requestQueue.enqueue(msg); - } - -} void QmlV8DebuggerClient::updateStack(const QVariant &bodyVal, const QVariant &refsVal) { @@ -1353,62 +1378,23 @@ void QmlV8DebuggerClient::updateStack(const QVariant &bodyVal, const QVariant &r int fromFrameIndex = body.value(_("fromFrame")).toInt(); + QTC_ASSERT(0 == fromFrameIndex); - if (0 == fromFrameIndex) { - StackFrames stackFrames; - foreach (const QVariant &frame, frames) { - stackFrames << createStackFrame(frame, refsVal); - } - d->engine->stackHandler()->setFrames(stackFrames); - } - - if (d->currentFrameIndex != fromFrameIndex) { - StackHandler *stackHandler = d->engine->stackHandler(); - stackHandler->setCurrentIndex(fromFrameIndex); - d->engine->gotoLocation(stackHandler->currentFrame()); - d->currentFrameIndex = fromFrameIndex; + StackHandler *stackHandler = d->engine->stackHandler(); + StackFrames stackFrames; + foreach (const QVariant &frame, frames) { + stackFrames << insertStackFrame(frame, refsVal); } + stackHandler->setFrames(stackFrames); + //Populate locals and watchers wrt top frame //Update all Locals visible in current scope //Traverse the scope chain and store the local properties //in a list and show them in the Locals Window. - const QVariantMap currentFrame = frames.value(0).toMap(); - d->clearCache(); - d->refsVal = refsVal; - //Set "this" variable - { - WatchData data; - data.exp = QByteArray("this"); - data.name = QString(data.exp); - data.iname = QByteArray("local.") + data.exp; - QVariantMap receiver = currentFrame.value(_("receiver")).toMap(); - if (receiver.contains(_(REF))) { - receiver = valueFromRef(receiver.value(_(REF)).toInt(), refsVal).toMap(); - } - data.id = receiver.value(_("handle")).toInt(); - QmlV8ObjectData receiverData = d->extractData(QVariant(receiver)); - data.type = receiverData.type; - data.value = receiverData.value.toString(); - data.setHasChildren(receiverData.properties.toList().count()); - d->localDataList << data; - } - - const QVariantList currentFrameScopes = currentFrame.value(_("scopes")).toList(); - foreach (const QVariant &scope, currentFrameScopes) { - //Do not query for global types (0) - //Showing global properties increases clutter. - if (scope.toMap().value(_("type")).toInt() == 0) - continue; - d->currentFrameScopes.push(scope.toMap().value(_("index")).toInt()); - } - if (!d->currentFrameScopes.isEmpty()) { - d->scope(d->currentFrameScopes.pop(), d->currentFrameIndex); - } else { - updateLocalsAndWatchers(); - } + setCurrentFrameDetails(frames.value(0), refsVal); } -StackFrame QmlV8DebuggerClient::createStackFrame(const QVariant &bodyVal, const QVariant &refsVal) +StackFrame QmlV8DebuggerClient::insertStackFrame(const QVariant &bodyVal, const QVariant &refsVal) { // { "seq" : <number>, // "type" : "response", @@ -1450,7 +1436,10 @@ StackFrame QmlV8DebuggerClient::createStackFrame(const QVariant &bodyVal, const if (func.contains(_(REF))) { func = valueFromRef(func.value(_(REF)).toInt(), refsVal).toMap(); } - stackFrame.function = d->extractData(QVariant(func)).value.toString(); + QString functionName = d->extractData(QVariant(func)).value.toString(); + if (functionName.isEmpty()) + functionName = tr("anonymous function"); + stackFrame.function = functionName; QVariantMap file = body.value(_("script")).toMap(); if (file.contains(_(REF))) { @@ -1470,37 +1459,76 @@ StackFrame QmlV8DebuggerClient::createStackFrame(const QVariant &bodyVal, const return stackFrame; } -void QmlV8DebuggerClient::updateLocals(const QVariant &localsVal, const QVariant &refsVal) +void QmlV8DebuggerClient::setCurrentFrameDetails(const QVariant &bodyVal, const QVariant &refsVal) { - //Add Locals - const QVariantList locals = localsVal.toList(); - QList<WatchData> localDataList; - foreach (const QVariant &localValue, locals) { - QVariantMap localData = localValue.toMap(); - WatchData data; - data.exp = localData.value(_(NAME)).toByteArray(); - //Check for v8 specific local data - if (data.exp.startsWith(".") || data.exp.isEmpty()) - continue; - - data.name = QString(data.exp); - data.iname = QByteArray("local.") + data.exp; - - localData = valueFromRef(localData.value(_(VALUE)).toMap() - .value(_(REF)).toInt(), refsVal).toMap(); - data.id = localData.value(_(HANDLE)).toInt(); + // { "seq" : <number>, + // "type" : "response", + // "request_seq" : <number>, + // "command" : "frame", + // "body" : { "index" : <frame number>, + // "receiver" : <frame receiver>, + // "func" : <function invoked>, + // "script" : <script for the function>, + // "constructCall" : <boolean indicating whether the function was called as constructor>, + // "debuggerFrame" : <boolean indicating whether this is an internal debugger frame>, + // "arguments" : [ { name: <name of the argument - missing of anonymous argument>, + // value: <value of the argument> + // }, + // ... <the array contains all the arguments> + // ], + // "locals" : [ { name: <name of the local variable>, + // value: <value of the local variable> + // }, + // ... <the array contains all the locals> + // ], + // "position" : <source position>, + // "line" : <source line>, + // "column" : <source column within the line>, + // "sourceLineText" : <text for current source line>, + // "scopes" : [ <array of scopes, see scope request below for format> ], - QmlV8ObjectData objectData = d->extractData(QVariant(localData)); - data.type = objectData.type; - data.value = objectData.value.toString(); + // } + // "running" : <is the VM running after sending this response> + // "success" : true + // } + QVariantMap currentFrame = bodyVal.toMap(); - data.setHasChildren(objectData.properties.toList().count()); + //Check if the frameIndex is same as current Stack Index + StackHandler *stackHandler = d->engine->stackHandler(); + int frameIndex = currentFrame.value("index").toInt(); - localDataList << data; + d->clearCache(); + d->refsVal = refsVal; + //Set "this" variable + { + WatchData data; + data.exp = QByteArray("this"); + data.name = QString(data.exp); + data.iname = QByteArray("local.") + data.exp; + QVariantMap receiver = currentFrame.value(_("receiver")).toMap(); + if (receiver.contains(_(REF))) { + receiver = valueFromRef(receiver.value(_(REF)).toInt(), refsVal).toMap(); + } + data.id = receiver.value(_("handle")).toInt(); + QmlV8ObjectData receiverData = d->extractData(QVariant(receiver)); + data.type = receiverData.type; + data.value = receiverData.value.toString(); + data.setHasChildren(receiverData.properties.toList().count()); + d->engine->watchHandler()->beginCycle(); + d->engine->watchHandler()->insertData(data); + d->engine->watchHandler()->endCycle(); } - d->engine->watchHandler()->insertBulkData(localDataList); - + const QVariantList currentFrameScopes = currentFrame.value(_("scopes")).toList(); + foreach (const QVariant &scope, currentFrameScopes) { + //Do not query for global types (0) + //Showing global properties increases clutter. + if (scope.toMap().value(_("type")).toInt() == 0) + continue; + d->scope(scope.toMap().value(_("index")).toInt()); + } + stackHandler->setCurrentIndex(frameIndex); + d->engine->gotoLocation(stackHandler->currentFrame()); } void QmlV8DebuggerClient::updateScope(const QVariant &bodyVal, const QVariant &refsVal) @@ -1527,13 +1555,22 @@ void QmlV8DebuggerClient::updateScope(const QVariant &bodyVal, const QVariant &r // "success" : true // } QVariantMap bodyMap = bodyVal.toMap(); - if (bodyMap.contains(_(REF))) { - bodyMap = valueFromRef(bodyMap.value(_(REF)).toInt(), + + //Check if the frameIndex is same as current Stack Index + StackHandler *stackHandler = d->engine->stackHandler(); + if (bodyMap.value(_("frameIndex")).toInt() != stackHandler->currentIndex()) + return; + + QVariantMap object = bodyMap.value(_("object")).toMap(); + if (object.contains(_(REF))) { + object = valueFromRef(object.value(_(REF)).toInt(), refsVal).toMap(); } - const QVariantList properties = bodyMap.value(_("properties")).toList(); + const QVariantList properties = object.value(_("properties")).toList(); + QList<int> handlesToLookup; + QList<WatchData> locals; foreach (const QVariant &property, properties) { QVariantMap localData = property.toMap(); WatchData data; @@ -1548,12 +1585,7 @@ void QmlV8DebuggerClient::updateScope(const QVariant &bodyVal, const QVariant &r int handle = localData.value(_(REF)).toInt(); localData = valueFromRef(handle, d->refsVal).toMap(); if (localData.isEmpty()) { - //Fetch Data asynchronously and insert later - // see expandLocalsAndWatchers() - if (!d->localsAndWatchers.contains(handle)) { - d->lookup(QList<int>() << handle); - d->localsAndWatchers.insert(handle, data.exp); - } + handlesToLookup << handle; } else { data.id = localData.value(_(HANDLE)).toInt(); @@ -1564,14 +1596,17 @@ void QmlV8DebuggerClient::updateScope(const QVariant &bodyVal, const QVariant &r data.setHasChildren(objectData.properties.toList().count()); - d->localDataList << data; + locals << data; } } - if (!d->currentFrameScopes.isEmpty()) { - d->scope(d->currentFrameScopes.pop(), d->currentFrameIndex); - } else { - updateLocalsAndWatchers(); + if (!handlesToLookup.isEmpty()) + d->lookup(handlesToLookup); + + if (!locals.isEmpty()) { + d->engine->watchHandler()->beginCycle(false); + d->engine->watchHandler()->insertBulkData(locals); + d->engine->watchHandler()->endCycle(); } } @@ -1593,15 +1628,8 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, con } QmlV8ObjectData body = d->extractData(QVariant(bodyMap)); - - if (d->evaluatingExpression.contains(sequence)) { - d->evaluatingExpression.take(sequence); - //Console - d->engine->showMessage(body.value.toString(), ScriptConsoleOutput); - - } else if (d->evaluatingWatches.contains(sequence)) { - d->requestBacktrace = false; - QString exp = d->evaluatingWatches.take(sequence); + QString exp = d->evaluatingExpression.take(sequence); + if (d->watchedExpressions.contains(exp)) { QByteArray iname = d->engine->watchHandler()->watcherName(exp.toLatin1()); SDEBUG(QString(iname)); WatchData data; @@ -1613,56 +1641,18 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, con data.type = body.type; data.value = body.value.toString(); } else { - //Do not set type since it is unkown + //Do not set type since it is unknown data.setError(body.value.toString()); } - //TODO:: Fix expanding watched objects/expressions -// const QVariantList properties = body.properties.toList(); -// data.setHasChildren(properties.count()); - //Insert the newly evaluated expression to the Watchers Window d->engine->watchHandler()->beginCycle(false); d->engine->watchHandler()->insertData(data); d->engine->watchHandler()->endCycle(); - //Check if there are more expressions to be evaluated - //Evaluate one at a time. - if (!d->watchesToEvaluate.isEmpty()) { - StackHandler *stackHandler = d->engine->stackHandler(); - const QString exp = d->watchesToEvaluate.pop(); - if (stackHandler->isContentsValid()) { - d->evaluate(exp, false, false, stackHandler->currentIndex()); - } else { - d->evaluate(exp); - } - d->evaluatingWatches.insert(d->sequence, exp); - - } - - - // foreach (const QVariant &property, properties) { - // QVariantMap propertyData = property.toMap(); - // WatchData data; - // data.exp = propertyData.value(_(NAME)).toByteArray(); - - // //Check for v8 specific local data - // if (data.exp.startsWith(".") || data.exp.isEmpty()) - // continue; - - // data.name = data.exp; - // data.iname = prepend + '.' + data.exp; - // propertyData = valueFromRef(propertyData.value(_(REF)).toInt(), - // refsVal).toMap(); - // data.id = propertyData.value(_(HANDLE)).toInt(); - - // QmlV8ObjectData objectData = d->extractData(QVariant(propertyData)); - // data.type = objectData.type; - // data.value = objectData.value.toString(); + } else { + d->engine->showMessage(body.value.toString(), ScriptConsoleOutput); - // data.setHasChildren(objectData.properties.toList().count()); - // d->engine->watchHandler()->insertData(data); - // } } } @@ -1732,6 +1722,7 @@ QVariant QmlV8DebuggerClient::valueFromRef(int handle, const QVariant &refsVal) void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const QVariant &refsVal) { + //FIX THIS // { "seq" : <number>, // "type" : "response", // "request_seq" : <number>, @@ -1809,7 +1800,6 @@ void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const d->engine->watchHandler()->beginCycle(false); d->engine->watchHandler()->insertBulkData(watchDataList); d->engine->watchHandler()->endCycle(); - d->localDataList << watchDataList; } void QmlV8DebuggerClient::highlightExceptionCode(int lineNumber, @@ -1872,37 +1862,5 @@ void QmlV8DebuggerClient::clearExceptionSelection() } -void QmlV8DebuggerClient::resetDebugger() -{ - clearExceptionSelection(); - d->currentFrameIndex = -1; - SDEBUG(QString(_("State: %1")).arg(d->debugServiceState)); -} - -void QmlV8DebuggerClient::updateLocalsAndWatchers() -{ - d->engine->watchHandler()->beginCycle(); - d->engine->watchHandler()->insertBulkData(d->localDataList); - d->engine->watchHandler()->endCycle(); - - //Push all Watched expressions to a stack. - //Evaluate the expressions one at a time - //and append the evaluated result to the watchers - //window (see updateEvaluationResult()) - foreach (const QString &expr, d->watchedExpressions) - d->watchesToEvaluate.push(expr); - - if (!d->watchesToEvaluate.isEmpty()) { - StackHandler *stackHandler = d->engine->stackHandler(); - const QString exp = d->watchesToEvaluate.pop(); - if (stackHandler->isContentsValid()) { - d->evaluate(exp, false, false, stackHandler->currentIndex()); - } else { - d->evaluate(exp); - } - d->evaluatingWatches.insert(d->sequence, exp); - } -} - } // Internal } // Debugger diff --git a/src/plugins/debugger/qml/qmlv8debuggerclient.h b/src/plugins/debugger/qml/qmlv8debuggerclient.h index a5ac30aa82e8283026c7d708b6f88a1c1df16f3f..1f8cec0271d34a46003e65ebfa3ebd224b066b8d 100644 --- a/src/plugins/debugger/qml/qmlv8debuggerclient.h +++ b/src/plugins/debugger/qml/qmlv8debuggerclient.h @@ -61,13 +61,6 @@ class QmlV8DebuggerClient : public QmlDebuggerClient Next }; - enum V8DebugServiceStates - { - RunningState, - WaitingForRequestState, - ProcessingRequestState - }; - public: explicit QmlV8DebuggerClient(QmlJsDebugClient::QDeclarativeDebugConnection *client); ~QmlV8DebuggerClient(); @@ -94,7 +87,7 @@ public: void assignValueInDebugger(const QByteArray expr, const quint64 &id, const QString &property, const QString &value); - void updateWatchData(const WatchData &data); + void updateWatchData(const WatchData &); void executeDebuggerCommand(const QString &command); void synchronizeWatchers(const QStringList &watchers); @@ -105,13 +98,12 @@ public: protected: void messageReceived(const QByteArray &data); - void sendMessage(const QByteArray &msg); private: void updateStack(const QVariant &bodyVal, const QVariant &refsVal); - StackFrame createStackFrame(const QVariant &bodyVal, const QVariant &refsVal); - void updateLocals(const QVariant &localsVal, const QVariant &refsVal); - void updateScope(const QVariant &localsVal, const QVariant &refsVal); + StackFrame insertStackFrame(const QVariant &bodyVal, const QVariant &refsVal); + void setCurrentFrameDetails(const QVariant &bodyVal, const QVariant &refsVal); + void updateScope(const QVariant &bodyVal, const QVariant &refsVal); void updateEvaluationResult(int sequence, bool success, const QVariant &bodyVal, const QVariant &refsVal); @@ -125,10 +117,6 @@ private: const QString &errorMessage); void clearExceptionSelection(); - void resetDebugger(); - - void updateLocalsAndWatchers(); - private: QmlV8DebuggerClientPrivate *d; friend class QmlV8DebuggerClientPrivate; diff --git a/src/plugins/debugger/qml/qmlv8debuggerclientconstants.h b/src/plugins/debugger/qml/qmlv8debuggerclientconstants.h index 0914c32efa175162a0269c8f4ef6a8fa2c85e3a5..d3a6d1500e37a8dd941132c52bbd32485ad0fdc4 100644 --- a/src/plugins/debugger/qml/qmlv8debuggerclientconstants.h +++ b/src/plugins/debugger/qml/qmlv8debuggerclientconstants.h @@ -36,6 +36,12 @@ namespace Debugger { namespace Internal { +const float CURRENT_SUPPORTED_VERSION = 2.0; +const char V8REQUEST[] = "v8request"; +const char V8MESSAGE[] = "v8message"; +const char SIGNALHANDLER[] = "signalhandler"; +const char CONNECT[] = "connect"; +const char INTERRUPT[] = "interrupt"; const char V8DEBUG[] = "V8DEBUG"; const char SEQ[] = "seq"; const char TYPE[] = "type"; @@ -88,9 +94,6 @@ const char LISTBREAKPOINTS[] = "listbreakpoints"; const char GARBAGECOLLECTOR[] = "gc"; //const char PROFILE[] = "profile"; -const char CONNECT[] = "connect"; -const char INTERRUPT[] = "interrupt"; - const char REQUEST[] = "request"; const char IN[] = "in"; const char NEXT[] = "next"; @@ -98,6 +101,7 @@ const char OUT[] = "out"; const char FUNCTION[] = "function"; const char SCRIPT[] = "script"; +const char SCRIPTREGEXP[] = "scriptRegExp"; const char EVENT[] = "event"; const char ALL[] = "all"; diff --git a/src/plugins/debugger/qml/qscriptdebuggerclient.cpp b/src/plugins/debugger/qml/qscriptdebuggerclient.cpp index f161ab50ad945d15d8f6bcf8200f70d7872517c2..0bb2263d8339c8638aba3fcb42ce1c0d63ba634c 100644 --- a/src/plugins/debugger/qml/qscriptdebuggerclient.cpp +++ b/src/plugins/debugger/qml/qscriptdebuggerclient.cpp @@ -204,6 +204,9 @@ void QScriptDebuggerClient::interruptInferior() void QScriptDebuggerClient::startSession() { + //Flush buffered data + flushSendBuffer(); + //Set all breakpoints BreakHandler *handler = d->engine->breakHandler(); foreach (BreakpointModelId id, handler->engineBreakpointIds(d->engine)) {