aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAurindam Jana <aurindam.jana@nokia.com>2011-11-24 18:12:17 +0100
committerQt by Nokia <qt-info@nokia.com>2011-11-25 15:58:35 +0100
commitad78e5fd290f69510f02b3b6bf3b6d2f52d59423 (patch)
tree4c377627be8f5fcb59b4d5fc52a6d177f24c7b18
parent831486bb2eed0c1d6bcab9fa75baea3d90bd07b1 (diff)
V8DebugService: Optimize Code.
Replace usage of QJSEngine with V8 APIs. Change-Id: I5221d11c1fb96a4912063d452af437a7f5bdb471 Reviewed-by: Christiaan Janssen <christiaan.janssen@nokia.com>
-rw-r--r--src/declarative/debugger/qv8debugservice.cpp526
-rw-r--r--src/declarative/debugger/qv8debugservice_p.h6
2 files changed, 267 insertions, 265 deletions
diff --git a/src/declarative/debugger/qv8debugservice.cpp b/src/declarative/debugger/qv8debugservice.cpp
index d28cd1348e..8741dd8837 100644
--- a/src/declarative/debugger/qv8debugservice.cpp
+++ b/src/declarative/debugger/qv8debugservice.cpp
@@ -42,12 +42,61 @@
#include "qv8debugservice_p.h"
#include "qdeclarativedebugservice_p_p.h"
#include <private/qv8debug_p.h>
-#include <private/qv8engine_p.h>
#include <private/qdeclarativeengine_p.h>
+#include <private/qjsconverter_impl_p.h>
#include <QtCore/QHash>
#include <QtCore/QFileInfo>
+#define DEBUGGER_SCRIPT "(function(){"\
+ "var DebuggerScript = {};"\
+ "DebuggerScript.getScriptName = function(eventData){"\
+ "return eventData.script_.script_.nameOrSourceURL();"\
+ "};"\
+ "DebuggerScript.getScripts = function(){"\
+ "var result = [];"\
+ "var scripts = Debug.scripts();"\
+ "for (var i = 0; i < scripts.length; ++i) {"\
+ "var script = scripts[i];"\
+ "if (script.type == Debug.ScriptType.Native) continue;"\
+ "result.push(script.nameOrSourceURL());"\
+ "}"\
+ "return result;"\
+ "};"\
+ "return DebuggerScript;"\
+ "})();"
+
+#define DEBUGGER_UTILITY "(function(){"\
+ "var DebuggerUtility = {};"\
+ "DebuggerUtility.parseRequest = function(request){"\
+ "return JSON.parse(request);"\
+ "};"\
+ "DebuggerUtility.stringifyRequest = function(request){"\
+ "return JSON.stringify(request);"\
+ "};"\
+ "return DebuggerUtility;"\
+ "})();"
+
+const char *V8_DEBUGGER_KEY_CONNECT = "connect";
+const char *V8_DEBUGGER_KEY_INTERRUPT = "interrupt";
+const char *V8_DEBUGGER_KEY_DISCONNECT = "disconnect";
+const char *V8_DEBUGGER_KEY_CLEARBREAKPOINT = "clearbreakpoint";
+const char *V8_DEBUGGER_KEY_CHANGEBREAKPOINT = "changebreakpoint";
+const char *V8_DEBUGGER_KEY_SETBREAKPOINT = "setbreakpoint";
+const char *V8_DEBUGGER_KEY_TARGET = "target";
+const char *V8_DEBUGGER_KEY_SCRIPT = "script";
+const char *V8_DEBUGGER_KEY_COMMAND = "command";
+const char *V8_DEBUGGER_KEY_SEQ = "seq";
+const char *V8_DEBUGGER_KEY_REQUEST_SEQ = "request_seq";
+const char *V8_DEBUGGER_KEY_SUCCESS = "success";
+const char *V8_DEBUGGER_KEY_BREAKPOINT = "breakpoint";
+const char *V8_DEBUGGER_KEY_ARGUMENTS = "arguments";
+const char *V8_DEBUGGER_KEY_ENABLED = "enabled";
+const char *V8_DEBUGGER_KEY_TYPE = "type";
+const char *V8_DEBUGGER_KEY_EVENT = "event";
+const char *V8_DEBUGGER_KEY_BODY = "body";
+const char *V8_DEBUGGER_KEY_RUNNING = "running";
+
QT_BEGIN_NAMESPACE
struct SignalHandlerData
@@ -77,7 +126,7 @@ void DebugMessageHandler(const v8::Debug::Message& message)
v8ServiceInstancePtr->debugMessageHandler(response, message.WillStartRunning());
if (event == v8::AfterCompile) {
- v8ServiceInstancePtr->appendSourcePath(response);
+ v8ServiceInstancePtr->appendSourcePath(message.GetEventData());
} //TODO::v8::Exception
}
@@ -88,22 +137,17 @@ public:
: connectReceived(false)
, scheduleBreak(false)
, debuggerThreadIsolate(0)
- , debuggerThreadEngine(0)
- , guiThreadIsolate(0)
- , guiThreadEngine(0)
, isRunning(true)
- , internalRequests(0)
{
}
~QV8DebugServicePrivate()
{
- delete debuggerThreadEngine;
+ debuggerScript.Dispose();
+ debuggerUtility.Dispose();
+ debuggerUtilityContext.Dispose();
if (debuggerThreadIsolate)
debuggerThreadIsolate->Dispose();
- delete guiThreadEngine;
- if (guiThreadIsolate)
- guiThreadIsolate->Dispose();
}
void initializeDebuggerThread();
@@ -111,14 +155,16 @@ public:
void sendDebugMessage(const QString &message);
void updateSourcePath(const QString &sourcePath);
static QByteArray packMessage(const QString &message);
+ QString createResponse(const QVariantMap &response) const;
+ v8::Handle<v8::Object> createV8Object(const QVariantMap &map) const;
bool connectReceived;
bool scheduleBreak;
v8::Isolate *debuggerThreadIsolate;
- QJSEngine *debuggerThreadEngine;
- v8::Isolate *guiThreadIsolate;
- QJSEngine *guiThreadEngine;
+ v8::Persistent<v8::Object> debuggerScript;
+ v8::Persistent<v8::Object> debuggerUtility;
+ v8::Persistent<v8::Context> debuggerUtilityContext;
// keep messageReceived() from running until initialize() has finished
QMutex initializeMutex;
@@ -127,7 +173,6 @@ public:
QHash<QString, QString> sourcePath;
QHash<QString, QString> requestCache;
QHash<int, SignalHandlerData> handlersList;
- int internalRequests;
};
QV8DebugService::QV8DebugService(QObject *parent)
@@ -139,7 +184,7 @@ QV8DebugService::QV8DebugService(QObject *parent)
// wait for statusChanged() -> initialize()
d->initializeMutex.lock();
if (registerService() == Enabled) {
- initialize();
+ initialize(false);
// ,block mode, client attached
while (!d->connectReceived) {
waitForMessage();
@@ -184,65 +229,25 @@ void QV8DebugService::debugMessageHandler(const QString &message, bool willStart
if (d->scheduleBreak)
scheduledDebugBreak();
- if (d->internalRequests > 0) {
- // there are outstanding internal requests,
- // check the sequence number: internal if seq is -1
-
- QVariantMap responseMap;
- {
- v8::Isolate::Scope i_scope(d->guiThreadIsolate);
- QJSValue parser = d->guiThreadEngine->evaluate(QLatin1String("JSON.parse"));
- QJSValue out = parser.call(QJSValue(), QJSValueList() << QJSValue(message));
- responseMap = out.toVariant().toMap();
- }
-
- if (responseMap.value(QLatin1String("request_seq")).toInt() == -1) {
- if (responseMap.value(QLatin1String("command")) == QLatin1String("scripts")) {
-
- // Reply to scripts request on connect:
-
- // {
- // "type": "response",
- // "request_seq": <number>,
- // "command": "scripts",
- // "body": [ { "name" : <name of script> } ]
- // }
-
- QVariantList body = responseMap.value(QLatin1String("body")).toList();
- foreach (const QVariant &listEntry, body) {
- QVariantMap entryMap = listEntry.toMap();
- const QString sourcePath = entryMap.value(QLatin1String("name")).toString();
- d->updateSourcePath(sourcePath);
- }
- }
-
- d->internalRequests--;
- return;
- }
- }
sendMessage(QV8DebugServicePrivate::packMessage(message));
}
-void QV8DebugService::appendSourcePath(const QString &message)
+void QV8DebugService::appendSourcePath(const v8::Handle<v8::Object> &eventData)
{
Q_D(QV8DebugService);
- QVariantMap msgMap;
- /* Parse the byte string in a separate isolate
- This will ensure that the debug message handler does not
- receive any messages related to this operation */
- {
- v8::Isolate::Scope scope(d->guiThreadIsolate);
- QJSValue parser = d->guiThreadEngine->evaluate(QLatin1String("JSON.parse"));
- QJSValue out = parser.call(QJSValue(), QJSValueList() << QJSValue(message));
- msgMap = out.toVariant().toMap();
- }
-
- const QString sourcePath(msgMap.value(QLatin1String("body")).toMap().value(
- QLatin1String("script")).toMap().value(
- QLatin1String("name")).toString());
- d->updateSourcePath(sourcePath);
+ Q_ASSERT(!d->debuggerScript.IsEmpty());
+ v8::HandleScope handleScope;
+ v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
+ v8::Context::Scope contextScope(debuggerContext);
+ v8::Handle<v8::Function> getScriptNameFn =
+ v8::Local<v8::Function>::Cast(d->debuggerScript->Get(v8::String::New("getScriptName")));
+ v8::Handle<v8::Value> argv[] = { eventData };
+ v8::Handle<v8::Value> scriptName = getScriptNameFn->Call(d->debuggerScript, 1, argv);
+ Q_ASSERT(scriptName->IsString());
+
+ d->updateSourcePath(QJSConverter::toString(scriptName->ToString()));
}
void QV8DebugService::signalEmitted(const QString &signal)
@@ -265,15 +270,36 @@ void QV8DebugService::signalEmitted(const QString &signal)
scheduledDebugBreak();
}
-void QV8DebugService::initialize()
+void QV8DebugService::initialize(bool getCompiledScripts)
{
Q_D(QV8DebugService);
+ if (d->debuggerScript.IsEmpty()) {
+ v8::HandleScope handleScope;
+ v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
+ v8::Context::Scope contextScope(debuggerContext);
+ v8::Handle<v8::Script> script = v8::Script::New(v8::String::New(DEBUGGER_SCRIPT), 0, 0, v8::Handle<v8::String>(), v8::Script::NativeMode);
+ d->debuggerScript = v8::Persistent<v8::Object>::New(v8::Local<v8::Object>::Cast(script->Run()));
+ }
v8::Debug::SetMessageHandler2(DebugMessageHandler);
- //Create an isolate & engine for parsing JSON messages in GUI thread
- d->guiThreadIsolate = v8::Isolate::New();
- v8::Isolate::Scope scope(d->guiThreadIsolate);
- d->guiThreadEngine = new QJSEngine();
+ if (getCompiledScripts) {
+ v8::HandleScope handleScope;
+ v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
+ v8::Context::Scope contextScope(debuggerContext);
+ v8::Handle<v8::Function> getScriptsFn =
+ v8::Local<v8::Function>::Cast(d->debuggerScript->Get(v8::String::New("getScripts")));
+ v8::Handle<v8::Value> argv[] = {};
+ v8::Handle<v8::Value> result = getScriptsFn->Call(d->debuggerScript, 0, argv);
+ if (result.IsEmpty())
+ return;
+
+ Q_ASSERT(!result->IsUndefined() && result->IsArray());
+ v8::Handle<v8::Array> scripts = v8::Handle<v8::Array>::Cast(result);
+ uint len = scripts->Length();
+ for (uint i = 0; i < len; ++i) {
+ d->updateSourcePath(QJSConverter::toString(scripts->Get(i)->ToString()));
+ }
+ }
d->initializeMutex.unlock();
}
@@ -287,42 +313,22 @@ void QV8DebugService::scheduledDebugBreak()
}
}
+void QV8DebugService::cancelDebugBreak()
+{
+ v8::Debug::CancelDebugBreak();
+}
+
// executed in the debugger thread
void QV8DebugService::statusChanged(QDeclarativeDebugService::Status newStatus)
{
Q_D(QV8DebugService);
if (newStatus == Enabled) {
- if (!d->debuggerThreadEngine)
+ if (!d->debuggerThreadIsolate)
d->initializeDebuggerThread();
// execute in GUI thread
d->initializeMutex.lock();
- QMetaObject::invokeMethod(this, "initialize", Qt::QueuedConnection);
-
- // Request already compiled scripts from v8 (recycling the sequence number from connect)
-
- // { "seq" : -1,
- // "type" : "request",
- // "command" : "scripts",
- // "arguments" : { "includeSource" : false }
- // }
- const QString obj(QLatin1String("{}"));
- v8::Isolate::Scope i_scope(d->debuggerThreadIsolate);
- QJSValue parser = d->debuggerThreadEngine->evaluate(QLatin1String("JSON.parse"));
- QJSValue jsonVal = parser.call(QJSValue(), QJSValueList() << obj);
- jsonVal.setProperty(QLatin1String("type"), QJSValue(QLatin1String("request")));
- jsonVal.setProperty(QLatin1String("seq"), QJSValue(-1));
- jsonVal.setProperty(QLatin1String("command"), QJSValue(QLatin1String("scripts")));
-
- QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
-
- args.setProperty(QLatin1String("includeSource"), QJSValue(false));
- jsonVal.setProperty(QLatin1String("arguments"), args);
-
- QJSValue stringify = d->debuggerThreadEngine->evaluate(QLatin1String("JSON.stringify"));
- QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
- d->internalRequests++;
- d->sendDebugMessage(json.toString());
+ QMetaObject::invokeMethod(this, "initialize", Qt::QueuedConnection, Q_ARG(bool, true));
}
}
@@ -338,7 +344,7 @@ void QV8DebugService::messageReceived(const QByteArray &message)
QMutexLocker locker(&d->initializeMutex);
if (command == "V8DEBUG") {
- if (!d->debuggerThreadEngine)
+ if (!d->debuggerThreadIsolate)
d->initializeDebuggerThread();
@@ -349,193 +355,139 @@ void QV8DebugService::messageReceived(const QByteArray &message)
request = QString::fromUtf8(requestArray);
}
- QVariantMap reqMap;
+ bool forwardRequestToV8 = false;
+ Q_ASSERT(!d->debuggerUtility.IsEmpty());
{
v8::Isolate::Scope i_scope(d->debuggerThreadIsolate);
- QJSValue parser = d->debuggerThreadEngine->evaluate(QLatin1String("JSON.parse"));
- QJSValue out = parser.call(QJSValue(), QJSValueList() << QJSValue(request));
- reqMap = out.toVariant().toMap();
- }
- const QString debugCommand(reqMap.value(QLatin1String("command")).toString());
- const int sequence = reqMap.value(QLatin1String("seq")).toInt();
-
- if (debugCommand == QLatin1String("connect")) {
- d->connectReceived = true;
- //Prepare the response string
- //Create a json message using v8 debugging protocol
- //and send it to client
-
- // { "type" : "response",
- // "request_seq" : <number>,
- // "command" : "connect",
- // "running" : <is the VM running after sending this response>
- // "success" : true
- // }
- {
- const QString obj(QLatin1String("{}"));
- v8::Isolate::Scope i_scope(d->debuggerThreadIsolate);
- QJSValue parser = d->debuggerThreadEngine->evaluate(QLatin1String("JSON.parse"));
- QJSValue jsonVal = parser.call(QJSValue(), QJSValueList() << obj);
- jsonVal.setProperty(QLatin1String("type"), QJSValue(QLatin1String("response")));
-
- jsonVal.setProperty(QLatin1String("request_seq"), QJSValue(sequence));
- jsonVal.setProperty(QLatin1String("command"), QJSValue(debugCommand));
- jsonVal.setProperty(QLatin1String("success"), QJSValue(true));
- jsonVal.setProperty(QLatin1String("running"), QJSValue(d->isRunning));
-
- QJSValue stringify = d->debuggerThreadEngine->evaluate(QLatin1String("JSON.stringify"));
- QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
- sendMessage(QV8DebugServicePrivate::packMessage(json.toString()));
- }
- } else if (debugCommand == QLatin1String("interrupt")) {
- //Prepare the response string
- //Create a json message using v8 debugging protocol
- //and send it to client
-
- // { "type" : "response",
- // "request_seq" : <number>,
- // "command" : "interrupt",
- // "running" : <is the VM running after sending this response>
- // "success" : true
- // }
- {
- const QString obj(QLatin1String("{}"));
- v8::Isolate::Scope i_scope(d->debuggerThreadIsolate);
- QJSValue parser = d->debuggerThreadEngine->evaluate(QLatin1String("JSON.parse"));
- QJSValue jsonVal = parser.call(QJSValue(), QJSValueList() << obj);
- jsonVal.setProperty(QLatin1String("type"), QJSValue(QLatin1String("response")));
-
- const int sequence = reqMap.value(QLatin1String("seq")).toInt();
- jsonVal.setProperty(QLatin1String("request_seq"), QJSValue(sequence));
- jsonVal.setProperty(QLatin1String("command"), QJSValue(debugCommand));
- jsonVal.setProperty(QLatin1String("success"), QJSValue(true));
- jsonVal.setProperty(QLatin1String("running"), QJSValue(d->isRunning));
-
- QJSValue stringify = d->debuggerThreadEngine->evaluate(QLatin1String("JSON.stringify"));
- QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
- sendMessage(QV8DebugServicePrivate::packMessage(json.toString()));
- }
- // break has to be executed in gui thread
- d->scheduleBreak = true;
- QMetaObject::invokeMethod(this, "scheduledDebugBreak", Qt::QueuedConnection);
- } else {
- bool forwardRequestToV8 = true;
-
- if (debugCommand == QLatin1String("setbreakpoint")) {
- const QVariantMap arguments = reqMap.value(QLatin1String("arguments")).toMap();
- const QString type(arguments.value(QLatin1String("type")).toString());
- if (type == QLatin1String("script")) {
- QString fileName(arguments.value(QLatin1String("target")).toString());
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(d->debuggerUtilityContext);
+
+ v8::Handle<v8::Function> parseFn =
+ v8::Local<v8::Function>::Cast(d->debuggerUtility->Get(v8::String::New("parseRequest")));
+ v8::Handle<v8::Value> argv[] = { QJSConverter::toString(request) };
+ v8::Handle<v8::Value> result = parseFn->Call(d->debuggerUtility, 1, argv);
+ Q_ASSERT(result->IsObject());
+
+ v8::Handle<v8::Object> requestObj = v8::Handle<v8::Object>::Cast(result);
+ const QString debugCommand = QJSConverter::toString(requestObj->Get(v8::String::New(V8_DEBUGGER_KEY_COMMAND))->ToString());
+ const int sequence = requestObj->Get(v8::String::New(V8_DEBUGGER_KEY_SEQ))->Int32Value();
+
+ if (debugCommand == QLatin1String(V8_DEBUGGER_KEY_CONNECT)) {
+ d->connectReceived = true;
+ QVariantMap response;
+ response.insert(QLatin1String(V8_DEBUGGER_KEY_COMMAND), QVariant(debugCommand));
+ response.insert(QLatin1String(V8_DEBUGGER_KEY_REQUEST_SEQ), QVariant(sequence));
+ response.insert(QLatin1String(V8_DEBUGGER_KEY_SUCCESS), QVariant(true));
+ sendMessage(QV8DebugServicePrivate::packMessage(d->createResponse(response)));
+
+ } else if (debugCommand == QLatin1String(V8_DEBUGGER_KEY_INTERRUPT)) {
+ // break has to be executed in gui thread
+ d->scheduleBreak = true;
+ QMetaObject::invokeMethod(this, "scheduledDebugBreak", Qt::QueuedConnection);
+ QVariantMap response;
+ response.insert(QLatin1String(V8_DEBUGGER_KEY_COMMAND), QVariant(debugCommand));
+ response.insert(QLatin1String(V8_DEBUGGER_KEY_REQUEST_SEQ), QVariant(sequence));
+ response.insert(QLatin1String(V8_DEBUGGER_KEY_SUCCESS), QVariant(true));
+ sendMessage(QV8DebugServicePrivate::packMessage(d->createResponse(response)));
+
+ } else if (debugCommand == QLatin1String(V8_DEBUGGER_KEY_DISCONNECT)) {
+ // cancel break has to be executed in gui thread
+ QMetaObject::invokeMethod(this, "cancelDebugBreak", Qt::QueuedConnection);
+ forwardRequestToV8 = true;
+
+ } else if (debugCommand == QLatin1String(V8_DEBUGGER_KEY_CLEARBREAKPOINT)) {
+ //check if the breakpoint is a negative integer (event breakpoint)
+ v8::Handle<v8::Object> argsObj = requestObj->Get(v8::String::New(V8_DEBUGGER_KEY_ARGUMENTS))->ToObject();
+ const int bp = argsObj->Get(v8::String::New(V8_DEBUGGER_KEY_BREAKPOINT))->Int32Value();
- //Check if the filepath has been cached
- if (d->sourcePath.contains(fileName)) {
- QString filePath = d->sourcePath.value(fileName);
- request.replace(fileName, filePath);
- } else {
- //Store the setbreakpoint message till filepath is resolved
- d->requestCache.insertMulti(fileName, request);
- forwardRequestToV8 = false;
- }
- } else if (type == QLatin1String("event")) {
- //Do not send this request to v8
- forwardRequestToV8 = false;
-
- //Prepare the response string
- //Create a json message using v8 debugging protocol
- //and send it to client
-
- // { "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
- // }
- {
- const QString obj(QLatin1String("{}"));
- v8::Isolate::Scope i_scope(d->debuggerThreadIsolate);
- QJSValue parser = d->debuggerThreadEngine->evaluate(QLatin1String("JSON.parse"));
- QJSValue jsonVal = parser.call(QJSValue(), QJSValueList() << obj);
- jsonVal.setProperty(QLatin1String("type"), QJSValue(QLatin1String("response")));
-
- const int sequence = reqMap.value(QLatin1String("seq")).toInt();
- jsonVal.setProperty(QLatin1String("request_seq"), QJSValue(sequence));
- jsonVal.setProperty(QLatin1String("command"), QJSValue(debugCommand));
-
- //Check that the function starts with 'on'
- QString eventName(arguments.value(QLatin1String("target")).toString());
-
-
- if (eventName.startsWith(QLatin1String("on"))) {
- SignalHandlerData data;
- //Only store the probable signal name.
- //Normalize to lower case.
- data.functionName = eventName.remove(0,2).toLower();
- data.enabled = arguments.value(QLatin1String("enabled")).toBool();
- d->handlersList.insert(-sequence, data);
-
- QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
-
- args.setProperty(QLatin1String("type"), QJSValue(QLatin1String("event")));
- args.setProperty(QLatin1String("breakpoint"), QJSValue(-sequence));
-
- jsonVal.setProperty(QLatin1String("body"), args);
- jsonVal.setProperty(QLatin1String("success"), QJSValue(true));
-
- } else {
- jsonVal.setProperty(QLatin1String("success"), QJSValue(false));
- }
-
-
- jsonVal.setProperty(QLatin1String("running"), QJSValue(d->isRunning));
-
- QJSValue stringify = d->debuggerThreadEngine->evaluate(QLatin1String("JSON.stringify"));
- QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
- sendMessage(QV8DebugServicePrivate::packMessage(json.toString()));
- }
+ if (bp < 0) {
+ d->handlersList.remove(bp);
+ } else {
+ forwardRequestToV8 = true;
}
- } else if (debugCommand == QLatin1String("changebreakpoint")) {
+
+ } else if (debugCommand == QLatin1String(V8_DEBUGGER_KEY_CHANGEBREAKPOINT)) {
//check if the breakpoint is a negative integer (event breakpoint)
- const QVariantMap arguments = reqMap.value(QLatin1String("arguments")).toMap();
- const int bp = arguments.value(QLatin1String("breakpoint")).toInt();
+ v8::Handle<v8::Object> argsObj = requestObj->Get(v8::String::New(V8_DEBUGGER_KEY_ARGUMENTS))->ToObject();
+ const int bp = argsObj->Get(v8::String::New(V8_DEBUGGER_KEY_BREAKPOINT))->Int32Value();
if (bp < 0) {
SignalHandlerData data = d->handlersList.value(bp);
- data.enabled = arguments.value(QLatin1String("enabled")).toBool();
+ data.enabled = argsObj->Get(v8::String::New(V8_DEBUGGER_KEY_ENABLED))->BooleanValue();
d->handlersList.insert(bp, data);
- forwardRequestToV8 = false;
+
+ } else {
+ forwardRequestToV8 = true;
}
- } else if (debugCommand == QLatin1String("clearbreakpoint")) {
- //check if the breakpoint is a negative integer (event breakpoint)
- const QVariantMap arguments = reqMap.value(QLatin1String("arguments")).toMap();
- const int bp = arguments.value(QLatin1String("breakpoint")).toInt();
- if (bp < 0) {
- d->handlersList.remove(bp);
- forwardRequestToV8 = false;
+ } else if (debugCommand == QLatin1String(V8_DEBUGGER_KEY_SETBREAKPOINT)) {
+ v8::Handle<v8::Object> argsObj = requestObj->Get(v8::String::New(V8_DEBUGGER_KEY_ARGUMENTS))->ToObject();
+ const QString type = QJSConverter::toString(argsObj->Get(v8::String::New(V8_DEBUGGER_KEY_TYPE))->ToString());
+ QString target = QJSConverter::toString(argsObj->Get(v8::String::New(V8_DEBUGGER_KEY_TARGET))->ToString());
+
+ if (type == QLatin1String(V8_DEBUGGER_KEY_SCRIPT)) {
+ //check if the script associated with the breakpoint is cached
+ if (d->sourcePath.contains(target)) {
+ //replace fileName with correct filePath
+ request.replace(target, d->sourcePath.value(target));
+ forwardRequestToV8 = true;
+
+ } else {
+ //store the message till file is compiled
+ d->requestCache.insertMulti(target, request);
+ }
+
+ } else if (type == QLatin1String(V8_DEBUGGER_KEY_EVENT)) {
+ //Handle this internally
+ bool success = true;
+ if (target.startsWith(QLatin1String("on"))) {
+ SignalHandlerData data;
+ //Only store the probable signal name.
+ //Normalize to lower case.
+ data.functionName = target.remove(0,2).toLower();
+ data.enabled = argsObj->Get(v8::String::New(V8_DEBUGGER_KEY_ENABLED))->BooleanValue();
+ d->handlersList.insert(-sequence, data);
+ } else {
+ success = false;
+ }
+ //TODO::have to send back response
+ QVariantMap body;
+ body.insert(QLatin1String(V8_DEBUGGER_KEY_TYPE), QVariant(QLatin1String(V8_DEBUGGER_KEY_EVENT)));
+ body.insert(QLatin1String(V8_DEBUGGER_KEY_BREAKPOINT), QVariant(-sequence));
+ QVariantMap response;
+ response.insert(QLatin1String(V8_DEBUGGER_KEY_COMMAND), QVariant(debugCommand));
+ response.insert(QLatin1String(V8_DEBUGGER_KEY_REQUEST_SEQ), QVariant(sequence));
+ response.insert(QLatin1String(V8_DEBUGGER_KEY_SUCCESS), QVariant(success));
+ response.insert(QLatin1String(V8_DEBUGGER_KEY_BODY), body);
+
+ sendMessage(QV8DebugServicePrivate::packMessage(d->createResponse(response)));
}
- } else if (debugCommand == QLatin1String("disconnect")) {
- v8::Debug::CancelDebugBreak();
+ } else {
+ //Forward all other requests
+ forwardRequestToV8 = true;
}
-
- if (forwardRequestToV8)
- d->sendDebugMessage(request);
}
+
+ if (forwardRequestToV8)
+ d->sendDebugMessage(request);
}
}
void QV8DebugServicePrivate::initializeDebuggerThread()
{
- Q_ASSERT(!debuggerThreadEngine);
+ Q_ASSERT(!debuggerThreadIsolate);
//Create an isolate & engine in debugger thread
debuggerThreadIsolate = v8::Isolate::New();
v8::Isolate::Scope i_scope(debuggerThreadIsolate);
- debuggerThreadEngine = new QJSEngine();
+ if (debuggerUtility.IsEmpty()) {
+ v8::HandleScope handleScope;
+ debuggerUtilityContext = v8::Context::New();
+ v8::Context::Scope contextScope(debuggerUtilityContext);
+ v8::Handle<v8::Script> script = v8::Script::New(v8::String::New(DEBUGGER_UTILITY), 0, 0, v8::Handle<v8::String>(), v8::Script::NativeMode);
+ debuggerUtility = v8::Persistent<v8::Object>::New(v8::Local<v8::Object>::Cast(script->Run()));
+ }
}
void QV8DebugServicePrivate::sendDebugMessage(const QString &message)
@@ -568,4 +520,52 @@ QByteArray QV8DebugServicePrivate::packMessage(const QString &message)
return reply;
}
+QString QV8DebugServicePrivate::createResponse(const QVariantMap &response) const
+{
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(debuggerUtilityContext);
+
+ v8::Handle<v8::Object> respObj = createV8Object(response);
+ respObj->Set(v8::String::New(V8_DEBUGGER_KEY_TYPE), v8::String::New("response"));
+ respObj->Set(v8::String::New(V8_DEBUGGER_KEY_RUNNING), v8::Boolean::New(isRunning));
+ v8::Handle<v8::Function> stringifyFn =
+ v8::Local<v8::Function>::Cast(debuggerUtility->Get(v8::String::New("stringifyRequest")));
+ v8::Handle<v8::Value> argv[] = { respObj };
+ v8::Handle<v8::Value> result = stringifyFn->Call(debuggerScript, 1, argv);
+ Q_ASSERT(result->IsString());
+
+ return QJSConverter::toString(result->ToString());
+
+}
+
+v8::Handle<v8::Object> QV8DebugServicePrivate::createV8Object(const QVariantMap &map) const
+{
+ v8::Handle<v8::Object> obj = v8::Object::New();
+ foreach (const QVariant &var, map) {
+ v8::Handle<v8::String> key = QJSConverter::toString(map.key(var));
+ v8::Handle<v8::Value> val;
+ switch (var.type()) {
+ case QVariant::Bool:
+ val = v8::Boolean::New(var.toBool());
+ break;
+ case QVariant::Int:
+ val = v8::Int32::New(var.toInt());
+ break;
+ case QVariant::String:
+ val = QJSConverter::toString(var.toString());
+ break;
+ case QVariant::Map:
+ createV8Object(var.toMap());
+ break;
+ default:
+ //Add other types when required.
+ //Not handled currently
+ break;
+ }
+ if (!val.IsEmpty())
+ obj->Set(key, val);
+ }
+ return obj;
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qv8debugservice_p.h b/src/declarative/debugger/qv8debugservice_p.h
index 802b77f056..2d063900f8 100644
--- a/src/declarative/debugger/qv8debugservice_p.h
+++ b/src/declarative/debugger/qv8debugservice_p.h
@@ -54,6 +54,7 @@
//
#include "qdeclarativedebugservice_p.h"
+#include <private/qv8_p.h>
QT_BEGIN_HEADER
@@ -78,13 +79,14 @@ public:
void debugMessageHandler(const QString &message, bool willStartRunning);
- void appendSourcePath(const QString &message);
+ void appendSourcePath(const v8::Handle<v8::Object> &eventData);
void signalEmitted(const QString &signal);
private slots:
void scheduledDebugBreak();
- void initialize();
+ void cancelDebugBreak();
+ void initialize(bool);
protected:
void statusChanged(Status newStatus);