History

Code cleanup

ksuprynowicz committed 3 years ago

Commit 5050cc91 parent d24038629 files · +57 −951Browse files

Showing the changes to libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp (1 of 29 files). Show all

Unified · Split

libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp+7−383
@@ -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
30Q_DECLARE_METATYPE(ScriptValue)27Q_DECLARE_METATYPE(ScriptValue)
31//V8TODO: default constructor would be needed
32//Q_DECLARE_METATYPE(V8ScriptValue)
33 28
34Q_DECLARE_METATYPE(QSharedPointer<ScriptObjectV8Proxy>)29Q_DECLARE_METATYPE(QSharedPointer<ScriptObjectV8Proxy>)
35Q_DECLARE_METATYPE(QSharedPointer<ScriptVariantV8Proxy>)30Q_DECLARE_METATYPE(QSharedPointer<ScriptVariantV8Proxy>)
@@ -76,7 +71,6 @@ private: // storage · 40 unmodified lines
76 71
77ScriptObjectV8Proxy::ScriptObjectV8Proxy(ScriptEngineV8* engine, QObject* object, bool ownsObject, const ScriptEngine::QObjectWrapOptions& options) :72ScriptObjectV8Proxy::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 up124 // 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
158ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val) {145ScriptObjectV8Proxy* 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-accessible275 // 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
408void ScriptObjectV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptObjectV8Proxy>& info) {373void 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
427ScriptObjectV8Proxy::QueryFlags ScriptObjectV8Proxy::queryProperty(const V8ScriptValue& object, const V8ScriptString& name, QueryFlags flags, uint* id) {388ScriptObjectV8Proxy::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 methods397 // 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 properties405 // 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
506void ScriptObjectV8Proxy::v8Get(v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {451void 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
554void ScriptObjectV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) {487void 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
601void ScriptObjectV8Proxy::v8GetPropertyNames(const v8::PropertyCallbackInfo<v8::Array>& info) {521void 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 instead615 } //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 map642 // 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 compilers698 // 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 proxy709 // 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
917void ScriptVariantV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) {820void 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
953void ScriptVariantV8Proxy::v8GetPropertyNames(const v8::PropertyCallbackInfo<v8::Array>& info) {850void 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
998ScriptMethodV8Proxy::~ScriptMethodV8Proxy() {885ScriptMethodV8Proxy::~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
1007void ScriptMethodV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptMethodV8Proxy>& info) {893void 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
1055void ScriptMethodV8Proxy::callback(const v8::FunctionCallbackInfo<v8::Value>& arguments) {926void 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
1456ScriptSignalV8Proxy::ScriptSignalV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, const QMetaMethod& meta) :1137ScriptSignalV8Proxy::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
1477void ScriptSignalV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptSignalV8Proxy>& info) {1158void 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_STATISTICS1255#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
1637void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) {1284void 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 arguments1296 // 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 connections1386 // 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
1771void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) {1401void 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);