Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 173 files). Show all
Unified · Split
| @@ -71,6 +71,8 @@ static const QString SCRIPT_EXCEPTION_FORMAT = "[UncaughtException] %1 in %2:%3" · 70 unmodified lines | ||
| 71 | 71 | Q_DECLARE_METATYPE(QScriptEngine::FunctionSignature) |
| 72 | 72 | int functionSignatureMetaID = qRegisterMetaType<QScriptEngine::FunctionSignature>(); |
| 73 | 73 | |
| 74 | +Q_LOGGING_CATEGORY(scriptengineScript, "hifi.scriptengine.script") | |
| 75 | + | |
| 74 | 76 | static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine){ |
| 75 | 77 | QString message = ""; |
| 76 | 78 | for (int i = 0; i < context->argumentCount(); i++) { |
| @@ -79,12 +81,14 @@ static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine){ · 2 unmodified lines | ||
| 79 | 81 | } |
| 80 | 82 | message += context->argument(i).toString(); |
| 81 | 83 | } |
| 82 | − qCDebug(scriptengine).noquote() << "script:print()<<" << message; // noquote() so that \n is treated as newline | |
| 84 | + qCDebug(scriptengineScript).noquote() << "script:print()<<" << message; // noquote() so that \n is treated as newline | |
| 83 | 85 | |
| 84 | 86 | message = message.replace("\\", "\\\\") |
| 85 | 87 | .replace("\n", "\\n") |
| 86 | 88 | .replace("\r", "\\r") |
| 87 | 89 | .replace("'", "\\'"); |
| 90 | + | |
| 91 | + // FIXME - this approach neeeds revisiting. print() comes here, which ends up doing an evaluate? | |
| 88 | 92 | engine->evaluate("Script.print('" + message + "')"); |
| 89 | 93 | |
| 90 | 94 | return QScriptValue(); |
| @@ -129,20 +133,20 @@ QString encodeEntityIdIntoEntityUrl(const QString& url, const QString& entityID) · 38 unmodified lines | ||
| 129 | 133 | return url + " [EntityID:" + entityID + "]"; |
| 130 | 134 | } |
| 131 | 135 | |
| 132 | −static bool hasCorrectSyntax(const QScriptProgram& program) { | |
| 136 | +static bool hasCorrectSyntax(const QScriptProgram& program, ScriptEngine* reportingEngine) { | |
| 133 | 137 | const auto syntaxCheck = QScriptEngine::checkSyntax(program.sourceCode()); |
| 134 | 138 | if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) { |
| 135 | 139 | const auto error = syntaxCheck.errorMessage(); |
| 136 | 140 | const auto line = QString::number(syntaxCheck.errorLineNumber()); |
| 137 | 141 | const auto column = QString::number(syntaxCheck.errorColumnNumber()); |
| 138 | 142 | const auto message = QString("[SyntaxError] %1 in %2:%3(%4)").arg(error, program.fileName(), line, column); |
| 139 | − qCWarning(scriptengine) << qPrintable(message); | |
| 143 | + reportingEngine->scriptErrorMessage(qPrintable(message)); | |
| 140 | 144 | return false; |
| 141 | 145 | } |
| 142 | 146 | return true; |
| 143 | 147 | } |
| 144 | 148 | |
| 145 | −static bool hadUncaughtExceptions(QScriptEngine& engine, const QString& fileName) { | |
| 149 | +static bool hadUncaughtExceptions(QScriptEngine& engine, const QString& fileName, ScriptEngine* reportingEngine) { | |
| 146 | 150 | if (engine.hasUncaughtException()) { |
| 147 | 151 | const auto backtrace = engine.uncaughtExceptionBacktrace(); |
| 148 | 152 | const auto exception = engine.uncaughtException().toString(); |
| @@ -154,7 +158,7 @@ static bool hadUncaughtExceptions(QScriptEngine& engine, const QString& fileName · 5 unmodified lines | ||
| 154 | 158 | static const auto lineSeparator = "\n "; |
| 155 | 159 | message += QString("\n[Backtrace]%1%2").arg(lineSeparator, backtrace.join(lineSeparator)); |
| 156 | 160 | } |
| 157 | − qCWarning(scriptengine) << qPrintable(message); | |
| 161 | + reportingEngine->scriptErrorMessage(qPrintable(message)); | |
| 158 | 162 | return true; |
| 159 | 163 | } |
| 160 | 164 | return false; |
| @@ -169,20 +173,20 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam · 8 unmodified lines | ||
| 169 | 173 | DependencyManager::get<ScriptEngines>()->addScriptEngine(this); |
| 170 | 174 | |
| 171 | 175 | connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) { |
| 172 | − hadUncaughtExceptions(*this, _fileNameString); | |
| 176 | + hadUncaughtExceptions(*this, _fileNameString, this); | |
| 173 | 177 | }); |
| 174 | 178 | |
| 175 | 179 | setProcessEventsInterval(MSECS_PER_SECOND); |
| 176 | 180 | } |
| 177 | 181 | |
| 178 | 182 | ScriptEngine::~ScriptEngine() { |
| 179 | − qCDebug(scriptengine) << "Script Engine shutting down:" << getFilename(); | |
| 183 | + scriptInfoMessage("Script Engine shutting down:" + getFilename()); | |
| 180 | 184 | |
| 181 | 185 | auto scriptEngines = DependencyManager::get<ScriptEngines>(); |
| 182 | 186 | if (scriptEngines) { |
| 183 | 187 | scriptEngines->removeScriptEngine(this); |
| 184 | 188 | } else { |
| 185 | − qCWarning(scriptengine) << "Script destroyed after ScriptEngines!"; | |
| 189 | + scriptWarningMessage("Script destroyed after ScriptEngines!"); | |
| 186 | 190 | } |
| 187 | 191 | } |
| 188 | 192 | |
| @@ -273,7 +277,7 @@ void ScriptEngine::runDebuggable() { · 84 unmodified lines | ||
| 273 | 277 | } |
| 274 | 278 | _lastUpdate = now; |
| 275 | 279 | // Debug and clear exceptions |
| 276 | − hadUncaughtExceptions(*this, _fileNameString); | |
| 280 | + hadUncaughtExceptions(*this, _fileNameString, this); | |
| 277 | 281 | }); |
| 278 | 282 | |
| 279 | 283 | timer->start(10); |
| @@ -358,7 +362,7 @@ void ScriptEngine::waitTillDoneRunning() { · 78 unmodified lines | ||
| 358 | 362 | QThread::yieldCurrentThread(); |
| 359 | 363 | } |
| 360 | 364 | |
| 361 | − qCDebug(scriptengine) << "Script Engine has stopped:" << getFilename(); | |
| 365 | + scriptInfoMessage("Script Engine has stopped:" + getFilename()); | |
| 362 | 366 | } |
| 363 | 367 | } |
| 364 | 368 | |
| @@ -397,10 +401,25 @@ void ScriptEngine::scriptContentsAvailable(const QUrl& url, const QString& scrip · 32 unmodified lines | ||
| 397 | 401 | emit scriptLoaded(url.toString()); |
| 398 | 402 | } |
| 399 | 403 | |
| 404 | +void ScriptEngine::scriptErrorMessage(const QString& message) { | |
| 405 | + qCCritical(scriptengine) << message; | |
| 406 | + emit errorMessage(message); | |
| 407 | +} | |
| 408 | + | |
| 409 | +void ScriptEngine::scriptWarningMessage(const QString& message) { | |
| 410 | + qCWarning(scriptengine) << message; | |
| 411 | + emit warningMessage(message); | |
| 412 | +} | |
| 413 | + | |
| 414 | +void ScriptEngine::scriptInfoMessage(const QString& message) { | |
| 415 | + qCInfo(scriptengine) << message; | |
| 416 | + emit infoMessage(message); | |
| 417 | +} | |
| 418 | + | |
| 400 | 419 | // FIXME - switch this to the new model of ScriptCache callbacks |
| 401 | 420 | void ScriptEngine::errorInLoadingScript(const QUrl& url) { |
| 402 | − qCDebug(scriptengine) << "ERROR Loading file:" << url.toString() << "line:" << __LINE__; | |
| 403 | − emit errorLoadingScript(_fileNameString); // ?? | |
| 421 | + scriptErrorMessage("ERROR Loading file:" + url.toString()); | |
| 422 | + emit errorLoadingScript(_fileNameString); | |
| 404 | 423 | } |
| 405 | 424 | |
| 406 | 425 | // Even though we never pass AnimVariantMap directly to and from javascript, the queued invokeMethod of |
| @@ -552,7 +571,7 @@ void ScriptEngine::init() { · 145 unmodified lines | ||
| 552 | 571 | void ScriptEngine::registerValue(const QString& valueName, QScriptValue value) { |
| 553 | 572 | if (QThread::currentThread() != thread()) { |
| 554 | 573 | #ifdef THREAD_DEBUGGING |
| 555 | − qDebug() << "*** WARNING *** ScriptEngine::registerValue() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]"; | |
| 574 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::registerValue() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]"; | |
| 556 | 575 | #endif |
| 557 | 576 | QMetaObject::invokeMethod(this, "registerValue", |
| 558 | 577 | Q_ARG(const QString&, valueName), |
| @@ -582,7 +601,7 @@ void ScriptEngine::registerValue(const QString& valueName, QScriptValue value) { · 23 unmodified lines | ||
| 582 | 601 | void ScriptEngine::registerGlobalObject(const QString& name, QObject* object) { |
| 583 | 602 | if (QThread::currentThread() != thread()) { |
| 584 | 603 | #ifdef THREAD_DEBUGGING |
| 585 | − qDebug() << "*** WARNING *** ScriptEngine::registerGlobalObject() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; | |
| 604 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::registerGlobalObject() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; | |
| 586 | 605 | #endif |
| 587 | 606 | QMetaObject::invokeMethod(this, "registerGlobalObject", |
| 588 | 607 | Q_ARG(const QString&, name), |
| @@ -590,7 +609,7 @@ void ScriptEngine::registerGlobalObject(const QString& name, QObject* object) { · 1 unmodified line | ||
| 590 | 609 | return; |
| 591 | 610 | } |
| 592 | 611 | #ifdef THREAD_DEBUGGING |
| 593 | − qDebug() << "ScriptEngine::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name; | |
| 612 | + qCDebug(scriptengine) << "ScriptEngine::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name; | |
| 594 | 613 | #endif |
| 595 | 614 | |
| 596 | 615 | if (!globalObject().property(name).isValid()) { |
| @@ -606,7 +625,7 @@ void ScriptEngine::registerGlobalObject(const QString& name, QObject* object) { · 9 unmodified lines | ||
| 606 | 625 | void ScriptEngine::registerFunction(const QString& name, QScriptEngine::FunctionSignature functionSignature, int numArguments) { |
| 607 | 626 | if (QThread::currentThread() != thread()) { |
| 608 | 627 | #ifdef THREAD_DEBUGGING |
| 609 | − qDebug() << "*** WARNING *** ScriptEngine::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; | |
| 628 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; | |
| 610 | 629 | #endif |
| 611 | 630 | QMetaObject::invokeMethod(this, "registerFunction", |
| 612 | 631 | Q_ARG(const QString&, name), |
| @@ -615,7 +634,7 @@ void ScriptEngine::registerFunction(const QString& name, QScriptEngine::Function · 2 unmodified lines | ||
| 615 | 634 | return; |
| 616 | 635 | } |
| 617 | 636 | #ifdef THREAD_DEBUGGING |
| 618 | − qDebug() << "ScriptEngine::registerFunction() called on thread [" << QThread::currentThread() << "] name:" << name; | |
| 637 | + qCDebug(scriptengine) << "ScriptEngine::registerFunction() called on thread [" << QThread::currentThread() << "] name:" << name; | |
| 619 | 638 | #endif |
| 620 | 639 | |
| 621 | 640 | QScriptValue scriptFun = newFunction(functionSignature, numArguments); |
| @@ -625,7 +644,7 @@ void ScriptEngine::registerFunction(const QString& name, QScriptEngine::Function · 3 unmodified lines | ||
| 625 | 644 | void ScriptEngine::registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature functionSignature, int numArguments) { |
| 626 | 645 | if (QThread::currentThread() != thread()) { |
| 627 | 646 | #ifdef THREAD_DEBUGGING |
| 628 | − qDebug() << "*** WARNING *** ScriptEngine::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] parent:" << parent << "name:" << name; | |
| 647 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] parent:" << parent << "name:" << name; | |
| 629 | 648 | #endif |
| 630 | 649 | QMetaObject::invokeMethod(this, "registerFunction", |
| 631 | 650 | Q_ARG(const QString&, name), |
| @@ -634,7 +653,7 @@ void ScriptEngine::registerFunction(const QString& parent, const QString& name, · 2 unmodified lines | ||
| 634 | 653 | return; |
| 635 | 654 | } |
| 636 | 655 | #ifdef THREAD_DEBUGGING |
| 637 | − qDebug() << "ScriptEngine::registerFunction() called on thread [" << QThread::currentThread() << "] parent:" << parent << "name:" << name; | |
| 656 | + qCDebug(scriptengine) << "ScriptEngine::registerFunction() called on thread [" << QThread::currentThread() << "] parent:" << parent << "name:" << name; | |
| 638 | 657 | #endif |
| 639 | 658 | |
| 640 | 659 | QScriptValue object = globalObject().property(parent); |
| @@ -648,7 +667,7 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func · 7 unmodified lines | ||
| 648 | 667 | QScriptEngine::FunctionSignature setter, const QString& parent) { |
| 649 | 668 | if (QThread::currentThread() != thread()) { |
| 650 | 669 | #ifdef THREAD_DEBUGGING |
| 651 | − qDebug() << "*** WARNING *** ScriptEngine::registerGetterSetter() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 670 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::registerGetterSetter() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 652 | 671 | " name:" << name << "parent:" << parent; |
| 653 | 672 | #endif |
| 654 | 673 | QMetaObject::invokeMethod(this, "registerGetterSetter", |
| @@ -659,7 +678,7 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func · 4 unmodified lines | ||
| 659 | 678 | return; |
| 660 | 679 | } |
| 661 | 680 | #ifdef THREAD_DEBUGGING |
| 662 | − qDebug() << "ScriptEngine::registerGetterSetter() called on thread [" << QThread::currentThread() << "] name:" << name << "parent:" << parent; | |
| 681 | + qCDebug(scriptengine) << "ScriptEngine::registerGetterSetter() called on thread [" << QThread::currentThread() << "] name:" << name << "parent:" << parent; | |
| 663 | 682 | #endif |
| 664 | 683 | |
| 665 | 684 | QScriptValue setterFunction = newFunction(setter, 1); |
| @@ -681,7 +700,7 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func · 15 unmodified lines | ||
| 681 | 700 | void ScriptEngine::removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) { |
| 682 | 701 | if (QThread::currentThread() != thread()) { |
| 683 | 702 | #ifdef THREAD_DEBUGGING |
| 684 | − qDebug() << "*** WARNING *** ScriptEngine::removeEventHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 703 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::removeEventHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 685 | 704 | "entityID:" << entityID << " eventName:" << eventName; |
| 686 | 705 | #endif |
| 687 | 706 | QMetaObject::invokeMethod(this, "removeEventHandler", |
| @@ -691,7 +710,7 @@ void ScriptEngine::removeEventHandler(const EntityItemID& entityID, const QStrin · 3 unmodified lines | ||
| 691 | 710 | return; |
| 692 | 711 | } |
| 693 | 712 | #ifdef THREAD_DEBUGGING |
| 694 | − qDebug() << "ScriptEngine::removeEventHandler() called on thread [" << QThread::currentThread() << "] entityID:" << entityID << " eventName : " << eventName; | |
| 713 | + qCDebug(scriptengine) << "ScriptEngine::removeEventHandler() called on thread [" << QThread::currentThread() << "] entityID:" << entityID << " eventName : " << eventName; | |
| 695 | 714 | #endif |
| 696 | 715 | |
| 697 | 716 | if (!_registeredHandlers.contains(entityID)) { |
| @@ -711,7 +730,7 @@ void ScriptEngine::removeEventHandler(const EntityItemID& entityID, const QStrin · 13 unmodified lines | ||
| 711 | 730 | void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) { |
| 712 | 731 | if (QThread::currentThread() != thread()) { |
| 713 | 732 | #ifdef THREAD_DEBUGGING |
| 714 | − qDebug() << "*** WARNING *** ScriptEngine::addEventHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 733 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::addEventHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 715 | 734 | "entityID:" << entityID << " eventName:" << eventName; |
| 716 | 735 | #endif |
| 717 | 736 | |
| @@ -722,7 +741,7 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& · 4 unmodified lines | ||
| 722 | 741 | return; |
| 723 | 742 | } |
| 724 | 743 | #ifdef THREAD_DEBUGGING |
| 725 | − qDebug() << "ScriptEngine::addEventHandler() called on thread [" << QThread::currentThread() << "] entityID:" << entityID << " eventName : " << eventName; | |
| 744 | + qCDebug(scriptengine) << "ScriptEngine::addEventHandler() called on thread [" << QThread::currentThread() << "] entityID:" << entityID << " eventName : " << eventName; | |
| 726 | 745 | #endif |
| 727 | 746 | |
| 728 | 747 | if (_registeredHandlers.count() == 0) { // First time any per-entity handler has been added in this script... |
| @@ -784,7 +803,7 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& · 55 unmodified lines | ||
| 784 | 803 | _registeredHandlers[entityID] = RegisteredEventHandlers(); |
| 785 | 804 | } |
| 786 | 805 | CallbackList& handlersForEvent = _registeredHandlers[entityID][eventName]; |
| 787 | − CallbackData handlerData = {handler, currentEntityIdentifier, currentSandboxURL}; | |
| 806 | + CallbackData handlerData = { handler, currentEntityIdentifier, currentSandboxURL }; | |
| 788 | 807 | handlersForEvent << handlerData; // Note that the same handler can be added many times. See removeEntityEventHandler(). |
| 789 | 808 | } |
| 790 | 809 | |
| @@ -797,7 +816,7 @@ QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fi · 6 unmodified lines | ||
| 797 | 816 | if (QThread::currentThread() != thread()) { |
| 798 | 817 | QScriptValue result; |
| 799 | 818 | #ifdef THREAD_DEBUGGING |
| 800 | − qDebug() << "*** WARNING *** ScriptEngine::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 819 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 801 | 820 | "sourceCode:" << sourceCode << " fileName:" << fileName << "lineNumber:" << lineNumber; |
| 802 | 821 | #endif |
| 803 | 822 | QMetaObject::invokeMethod(this, "evaluate", Qt::BlockingQueuedConnection, |
| @@ -810,7 +829,7 @@ QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fi · 6 unmodified lines | ||
| 810 | 829 | |
| 811 | 830 | // Check syntax |
| 812 | 831 | const QScriptProgram program(sourceCode, fileName, lineNumber); |
| 813 | − if (!hasCorrectSyntax(program)) { | |
| 832 | + if (!hasCorrectSyntax(program, this)) { | |
| 814 | 833 | return QScriptValue(); |
| 815 | 834 | } |
| 816 | 835 | |
| @@ -818,7 +837,7 @@ QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fi · 1 unmodified line | ||
| 818 | 837 | const auto result = QScriptEngine::evaluate(program); |
| 819 | 838 | --_evaluatesPending; |
| 820 | 839 | |
| 821 | − const auto hadUncaughtException = hadUncaughtExceptions(*this, program.fileName()); | |
| 840 | + const auto hadUncaughtException = hadUncaughtExceptions(*this, program.fileName(), this); | |
| 822 | 841 | emit evaluationFinished(result, hadUncaughtException); |
| 823 | 842 | return result; |
| 824 | 843 | } |
| @@ -862,23 +881,48 @@ void ScriptEngine::run() { · 37 unmodified lines | ||
| 862 | 881 | // Throttle to SCRIPT_FPS |
| 863 | 882 | // We'd like to try to keep the script at a solid SCRIPT_FPS update rate. And so we will |
| 864 | 883 | // calculate a sleepUntil to be the time from our start time until the original target |
| 865 | − // sleepUntil for this frame. | |
| 866 | − const std::chrono::microseconds FRAME_DURATION(USECS_PER_SECOND / SCRIPT_FPS + 1); | |
| 867 | − clock::time_point targetSleepUntil(startTime + thisFrame++ * FRAME_DURATION); | |
| 868 | − | |
| 869 | − // However, if our sleepUntil is not at least our average update time into the future | |
| 870 | − // it means our script is taking too long in it's updates, and we want to punish the | |
| 871 | − // script a little bit. So we will force the sleepUntil to be at least our averageUpdate | |
| 872 | − // time into the future. | |
| 884 | + // sleepUntil for this frame. This approach will allow us to "catch up" in the event | |
| 885 | + // that some of our script udpates/frames take a little bit longer than the target average | |
| 886 | + // to execute. | |
| 887 | + // NOTE: if we go to variable SCRIPT_FPS, then we will need to reconsider this approach | |
| 888 | + const std::chrono::microseconds TARGET_SCRIPT_FRAME_DURATION(USECS_PER_SECOND / SCRIPT_FPS + 1); | |
| 889 | + clock::time_point targetSleepUntil(startTime + (thisFrame++ * TARGET_SCRIPT_FRAME_DURATION)); | |
| 890 | + | |
| 891 | + // However, if our sleepUntil is not at least our average update and timer execution time | |
| 892 | + // into the future it means our script is taking too long in its updates, and we want to | |
| 893 | + // punish the script a little bit. So we will force the sleepUntil to be at least our | |
| 894 | + // averageUpdate + averageTimerPerFrame time into the future. | |
| 873 | 895 | auto averageUpdate = totalUpdates / thisFrame; |
| 874 | − auto sleepUntil = std::max(targetSleepUntil, beforeSleep + averageUpdate); | |
| 896 | + auto averageTimerPerFrame = _totalTimerExecution / thisFrame; | |
| 897 | + auto averageTimerAndUpdate = averageUpdate + averageTimerPerFrame; | |
| 898 | + auto sleepUntil = std::max(targetSleepUntil, beforeSleep + averageTimerAndUpdate); | |
| 875 | 899 | |
| 876 | 900 | // We don't want to actually sleep for too long, because it causes our scripts to hang |
| 877 | 901 | // on shutdown and stop... so we want to loop and sleep until we've spent our time in |
| 878 | 902 | // purgatory, constantly checking to see if our script was asked to end |
| 903 | + bool processedEvents = false; | |
| 879 | 904 | while (!_isFinished && clock::now() < sleepUntil) { |
| 905 | + | |
| 880 | 906 | QCoreApplication::processEvents(); // before we sleep again, give events a chance to process |
| 881 | − auto thisSleepUntil = std::min(sleepUntil, clock::now() + FRAME_DURATION); | |
| 907 | + processedEvents = true; | |
| 908 | + | |
| 909 | + // If after processing events, we're past due, exit asap | |
| 910 | + if (clock::now() >= sleepUntil) { | |
| 911 | + break; | |
| 912 | + } | |
| 913 | + | |
| 914 | + // determine how long before the next timer should fire, we'd ideally like to sleep just | |
| 915 | + // that long, so the next processEvents() will allow the timers to fire on time. | |
| 916 | + const std::chrono::microseconds minTimerTimeRemaining(USECS_PER_MSEC * getTimersRemainingTime()); | |
| 917 | + | |
| 918 | + // However, if we haven't yet slept at least as long as our average timer per frame, then we will | |
| 919 | + // punish the timers to at least wait as long as the average run time of the timers. | |
| 920 | + auto untilTimer = std::max(minTimerTimeRemaining, averageTimerPerFrame); | |
| 921 | + | |
| 922 | + // choose the closest time point, our | |
| 923 | + auto remainingSleepUntil = std::chrono::duration_cast<std::chrono::microseconds>(sleepUntil - clock::now()); | |
| 924 | + auto closestUntil = std::min(remainingSleepUntil, untilTimer); | |
| 925 | + auto thisSleepUntil = std::min(sleepUntil, clock::now() + closestUntil); | |
| 882 | 926 | std::this_thread::sleep_until(thisSleepUntil); |
| 883 | 927 | } |
| 884 | 928 | |
| @@ -903,7 +947,10 @@ void ScriptEngine::run() { · 18 unmodified lines | ||
| 903 | 947 | break; |
| 904 | 948 | } |
| 905 | 949 | |
| 906 | − QCoreApplication::processEvents(); | |
| 950 | + // Only call this if we didn't processEvents as part of waiting for next frame | |
| 951 | + if (!processedEvents) { | |
| 952 | + QCoreApplication::processEvents(); | |
| 953 | + } | |
| 907 | 954 | |
| 908 | 955 | if (_isFinished) { |
| 909 | 956 | break; |
| @@ -935,10 +982,10 @@ void ScriptEngine::run() { · 25 unmodified lines | ||
| 935 | 982 | _lastUpdate = now; |
| 936 | 983 | |
| 937 | 984 | // Debug and clear exceptions |
| 938 | − hadUncaughtExceptions(*this, _fileNameString); | |
| 985 | + hadUncaughtExceptions(*this, _fileNameString, this); | |
| 939 | 986 | } |
| 940 | 987 | |
| 941 | − qCDebug(scriptengine) << "Script Engine stopping:" << getFilename(); | |
| 988 | + scriptInfoMessage("Script Engine stopping:" + getFilename()); | |
| 942 | 989 | |
| 943 | 990 | stopAllTimers(); // make sure all our timers are stopped if the script is ending |
| 944 | 991 | emit scriptEnding(); |
| @@ -966,6 +1013,21 @@ void ScriptEngine::run() { · 21 unmodified lines | ||
| 966 | 1013 | emit doneRunning(); |
| 967 | 1014 | } |
| 968 | 1015 | |
| 1016 | +quint64 ScriptEngine::getTimersRemainingTime() { | |
| 1017 | + quint64 minimumTime = USECS_PER_SECOND; // anything larger than this can be ignored | |
| 1018 | + QMutableHashIterator<QTimer*, CallbackData> i(_timerFunctionMap); | |
| 1019 | + while (i.hasNext()) { | |
| 1020 | + i.next(); | |
| 1021 | + QTimer* timer = i.key(); | |
| 1022 | + int remainingTime = timer->remainingTime(); | |
| 1023 | + if (remainingTime >= 0) { | |
| 1024 | + minimumTime = std::min((quint64)remainingTime, minimumTime); | |
| 1025 | + } | |
| 1026 | + } | |
| 1027 | + return minimumTime; | |
| 1028 | +} | |
| 1029 | + | |
| 1030 | + | |
| 969 | 1031 | // NOTE: This is private because it must be called on the same thread that created the timers, which is why |
| 970 | 1032 | // we want to only call it in our own run "shutdown" processing. |
| 971 | 1033 | void ScriptEngine::stopAllTimers() { |
| @@ -1011,7 +1073,7 @@ void ScriptEngine::stop(bool marshal) { · 39 unmodified lines | ||
| 1011 | 1073 | void ScriptEngine::callAnimationStateHandler(QScriptValue callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler) { |
| 1012 | 1074 | if (QThread::currentThread() != thread()) { |
| 1013 | 1075 | #ifdef THREAD_DEBUGGING |
| 1014 | − qDebug() << "*** WARNING *** ScriptEngine::callAnimationStateHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; | |
| 1076 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::callAnimationStateHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; | |
| 1015 | 1077 | #endif |
| 1016 | 1078 | QMetaObject::invokeMethod(this, "callAnimationStateHandler", |
| 1017 | 1079 | Q_ARG(QScriptValue, callback), |
| @@ -1045,7 +1107,7 @@ void ScriptEngine::timerFired() { · 27 unmodified lines | ||
| 1045 | 1107 | { |
| 1046 | 1108 | auto engine = DependencyManager::get<ScriptEngines>(); |
| 1047 | 1109 | if (!engine || engine->isStopped()) { |
| 1048 | − qCDebug(scriptengine) << "Script.timerFired() while shutting down is ignored... parent script:" << getFilename(); | |
| 1110 | + scriptWarningMessage("Script.timerFired() while shutting down is ignored... parent script:" + getFilename()); | |
| 1049 | 1111 | return; // bail early |
| 1050 | 1112 | } |
| 1051 | 1113 | } |
| @@ -1061,7 +1123,12 @@ void ScriptEngine::timerFired() { · 9 unmodified lines | ||
| 1061 | 1123 | |
| 1062 | 1124 | // call the associated JS function, if it exists |
| 1063 | 1125 | if (timerData.function.isValid()) { |
| 1126 | + auto preTimer = p_high_resolution_clock::now(); | |
| 1064 | 1127 | callWithEnvironment(timerData.definingEntityIdentifier, timerData.definingSandboxURL, timerData.function, timerData.function, QScriptValueList()); |
| 1128 | + auto postTimer = p_high_resolution_clock::now(); | |
| 1129 | + auto elapsed = (postTimer - preTimer); | |
| 1130 | + _totalTimerExecution += std::chrono::duration_cast<std::chrono::microseconds>(elapsed); | |
| 1131 | + | |
| 1065 | 1132 | } |
| 1066 | 1133 | } |
| 1067 | 1134 | |
| @@ -1071,12 +1138,18 @@ QObject* ScriptEngine::setupTimerWithInterval(const QScriptValue& function, int · 3 unmodified lines | ||
| 1071 | 1138 | QTimer* newTimer = new QTimer(this); |
| 1072 | 1139 | newTimer->setSingleShot(isSingleShot); |
| 1073 | 1140 | |
| 1141 | + // The default timer type is not very accurate below about 200ms http://doc.qt.io/qt-5/qt.html#TimerType-enum | |
| 1142 | + static const int MIN_TIMEOUT_FOR_COARSE_TIMER = 200; | |
| 1143 | + if (intervalMS < MIN_TIMEOUT_FOR_COARSE_TIMER) { | |
| 1144 | + newTimer->setTimerType(Qt::PreciseTimer); | |
| 1145 | + } | |
| 1146 | + | |
| 1074 | 1147 | connect(newTimer, &QTimer::timeout, this, &ScriptEngine::timerFired); |
| 1075 | 1148 | |
| 1076 | 1149 | // make sure the timer stops when the script does |
| 1077 | 1150 | connect(this, &ScriptEngine::scriptEnding, newTimer, &QTimer::stop); |
| 1078 | 1151 | |
| 1079 | − CallbackData timerData = {function, currentEntityIdentifier, currentSandboxURL}; | |
| 1152 | + CallbackData timerData = {function, currentEntityIdentifier, currentSandboxURL }; | |
| 1080 | 1153 | _timerFunctionMap.insert(newTimer, timerData); |
| 1081 | 1154 | |
| 1082 | 1155 | newTimer->start(intervalMS); |
| @@ -1085,7 +1158,7 @@ QObject* ScriptEngine::setupTimerWithInterval(const QScriptValue& function, int · 2 unmodified lines | ||
| 1085 | 1158 | |
| 1086 | 1159 | QObject* ScriptEngine::setInterval(const QScriptValue& function, int intervalMS) { |
| 1087 | 1160 | if (DependencyManager::get<ScriptEngines>()->isStopped()) { |
| 1088 | − qCDebug(scriptengine) << "Script.setInterval() while shutting down is ignored... parent script:" << getFilename(); | |
| 1161 | + scriptWarningMessage("Script.setInterval() while shutting down is ignored... parent script:" + getFilename()); | |
| 1089 | 1162 | return NULL; // bail early |
| 1090 | 1163 | } |
| 1091 | 1164 | |
| @@ -1094,7 +1167,7 @@ QObject* ScriptEngine::setInterval(const QScriptValue& function, int intervalMS) · 2 unmodified lines | ||
| 1094 | 1167 | |
| 1095 | 1168 | QObject* ScriptEngine::setTimeout(const QScriptValue& function, int timeoutMS) { |
| 1096 | 1169 | if (DependencyManager::get<ScriptEngines>()->isStopped()) { |
| 1097 | − qCDebug(scriptengine) << "Script.setTimeout() while shutting down is ignored... parent script:" << getFilename(); | |
| 1170 | + scriptWarningMessage("Script.setTimeout() while shutting down is ignored... parent script:" + getFilename()); | |
| 1098 | 1171 | return NULL; // bail early |
| 1099 | 1172 | } |
| 1100 | 1173 | |
| @@ -1154,8 +1227,8 @@ void ScriptEngine::print(const QString& message) { · 53 unmodified lines | ||
| 1154 | 1227 | // all of the files have finished loading. |
| 1155 | 1228 | void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callback) { |
| 1156 | 1229 | if (DependencyManager::get<ScriptEngines>()->isStopped()) { |
| 1157 | − qCDebug(scriptengine) << "Script.include() while shutting down is ignored..." | |
| 1158 | − << "includeFiles:" << includeFiles << "parent script:" << getFilename(); | |
| 1230 | + scriptWarningMessage("Script.include() while shutting down is ignored... includeFiles:" | |
| 1231 | + + includeFiles.join(",") + "parent script:" + getFilename()); | |
| 1159 | 1232 | return; // bail early |
| 1160 | 1233 | } |
| 1161 | 1234 | QList<QUrl> urls; |
| @@ -1183,7 +1256,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac · 21 unmodified lines | ||
| 1183 | 1256 | thisURL = expandScriptUrl(QUrl::fromLocalFile(expandScriptPath(file))); |
| 1184 | 1257 | QUrl defaultScriptsLoc = defaultScriptsLocation(); |
| 1185 | 1258 | if (!defaultScriptsLoc.isParentOf(thisURL)) { |
| 1186 | − qDebug() << "ScriptEngine::include -- skipping" << file << "-- outside of standard libraries"; | |
| 1259 | + scriptWarningMessage("Script.include() -- skipping" + file + "-- outside of standard libraries"); | |
| 1187 | 1260 | continue; |
| 1188 | 1261 | } |
| 1189 | 1262 | isStandardLibrary = true; |
| @@ -1194,8 +1267,9 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac · 4 unmodified lines | ||
| 1194 | 1267 | if (!isStandardLibrary && !currentSandboxURL.isEmpty() && (thisURL.scheme() == "file") && |
| 1195 | 1268 | (currentSandboxURL.scheme() != "file" || |
| 1196 | 1269 | !thisURL.toString(strippingFlags).startsWith(currentSandboxURL.toString(strippingFlags), getSensitivity()))) { |
| 1197 | − qCWarning(scriptengine) << "Script.include() ignoring file path" | |
| 1198 | − << thisURL << "outside of original entity script" << currentSandboxURL; | |
| 1270 | + | |
| 1271 | + scriptWarningMessage("Script.include() ignoring file path" + thisURL.toString() | |
| 1272 | + + "outside of original entity script" + currentSandboxURL.toString()); | |
| 1199 | 1273 | } else { |
| 1200 | 1274 | // We could also check here for CORS, but we don't yet. |
| 1201 | 1275 | // It turns out that QUrl.resolve will not change hosts and copy authority, so we don't need to check that here. |
| @@ -1217,7 +1291,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac · 15 unmodified lines | ||
| 1217 | 1291 | for (QUrl url : urls) { |
| 1218 | 1292 | QString contents = data[url]; |
| 1219 | 1293 | if (contents.isNull()) { |
| 1220 | − qCDebug(scriptengine) << "Error loading file: " << url << "line:" << __LINE__; | |
| 1294 | + scriptErrorMessage("Error loading file: " + url.toString()); | |
| 1221 | 1295 | } else { |
| 1222 | 1296 | std::lock_guard<std::recursive_mutex> lock(_lock); |
| 1223 | 1297 | if (!_includedURLs.contains(url)) { |
| @@ -1231,7 +1305,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac · 7 unmodified lines | ||
| 1231 | 1305 | |
| 1232 | 1306 | doWithEnvironment(capturedEntityIdentifier, capturedSandboxURL, operation); |
| 1233 | 1307 | } else { |
| 1234 | − qCDebug(scriptengine) << "Script.include() skipping evaluation of previously included url:" << url; | |
| 1308 | + scriptWarningMessage("Script.include() skipping evaluation of previously included url:" + url.toString()); | |
| 1235 | 1309 | } |
| 1236 | 1310 | } |
| 1237 | 1311 | } |
| @@ -1260,8 +1334,8 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac · 22 unmodified lines | ||
| 1260 | 1334 | |
| 1261 | 1335 | void ScriptEngine::include(const QString& includeFile, QScriptValue callback) { |
| 1262 | 1336 | if (DependencyManager::get<ScriptEngines>()->isStopped()) { |
| 1263 | − qCDebug(scriptengine) << "Script.include() while shutting down is ignored... " | |
| 1264 | − << "includeFile:" << includeFile << "parent script:" << getFilename(); | |
| 1337 | + scriptWarningMessage("Script.include() while shutting down is ignored... includeFile:" | |
| 1338 | + + includeFile + "parent script:" + getFilename()); | |
| 1265 | 1339 | return; // bail early |
| 1266 | 1340 | } |
| 1267 | 1341 | |
| @@ -1275,13 +1349,13 @@ void ScriptEngine::include(const QString& includeFile, QScriptValue callback) { · 7 unmodified lines | ||
| 1275 | 1349 | // the Application or other context will connect to in order to know to actually load the script |
| 1276 | 1350 | void ScriptEngine::load(const QString& loadFile) { |
| 1277 | 1351 | if (DependencyManager::get<ScriptEngines>()->isStopped()) { |
| 1278 | − qCDebug(scriptengine) << "Script.load() while shutting down is ignored... " | |
| 1279 | − << "loadFile:" << loadFile << "parent script:" << getFilename(); | |
| 1352 | + scriptWarningMessage("Script.load() while shutting down is ignored... loadFile:" | |
| 1353 | + + loadFile + "parent script:" + getFilename()); | |
| 1280 | 1354 | return; // bail early |
| 1281 | 1355 | } |
| 1282 | 1356 | if (!currentEntityIdentifier.isInvalidID()) { |
| 1283 | − qCWarning(scriptengine) << "Script.load() from entity script is ignored... " | |
| 1284 | − << "loadFile:" << loadFile << "parent script:" << getFilename(); | |
| 1357 | + scriptWarningMessage("Script.load() from entity script is ignored... loadFile:" | |
| 1358 | + + loadFile + "parent script:" + getFilename()); | |
| 1285 | 1359 | return; // bail early |
| 1286 | 1360 | } |
| 1287 | 1361 | |
| @@ -1298,7 +1372,7 @@ void ScriptEngine::load(const QString& loadFile) { · 10 unmodified lines | ||
| 1298 | 1372 | // Look up the handler associated with eventName and entityID. If found, evalute the argGenerator thunk and call the handler with those args |
| 1299 | 1373 | void ScriptEngine::forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHandlerArgs) { |
| 1300 | 1374 | if (QThread::currentThread() != thread()) { |
| 1301 | − qDebug() << "*** ERROR *** ScriptEngine::forwardHandlerCall() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]"; | |
| 1375 | + qCDebug(scriptengine) << "*** ERROR *** ScriptEngine::forwardHandlerCall() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]"; | |
| 1302 | 1376 | assert(false); |
| 1303 | 1377 | return ; |
| 1304 | 1378 | } |
| @@ -1332,7 +1406,7 @@ void ScriptEngine::loadEntityScript(QWeakPointer<ScriptEngine> theEngine, const · 27 unmodified lines | ||
| 1332 | 1406 | QSharedPointer<ScriptEngine> strongEngine = theEngine.toStrongRef(); |
| 1333 | 1407 | if (strongEngine) { |
| 1334 | 1408 | #ifdef THREAD_DEBUGGING |
| 1335 | − qDebug() << "ScriptEngine::entityScriptContentAvailable() IN LAMBDA contentAvailable on thread [" | |
| 1409 | + qCDebug(scriptengine) << "ScriptEngine::entityScriptContentAvailable() IN LAMBDA contentAvailable on thread [" | |
| 1336 | 1410 | << QThread::currentThread() << "] expected thread [" << strongEngine->thread() << "]"; |
| 1337 | 1411 | #endif |
| 1338 | 1412 | strongEngine->entityScriptContentAvailable(entityID, scriptOrURL, contents, isURL, success); |
| @@ -1345,7 +1419,7 @@ void ScriptEngine::loadEntityScript(QWeakPointer<ScriptEngine> theEngine, const · 6 unmodified lines | ||
| 1345 | 1419 | void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success) { |
| 1346 | 1420 | if (QThread::currentThread() != thread()) { |
| 1347 | 1421 | #ifdef THREAD_DEBUGGING |
| 1348 | − qDebug() << "*** WARNING *** ScriptEngine::entityScriptContentAvailable() called on wrong thread [" | |
| 1422 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::entityScriptContentAvailable() called on wrong thread [" | |
| 1349 | 1423 | << QThread::currentThread() << "], invoking on correct thread [" << thread() |
| 1350 | 1424 | << "] " "entityID:" << entityID << "scriptOrURL:" << scriptOrURL << "contents:" |
| 1351 | 1425 | << contents << "isURL:" << isURL << "success:" << success; |
| @@ -1361,7 +1435,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 9 unmodified lines | ||
| 1361 | 1435 | } |
| 1362 | 1436 | |
| 1363 | 1437 | #ifdef THREAD_DEBUGGING |
| 1364 | − qDebug() << "ScriptEngine::entityScriptContentAvailable() thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; | |
| 1438 | + qCDebug(scriptengine) << "ScriptEngine::entityScriptContentAvailable() thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; | |
| 1365 | 1439 | #endif |
| 1366 | 1440 | |
| 1367 | 1441 | auto scriptCache = DependencyManager::get<ScriptCache>(); |
| @@ -1369,7 +1443,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 1 unmodified line | ||
| 1369 | 1443 | auto fileName = isURL ? scriptOrURL : "EmbeddedEntityScript"; |
| 1370 | 1444 | |
| 1371 | 1445 | QScriptProgram program(contents, fileName); |
| 1372 | − if (!hasCorrectSyntax(program)) { | |
| 1446 | + if (!hasCorrectSyntax(program, this)) { | |
| 1373 | 1447 | if (!isFileUrl) { |
| 1374 | 1448 | scriptCache->addScriptToBadScriptList(scriptOrURL); |
| 1375 | 1449 | } |
| @@ -1397,7 +1471,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 21 unmodified lines | ||
| 1397 | 1471 | }); |
| 1398 | 1472 | testConstructor = sandbox.evaluate(program); |
| 1399 | 1473 | } |
| 1400 | − if (hadUncaughtExceptions(sandbox, program.fileName())) { | |
| 1474 | + if (hadUncaughtExceptions(sandbox, program.fileName(), this)) { | |
| 1401 | 1475 | return; |
| 1402 | 1476 | } |
| 1403 | 1477 | |
| @@ -1411,10 +1485,10 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 7 unmodified lines | ||
| 1411 | 1485 | if (testConstructorValue.size() > maxTestConstructorValueSize) { |
| 1412 | 1486 | testConstructorValue = testConstructorValue.mid(0, maxTestConstructorValueSize) + "..."; |
| 1413 | 1487 | } |
| 1414 | − qCDebug(scriptengine) << "Error -- ScriptEngine::loadEntityScript() entity:" << entityID | |
| 1415 | − << "failed to load entity script -- expected a function, got " + testConstructorType | |
| 1416 | − << "," << testConstructorValue | |
| 1417 | − << "," << scriptOrURL; | |
| 1488 | + scriptErrorMessage("Error -- ScriptEngine::loadEntityScript() entity:" + entityID.toString() | |
| 1489 | + + "failed to load entity script -- expected a function, got " + testConstructorType | |
| 1490 | + + "," + testConstructorValue | |
| 1491 | + + "," + scriptOrURL); | |
| 1418 | 1492 | |
| 1419 | 1493 | if (!isFileUrl) { |
| 1420 | 1494 | scriptCache->addScriptToBadScriptList(scriptOrURL); |
| @@ -1449,7 +1523,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 28 unmodified lines | ||
| 1449 | 1523 | void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) { |
| 1450 | 1524 | if (QThread::currentThread() != thread()) { |
| 1451 | 1525 | #ifdef THREAD_DEBUGGING |
| 1452 | − qDebug() << "*** WARNING *** ScriptEngine::unloadEntityScript() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 1526 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::unloadEntityScript() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 1453 | 1527 | "entityID:" << entityID; |
| 1454 | 1528 | #endif |
| 1455 | 1529 | |
| @@ -1458,7 +1532,7 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) { · 2 unmodified lines | ||
| 1458 | 1532 | return; |
| 1459 | 1533 | } |
| 1460 | 1534 | #ifdef THREAD_DEBUGGING |
| 1461 | − qDebug() << "ScriptEngine::unloadEntityScript() called on correct thread [" << thread() << "] " | |
| 1535 | + qCDebug(scriptengine) << "ScriptEngine::unloadEntityScript() called on correct thread [" << thread() << "] " | |
| 1462 | 1536 | "entityID:" << entityID; |
| 1463 | 1537 | #endif |
| 1464 | 1538 | |
| @@ -1472,14 +1546,14 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) { · 7 unmodified lines | ||
| 1472 | 1546 | void ScriptEngine::unloadAllEntityScripts() { |
| 1473 | 1547 | if (QThread::currentThread() != thread()) { |
| 1474 | 1548 | #ifdef THREAD_DEBUGGING |
| 1475 | − qDebug() << "*** WARNING *** ScriptEngine::unloadAllEntityScripts() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]"; | |
| 1549 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::unloadAllEntityScripts() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]"; | |
| 1476 | 1550 | #endif |
| 1477 | 1551 | |
| 1478 | 1552 | QMetaObject::invokeMethod(this, "unloadAllEntityScripts"); |
| 1479 | 1553 | return; |
| 1480 | 1554 | } |
| 1481 | 1555 | #ifdef THREAD_DEBUGGING |
| 1482 | − qDebug() << "ScriptEngine::unloadAllEntityScripts() called on correct thread [" << thread() << "]"; | |
| 1556 | + qCDebug(scriptengine) << "ScriptEngine::unloadAllEntityScripts() called on correct thread [" << thread() << "]"; | |
| 1483 | 1557 | #endif |
| 1484 | 1558 | foreach(const EntityItemID& entityID, _entityScripts.keys()) { |
| 1485 | 1559 | callEntityScriptMethod(entityID, "unload"); |
| @@ -1487,13 +1561,13 @@ void ScriptEngine::unloadAllEntityScripts() { · 1 unmodified line | ||
| 1487 | 1561 | _entityScripts.clear(); |
| 1488 | 1562 | |
| 1489 | 1563 | #ifdef DEBUG_ENGINE_STATE |
| 1490 | − qDebug() << "---- CURRENT STATE OF ENGINE: --------------------------"; | |
| 1564 | + qCDebug(scriptengine) << "---- CURRENT STATE OF ENGINE: --------------------------"; | |
| 1491 | 1565 | QScriptValueIterator it(globalObject()); |
| 1492 | 1566 | while (it.hasNext()) { |
| 1493 | 1567 | it.next(); |
| 1494 | − qDebug() << it.name() << ":" << it.value().toString(); | |
| 1568 | + qCDebug(scriptengine) << it.name() << ":" << it.value().toString(); | |
| 1495 | 1569 | } |
| 1496 | − qDebug() << "--------------------------------------------------------"; | |
| 1570 | + qCDebug(scriptengine) << "--------------------------------------------------------"; | |
| 1497 | 1571 | #endif // DEBUG_ENGINE_STATE |
| 1498 | 1572 | } |
| 1499 | 1573 | |
| @@ -1514,7 +1588,7 @@ void ScriptEngine::refreshFileScript(const EntityItemID& entityID) { · 14 unmodified lines | ||
| 1514 | 1588 | QString filePath = QUrl(details.scriptText).toLocalFile(); |
| 1515 | 1589 | auto lastModified = QFileInfo(filePath).lastModified().toMSecsSinceEpoch(); |
| 1516 | 1590 | if (lastModified > details.lastModified) { |
| 1517 | − qCDebug(scriptengine) << "Reloading modified script " << details.scriptText; | |
| 1591 | + scriptInfoMessage("Reloading modified script " + details.scriptText); | |
| 1518 | 1592 | |
| 1519 | 1593 | QFile file(filePath); |
| 1520 | 1594 | file.open(QIODevice::ReadOnly); |
| @@ -1522,7 +1596,7 @@ void ScriptEngine::refreshFileScript(const EntityItemID& entityID) { · 1 unmodified line | ||
| 1522 | 1596 | this->unloadEntityScript(entityID); |
| 1523 | 1597 | this->entityScriptContentAvailable(entityID, details.scriptText, scriptContents, true, true); |
| 1524 | 1598 | if (!_entityScripts.contains(entityID)) { |
| 1525 | − qWarning() << "Reload script " << details.scriptText << " failed"; | |
| 1599 | + scriptWarningMessage("Reload script " + details.scriptText + " failed"); | |
| 1526 | 1600 | } else { |
| 1527 | 1601 | details = _entityScripts[entityID]; |
| 1528 | 1602 | } |
| @@ -1549,7 +1623,7 @@ void ScriptEngine::doWithEnvironment(const EntityItemID& entityID, const QUrl& s · 20 unmodified lines | ||
| 1549 | 1623 | #else |
| 1550 | 1624 | operation(); |
| 1551 | 1625 | #endif |
| 1552 | − hadUncaughtExceptions(*this, _fileNameString); | |
| 1626 | + hadUncaughtExceptions(*this, _fileNameString, this); | |
| 1553 | 1627 | |
| 1554 | 1628 | currentEntityIdentifier = oldIdentifier; |
| 1555 | 1629 | currentSandboxURL = oldSandboxURL; |
| @@ -1564,7 +1638,7 @@ void ScriptEngine::callWithEnvironment(const EntityItemID& entityID, const QUrl& · 8 unmodified lines | ||
| 1564 | 1638 | void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const QStringList& params) { |
| 1565 | 1639 | if (QThread::currentThread() != thread()) { |
| 1566 | 1640 | #ifdef THREAD_DEBUGGING |
| 1567 | − qDebug() << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 1641 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 1568 | 1642 | "entityID:" << entityID << "methodName:" << methodName; |
| 1569 | 1643 | #endif |
| 1570 | 1644 | |
| @@ -1575,7 +1649,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 4 unmodified lines | ||
| 1575 | 1649 | return; |
| 1576 | 1650 | } |
| 1577 | 1651 | #ifdef THREAD_DEBUGGING |
| 1578 | − qDebug() << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] " | |
| 1652 | + qCDebug(scriptengine) << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] " | |
| 1579 | 1653 | "entityID:" << entityID << "methodName:" << methodName; |
| 1580 | 1654 | #endif |
| 1581 | 1655 | |
| @@ -1596,7 +1670,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 14 unmodified lines | ||
| 1596 | 1670 | void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const PointerEvent& event) { |
| 1597 | 1671 | if (QThread::currentThread() != thread()) { |
| 1598 | 1672 | #ifdef THREAD_DEBUGGING |
| 1599 | − qDebug() << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 1673 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 1600 | 1674 | "entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent"; |
| 1601 | 1675 | #endif |
| 1602 | 1676 | |
| @@ -1607,7 +1681,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 4 unmodified lines | ||
| 1607 | 1681 | return; |
| 1608 | 1682 | } |
| 1609 | 1683 | #ifdef THREAD_DEBUGGING |
| 1610 | − qDebug() << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] " | |
| 1684 | + qCDebug(scriptengine) << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] " | |
| 1611 | 1685 | "entityID:" << entityID << "methodName:" << methodName << "event: pointerEvent"; |
| 1612 | 1686 | #endif |
| 1613 | 1687 | |
| @@ -1628,7 +1702,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 14 unmodified lines | ||
| 1628 | 1702 | void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision) { |
| 1629 | 1703 | if (QThread::currentThread() != thread()) { |
| 1630 | 1704 | #ifdef THREAD_DEBUGGING |
| 1631 | − qDebug() << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 1705 | + qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " | |
| 1632 | 1706 | "entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision"; |
| 1633 | 1707 | #endif |
| 1634 | 1708 | |
| @@ -1640,7 +1714,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 5 unmodified lines | ||
| 1640 | 1714 | return; |
| 1641 | 1715 | } |
| 1642 | 1716 | #ifdef THREAD_DEBUGGING |
| 1643 | − qDebug() << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] " | |
| 1717 | + qCDebug(scriptengine) << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] " | |
| 1644 | 1718 | "entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision"; |
| 1645 | 1719 | #endif |
| 1646 | 1720 | |