QV8Engine: Console APIs, Extend functionality
authorAurindam Jana <aurindam.jana@nokia.com>
Thu, 10 Nov 2011 14:59:05 +0000 (15:59 +0100)
committerQt by Nokia <qt-info@nokia.com>
Wed, 14 Dec 2011 03:51:21 +0000 (04:51 +0100)
Added console.trace, console.profile, console.profileEnd.

Change-Id: Icc38ddd550989eaba0085ece120695a13ec17322
Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
src/declarative/debugger/qdeclarativedebugtrace.cpp
src/declarative/debugger/qdeclarativedebugtrace_p.h
src/declarative/qml/v8/qdeclarativebuiltinfunctions.cpp
src/declarative/qml/v8/qdeclarativebuiltinfunctions_p.h
src/declarative/qml/v8/qv8engine.cpp
tests/auto/declarative/debugger/qdeclarativedebugtrace/tst_qdeclarativedebugtrace.cpp
tests/auto/declarative/qdeclarativeqt/data/console.qml [moved from tests/auto/declarative/qdeclarativeqt/data/consoleLog.qml with 83% similarity]
tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp

index c28a612..f3f8156 100644 (file)
@@ -98,57 +98,86 @@ void QDeclarativeDebugTrace::initialize()
     traceInstance();
 }
 
+bool QDeclarativeDebugTrace::startProfiling()
+{
+    return traceInstance()->startProfilingImpl();
+}
+
+bool QDeclarativeDebugTrace::stopProfiling()
+{
+    return traceInstance()->stopProfilingImpl();
+}
+
 void QDeclarativeDebugTrace::addEvent(EventType t)
 {
-    if (QDeclarativeDebugService::isDebuggingEnabled())
-        traceInstance()->addEventImpl(t);
+    traceInstance()->addEventImpl(t);
 }
 
 void QDeclarativeDebugTrace::startRange(RangeType t)
 {
-    if (QDeclarativeDebugService::isDebuggingEnabled())
-        traceInstance()->startRangeImpl(t);
+    traceInstance()->startRangeImpl(t);
 }
 
 void QDeclarativeDebugTrace::rangeData(RangeType t, const QString &data)
 {
-    if (QDeclarativeDebugService::isDebuggingEnabled())
-        traceInstance()->rangeDataImpl(t, data);
+    traceInstance()->rangeDataImpl(t, data);
 }
 
 void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &data)
 {
-    if (QDeclarativeDebugService::isDebuggingEnabled())
-        traceInstance()->rangeDataImpl(t, data);
+    traceInstance()->rangeDataImpl(t, data);
 }
 
 void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QString &fileName, int line)
 {
-    if (QDeclarativeDebugService::isDebuggingEnabled())
-        traceInstance()->rangeLocationImpl(t, fileName, line);
+    traceInstance()->rangeLocationImpl(t, fileName, line);
 }
 
 void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QUrl &fileName, int line)
 {
-    if (QDeclarativeDebugService::isDebuggingEnabled())
-        traceInstance()->rangeLocationImpl(t, fileName, line);
+    traceInstance()->rangeLocationImpl(t, fileName, line);
 }
 
 void QDeclarativeDebugTrace::endRange(RangeType t)
 {
-    if (QDeclarativeDebugService::isDebuggingEnabled())
-        traceInstance()->endRangeImpl(t);
+    traceInstance()->endRangeImpl(t);
 }
 
 void QDeclarativeDebugTrace::animationFrame(qint64 delta)
 {
-    Q_ASSERT(QDeclarativeDebugService::isDebuggingEnabled());
     traceInstance()->animationFrameImpl(delta);
 }
 
