From 0f9cd5d0c7a9c58f0627d43e4a147d70b1e9f16a Mon Sep 17 00:00:00 2001 From: NeetBhagat Date: Thu, 1 Jun 2017 12:18:32 +0530 Subject: [PATCH 1/9] intial commit hifi: #21369 Implement parts of the JS "console" object --- interface/src/ui/JSConsole.cpp | 11 +- interface/src/ui/JSConsole.h | 6 +- interface/src/ui/TestingDialog.cpp | 3 +- .../src/ConsoleScriptingInterface.cpp | 137 ++++++++++++++++++ .../src/ConsoleScriptingInterface.h | 51 +++++++ libraries/script-engine/src/ScriptEngine.cpp | 6 +- libraries/script-engine/src/ScriptEngine.h | 5 +- scripts/developer/tests/printTest.js | 6 + 8 files changed, 217 insertions(+), 8 deletions(-) create mode 100644 libraries/script-engine/src/ConsoleScriptingInterface.cpp create mode 100644 libraries/script-engine/src/ConsoleScriptingInterface.h diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 79314ce49a..3c1787ab2e 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -21,6 +21,7 @@ #include "Application.h" #include "JSConsole.h" #include "ScriptHighlighting.h" +//#include "D:\Dhruvesh\Project\Hifi\github\hifi\libraries\script-engine\src\ScriptEngineLogging.h" const int NO_CURRENT_HISTORY_COMMAND = -1; const int MAX_HISTORY_SIZE = 64; @@ -84,6 +85,7 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) { disconnect(_scriptEngine, &ScriptEngine::infoMessage, this, &JSConsole::handleInfo); disconnect(_scriptEngine, &ScriptEngine::warningMessage, this, &JSConsole::handleWarning); disconnect(_scriptEngine, &ScriptEngine::errorMessage, this, &JSConsole::handleError); + disconnect(_scriptEngine, &ScriptEngine::clearDebugWindow, this, &JSConsole::clear); if (_ownScriptEngine) { _scriptEngine->deleteLater(); } @@ -97,6 +99,7 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) { connect(_scriptEngine, &ScriptEngine::infoMessage, this, &JSConsole::handleInfo); connect(_scriptEngine, &ScriptEngine::warningMessage, this, &JSConsole::handleWarning); connect(_scriptEngine, &ScriptEngine::errorMessage, this, &JSConsole::handleError); + connect(_scriptEngine, &ScriptEngine::clearDebugWindow, this, &JSConsole::clear); } void JSConsole::executeCommand(const QString& command) { @@ -144,6 +147,7 @@ void JSConsole::commandFinished() { void JSConsole::handleError(const QString& message, const QString& scriptName) { Q_UNUSED(scriptName); appendMessage(GUTTER_ERROR, "" + message.toHtmlEscaped() + ""); + } void JSConsole::handlePrint(const QString& message, const QString& scriptName) { @@ -291,11 +295,14 @@ void JSConsole::appendMessage(const QString& gutter, const QString& message) { } void JSConsole::clear() { + /* qCDebug(scriptengine) << "============================="; + qCDebug(scriptengine) << "Clear fUNCTION";*/ QLayoutItem* item; while ((item = _ui->logArea->layout()->takeAt(0)) != NULL) { + // qCDebug(scriptengine) << "While loop called"; delete item->widget(); delete item; } - _ui->logArea->updateGeometry(); - scrollToBottom(); + // _ui->logArea->updateGeometry(); + // scrollToBottom(); } diff --git a/interface/src/ui/JSConsole.h b/interface/src/ui/JSConsole.h index 864f847071..1e33414183 100644 --- a/interface/src/ui/JSConsole.h +++ b/interface/src/ui/JSConsole.h @@ -32,8 +32,7 @@ public: JSConsole(QWidget* parent, ScriptEngine* scriptEngine = NULL); ~JSConsole(); - void setScriptEngine(ScriptEngine* scriptEngine = NULL); - void clear(); + void setScriptEngine(ScriptEngine* scriptEngine = NULL); public slots: void executeCommand(const QString& command); @@ -51,7 +50,8 @@ protected slots: void handleInfo(const QString& message, const QString& scriptName); void handleWarning(const QString& message, const QString& scriptName); void handleError(const QString& message, const QString& scriptName); - void commandFinished(); + void commandFinished(); + void clear(); private: void appendMessage(const QString& gutter, const QString& message); diff --git a/interface/src/ui/TestingDialog.cpp b/interface/src/ui/TestingDialog.cpp index f55eb63a5b..10e66e05a1 100644 --- a/interface/src/ui/TestingDialog.cpp +++ b/interface/src/ui/TestingDialog.cpp @@ -26,10 +26,11 @@ TestingDialog::TestingDialog(QWidget* parent) : auto _engines = DependencyManager::get(); _engine = _engines->loadScript(qApp->applicationDirPath() + testRunnerRelativePath); _console->setScriptEngine(_engine); - connect(_engine, &ScriptEngine::finished, this, &TestingDialog::onTestingFinished); + connect(_engine, &ScriptEngine::finished, this, &TestingDialog::onTestingFinished); } void TestingDialog::onTestingFinished(const QString& scriptPath) { _engine = nullptr; _console->setScriptEngine(nullptr); + } diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.cpp b/libraries/script-engine/src/ConsoleScriptingInterface.cpp new file mode 100644 index 0000000000..4131f81320 --- /dev/null +++ b/libraries/script-engine/src/ConsoleScriptingInterface.cpp @@ -0,0 +1,137 @@ +// +// ConsoleScriptingInterface.cpp +// libraries/script-engine/src +// +// Created by volansystech on 6/1/17. +// Copyright 2014 High Fidelity, Inc. +// +// ConsoleScriptingInterface is responsible to print logs +// using "console" object on debug Window and Logs/log file with proper tags. +// Used in Javascripts file. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ConsoleScriptingInterface.h" +#include "ScriptEngine.h" + +void ConsoleScriptingInterface::info(QString message) { + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptInfoMessage(message); + } +} + +void ConsoleScriptingInterface::log(QString message) { + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptPrintedMessage(message); + } +} + +void ConsoleScriptingInterface::debug(QString message) { + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptPrintedMessage(message); + } +} + +void ConsoleScriptingInterface::warn(QString message) { + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptWarningMessage(message); + } +} + +void ConsoleScriptingInterface::error(QString message) { + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptErrorMessage(message); + } +} + +void ConsoleScriptingInterface::exception(QString message) { + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptErrorMessage(message); + } +} + +void ConsoleScriptingInterface::time(QString labelName) { + QDateTime date; + std::string val_string = "2017-06-06 11:15:00.000"; + QString d = QString::fromStdString(val_string.substr(0, 19)); + date = QDateTime::fromString(d, "yyyy-MM-dd HH:mm:ss"); + qDebug() << d; + qDebug() << d.length() << date.toUTC(); + + QDateTime _currentTime = QDateTime::currentDateTime().toUTC(); + _listOfTimeValues.insert(labelName, date.toUTC()); +} + +void ConsoleScriptingInterface::timeEnd(QString labelName) { + QDateTime _dateTimeOfLabel; + QString message; + qint64 millisecondsDiff = 0; + + bool _labelInList = _listOfTimeValues.contains(labelName); + + //Check if not exist items in list + if (!_labelInList) { + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + message = "No such label found " + labelName; + scriptEngine->scriptErrorMessage(message); + } + return; + } + QDateTime _currentDateTimeValue = QDateTime::currentDateTime().toUTC(); + _dateTimeOfLabel = _listOfTimeValues.value(labelName); + + if (!_dateTimeOfLabel.isNull()) { + _listOfTimeValues.remove(labelName); + } + + if (_dateTimeOfLabel.toString(TIME_FORMAT) == _currentDateTimeValue.toString(TIME_FORMAT)) { + millisecondsDiff = _dateTimeOfLabel.msecsTo(_currentDateTimeValue); + message = QString::number(millisecondsDiff) + " ms"; + } else { + message = secondsToString(_dateTimeOfLabel.secsTo(_currentDateTimeValue)); + } + + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptPrintedMessage("Time : " + message); + } +} + +QString ConsoleScriptingInterface::secondsToString(qint64 seconds) +{ + qint64 days = seconds / DAY; + QTime timeDuration = QTime(0, 0).addSecs(seconds % DAY); + + return QString("%1 days, %2 hours, %3 minutes, %4 seconds") + .arg(QString::number(days)).arg(QString::number(timeDuration.hour())).arg(QString::number(timeDuration.minute())).arg(QString::number(timeDuration.second())); +} + +void ConsoleScriptingInterface::asserts(bool condition, QString message) { + if (!condition) { + QString assertFailed = "Assertion failed"; + if (message.isEmpty()) { + message = assertFailed; + } else { + if (typeid(message) != typeid(QString)) { + message = assertFailed; + } else { + message = assertFailed + " " + message; + } + } + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptErrorMessage(message); + } + } +} + +void ConsoleScriptingInterface::trace(QString labelName) { + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptErrorMessage(labelName); + } +} +void ConsoleScriptingInterface::clear() { + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->clearConsole(); + } +} \ No newline at end of file diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.h b/libraries/script-engine/src/ConsoleScriptingInterface.h new file mode 100644 index 0000000000..70969a11fb --- /dev/null +++ b/libraries/script-engine/src/ConsoleScriptingInterface.h @@ -0,0 +1,51 @@ +// +// ConsoleScriptingInterface.h +// libraries/script-engine/src +// +// Created by volansystech on 6/1/17. +// Copyright 2014 High Fidelity, Inc. +// +// ConsoleScriptingInterface is responsible to print log. +// using "console" object on debug Window and Logs/log file with proper tags. +// Used in Javascripts file. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once +#ifndef hifi_ConsoleScriptingInterface_h +#define hifi_ConsoleScriptingInterface_h + + +#include +#include +#include +#include + + +/// Scriptable interface of console object. Used exclusively in the JavaScript API +class ConsoleScriptingInterface : public QObject, protected QScriptable { + Q_OBJECT +public slots: + void info(QString message); + void log(QString message); + void debug(QString message); + void warn(QString message); + void error(QString message); + void exception(QString message); + void time(QString labelName); + void timeEnd(QString labelName); + void asserts(bool condition, QString data=""); + void trace(QString labelName); + void clear(); +public: + QString secondsToString(qint64 seconds); + bool isInteger(const std::string & s); +private: + QMap _listOfTimeValues; + const qint64 DAY = 86400; + const QString TIME_FORMAT = "yyyy-MM-dd HH:mm"; +}; + +#endif // hifi_ConsoleScriptingInterface_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 61bf601019..add7ab411d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -485,7 +485,10 @@ void ScriptEngine::scriptPrintedMessage(const QString& message) { qCDebug(scriptengine) << message; emit printedMessage(message, getFilename()); } - +void ScriptEngine::clearConsole() { + qCDebug(scriptengine) << "Clearing debug window"; + emit clearDebugWindow(); +} // Even though we never pass AnimVariantMap directly to and from javascript, the queued invokeMethod of // callAnimationStateHandler requires that the type be registered. // These two are meaningful, if we ever do want to use them... @@ -665,6 +668,7 @@ void ScriptEngine::init() { registerGlobalObject("Entities", entityScriptingInterface.data()); registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); + registerGlobalObject("console", &_consoleScriptingInterface); registerGlobalObject("Mat4", &_mat4Library); registerGlobalObject("Uuid", &_uuidLibrary); registerGlobalObject("Messages", DependencyManager::get().data()); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 010cdfbc75..a12a399b84 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -41,6 +41,7 @@ #include "ScriptCache.h" #include "ScriptUUID.h" #include "Vec3.h" +#include "ConsoleScriptingInterface.h" #include "SettingHandle.h" class QScriptEngineDebugger; @@ -225,7 +226,7 @@ public: void scriptWarningMessage(const QString& message); void scriptInfoMessage(const QString& message); void scriptPrintedMessage(const QString& message); - + void clearConsole(); int getNumRunningEntityScripts() const; bool getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const; @@ -245,6 +246,7 @@ signals: void warningMessage(const QString& message, const QString& scriptName); void infoMessage(const QString& message, const QString& scriptName); void runningStateChanged(); + void clearDebugWindow(); void loadScript(const QString& scriptName, bool isUserLoaded); void reloadScript(const QString& scriptName, bool isUserLoaded); void doneRunning(); @@ -305,6 +307,7 @@ protected: Vec3 _vec3Library; Mat4 _mat4Library; ScriptUUID _uuidLibrary; + ConsoleScriptingInterface _consoleScriptingInterface; std::atomic _isUserLoaded { false }; bool _isReloading { false }; diff --git a/scripts/developer/tests/printTest.js b/scripts/developer/tests/printTest.js index c1fe6ec745..4e6d68e170 100644 --- a/scripts/developer/tests/printTest.js +++ b/scripts/developer/tests/printTest.js @@ -36,4 +36,10 @@ function main() { Uuid.print('[Uuid.print]', Uuid.fromString(Uuid.toString(0))); } + console.info('[console.info] hello world'); + console.log('[console.log] hello world'); + console.debug('[console.Debug] hello world'); + console.warn('[console.Warn] hello world'); + console.error('[console.error] hello world'); + console.exception('[console.exception] hello world'); } From 904e25c9e3d031bb1b99373cd1b1ca73ab25afaf Mon Sep 17 00:00:00 2001 From: NeetBhagat Date: Tue, 6 Jun 2017 19:00:21 +0530 Subject: [PATCH 2/9] intial commit #21369 Working on clear method of console --- interface/resources/qml/QmlWindow.qml | 6 + interface/src/Application.cpp | 1 + interface/src/ui/JSConsole.cpp | 43 +++--- interface/src/ui/JSConsole.h | 10 +- interface/src/ui/TestingDialog.cpp | 7 +- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 141 ++++++++++-------- libraries/gl/src/gl/OffscreenQmlSurface.h | 44 +++--- libraries/script-engine/src/ScriptEngine.cpp | 3 +- libraries/script-engine/src/ScriptEngines.cpp | 4 + libraries/script-engine/src/ScriptEngines.h | 2 + libraries/ui/src/QmlWindowClass.cpp | 3 + libraries/ui/src/QmlWindowClass.h | 1 + scripts/developer/debugging/debugWindow.js | 4 + scripts/developer/debugging/debugWindow.qml | 6 +- 14 files changed, 154 insertions(+), 121 deletions(-) diff --git a/interface/resources/qml/QmlWindow.qml b/interface/resources/qml/QmlWindow.qml index ac18d36ce6..2fb8bac1ec 100644 --- a/interface/resources/qml/QmlWindow.qml +++ b/interface/resources/qml/QmlWindow.qml @@ -74,6 +74,12 @@ Windows.Window { root.dynamicContent.fromScript(message); } } + + function fromConsole() { + if (root.dynamicContent && root.dynamicContent.fromConsole) { + root.dynamicContent.fromConsole(); + } + } // Handle message traffic from our loaded QML to the script that launched us signal sendToScript(var message); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a726785746..f5f97bd106 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5514,6 +5514,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri connect(scriptEngine, &ScriptEngine::errorMessage, DependencyManager::get().data(), &ScriptEngines::onErrorMessage); connect(scriptEngine, &ScriptEngine::warningMessage, DependencyManager::get().data(), &ScriptEngines::onWarningMessage); connect(scriptEngine, &ScriptEngine::infoMessage, DependencyManager::get().data(), &ScriptEngines::onInfoMessage); + connect(scriptEngine, &ScriptEngine::clearDebugWindow, DependencyManager::get().data(), &ScriptEngines::OnClearConsole); } bool Application::canAcceptURL(const QString& urlString) const { diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 3c1787ab2e..d8710c3135 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -21,7 +21,6 @@ #include "Application.h" #include "JSConsole.h" #include "ScriptHighlighting.h" -//#include "D:\Dhruvesh\Project\Hifi\github\hifi\libraries\script-engine\src\ScriptEngineLogging.h" const int NO_CURRENT_HISTORY_COMMAND = -1; const int MAX_HISTORY_SIZE = 64; @@ -36,15 +35,15 @@ const QString RESULT_ERROR_STYLE = "color: #d13b22;"; const QString GUTTER_PREVIOUS_COMMAND = "<"; const QString GUTTER_ERROR = "X"; -const QString JSConsole::_consoleFileName { "about:console" }; +const QString JSConsole::_consoleFileName{ "about:console" }; JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : - QWidget(parent), - _ui(new Ui::Console), - _currentCommandInHistory(NO_CURRENT_HISTORY_COMMAND), - _commandHistory(), - _ownScriptEngine(scriptEngine == NULL), - _scriptEngine(NULL) { +QWidget(parent), +_ui(new Ui::Console), +_currentCommandInHistory(NO_CURRENT_HISTORY_COMMAND), +_commandHistory(), +_ownScriptEngine(scriptEngine == NULL), +_scriptEngine(NULL) { _ui->setupUi(this); _ui->promptTextEdit->setLineWrapMode(QTextEdit::NoWrap); @@ -85,7 +84,6 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) { disconnect(_scriptEngine, &ScriptEngine::infoMessage, this, &JSConsole::handleInfo); disconnect(_scriptEngine, &ScriptEngine::warningMessage, this, &JSConsole::handleWarning); disconnect(_scriptEngine, &ScriptEngine::errorMessage, this, &JSConsole::handleError); - disconnect(_scriptEngine, &ScriptEngine::clearDebugWindow, this, &JSConsole::clear); if (_ownScriptEngine) { _scriptEngine->deleteLater(); } @@ -99,7 +97,6 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) { connect(_scriptEngine, &ScriptEngine::infoMessage, this, &JSConsole::handleInfo); connect(_scriptEngine, &ScriptEngine::warningMessage, this, &JSConsole::handleWarning); connect(_scriptEngine, &ScriptEngine::errorMessage, this, &JSConsole::handleError); - connect(_scriptEngine, &ScriptEngine::clearDebugWindow, this, &JSConsole::clear); } void JSConsole::executeCommand(const QString& command) { @@ -119,9 +116,9 @@ void JSConsole::executeCommand(const QString& command) { QScriptValue JSConsole::executeCommandInWatcher(const QString& command) { QScriptValue result; QMetaObject::invokeMethod(_scriptEngine, "evaluate", Qt::ConnectionType::BlockingQueuedConnection, - Q_RETURN_ARG(QScriptValue, result), - Q_ARG(const QString&, command), - Q_ARG(const QString&, _consoleFileName)); + Q_RETURN_ARG(QScriptValue, result), + Q_ARG(const QString&, command), + Q_ARG(const QString&, _consoleFileName)); return result; } @@ -147,7 +144,6 @@ void JSConsole::commandFinished() { void JSConsole::handleError(const QString& message, const QString& scriptName) { Q_UNUSED(scriptName); appendMessage(GUTTER_ERROR, "" + message.toHtmlEscaped() + ""); - } void JSConsole::handlePrint(const QString& message, const QString& scriptName) { @@ -184,7 +180,8 @@ bool JSConsole::eventFilter(QObject* sender, QEvent* event) { // If the shift key is being used then treat it as a regular return/enter. If this isn't done, // a new QTextBlock isn't created. keyEvent->setModifiers(keyEvent->modifiers() & ~Qt::ShiftModifier); - } else { + } + else { QString command = _ui->promptTextEdit->toPlainText().trimmed(); if (!command.isEmpty()) { @@ -196,7 +193,8 @@ bool JSConsole::eventFilter(QObject* sender, QEvent* event) { return true; } - } else if (key == Qt::Key_Down) { + } + else if (key == Qt::Key_Down) { // Go to the next command in history if the cursor is at the last line of the current command. int blockNumber = _ui->promptTextEdit->textCursor().blockNumber(); int blockCount = _ui->promptTextEdit->document()->blockCount(); @@ -204,7 +202,8 @@ bool JSConsole::eventFilter(QObject* sender, QEvent* event) { setToNextCommandInHistory(); return true; } - } else if (key == Qt::Key_Up) { + } + else if (key == Qt::Key_Up) { // Go to the previous command in history if the cursor is at the first line of the current command. int blockNumber = _ui->promptTextEdit->textCursor().blockNumber(); if (blockNumber == 0) { @@ -222,7 +221,8 @@ void JSConsole::setToNextCommandInHistory() { _currentCommandInHistory--; if (_currentCommandInHistory == NO_CURRENT_HISTORY_COMMAND) { setAndSelectCommand(_rootCommand); - } else { + } + else { setAndSelectCommand(_commandHistory[_currentCommandInHistory]); } } @@ -295,14 +295,11 @@ void JSConsole::appendMessage(const QString& gutter, const QString& message) { } void JSConsole::clear() { - /* qCDebug(scriptengine) << "============================="; - qCDebug(scriptengine) << "Clear fUNCTION";*/ QLayoutItem* item; while ((item = _ui->logArea->layout()->takeAt(0)) != NULL) { - // qCDebug(scriptengine) << "While loop called"; delete item->widget(); delete item; } - // _ui->logArea->updateGeometry(); - // scrollToBottom(); + _ui->logArea->updateGeometry(); + scrollToBottom(); } diff --git a/interface/src/ui/JSConsole.h b/interface/src/ui/JSConsole.h index 1e33414183..226df6fe54 100644 --- a/interface/src/ui/JSConsole.h +++ b/interface/src/ui/JSConsole.h @@ -32,9 +32,10 @@ public: JSConsole(QWidget* parent, ScriptEngine* scriptEngine = NULL); ~JSConsole(); - void setScriptEngine(ScriptEngine* scriptEngine = NULL); + void setScriptEngine(ScriptEngine* scriptEngine = NULL); + void clear(); -public slots: + public slots: void executeCommand(const QString& command); protected: @@ -43,15 +44,14 @@ protected: virtual void mouseReleaseEvent(QMouseEvent* event) override; virtual void showEvent(QShowEvent* event) override; -protected slots: + protected slots: void scrollToBottom(); void resizeTextInput(); void handlePrint(const QString& message, const QString& scriptName); void handleInfo(const QString& message, const QString& scriptName); void handleWarning(const QString& message, const QString& scriptName); void handleError(const QString& message, const QString& scriptName); - void commandFinished(); - void clear(); + void commandFinished(); private: void appendMessage(const QString& gutter, const QString& message); diff --git a/interface/src/ui/TestingDialog.cpp b/interface/src/ui/TestingDialog.cpp index 10e66e05a1..4c3854eeb4 100644 --- a/interface/src/ui/TestingDialog.cpp +++ b/interface/src/ui/TestingDialog.cpp @@ -15,8 +15,8 @@ #include "Application.h" TestingDialog::TestingDialog(QWidget* parent) : - QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint), - _console(new JSConsole(this)) +QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint), +_console(new JSConsole(this)) { setAttribute(Qt::WA_DeleteOnClose); setWindowTitle(windowLabel); @@ -26,11 +26,10 @@ TestingDialog::TestingDialog(QWidget* parent) : auto _engines = DependencyManager::get(); _engine = _engines->loadScript(qApp->applicationDirPath() + testRunnerRelativePath); _console->setScriptEngine(_engine); - connect(_engine, &ScriptEngine::finished, this, &TestingDialog::onTestingFinished); + connect(_engine, &ScriptEngine::finished, this, &TestingDialog::onTestingFinished); } void TestingDialog::onTestingFinished(const QString& scriptPath) { _engine = nullptr; _console->setScriptEngine(nullptr); - } diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 3bbd26e010..4d745fa1a1 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -44,7 +44,7 @@ Q_LOGGING_CATEGORY(trace_render_qml_gl, "trace.render.qml.gl") struct TextureSet { // The number of surfaces with this size - size_t count { 0 }; + size_t count{ 0 }; std::list returnedTextures; }; @@ -193,7 +193,7 @@ private: std::unordered_map _textureSizes; Mutex _mutex; std::list _returnedTextures; - size_t _totalTextureUsage { 0 }; + size_t _totalTextureUsage{ 0 }; } offscreenTextures; class UrlHandler : public QObject { @@ -286,7 +286,7 @@ void OffscreenQmlSurface::render() { } PROFILE_RANGE(render_qml_gl, __FUNCTION__) - _canvas->makeCurrent(); + _canvas->makeCurrent(); _renderControl->sync(); _quickWindow->setRenderTarget(_fbo, QSize(_size.x, _size.y)); @@ -532,8 +532,8 @@ QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::functionisLoading()) { connect(_qmlComponent, &QQmlComponent::statusChanged, this, [this, f](QQmlComponent::Status){ - finishQmlLoad(f); - }); + finishQmlLoad(f); + }); return nullptr; } @@ -563,7 +563,8 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::functionpolishItems(); + _renderControl->polishItems(); _polish = false; } @@ -648,7 +649,8 @@ QPointF OffscreenQmlSurface::mapWindowToUi(const QPointF& sourcePosition, QObjec vec2 sourceSize; if (dynamic_cast(sourceObject)) { sourceSize = toGlm(((QWidget*)sourceObject)->size()); - } else if (dynamic_cast(sourceObject)) { + } + else if (dynamic_cast(sourceObject)) { sourceSize = toGlm(((QWindow*)sourceObject)->size()); } vec2 offscreenPosition = toGlm(sourcePosition); @@ -691,61 +693,61 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even #endif switch (event->type()) { - case QEvent::Resize: { - QResizeEvent* resizeEvent = static_cast(event); - QWidget* widget = dynamic_cast(originalDestination); - if (widget) { - this->resize(resizeEvent->size()); - } - break; + case QEvent::Resize: { + QResizeEvent* resizeEvent = static_cast(event); + QWidget* widget = dynamic_cast(originalDestination); + if (widget) { + this->resize(resizeEvent->size()); } + break; + } - case QEvent::KeyPress: - case QEvent::KeyRelease: { - event->ignore(); - if (QCoreApplication::sendEvent(_quickWindow, event)) { - return event->isAccepted(); - } - break; + case QEvent::KeyPress: + case QEvent::KeyRelease: { + event->ignore(); + if (QCoreApplication::sendEvent(_quickWindow, event)) { + return event->isAccepted(); } + break; + } - case QEvent::Wheel: { - QWheelEvent* wheelEvent = static_cast(event); - QPointF transformedPos = mapToVirtualScreen(wheelEvent->pos(), originalDestination); - QWheelEvent mappedEvent( - transformedPos, - wheelEvent->delta(), wheelEvent->buttons(), - wheelEvent->modifiers(), wheelEvent->orientation()); - mappedEvent.ignore(); - if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) { - return mappedEvent.isAccepted(); - } - break; + case QEvent::Wheel: { + QWheelEvent* wheelEvent = static_cast(event); + QPointF transformedPos = mapToVirtualScreen(wheelEvent->pos(), originalDestination); + QWheelEvent mappedEvent( + transformedPos, + wheelEvent->delta(), wheelEvent->buttons(), + wheelEvent->modifiers(), wheelEvent->orientation()); + mappedEvent.ignore(); + if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) { + return mappedEvent.isAccepted(); } + break; + } - // Fall through - case QEvent::MouseButtonDblClick: - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: { - QMouseEvent* mouseEvent = static_cast(event); - QPointF transformedPos = mapToVirtualScreen(mouseEvent->localPos(), originalDestination); - QMouseEvent mappedEvent(mouseEvent->type(), - transformedPos, - mouseEvent->screenPos(), mouseEvent->button(), - mouseEvent->buttons(), mouseEvent->modifiers()); - if (event->type() == QEvent::MouseMove) { - _qmlEngine->rootContext()->setContextProperty("lastMousePosition", transformedPos); - } - mappedEvent.ignore(); - if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) { - return mappedEvent.isAccepted(); - } - break; + // Fall through + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: { + QMouseEvent* mouseEvent = static_cast(event); + QPointF transformedPos = mapToVirtualScreen(mouseEvent->localPos(), originalDestination); + QMouseEvent mappedEvent(mouseEvent->type(), + transformedPos, + mouseEvent->screenPos(), mouseEvent->button(), + mouseEvent->buttons(), mouseEvent->modifiers()); + if (event->type() == QEvent::MouseMove) { + _qmlEngine->rootContext()->setContextProperty("lastMousePosition", transformedPos); } + mappedEvent.ignore(); + if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) { + return mappedEvent.isAccepted(); + } + break; + } - default: - break; + default: + break; } return false; @@ -800,7 +802,7 @@ Q_DECLARE_METATYPE(std::function); auto VariantLambdaType = qRegisterMetaType>(); -void OffscreenQmlSurface::executeOnUiThread(std::function function, bool blocking ) { +void OffscreenQmlSurface::executeOnUiThread(std::function function, bool blocking) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "executeOnUiThread", blocking ? Qt::BlockingQueuedConnection : Qt::QueuedConnection, Q_ARG(std::function, function)); @@ -892,16 +894,20 @@ void OffscreenQmlSurface::synthesizeKeyPress(QString key) { if (equals(utf8Key, SHIFT_ARROW) || equals(utf8Key, NUMERIC_SHIFT_ARROW) || equals(utf8Key, (uint8_t*)PUNCTUATION_STRING) || equals(utf8Key, (uint8_t*)ALPHABET_STRING)) { return; // ignore - } else if (equals(utf8Key, BACKSPACE_SYMBOL)) { + } + else if (equals(utf8Key, BACKSPACE_SYMBOL)) { scanCode = Qt::Key_Backspace; keyString = "\x08"; - } else if (equals(utf8Key, RETURN_SYMBOL)) { + } + else if (equals(utf8Key, RETURN_SYMBOL)) { scanCode = Qt::Key_Return; keyString = "\x0d"; - } else if (equals(utf8Key, LEFT_ARROW)) { + } + else if (equals(utf8Key, LEFT_ARROW)) { scanCode = Qt::Key_Left; keyString = ""; - } else if (equals(utf8Key, RIGHT_ARROW)) { + } + else if (equals(utf8Key, RIGHT_ARROW)) { scanCode = Qt::Key_Right; keyString = ""; } @@ -941,7 +947,8 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n void OffscreenQmlSurface::emitScriptEvent(const QVariant& message) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "emitScriptEvent", Qt::QueuedConnection, Q_ARG(QVariant, message)); - } else { + } + else { emit scriptEventReceived(message); } } @@ -949,7 +956,8 @@ void OffscreenQmlSurface::emitScriptEvent(const QVariant& message) { void OffscreenQmlSurface::emitWebEvent(const QVariant& message) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "emitWebEvent", Qt::QueuedConnection, Q_ARG(QVariant, message)); - } else { + } + else { // Special case to handle raising and lowering the virtual keyboard. const QString RAISE_KEYBOARD = "_RAISE_KEYBOARD"; const QString RAISE_KEYBOARD_NUMERIC = "_RAISE_KEYBOARD_NUMERIC"; @@ -957,9 +965,11 @@ void OffscreenQmlSurface::emitWebEvent(const QVariant& message) { QString messageString = message.type() == QVariant::String ? message.toString() : ""; if (messageString.left(RAISE_KEYBOARD.length()) == RAISE_KEYBOARD) { setKeyboardRaised(_currentFocusItem, true, messageString == RAISE_KEYBOARD_NUMERIC); - } else if (messageString == LOWER_KEYBOARD) { + } + else if (messageString == LOWER_KEYBOARD) { setKeyboardRaised(_currentFocusItem, false); - } else { + } + else { emit webEventReceived(message); } } @@ -968,7 +978,8 @@ void OffscreenQmlSurface::emitWebEvent(const QVariant& message) { void OffscreenQmlSurface::sendToQml(const QVariant& message) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "emitQmlEvent", Qt::QueuedConnection, Q_ARG(QVariant, message)); - } else if (_rootItem) { + } + else if (_rootItem) { // call fromScript method on qml root QMetaObject::invokeMethod(_rootItem, "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message)); } diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.h b/libraries/gl/src/gl/OffscreenQmlSurface.h index efd35fce8b..95c6b01557 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.h +++ b/libraries/gl/src/gl/OffscreenQmlSurface.h @@ -37,7 +37,7 @@ class QQuickItem; class OffscreenQmlSurface : public QObject { Q_OBJECT - Q_PROPERTY(bool focusText READ isFocusText NOTIFY focusTextChanged) + Q_PROPERTY(bool focusText READ isFocusText NOTIFY focusTextChanged) public: OffscreenQmlSurface(); virtual ~OffscreenQmlSurface(); @@ -95,12 +95,12 @@ signals: void focusObjectChanged(QObject* newFocus); void focusTextChanged(bool focusText); -public slots: + public slots: void onAboutToQuit(); void focusDestroyed(QObject *obj); // event bridge -public slots: + public slots: void emitScriptEvent(const QVariant& scriptMessage); void emitWebEvent(const QVariant& webMessage); signals: @@ -108,7 +108,7 @@ signals: void webEventReceived(const QVariant& message); // qml event bridge -public slots: + public slots: void sendToQml(const QVariant& message); signals: void fromQml(QVariant message); @@ -126,37 +126,37 @@ private: void cleanup(); QJsonObject getGLContextData(); -private slots: + private slots: void updateQuick(); void onFocusObjectChanged(QObject* newFocus); private: - QQuickWindow* _quickWindow { nullptr }; + QQuickWindow* _quickWindow{ nullptr }; QMyQuickRenderControl* _renderControl{ nullptr }; - QQmlEngine* _qmlEngine { nullptr }; - QQmlComponent* _qmlComponent { nullptr }; - QQuickItem* _rootItem { nullptr }; - OffscreenGLCanvas* _canvas { nullptr }; + QQmlEngine* _qmlEngine{ nullptr }; + QQmlComponent* _qmlComponent{ nullptr }; + QQuickItem* _rootItem{ nullptr }; + OffscreenGLCanvas* _canvas{ nullptr }; QJsonObject _glData; QTimer _updateTimer; - uint32_t _fbo { 0 }; - uint32_t _depthStencil { 0 }; - uint64_t _lastRenderTime { 0 }; + uint32_t _fbo{ 0 }; + uint32_t _depthStencil{ 0 }; + uint64_t _lastRenderTime{ 0 }; uvec2 _size; // Texture management - TextureAndFence _latestTextureAndFence { 0, 0 }; + TextureAndFence _latestTextureAndFence{ 0, 0 }; - bool _render { false }; - bool _polish { true }; - bool _paused { true }; - bool _focusText { false }; - uint8_t _maxFps { 60 }; - MouseTranslator _mouseTranslator { [](const QPointF& p) { return p.toPoint(); } }; - QWindow* _proxyWindow { nullptr }; + bool _render{ false }; + bool _polish{ true }; + bool _paused{ true }; + bool _focusText{ false }; + uint8_t _maxFps{ 60 }; + MouseTranslator _mouseTranslator{ [](const QPointF& p) { return p.toPoint(); } }; + QWindow* _proxyWindow{ nullptr }; - QQuickItem* _currentFocusItem { nullptr }; + QQuickItem* _currentFocusItem{ nullptr }; }; #endif diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index add7ab411d..5c7ca6aadc 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -485,10 +485,11 @@ void ScriptEngine::scriptPrintedMessage(const QString& message) { qCDebug(scriptengine) << message; emit printedMessage(message, getFilename()); } + void ScriptEngine::clearConsole() { - qCDebug(scriptengine) << "Clearing debug window"; emit clearDebugWindow(); } + // Even though we never pass AnimVariantMap directly to and from javascript, the queued invokeMethod of // callAnimationStateHandler requires that the type be registered. // These two are meaningful, if we ever do want to use them... diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 1cb0c117da..9135d263ef 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -54,6 +54,10 @@ void ScriptEngines::onInfoMessage(const QString& message, const QString& scriptN emit infoMessage(message, scriptName); } +void ScriptEngines::OnClearConsole() { + emit clearDebugWindow(); +} + void ScriptEngines::onErrorLoadingScript(const QString& url) { emit errorLoadingScript(url); } diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 5152c3952a..233a11c2a0 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -79,6 +79,7 @@ signals: void warningMessage(const QString& message, const QString& engineName); void infoMessage(const QString& message, const QString& engineName); void errorLoadingScript(const QString& url); + void clearDebugWindow(); public slots: void onPrintedMessage(const QString& message, const QString& scriptName); @@ -86,6 +87,7 @@ public slots: void onWarningMessage(const QString& message, const QString& scriptName); void onInfoMessage(const QString& message, const QString& scriptName); void onErrorLoadingScript(const QString& url); + void OnClearConsole(); protected slots: void onScriptFinished(const QString& fileNameString, ScriptEngine* engine); diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index c0e94058ae..22cec5dcbb 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -153,6 +153,9 @@ void QmlWindowClass::sendToQml(const QVariant& message) { QMetaObject::invokeMethod(asQuickItem(), "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message)); } +void QmlWindowClass::clearConsole() { + QMetaObject::invokeMethod(asQuickItem(), "fromConsole", Qt::QueuedConnection); +} void QmlWindowClass::emitScriptEvent(const QVariant& scriptMessage) { if (QThread::currentThread() != thread()) { diff --git a/libraries/ui/src/QmlWindowClass.h b/libraries/ui/src/QmlWindowClass.h index 95777718bf..463ec91d86 100644 --- a/libraries/ui/src/QmlWindowClass.h +++ b/libraries/ui/src/QmlWindowClass.h @@ -53,6 +53,7 @@ public slots: // Scripts can use this to send a message to the QML object void sendToQml(const QVariant& message); + void clearConsole(); // QmlWindow content may include WebView requiring EventBridge. void emitScriptEvent(const QVariant& scriptMessage); diff --git a/scripts/developer/debugging/debugWindow.js b/scripts/developer/debugging/debugWindow.js index 30a050e667..0cf3b18e72 100644 --- a/scripts/developer/debugging/debugWindow.js +++ b/scripts/developer/debugging/debugWindow.js @@ -49,4 +49,8 @@ ScriptDiscoveryService.infoMessage.connect(function(message, scriptFileName) { sendToLogWindow("INFO", message, scriptFileName); }); +ScriptDiscoveryService.clearDebugWindow.connect(function () { + window.clearConsole(); +}); + }()); // END LOCAL_SCOPE \ No newline at end of file diff --git a/scripts/developer/debugging/debugWindow.qml b/scripts/developer/debugging/debugWindow.qml index 20fa24358d..08fae994c8 100644 --- a/scripts/developer/debugging/debugWindow.qml +++ b/scripts/developer/debugging/debugWindow.qml @@ -29,7 +29,7 @@ Rectangle { height: parent.height text:"" } - + function fromScript(message) { var MAX_LINE_COUNT = 2000; var TRIM_LINES = 500; @@ -40,6 +40,10 @@ Rectangle { } textArea.append(message); } + + function fromConsole(){ + textArea.remove(0,textArea.length); + } } From dd91346c18bbb732c8f3de4106b60825db1c4575 Mon Sep 17 00:00:00 2001 From: NeetBhagat Date: Fri, 9 Jun 2017 11:43:16 +0530 Subject: [PATCH 3/9] Started group functions. --- .../src/ConsoleScriptingInterface.cpp | 64 ++++++++++++++++++- .../src/ConsoleScriptingInterface.h | 8 +++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.cpp b/libraries/script-engine/src/ConsoleScriptingInterface.cpp index ad114526cb..e237bb53ff 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.cpp +++ b/libraries/script-engine/src/ConsoleScriptingInterface.cpp @@ -22,7 +22,10 @@ void ConsoleScriptingInterface::info(QString message) { } } -void ConsoleScriptingInterface::log(QString message) { +void ConsoleScriptingInterface::log(QString message) { + /*if (!listgrp.isEmpty()){ + listgrp.append(qMakePair(currentGroupSelection, message)); + }*/ if (ScriptEngine* scriptEngine = qobject_cast(engine())) { scriptEngine->scriptPrintedMessage(message); } @@ -130,3 +133,62 @@ void ConsoleScriptingInterface::clear() { scriptEngine->clearConsole(); } } + +void ConsoleScriptingInterface::group(QString groupName) { + listgrp.append(qMakePair(defaultGroupName, groupName)); + currentGroupSelection = groupName; +} + +void ConsoleScriptingInterface::groupCollapsed(QString groupName) { + listgrp.append(qMakePair(defaultGroupCollapseName, groupName)); + currentGroupSelection = groupName; +} + +void ConsoleScriptingInterface::consoleLog(QString groupName) { + if (!listgrp.isEmpty()){ + listgrp.append(qMakePair(currentGroupSelection, groupName)); + } +} + +int collapseCount = 0; +QString addSpace = " "; +void ConsoleScriptingInterface::groupEnd() { + QString endGroup= "endGroup"; + listgrp.append(qMakePair(currentGroupSelection, endGroup)); + //currentGroupSelection = groupName; +} + +void show(){ + QString tmp; + QPair pair; + for (int i = 0; i _listOfTimeValues; const qint64 DAY = 86400; const QString TIME_FORMAT = "yyyy-MM-dd HH:mm"; + QString currentGroupSelection; + QString defaultGroupName = "group"; + QString defaultGroupCollapseName = "groupCollapse"; + QList > listgrp; }; #endif // hifi_ConsoleScriptingInterface_h From 2bd2804d0bd24349890e9abede12b91a06b0c4cb Mon Sep 17 00:00:00 2001 From: NeetBhagat Date: Fri, 9 Jun 2017 20:31:58 +0530 Subject: [PATCH 4/9] complete Group Functionality i.e Group,GroupCollapsed,GroupEnd --- .../src/ConsoleScriptingInterface.cpp | 241 +++++++++--------- .../src/ConsoleScriptingInterface.h | 25 +- 2 files changed, 140 insertions(+), 126 deletions(-) diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.cpp b/libraries/script-engine/src/ConsoleScriptingInterface.cpp index e237bb53ff..cca80234e0 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.cpp +++ b/libraries/script-engine/src/ConsoleScriptingInterface.cpp @@ -17,115 +17,122 @@ #include "ScriptEngine.h" void ConsoleScriptingInterface::info(QString message) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptInfoMessage(message); - } + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptInfoMessage(message); + } } -void ConsoleScriptingInterface::log(QString message) { +void ConsoleScriptingInterface::log(QString message) { /*if (!listgrp.isEmpty()){ - listgrp.append(qMakePair(currentGroupSelection, message)); + listgrp.append(qMakePair(currentGroupSelection, message)); }*/ - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptPrintedMessage(message); - } + /*_listOfGroupData.append(qMakePair(_selectedGroup, message)); + if (!_listOfGroupData.isEmpty()) { + showdata(_selectedGroup, message); + }*/ + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptPrintedMessage(message); + } } void ConsoleScriptingInterface::debug(QString message) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptPrintedMessage(message); - } + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptPrintedMessage(message); + } } void ConsoleScriptingInterface::warn(QString message) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptWarningMessage(message); - } + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptWarningMessage(message); + } } void ConsoleScriptingInterface::error(QString message) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptErrorMessage(message); - } + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptErrorMessage(message); + } } void ConsoleScriptingInterface::exception(QString message) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptErrorMessage(message); - } + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptErrorMessage(message); + } } void ConsoleScriptingInterface::time(QString labelName) { - QDateTime _currentTime = QDateTime::currentDateTime().toUTC(); - _listOfTimeValues.insert(labelName, _currentTime.toUTC()); + QDateTime _currentTime = QDateTime::currentDateTime().toUTC(); + _listOfTimeValues.insert(labelName, _currentTime.toUTC()); } void ConsoleScriptingInterface::timeEnd(QString labelName) { - QDateTime _dateTimeOfLabel; - QString message; - qint64 millisecondsDiff = 0; + QDateTime _dateTimeOfLabel; + QString message; + qint64 millisecondsDiff = 0; - bool _labelInList = _listOfTimeValues.contains(labelName); - - //Check if not exist items in list - if (!_labelInList) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - message = "No such label found " + labelName; - scriptEngine->scriptErrorMessage(message); - } - return; - } + bool _labelInList = _listOfTimeValues.contains(labelName); - QDateTime _currentDateTimeValue = QDateTime::currentDateTime().toUTC(); - _dateTimeOfLabel = _listOfTimeValues.value(labelName); + //Check if not exist items in list + if (!_labelInList) { + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + message = "No such label found " + labelName; + scriptEngine->scriptErrorMessage(message); + } + return; + } - if (!_dateTimeOfLabel.isNull()) { - _listOfTimeValues.remove(labelName); - } - - if (_dateTimeOfLabel.toString(TIME_FORMAT) == _currentDateTimeValue.toString(TIME_FORMAT)) { - millisecondsDiff = _dateTimeOfLabel.msecsTo(_currentDateTimeValue); - message = QString::number(millisecondsDiff) + " ms"; - } else { - message = secondsToString(_dateTimeOfLabel.secsTo(_currentDateTimeValue)); - } + QDateTime _currentDateTimeValue = QDateTime::currentDateTime().toUTC(); + _dateTimeOfLabel = _listOfTimeValues.value(labelName); - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptPrintedMessage("Time : " + message); - } + if (!_dateTimeOfLabel.isNull()) { + _listOfTimeValues.remove(labelName); + } + + if (_dateTimeOfLabel.toString(TIME_FORMAT) == _currentDateTimeValue.toString(TIME_FORMAT)) { + millisecondsDiff = _dateTimeOfLabel.msecsTo(_currentDateTimeValue); + message = QString::number(millisecondsDiff) + " ms"; + } + else { + message = secondsToString(_dateTimeOfLabel.secsTo(_currentDateTimeValue)); + } + + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptPrintedMessage("Time : " + message); + } } QString ConsoleScriptingInterface::secondsToString(qint64 seconds) -{ - qint64 days = seconds / DAY; - QTime timeDuration = QTime(0, 0).addSecs(seconds % DAY); +{ + qint64 days = seconds / DAY; + QTime timeDuration = QTime(0, 0).addSecs(seconds % DAY); - return QString("%1 days, %2 hours, %3 minutes, %4 seconds") - .arg(QString::number(days)).arg(QString::number(timeDuration.hour())).arg(QString::number(timeDuration.minute())).arg(QString::number(timeDuration.second())); + return QString("%1 days, %2 hours, %3 minutes, %4 seconds") + .arg(QString::number(days)).arg(QString::number(timeDuration.hour())).arg(QString::number(timeDuration.minute())).arg(QString::number(timeDuration.second())); } void ConsoleScriptingInterface::asserts(bool condition, QString message) { - if (!condition) { - QString assertFailed = "Assertion failed"; - if (message.isEmpty()) { - message = assertFailed; - } else { - if (typeid(message) != typeid(QString)) { - message = assertFailed; - } else { - message = assertFailed + " " + message; - } - } - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptErrorMessage(message); - } - } + if (!condition) { + QString assertFailed = "Assertion failed"; + if (message.isEmpty()) { + message = assertFailed; + } + else { + if (typeid(message) != typeid(QString)) { + message = assertFailed; + } + else { + message = assertFailed + " " + message; + } + } + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptErrorMessage(message); + } + } } void ConsoleScriptingInterface::trace(QString labelName) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptErrorMessage(labelName); - } + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptErrorMessage(labelName); + } } void ConsoleScriptingInterface::clear() { @@ -135,60 +142,62 @@ void ConsoleScriptingInterface::clear() { } void ConsoleScriptingInterface::group(QString groupName) { - listgrp.append(qMakePair(defaultGroupName, groupName)); - currentGroupSelection = groupName; + _listOfGroupData.append(qMakePair(GROUP, groupName)); + _selectedGroup = groupName; + showdata(GROUP, groupName); } void ConsoleScriptingInterface::groupCollapsed(QString groupName) { - listgrp.append(qMakePair(defaultGroupCollapseName, groupName)); - currentGroupSelection = groupName; + _listOfGroupData.append(qMakePair(GROUPCOLLAPSED, groupName)); + _selectedGroup = groupName; + showdata(GROUPCOLLAPSED, groupName); } -void ConsoleScriptingInterface::consoleLog(QString groupName) { - if (!listgrp.isEmpty()){ - listgrp.append(qMakePair(currentGroupSelection, groupName)); +void ConsoleScriptingInterface::consoleLog(QString message) { + _listOfGroupData.append(qMakePair(_selectedGroup, message)); + if (!_listOfGroupData.isEmpty()) { + showdata(_selectedGroup, message); } } -int collapseCount = 0; -QString addSpace = " "; -void ConsoleScriptingInterface::groupEnd() { - QString endGroup= "endGroup"; - listgrp.append(qMakePair(currentGroupSelection, endGroup)); - //currentGroupSelection = groupName; +void ConsoleScriptingInterface::groupEnd() { + _listOfGroupData.append(qMakePair(_selectedGroup, GROUPEND)); + showdata(_selectedGroup, GROUPEND); } -void show(){ - QString tmp; - QPair pair; - for (int i = 0; i groupData; + QString firstGroupData; + + for (int index = 0; index<_listOfGroupData.count(); index++) { + groupData = _listOfGroupData.at(index); + firstGroupData = groupData.first; + if (groupData.first == GROUP || groupData.first == GROUPCOLLAPSED) { + firstGroupData = groupData.second; + if (_isSameLevel) { + _addSpace = _addSpace.mid(0, _addSpace.length() - 3); } - collapseCount++; - pair.second = addSpace + pair.second; - debug(pair.second); - } - else { - if (pair.first == tmp) { - pair.second = addSpace + pair.second; - debug(pair.second); + _addSpace += " "; //add inner groupcollapsed + + if (groupData.first == GROUPCOLLAPSED) { + QString space = _addSpace.mid(0, _addSpace.length() - 1); + debug(space + groupData.second); + } else { + debug(_addSpace + groupData.second); + } + _isSameLevel = false; + } else if (groupData.second == GROUPEND) { + _addSpace = _addSpace.mid(0, _addSpace.length() - 3); + } else { + if (groupData.first == firstGroupData && groupData.first != GROUPCOLLAPSED && groupData.first != GROUP && groupData.second != GROUPEND) { + if (!_isSameLevel) { + _addSpace += " "; //2 space inner element + _isSameLevel = true; //same level log entry + } + debug(_addSpace + groupData.second); } } } - addSpace = ""; - tmp = ""; - collapseCount = 0; - listgrp.clear(); -} \ No newline at end of file + _listOfGroupData.removeOne(qMakePair(currentGroup, groupName)); + +} diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.h b/libraries/script-engine/src/ConsoleScriptingInterface.h index ca65b7d3fd..d8e7ed038c 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.h +++ b/libraries/script-engine/src/ConsoleScriptingInterface.h @@ -22,6 +22,7 @@ #include #include #include +#include /// Scriptable interface of console object. Used exclusively in the JavaScript API @@ -35,25 +36,29 @@ public slots: void error(QString message); void exception(QString message); void time(QString labelName); - void timeEnd(QString labelName); + void timeEnd(QString labelName); void asserts(bool condition, QString message = ""); void trace(QString labelName); - void clear(); + void clear(); void group(QString groupName); - void groupCollapsed(QString groupName); - void consoleLog(QString groupName); - void groupEnd(); + void groupCollapsed(QString groupName); + void groupEnd(); + void consoleLog(QString message); + void showdata(QString currentGroup, QString groupName); public: QString secondsToString(qint64 seconds); bool isInteger(const std::string & s); private: QHash _listOfTimeValues; const qint64 DAY = 86400; - const QString TIME_FORMAT = "yyyy-MM-dd HH:mm"; - QString currentGroupSelection; - QString defaultGroupName = "group"; - QString defaultGroupCollapseName = "groupCollapse"; - QList > listgrp; + const QString TIME_FORMAT = "yyyy-MM-dd HH:mm"; + QString _selectedGroup; + const QString GROUP = "group"; + const QString GROUPCOLLAPSED = "groupCollapse"; + const QString GROUPEND = "groupEnd"; + bool _isSameLevel = false; + QString _addSpace = ""; + QList > _listOfGroupData; }; #endif // hifi_ConsoleScriptingInterface_h From 71bff04ce07e823b54bb342cca82fc94ca60a1b0 Mon Sep 17 00:00:00 2001 From: NeetBhagat Date: Mon, 12 Jun 2017 12:38:56 +0530 Subject: [PATCH 5/9] Update group functionality by removing consoleLog method from consoleScriptingInterfaceClass. --- .../src/ConsoleScriptingInterface.cpp | 86 ++++++++----------- .../src/ConsoleScriptingInterface.h | 7 +- 2 files changed, 39 insertions(+), 54 deletions(-) diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.cpp b/libraries/script-engine/src/ConsoleScriptingInterface.cpp index cca80234e0..ed2fcfadcc 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.cpp +++ b/libraries/script-engine/src/ConsoleScriptingInterface.cpp @@ -23,15 +23,12 @@ void ConsoleScriptingInterface::info(QString message) { } void ConsoleScriptingInterface::log(QString message) { - /*if (!listgrp.isEmpty()){ - listgrp.append(qMakePair(currentGroupSelection, message)); - }*/ - /*_listOfGroupData.append(qMakePair(_selectedGroup, message)); - if (!_listOfGroupData.isEmpty()) { - showdata(_selectedGroup, message); - }*/ - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptPrintedMessage(message); + if (_isGroupEnd) { + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + scriptEngine->scriptPrintedMessage(message); + } + } else { + consoleGroupLog(_selectedGroup, message); } } @@ -142,62 +139,51 @@ void ConsoleScriptingInterface::clear() { } void ConsoleScriptingInterface::group(QString groupName) { - _listOfGroupData.append(qMakePair(GROUP, groupName)); _selectedGroup = groupName; - showdata(GROUP, groupName); + consoleGroupLog(GROUP, groupName); } void ConsoleScriptingInterface::groupCollapsed(QString groupName) { - _listOfGroupData.append(qMakePair(GROUPCOLLAPSED, groupName)); _selectedGroup = groupName; - showdata(GROUPCOLLAPSED, groupName); -} - -void ConsoleScriptingInterface::consoleLog(QString message) { - _listOfGroupData.append(qMakePair(_selectedGroup, message)); - if (!_listOfGroupData.isEmpty()) { - showdata(_selectedGroup, message); - } + consoleGroupLog(GROUPCOLLAPSED, groupName); } void ConsoleScriptingInterface::groupEnd() { - _listOfGroupData.append(qMakePair(_selectedGroup, GROUPEND)); - showdata(_selectedGroup, GROUPEND); + consoleGroupLog(_selectedGroup, GROUPEND); } -void ConsoleScriptingInterface::showdata(QString currentGroup, QString groupName) { +void ConsoleScriptingInterface::consoleGroupLog(QString currentGroup, QString groupName) { QPair groupData; - QString firstGroupData; + QString groupKeyName; - for (int index = 0; index<_listOfGroupData.count(); index++) { - groupData = _listOfGroupData.at(index); - firstGroupData = groupData.first; - if (groupData.first == GROUP || groupData.first == GROUPCOLLAPSED) { - firstGroupData = groupData.second; - if (_isSameLevel) { - _addSpace = _addSpace.mid(0, _addSpace.length() - 3); - } - _addSpace += " "; //add inner groupcollapsed - - if (groupData.first == GROUPCOLLAPSED) { - QString space = _addSpace.mid(0, _addSpace.length() - 1); - debug(space + groupData.second); - } else { - debug(_addSpace + groupData.second); - } - _isSameLevel = false; - } else if (groupData.second == GROUPEND) { + groupData = qMakePair(currentGroup, groupName); + groupKeyName = groupData.first; + if (groupData.first == GROUP || groupData.first == GROUPCOLLAPSED) { + groupKeyName = groupData.second; + if (_isSameLevel) { _addSpace = _addSpace.mid(0, _addSpace.length() - 3); + } + if (_isGroupEnd) { + _addSpace = ""; + _isGroupEnd = false; } else { - if (groupData.first == firstGroupData && groupData.first != GROUPCOLLAPSED && groupData.first != GROUP && groupData.second != GROUPEND) { - if (!_isSameLevel) { - _addSpace += " "; //2 space inner element - _isSameLevel = true; //same level log entry - } - debug(_addSpace + groupData.second); + _addSpace += " "; + } + debug(_addSpace.mid(0, _addSpace.length() - 1) + groupData.second); + _isSameLevel = false; + } else { + if (groupData.first == groupKeyName && groupData.first != GROUPCOLLAPSED && groupData.first != GROUP && groupData.second != GROUPEND) { + if (!_isSameLevel) { + _addSpace += " "; //space inner element + _isSameLevel = true; //same level log entry } + debug(_addSpace + groupData.second); + } + } + if (groupData.second == GROUPEND) { + _addSpace = _addSpace.mid(0, _addSpace.length() - 3); + if (_addSpace.length() == 0) { + _isGroupEnd = true; } } - _listOfGroupData.removeOne(qMakePair(currentGroup, groupName)); - } diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.h b/libraries/script-engine/src/ConsoleScriptingInterface.h index d8e7ed038c..c281139fea 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.h +++ b/libraries/script-engine/src/ConsoleScriptingInterface.h @@ -42,9 +42,8 @@ public slots: void clear(); void group(QString groupName); void groupCollapsed(QString groupName); - void groupEnd(); - void consoleLog(QString message); - void showdata(QString currentGroup, QString groupName); + void groupEnd(); + void consoleGroupLog(QString currentGroup, QString groupName); public: QString secondsToString(qint64 seconds); bool isInteger(const std::string & s); @@ -58,7 +57,7 @@ private: const QString GROUPEND = "groupEnd"; bool _isSameLevel = false; QString _addSpace = ""; - QList > _listOfGroupData; + bool _isGroupEnd = true; }; #endif // hifi_ConsoleScriptingInterface_h From e8fc766c2b3d23d53e8da7e38e0b8b6a4f541117 Mon Sep 17 00:00:00 2001 From: NeetBhagat Date: Mon, 12 Jun 2017 20:24:59 +0530 Subject: [PATCH 6/9] Complete Console Exception. --- .../src/ConsoleScriptingInterface.cpp | 42 +++++++++++++++++-- .../src/ConsoleScriptingInterface.h | 9 ++-- libraries/script-engine/src/ScriptEngine.cpp | 20 +++++++++ libraries/script-engine/src/ScriptEngine.h | 3 +- libraries/shared/src/BaseScriptEngine.cpp | 36 +++++++++++++++- libraries/shared/src/BaseScriptEngine.h | 10 +++-- 6 files changed, 108 insertions(+), 12 deletions(-) diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.cpp b/libraries/script-engine/src/ConsoleScriptingInterface.cpp index ed2fcfadcc..c4c59f2f94 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.cpp +++ b/libraries/script-engine/src/ConsoleScriptingInterface.cpp @@ -52,10 +52,46 @@ void ConsoleScriptingInterface::error(QString message) { void ConsoleScriptingInterface::exception(QString message) { if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptErrorMessage(message); + scriptEngine->logConsoleException(message); } + } +bool ConsoleScriptingInterface:: hasCorrectSyntax(QScriptProgram& program) { + const auto syntaxCheck = QScriptEngine::checkSyntax(program.sourceCode()); + if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) { + const auto error = syntaxCheck.errorMessage(); + const auto line = QString::number(syntaxCheck.errorLineNumber()); + const auto column = QString::number(syntaxCheck.errorColumnNumber()); + const auto message = QString("[SyntaxError] %1 in %2:%3(%4)").arg(error, program.fileName(), line, column); + qCritical() << qPrintable(message); + return false; + } + return true; +} + +QString ConsoleScriptingInterface::hadUncaughtExceptions(QScriptEngine& engine, QString& fileName) { + log("4"); + //if (engine.hasUncaughtException()) { + const auto backtrace = engine.uncaughtExceptionBacktrace(); + const auto exception = engine.uncaughtException().toString(); + const auto line = QString::number(engine.uncaughtExceptionLineNumber()); + engine.clearExceptions(); + log("5"); + static const QString SCRIPT_EXCEPTION_FORMAT = "[UncaughtException] %1 in %2:%3"; + auto message = QString(SCRIPT_EXCEPTION_FORMAT).arg(exception, fileName, line); + if (!backtrace.empty()) { + static const auto lineSeparator = "\n "; + message += QString("\n[Backtrace]%1%2").arg(lineSeparator, backtrace.join(lineSeparator)); + } + // qCritical() << qPrintable(message); + log("6"); + return message; + //} + //return false; +} + + void ConsoleScriptingInterface::time(QString labelName) { QDateTime _currentTime = QDateTime::currentDateTime().toUTC(); _listOfTimeValues.insert(labelName, _currentTime.toUTC()); @@ -126,9 +162,9 @@ void ConsoleScriptingInterface::asserts(bool condition, QString message) { } } -void ConsoleScriptingInterface::trace(QString labelName) { +void ConsoleScriptingInterface::trace() { if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptErrorMessage(labelName); + scriptEngine->logTraceException(); } } diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.h b/libraries/script-engine/src/ConsoleScriptingInterface.h index c281139fea..1dad4d8440 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.h +++ b/libraries/script-engine/src/ConsoleScriptingInterface.h @@ -22,6 +22,8 @@ #include #include #include +#include "EntityEditFilters.h" +#include #include @@ -38,15 +40,16 @@ public slots: void time(QString labelName); void timeEnd(QString labelName); void asserts(bool condition, QString message = ""); - void trace(QString labelName); + void trace(); void clear(); void group(QString groupName); void groupCollapsed(QString groupName); void groupEnd(); void consoleGroupLog(QString currentGroup, QString groupName); public: - QString secondsToString(qint64 seconds); - bool isInteger(const std::string & s); + QString secondsToString(qint64 seconds); + bool hasCorrectSyntax(QScriptProgram& program); + QString hadUncaughtExceptions(QScriptEngine& engine, QString& fileName); private: QHash _listOfTimeValues; const qint64 DAY = 86400; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 5c7ca6aadc..34048ff9c4 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -145,6 +145,17 @@ QString encodeEntityIdIntoEntityUrl(const QString& url, const QString& entityID) return url + " [EntityID:" + entityID + "]"; } +void ScriptEngine::logConsoleException(QString message) { + this->raiseConsoleException(this->makeError(message)); +} + +QString ScriptEngine::logTraceException() { + QScriptValue value = this->raiseConsoleTraceException(this->makeError("")); + auto trace = formatTrace(value, _enableExtendedJSExceptions.get()); + scriptInfoMessage(trace); + return trace; +} + QString ScriptEngine::logException(const QScriptValue& exception) { auto message = formatException(exception, _enableExtendedJSExceptions.get()); scriptErrorMessage(message); @@ -187,6 +198,15 @@ ScriptEngine::ScriptEngine(Context context, const QString& scriptContents, const } logException(output); }); + + // this is where all unhandled exceptions end up getting logged + /* connect(this, &BaseScriptEngine::unhandledException, this, [this](const QScriptValue& err) { + auto output = err.engine() == this ? err : makeError(err); + if (!output.property("detail").isValid()) { + output.setProperty("detail", "UnhandledException"); + } + logException(output); + });*/ } QString ScriptEngine::getContext() const { diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index c3b97b7f9e..590c75f759 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -148,7 +148,8 @@ public: /// to scripts. we may not need this to be invokable void loadURL(const QUrl& scriptURL, bool reload); bool hasValidScriptSuffix(const QString& scriptFileName); - + void logConsoleException(QString message); + QString logTraceException(); Q_INVOKABLE QString getContext() const; Q_INVOKABLE bool isClientScript() const { return _context == CLIENT_SCRIPT; } Q_INVOKABLE bool isEntityClientScript() const { return _context == ENTITY_CLIENT_SCRIPT; } diff --git a/libraries/shared/src/BaseScriptEngine.cpp b/libraries/shared/src/BaseScriptEngine.cpp index c92d629b75..711af818e6 100644 --- a/libraries/shared/src/BaseScriptEngine.cpp +++ b/libraries/shared/src/BaseScriptEngine.cpp @@ -22,6 +22,7 @@ #include "Profile.h" const QString BaseScriptEngine::SCRIPT_EXCEPTION_FORMAT { "[%0] %1 in %2:%3" }; +const QString BaseScriptEngine::SCRIPT_TRACE_FORMAT{ "[%0] %1" }; const QString BaseScriptEngine::SCRIPT_BACKTRACE_SEP { "\n " }; bool BaseScriptEngine::IS_THREADSAFE_INVOCATION(const QThread *thread, const QString& method) { @@ -159,7 +160,7 @@ QScriptValue BaseScriptEngine::cloneUncaughtException(const QString& extraDetail #endif return err; } - + QString BaseScriptEngine::formatException(const QScriptValue& exception, bool includeExtendedDetails) { if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { return QString(); @@ -192,6 +193,27 @@ QString BaseScriptEngine::formatException(const QScriptValue& exception, bool in return result; } +QString BaseScriptEngine::formatTrace(const QScriptValue& value, bool includeExtendedDetails) { + if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { + return QString(); + } + QString note{ "TRACE" }; + QString result; + + if (!value.isObject()) { + return result; + } + const auto fileName = value.property("fileName").toString(); + const auto lineNumber = value.property("lineNumber").toString(); + const auto stacktrace = value.property("stack").toString(); + + result = QString(SCRIPT_TRACE_FORMAT).arg(fileName, lineNumber); + if (!stacktrace.isEmpty()) { + result += QString("\n[Trace]%1%2").arg(SCRIPT_BACKTRACE_SEP).arg(stacktrace); + } + return result; +} + bool BaseScriptEngine::raiseException(const QScriptValue& exception) { if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { return false; @@ -208,6 +230,18 @@ bool BaseScriptEngine::raiseException(const QScriptValue& exception) { return false; } +void BaseScriptEngine::raiseConsoleException(const QScriptValue& exception) { + if (currentContext()) { + currentContext()->throwValue(makeError(exception)); + } +} + +QScriptValue BaseScriptEngine::raiseConsoleTraceException(const QScriptValue& exception) { + if (currentContext()) { + return currentContext()->throwValue(makeError(exception)); + } +} + bool BaseScriptEngine::maybeEmitUncaughtException(const QString& debugHint) { if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { return false; diff --git a/libraries/shared/src/BaseScriptEngine.h b/libraries/shared/src/BaseScriptEngine.h index 138e46fafa..fee65896b8 100644 --- a/libraries/shared/src/BaseScriptEngine.h +++ b/libraries/shared/src/BaseScriptEngine.h @@ -21,6 +21,7 @@ class BaseScriptEngine : public QScriptEngine, public QEnableSharedFromThis Date: Tue, 13 Jun 2017 14:12:29 +0530 Subject: [PATCH 7/9] Complete the functionality of console.trace(). --- .../src/ConsoleScriptingInterface.cpp | 74 ++++--------------- libraries/script-engine/src/ScriptEngine.cpp | 11 --- libraries/script-engine/src/ScriptEngine.h | 4 +- libraries/shared/src/BaseScriptEngine.cpp | 36 +-------- libraries/shared/src/BaseScriptEngine.h | 10 +-- 5 files changed, 21 insertions(+), 114 deletions(-) diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.cpp b/libraries/script-engine/src/ConsoleScriptingInterface.cpp index c4c59f2f94..dfe6973395 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.cpp +++ b/libraries/script-engine/src/ConsoleScriptingInterface.cpp @@ -52,46 +52,10 @@ void ConsoleScriptingInterface::error(QString message) { void ConsoleScriptingInterface::exception(QString message) { if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->logConsoleException(message); + scriptEngine->scriptErrorMessage(message); } - } -bool ConsoleScriptingInterface:: hasCorrectSyntax(QScriptProgram& program) { - const auto syntaxCheck = QScriptEngine::checkSyntax(program.sourceCode()); - if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) { - const auto error = syntaxCheck.errorMessage(); - const auto line = QString::number(syntaxCheck.errorLineNumber()); - const auto column = QString::number(syntaxCheck.errorColumnNumber()); - const auto message = QString("[SyntaxError] %1 in %2:%3(%4)").arg(error, program.fileName(), line, column); - qCritical() << qPrintable(message); - return false; - } - return true; -} - -QString ConsoleScriptingInterface::hadUncaughtExceptions(QScriptEngine& engine, QString& fileName) { - log("4"); - //if (engine.hasUncaughtException()) { - const auto backtrace = engine.uncaughtExceptionBacktrace(); - const auto exception = engine.uncaughtException().toString(); - const auto line = QString::number(engine.uncaughtExceptionLineNumber()); - engine.clearExceptions(); - log("5"); - static const QString SCRIPT_EXCEPTION_FORMAT = "[UncaughtException] %1 in %2:%3"; - auto message = QString(SCRIPT_EXCEPTION_FORMAT).arg(exception, fileName, line); - if (!backtrace.empty()) { - static const auto lineSeparator = "\n "; - message += QString("\n[Backtrace]%1%2").arg(lineSeparator, backtrace.join(lineSeparator)); - } - // qCritical() << qPrintable(message); - log("6"); - return message; - //} - //return false; -} - - void ConsoleScriptingInterface::time(QString labelName) { QDateTime _currentTime = QDateTime::currentDateTime().toUTC(); _listOfTimeValues.insert(labelName, _currentTime.toUTC()); @@ -106,10 +70,8 @@ void ConsoleScriptingInterface::timeEnd(QString labelName) { //Check if not exist items in list if (!_labelInList) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - message = "No such label found " + labelName; - scriptEngine->scriptErrorMessage(message); - } + message = "No such label found " + labelName; + error(message); return; } @@ -123,14 +85,10 @@ void ConsoleScriptingInterface::timeEnd(QString labelName) { if (_dateTimeOfLabel.toString(TIME_FORMAT) == _currentDateTimeValue.toString(TIME_FORMAT)) { millisecondsDiff = _dateTimeOfLabel.msecsTo(_currentDateTimeValue); message = QString::number(millisecondsDiff) + " ms"; - } - else { + } else { message = secondsToString(_dateTimeOfLabel.secsTo(_currentDateTimeValue)); } - - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptPrintedMessage("Time : " + message); - } + log("Time : " + message); } QString ConsoleScriptingInterface::secondsToString(qint64 seconds) @@ -147,24 +105,24 @@ void ConsoleScriptingInterface::asserts(bool condition, QString message) { QString assertFailed = "Assertion failed"; if (message.isEmpty()) { message = assertFailed; - } - else { - if (typeid(message) != typeid(QString)) { + } else { + QString inputType = typeid(message).name(); + if (!inputType.compare("QString")) { message = assertFailed; - } - else { + } else { message = assertFailed + " " + message; } } - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptErrorMessage(message); - } + error(message); } } -void ConsoleScriptingInterface::trace() { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->logTraceException(); +void ConsoleScriptingInterface::trace() { + const auto lineSeparator = "\n "; + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + QStringList backtrace = scriptEngine->currentContext()->backtrace(); + auto message = QString("\n[Backtrace]%1%2").arg(lineSeparator, backtrace.join(lineSeparator)); + scriptEngine->scriptPrintedMessage(message); } } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 34048ff9c4..114731a4d8 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -145,17 +145,6 @@ QString encodeEntityIdIntoEntityUrl(const QString& url, const QString& entityID) return url + " [EntityID:" + entityID + "]"; } -void ScriptEngine::logConsoleException(QString message) { - this->raiseConsoleException(this->makeError(message)); -} - -QString ScriptEngine::logTraceException() { - QScriptValue value = this->raiseConsoleTraceException(this->makeError("")); - auto trace = formatTrace(value, _enableExtendedJSExceptions.get()); - scriptInfoMessage(trace); - return trace; -} - QString ScriptEngine::logException(const QScriptValue& exception) { auto message = formatException(exception, _enableExtendedJSExceptions.get()); scriptErrorMessage(message); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 590c75f759..71f2378a0b 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -147,9 +147,7 @@ public: /// to run... NOTE - this is used by Application currently to load the url. We don't really want it to be exposed /// to scripts. we may not need this to be invokable void loadURL(const QUrl& scriptURL, bool reload); - bool hasValidScriptSuffix(const QString& scriptFileName); - void logConsoleException(QString message); - QString logTraceException(); + bool hasValidScriptSuffix(const QString& scriptFileName); Q_INVOKABLE QString getContext() const; Q_INVOKABLE bool isClientScript() const { return _context == CLIENT_SCRIPT; } Q_INVOKABLE bool isEntityClientScript() const { return _context == ENTITY_CLIENT_SCRIPT; } diff --git a/libraries/shared/src/BaseScriptEngine.cpp b/libraries/shared/src/BaseScriptEngine.cpp index 711af818e6..c92d629b75 100644 --- a/libraries/shared/src/BaseScriptEngine.cpp +++ b/libraries/shared/src/BaseScriptEngine.cpp @@ -22,7 +22,6 @@ #include "Profile.h" const QString BaseScriptEngine::SCRIPT_EXCEPTION_FORMAT { "[%0] %1 in %2:%3" }; -const QString BaseScriptEngine::SCRIPT_TRACE_FORMAT{ "[%0] %1" }; const QString BaseScriptEngine::SCRIPT_BACKTRACE_SEP { "\n " }; bool BaseScriptEngine::IS_THREADSAFE_INVOCATION(const QThread *thread, const QString& method) { @@ -160,7 +159,7 @@ QScriptValue BaseScriptEngine::cloneUncaughtException(const QString& extraDetail #endif return err; } - + QString BaseScriptEngine::formatException(const QScriptValue& exception, bool includeExtendedDetails) { if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { return QString(); @@ -193,27 +192,6 @@ QString BaseScriptEngine::formatException(const QScriptValue& exception, bool in return result; } -QString BaseScriptEngine::formatTrace(const QScriptValue& value, bool includeExtendedDetails) { - if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { - return QString(); - } - QString note{ "TRACE" }; - QString result; - - if (!value.isObject()) { - return result; - } - const auto fileName = value.property("fileName").toString(); - const auto lineNumber = value.property("lineNumber").toString(); - const auto stacktrace = value.property("stack").toString(); - - result = QString(SCRIPT_TRACE_FORMAT).arg(fileName, lineNumber); - if (!stacktrace.isEmpty()) { - result += QString("\n[Trace]%1%2").arg(SCRIPT_BACKTRACE_SEP).arg(stacktrace); - } - return result; -} - bool BaseScriptEngine::raiseException(const QScriptValue& exception) { if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { return false; @@ -230,18 +208,6 @@ bool BaseScriptEngine::raiseException(const QScriptValue& exception) { return false; } -void BaseScriptEngine::raiseConsoleException(const QScriptValue& exception) { - if (currentContext()) { - currentContext()->throwValue(makeError(exception)); - } -} - -QScriptValue BaseScriptEngine::raiseConsoleTraceException(const QScriptValue& exception) { - if (currentContext()) { - return currentContext()->throwValue(makeError(exception)); - } -} - bool BaseScriptEngine::maybeEmitUncaughtException(const QString& debugHint) { if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { return false; diff --git a/libraries/shared/src/BaseScriptEngine.h b/libraries/shared/src/BaseScriptEngine.h index fee65896b8..8fdbb001a1 100644 --- a/libraries/shared/src/BaseScriptEngine.h +++ b/libraries/shared/src/BaseScriptEngine.h @@ -20,8 +20,7 @@ class BaseScriptEngine : public QScriptEngine, public QEnableSharedFromThis { Q_OBJECT public: - static const QString SCRIPT_EXCEPTION_FORMAT; - static const QString SCRIPT_TRACE_FORMAT; + static const QString SCRIPT_EXCEPTION_FORMAT; static const QString SCRIPT_BACKTRACE_SEP; // threadsafe "unbound" version of QScriptEngine::nullValue() @@ -31,8 +30,7 @@ public: Q_INVOKABLE QScriptValue lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1); Q_INVOKABLE QScriptValue makeError(const QScriptValue& other = QScriptValue(), const QString& type = "Error"); - Q_INVOKABLE QString formatException(const QScriptValue& exception, bool includeExtendedDetails); - Q_INVOKABLE QString formatTrace(const QScriptValue& val, bool includeExtendedDetails); + Q_INVOKABLE QString formatException(const QScriptValue& exception, bool includeExtendedDetails); QScriptValue cloneUncaughtException(const QString& detail = QString()); QScriptValue evaluateInClosure(const QScriptValue& locals, const QScriptProgram& program); @@ -41,9 +39,7 @@ public: // if the currentContext() is valid then throw the passed exception; otherwise, immediately emit it. // note: this is used in cases where C++ code might call into JS API methods directly - bool raiseException(const QScriptValue& exception); - void raiseConsoleException(const QScriptValue& exception); - QScriptValue raiseConsoleTraceException(const QScriptValue& exception); + bool raiseException(const QScriptValue& exception); // helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways static bool IS_THREADSAFE_INVOCATION(const QThread *thread, const QString& method); signals: From 9646eba8733765ba77beb38608bcd804f8816e44 Mon Sep 17 00:00:00 2001 From: NeetBhagat Date: Tue, 13 Jun 2017 20:25:01 +0530 Subject: [PATCH 8/9] Complete console.trace and added a testcases for all 13 functions. --- interface/resources/qml/QmlWindow.qml | 6 +- interface/src/Application.cpp | 2 +- .../src/ConsoleScriptingInterface.cpp | 140 ++++++------------ .../src/ConsoleScriptingInterface.h | 44 ++---- libraries/script-engine/src/ScriptEngine.cpp | 20 +-- libraries/script-engine/src/ScriptEngine.h | 6 +- libraries/script-engine/src/ScriptEngines.cpp | 2 +- libraries/script-engine/src/ScriptEngines.h | 2 +- libraries/shared/src/BaseScriptEngine.h | 12 +- libraries/ui/src/QmlWindowClass.cpp | 4 +- libraries/ui/src/QmlWindowClass.h | 2 +- scripts/developer/debugging/debugWindow.js | 6 +- scripts/developer/debugging/debugWindow.qml | 8 +- scripts/developer/tests/consoleObjectTest.js | 109 ++++++++++++++ scripts/developer/tests/printTest.js | 6 - 15 files changed, 204 insertions(+), 165 deletions(-) create mode 100644 scripts/developer/tests/consoleObjectTest.js diff --git a/interface/resources/qml/QmlWindow.qml b/interface/resources/qml/QmlWindow.qml index c746dd7b9d..9a84418b3a 100644 --- a/interface/resources/qml/QmlWindow.qml +++ b/interface/resources/qml/QmlWindow.qml @@ -66,9 +66,9 @@ Windows.Window { } } - function fromConsole() { - if (root.dynamicContent && root.dynamicContent.fromConsole) { - root.dynamicContent.fromConsole(); + function clearDebugWindow() { + if (root.dynamicContent && root.dynamicContent.clearWindow) { + root.dynamicContent.clearWindow(); } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d5d545a534..61448fc094 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5577,7 +5577,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri connect(scriptEngine, &ScriptEngine::errorMessage, DependencyManager::get().data(), &ScriptEngines::onErrorMessage); connect(scriptEngine, &ScriptEngine::warningMessage, DependencyManager::get().data(), &ScriptEngines::onWarningMessage); connect(scriptEngine, &ScriptEngine::infoMessage, DependencyManager::get().data(), &ScriptEngines::onInfoMessage); - connect(scriptEngine, &ScriptEngine::clearDebugWindow, DependencyManager::get().data(), &ScriptEngines::OnClearConsole); + connect(scriptEngine, &ScriptEngine::clearDebugWindow, DependencyManager::get().data(), &ScriptEngines::onClearDebugWindow); } bool Application::canAcceptURL(const QString& urlString) const { diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.cpp b/libraries/script-engine/src/ConsoleScriptingInterface.cpp index dfe6973395..c319bc6d31 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.cpp +++ b/libraries/script-engine/src/ConsoleScriptingInterface.cpp @@ -2,12 +2,14 @@ // ConsoleScriptingInterface.cpp // libraries/script-engine/src // -// Created by volansystech on 6/1/17. +// Created by NeetBhagat on 6/1/17. // Copyright 2014 High Fidelity, Inc. // -// ConsoleScriptingInterface is responsible to print logs -// using "console" object on debug Window and Logs/log file with proper tags. -// Used in Javascripts file. +// ConsoleScriptingInterface is responsible for following functionality +// Printing logs with various tags and grouping on debug Window and Logs/log file. +// Debugging functionalities like Timer start-end, assertion, trace. +// To use these functionalities, use "console" object in Javascript files. +// For examples please refer "scripts/developer/tests/consoleObjectTest.js" // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -16,6 +18,10 @@ #include "ConsoleScriptingInterface.h" #include "ScriptEngine.h" +#define INDENTATION 4 +const QString LINE_SEPARATOR = "\n "; +const QString STACK_TRACE_FORMAT = "\n[Stacktrace]%1%2"; + void ConsoleScriptingInterface::info(QString message) { if (ScriptEngine* scriptEngine = qobject_cast(engine())) { scriptEngine->scriptInfoMessage(message); @@ -23,12 +29,12 @@ void ConsoleScriptingInterface::info(QString message) { } void ConsoleScriptingInterface::log(QString message) { - if (_isGroupEnd) { + if (_groupDetails.count() == 0) { if (ScriptEngine* scriptEngine = qobject_cast(engine())) { scriptEngine->scriptPrintedMessage(message); } } else { - consoleGroupLog(_selectedGroup, message); + this->logGroupMessage(message); } } @@ -57,127 +63,79 @@ void ConsoleScriptingInterface::exception(QString message) { } void ConsoleScriptingInterface::time(QString labelName) { - QDateTime _currentTime = QDateTime::currentDateTime().toUTC(); - _listOfTimeValues.insert(labelName, _currentTime.toUTC()); + _timerDetails.insert(labelName, QDateTime::currentDateTime().toUTC()); + QString message = QString("%1: timer started").arg(labelName); + this->log(message); } void ConsoleScriptingInterface::timeEnd(QString labelName) { - QDateTime _dateTimeOfLabel; - QString message; - qint64 millisecondsDiff = 0; - - bool _labelInList = _listOfTimeValues.contains(labelName); - - //Check if not exist items in list - if (!_labelInList) { - message = "No such label found " + labelName; - error(message); + if (!_timerDetails.contains(labelName)) { + this->error("No such label found " + labelName); return; } - QDateTime _currentDateTimeValue = QDateTime::currentDateTime().toUTC(); - _dateTimeOfLabel = _listOfTimeValues.value(labelName); - - if (!_dateTimeOfLabel.isNull()) { - _listOfTimeValues.remove(labelName); + if (_timerDetails.value(labelName).isNull()) { + _timerDetails.remove(labelName); + this->error("Invalid start time for " + labelName); + return; } + + QDateTime _startTime = _timerDetails.value(labelName); + QDateTime _endTime = QDateTime::currentDateTime().toUTC(); + qint64 diffInMS = _startTime.msecsTo(_endTime); + + QString message = QString("%1: %2ms").arg(labelName).arg(QString::number(diffInMS)); + _timerDetails.remove(labelName); - if (_dateTimeOfLabel.toString(TIME_FORMAT) == _currentDateTimeValue.toString(TIME_FORMAT)) { - millisecondsDiff = _dateTimeOfLabel.msecsTo(_currentDateTimeValue); - message = QString::number(millisecondsDiff) + " ms"; - } else { - message = secondsToString(_dateTimeOfLabel.secsTo(_currentDateTimeValue)); - } - log("Time : " + message); -} - -QString ConsoleScriptingInterface::secondsToString(qint64 seconds) -{ - qint64 days = seconds / DAY; - QTime timeDuration = QTime(0, 0).addSecs(seconds % DAY); - - return QString("%1 days, %2 hours, %3 minutes, %4 seconds") - .arg(QString::number(days)).arg(QString::number(timeDuration.hour())).arg(QString::number(timeDuration.minute())).arg(QString::number(timeDuration.second())); + this->log(message); } void ConsoleScriptingInterface::asserts(bool condition, QString message) { if (!condition) { - QString assertFailed = "Assertion failed"; + QString assertionResult; if (message.isEmpty()) { - message = assertFailed; + assertionResult = "Assertion failed"; } else { - QString inputType = typeid(message).name(); - if (!inputType.compare("QString")) { - message = assertFailed; - } else { - message = assertFailed + " " + message; - } + assertionResult = QString("Assertion failed : %1").arg(message); } - error(message); + this->error(assertionResult); } } void ConsoleScriptingInterface::trace() { - const auto lineSeparator = "\n "; if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - QStringList backtrace = scriptEngine->currentContext()->backtrace(); - auto message = QString("\n[Backtrace]%1%2").arg(lineSeparator, backtrace.join(lineSeparator)); - scriptEngine->scriptPrintedMessage(message); + scriptEngine->scriptPrintedMessage + (QString(STACK_TRACE_FORMAT).arg(LINE_SEPARATOR, + scriptEngine->currentContext()->backtrace().join(LINE_SEPARATOR))); } } void ConsoleScriptingInterface::clear() { if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->clearConsole(); + scriptEngine->clearDebugLogWindow(); } } void ConsoleScriptingInterface::group(QString groupName) { - _selectedGroup = groupName; - consoleGroupLog(GROUP, groupName); + this->logGroupMessage(groupName); + _groupDetails.push_back(groupName); } void ConsoleScriptingInterface::groupCollapsed(QString groupName) { - _selectedGroup = groupName; - consoleGroupLog(GROUPCOLLAPSED, groupName); + this->logGroupMessage(groupName); + _groupDetails.push_back(groupName); } void ConsoleScriptingInterface::groupEnd() { - consoleGroupLog(_selectedGroup, GROUPEND); + _groupDetails.removeLast(); } -void ConsoleScriptingInterface::consoleGroupLog(QString currentGroup, QString groupName) { - QPair groupData; - QString groupKeyName; - - groupData = qMakePair(currentGroup, groupName); - groupKeyName = groupData.first; - if (groupData.first == GROUP || groupData.first == GROUPCOLLAPSED) { - groupKeyName = groupData.second; - if (_isSameLevel) { - _addSpace = _addSpace.mid(0, _addSpace.length() - 3); - } - if (_isGroupEnd) { - _addSpace = ""; - _isGroupEnd = false; - } else { - _addSpace += " "; - } - debug(_addSpace.mid(0, _addSpace.length() - 1) + groupData.second); - _isSameLevel = false; - } else { - if (groupData.first == groupKeyName && groupData.first != GROUPCOLLAPSED && groupData.first != GROUP && groupData.second != GROUPEND) { - if (!_isSameLevel) { - _addSpace += " "; //space inner element - _isSameLevel = true; //same level log entry - } - debug(_addSpace + groupData.second); - } - } - if (groupData.second == GROUPEND) { - _addSpace = _addSpace.mid(0, _addSpace.length() - 3); - if (_addSpace.length() == 0) { - _isGroupEnd = true; - } +void ConsoleScriptingInterface::logGroupMessage(QString message) { + int _appendIndentation = _groupDetails.count() * INDENTATION; + QString logMessage; + for (int count = 0; count < _appendIndentation; count++) { + logMessage.append(" "); } + logMessage.append(message); + this->debug(logMessage); } diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.h b/libraries/script-engine/src/ConsoleScriptingInterface.h index 1dad4d8440..03fdabe888 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.h +++ b/libraries/script-engine/src/ConsoleScriptingInterface.h @@ -2,12 +2,14 @@ // ConsoleScriptingInterface.h // libraries/script-engine/src // -// Created by volansystech on 6/1/17. +// Created by NeetBhagat on 6/1/17. // Copyright 2014 High Fidelity, Inc. // -// ConsoleScriptingInterface is responsible to print log. -// using "console" object on debug Window and Logs/log file with proper tags. -// Used in Javascripts file. +// ConsoleScriptingInterface is responsible for following functionality +// Printing logs with various tags and grouping on debug Window and Logs/log file. +// Debugging functionalities like Timer start-end, assertion, trace. +// To use these functionalities, use "console" object in Javascript files. +// For examples please refer "scripts/developer/tests/consoleObjectTest.js" // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -17,17 +19,13 @@ #ifndef hifi_ConsoleScriptingInterface_h #define hifi_ConsoleScriptingInterface_h - #include #include #include -#include -#include "EntityEditFilters.h" -#include #include +#include - -/// Scriptable interface of console object. Used exclusively in the JavaScript API +// Scriptable interface of "console" object. Used exclusively in the JavaScript API class ConsoleScriptingInterface : public QObject, protected QScriptable { Q_OBJECT public slots: @@ -38,29 +36,17 @@ public slots: void error(QString message); void exception(QString message); void time(QString labelName); - void timeEnd(QString labelName); + void timeEnd(QString labelName); void asserts(bool condition, QString message = ""); void trace(); - void clear(); + void clear(); void group(QString groupName); - void groupCollapsed(QString groupName); - void groupEnd(); - void consoleGroupLog(QString currentGroup, QString groupName); -public: - QString secondsToString(qint64 seconds); - bool hasCorrectSyntax(QScriptProgram& program); - QString hadUncaughtExceptions(QScriptEngine& engine, QString& fileName); + void groupCollapsed(QString groupName); + void groupEnd(); private: - QHash _listOfTimeValues; - const qint64 DAY = 86400; - const QString TIME_FORMAT = "yyyy-MM-dd HH:mm"; - QString _selectedGroup; - const QString GROUP = "group"; - const QString GROUPCOLLAPSED = "groupCollapse"; - const QString GROUPEND = "groupEnd"; - bool _isSameLevel = false; - QString _addSpace = ""; - bool _isGroupEnd = true; + QHash _timerDetails; + QList _groupDetails; + void logGroupMessage(QString msg); }; #endif // hifi_ConsoleScriptingInterface_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 114731a4d8..96d3ec95e7 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -187,15 +187,6 @@ ScriptEngine::ScriptEngine(Context context, const QString& scriptContents, const } logException(output); }); - - // this is where all unhandled exceptions end up getting logged - /* connect(this, &BaseScriptEngine::unhandledException, this, [this](const QScriptValue& err) { - auto output = err.engine() == this ? err : makeError(err); - if (!output.property("detail").isValid()) { - output.setProperty("detail", "UnhandledException"); - } - logException(output); - });*/ } QString ScriptEngine::getContext() const { @@ -481,21 +472,21 @@ void ScriptEngine::scriptErrorMessage(const QString& message) { } void ScriptEngine::scriptWarningMessage(const QString& message) { - qCWarning(scriptengine) << message; + qCWarning(scriptengine) << qPrintable(message); emit warningMessage(message, getFilename()); } void ScriptEngine::scriptInfoMessage(const QString& message) { - qCInfo(scriptengine) << message; + qCInfo(scriptengine) << qPrintable(message); emit infoMessage(message, getFilename()); } void ScriptEngine::scriptPrintedMessage(const QString& message) { - qCDebug(scriptengine) << message; + qCDebug(scriptengine) << qPrintable(message); emit printedMessage(message, getFilename()); } -void ScriptEngine::clearConsole() { +void ScriptEngine::clearDebugLogWindow() { emit clearDebugWindow(); } @@ -678,11 +669,10 @@ void ScriptEngine::init() { registerGlobalObject("Entities", entityScriptingInterface.data()); registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); - registerGlobalObject("console", &_consoleScriptingInterface); registerGlobalObject("Mat4", &_mat4Library); registerGlobalObject("Uuid", &_uuidLibrary); registerGlobalObject("Messages", DependencyManager::get().data()); - + registerGlobalObject("console", &_consoleScriptingInterface); registerGlobalObject("File", new FileScriptingInterface(this)); qScriptRegisterMetaType(this, animVarMapToScriptValue, animVarMapFromScriptValue); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 71f2378a0b..9da8603814 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -147,7 +147,8 @@ public: /// to run... NOTE - this is used by Application currently to load the url. We don't really want it to be exposed /// to scripts. we may not need this to be invokable void loadURL(const QUrl& scriptURL, bool reload); - bool hasValidScriptSuffix(const QString& scriptFileName); + bool hasValidScriptSuffix(const QString& scriptFileName); + Q_INVOKABLE QString getContext() const; Q_INVOKABLE bool isClientScript() const { return _context == CLIENT_SCRIPT; } Q_INVOKABLE bool isEntityClientScript() const { return _context == ENTITY_CLIENT_SCRIPT; } @@ -225,8 +226,7 @@ public: void scriptWarningMessage(const QString& message); void scriptInfoMessage(const QString& message); void scriptPrintedMessage(const QString& message); - - void clearConsole(); + void clearDebugLogWindow(); int getNumRunningEntityScripts() const; bool getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const; diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 9135d263ef..fb0fb8b18f 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -54,7 +54,7 @@ void ScriptEngines::onInfoMessage(const QString& message, const QString& scriptN emit infoMessage(message, scriptName); } -void ScriptEngines::OnClearConsole() { +void ScriptEngines::onClearDebugWindow() { emit clearDebugWindow(); } diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 233a11c2a0..91dc54a0ec 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -87,7 +87,7 @@ public slots: void onWarningMessage(const QString& message, const QString& scriptName); void onInfoMessage(const QString& message, const QString& scriptName); void onErrorLoadingScript(const QString& url); - void OnClearConsole(); + void onClearDebugWindow(); protected slots: void onScriptFinished(const QString& fileNameString, ScriptEngine* engine); diff --git a/libraries/shared/src/BaseScriptEngine.h b/libraries/shared/src/BaseScriptEngine.h index 8fdbb001a1..138e46fafa 100644 --- a/libraries/shared/src/BaseScriptEngine.h +++ b/libraries/shared/src/BaseScriptEngine.h @@ -20,7 +20,7 @@ class BaseScriptEngine : public QScriptEngine, public QEnableSharedFromThis { Q_OBJECT public: - static const QString SCRIPT_EXCEPTION_FORMAT; + static const QString SCRIPT_EXCEPTION_FORMAT; static const QString SCRIPT_BACKTRACE_SEP; // threadsafe "unbound" version of QScriptEngine::nullValue() @@ -29,9 +29,10 @@ public: BaseScriptEngine() {} Q_INVOKABLE QScriptValue lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1); - Q_INVOKABLE QScriptValue makeError(const QScriptValue& other = QScriptValue(), const QString& type = "Error"); - Q_INVOKABLE QString formatException(const QScriptValue& exception, bool includeExtendedDetails); - QScriptValue cloneUncaughtException(const QString& detail = QString()); + Q_INVOKABLE QScriptValue makeError(const QScriptValue& other = QScriptValue(), const QString& type = "Error"); + Q_INVOKABLE QString formatException(const QScriptValue& exception, bool includeExtendedDetails); + + QScriptValue cloneUncaughtException(const QString& detail = QString()); QScriptValue evaluateInClosure(const QScriptValue& locals, const QScriptProgram& program); // if there is a pending exception and we are at the top level (non-recursive) stack frame, this emits and resets it @@ -39,7 +40,8 @@ public: // if the currentContext() is valid then throw the passed exception; otherwise, immediately emit it. // note: this is used in cases where C++ code might call into JS API methods directly - bool raiseException(const QScriptValue& exception); + bool raiseException(const QScriptValue& exception); + // helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways static bool IS_THREADSAFE_INVOCATION(const QThread *thread, const QString& method); signals: diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index 26007a7ec7..f5bb880957 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -153,8 +153,8 @@ void QmlWindowClass::sendToQml(const QVariant& message) { QMetaObject::invokeMethod(asQuickItem(), "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message)); } -void QmlWindowClass::clearConsole() { - QMetaObject::invokeMethod(asQuickItem(), "fromConsole", Qt::QueuedConnection); +void QmlWindowClass::clearDebugWindow() { + QMetaObject::invokeMethod(asQuickItem(), "clearDebugWindow", Qt::QueuedConnection); } void QmlWindowClass::emitScriptEvent(const QVariant& scriptMessage) { diff --git a/libraries/ui/src/QmlWindowClass.h b/libraries/ui/src/QmlWindowClass.h index 463ec91d86..4f604133a5 100644 --- a/libraries/ui/src/QmlWindowClass.h +++ b/libraries/ui/src/QmlWindowClass.h @@ -53,7 +53,7 @@ public slots: // Scripts can use this to send a message to the QML object void sendToQml(const QVariant& message); - void clearConsole(); + void clearDebugWindow(); // QmlWindow content may include WebView requiring EventBridge. void emitScriptEvent(const QVariant& scriptMessage); diff --git a/scripts/developer/debugging/debugWindow.js b/scripts/developer/debugging/debugWindow.js index fcb0004dd5..6dd116089a 100644 --- a/scripts/developer/debugging/debugWindow.js +++ b/scripts/developer/debugging/debugWindow.js @@ -49,8 +49,8 @@ ScriptDiscoveryService.infoMessage.connect(function(message, scriptFileName) { sendToLogWindow("INFO", message, scriptFileName); }); -ScriptDiscoveryService.clearDebugWindow.connect(function () { - window.clearConsole(); +ScriptDiscoveryService.clearDebugWindow.connect(function() { + window.clearDebugWindow(); }); -}()); // END LOCAL_SCOPE +}()); diff --git a/scripts/developer/debugging/debugWindow.qml b/scripts/developer/debugging/debugWindow.qml index 075516ebb0..2370803335 100644 --- a/scripts/developer/debugging/debugWindow.qml +++ b/scripts/developer/debugging/debugWindow.qml @@ -40,10 +40,10 @@ Rectangle { } textArea.append(message); } - - function fromConsole(){ - textArea.remove(0,textArea.length); - } + + function clearWindow() { + textArea.remove(0,textArea.length); + } } diff --git a/scripts/developer/tests/consoleObjectTest.js b/scripts/developer/tests/consoleObjectTest.js new file mode 100644 index 0000000000..7e2416833f --- /dev/null +++ b/scripts/developer/tests/consoleObjectTest.js @@ -0,0 +1,109 @@ +// Examples and understanding of console object. Include console methods like +// info, log, debug, warn, error, exception, trace, clear, asserts, group, groupCollapsed, groupEnd, time, timeEnd. +// Useful in debugging and exclusively made for JavaScript files. +// To view the logs click on Developer -> script logs [logs on debug window] and for text file logs go to Logs/log file. + +main(); + +function main() { + + var someObject = { str: "Some text", id: 5 }; + var someValue = 5; + + // console.info examples + console.info("[console.info] Hello World."); + console.info(5 + 6); + console.info(someObject.str); + console.info(a = 2 * 6); + console.info(someValue); + console.info('someObject id ' + someObject.id); + + // console.log examples + console.log("[console.log] Hello World"); + console.log(5 + 6); + console.log(someObject.str); + console.log(a = 2 * 6); + console.log(someValue); + console.log('someObject id ' + someObject.id); + + // console.debug examples + console.debug("[console.debug] Hello World."); + console.debug(5 + 6); + console.debug(someObject.str); + console.debug(a = 2 * 6); + console.debug(someValue); + console.debug('someObject id ' + someObject.id); + + // console.warn examples + console.warn("[console.warn] This is warning message."); + console.warn(5 + 6); + console.warn(someObject.str); + console.warn(a = 2 * 6); + console.warn(someValue); + console.warn('someObject id ' + someObject.id); + + // console.error examples + console.error('An error occurred!'); + console.error('An error occurred! ', 'Value = ', someValue); + console.error('An error occurred! ' + 'Value = ' + someValue); + + // console.exception examples + console.exception('An exception occurred!'); + console.exception('An exception occurred! ', 'Value = ', someValue); + console.exception('An exception occurred! ' + 'Value = ' + someValue); + + // console.trace examples + function fooA() { + function fooB() { + function fooC() { + console.trace(); + } + fooC(); + } + fooB(); + } + fooA(); + + //console.asserts() examples + var valA = 1, valB = "1"; + console.asserts(valA === valB, "Value A doesn't equal to B"); + console.asserts(valA === valB); + console.asserts(5 === 5, "5 equals to 5"); + console.asserts(5 === 5); + console.asserts(5 > 6, "5 is not greater than 6"); + + //console.group() examples. + console.group("Group 1"); + console.log("Sentence 1"); + console.log("Sentence 2"); + console.group("Group 2"); + console.log("Sentence 3"); + console.log("Sentence 4"); + console.groupCollapsed("Group 3"); + console.log("Sentence 5"); + console.log("Sentence 6"); + console.groupEnd(); + console.log("Sentence 7"); + console.groupEnd(); + console.log("Sentence 8"); + console.groupEnd(); + console.log("Sentence 9"); + + //console.time(),console.timeEnd() examples + console.time('Timer1'); + // Do some process + sleep(1000); + console.timeEnd('Timer1'); + + // use console.clear() to clean Debug Window logs + // console.clear(); +} + +function sleep(milliseconds) { + var start = new Date().getTime(); + for (var i = 0; i < 1e7; i++) { + if ((new Date().getTime() - start) > milliseconds){ + break; + } + } +} diff --git a/scripts/developer/tests/printTest.js b/scripts/developer/tests/printTest.js index 4e6d68e170..c1fe6ec745 100644 --- a/scripts/developer/tests/printTest.js +++ b/scripts/developer/tests/printTest.js @@ -36,10 +36,4 @@ function main() { Uuid.print('[Uuid.print]', Uuid.fromString(Uuid.toString(0))); } - console.info('[console.info] hello world'); - console.log('[console.log] hello world'); - console.debug('[console.Debug] hello world'); - console.warn('[console.Warn] hello world'); - console.error('[console.error] hello world'); - console.exception('[console.exception] hello world'); } From 2909aa9ac8dc3b560b849125baa69e5cb38ab423 Mon Sep 17 00:00:00 2001 From: NeetBhagat Date: Sat, 17 Jun 2017 00:42:29 +0530 Subject: [PATCH 9/9] Resolve comments of @zappoman. -- Rename "asserts" to "assert" -- Log printing methods will accept lists of objects or strings. --- .../src/ConsoleScriptingInterface.cpp | 175 +++++++++++------- .../src/ConsoleScriptingInterface.h | 30 +-- libraries/script-engine/src/ScriptEngine.cpp | 12 +- scripts/developer/tests/consoleObjectTest.js | 25 ++- 4 files changed, 151 insertions(+), 91 deletions(-) diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.cpp b/libraries/script-engine/src/ConsoleScriptingInterface.cpp index c319bc6d31..f3ceee63f7 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.cpp +++ b/libraries/script-engine/src/ConsoleScriptingInterface.cpp @@ -18,124 +18,165 @@ #include "ConsoleScriptingInterface.h" #include "ScriptEngine.h" -#define INDENTATION 4 +#define INDENTATION 4 // 1 Tab - 4 spaces const QString LINE_SEPARATOR = "\n "; +const QString SPACE_SEPARATOR = " "; const QString STACK_TRACE_FORMAT = "\n[Stacktrace]%1%2"; +QList ConsoleScriptingInterface::_groupDetails = QList(); -void ConsoleScriptingInterface::info(QString message) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptInfoMessage(message); +QScriptValue ConsoleScriptingInterface::info(QScriptContext* context, QScriptEngine* engine) { + if (ScriptEngine* scriptEngine = qobject_cast(engine)) { + scriptEngine->scriptInfoMessage(appendArguments(context)); } + return QScriptValue::NullValue; } -void ConsoleScriptingInterface::log(QString message) { +QScriptValue ConsoleScriptingInterface::log(QScriptContext* context, QScriptEngine* engine) { + QString message = appendArguments(context); if (_groupDetails.count() == 0) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + if (ScriptEngine* scriptEngine = qobject_cast(engine)) { scriptEngine->scriptPrintedMessage(message); } } else { - this->logGroupMessage(message); + logGroupMessage(message, engine); } + return QScriptValue::NullValue; } -void ConsoleScriptingInterface::debug(QString message) { +QScriptValue ConsoleScriptingInterface::debug(QScriptContext* context, QScriptEngine* engine) { + if (ScriptEngine* scriptEngine = qobject_cast(engine)) { + scriptEngine->scriptPrintedMessage(appendArguments(context)); + } + return QScriptValue::NullValue; +} + +QScriptValue ConsoleScriptingInterface::warn(QScriptContext* context, QScriptEngine* engine) { + if (ScriptEngine* scriptEngine = qobject_cast(engine)) { + scriptEngine->scriptWarningMessage(appendArguments(context)); + } + return QScriptValue::NullValue; +} + +QScriptValue ConsoleScriptingInterface::error(QScriptContext* context, QScriptEngine* engine) { + if (ScriptEngine* scriptEngine = qobject_cast(engine)) { + scriptEngine->scriptErrorMessage(appendArguments(context)); + } + return QScriptValue::NullValue; +} + +QScriptValue ConsoleScriptingInterface::exception(QScriptContext* context, QScriptEngine* engine) { + if (ScriptEngine* scriptEngine = qobject_cast(engine)) { + scriptEngine->scriptErrorMessage(appendArguments(context)); + } + return QScriptValue::NullValue; +} + +void ConsoleScriptingInterface::time(QString labelName) { + _timerDetails.insert(labelName, QDateTime::currentDateTime().toUTC()); + QString message = QString("%1: Timer started").arg(labelName); if (ScriptEngine* scriptEngine = qobject_cast(engine())) { scriptEngine->scriptPrintedMessage(message); } } -void ConsoleScriptingInterface::warn(QString message) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptWarningMessage(message); - } -} - -void ConsoleScriptingInterface::error(QString message) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptErrorMessage(message); - } -} - -void ConsoleScriptingInterface::exception(QString message) { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { - scriptEngine->scriptErrorMessage(message); - } -} - -void ConsoleScriptingInterface::time(QString labelName) { - _timerDetails.insert(labelName, QDateTime::currentDateTime().toUTC()); - QString message = QString("%1: timer started").arg(labelName); - this->log(message); -} - void ConsoleScriptingInterface::timeEnd(QString labelName) { - if (!_timerDetails.contains(labelName)) { - this->error("No such label found " + labelName); - return; - } + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { + if (!_timerDetails.contains(labelName)) { + scriptEngine->scriptErrorMessage("No such label found " + labelName); + return; + } - if (_timerDetails.value(labelName).isNull()) { + if (_timerDetails.value(labelName).isNull()) { + _timerDetails.remove(labelName); + scriptEngine->scriptErrorMessage("Invalid start time for " + labelName); + return; + } + QDateTime _startTime = _timerDetails.value(labelName); + QDateTime _endTime = QDateTime::currentDateTime().toUTC(); + qint64 diffInMS = _startTime.msecsTo(_endTime); + + QString message = QString("%1: %2ms").arg(labelName).arg(QString::number(diffInMS)); _timerDetails.remove(labelName); - this->error("Invalid start time for " + labelName); - return; - } - - QDateTime _startTime = _timerDetails.value(labelName); - QDateTime _endTime = QDateTime::currentDateTime().toUTC(); - qint64 diffInMS = _startTime.msecsTo(_endTime); - - QString message = QString("%1: %2ms").arg(labelName).arg(QString::number(diffInMS)); - _timerDetails.remove(labelName); - this->log(message); + scriptEngine->scriptPrintedMessage(message); + } } -void ConsoleScriptingInterface::asserts(bool condition, QString message) { +QScriptValue ConsoleScriptingInterface::assertion(QScriptContext* context, QScriptEngine* engine) { + QString message; + bool condition = false; + for (int i = 0; i < context->argumentCount(); i++) { + if (i == 0) { + condition = context->argument(i).toBool(); // accept first value as condition + } else { + message += SPACE_SEPARATOR + context->argument(i).toString(); // accept other parameters as message + } + } + + QString assertionResult; if (!condition) { - QString assertionResult; if (message.isEmpty()) { assertionResult = "Assertion failed"; } else { assertionResult = QString("Assertion failed : %1").arg(message); } - this->error(assertionResult); + if (ScriptEngine* scriptEngine = qobject_cast(engine)) { + scriptEngine->scriptErrorMessage(assertionResult); + } } + return QScriptValue::NullValue; } -void ConsoleScriptingInterface::trace() { - if (ScriptEngine* scriptEngine = qobject_cast(engine())) { +void ConsoleScriptingInterface::trace() { + if (ScriptEngine* scriptEngine = qobject_cast(engine())) { scriptEngine->scriptPrintedMessage (QString(STACK_TRACE_FORMAT).arg(LINE_SEPARATOR, scriptEngine->currentContext()->backtrace().join(LINE_SEPARATOR))); } } -void ConsoleScriptingInterface::clear() { +void ConsoleScriptingInterface::clear() { if (ScriptEngine* scriptEngine = qobject_cast(engine())) { scriptEngine->clearDebugLogWindow(); } } -void ConsoleScriptingInterface::group(QString groupName) { - this->logGroupMessage(groupName); - _groupDetails.push_back(groupName); +QScriptValue ConsoleScriptingInterface::group(QScriptContext* context, QScriptEngine* engine) { + logGroupMessage(context->argument(0).toString(), engine); // accept first parameter as label + _groupDetails.push_back(context->argument(0).toString()); + return QScriptValue::NullValue; } -void ConsoleScriptingInterface::groupCollapsed(QString groupName) { - this->logGroupMessage(groupName); - _groupDetails.push_back(groupName); +QScriptValue ConsoleScriptingInterface::groupCollapsed(QScriptContext* context, QScriptEngine* engine) { + logGroupMessage(context->argument(0).toString(), engine); // accept first parameter as label + _groupDetails.push_back(context->argument(0).toString()); + return QScriptValue::NullValue; } -void ConsoleScriptingInterface::groupEnd() { - _groupDetails.removeLast(); +QScriptValue ConsoleScriptingInterface::groupEnd(QScriptContext* context, QScriptEngine* engine) { + ConsoleScriptingInterface::_groupDetails.removeLast(); + return QScriptValue::NullValue; } -void ConsoleScriptingInterface::logGroupMessage(QString message) { - int _appendIndentation = _groupDetails.count() * INDENTATION; +QString ConsoleScriptingInterface::appendArguments(QScriptContext* context) { + QString message; + for (int i = 0; i < context->argumentCount(); i++) { + if (i > 0) { + message += SPACE_SEPARATOR; + } + message += context->argument(i).toString(); + } + return message; +} + +void ConsoleScriptingInterface::logGroupMessage(QString message, QScriptEngine* engine) { + int _addSpaces = _groupDetails.count() * INDENTATION; QString logMessage; - for (int count = 0; count < _appendIndentation; count++) { - logMessage.append(" "); + for (int i = 0; i < _addSpaces; i++) { + logMessage.append(SPACE_SEPARATOR); } logMessage.append(message); - this->debug(logMessage); + if (ScriptEngine* scriptEngine = qobject_cast(engine)) { + scriptEngine->scriptPrintedMessage(logMessage); + } } diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.h b/libraries/script-engine/src/ConsoleScriptingInterface.h index 03fdabe888..444ea93504 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.h +++ b/libraries/script-engine/src/ConsoleScriptingInterface.h @@ -28,25 +28,29 @@ // Scriptable interface of "console" object. Used exclusively in the JavaScript API class ConsoleScriptingInterface : public QObject, protected QScriptable { Q_OBJECT +public: + static QScriptValue info(QScriptContext* context, QScriptEngine* engine); + static QScriptValue log(QScriptContext* context, QScriptEngine* engine); + static QScriptValue debug(QScriptContext* context, QScriptEngine* engine); + static QScriptValue warn(QScriptContext* context, QScriptEngine* engine); + static QScriptValue error(QScriptContext* context, QScriptEngine* engine); + static QScriptValue exception(QScriptContext* context, QScriptEngine* engine); + static QScriptValue assertion(QScriptContext* context, QScriptEngine* engine); + static QScriptValue group(QScriptContext* context, QScriptEngine* engine); + static QScriptValue groupCollapsed(QScriptContext* context, QScriptEngine* engine); + static QScriptValue groupEnd(QScriptContext* context, QScriptEngine* engine); + public slots: - void info(QString message); - void log(QString message); - void debug(QString message); - void warn(QString message); - void error(QString message); - void exception(QString message); void time(QString labelName); void timeEnd(QString labelName); - void asserts(bool condition, QString message = ""); void trace(); void clear(); - void group(QString groupName); - void groupCollapsed(QString groupName); - void groupEnd(); -private: + +private: QHash _timerDetails; - QList _groupDetails; - void logGroupMessage(QString msg); + static QList _groupDetails; + static void logGroupMessage(QString message, QScriptEngine* engine); + static QString appendArguments(QScriptContext* context); }; #endif // hifi_ConsoleScriptingInterface_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 96d3ec95e7..8c64589c3d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -672,8 +672,18 @@ void ScriptEngine::init() { registerGlobalObject("Mat4", &_mat4Library); registerGlobalObject("Uuid", &_uuidLibrary); registerGlobalObject("Messages", DependencyManager::get().data()); - registerGlobalObject("console", &_consoleScriptingInterface); registerGlobalObject("File", new FileScriptingInterface(this)); + registerGlobalObject("console", &_consoleScriptingInterface); + registerFunction("console", "info", ConsoleScriptingInterface::info, currentContext()->argumentCount()); + registerFunction("console", "log", ConsoleScriptingInterface::log, currentContext()->argumentCount()); + registerFunction("console", "debug", ConsoleScriptingInterface::debug, currentContext()->argumentCount()); + registerFunction("console", "warn", ConsoleScriptingInterface::warn, currentContext()->argumentCount()); + registerFunction("console", "error", ConsoleScriptingInterface::error, currentContext()->argumentCount()); + registerFunction("console", "exception", ConsoleScriptingInterface::exception, currentContext()->argumentCount()); + registerFunction("console", "assert", ConsoleScriptingInterface::assertion, currentContext()->argumentCount()); + registerFunction("console", "group", ConsoleScriptingInterface::group, 1); + registerFunction("console", "groupCollapsed", ConsoleScriptingInterface::groupCollapsed, 1); + registerFunction("console", "groupEnd", ConsoleScriptingInterface::groupEnd, 0); qScriptRegisterMetaType(this, animVarMapToScriptValue, animVarMapFromScriptValue); qScriptRegisterMetaType(this, resultHandlerToScriptValue, resultHandlerFromScriptValue); diff --git a/scripts/developer/tests/consoleObjectTest.js b/scripts/developer/tests/consoleObjectTest.js index 7e2416833f..a59652dc09 100644 --- a/scripts/developer/tests/consoleObjectTest.js +++ b/scripts/developer/tests/consoleObjectTest.js @@ -17,6 +17,7 @@ function main() { console.info(a = 2 * 6); console.info(someValue); console.info('someObject id ' + someObject.id); + console.info('Hello World ', 'someObject.id = ', someObject.id, "a = 2 * 6 = ", a = 2 * 6); // console.log examples console.log("[console.log] Hello World"); @@ -25,6 +26,7 @@ function main() { console.log(a = 2 * 6); console.log(someValue); console.log('someObject id ' + someObject.id); + console.log('Hello World ', 'someObject.id = ', someObject.id, "a = 2 * 6 = ", a = 2 * 6); // console.debug examples console.debug("[console.debug] Hello World."); @@ -33,6 +35,7 @@ function main() { console.debug(a = 2 * 6); console.debug(someValue); console.debug('someObject id ' + someObject.id); + console.debug('Hello World ', 'someObject.id = ', someObject.id, "a = 2 * 6 = ", a = 2 * 6); // console.warn examples console.warn("[console.warn] This is warning message."); @@ -41,6 +44,7 @@ function main() { console.warn(a = 2 * 6); console.warn(someValue); console.warn('someObject id ' + someObject.id); + console.warn('Hello World ', 'someObject.id = ', someObject.id, "a = 2 * 6 = ", a = 2 * 6); // console.error examples console.error('An error occurred!'); @@ -64,15 +68,16 @@ function main() { } fooA(); - //console.asserts() examples + // console.assert() examples var valA = 1, valB = "1"; - console.asserts(valA === valB, "Value A doesn't equal to B"); - console.asserts(valA === valB); - console.asserts(5 === 5, "5 equals to 5"); - console.asserts(5 === 5); - console.asserts(5 > 6, "5 is not greater than 6"); + console.assert(valA === valB, "Value A doesn't equal to B"); + console.assert(valA === valB); + console.assert(5 === 5, "5 equals to 5"); + console.assert(5 === 5); + console.assert(5 > 6, "5 is not greater than 6"); + console.assert(5 > 6, "5 is not greater than 6", "This assertion will fail"); - //console.group() examples. + // console.group() examples. console.group("Group 1"); console.log("Sentence 1"); console.log("Sentence 2"); @@ -89,11 +94,11 @@ function main() { console.groupEnd(); console.log("Sentence 9"); - //console.time(),console.timeEnd() examples - console.time('Timer1'); + // console.time(),console.timeEnd() examples + console.time('MyTimer'); // Do some process sleep(1000); - console.timeEnd('Timer1'); + console.timeEnd('MyTimer'); // use console.clear() to clean Debug Window logs // console.clear();