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
3838 static const void *internalPointsToQVariantProxy = (void *)0x13371000;
3939 //static const void *internalPointsToSignalProxy = (void *)0x13372000;
4040 static 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
43+static const void *internalPointsToQVariant = (void *)0x13374000;
4144
4245 // Used strictly to replace the "this" object value for property access. May expand to a full context element
4346 // if we find it necessary to, but hopefully not needed
@@ -703,6 +706,17 @@ void ScriptObjectV8Proxy::setProperty(V8ScriptValue& object, const V8ScriptStrin · 659 unmodified lines
703706
704707 ScriptVariantV8Proxy::ScriptVariantV8Proxy(ScriptEngineV8* engine, const QVariant& variant, V8ScriptValue scriptProto, ScriptObjectV8Proxy* proto) :
705708 _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));
706720 _name = QString::fromLatin1(variant.typeName());
707721 }
708722
@@ -711,7 +725,7 @@ ScriptVariantV8Proxy::~ScriptVariantV8Proxy() { · 2 unmodified lines
711725 v8::Locker locker(isolate);
712726 v8::Isolate::Scope isolateScope(isolate);
713727 v8::HandleScope handleScope(isolate);
714− _v8ObjectTemplate.Reset();
728+ //_v8ObjectTemplate.Reset();
715729 _v8Object.Reset();
716730 }
717731
@@ -728,14 +742,15 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa · 10 unmodified lines
728742 return V8ScriptValue(engine, v8::Undefined(isolate));
729743 }
730744 // V8TODO probably needs connection to be deleted
731− // V8TODO what to do with proto variable?
732745 auto proxy = new ScriptVariantV8Proxy(engine, variant, proto, protoProxy);
733− auto variantDataTemplate = v8::ObjectTemplate::New(isolate);
734− variantDataTemplate->SetInternalFieldCount(2);
735− auto variantData = variantDataTemplate->NewInstance(engine->getContext()).ToLocalChecked();
736− variantData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantProxy));
737− variantData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(proxy));
738− return V8ScriptValue(engine, variantData);
746+
747+ auto variantProxyTemplate = v8::ObjectTemplate::New(isolate);
748+ variantProxyTemplate->SetInternalFieldCount(2);
749+ variantProxyTemplate->SetHandler(v8::NamedPropertyHandlerConfiguration(v8Get, v8Set, nullptr, nullptr, v8GetPropertyNames));
750+ auto variantProxy = variantProxyTemplate->NewInstance(engine->getContext()).ToLocalChecked();
751+ variantProxy->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantProxy));
752+ variantProxy->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(proxy));
753+ return V8ScriptValue(engine, variantProxy);
739754 }
740755
741756 ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) {
@@ -759,9 +774,141 @@ ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val · 17 unmodified lines
759774 return reinterpret_cast<ScriptVariantV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1));
760775 }
761776
777+ScriptVariantV8Proxy* 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+
795+QVariant* 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+
814+void 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+
846+void 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+
882+void 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+
762908 QVariant ScriptVariantV8Proxy::unwrap(const V8ScriptValue& val) {
763909 ScriptVariantV8Proxy* proxy = unwrapProxy(val);
764910 return proxy ? proxy->toQVariant() : QVariant();
911+ // V8TODO
765912 }
766913
767914 ScriptMethodV8Proxy::ScriptMethodV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime,