From a3b24d233c15674a0f82257ecd6ec96b9836a611 Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Wed, 27 Oct 2010 18:44:25 +0200
Subject: [PATCH] debugger: pimpl JSDebuggerAgent

---
 .../qmljsdebugger/include/jsdebuggeragent.h   |  44 ++---
 .../qml/qmljsdebugger/jsdebuggeragent.cpp     | 167 ++++++++++++------
 2 files changed, 124 insertions(+), 87 deletions(-)

diff --git a/share/qtcreator/qml/qmljsdebugger/include/jsdebuggeragent.h b/share/qtcreator/qml/qmljsdebugger/include/jsdebuggeragent.h
index 6b5ccff62b1..521ad0522e9 100644
--- a/share/qtcreator/qml/qmljsdebugger/include/jsdebuggeragent.h
+++ b/share/qtcreator/qml/qmljsdebugger/include/jsdebuggeragent.h
@@ -54,27 +54,26 @@
 //
 
 #include <QtScript/qscriptengineagent.h>
-#include <QtScript/QScriptValue>
-#include <QtCore/QEventLoop>
-#include <QtCore/QSet>
-#include <QtCore/QStringList>
 
 #include "qt_private/qdeclarativedebugservice_p.h"
 
 #include "qmljsdebugger_global.h"
 
-QT_FORWARD_DECLARE_CLASS(QScriptContext);
-QT_FORWARD_DECLARE_CLASS(QDeclarativeEngine);
+QT_BEGIN_NAMESPACE
+class QScriptValue;
+class QDeclarativeEngine;
+QT_END_NAMESPACE
 
 namespace QmlJSDebugger {
 
-class JSAgentWatchData;
-class SetupExecEnv;
+class JSDebuggerAgentPrivate;
 
 class QMLJSDEBUGGER_EXPORT JSDebuggerAgent
-  : public QDeclarativeDebugService, public QScriptEngineAgent
+    : public QDeclarativeDebugService
+    , public QScriptEngineAgent
 {
     Q_OBJECT
+
 public:
     JSDebuggerAgent(QScriptEngine *engine);
     JSDebuggerAgent(QDeclarativeEngine *engine);
@@ -107,35 +106,14 @@ public:
 
     void messageReceived(const QByteArray &);
     void statusChanged(Status status);
+    void baseMessageReceived(const QByteArray &message)
+        { QDeclarativeDebugService::messageReceived(message); }
 
 public slots:
 //    void pauses();
 
 private:
-    friend class SetupExecEnv;
-    enum State {
-        NoState,
-        SteppingIntoState,
-        SteppingOverState,
-        SteppingOutState,
-        Stopped
-    };
-    State state;
-    int stepDepth;
-    int stepCount;
-
-    void continueExec();
-    void stopped(bool becauseOfException = false, const QScriptValue &exception = QScriptValue());
-
-
-    void recordKnownObjects(const QList<JSAgentWatchData> &);
-    QList<JSAgentWatchData> getLocals(QScriptContext *);
-
-    QEventLoop loop;
-    QHash <qint64, QString> filenames;
-    QSet< QPair<QString, qint32> > breakpointList;
-    QStringList watchExpressions;
-    QSet<qint64> knownObjectIds;
+    JSDebuggerAgentPrivate *d;
 };
 
 } // namespace QmlJSDebugger