+void QDeclarativeDebugTrace::sendProfilingData()
+{
+    traceInstance()->sendMessages();
+}
+
+bool QDeclarativeDebugTrace::startProfilingImpl()
+{
+    bool success = false;
+    if (!profilingEnabled()) {
+        setProfilingEnabled(true);
+        addEventImpl(StartTrace);
+        success = true;
+    }
+    return success;
+}
+
+bool QDeclarativeDebugTrace::stopProfilingImpl()
+{
+    bool success = false;
+    if (profilingEnabled()) {
+        addEventImpl(EndTrace);
+        setProfilingEnabled(false);
+        success = true;
+    }
+    return success;
+}
+
 void QDeclarativeDebugTrace::addEventImpl(EventType event)
 {
-    if (status() != Enabled || !m_enabled)
+    if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
         return;
 
     QDeclarativeDebugData ed = {m_timer.nsecsElapsed(), (int)Event, (int)event, QString(), -1, 0, 0};
@@ -157,7 +186,7 @@ void QDeclarativeDebugTrace::addEventImpl(EventType event)
 
 void QDeclarativeDebugTrace::startRangeImpl(RangeType range)
 {
-    if (status() != Enabled || !m_enabled)
+    if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
         return;
 
     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeStart, (int)range, QString(), -1, 0, 0};
@@ -166,7 +195,7 @@ void QDeclarativeDebugTrace::startRangeImpl(RangeType range)
 
 void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData)
 {
-    if (status() != Enabled || !m_enabled)
+    if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
         return;
 
     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData, -1, 0, 0};
@@ -175,7 +204,7 @@ void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData
 
 void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData)
 {
-    if (status() != Enabled || !m_enabled)
+    if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
         return;
 
     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1, 0, 0};
@@ -184,7 +213,7 @@ void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData)
 
 void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QString &fileName, int line)
 {
-    if (status() != Enabled || !m_enabled)
+    if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
         return;
 
     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName, line, 0, 0};
@@ -193,7 +222,7 @@ void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QString &f
 
 void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QUrl &fileName, int line)
 {
-    if (status() != Enabled || !m_enabled)
+    if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
         return;
 
     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line, 0, 0};
@@ -202,7 +231,7 @@ void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QUrl &file
 
 void QDeclarativeDebugTrace::endRangeImpl(RangeType range)
 {
-    if (status() != Enabled || !m_enabled)
+    if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
         return;
 
     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeEnd, (int)range, QString(), -1, 0, 0};
@@ -211,7 +240,8 @@ void QDeclarativeDebugTrace::endRangeImpl(RangeType range)
 
 void QDeclarativeDebugTrace::animationFrameImpl(qint64 delta)
 {
-    if (status() != Enabled || !m_enabled)
+    Q_ASSERT(QDeclarativeDebugService::isDebuggingEnabled());
+    if (!m_enabled)
         return;
 
     int animCount = QUnifiedTimer::instance()->runningAnimationCount();
@@ -234,6 +264,16 @@ void QDeclarativeDebugTrace::processMessage(const QDeclarativeDebugData &message
     m_data.append(message);
 }
 
+bool QDeclarativeDebugTrace::profilingEnabled()
+{
+    return m_enabled;
+}
+
+void QDeclarativeDebugTrace::setProfilingEnabled(bool enable)
+{
+    m_enabled = enable;
+}
+
 /*
     Send the messages queued up by processMessage
 */
@@ -262,15 +302,11 @@ void QDeclarativeDebugTrace::messageReceived(const QByteArray &message)
 
     m_messageReceived = true;
 
-    if (m_enabled != enabled) {
-        if (enabled) {
-            m_enabled = true;
-            addEventImpl(StartTrace);
-        } else {
-            addEventImpl(EndTrace);
-            m_enabled = false;
+    if (enabled) {
+        startProfilingImpl();
+    } else {
+        if (stopProfilingImpl())
             sendMessages();
-        }
     }
 }
 
index bcea4d0..a52c3ea 100644 (file)
@@ -119,8 +119,9 @@ public:
 
     static void initialize();
 
+    static bool startProfiling();
+    static bool stopProfiling();
     static void addEvent(EventType);
-
     static void startRange(RangeType);
     static void rangeData(RangeType, const QString &);
     static void rangeData(RangeType, const QUrl &);
@@ -129,11 +130,17 @@ public:
     static void endRange(RangeType);
     static void animationFrame(qint64);
 
+    static void sendProfilingData();
+
     QDeclarativeDebugTrace();
     ~QDeclarativeDebugTrace();
+
 protected:
     virtual void messageReceived(const QByteArray &);
+
 private:
+    bool startProfilingImpl();
+    bool stopProfilingImpl();
     void addEventImpl(EventType);
     void startRangeImpl(RangeType);
     void rangeDataImpl(RangeType, const QString &);
@@ -142,8 +149,13 @@ private:
     void rangeLocationImpl(RangeType, const QUrl &, int);
     void endRangeImpl(RangeType);
     void animationFrameImpl(qint64);
-    void processMessage(const QDeclarativeDebugData &);
+
+    bool profilingEnabled();
+    void setProfilingEnabled(bool enable);
     void sendMessages();
+    void processMessage(const QDeclarativeDebugData &);
+
+private:
     QElapsedTimer m_timer;
     bool m_enabled;
     bool m_messageReceived;
index 8613ae4..d3d37c2 100644 (file)
@@ -48,6 +48,9 @@
 #include <private/qdeclarativelocale_p.h>
 #include <private/qv8engine_p.h>
 
+#include <private/qv8profilerservice_p.h>
+#include <private/qdeclarativedebugtrace_p.h>
+
 #include <QtCore/qstring.h>
 #include <QtCore/qdatetime.h>
 #include <QtCore/qcryptographichash.h>
@@ -55,6 +58,7 @@
 #include <QtCore/qsize.h>
 #include <QtCore/qpoint.h>
 #include <QtCore/qurl.h>
+#include <QtCore/qfile.h>
 #include <QtCore/qcoreapplication.h>
 
 #include <QtGui/qcolor.h>
@@ -139,6 +143,58 @@ v8::Handle<v8::Value> gc(const v8::Arguments &args)
     return v8::Undefined();
 }
 
