diff --git a/src/tools/qml/qmlviewer/jsdebuggeragent.cpp b/src/tools/qml/qmlviewer/jsdebuggeragent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ede07ebda5750894f969876af6dfea7d81aa7624
--- /dev/null
+++ b/src/tools/qml/qmlviewer/jsdebuggeragent.cpp
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtSCriptTools module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "jsdebuggeragent.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qset.h>
+#include <QtScript/qscriptengine.h>
+#include <QtScript/QScriptContextInfo>
+#include <QtCore/QDebug>
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+  Constructs a new agent for the given \a engine. The agent will
+  report debugging-related events (e.g. step completion) to the given
+  \a backend.
+*/
+JSDebuggerAgent::JSDebuggerAgent(QScriptEngine *engine)
+    : QDeclarativeDebugService("JSDebugger"), QScriptEngineAgent(engine)
+{}
+
+/*!
+  Destroys this QScriptDebuggerAgent.
+*/
+JSDebuggerAgent::~JSDebuggerAgent()
+{}
+
+/*!
+  \reimp
+*/
+void JSDebuggerAgent::scriptLoad(qint64 id, const QString & program,
+                                      const QString &fileName, int )
+{
+    filenames.insert(id, QUrl(fileName).toLocalFile());
+    programs.insert(id, program);
+}
+
+/*!
+  \reimp
+*/
+void JSDebuggerAgent::scriptUnload(qint64 id)
+{
+    filenames.remove(id);
+}
+
+/*!
+  \reimp
+*/
+void JSDebuggerAgent::contextPush()
+{
+}
+
+/*!
+  \reimp
+*/
+void JSDebuggerAgent::contextPop()
+{
+}
+
+/*!
+  \reimp
+*/
+void JSDebuggerAgent::functionEntry(qint64 scriptId)
+{
+    Q_UNUSED(scriptId);
+    stepDepth++;
+}
+
+/*!
+  \reimp
+*/
+void JSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue)
+{
+    Q_UNUSED(scriptId);
+    Q_UNUSED(returnValue);
+    stepDepth--;
+}
+
+/*!
+  \reimp
+*/
+void JSDebuggerAgent::positionChange(qint64 scriptId,
+                                   int lineNumber, int columnNumber)
+{
+    Q_UNUSED(columnNumber);
+
+    if(state == Stopped)
+        return; //no re-entrency
+
+    // check breakpoints
+    if (!breakpointList.isEmpty()) {
+        QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
+        if (it != filenames.constEnd()) {
+            QPair<QString, qint32> key = qMakePair(*it, lineNumber);
+            if (breakpointList.contains(key)) {
+                stopped();
+                return;
+            }
+        }
+    }
+
+
+    switch (state) {
+    case NoState:
+    case Stopped:
+        // Do nothing
+        break;
+
+    case SteppingOutState:
+        if (stepDepth >= 0)
+            break;
+        //fallthough
+    case SteppingOverState:
+        if (stepDepth > 0)
+            break;
+        //fallthough
+    case SteppingIntoState:
+        qDebug() << programs.value(scriptId);
+        stopped();
+        break;
+    }
+
+}
+
+/*!
+  \reimp
+*/
+void JSDebuggerAgent::exceptionThrow(qint64 scriptId,
+                                   const QScriptValue &exception,
+                                   bool hasHandler)
+{
+    Q_UNUSED(scriptId);
+    Q_UNUSED(exception);
+    Q_UNUSED(hasHandler);
+/* ... */
+}
+
+/*!
+  \reimp
+*/
+void JSDebuggerAgent::exceptionCatch(qint64 scriptId,
+                                          const QScriptValue &exception)
+{
+    Q_UNUSED(scriptId);
+    Q_UNUSED(exception);
+}
+
+void JSDebuggerAgent::messageReceived(const QByteArray& message)
+{
+    QDataStream ds(message);
+    QByteArray command;
+    ds >> command;
+    if (command == "BREAKPOINTS") {
+        ds >> breakpointList;
+    } else if (command == "WATCH_EXPRESSIONS") {
+        ds >> watchExpressions;
+    } else if (command == "STEPOVER") {
+        stepDepth = 0;
+        state = SteppingOverState;
+        continueExec();
+    } else if (command == "STEPINTO" || command == "INTERRUPT") {
+        stepDepth = 0;
+        state = SteppingIntoState;
+        continueExec();
+    } else if (command == "STEPOUT") {
+        stepDepth = 0;
+        state = SteppingOutState;
+        continueExec();
+    } else if (command == "CONTINUE") {
+        state = NoState;
+        continueExec();
+    } else if (command == "EXEC") {
+        State oldState = state;
+        state = Stopped;
+        QByteArray id;
+        QString expr;
+        ds >> id >> expr;
+
+        QVariant val = engine()->evaluate(expr).toVariant();
+        // Clear any exceptions occurred during locals evaluation.
+        engine()->clearExceptions();
+
+        QByteArray reply;
+        QDataStream rs(&reply, QIODevice::WriteOnly);
+        rs << QByteArray("RESULT") << id << expr << val;
+        sendMessage(reply);
+        state = oldState;
+
+    } else {
+        qDebug() << Q_FUNC_INFO << "Unknown command" << command;
+    }
+
+    QDeclarativeDebugService::messageReceived(message);
+}
+
+void JSDebuggerAgent::stopped()
+{
+    state = Stopped;
+    QList<QPair<QString, QPair<QString, qint32> > > backtrace;
+
+    for (QScriptContext* ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
+        QScriptContextInfo info(ctx);
+
+        QString functionName = info.functionName();
+        if (functionName.isEmpty()) {
+            if (ctx->parentContext()) {
+                switch (info.functionType()) {
+                case QScriptContextInfo::ScriptFunction:
+                    functionName = QLatin1String("<anonymous>");
+                    break;
+                case QScriptContextInfo::NativeFunction:
+                    functionName = QLatin1String("<native>");
+                    break;
+                case QScriptContextInfo::QtFunction:
+                case QScriptContextInfo::QtPropertyFunction:
+                    functionName = QLatin1String("<native slot>");
+                    break;
+                }
+            } else {
+                functionName = QLatin1String("<global>");
+            }
+        }
+        backtrace.append(qMakePair(functionName, qMakePair( QUrl(info.fileName()).toLocalFile(), info.lineNumber() ) ) );
+    }
+    QList<QPair<QString, QVariant> > watches;
+    foreach (const QString &expr, watchExpressions) {
+        watches << qMakePair(expr,  engine()->evaluate(expr).toVariant());
+    }
+
+    // Clear any exceptions occurred during locals evaluation.
+    engine()->clearExceptions();
+
+
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    rs << QByteArray("STOPPED") << backtrace << watches;
+    sendMessage(reply);
+
+    loop.exec(QEventLoop::ExcludeUserInputEvents);
+}
+
+void JSDebuggerAgent::continueExec()
+{
+    loop.quit();
+}
+
+void JSDebuggerAgent::enabledChanged(bool on)
+{
+    engine()->setAgent(on ? this : 0);
+    QDeclarativeDebugService::enabledChanged(on);
+}
+
+QT_END_NAMESPACE
diff --git a/src/tools/qml/qmlviewer/jsdebuggeragent.h b/src/tools/qml/qmlviewer/jsdebuggeragent.h
new file mode 100644
index 0000000000000000000000000000000000000000..44002b9b5a7d193a4ed342c50c41e1537a4ddb90
--- /dev/null
+++ b/src/tools/qml/qmlviewer/jsdebuggeragent.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtSCriptTools module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTDEBUGGERAGENT_P_H
+#define QSCRIPTDEBUGGERAGENT_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtScript/qscriptengineagent.h>
+#include <QtCore/QEventLoop>
+#include <QtCore/QSet>
+#include <private/qdeclarativedebugservice_p.h>
+#include <QtCore/QStringList>
+
+
+QT_BEGIN_NAMESPACE
+
+class JSDebuggerAgent : public QDeclarativeDebugService , public QScriptEngineAgent
+{ Q_OBJECT
+public:
+    JSDebuggerAgent(QScriptEngine *engine);
+    ~JSDebuggerAgent();
+
+    // reimplemented
+    void scriptLoad(qint64 id, const QString &program,
+                    const QString &fileName, int baseLineNumber);
+    void scriptUnload(qint64 id);
+
+    void contextPush();
+    void contextPop();
+
+    void functionEntry(qint64 scriptId);
+    void functionExit(qint64 scriptId,
+                      const QScriptValue &returnValue);
+
+    void positionChange(qint64 scriptId,
+                        int lineNumber, int columnNumber);
+
+    void exceptionThrow(qint64 scriptId,
+                        const QScriptValue &exception,
+                        bool hasHandler);
+    void exceptionCatch(qint64 scriptId,
+                        const QScriptValue &exception);
+
+/*    bool supportsExtension(Extension extension) const;
+    QVariant extension(Extension extension,
+                       const QVariant &argument = QVariant());*/
+
+    void messageReceived(const QByteArray &);
+    void enabledChanged(bool);
+
+public slots:
+//    void pauses();
+
+private:
+    enum State {
+        NoState,
+        SteppingIntoState,
+        SteppingOverState,
+        SteppingOutState,
+        Stopped
+    };
+    State state;
+    int stepDepth;
+    int stepCount;
+
+    void continueExec();
+    void stopped();
+
+    QEventLoop loop;
+    QHash <qint64, QString> filenames;
+    QHash <qint64, QString> programs;
+    QSet< QPair<QString, qint32> > breakpointList;
+    QStringList watchExpressions;
+
+    Q_DISABLE_COPY(JSDebuggerAgent)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/tools/qml/qmlviewer/main.cpp b/src/tools/qml/qmlviewer/main.cpp
index 4c410eeb3127c658d7fbe8591557381e6e11e21c..b57e6093f7d60dbe06501ace804c6772d3996ef7 100644
--- a/src/tools/qml/qmlviewer/main.cpp
+++ b/src/tools/qml/qmlviewer/main.cpp
@@ -226,6 +226,7 @@ int main(int argc, char ** argv)
     bool useNativeFileBrowser = true;
     bool experimentalGestures = false;
     bool designModeBehavior = false;
+    bool debuggerModeBehavior = false;
 
     WarningsConfig warningsConfig = DefaultWarnings;
     bool sizeToView = true;
@@ -332,6 +333,8 @@ int main(int argc, char ** argv)
             experimentalGestures = true;
         } else if (arg == "-designmode") {
             designModeBehavior = true;
+        } else if (arg == "-debugger") {
+            debuggerModeBehavior = true;
         } else if (arg[0] != '-') {
             fileName = arg;
         } else if (1 || arg == "-help") {
@@ -406,6 +409,7 @@ int main(int argc, char ** argv)
         viewer->enableExperimentalGestures();
 
     viewer->setDesignModeBehavior(designModeBehavior);
+    viewer->setDebugMode(debuggerModeBehavior);
 
     foreach (QString lib, imports)
         viewer->addLibraryPath(lib);
diff --git a/src/tools/qml/qmlviewer/qml.pri b/src/tools/qml/qmlviewer/qml.pri
index bb12d683f51da30e34a55985cd2d899cc396d9b1..dff02fe71383fff1d342327b0b282ab17282f635 100644
--- a/src/tools/qml/qmlviewer/qml.pri
+++ b/src/tools/qml/qmlviewer/qml.pri
@@ -14,14 +14,17 @@ HEADERS += $$PWD/qmlruntime.h \
            $$PWD/deviceorientation.h \
            $$PWD/loggerwidget.h \
            $$PWD/qdeclarativedesigndebugserver.h \
-           $$PWD/qdeclarativedesignview.h
+           $$PWD/qdeclarativedesignview.h \
+           $$PWD/jsdebuggeragent.h
+
 
 SOURCES += $$PWD/qmlruntime.cpp \
            $$PWD/proxysettings.cpp \
            $$PWD/qdeclarativetester.cpp \
            $$PWD/loggerwidget.cpp \
            $$PWD/qdeclarativedesigndebugserver.cpp \
-           $$PWD/qdeclarativedesignview.cpp
+           $$PWD/qdeclarativedesignview.cpp \
+           $$PWD/jsdebuggeragent.cpp
 
 
 RESOURCES += $$PWD/qmlruntime.qrc
diff --git a/src/tools/qml/qmlviewer/qmlruntime.cpp b/src/tools/qml/qmlviewer/qmlruntime.cpp
index 9c09882322628c08f9176b1eb6d3b66066495bd0..0d725cf536c0298ee2bad0e8ca688439c35cf29a 100644
--- a/src/tools/qml/qmlviewer/qmlruntime.cpp
+++ b/src/tools/qml/qmlviewer/qmlruntime.cpp
@@ -62,6 +62,7 @@
 #include "qdeclarative.h"
 #include <QAbstractAnimation>
 #include <private/qabstractanimation_p.h>
+#include <private/qdeclarativeengine_p.h>
 
 #include <QSettings>
 #include <QXmlStreamReader>
@@ -101,6 +102,7 @@
 #endif
 
 #include <qdeclarativetester.h>
+#include "jsdebuggeragent.h"
 
 QT_BEGIN_NAMESPACE
 
@@ -634,6 +636,15 @@ void QDeclarativeViewer::setDesignModeBehavior(bool value)
     canvas->toolbar()->setEnabled(value);
 }
 
+void QDeclarativeViewer::setDebugMode(bool on)
+{
+    //if (on)
+    {
+        new JSDebuggerAgent(QDeclarativeEnginePrivate::getScriptEngine(canvas->engine()));
+    }
+}
+
+
 void QDeclarativeViewer::enableExperimentalGestures()
 {
     canvas->viewport()->grabGesture(Qt::TapGesture,Qt::DontStartGestureOnChildren|Qt::ReceivePartialGestures|Qt::IgnoredGesturesPropagateToParent);
diff --git a/src/tools/qml/qmlviewer/qmlruntime.h b/src/tools/qml/qmlviewer/qmlruntime.h
index 92dc09a0fe31a60751d72d4e60ea8bea119867db..f0d0e294399a90e48b7347f868397c054062438a 100644
--- a/src/tools/qml/qmlviewer/qmlruntime.h
+++ b/src/tools/qml/qmlviewer/qmlruntime.h
@@ -114,6 +114,7 @@ public:
 
 public slots:
     void setDesignModeBehavior(bool value);
+    void setDebugMode(bool on);
     void sceneResized(QSize size);
     bool open(const QString&);
     void openFile();