History

Improve script engine error logging + some cleanup

Atlante45 committed 11 years ago

Commit 421d9671 parent 4e33aa83 files · +56 −25Browse files

Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 3 files). Show all

Unified · Split

libraries/script-engine/src/ScriptEngine.cpp+51−23
@@ -556,7 +556,7 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& · 555 unmodified lines
556556 }
557557
558558
559−QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber) {
559+QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fileName, int lineNumber) {
560560 if (_stoppingAllScripts) {
561561 return QScriptValue(); // bail early
562562 }
@@ -565,27 +565,30 @@ QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileN · 2 unmodified lines
565565 QScriptValue result;
566566 #ifdef THREAD_DEBUGGING
567567 qDebug() << "*** WARNING *** ScriptEngine::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
568− "program:" << program << " fileName:" << fileName << "lineNumber:" << lineNumber;
568+ "sourceCode:" << sourceCode << " fileName:" << fileName << "lineNumber:" << lineNumber;
569569 #endif
570570 QMetaObject::invokeMethod(this, "evaluate", Qt::BlockingQueuedConnection,
571571 Q_RETURN_ARG(QScriptValue, result),
572− Q_ARG(const QString&, program),
572+ Q_ARG(const QString&, sourceCode),
573573 Q_ARG(const QString&, fileName),
574574 Q_ARG(int, lineNumber));
575575 return result;
576576 }
577−
578− _evaluatesPending++;
579− QScriptValue result = QScriptEngine::evaluate(program, fileName, lineNumber);
580− if (hasUncaughtException()) {
581− int line = uncaughtExceptionLineNumber();
582− qCDebug(scriptengine) << "Uncaught exception at (" << _fileNameString << " : " << fileName << ") line" << line << ": " << result.toString();
577+
578+ // Check synthax
579+ const QScriptProgram program(sourceCode, fileName, lineNumber);
580+ if (!checkSynthax(program)) {
581+ return QScriptValue();
583582 }
584− _evaluatesPending--;
583+
584+ ++_evaluatesPending;
585+ const auto result = QScriptEngine::evaluate(program);
586+ --_evaluatesPending;
587+
588+ const auto hadUncaughtException = checkExceptions(this, program.fileName());
585589 if (_wantSignals) {
586− emit evaluationFinished(result, hasUncaughtException());
590+ emit evaluationFinished(result, hadUncaughtException);
587591 }
588− clearExceptions();
589592 return result;
590593 }
591594
@@ -603,7 +606,7 @@ void ScriptEngine::run() { · 11 unmodified lines
603606 emit runningStateChanged();
604607 }
605608
606− QScriptValue result = evaluate(_scriptContents);
609+ QScriptValue result = evaluate(_scriptContents, _fileNameString);
607610
608611 QElapsedTimer startTime;
609612 startTime.start();
@@ -644,15 +647,6 @@ void ScriptEngine::run() { · 34 unmodified lines
644647 qint64 now = usecTimestampNow();
645648 float deltaTime = (float) (now - lastUpdate) / (float) USECS_PER_SECOND;
646649
647− if (hasUncaughtException()) {
648− int line = uncaughtExceptionLineNumber();
649− qCDebug(scriptengine) << "Uncaught exception at (" << _fileNameString << ") line" << line << ":" << uncaughtException().toString();
650− if (_wantSignals) {
651− emit errorMessage("Uncaught exception at (" + _fileNameString + ") line" + QString::number(line) + ":" + uncaughtException().toString());
652− }
653− clearExceptions();
654− }
655−
656650 if (!_isFinished) {
657651 if (_wantSignals) {
658652 emit update(deltaTime);
@@ -660,6 +654,7 @@ void ScriptEngine::run() { · 1 unmodified line
660654 }
661655 lastUpdate = now;
662656
657+ checkExceptions(this, _fileNameString);
663658 }
664659
665660 stopAllTimers(); // make sure all our timers are stopped if the script is ending
@@ -896,6 +891,38 @@ void ScriptEngine::load(const QString& loadFile) { · 230 unmodified lines
896891 }
897892 }
898893
894+
895+bool ScriptEngine::checkSynthax(const QScriptProgram& program) {
896+ const auto syntaxCheck = QScriptEngine::checkSyntax(program.sourceCode());
897+ if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) {
898+ const auto error = syntaxCheck.errorMessage();
899+ const auto line = QString::number(syntaxCheck.errorLineNumber());
900+ const auto column = QString::number(syntaxCheck.errorColumnNumber());
901+ const auto message = QString("[SyntaxError] %1 in %2:%3(%4)").arg(error, program.fileName(), line, column);
902+ qCWarning(scriptengine) << qPrintable(message);
903+ return false;
904+ }
905+ return true;
906+}
907+
908+bool ScriptEngine::checkExceptions(QScriptEngine* engine, const QString& fileName) {
909+ if (engine->hasUncaughtException()) {
910+ const auto backtrace = engine->uncaughtExceptionBacktrace();
911+ const auto exception = engine->uncaughtException().toString();
912+ const auto line = QString::number(engine->uncaughtExceptionLineNumber());
913+ engine->clearExceptions();
914+
915+ auto message = QString("[UncaughtException] %1 in %2:%3").arg(exception, fileName, line);
916+ if (!backtrace.empty()) {
917+ static const auto lineSeparator = "\n ";
918+ message += QString("\n[Backtrace]%1%2").arg(lineSeparator, backtrace.join(lineSeparator));
919+ }
920+ qCWarning(scriptengine) << qPrintable(message);
921+ return false;
922+ }
923+ return true;
924+}
925+
899926 // Look up the handler associated with eventName and entityID. If found, evalute the argGenerator thunk and call the handler with those args
900927 void ScriptEngine::forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs) {
901928 if (QThread::currentThread() != thread()) {
@@ -1015,7 +1042,8 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 113 unmodified lines
10151042 lastModified = (quint64)QFileInfo(file).lastModified().toMSecsSinceEpoch();
10161043 }
10171044
1018− QScriptValue entityScriptConstructor = evaluate(contents);
1045+ auto fileName = QString("(EntityID:%1, %2)").arg(entityID.toString(), isURL ? scriptOrURL : "EmbededEntityScript");
1046+ QScriptValue entityScriptConstructor = evaluate(contents, fileName);
10191047 QScriptValue entityScriptObject = entityScriptConstructor.construct();
10201048 EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject, lastModified };
10211049 _entityScripts[entityID] = newDetails;