+v8::Handle<v8::Value> consoleError(const v8::Arguments &args)
+{
+    return console(Error, args);
+}
+
+v8::Handle<v8::Value> consoleLog(const v8::Arguments &args)
+{
+    //console.log
+    //console.debug
+    //print
+    return console(Log, args);
+}
+
+v8::Handle<v8::Value> consoleProfile(const v8::Arguments &args)
+{
+    //DeclarativeDebugTrace cannot handle nested profiling
+    //although v8 can handle several profiling at once,
+    //we do not allow that. Hence, we pass an empty(default) title
+    Q_UNUSED(args);
+    QString title;
+
+    if (QDeclarativeDebugTrace::startProfiling()) {
+        QV8ProfilerService::instance()->startProfiling(title);
+        qDebug("Profiling started.");
+    } else {
+        qWarning("Profiling is already in progress. First, end current profiling session.");
+    }
+
+    return v8::Undefined();
+}
+
+v8::Handle<v8::Value> consoleProfileEnd(const v8::Arguments &args)
+{
+    //DeclarativeDebugTrace cannot handle nested profiling
+    //although v8 can handle several profiling at once,
+    //we do not allow that. Hence, we pass an empty(default) title
+    Q_UNUSED(args);
+    QString title;
+
+    if (QDeclarativeDebugTrace::stopProfiling()) {
+        QV8ProfilerService *profiler = QV8ProfilerService::instance();
+        profiler->stopProfiling(title);
+        QDeclarativeDebugTrace::sendProfilingData();
+        profiler->sendProfilingData();
+        qDebug("Profiling ended.");
+    } else {
+        qWarning("Profiling was not started.");
+    }
+
+    return v8::Undefined();
+}
+
 v8::Handle<v8::Value> consoleTime(const v8::Arguments &args)
 {
     if (args.Length() != 1)
@@ -161,12 +217,25 @@ v8::Handle<v8::Value> consoleTimeEnd(const v8::Arguments &args)
     return v8::Undefined();
 }
 
