Showing the changes to libraries/script-engine/src/qtscript/ScriptEngineQtScript.cpp (1 of 14 files). Show all
Unified · Split
| @@ -62,13 +62,16 @@ static const QScriptValue::PropertyFlags READONLY_HIDDEN_PROP_FLAGS { READONLY_P · 61 unmodified lines | |||
| 62 | 62 | ||
| 63 | static const bool HIFI_AUTOREFRESH_FILE_SCRIPTS { true }; | 63 | static const bool HIFI_AUTOREFRESH_FILE_SCRIPTS { true }; |
| 64 | 64 | ||
| 65 | Q_DECLARE_METATYPE(ScriptValuePointer); | ||
| 66 | |||
| 65 | Q_DECLARE_METATYPE(QScriptEngine::FunctionSignature) | 67 | Q_DECLARE_METATYPE(QScriptEngine::FunctionSignature) |
| 66 | int qfunctionSignatureMetaID = qRegisterMetaType<QScriptEngine::FunctionSignature>(); | 68 | int qfunctionSignatureMetaID = qRegisterMetaType<QScriptEngine::FunctionSignature>(); |
| 67 | 69 | ||
| 68 | int scriptEnginePointerMetaID = qRegisterMetaType<ScriptEngineQtScriptPointer>(); | 70 | int scriptEnginePointerMetaID = qRegisterMetaType<ScriptEngineQtScriptPointer>(); |
| 69 | 71 | ||
| 70 | bool ScriptEngineQtScript::IS_THREADSAFE_INVOCATION(const QThread* thread, const QString& method) { | 72 | bool ScriptEngineQtScript::IS_THREADSAFE_INVOCATION(const QThread* thread, const QString& method) { |
| 71 | if (QThread::currentThread() == thread) { | 73 | const QThread* currentThread = QThread::currentThread(); |
| 74 | if (currentThread == thread) { | ||
| 72 | return true; | 75 | return true; |
| 73 | } | 76 | } |
| 74 | qCCritical(scriptengine) << QString("Scripting::%1 @ %2 -- ignoring thread-unsafe call from %3") | 77 | qCCritical(scriptengine) << QString("Scripting::%1 @ %2 -- ignoring thread-unsafe call from %3") |
| @@ -380,11 +383,22 @@ static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine) { · 305 unmodified lines | |||
| 380 | return QScriptValue(); | 383 | return QScriptValue(); |
| 381 | } | 384 | } |
| 382 | 385 | ||
| 386 | static QScriptValue ScriptValueToQScriptValue(QScriptEngine* engine, const ScriptValuePointer& src) { | ||
| 387 | return ScriptValueQtWrapper::fullUnwrap(static_cast<ScriptEngineQtScript*>(engine), src); | ||
| 388 | } | ||
| 389 | |||
| 390 | static void ScriptValueFromQScriptValue(const QScriptValue& src, ScriptValuePointer& dest) { | ||
| 391 | ScriptEngineQtScript* engine = static_cast<ScriptEngineQtScript*>(src.engine()); | ||
| 392 | dest = ScriptValuePointer(new ScriptValueQtWrapper(engine, src)); | ||
| 393 | } | ||
| 394 | |||
| 383 | ScriptEngineQtScript::ScriptEngineQtScript(ScriptManager* scriptManager) : | 395 | ScriptEngineQtScript::ScriptEngineQtScript(ScriptManager* scriptManager) : |
| 384 | QScriptEngine(), | 396 | QScriptEngine(), |
| 385 | _manager(scriptManager), | 397 | _manager(scriptManager), |
| 386 | _arrayBufferClass(new ArrayBufferClass(this)) | 398 | _arrayBufferClass(new ArrayBufferClass(this)) |
| 387 | { | 399 | { |
| 400 | qScriptRegisterMetaType(this, ScriptValueToQScriptValue, ScriptValueFromQScriptValue); | ||
| 401 | |||
| 388 | if (_manager) { | 402 | if (_manager) { |
| 389 | connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) { | 403 | connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) { |
| 390 | if (hasUncaughtException()) { | 404 | if (hasUncaughtException()) { |
| @@ -397,6 +411,7 @@ ScriptEngineQtScript::ScriptEngineQtScript(ScriptManager* scriptManager) : · 6 unmodified lines | |||
| 397 | emit _manager->unhandledException(ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(thrown)))); | 411 | emit _manager->unhandledException(ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(thrown)))); |
| 398 | } | 412 | } |
| 399 | }, Qt::DirectConnection); | 413 | }, Qt::DirectConnection); |
| 414 | moveToThread(scriptManager->thread()); | ||
| 400 | } | 415 | } |
| 401 | 416 | ||
| 402 | QScriptValue null = QScriptEngine::nullValue(); | 417 | QScriptValue null = QScriptEngine::nullValue(); |
| @@ -993,6 +1008,10 @@ QThread* ScriptEngineQtScript::thread() const { · 590 unmodified lines | |||
| 993 | return QScriptEngine::thread(); | 1008 | return QScriptEngine::thread(); |
| 994 | } | 1009 | } |
| 995 | 1010 | ||
| 1011 | void ScriptEngineQtScript::setThread(QThread* thread) { | ||
| 1012 | moveToThread(thread); | ||
| 1013 | } | ||
| 1014 | |||
| 996 | ScriptValuePointer ScriptEngineQtScript::uncaughtException() const { | 1015 | ScriptValuePointer ScriptEngineQtScript::uncaughtException() const { |
| 997 | QScriptValue result = QScriptEngine::uncaughtException(); | 1016 | QScriptValue result = QScriptEngine::uncaughtException(); |
| 998 | return ScriptValuePointer(new ScriptValueQtWrapper(const_cast<ScriptEngineQtScript*>(this), std::move(result))); | 1017 | return ScriptValuePointer(new ScriptValueQtWrapper(const_cast<ScriptEngineQtScript*>(this), std::move(result))); |
| @@ -1013,47 +1032,11 @@ bool ScriptEngineQtScript::raiseException(const ScriptValuePointer& exception) { · 14 unmodified lines | |||
| 1013 | } | 1032 | } |
| 1014 | 1033 | ||
| 1015 | ScriptValuePointer ScriptEngineQtScript::create(int type, const void* ptr) { | 1034 | ScriptValuePointer ScriptEngineQtScript::create(int type, const void* ptr) { |
| 1016 | // first we'll try custom types registered with us | ||
| 1017 | ScriptEngine::MarshalFunction marshalFunc = nullptr; | ||
| 1018 | ScriptValuePointer prototype; | ||
| 1019 | { | ||
| 1020 | std::lock_guard<std::mutex> guard(_customTypeProtect); | ||
| 1021 | TCustomTypeMap::const_iterator loc = _customTypes.find(type); | ||
| 1022 | if (loc != _customTypes.end()) { | ||
| 1023 | const CustomTypeInfo& typeInfo = loc->second; | ||
| 1024 | marshalFunc = typeInfo.marshalFunc; | ||
| 1025 | prototype = typeInfo.prototype; | ||
| 1026 | } | ||
| 1027 | } | ||
| 1028 | if (marshalFunc) { | ||
| 1029 | ScriptValuePointer result = marshalFunc(this, ptr); | ||
| 1030 | if (result && prototype) { | ||
| 1031 | result->setPrototype(prototype); | ||
| 1032 | } | ||
| 1033 | return result; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | // falling back to having QtScript handle it | ||
| 1037 | QScriptValue result = qScriptValueFromValue_helper(this, type, ptr); | 1035 | QScriptValue result = qScriptValueFromValue_helper(this, type, ptr); |
| 1038 | return ScriptValuePointer(new ScriptValueQtWrapper(const_cast<ScriptEngineQtScript*>(this), std::move(result))); | 1036 | return ScriptValuePointer(new ScriptValueQtWrapper(const_cast<ScriptEngineQtScript*>(this), std::move(result))); |
| 1039 | } | 1037 | } |
| 1040 | 1038 | ||
| 1041 | bool ScriptEngineQtScript::convert(const ScriptValuePointer& value, int type, void* ptr) { | 1039 | bool ScriptEngineQtScript::convert(const ScriptValuePointer& value, int type, void* ptr) { |
| 1042 | // first we'll try custom types registered with us | ||
| 1043 | ScriptEngine::DemarshalFunction demarshalFunc = nullptr; | ||
| 1044 | { | ||
| 1045 | std::lock_guard<std::mutex> guard(_customTypeProtect); | ||
| 1046 | TCustomTypeMap::const_iterator loc = _customTypes.find(type); | ||
| 1047 | if (loc != _customTypes.end()) { | ||
| 1048 | demarshalFunc = loc->second.demarshalFunc; | ||
| 1049 | } | ||
| 1050 | } | ||
| 1051 | if (demarshalFunc) { | ||
| 1052 | demarshalFunc(value, ptr); | ||
| 1053 | return true; | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | // falling back to having QtScript handle it | ||
| 1057 | ScriptValueQtWrapper* unwrapped = ScriptValueQtWrapper::unwrap(value); | 1040 | ScriptValueQtWrapper* unwrapped = ScriptValueQtWrapper::unwrap(value); |
| 1058 | if (unwrapped == nullptr) { | 1041 | if (unwrapped == nullptr) { |
| 1059 | return false; | 1042 | return false; |
| @@ -1061,22 +1044,100 @@ bool ScriptEngineQtScript::convert(const ScriptValuePointer& value, int type, vo · 1 unmodified line | |||
| 1061 | return qscriptvalue_cast_helper(unwrapped->toQtValue(), type, ptr); | 1044 | return qscriptvalue_cast_helper(unwrapped->toQtValue(), type, ptr); |
| 1062 | } | 1045 | } |
| 1063 | 1046 | ||
| 1047 | template <int i> | ||
| 1048 | class CustomTypeInstance { | ||
| 1049 | public: | ||
| 1050 | static ScriptEngine::MarshalFunction marshalFunc; | ||
| 1051 | static ScriptEngine::DemarshalFunction demarshalFunc; | ||
| 1052 | |||
| 1053 | static QScriptValue internalMarshalFunc(QScriptEngine* engine, const void* src) { | ||
| 1054 | ScriptEngineQtScript* unwrappedEngine = static_cast<ScriptEngineQtScript*>(engine); | ||
| 1055 | ScriptValuePointer dest = marshalFunc(unwrappedEngine, src); | ||
| 1056 | return ScriptValueQtWrapper::fullUnwrap(unwrappedEngine, dest); | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | static void internalDemarshalFunc(const QScriptValue& src, void* dest) { | ||
| 1060 | ScriptEngineQtScript* unwrappedEngine = static_cast<ScriptEngineQtScript*>(src.engine()); | ||
| 1061 | ScriptValuePointer wrappedSrc(new ScriptValueQtWrapper(unwrappedEngine, src)); | ||
| 1062 | demarshalFunc(wrappedSrc, dest); | ||
| 1063 | } | ||
| 1064 | }; | ||
| 1065 | template <int i> | ||
| 1066 | ScriptEngine::MarshalFunction CustomTypeInstance<i>::marshalFunc; | ||
| 1067 | template <int i> | ||
| 1068 | ScriptEngine::DemarshalFunction CustomTypeInstance<i>::demarshalFunc; | ||
| 1069 | |||
| 1070 | // I would *LOVE* it if there was a different way to do this, jeez! | ||
| 1071 | // Qt requires two functions that have no parameters that give any context, | ||
| 1072 | // one of the must return a QScriptValue (so we can't void* them into generics and stick them in the templates). | ||
| 1073 | // This *has* to be done via templates but the whole point of this is to avoid leaking types into the rest of | ||
| 1074 | // the system that would require anyone other than us to have a dependency on QtScript | ||
| 1075 | #define CUSTOM_TYPE_ENTRY(idx) \ | ||
| 1076 | case idx: \ | ||
| 1077 | CustomTypeInstance<idx>::marshalFunc = marshalFunc; \ | ||
| 1078 | CustomTypeInstance<idx>::demarshalFunc = demarshalFunc; \ | ||
| 1079 | internalMarshalFunc = CustomTypeInstance<idx>::internalMarshalFunc; \ | ||
| 1080 | internalDemarshalFunc = CustomTypeInstance<idx>::internalDemarshalFunc; \ | ||
| 1081 | break; | ||
| 1082 | #define CUSTOM_TYPE_ENTRY_10(idx) \ | ||
| 1083 | CUSTOM_TYPE_ENTRY((idx * 10)); \ | ||
| 1084 | CUSTOM_TYPE_ENTRY((idx * 10) + 1); \ | ||
| 1085 | CUSTOM_TYPE_ENTRY((idx * 10) + 2); \ | ||
| 1086 | CUSTOM_TYPE_ENTRY((idx * 10) + 3); \ | ||
| 1087 | CUSTOM_TYPE_ENTRY((idx * 10) + 4); \ | ||
| 1088 | CUSTOM_TYPE_ENTRY((idx * 10) + 5); \ | ||
| 1089 | CUSTOM_TYPE_ENTRY((idx * 10) + 6); \ | ||
| 1090 | CUSTOM_TYPE_ENTRY((idx * 10) + 7); \ | ||
| 1091 | CUSTOM_TYPE_ENTRY((idx * 10) + 8); \ | ||
| 1092 | CUSTOM_TYPE_ENTRY((idx * 10) + 9); | ||
| 1093 | |||
| 1064 | void ScriptEngineQtScript::registerCustomType(int type, | 1094 | void ScriptEngineQtScript::registerCustomType(int type, |
| 1065 | ScriptEngine::MarshalFunction marshalFunc, | 1095 | ScriptEngine::MarshalFunction marshalFunc, |
| 1066 | ScriptEngine::DemarshalFunction demarshalFunc, | 1096 | ScriptEngine::DemarshalFunction demarshalFunc, |
| 1067 | const ScriptValuePointer& prototype) | 1097 | const ScriptValuePointer& prototype) |
| 1068 | { | 1098 | { |
| 1069 | ScriptValueQtWrapper* unwrapped = ScriptValueQtWrapper::unwrap(prototype); | 1099 | QScriptValue unwrapped = ScriptValueQtWrapper::fullUnwrap(this, prototype); |
| 1070 | if (unwrapped == nullptr) { | 1100 | QScriptEngine::MarshalFunction internalMarshalFunc; |
| 1101 | QScriptEngine::DemarshalFunction internalDemarshalFunc; | ||
| 1102 | |||
| 1103 | if (_nextCustomType >= 300) { // have we ran out of translators? | ||
| 1104 | Q_ASSERT(false); | ||
| 1071 | return; | 1105 | return; |
| 1072 | } | 1106 | } |
| 1073 | 1107 | ||
| 1074 | std::lock_guard<std::mutex> guard(_customTypeProtect); | 1108 | switch (_nextCustomType++) { |
| 1075 | TCustomTypeMap::iterator loc = _customTypes.find(type); | 1109 | CUSTOM_TYPE_ENTRY_10(0); |
| 1076 | if(loc == _customTypes.end()) { | 1110 | CUSTOM_TYPE_ENTRY_10(1); |
| 1077 | _customTypes.insert(TCustomTypeMap::value_type(type, CustomTypeInfo())).first; | 1111 | CUSTOM_TYPE_ENTRY_10(2); |
| 1078 | } | 1112 | CUSTOM_TYPE_ENTRY_10(3); |
| 1079 | CustomTypeInfo& typeInfo = loc->second; | 1113 | CUSTOM_TYPE_ENTRY_10(4); |
| 1080 | typeInfo.marshalFunc = marshalFunc; | 1114 | CUSTOM_TYPE_ENTRY_10(5); |
| 1081 | typeInfo.demarshalFunc = demarshalFunc; | 1115 | CUSTOM_TYPE_ENTRY_10(6); |
| 1116 | CUSTOM_TYPE_ENTRY_10(7); | ||
| 1117 | CUSTOM_TYPE_ENTRY_10(8); | ||
| 1118 | CUSTOM_TYPE_ENTRY_10(9); | ||
| 1119 | CUSTOM_TYPE_ENTRY_10(10); | ||
| 1120 | CUSTOM_TYPE_ENTRY_10(11); | ||
| 1121 | CUSTOM_TYPE_ENTRY_10(12); | ||
| 1122 | CUSTOM_TYPE_ENTRY_10(13); | ||
| 1123 | CUSTOM_TYPE_ENTRY_10(14); | ||
| 1124 | CUSTOM_TYPE_ENTRY_10(15); | ||
| 1125 | CUSTOM_TYPE_ENTRY_10(16); | ||
| 1126 | CUSTOM_TYPE_ENTRY_10(17); | ||
| 1127 | CUSTOM_TYPE_ENTRY_10(18); | ||
| 1128 | CUSTOM_TYPE_ENTRY_10(19); | ||
| 1129 | CUSTOM_TYPE_ENTRY_10(20); | ||
| 1130 | CUSTOM_TYPE_ENTRY_10(21); | ||
| 1131 | CUSTOM_TYPE_ENTRY_10(22); | ||
| 1132 | CUSTOM_TYPE_ENTRY_10(23); | ||
| 1133 | CUSTOM_TYPE_ENTRY_10(24); | ||
| 1134 | CUSTOM_TYPE_ENTRY_10(25); | ||
| 1135 | CUSTOM_TYPE_ENTRY_10(26); | ||
| 1136 | CUSTOM_TYPE_ENTRY_10(27); | ||
| 1137 | CUSTOM_TYPE_ENTRY_10(28); | ||
| 1138 | CUSTOM_TYPE_ENTRY_10(29); | ||
| 1139 | CUSTOM_TYPE_ENTRY_10(30); | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | qScriptRegisterMetaType_helper(this, type, internalMarshalFunc, internalDemarshalFunc, unwrapped); | ||
| 1082 | } | 1143 | } |