aboutsummaryrefslogtreecommitdiffstats
path: root/src/bindings/eina_js/eina_js_compatibility.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/bindings/eina_js/eina_js_compatibility.hh')
-rw-r--r--src/bindings/eina_js/eina_js_compatibility.hh918
1 files changed, 918 insertions, 0 deletions
diff --git a/src/bindings/eina_js/eina_js_compatibility.hh b/src/bindings/eina_js/eina_js_compatibility.hh
new file mode 100644
index 0000000000..9ef0cb814e
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_compatibility.hh
@@ -0,0 +1,918 @@
+#ifndef EFL_EINA_JS_COMPATIBILITY_HH
+#define EFL_EINA_JS_COMPATIBILITY_HH
+
+#include <type_traits>
+#include <utility>
+#include <map>
+#include <string>
+#include <cstdlib>
+
+
+#ifdef HAVE_NODE_V8_H
+#include <node/v8.h>
+#elif defined(HAVE_NODEJS_DEPS_V8_V8_H)
+#include <nodejs/deps/v8/v8.h>
+#elif defined(HAVE_NODEJS_DEPS_V8_INCLUDE_V8_H)
+#include <nodejs/deps/v8/include/v8.h>
+#elif defined(HAVE_NODEJS_SRC_V8_H)
+#include <nodejs/src/v8.h>
+#elif defined(HAVE_V8_H)
+#include <v8.h>
+#else
+#error We must have at least one v8 header to include
+#endif
+
+namespace v8 {
+
+template <typename T>
+struct FunctionCallbackInfo;
+template <typename T>
+struct PropertyCallbackInfo;
+template <typename T>
+#ifdef HAVE_V8_GLOBAL
+struct Global;
+#else
+struct UniquePersistent;
+#endif
+
+class AccessorInfo;
+
+class Arguments;
+
+}
+
+namespace efl { namespace eina { namespace js {
+
+template <typename T>
+struct value_tag
+{
+ typedef T type;
+};
+
+template <typename T, typename... U>
+struct complex_tag
+{
+ T value;
+ typedef std::tuple<U...> inner_types;
+};
+
+template <typename T>
+struct make_tag_traits
+{
+ typedef typename std::remove_reference<T>::type a1;
+ typedef typename std::conditional
+ <std::is_pointer<T>::value
+ , typename std::remove_cv<T>::type
+ , T>::type type;
+};
+
+template <typename T, typename... U>
+using make_complex_tag = complex_tag<typename make_tag_traits<T>::type
+ , typename make_tag_traits<U>::type...>;
+
+template <typename T>
+struct struct_tag
+{
+ T value;
+};
+
+template <typename T>
+using make_struct_tag = struct_tag<typename make_tag_traits<T>::type>;
+
+template <typename T>
+struct struct_ptr_tag
+{
+ T value;
+};
+
+template <typename T>
+using make_struct_ptr_tag = struct_ptr_tag<typename make_tag_traits<T>::type>;
+
+template <typename T, typename... Ts>
+struct remove_tag
+{
+ typedef T type;
+};
+
+template <typename T, typename... U>
+struct remove_tag<complex_tag<T, U...>>
+{
+ typedef typename eina::js::remove_tag<T, U...>::type type;
+};
+
+template <typename T>
+struct remove_tag<struct_tag<T>>
+{
+ typedef typename eina::js::remove_tag<T>::type type;
+};
+
+template <typename T>
+struct remove_tag<struct_ptr_tag<T>>
+{
+ typedef typename eina::js::remove_tag<T>::type type;
+};
+
+template <typename T>
+struct is_handable_by_value
+{
+ static constexpr bool value = !std::is_class<T>::value || std::is_same<T, ::efl::eo::concrete>::value;
+};
+
+template <typename... T>
+struct container_wrapper
+{
+ typedef typename eina::js::remove_tag<T...>::type _notag_type;
+ typedef typename std::conditional<
+ std::is_convertible<_notag_type, Eo const* const>::value
+ , typename std::conditional<
+ std::is_const<typename std::remove_pointer<_notag_type>::type>::value
+ , ::efl::eo::concrete const
+ , ::efl::eo::concrete
+ >::type
+ , _notag_type
+ >::type type;
+};
+
+template <typename T>
+T container_wrap(T&& v)
+{
+ return std::forward<T>(v);
+}
+
+inline ::efl::eo::concrete container_wrap(Eo* v)
+{
+ if(v)
+ eo_ref(v);
+ return ::efl::eo::concrete{v};
+}
+
+inline ::efl::eo::concrete container_wrap(Eo const* v)
+{
+ if (v)
+ eo_ref(v);
+ return ::efl::eo::concrete{const_cast<Eo*>(v)};
+}
+
+template <typename T>
+T& container_unwrap(T& v)
+{
+ return v;
+}
+
+inline Eo* container_unwrap(::efl::eo::concrete& v)
+{
+ return v._eo_ptr();
+}
+
+inline Eo* container_unwrap(::efl::eo::concrete const& v)
+{
+ return v._eo_ptr();
+}
+
+template <typename T>
+struct is_complex_tag : std::false_type {};
+
+template <typename... T>
+struct is_complex_tag<complex_tag<T...>> : std::true_type {};
+
+template <typename T>
+struct is_struct_tag : std::false_type {};
+
+template <typename T>
+struct is_struct_tag<struct_tag<T>> : std::true_type {};
+
+template <typename T>
+struct is_struct_ptr_tag : std::false_type {};
+
+template <typename T>
+struct is_struct_ptr_tag<struct_ptr_tag<T>> : std::true_type {};
+
+template <typename T>
+struct is_type_tag
+{
+ static constexpr bool value =
+ is_complex_tag<T>::value
+ || is_struct_tag<T>::value
+ || is_struct_ptr_tag<T>::value;
+};
+
+
+// Class name getters
+struct cls_name_getter_base {};
+struct cls_name_getter_generated_base : cls_name_getter_base {};
+/// Name getter for types that are not classes
+struct nonclass_cls_name_getter : cls_name_getter_base
+{
+ static char const* class_name() { return ""; }
+};
+
+// JS container base
+enum container_type
+{
+ list_container_type
+ , array_container_type
+ , container_type_size
+};
+
+struct eina_container_base
+{
+ virtual ~eina_container_base() {}
+
+ virtual std::size_t size() const = 0;
+ virtual eina_container_base* concat(eina_container_base const& rhs) const = 0;
+ virtual eina_container_base* slice(std::int64_t i, std::int64_t j) const = 0;
+ virtual int index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const = 0;
+ virtual int last_index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const = 0;
+ virtual v8::Local<v8::Value> get(v8::Isolate*, std::size_t) const = 0;
+ virtual v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t index, v8::Local<v8::Value> v) = 0;
+ virtual int push(v8::Isolate* isolate, v8::Local<v8::Value> v) = 0;
+ virtual v8::Local<v8::Value> pop(v8::Isolate* isolate) = 0;
+ virtual v8::Local<v8::String> to_string(v8::Isolate*) const = 0;
+ virtual v8::Local<v8::String> join(v8::Isolate*, v8::Local<v8::Value> separator) const = 0;
+ virtual container_type get_container_type() const = 0;
+ virtual void* get_container_native_handle() = 0;
+ virtual void const* get_container_native_handle() const = 0;
+};
+
+// Containers forward declarations
+
+// Array
+template <typename T, typename K = nonclass_cls_name_getter, typename W = typename container_wrapper<T>::type>
+struct eina_array;
+template <typename T, typename K = nonclass_cls_name_getter, typename W = typename container_wrapper<T>::type>
+struct range_eina_array;
+
+EAPI v8::Handle<v8::Function> get_array_instance_template();
+
+// List
+template <typename T, typename K = nonclass_cls_name_getter, typename W = typename container_wrapper<T>::type>
+struct eina_list;
+template <typename T, typename K = nonclass_cls_name_getter, typename W = typename container_wrapper<T>::type>
+struct range_eina_list;
+
+EAPI v8::Handle<v8::Function> get_list_instance_template();
+
+// Accessor
+template <typename T, typename W>
+v8::Local<v8::Object> export_accessor(::efl::eina::accessor<W>&, v8::Isolate*, const char*);
+
+template <typename T>
+::efl::eina::accessor<T>& import_accessor(v8::Handle<v8::Object>);
+
+// Wrap value functions
+template <typename R, typename T>
+typename std::remove_cv<typename std::remove_reference<R>::type>::type
+wrap_value(T v, value_tag<R>
+ , typename std::enable_if<!is_type_tag<typename std::remove_cv<R>::type>::value>::type* = 0)
+{
+ return v;
+}
+
+template <typename R, typename T>
+R wrap_value(T const& v, value_tag<eina::js::struct_tag<T>>)
+{
+ return R {v};
+}
+
+template <typename R, typename T>
+R wrap_value(T v, value_tag<eina::js::struct_ptr_tag<T>>)
+{
+ return R {v};
+}
+
+template <typename R, typename T, typename... U>
+R wrap_value(T v, value_tag<eina::js::complex_tag<T, U...>>)
+{
+ return R {v};
+}
+
+template <typename T = v8::External>
+struct _libv8_isolate_test
+{
+ using new_signature = v8::Local<T>(*)(v8::Isolate*, void*);
+ static const bool value = std::is_same<decltype(static_cast<new_signature>(&T::New)), new_signature>::value;
+};
+
+template <typename T = v8::FunctionTemplate, typename Enable = void>
+struct _libv8_callback_info_test;
+
+typedef v8::Handle<v8::Value>(*_libv8_invocation_callback)(v8::Arguments const&);
+
+template <typename T>
+struct _libv8_callback_info_test
+<T, typename std::enable_if
+ <!std::is_same<decltype( & T::SetCallHandler)
+ , void (T::*)(_libv8_invocation_callback, v8::Handle<v8::Value>)>::value>::type>
+ : std::true_type
+{
+};
+
+template <typename T>
+struct _libv8_callback_info_test
+<T, typename std::enable_if
+ <std::is_same<decltype( & T::SetCallHandler)
+ , void (T::*)(_libv8_invocation_callback, v8::Handle<v8::Value>)>::value>::type>
+ : std::false_type
+{
+};
+
+template <typename T = v8::ObjectTemplate, typename Enable = void>
+struct _libv8_property_callback_info_test
+ : std::true_type {};
+
+typedef v8::Handle<v8::Value>(*_libv8_getter_callback)(v8::Local<v8::String>, v8::AccessorInfo const&);
+typedef void(*_libv8_setter_callback)(v8::Local<v8::String>, v8::Local<v8::Value>, v8::AccessorInfo const&);
+
+template <typename T>
+struct _libv8_property_callback_info_test
+<T, typename std::enable_if
+ <std::is_same<decltype( & T::SetAccessor)
+ , void (T::*)
+ (v8::Handle<v8::String>
+ , _libv8_getter_callback
+ , _libv8_setter_callback
+ , v8::Handle<v8::Value>
+ , v8::AccessControl
+ , v8::PropertyAttribute
+ , v8::Handle<v8::AccessorSignature>
+ )>::value>::type>
+ : std::false_type
+{
+};
+
+static constexpr bool const v8_uses_isolate = _libv8_isolate_test<>::value;
+static constexpr bool const v8_uses_callback_info = _libv8_callback_info_test<>::value;
+static constexpr bool const v8_uses_property_callback_info = _libv8_property_callback_info_test<>::value;
+
+using compatibility_return_type = std::conditional<v8_uses_callback_info, void, v8::Handle<v8::Value> >::type;
+using compatibility_callback_info_type
+ = std::conditional<v8_uses_callback_info, v8::FunctionCallbackInfo<v8::Value> const&, v8::Arguments const&>
+ ::type;
+using compatibility_callback_info_pointer
+ = std::conditional<v8_uses_callback_info, v8::FunctionCallbackInfo<v8::Value> const*, v8::Arguments const*>
+ ::type;
+
+typedef compatibility_return_type(*compatibility_function_callback)(compatibility_callback_info_type);
+
+using compatibility_accessor_getter_return_type
+ = std::conditional<v8_uses_property_callback_info, void, v8::Handle<v8::Value> >::type;
+using compatibility_accessor_getter_callback_info_type
+ = std::conditional<v8_uses_property_callback_info
+ , v8::PropertyCallbackInfo<v8::Value> const&, v8::AccessorInfo const&>
+ ::type;
+
+using compatibility_accessor_setter_return_type
+ = void;
+using compatibility_accessor_setter_callback_info_type
+ = std::conditional<v8_uses_property_callback_info
+ , v8::PropertyCallbackInfo<void> const&, v8::AccessorInfo const&>
+ ::type;
+
+using compatibility_indexed_property_getset_return_type
+ = std::conditional<v8_uses_property_callback_info, void, v8::Handle<v8::Value> >::type;
+using compatibility_indexed_property_callback_info_type
+ = std::conditional<v8_uses_property_callback_info
+ , v8::PropertyCallbackInfo<v8::Value> const&, v8::AccessorInfo const&>
+ ::type;
+
+static_assert(v8_uses_property_callback_info == v8_uses_callback_info
+ && v8_uses_callback_info == v8_uses_isolate, "");
+
+template <typename T>
+struct compatibility_type_tag {};
+
+template <bool = v8_uses_isolate>
+struct compatibility_string;
+
+template <>
+struct compatibility_string<true> : v8::String
+{
+ template <typename... Args>
+ static v8::Local<v8::String> New(Args...args)
+ {
+ return NewFromUtf8(v8::Isolate::GetCurrent(), args...);
+ }
+};
+
+template <>
+struct compatibility_string<false> : v8::String
+{
+};
+
+template <typename...Args>
+auto compatibility_new_impl(v8::Isolate*, std::true_type, compatibility_type_tag<v8::String>
+ , Args...args) ->
+ decltype(compatibility_string<>::New(args...))
+{
+ return compatibility_string<>::New(args...);
+}
+
+template <typename...Args>
+auto compatibility_new_impl(v8::Isolate*, std::false_type, compatibility_type_tag<v8::String>
+ , Args...args) ->
+ decltype(compatibility_string<>::New(args...))
+{
+ return compatibility_string<>::New(args...);
+}
+
+template <typename...Args>
+auto compatibility_new_impl(std::nullptr_t, std::true_type, compatibility_type_tag<v8::String>
+ , Args...args) ->
+ decltype(compatibility_string<>::New(args...))
+{
+ return compatibility_string<>::New(args...);
+}
+
+template <typename...Args>
+auto compatibility_new_impl(std::nullptr_t, std::false_type, compatibility_type_tag<v8::String>
+ , Args...args) ->
+ decltype(compatibility_string<>::New(args...))
+{
+ return compatibility_string<>::New(args...);
+}
+
+template <typename T, typename...Args>
+auto compatibility_new_impl(v8::Isolate* isolate, std::true_type, compatibility_type_tag<T>
+ , Args...args) ->
+ decltype(T::New(isolate, args...))
+{
+ return T::New(isolate, args...);
+}
+
+template <typename T, typename...Args>
+auto compatibility_new_impl(v8::Isolate*, std::false_type, compatibility_type_tag<T>
+ , Args...args) ->
+ decltype(T::New(args...))
+{
+ return T::New(args...);
+}
+
+template <typename T, typename...Args>
+auto compatibility_new_impl(std::nullptr_t, std::true_type, compatibility_type_tag<T>
+ , Args...args) ->
+ decltype(T::New(v8::Isolate::GetCurrent(), args...))
+{
+ return T::New(v8::Isolate::GetCurrent(), args...);
+}
+
+template <typename T, typename...Args>
+auto compatibility_new_impl(std::nullptr_t, std::false_type, compatibility_type_tag<T>
+ , Args...args) ->
+ decltype(T::New(args...))
+{
+ return T::New(args...);
+}
+
+template <typename T, typename...Args>
+auto compatibility_new(v8::Isolate* isolate, Args...args) ->
+ decltype(js::compatibility_new_impl<>
+ (isolate, std::integral_constant<bool, v8_uses_isolate>()
+ , compatibility_type_tag<T>()
+ , args...))
+{
+ return js::compatibility_new_impl(isolate, std::integral_constant<bool, v8_uses_isolate>()
+ , compatibility_type_tag<T>()
+ , args...);
+}
+
+template <typename T, typename...Args>
+auto compatibility_new(std::nullptr_t, Args...args) ->
+ decltype(js::compatibility_new_impl<>(nullptr, std::integral_constant<bool, v8_uses_isolate>()
+ , compatibility_type_tag<T>()
+ , args...))
+{
+ return js::compatibility_new_impl<>(nullptr, std::integral_constant<bool, v8_uses_isolate>()
+ , compatibility_type_tag<T>()
+ , args...);
+}
+
+#ifdef HAVE_V8_CREATE_PARAMS
+namespace detail {
+class array_buffer_allocator : public v8::ArrayBuffer::Allocator
+{
+ public:
+ virtual void* Allocate(std::size_t length)
+ {
+ void* data = AllocateUninitialized(length);
+ return data ? std::memset(data, 0, length) : data;
+ }
+ virtual void* AllocateUninitialized(std::size_t length) { return std::malloc(length); }
+ virtual void Free(void* data, std::size_t) { std::free(data); }
+};
+}
+
+inline v8::Isolate* compatibility_isolate_new()
+{
+ static detail::array_buffer_allocator allocator;
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = &allocator;
+ return v8::Isolate::New(create_params);
+}
+
+#else
+
+inline v8::Isolate* compatibility_isolate_new()
+{
+ return v8::Isolate::New();
+}
+
+#endif
+
+template <typename T, typename U>
+inline void compatibility_return_impl(T object, U const& info, std::true_type)
+{
+ info.GetReturnValue().Set(object);
+}
+
+template <typename T>
+inline v8::Handle<v8::Value>
+compatibility_return_impl(T object, compatibility_callback_info_type, std::false_type)
+{
+ return object;
+}
+
+template <typename T>
+inline v8::Handle<v8::Value>
+compatibility_return_impl(T object, compatibility_accessor_getter_callback_info_type, std::false_type)
+{
+ return object;
+}
+
+template <typename T>
+compatibility_return_type
+compatibility_return(T object, compatibility_callback_info_type args)
+{
+ return compatibility_return_impl(object, args, std::integral_constant<bool, v8_uses_callback_info>());
+}
+
+template <typename T>
+compatibility_return_type
+compatibility_return(T object, compatibility_accessor_getter_callback_info_type args)
+{
+ return compatibility_return_impl(object, args, std::integral_constant<bool, v8_uses_property_callback_info>());
+}
+
+inline void compatibility_return_nil_impl(std::true_type) {}
+
+inline v8::Handle<v8::Value>
+compatibility_return_nil_impl(std::false_type)
+{
+ return v8::Handle<v8::Value>();
+}
+
+inline
+compatibility_return_type
+compatibility_return()
+{
+ return compatibility_return_nil_impl(std::integral_constant<bool, v8_uses_callback_info>());
+}
+
+struct _v8_isolate_throw_exception : v8::Isolate
+{
+ v8::Handle<v8::Value> ThrowException_impl(v8::Handle<v8::Value> v)
+ {
+ using namespace v8;
+ return ThrowException(v);
+ }
+};
+
+inline void
+compatibility_throw_impl(v8::Isolate* isolate, v8::Local<v8::Value> exception, std::true_type)
+{
+ static_cast<_v8_isolate_throw_exception*>(isolate)->ThrowException_impl(exception);
+}
+
+inline v8::Handle<v8::Value>
+compatibility_throw_impl(v8::Isolate* isolate, v8::Local<v8::Value> exception, std::false_type)
+{
+ return static_cast<_v8_isolate_throw_exception*>(isolate)->ThrowException_impl(exception);
+}
+
+inline std::conditional<v8_uses_isolate, void, v8::Handle<v8::Value> >::type
+compatibility_throw(v8::Isolate* isolate, v8::Local<v8::Value> exception)
+{
+ return compatibility_throw_impl(isolate, exception, std::integral_constant<bool, v8_uses_isolate>());
+}
+
+inline void
+compatibility_throw_impl(v8::Local<v8::Value> exception, std::true_type)
+{
+ static_cast<_v8_isolate_throw_exception*>(v8::Isolate::GetCurrent())->ThrowException_impl(exception);
+}
+
+inline v8::Handle<v8::Value>
+compatibility_throw_impl(v8::Local<v8::Value> exception, std::false_type)
+{
+ return static_cast<_v8_isolate_throw_exception*>(v8::Isolate::GetCurrent())->ThrowException_impl(exception);
+}
+
+inline std::conditional<v8_uses_isolate, void, v8::Handle<v8::Value> >::type
+compatibility_throw(v8::Local<v8::Value> exception)
+{
+ return compatibility_throw_impl(exception, std::integral_constant<bool, v8_uses_isolate>());
+}
+
+template <typename T, typename U>
+v8::Local<T> compatibility_cast(v8::Local<U> v);
+template <typename T, typename U>
+v8::Local<T> compatibility_cast(U* v);
+
+template <typename Tag>
+struct hack_private_member {
+ /* export it ... */
+ typedef typename Tag::type type;
+ static type ptr;
+};
+
+template <typename Tag>
+typename hack_private_member<Tag>::type hack_private_member<Tag>::ptr;
+
+template <typename Tag, typename Tag::type p>
+struct rob_private_member : hack_private_member<Tag> {
+ /* fill it ... */
+ struct filler {
+ filler() { hack_private_member<Tag>::ptr = p; }
+ };
+ static filler filler_obj;
+};
+
+template<typename Tag, typename Tag::type p>
+typename rob_private_member<Tag, p>::filler rob_private_member<Tag, p>::filler_obj;
+
+template <typename T>
+struct persistent_base_new { typedef T*(*type)(v8::Isolate*, T*); };
+
+template class rob_private_member<persistent_base_new<v8::Value>, &v8::PersistentBase<v8::Value>::New>;
+
+template <typename T>
+v8::Local<T> make_persistent(v8::Isolate* isolate, v8::Handle<T> v)
+{
+ v8::Value* p = hack_private_member<persistent_base_new<v8::Value>>::ptr
+ (isolate, *compatibility_cast<v8::Value>(v));
+ return compatibility_cast<T>(compatibility_cast<v8::Value>(p));
+}
+
+template <typename T, typename F>
+v8::Local<T> make_weak(v8::Isolate* isolate, v8::Handle<T> v, F&& f)
+{
+ v8::Value* p = hack_private_member<persistent_base_new<v8::Value>>::ptr
+ (isolate, *compatibility_cast<v8::Value>(v));
+ v8::PersistentBase<v8::Value>* persistent = static_cast<v8::PersistentBase<v8::Value>*>
+ (static_cast<void*>(&p));
+
+ auto callback = [](const v8::WeakCallbackInfo<typename std::remove_reference<F>::type>& data) -> void
+ {
+ typename std::remove_reference<F>::type* f = data.GetParameter();
+ (*f)();
+ delete f;
+ };
+
+ persistent->SetWeak(new typename std::remove_reference<F>::type(std::forward<F>(f)),
+ callback, v8::WeakCallbackType::kParameter);
+ return compatibility_cast<T>(compatibility_cast<v8::Value>(p));
+}
+
+template <typename T>
+struct global_ref
+{
+ global_ref() {}
+ global_ref(v8::Local<T> v)
+ : _value(make_persistent(nullptr, v))
+ {
+ }
+ global_ref(v8::Isolate* isolate, v8::Local<T> v)
+ : _value(make_persistent(isolate, v))
+ {
+ }
+
+ void dispose() const
+ {
+ v8::PersistentBase<T>* p = static_cast<v8::PersistentBase<T>*>(static_cast<void*>(&_value));
+ p->Reset();
+ }
+
+ v8::Handle<T> handle() const { return _value; }
+private:
+ mutable v8::Local<T> _value;
+};
+
+template <typename T = std::integral_constant<bool, v8_uses_isolate> >
+struct _v8_object_internal_field;
+
+template <>
+struct _v8_object_internal_field<std::true_type> : v8::Object
+{
+};
+
+inline void* GetPointerFromInternalField(int) { return nullptr; }
+inline void SetPointerInInternalField(int, void*) {}
+
+template <>
+struct _v8_object_internal_field<std::false_type> : v8::Object
+{
+ void* GetAlignedPointerFromInternalField(int index)
+ {
+ return GetPointerFromInternalField(index);
+ }
+ void SetAlignedPointerInInternalField(int index, void* p)
+ {
+ SetPointerInInternalField(index, p);
+ }
+};
+
+template <typename T = void*>
+inline T compatibility_get_pointer_internal_field(v8::Handle<v8::Object> object, std::size_t index)
+{
+ return reinterpret_cast<T>
+ (static_cast<_v8_object_internal_field<>*>(*object)->GetAlignedPointerFromInternalField(index));
+}
+
+template <typename T>
+inline void compatibility_set_pointer_internal_field(v8::Handle<v8::Object> object, std::size_t index
+ , T* pointer)
+{
+ static_cast<_v8_object_internal_field<>*>(*object)->SetAlignedPointerInInternalField(index, pointer);
+}
+
+template <typename T = void, bool = v8_uses_isolate>
+struct compatibility_handle_scope_impl;
+
+template <typename T>
+struct compatibility_handle_scope_impl<T, true> : v8::HandleScope
+{
+ compatibility_handle_scope_impl()
+ : HandleScope(v8::Isolate::GetCurrent())
+ {}
+ compatibility_handle_scope_impl(v8::Isolate* isolate)
+ : HandleScope((assert(isolate != nullptr), isolate))
+ {}
+};
+
+template <typename T>
+struct compatibility_handle_scope_impl<T, false> : v8::HandleScope
+{
+ compatibility_handle_scope_impl()
+ {}
+ compatibility_handle_scope_impl(v8::Isolate*)
+ {}
+};
+
+using compatibility_handle_scope = compatibility_handle_scope_impl<>;
+
+template <bool = v8_uses_isolate>
+struct _v8_initialize_icu;
+
+template <>
+struct _v8_initialize_icu<true> : v8::V8
+{
+};
+
+template <>
+struct _v8_initialize_icu<false> : v8::V8
+{
+ static bool InitializeICU(const char* = NULL)
+ {
+ return true;
+ }
+};
+
+inline void compatibility_initialize()
+{
+#ifdef HAVE_V8_CREATE_PARAMS
+ constexpr const char* argv[] = {""};
+ static_cast<_v8_initialize_icu<>*>(nullptr)->InitializeICU();
+ v8::V8::InitializeExternalStartupData(argv[0]);
+ v8::V8::Initialize();
+#else
+ v8::V8::Initialize();
+ static_cast<_v8_initialize_icu<>*>(nullptr)->InitializeICU();
+#endif
+}
+
+template <typename T, typename U>
+v8::Local<T> compatibility_cast(v8::Local<U> v)
+{
+ static_assert(sizeof(v8::Local<T>) == sizeof(v8::Local<U>), "");
+ v8::Local<T> l;
+ std::memcpy(&l, &v, sizeof(v8::Local<T>));
+ return l;
+}
+
+template <typename T, typename U>
+v8::Local<T> compatibility_cast(U* v)
+{
+ static_assert(sizeof(v8::Local<T>) == sizeof(U*), "");
+ v8::Local<T> l;
+ std::memcpy(&l, &v, sizeof(v8::Local<T>));
+ return l;
+}
+
+template <typename T = v8::Isolate, bool = v8_uses_isolate>
+struct _v8_get_current_context;
+
+template <typename T>
+struct _v8_get_current_context<T, false> : v8::Context
+{
+};
+
+template <typename T>
+struct _v8_get_current_context<T, true> : T
+{
+ static v8::Local<v8::Context> GetCurrent()
+ {
+ return T::GetCurrent()->GetCurrentContext();
+ }
+};
+
+template <typename T>
+inline v8::Local<v8::Value>
+new_v8_external_instance(v8::Handle<v8::Function>& ctor, T v, v8::Isolate* isolate)
+{
+ // TODO: ensure v8::External ownership ??? (memory leak in case NewInstance throws)
+ v8::Handle<v8::Value> a[] = {efl::eina::js::compatibility_new<v8::External>(isolate, v)};
+ return ctor->NewInstance(1, a);
+}
+
+inline
+compatibility_return_type cast_function(compatibility_callback_info_type args);
+
+inline v8::Local<v8::Value>
+new_v8_external_instance(v8::Handle<v8::Function>& ctor, Eo* v, v8::Isolate* isolate)
+{
+ // TODO: ensure v8::External ownership ??? (memory leak in case NewInstance throws)
+ v8::Handle<v8::Value> a[] = {efl::eina::js::compatibility_new<v8::External>(isolate, v)};
+ auto obj = ctor->NewInstance(1, a);
+ obj->Set(compatibility_new<v8::String>(isolate, "cast"),
+ compatibility_new<v8::FunctionTemplate>(isolate, &cast_function)->GetFunction());
+ return obj;
+}
+
+inline v8::Local<v8::Object> compatibility_global()
+{
+ return _v8_get_current_context<>::GetCurrent()->Global();
+}
+
+EAPI extern std::map<std::string, v8::Local<v8::Function>> constructors_map_;
+
+inline v8::Handle<v8::Function> get_class_constructor(std::string const& class_name)
+{
+ auto it = constructors_map_.find(class_name);
+ if (it == constructors_map_.end())
+ throw std::runtime_error("Class not found");
+ return it->second;
+}
+
+inline void register_class_constructor(std::string const& class_name,
+ v8::Handle<v8::Function> constructor_ptr)
+{
+ // TODO: check if already exist?
+ constructors_map_[class_name] = constructor_ptr;
+}
+
+template<class T = v8::StackTrace>
+typename std::enable_if<!v8_uses_isolate, v8::Local<T>>::type
+compatibility_current_stack_trace(v8::Isolate*, int frame_limit,
+ v8::StackTrace::StackTraceOptions options)
+{
+ return T::CurrentStackTrace(frame_limit, options);
+}
+
+template<class T = v8::StackTrace>
+typename std::enable_if<v8_uses_isolate, v8::Local<T>>::type
+compatibility_current_stack_trace(v8::Isolate *isolate, int frame_limit,
+ v8::StackTrace::StackTraceOptions options)
+{
+ return T::CurrentStackTrace(isolate, frame_limit, options);
+}
+
+inline
+compatibility_return_type cast_function(compatibility_callback_info_type args)
+{
+ auto isolate = args.GetIsolate();
+ compatibility_handle_scope scope(isolate);
+ v8::Local<v8::Value> type;
+ if(args.Length() == 1 && (type = args[0])->IsString())
+ {
+ v8::Local<v8::Object> self = args.This();
+ v8::Local<v8::Value> external = self->GetInternalField(0);
+ Eo* eo = static_cast<Eo*>(v8::External::Cast(*external)->Value());
+
+ v8::String::Utf8Value str(type->ToString());
+ char* class_name = *str;
+
+ auto ctor = ::efl::eina::js::get_class_constructor(class_name);
+ return compatibility_return
+ (new_v8_external_instance(ctor, ::eo_ref(eo), isolate), args);
+ }
+ else
+ {
+ eina::js::compatibility_throw
+ (isolate, v8::Exception::TypeError
+ (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected String type")));
+ return compatibility_return();
+ }
+}
+
+} } }
+
+#endif