-v8::Handle<v8::Value> consoleLog(const v8::Arguments &args)
+v8::Handle<v8::Value> consoleTrace(const v8::Arguments &args)
 {
-    //console.log
-    //console.debug
-    //print
-    return console(Log, args);
+    if (args.Length() != 0)
+        V8THROW_ERROR("console.trace(): Invalid arguments");
+
+    //The v8 default is currently 10 stack frames.
+    v8::Handle<v8::StackTrace> stackTrace =
+        v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview);
+    int stackCount = stackTrace->GetFrameCount();
+
+    for (uint i = 0; i < stackCount; i++) {
+        v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(i);
+        v8::String::Utf8Value func_name(frame->GetFunctionName());
+        v8::String::Utf8Value script_name(frame->GetScriptName());
+        int lineNumber = frame->GetLineNumber();
+        int columnNumber = frame->GetColumn();
+        qDebug("%s (%s:%d:%d)\n", *func_name, *script_name, lineNumber, columnNumber);
+    }
+    return v8::Undefined();
 }
 
 v8::Handle<v8::Value> consoleWarn(const v8::Arguments &args)
@@ -174,11 +243,6 @@ v8::Handle<v8::Value> consoleWarn(const v8::Arguments &args)
     return console(Warn, args);
 }
 
-v8::Handle<v8::Value> consoleError(const v8::Arguments &args)
-{
-    return console(Error, args);
-}
-
 v8::Handle<v8::Value> stringArg(const v8::Arguments &args)
 {
     QString value = V8ENGINE()->toString(args.This()->ToString());
index 8a4ac06..dee0ffe 100644 (file)
@@ -61,11 +61,14 @@ QT_BEGIN_NAMESPACE
 namespace QDeclarativeBuiltinFunctions
 {
 v8::Handle<v8::Value> gc(const v8::Arguments &args);
-v8::Handle<v8::Value> consoleLog(const v8::Arguments &args);
-v8::Handle<v8::Value> consoleWarn(const v8::Arguments &args);
 v8::Handle<v8::Value> consoleError(const v8::Arguments &args);
+v8::Handle<v8::Value> consoleLog(const v8::Arguments &args);
+v8::Handle<v8::Value> consoleProfile(const v8::Arguments &args);
+v8::Handle<v8::Value> consoleProfileEnd(const v8::Arguments &args);
 v8::Handle<v8::Value> consoleTime(const v8::Arguments &args);
 v8::Handle<v8::Value> consoleTimeEnd(const v8::Arguments &args);
+v8::Handle<v8::Value> consoleTrace(const v8::Arguments &args);
+v8::Handle<v8::Value> consoleWarn(const v8::Arguments &args);
 v8::Handle<v8::Value> isQtObject(const v8::Arguments &args);
 v8::Handle<v8::Value> rgba(const v8::Arguments &args);
 v8::Handle<v8::Value> hsla(const v8::Arguments &args);
index 9b29aec..632a8ea 100644 (file)
@@ -525,16 +525,16 @@ void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global)
 
     v8::Local<v8::Object> console = v8::Object::New();
     v8::Local<v8::Function> consoleLogFn = V8FUNCTION(consoleLog, this);
-    v8::Local<v8::Function> consoleWarnFn = V8FUNCTION(consoleWarn, this);
-    v8::Local<v8::Function> consoleErrorFn = V8FUNCTION(consoleError, this);
-    v8::Local<v8::Function> consoleTimeFn = V8FUNCTION(consoleTime, this);
-    v8::Local<v8::Function> consoleTimeEndFn = V8FUNCTION(consoleTimeEnd, this);
-    console->Set(v8::String::New("log"), consoleLogFn);
+
     console->Set(v8::String::New("debug"), consoleLogFn);
-    console->Set(v8::String::New("warn"), consoleWarnFn);
-    console->Set(v8::String::New("error"), consoleErrorFn);
-    console->Set(v8::String::New("time"), consoleTimeFn);
-    console->Set(v8::String::New("timeEnd"), consoleTimeEndFn);
+    console->Set(v8::String::New("error"), V8FUNCTION(consoleError, this));
+    console->Set(v8::String::New("log"), consoleLogFn);
+    console->Set(v8::String::New("profile"), V8FUNCTION(consoleProfile, this));
+    console->Set(v8::String::New("profileEnd"), V8FUNCTION(consoleProfileEnd, this));
+    console->Set(v8::String::New("time"), V8FUNCTION(consoleTime, this));
+    console->Set(v8::String::New("timeEnd"), V8FUNCTION(consoleTimeEnd, this));
+    console->Set(v8::String::New("trace"), V8FUNCTION(consoleTrace, this));
+    console->Set(v8::String::New("warn"), V8FUNCTION(consoleWarn, this));
 
     v8::Local<v8::Object> qt = v8::Object::New();
 
index 3b5311e..0a23a5b 100644 (file)
@@ -226,6 +226,7 @@ void tst_QDeclarativeDebugTrace::blockingConnectWithTraceEnabled()
         QFAIL(qPrintable(failMsg));
     }
 
