Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 3 files). Show all
Unified · Split
| @@ -556,7 +556,7 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& · 555 unmodified lines | |||
| 556 | } | 556 | } |
| 557 | 557 | ||
| 558 | 558 | ||
| 559 | QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber) { | 559 | QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fileName, int lineNumber) { |
| 560 | if (_stoppingAllScripts) { | 560 | if (_stoppingAllScripts) { |
| 561 | return QScriptValue(); // bail early | 561 | return QScriptValue(); // bail early |
| 562 | } | 562 | } |
| @@ -565,27 +565,30 @@ QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileN · 2 unmodified lines | |||
| 565 | QScriptValue result; | 565 | QScriptValue result; |
| 566 | #ifdef THREAD_DEBUGGING | 566 | #ifdef THREAD_DEBUGGING |
| 567 | qDebug() << "*** WARNING *** ScriptEngine::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | 567 | 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; |
| 569 | #endif | 569 | #endif |
| 570 | QMetaObject::invokeMethod(this, "evaluate", Qt::BlockingQueuedConnection, | 570 | QMetaObject::invokeMethod(this, "evaluate", Qt::BlockingQueuedConnection, |
| 571 | Q_RETURN_ARG(QScriptValue, result), | 571 | Q_RETURN_ARG(QScriptValue, result), |
| 572 | Q_ARG(const QString&, program), | 572 | Q_ARG(const QString&, sourceCode), |
| 573 | Q_ARG(const QString&, fileName), | 573 | Q_ARG(const QString&, fileName), |
| 574 | Q_ARG(int, lineNumber)); | 574 | Q_ARG(int, lineNumber)); |
| 575 | return result; | 575 | return result; |
| 576 | } | 576 | } |
| 577 | 577 | ||
| 578 | _evaluatesPending++; | 578 | // Check synthax |
| 579 | QScriptValue result = QScriptEngine::evaluate(program, fileName, lineNumber); | 579 | const QScriptProgram program(sourceCode, fileName, lineNumber); |
| 580 | if (hasUncaughtException()) { | 580 | if (!checkSynthax(program)) { |
| 581 | int line = uncaughtExceptionLineNumber(); | 581 | return QScriptValue(); |
| 582 | qCDebug(scriptengine) << "Uncaught exception at (" << _fileNameString << " : " << fileName << ") line" << line << ": " << result.toString(); | ||
| 583 | } | 582 | } |
| 584 | _evaluatesPending--; | 583 | |
| 584 | ++_evaluatesPending; | ||
| 585 | const auto result = QScriptEngine::evaluate(program); | ||
| 586 | --_evaluatesPending; | ||
| 587 | |||
| 588 | const auto hadUncaughtException = checkExceptions(this, program.fileName()); | ||
| 585 | if (_wantSignals) { | 589 | if (_wantSignals) { |
| 586 | emit evaluationFinished(result, hasUncaughtException()); | 590 | emit evaluationFinished(result, hadUncaughtException); |
| 587 | } | 591 | } |
| 588 | clearExceptions(); | ||
| 589 | return result; | 592 | return result; |
| 590 | } | 593 | } |
| 591 | 594 | ||
| @@ -603,7 +606,7 @@ void ScriptEngine::run() { · 11 unmodified lines | |||
| 603 | emit runningStateChanged(); | 606 | emit runningStateChanged(); |
| 604 | } | 607 | } |
| 605 | 608 | ||
| 606 | QScriptValue result = evaluate(_scriptContents); | 609 | QScriptValue result = evaluate(_scriptContents, _fileNameString); |
| 607 | 610 | ||
| 608 | QElapsedTimer startTime; | 611 | QElapsedTimer startTime; |
| 609 | startTime.start(); | 612 | startTime.start(); |
| @@ -644,15 +647,6 @@ void ScriptEngine::run() { · 34 unmodified lines | |||
| 644 | qint64 now = usecTimestampNow(); | 647 | qint64 now = usecTimestampNow(); |
| 645 | float deltaTime = (float) (now - lastUpdate) / (float) USECS_PER_SECOND; | 648 | float deltaTime = (float) (now - lastUpdate) / (float) USECS_PER_SECOND; |
| 646 | 649 | ||
| 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 | |||
| 656 | if (!_isFinished) { | 650 | if (!_isFinished) { |
| 657 | if (_wantSignals) { | 651 | if (_wantSignals) { |
| 658 | emit update(deltaTime); | 652 | emit update(deltaTime); |
| @@ -660,6 +654,7 @@ void ScriptEngine::run() { · 1 unmodified line | |||
| 660 | } | 654 | } |
| 661 | lastUpdate = now; | 655 | lastUpdate = now; |
| 662 | 656 | ||
| 657 | checkExceptions(this, _fileNameString); | ||
| 663 | } | 658 | } |
| 664 | 659 | ||
| 665 | stopAllTimers(); // make sure all our timers are stopped if the script is ending | 660 | 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 | |||
| 896 | } | 891 | } |
| 897 | } | 892 | } |
| 898 | 893 | ||
| 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 | |||
| 899 | // Look up the handler associated with eventName and entityID. If found, evalute the argGenerator thunk and call the handler with those args | 926 | // Look up the handler associated with eventName and entityID. If found, evalute the argGenerator thunk and call the handler with those args |
| 900 | void ScriptEngine::forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs) { | 927 | void ScriptEngine::forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs) { |
| 901 | if (QThread::currentThread() != thread()) { | 928 | if (QThread::currentThread() != thread()) { |
| @@ -1015,7 +1042,8 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 113 unmodified lines | |||
| 1015 | lastModified = (quint64)QFileInfo(file).lastModified().toMSecsSinceEpoch(); | 1042 | lastModified = (quint64)QFileInfo(file).lastModified().toMSecsSinceEpoch(); |
| 1016 | } | 1043 | } |
| 1017 | 1044 | ||
| 1018 | QScriptValue entityScriptConstructor = evaluate(contents); | 1045 | auto fileName = QString("(EntityID:%1, %2)").arg(entityID.toString(), isURL ? scriptOrURL : "EmbededEntityScript"); |
| 1046 | QScriptValue entityScriptConstructor = evaluate(contents, fileName); | ||
| 1019 | QScriptValue entityScriptObject = entityScriptConstructor.construct(); | 1047 | QScriptValue entityScriptObject = entityScriptConstructor.construct(); |
| 1020 | EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject, lastModified }; | 1048 | EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject, lastModified }; |
| 1021 | _entityScripts[entityID] = newDetails; | 1049 | _entityScripts[entityID] = newDetails; |