diff --git a/share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp b/share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp
index 8c9c9d1add9..60d691f5c37 100644
--- a/share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp
+++ b/share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp
@@ -53,32 +53,17 @@
 
 namespace QmlJSDebugger {
 
-class SetupExecEnv
+enum JSDebuggerState
 {
-public:
-    SetupExecEnv(JSDebuggerAgent *a)
-        : agent(a),
-          previousState(a->state),
-          hadException(a->engine()->hasUncaughtException())
-    {
-        agent->state = JSDebuggerAgent::Stopped;
-    }
-
-    ~SetupExecEnv() {
-        if (!hadException && agent->engine()->hasUncaughtException())
-            agent->engine()->clearExceptions();
-        agent->state = previousState;
-    }
-
-private:
-    JSDebuggerAgent *agent;
-    JSDebuggerAgent::State previousState;
-    bool hadException;
+    NoState,
+    SteppingIntoState,
+    SteppingOverState,
+    SteppingOutState,
+    StoppedState
 };
 
-class JSAgentWatchData
+struct JSAgentWatchData
 {
-public:
     QByteArray exp;
     QByteArray name;
     QByteArray value;
@@ -93,9 +78,8 @@ QDataStream &operator<<(QDataStream &s, const JSAgentWatchData &data)
         << data.type << data.hasChildren << data.objectId;
 }
 
-class JSAgentStackData
+struct JSAgentStackData
 {
-public:
     QByteArray functionName;
     QByteArray fileName;
     qint32 lineNumber;
@@ -106,6 +90,60 @@ QDataStream &operator<<(QDataStream &s, const JSAgentStackData &data)
     return s << data.functionName << data.fileName << data.lineNumber;
 }
 
+typedef JSAgentStackData JSBreakpointData;
+
+class JSDebuggerAgentPrivate
+{
+public:
+    JSDebuggerAgentPrivate(JSDebuggerAgent *q)
+        : q(q), state(NoState)
+    {}
+
+    void continueExec();
+    void recordKnownObjects(const QList<JSAgentWatchData> &);
+    QList<JSAgentWatchData> getLocals(QScriptContext *);
+    void positionChange(qint64 scriptId, int lineNumber, int columnNumber);
+    QScriptEngine *engine() { return q->engine(); }
+    void stopped();
+    void messageReceived(const QByteArray &message);
+    void sendMessage(const QByteArray &message) { q->sendMessage(message); }
+
+public:
+    JSDebuggerAgent *q;
+    JSDebuggerState state;
+    int stepDepth;
+    int stepCount;
+
+    QEventLoop loop;
+    QHash <qint64, QString> filenames;
+    QSet< QPair<QString, qint32> > breakpointList;
+    QStringList watchExpressions;
+    QSet<qint64> knownObjectIds;
+};
+
+class SetupExecEnv
+{
+public:
+    SetupExecEnv(JSDebuggerAgentPrivate *a)
+        : agent(a),
+          previousState(a->state),
+          hadException(a->engine()->hasUncaughtException())
+    {
+        agent->state = StoppedState;
+    }
+
+    ~SetupExecEnv()
+    {
+        if (!hadException && agent->engine()->hasUncaughtException())
+            agent->engine()->clearExceptions();
+        agent->state = previousState;
+    }
+
+private:
+    JSDebuggerAgentPrivate *agent;
+    JSDebuggerState previousState;
+    bool hadException;
+};
 
 static JSAgentWatchData fromScriptValue(const QString &expression,
     const QScriptValue &value)
@@ -194,20 +232,21 @@ static QList<JSAgentWatchData> expandObject(const QScriptValue &object)
     return result;
 }
 
-void JSDebuggerAgent::recordKnownObjects(const QList<JSAgentWatchData>& list)
+void JSDebuggerAgentPrivate::recordKnownObjects(const QList<JSAgentWatchData>& list)
 {
     foreach (const JSAgentWatchData &data, list)
         knownObjectIds << data.objectId;
 }
 