+    QVERIFY(m_client->traceMessages.count());
     // must start with "StartTrace"
     QCOMPARE(m_client->traceMessages.first().messageType, (int)QDeclarativeDebugTrace::Event);
     QCOMPARE(m_client->traceMessages.first().detailType, (int)QDeclarativeDebugTrace::StartTrace);
@@ -249,6 +250,8 @@ void tst_QDeclarativeDebugTrace::blockingConnectWithTraceDisabled()
         QFAIL(qPrintable(failMsg));
     }
 
+    QVERIFY(m_client->traceMessages.count());
+
     // must start with "StartTrace"
     QCOMPARE(m_client->traceMessages.first().messageType, (int)QDeclarativeDebugTrace::Event);
     QCOMPARE(m_client->traceMessages.first().detailType, (int)QDeclarativeDebugTrace::StartTrace);
@@ -11,7 +11,8 @@ QtObject {
         var f = true
         var g = {toString: function() { throw new Error('toString'); }}
 
-
+        console.profile("profile1")
+        console.time("timer1")
         console.log("completed", "ok")
         console.log("completed ok")
         console.debug("completed ok")
@@ -27,6 +28,9 @@ QtObject {
         console.log(g)
         console.log(1, "pong!", new Object)
         console.log(1, ["ping","pong"], new Object, 2)
+        console.trace()
+        console.timeEnd("timer1")
+        console.profileEnd("profile1")
         console.log(exception) //This has to be at the end
     }
 }
index 5b3ea5e..6171800 100644 (file)
@@ -78,7 +78,7 @@ private slots:
     void createComponent();
     void createComponent_pragmaLibrary();
     void createQmlObject();
-    void consoleLog();
+    void console();
     void dateTimeConversion();
     void dateTimeFormatting();
     void dateTimeFormatting_data();
@@ -458,10 +458,14 @@ void tst_qdeclarativeqt::createQmlObject()
     delete object;
 }
 
-void tst_qdeclarativeqt::consoleLog()
+void tst_qdeclarativeqt::console()
 {
-    int startLineNumber = 30;
-    QUrl testFileUrl = TEST_FILE("consoleLog.qml");
+    QUrl testFileUrl = TEST_FILE("console.qml");
+    QString testException = QString(QLatin1String("%1:%2: ReferenceError: Can't find variable: exception")).arg(testFileUrl.toString()).arg(34);
+    QString testTrace = QString(QLatin1String("onCompleted (%1:%2:%3)\n")).arg(testFileUrl.toString()).arg(31).arg(17);
+    QTest::ignoreMessage(QtDebugMsg, qPrintable(testTrace));
+    QTest::ignoreMessage(QtDebugMsg, "Profiling started.");
+    QTest::ignoreMessage(QtDebugMsg, "Profiling ended.");
     QTest::ignoreMessage(QtDebugMsg, "completed ok");
     QTest::ignoreMessage(QtDebugMsg, "completed ok");
     QTest::ignoreMessage(QtDebugMsg, "completed ok");
@@ -479,8 +483,9 @@ void tst_qdeclarativeqt::consoleLog()
     QTest::ignoreMessage(QtDebugMsg, "1 pong! Object");
     QTest::ignoreMessage(QtDebugMsg, "1 [ping,pong] Object 2");
 
-    QString testException = QString(QLatin1String("%1:%2: ReferenceError: Can't find variable: exception")).arg(testFileUrl.toString());
-    QTest::ignoreMessage(QtWarningMsg, qPrintable(testException.arg(startLineNumber++)));
+
+    QTest::ignoreMessage(QtWarningMsg, qPrintable(testException));
+
 
     QDeclarativeComponent component(&engine, testFileUrl);
     QObject *object = component.create();