Showing the changes to libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp (1 of 29 files). Show all
Unified · Split
| @@ -24,12 +24,7 @@ · 23 unmodified lines | |||
| 24 | #include "ScriptValueV8Wrapper.h" | 24 | #include "ScriptValueV8Wrapper.h" |
| 25 | #include "ScriptEngineLoggingV8.h" | 25 | #include "ScriptEngineLoggingV8.h" |
| 26 | 26 | ||
| 27 | //V8TODO: is this needed for anything? It could cause trouble with multithreading if V8ScriptContext is v8::Persistent | ||
| 28 | //Q_DECLARE_METATYPE(V8ScriptContext*) | ||
| 29 | |||
| 30 | Q_DECLARE_METATYPE(ScriptValue) | 27 | Q_DECLARE_METATYPE(ScriptValue) |
| 31 | //V8TODO: default constructor would be needed | ||
| 32 | //Q_DECLARE_METATYPE(V8ScriptValue) | ||
| 33 | 28 | ||
| 34 | Q_DECLARE_METATYPE(QSharedPointer<ScriptObjectV8Proxy>) | 29 | Q_DECLARE_METATYPE(QSharedPointer<ScriptObjectV8Proxy>) |
| 35 | Q_DECLARE_METATYPE(QSharedPointer<ScriptVariantV8Proxy>) | 30 | Q_DECLARE_METATYPE(QSharedPointer<ScriptVariantV8Proxy>) |
| @@ -76,7 +71,6 @@ private: // storage · 40 unmodified lines | |||
| 76 | 71 | ||
| 77 | ScriptObjectV8Proxy::ScriptObjectV8Proxy(ScriptEngineV8* engine, QObject* object, bool ownsObject, const ScriptEngine::QObjectWrapOptions& options) : | 72 | ScriptObjectV8Proxy::ScriptObjectV8Proxy(ScriptEngineV8* engine, QObject* object, bool ownsObject, const ScriptEngine::QObjectWrapOptions& options) : |
| 78 | _engine(engine), _wrapOptions(options), _ownsObject(ownsObject), _object(object) { | 73 | _engine(engine), _wrapOptions(options), _ownsObject(ownsObject), _object(object) { |
| 79 | //_v8ObjectTemplate(engine->getIsolate(), v8::ObjectTemplate::New(engine->getIsolate()) | ||
| 80 | Q_ASSERT(_engine != nullptr); | 74 | Q_ASSERT(_engine != nullptr); |
| 81 | investigate(); | 75 | investigate(); |
| 82 | } | 76 | } |
| @@ -90,11 +84,9 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o · 7 unmodified lines | |||
| 90 | ScriptEngineV8::ObjectWrapperMap::const_iterator lookup = engine->_qobjectWrapperMap.find(object); | 84 | ScriptEngineV8::ObjectWrapperMap::const_iterator lookup = engine->_qobjectWrapperMap.find(object); |
| 91 | if (lookup != engine->_qobjectWrapperMap.end()) { | 85 | if (lookup != engine->_qobjectWrapperMap.end()) { |
| 92 | QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock(); | 86 | QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock(); |
| 93 | // V8TODO: is conversion to QVariant and back needed? | ||
| 94 | if (proxy) { | 87 | if (proxy) { |
| 95 | return V8ScriptValue(engine, proxy.get()->toV8Value()); | 88 | return V8ScriptValue(engine, proxy.get()->toV8Value()); |
| 96 | } | 89 | } |
| 97 | //if (proxy) return engine->newObject(proxy.get(), engine->newVariant(QVariant::fromValue(proxy)));; | ||
| 98 | } | 90 | } |
| 99 | } | 91 | } |
| 100 | 92 | ||
| @@ -125,12 +117,10 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o · 24 unmodified lines | |||
| 125 | ScriptEngineV8::ObjectWrapperMap::const_iterator lookup = engine->_qobjectWrapperMap.find(object); | 117 | ScriptEngineV8::ObjectWrapperMap::const_iterator lookup = engine->_qobjectWrapperMap.find(object); |
| 126 | if (lookup != engine->_qobjectWrapperMap.end()) { | 118 | if (lookup != engine->_qobjectWrapperMap.end()) { |
| 127 | QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock(); | 119 | QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock(); |
| 128 | //if (proxy) return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));; | ||
| 129 | if (proxy) { | 120 | if (proxy) { |
| 130 | return V8ScriptValue(engine, proxy.get()->toV8Value()); | 121 | return V8ScriptValue(engine, proxy.get()->toV8Value()); |
| 131 | } | 122 | } |
| 132 | } | 123 | } |
| 133 | // V8TODO add a V8 callback that removes pointer for the script engine owned ob from the map so that it gets deleted | ||
| 134 | // register the wrapper with the engine and make sure it cleans itself up | 124 | // register the wrapper with the engine and make sure it cleans itself up |
| 135 | engine->_qobjectWrapperMap.insert(object, proxy); | 125 | engine->_qobjectWrapperMap.insert(object, proxy); |
| 136 | engine->_qobjectWrapperMapV8.insert(object, proxy); | 126 | engine->_qobjectWrapperMapV8.insert(object, proxy); |
| @@ -146,13 +136,10 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o · 9 unmodified lines | |||
| 146 | if (lookupV8 != enginePtr->_qobjectWrapperMapV8.end()) { | 136 | if (lookupV8 != enginePtr->_qobjectWrapperMapV8.end()) { |
| 147 | enginePtr->_qobjectWrapperMapV8.erase(lookupV8); | 137 | enginePtr->_qobjectWrapperMapV8.erase(lookupV8); |
| 148 | } | 138 | } |
| 149 | //qDebug() << "ScriptObjectV8Proxy::newQObject object deleted, object count: " << enginePtr->_qobjectWrapperMapV8.size(); | ||
| 150 | }); | 139 | }); |
| 151 | //qDebug() << "ScriptObjectV8Proxy::newQObject object count: " << engine->_qobjectWrapperMapV8.size(); | ||
| 152 | } | 140 | } |
| 153 | 141 | ||
| 154 | return V8ScriptValue(engine, proxy.get()->toV8Value()); | 142 | return V8ScriptValue(engine, proxy.get()->toV8Value()); |
| 155 | //return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy))); | ||
| 156 | } | 143 | } |
| 157 | 144 | ||
| 158 | ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val) { | 145 | ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val) { |
| @@ -162,20 +149,17 @@ ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val) · 3 unmodified lines | |||
| 162 | v8::HandleScope handleScope(isolate); | 149 | v8::HandleScope handleScope(isolate); |
| 163 | v8::Local<v8::Context> context = val.constGetContext(); | 150 | v8::Local<v8::Context> context = val.constGetContext(); |
| 164 | v8::Context::Scope contextScope(context); | 151 | v8::Context::Scope contextScope(context); |
| 165 | //V8TODO This shouldn't cause problems but I'm not sure if it's ok | ||
| 166 | //v8::HandleScope handleScope(const_cast<v8::Isolate*>(val.constGetIsolate())); | ||
| 167 | auto v8Value = val.constGet(); | 152 | auto v8Value = val.constGet(); |
| 168 | Q_ASSERT(!v8Value.IsEmpty()); | 153 | Q_ASSERT(!v8Value.IsEmpty()); |
| 154 | |||
| 169 | if (v8Value->IsNullOrUndefined()) { | 155 | if (v8Value->IsNullOrUndefined()) { |
| 170 | return nullptr; | 156 | return nullptr; |
| 171 | } | 157 | } |
| 172 | if (!v8Value->IsObject()) { | 158 | if (!v8Value->IsObject()) { |
| 173 | //qCDebug(scriptengine_v8) << "Cannot unwrap proxy - value is not an object"; | ||
| 174 | return nullptr; | 159 | return nullptr; |
| 175 | } | 160 | } |
| 176 | v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(v8Value); | 161 | v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(v8Value); |
| 177 | if (v8Object->InternalFieldCount() != 3) { | 162 | if (v8Object->InternalFieldCount() != 3) { |
| 178 | //qCDebug(scriptengine_v8) << "Cannot unwrap proxy - wrong number of internal fields"; | ||
| 179 | return nullptr; | 163 | return nullptr; |
| 180 | } | 164 | } |
| 181 | if (v8Object->GetAlignedPointerFromInternalField(0) != internalPointsToQObjectProxy) { | 165 | if (v8Object->GetAlignedPointerFromInternalField(0) != internalPointsToQObjectProxy) { |
| @@ -189,20 +173,16 @@ ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(v8::Isolate* isolate, v8:: · 7 unmodified lines | |||
| 189 | v8::Locker locker(isolate); | 173 | v8::Locker locker(isolate); |
| 190 | v8::Isolate::Scope isolateScope(isolate); | 174 | v8::Isolate::Scope isolateScope(isolate); |
| 191 | v8::HandleScope handleScope(isolate); | 175 | v8::HandleScope handleScope(isolate); |
| 192 | //V8TODO: shouldn't there be context scope here? | 176 | //V8TODO: should there be context scope here? |
| 193 | //v8::Local<v8::Context> context = val.constGetContext(); | 177 | |
| 194 | //v8::Context::Scope contextScope(context); | ||
| 195 | if (value->IsNullOrUndefined()) { | 178 | if (value->IsNullOrUndefined()) { |
| 196 | //qCDebug(scriptengine_v8) << "Cannot unwrap proxy - value is not an object"; | ||
| 197 | return nullptr; | 179 | return nullptr; |
| 198 | } | 180 | } |
| 199 | if (!value->IsObject()) { | 181 | if (!value->IsObject()) { |
| 200 | //qCDebug(scriptengine_v8) << "Cannot unwrap proxy - value is not an object"; | ||
| 201 | return nullptr; | 182 | return nullptr; |
| 202 | } | 183 | } |
| 203 | v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(value); | 184 | v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(value); |
| 204 | if (v8Object->InternalFieldCount() != 3) { | 185 | if (v8Object->InternalFieldCount() != 3) { |
| 205 | //qCDebug(scriptengine_v8) << "Cannot unwrap proxy - wrong number of internal fields"; | ||
| 206 | return nullptr; | 186 | return nullptr; |
| 207 | } | 187 | } |
| 208 | if (v8Object->GetAlignedPointerFromInternalField(0) != internalPointsToQObjectProxy) { | 188 | if (v8Object->GetAlignedPointerFromInternalField(0) != internalPointsToQObjectProxy) { |
| @@ -257,13 +237,8 @@ void ScriptObjectV8Proxy::investigate() { · 48 unmodified lines | |||
| 257 | 237 | ||
| 258 | const QMetaObject* metaObject = qobject->metaObject(); | 238 | const QMetaObject* metaObject = qobject->metaObject(); |
| 259 | 239 | ||
| 260 | //auto objectTemplate = _v8ObjectTemplate.Get(_engine->getIsolate()); | ||
| 261 | auto objectTemplate = _engine->getObjectProxyTemplate(); | 240 | auto objectTemplate = _engine->getObjectProxyTemplate(); |
| 262 | /*auto objectTemplate = v8::ObjectTemplate::New(_engine->getIsolate()); | ||
| 263 | objectTemplate->SetInternalFieldCount(3); | ||
| 264 | objectTemplate->SetHandler(v8::NamedPropertyHandlerConfiguration(v8Get, v8Set, nullptr, nullptr, v8GetPropertyNames));*/ | ||
| 265 | 241 | ||
| 266 | //qCDebug(scriptengine_v8) << "Investigate: " << metaObject->className(); | ||
| 267 | if (QString("ConsoleScriptingInterface") == metaObject->className()) { | 242 | if (QString("ConsoleScriptingInterface") == metaObject->className()) { |
| 268 | printf("ConsoleScriptingInterface"); | 243 | printf("ConsoleScriptingInterface"); |
| 269 | } | 244 | } |
| @@ -274,7 +249,6 @@ void ScriptObjectV8Proxy::investigate() { · 4 unmodified lines | |||
| 274 | QMetaProperty prop = metaObject->property(idx); | 249 | QMetaProperty prop = metaObject->property(idx); |
| 275 | if (!prop.isScriptable()) continue; | 250 | if (!prop.isScriptable()) continue; |
| 276 | 251 | ||
| 277 | //qCDebug(scriptengine_v8) << "Investigate: " << metaObject->className() << " Property: " << prop.name(); | ||
| 278 | // always exclude child objects (at least until we decide otherwise) | 252 | // always exclude child objects (at least until we decide otherwise) |
| 279 | int metaTypeId = prop.userType(); | 253 | int metaTypeId = prop.userType(); |
| 280 | if (metaTypeId != QMetaType::UnknownType) { | 254 | if (metaTypeId != QMetaType::UnknownType) { |
| @@ -284,7 +258,6 @@ void ScriptObjectV8Proxy::investigate() { · 3 unmodified lines | |||
| 284 | } | 258 | } |
| 285 | } | 259 | } |
| 286 | 260 | ||
| 287 | //auto v8Name = v8::String::NewFromUtf8(_engine->getIsolate(), prop.name()).ToLocalChecked(); | ||
| 288 | PropertyDef& propDef = _props.insert(idx, PropertyDef(prop.name(), idx)).value(); | 261 | PropertyDef& propDef = _props.insert(idx, PropertyDef(prop.name(), idx)).value(); |
| 289 | _propNameMap.insert(prop.name(), &propDef); | 262 | _propNameMap.insert(prop.name(), &propDef); |
| 290 | propDef.flags = ScriptValue::Undeletable | ScriptValue::PropertyGetter | ScriptValue::PropertySetter | | 263 | propDef.flags = ScriptValue::Undeletable | ScriptValue::PropertyGetter | ScriptValue::PropertySetter | |
| @@ -298,7 +271,6 @@ void ScriptObjectV8Proxy::investigate() { · 7 unmodified lines | |||
| 298 | QHash<QString, int> methodNames; | 271 | QHash<QString, int> methodNames; |
| 299 | for (int idx = startIdx; idx < num; ++idx) { | 272 | for (int idx = startIdx; idx < num; ++idx) { |
| 300 | QMetaMethod method = metaObject->method(idx); | 273 | QMetaMethod method = metaObject->method(idx); |
| 301 | //qCDebug(scriptengine_v8) << "Investigate: " << metaObject->className() << " Method: " << method.name(); | ||
| 302 | 274 | ||
| 303 | // perhaps keep this comment? Calls (like AudioScriptingInterface::playSound) seem to expect non-public methods to be script-accessible | 275 | // perhaps keep this comment? Calls (like AudioScriptingInterface::playSound) seem to expect non-public methods to be script-accessible |
| 304 | /* if (method.access() != QMetaMethod::Public) continue;*/ | 276 | /* if (method.access() != QMetaMethod::Public) continue;*/ |
| @@ -333,9 +305,6 @@ void ScriptObjectV8Proxy::investigate() { · 28 unmodified lines | |||
| 333 | signalDef.name = szName; | 305 | signalDef.name = szName; |
| 334 | signalDef.signal = method; | 306 | signalDef.signal = method; |
| 335 | _signalNameMap.insert(szName, &signalDef); | 307 | _signalNameMap.insert(szName, &signalDef); |
| 336 | //qCDebug(scriptengine_v8) << "Utf8Value 1: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), nameString)); | ||
| 337 | //qCDebug(scriptengine_v8) << "Utf8Value 2: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), name.constGet())); | ||
| 338 | //qCDebug(scriptengine_v8) << "toQString: " << name.toQString(); | ||
| 339 | methodNames.insert(szName, idx); | 308 | methodNames.insert(szName, idx); |
| 340 | } else { | 309 | } else { |
| 341 | int originalMethodId = nameLookup.value(); | 310 | int originalMethodId = nameLookup.value(); |
| @@ -376,10 +345,6 @@ void ScriptObjectV8Proxy::investigate() { · 34 unmodified lines | |||
| 376 | } | 345 | } |
| 377 | 346 | ||
| 378 | v8::Local<v8::Object> v8Object = objectTemplate->NewInstance(_engine->getContext()).ToLocalChecked(); | 347 | v8::Local<v8::Object> v8Object = objectTemplate->NewInstance(_engine->getContext()).ToLocalChecked(); |
| 379 | /*if (QString(metaObject->className()) == QString("TestQObject")) { | ||
| 380 | //qDebug() << "TestQObject investigate: _methods.size: " << _methods.size(); | ||
| 381 | return; | ||
| 382 | }*/ | ||
| 383 | 348 | ||
| 384 | v8Object->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQObjectProxy)); | 349 | v8Object->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQObjectProxy)); |
| 385 | v8Object->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(this)); | 350 | v8Object->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(this)); |
| @@ -406,9 +371,6 @@ void ScriptObjectV8Proxy::investigate() { · 20 unmodified lines | |||
| 406 | } | 371 | } |
| 407 | 372 | ||
| 408 | void ScriptObjectV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptObjectV8Proxy>& info) { | 373 | void ScriptObjectV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptObjectV8Proxy>& info) { |
| 409 | //V8TODO: does the object need to be moved to script engine thread? | ||
| 410 | //V8TODO: why does this never get called? | ||
| 411 | //qDebug(scriptengine_v8) << "ScriptObjectV8Proxy::weakHandleCallback"; | ||
| 412 | auto proxy = info.GetParameter(); | 374 | auto proxy = info.GetParameter(); |
| 413 | proxy->_v8Object.Reset(); | 375 | proxy->_v8Object.Reset(); |
| 414 | info.GetParameter()->_object->deleteLater(); | 376 | info.GetParameter()->_object->deleteLater(); |
| @@ -423,41 +385,24 @@ QString ScriptObjectV8Proxy::name() const { · 8 unmodified lines | |||
| 423 | return _object->metaObject()->className(); | 385 | return _object->metaObject()->className(); |
| 424 | } | 386 | } |
| 425 | 387 | ||
| 426 | // V8TODO: check if it would be more optimal to use V8ScriptString& name or QString name | ||
| 427 | ScriptObjectV8Proxy::QueryFlags ScriptObjectV8Proxy::queryProperty(const V8ScriptValue& object, const V8ScriptString& name, QueryFlags flags, uint* id) { | 388 | ScriptObjectV8Proxy::QueryFlags ScriptObjectV8Proxy::queryProperty(const V8ScriptValue& object, const V8ScriptString& name, QueryFlags flags, uint* id) { |
| 428 | auto isolate = _engine->getIsolate(); | 389 | auto isolate = _engine->getIsolate(); |
| 429 | v8::Locker locker(isolate); | 390 | v8::Locker locker(isolate); |
| 430 | v8::Isolate::Scope isolateScope(isolate); | 391 | v8::Isolate::Scope isolateScope(isolate); |
| 431 | v8::HandleScope handleScope(isolate); | 392 | v8::HandleScope handleScope(isolate); |
| 432 | // V8TODO: this might be inefficient when there's large number of properties | ||
| 433 | v8::Local<v8::Context> context = _engine->getContext(); | 393 | v8::Local<v8::Context> context = _engine->getContext(); |
| 434 | v8::Context::Scope contextScope(context); | 394 | v8::Context::Scope contextScope(context); |
| 435 | QString nameStr(*v8::String::Utf8Value(isolate, name.constGet())); | 395 | QString nameStr(*v8::String::Utf8Value(isolate, name.constGet())); |
| 436 | 396 | ||
| 437 | // check for methods | 397 | // check for methods |
| 438 | /*for (MethodDefMap::const_iterator trans = _methods.cbegin(); trans != _methods.cend(); ++trans) { | ||
| 439 | v8::String::Utf8Value methodNameStr(isolate, trans.value().name.constGet()); | ||
| 440 | //qCDebug(scriptengine_v8) << "queryProperty : " << *nameStr << " method: " << *methodNameStr; | ||
| 441 | if (!(trans.value().name == name)) continue; | ||
| 442 | *id = trans.key() | METHOD_TYPE; | ||
| 443 | return flags & (HandlesReadAccess | HandlesWriteAccess); | ||
| 444 | }*/ | ||
| 445 | MethodNameMap::const_iterator method = _methodNameMap.find(nameStr); | 398 | MethodNameMap::const_iterator method = _methodNameMap.find(nameStr); |
| 446 | if (method != _methodNameMap.cend()) { | 399 | if (method != _methodNameMap.cend()) { |
| 447 | //v8::String::Utf8Value methodNameStr(isolate, trans.value().name.constGet()); | ||
| 448 | //qCDebug(scriptengine_v8) << "queryProperty : " << *nameStr << " method: " << *methodNameStr; | ||
| 449 | const MethodDef* methodDef = method.value(); | 400 | const MethodDef* methodDef = method.value(); |
| 450 | *id = methodDef->_id | METHOD_TYPE; | 401 | *id = methodDef->_id | METHOD_TYPE; |
| 451 | return flags & (HandlesReadAccess | HandlesWriteAccess); | 402 | return flags & (HandlesReadAccess | HandlesWriteAccess); |
| 452 | } | 403 | } |
| 453 | 404 | ||
| 454 | // check for properties | 405 | // check for properties |
| 455 | /*for (PropertyDefMap::const_iterator trans = _props.cbegin(); trans != _props.cend(); ++trans) { | ||
| 456 | const PropertyDef& propDef = trans.value(); | ||
| 457 | if (!(propDef.name == name)) continue; | ||
| 458 | *id = trans.key() | PROPERTY_TYPE; | ||
| 459 | return flags & (HandlesReadAccess | HandlesWriteAccess); | ||
| 460 | }*/ | ||
| 461 | PropertyNameMap::const_iterator prop = _propNameMap.find(nameStr); | 406 | PropertyNameMap::const_iterator prop = _propNameMap.find(nameStr); |
| 462 | if (prop != _propNameMap.cend()) { | 407 | if (prop != _propNameMap.cend()) { |
| 463 | const PropertyDef* propDef = prop.value(); | 408 | const PropertyDef* propDef = prop.value(); |
| @@ -505,9 +450,7 @@ ScriptValue::PropertyFlags ScriptObjectV8Proxy::propertyFlags(const V8ScriptValu · 41 unmodified lines | |||
| 505 | 450 | ||
| 506 | void ScriptObjectV8Proxy::v8Get(v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { | 451 | void ScriptObjectV8Proxy::v8Get(v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 507 | v8::HandleScope handleScope(info.GetIsolate()); | 452 | v8::HandleScope handleScope(info.GetIsolate()); |
| 508 | //V8TODO: should there be a context scope here? | ||
| 509 | v8::String::Utf8Value utf8Value(info.GetIsolate(), name); | 453 | v8::String::Utf8Value utf8Value(info.GetIsolate(), name); |
| 510 | //qCDebug(scriptengine_v8) << "Get: " << *utf8Value; | ||
| 511 | v8::Local<v8::Value> objectV8 = info.This(); | 454 | v8::Local<v8::Value> objectV8 = info.This(); |
| 512 | ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8); | 455 | ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8); |
| 513 | if (!proxy) { | 456 | if (!proxy) { |
| @@ -521,17 +464,7 @@ void ScriptObjectV8Proxy::v8Get(v8::Local<v8::Name> name, const v8::PropertyCall · 7 unmodified lines | |||
| 521 | Q_ASSERT(false); | 464 | Q_ASSERT(false); |
| 522 | } | 465 | } |
| 523 | v8::Local<v8::String> v8NameString; | 466 | v8::Local<v8::String> v8NameString; |
| 524 | /*if (name->IsString()) { | ||
| 525 | v8NameString = v8::Local<v8::String>::Cast(name); | ||
| 526 | } else { | ||
| 527 | if (!name->ToString(info.GetIsolate()->GetCurrentContext()).ToLocal(&v8NameString)) { | ||
| 528 | Q_ASSERT(false); | ||
| 529 | } | ||
| 530 | } | ||
| 531 | 467 | ||
| 532 | if (name->IsSymbol()) { | ||
| 533 | qCDebug(scriptengine_v8) << "ScriptObjectV8Proxy::v8Set: symbol: " + nameString.toQString(); | ||
| 534 | }*/ | ||
| 535 | if (name->IsString()) { | 468 | if (name->IsString()) { |
| 536 | V8ScriptString nameString(proxy->_engine, v8::Local<v8::String>::Cast(name)); | 469 | V8ScriptString nameString(proxy->_engine, v8::Local<v8::String>::Cast(name)); |
| 537 | uint id; | 470 | uint id; |
| @@ -553,9 +486,7 @@ void ScriptObjectV8Proxy::v8Get(v8::Local<v8::Name> name, const v8::PropertyCall · 15 unmodified lines | |||
| 553 | 486 | ||
| 554 | void ScriptObjectV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { | 487 | void ScriptObjectV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 555 | v8::HandleScope handleScope(info.GetIsolate()); | 488 | v8::HandleScope handleScope(info.GetIsolate()); |
| 556 | //V8TODO: should there be a context scope here? | ||
| 557 | v8::String::Utf8Value utf8Value(info.GetIsolate(), name); | 489 | v8::String::Utf8Value utf8Value(info.GetIsolate(), name); |
| 558 | //qCDebug(scriptengine_v8) << "Set: " << *utf8Value; | ||
| 559 | v8::Local<v8::Value> objectV8 = info.This(); | 490 | v8::Local<v8::Value> objectV8 = info.This(); |
| 560 | ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8); | 491 | ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8); |
| 561 | if (!proxy) { | 492 | if (!proxy) { |
| @@ -568,18 +499,7 @@ void ScriptObjectV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> v · 6 unmodified lines | |||
| 568 | qCDebug(scriptengine_v8) << notStringMessage; | 499 | qCDebug(scriptengine_v8) << notStringMessage; |
| 569 | Q_ASSERT(false); | 500 | Q_ASSERT(false); |
| 570 | } | 501 | } |
| 571 | /*v8::Local<v8::String> v8NameString; | 502 | |
| 572 | if (name->IsString()) { | ||
| 573 | v8NameString = v8::Local<v8::String>::Cast(name); | ||
| 574 | } else { | ||
| 575 | if (!name->ToString(info.GetIsolate()->GetCurrentContext()).ToLocal(&v8NameString)) { | ||
| 576 | Q_ASSERT(false); | ||
| 577 | } | ||
| 578 | } | ||
| 579 | if (name->IsSymbol()) { | ||
| 580 | qCDebug(scriptengine_v8) << "ScriptObjectV8Proxy::v8Set: symbol: " + nameString.toQString(); | ||
| 581 | }*/ | ||
| 582 | //V8ScriptString nameString(info.GetIsolate(), name->ToString(proxy->_engine->getContext()).ToLocalChecked()); | ||
| 583 | if (name->IsString()) { | 503 | if (name->IsString()) { |
| 584 | V8ScriptString nameString(proxy->_engine, v8::Local<v8::String>::Cast(name)); | 504 | V8ScriptString nameString(proxy->_engine, v8::Local<v8::String>::Cast(name)); |
| 585 | uint id; | 505 | uint id; |
| @@ -590,7 +510,7 @@ void ScriptObjectV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> v · 4 unmodified lines | |||
| 590 | return; | 510 | return; |
| 591 | } | 511 | } |
| 592 | } | 512 | } |
| 593 | // V8TODO: Should it be v8::Object or v8::Local<v8::Object>? | 513 | |
| 594 | if (info.This()->GetInternalField(2).As<v8::Object>()->Set(proxy->_engine->getContext(), name, value).FromMaybe(false)) { | 514 | if (info.This()->GetInternalField(2).As<v8::Object>()->Set(proxy->_engine->getContext(), name, value).FromMaybe(false)) { |
| 595 | info.GetReturnValue().Set(value); | 515 | info.GetReturnValue().Set(value); |
| 596 | } else { | 516 | } else { |
| @@ -599,7 +519,6 @@ void ScriptObjectV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> v · 2 unmodified lines | |||
| 599 | } | 519 | } |
| 600 | 520 | ||
| 601 | void ScriptObjectV8Proxy::v8GetPropertyNames(const v8::PropertyCallbackInfo<v8::Array>& info) { | 521 | void ScriptObjectV8Proxy::v8GetPropertyNames(const v8::PropertyCallbackInfo<v8::Array>& info) { |
| 602 | //qCDebug(scriptengine_v8) << "ScriptObjectV8Proxy::v8GetPropertyNames called"; | ||
| 603 | v8::HandleScope handleScope(info.GetIsolate()); | 522 | v8::HandleScope handleScope(info.GetIsolate()); |
| 604 | auto context = info.GetIsolate()->GetCurrentContext(); | 523 | auto context = info.GetIsolate()->GetCurrentContext(); |
| 605 | v8::Context::Scope contextScope(context); | 524 | v8::Context::Scope contextScope(context); |
| @@ -610,7 +529,6 @@ void ScriptObjectV8Proxy::v8GetPropertyNames(const v8::PropertyCallbackInfo<v8:: · 4 unmodified lines | |||
| 610 | return; | 529 | return; |
| 611 | } | 530 | } |
| 612 | V8ScriptValue object(proxy->_engine, objectV8); | 531 | V8ScriptValue object(proxy->_engine, objectV8); |
| 613 | //uint id; | ||
| 614 | v8::Local<v8::Array> properties = proxy->getPropertyNames(); | 532 | v8::Local<v8::Array> properties = proxy->getPropertyNames(); |
| 615 | v8::Local<v8::Array> objectProperties; | 533 | v8::Local<v8::Array> objectProperties; |
| 616 | uint32_t propertiesLength = properties->Length(); | 534 | uint32_t propertiesLength = properties->Length(); |
| @@ -695,7 +613,6 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 78 unmodified lines | |||
| 695 | qCDebug(scriptengine_v8) << "Method with QMetaType::UnknownType " << metaObject->className() << " " << (*iter).name(); | 613 | qCDebug(scriptengine_v8) << "Method with QMetaType::UnknownType " << metaObject->className() << " " << (*iter).name(); |
| 696 | } | 614 | } |
| 697 | } //V8TODO: is new method created during every call? It needs to be cached instead | 615 | } //V8TODO: is new method created during every call? It needs to be cached instead |
| 698 | //bool isMethodDefined = false; | ||
| 699 | v8::Local<v8::Value> property; | 616 | v8::Local<v8::Value> property; |
| 700 | if(_v8Object.Get(isolate)->GetInternalField(2).As<v8::Object>()->Get(_engine->getContext(), name.constGet()).ToLocal(&property)) { | 617 | if(_v8Object.Get(isolate)->GetInternalField(2).As<v8::Object>()->Get(_engine->getContext(), name.constGet()).ToLocal(&property)) { |
| 701 | if (!property->IsUndefined()) { | 618 | if (!property->IsUndefined()) { |
| @@ -725,7 +642,6 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 23 unmodified lines | |||
| 725 | // It's not necessarily new, newQObject looks for it first in object wrapper map | 642 | // It's not necessarily new, newQObject looks for it first in object wrapper map |
| 726 | // V8TODO: won't ScriptEngine::ScriptOwnership cause trouble here? | 643 | // V8TODO: won't ScriptEngine::ScriptOwnership cause trouble here? |
| 727 | return ScriptObjectV8Proxy::newQObject(_engine, proxy, ScriptEngine::ScriptOwnership, options); | 644 | return ScriptObjectV8Proxy::newQObject(_engine, proxy, ScriptEngine::ScriptOwnership, options); |
| 728 | //return _engine->newQObject(proxy, ScriptEngine::ScriptOwnership, options); | ||
| 729 | } | 645 | } |
| 730 | } | 646 | } |
| 731 | return V8ScriptValue(_engine, v8::Null(isolate)); | 647 | return V8ScriptValue(_engine, v8::Null(isolate)); |
| @@ -777,8 +693,6 @@ ScriptVariantV8Proxy::ScriptVariantV8Proxy(ScriptEngineV8* engine, const QVarian · 45 unmodified lines | |||
| 777 | v8::HandleScope handleScope(isolate); | 693 | v8::HandleScope handleScope(isolate); |
| 778 | v8::Context::Scope contextScope(engine->getContext()); | 694 | v8::Context::Scope contextScope(engine->getContext()); |
| 779 | auto variantDataTemplate = _engine->getVariantDataTemplate(); | 695 | auto variantDataTemplate = _engine->getVariantDataTemplate(); |
| 780 | //auto variantDataTemplate = v8::ObjectTemplate::New(isolate); | ||
| 781 | //variantDataTemplate->SetInternalFieldCount(2); | ||
| 782 | auto variantData = variantDataTemplate->NewInstance(engine->getContext()).ToLocalChecked(); | 696 | auto variantData = variantDataTemplate->NewInstance(engine->getContext()).ToLocalChecked(); |
| 783 | variantData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantInProxy)); | 697 | variantData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantInProxy)); |
| 784 | // Internal field doesn't point directly to QVariant, because then alignment would need to be guaranteed in all compilers | 698 | // Internal field doesn't point directly to QVariant, because then alignment would need to be guaranteed in all compilers |
| @@ -793,7 +707,6 @@ ScriptVariantV8Proxy::~ScriptVariantV8Proxy() { · 8 unmodified lines | |||
| 793 | v8::Isolate::Scope isolateScope(isolate); | 707 | v8::Isolate::Scope isolateScope(isolate); |
| 794 | v8::HandleScope handleScope(isolate); | 708 | v8::HandleScope handleScope(isolate); |
| 795 | // V8TODO: Add similar deletion handling as for object proxy | 709 | // V8TODO: Add similar deletion handling as for object proxy |
| 796 | //_v8ObjectTemplate.Reset(); | ||
| 797 | _v8Object.Reset(); | 710 | _v8Object.Reset(); |
| 798 | } | 711 | } |
| 799 | 712 | ||
| @@ -814,9 +727,6 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa · 14 unmodified lines | |||
| 814 | auto proxy = new ScriptVariantV8Proxy(engine, variant, proto, protoProxy); | 727 | auto proxy = new ScriptVariantV8Proxy(engine, variant, proto, protoProxy); |
| 815 | 728 | ||
| 816 | auto variantProxyTemplate = engine->getVariantProxyTemplate(); | 729 | auto variantProxyTemplate = engine->getVariantProxyTemplate(); |
| 817 | //auto variantProxyTemplate = v8::ObjectTemplate::New(isolate); | ||
| 818 | //variantProxyTemplate->SetInternalFieldCount(2); | ||
| 819 | //variantProxyTemplate->SetHandler(v8::NamedPropertyHandlerConfiguration(v8Get, v8Set, nullptr, nullptr, v8GetPropertyNames)); | ||
| 820 | auto variantProxy = variantProxyTemplate->NewInstance(engine->getContext()).ToLocalChecked(); | 730 | auto variantProxy = variantProxyTemplate->NewInstance(engine->getContext()).ToLocalChecked(); |
| 821 | variantProxy->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantProxy)); | 731 | variantProxy->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantProxy)); |
| 822 | variantProxy->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(proxy)); | 732 | variantProxy->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(proxy)); |
| @@ -905,13 +815,6 @@ void ScriptVariantV8Proxy::v8Get(v8::Local<v8::Name> name, const v8::PropertyCal · 82 unmodified lines | |||
| 905 | } | 815 | } |
| 906 | 816 | ||
| 907 | qCDebug(scriptengine_v8) << "Value not found: " << *utf8Name; | 817 | qCDebug(scriptengine_v8) << "Value not found: " << *utf8Name; |
| 908 | // V8TODO: this is done differently for variant proxy - use internal field of _v8Object instead? | ||
| 909 | /*v8::Local<v8::Value> property; | ||
| 910 | if(info.This()->GetInternalField(2).As<v8::Object>()->Get(proxy->_engine->getContext(), name).ToLocal(&property)) { | ||
| 911 | info.GetReturnValue().Set(property); | ||
| 912 | } else { | ||
| 913 | qCDebug(scriptengine_v8) << "Value not found: " << *utf8Value; | ||
| 914 | }*/ | ||
| 915 | } | 818 | } |
| 916 | 819 | ||
| 917 | void ScriptVariantV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { | 820 | void ScriptVariantV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { |
| @@ -941,18 +844,11 @@ void ScriptVariantV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> · 23 unmodified lines | |||
| 941 | return; | 844 | return; |
| 942 | } | 845 | } |
| 943 | } | 846 | } |
| 944 | // V8TODO: this is done differently for variant proxy - use internal field of _v8Object instead? | ||
| 945 | /*if (info.This()->GetInternalField(2).As<v8::Object>()->Set(proxy->_engine->getContext(), name, value).FromMaybe(false)) { | ||
| 946 | info.GetReturnValue().Set(value); | ||
| 947 | } else { | ||
| 948 | qCDebug(scriptengine_v8) << "Set failed: " << *utf8Name; | ||
| 949 | }*/ | ||
| 950 | qCDebug(scriptengine_v8) << "Set failed: " << *utf8Name; | 847 | qCDebug(scriptengine_v8) << "Set failed: " << *utf8Name; |
| 951 | } | 848 | } |
| 952 | 849 | ||
| 953 | void ScriptVariantV8Proxy::v8GetPropertyNames(const v8::PropertyCallbackInfo<v8::Array>& info) { | 850 | void ScriptVariantV8Proxy::v8GetPropertyNames(const v8::PropertyCallbackInfo<v8::Array>& info) { |
| 954 | //V8TODO: Only methods from the prototype should be listed. | 851 | //V8TODO: Only methods from the prototype should be listed. |
| 955 | //qCDebug(scriptengine_v8) << "ScriptObjectV8Proxy::v8GetPropertyNames called"; | ||
| 956 | v8::HandleScope handleScope(info.GetIsolate()); | 852 | v8::HandleScope handleScope(info.GetIsolate()); |
| 957 | auto context = info.GetIsolate()->GetCurrentContext(); | 853 | auto context = info.GetIsolate()->GetCurrentContext(); |
| 958 | v8::Context::Scope contextScope(context); | 854 | v8::Context::Scope contextScope(context); |
| @@ -965,15 +861,6 @@ void ScriptVariantV8Proxy::v8GetPropertyNames(const v8::PropertyCallbackInfo<v8: · 6 unmodified lines | |||
| 965 | V8ScriptValue object(proxy->_engine, objectV8); | 861 | V8ScriptValue object(proxy->_engine, objectV8); |
| 966 | v8::Local<v8::Array> properties = proxy->_proto->getPropertyNames(); | 862 | v8::Local<v8::Array> properties = proxy->_proto->getPropertyNames(); |
| 967 | v8::Local<v8::Array> objectProperties; | 863 | v8::Local<v8::Array> objectProperties; |
| 968 | // V8TODO: this is done differently for variant proxy - use internal field of _v8Object instead? | ||
| 969 | /*uint32_t propertiesLength = properties->Length(); | ||
| 970 | if (info.This()->GetInternalField(2).As<v8::Object>()->GetPropertyNames(context).ToLocal(&objectProperties)) { | ||
| 971 | for (uint32_t n = 0; n < objectProperties->Length(); n++) { | ||
| 972 | if(!properties->Set(context, propertiesLength+n, objectProperties->Get(context, n).ToLocalChecked()).FromMaybe(false)) { | ||
| 973 | qCDebug(scriptengine_v8) << "ScriptObjectV8Proxy::v8GetPropertyNames: Cannot add member name"; | ||
| 974 | } | ||
| 975 | } | ||
| 976 | }*/ | ||
| 977 | info.GetReturnValue().Set(properties); | 864 | info.GetReturnValue().Set(properties); |
| 978 | } | 865 | } |
| 979 | 866 | ||
| @@ -996,7 +883,6 @@ ScriptMethodV8Proxy::ScriptMethodV8Proxy(ScriptEngineV8* engine, QObject* object · 16 unmodified lines | |||
| 996 | } | 883 | } |
| 997 | 884 | ||
| 998 | ScriptMethodV8Proxy::~ScriptMethodV8Proxy() { | 885 | ScriptMethodV8Proxy::~ScriptMethodV8Proxy() { |
| 999 | //qCDebug(scriptengine_v8) << "ScriptMethodV8Proxy destroyed"; | ||
| 1000 | auto isolate = _engine->getIsolate(); | 886 | auto isolate = _engine->getIsolate(); |
| 1001 | v8::Locker locker(isolate); | 887 | v8::Locker locker(isolate); |
| 1002 | v8::Isolate::Scope isolateScope(isolate); | 888 | v8::Isolate::Scope isolateScope(isolate); |
| @@ -1005,7 +891,6 @@ ScriptMethodV8Proxy::~ScriptMethodV8Proxy() { · 2 unmodified lines | |||
| 1005 | } | 891 | } |
| 1006 | 892 | ||
| 1007 | void ScriptMethodV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptMethodV8Proxy>& info) { | 893 | void ScriptMethodV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptMethodV8Proxy>& info) { |
| 1008 | //qDebug(scriptengine_v8) << "ScriptMethodV8Proxy::weakHandleCallback"; | ||
| 1009 | auto proxy = info.GetParameter(); | 894 | auto proxy = info.GetParameter(); |
| 1010 | proxy->_objectLifetime.Reset(); | 895 | proxy->_objectLifetime.Reset(); |
| 1011 | info.GetParameter()->deleteLater(); | 896 | info.GetParameter()->deleteLater(); |
| @@ -1019,12 +904,8 @@ V8ScriptValue ScriptMethodV8Proxy::newMethod(ScriptEngineV8* engine, QObject* ob · 7 unmodified lines | |||
| 1019 | v8::HandleScope handleScope(isolate); | 904 | v8::HandleScope handleScope(isolate); |
| 1020 | v8::Context::Scope contextScope(engine->getContext()); | 905 | v8::Context::Scope contextScope(engine->getContext()); |
| 1021 | auto methodDataTemplate = engine->getMethodDataTemplate(); | 906 | auto methodDataTemplate = engine->getMethodDataTemplate(); |
| 1022 | //auto methodDataTemplate = v8::ObjectTemplate::New(isolate); | ||
| 1023 | //methodDataTemplate->SetInternalFieldCount(2); | ||
| 1024 | auto methodData = methodDataTemplate->NewInstance(engine->getContext()).ToLocalChecked(); | 907 | auto methodData = methodDataTemplate->NewInstance(engine->getContext()).ToLocalChecked(); |
| 1025 | methodData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToMethodProxy)); | 908 | methodData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToMethodProxy)); |
| 1026 | // V8TODO it needs to be deleted somehow on object destruction | ||
| 1027 | // weak persistent callback would do this | ||
| 1028 | methodData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(new ScriptMethodV8Proxy(engine, object, lifetime, metas, numMaxParams))); | 909 | methodData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(new ScriptMethodV8Proxy(engine, object, lifetime, metas, numMaxParams))); |
| 1029 | auto v8Function = v8::Function::New(engine->getContext(), callback, methodData, numMaxParams).ToLocalChecked(); | 910 | auto v8Function = v8::Function::New(engine->getContext(), callback, methodData, numMaxParams).ToLocalChecked(); |
| 1030 | return V8ScriptValue(engine, v8Function); | 911 | return V8ScriptValue(engine, v8Function); |
| @@ -1042,31 +923,16 @@ QString ScriptMethodV8Proxy::fullName() const { · 11 unmodified lines | |||
| 1042 | return QString("%1::%2").arg(_object->metaObject()->className(), firstMethod.name()); | 923 | return QString("%1::%2").arg(_object->metaObject()->className(), firstMethod.name()); |
| 1043 | } | 924 | } |
| 1044 | 925 | ||
| 1045 | // V8TODO | ||
| 1046 | /*bool ScriptMethodV8Proxy::supportsExtension(Extension extension) const { | ||
| 1047 | switch (extension) { | ||
| 1048 | case Callable: | ||
| 1049 | return true; | ||
| 1050 | default: | ||
| 1051 | return false; | ||
| 1052 | } | ||
| 1053 | }*/ | ||
| 1054 | |||
| 1055 | void ScriptMethodV8Proxy::callback(const v8::FunctionCallbackInfo<v8::Value>& arguments) { | 926 | void ScriptMethodV8Proxy::callback(const v8::FunctionCallbackInfo<v8::Value>& arguments) { |
| 1056 | v8::Locker locker(arguments.GetIsolate()); | 927 | v8::Locker locker(arguments.GetIsolate()); |
| 1057 | v8::Isolate::Scope isolateScope(arguments.GetIsolate()); | 928 | v8::Isolate::Scope isolateScope(arguments.GetIsolate()); |
| 1058 | v8::HandleScope handleScope(arguments.GetIsolate()); | 929 | v8::HandleScope handleScope(arguments.GetIsolate()); |
| 1059 | //Q_ASSERT(!arguments.GetIsolate()->GetCurrentContext().IsEmpty()); | ||
| 1060 | v8::Context::Scope contextScope(arguments.GetIsolate()->GetCurrentContext()); | 930 | v8::Context::Scope contextScope(arguments.GetIsolate()->GetCurrentContext()); |
| 1061 | if (!arguments.Data()->IsObject()) { | 931 | if (!arguments.Data()->IsObject()) { |
| 1062 | arguments.GetIsolate()->ThrowError("Method value is not an object"); | 932 | arguments.GetIsolate()->ThrowError("Method value is not an object"); |
| 1063 | return; | 933 | return; |
| 1064 | } | 934 | } |
| 1065 | v8::Local<v8::Object> data = v8::Local<v8::Object>::Cast(arguments.Data()); | 935 | v8::Local<v8::Object> data = v8::Local<v8::Object>::Cast(arguments.Data()); |
| 1066 | /*if (!arguments.Data()->IsCallable()) { | ||
| 1067 | arguments.GetIsolate()->ThrowError("Method value is not callable"); | ||
| 1068 | return; | ||
| 1069 | }*/ | ||
| 1070 | if (data->InternalFieldCount() != 2) { | 936 | if (data->InternalFieldCount() != 2) { |
| 1071 | arguments.GetIsolate()->ThrowError("Incorrect number of internal fields during method call"); | 937 | arguments.GetIsolate()->ThrowError("Incorrect number of internal fields during method call"); |
| 1072 | return; | 938 | return; |
| @@ -1092,8 +958,6 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 19 unmodified lines | |||
| 1092 | return; | 958 | return; |
| 1093 | } | 959 | } |
| 1094 | 960 | ||
| 1095 | //v8::HandleScope handleScope(_engine->getIsolate()); | ||
| 1096 | |||
| 1097 | int scriptNumArgs = arguments.Length(); | 961 | int scriptNumArgs = arguments.Length(); |
| 1098 | int numArgs = std::min(scriptNumArgs, _numMaxParams); | 962 | int numArgs = std::min(scriptNumArgs, _numMaxParams); |
| 1099 | 963 | ||
| @@ -1113,7 +977,6 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 13 unmodified lines | |||
| 1113 | int bestMeta = 0; | 977 | int bestMeta = 0; |
| 1114 | int bestConversionPenaltyScore = 0; | 978 | int bestConversionPenaltyScore = 0; |
| 1115 | 979 | ||
| 1116 | |||
| 1117 | for (int i = 0; i < num_metas; i++) { | 980 | for (int i = 0; i < num_metas; i++) { |
| 1118 | const QMetaMethod& meta = _metas[i]; | 981 | const QMetaMethod& meta = _metas[i]; |
| 1119 | int methodNumArgs = meta.parameterCount(); | 982 | int methodNumArgs = meta.parameterCount(); |
| @@ -1208,16 +1071,6 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 88 unmodified lines | |||
| 1208 | return; | 1071 | return; |
| 1209 | } else if (returnTypeId == scriptValueTypeId) { | 1072 | } else if (returnTypeId == scriptValueTypeId) { |
| 1210 | ScriptValue result; | 1073 | ScriptValue result; |
| 1211 | /*if (_metas.front().name() == "createGarbageCollectorDebuggingObject") { | ||
| 1212 | //qDebug() << "createGarbageCollectorDebuggingObject"; | ||
| 1213 | return; | ||
| 1214 | }*/ | ||
| 1215 | /*const char* typeName = meta.typeName(); | ||
| 1216 | QVariant qRetVal(returnTypeId, static_cast<void*>(NULL)); | ||
| 1217 | QGenericReturnArgument sRetVal(typeName, const_cast<void*>(qRetVal.constData())); | ||
| 1218 | bool success = meta.invoke(qobject, Qt::DirectConnection, sRetVal, qGenArgs[0], | ||
| 1219 | qGenArgs[1], qGenArgs[2], qGenArgs[3], qGenArgs[4], qGenArgs[5], qGenArgs[6], | ||
| 1220 | qGenArgs[7], qGenArgs[8], qGenArgs[9]);*/ | ||
| 1221 | bool success = meta.invoke(qobject, Qt::DirectConnection, Q_RETURN_ARG(ScriptValue, result), qGenArgs[0], | 1074 | bool success = meta.invoke(qobject, Qt::DirectConnection, Q_RETURN_ARG(ScriptValue, result), qGenArgs[0], |
| 1222 | qGenArgs[1], qGenArgs[2], qGenArgs[3], qGenArgs[4], qGenArgs[5], qGenArgs[6], | 1075 | qGenArgs[1], qGenArgs[2], qGenArgs[3], qGenArgs[4], qGenArgs[5], qGenArgs[6], |
| 1223 | qGenArgs[7], qGenArgs[8], qGenArgs[9]); | 1076 | qGenArgs[7], qGenArgs[8], qGenArgs[9]); |
| @@ -1226,7 +1079,6 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 2 unmodified lines | |||
| 1226 | return; | 1079 | return; |
| 1227 | } | 1080 | } |
| 1228 | V8ScriptValue v8Result = ScriptValueV8Wrapper::fullUnwrap(_engine, result); | 1081 | V8ScriptValue v8Result = ScriptValueV8Wrapper::fullUnwrap(_engine, result); |
| 1229 | //V8ScriptValue v8Result = _engine->castVariantToValue(qRetVal); | ||
| 1230 | arguments.GetReturnValue().Set(v8Result.get()); | 1082 | arguments.GetReturnValue().Set(v8Result.get()); |
| 1231 | return; | 1083 | return; |
| 1232 | } else { | 1084 | } else { |
| @@ -1271,8 +1123,6 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 38 unmodified lines | |||
| 1271 | .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName); | 1123 | .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName); |
| 1272 | qCDebug(scriptengine_v8) << errorMessage << "\n Backtrace:" << _engine->currentContext()->backtrace(); | 1124 | qCDebug(scriptengine_v8) << errorMessage << "\n Backtrace:" << _engine->currentContext()->backtrace(); |
| 1273 | isolate->ThrowError(v8::String::NewFromUtf8(isolate, errorMessage.toStdString().c_str()).ToLocalChecked()); | 1125 | isolate->ThrowError(v8::String::NewFromUtf8(isolate, errorMessage.toStdString().c_str()).ToLocalChecked()); |
| 1274 | //context->throwError(V8ScriptContext::TypeError, QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4") | ||
| 1275 | // .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName)); | ||
| 1276 | return; | 1126 | return; |
| 1277 | } | 1127 | } |
| 1278 | } | 1128 | } |
| @@ -1280,179 +1130,10 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 1 unmodified line | |||
| 1280 | QString errorMessage = QString("Native call of %1 failed: could not locate an overload with the requested arguments").arg(fullName()); | 1130 | QString errorMessage = QString("Native call of %1 failed: could not locate an overload with the requested arguments").arg(fullName()); |
| 1281 | qCDebug(scriptengine_v8) << errorMessage; | 1131 | qCDebug(scriptengine_v8) << errorMessage; |
| 1282 | isolate->ThrowError(v8::String::NewFromUtf8(isolate, errorMessage.toStdString().c_str()).ToLocalChecked()); | 1132 | isolate->ThrowError(v8::String::NewFromUtf8(isolate, errorMessage.toStdString().c_str()).ToLocalChecked()); |
| 1283 | // V8TODO: it happens sometimes for some reason | ||
| 1284 | Q_ASSERT(false); // really shouldn't have gotten here -- it didn't work before and it's working now? | 1133 | Q_ASSERT(false); // really shouldn't have gotten here -- it didn't work before and it's working now? |
| 1285 | return; | 1134 | return; |
| 1286 | } | 1135 | } |
| 1287 | 1136 | ||
| 1288 | //V8TODO: was this used anywhere? | ||
| 1289 | /*QVariant ScriptMethodV8Proxy::extension(Extension extension, const QVariant& argument) { | ||
| 1290 | if (extension != Callable) return QVariant(); | ||
| 1291 | V8ScriptContext* context = qvariant_cast<V8ScriptContext*>(argument); | ||
| 1292 | |||
| 1293 | QObject* qobject = _object; | ||
| 1294 | if (!qobject) { | ||
| 1295 | context->throwError(V8ScriptContext::ReferenceError, "Referencing deleted native object"); | ||
| 1296 | return QVariant(); | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | int scriptNumArgs = context->argumentCount(); | ||
| 1300 | int numArgs = std::min(scriptNumArgs, _numMaxParams); | ||
| 1301 | |||
| 1302 | const int scriptValueTypeId = qMetaTypeId<ScriptValue>(); | ||
| 1303 | |||
| 1304 | int parameterConversionFailureId = 0; | ||
| 1305 | int parameterConversionFailureCount = 0; | ||
| 1306 | |||
| 1307 | int num_metas = _metas.size(); | ||
| 1308 | QVector< QList<ScriptValue> > qScriptArgLists; | ||
| 1309 | QVector< QVector <QGenericArgument> > qGenArgsVectors; | ||
| 1310 | QVector< QList<QVariant> > qVarArgLists; | ||
| 1311 | qScriptArgLists.resize(num_metas); | ||
| 1312 | qGenArgsVectors.resize(num_metas); | ||
| 1313 | qVarArgLists.resize(num_metas); | ||
| 1314 | bool isValidMetaSelected = false; | ||
| 1315 | int bestMeta = 0; | ||
| 1316 | int bestConversionPenaltyScore = 0; | ||
| 1317 | |||
| 1318 | for (int i = 0; i < num_metas; i++) { | ||
| 1319 | const QMetaMethod& meta = _metas[i]; | ||
| 1320 | int methodNumArgs = meta.parameterCount(); | ||
| 1321 | if (methodNumArgs != numArgs) { | ||
| 1322 | continue; | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | qGenArgsVectors[i].resize(10); | ||
| 1326 | int conversionPenaltyScore = 0; | ||
| 1327 | int conversionFailures = 0; | ||
| 1328 | |||
| 1329 | for (int arg = 0; arg < numArgs; ++arg) { | ||
| 1330 | int methodArgTypeId = meta.parameterType(arg); | ||
| 1331 | Q_ASSERT(methodArgTypeId != QMetaType::UnknownType); | ||
| 1332 | V8ScriptValue argVal = context->argument(arg); | ||
| 1333 | if (methodArgTypeId == scriptValueTypeId) { | ||
| 1334 | qScriptArgLists[i].append(ScriptValue(new ScriptValueV8Wrapper(_engine, argVal))); | ||
| 1335 | qGenArgsVectors[i][arg] = Q_ARG(ScriptValue, qScriptArgLists[i].back()); | ||
| 1336 | } else if (methodArgTypeId == QMetaType::QVariant) { | ||
| 1337 | qVarArgLists[i].append(argVal.toVariant()); | ||
| 1338 | qGenArgsVectors[i][arg] = Q_ARG(QVariant, qVarArgLists[i].back()); | ||
| 1339 | } else { | ||
| 1340 | QVariant varArgVal; | ||
| 1341 | if (!_engine->castValueToVariant(argVal, varArgVal, methodArgTypeId)) { | ||
| 1342 | conversionFailures++; | ||
| 1343 | } else { | ||
| 1344 | qVarArgLists[i].append(varArgVal); | ||
| 1345 | const QVariant& converted = qVarArgLists[i].back(); | ||
| 1346 | conversionPenaltyScore = _engine->computeCastPenalty(argVal, methodArgTypeId); | ||
| 1347 | |||
| 1348 | // a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant | ||
| 1349 | // A const_cast is needed because calling data() would detach the QVariant. | ||
| 1350 | qGenArgsVectors[i][arg] = | ||
| 1351 | QGenericArgument(QMetaType::typeName(converted.userType()), const_cast<void*>(converted.constData())); | ||
| 1352 | } | ||
| 1353 | } | ||
| 1354 | } | ||
| 1355 | if (conversionFailures) { | ||
| 1356 | if (conversionFailures < parameterConversionFailureCount || !parameterConversionFailureCount) { | ||
| 1357 | parameterConversionFailureCount = conversionFailures; | ||
| 1358 | parameterConversionFailureId = meta.methodIndex(); | ||
| 1359 | } | ||
| 1360 | continue; | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | if (!isValidMetaSelected) { | ||
| 1364 | isValidMetaSelected = true; | ||
| 1365 | bestMeta = i; | ||
| 1366 | bestConversionPenaltyScore = conversionPenaltyScore; | ||
| 1367 | } | ||
| 1368 | if (isValidMetaSelected && bestConversionPenaltyScore > conversionPenaltyScore) { | ||
| 1369 | bestMeta = i; | ||
| 1370 | bestConversionPenaltyScore = conversionPenaltyScore; | ||
| 1371 | } | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | if (isValidMetaSelected) { | ||
| 1375 | ScriptContextV8Wrapper ourContext(_engine, context); | ||
| 1376 | ScriptContextGuard guard(&ourContext); | ||
| 1377 | const QMetaMethod& meta = _metas[bestMeta]; | ||
| 1378 | int returnTypeId = meta.returnType(); | ||
| 1379 | QVector <QGenericArgument> &qGenArgs = qGenArgsVectors[bestMeta]; | ||
| 1380 | |||
| 1381 | // The Qt MOC engine will automatically call qRegisterMetaType on invokable parameters and properties, but there's | ||
| 1382 | // nothing in there for return values so these need to be explicitly runtime-registered! | ||
| 1383 | Q_ASSERT(returnTypeId != QMetaType::UnknownType); | ||
| 1384 | if (returnTypeId == QMetaType::UnknownType) { | ||
| 1385 | _engine->getIsolate()->ThrowError(v8::String::NewFromUtf8(_engine->getIsolate(), QString("Cannot call native function %1, its return value has not been registered with Qt").arg(fullName()).toStdString().c_str()).ToLocalChecked()); | ||
| 1386 | return QVariant(); | ||
| 1387 | } else if (returnTypeId == QMetaType::Void) { | ||
| 1388 | bool success = meta.invoke(qobject, Qt::DirectConnection, qGenArgs[0], qGenArgs[1], qGenArgs[2], qGenArgs[3], | ||
| 1389 | qGenArgs[4], qGenArgs[5], qGenArgs[6], qGenArgs[7], qGenArgs[8], qGenArgs[9]); | ||
| 1390 | if (!success) { | ||
| 1391 | _engine->getIsolate()->ThrowError(v8::String::NewFromUtf8(_engine->getIsolate(), QString("Unexpected: Native call of %1 failed").arg(fullName()).toStdString().c_str()).ToLocalChecked()); | ||
| 1392 | } | ||
| 1393 | return QVariant(); | ||
| 1394 | } else if (returnTypeId == scriptValueTypeId) { | ||
| 1395 | ScriptValue result; | ||
| 1396 | bool success = meta.invoke(qobject, Qt::DirectConnection, Q_RETURN_ARG(ScriptValue, result), qGenArgs[0], | ||
| 1397 | qGenArgs[1], qGenArgs[2], qGenArgs[3], qGenArgs[4], qGenArgs[5], qGenArgs[6], | ||
| 1398 | qGenArgs[7], qGenArgs[8], qGenArgs[9]); | ||
| 1399 | if (!success) { | ||
| 1400 | _engine->getIsolate()->ThrowError(v8::String::NewFromUtf8(_engine->getIsolate(), QString("Unexpected: Native call of %1 failed").arg(fullName()).toStdString().c_str()).ToLocalChecked()); | ||
| 1401 | return QVariant(); | ||
| 1402 | } | ||
| 1403 | V8ScriptValue qResult = ScriptValueV8Wrapper::fullUnwrap(_engine, result); | ||
| 1404 | return QVariant::fromValue(qResult); | ||
| 1405 | } else { | ||
| 1406 | // a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant | ||
| 1407 | const char* typeName = meta.typeName(); | ||
| 1408 | QVariant qRetVal(returnTypeId, static_cast<void*>(NULL)); | ||
| 1409 | QGenericReturnArgument sRetVal(typeName, const_cast<void*>(qRetVal.constData())); | ||
| 1410 | |||
| 1411 | bool success = | ||
| 1412 | meta.invoke(qobject, Qt::DirectConnection, sRetVal, qGenArgs[0], qGenArgs[1], qGenArgs[2], qGenArgs[3], | ||
| 1413 | qGenArgs[4], qGenArgs[5], qGenArgs[6], qGenArgs[7], qGenArgs[8], qGenArgs[9]); | ||
| 1414 | if (!success) { | ||
| 1415 | _engine->getIsolate()->ThrowError(v8::String::NewFromUtf8(_engine->getIsolate(), QString("Unexpected: Native call of %1 failed").arg(fullName()).toStdString().c_str()).ToLocalChecked()); | ||
| 1416 | return QVariant(); | ||
| 1417 | } | ||
| 1418 | V8ScriptValue qResult = _engine->castVariantToValue(qRetVal); | ||
| 1419 | return QVariant::fromValue(qResult); | ||
| 1420 | } | ||
| 1421 | } | ||
| 1422 | |||
| 1423 | // we failed to convert the call to C++, try to create a somewhat sane error message | ||
| 1424 | if (parameterConversionFailureCount == 0) { | ||
| 1425 | _engine->getIsolate()->ThrowError(v8::String::NewFromUtf8(_engine->getIsolate(), QString("Native call of %1 failed: unexpected parameter count").arg(fullName()).toStdString().c_str()).ToLocalChecked()); | ||
| 1426 | return QVariant(); | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | const QMetaMethod& meta = _object->metaObject()->method(parameterConversionFailureId); | ||
| 1430 | int methodNumArgs = meta.parameterCount(); | ||
| 1431 | Q_ASSERT(methodNumArgs == numArgs); | ||
| 1432 | |||
| 1433 | for (int arg = 0; arg < numArgs; ++arg) { | ||
| 1434 | int methodArgTypeId = meta.parameterType(arg); | ||
| 1435 | Q_ASSERT(methodArgTypeId != QMetaType::UnknownType); | ||
| 1436 | V8ScriptValue argVal = context->argument(arg); | ||
| 1437 | if (methodArgTypeId != scriptValueTypeId && methodArgTypeId != QMetaType::QVariant) { | ||
| 1438 | QVariant varArgVal; | ||
| 1439 | if (!_engine->castValueToVariant(argVal, varArgVal, methodArgTypeId)) { | ||
| 1440 | QByteArray methodTypeName = QMetaType(methodArgTypeId).name(); | ||
| 1441 | QByteArray argTypeName = _engine->valueType(argVal).toLatin1(); | ||
| 1442 | _engine->getIsolate()->ThrowError(v8::String::NewFromUtf8(_engine->getIsolate(), QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4") | ||
| 1443 | .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName).toStdString().c_str()).ToLocalChecked()); | ||
| 1444 | context->throwError(V8ScriptContext::TypeError, QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4") | ||
| 1445 | .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName)); | ||
| 1446 | return QVariant(); | ||
| 1447 | } | ||
| 1448 | } | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | context->throwError(QString("Native call of %1 failed: could not locate an overload with the requested arguments").arg(fullName())); | ||
| 1452 | Q_ASSERT(false); // really shouldn't have gotten here -- it didn't work before and it's working now? | ||
| 1453 | return QVariant(); | ||
| 1454 | }*/ | ||
| 1455 | |||
| 1456 | ScriptSignalV8Proxy::ScriptSignalV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, const QMetaMethod& meta) : | 1137 | ScriptSignalV8Proxy::ScriptSignalV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, const QMetaMethod& meta) : |
| 1457 | _engine(engine), _object(object), _meta(meta), _metaCallId(discoverMetaCallIdx()) { | 1138 | _engine(engine), _object(object), _meta(meta), _metaCallId(discoverMetaCallIdx()) { |
| 1458 | auto isolate = _engine->getIsolate(); | 1139 | auto isolate = _engine->getIsolate(); |
| @@ -1475,7 +1156,6 @@ ScriptSignalV8Proxy::~ScriptSignalV8Proxy() { · 16 unmodified lines | |||
| 1475 | } | 1156 | } |
| 1476 | 1157 | ||
| 1477 | void ScriptSignalV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptSignalV8Proxy>& info) { | 1158 | void ScriptSignalV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptSignalV8Proxy>& info) { |
| 1478 | //qDebug(scriptengine_v8) << "ScriptSignalV8Proxy::weakHandleCallback"; | ||
| 1479 | auto proxy = info.GetParameter(); | 1159 | auto proxy = info.GetParameter(); |
| 1480 | proxy->_objectLifetime.Reset(); | 1160 | proxy->_objectLifetime.Reset(); |
| 1481 | proxy->deleteLater(); | 1161 | proxy->deleteLater(); |
| @@ -1512,17 +1192,6 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu · 30 unmodified lines | |||
| 1512 | v8::Locker locker(isolate); | 1192 | v8::Locker locker(isolate); |
| 1513 | v8::Isolate::Scope isolateScope(isolate); | 1193 | v8::Isolate::Scope isolateScope(isolate); |
| 1514 | 1194 | ||
| 1515 | //V8ScriptValueList args(isolate, v8::Null(isolate)); | ||
| 1516 | // Moved to inside of the lock - could it cause crashes if left here? | ||
| 1517 | /*v8::Local<v8::Value> args[Q_METAMETHOD_INVOKE_MAX_ARGS]; | ||
| 1518 | int numArgs = _meta.parameterCount(); | ||
| 1519 | for (int arg = 0; arg < numArgs; ++arg) { | ||
| 1520 | int methodArgTypeId = _meta.parameterType(arg); | ||
| 1521 | Q_ASSERT(methodArgTypeId != QMetaType::UnknownType); | ||
| 1522 | QVariant argValue(methodArgTypeId, arguments[arg+1]); | ||
| 1523 | args[arg] = _engine->castVariantToValue(argValue).get(); | ||
| 1524 | }*/ | ||
| 1525 | |||
| 1526 | QList<Connection> connections; | 1195 | QList<Connection> connections; |
| 1527 | withReadLock([&]{ | 1196 | withReadLock([&]{ |
| 1528 | connections = _connections; | 1197 | connections = _connections; |
| @@ -1530,9 +1199,7 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu · 1 unmodified line | |||
| 1530 | 1199 | ||
| 1531 | // V8TODO: this may cause deadlocks on connect/disconnect, so the connect/disconnect procedure needs to be reworked. | 1200 | // V8TODO: this may cause deadlocks on connect/disconnect, so the connect/disconnect procedure needs to be reworked. |
| 1532 | // It should probably add events to a separate list that would be processed before and after all the events for the signal. | 1201 | // It should probably add events to a separate list that would be processed before and after all the events for the signal. |
| 1533 | //withReadLock([&]{ | ||
| 1534 | { | 1202 | { |
| 1535 | // V8TODO: check all other lambda functions to make sure they have handle scope - could they cause crashes otherwise? | ||
| 1536 | v8::HandleScope handleScope(isolate); | 1203 | v8::HandleScope handleScope(isolate); |
| 1537 | // V8TODO: should we use function creation context, or context in which connect happened? | 1204 | // V8TODO: should we use function creation context, or context in which connect happened? |
| 1538 | auto context = _engine->getContext(); | 1205 | auto context = _engine->getContext(); |
| @@ -1545,23 +1212,9 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu · 6 unmodified lines | |||
| 1545 | QVariant argValue(methodArgTypeId, arguments[arg + 1]); | 1212 | QVariant argValue(methodArgTypeId, arguments[arg + 1]); |
| 1546 | args[arg] = _engine->castVariantToValue(argValue).get(); | 1213 | args[arg] = _engine->castVariantToValue(argValue).get(); |
| 1547 | } | 1214 | } |
| 1548 | //for (ConnectionList::iterator iter = _connections.begin(); iter != _connections.end(); ++iter) { | ||
| 1549 | for (ConnectionList::iterator iter = connections.begin(); iter != connections.end(); ++iter) { | 1215 | for (ConnectionList::iterator iter = connections.begin(); iter != connections.end(); ++iter) { |
| 1550 | Connection& conn = *iter; | 1216 | Connection& conn = *iter; |
| 1551 | { | 1217 | { |
| 1552 | /*if (!conn.callback.get()->IsFunction()) { | ||
| 1553 | auto stringV8 = conn.callback.get()->ToDetailString(context).ToLocalChecked(); | ||
| 1554 | QString error = *v8::String::Utf8Value(_engine->getIsolate(), stringV8); | ||
| 1555 | qCDebug(scriptengine_v8) << error; | ||
| 1556 | Q_ASSERT(false); | ||
| 1557 | } | ||
| 1558 | v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(conn.callback.get()); | ||
| 1559 | auto functionContext = callback->CreationContext(); | ||
| 1560 | v8::Context::Scope functionContextScope(functionContext); | ||
| 1561 | _engine->pushContext(functionContext);*/ | ||
| 1562 | /*auto functionContext = _v8Context.Get(_engine->getIsolate()); | ||
| 1563 | _engine->pushContext(functionContext); | ||
| 1564 | v8::Context::Scope functionContextScope(functionContext);*/ | ||
| 1565 | auto functionContext = context; | 1218 | auto functionContext = context; |
| 1566 | 1219 | ||
| 1567 | Q_ASSERT(!conn.callback.get().IsEmpty()); | 1220 | Q_ASSERT(!conn.callback.get().IsEmpty()); |
| @@ -1595,11 +1248,9 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu · 27 unmodified lines | |||
| 1595 | 1248 | ||
| 1596 | _engine->setUncaughtException(tryCatch, "Error in signal proxy"); | 1249 | _engine->setUncaughtException(tryCatch, "Error in signal proxy"); |
| 1597 | } | 1250 | } |
| 1598 | //_engine->popContext(); | ||
| 1599 | } | 1251 | } |
| 1600 | } | 1252 | } |
| 1601 | } | 1253 | } |
| 1602 | //}); | ||
| 1603 | 1254 | ||
| 1604 | #ifdef SCRIPT_EVENT_PERFORMANCE_STATISTICS | 1255 | #ifdef SCRIPT_EVENT_PERFORMANCE_STATISTICS |
| 1605 | _totalCallTime_s += callTimer.elapsed() / 1000.0f; | 1256 | _totalCallTime_s += callTimer.elapsed() / 1000.0f; |
| @@ -1630,10 +1281,6 @@ ScriptSignalV8Proxy::ConnectionList::iterator ScriptSignalV8Proxy::findConnectio · 24 unmodified lines | |||
| 1630 | return iterOut; | 1281 | return iterOut; |
| 1631 | } | 1282 | } |
| 1632 | 1283 | ||
| 1633 | /*void ScriptSignalV8Proxy::connect(ScriptValue arg0) { | ||
| 1634 | connect(arg0, ScriptValue(_engine->getIsolate(), v8::Undefined(_engine->getIsolate()))); | ||
| 1635 | }*/ | ||
| 1636 | |||
| 1637 | void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { | 1284 | void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { |
| 1638 | v8::Isolate *isolate = _engine->getIsolate(); | 1285 | v8::Isolate *isolate = _engine->getIsolate(); |
| 1639 | v8::Locker locker(isolate); | 1286 | v8::Locker locker(isolate); |
| @@ -1646,8 +1293,6 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 6 unmodified lines | |||
| 1646 | return; | 1293 | return; |
| 1647 | } | 1294 | } |
| 1648 | 1295 | ||
| 1649 | //v8::HandleScope handleScope(isolate); | ||
| 1650 | |||
| 1651 | // untangle the arguments | 1296 | // untangle the arguments |
| 1652 | V8ScriptValue callback(_engine, v8::Null(isolate)); | 1297 | V8ScriptValue callback(_engine, v8::Null(isolate)); |
| 1653 | V8ScriptValue callbackThis(_engine, v8::Null(isolate)); | 1298 | V8ScriptValue callbackThis(_engine, v8::Null(isolate)); |
| @@ -1697,15 +1342,12 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 43 unmodified lines | |||
| 1697 | ScriptSignalV8Proxy* thisProxy = dynamic_cast<ScriptSignalV8Proxy*>(ScriptObjectV8Proxy::unwrapProxy(v8ThisObject)->toQObject()); | 1342 | ScriptSignalV8Proxy* thisProxy = dynamic_cast<ScriptSignalV8Proxy*>(ScriptObjectV8Proxy::unwrapProxy(v8ThisObject)->toQObject()); |
| 1698 | Q_ASSERT(thisProxy); | 1343 | Q_ASSERT(thisProxy); |
| 1699 | qCDebug(scriptengine_v8) << "ScriptSignalV8Proxy::connect: " << thisProxy->fullName() << " fullName: " << fullName(); | 1344 | qCDebug(scriptengine_v8) << "ScriptSignalV8Proxy::connect: " << thisProxy->fullName() << " fullName: " << fullName(); |
| 1700 | //Q_ASSERT(destFunction->InternalFieldCount() == 4); | ||
| 1701 | //Q_ASSERT(destData.get()->IsArray()); | ||
| 1702 | //v8::Local<v8::Value> destData = destFunction->GetInternalField(3); | ||
| 1703 | if (!destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData)) { | 1345 | if (!destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData)) { |
| 1704 | Q_ASSERT(false); | 1346 | Q_ASSERT(false); |
| 1705 | } | 1347 | } |
| 1706 | if (destData->IsArray()) { | 1348 | if (destData->IsArray()) { |
| 1707 | v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData); | 1349 | v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData); |
| 1708 | int length = destArray->Length();//destData.property("length").toInteger(); | 1350 | int length = destArray->Length(); |
| 1709 | // V8TODO: Maybe copying array is unnecessary? | 1351 | // V8TODO: Maybe copying array is unnecessary? |
| 1710 | v8::Local<v8::Array> newArray = v8::Array::New(isolate, length + 1); | 1352 | v8::Local<v8::Array> newArray = v8::Array::New(isolate, length + 1); |
| 1711 | bool foundIt = false; | 1353 | bool foundIt = false; |
| @@ -1726,7 +1368,6 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 14 unmodified lines | |||
| 1726 | } | 1368 | } |
| 1727 | } | 1369 | } |
| 1728 | if (!newArray->Set(destFunctionContext, length, v8ThisObject.get()).FromMaybe(false)) { | 1370 | if (!newArray->Set(destFunctionContext, length, v8ThisObject.get()).FromMaybe(false)) { |
| 1729 | //if (!newArray->Set(destFunctionContext, length, v8ThisObject.get()).FromMaybe(false)) { | ||
| 1730 | Q_ASSERT(false); | 1371 | Q_ASSERT(false); |
| 1731 | } | 1372 | } |
| 1732 | if (!destFunction->Set(destFunctionContext, destDataName, newArray).FromMaybe(false)) { | 1373 | if (!destFunction->Set(destFunctionContext, destDataName, newArray).FromMaybe(false)) { |
| @@ -1741,16 +1382,9 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 8 unmodified lines | |||
| 1741 | Q_ASSERT(false); | 1382 | Q_ASSERT(false); |
| 1742 | } | 1383 | } |
| 1743 | } | 1384 | } |
| 1744 | /*{ | ||
| 1745 | V8ScriptValueList args; | ||
| 1746 | args << thisObject(); | ||
| 1747 | destData.property("push").call(destData, args); | ||
| 1748 | }*/ | ||
| 1749 | 1385 | ||
| 1750 | // add this to our internal list of connections | 1386 | // add this to our internal list of connections |
| 1751 | Connection newConnection(callbackThis, callback); | 1387 | Connection newConnection(callbackThis, callback); |
| 1752 | //newConn.callback = callback; | ||
| 1753 | //newConn.thisValue = callbackThis; | ||
| 1754 | 1388 | ||
| 1755 | withWriteLock([&]{ | 1389 | withWriteLock([&]{ |
| 1756 | _connections.append(newConnection); | 1390 | _connections.append(newConnection); |
| @@ -1764,10 +1398,6 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 7 unmodified lines | |||
| 1764 | } | 1398 | } |
| 1765 | } | 1399 | } |
| 1766 | 1400 | ||
| 1767 | /*void ScriptSignalV8Proxy::disconnect(ScriptValue arg0) { | ||
| 1768 | disconnect(arg0, V8ScriptValue(_engine->getIsolate(), v8::Undefined(_engine->getIsolate()))); | ||
| 1769 | }*/ | ||
| 1770 | |||
| 1771 | void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) { | 1401 | void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) { |
| 1772 | QObject* qobject = _object; | 1402 | QObject* qobject = _object; |
| 1773 | v8::Isolate *isolate = _engine->getIsolate(); | 1403 | v8::Isolate *isolate = _engine->getIsolate(); |
| @@ -1832,18 +1462,15 @@ void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) { · 58 unmodified lines | |||
| 1832 | ScriptSignalV8Proxy* thisProxy = dynamic_cast<ScriptSignalV8Proxy*>(ScriptObjectV8Proxy::unwrapProxy(v8ThisObject)->toQObject()); | 1462 | ScriptSignalV8Proxy* thisProxy = dynamic_cast<ScriptSignalV8Proxy*>(ScriptObjectV8Proxy::unwrapProxy(v8ThisObject)->toQObject()); |
| 1833 | Q_ASSERT(thisProxy); | 1463 | Q_ASSERT(thisProxy); |
| 1834 | qCDebug(scriptengine_v8) << "ScriptSignalV8Proxy::disconnect: " << thisProxy->fullName() << " fullName: " << fullName(); | 1464 | qCDebug(scriptengine_v8) << "ScriptSignalV8Proxy::disconnect: " << thisProxy->fullName() << " fullName: " << fullName(); |
| 1835 | //V8ScriptValue destData = callback.data(); | ||
| 1836 | //Q_ASSERT(destData->IsArray()); | ||
| 1837 | if (!destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData)) { | 1465 | if (!destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData)) { |
| 1838 | Q_ASSERT(false); | 1466 | Q_ASSERT(false); |
| 1839 | } | 1467 | } |
| 1840 | if (destData->IsArray()) { | 1468 | if (destData->IsArray()) { |
| 1841 | v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData); | 1469 | v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData); |
| 1842 | int length = destArray->Length();//destData.property("length").toInteger(); | 1470 | int length = destArray->Length(); |
| 1843 | v8::Local<v8::Array> newArray = v8::Array::New(isolate, length - 1); | 1471 | v8::Local<v8::Array> newArray = v8::Array::New(isolate, length - 1); |
| 1844 | bool foundIt = false; | 1472 | bool foundIt = false; |
| 1845 | int newIndex = 0; | 1473 | int newIndex = 0; |
| 1846 | //for (int idx = 0; idx < length && !foundIt; ++idx) { | ||
| 1847 | for (int idx = 0; idx < length; ++idx) { | 1474 | for (int idx = 0; idx < length; ++idx) { |
| 1848 | v8::Local<v8::Value> entry = destArray->Get(destFunctionContext, idx).ToLocalChecked(); | 1475 | v8::Local<v8::Value> entry = destArray->Get(destFunctionContext, idx).ToLocalChecked(); |
| 1849 | // For debugging: | 1476 | // For debugging: |
| @@ -1863,9 +1490,6 @@ void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) { · 13 unmodified lines | |||
| 1863 | //V8TODO: compare proxies instead? | 1490 | //V8TODO: compare proxies instead? |
| 1864 | foundIt = true; | 1491 | foundIt = true; |
| 1865 | qCDebug(scriptengine_v8) << "ScriptSignalV8Proxy::disconnect foundIt"; | 1492 | qCDebug(scriptengine_v8) << "ScriptSignalV8Proxy::disconnect foundIt"; |
| 1866 | //V8ScriptValueList args; | ||
| 1867 | //args << idx << 1; | ||
| 1868 | //destData.property("splice").call(destData, args); | ||
| 1869 | } else { | 1493 | } else { |
| 1870 | if (!newArray->Set(destFunctionContext, newIndex, entry).FromMaybe(false)) { | 1494 | if (!newArray->Set(destFunctionContext, newIndex, entry).FromMaybe(false)) { |
| 1871 | Q_ASSERT(false); | 1495 | Q_ASSERT(false); |