This is a slightly hacky way to make ScriptManager work without any networking, and minimize the number of dependencies needed to run a test.
Showing the changes to libraries/script-engine/src/ScriptManager.cpp (1 of 7 files). Show all
Unified · Split
| @@ -269,6 +269,9 @@ ScriptManager::ScriptManager(Context context, const QString& scriptContents, con · 268 unmodified lines | |||
| 269 | case Context::AGENT_SCRIPT: | 269 | case Context::AGENT_SCRIPT: |
| 270 | _type = Type::AGENT; | 270 | _type = Type::AGENT; |
| 271 | break; | 271 | break; |
| 272 | case Context::NETWORKLESS_TEST_SCRIPT: | ||
| 273 | _type = Type::NETWORKLESS_TEST; | ||
| 274 | break; | ||
| 272 | } | 275 | } |
| 273 | 276 | ||
| 274 | _scriptingInterface = std::make_shared<ScriptManagerScriptingInterface>(this); | 277 | _scriptingInterface = std::make_shared<ScriptManagerScriptingInterface>(this); |
| @@ -321,6 +324,8 @@ QString ScriptManager::getContext() const { · 46 unmodified lines | |||
| 321 | return "entity_server"; | 324 | return "entity_server"; |
| 322 | case AGENT_SCRIPT: | 325 | case AGENT_SCRIPT: |
| 323 | return "agent"; | 326 | return "agent"; |
| 327 | case NETWORKLESS_TEST_SCRIPT: | ||
| 328 | return "networkless_test"; | ||
| 324 | default: | 329 | default: |
| 325 | return "unknown"; | 330 | return "unknown"; |
| 326 | } | 331 | } |
| @@ -664,15 +669,25 @@ void ScriptManager::init() { · 337 unmodified lines | |||
| 664 | } | 669 | } |
| 665 | 670 | ||
| 666 | _isInitialized = true; | 671 | _isInitialized = true; |
| 667 | runStaticInitializers(this); | 672 | |
| 673 | if (_context != NETWORKLESS_TEST_SCRIPT) { | ||
| 674 | // This initializes a bunch of systems that want network access. We | ||
| 675 | // want to avoid it in test script mode. | ||
| 676 | runStaticInitializers(this); | ||
| 677 | } | ||
| 668 | 678 | ||
| 669 | auto scriptEngine = _engine.get(); | 679 | auto scriptEngine = _engine.get(); |
| 670 | 680 | ||
| 671 | ScriptValue xmlHttpRequestConstructorValue = scriptEngine->newFunction(XMLHttpRequestClass::constructor); | 681 | if (_context != NETWORKLESS_TEST_SCRIPT) { |
| 672 | scriptEngine->globalObject().setProperty("XMLHttpRequest", xmlHttpRequestConstructorValue); | 682 | // For test scripts we want to minimize the amount of functionality available, for the least |
| 683 | // amount of dependencies and faster test system startup. | ||
| 684 | |||
| 685 | ScriptValue xmlHttpRequestConstructorValue = scriptEngine->newFunction(XMLHttpRequestClass::constructor); | ||
| 686 | scriptEngine->globalObject().setProperty("XMLHttpRequest", xmlHttpRequestConstructorValue); | ||
| 673 | 687 | ||
| 674 | ScriptValue webSocketConstructorValue = scriptEngine->newFunction(WebSocketClass::constructor); | 688 | ScriptValue webSocketConstructorValue = scriptEngine->newFunction(WebSocketClass::constructor); |
| 675 | scriptEngine->globalObject().setProperty("WebSocket", webSocketConstructorValue); | 689 | scriptEngine->globalObject().setProperty("WebSocket", webSocketConstructorValue); |
| 690 | } | ||
| 676 | 691 | ||
| 677 | /*@jsdoc | 692 | /*@jsdoc |
| 678 | * Prints a message to the program log and emits {@link Script.printedMessage}. | 693 | * Prints a message to the program log and emits {@link Script.printedMessage}. |
| @@ -703,7 +718,12 @@ void ScriptManager::init() { · 24 unmodified lines | |||
| 703 | scriptEngine->registerGlobalObject("Vec3", &_vec3Library); | 718 | scriptEngine->registerGlobalObject("Vec3", &_vec3Library); |
| 704 | scriptEngine->registerGlobalObject("Mat4", &_mat4Library); | 719 | scriptEngine->registerGlobalObject("Mat4", &_mat4Library); |
| 705 | scriptEngine->registerGlobalObject("Uuid", &_uuidLibrary); | 720 | scriptEngine->registerGlobalObject("Uuid", &_uuidLibrary); |
| 706 | scriptEngine->registerGlobalObject("Messages", DependencyManager::get<MessagesClient>().data()); | 721 | |
| 722 | if (_context != NETWORKLESS_TEST_SCRIPT) { | ||
| 723 | // This requires networking, we want to avoid the need for it in test scripts | ||
| 724 | scriptEngine->registerGlobalObject("Messages", DependencyManager::get<MessagesClient>().data()); | ||
| 725 | } | ||
| 726 | |||
| 707 | scriptEngine->registerGlobalObject("File", new FileScriptingInterface(this)); | 727 | scriptEngine->registerGlobalObject("File", new FileScriptingInterface(this)); |
| 708 | scriptEngine->registerGlobalObject("console", &_consoleScriptingInterface); | 728 | scriptEngine->registerGlobalObject("console", &_consoleScriptingInterface); |
| 709 | scriptEngine->registerFunction("console", "info", ConsoleScriptingInterface::info, scriptEngine->currentContext()->argumentCount()); | 729 | scriptEngine->registerFunction("console", "info", ConsoleScriptingInterface::info, scriptEngine->currentContext()->argumentCount()); |
| @@ -717,25 +737,28 @@ void ScriptManager::init() { · 7 unmodified lines | |||
| 717 | scriptEngine->registerFunction("console", "groupCollapsed", ConsoleScriptingInterface::groupCollapsed, 1); | 737 | scriptEngine->registerFunction("console", "groupCollapsed", ConsoleScriptingInterface::groupCollapsed, 1); |
| 718 | scriptEngine->registerFunction("console", "groupEnd", ConsoleScriptingInterface::groupEnd, 0); | 738 | scriptEngine->registerFunction("console", "groupEnd", ConsoleScriptingInterface::groupEnd, 0); |
| 719 | 739 | ||
| 720 | // Scriptable cache access | ||
| 721 | auto resourcePrototype = createScriptableResourcePrototype(shared_from_this()); | ||
| 722 | scriptEngine->globalObject().setProperty("Resource", resourcePrototype); | ||
| 723 | scriptEngine->setDefaultPrototype(qMetaTypeId<ScriptableResource*>(), resourcePrototype); | ||
| 724 | |||
| 725 | // constants | 740 | // constants |
| 726 | scriptEngine->globalObject().setProperty("TREE_SCALE", scriptEngine->newValue(TREE_SCALE)); | 741 | scriptEngine->globalObject().setProperty("TREE_SCALE", scriptEngine->newValue(TREE_SCALE)); |
| 727 | 742 | ||
| 728 | scriptEngine->registerGlobalObject("Assets", _assetScriptingInterface); | 743 | if (_context != NETWORKLESS_TEST_SCRIPT) { |
| 729 | scriptEngine->registerGlobalObject("Resources", DependencyManager::get<ResourceScriptingInterface>().data()); | 744 | // Scriptable cache access |
| 745 | auto resourcePrototype = createScriptableResourcePrototype(shared_from_this()); | ||
| 746 | scriptEngine->globalObject().setProperty("Resource", resourcePrototype); | ||
| 747 | scriptEngine->setDefaultPrototype(qMetaTypeId<ScriptableResource*>(), resourcePrototype); | ||
| 748 | |||
| 749 | scriptEngine->registerGlobalObject("Assets", _assetScriptingInterface); | ||
| 750 | scriptEngine->registerGlobalObject("Resources", DependencyManager::get<ResourceScriptingInterface>().data()); | ||
| 730 | 751 | ||
| 731 | scriptEngine->registerGlobalObject("DebugDraw", &DebugDraw::getInstance()); | 752 | scriptEngine->registerGlobalObject("DebugDraw", &DebugDraw::getInstance()); |
| 732 | 753 | ||
| 733 | scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data()); | 754 | scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data()); |
| 755 | } | ||
| 734 | 756 | ||
| 735 | #if DEV_BUILD || PR_BUILD | 757 | #if DEV_BUILD || PR_BUILD |
| 736 | scriptEngine->registerGlobalObject("StackTest", new StackTestScriptingInterface(this)); | 758 | scriptEngine->registerGlobalObject("StackTest", new StackTestScriptingInterface(this)); |
| 737 | #endif | 759 | #endif |
| 738 | 760 | ||
| 761 | qCDebug(scriptengine) << "Engine initialized"; | ||
| 739 | } | 762 | } |
| 740 | 763 | ||
| 741 | // registers a global object by name | 764 | // registers a global object by name |
| @@ -820,6 +843,10 @@ void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString& · 78 unmodified lines | |||
| 820 | } | 843 | } |
| 821 | 844 | ||
| 822 | bool ScriptManager::isStopped() const { | 845 | bool ScriptManager::isStopped() const { |
| 846 | if (_context == NETWORKLESS_TEST_SCRIPT) { | ||
| 847 | return false; | ||
| 848 | } | ||
| 849 | |||
| 823 | QSharedPointer<ScriptEngines> scriptEngines(_scriptEngines); | 850 | QSharedPointer<ScriptEngines> scriptEngines(_scriptEngines); |
| 824 | return !scriptEngines || scriptEngines->isStopped(); | 851 | return !scriptEngines || scriptEngines->isStopped(); |
| 825 | } | 852 | } |
| @@ -841,6 +868,7 @@ void ScriptManager::run() { · 15 unmodified lines | |||
| 841 | PROFILE_SET_THREAD_NAME("Script: " + name); | 868 | PROFILE_SET_THREAD_NAME("Script: " + name); |
| 842 | 869 | ||
| 843 | if (isStopped()) { | 870 | if (isStopped()) { |
| 871 | qCCritical(scriptengine) << "ScriptManager is stopped or ScriptEngines is not available, refusing to run script"; | ||
| 844 | return; // bail early - avoid setting state in init(), as evaluate() will bail too | 872 | return; // bail early - avoid setting state in init(), as evaluate() will bail too |
| 845 | } | 873 | } |
| 846 | 874 | ||
| @@ -873,8 +901,12 @@ void ScriptManager::run() { · 26 unmodified lines | |||
| 873 | 901 | ||
| 874 | std::chrono::microseconds totalUpdates(0); | 902 | std::chrono::microseconds totalUpdates(0); |
| 875 | 903 | ||
| 904 | qCDebug(scriptengine) << "Waiting for finish"; | ||
| 905 | |||
| 876 | // TODO: Integrate this with signals/slots instead of reimplementing throttling for ScriptManager | 906 | // TODO: Integrate this with signals/slots instead of reimplementing throttling for ScriptManager |
| 877 | while (!_isFinished) { | 907 | while (!_isFinished) { |
| 908 | qCDebug(scriptengine) << "In script event loop"; | ||
| 909 | |||
| 878 | auto beforeSleep = clock::now(); | 910 | auto beforeSleep = clock::now(); |
| 879 | 911 | ||
| 880 | // Throttle to SCRIPT_FPS | 912 | // Throttle to SCRIPT_FPS |