-QList<JSAgentWatchData> JSDebuggerAgent::getLocals(QScriptContext *ctx)
+QList<JSAgentWatchData> JSDebuggerAgentPrivate::getLocals(QScriptContext *ctx)
 {
     QList<JSAgentWatchData> locals;
     if (ctx) {
         QScriptValue activationObject = ctx->activationObject();
         QScriptValue thisObject = ctx->thisObject();
         locals = expandObject(activationObject);
-        if (thisObject.isObject() && thisObject.objectId() != engine()->globalObject().objectId())
+        if (thisObject.isObject()
+                && thisObject.objectId() != engine()->globalObject().objectId())
             locals.prepend(fromScriptValue("this", thisObject));
         recordKnownObjects(locals);
         knownObjectIds << activationObject.objectId();
@@ -221,30 +260,33 @@ QList<JSAgentWatchData> JSDebuggerAgent::getLocals(QScriptContext *ctx)
   \a backend.
 */
 JSDebuggerAgent::JSDebuggerAgent(QScriptEngine *engine)
-    : QDeclarativeDebugService("JSDebugger"), QScriptEngineAgent(engine)
-    , state(NoState)
+    : QDeclarativeDebugService("JSDebugger")
+    , QScriptEngineAgent(engine)
+    , d(new JSDebuggerAgentPrivate(this))
 {}
 
 JSDebuggerAgent::JSDebuggerAgent(QDeclarativeEngine *engine)
     : QDeclarativeDebugService("JSDebugger")
     , QScriptEngineAgent(QDeclarativeDebugHelper::getScriptEngine(engine))
-    , state(NoState)
+    , d(new JSDebuggerAgentPrivate(this))
 {}
 
 /*!
   Destroys this QScriptDebuggerAgent.
 */
 JSDebuggerAgent::~JSDebuggerAgent()
-{}
+{
+    delete d;
+}
 
 /*!
   \reimp
 */
-void JSDebuggerAgent::scriptLoad(qint64 id, const QString & program,
-                                      const QString &fileName, int )
+void JSDebuggerAgent::scriptLoad(qint64 id, const QString &program,
+                                 const QString &fileName, int)
 {
     Q_UNUSED(program);
-    filenames.insert(id, QUrl(fileName).toLocalFile());
+    d->filenames.insert(id, QUrl(fileName).toLocalFile());
 }
 
 /*!
@@ -252,7 +294,7 @@ void JSDebuggerAgent::scriptLoad(qint64 id, const QString & program,
 */
 void JSDebuggerAgent::scriptUnload(qint64 id)
 {
-    filenames.remove(id);
+    d->filenames.remove(id);
 }
 
 /*!
@@ -275,7 +317,7 @@ void JSDebuggerAgent::contextPop()
 void JSDebuggerAgent::functionEntry(qint64 scriptId)
 {
     Q_UNUSED(scriptId);
-    stepDepth++;
+    d->stepDepth++;
 }
 
 /*!
@@ -285,26 +327,38 @@ void JSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnVa
 {
     Q_UNUSED(scriptId);
     Q_UNUSED(returnValue);
-    stepDepth--;
+    d->stepDepth--;
 }
 
 /*!
   \reimp
 */
-void JSDebuggerAgent::positionChange(qint64 scriptId,
-                                   int lineNumber, int columnNumber)
+void JSDebuggerAgent::positionChange
+    (qint64 scriptId, int lineNumber, int columnNumber)
+{
+    d->positionChange(scriptId, lineNumber, columnNumber);
+}
+
+void JSDebuggerAgentPrivate::positionChange
+    (qint64 scriptId, int lineNumber, int columnNumber)
 {
     Q_UNUSED(columnNumber);
 
-    if (state == Stopped)
+    if (state == StoppedState)
         return; //no re-entrency
 
     // check breakpoints
     if (!breakpointList.isEmpty()) {
         QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
+        QScriptContext *ctx = engine()->currentContext();
+        QScriptContextInfo info(ctx);
         if (it == filenames.constEnd()) {
             // It is possible that the scripts are loaded before the agent is attached
-            QString filename = QUrl(QScriptContextInfo(engine()->currentContext()).fileName()).toLocalFile();
+            QString filename = QUrl(info.fileName()).toLocalFile();
+
+            JSAgentStackData frame;
+            frame.functionName = info.functionName().toUtf8();
+
             QPair<QString, qint32> key = qMakePair(filename, lineNumber);
             it = filenames.insert(scriptId, filename);
         }
@@ -317,7 +371,7 @@ void JSDebuggerAgent::positionChange(qint64 scriptId,
 
     switch (state) {
     case NoState:
-    case Stopped:
+    case StoppedState:
         // Do nothing
         break;
     case SteppingOutState:
@@ -347,7 +401,7 @@ void JSDebuggerAgent::exceptionThrow(qint64 scriptId,
     Q_UNUSED(hasHandler);
 //    qDebug() << Q_FUNC_INFO << exception.toString() << hasHandler;
 #if 0 //sometimes, we get exceptions that we should just ignore.
-    if (!hasHandler && state != Stopped)
+    if (!hasHandler && state != StoppedState)
         stopped(true, exception);
 #endif
 }
@@ -355,30 +409,32 @@ void JSDebuggerAgent::exceptionThrow(qint64 scriptId,
 /*!
   \reimp
 */
-void JSDebuggerAgent::exceptionCatch(qint64 scriptId,
-                                          const QScriptValue &exception)
+void JSDebuggerAgent::exceptionCatch(qint64 scriptId, const QScriptValue &exception)
 {
     Q_UNUSED(scriptId);
     Q_UNUSED(exception);
 }
 
-bool JSDebuggerAgent::supportsExtension(QScriptEngineAgent::Extension extension) const
+bool JSDebuggerAgent::supportsExtension(Extension extension) const
 {
     return extension == QScriptEngineAgent::DebuggerInvocationRequest;
 }
 
-QVariant JSDebuggerAgent::extension(QScriptEngineAgent::Extension extension, const QVariant& argument)
+QVariant JSDebuggerAgent::extension(Extension extension, const QVariant &argument)
 {
     if (extension == QScriptEngineAgent::DebuggerInvocationRequest) {
-        stopped();
+        d->stopped();
         return QVariant();
     }
     return QScriptEngineAgent::extension(extension, argument);
 }
 
+void JSDebuggerAgent::messageReceived(const QByteArray &message)
+{
+    d->messageReceived(message);
+}
 
-
-void JSDebuggerAgent::messageReceived(const QByteArray& message)
+void JSDebuggerAgentPrivate::messageReceived(const QByteArray &message)
 {
     QDataStream ds(message);
     QByteArray command;
@@ -484,13 +540,16 @@ void JSDebuggerAgent::messageReceived(const QByteArray& message)
         qDebug() << Q_FUNC_INFO << "Unknown command" << command;
     }
 
-    QDeclarativeDebugService::messageReceived(message);
+    q->baseMessageReceived(message);
 }
 
-void JSDebuggerAgent::stopped(bool becauseOfException, const QScriptValue &exception)
+void JSDebuggerAgentPrivate::stopped()
 {
+    bool becauseOfException = false;
+    const QScriptValue &exception = QScriptValue();
+
     knownObjectIds.clear();
-    state = Stopped;
+    state = StoppedState;
     QList<JSAgentStackData> backtrace;
 
     for (QScriptContext* ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
@@ -544,7 +603,7 @@ void JSDebuggerAgent::stopped(bool becauseOfException, const QScriptValue &excep
     loop.exec(QEventLoop::ExcludeUserInputEvents);
 }
 
-void JSDebuggerAgent::continueExec()
+void JSDebuggerAgentPrivate::continueExec()
 {
     loop.quit();
 }
-- 
GitLab