From a7f5c93de3f9811eef3f5a19ab6dec83b997e0d6 Mon Sep 17 00:00:00 2001 From: Aurindam Jana Date: Tue, 8 Nov 2011 11:39:16 +0100 Subject: [PATCH] QV8Engine: Console APIs Modified functionality for console.log, console.debug. Added script and line information. Added functions console.warn and console.error. Change-Id: Id9f4dce5658a09b00522f8e087caf8f4242f418a Reviewed-by: Kai Koehne --- .../qml/v8/qdeclarativebuiltinfunctions.cpp | 86 ++++++++++++++++++---- .../qml/v8/qdeclarativebuiltinfunctions_p.h | 8 +- src/declarative/qml/v8/qv8engine.cpp | 16 ++-- .../tst_qdeclarativeanimations.cpp | 8 +- .../tst_qdeclarativeecmascript.cpp | 6 +- .../tst_qdeclarativelanguage.cpp | 18 +++-- .../declarative/qdeclarativeqt/data/consoleLog.qml | 22 ++++++ .../qdeclarativeqt/tst_qdeclarativeqt.cpp | 35 +++++++-- .../qdeclarativestates/tst_qdeclarativestates.cpp | 5 +- .../tst_qdeclarativevaluetypes.cpp | 5 +- 10 files changed, 164 insertions(+), 45 deletions(-) diff --git a/src/declarative/qml/v8/qdeclarativebuiltinfunctions.cpp b/src/declarative/qml/v8/qdeclarativebuiltinfunctions.cpp index 918fd52..fed0569 100644 --- a/src/declarative/qml/v8/qdeclarativebuiltinfunctions.cpp +++ b/src/declarative/qml/v8/qdeclarativebuiltinfunctions.cpp @@ -66,29 +66,69 @@ QT_BEGIN_NAMESPACE namespace QDeclarativeBuiltinFunctions { -v8::Handle gc(const v8::Arguments &args) -{ - Q_UNUSED(args); - QV8Engine::gc(); - return v8::Undefined(); -} +enum ConsoleLogTypes { + Log, + Warn, + Error +}; -v8::Handle print(const v8::Arguments &args) +v8::Handle console(ConsoleLogTypes logType, const v8::Arguments &args) { + int line = -1; + QString scriptName; + v8::HandleScope handleScope; + + { + v8::Local stackTrace = v8::StackTrace::CurrentStackTrace(1); + if (stackTrace->GetFrameCount()) { + v8::Local currentStackFrame = stackTrace->GetFrame(0); + line = currentStackFrame->GetLineNumber(); + scriptName = V8ENGINE()->toString(currentStackFrame->GetScriptName()); + } + } + QString result; for (int i = 0; i < args.Length(); ++i) { if (i != 0) result.append(QLatin1Char(' ')); - v8::Local jsstr = args[i]->ToString(); - if (!jsstr.IsEmpty()) { - QString qstr; - qstr.resize(jsstr->Length()); - jsstr->Write((uint16_t*)qstr.data()); - result.append(qstr); + v8::Local value = args[i]; + //Check for Object Type + if (value->IsObject() && !value->IsFunction() + && !value->IsArray() && !value->IsDate() + && !value->IsRegExp()) { + result = QLatin1String("Object"); + } else { + v8::Local jsstr = value->ToString(); + result.append(V8ENGINE()->toString(jsstr)); + if (value->IsArray()) + result = QString(QLatin1String("[%1]")).arg(result); } } - qDebug("%s", qPrintable(result)); + + QString log = QString(QLatin1String("%1 (%2:%3)")).arg(result).arg(scriptName).arg(line); + + switch (logType) { + case Log: + qDebug("%s", qPrintable(log)); + break; + case Warn: + qWarning("%s", qPrintable(log)); + break; + case Error: + qCritical("%s", qPrintable(log)); + break; + default: + break; + } + + return v8::Undefined(); +} + +v8::Handle gc(const v8::Arguments &args) +{ + Q_UNUSED(args); + QV8Engine::gc(); return v8::Undefined(); } @@ -114,6 +154,24 @@ v8::Handle consoleTimeEnd(const v8::Arguments &args) return v8::Undefined(); } +v8::Handle consoleLog(const v8::Arguments &args) +{ + //console.log + //console.debug + //print + return console(Log, args); +} + +v8::Handle consoleWarn(const v8::Arguments &args) +{ + return console(Warn, args); +} + +v8::Handle consoleError(const v8::Arguments &args) +{ + return console(Error, args); +} + v8::Handle stringArg(const v8::Arguments &args) { QString value = V8ENGINE()->toString(args.This()->ToString()); diff --git a/src/declarative/qml/v8/qdeclarativebuiltinfunctions_p.h b/src/declarative/qml/v8/qdeclarativebuiltinfunctions_p.h index 35ea885..8810f77 100644 --- a/src/declarative/qml/v8/qdeclarativebuiltinfunctions_p.h +++ b/src/declarative/qml/v8/qdeclarativebuiltinfunctions_p.h @@ -61,7 +61,11 @@ QT_BEGIN_NAMESPACE namespace QDeclarativeBuiltinFunctions { v8::Handle gc(const v8::Arguments &args); -v8::Handle print(const v8::Arguments &args); +v8::Handle consoleLog(const v8::Arguments &args); +v8::Handle consoleWarn(const v8::Arguments &args); +v8::Handle consoleError(const v8::Arguments &args); +v8::Handle consoleTime(const v8::Arguments &args); +v8::Handle consoleTimeEnd(const v8::Arguments &args); v8::Handle isQtObject(const v8::Arguments &args); v8::Handle rgba(const v8::Arguments &args); v8::Handle hsla(const v8::Arguments &args); @@ -91,8 +95,6 @@ v8::Handle qsTr(const v8::Arguments &args); v8::Handle qsTrNoOp(const v8::Arguments &args); v8::Handle qsTrId(const v8::Arguments &args); v8::Handle qsTrIdNoOp(const v8::Arguments &args); -v8::Handle consoleTime(const v8::Arguments &args); -v8::Handle consoleTimeEnd(const v8::Arguments &args); v8::Handle stringArg(const v8::Arguments &args); } diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp index 6f744e5..791c972 100644 --- a/src/declarative/qml/v8/qv8engine.cpp +++ b/src/declarative/qml/v8/qv8engine.cpp @@ -518,13 +518,17 @@ struct StaticQtMetaObject : public QObject void QV8Engine::initializeGlobal(v8::Handle global) { using namespace QDeclarativeBuiltinFunctions; - v8::Local printFn = V8FUNCTION(print, this); - v8::Local consoleTimeFn = V8FUNCTION(consoleTime, this); - v8::Local consoleTimeEndFn = V8FUNCTION(consoleTimeEnd, this); v8::Local console = v8::Object::New(); - console->Set(v8::String::New("log"), printFn); - console->Set(v8::String::New("debug"), printFn); + v8::Local consoleLogFn = V8FUNCTION(consoleLog, this); + v8::Local consoleWarnFn = V8FUNCTION(consoleWarn, this); + v8::Local consoleErrorFn = V8FUNCTION(consoleError, this); + v8::Local consoleTimeFn = V8FUNCTION(consoleTime, this); + v8::Local 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); @@ -579,7 +583,7 @@ void QV8Engine::initializeGlobal(v8::Handle global) global->Set(v8::String::New("qsTrId"), V8FUNCTION(qsTrId, this)); global->Set(v8::String::New("QT_TRID_NOOP"), V8FUNCTION(qsTrIdNoOp, this)); - global->Set(v8::String::New("print"), printFn); + global->Set(v8::String::New("print"), consoleLogFn); global->Set(v8::String::New("console"), console); global->Set(v8::String::New("Qt"), qt); global->Set(v8::String::New("gc"), V8FUNCTION(QDeclarativeBuiltinFunctions::gc, this)); diff --git a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp index 515c8fa..34b8e10 100644 --- a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp +++ b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp @@ -806,9 +806,11 @@ void tst_qdeclarativeanimations::attached() { QDeclarativeEngine engine; - QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("attached.qml"))); - QTest::ignoreMessage(QtDebugMsg, "off"); - QTest::ignoreMessage(QtDebugMsg, "on"); + QUrl url(QUrl::fromLocalFile(TESTDATA("attached.qml"))); + QDeclarativeComponent c(&engine, url); + QString messageFormat = QString(QLatin1String("%1 (%2:%3)")); + QTest::ignoreMessage(QtDebugMsg, messageFormat.arg(QLatin1String("off")).arg(url.toString()).arg(24).toLatin1()); + QTest::ignoreMessage(QtDebugMsg, messageFormat.arg(QLatin1String("on")).arg(url.toString()).arg(20).toLatin1()); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); } diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index cccbdb0..492ed73 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -1590,7 +1590,8 @@ void tst_qdeclarativeecmascript::shutdownErrors() void tst_qdeclarativeecmascript::compositePropertyType() { QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml")); - QTest::ignoreMessage(QtDebugMsg, "hello world"); + QString messageFormat = QString(QLatin1String("hello world (%1:%2)")).arg(TEST_FILE("compositePropertyType.qml").toString()).arg(7); + QTest::ignoreMessage(QtDebugMsg, qPrintable(messageFormat)); QObject *object = qobject_cast(component.create()); delete object; } @@ -4362,7 +4363,8 @@ void tst_qdeclarativeecmascript::qtbug_9792() MyQmlObject *object = qobject_cast(component.create(context)); QVERIFY(object != 0); - QTest::ignoreMessage(QtDebugMsg, "Hello world!"); + QString message = QString(QLatin1String("Hello world! (%1:%2)")).arg(TEST_FILE("qtbug_9792.qml").toString()).arg(4); + QTest::ignoreMessage(QtDebugMsg, qPrintable(message)); object->basicSignal(); delete context; diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp index 64ab5d8..a3fb5f0 100644 --- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -850,7 +850,8 @@ void tst_qdeclarativelanguage::dynamicObjectProperties() // Tests the declaration of dynamic signals and slots void tst_qdeclarativelanguage::dynamicSignalsAndSlots() { - QTest::ignoreMessage(QtDebugMsg, "1921"); + QString message = QString(QLatin1String("1921 (%1:%2)")).arg(TEST_FILE("dynamicSignalsAndSlots.qml").toString()).arg(9); + QTest::ignoreMessage(QtDebugMsg, qPrintable(message)); QDeclarativeComponent component(&engine, TEST_FILE("dynamicSignalsAndSlots.qml")); VERIFY_ERRORS(0); @@ -1288,9 +1289,10 @@ void tst_qdeclarativelanguage::onCompleted() { QDeclarativeComponent component(&engine, TEST_FILE("onCompleted.qml")); VERIFY_ERRORS(0); - QTest::ignoreMessage(QtDebugMsg, "Completed 6 10"); - QTest::ignoreMessage(QtDebugMsg, "Completed 6 10"); - QTest::ignoreMessage(QtDebugMsg, "Completed 10 11"); + QString formatMessage = QString(QLatin1String("%1 (%2:%3)")); + QTest::ignoreMessage(QtDebugMsg, formatMessage.arg(QLatin1String("Completed 6 10")).arg(TEST_FILE("onCompleted.qml").toString()).arg(8).toLatin1()); + QTest::ignoreMessage(QtDebugMsg, formatMessage.arg(QLatin1String("Completed 6 10")).arg(TEST_FILE("onCompleted.qml").toString()).arg(14).toLatin1()); + QTest::ignoreMessage(QtDebugMsg, formatMessage.arg(QLatin1String("Completed 10 11")).arg(TEST_FILE("OnCompletedType.qml").toString()).arg(7).toLatin1()); QObject *object = component.create(); QVERIFY(object != 0); } @@ -1302,10 +1304,10 @@ void tst_qdeclarativelanguage::onDestruction() VERIFY_ERRORS(0); QObject *object = component.create(); QVERIFY(object != 0); - - QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10"); - QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10"); - QTest::ignoreMessage(QtDebugMsg, "Destruction 10 11"); + QString formatMessage = QString(QLatin1String("%1 (%2:%3)")); + QTest::ignoreMessage(QtDebugMsg, formatMessage.arg(QLatin1String("Destruction 6 10")).arg(TEST_FILE("onDestruction.qml").toString()).arg(8).toLatin1()); + QTest::ignoreMessage(QtDebugMsg, formatMessage.arg(QLatin1String("Destruction 6 10")).arg(TEST_FILE("onDestruction.qml").toString()).arg(14).toLatin1()); + QTest::ignoreMessage(QtDebugMsg, formatMessage.arg(QLatin1String("Destruction 10 11")).arg(TEST_FILE("OnDestructionType.qml").toString()).arg(7).toLatin1()); delete object; } diff --git a/tests/auto/declarative/qdeclarativeqt/data/consoleLog.qml b/tests/auto/declarative/qdeclarativeqt/data/consoleLog.qml index 4c581cf..afb758a 100644 --- a/tests/auto/declarative/qdeclarativeqt/data/consoleLog.qml +++ b/tests/auto/declarative/qdeclarativeqt/data/consoleLog.qml @@ -1,8 +1,30 @@ import QtQuick 2.0 QtObject { + id: root Component.onCompleted: { + var a = [1, 2] + var b = {a: "hello", d: 1 } + var c + var d = 12 + var e = function() { return 5;} + var f = true + var g = {toString: function() { throw new Error('toString'); }} + + console.log("completed", "ok") console.log("completed ok") + console.debug("completed ok") + console.warn("completed ok") + console.error("completed ok") + console.log(a) + console.log(b) + console.log(c) + console.log(d) + console.log(e) + console.log(f) + console.log(root) + console.log(g) + console.log(exception) //This has to be at the end } } diff --git a/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp b/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp index b6cebf4..c550ac2 100644 --- a/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp +++ b/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp @@ -437,8 +437,8 @@ void tst_qdeclarativeqt::createQmlObject() QString warning3 = component.url().toString()+ ":11: Error: Qt.createQmlObject(): failed to create object: \n " + TEST_FILE("main.qml").toString() + ":4:1: Duplicate property name"; QString warning4 = component.url().toString()+ ":9: Error: Qt.createQmlObject(): Missing parent object"; QString warning5 = component.url().toString()+ ":8: Error: Qt.createQmlObject(): Invalid arguments"; - QString warning6 = "RunTimeError: Qt.createQmlObject(): failed to create object: \n " + TEST_FILE("inline").toString() + ":3: Cannot assign object type QObject with no default method"; - + QString messageFormat = QString(QLatin1String("%1 (%2:%3)")); + QString warning6 = messageFormat.arg("RunTimeError: Qt.createQmlObject(): failed to create object: \n " + TEST_FILE("inline").toString() + ":3: Cannot assign object type QObject with no default method").arg(TEST_FILE("createQmlObject.qml").toString()).arg(23); QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1)); QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2)); QTest::ignoreMessage(QtWarningMsg, qPrintable(warning3)); @@ -461,9 +461,34 @@ void tst_qdeclarativeqt::createQmlObject() void tst_qdeclarativeqt::consoleLog() { - QTest::ignoreMessage(QtDebugMsg, "completed ok"); - QTest::ignoreMessage(QtDebugMsg, "completed ok"); - QDeclarativeComponent component(&engine, TEST_FILE("consoleLog.qml")); + int startLineNumber = 15; + QUrl testFileUrl = TEST_FILE("consoleLog.qml"); + QString testString = QString(QLatin1String("completed ok (%1:%2)")).arg(testFileUrl.toString()); + QTest::ignoreMessage(QtDebugMsg, qPrintable(testString.arg(startLineNumber++))); + QTest::ignoreMessage(QtDebugMsg, qPrintable(testString.arg(startLineNumber++))); + QTest::ignoreMessage(QtDebugMsg, qPrintable(testString.arg(startLineNumber++))); + QTest::ignoreMessage(QtWarningMsg, qPrintable(testString.arg(startLineNumber++))); + QTest::ignoreMessage(QtCriticalMsg, qPrintable(testString.arg(startLineNumber++))); + + QString testArray = QString(QLatin1String("[1,2] (%1:%2)")).arg(testFileUrl.toString()); + QTest::ignoreMessage(QtDebugMsg, qPrintable(testArray.arg(startLineNumber++))); + QString testObject = QString(QLatin1String("Object (%1:%2)")).arg(testFileUrl.toString()); + QTest::ignoreMessage(QtDebugMsg, qPrintable(testObject.arg(startLineNumber++))); + QString testUndefined = QString(QLatin1String("undefined (%1:%2)")).arg(testFileUrl.toString()); + QTest::ignoreMessage(QtDebugMsg, qPrintable(testUndefined.arg(startLineNumber++))); + QString testNumber = QString(QLatin1String("12 (%1:%2)")).arg(testFileUrl.toString()); + QTest::ignoreMessage(QtDebugMsg, qPrintable(testNumber.arg(startLineNumber++))); + QString testFunction = QString(QLatin1String("function () { return 5;} (%1:%2)")).arg(testFileUrl.toString()); + QTest::ignoreMessage(QtDebugMsg, qPrintable(testFunction.arg(startLineNumber++))); + QString testBoolean = QString(QLatin1String("true (%1:%2)")).arg(testFileUrl.toString()); + QTest::ignoreMessage(QtDebugMsg, qPrintable(testBoolean.arg(startLineNumber++))); + QTest::ignoreMessage(QtDebugMsg, qPrintable(testObject.arg(startLineNumber++))); + QTest::ignoreMessage(QtDebugMsg, qPrintable(testObject.arg(startLineNumber++))); + + QString testException = QString(QLatin1String("%1:%2: ReferenceError: Can't find variable: exception")).arg(testFileUrl.toString()); + QTest::ignoreMessage(QtWarningMsg, qPrintable(testException.arg(startLineNumber++))); + + QDeclarativeComponent component(&engine, testFileUrl); QObject *object = component.create(); QVERIFY(object != 0); delete object; diff --git a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp index 05975aa..5c9760a 100644 --- a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp +++ b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp @@ -1228,8 +1228,9 @@ void tst_qdeclarativestates::tempState() QQuickRectangle *rect = qobject_cast(rectComponent.create()); QVERIFY(rect != 0); QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect); - QTest::ignoreMessage(QtDebugMsg, "entering placed"); - QTest::ignoreMessage(QtDebugMsg, "entering idle"); + QString messageFormat = QString(QLatin1String("%1 (file://%2:%3)")); + QTest::ignoreMessage(QtDebugMsg, messageFormat.arg(QLatin1String("entering placed")).arg(TESTDATA("legalTempState.qml")).arg(11).toLatin1()); + QTest::ignoreMessage(QtDebugMsg, messageFormat.arg(QLatin1String("entering idle")).arg(TESTDATA("legalTempState.qml")).arg(15).toLatin1()); rectPrivate->setState("placed"); QCOMPARE(rectPrivate->state(), QLatin1String("idle")); } diff --git a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp index db0e05b..b9a249f 100644 --- a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp +++ b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp @@ -1059,8 +1059,9 @@ void tst_qdeclarativevaluetypes::bindingConflict() // doesn't crash void tst_qdeclarativevaluetypes::deletedObject() { + QString messageFormat = QString(QLatin1String("%1 (%2:%3)")); QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml")); - QTest::ignoreMessage(QtDebugMsg, "Test: 2"); + QTest::ignoreMessage(QtDebugMsg, messageFormat.arg(QLatin1String("Test: 2")).arg(TEST_FILE("deletedObject.js").toString()).arg(6).toLatin1()); MyTypeObject *object = qobject_cast(component.create()); QVERIFY(object != 0); @@ -1068,7 +1069,7 @@ void tst_qdeclarativevaluetypes::deletedObject() QVERIFY(dObject != 0); delete dObject; - QTest::ignoreMessage(QtDebugMsg, "Test: undefined"); + QTest::ignoreMessage(QtDebugMsg, messageFormat.arg(QLatin1String("Test: undefined")).arg(TEST_FILE("deletedObject.js").toString()).arg(11).toLatin1()); object->emitRunScript(); delete object; -- 2.7.4