Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 2 files). Show all
Unified · Split
| @@ -578,7 +578,7 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& · 577 unmodified lines | |||
| 578 | _registeredHandlers[entityID] = RegisteredEventHandlers(); | 578 | _registeredHandlers[entityID] = RegisteredEventHandlers(); |
| 579 | } | 579 | } |
| 580 | CallbackList& handlersForEvent = _registeredHandlers[entityID][eventName]; | 580 | CallbackList& handlersForEvent = _registeredHandlers[entityID][eventName]; |
| 581 | CallbackData handlerData = {handler, currentEntityIdentifier}; | 581 | CallbackData handlerData = {handler, currentEntityIdentifier, currentSandboxURL}; |
| 582 | handlersForEvent << handlerData; // Note that the same handler can be added many times. See removeEntityEventHandler(). | 582 | handlersForEvent << handlerData; // Note that the same handler can be added many times. See removeEntityEventHandler(). |
| 583 | } | 583 | } |
| 584 | 584 | ||
| @@ -795,7 +795,7 @@ void ScriptEngine::timerFired() { · 210 unmodified lines | |||
| 795 | 795 | ||
| 796 | // call the associated JS function, if it exists | 796 | // call the associated JS function, if it exists |
| 797 | if (timerData.function.isValid()) { | 797 | if (timerData.function.isValid()) { |
| 798 | callWithEnvironment(timerData.definingEntityIdentifier, timerData.function, timerData.function, QScriptValueList()); | 798 | callWithEnvironment(timerData.definingEntityIdentifier, timerData.definingSandboxURL, timerData.function, timerData.function, QScriptValueList()); |
| 799 | } | 799 | } |
| 800 | } | 800 | } |
| 801 | 801 | ||
| @@ -810,7 +810,7 @@ QObject* ScriptEngine::setupTimerWithInterval(const QScriptValue& function, int · 8 unmodified lines | |||
| 810 | // make sure the timer stops when the script does | 810 | // make sure the timer stops when the script does |
| 811 | connect(this, &ScriptEngine::scriptEnding, newTimer, &QTimer::stop); | 811 | connect(this, &ScriptEngine::scriptEnding, newTimer, &QTimer::stop); |
| 812 | 812 | ||
| 813 | CallbackData timerData = {function, currentEntityIdentifier}; | 813 | CallbackData timerData = {function, currentEntityIdentifier, currentSandboxURL}; |
| 814 | _timerFunctionMap.insert(newTimer, timerData); | 814 | _timerFunctionMap.insert(newTimer, timerData); |
| 815 | 815 | ||
| 816 | newTimer->start(intervalMS); | 816 | newTimer->start(intervalMS); |
| @@ -885,19 +885,46 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac · 68 unmodified lines | |||
| 885 | return; // bail early | 885 | return; // bail early |
| 886 | } | 886 | } |
| 887 | QList<QUrl> urls; | 887 | QList<QUrl> urls; |
| 888 | bool knowsSensitivity = false; | ||
| 889 | Qt::CaseSensitivity sensitivity; | ||
| 890 | auto getSensitivity = [&]() { | ||
| 891 | if (!knowsSensitivity) { | ||
| 892 | QString path = currentSandboxURL.path(); | ||
| 893 | QFileInfo upperFI(path.toUpper()); | ||
| 894 | QFileInfo lowerFI(path.toLower()); | ||
| 895 | sensitivity = (upperFI == lowerFI) ? Qt::CaseInsensitive : Qt::CaseSensitive; | ||
| 896 | knowsSensitivity = true; | ||
| 897 | } | ||
| 898 | return sensitivity; | ||
| 899 | }; | ||
| 900 | |||
| 888 | for (QString file : includeFiles) { | 901 | for (QString file : includeFiles) { |
| 889 | QUrl thisURL { resolvePath(file) }; | 902 | QUrl thisURL { resolvePath(file) }; |
| 890 | if (!_includedURLs.contains(thisURL)) { | 903 | if (!_includedURLs.contains(thisURL)) { |
| 891 | urls.append(thisURL); | 904 | if (!currentSandboxURL.isEmpty() && (thisURL.scheme() == "file") && |
| 892 | _includedURLs << thisURL; | 905 | ( |
| 893 | } | 906 | (currentSandboxURL.scheme() != "file") || |
| 894 | else { | 907 | ( |
| 908 | !thisURL.toString(QUrl::RemoveFilename).startsWith(defaultScriptsLocation().toString(), getSensitivity()) && | ||
| 909 | !thisURL.toString(QUrl::RemoveFilename).startsWith(currentSandboxURL.toString(QUrl::RemoveFilename), getSensitivity()) | ||
| 910 | ) | ||
| 911 | ) | ||
| 912 | ) { | ||
| 913 | qCWarning(scriptengine) << "Script.include() ignoring file path" << thisURL << "outside of original entity script" << currentSandboxURL; | ||
| 914 | } else { | ||
| 915 | // We could also check here for CORS, but we don't yet. | ||
| 916 | // It turns out that QUrl.resolve will not change hosts and copy authority, so we don't need to check that here. | ||
| 917 | urls.append(thisURL); | ||
| 918 | _includedURLs << thisURL; | ||
| 919 | } | ||
| 920 | } else { | ||
| 895 | qCDebug(scriptengine) << "Script.include() ignoring previously included url:" << thisURL; | 921 | qCDebug(scriptengine) << "Script.include() ignoring previously included url:" << thisURL; |
| 896 | } | 922 | } |
| 897 | } | 923 | } |
| 898 | 924 | ||
| 899 | BatchLoader* loader = new BatchLoader(urls); | 925 | BatchLoader* loader = new BatchLoader(urls); |
| 900 | EntityItemID capturedEntityIdentifier = currentEntityIdentifier; | 926 | EntityItemID capturedEntityIdentifier = currentEntityIdentifier; |
| 927 | QUrl capturedSandboxURL = currentSandboxURL; | ||
| 901 | 928 | ||
| 902 | auto evaluateScripts = [=](const QMap<QUrl, QString>& data) { | 929 | auto evaluateScripts = [=](const QMap<QUrl, QString>& data) { |
| 903 | auto parentURL = _parentURL; | 930 | auto parentURL = _parentURL; |
| @@ -912,13 +939,13 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac · 8 unmodified lines | |||
| 912 | auto operation = [&]() { | 939 | auto operation = [&]() { |
| 913 | evaluate(contents, url.toString()); | 940 | evaluate(contents, url.toString()); |
| 914 | }; | 941 | }; |
| 915 | doWithEnvironment(capturedEntityIdentifier, operation); | 942 | doWithEnvironment(capturedEntityIdentifier, capturedSandboxURL, operation); |
| 916 | } | 943 | } |
| 917 | } | 944 | } |
| 918 | _parentURL = parentURL; | 945 | _parentURL = parentURL; |
| 919 | 946 | ||
| 920 | if (callback.isFunction()) { | 947 | if (callback.isFunction()) { |
| 921 | callWithEnvironment(capturedEntityIdentifier, QScriptValue(callback), QScriptValue(), QScriptValueList()); | 948 | callWithEnvironment(capturedEntityIdentifier, capturedSandboxURL, QScriptValue(callback), QScriptValue(), QScriptValueList()); |
| 922 | } | 949 | } |
| 923 | 950 | ||
| 924 | loader->deleteLater(); | 951 | loader->deleteLater(); |
| @@ -996,10 +1023,11 @@ void ScriptEngine::forwardHandlerCall(const EntityItemID& entityID, const QStrin · 71 unmodified lines | |||
| 996 | CallbackList handlersForEvent = handlersOnEntity[eventName]; | 1023 | CallbackList handlersForEvent = handlersOnEntity[eventName]; |
| 997 | if (!handlersForEvent.isEmpty()) { | 1024 | if (!handlersForEvent.isEmpty()) { |
| 998 | for (int i = 0; i < handlersForEvent.count(); ++i) { | 1025 | for (int i = 0; i < handlersForEvent.count(); ++i) { |
| 999 | // handlersForEvent[i] can tonain many handlers that may have each been added by different interface or entity scripts, | 1026 | // handlersForEvent[i] can contain many handlers that may have each been added by different interface or entity scripts, |
| 1000 | // and the entity scripts may be for entities other than the one this is a handler for. | 1027 | // and the entity scripts may be for entities other than the one this is a handler for. |
| 1001 | // Fortunately, the definingEntityIdentifier captured the entity script id (if any) when the handler was added. | 1028 | // Fortunately, the definingEntityIdentifier captured the entity script id (if any) when the handler was added. |
| 1002 | callWithEnvironment(handlersForEvent[i].definingEntityIdentifier, handlersForEvent[i].function, QScriptValue(), eventHandlerArgs); | 1029 | CallbackData& handler = handlersForEvent[i]; |
| 1030 | callWithEnvironment(handler.definingEntityIdentifier, handler.definingSandboxURL, handler.function, QScriptValue(), eventHandlerArgs); | ||
| 1003 | } | 1031 | } |
| 1004 | } | 1032 | } |
| 1005 | } | 1033 | } |
| @@ -1106,13 +1134,14 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 100 unmodified lines | |||
| 1106 | lastModified = (quint64)QFileInfo(file).lastModified().toMSecsSinceEpoch(); | 1134 | lastModified = (quint64)QFileInfo(file).lastModified().toMSecsSinceEpoch(); |
| 1107 | } | 1135 | } |
| 1108 | QScriptValue entityScriptConstructor, entityScriptObject; | 1136 | QScriptValue entityScriptConstructor, entityScriptObject; |
| 1137 | QUrl sandboxURL = currentSandboxURL.isEmpty() ? scriptOrURL : currentSandboxURL; | ||
| 1109 | auto initialization = [&]{ | 1138 | auto initialization = [&]{ |
| 1110 | entityScriptConstructor = evaluate(contents, fileName); | 1139 | entityScriptConstructor = evaluate(contents, fileName); |
| 1111 | entityScriptObject = entityScriptConstructor.construct(); | 1140 | entityScriptObject = entityScriptConstructor.construct(); |
| 1112 | }; | 1141 | }; |
| 1113 | doWithEnvironment(entityID, initialization); | 1142 | doWithEnvironment(entityID, sandboxURL, initialization); |
| 1114 | 1143 | ||
| 1115 | EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject, lastModified }; | 1144 | EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject, lastModified, sandboxURL }; |
| 1116 | _entityScripts[entityID] = newDetails; | 1145 | _entityScripts[entityID] = newDetails; |
| 1117 | if (isURL) { | 1146 | if (isURL) { |
| 1118 | setParentURL(""); | 1147 | setParentURL(""); |
| @@ -1201,9 +1230,11 @@ void ScriptEngine::refreshFileScript(const EntityItemID& entityID) { · 82 unmodified lines | |||
| 1201 | // Even if entityID is supplied as currentEntityIdentifier, this still documents the source | 1230 | // Even if entityID is supplied as currentEntityIdentifier, this still documents the source |
| 1202 | // of the code being executed (e.g., if we ever sandbox different entity scripts, or provide different | 1231 | // of the code being executed (e.g., if we ever sandbox different entity scripts, or provide different |
| 1203 | // global values for different entity scripts). | 1232 | // global values for different entity scripts). |
| 1204 | void ScriptEngine::doWithEnvironment(const EntityItemID& entityID, std::function<void()> operation) { | 1233 | void ScriptEngine::doWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, std::function<void()> operation) { |
| 1205 | EntityItemID oldIdentifier = currentEntityIdentifier; | 1234 | EntityItemID oldIdentifier = currentEntityIdentifier; |
| 1235 | QUrl oldSandboxURL = currentSandboxURL; | ||
| 1206 | currentEntityIdentifier = entityID; | 1236 | currentEntityIdentifier = entityID; |
| 1237 | currentSandboxURL = sandboxURL; | ||
| 1207 | 1238 | ||
| 1208 | #if DEBUG_CURRENT_ENTITY | 1239 | #if DEBUG_CURRENT_ENTITY |
| 1209 | QScriptValue oldData = this->globalObject().property("debugEntityID"); | 1240 | QScriptValue oldData = this->globalObject().property("debugEntityID"); |
| @@ -1215,12 +1246,13 @@ void ScriptEngine::doWithEnvironment(const EntityItemID& entityID, std::function · 5 unmodified lines | |||
| 1215 | #endif | 1246 | #endif |
| 1216 | 1247 | ||
| 1217 | currentEntityIdentifier = oldIdentifier; | 1248 | currentEntityIdentifier = oldIdentifier; |
| 1249 | currentSandboxURL = oldSandboxURL; | ||
| 1218 | } | 1250 | } |
| 1219 | void ScriptEngine::callWithEnvironment(const EntityItemID& entityID, QScriptValue function, QScriptValue thisObject, QScriptValueList args) { | 1251 | void ScriptEngine::callWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, QScriptValue function, QScriptValue thisObject, QScriptValueList args) { |
| 1220 | auto operation = [&]() { | 1252 | auto operation = [&]() { |
| 1221 | function.call(thisObject, args); | 1253 | function.call(thisObject, args); |
| 1222 | }; | 1254 | }; |
| 1223 | doWithEnvironment(entityID, operation); | 1255 | doWithEnvironment(entityID, sandboxURL, operation); |
| 1224 | } | 1256 | } |
| 1225 | 1257 | ||
| 1226 | void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const QStringList& params) { | 1258 | void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const QStringList& params) { |
| @@ -1249,7 +1281,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 22 unmodified lines | |||
| 1249 | QScriptValueList args; | 1281 | QScriptValueList args; |
| 1250 | args << entityID.toScriptValue(this); | 1282 | args << entityID.toScriptValue(this); |
| 1251 | args << qScriptValueFromSequence(this, params); | 1283 | args << qScriptValueFromSequence(this, params); |
| 1252 | callWithEnvironment(entityID, entityScript.property(methodName), entityScript, args); | 1284 | callWithEnvironment(entityID, details.definingSandboxURL, entityScript.property(methodName), entityScript, args); |
| 1253 | } | 1285 | } |
| 1254 | 1286 | ||
| 1255 | } | 1287 | } |
| @@ -1281,7 +1313,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 25 unmodified lines | |||
| 1281 | QScriptValueList args; | 1313 | QScriptValueList args; |
| 1282 | args << entityID.toScriptValue(this); | 1314 | args << entityID.toScriptValue(this); |
| 1283 | args << event.toScriptValue(this); | 1315 | args << event.toScriptValue(this); |
| 1284 | callWithEnvironment(entityID, entityScript.property(methodName), entityScript, args); | 1316 | callWithEnvironment(entityID, details.definingSandboxURL, entityScript.property(methodName), entityScript, args); |
| 1285 | } | 1317 | } |
| 1286 | } | 1318 | } |
| 1287 | } | 1319 | } |
| @@ -1315,7 +1347,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 27 unmodified lines | |||
| 1315 | args << entityID.toScriptValue(this); | 1347 | args << entityID.toScriptValue(this); |
| 1316 | args << otherID.toScriptValue(this); | 1348 | args << otherID.toScriptValue(this); |
| 1317 | args << collisionToScriptValue(this, collision); | 1349 | args << collisionToScriptValue(this, collision); |
| 1318 | callWithEnvironment(entityID, entityScript.property(methodName), entityScript, args); | 1350 | callWithEnvironment(entityID, details.definingSandboxURL, entityScript.property(methodName), entityScript, args); |
| 1319 | } | 1351 | } |
| 1320 | } | 1352 | } |
| 1321 | } | 1353 | } |