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 | 38 | static const void *internalPointsToQVariantProxy = (void *)0x13371000; |
| 39 | 39 | //static const void *internalPointsToSignalProxy = (void *)0x13372000; |
| 40 | 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 | 45 | // Used strictly to replace the "this" object value for property access. May expand to a full context element |
| 43 | 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 | 707 | ScriptVariantV8Proxy::ScriptVariantV8Proxy(ScriptEngineV8* engine, const QVariant& variant, V8ScriptValue scriptProto, ScriptObjectV8Proxy* proto) : |
| 705 | 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 | 720 | _name = QString::fromLatin1(variant.typeName()); |
| 707 | 721 | } |
| 708 | 722 | |
| @@ -711,7 +725,7 @@ ScriptVariantV8Proxy::~ScriptVariantV8Proxy() { · 2 unmodified lines | ||
| 711 | 725 | v8::Locker locker(isolate); |
| 712 | 726 | v8::Isolate::Scope isolateScope(isolate); |
| 713 | 727 | v8::HandleScope handleScope(isolate); |
| 714 | − _v8ObjectTemplate.Reset(); | |
| 728 | + //_v8ObjectTemplate.Reset(); | |
| 715 | 729 | _v8Object.Reset(); |
| 716 | 730 | } |
| 717 | 731 | |
| @@ -728,14 +742,15 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa · 10 unmodified lines | ||
| 728 | 742 | return V8ScriptValue(engine, v8::Undefined(isolate)); |
| 729 | 743 | } |
| 730 | 744 | // V8TODO probably needs connection to be deleted |
| 731 | − // V8TODO what to do with proto variable? | |
| 732 | 745 | 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); | |
| 739 | 754 | } |
| 740 | 755 | |
| 741 | 756 | ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) { |
| @@ -759,9 +774,141 @@ ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val · 17 unmodified lines | ||
| 759 | 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 | 908 | QVariant ScriptVariantV8Proxy::unwrap(const V8ScriptValue& val) { |
| 763 | 909 | ScriptVariantV8Proxy* proxy = unwrapProxy(val); |
| 764 | 910 | return proxy ? proxy->toQVariant() : QVariant(); |
| 911 | + // V8TODO | |
| 765 | 912 | } |
| 766 | 913 | |
| 767 | 914 | ScriptMethodV8Proxy::ScriptMethodV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, |