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 | 63 | static const bool HIFI_AUTOREFRESH_FILE_SCRIPTS { true }; |
| 64 | 64 | |
| 65 | +Q_DECLARE_METATYPE(ScriptValuePointer); | |
| 66 | + | |
| 65 | 67 | Q_DECLARE_METATYPE(QScriptEngine::FunctionSignature) |
| 66 | 68 | int qfunctionSignatureMetaID = qRegisterMetaType<QScriptEngine::FunctionSignature>(); |
| 67 | 69 | |
| 68 | 70 | int scriptEnginePointerMetaID = qRegisterMetaType<ScriptEngineQtScriptPointer>(); |
| 69 | 71 | |
| 70 | 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 | 75 | return true; |
| 73 | 76 | } |
| 74 | 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 | 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 | 395 | ScriptEngineQtScript::ScriptEngineQtScript(ScriptManager* scriptManager) : |
| 384 | 396 | QScriptEngine(), |
| 385 | 397 | _manager(scriptManager), |
| 386 | 398 | _arrayBufferClass(new ArrayBufferClass(this)) |
| 387 | 399 | { |
| 400 | + qScriptRegisterMetaType(this, ScriptValueToQScriptValue, ScriptValueFromQScriptValue); | |
| 401 | + | |
| 388 | 402 | if (_manager) { |
| 389 | 403 | connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) { |
| 390 | 404 | if (hasUncaughtException()) { |
| @@ -397,6 +411,7 @@ ScriptEngineQtScript::ScriptEngineQtScript(ScriptManager* scriptManager) : · 6 unmodified lines | ||
| 397 | 411 | emit _manager->unhandledException(ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(thrown)))); |
| 398 | 412 | } |
| 399 | 413 | }, Qt::DirectConnection); |
| 414 | + moveToThread(scriptManager->thread()); | |
| 400 | 415 | } |
| 401 | 416 | |
| 402 | 417 | QScriptValue null = QScriptEngine::nullValue(); |
| @@ -993,6 +1008,10 @@ QThread* ScriptEngineQtScript::thread() const { · 590 unmodified lines | ||
| 993 | 1008 | return QScriptEngine::thread(); |
| 994 | 1009 | } |
| 995 | 1010 | |
| 1011 | +void ScriptEngineQtScript::setThread(QThread* thread) { | |
| 1012 | + moveToThread(thread); | |
| 1013 | +} | |
| 1014 | + | |
| 996 | 1015 | ScriptValuePointer ScriptEngineQtScript::uncaughtException() const { |
| 997 | 1016 | QScriptValue result = QScriptEngine::uncaughtException(); |
| 998 | 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 | 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 | 1035 | QScriptValue result = qScriptValueFromValue_helper(this, type, ptr); |
| 1038 | 1036 | return ScriptValuePointer(new ScriptValueQtWrapper(const_cast<ScriptEngineQtScript*>(this), std::move(result))); |
| 1039 | 1037 | } |
| 1040 | 1038 | |
| 1041 | 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 | 1040 | ScriptValueQtWrapper* unwrapped = ScriptValueQtWrapper::unwrap(value); |
| 1058 | 1041 | if (unwrapped == nullptr) { |
| 1059 | 1042 | return false; |
| @@ -1061,22 +1044,100 @@ bool ScriptEngineQtScript::convert(const ScriptValuePointer& value, int type, vo · 1 unmodified line | ||
| 1061 | 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 | 1094 | void ScriptEngineQtScript::registerCustomType(int type, |
| 1065 | 1095 | ScriptEngine::MarshalFunction marshalFunc, |
| 1066 | 1096 | ScriptEngine::DemarshalFunction demarshalFunc, |
| 1067 | 1097 | const ScriptValuePointer& prototype) |
| 1068 | 1098 | { |
| 1069 | − ScriptValueQtWrapper* unwrapped = ScriptValueQtWrapper::unwrap(prototype); | |
| 1070 | − if (unwrapped == nullptr) { | |
| 1099 | + QScriptValue unwrapped = ScriptValueQtWrapper::fullUnwrap(this, prototype); | |
| 1100 | + QScriptEngine::MarshalFunction internalMarshalFunc; | |
| 1101 | + QScriptEngine::DemarshalFunction internalDemarshalFunc; | |
| 1102 | + | |
| 1103 | + if (_nextCustomType >= 300) { // have we ran out of translators? | |
| 1104 | + Q_ASSERT(false); | |
| 1071 | 1105 | return; |
| 1072 | 1106 | } |
| 1073 | 1107 | |
| 1074 | − std::lock_guard<std::mutex> guard(_customTypeProtect); | |
| 1075 | − TCustomTypeMap::iterator loc = _customTypes.find(type); | |
| 1076 | − if(loc == _customTypes.end()) { | |
| 1077 | − _customTypes.insert(TCustomTypeMap::value_type(type, CustomTypeInfo())).first; | |
| 1078 | − } | |
| 1079 | − CustomTypeInfo& typeInfo = loc->second; | |
| 1080 | − typeInfo.marshalFunc = marshalFunc; | |
| 1081 | − typeInfo.demarshalFunc = demarshalFunc; | |
| 1108 | + switch (_nextCustomType++) { | |
| 1109 | + CUSTOM_TYPE_ENTRY_10(0); | |
| 1110 | + CUSTOM_TYPE_ENTRY_10(1); | |
| 1111 | + CUSTOM_TYPE_ENTRY_10(2); | |
| 1112 | + CUSTOM_TYPE_ENTRY_10(3); | |
| 1113 | + CUSTOM_TYPE_ENTRY_10(4); | |
| 1114 | + CUSTOM_TYPE_ENTRY_10(5); | |
| 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 | } |