mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 16:09:22 +02:00
Complete Console Exception.
This commit is contained in:
parent
71bff04ce0
commit
e8fc766c2b
6 changed files with 108 additions and 12 deletions
|
@ -52,10 +52,46 @@ void ConsoleScriptingInterface::error(QString message) {
|
|||
|
||||
void ConsoleScriptingInterface::exception(QString message) {
|
||||
if (ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(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<ScriptEngine*>(engine())) {
|
||||
scriptEngine->scriptErrorMessage(labelName);
|
||||
scriptEngine->logTraceException();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <QtCore/QString>
|
||||
#include <QtScript/QScriptable>
|
||||
#include <QHash>
|
||||
#include "EntityEditFilters.h"
|
||||
#include <QUrl>
|
||||
#include <QList>
|
||||
|
||||
|
||||
|
@ -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<QString, QDateTime> _listOfTimeValues;
|
||||
const qint64 DAY = 86400;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -21,6 +21,7 @@ class BaseScriptEngine : public QScriptEngine, public QEnableSharedFromThis<Base
|
|||
Q_OBJECT
|
||||
public:
|
||||
static const QString SCRIPT_EXCEPTION_FORMAT;
|
||||
static const QString SCRIPT_TRACE_FORMAT;
|
||||
static const QString SCRIPT_BACKTRACE_SEP;
|
||||
|
||||
// threadsafe "unbound" version of QScriptEngine::nullValue()
|
||||
|
@ -29,10 +30,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 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 QString formatTrace(const QScriptValue& val, 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
|
||||
|
@ -41,7 +42,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);
|
||||
|
||||
void raiseConsoleException(const QScriptValue& exception);
|
||||
QScriptValue raiseConsoleTraceException(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:
|
||||
|
|
Loading…
Reference in a new issue