Showing the changes to libraries/script-engine/src/ScriptManager.cpp (1 of 170 files). Show all
Unified · Split
| @@ -87,7 +87,7 @@ int scriptManagerPointerMetaID = qRegisterMetaType<ScriptManagerPointer>(); · 86 unmodified lines | ||
| 87 | 87 | |
| 88 | 88 | Q_DECLARE_METATYPE(ExternalResource::Bucket); |
| 89 | 89 | |
| 90 | −Q_DECLARE_METATYPE(ScriptValuePointer); | |
| 90 | +Q_DECLARE_METATYPE(ScriptValue); | |
| 91 | 91 | |
| 92 | 92 | // --- Static script initialization registry |
| 93 | 93 | |
| @@ -109,21 +109,21 @@ static void runStaticInitializers(ScriptManager* manager) { · 15 unmodified lines | ||
| 109 | 109 | |
| 110 | 110 | // --- |
| 111 | 111 | |
| 112 | −static ScriptValuePointer debugPrint(ScriptContext* context, ScriptEngine* engine) { | |
| 112 | +static ScriptValue debugPrint(ScriptContext* context, ScriptEngine* engine) { | |
| 113 | 113 | // assemble the message by concatenating our arguments |
| 114 | 114 | QString message = ""; |
| 115 | 115 | for (int i = 0; i < context->argumentCount(); i++) { |
| 116 | 116 | if (i > 0) { |
| 117 | 117 | message += " "; |
| 118 | 118 | } |
| 119 | − message += context->argument(i)->toString(); | |
| 119 | + message += context->argument(i).toString(); | |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | 122 | // was this generated by a script engine? If we don't recognize it then send the message and exit |
| 123 | 123 | ScriptManager* scriptManager = engine->manager(); |
| 124 | 124 | if (!scriptManager) { |
| 125 | 125 | qCDebug(scriptengine_script, "%s", qUtf8Printable(message)); |
| 126 | − return ScriptValuePointer(); | |
| 126 | + return ScriptValue(); | |
| 127 | 127 | } |
| 128 | 128 | |
| 129 | 129 | // This message was sent by one of our script engines, let's try to see if we can find the source. |
| @@ -170,7 +170,7 @@ static ScriptValuePointer debugPrint(ScriptContext* context, ScriptEngine* engin · 40 unmodified lines | ||
| 170 | 170 | qCDebug(scriptengine_script, "[%s] %s", qUtf8Printable(scriptManager->getFilename()), qUtf8Printable(message)); |
| 171 | 171 | } |
| 172 | 172 | |
| 173 | − return ScriptValuePointer(); | |
| 173 | + return ScriptValue(); | |
| 174 | 174 | } |
| 175 | 175 | |
| 176 | 176 | // FIXME Come up with a way to properly encode entity IDs in filename |
| @@ -193,7 +193,7 @@ QString encodeEntityIdIntoEntityUrl(const QString& url, const QString& entityID) · 16 unmodified lines | ||
| 193 | 193 | return url + " [EntityID:" + entityID + "]"; |
| 194 | 194 | } |
| 195 | 195 | |
| 196 | −QString ScriptManager::logException(const ScriptValuePointer& exception) { | |
| 196 | +QString ScriptManager::logException(const ScriptValue& exception) { | |
| 197 | 197 | auto message = formatException(exception, _enableExtendedJSExceptions.get()); |
| 198 | 198 | scriptErrorMessage(message); |
| 199 | 199 | return message; |
| @@ -249,10 +249,10 @@ ScriptManager::ScriptManager(Context context, const QString& scriptContents, con · 49 unmodified lines | ||
| 249 | 249 | } |
| 250 | 250 | |
| 251 | 251 | // this is where all unhandled exceptions end up getting logged |
| 252 | − connect(this, &ScriptManager::unhandledException, this, [this](const ScriptValuePointer& err) { | |
| 253 | − auto output = err->engine() == _engine ? err : _engine->makeError(err); | |
| 254 | − if (!output->property("detail")->isValid()) { | |
| 255 | − output->setProperty("detail", "UnhandledException"); | |
| 252 | + connect(this, &ScriptManager::unhandledException, this, [this](const ScriptValue& err) { | |
| 253 | + auto output = err.engine() == _engine ? err : _engine->makeError(err); | |
| 254 | + if (!output.property("detail").isValid()) { | |
| 255 | + output.setProperty("detail", "UnhandledException"); | |
| 256 | 256 | } |
| 257 | 257 | logException(output); |
| 258 | 258 | }); |
| @@ -516,10 +516,10 @@ void ScriptManager::clearDebugLogWindow() { · 257 unmodified lines | ||
| 516 | 516 | // Templated qScriptRegisterMetaType fails to compile with raw pointers |
| 517 | 517 | using ScriptableResourceRawPtr = ScriptableResource*; |
| 518 | 518 | |
| 519 | −static ScriptValuePointer scriptableResourceToScriptValue(ScriptEngine* engine, | |
| 519 | +static ScriptValue scriptableResourceToScriptValue(ScriptEngine* engine, | |
| 520 | 520 | const ScriptableResourceRawPtr& resource) { |
| 521 | 521 | if (!resource) { |
| 522 | − return ScriptValuePointer(); // probably shutting down | |
| 522 | + return ScriptValue(); // probably shutting down | |
| 523 | 523 | } |
| 524 | 524 | |
| 525 | 525 | // The first script to encounter this resource will track its memory. |
| @@ -538,8 +538,8 @@ static ScriptValuePointer scriptableResourceToScriptValue(ScriptEngine* engine, · 12 unmodified lines | ||
| 538 | 538 | return object; |
| 539 | 539 | } |
| 540 | 540 | |
| 541 | −static void scriptableResourceFromScriptValue(const ScriptValuePointer& value, ScriptableResourceRawPtr& resource) { | |
| 542 | − resource = static_cast<ScriptableResourceRawPtr>(value->toQObject()); | |
| 541 | +static void scriptableResourceFromScriptValue(const ScriptValue& value, ScriptableResourceRawPtr& resource) { | |
| 542 | + resource = static_cast<ScriptableResourceRawPtr>(value.toQObject()); | |
| 543 | 543 | } |
| 544 | 544 | |
| 545 | 545 | /*@jsdoc |
| @@ -555,7 +555,7 @@ static void scriptableResourceFromScriptValue(const ScriptValuePointer& value, S · 9 unmodified lines | ||
| 555 | 555 | * |
| 556 | 556 | * @property {Resource.State} State - The possible loading states of a resource. <em>Read-only.</em> |
| 557 | 557 | */ |
| 558 | −static ScriptValuePointer createScriptableResourcePrototype(ScriptManagerPointer manager) { | |
| 558 | +static ScriptValue createScriptableResourcePrototype(ScriptManagerPointer manager) { | |
| 559 | 559 | auto engine = manager->engine(); |
| 560 | 560 | auto prototype = engine->newObject(); |
| 561 | 561 | |
| @@ -569,17 +569,17 @@ static ScriptValuePointer createScriptableResourcePrototype(ScriptManagerPointer · 7 unmodified lines | ||
| 569 | 569 | |
| 570 | 570 | auto prototypeState = engine->newQObject(state, ScriptEngine::QtOwnership, |
| 571 | 571 | ScriptEngine::ExcludeSlots | ScriptEngine::ExcludeSuperClassMethods); |
| 572 | − prototype->setProperty("State", prototypeState); | |
| 572 | + prototype.setProperty("State", prototypeState); | |
| 573 | 573 | |
| 574 | 574 | return prototype; |
| 575 | 575 | } |
| 576 | 576 | |
| 577 | −ScriptValuePointer externalResourceBucketToScriptValue(ScriptEngine* engine, ExternalResource::Bucket const& in) { | |
| 577 | +ScriptValue externalResourceBucketToScriptValue(ScriptEngine* engine, ExternalResource::Bucket const& in) { | |
| 578 | 578 | return engine->newValue((int)in); |
| 579 | 579 | } |
| 580 | 580 | |
| 581 | −void externalResourceBucketFromScriptValue(const ScriptValuePointer& object, ExternalResource::Bucket& out) { | |
| 582 | − out = static_cast<ExternalResource::Bucket>(object->toInt32()); | |
| 581 | +void externalResourceBucketFromScriptValue(const ScriptValue& object, ExternalResource::Bucket& out) { | |
| 582 | + out = static_cast<ExternalResource::Bucket>(object.toInt32()); | |
| 583 | 583 | } |
| 584 | 584 | |
| 585 | 585 | void ScriptManager::resetModuleCache(bool deleteScriptCache) { |
| @@ -587,33 +587,33 @@ void ScriptManager::resetModuleCache(bool deleteScriptCache) { · 1 unmodified line | ||
| 587 | 587 | executeOnScriptThread([=]() { resetModuleCache(deleteScriptCache); }); |
| 588 | 588 | return; |
| 589 | 589 | } |
| 590 | − auto jsRequire = _engine->globalObject()->property("Script")->property("require"); | |
| 591 | − auto cache = jsRequire->property("cache"); | |
| 592 | − auto cacheMeta = jsRequire->data(); | |
| 590 | + auto jsRequire = _engine->globalObject().property("Script").property("require"); | |
| 591 | + auto cache = jsRequire.property("cache"); | |
| 592 | + auto cacheMeta = jsRequire.data(); | |
| 593 | 593 | |
| 594 | 594 | if (deleteScriptCache) { |
| 595 | − auto it = cache->newIterator(); | |
| 595 | + auto it = cache.newIterator(); | |
| 596 | 596 | while (it->hasNext()) { |
| 597 | 597 | it->next(); |
| 598 | 598 | if (it->flags() & ScriptValue::SkipInEnumeration) { |
| 599 | 599 | continue; |
| 600 | 600 | } |
| 601 | 601 | qCDebug(scriptengine) << "resetModuleCache(true) -- staging " << it->name() << " for cache reset at next require"; |
| 602 | − cacheMeta->setProperty(it->name(), true); | |
| 602 | + cacheMeta.setProperty(it->name(), true); | |
| 603 | 603 | } |
| 604 | 604 | } |
| 605 | 605 | cache = _engine->newObject(); |
| 606 | − if (!cacheMeta->isObject()) { | |
| 606 | + if (!cacheMeta.isObject()) { | |
| 607 | 607 | cacheMeta = _engine->newObject(); |
| 608 | − cacheMeta->setProperty("id", "Script.require.cacheMeta"); | |
| 609 | − cacheMeta->setProperty("type", "cacheMeta"); | |
| 610 | − jsRequire->setData(cacheMeta); | |
| 608 | + cacheMeta.setProperty("id", "Script.require.cacheMeta"); | |
| 609 | + cacheMeta.setProperty("type", "cacheMeta"); | |
| 610 | + jsRequire.setData(cacheMeta); | |
| 611 | 611 | } |
| 612 | − cache->setProperty("__created__", (double)QDateTime::currentMSecsSinceEpoch(), ScriptValue::SkipInEnumeration); | |
| 612 | + cache.setProperty("__created__", (double)QDateTime::currentMSecsSinceEpoch(), ScriptValue::SkipInEnumeration); | |
| 613 | 613 | #if DEBUG_JS_MODULES |
| 614 | 614 | cache.setProperty("__meta__", cacheMeta, READONLY_HIDDEN_PROP_FLAGS); |
| 615 | 615 | #endif |
| 616 | − jsRequire->setProperty("cache", cache, READONLY_PROP_FLAGS); | |
| 616 | + jsRequire.setProperty("cache", cache, READONLY_PROP_FLAGS); | |
| 617 | 617 | } |
| 618 | 618 | |
| 619 | 619 | void ScriptManager::init() { |
| @@ -638,11 +638,11 @@ void ScriptManager::init() { · 18 unmodified lines | ||
| 638 | 638 | scriptRegisterSequenceMetaType<QVector<glm::quat>>(scriptEngine); |
| 639 | 639 | scriptRegisterSequenceMetaType<QVector<QString>>(scriptEngine); |
| 640 | 640 | |
| 641 | − ScriptValuePointer xmlHttpRequestConstructorValue = scriptEngine->newFunction(XMLHttpRequestClass::constructor); | |
| 642 | − scriptEngine->globalObject()->setProperty("XMLHttpRequest", xmlHttpRequestConstructorValue); | |
| 641 | + ScriptValue xmlHttpRequestConstructorValue = scriptEngine->newFunction(XMLHttpRequestClass::constructor); | |
| 642 | + scriptEngine->globalObject().setProperty("XMLHttpRequest", xmlHttpRequestConstructorValue); | |
| 643 | 643 | |
| 644 | − ScriptValuePointer webSocketConstructorValue = scriptEngine->newFunction(WebSocketClass::constructor); | |
| 645 | − scriptEngine->globalObject()->setProperty("WebSocket", webSocketConstructorValue); | |
| 644 | + ScriptValue webSocketConstructorValue = scriptEngine->newFunction(WebSocketClass::constructor); | |
| 645 | + scriptEngine->globalObject().setProperty("WebSocket", webSocketConstructorValue); | |
| 646 | 646 | |
| 647 | 647 | /*@jsdoc |
| 648 | 648 | * Prints a message to the program log and emits {@link Script.printedMessage}. |
| @@ -651,7 +651,7 @@ void ScriptManager::init() { · 2 unmodified lines | ||
| 651 | 651 | * @function print |
| 652 | 652 | * @param {...*} [message] - The message values to print. |
| 653 | 653 | */ |
| 654 | − scriptEngine->globalObject()->setProperty("print", scriptEngine->newFunction(debugPrint)); | |
| 654 | + scriptEngine->globalObject().setProperty("print", scriptEngine->newFunction(debugPrint)); | |
| 655 | 655 | |
| 656 | 656 | scriptRegisterMetaType(scriptEngine, animationDetailsToScriptValue, animationDetailsFromScriptValue); |
| 657 | 657 | scriptRegisterMetaType(scriptEngine, webSocketToScriptValue, webSocketFromScriptValue); |
| @@ -665,10 +665,10 @@ void ScriptManager::init() { · 7 unmodified lines | ||
| 665 | 665 | |
| 666 | 666 | { |
| 667 | 667 | // set up Script.require.resolve and Script.require.cache |
| 668 | − auto Script = scriptEngine->globalObject()->property("Script"); | |
| 669 | − auto require = Script->property("require"); | |
| 670 | − auto resolve = Script->property("_requireResolve"); | |
| 671 | − require->setProperty("resolve", resolve, READONLY_PROP_FLAGS); | |
| 668 | + auto Script = scriptEngine->globalObject().property("Script"); | |
| 669 | + auto require = Script.property("require"); | |
| 670 | + auto resolve = Script.property("_requireResolve"); | |
| 671 | + require.setProperty("resolve", resolve, READONLY_PROP_FLAGS); | |
| 672 | 672 | resetModuleCache(); |
| 673 | 673 | } |
| 674 | 674 | |
| @@ -697,12 +697,12 @@ void ScriptManager::init() { · 22 unmodified lines | ||
| 697 | 697 | |
| 698 | 698 | // Scriptable cache access |
| 699 | 699 | auto resourcePrototype = createScriptableResourcePrototype(qSharedPointerCast<ScriptManager>(sharedFromThis())); |
| 700 | − scriptEngine->globalObject()->setProperty("Resource", resourcePrototype); | |
| 700 | + scriptEngine->globalObject().setProperty("Resource", resourcePrototype); | |
| 701 | 701 | scriptEngine->setDefaultPrototype(qMetaTypeId<ScriptableResource*>(), resourcePrototype); |
| 702 | 702 | scriptRegisterMetaType(scriptEngine, scriptableResourceToScriptValue, scriptableResourceFromScriptValue); |
| 703 | 703 | |
| 704 | 704 | // constants |
| 705 | − scriptEngine->globalObject()->setProperty("TREE_SCALE", scriptEngine->newValue(TREE_SCALE)); | |
| 705 | + scriptEngine->globalObject().setProperty("TREE_SCALE", scriptEngine->newValue(TREE_SCALE)); | |
| 706 | 706 | |
| 707 | 707 | scriptEngine->registerGlobalObject("Assets", _assetScriptingInterface); |
| 708 | 708 | scriptEngine->registerGlobalObject("Resources", DependencyManager::get<ResourceScriptingInterface>().data()); |
| @@ -718,14 +718,14 @@ void ScriptManager::init() { · 9 unmodified lines | ||
| 718 | 718 | scriptEngine->registerGlobalObject("StackTest", new StackTestScriptingInterface(this)); |
| 719 | 719 | #endif |
| 720 | 720 | |
| 721 | − scriptEngine->globalObject()->setProperty("KALILA", "isWaifu"); | |
| 722 | − scriptEngine->globalObject()->setProperty("Kute", scriptEngine->newFunction([](ScriptContext* context, ScriptEngine* engine) -> ScriptValuePointer { | |
| 723 | − return context->engine()->newValue(context->argument(0)->toString().toLower() == "kalila" ? true : false); | |
| 721 | + scriptEngine->globalObject().setProperty("KALILA", "isWaifu"); | |
| 722 | + scriptEngine->globalObject().setProperty("Kute", scriptEngine->newFunction([](ScriptContext* context, ScriptEngine* engine) -> ScriptValue { | |
| 723 | + return context->engine()->newValue(context->argument(0).toString().toLower() == "kalila" ? true : false); | |
| 724 | 724 | })); |
| 725 | 725 | } |
| 726 | 726 | |
| 727 | 727 | // Unregister the handlers for this eventName and entityID. |
| 728 | −void ScriptManager::removeEventHandler(const EntityItemID& entityID, const QString& eventName, ScriptValuePointer handler) { | |
| 728 | +void ScriptManager::removeEventHandler(const EntityItemID& entityID, const QString& eventName, const ScriptValue& handler) { | |
| 729 | 729 | if (QThread::currentThread() != thread()) { |
| 730 | 730 | #ifdef THREAD_DEBUGGING |
| 731 | 731 | qCDebug(scriptengine) << "*** WARNING *** ScriptManager::removeEventHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " |
| @@ -734,7 +734,7 @@ void ScriptManager::removeEventHandler(const EntityItemID& entityID, const QStri · 2 unmodified lines | ||
| 734 | 734 | QMetaObject::invokeMethod(this, "removeEventHandler", |
| 735 | 735 | Q_ARG(const EntityItemID&, entityID), |
| 736 | 736 | Q_ARG(const QString&, eventName), |
| 737 | − Q_ARG(ScriptValuePointer, handler)); | |
| 737 | + Q_ARG(const ScriptValue&, handler)); | |
| 738 | 738 | return; |
| 739 | 739 | } |
| 740 | 740 | #ifdef THREAD_DEBUGGING |
| @@ -746,9 +746,9 @@ void ScriptManager::removeEventHandler(const EntityItemID& entityID, const QStri · 5 unmodified lines | ||
| 746 | 746 | } |
| 747 | 747 | RegisteredEventHandlers& handlersOnEntity = _registeredHandlers[entityID]; |
| 748 | 748 | CallbackList& handlersForEvent = handlersOnEntity[eventName]; |
| 749 | − // ScriptValuePointer does not have operator==(), so we can't use QList::removeOne and friends. So iterate. | |
| 749 | + // ScriptValue does not have operator==(), so we can't use QList::removeOne and friends. So iterate. | |
| 750 | 750 | for (int i = 0; i < handlersForEvent.count(); ++i) { |
| 751 | − if (handlersForEvent[i].function->equals(handler)) { | |
| 751 | + if (handlersForEvent[i].function.equals(handler)) { | |
| 752 | 752 | handlersForEvent.removeAt(i); |
| 753 | 753 | return; // Design choice: since comparison is relatively expensive, just remove the first matching handler. |
| 754 | 754 | } |
| @@ -771,7 +771,7 @@ void ScriptManager::removeAllEventHandlers(const EntityItemID& entityID) { · 16 unmodified lines | ||
| 771 | 771 | } |
| 772 | 772 | |
| 773 | 773 | // Register the handler. |
| 774 | −void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString& eventName, ScriptValuePointer handler) { | |
| 774 | +void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString& eventName, const ScriptValue& handler) { | |
| 775 | 775 | if (QThread::currentThread() != thread()) { |
| 776 | 776 | #ifdef THREAD_DEBUGGING |
| 777 | 777 | qCDebug(scriptengine) << "*** WARNING *** ScriptManager::addEventHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " |
| @@ -781,7 +781,7 @@ void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString& · 3 unmodified lines | ||
| 781 | 781 | QMetaObject::invokeMethod(this, "addEventHandler", |
| 782 | 782 | Q_ARG(const EntityItemID&, entityID), |
| 783 | 783 | Q_ARG(const QString&, eventName), |
| 784 | − Q_ARG(ScriptValuePointer, handler)); | |
| 784 | + Q_ARG(const ScriptValue&, handler)); | |
| 785 | 785 | return; |
| 786 | 786 | } |
| 787 | 787 | #ifdef THREAD_DEBUGGING |
| @@ -951,7 +951,7 @@ void ScriptManager::run() { · 163 unmodified lines | ||
| 951 | 951 | // only clear exceptions if we are not in the middle of evaluating |
| 952 | 952 | if (!_engine->isEvaluating() && _engine->hasUncaughtException()) { |
| 953 | 953 | qCWarning(scriptengine) << __FUNCTION__ << "---------- UNCAUGHT EXCEPTION --------"; |
| 954 | − qCWarning(scriptengine) << "runInThread" << _engine->uncaughtException()->toString(); | |
| 954 | + qCWarning(scriptengine) << "runInThread" << _engine->uncaughtException().toString(); | |
| 955 | 955 | emit unhandledException(_engine->cloneUncaughtException(__FUNCTION__)); |
| 956 | 956 | _engine->clearExceptions(); |
| 957 | 957 | } |
| @@ -1037,7 +1037,7 @@ void ScriptManager::timerFired() { · 79 unmodified lines | ||
| 1037 | 1037 | } |
| 1038 | 1038 | |
| 1039 | 1039 | // call the associated JS function, if it exists |
| 1040 | − if (timerData.function->isValid()) { | |
| 1040 | + if (timerData.function.isValid()) { | |
| 1041 | 1041 | PROFILE_RANGE(script, __FUNCTION__); |
| 1042 | 1042 | auto preTimer = p_high_resolution_clock::now(); |
| 1043 | 1043 | callWithEnvironment(timerData.definingEntityIdentifier, timerData.definingSandboxURL, timerData.function, timerData.function, ScriptValueList()); |
| @@ -1045,11 +1045,11 @@ void ScriptManager::timerFired() { · 1 unmodified line | ||
| 1045 | 1045 | auto elapsed = (postTimer - preTimer); |
| 1046 | 1046 | _totalTimerExecution += std::chrono::duration_cast<std::chrono::microseconds>(elapsed); |
| 1047 | 1047 | } else { |
| 1048 | − qCWarning(scriptengine) << "timerFired -- invalid function" << timerData.function->toVariant().toString(); | |
| 1048 | + qCWarning(scriptengine) << "timerFired -- invalid function" << timerData.function.toVariant().toString(); | |
| 1049 | 1049 | } |
| 1050 | 1050 | } |
| 1051 | 1051 | |
| 1052 | −QObject* ScriptManager::setupTimerWithInterval(const ScriptValuePointer& function, int intervalMS, bool isSingleShot) { | |
| 1052 | +QObject* ScriptManager::setupTimerWithInterval(const ScriptValue& function, int intervalMS, bool isSingleShot) { | |
| 1053 | 1053 | // create the timer, add it to the map, and start it |
| 1054 | 1054 | QTimer* newTimer = new QTimer(this); |
| 1055 | 1055 | newTimer->setSingleShot(isSingleShot); |
| @@ -1073,7 +1073,7 @@ QObject* ScriptManager::setupTimerWithInterval(const ScriptValuePointer& functio · 17 unmodified lines | ||
| 1073 | 1073 | return newTimer; |
| 1074 | 1074 | } |
| 1075 | 1075 | |
| 1076 | −QObject* ScriptManager::setInterval(const ScriptValuePointer& function, int intervalMS) { | |
| 1076 | +QObject* ScriptManager::setInterval(const ScriptValue& function, int intervalMS) { | |
| 1077 | 1077 | if (isStopped()) { |
| 1078 | 1078 | scriptWarningMessage("Script.setInterval() while shutting down is ignored... parent script:" + getFilename()); |
| 1079 | 1079 | return NULL; // bail early |
| @@ -1082,7 +1082,7 @@ QObject* ScriptManager::setInterval(const ScriptValuePointer& function, int inte · 2 unmodified lines | ||
| 1082 | 1082 | return setupTimerWithInterval(function, intervalMS, false); |
| 1083 | 1083 | } |
| 1084 | 1084 | |
| 1085 | −QObject* ScriptManager::setTimeout(const ScriptValuePointer& function, int timeoutMS) { | |
| 1085 | +QObject* ScriptManager::setTimeout(const ScriptValue& function, int timeoutMS) { | |
| 1086 | 1086 | if (isStopped()) { |
| 1087 | 1087 | scriptWarningMessage("Script.setTimeout() while shutting down is ignored... parent script:" + getFilename()); |
| 1088 | 1088 | return NULL; // bail early |
| @@ -1174,7 +1174,7 @@ QString ScriptManager::_requireResolve(const QString& moduleId, const QString& r · 85 unmodified lines | ||
| 1174 | 1174 | } |
| 1175 | 1175 | auto message = QString("Cannot find module '%1' (%2)").arg(displayId); |
| 1176 | 1176 | |
| 1177 | − auto throwResolveError = [&](const ScriptValuePointer& error) -> QString { | |
| 1177 | + auto throwResolveError = [&](const ScriptValue& error) -> QString { | |
| 1178 | 1178 | _engine->raiseException(error); |
| 1179 | 1179 | _engine->maybeEmitUncaughtException("require.resolve"); |
| 1180 | 1180 | return QString(); |
| @@ -1253,73 +1253,73 @@ QString ScriptManager::_requireResolve(const QString& moduleId, const QString& r · 72 unmodified lines | ||
| 1253 | 1253 | } |
| 1254 | 1254 | |
| 1255 | 1255 | // retrieves the current parent module from the JS scope chain |
| 1256 | −ScriptValuePointer ScriptManager::currentModule() { | |
| 1256 | +ScriptValue ScriptManager::currentModule() { | |
| 1257 | 1257 | if (!_engine->IS_THREADSAFE_INVOCATION(__FUNCTION__)) { |
| 1258 | 1258 | return _engine->nullValue(); |
| 1259 | 1259 | } |
| 1260 | − auto jsRequire = _engine->globalObject()->property("Script")->property("require"); | |
| 1261 | − auto cache = jsRequire->property("cache"); | |
| 1262 | − ScriptValuePointer candidate; | |
| 1260 | + auto jsRequire = _engine->globalObject().property("Script").property("require"); | |
| 1261 | + auto cache = jsRequire.property("cache"); | |
| 1262 | + ScriptValue candidate; | |
| 1263 | 1263 | ScriptContextPointer parentContext; // using this variable to maintain parent variable lifespan |
| 1264 | − for (auto context = _engine->currentContext(); context && (!candidate || !candidate->isObject()); parentContext = context->parentContext(), context = parentContext.data()) { | |
| 1264 | + for (auto context = _engine->currentContext(); context && !candidate.isObject(); parentContext = context->parentContext(), context = parentContext.data()) { | |
| 1265 | 1265 | auto contextInfo = context->functionContext(); |
| 1266 | − candidate = cache->property(contextInfo->fileName()); | |
| 1266 | + candidate = cache.property(contextInfo->fileName()); | |
| 1267 | 1267 | } |
| 1268 | − if (!candidate || !candidate->isObject()) { | |
| 1269 | − return ScriptValuePointer(); | |
| 1268 | + if (!candidate.isObject()) { | |
| 1269 | + return ScriptValue(); | |
| 1270 | 1270 | } |
| 1271 | 1271 | return candidate; |
| 1272 | 1272 | } |
| 1273 | 1273 | |
| 1274 | 1274 | // replaces or adds "module" to "parent.children[]" array |
| 1275 | 1275 | // (for consistency with Node.js and userscript cache invalidation without "cache busters") |
| 1276 | −bool ScriptManager::registerModuleWithParent(const ScriptValuePointer& module, const ScriptValuePointer& parent) { | |
| 1277 | − auto children = parent->property("children"); | |
| 1278 | − if (children->isArray()) { | |
| 1279 | − auto key = module->property("id"); | |
| 1280 | − auto length = children->property("length")->toInt32(); | |
| 1276 | +bool ScriptManager::registerModuleWithParent(const ScriptValue& module, const ScriptValue& parent) { | |
| 1277 | + auto children = parent.property("children"); | |
| 1278 | + if (children.isArray()) { | |
| 1279 | + auto key = module.property("id"); | |
| 1280 | + auto length = children.property("length").toInt32(); | |
| 1281 | 1281 | for (int i = 0; i < length; i++) { |
| 1282 | − if (children->property(i)->property("id")->strictlyEquals(key)) { | |
| 1283 | − qCDebug(scriptengine_module) << key->toString() << " updating parent.children[" << i << "] = module"; | |
| 1284 | − children->setProperty(i, module); | |
| 1282 | + if (children.property(i).property("id").strictlyEquals(key)) { | |
| 1283 | + qCDebug(scriptengine_module) << key.toString() << " updating parent.children[" << i << "] = module"; | |
| 1284 | + children.setProperty(i, module); | |
| 1285 | 1285 | return true; |
| 1286 | 1286 | } |
| 1287 | 1287 | } |
| 1288 | − qCDebug(scriptengine_module) << key->toString() << " appending parent.children[" << length << "] = module"; | |
| 1289 | − children->setProperty(length, module); | |
| 1288 | + qCDebug(scriptengine_module) << key.toString() << " appending parent.children[" << length << "] = module"; | |
| 1289 | + children.setProperty(length, module); | |
| 1290 | 1290 | return true; |
| 1291 | − } else if (parent->isValid()) { | |
| 1292 | − qCDebug(scriptengine_module) << "registerModuleWithParent -- unrecognized parent" << parent->toVariant().toString(); | |
| 1291 | + } else if (parent.isValid()) { | |
| 1292 | + qCDebug(scriptengine_module) << "registerModuleWithParent -- unrecognized parent" << parent.toVariant().toString(); | |
| 1293 | 1293 | } |
| 1294 | 1294 | return false; |
| 1295 | 1295 | } |
| 1296 | 1296 | |
| 1297 | 1297 | // creates a new JS "module" Object with default metadata properties |
| 1298 | −ScriptValuePointer ScriptManager::newModule(const QString& modulePath, const ScriptValuePointer& parent) { | |
| 1298 | +ScriptValue ScriptManager::newModule(const QString& modulePath, const ScriptValue& parent) { | |
| 1299 | 1299 | auto closure = _engine->newObject(); |
| 1300 | 1300 | auto exports = _engine->newObject(); |
| 1301 | 1301 | auto module = _engine->newObject(); |
| 1302 | − qCDebug(scriptengine_module) << "newModule" << parent->property("filename")->toString(); | |
| 1302 | + qCDebug(scriptengine_module) << "newModule" << parent.property("filename").toString(); | |
| 1303 | 1303 | |
| 1304 | − closure->setProperty("module", module, READONLY_PROP_FLAGS); | |
| 1304 | + closure.setProperty("module", module, READONLY_PROP_FLAGS); | |
| 1305 | 1305 | |
| 1306 | 1306 | // note: this becomes the "exports" free variable, so should not be set read only |
| 1307 | − closure->setProperty("exports", exports); | |
| 1307 | + closure.setProperty("exports", exports); | |
| 1308 | 1308 | |
| 1309 | 1309 | // make the closure available to module instantiation |
| 1310 | − module->setProperty("__closure__", closure, READONLY_HIDDEN_PROP_FLAGS); | |
| 1310 | + module.setProperty("__closure__", closure, READONLY_HIDDEN_PROP_FLAGS); | |
| 1311 | 1311 | |
| 1312 | 1312 | // for consistency with Node.js Module |
| 1313 | − module->setProperty("id", modulePath, READONLY_PROP_FLAGS); | |
| 1314 | − module->setProperty("filename", modulePath, READONLY_PROP_FLAGS); | |
| 1315 | − module->setProperty("exports", exports); // not readonly | |
| 1316 | − module->setProperty("loaded", false, READONLY_PROP_FLAGS); | |
| 1317 | − module->setProperty("parent", parent, READONLY_PROP_FLAGS); | |
| 1318 | − module->setProperty("children", _engine->newArray(), READONLY_PROP_FLAGS); | |
| 1313 | + module.setProperty("id", modulePath, READONLY_PROP_FLAGS); | |
| 1314 | + module.setProperty("filename", modulePath, READONLY_PROP_FLAGS); | |
| 1315 | + module.setProperty("exports", exports); // not readonly | |
| 1316 | + module.setProperty("loaded", false, READONLY_PROP_FLAGS); | |
| 1317 | + module.setProperty("parent", parent, READONLY_PROP_FLAGS); | |
| 1318 | + module.setProperty("children", _engine->newArray(), READONLY_PROP_FLAGS); | |
| 1319 | 1319 | |
| 1320 | 1320 | // module.require is a bound version of require that always resolves relative to that module's path |
| 1321 | 1321 | auto boundRequire = _engine->evaluate("(function(id) { return Script.require(Script.require.resolve(id, this.filename)); })", "(boundRequire)"); |
| 1322 | − module->setProperty("require", boundRequire, READONLY_PROP_FLAGS); | |
| 1322 | + module.setProperty("require", boundRequire, READONLY_PROP_FLAGS); | |
| 1323 | 1323 | |
| 1324 | 1324 | return module; |
| 1325 | 1325 | } |
| @@ -1383,23 +1383,23 @@ QVariantMap ScriptManager::fetchModuleSource(const QString& modulePath, const bo · 57 unmodified lines | ||
| 1383 | 1383 | } |
| 1384 | 1384 | |
| 1385 | 1385 | // evaluate a pending module object using the fetched source code |
| 1386 | −ScriptValuePointer ScriptManager::instantiateModule(const ScriptValuePointer& module, const QString& sourceCode) { | |
| 1387 | − ScriptValuePointer result; | |
| 1388 | − auto modulePath = module->property("filename")->toString(); | |
| 1389 | − auto closure = module->property("__closure__"); | |
| 1386 | +ScriptValue ScriptManager::instantiateModule(const ScriptValue& module, const QString& sourceCode) { | |
| 1387 | + ScriptValue result; | |
| 1388 | + auto modulePath = module.property("filename").toString(); | |
| 1389 | + auto closure = module.property("__closure__"); | |
| 1390 | 1390 | |
| 1391 | 1391 | qCDebug(scriptengine_module) << QString("require.instantiateModule: %1 / %2 bytes") |
| 1392 | 1392 | .arg(QUrl(modulePath).fileName()).arg(sourceCode.length()); |
| 1393 | 1393 | |
| 1394 | − if (module->property("content-type")->toString() == "application/json") { | |
| 1394 | + if (module.property("content-type").toString() == "application/json") { | |
| 1395 | 1395 | qCDebug(scriptengine_module) << "... parsing as JSON"; |
| 1396 | − closure->setProperty("__json", sourceCode); | |
| 1396 | + closure.setProperty("__json", sourceCode); | |
| 1397 | 1397 | result = _engine->evaluateInClosure(closure, _engine->newProgram( "module.exports = JSON.parse(__json)", modulePath )); |
| 1398 | 1398 | } else { |
| 1399 | 1399 | // scoped vars for consistency with Node.js |
| 1400 | − closure->setProperty("require", module->property("require")); | |
| 1401 | − closure->setProperty("__filename", modulePath, READONLY_HIDDEN_PROP_FLAGS); | |
| 1402 | − closure->setProperty("__dirname", QString(modulePath).replace(QRegExp("/[^/]*$"), ""), READONLY_HIDDEN_PROP_FLAGS); | |
| 1400 | + closure.setProperty("require", module.property("require")); | |
| 1401 | + closure.setProperty("__filename", modulePath, READONLY_HIDDEN_PROP_FLAGS); | |
| 1402 | + closure.setProperty("__dirname", QString(modulePath).replace(QRegExp("/[^/]*$"), ""), READONLY_HIDDEN_PROP_FLAGS); | |
| 1403 | 1403 | result = _engine->evaluateInClosure(closure, _engine->newProgram( sourceCode, modulePath )); |
| 1404 | 1404 | } |
| 1405 | 1405 | _engine->maybeEmitUncaughtException(__FUNCTION__); |
| @@ -1407,19 +1407,19 @@ ScriptValuePointer ScriptManager::instantiateModule(const ScriptValuePointer& mo · 1 unmodified line | ||
| 1407 | 1407 | } |
| 1408 | 1408 | |
| 1409 | 1409 | // CommonJS/Node.js like require/module support |
| 1410 | −ScriptValuePointer ScriptManager::require(const QString& moduleId) { | |
| 1410 | +ScriptValue ScriptManager::require(const QString& moduleId) { | |
| 1411 | 1411 | qCDebug(scriptengine_module) << "ScriptManager::require(" << moduleId.left(MAX_DEBUG_VALUE_LENGTH) << ")"; |
| 1412 | 1412 | if (!_engine->IS_THREADSAFE_INVOCATION(__FUNCTION__)) { |
| 1413 | 1413 | return _engine->nullValue(); |
| 1414 | 1414 | } |
| 1415 | 1415 | |
| 1416 | − auto jsRequire = _engine->globalObject()->property("Script")->property("require"); | |
| 1416 | + auto jsRequire = _engine->globalObject().property("Script").property("require"); | |
| 1417 | 1417 | auto cacheMeta = jsRequire.data(); |
| 1418 | − auto cache = jsRequire->property("cache"); | |
| 1418 | + auto cache = jsRequire.property("cache"); | |
| 1419 | 1419 | auto parent = currentModule(); |
| 1420 | 1420 | |
| 1421 | − auto throwModuleError = [&](const QString& modulePath, const ScriptValuePointer& error) { | |
| 1422 | − cache->setProperty(modulePath, _engine->nullValue()); | |
| 1421 | + auto throwModuleError = [&](const QString& modulePath, const ScriptValue& error) { | |
| 1422 | + cache.setProperty(modulePath, _engine->nullValue()); | |
| 1423 | 1423 | if (!error.isNull()) { |
| 1424 | 1424 | #ifdef DEBUG_JS_MODULES |
| 1425 | 1425 | qCWarning(scriptengine_module) << "throwing module error:" << error.toString() << modulePath << error.property("stack").toString(); |
| @@ -1439,7 +1439,7 @@ ScriptValuePointer ScriptManager::require(const QString& moduleId) { · 13 unmodified lines | ||
| 1439 | 1439 | } |
| 1440 | 1440 | |
| 1441 | 1441 | // check the resolved path against the cache |
| 1442 | − auto module = cache->property(modulePath); | |
| 1442 | + auto module = cache.property(modulePath); | |
| 1443 | 1443 | |
| 1444 | 1444 | // modules get cached in `Script.require.cache` and (similar to Node.js) users can access it |
| 1445 | 1445 | // to inspect particular entries and invalidate them by deleting the key: |
| @@ -1449,16 +1449,16 @@ ScriptValuePointer ScriptManager::require(const QString& moduleId) { · 3 unmodified lines | ||
| 1449 | 1449 | Setting::Handle<bool> getCachebustSetting {"cachebustScriptRequire", false }; |
| 1450 | 1450 | |
| 1451 | 1451 | // cacheMeta is just used right now to tell deleted keys apart from undefined ones |
| 1452 | − bool invalidateCache = getCachebustSetting.get() || (module->isUndefined() && cacheMeta->property(moduleId)->isValid()); | |
| 1452 | + bool invalidateCache = getCachebustSetting.get() || (module.isUndefined() && cacheMeta.property(moduleId).isValid()); | |
| 1453 | 1453 | |
| 1454 | 1454 | // reset the cacheMeta record so invalidation won't apply next time, even if the module fails to load |
| 1455 | − cacheMeta->setProperty(modulePath, ScriptValuePointer()); | |
| 1455 | + cacheMeta.setProperty(modulePath, ScriptValue()); | |
| 1456 | 1456 | |
| 1457 | − auto exports = module->property("exports"); | |
| 1458 | − if (!invalidateCache && exports->isObject()) { | |
| 1457 | + auto exports = module.property("exports"); | |
| 1458 | + if (!invalidateCache && exports.isObject()) { | |
| 1459 | 1459 | // we have found a cached module -- just need to possibly register it with current parent |
| 1460 | 1460 | qCDebug(scriptengine_module) << QString("require - using cached module for '%1' (loaded: %2)") |
| 1461 | − .arg(moduleId).arg(module->property("loaded")->toString()); | |
| 1461 | + .arg(moduleId).arg(module.property("loaded").toString()); | |
| 1462 | 1462 | registerModuleWithParent(module, parent); |
| 1463 | 1463 | _engine->maybeEmitUncaughtException("cached module"); |
| 1464 | 1464 | return exports; |
| @@ -1469,7 +1469,7 @@ ScriptValuePointer ScriptManager::require(const QString& moduleId) { · 4 unmodified lines | ||
| 1469 | 1469 | registerModuleWithParent(module, parent); |
| 1470 | 1470 | |
| 1471 | 1471 | // add it to the cache (this is done early so any cyclic dependencies pick up) |
| 1472 | − cache->setProperty(modulePath, module); | |
| 1472 | + cache.setProperty(modulePath, module); | |
| 1473 | 1473 | |
| 1474 | 1474 | // download the module source |
| 1475 | 1475 | auto req = fetchModuleSource(modulePath, invalidateCache); |
| @@ -1487,36 +1487,36 @@ ScriptValuePointer ScriptManager::require(const QString& moduleId) { · 11 unmodified lines | ||
| 1487 | 1487 | auto sourceCode = req["contents"].toString(); |
| 1488 | 1488 | |
| 1489 | 1489 | if (QUrl(modulePath).fileName().endsWith(".json", Qt::CaseInsensitive)) { |
| 1490 | − module->setProperty("content-type", "application/json"); | |
| 1490 | + module.setProperty("content-type", "application/json"); | |
| 1491 | 1491 | } else { |
| 1492 | − module->setProperty("content-type", "application/javascript"); | |
| 1492 | + module.setProperty("content-type", "application/javascript"); | |
| 1493 | 1493 | } |
| 1494 | 1494 | |
| 1495 | 1495 | // evaluate the module |
| 1496 | 1496 | auto result = instantiateModule(module, sourceCode); |
| 1497 | 1497 | |
| 1498 | − if (result->isError() && !result->strictlyEquals(module->property("exports"))) { | |
| 1499 | − qCWarning(scriptengine_module) << "-- result.isError --" << result->toString(); | |
| 1498 | + if (result.isError() && !result.strictlyEquals(module.property("exports"))) { | |
| 1499 | + qCWarning(scriptengine_module) << "-- result.isError --" << result.toString(); | |
| 1500 | 1500 | return throwModuleError(modulePath, result); |
| 1501 | 1501 | } |
| 1502 | 1502 | |
| 1503 | 1503 | // mark as fully-loaded |
| 1504 | − module->setProperty("loaded", true, READONLY_PROP_FLAGS); | |
| 1504 | + module.setProperty("loaded", true, READONLY_PROP_FLAGS); | |
| 1505 | 1505 | |
| 1506 | 1506 | // set up a new reference point for detecting cache key deletion |
| 1507 | − cacheMeta->setProperty(modulePath, module); | |
| 1507 | + cacheMeta.setProperty(modulePath, module); | |
| 1508 | 1508 | |
| 1509 | 1509 | qCDebug(scriptengine_module) << "//ScriptManager::require(" << moduleId << ")"; |
| 1510 | 1510 | |
| 1511 | 1511 | _engine->maybeEmitUncaughtException(__FUNCTION__); |
| 1512 | − return module->property("exports"); | |
| 1512 | + return module.property("exports"); | |
| 1513 | 1513 | } |
| 1514 | 1514 | |
| 1515 | 1515 | // If a callback is specified, the included files will be loaded asynchronously and the callback will be called |
| 1516 | 1516 | // when all of the files have finished loading. |
| 1517 | 1517 | // If no callback is specified, the included files will be loaded synchronously and will block execution until |
| 1518 | 1518 | // all of the files have finished loading. |
| 1519 | −void ScriptManager::include(const QStringList& includeFiles, ScriptValuePointer callback) { | |
| 1519 | +void ScriptManager::include(const QStringList& includeFiles, const ScriptValue& callback) { | |
| 1520 | 1520 | if (!_engine->IS_THREADSAFE_INVOCATION(__FUNCTION__)) { |
| 1521 | 1521 | return; |
| 1522 | 1522 | } |
| @@ -1592,8 +1592,8 @@ void ScriptManager::include(const QStringList& includeFiles, ScriptValuePointer · 69 unmodified lines | ||
| 1592 | 1592 | } |
| 1593 | 1593 | _parentURL = parentURL; |
| 1594 | 1594 | |
| 1595 | − if (callback && callback->isFunction()) { | |
| 1596 | − callWithEnvironment(capturedEntityIdentifier, capturedSandboxURL, callback, ScriptValuePointer(), ScriptValueList()); | |
| 1595 | + if (callback.isFunction()) { | |
| 1596 | + callWithEnvironment(capturedEntityIdentifier, capturedSandboxURL, callback, ScriptValue(), ScriptValueList()); | |
| 1597 | 1597 | } |
| 1598 | 1598 | |
| 1599 | 1599 | loader->deleteLater(); |
| @@ -1606,14 +1606,14 @@ void ScriptManager::include(const QStringList& includeFiles, ScriptValuePointer · 6 unmodified lines | ||
| 1606 | 1606 | |
| 1607 | 1607 | loader->start(processLevelMaxRetries); |
| 1608 | 1608 | |
| 1609 | − if ((!callback || !callback->isFunction()) && !loader->isFinished()) { | |
| 1609 | + if (!callback.isFunction() && !loader->isFinished()) { | |
| 1610 | 1610 | QEventLoop loop; |
| 1611 | 1611 | QObject::connect(loader, &BatchLoader::finished, &loop, &QEventLoop::quit); |
| 1612 | 1612 | loop.exec(); |
| 1613 | 1613 | } |
| 1614 | 1614 | } |
| 1615 | 1615 | |
| 1616 | −void ScriptManager::include(const QString& includeFile, ScriptValuePointer callback) { | |
| 1616 | +void ScriptManager::include(const QString& includeFile, const ScriptValue& callback) { | |
| 1617 | 1617 | if (isStopped()) { |
| 1618 | 1618 | scriptWarningMessage("Script.include() while shutting down is ignored... includeFile:" |
| 1619 | 1619 | + includeFile + "parent script:" + getFilename()); |
| @@ -1654,7 +1654,7 @@ void ScriptManager::load(const QString& loadFile) { · 34 unmodified lines | ||
| 1654 | 1654 | } |
| 1655 | 1655 | |
| 1656 | 1656 | // Look up the handler associated with eventName and entityID. If found, evalute the argGenerator thunk and call the handler with those args |
| 1657 | −void ScriptManager::forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, ScriptValueList eventHandlerArgs) { | |
| 1657 | +void ScriptManager::forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, const ScriptValueList& eventHandlerArgs) { | |
| 1658 | 1658 | if (QThread::currentThread() != thread()) { |
| 1659 | 1659 | qCDebug(scriptengine) << "*** ERROR *** ScriptManager::forwardHandlerCall() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]"; |
| 1660 | 1660 | assert(false); |
| @@ -1674,7 +1674,7 @@ void ScriptManager::forwardHandlerCall(const EntityItemID& entityID, const QStri · 13 unmodified lines | ||
| 1674 | 1674 | // and the entity scripts may be for entities other than the one this is a handler for. |
| 1675 | 1675 | // Fortunately, the definingEntityIdentifier captured the entity script id (if any) when the handler was added. |
| 1676 | 1676 | CallbackData& handler = handlersForEvent[i]; |
| 1677 | − callWithEnvironment(handler.definingEntityIdentifier, handler.definingSandboxURL, handler.function, ScriptValuePointer(), eventHandlerArgs); | |
| 1677 | + callWithEnvironment(handler.definingEntityIdentifier, handler.definingSandboxURL, handler.function, ScriptValue(), eventHandlerArgs); | |
| 1678 | 1678 | } |
| 1679 | 1679 | } |
| 1680 | 1680 | } |
| @@ -1921,13 +1921,13 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 240 unmodified lines | ||
| 1921 | 1921 | |
| 1922 | 1922 | // SYNTAX ERRORS |
| 1923 | 1923 | auto syntaxError = _engine->lintScript(contents, fileName); |
| 1924 | − if (syntaxError->isError()) { | |
| 1925 | − auto message = syntaxError->property("formatted")->toString(); | |
| 1924 | + if (syntaxError.isError()) { | |
| 1925 | + auto message = syntaxError.property("formatted").toString(); | |
| 1926 | 1926 | if (message.isEmpty()) { |
| 1927 | − message = syntaxError->toString(); | |
| 1927 | + message = syntaxError.toString(); | |
| 1928 | 1928 | } |
| 1929 | 1929 | setError(QString("Bad syntax (%1)").arg(message), EntityScriptStatus::ERROR_RUNNING_SCRIPT); |
| 1930 | − syntaxError->setProperty("detail", entityID.toString()); | |
| 1930 | + syntaxError.setProperty("detail", entityID.toString()); | |
| 1931 | 1931 | emit unhandledException(syntaxError); |
| 1932 | 1932 | return; |
| 1933 | 1933 | } |
| @@ -1946,7 +1946,7 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 12 unmodified lines | ||
| 1946 | 1946 | const int SANDBOX_TIMEOUT = 0.25 * MSECS_PER_SECOND; |
| 1947 | 1947 | ScriptEnginePointer sandbox = newScriptEngine(); |
| 1948 | 1948 | sandbox->setProcessEventsInterval(SANDBOX_TIMEOUT); |
| 1949 | − ScriptValuePointer testConstructor, exception; | |
| 1949 | + ScriptValue testConstructor, exception; | |
| 1950 | 1950 | if (atoi(getenv("UNSAFE_ENTITY_SCRIPTS") ? getenv("UNSAFE_ENTITY_SCRIPTS") : "0")) |
| 1951 | 1951 | { |
| 1952 | 1952 | QTimer timeout; |
| @@ -1966,7 +1966,7 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 13 unmodified lines | ||
| 1966 | 1966 | if (sandbox->hasUncaughtException()) { |
| 1967 | 1967 | exception = sandbox->cloneUncaughtException(QString("(preflight %1)").arg(entityID.toString())); |
| 1968 | 1968 | sandbox->clearExceptions(); |
| 1969 | − } else if (testConstructor && testConstructor->isError()) { | |
| 1969 | + } else if (testConstructor.isError()) { | |
| 1970 | 1970 | exception = testConstructor; |
| 1971 | 1971 | } |
| 1972 | 1972 | } else { |
| @@ -2041,7 +2041,7 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 68 unmodified lines | ||
| 2041 | 2041 | if (sandbox->hasUncaughtException()) { |
| 2042 | 2042 | exception = sandbox->cloneUncaughtException(QString("(preflight %1)").arg(entityID.toString())); |
| 2043 | 2043 | sandbox->clearExceptions(); |
| 2044 | − } else if (testConstructor && testConstructor->isError()) { | |
| 2044 | + } else if (testConstructor.isError()) { | |
| 2045 | 2045 | exception = testConstructor; |
| 2046 | 2046 | } |
| 2047 | 2047 | } |
| @@ -2051,7 +2051,7 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 3 unmodified lines | ||
| 2051 | 2051 | // exception = makeError("UNSAFE_ENTITY_SCRIPTS == 0"); |
| 2052 | 2052 | } |
| 2053 | 2053 | |
| 2054 | − if (exception && exception->isError()) { | |
| 2054 | + if (exception.isError()) { | |
| 2055 | 2055 | // create a local copy using makeError to decouple from the sandbox engine |
| 2056 | 2056 | exception = _engine->makeError(exception); |
| 2057 | 2057 | setError(formatException(exception, _enableExtendedJSExceptions.get()), EntityScriptStatus::ERROR_RUNNING_SCRIPT); |
| @@ -2060,12 +2060,12 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 2 unmodified lines | ||
| 2060 | 2060 | } |
| 2061 | 2061 | |
| 2062 | 2062 | // CONSTRUCTOR VIABILITY |
| 2063 | − if (!testConstructor || !testConstructor->isFunction()) { | |
| 2064 | − QString testConstructorType = QString(testConstructor->toVariant().typeName()); | |
| 2063 | + if (!testConstructor.isFunction()) { | |
| 2064 | + QString testConstructorType = QString(testConstructor.toVariant().typeName()); | |
| 2065 | 2065 | if (testConstructorType == "") { |
| 2066 | 2066 | testConstructorType = "empty"; |
| 2067 | 2067 | } |
| 2068 | − QString testConstructorValue = testConstructor->toString(); | |
| 2068 | + QString testConstructorValue = testConstructor.toString(); | |
| 2069 | 2069 | if (testConstructorValue.size() > MAX_DEBUG_VALUE_LENGTH) { |
| 2070 | 2070 | testConstructorValue = testConstructorValue.mid(0, MAX_DEBUG_VALUE_LENGTH) + "..."; |
| 2071 | 2071 | } |
| @@ -2073,8 +2073,8 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 1 unmodified line | ||
| 2073 | 2073 | .arg(testConstructorType).arg(testConstructorValue); |
| 2074 | 2074 | |
| 2075 | 2075 | auto err = _engine->makeError(_engine->newValue(message)); |
| 2076 | − err->setProperty("fileName", scriptOrURL); | |
| 2077 | − err->setProperty("detail", "(constructor " + entityID.toString() + ")"); | |
| 2076 | + err.setProperty("fileName", scriptOrURL); | |
| 2077 | + err.setProperty("detail", "(constructor " + entityID.toString() + ")"); | |
| 2078 | 2078 | |
| 2079 | 2079 | setError("Could not find constructor (" + testConstructorType + ")", EntityScriptStatus::ERROR_RUNNING_SCRIPT); |
| 2080 | 2080 | emit unhandledException(err); |
| @@ -2089,11 +2089,11 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 8 unmodified lines | ||
| 2089 | 2089 | } |
| 2090 | 2090 | |
| 2091 | 2091 | // THE ACTUAL EVALUATION AND CONSTRUCTION |
| 2092 | − ScriptValuePointer entityScriptConstructor, entityScriptObject; | |
| 2092 | + ScriptValue entityScriptConstructor, entityScriptObject; | |
| 2093 | 2093 | QUrl sandboxURL = currentSandboxURL.isEmpty() ? scriptOrURL : currentSandboxURL; |
| 2094 | 2094 | auto initialization = [&]{ |
| 2095 | 2095 | entityScriptConstructor = _engine->evaluate(contents, fileName); |
| 2096 | − entityScriptObject = entityScriptConstructor->construct(); | |
| 2096 | + entityScriptObject = entityScriptConstructor.construct(); | |
| 2097 | 2097 | |
| 2098 | 2098 | if (_engine->hasUncaughtException()) { |
| 2099 | 2099 | entityScriptObject = _engine->cloneUncaughtException("(construct " + entityID.toString() + ")"); |
| @@ -2103,7 +2103,7 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 3 unmodified lines | ||
| 2103 | 2103 | |
| 2104 | 2104 | doWithEnvironment(entityID, sandboxURL, initialization); |
| 2105 | 2105 | |
| 2106 | − if (entityScriptObject && entityScriptObject->isError()) { | |
| 2106 | + if (entityScriptObject.isError()) { | |
| 2107 | 2107 | auto exception = entityScriptObject; |
| 2108 | 2108 | setError(formatException(exception, _enableExtendedJSExceptions.get()), EntityScriptStatus::ERROR_RUNNING_SCRIPT); |
| 2109 | 2109 | emit unhandledException(exception); |
| @@ -2266,7 +2266,7 @@ void ScriptManager::doWithEnvironment(const EntityItemID& entityID, const QUrl& · 156 unmodified lines | ||
| 2266 | 2266 | currentSandboxURL = sandboxURL; |
| 2267 | 2267 | |
| 2268 | 2268 | #if DEBUG_CURRENT_ENTITY |
| 2269 | − ScriptValuePointer oldData = this->globalObject().property("debugEntityID"); | |
| 2269 | + ScriptValue oldData = this->globalObject().property("debugEntityID"); | |
| 2270 | 2270 | this->globalObject().setProperty("debugEntityID", entityID.toScriptValue(this)); // Make the entityID available to javascript as a global. |
| 2271 | 2271 | operation(); |
| 2272 | 2272 | this->globalObject().setProperty("debugEntityID", oldData); |
| @@ -2278,9 +2278,9 @@ void ScriptManager::doWithEnvironment(const EntityItemID& entityID, const QUrl& · 5 unmodified lines | ||
| 2278 | 2278 | currentSandboxURL = oldSandboxURL; |
| 2279 | 2279 | } |
| 2280 | 2280 | |
| 2281 | −void ScriptManager::callWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, ScriptValuePointer function, ScriptValuePointer thisObject, ScriptValueList args) { | |
| 2281 | +void ScriptManager::callWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, const ScriptValue& function, const ScriptValue& thisObject, const ScriptValueList& args) { | |
| 2282 | 2282 | auto operation = [&]() { |
| 2283 | − function->call(thisObject, args); | |
| 2283 | + function.call(thisObject, args); | |
| 2284 | 2284 | }; |
| 2285 | 2285 | doWithEnvironment(entityID, sandboxURL, operation); |
| 2286 | 2286 | } |
| @@ -2313,7 +2313,7 @@ void ScriptManager::callEntityScriptMethod(const EntityItemID& entityID, const Q · 26 unmodified lines | ||
| 2313 | 2313 | QWriteLocker locker { &_entityScriptsLock }; |
| 2314 | 2314 | details = _entityScripts[entityID]; |
| 2315 | 2315 | } |
| 2316 | − ScriptValuePointer entityScript = details.scriptObject; // previously loaded | |
| 2316 | + ScriptValue entityScript = details.scriptObject; // previously loaded | |
| 2317 | 2317 | |
| 2318 | 2318 | // If this is a remote call, we need to check to see if the function is remotely callable |
| 2319 | 2319 | // we do this by checking for the existance of the 'remotelyCallable' property on the |
| @@ -2323,11 +2323,11 @@ void ScriptManager::callEntityScriptMethod(const EntityItemID& entityID, const Q · 3 unmodified lines | ||
| 2323 | 2323 | if (remoteCallerID == QUuid()) { |
| 2324 | 2324 | callAllowed = true; |
| 2325 | 2325 | } else { |
| 2326 | − if (entityScript->property("remotelyCallable")->isArray()) { | |
| 2327 | − auto callables = entityScript->property("remotelyCallable"); | |
| 2328 | − auto callableCount = callables->property("length")->toInteger(); | |
| 2326 | + if (entityScript.property("remotelyCallable").isArray()) { | |
| 2327 | + auto callables = entityScript.property("remotelyCallable"); | |
| 2328 | + auto callableCount = callables.property("length").toInteger(); | |
| 2329 | 2329 | for (int i = 0; i < callableCount; i++) { |
| 2330 | − auto callable = callables->property(i)->toString(); | |
| 2330 | + auto callable = callables.property(i).toString(); | |
| 2331 | 2331 | if (callable == methodName) { |
| 2332 | 2332 | callAllowed = true; |
| 2333 | 2333 | break; |
| @@ -2339,17 +2339,17 @@ void ScriptManager::callEntityScriptMethod(const EntityItemID& entityID, const Q · 5 unmodified lines | ||
| 2339 | 2339 | } |
| 2340 | 2340 | } |
| 2341 | 2341 | |
| 2342 | − if (callAllowed && entityScript->property(methodName)->isFunction()) { | |
| 2342 | + if (callAllowed && entityScript.property(methodName).isFunction()) { | |
| 2343 | 2343 | auto scriptEngine = engine().data(); |
| 2344 | 2344 | |
| 2345 | 2345 | ScriptValueList args; |
| 2346 | 2346 | args << EntityItemIDtoScriptValue(scriptEngine, entityID); |
| 2347 | 2347 | args << scriptValueFromSequence(scriptEngine, params); |
| 2348 | 2348 | |
| 2349 | − ScriptValuePointer oldData = scriptEngine->globalObject()->property("Script")->property("remoteCallerID"); | |
| 2350 | − scriptEngine->globalObject()->property("Script")->setProperty("remoteCallerID", remoteCallerID.toString()); // Make the remoteCallerID available to javascript as a global. | |
| 2351 | − callWithEnvironment(entityID, details.definingSandboxURL, entityScript->property(methodName), entityScript, args); | |
| 2352 | − scriptEngine->globalObject()->property("Script")->setProperty("remoteCallerID", oldData); | |
| 2349 | + ScriptValue oldData = scriptEngine->globalObject().property("Script").property("remoteCallerID"); | |
| 2350 | + scriptEngine->globalObject().property("Script").setProperty("remoteCallerID", remoteCallerID.toString()); // Make the remoteCallerID available to javascript as a global. | |
| 2351 | + callWithEnvironment(entityID, details.definingSandboxURL, entityScript.property(methodName), entityScript, args); | |
| 2352 | + scriptEngine->globalObject().property("Script").setProperty("remoteCallerID", oldData); | |
| 2353 | 2353 | } |
| 2354 | 2354 | } |
| 2355 | 2355 | } |
| @@ -2381,14 +2381,14 @@ void ScriptManager::callEntityScriptMethod(const EntityItemID& entityID, const Q · 25 unmodified lines | ||
| 2381 | 2381 | QWriteLocker locker { &_entityScriptsLock }; |
| 2382 | 2382 | details = _entityScripts[entityID]; |
| 2383 | 2383 | } |
| 2384 | − ScriptValuePointer entityScript = details.scriptObject; // previously loaded | |
| 2385 | − if (entityScript->property(methodName)->isFunction()) { | |
| 2384 | + ScriptValue entityScript = details.scriptObject; // previously loaded | |
| 2385 | + if (entityScript.property(methodName).isFunction()) { | |
| 2386 | 2386 | auto scriptEngine = engine().data(); |
| 2387 | 2387 | |
| 2388 | 2388 | ScriptValueList args; |
| 2389 | 2389 | args << EntityItemIDtoScriptValue(scriptEngine, entityID); |
| 2390 | 2390 | args << event.toScriptValue(scriptEngine); |
| 2391 | − callWithEnvironment(entityID, details.definingSandboxURL, entityScript->property(methodName), entityScript, args); | |
| 2391 | + callWithEnvironment(entityID, details.definingSandboxURL, entityScript.property(methodName), entityScript, args); | |
| 2392 | 2392 | } |
| 2393 | 2393 | } |
| 2394 | 2394 | } |
| @@ -2421,15 +2421,15 @@ void ScriptManager::callEntityScriptMethod(const EntityItemID& entityID, const Q · 26 unmodified lines | ||
| 2421 | 2421 | QWriteLocker locker { &_entityScriptsLock }; |
| 2422 | 2422 | details = _entityScripts[entityID]; |
| 2423 | 2423 | } |
| 2424 | − ScriptValuePointer entityScript = details.scriptObject; // previously loaded | |
| 2425 | − if (entityScript->property(methodName)->isFunction()) { | |
| 2424 | + ScriptValue entityScript = details.scriptObject; // previously loaded | |
| 2425 | + if (entityScript.property(methodName).isFunction()) { | |
| 2426 | 2426 | auto scriptEngine = engine().data(); |
| 2427 | 2427 | |
| 2428 | 2428 | ScriptValueList args; |
| 2429 | 2429 | args << EntityItemIDtoScriptValue(scriptEngine, entityID); |
| 2430 | 2430 | args << EntityItemIDtoScriptValue(scriptEngine, otherID); |
| 2431 | 2431 | args << collisionToScriptValue(scriptEngine, collision); |
| 2432 | − callWithEnvironment(entityID, details.definingSandboxURL, entityScript->property(methodName), entityScript, args); | |
| 2432 | + callWithEnvironment(entityID, details.definingSandboxURL, entityScript.property(methodName), entityScript, args); | |
| 2433 | 2433 | } |
| 2434 | 2434 | } |
| 2435 | 2435 | } |
| @@ -2438,28 +2438,28 @@ QString ScriptManager::getExternalPath(ExternalResource::Bucket bucket, const QS · 2 unmodified lines | ||
| 2438 | 2438 | return ExternalResource::getInstance()->getUrl(bucket, path); |
| 2439 | 2439 | } |
| 2440 | 2440 | |
| 2441 | −QString ScriptManager::formatException(const ScriptValuePointer& exception, bool includeExtendedDetails) { | |
| 2441 | +QString ScriptManager::formatException(const ScriptValue& exception, bool includeExtendedDetails) { | |
| 2442 | 2442 | if (!_engine->IS_THREADSAFE_INVOCATION(__FUNCTION__)) { |
| 2443 | 2443 | return QString(); |
| 2444 | 2444 | } |
| 2445 | 2445 | QString note{ "UncaughtException" }; |
| 2446 | 2446 | QString result; |
| 2447 | 2447 | |
| 2448 | − if (!exception->isObject()) { | |
| 2448 | + if (!exception.isObject()) { | |
| 2449 | 2449 | return result; |
| 2450 | 2450 | } |
| 2451 | − const auto message = exception->toString(); | |
| 2452 | − const auto fileName = exception->property("fileName")->toString(); | |
| 2453 | − const auto lineNumber = exception->property("lineNumber")->toString(); | |
| 2454 | − const auto stacktrace = exception->property("stack")->toString(); | |
| 2451 | + const auto message = exception.toString(); | |
| 2452 | + const auto fileName = exception.property("fileName").toString(); | |
| 2453 | + const auto lineNumber = exception.property("lineNumber").toString(); | |
| 2454 | + const auto stacktrace = exception.property("stack").toString(); | |
| 2455 | 2455 | |
| 2456 | 2456 | if (includeExtendedDetails) { |
| 2457 | 2457 | // Display additional exception / troubleshooting hints that can be added via the custom Error .detail property |
| 2458 | 2458 | // Example difference: |
| 2459 | 2459 | // [UncaughtExceptions] Error: Can't find variable: foobar in atp:/myentity.js\n... |
| 2460 | 2460 | // [UncaughtException (construct {1eb5d3fa-23b1-411c-af83-163af7220e3f})] Error: Can't find variable: foobar in atp:/myentity.js\n... |
| 2461 | − if (exception->property("detail")->isValid()) { | |
| 2462 | − note += " " + exception->property("detail")->toString(); | |
| 2461 | + if (exception.property("detail").isValid()) { | |
| 2462 | + note += " " + exception.property("detail").toString(); | |
| 2463 | 2463 | } |
| 2464 | 2464 | } |
| 2465 | 2465 | |
| @@ -2470,6 +2470,6 @@ QString ScriptManager::formatException(const ScriptValuePointer& exception, bool · 4 unmodified lines | ||
| 2470 | 2470 | return result; |
| 2471 | 2471 | } |
| 2472 | 2472 | |
| 2473 | −ScriptValuePointer ScriptManager::evaluate(const QString& program, const QString& fileName) { | |
| 2473 | +ScriptValue ScriptManager::evaluate(const QString& program, const QString& fileName) { | |
| 2474 | 2474 | return _engine->evaluate(program, fileName); |
| 2475 | 2475 | } |