Showing the changes to libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp (1 of 4 files). Show all
Unified · Split
| @@ -38,6 +38,9 @@ static const void *internalPointsToQObjectProxy = (void *)0x13370000; · 37 unmodified lines | |||
| 38 | static const void *internalPointsToQVariantProxy = (void *)0x13371000; | 38 | static const void *internalPointsToQVariantProxy = (void *)0x13371000; |
| 39 | //static const void *internalPointsToSignalProxy = (void *)0x13372000; | 39 | //static const void *internalPointsToSignalProxy = (void *)0x13372000; |
| 40 | static const void *internalPointsToMethodProxy = (void *)0x13373000; | 40 | 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; | ||
| 41 | 44 | ||
| 42 | // Used strictly to replace the "this" object value for property access. May expand to a full context element | 45 | // 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 needed | 46 | // 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 | ||
| 704 | ScriptVariantV8Proxy::ScriptVariantV8Proxy(ScriptEngineV8* engine, const QVariant& variant, V8ScriptValue scriptProto, ScriptObjectV8Proxy* proto) : | 707 | ScriptVariantV8Proxy::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 deleted | 744 | // 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 | ||
| 741 | ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) { | 756 | ScriptVariantV8Proxy* 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 | ||
| 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 | |||
| 762 | QVariant ScriptVariantV8Proxy::unwrap(const V8ScriptValue& val) { | 908 | QVariant 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 | ||
| 767 | ScriptMethodV8Proxy::ScriptMethodV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, | 914 | ScriptMethodV8Proxy::ScriptMethodV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, |