History

Addeed V8 getters/setters to ScriptVariantV8Proxy, fixed animation scripting

ksuprynowicz committed 3 years ago

Commit 27554da1 parent 4e917654 files · +173 −10Browse files

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

Unified · Split

libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp+155−8
@@ -38,6 +38,9 @@ static const void *internalPointsToQObjectProxy = (void *)0x13370000; · 37 unmodified lines
38static const void *internalPointsToQVariantProxy = (void *)0x13371000;38static const void *internalPointsToQVariantProxy = (void *)0x13371000;
39//static const void *internalPointsToSignalProxy = (void *)0x13372000;39//static const void *internalPointsToSignalProxy = (void *)0x13372000;
40static const void *internalPointsToMethodProxy = (void *)0x13373000;40static const void *internalPointsToMethodProxy = (void *)0x13373000;
41// This is used to pass object in ScriptVariantV8Proxy to methods of prototype object, for example passing AnimationPointer to AnimationObject
42// Object is then converted using scriptvalue_cast for use inside the prototype
43static const void *internalPointsToQVariant = (void *)0x13374000;
41 44
42// Used strictly to replace the "this" object value for property access. May expand to a full context element45// Used strictly to replace the "this" object value for property access. May expand to a full context element
43// if we find it necessary to, but hopefully not needed46// if we find it necessary to, but hopefully not needed
@@ -703,6 +706,17 @@ void ScriptObjectV8Proxy::setProperty(V8ScriptValue& object, const V8ScriptStrin · 659 unmodified lines
703 706
704ScriptVariantV8Proxy::ScriptVariantV8Proxy(ScriptEngineV8* engine, const QVariant& variant, V8ScriptValue scriptProto, ScriptObjectV8Proxy* proto) :707ScriptVariantV8Proxy::ScriptVariantV8Proxy(ScriptEngineV8* engine, const QVariant& variant, V8ScriptValue scriptProto, ScriptObjectV8Proxy* proto) :
705 _engine(engine), _variant(variant), _scriptProto(scriptProto), _proto(proto) {708 _engine(engine), _variant(variant), _scriptProto(scriptProto), _proto(proto) {
709 auto isolate = engine->getIsolate();
710 v8::Locker locker(isolate);
711 v8::Isolate::Scope isolateScope(isolate);
712 v8::HandleScope handleScope(isolate);
713 v8::Context::Scope contextScope(engine->getContext());
714 auto variantDataTemplate = v8::ObjectTemplate::New(isolate);
715 variantDataTemplate->SetInternalFieldCount(2);
716 auto variantData = variantDataTemplate->NewInstance(engine->getContext()).ToLocalChecked();
717 variantData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariant));
718 variantData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(&_variant));
719 _v8Object.Reset(isolate, v8::Local<v8::Object>::Cast(variantData));
706 _name = QString::fromLatin1(variant.typeName());720 _name = QString::fromLatin1(variant.typeName());
707}721}
708 722
@@ -711,7 +725,7 @@ ScriptVariantV8Proxy::~ScriptVariantV8Proxy() { · 2 unmodified lines
711 v8::Locker locker(isolate);725 v8::Locker locker(isolate);
712 v8::Isolate::Scope isolateScope(isolate);726 v8::Isolate::Scope isolateScope(isolate);
713 v8::HandleScope handleScope(isolate);727 v8::HandleScope handleScope(isolate);
714 _v8ObjectTemplate.Reset();728 //_v8ObjectTemplate.Reset();
715 _v8Object.Reset();729 _v8Object.Reset();
716}730}
717 731
@@ -728,14 +742,15 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa · 10 unmodified lines
728 return V8ScriptValue(engine, v8::Undefined(isolate));742 return V8ScriptValue(engine, v8::Undefined(isolate));
729 }743 }
730 // V8TODO probably needs connection to be deleted744 // V8TODO probably needs connection to be deleted
731 // V8TODO what to do with proto variable?
732 auto proxy = new ScriptVariantV8Proxy(engine, variant, proto, protoProxy);745 auto proxy = new ScriptVariantV8Proxy(engine, variant, proto, protoProxy);
733 auto variantDataTemplate = v8::ObjectTemplate::New(isolate);746
734 variantDataTemplate->SetInternalFieldCount(2);747 auto variantProxyTemplate = v8::ObjectTemplate::New(isolate);
735 auto variantData = variantDataTemplate->NewInstance(engine->getContext()).ToLocalChecked();748 variantProxyTemplate->SetInternalFieldCount(2);
736 variantData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantProxy));749 variantProxyTemplate->SetHandler(v8::NamedPropertyHandlerConfiguration(v8Get, v8Set, nullptr, nullptr, v8GetPropertyNames));
737 variantData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(proxy));750 auto variantProxy = variantProxyTemplate->NewInstance(engine->getContext()).ToLocalChecked();
738 return V8ScriptValue(engine, variantData);751 variantProxy->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantProxy));
752 variantProxy->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(proxy));
753 return V8ScriptValue(engine, variantProxy);
739}754}
740 755
741ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) {756ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) {
@@ -759,9 +774,141 @@ ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val · 17 unmodified lines
759 return reinterpret_cast<ScriptVariantV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1));774 return reinterpret_cast<ScriptVariantV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1));
760}775}
761 776
777ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(v8::Isolate* isolate, v8::Local<v8::Value> &value) {
778 v8::Locker locker(isolate);
779 v8::Isolate::Scope isolateScope(isolate);
780 v8::HandleScope handleScope(isolate);
781
782 if (!value->IsObject()) {
783 return nullptr;
784 }
785 v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(value);
786 if (v8Object->InternalFieldCount() != 2) {
787 return nullptr;
788 }
789 if (v8Object->GetAlignedPointerFromInternalField(0) != internalPointsToQVariantProxy) {
790 return nullptr;
791 }
792 return reinterpret_cast<ScriptVariantV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1));
793}
794
795QVariant* ScriptVariantV8Proxy::unwrapQVariantPointer(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
796 v8::Locker locker(isolate);
797 v8::Isolate::Scope isolateScope(isolate);
798 v8::HandleScope handleScope(isolate);
799
800 if (!value->IsObject()) {
801 return nullptr;
802 }
803 v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(value);
804 if (v8Object->InternalFieldCount() != 2) {
805 return nullptr;
806 }
807 if (v8Object->GetAlignedPointerFromInternalField(0) != internalPointsToQVariant) {
808 return nullptr;
809 }
810 return reinterpret_cast<QVariant*>(v8Object->GetAlignedPointerFromInternalField(1));
811}
812
813
814void ScriptVariantV8Proxy::v8Get(v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
815 v8::HandleScope handleScope(info.GetIsolate());
816 v8::String::Utf8Value utf8Name(info.GetIsolate(), name);
817 v8::Local<v8::Value> objectV8 = info.This();
818 ScriptVariantV8Proxy *proxy = ScriptVariantV8Proxy::unwrapProxy(info.GetIsolate(), objectV8);
819 if (!proxy) {
820 qDebug(scriptengine) << "Proxy object not found when getting: " << *utf8Name;
821 return;
822 }
823 V8ScriptValue object(proxy->_engine, proxy->_v8Object.Get(info.GetIsolate()));
824
825 if (name->IsString()) {
826 V8ScriptString nameString(proxy->_engine, v8::Local<v8::String>::Cast(name));
827 uint id;
828 ScriptObjectV8Proxy::QueryFlags flags = proxy->_proto->queryProperty(object, nameString, ScriptObjectV8Proxy::HandlesReadAccess, &id);
829 if (flags) {
830 V8ScriptValue value = proxy->property(object, nameString, id);
831 info.GetReturnValue().Set(value.get());
832 return;
833 }
834 }
835
836 qDebug(scriptengine) << "Value not found: " << *utf8Name;
837 // V8TODO: this is done differently for variant proxy - use internal field of _v8Object instead?
838 /*v8::Local<v8::Value> property;
839 if(info.This()->GetInternalField(2).As<v8::Object>()->Get(proxy->_engine->getContext(), name).ToLocal(&property)) {
840 info.GetReturnValue().Set(property);
841 } else {
842 qDebug(scriptengine) << "Value not found: " << *utf8Value;
843 }*/
844}
845
846void ScriptVariantV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) {
847 v8::HandleScope handleScope(info.GetIsolate());
848 v8::String::Utf8Value utf8Name(info.GetIsolate(), name);
849 v8::Local<v8::Value> objectV8 = info.This();
850 ScriptVariantV8Proxy *proxy = ScriptVariantV8Proxy::unwrapProxy(info.GetIsolate(), objectV8);
851 if (!proxy) {
852 qDebug(scriptengine) << "Proxy object not found when getting: " << *utf8Name;
853 return;
854 }
855
856 V8ScriptValue object(proxy->_engine, objectV8);
857 if (!name->IsString() && !name->IsSymbol()) {
858 QString notStringMessage("ScriptObjectV8Proxy::v8Set: " + proxy->_engine->scriptValueDebugDetailsV8(V8ScriptValue(proxy->_engine, name)));
859 qDebug(scriptengine) << notStringMessage;
860 Q_ASSERT(false);
861 }
862
863 if (name->IsString()) {
864 V8ScriptString nameString(proxy->_engine, v8::Local<v8::String>::Cast(name));
865 uint id;
866 ScriptObjectV8Proxy::QueryFlags flags = proxy->_proto->queryProperty(object, nameString, ScriptObjectV8Proxy::HandlesWriteAccess, &id);
867 if (flags) {
868 proxy->setProperty(object, nameString, id, V8ScriptValue(proxy->_engine, value));
869 info.GetReturnValue().Set(value);
870 return;
871 }
872 }
873 // V8TODO: this is done differently for variant proxy - use internal field of _v8Object instead?
874 /*if (info.This()->GetInternalField(2).As<v8::Object>()->Set(proxy->_engine->getContext(), name, value).FromMaybe(false)) {
875 info.GetReturnValue().Set(value);
876 } else {
877 qDebug(scriptengine) << "Set failed: " << *utf8Name;
878 }*/
879 qDebug(scriptengine) << "Set failed: " << *utf8Name;
880}
881
882void ScriptVariantV8Proxy::v8GetPropertyNames(const v8::PropertyCallbackInfo<v8::Array>& info) {
883 qDebug(scriptengine) << "ScriptObjectV8Proxy::v8GetPropertyNames called";
884 v8::HandleScope handleScope(info.GetIsolate());
885 auto context = info.GetIsolate()->GetCurrentContext();
886 v8::Context::Scope contextScope(context);
887 v8::Local<v8::Value> objectV8 = info.This();
888 ScriptVariantV8Proxy *proxy = ScriptVariantV8Proxy::unwrapProxy(info.GetIsolate(), objectV8);
889 if (!proxy) {
890 qDebug(scriptengine) << "ScriptObjectV8Proxy::v8GetPropertyNames: Proxy object not found when listing";
891 return;
892 }
893 V8ScriptValue object(proxy->_engine, objectV8);
894 v8::Local<v8::Array> properties = proxy->_proto->getPropertyNames();
895 v8::Local<v8::Array> objectProperties;
896 // V8TODO: this is done differently for variant proxy - use internal field of _v8Object instead?
897 /*uint32_t propertiesLength = properties->Length();
898 if (info.This()->GetInternalField(2).As<v8::Object>()->GetPropertyNames(context).ToLocal(&objectProperties)) {
899 for (uint32_t n = 0; n < objectProperties->Length(); n++) {
900 if(!properties->Set(context, propertiesLength+n, objectProperties->Get(context, n).ToLocalChecked()).FromMaybe(false)) {
901 qDebug(scriptengine) << "ScriptObjectV8Proxy::v8GetPropertyNames: Cannot add member name";
902 }
903 }
904 }*/
905 info.GetReturnValue().Set(properties);
906}
907
762QVariant ScriptVariantV8Proxy::unwrap(const V8ScriptValue& val) {908QVariant ScriptVariantV8Proxy::unwrap(const V8ScriptValue& val) {
763 ScriptVariantV8Proxy* proxy = unwrapProxy(val);909 ScriptVariantV8Proxy* proxy = unwrapProxy(val);
764 return proxy ? proxy->toQVariant() : QVariant();910 return proxy ? proxy->toQVariant() : QVariant();
911 // V8TODO
765}912}
766 913
767ScriptMethodV8Proxy::ScriptMethodV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime,914ScriptMethodV8Proxy::ScriptMethodV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime,