aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/debugger/qdeclarativedebugserver.cpp228
-rw-r--r--src/declarative/debugger/qdeclarativedebugserver_p.h6
-rw-r--r--src/declarative/debugger/qdeclarativeenginedebugservice.cpp5
-rw-r--r--src/declarative/debugger/qdeclarativeenginedebugservice_p.h1
-rw-r--r--src/declarative/debugger/qdeclarativeinspectorservice.cpp5
-rw-r--r--src/declarative/debugger/qdeclarativeinspectorservice_p.h3
-rw-r--r--src/declarative/debugger/qv8debugservice.cpp135
-rw-r--r--src/declarative/debugger/qv8debugservice_p.h6
-rw-r--r--src/declarative/debugger/qv8profilerservice.cpp10
-rw-r--r--tests/auto/declarative/debugger/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp13
-rw-r--r--tests/auto/declarative/debugger/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp19
11 files changed, 276 insertions, 155 deletions
diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp
index 5c86c45116..b8963d24f3 100644
--- a/src/declarative/debugger/qdeclarativedebugserver.cpp
+++ b/src/declarative/debugger/qdeclarativedebugserver.cpp
@@ -47,6 +47,7 @@
#include <QtCore/QDir>
#include <QtCore/QPluginLoader>
#include <QtCore/QStringList>
+#include <QtCore/qwaitcondition.h>
#include <private/qobject_p.h>
#include <private/qcoreapplication_p.h>
@@ -80,6 +81,8 @@ const int protocolVersion = 1;
// print detailed information about loading of plugins
DEFINE_BOOL_CONFIG_OPTION(qmlDebugVerbose, QML_DEBUGGER_VERBOSE)
+class QDeclarativeDebugServerThread;
+
class QDeclarativeDebugServerPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QDeclarativeDebugServer)
@@ -87,30 +90,56 @@ public:
QDeclarativeDebugServerPrivate();
void advertisePlugins();
+ QDeclarativeDebugServerConnection *loadConnectionPlugin(const QString &pluginName);
QDeclarativeDebugServerConnection *connection;
QHash<QString, QDeclarativeDebugService *> plugins;
+ mutable QReadWriteLock pluginsLock;
QStringList clientPlugins;
bool gotHello;
- QString waitingForMsgFromService;
- bool waitingForMsgSucceeded;
+
+ QMutex messageArrivedMutex;
+ QWaitCondition messageArrivedCondition;
+ QStringList waitingForMessageNames;
+ QDeclarativeDebugServerThread *thread;
+ QPluginLoader loader;
private:
// private slot
- void _q_deliverMessage(const QString &serviceName, const QByteArray &message);
- static QDeclarativeDebugServerConnection *loadConnectionPlugin(QPluginLoader *loader, const QString &pluginName);
+ void _q_sendMessage(const QByteArray &message);
+};
+class QDeclarativeDebugServerThread : public QThread
+{
+public:
+ void setPluginName(const QString &pluginName) {
+ m_pluginName = pluginName;
+ }
+
+ void setPort(int port, bool block) {
+ m_port = port;
+ m_block = block;
+ }
+
+ void run();
+
+private:
+ QString m_pluginName;
+ int m_port;
+ bool m_block;
};
QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() :
connection(0),
gotHello(false),
- waitingForMsgSucceeded(false)
+ thread(0)
{
}
void QDeclarativeDebugServerPrivate::advertisePlugins()
{
+ Q_Q(QDeclarativeDebugServer);
+
if (!gotHello)
return;
@@ -119,11 +148,12 @@ void QDeclarativeDebugServerPrivate::advertisePlugins()
QDataStream out(&message, QIODevice::WriteOnly);
out << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys();
}
- connection->send(message);
+
+ QMetaObject::invokeMethod(q, "_q_sendMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
}
QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectionPlugin(
- QPluginLoader *loader, const QString &pluginName)
+ const QString &pluginName)
{
#ifndef QT_NO_LIBRARY
QStringList pluginCandidates;
@@ -143,14 +173,13 @@ QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectio
if (qmlDebugVerbose())
qDebug() << "QDeclarativeDebugServer: Trying to load plugin " << pluginPath << "...";
- loader->setFileName(pluginPath);
- if (!loader->load()) {
+ loader.setFileName(pluginPath);
+ if (!loader.load()) {
if (qmlDebugVerbose())
- qDebug() << "QDeclarativeDebugServer: Error while loading: " << loader->errorString();
+ qDebug() << "QDeclarativeDebugServer: Error while loading: " << loader.errorString();
continue;
}
- QDeclarativeDebugServerConnection *connection = 0;
- if (QObject *instance = loader->instance())
+ if (QObject *instance = loader.instance())
connection = qobject_cast<QDeclarativeDebugServerConnection*>(instance);
if (connection) {
@@ -163,12 +192,29 @@ QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectio
if (qmlDebugVerbose())
qDebug() << "QDeclarativeDebugServer: Plugin does not implement interface QDeclarativeDebugServerConnection.";
- loader->unload();
+ loader.unload();
}
#endif
return 0;
}
+void QDeclarativeDebugServerThread::run()
+{
+ QDeclarativeDebugServer *server = QDeclarativeDebugServer::instance();
+ QDeclarativeDebugServerConnection *connection
+ = server->d_func()->loadConnectionPlugin(m_pluginName);
+ if (connection) {
+ connection->setServer(QDeclarativeDebugServer::instance());
+ connection->setPort(m_port, m_block);
+ } else {
+ QCoreApplicationPrivate *appD = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
+ qWarning() << QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
+ "Remote debugger plugin has not been found.").arg(appD->qmljsDebugArgumentsString());
+ }
+
+ exec();
+}
+
bool QDeclarativeDebugServer::hasDebuggingClient() const
{
Q_D(const QDeclarativeDebugServer);
@@ -177,10 +223,11 @@ bool QDeclarativeDebugServer::hasDebuggingClient() const
&& d->gotHello;
}
+static QDeclarativeDebugServer *qDeclarativeDebugServer = 0;
+
QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
{
static bool commandLineTested = false;
- static QDeclarativeDebugServer *server = 0;
if (!commandLineTested) {
commandLineTested = true;
@@ -215,20 +262,22 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block"));
if (ok) {
- server = new QDeclarativeDebugServer();
- QPluginLoader *loader = new QPluginLoader(server);
- QDeclarativeDebugServerConnection *connection
- = QDeclarativeDebugServerPrivate::loadConnectionPlugin(loader, pluginName);
- if (connection) {
- server->d_func()->connection = connection;
-
- connection->setServer(server);
- connection->setPort(port, block);
- } else {
- qWarning() << QString::fromLatin1(
- "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
- "Remote debugger plugin has not been found.").arg(
- appD->qmljsDebugArgumentsString());
+ qDeclarativeDebugServer = new QDeclarativeDebugServer();
+
+ QDeclarativeDebugServerThread *thread = new QDeclarativeDebugServerThread;
+
+ qDeclarativeDebugServer = new QDeclarativeDebugServer();
+ qDeclarativeDebugServer->d_func()->thread = thread;
+ qDeclarativeDebugServer->moveToThread(thread);
+ thread->setPluginName(pluginName);
+ thread->setPort(port, block);
+ thread->start();
+
+ if (block) {
+ QDeclarativeDebugServerPrivate *d = qDeclarativeDebugServer->d_func();
+ d->messageArrivedMutex.lock();
+ d->messageArrivedCondition.wait(&d->messageArrivedMutex);
+ d->messageArrivedMutex.unlock();
}
} else {
@@ -248,7 +297,7 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
#endif
}
- return server;
+ return qDeclarativeDebugServer;
}
QDeclarativeDebugServer::QDeclarativeDebugServer()
@@ -261,6 +310,7 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
Q_D(QDeclarativeDebugServer);
QDataStream in(message);
+
QString name;
in >> name;
@@ -282,8 +332,9 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
d->gotHello = true;
- QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
- for (; iter != d->plugins.end(); ++iter) {
+ QReadLocker(&d->pluginsLock);
+ QHash<QString, QDeclarativeDebugService*>::ConstIterator iter = d->plugins.constBegin();
+ for (; iter != d->plugins.constEnd(); ++iter) {
QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
if (d->clientPlugins.contains(iter.key()))
newStatus = QDeclarativeDebugService::Enabled;
@@ -292,6 +343,7 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
}
qWarning("QDeclarativeDebugServer: Connection established");
+ d->messageArrivedCondition.wakeAll();
} else if (op == 1) {
@@ -299,8 +351,9 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
QStringList oldClientPlugins = d->clientPlugins;
in >> d->clientPlugins;
- QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
- for (; iter != d->plugins.end(); ++iter) {
+ QReadLocker(&d->pluginsLock);
+ QHash<QString, QDeclarativeDebugService*>::ConstIterator iter = d->plugins.constBegin();
+ for (; iter != d->plugins.constEnd(); ++iter) {
const QString pluginName = iter.key();
QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
if (d->clientPlugins.contains(pluginName))
@@ -324,18 +377,15 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
QByteArray message;
in >> message;
- if (d->waitingForMsgFromService == name) {
- // deliver directly so that it is delivered before waitForMessage is returning.
- d->_q_deliverMessage(name, message);
- d->waitingForMsgSucceeded = true;
+ QReadLocker(&d->pluginsLock);
+ QHash<QString, QDeclarativeDebugService *>::Iterator iter = d->plugins.find(name);
+ if (iter == d->plugins.end()) {
+ qWarning() << "QDeclarativeDebugServer: Message received for missing plugin" << name;
} else {
- // deliver message in next event loop run.
- // Fixes the case that the service does start it's own event loop ...,
- // but the networking code doesn't deliver any new messages because readyRead
- // hasn't returned.
- QMetaObject::invokeMethod(this, "_q_deliverMessage", Qt::QueuedConnection,
- Q_ARG(QString, name),
- Q_ARG(QByteArray, message));
+ (*iter)->messageReceived(message);
+
+ if (d->waitingForMessageNames.removeOne(name))
+ d->messageArrivedCondition.wakeAll();
}
} else {
qWarning("QDeclarativeDebugServer: Invalid hello message");
@@ -344,89 +394,105 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
}
}
-void QDeclarativeDebugServerPrivate::_q_deliverMessage(const QString &serviceName, const QByteArray &message)
+void QDeclarativeDebugServerPrivate::_q_sendMessage(const QByteArray &message)
{
- QHash<QString, QDeclarativeDebugService *>::Iterator iter = plugins.find(serviceName);
- if (iter == plugins.end()) {
- qWarning() << "QDeclarativeDebugServer: Message received for missing plugin" << serviceName;
- } else {
- (*iter)->messageReceived(message);
- }
+ if (connection)
+ connection->send(message);
}
QList<QDeclarativeDebugService*> QDeclarativeDebugServer::services() const
{
const Q_D(QDeclarativeDebugServer);
+ QReadLocker(&d->pluginsLock);
return d->plugins.values();
}
QStringList QDeclarativeDebugServer::serviceNames() const
{
const Q_D(QDeclarativeDebugServer);
+ QReadLocker(&d->pluginsLock);
return d->plugins.keys();
}
bool QDeclarativeDebugServer::addService(QDeclarativeDebugService *service)
{
Q_D(QDeclarativeDebugServer);
- if (!service || d->plugins.contains(service->name()))
- return false;
-
- d->plugins.insert(service->name(), service);
- d->advertisePlugins();
-
- QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
- if (d->clientPlugins.contains(service->name()))
- newStatus = QDeclarativeDebugService::Enabled;
- service->d_func()->status = newStatus;
- service->statusChanged(newStatus);
+ {
+ QWriteLocker(&d->pluginsLock);
+ if (!service || d->plugins.contains(service->name()))
+ return false;
+ d->plugins.insert(service->name(), service);
+ }
+ {
+ QReadLocker(&d->pluginsLock);
+ d->advertisePlugins();
+ QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
+ if (d->clientPlugins.contains(service->name()))
+ newStatus = QDeclarativeDebugService::Enabled;
+ service->d_func()->status = newStatus;
+ }
return true;
}
bool QDeclarativeDebugServer::removeService(QDeclarativeDebugService *service)
{
Q_D(QDeclarativeDebugServer);
- if (!service || !d->plugins.contains(service->name()))
- return false;
-
- d->plugins.remove(service->name());
- d->advertisePlugins();
+ {
+ QWriteLocker(&d->pluginsLock);
+ if (!service || !d->plugins.contains(service->name()))
+ return false;
+ d->plugins.remove(service->name());
+ }
+ {
+ QReadLocker(&d->pluginsLock);
+ d->advertisePlugins();
+ QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::NotConnected;
+ service->d_func()->server = 0;
+ service->d_func()->status = newStatus;
+ service->statusChanged(newStatus);
+
+ // Last service? Then stop thread & delete instance
+ if (d->plugins.isEmpty()) {
+ d->thread->exit();
+ d->thread->wait();
+ delete d->thread;
+ delete d->connection;
+
+ qDeclarativeDebugServer = 0;
+ deleteLater();
+ }
+ }
- QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::NotConnected;
- service->d_func()->server = 0;
- service->d_func()->status = newStatus;
- service->statusChanged(newStatus);
return true;
}
void QDeclarativeDebugServer::sendMessage(QDeclarativeDebugService *service,
const QByteArray &message)
{
- Q_D(QDeclarativeDebugServer);
QByteArray msg;
{
QDataStream out(&msg, QIODevice::WriteOnly);
out << service->name() << message;
}
- d->connection->send(msg);
+
+ QMetaObject::invokeMethod(this, "_q_sendMessage", Qt::QueuedConnection, Q_ARG(QByteArray, msg));
}
bool QDeclarativeDebugServer::waitForMessage(QDeclarativeDebugService *service)
{
Q_D(QDeclarativeDebugServer);
+ QReadLocker(&d->pluginsLock);
if (!service
- || !d->plugins.contains(service->name())
- || !d->waitingForMsgFromService.isEmpty())
+ || !d->plugins.contains(service->name()))
return false;
- d->waitingForMsgSucceeded = false;
- d->waitingForMsgFromService = service->name();
-
+ d->messageArrivedMutex.lock();
+ d->waitingForMessageNames << service->name();
do {
- d->connection->waitForMessage();
- } while (!d->waitingForMsgSucceeded);
- d->waitingForMsgFromService.clear();
+ d->messageArrivedCondition.wait(&d->messageArrivedMutex);
+ } while (d->waitingForMessageNames.contains(service->name()));
+ d->messageArrivedMutex.unlock();
return true;
}
diff --git a/src/declarative/debugger/qdeclarativedebugserver_p.h b/src/declarative/debugger/qdeclarativedebugserver_p.h
index d80633cd7d..1333634446 100644
--- a/src/declarative/debugger/qdeclarativedebugserver_p.h
+++ b/src/declarative/debugger/qdeclarativedebugserver_p.h
@@ -80,19 +80,21 @@ public:
QList<QDeclarativeDebugService*> services() const;
QStringList serviceNames() const;
+
bool addService(QDeclarativeDebugService *service);
bool removeService(QDeclarativeDebugService *service);
- void sendMessage(QDeclarativeDebugService *service, const QByteArray &message);
void receiveMessage(const QByteArray &message);
bool waitForMessage(QDeclarativeDebugService *service);
+ void sendMessage(QDeclarativeDebugService *service, const QByteArray &message);
private:
friend class QDeclarativeDebugService;
friend class QDeclarativeDebugServicePrivate;
+ friend class QDeclarativeDebugServerThread;
QDeclarativeDebugServer();
- Q_PRIVATE_SLOT(d_func(), void _q_deliverMessage(QString, QByteArray))
+ Q_PRIVATE_SLOT(d_func(), void _q_sendMessage(QByteArray))
};
QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativeenginedebugservice.cpp b/src/declarative/debugger/qdeclarativeenginedebugservice.cpp
index a1b02abe8e..ac188b0789 100644
--- a/src/declarative/debugger/qdeclarativeenginedebugservice.cpp
+++ b/src/declarative/debugger/qdeclarativeenginedebugservice.cpp
@@ -387,6 +387,11 @@ QDeclarativeEngineDebugService::objectData(QObject *object)
void QDeclarativeEngineDebugService::messageReceived(const QByteArray &message)
{
+ QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
+}
+
+void QDeclarativeEngineDebugService::processMessage(const QByteArray &message)
+{
QDataStream ds(message);
QByteArray type;
diff --git a/src/declarative/debugger/qdeclarativeenginedebugservice_p.h b/src/declarative/debugger/qdeclarativeenginedebugservice_p.h
index 3674b83fe7..d3e5c79297 100644
--- a/src/declarative/debugger/qdeclarativeenginedebugservice_p.h
+++ b/src/declarative/debugger/qdeclarativeenginedebugservice_p.h
@@ -104,6 +104,7 @@ protected:
virtual void messageReceived(const QByteArray &);
private Q_SLOTS:
+ void processMessage(const QByteArray &msg);
void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
private:
diff --git a/src/declarative/debugger/qdeclarativeinspectorservice.cpp b/src/declarative/debugger/qdeclarativeinspectorservice.cpp
index c3f90d2cab..90ab6ad6cb 100644
--- a/src/declarative/debugger/qdeclarativeinspectorservice.cpp
+++ b/src/declarative/debugger/qdeclarativeinspectorservice.cpp
@@ -133,6 +133,11 @@ void QDeclarativeInspectorService::updateStatus()
void QDeclarativeInspectorService::messageReceived(const QByteArray &message)
{
+ QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
+}
+
+void QDeclarativeInspectorService::processMessage(const QByteArray &message)
+{
if (m_currentInspectorPlugin)
m_currentInspectorPlugin->clientMessage(message);
}
diff --git a/src/declarative/debugger/qdeclarativeinspectorservice_p.h b/src/declarative/debugger/qdeclarativeinspectorservice_p.h
index 9aa71ae953..6362f5b159 100644
--- a/src/declarative/debugger/qdeclarativeinspectorservice_p.h
+++ b/src/declarative/debugger/qdeclarativeinspectorservice_p.h
@@ -83,6 +83,9 @@ protected:
virtual void statusChanged(Status status);
virtual void messageReceived(const QByteArray &);
+private slots:
+ void processMessage(const QByteArray &message);
+
private:
void updateStatus();
void loadInspectorPlugins();
diff --git a/src/declarative/debugger/qv8debugservice.cpp b/src/declarative/debugger/qv8debugservice.cpp
index 2f7ca348fd..f708f592b4 100644
--- a/src/declarative/debugger/qv8debugservice.cpp
+++ b/src/declarative/debugger/qv8debugservice.cpp
@@ -45,7 +45,6 @@
#include <private/qv8engine_p.h>
#include <private/qdeclarativeengine_p.h>
-#include <QtCore/QEventLoop>
#include <QtCore/QHash>
#include <QtCore/QFileInfo>
@@ -72,12 +71,9 @@ void DebugMessageHandler(const v8::Debug::Message& message)
message.GetJSON()));
QV8DebugService *service = QV8DebugService::instance();
- service->debugMessageHandler(response);
+ service->debugMessageHandler(response, message.WillStartRunning());
- if ((event == v8::Break || event == v8::Exception) &&
- !message.WillStartRunning()) {
- service->executionStopped();
- } else if (event == v8::AfterCompile) {
+ if (event == v8::AfterCompile) {
service->appendSourcePath(response);
} //TODO::v8::Exception
}
@@ -87,32 +83,41 @@ class QV8DebugServicePrivate : public QDeclarativeDebugServicePrivate
public:
QV8DebugServicePrivate()
:initialized(false)
+ , scheduleBreak(false)
+ , debuggerThreadIsolate(0)
+ , debuggerThreadEngine(0)
+ , isRunning(true)
{
- //Create a new isolate
- isolate = v8::Isolate::New();
-
- //Enter the isolate and initialize
- v8::Isolate::Scope i_scope(isolate);
+ //Create an isolate & engine in GUI thread
+ guiThreadIsolate = v8::Isolate::New();
+ v8::Isolate::Scope i_scope(guiThreadIsolate);
v8::V8::Initialize();
-
- //Create an instance in the new isolate
- engine = new QJSEngine();
+ guiThreadEngine = new QJSEngine();
}
~QV8DebugServicePrivate()
{
- delete engine;
- isolate->Dispose();
+ delete debuggerThreadEngine;
+ if (debuggerThreadIsolate)
+ debuggerThreadIsolate->Dispose();
+ delete guiThreadEngine;
+ if (guiThreadIsolate)
+ guiThreadIsolate->Dispose();
}
void sendDebugMessage(const QString &message);
static QByteArray packMessage(const QString &message);
bool initialized;
- QJSEngine *engine;
- v8::Isolate *isolate;
+ bool scheduleBreak;
+
+ v8::Isolate *debuggerThreadIsolate;
+ QJSEngine *debuggerThreadEngine;
+ v8::Isolate *guiThreadIsolate;
+ QJSEngine *guiThreadEngine;
+
QList<QDeclarativeEngine *> engines;
- QEventLoop loop;
+ bool isRunning;
QHash<QString, QString> sourcePath;
QHash<QString, QString> requestCache;
QHash<int, SignalHandlerData> handlersList;
@@ -166,20 +171,18 @@ void QV8DebugService::removeEngine(QDeclarativeEngine *engine)
d->engines.removeAll(engine);
}
-void QV8DebugService::debugMessageHandler(const QString &message)
-{
- sendMessage(QV8DebugServicePrivate::packMessage(message));
-}
-
-void QV8DebugService::executionStopped()
+void QV8DebugService::debugMessageHandler(const QString &message, bool willStartRunning)
{
Q_D(QV8DebugService);
+ d->isRunning = willStartRunning;
- if (!d->loop.isRunning()) {
- d->loop.exec(QEventLoop::ExcludeUserInputEvents);
- }
+ if (d->scheduleBreak)
+ scheduledDebugBreak();
+
+ sendMessage(QV8DebugServicePrivate::packMessage(message));
}
+
void QV8DebugService::appendSourcePath(const QString &message)
{
Q_D(QV8DebugService);
@@ -189,8 +192,8 @@ void QV8DebugService::appendSourcePath(const QString &message)
This will ensure that the debug message handler does not
receive any messages related to this operation */
{
- v8::Isolate::Scope i_scope(d->isolate);
- QJSValue parser = d->engine->evaluate(QLatin1String("JSON.parse"));
+ 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();
}
@@ -220,18 +223,26 @@ void QV8DebugService::signalEmitted(const QString &signal)
//is no need for additional check.
Q_D(QV8DebugService);
- bool debugBreak = false;
//Parse just the name and remove the class info
//Normalize to Lower case.
QString signalName = signal.left(signal.indexOf(QLatin1String("("))).toLower();
foreach (const SignalHandlerData &data, d->handlersList) {
if (data.functionName == signalName
&& data.enabled) {
- debugBreak = true;
+ d->scheduleBreak = true;
}
}
- if (debugBreak)
+ if (d->scheduleBreak)
+ scheduledDebugBreak();
+}
+
+void QV8DebugService::scheduledDebugBreak()
+{
+ Q_D(QV8DebugService);
+ if (d->scheduleBreak) {
v8::Debug::DebugBreak();
+ d->scheduleBreak = false;
+ }
}
void QV8DebugService::messageReceived(const QByteArray &message)
@@ -243,6 +254,16 @@ void QV8DebugService::messageReceived(const QByteArray &message)
ds >> command;
if (command == "V8DEBUG") {
+
+ if (!d->debuggerThreadEngine) {
+ //Create an isolate & engine in debugger thread
+ d->debuggerThreadIsolate = v8::Isolate::New();
+ v8::Isolate::Scope i_scope(d->debuggerThreadIsolate);
+ v8::V8::Initialize();
+ d->debuggerThreadEngine = new QJSEngine();
+ }
+
+
QString request;
{
QByteArray requestArray;
@@ -251,12 +272,9 @@ void QV8DebugService::messageReceived(const QByteArray &message)
}
QVariantMap reqMap;
- /* 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 i_scope(d->isolate);
- QJSValue parser = d->engine->evaluate(QLatin1String("JSON.parse"));
+ 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();
}
@@ -276,9 +294,9 @@ void QV8DebugService::messageReceived(const QByteArray &message)
// "success" : true
// }
{
- v8::Isolate::Scope i_scope(d->isolate);
const QString obj(QLatin1String("{}"));
- QJSValue parser = d->engine->evaluate(QLatin1String("JSON.parse"));
+ 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")));
@@ -286,16 +304,14 @@ void QV8DebugService::messageReceived(const QByteArray &message)
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->loop.isRunning()));
+ jsonVal.setProperty(QLatin1String("running"), QJSValue(d->isRunning));
- QJSValue stringify = d->engine->evaluate(QLatin1String("JSON.stringify"));
+ QJSValue stringify = d->debuggerThreadEngine->evaluate(QLatin1String("JSON.stringify"));
QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
- debugMessageHandler(json.toString());
-
+ sendMessage(QV8DebugServicePrivate::packMessage(json.toString()));
}
} else if (debugCommand == QLatin1String("interrupt")) {
- v8::Debug::DebugBreak();
//Prepare the response string
//Create a json message using v8 debugging protocol
//and send it to client
@@ -307,9 +323,9 @@ void QV8DebugService::messageReceived(const QByteArray &message)
// "success" : true
// }
{
- v8::Isolate::Scope i_scope(d->isolate);
const QString obj(QLatin1String("{}"));
- QJSValue parser = d->engine->evaluate(QLatin1String("JSON.parse"));
+ 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")));
@@ -317,14 +333,15 @@ void QV8DebugService::messageReceived(const QByteArray &message)
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->loop.isRunning()));
+ jsonVal.setProperty(QLatin1String("running"), QJSValue(d->isRunning));
- QJSValue stringify = d->engine->evaluate(QLatin1String("JSON.stringify"));
+ QJSValue stringify = d->debuggerThreadEngine->evaluate(QLatin1String("JSON.stringify"));
QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
- debugMessageHandler(json.toString());
-
+ 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;
@@ -363,9 +380,9 @@ void QV8DebugService::messageReceived(const QByteArray &message)
// "success" : true
// }
{
- v8::Isolate::Scope i_scope(d->isolate);
const QString obj(QLatin1String("{}"));
- QJSValue parser = d->engine->evaluate(QLatin1String("JSON.parse"));
+ 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")));
@@ -398,12 +415,11 @@ void QV8DebugService::messageReceived(const QByteArray &message)
}
- jsonVal.setProperty(QLatin1String("running"), QJSValue(!d->loop.isRunning()));
+ jsonVal.setProperty(QLatin1String("running"), QJSValue(d->isRunning));
- QJSValue stringify = d->engine->evaluate(QLatin1String("JSON.stringify"));
+ QJSValue stringify = d->debuggerThreadEngine->evaluate(QLatin1String("JSON.stringify"));
QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
- debugMessageHandler(json.toString());
-
+ sendMessage(QV8DebugServicePrivate::packMessage(json.toString()));
}
}
} else if (debugCommand == QLatin1String("changebreakpoint")) {
@@ -440,9 +456,6 @@ void QV8DebugService::messageReceived(const QByteArray &message)
void QV8DebugServicePrivate::sendDebugMessage(const QString &message)
{
- if (loop.isRunning())
- loop.exit();
-
v8::Debug::SendCommand(message.utf16(), message.size());
}
diff --git a/src/declarative/debugger/qv8debugservice_p.h b/src/declarative/debugger/qv8debugservice_p.h
index d8101ae3ff..9785bb9849 100644
--- a/src/declarative/debugger/qv8debugservice_p.h
+++ b/src/declarative/debugger/qv8debugservice_p.h
@@ -76,13 +76,15 @@ public:
void addEngine(QDeclarativeEngine *);
void removeEngine(QDeclarativeEngine *);
- void debugMessageHandler(const QString &message);
- void executionStopped();
+ void debugMessageHandler(const QString &message, bool willStartRunning);
void appendSourcePath(const QString &message);
void signalEmitted(const QString &signal);
+private slots:
+ void scheduledDebugBreak();
+
protected:
void messageReceived(const QByteArray &);
diff --git a/src/declarative/debugger/qv8profilerservice.cpp b/src/declarative/debugger/qv8profilerservice.cpp
index 48d2d1365d..807fe83b45 100644
--- a/src/declarative/debugger/qv8profilerservice.cpp
+++ b/src/declarative/debugger/qv8profilerservice.cpp
@@ -84,6 +84,7 @@ class QV8ProfilerServicePrivate : public QDeclarativeDebugServicePrivate
public:
QV8ProfilerServicePrivate()
:initialized(false)
+ , isolate(0)
{
}
@@ -96,6 +97,7 @@ public:
bool initialized;
QList<QDeclarativeEngine *> engines;
+ v8::Isolate *isolate;
};
QV8ProfilerService::QV8ProfilerService(QObject *parent)
@@ -146,6 +148,14 @@ void QV8ProfilerService::messageReceived(const QByteArray &message)
QByteArray title;
ds >> command >> option;
+ if (!d->isolate) {
+ d->isolate = v8::Isolate::New();
+ v8::Isolate::Scope scope(d->isolate);
+ v8::V8::Initialize();
+ }
+
+ v8::Isolate::Scope scope(d->isolate);
+
if (command == "V8PROFILER") {
ds >> title;
if (option == "start") {
diff --git a/tests/auto/declarative/debugger/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp b/tests/auto/declarative/debugger/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp
index 82e25598e9..46a711ae78 100644
--- a/tests/auto/declarative/debugger/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp
+++ b/tests/auto/declarative/debugger/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp
@@ -80,11 +80,16 @@ void tst_QDeclarativeDebugClient::initTestCase()
QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::handshake()", m_conn);
QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::handshake()");
- m_conn->connectToHost("127.0.0.1", PORT);
-
QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Connection established");
- bool ok = m_conn->waitForConnected();
- QVERIFY(ok);
+ for (int i = 0; i < 50; ++i) {
+ // try for 5 seconds ...
+ m_conn->connectToHost("127.0.0.1", PORT);
+ if (m_conn->waitForConnected())
+ break;
+ QTest::qSleep(100);
+ }
+
+ QVERIFY(m_conn->isConnected());
QTRY_VERIFY(QDeclarativeDebugService::hasDebuggingClient());
QTRY_COMPARE(client.status(), QDeclarativeDebugClient::Enabled);
diff --git a/tests/auto/declarative/debugger/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp b/tests/auto/declarative/debugger/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp
index 8f829a6468..6063c1fdcb 100644
--- a/tests/auto/declarative/debugger/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp
+++ b/tests/auto/declarative/debugger/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp
@@ -53,6 +53,8 @@
#include "../../shared/util.h"
#include "../shared/debugutil_p.h"
+#define PORT 13769
+#define STR_PORT "13769"
class tst_QDeclarativeDebugService : public QObject
{
@@ -73,15 +75,22 @@ private slots:
void tst_QDeclarativeDebugService::initTestCase()
{
- QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 13769...");
+ const QString waitingMsg = QString("QDeclarativeDebugServer: Waiting for connection on port %1...").arg(PORT);
+ QTest::ignoreMessage(QtWarningMsg, waitingMsg.toAscii().constData());
new QDeclarativeEngine(this);
m_conn = new QDeclarativeDebugConnection(this);
- m_conn->connectToHost("127.0.0.1", 13769);
+
QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Connection established");
- bool ok = m_conn->waitForConnected();
- QVERIFY(ok);
+ for (int i = 0; i < 50; ++i) {
+ // try for 5 seconds ...
+ m_conn->connectToHost("127.0.0.1", PORT);
+ if (m_conn->waitForConnected())
+ break;
+ QTest::qSleep(100);
+ }
+ QVERIFY(m_conn->isConnected());
QTRY_VERIFY(QDeclarativeDebugService::hasDebuggingClient());
}
@@ -187,7 +196,7 @@ int main(int argc, char *argv[])
char **_argv = new char*[_argc];
for (int i = 0; i < argc; ++i)
_argv[i] = argv[i];
- char arg[] = "-qmljsdebugger=port:13769";
+ char arg[] = "-qmljsdebugger=port:" STR_PORT;
_argv[_argc - 1] = arg;
QGuiApplication app(_argc, _argv);