Showing the changes to libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp (1 of 21 files). Show all
Unified · Split
| @@ -76,7 +76,7 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o · 75 unmodified lines | |||
| 76 | QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock(); | 76 | QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock(); |
| 77 | // V8TODO: is conversion to QVariant and back needed? | 77 | // V8TODO: is conversion to QVariant and back needed? |
| 78 | if (proxy) { | 78 | if (proxy) { |
| 79 | return V8ScriptValue(engine->getIsolate(), proxy.get()->toV8Value()); | 79 | return V8ScriptValue(engine, proxy.get()->toV8Value()); |
| 80 | } | 80 | } |
| 81 | //if (proxy) return engine->newObject(proxy.get(), engine->newVariant(QVariant::fromValue(proxy)));; | 81 | //if (proxy) return engine->newObject(proxy.get(), engine->newVariant(QVariant::fromValue(proxy)));; |
| 82 | } | 82 | } |
| @@ -111,7 +111,7 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o · 28 unmodified lines | |||
| 111 | QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock(); | 111 | QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock(); |
| 112 | //if (proxy) return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));; | 112 | //if (proxy) return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));; |
| 113 | if (proxy) { | 113 | if (proxy) { |
| 114 | return V8ScriptValue(engine->getIsolate(), proxy.get()->toV8Value()); | 114 | return V8ScriptValue(engine, proxy.get()->toV8Value()); |
| 115 | } | 115 | } |
| 116 | } | 116 | } |
| 117 | // V8TODO add a V8 callback that removes pointer for the script engine owned ob from the map so that it gets deleted | 117 | // V8TODO add a V8 callback that removes pointer for the script engine owned ob from the map so that it gets deleted |
| @@ -133,7 +133,7 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o · 15 unmodified lines | |||
| 133 | }); | 133 | }); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | return V8ScriptValue(engine->getIsolate(), proxy.get()->toV8Value()); | 136 | return V8ScriptValue(engine, proxy.get()->toV8Value()); |
| 137 | //return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy))); | 137 | //return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy))); |
| 138 | } | 138 | } |
| 139 | 139 | ||
| @@ -157,6 +157,25 @@ ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val) · 17 unmodified lines | |||
| 157 | return reinterpret_cast<ScriptObjectV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1)); | 157 | return reinterpret_cast<ScriptObjectV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1)); |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(v8::Isolate* isolate, v8::Local<v8::Value> &value) { | ||
| 161 | //V8TODO This shouldn't cause problems but I'm not sure if it's ok | ||
| 162 | v8::HandleScope handleScope(isolate); | ||
| 163 | if (!value->IsObject()) { | ||
| 164 | //qDebug(scriptengine) << "Cannot unwrap proxy - value is not an object"; | ||
| 165 | return nullptr; | ||
| 166 | } | ||
| 167 | v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(value); | ||
| 168 | if (v8Object->InternalFieldCount() != 3) { | ||
| 169 | //qDebug(scriptengine) << "Cannot unwrap proxy - wrong number of internal fields"; | ||
| 170 | return nullptr; | ||
| 171 | } | ||
| 172 | if (v8Object->GetAlignedPointerFromInternalField(0) != internalPointsToQObjectProxy) { | ||
| 173 | qDebug(scriptengine) << "Cannot unwrap proxy - internal fields don't point to object proxy"; | ||
| 174 | return nullptr; | ||
| 175 | } | ||
| 176 | return reinterpret_cast<ScriptObjectV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1)); | ||
| 177 | } | ||
| 178 | |||
| 160 | QObject* ScriptObjectV8Proxy::unwrap(const V8ScriptValue& val) { | 179 | QObject* ScriptObjectV8Proxy::unwrap(const V8ScriptValue& val) { |
| 161 | ScriptObjectV8Proxy* proxy = unwrapProxy(val); | 180 | ScriptObjectV8Proxy* proxy = unwrapProxy(val); |
| 162 | return proxy ? proxy->toQObject() : nullptr; | 181 | return proxy ? proxy->toQObject() : nullptr; |
| @@ -209,7 +228,7 @@ void ScriptObjectV8Proxy::investigate() { · 46 unmodified lines | |||
| 209 | } | 228 | } |
| 210 | 229 | ||
| 211 | auto v8Name = v8::String::NewFromUtf8(_engine->getIsolate(), prop.name()).ToLocalChecked(); | 230 | auto v8Name = v8::String::NewFromUtf8(_engine->getIsolate(), prop.name()).ToLocalChecked(); |
| 212 | PropertyDef& propDef = _props.insert(idx, PropertyDef(_engine->getIsolate(), v8Name)).value(); | 231 | PropertyDef& propDef = _props.insert(idx, PropertyDef(_engine, v8Name)).value(); |
| 213 | propDef.flags = ScriptValue::Undeletable | ScriptValue::PropertyGetter | ScriptValue::PropertySetter | | 232 | propDef.flags = ScriptValue::Undeletable | ScriptValue::PropertyGetter | ScriptValue::PropertySetter | |
| 214 | ScriptValue::QObjectMember; | 233 | ScriptValue::QObjectMember; |
| 215 | if (prop.isConstant()) propDef.flags |= ScriptValue::ReadOnly; | 234 | if (prop.isConstant()) propDef.flags |= ScriptValue::ReadOnly; |
| @@ -248,11 +267,11 @@ void ScriptObjectV8Proxy::investigate() { · 32 unmodified lines | |||
| 248 | } | 267 | } |
| 249 | 268 | ||
| 250 | auto nameString = v8::String::NewFromUtf8(_engine->getIsolate(), szName.data(), v8::NewStringType::kNormal, szName.length()).ToLocalChecked(); | 269 | auto nameString = v8::String::NewFromUtf8(_engine->getIsolate(), szName.data(), v8::NewStringType::kNormal, szName.length()).ToLocalChecked(); |
| 251 | V8ScriptString name(_engine->getIsolate(), nameString); | 270 | V8ScriptString name(_engine, nameString); |
| 252 | auto nameLookup = methodNames.find(name); | 271 | auto nameLookup = methodNames.find(name); |
| 253 | if (isSignal) { | 272 | if (isSignal) { |
| 254 | if (nameLookup == methodNames.end()) { | 273 | if (nameLookup == methodNames.end()) { |
| 255 | SignalDef& signalDef = _signals.insert(idx, SignalDef(_engine->getIsolate(), name.get())).value(); | 274 | SignalDef& signalDef = _signals.insert(idx, SignalDef(_engine, name.get())).value(); |
| 256 | signalDef.name = name; | 275 | signalDef.name = name; |
| 257 | signalDef.signal = method; | 276 | signalDef.signal = method; |
| 258 | //qDebug(scriptengine) << "Utf8Value 1: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), nameString)); | 277 | //qDebug(scriptengine) << "Utf8Value 1: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), nameString)); |
| @@ -280,7 +299,7 @@ void ScriptObjectV8Proxy::investigate() { · 21 unmodified lines | |||
| 280 | } | 299 | } |
| 281 | } | 300 | } |
| 282 | if (nameLookup == methodNames.end()) { | 301 | if (nameLookup == methodNames.end()) { |
| 283 | MethodDef& methodDef = _methods.insert(idx, MethodDef(_engine->getIsolate(), name.get())).value(); | 302 | MethodDef& methodDef = _methods.insert(idx, MethodDef(_engine, name.get())).value(); |
| 284 | methodDef.name = name; | 303 | methodDef.name = name; |
| 285 | methodDef.numMaxParms = parameterCount; | 304 | methodDef.numMaxParms = parameterCount; |
| 286 | methodDef.methods.append(method); | 305 | methodDef.methods.append(method); |
| @@ -308,7 +327,8 @@ void ScriptObjectV8Proxy::investigate() { · 21 unmodified lines | |||
| 308 | // Add all the methods objects as properties - this allows adding properties to a given method later. Is used by Script.request. | 327 | // Add all the methods objects as properties - this allows adding properties to a given method later. Is used by Script.request. |
| 309 | // V8TODO: Should these be deleted when the script-owned object is destroyed? It needs checking if script-owned objects will be garbage-collected, or will self-referencing prevent it. | 328 | // V8TODO: Should these be deleted when the script-owned object is destroyed? It needs checking if script-owned objects will be garbage-collected, or will self-referencing prevent it. |
| 310 | for (auto i = _methods.begin(); i != _methods.end(); i++) { | 329 | for (auto i = _methods.begin(); i != _methods.end(); i++) { |
| 311 | V8ScriptValue method = ScriptMethodV8Proxy::newMethod(_engine, qobject, V8ScriptValue(_engine->getIsolate(), v8Object), i.value().methods, i.value().numMaxParms); | 330 | V8ScriptValue method = ScriptMethodV8Proxy::newMethod(_engine, qobject, V8ScriptValue(_engine, v8Object), |
| 331 | i.value().methods, i.value().numMaxParms); | ||
| 312 | if(!propertiesObject->Set(_engine->getContext(), i.value().name.constGet(), method.get()).FromMaybe(false)) { | 332 | if(!propertiesObject->Set(_engine->getContext(), i.value().name.constGet(), method.get()).FromMaybe(false)) { |
| 313 | Q_ASSERT(false); | 333 | Q_ASSERT(false); |
| 314 | } | 334 | } |
| @@ -389,13 +409,15 @@ void ScriptObjectV8Proxy::v8Get(v8::Local<v8::Name> name, const v8::PropertyCall · 74 unmodified lines | |||
| 389 | v8::HandleScope handleScope(info.GetIsolate()); | 409 | v8::HandleScope handleScope(info.GetIsolate()); |
| 390 | v8::String::Utf8Value utf8Value(info.GetIsolate(), name); | 410 | v8::String::Utf8Value utf8Value(info.GetIsolate(), name); |
| 391 | //qDebug(scriptengine) << "Get: " << *utf8Value; | 411 | //qDebug(scriptengine) << "Get: " << *utf8Value; |
| 392 | V8ScriptValue object(info.GetIsolate(), info.This()); | 412 | v8::Local<v8::Value> objectV8 = info.This(); |
| 393 | ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(object); | 413 | ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8); |
| 394 | if (!proxy) { | 414 | if (!proxy) { |
| 395 | qDebug(scriptengine) << "Proxy object not found when getting: " << *utf8Value; | 415 | qDebug(scriptengine) << "Proxy object not found when getting: " << *utf8Value; |
| 396 | return; | 416 | return; |
| 397 | } | 417 | } |
| 398 | V8ScriptString nameString(info.GetIsolate(), v8::Local<v8::String>::Cast(name)); | 418 | V8ScriptValue object(proxy->_engine, objectV8); |
| 419 | Q_ASSERT(name->IsString()); | ||
| 420 | V8ScriptString nameString(proxy->_engine, v8::Local<v8::String>::Cast(name)); | ||
| 399 | uint id; | 421 | uint id; |
| 400 | QueryFlags flags = proxy->queryProperty(object, nameString, HandlesReadAccess, &id); | 422 | QueryFlags flags = proxy->queryProperty(object, nameString, HandlesReadAccess, &id); |
| 401 | if (flags) { | 423 | if (flags) { |
| @@ -415,18 +437,20 @@ void ScriptObjectV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> v · 13 unmodified lines | |||
| 415 | v8::HandleScope handleScope(info.GetIsolate()); | 437 | v8::HandleScope handleScope(info.GetIsolate()); |
| 416 | v8::String::Utf8Value utf8Value(info.GetIsolate(), name); | 438 | v8::String::Utf8Value utf8Value(info.GetIsolate(), name); |
| 417 | //qDebug(scriptengine) << "Set: " << *utf8Value; | 439 | //qDebug(scriptengine) << "Set: " << *utf8Value; |
| 418 | V8ScriptValue object(info.GetIsolate(), info.This()); | 440 | v8::Local<v8::Value> objectV8 = info.This(); |
| 419 | ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(object); | 441 | ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8); |
| 420 | if (!proxy) { | 442 | if (!proxy) { |
| 421 | qDebug(scriptengine) << "Proxy object not found when setting: " << *utf8Value; | 443 | qDebug(scriptengine) << "Proxy object not found when setting: " << *utf8Value; |
| 422 | return; | 444 | return; |
| 423 | } | 445 | } |
| 424 | V8ScriptString nameString(info.GetIsolate(), v8::Local<v8::String>::Cast(name)); | 446 | V8ScriptValue object(proxy->_engine, objectV8); |
| 447 | Q_ASSERT(name->IsString()); | ||
| 448 | V8ScriptString nameString(proxy->_engine, v8::Local<v8::String>::Cast(name)); | ||
| 425 | //V8ScriptString nameString(info.GetIsolate(), name->ToString(proxy->_engine->getContext()).ToLocalChecked()); | 449 | //V8ScriptString nameString(info.GetIsolate(), name->ToString(proxy->_engine->getContext()).ToLocalChecked()); |
| 426 | uint id; | 450 | uint id; |
| 427 | QueryFlags flags = proxy->queryProperty(object, nameString, HandlesWriteAccess, &id); | 451 | QueryFlags flags = proxy->queryProperty(object, nameString, HandlesWriteAccess, &id); |
| 428 | if (flags) { | 452 | if (flags) { |
| 429 | proxy->setProperty(object, nameString, id, V8ScriptValue(info.GetIsolate(), value)); | 453 | proxy->setProperty(object, nameString, id, V8ScriptValue(proxy->_engine, value)); |
| 430 | info.GetReturnValue().Set(value); | 454 | info.GetReturnValue().Set(value); |
| 431 | } else { | 455 | } else { |
| 432 | // V8TODO: Should it be v8::Object or v8::Local<v8::Object>? | 456 | // V8TODO: Should it be v8::Object or v8::Local<v8::Object>? |
| @@ -447,7 +471,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 14 unmodified lines | |||
| 447 | QObject* qobject = _object; | 471 | QObject* qobject = _object; |
| 448 | if (!qobject) { | 472 | if (!qobject) { |
| 449 | _engine->getIsolate()->ThrowError("Referencing deleted native object"); | 473 | _engine->getIsolate()->ThrowError("Referencing deleted native object"); |
| 450 | return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate())); | 474 | return V8ScriptValue(_engine, v8::Null(_engine->getIsolate())); |
| 451 | } | 475 | } |
| 452 | 476 | ||
| 453 | const QMetaObject* metaObject = qobject->metaObject(); | 477 | const QMetaObject* metaObject = qobject->metaObject(); |
| @@ -456,7 +480,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 2 unmodified lines | |||
| 456 | case PROPERTY_TYPE: { | 480 | case PROPERTY_TYPE: { |
| 457 | int propId = id & ~TYPE_MASK; | 481 | int propId = id & ~TYPE_MASK; |
| 458 | PropertyDefMap::const_iterator lookup = _props.find(propId); | 482 | PropertyDefMap::const_iterator lookup = _props.find(propId); |
| 459 | if (lookup == _props.cend()) return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate())); | 483 | if (lookup == _props.cend()) return V8ScriptValue(_engine, v8::Null(_engine->getIsolate())); |
| 460 | 484 | ||
| 461 | QMetaProperty prop = metaObject->property(propId); | 485 | QMetaProperty prop = metaObject->property(propId); |
| 462 | ScriptValue scriptThis = ScriptValue(new ScriptValueV8Wrapper(_engine, object)); | 486 | ScriptValue scriptThis = ScriptValue(new ScriptValueV8Wrapper(_engine, object)); |
| @@ -469,7 +493,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 6 unmodified lines | |||
| 469 | case METHOD_TYPE: { | 493 | case METHOD_TYPE: { |
| 470 | int methodId = id & ~TYPE_MASK; | 494 | int methodId = id & ~TYPE_MASK; |
| 471 | MethodDefMap::const_iterator lookup = _methods.find(methodId); | 495 | MethodDefMap::const_iterator lookup = _methods.find(methodId); |
| 472 | if (lookup == _methods.cend()) return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate())); | 496 | if (lookup == _methods.cend()) return V8ScriptValue(_engine, v8::Null(_engine->getIsolate())); |
| 473 | const MethodDef& methodDef = lookup.value(); | 497 | const MethodDef& methodDef = lookup.value(); |
| 474 | for (auto iter = methodDef.methods.begin(); iter != methodDef.methods.end(); iter++ ) { | 498 | for (auto iter = methodDef.methods.begin(); iter != methodDef.methods.end(); iter++ ) { |
| 475 | if((*iter).returnType() == QMetaType::UnknownType) { | 499 | if((*iter).returnType() == QMetaType::UnknownType) { |
| @@ -480,7 +504,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 4 unmodified lines | |||
| 480 | v8::Local<v8::Value> property; | 504 | v8::Local<v8::Value> property; |
| 481 | if(_v8Object.Get(_engine->getIsolate())->GetInternalField(2).As<v8::Object>()->Get(_engine->getContext(), name.constGet()).ToLocal(&property)) { | 505 | if(_v8Object.Get(_engine->getIsolate())->GetInternalField(2).As<v8::Object>()->Get(_engine->getContext(), name.constGet()).ToLocal(&property)) { |
| 482 | if (!property->IsUndefined()) { | 506 | if (!property->IsUndefined()) { |
| 483 | return V8ScriptValue(_engine->getIsolate(), property); | 507 | return V8ScriptValue(_engine, property); |
| 484 | } | 508 | } |
| 485 | } | 509 | } |
| 486 | Q_ASSERT(false); | 510 | Q_ASSERT(false); |
| @@ -490,7 +514,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 3 unmodified lines | |||
| 490 | case SIGNAL_TYPE: { | 514 | case SIGNAL_TYPE: { |
| 491 | int signalId = id & ~TYPE_MASK; | 515 | int signalId = id & ~TYPE_MASK; |
| 492 | SignalDefMap::const_iterator defLookup = _signals.find(signalId); | 516 | SignalDefMap::const_iterator defLookup = _signals.find(signalId); |
| 493 | if (defLookup == _signals.cend()) return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate())); | 517 | if (defLookup == _signals.cend()) return V8ScriptValue(_engine, v8::Null(_engine->getIsolate())); |
| 494 | 518 | ||
| 495 | InstanceMap::const_iterator instLookup = _signalInstances.find(signalId); | 519 | InstanceMap::const_iterator instLookup = _signalInstances.find(signalId); |
| 496 | if (instLookup == _signalInstances.cend() || instLookup.value().isNull()) { | 520 | if (instLookup == _signalInstances.cend() || instLookup.value().isNull()) { |
| @@ -508,7 +532,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 11 unmodified lines | |||
| 508 | //return _engine->newQObject(proxy, ScriptEngine::ScriptOwnership, options); | 532 | //return _engine->newQObject(proxy, ScriptEngine::ScriptOwnership, options); |
| 509 | } | 533 | } |
| 510 | } | 534 | } |
| 511 | return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate())); | 535 | return V8ScriptValue(_engine, v8::Null(_engine->getIsolate())); |
| 512 | } | 536 | } |
| 513 | 537 | ||
| 514 | void ScriptObjectV8Proxy::setProperty(V8ScriptValue& object, const V8ScriptString& name, uint id, const V8ScriptValue& value) { | 538 | void ScriptObjectV8Proxy::setProperty(V8ScriptValue& object, const V8ScriptString& name, uint id, const V8ScriptValue& value) { |
| @@ -562,7 +586,7 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa · 47 unmodified lines | |||
| 562 | if (!protoProxy) { | 586 | if (!protoProxy) { |
| 563 | Q_ASSERT(protoProxy); | 587 | Q_ASSERT(protoProxy); |
| 564 | //return engine->newVariant(variant); | 588 | //return engine->newVariant(variant); |
| 565 | return V8ScriptValue(engine->getIsolate(), v8::Undefined(engine->getIsolate())); | 589 | return V8ScriptValue(engine, v8::Undefined(engine->getIsolate())); |
| 566 | } | 590 | } |
| 567 | // V8TODO probably needs connection to be deleted | 591 | // V8TODO probably needs connection to be deleted |
| 568 | // V8TODO what to do with proto variable? | 592 | // V8TODO what to do with proto variable? |
| @@ -572,7 +596,7 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa · 3 unmodified lines | |||
| 572 | auto variantData = variantDataTemplate->NewInstance(engine->getContext()).ToLocalChecked(); | 596 | auto variantData = variantDataTemplate->NewInstance(engine->getContext()).ToLocalChecked(); |
| 573 | variantData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantProxy)); | 597 | variantData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantProxy)); |
| 574 | variantData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(proxy)); | 598 | variantData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(proxy)); |
| 575 | return V8ScriptValue(engine->getIsolate(), variantData); | 599 | return V8ScriptValue(engine, variantData); |
| 576 | } | 600 | } |
| 577 | 601 | ||
| 578 | ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) { | 602 | ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) { |
| @@ -620,7 +644,7 @@ V8ScriptValue ScriptMethodV8Proxy::newMethod(ScriptEngineV8* engine, QObject* ob · 41 unmodified lines | |||
| 620 | // V8TODO it needs to be deleted somehow on object destruction | 644 | // V8TODO it needs to be deleted somehow on object destruction |
| 621 | methodData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(new ScriptMethodV8Proxy(engine, object, lifetime, metas, numMaxParams))); | 645 | methodData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(new ScriptMethodV8Proxy(engine, object, lifetime, metas, numMaxParams))); |
| 622 | auto v8Function = v8::Function::New(engine->getContext(), callback, methodData, numMaxParams).ToLocalChecked(); | 646 | auto v8Function = v8::Function::New(engine->getContext(), callback, methodData, numMaxParams).ToLocalChecked(); |
| 623 | return V8ScriptValue(engine->getIsolate(), v8Function); | 647 | return V8ScriptValue(engine, v8Function); |
| 624 | } | 648 | } |
| 625 | 649 | ||
| 626 | QString ScriptMethodV8Proxy::fullName() const { | 650 | QString ScriptMethodV8Proxy::fullName() const { |
| @@ -722,11 +746,11 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 95 unmodified lines | |||
| 722 | Q_ASSERT(methodArgTypeId != QMetaType::UnknownType); | 746 | Q_ASSERT(methodArgTypeId != QMetaType::UnknownType); |
| 723 | v8::Local<v8::Value> argVal = arguments[arg]; | 747 | v8::Local<v8::Value> argVal = arguments[arg]; |
| 724 | if (methodArgTypeId == scriptValueTypeId) { | 748 | if (methodArgTypeId == scriptValueTypeId) { |
| 725 | qScriptArgLists[i].append(ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(isolate, argVal)))); | 749 | qScriptArgLists[i].append(ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine, argVal)))); |
| 726 | qGenArgsVectors[i][arg] = Q_ARG(ScriptValue, qScriptArgLists[i].back()); | 750 | qGenArgsVectors[i][arg] = Q_ARG(ScriptValue, qScriptArgLists[i].back()); |
| 727 | } else if (methodArgTypeId == QMetaType::QVariant) { | 751 | } else if (methodArgTypeId == QMetaType::QVariant) { |
| 728 | QVariant varArgVal; | 752 | QVariant varArgVal; |
| 729 | if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) { | 753 | if (!_engine->castValueToVariant(V8ScriptValue(_engine, argVal), varArgVal, methodArgTypeId)) { |
| 730 | conversionFailures++; | 754 | conversionFailures++; |
| 731 | } else { | 755 | } else { |
| 732 | qVarArgLists[i].append(varArgVal); | 756 | qVarArgLists[i].append(varArgVal); |
| @@ -734,12 +758,12 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 1 unmodified line | |||
| 734 | } | 758 | } |
| 735 | } else { | 759 | } else { |
| 736 | QVariant varArgVal; | 760 | QVariant varArgVal; |
| 737 | if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) { | 761 | if (!_engine->castValueToVariant(V8ScriptValue(_engine, argVal), varArgVal, methodArgTypeId)) { |
| 738 | conversionFailures++; | 762 | conversionFailures++; |
| 739 | } else { | 763 | } else { |
| 740 | qVarArgLists[i].append(varArgVal); | 764 | qVarArgLists[i].append(varArgVal); |
| 741 | const QVariant& converted = qVarArgLists[i].back(); | 765 | const QVariant& converted = qVarArgLists[i].back(); |
| 742 | conversionPenaltyScore = _engine->computeCastPenalty(V8ScriptValue(isolate, argVal), methodArgTypeId); | 766 | conversionPenaltyScore = _engine->computeCastPenalty(V8ScriptValue(_engine, argVal), methodArgTypeId); |
| 743 | 767 | ||
| 744 | // a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant | 768 | // a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant |
| 745 | // A const_cast is needed because calling data() would detach the QVariant. | 769 | // A const_cast is needed because calling data() would detach the QVariant. |
| @@ -834,9 +858,9 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 88 unmodified lines | |||
| 834 | v8::Local<v8::Value> argVal = arguments[arg]; | 858 | v8::Local<v8::Value> argVal = arguments[arg]; |
| 835 | if (methodArgTypeId != scriptValueTypeId) { | 859 | if (methodArgTypeId != scriptValueTypeId) { |
| 836 | QVariant varArgVal; | 860 | QVariant varArgVal; |
| 837 | if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) { | 861 | if (!_engine->castValueToVariant(V8ScriptValue(_engine, argVal), varArgVal, methodArgTypeId)) { |
| 838 | QByteArray methodTypeName = QMetaType(methodArgTypeId).name(); | 862 | QByteArray methodTypeName = QMetaType(methodArgTypeId).name(); |
| 839 | QByteArray argTypeName = _engine->valueType(V8ScriptValue(isolate, argVal)).toLatin1(); | 863 | QByteArray argTypeName = _engine->valueType(V8ScriptValue(_engine, argVal)).toLatin1(); |
| 840 | QString errorMessage = QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4") | 864 | QString errorMessage = QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4") |
| 841 | .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName); | 865 | .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName); |
| 842 | qDebug(scriptengine) << errorMessage << "\n Backtrace:" << _engine->currentContext()->backtrace(); | 866 | qDebug(scriptengine) << errorMessage << "\n Backtrace:" << _engine->currentContext()->backtrace(); |
| @@ -1043,6 +1067,8 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu · 200 unmodified lines | |||
| 1043 | v8::Locker locker(isolate); | 1067 | v8::Locker locker(isolate); |
| 1044 | v8::Isolate::Scope isolateScope(isolate); | 1068 | v8::Isolate::Scope isolateScope(isolate); |
| 1045 | v8::HandleScope handleScope(isolate); | 1069 | v8::HandleScope handleScope(isolate); |
| 1070 | // V8TODO: should we use function creation context, or context in which connect happened? | ||
| 1071 | |||
| 1046 | auto context = _engine->getContext(); | 1072 | auto context = _engine->getContext(); |
| 1047 | v8::Context::Scope contextScope(context); | 1073 | v8::Context::Scope contextScope(context); |
| 1048 | 1074 | ||
| @@ -1063,20 +1089,29 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu · 14 unmodified lines | |||
| 1063 | 1089 | ||
| 1064 | for (ConnectionList::iterator iter = connections.begin(); iter != connections.end(); ++iter) { | 1090 | for (ConnectionList::iterator iter = connections.begin(); iter != connections.end(); ++iter) { |
| 1065 | Connection& conn = *iter; | 1091 | Connection& conn = *iter; |
| 1066 | v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(conn.callback.get()); | 1092 | Q_ASSERT(!conn.callback.get().IsEmpty()); |
| 1067 | v8::Local<v8::Value> v8This; | 1093 | Q_ASSERT(!conn.callback.get()->IsUndefined()); |
| 1068 | if (conn.thisValue.get()->IsObject()) { | 1094 | Q_ASSERT(conn.callback.get()->IsFunction()); |
| 1069 | v8This = conn.thisValue.get(); | 1095 | { |
| 1070 | } else { | 1096 | v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(conn.callback.get()); |
| 1071 | v8This = _engine->getContext()->Global(); | 1097 | auto functionContext = callback->CreationContext(); |
| 1072 | } | 1098 | _engine->pushContext(functionContext); |
| 1099 | v8::Context::Scope functionContextScope(functionContext); | ||
| 1100 | v8::Local<v8::Value> v8This; | ||
| 1101 | if (conn.thisValue.get()->IsObject()) { | ||
| 1102 | v8This = conn.thisValue.get(); | ||
| 1103 | } else { | ||
| 1104 | v8This = _engine->getContext()->Global(); | ||
| 1105 | } | ||
| 1073 | 1106 | ||
| 1074 | v8::TryCatch tryCatch(isolate); | 1107 | v8::TryCatch tryCatch(isolate); |
| 1075 | callback->Call(_engine->getContext(), v8This, numArgs, args); | 1108 | callback->Call(_engine->getContext(), v8This, numArgs, args); |
| 1076 | if (tryCatch.HasCaught()) { | 1109 | if (tryCatch.HasCaught()) { |
| 1077 | qCDebug(scriptengine) << "Signal proxy " << fullName() << " connection call failed: \"" | 1110 | qCDebug(scriptengine) << "Signal proxy " << fullName() << " connection call failed: \"" |
| 1078 | << _engine->formatErrorMessageFromTryCatch(tryCatch) | 1111 | << _engine->formatErrorMessageFromTryCatch(tryCatch) |
| 1079 | << "\nThis provided: " << conn.thisValue.get()->IsObject(); | 1112 | << "\nThis provided: " << conn.thisValue.get()->IsObject(); |
| 1113 | } | ||
| 1114 | _engine->popContext(); | ||
| 1080 | } | 1115 | } |
| 1081 | } | 1116 | } |
| 1082 | 1117 | ||
| @@ -1125,8 +1160,8 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 42 unmodified lines | |||
| 1125 | //v8::HandleScope handleScope(isolate); | 1160 | //v8::HandleScope handleScope(isolate); |
| 1126 | 1161 | ||
| 1127 | // untangle the arguments | 1162 | // untangle the arguments |
| 1128 | V8ScriptValue callback(isolate, v8::Null(isolate)); | 1163 | V8ScriptValue callback(_engine, v8::Null(isolate)); |
| 1129 | V8ScriptValue callbackThis(isolate, v8::Null(isolate)); | 1164 | V8ScriptValue callbackThis(_engine, v8::Null(isolate)); |
| 1130 | if (arg1.isFunction()) { | 1165 | if (arg1.isFunction()) { |
| 1131 | auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0); | 1166 | auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0); |
| 1132 | auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1); | 1167 | auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1); |
| @@ -1158,6 +1193,9 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 25 unmodified lines | |||
| 1158 | } | 1193 | } |
| 1159 | 1194 | ||
| 1160 | // add a reference to ourselves to the destination callback | 1195 | // add a reference to ourselves to the destination callback |
| 1196 | Q_ASSERT(!callback.get().IsEmpty()); | ||
| 1197 | Q_ASSERT(!callback.get()->IsUndefined()); | ||
| 1198 | Q_ASSERT(callback.get()->IsFunction()); | ||
| 1161 | v8::Local<v8::Function> destFunction = v8::Local<v8::Function>::Cast(callback.get()); | 1199 | v8::Local<v8::Function> destFunction = v8::Local<v8::Function>::Cast(callback.get()); |
| 1162 | v8::Local<v8::String> destDataName = v8::String::NewFromUtf8(isolate, "__data__").ToLocalChecked(); | 1200 | v8::Local<v8::String> destDataName = v8::String::NewFromUtf8(isolate, "__data__").ToLocalChecked(); |
| 1163 | v8::Local<v8::Value> destData; | 1201 | v8::Local<v8::Value> destData; |
| @@ -1166,7 +1204,10 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 2 unmodified lines | |||
| 1166 | //Q_ASSERT(destFunction->InternalFieldCount() == 4); | 1204 | //Q_ASSERT(destFunction->InternalFieldCount() == 4); |
| 1167 | //Q_ASSERT(destData.get()->IsArray()); | 1205 | //Q_ASSERT(destData.get()->IsArray()); |
| 1168 | //v8::Local<v8::Value> destData = destFunction->GetInternalField(3); | 1206 | //v8::Local<v8::Value> destData = destFunction->GetInternalField(3); |
| 1169 | if (destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData) && destData->IsArray()) { | 1207 | if (!destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData)) { |
| 1208 | Q_ASSERT(false); | ||
| 1209 | } | ||
| 1210 | if (destData->IsArray()) { | ||
| 1170 | v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData); | 1211 | v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData); |
| 1171 | int length = destArray->Length();//destData.property("length").toInteger(); | 1212 | int length = destArray->Length();//destData.property("length").toInteger(); |
| 1172 | v8::Local<v8::Array> newArray = v8::Array::New(isolate, length + 1); | 1213 | v8::Local<v8::Array> newArray = v8::Array::New(isolate, length + 1); |
| @@ -1232,8 +1273,8 @@ void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) { · 59 unmodified lines | |||
| 1232 | v8::Context::Scope contextScope(_engine->getContext()); | 1273 | v8::Context::Scope contextScope(_engine->getContext()); |
| 1233 | 1274 | ||
| 1234 | // untangle the arguments | 1275 | // untangle the arguments |
| 1235 | V8ScriptValue callback(isolate, v8::Null(isolate)); | 1276 | V8ScriptValue callback(_engine, v8::Null(isolate)); |
| 1236 | V8ScriptValue callbackThis(isolate, v8::Null(isolate)); | 1277 | V8ScriptValue callbackThis(_engine, v8::Null(isolate)); |
| 1237 | if (arg1.isFunction()) { | 1278 | if (arg1.isFunction()) { |
| 1238 | auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0); | 1279 | auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0); |
| 1239 | auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1); | 1280 | auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1); |
| @@ -1277,7 +1318,10 @@ void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) { · 37 unmodified lines | |||
| 1277 | V8ScriptValue v8ThisObject = ScriptValueV8Wrapper::fullUnwrap(_engine, thisObject()); | 1318 | V8ScriptValue v8ThisObject = ScriptValueV8Wrapper::fullUnwrap(_engine, thisObject()); |
| 1278 | //V8ScriptValue destData = callback.data(); | 1319 | //V8ScriptValue destData = callback.data(); |
| 1279 | //Q_ASSERT(destData->IsArray()); | 1320 | //Q_ASSERT(destData->IsArray()); |
| 1280 | if (destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData) && destData->IsArray()) { | 1321 | if (!destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData)) { |
| 1322 | Q_ASSERT(false); | ||
| 1323 | } | ||
| 1324 | if (destData->IsArray()) { | ||
| 1281 | v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData); | 1325 | v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData); |
| 1282 | int length = destArray->Length();//destData.property("length").toInteger(); | 1326 | int length = destArray->Length();//destData.property("length").toInteger(); |
| 1283 | v8::Local<v8::Array> newArray = v8::Array::New(isolate, length - 1); | 1327 | v8::Local<v8::Array> newArray = v8::Array::New(isolate, length - 1); |