summaryrefslogtreecommitdiff
path: root/src/bindings/eina_js
diff options
context:
space:
mode:
Diffstat (limited to 'src/bindings/eina_js')
-rw-r--r--src/bindings/eina_js/Eina_Js.hh50
-rw-r--r--src/bindings/eina_js/eina_js_accessor.cc34
-rw-r--r--src/bindings/eina_js/eina_js_accessor.hh87
-rw-r--r--src/bindings/eina_js/eina_js_array.hh119
-rw-r--r--src/bindings/eina_js/eina_js_compatibility.cc12
-rw-r--r--src/bindings/eina_js/eina_js_compatibility.hh918
-rw-r--r--src/bindings/eina_js/eina_js_container.cc495
-rw-r--r--src/bindings/eina_js/eina_js_container.hh351
-rw-r--r--src/bindings/eina_js/eina_js_error.cc24
-rw-r--r--src/bindings/eina_js/eina_js_error.hh25
-rw-r--r--src/bindings/eina_js/eina_js_get_value.hh449
-rw-r--r--src/bindings/eina_js/eina_js_get_value_from_c.hh261
-rw-r--r--src/bindings/eina_js/eina_js_iterator.cc32
-rw-r--r--src/bindings/eina_js/eina_js_iterator.hh81
-rw-r--r--src/bindings/eina_js/eina_js_list.hh132
-rw-r--r--src/bindings/eina_js/eina_js_log.cc742
-rw-r--r--src/bindings/eina_js/eina_js_log.hh133
-rw-r--r--src/bindings/eina_js/eina_js_node.hh14
-rw-r--r--src/bindings/eina_js/eina_js_value.cc132
-rw-r--r--src/bindings/eina_js/eina_js_value.hh142
20 files changed, 4233 insertions, 0 deletions
diff --git a/src/bindings/eina_js/Eina_Js.hh b/src/bindings/eina_js/Eina_Js.hh
new file mode 100644
index 0000000..b193b54
--- /dev/null
+++ b/src/bindings/eina_js/Eina_Js.hh
@@ -0,0 +1,50 @@
1
2#ifndef EFL_EINA_JS_HH
3#define EFL_EINA_JS_HH
4
5#include <Eina.hh>
6#include <eo_concrete.hh>
7
8#ifdef EAPI
9# undef EAPI
10#endif
11
12#ifdef _WIN32
13# ifdef EFL_EINA_JS_BUILD
14# ifdef DLL_EXPORT
15# define EAPI __declspec(dllexport)
16# else
17# define EAPI
18# endif /* ! DLL_EXPORT */
19# else
20# define EAPI __declspec(dllimport)
21# endif /* ! EFL_ECORE_BUILD */
22#else
23# ifdef __GNUC__
24# if __GNUC__ >= 4
25# define EAPI __attribute__ ((visibility("default")))
26# else
27# define EAPI
28# endif
29# else
30# define EAPI
31# endif
32#endif /* ! _WIN32 */
33
34#include <eina_js_container.hh>
35#include <eina_js_accessor.hh>
36#include <eina_js_array.hh>
37#include <eina_js_compatibility.hh>
38#include <eina_js_error.hh>
39#include <eina_js_get_value_from_c.hh>
40#include <eina_js_get_value.hh>
41#include <eina_js_iterator.hh>
42#include <eina_js_list.hh>
43#include <eina_js_log.hh>
44#include <eina_js_value.hh>
45#include <eina_js_log.hh>
46
47#undef EAPI
48#define EAPI
49
50#endif
diff --git a/src/bindings/eina_js/eina_js_accessor.cc b/src/bindings/eina_js/eina_js_accessor.cc
new file mode 100644
index 0000000..d689154
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_accessor.cc
@@ -0,0 +1,34 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include <Eina.hh>
6
7#include <Eina_Js.hh>
8
9#include <iostream>
10
11namespace efl { namespace eina { namespace js {
12
13EAPI void register_destroy_accessor(v8::Isolate *isolate,
14 v8::Handle<v8::Object> global,
15 v8::Handle<v8::String> name)
16{
17 typedef void (*deleter_t)(void*);
18
19 auto f = [](compatibility_callback_info_type info) -> compatibility_return_type
20 {
21 if (info.Length() != 1 || !info[0]->IsObject())
22 return compatibility_return();
23
24 v8::Handle<v8::Object> o = info[0]->ToObject();
25
26 deleter_t deleter = compatibility_get_pointer_internal_field<deleter_t>(o, 1);
27 deleter(compatibility_get_pointer_internal_field<>(o, 0));
28 return compatibility_return();
29 };
30
31 global->Set(name, compatibility_new<v8::FunctionTemplate>(isolate, f)->GetFunction());
32}
33
34} } } // namespace efl { namespace js {
diff --git a/src/bindings/eina_js/eina_js_accessor.hh b/src/bindings/eina_js/eina_js_accessor.hh
new file mode 100644
index 0000000..abf3090
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_accessor.hh
@@ -0,0 +1,87 @@
1#ifndef EINA_JS_ACCESSOR_HH
2#define EINA_JS_ACCESSOR_HH
3
4#include <memory>
5
6#include <eina_js_value.hh>
7#include <eina_js_compatibility.hh>
8#include <eina_js_get_value.hh>
9#include <eina_js_get_value_from_c.hh>
10
11#include <iostream>
12
13namespace efl { namespace eina { namespace js {
14
15template <typename T, typename A>
16js::compatibility_return_type accessor_get(js::compatibility_callback_info_type info)
17{
18 v8::Isolate* isolate = info.GetIsolate();
19 if (info.Length() != 1 || !info[0]->IsNumber())
20 return js::compatibility_return();
21
22 auto idx = js::get_value_from_javascript
23 (info[0], isolate, "", js::value_tag<std::size_t>());
24
25 std::string class_name;
26 if (info.Data()->IsString())
27 {
28 v8::String::Utf8Value str(info.Data());
29 class_name = *str;
30 }
31
32 void *ptr = compatibility_get_pointer_internal_field(info.Holder(), 0);
33
34 return compatibility_return
35 (::efl::eina::js::get_value_from_c
36 (js::wrap_value<T>(container_unwrap((*static_cast<A*>(ptr))[idx]), js::value_tag<T>{})
37 , isolate, class_name.c_str()), info);
38};
39
40/* Creates a copy from \p a accessor and exports it to be manipulated by the JS
41 code */
42template <typename T, typename W>
43inline v8::Local<v8::Object> export_accessor(::efl::eina::accessor<W> &a, v8::Isolate *isolate, const char* class_name)
44{
45 typedef ::efl::eina::accessor<W> accessor_type;
46
47 static efl::eina::js::global_ref<v8::ObjectTemplate> obj_tpl
48 (isolate,
49 [&]()
50 {
51 auto obj_tpl = compatibility_new<v8::ObjectTemplate>(isolate);
52 (*obj_tpl)->SetInternalFieldCount(1);
53
54 // TODO: (*obj_tpl)->SetIndexedPropertyHandler(&accessor_get<accessor_type>);
55
56 (*obj_tpl)->Set(js::compatibility_new<v8::String>(isolate, "get")
57 , js::compatibility_new<v8::FunctionTemplate>(isolate
58 , &accessor_get<T, accessor_type>
59 , js::compatibility_new<v8::String>(isolate, class_name)));
60 return obj_tpl;
61 }());
62
63 auto instance = obj_tpl.handle()->NewInstance();
64 compatibility_set_pointer_internal_field(instance, 0, &a);
65 return instance;
66}
67
68/* Extracts and returns a copy from the internal accessor object from the JS
69 object */
70template <typename T>
71::efl::eina::accessor<T>& import_accessor(v8::Handle<v8::Object> o)
72{
73 typedef ::efl::eina::accessor<T> accessor_type;
74
75 void* ptr = compatibility_get_pointer_internal_field(o, 0);
76
77 return *static_cast<accessor_type*>(ptr);
78}
79
80/* Registers the function to destroy the accessor objects to the JS code */
81void register_destroy_accessor(v8::Isolate *isolate,
82 v8::Handle<v8::Object> global,
83 v8::Handle<v8::String> name);
84
85} } } // namespace efl::js
86
87#endif /* EINA_JS_ACCESSOR_HH */
diff --git a/src/bindings/eina_js/eina_js_array.hh b/src/bindings/eina_js/eina_js_array.hh
new file mode 100644
index 0000000..9cdd142
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_array.hh
@@ -0,0 +1,119 @@
1#ifndef EINA_JS_ARRAY_HH
2#define EINA_JS_ARRAY_HH
3
4#include <iostream>
5
6#include <iterator>
7
8#include <eina_js_container.hh>
9
10namespace efl { namespace eina { namespace js {
11
12template <typename T, typename K, typename W>
13struct eina_array : eina_container_common<efl::eina::array
14 <W
15 , typename std::conditional
16 <std::is_base_of<efl::eo::concrete, W>::value
17 , efl::eina::eo_clone_allocator
18 , efl::eina::malloc_clone_allocator
19 >::type>, T, K>
20{
21 typedef eina_container_common<efl::eina::array<W
22 , typename std::conditional
23 <std::is_base_of<efl::eo::concrete, W>::value
24 , efl::eina::eo_clone_allocator
25 , efl::eina::malloc_clone_allocator
26 >::type>, T, K> base_type;
27 using base_type::base_type;
28 typedef typename base_type::container_type container_type;
29
30 eina_container_base* concat(eina_container_base const& other) const
31 {
32 return detail::concat(*this, other);
33 }
34 eina_container_base* slice(std::int64_t i, std::int64_t j) const
35 {
36 return detail::slice(*this, i, j);
37 }
38 v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t index, v8::Local<v8::Value> v)
39 {
40 return detail::set<T,W>(isolate, *this, index, v);
41 }
42 int push(v8::Isolate* isolate, v8::Local<v8::Value> v)
43 {
44 return detail::push<T,W>(isolate, *this, v);
45 }
46 v8::Local<v8::Value> pop(v8::Isolate* isolate)
47 {
48 return detail::pop<T,W,K>(isolate, *this);
49 }
50 js::container_type get_container_type() const { return array_container_type; }
51};
52
53template <typename T, typename K, typename W>
54struct range_eina_array : eina_container_common<efl::eina::range_array<W>, T, K>
55{
56 typedef eina_container_common<efl::eina::range_array<W>, T, K> base_type;
57 using base_type::base_type;
58 typedef typename base_type::container_type container_type;
59 typedef typename std::conditional
60 <std::is_base_of<efl::eo::concrete, W>::value
61 , efl::eina::eo_clone_allocator
62 , efl::eina::malloc_clone_allocator
63 >::type clone_allocator_type;
64
65 eina_container_base* concat(eina_container_base const& other) const
66 {
67 range_eina_array<T, K, W> const& rhs = static_cast<range_eina_array<T, K, W>const&>(other);
68 efl::eina::array<W, clone_allocator_type>
69 array(this->_container.begin(), this->_container.end());
70 array.insert(array.end(), rhs._container.begin(), rhs._container.end());
71 return new eina_array<T, K, W>(array.release_native_handle());
72 }
73 eina_container_base* slice(std::int64_t i, std::int64_t j) const
74 {
75 efl::eina::array<W, clone_allocator_type>
76 array(std::next(this->_container.begin(), i), std::next(this->_container.begin(), j));
77 return new eina_array<T, K, W>(array.release_native_handle());
78 }
79 js::container_type get_container_type() const { return array_container_type; }
80};
81
82// Problematic types.
83template <>
84struct eina_array<_Elm_Calendar_Mark*, js::nonclass_cls_name_getter, _Elm_Calendar_Mark>
85 : empty_container_base
86{ eina_array(Eina_Array const*){} };
87template <>
88struct eina_array<Elm_Gen_Item*, js::nonclass_cls_name_getter, Elm_Gen_Item>
89 : empty_container_base
90{ eina_array(Eina_Array const*){} };
91template <>
92struct eina_array<_Evas_Textblock_Rectangle*, js::nonclass_cls_name_getter, _Evas_Textblock_Rectangle>
93 : empty_container_base
94{ eina_array(Eina_Array const*){} };
95template <>
96struct eina_array<_Elm_Map_Overlay*, js::nonclass_cls_name_getter, _Elm_Map_Overlay>
97 : empty_container_base
98{ eina_array(Eina_Array const*){} };
99
100template <>
101struct range_eina_array<_Elm_Calendar_Mark*, js::nonclass_cls_name_getter, _Elm_Calendar_Mark>
102 : empty_container_base
103{ range_eina_array(Eina_Array const*){} };
104template <>
105struct range_eina_array<Elm_Gen_Item*, js::nonclass_cls_name_getter, Elm_Gen_Item>
106 : empty_container_base
107{ range_eina_array(Eina_Array const*){} };
108template <>
109struct range_eina_array<_Evas_Textblock_Rectangle*, js::nonclass_cls_name_getter, _Evas_Textblock_Rectangle>
110 : empty_container_base
111{ range_eina_array(Eina_Array const*){} };
112template <>
113struct range_eina_array<_Elm_Map_Overlay*, js::nonclass_cls_name_getter, _Elm_Map_Overlay>
114 : empty_container_base
115{ range_eina_array(Eina_Array const*){} };
116
117} } }
118
119#endif
diff --git a/src/bindings/eina_js/eina_js_compatibility.cc b/src/bindings/eina_js/eina_js_compatibility.cc
new file mode 100644
index 0000000..a1d992f
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_compatibility.cc
@@ -0,0 +1,12 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include <Eina.hh>
6#include <Eina_Js.hh>
7
8namespace efl { namespace eina { namespace js {
9
10std::map<std::string, v8::Local<v8::Function>> constructors_map_;
11
12} } }
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 0000000..9ef0cb8
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_compatibility.hh
@@ -0,0 +1,918 @@
1#ifndef EFL_EINA_JS_COMPATIBILITY_HH
2#define EFL_EINA_JS_COMPATIBILITY_HH
3
4#include <type_traits>
5#include <utility>
6#include <map>
7#include <string>
8#include <cstdlib>
9
10
11#ifdef HAVE_NODE_V8_H
12#include <node/v8.h>
13#elif defined(HAVE_NODEJS_DEPS_V8_V8_H)
14#include <nodejs/deps/v8/v8.h>
15#elif defined(HAVE_NODEJS_DEPS_V8_INCLUDE_V8_H)
16#include <nodejs/deps/v8/include/v8.h>
17#elif defined(HAVE_NODEJS_SRC_V8_H)
18#include <nodejs/src/v8.h>
19#elif defined(HAVE_V8_H)
20#include <v8.h>
21#else
22#error We must have at least one v8 header to include
23#endif
24
25namespace v8 {
26
27template <typename T>
28struct FunctionCallbackInfo;
29template <typename T>
30struct PropertyCallbackInfo;
31template <typename T>
32#ifdef HAVE_V8_GLOBAL
33struct Global;
34#else
35struct UniquePersistent;
36#endif
37
38class AccessorInfo;
39
40class Arguments;
41
42}
43
44namespace efl { namespace eina { namespace js {
45
46template <typename T>
47struct value_tag
48{
49 typedef T type;
50};
51
52template <typename T, typename... U>
53struct complex_tag
54{
55 T value;
56 typedef std::tuple<U...> inner_types;
57};
58
59template <typename T>
60struct make_tag_traits
61{
62 typedef typename std::remove_reference<T>::type a1;
63 typedef typename std::conditional
64 <std::is_pointer<T>::value
65 , typename std::remove_cv<T>::type
66 , T>::type type;
67};
68
69template <typename T, typename... U>
70using make_complex_tag = complex_tag<typename make_tag_traits<T>::type
71 , typename make_tag_traits<U>::type...>;
72
73template <typename T>
74struct struct_tag
75{
76 T value;
77};
78
79template <typename T>
80using make_struct_tag = struct_tag<typename make_tag_traits<T>::type>;
81
82template <typename T>
83struct struct_ptr_tag
84{
85 T value;
86};
87
88template <typename T>
89using make_struct_ptr_tag = struct_ptr_tag<typename make_tag_traits<T>::type>;
90
91template <typename T, typename... Ts>
92struct remove_tag
93{
94 typedef T type;
95};
96
97template <typename T, typename... U>
98struct remove_tag<complex_tag<T, U...>>
99{
100 typedef typename eina::js::remove_tag<T, U...>::type type;
101};
102
103template <typename T>
104struct remove_tag<struct_tag<T>>
105{
106 typedef typename eina::js::remove_tag<T>::type type;
107};
108
109template <typename T>
110struct remove_tag<struct_ptr_tag<T>>
111{
112 typedef typename eina::js::remove_tag<T>::type type;
113};
114
115template <typename T>
116struct is_handable_by_value
117{
118 static constexpr bool value = !std::is_class<T>::value || std::is_same<T, ::efl::eo::concrete>::value;
119};
120
121template <typename... T>
122struct container_wrapper
123{
124 typedef typename eina::js::remove_tag<T...>::type _notag_type;
125 typedef typename std::conditional<
126 std::is_convertible<_notag_type, Eo const* const>::value
127 , typename std::conditional<
128 std::is_const<typename std::remove_pointer<_notag_type>::type>::value
129 , ::efl::eo::concrete const
130 , ::efl::eo::concrete
131 >::type
132 , _notag_type
133 >::type type;
134};
135
136template <typename T>
137T container_wrap(T&& v)
138{
139 return std::forward<T>(v);
140}
141
142inline ::efl::eo::concrete container_wrap(Eo* v)
143{
144 if(v)
145 eo_ref(v);
146 return ::efl::eo::concrete{v};
147}
148
149inline ::efl::eo::concrete container_wrap(Eo const* v)
150{
151 if (v)
152 eo_ref(v);
153 return ::efl::eo::concrete{const_cast<Eo*>(v)};
154}
155
156template <typename T>
157T& container_unwrap(T& v)
158{
159 return v;
160}
161
162inline Eo* container_unwrap(::efl::eo::concrete& v)
163{
164 return v._eo_ptr();
165}
166
167inline Eo* container_unwrap(::efl::eo::concrete const& v)
168{
169 return v._eo_ptr();
170}
171
172template <typename T>
173struct is_complex_tag : std::false_type {};
174
175template <typename... T>
176struct is_complex_tag<complex_tag<T...>> : std::true_type {};
177
178template <typename T>
179struct is_struct_tag : std::false_type {};
180
181template <typename T>
182struct is_struct_tag<struct_tag<T>> : std::true_type {};
183
184template <typename T>
185struct is_struct_ptr_tag : std::false_type {};
186
187template <typename T>
188struct is_struct_ptr_tag<struct_ptr_tag<T>> : std::true_type {};
189
190template <typename T>
191struct is_type_tag
192{
193 static constexpr bool value =
194 is_complex_tag<T>::value
195 || is_struct_tag<T>::value
196 || is_struct_ptr_tag<T>::value;
197};
198
199
200// Class name getters
201struct cls_name_getter_base {};
202struct cls_name_getter_generated_base : cls_name_getter_base {};
203/// Name getter for types that are not classes
204struct nonclass_cls_name_getter : cls_name_getter_base
205{
206 static char const* class_name() { return ""; }
207};
208
209// JS container base
210enum container_type
211{
212 list_container_type
213 , array_container_type
214 , container_type_size
215};
216
217struct eina_container_base
218{
219 virtual ~eina_container_base() {}
220
221 virtual std::size_t size() const = 0;
222 virtual eina_container_base* concat(eina_container_base const& rhs) const = 0;
223 virtual eina_container_base* slice(std::int64_t i, std::int64_t j) const = 0;
224 virtual int index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const = 0;
225 virtual int last_index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const = 0;
226 virtual v8::Local<v8::Value> get(v8::Isolate*, std::size_t) const = 0;
227 virtual v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t index, v8::Local<v8::Value> v) = 0;
228 virtual int push(v8::Isolate* isolate, v8::Local<v8::Value> v) = 0;
229 virtual v8::Local<v8::Value> pop(v8::Isolate* isolate) = 0;
230 virtual v8::Local<v8::String> to_string(v8::Isolate*) const = 0;
231 virtual v8::Local<v8::String> join(v8::Isolate*, v8::Local<v8::Value> separator) const = 0;
232 virtual container_type get_container_type() const = 0;
233 virtual void* get_container_native_handle() = 0;
234 virtual void const* get_container_native_handle() const = 0;
235};
236
237// Containers forward declarations
238
239// Array
240template <typename T, typename K = nonclass_cls_name_getter, typename W = typename container_wrapper<T>::type>
241struct eina_array;
242template <typename T, typename K = nonclass_cls_name_getter, typename W = typename container_wrapper<T>::type>
243struct range_eina_array;
244
245EAPI v8::Handle<v8::Function> get_array_instance_template();
246
247// List
248template <typename T, typename K = nonclass_cls_name_getter, typename W = typename container_wrapper<T>::type>
249struct eina_list;
250template <typename T, typename K = nonclass_cls_name_getter, typename W = typename container_wrapper<T>::type>
251struct range_eina_list;
252
253EAPI v8::Handle<v8::Function> get_list_instance_template();
254
255// Accessor
256template <typename T, typename W>
257v8::Local<v8::Object> export_accessor(::efl::eina::accessor<W>&, v8::Isolate*, const char*);
258
259template <typename T>
260::efl::eina::accessor<T>& import_accessor(v8::Handle<v8::Object>);
261
262// Wrap value functions
263template <typename R, typename T>
264typename std::remove_cv<typename std::remove_reference<R>::type>::type
265wrap_value(T v, value_tag<R>
266 , typename std::enable_if<!is_type_tag<typename std::remove_cv<R>::type>::value>::type* = 0)
267{
268 return v;
269}
270
271template <typename R, typename T>
272R wrap_value(T const& v, value_tag<eina::js::struct_tag<T>>)
273{
274 return R {v};
275}
276
277template <typename R, typename T>
278R wrap_value(T v, value_tag<eina::js::struct_ptr_tag<T>>)
279{
280 return R {v};
281}
282
283template <typename R, typename T, typename... U>
284R wrap_value(T v, value_tag<eina::js::complex_tag<T, U...>>)
285{
286 return R {v};
287}
288
289template <typename T = v8::External>
290struct _libv8_isolate_test
291{
292 using new_signature = v8::Local<T>(*)(v8::Isolate*, void*);
293 static const bool value = std::is_same<decltype(static_cast<new_signature>(&T::New)), new_signature>::value;
294};
295
296template <typename T = v8::FunctionTemplate, typename Enable = void>
297struct _libv8_callback_info_test;
298
299typedef v8::Handle<v8::Value>(*_libv8_invocation_callback)(v8::Arguments const&);
300
301template <typename T>
302struct _libv8_callback_info_test
303<T, typename std::enable_if
304 <!std::is_same<decltype( & T::SetCallHandler)
305 , void (T::*)(_libv8_invocation_callback, v8::Handle<v8::Value>)>::value>::type>
306 : std::true_type
307{
308};
309
310template <typename T>
311struct _libv8_callback_info_test
312<T, typename std::enable_if
313 <std::is_same<decltype( & T::SetCallHandler)
314 , void (T::*)(_libv8_invocation_callback, v8::Handle<v8::Value>)>::value>::type>
315 : std::false_type
316{
317};
318
319template <typename T = v8::ObjectTemplate, typename Enable = void>
320struct _libv8_property_callback_info_test
321 : std::true_type {};
322
323typedef v8::Handle<v8::Value>(*_libv8_getter_callback)(v8::Local<v8::String>, v8::AccessorInfo const&);
324typedef void(*_libv8_setter_callback)(v8::Local<v8::String>, v8::Local<v8::Value>, v8::AccessorInfo const&);
325
326template <typename T>
327struct _libv8_property_callback_info_test
328<T, typename std::enable_if
329 <std::is_same<decltype( & T::SetAccessor)
330 , void (T::*)
331 (v8::Handle<v8::String>
332 , _libv8_getter_callback
333 , _libv8_setter_callback
334 , v8::Handle<v8::Value>
335 , v8::AccessControl
336 , v8::PropertyAttribute
337 , v8::Handle<v8::AccessorSignature>
338 )>::value>::type>
339 : std::false_type
340{
341};
342
343static constexpr bool const v8_uses_isolate = _libv8_isolate_test<>::value;
344static constexpr bool const v8_uses_callback_info = _libv8_callback_info_test<>::value;
345static constexpr bool const v8_uses_property_callback_info = _libv8_property_callback_info_test<>::value;
346
347using compatibility_return_type = std::conditional<v8_uses_callback_info, void, v8::Handle<v8::Value> >::type;
348using compatibility_callback_info_type
349 = std::conditional<v8_uses_callback_info, v8::FunctionCallbackInfo<v8::Value> const&, v8::Arguments const&>
350 ::type;
351using compatibility_callback_info_pointer
352 = std::conditional<v8_uses_callback_info, v8::FunctionCallbackInfo<v8::Value> const*, v8::Arguments const*>
353 ::type;
354
355typedef compatibility_return_type(*compatibility_function_callback)(compatibility_callback_info_type);
356
357using compatibility_accessor_getter_return_type
358 = std::conditional<v8_uses_property_callback_info, void, v8::Handle<v8::Value> >::type;
359using compatibility_accessor_getter_callback_info_type
360 = std::conditional<v8_uses_property_callback_info
361 , v8::PropertyCallbackInfo<v8::Value> const&, v8::AccessorInfo const&>
362 ::type;
363
364using compatibility_accessor_setter_return_type
365 = void;
366using compatibility_accessor_setter_callback_info_type
367 = std::conditional<v8_uses_property_callback_info
368 , v8::PropertyCallbackInfo<void> const&, v8::AccessorInfo const&>
369 ::type;
370
371using compatibility_indexed_property_getset_return_type
372 = std::conditional<v8_uses_property_callback_info, void, v8::Handle<v8::Value> >::type;
373using compatibility_indexed_property_callback_info_type
374 = std::conditional<v8_uses_property_callback_info
375 , v8::PropertyCallbackInfo<v8::Value> const&, v8::AccessorInfo const&>
376 ::type;
377
378static_assert(v8_uses_property_callback_info == v8_uses_callback_info
379 && v8_uses_callback_info == v8_uses_isolate, "");
380
381template <typename T>
382struct compatibility_type_tag {};
383
384template <bool = v8_uses_isolate>
385struct compatibility_string;
386
387template <>
388struct compatibility_string<true> : v8::String
389{
390 template <typename... Args>
391 static v8::Local<v8::String> New(Args...args)
392 {
393 return NewFromUtf8(v8::Isolate::GetCurrent(), args...);
394 }
395};
396
397template <>
398struct compatibility_string<false> : v8::String
399{
400};
401
402template <typename...Args>
403auto compatibility_new_impl(v8::Isolate*, std::true_type, compatibility_type_tag<v8::String>
404 , Args...args) ->
405 decltype(compatibility_string<>::New(args...))
406{
407 return compatibility_string<>::New(args...);
408}
409
410template <typename...Args>
411auto compatibility_new_impl(v8::Isolate*, std::false_type, compatibility_type_tag<v8::String>
412 , Args...args) ->
413 decltype(compatibility_string<>::New(args...))
414{
415 return compatibility_string<>::New(args...);
416}
417
418template <typename...Args>
419auto compatibility_new_impl(std::nullptr_t, std::true_type, compatibility_type_tag<v8::String>
420 , Args...args) ->
421 decltype(compatibility_string<>::New(args...))
422{
423 return compatibility_string<>::New(args...);
424}
425
426template <typename...Args>
427auto compatibility_new_impl(std::nullptr_t, std::false_type, compatibility_type_tag<v8::String>
428 , Args...args) ->
429 decltype(compatibility_string<>::New(args...))
430{
431 return compatibility_string<>::New(args...);
432}
433
434template <typename T, typename...Args>
435auto compatibility_new_impl(v8::Isolate* isolate, std::true_type, compatibility_type_tag<T>
436 , Args...args) ->
437 decltype(T::New(isolate, args...))
438{
439 return T::New(isolate, args...);
440}
441
442template <typename T, typename...Args>
443auto compatibility_new_impl(v8::Isolate*, std::false_type, compatibility_type_tag<T>
444 , Args...args) ->
445 decltype(T::New(args...))
446{
447 return T::New(args...);
448}
449
450template <typename T, typename...Args>
451auto compatibility_new_impl(std::nullptr_t, std::true_type, compatibility_type_tag<T>
452 , Args...args) ->
453 decltype(T::New(v8::Isolate::GetCurrent(), args...))
454{
455 return T::New(v8::Isolate::GetCurrent(), args...);
456}
457
458template <typename T, typename...Args>
459auto compatibility_new_impl(std::nullptr_t, std::false_type, compatibility_type_tag<T>
460 , Args...args) ->
461 decltype(T::New(args...))
462{
463 return T::New(args...);
464}
465
466template <typename T, typename...Args>
467auto compatibility_new(v8::Isolate* isolate, Args...args) ->
468 decltype(js::compatibility_new_impl<>
469 (isolate, std::integral_constant<bool, v8_uses_isolate>()
470 , compatibility_type_tag<T>()
471 , args...))
472{
473 return js::compatibility_new_impl(isolate, std::integral_constant<bool, v8_uses_isolate>()
474 , compatibility_type_tag<T>()
475 , args...);
476}
477
478template <typename T, typename...Args>
479auto compatibility_new(std::nullptr_t, Args...args) ->
480 decltype(js::compatibility_new_impl<>(nullptr, std::integral_constant<bool, v8_uses_isolate>()
481 , compatibility_type_tag<T>()
482 , args...))
483{
484 return js::compatibility_new_impl<>(nullptr, std::integral_constant<bool, v8_uses_isolate>()
485 , compatibility_type_tag<T>()
486 , args...);
487}
488
489#ifdef HAVE_V8_CREATE_PARAMS
490namespace detail {
491class array_buffer_allocator : public v8::ArrayBuffer::Allocator
492{
493 public:
494 virtual void* Allocate(std::size_t length)
495 {
496 void* data = AllocateUninitialized(length);
497 return data ? std::memset(data, 0, length) : data;
498 }
499 virtual void* AllocateUninitialized(std::size_t length) { return std::malloc(length); }
500 virtual void Free(void* data, std::size_t) { std::free(data); }
501};
502}
503
504inline v8::Isolate* compatibility_isolate_new()
505{
506 static detail::array_buffer_allocator allocator;
507 v8::Isolate::CreateParams create_params;
508 create_params.array_buffer_allocator = &allocator;
509 return v8::Isolate::New(create_params);
510}
511
512#else
513
514inline v8::Isolate* compatibility_isolate_new()
515{
516 return v8::Isolate::New();
517}
518
519#endif
520
521template <typename T, typename U>
522inline void compatibility_return_impl(T object, U const& info, std::true_type)
523{
524 info.GetReturnValue().Set(object);
525}
526
527template <typename T>
528inline v8::Handle<v8::Value>
529compatibility_return_impl(T object, compatibility_callback_info_type, std::false_type)
530{
531 return object;
532}
533
534template <typename T>
535inline v8::Handle<v8::Value>
536compatibility_return_impl(T object, compatibility_accessor_getter_callback_info_type, std::false_type)
537{
538 return object;
539}
540
541template <typename T>
542compatibility_return_type
543compatibility_return(T object, compatibility_callback_info_type args)
544{
545 return compatibility_return_impl(object, args, std::integral_constant<bool, v8_uses_callback_info>());
546}
547
548template <typename T>
549compatibility_return_type
550compatibility_return(T object, compatibility_accessor_getter_callback_info_type args)
551{
552 return compatibility_return_impl(object, args, std::integral_constant<bool, v8_uses_property_callback_info>());
553}
554
555inline void compatibility_return_nil_impl(std::true_type) {}
556
557inline v8::Handle<v8::Value>
558compatibility_return_nil_impl(std::false_type)
559{
560 return v8::Handle<v8::Value>();
561}
562
563inline
564compatibility_return_type
565compatibility_return()
566{
567 return compatibility_return_nil_impl(std::integral_constant<bool, v8_uses_callback_info>());
568}
569
570struct _v8_isolate_throw_exception : v8::Isolate
571{
572 v8::Handle<v8::Value> ThrowException_impl(v8::Handle<v8::Value> v)
573 {
574 using namespace v8;
575 return ThrowException(v);
576 }
577};
578
579inline void
580compatibility_throw_impl(v8::Isolate* isolate, v8::Local<v8::Value> exception, std::true_type)
581{
582 static_cast<_v8_isolate_throw_exception*>(isolate)->ThrowException_impl(exception);
583}
584
585inline v8::Handle<v8::Value>
586compatibility_throw_impl(v8::Isolate* isolate, v8::Local<v8::Value> exception, std::false_type)
587{
588 return static_cast<_v8_isolate_throw_exception*>(isolate)->ThrowException_impl(exception);
589}
590
591inline std::conditional<v8_uses_isolate, void, v8::Handle<v8::Value> >::type
592compatibility_throw(v8::Isolate* isolate, v8::Local<v8::Value> exception)
593{
594 return compatibility_throw_impl(isolate, exception, std::integral_constant<bool, v8_uses_isolate>());
595}
596
597inline void
598compatibility_throw_impl(v8::Local<v8::Value> exception, std::true_type)
599{
600 static_cast<_v8_isolate_throw_exception*>(v8::Isolate::GetCurrent())->ThrowException_impl(exception);
601}
602
603inline v8::Handle<v8::Value>
604compatibility_throw_impl(v8::Local<v8::Value> exception, std::false_type)
605{
606 return static_cast<_v8_isolate_throw_exception*>(v8::Isolate::GetCurrent())->ThrowException_impl(exception);
607}
608
609inline std::conditional<v8_uses_isolate, void, v8::Handle<v8::Value> >::type
610compatibility_throw(v8::Local<v8::Value> exception)
611{
612 return compatibility_throw_impl(exception, std::integral_constant<bool, v8_uses_isolate>());
613}
614
615template <typename T, typename U>
616v8::Local<T> compatibility_cast(v8::Local<U> v);
617template <typename T, typename U>
618v8::Local<T> compatibility_cast(U* v);
619
620template <typename Tag>
621struct hack_private_member {
622 /* export it ... */
623 typedef typename Tag::type type;
624 static type ptr;
625};
626
627template <typename Tag>
628typename hack_private_member<Tag>::type hack_private_member<Tag>::ptr;
629
630template <typename Tag, typename Tag::type p>
631struct rob_private_member : hack_private_member<Tag> {
632 /* fill it ... */
633 struct filler {
634 filler() { hack_private_member<Tag>::ptr = p; }
635 };
636 static filler filler_obj;
637};
638
639template<typename Tag, typename Tag::type p>
640typename rob_private_member<Tag, p>::filler rob_private_member<Tag, p>::filler_obj;
641
642template <typename T>
643struct persistent_base_new { typedef T*(*type)(v8::Isolate*, T*); };
644
645template class rob_private_member<persistent_base_new<v8::Value>, &v8::PersistentBase<v8::Value>::New>;
646
647template <typename T>
648v8::Local<T> make_persistent(v8::Isolate* isolate, v8::Handle<T> v)
649{
650 v8::Value* p = hack_private_member<persistent_base_new<v8::Value>>::ptr
651 (isolate, *compatibility_cast<v8::Value>(v));
652 return compatibility_cast<T>(compatibility_cast<v8::Value>(p));
653}
654
655template <typename T, typename F>
656v8::Local<T> make_weak(v8::Isolate* isolate, v8::Handle<T> v, F&& f)
657{
658 v8::Value* p = hack_private_member<persistent_base_new<v8::Value>>::ptr
659 (isolate, *compatibility_cast<v8::Value>(v));
660 v8::PersistentBase<v8::Value>* persistent = static_cast<v8::PersistentBase<v8::Value>*>
661 (static_cast<void*>(&p));
662
663 auto callback = [](const v8::WeakCallbackInfo<typename std::remove_reference<F>::type>& data) -> void
664 {
665 typename std::remove_reference<F>::type* f = data.GetParameter();
666 (*f)();
667 delete f;
668 };
669
670 persistent->SetWeak(new typename std::remove_reference<F>::type(std::forward<F>(f)),
671 callback, v8::WeakCallbackType::kParameter);
672 return compatibility_cast<T>(compatibility_cast<v8::Value>(p));
673}
674
675template <typename T>
676struct global_ref
677{
678 global_ref() {}
679 global_ref(v8::Local<T> v)
680 : _value(make_persistent(nullptr, v))
681 {
682 }
683 global_ref(v8::Isolate* isolate, v8::Local<T> v)
684 : _value(make_persistent(isolate, v))
685 {
686 }
687
688 void dispose() const
689 {
690 v8::PersistentBase<T>* p = static_cast<v8::PersistentBase<T>*>(static_cast<void*>(&_value));
691 p->Reset();
692 }
693
694 v8::Handle<T> handle() const { return _value; }
695private:
696 mutable v8::Local<T> _value;
697};
698
699template <typename T = std::integral_constant<bool, v8_uses_isolate> >
700struct _v8_object_internal_field;
701
702template <>
703struct _v8_object_internal_field<std::true_type> : v8::Object
704{
705};
706
707inline void* GetPointerFromInternalField(int) { return nullptr; }
708inline void SetPointerInInternalField(int, void*) {}
709
710template <>
711struct _v8_object_internal_field<std::false_type> : v8::Object
712{
713 void* GetAlignedPointerFromInternalField(int index)
714 {
715 return GetPointerFromInternalField(index);
716 }
717 void SetAlignedPointerInInternalField(int index, void* p)
718 {
719 SetPointerInInternalField(index, p);
720 }
721};
722
723template <typename T = void*>
724inline T compatibility_get_pointer_internal_field(v8::Handle<v8::Object> object, std::size_t index)
725{
726 return reinterpret_cast<T>
727 (static_cast<_v8_object_internal_field<>*>(*object)->GetAlignedPointerFromInternalField(index));
728}
729
730template <typename T>
731inline void compatibility_set_pointer_internal_field(v8::Handle<v8::Object> object, std::size_t index
732 , T* pointer)
733{
734 static_cast<_v8_object_internal_field<>*>(*object)->SetAlignedPointerInInternalField(index, pointer);
735}
736
737template <typename T = void, bool = v8_uses_isolate>
738struct compatibility_handle_scope_impl;
739
740template <typename T>
741struct compatibility_handle_scope_impl<T, true> : v8::HandleScope
742{
743 compatibility_handle_scope_impl()
744 : HandleScope(v8::Isolate::GetCurrent())
745 {}
746 compatibility_handle_scope_impl(v8::Isolate* isolate)
747 : HandleScope((assert(isolate != nullptr), isolate))
748 {}
749};
750
751template <typename T>
752struct compatibility_handle_scope_impl<T, false> : v8::HandleScope
753{
754 compatibility_handle_scope_impl()
755 {}
756 compatibility_handle_scope_impl(v8::Isolate*)
757 {}
758};
759
760using compatibility_handle_scope = compatibility_handle_scope_impl<>;
761
762template <bool = v8_uses_isolate>
763struct _v8_initialize_icu;
764
765template <>
766struct _v8_initialize_icu<true> : v8::V8
767{
768};
769
770template <>
771struct _v8_initialize_icu<false> : v8::V8
772{
773 static bool InitializeICU(const char* = NULL)
774 {
775 return true;
776 }
777};
778
779inline void compatibility_initialize()
780{
781#ifdef HAVE_V8_CREATE_PARAMS
782 constexpr const char* argv[] = {""};
783 static_cast<_v8_initialize_icu<>*>(nullptr)->InitializeICU();
784 v8::V8::InitializeExternalStartupData(argv[0]);
785 v8::V8::Initialize();
786#else
787 v8::V8::Initialize();
788 static_cast<_v8_initialize_icu<>*>(nullptr)->InitializeICU();
789#endif
790}
791
792template <typename T, typename U>
793v8::Local<T> compatibility_cast(v8::Local<U> v)
794{
795 static_assert(sizeof(v8::Local<T>) == sizeof(v8::Local<U>), "");
796 v8::Local<T> l;
797 std::memcpy(&l, &v, sizeof(v8::Local<T>));
798 return l;
799}
800
801template <typename T, typename U>
802v8::Local<T> compatibility_cast(U* v)
803{
804 static_assert(sizeof(v8::Local<T>) == sizeof(U*), "");
805 v8::Local<T> l;
806 std::memcpy(&l, &v, sizeof(v8::Local<T>));
807 return l;
808}
809
810template <typename T = v8::Isolate, bool = v8_uses_isolate>
811struct _v8_get_current_context;
812
813template <typename T>
814struct _v8_get_current_context<T, false> : v8::Context
815{
816};
817
818template <typename T>
819struct _v8_get_current_context<T, true> : T
820{
821 static v8::Local<v8::Context> GetCurrent()
822 {
823 return T::GetCurrent()->GetCurrentContext();
824 }
825};
826
827template <typename T>
828inline v8::Local<v8::Value>
829new_v8_external_instance(v8::Handle<v8::Function>& ctor, T v, v8::Isolate* isolate)
830{
831 // TODO: ensure v8::External ownership ??? (memory leak in case NewInstance throws)
832 v8::Handle<v8::Value> a[] = {efl::eina::js::compatibility_new<v8::External>(isolate, v)};
833 return ctor->NewInstance(1, a);
834}
835
836inline
837compatibility_return_type cast_function(compatibility_callback_info_type args);
838
839inline v8::Local<v8::Value>
840new_v8_external_instance(v8::Handle<v8::Function>& ctor, Eo* v, v8::Isolate* isolate)
841{
842 // TODO: ensure v8::External ownership ??? (memory leak in case NewInstance throws)
843 v8::Handle<v8::Value> a[] = {efl::eina::js::compatibility_new<v8::External>(isolate, v)};
844 auto obj = ctor->NewInstance(1, a);
845 obj->Set(compatibility_new<v8::String>(isolate, "cast"),
846 compatibility_new<v8::FunctionTemplate>(isolate, &cast_function)->GetFunction());
847 return obj;
848}
849
850inline v8::Local<v8::Object> compatibility_global()
851{
852 return _v8_get_current_context<>::GetCurrent()->Global();
853}
854
855EAPI extern std::map<std::string, v8::Local<v8::Function>> constructors_map_;
856
857inline v8::Handle<v8::Function> get_class_constructor(std::string const& class_name)
858{
859 auto it = constructors_map_.find(class_name);
860 if (it == constructors_map_.end())
861 throw std::runtime_error("Class not found");
862 return it->second;
863}
864
865inline void register_class_constructor(std::string const& class_name,
866 v8::Handle<v8::Function> constructor_ptr)
867{
868 // TODO: check if already exist?
869 constructors_map_[class_name] = constructor_ptr;
870}
871
872template<class T = v8::StackTrace>
873typename std::enable_if<!v8_uses_isolate, v8::Local<T>>::type
874compatibility_current_stack_trace(v8::Isolate*, int frame_limit,
875 v8::StackTrace::StackTraceOptions options)
876{
877 return T::CurrentStackTrace(frame_limit, options);
878}
879
880template<class T = v8::StackTrace>
881typename std::enable_if<v8_uses_isolate, v8::Local<T>>::type
882compatibility_current_stack_trace(v8::Isolate *isolate, int frame_limit,
883 v8::StackTrace::StackTraceOptions options)
884{
885 return T::CurrentStackTrace(isolate, frame_limit, options);
886}
887
888inline
889compatibility_return_type cast_function(compatibility_callback_info_type args)
890{
891 auto isolate = args.GetIsolate();
892 compatibility_handle_scope scope(isolate);
893 v8::Local<v8::Value> type;
894 if(args.Length() == 1 && (type = args[0])->IsString())
895 {
896 v8::Local<v8::Object> self = args.This();
897 v8::Local<v8::Value> external = self->GetInternalField(0);
898 Eo* eo = static_cast<Eo*>(v8::External::Cast(*external)->Value());
899
900 v8::String::Utf8Value str(type->ToString());
901 char* class_name = *str;
902
903 auto ctor = ::efl::eina::js::get_class_constructor(class_name);
904 return compatibility_return
905 (new_v8_external_instance(ctor, ::eo_ref(eo), isolate), args);
906 }
907 else
908 {
909 eina::js::compatibility_throw
910 (isolate, v8::Exception::TypeError
911 (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected String type")));
912 return compatibility_return();
913 }
914}
915
916} } }
917
918#endif
diff --git a/src/bindings/eina_js/eina_js_container.cc b/src/bindings/eina_js/eina_js_container.cc
new file mode 100644
index 0000000..60c53e0
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_container.cc
@@ -0,0 +1,495 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include <Eina.hh>
6#include <Eina.h>
7#include <cstdlib>
8
9#include <Eo.h>
10
11#include <eina_integer_sequence.hh>
12#include <eina_tuple.hh>
13#include <eina_ptrlist.hh>
14
15#include <Eina_Js.hh>
16
17#include <tuple>
18
19#include <iostream>
20
21namespace efl { namespace eina { namespace js {
22
23template <typename T>
24struct tag { typedef T type; };
25
26namespace {
27
28global_ref<v8::ObjectTemplate> instance_persistents[container_type_size];
29global_ref<v8::Function> instance_templates[container_type_size];
30
31v8::Local<v8::Value> push(eina_container_base& self, v8::Isolate* isolate, v8::Local<v8::Value> value)
32{
33 return v8::Integer::New(isolate, self.push(isolate, value));
34}
35
36v8::Local<v8::Value> pop(eina_container_base& self, v8::Isolate* isolate, v8::Local<v8::Value>)
37{
38 return self.pop(isolate);
39}
40
41v8::Local<v8::Value> concat(eina_container_base& lhs, v8::Isolate* isolate, v8::Local<v8::Value> other)
42{
43 const char* error_message = 0;
44 if(other->IsObject())
45 {
46 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(other);
47 v8::String::Utf8Value constructor_name (obj->GetConstructorName());
48 if(obj->GetConstructorName()->Equals(efl::eina::js::compatibility_new<v8::String>(isolate, "eina_list"))
49 || obj->GetConstructorName()->Equals(efl::eina::js::compatibility_new<v8::String>(isolate, "eina_array")))
50 {
51 eina_container_base& rhs = *static_cast<eina_container_base*>
52 (efl::eina::js::compatibility_get_pointer_internal_field(obj, 0));
53 std::type_info const& typeinfo_lhs = typeid(lhs)
54 , &typeinfo_rhs = typeid(rhs);
55 if(!typeinfo_lhs.before(typeinfo_rhs) && !typeinfo_rhs.before(typeinfo_lhs))
56 {
57 v8::Handle<v8::Value> a[] =
58 {efl::eina::js::compatibility_new<v8::External>(isolate, rhs.concat(lhs))};
59 assert(!!*instance_templates[lhs.get_container_type()].handle());
60 v8::Local<v8::Object> result =
61 instance_templates[lhs.get_container_type()].handle()->NewInstance(1, a);
62 return result;
63 }
64 else
65 error_message = "Containers are not of the same type.";
66 }
67 else
68 error_message = "Object to be concatenated is not a container.";
69 }
70 else
71 error_message = "Concatenation argument is not an container";
72
73 eina::js::compatibility_throw
74 (isolate, v8::Exception::TypeError(eina::js::compatibility_new<v8::String>(isolate, error_message)));
75
76 return v8::Undefined(isolate);
77}
78
79v8::Local<v8::Value> slice(eina_container_base& self, v8::Isolate* isolate, v8::Local<v8::Value> begin
80 , v8::Local<v8::Value> end)
81{
82 std::size_t i, j;
83
84 if(begin->IsUint32() || begin->IsInt32())
85 i = begin->IntegerValue();
86 else if (begin->IsUndefined())
87 i = 0;
88 else
89 return v8::Undefined(isolate);
90
91 if(end->IsUint32() || end->IsInt32())
92 j = end->IntegerValue();
93 else if (end->IsUndefined())
94 j = self.size();
95 else
96 return v8::Undefined(isolate);
97
98 v8::Handle<v8::Value> a[] = {efl::eina::js::compatibility_new<v8::External>(isolate, self.slice(i, j))};
99 v8::Local<v8::Object> result = instance_templates[self.get_container_type()].handle()
100 ->NewInstance(1, a);
101 return result;
102}
103
104compatibility_accessor_getter_return_type length
105 (v8::Local<v8::String>, compatibility_accessor_getter_callback_info_type info)
106{
107 v8::Local<v8::Object> self_obj = compatibility_cast<v8::Object>(info.This());
108 eina_container_base* self = static_cast<eina_container_base*>
109 (compatibility_get_pointer_internal_field(self_obj, 0));
110 return compatibility_return(js::get_value_from_c(self->size(), info.GetIsolate(), ""), info);
111}
112
113compatibility_indexed_property_getset_return_type index_get
114 (uint32_t index, compatibility_indexed_property_callback_info_type info)
115{
116 v8::Local<v8::Object> self_obj = v8::Local<v8::Object>::Cast(info.This());
117 eina_container_base* self = static_cast<eina_container_base*>
118 (compatibility_get_pointer_internal_field(self_obj, 0));
119 return compatibility_return(self->get(info.GetIsolate(), index), info);
120}
121
122compatibility_indexed_property_getset_return_type index_set
123 (uint32_t index, v8::Local<v8::Value> value, compatibility_indexed_property_callback_info_type info)
124{
125 v8::Local<v8::Object> self_obj = v8::Local<v8::Object>::Cast(info.This());
126 eina_container_base* self = static_cast<eina_container_base*>
127 (compatibility_get_pointer_internal_field(self_obj, 0));
128
129 return compatibility_return(self->set(info.GetIsolate(), index, value), info);
130}
131
132
133#define GENERATE_CONTAINER_CONSTRUCT_TYPE_IF(x) GENERATE_CONTAINER_CONSTRUCT_TYPE2_IF(x, x)
134#define GENERATE_CONTAINER_CONSTRUCT_TYPE2_IF(x, y) if (!strcmp(class_name, #x)) \
135 return new Container<y, nonclass_cls_name_getter, typename container_wrapper<y>::type>();
136
137template< template<typename, typename, typename> class Container>
138eina_container_base* construct_container(const char* class_name)
139{
140 GENERATE_CONTAINER_CONSTRUCT_TYPE_IF(int);
141 GENERATE_CONTAINER_CONSTRUCT_TYPE_IF(float);
142 GENERATE_CONTAINER_CONSTRUCT_TYPE2_IF(bool, Eina_Bool);
143 GENERATE_CONTAINER_CONSTRUCT_TYPE2_IF(string, char*);
144
145 return 0;
146}
147
148compatibility_return_type new_eina_list_internal(compatibility_callback_info_type args)
149{
150 if(args.IsConstructCall())
151 {
152 if(args.Length() == 0)
153 {
154 eina_container_base* p = new eina_list<int>;
155 compatibility_set_pointer_internal_field
156 (args.This(), 0, dynamic_cast<void*>(p));
157 }
158 else
159 {
160 if(args[0]->IsExternal())
161 {
162 eina_container_base* base = reinterpret_cast<eina_container_base*>
163 (v8::External::Cast(*args[0])->Value());
164 compatibility_set_pointer_internal_field
165 (args.This(), 0, dynamic_cast<void*>(base));
166 }
167 else
168 std::abort();
169 }
170 }
171 else
172 std::abort();
173 return compatibility_return();
174}
175
176compatibility_return_type new_eina_list(compatibility_callback_info_type args)
177{
178 if(args.IsConstructCall())
179 {
180 if(args.Length() == 0) // Default constructor, list of ints. Or should be list of Eo's?
181 {
182 eina_container_base* p = new eina_list<int>;
183 compatibility_set_pointer_internal_field
184 (args.This(), 0, dynamic_cast<void*>(p));
185 return compatibility_return();
186 }
187 else if (args.Length() == 1 && args[0]->IsString())
188 {
189 v8::String::Utf8Value string(args[0]);
190 eina_container_base* p = construct_container<efl::eina::js::eina_list>(*string);
191 if (!p) {
192 return eina::js::compatibility_throw
193 (args.GetIsolate(), v8::Exception::TypeError
194 (eina::js::compatibility_new<v8::String>(args.GetIsolate(), "Invalid type for container.")));
195 }
196 compatibility_set_pointer_internal_field
197 (args.This(), 0, dynamic_cast<void*>(p));
198 return compatibility_return();
199 }
200 }
201 return eina::js::compatibility_throw
202 (args.GetIsolate(), v8::Exception::TypeError
203 (eina::js::compatibility_new<v8::String>(args.GetIsolate(), "Wrong number of arguments for constructor call")));
204}
205
206compatibility_return_type new_eina_array_internal(compatibility_callback_info_type args)
207{
208 if(args.IsConstructCall())
209 {
210 if(args.Length() == 0)
211 {
212 eina_container_base* p = new eina_array<int>;
213 compatibility_set_pointer_internal_field
214 (args.This(), 0, dynamic_cast<void*>(p));
215 }
216 else
217 {
218 if(args[0]->IsExternal())
219 {
220 eina_container_base* base = reinterpret_cast<eina_container_base*>
221 (v8::External::Cast(*args[0])->Value());
222 compatibility_set_pointer_internal_field
223 (args.This(), 0, dynamic_cast<void*>(base));
224 }
225 else
226 std::abort();
227 }
228 }
229 else
230 std::abort();
231 return compatibility_return();
232}
233
234compatibility_return_type new_eina_array(compatibility_callback_info_type args)
235{
236 if(args.IsConstructCall())
237 {
238 if(args.Length() == 0)
239 {
240 eina_container_base* p = new eina_array<int>;
241 compatibility_set_pointer_internal_field
242 (args.This(), 0, dynamic_cast<void*>(p));
243 return compatibility_return();
244 }
245 else if (args.Length() == 1 && args[0]->IsString())
246 {
247 v8::String::Utf8Value string(args[0]);
248 eina_container_base* p = construct_container<efl::eina::js::eina_array>(*string);
249 if (!p) {
250 return eina::js::compatibility_throw
251 (args.GetIsolate(), v8::Exception::TypeError
252 (eina::js::compatibility_new<v8::String>(args.GetIsolate(), "Invalid type for container.")));
253 }
254 compatibility_set_pointer_internal_field
255 (args.This(), 0, dynamic_cast<void*>(p));
256 return compatibility_return();
257 }
258 }
259 return eina::js::compatibility_throw
260 (args.GetIsolate(), v8::Exception::TypeError
261 (eina::js::compatibility_new<v8::String>(args.GetIsolate(), "Wrong number of arguments for constructor call")));
262}
263
264template <typename F>
265struct function_params;
266
267template <typename R, typename... Sig>
268struct function_params<R(*)(Sig...)>
269{
270 typedef std::tuple<Sig...> type;
271};
272
273template <typename F>
274struct function_result;
275
276template <typename R, typename... Sig>
277struct function_result<R(*)(Sig...)>
278{
279 typedef R type;
280};
281
282template <typename T>
283struct is_persistent : std::false_type {};
284
285template <typename...A>
286struct is_persistent<v8::Persistent<A...> > : std::true_type {};
287
288template <std::size_t I, typename Sig>
289typename std::tuple_element<I, Sig>::type
290get_element(v8::Isolate* isolate
291 , compatibility_callback_info_type args
292 , typename std::enable_if
293 <is_persistent<typename std::tuple_element<I, Sig>::type>::value>::type* = 0)
294{
295 return typename std::tuple_element<I, Sig>::type(isolate, args[I]);
296}
297
298template <std::size_t I, typename Sig>
299typename std::tuple_element<I, Sig>::type
300get_element(v8::Isolate* /*isolate*/
301 , compatibility_callback_info_type args
302 , typename std::enable_if
303 <!is_persistent<typename std::tuple_element<I, Sig>::type>::value>::type* = 0)
304{
305 return args[I];
306}
307
308template <typename Sig, typename R, typename T, typename F, std::size_t... N>
309R call_impl(v8::Isolate* isolate
310 , compatibility_callback_info_type args
311 , T* self, F* f
312 , eina::index_sequence<N...>)
313{
314 assert(self != 0);
315 return (*f)(*self, isolate, js::get_element<N, Sig>(isolate, args)...);
316}
317
318template <typename Sig, typename T, typename F, typename R>
319compatibility_return_type call_generic_impl(compatibility_callback_info_type args, tag<R>)
320{
321 T* self = static_cast<T*>
322 (compatibility_get_pointer_internal_field<>(args.This(), 0));
323 F* f = reinterpret_cast<F*>(v8::External::Cast(*args.Data())->Value());
324 return compatibility_return
325 (js::get_value_from_c
326 (js::call_impl<Sig, R>(args.GetIsolate(), args, self, f
327 , eina::make_index_sequence<std::tuple_size<Sig>::value>())
328 , args.GetIsolate(), "")
329 , args);
330}
331
332template <typename Sig, typename T, typename F>
333compatibility_return_type call_generic_impl(compatibility_callback_info_type args, tag<void>)
334{
335 T* self = static_cast<T*>
336 (compatibility_get_pointer_internal_field(args.This(), 0));
337 F* f = reinterpret_cast<F*>(v8::External::Cast(*args.Data())->Value());
338 js::call_impl<Sig, void>(args.GetIsolate(), args, self, f
339 , eina::make_index_sequence<std::tuple_size<Sig>::value>());
340 return compatibility_return();
341}
342
343template <typename Sig, typename R, typename T, typename F>
344compatibility_return_type call_generic(compatibility_callback_info_type args)
345{
346 return efl::eina::js::call_generic_impl<Sig, T, F>(args, tag<R>());
347}
348
349template <typename Sig, typename T, typename F, typename R>
350compatibility_return_type call_function_impl(compatibility_callback_info_type args, tag<R>)
351{
352 T* self = static_cast<T*>
353 (compatibility_get_pointer_internal_field(args.This(), 0));
354 F f = reinterpret_cast<F>(v8::External::Cast(*args.Data())->Value());
355 return compatibility_return
356 (/*js::get_value_from_c*/
357 (js::call_impl<Sig, R>(args.GetIsolate(), args, self, f
358 , eina::make_index_sequence<std::tuple_size<Sig>::value>())
359 /*, args.GetIsolate(), ""*/)
360 , args);
361}
362
363template <typename Sig, typename T, typename F>
364compatibility_return_type call_function_impl(compatibility_callback_info_type args, tag<void>)
365{
366 T* self = static_cast<T*>
367 (compatibility_get_pointer_internal_field(args.This(), 0));
368 F f = reinterpret_cast<F>(v8::External::Cast(*args.Data())->Value());
369 js::call_impl<Sig, void>(args.GetIsolate(), args, self, f
370 , eina::make_index_sequence<std::tuple_size<Sig>::value>());
371 return compatibility_return();
372}
373
374template <typename Sig, typename R, typename T, typename F>
375compatibility_return_type call_function(compatibility_callback_info_type args)
376{
377 return efl::eina::js::call_function_impl<Sig, T, F>(args, tag<R>());
378}
379
380template <typename T, typename F>
381void register_(v8::Isolate* isolate, const char* name, F f, v8::Handle<v8::ObjectTemplate> template_
382 , typename std::enable_if<std::is_function<typename std::remove_pointer<F>::type>::value>::type* = 0)
383{
384 template_->Set(compatibility_new<v8::String>(isolate, name)
385 , compatibility_new<v8::FunctionTemplate>
386 (isolate, &efl::eina::js::call_function
387 <typename eina::_mpl::pop_front<typename function_params<F>::type, 2u>::type
388 , typename function_result<F>::type, T, F>
389 , compatibility_new<v8::External>
390 (isolate, reinterpret_cast<void*>(f))));
391}
392
393template <typename T, typename...Sig, typename F>
394void register_(v8::Isolate* isolate, const char* name, F&& f, v8::Handle<v8::ObjectTemplate> template_
395 , typename std::enable_if<!std::is_function<typename std::remove_pointer<F>::type>::value>::type* = 0)
396{
397 using result_type = decltype
398 (std::declval<F>()
399 (std::declval<T&>(), std::declval<v8::Isolate*>()
400 , std::declval<Sig>()...)
401 );
402 template_->Set(compatibility_new<v8::String>(isolate, name)
403 , compatibility_new<v8::FunctionTemplate>
404 (isolate
405 , &efl::eina::js::call_generic<std::tuple<Sig...>, result_type, T, F>
406 , compatibility_new<v8::External>
407 (isolate, new F(std::forward<F>(f)))));
408}
409
410v8::Local<v8::ObjectTemplate> register_template(v8::Isolate* isolate, v8::Handle<v8::FunctionTemplate> constructor)
411{
412 v8::Local<v8::ObjectTemplate> instance_t = constructor->InstanceTemplate();
413 instance_t->SetInternalFieldCount(1);
414
415 instance_t->SetIndexedPropertyHandler(& efl::eina::js::index_get, & efl::eina::js::index_set);
416
417 v8::Local<v8::ObjectTemplate> prototype = constructor->PrototypeTemplate();
418 prototype->SetAccessor(compatibility_new<v8::String>(isolate, "length"), &efl::eina::js::length);
419
420 using namespace std::placeholders;
421 js::register_<js::eina_container_base>
422 (isolate, "push", &js::push, prototype);
423 js::register_<js::eina_container_base>
424 (isolate, "pop", &js::pop, prototype);
425 js::register_<js::eina_container_base>
426 (isolate, "concat", &js::concat, prototype);
427 js::register_<js::eina_container_base>
428 (isolate, "slice", &js::slice, prototype);
429 js::register_<js::eina_container_base>
430 (isolate, "toString", std::bind(&js::eina_container_base::to_string, _1, _2), prototype);
431 js::register_<js::eina_container_base, v8::Local<v8::Value> >
432 (isolate, "join", std::bind(&js::eina_container_base::join, _1, _2, _3), prototype);
433 js::register_<js::eina_container_base, v8::Local<v8::Value> >
434 (isolate, "indexOf", std::bind(&js::eina_container_base::index_of, _1, _2, _3), prototype);
435 js::register_<js::eina_container_base, v8::Local<v8::Value> >
436 (isolate, "lastIndexOf", std::bind(&js::eina_container_base::last_index_of, _1, _2, _3), prototype);
437
438 return instance_t;
439}
440
441void register_class(v8::Isolate* isolate, container_type type, const char* class_name
442 , compatibility_function_callback callback)
443{
444 v8::Handle<v8::FunctionTemplate> constructor
445 = compatibility_new<v8::FunctionTemplate>(isolate, callback);
446 constructor->SetClassName(compatibility_new<v8::String>(isolate, class_name));
447
448 v8::Local<v8::ObjectTemplate> instance_t = efl::eina::js::register_template(isolate, constructor);
449
450 efl::eina::js::instance_persistents[type] = global_ref<v8::ObjectTemplate>{isolate, instance_t};
451 efl::eina::js::instance_templates[type] = global_ref<v8::Function>{isolate, constructor->GetFunction()};
452}
453void register_class(v8::Isolate* isolate, container_type, const char* class_name_
454 , const char* constructor_name_
455 , compatibility_function_callback callback
456 , v8::Handle<v8::Object> exports)
457{
458 v8::Handle<v8::FunctionTemplate> constructor
459 = compatibility_new<v8::FunctionTemplate>(isolate, callback);
460 auto class_name = compatibility_new<v8::String>(isolate, class_name_);
461 auto constructor_name = compatibility_new<v8::String>(isolate, constructor_name_);
462 constructor->SetClassName(class_name);
463
464 v8::Local<v8::ObjectTemplate> instance_t = efl::eina::js::register_template(isolate, constructor);
465 (void)instance_t;
466
467 exports->Set(constructor_name, constructor->GetFunction());
468}
469
470}
471
472EAPI v8::Handle<v8::Function> get_list_instance_template()
473{
474 return efl::eina::js::instance_templates[efl::eina::js::list_container_type].handle();
475}
476
477EAPI v8::Handle<v8::Function> get_array_instance_template()
478{
479 return efl::eina::js::instance_templates[efl::eina::js::array_container_type].handle();
480}
481
482} } }
483
484EAPI void eina_container_register(v8::Handle<v8::Object> exports, v8::Isolate* isolate)
485{
486 efl::eina::js::register_class(isolate, efl::eina::js::list_container_type
487 , "eina_list", &efl::eina::js::new_eina_list_internal);
488 efl::eina::js::register_class(isolate, efl::eina::js::list_container_type
489 , "eina_list", "List", &efl::eina::js::new_eina_list, exports);
490 efl::eina::js::register_class(isolate, efl::eina::js::array_container_type
491 , "eina_array", &efl::eina::js::new_eina_array_internal);
492 efl::eina::js::register_class(isolate, efl::eina::js::array_container_type
493 , "eina_array", "Array", &efl::eina::js::new_eina_array, exports);
494}
495
diff --git a/src/bindings/eina_js/eina_js_container.hh b/src/bindings/eina_js/eina_js_container.hh
new file mode 100644
index 0000000..21343fd
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_container.hh
@@ -0,0 +1,351 @@
1#ifndef EINA_JS_CONTAINER_HH
2#define EINA_JS_CONTAINER_HH
3
4#include <algorithm>
5
6#include <eina_js_compatibility.hh>
7#include <eina_js_get_value.hh>
8#include <eina_js_get_value_from_c.hh>
9
10struct _Elm_Calendar_Mark;
11struct Elm_Gen_Item;
12struct _Eina_Rectangle;
13struct _Evas_Textblock_Rectangle;
14struct _Elm_Map_Overlay;
15
16namespace efl { namespace eina { namespace js {
17
18namespace detail {
19
20template <typename T>
21eina_container_base* concat(T const& self, eina_container_base const& other)
22{
23 T const& rhs = static_cast<T const&>(other);
24 typedef typename T::container_type container_type;
25 container_type container(self._container.begin(), self._container.end());
26 container.insert(container.end(), rhs._container.begin(), rhs._container.end());
27 return new T(container.release_native_handle());
28}
29
30template <typename T>
31eina_container_base* slice(T const& self, std::int64_t i, std::int64_t j)
32{
33 typedef typename T::container_type container_type;
34 container_type container(std::next(self._container.begin(), i), std::next(self._container.begin(), j));
35 return new T(container.release_native_handle());
36}
37
38// T, W from the container instantiation
39template<typename T, typename W, typename C>
40int push(v8::Isolate* isolate, C& self, v8::Local<v8::Value> v)
41{
42 try
43 {
44 W value = container_wrap(get_value_from_javascript(v, isolate, "", value_tag<T>()));
45 self._container.push_back(value);
46 }
47 catch (std::logic_error const&)
48 {
49 return -1;
50 }
51 return self.size();
52}
53
54template<typename T, typename W, typename K, typename C>
55v8::Local<v8::Value> pop(v8::Isolate* isolate, C& self)
56{
57
58 if (self._container.empty())
59 return v8::Undefined(isolate);
60
61 auto value = eina::js::get_value_from_c(
62 eina::js::wrap_value<T>(eina::js::container_unwrap(self._container.back()), eina::js::value_tag<T>{})
63 , isolate
64 , K::class_name());
65 self._container.pop_back();
66 return value;
67}
68template<typename T, typename W, typename C>
69v8::Local<v8::Value> set(v8::Isolate* isolate, C& self, std::size_t index, v8::Local<v8::Value> v)
70 {
71 using notag_type = typename remove_tag<T>::type;
72 try
73 {
74 W value = container_wrap(get_value_from_javascript(v, isolate, "", value_tag<T>()));
75
76 if (index >= self.size())
77 {
78 std::size_t items_to_add = index - self.size() + 1;
79 for (int i = items_to_add; i; i--)
80 {
81 self._container.push_back(container_wrap(notag_type{}));
82 }
83 }
84
85 auto v2 = std::next(self._container.begin(), index);
86 *v2 = value;
87 }
88 catch (std::logic_error const&)
89 {
90 return v8::Undefined(isolate);
91 }
92
93 return v;
94 }
95
96}
97
98template <typename InputIterator, typename T>
99inline InputIterator find_element(InputIterator first, InputIterator last, T const& value, typename std::enable_if<is_handable_by_value<T>::value>::type* = 0)
100{
101 return std::find(first, last, value);
102}
103
104template <typename InputIterator, typename T>
105inline InputIterator find_element(InputIterator first, InputIterator last, T const& value, typename std::enable_if<!is_handable_by_value<T>::value>::type* = 0)
106{
107 return std::find_if(first, last, [&](T const& e){ return &e == &value; });
108}
109
110template <typename InputIterator>
111inline InputIterator find_element(InputIterator first, InputIterator last, char * value)
112{
113 return std::find_if(first, last, [=](char* e){ return strcmp(e, value) == 0; });
114}
115
116template <typename CharT, typename T>
117inline void stream_element(std::basic_ostream<CharT>& s, T const& value, typename std::enable_if<is_handable_by_value<T>::value>::type* = 0)
118{
119 s << value;
120}
121
122template <typename CharT, typename T>
123inline void stream_element(std::basic_ostream<CharT>& s, T const& value, typename std::enable_if<!is_handable_by_value<T>::value>::type* = 0)
124{
125 s << &value;
126}
127
128template <typename CharT>
129inline void stream_element(std::basic_ostream<CharT>& s, Eina_Bool value)
130{
131 s << (value ? "true" : "false");
132}
133
134template <typename C, typename T, typename K>
135struct eina_container_common;
136
137
138template <typename C, typename V, typename T, typename K, typename Enable = void>
139struct eina_container_type_specific
140 : eina_container_base
141{
142 v8::Local<v8::Value> get(v8::Isolate* isolate, std::size_t index) const
143 {
144 if(index >= this->size())
145 return v8::Undefined(isolate);
146 return eina::js::get_value_from_c(
147 eina::js::wrap_value<T>(eina::js::container_unwrap(*std::next(container_get().begin(), index)), eina::js::value_tag<T>{})
148 , isolate
149 , K::class_name());
150 }
151 int index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const
152 {
153 try
154 {
155 V value = container_wrap(get_value_from_javascript(
156 v, isolate, K::class_name(), eina::js::value_tag<T>{}, false));
157 typedef typename C::const_iterator iterator;
158 iterator first = container_get().cbegin()
159 , last = container_get().cend()
160 , found = find_element(first, last, value);
161 if(found == last)
162 return -1;
163 else
164 return std::distance(first, found);
165 }
166 catch (std::logic_error const&)
167 {
168 return -1;
169 }
170 }
171 int last_index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const
172 {
173 try
174 {
175 V value = container_wrap(get_value_from_javascript(
176 v, isolate, K::class_name(), eina::js::value_tag<T>{}, false));
177 auto last = container_get().crend()
178 , found = find_element(container_get().crbegin(), last, value);
179 if(found == last)
180 return -1;
181 else
182 return std::distance(container_get().cbegin(), found.base()) -1;
183 }
184 catch (std::logic_error const&)
185 {
186 return -1;
187 }
188 }
189 void* get_container_native_handle()
190 {
191 void const* h = container_get().native_handle();
192 return const_cast<void*>(h);
193 }
194 void const* get_container_native_handle() const
195 {
196 return container_get().native_handle();
197 }
198 C& container_get() { return static_cast<eina_container_common<C, T, K>&>(*this)._container; }
199 C const& container_get() const { return static_cast<eina_container_common<C, T, K>const&>(*this)._container; }
200};
201
202template <typename C, typename T, typename K>
203struct eina_container_common : eina_container_type_specific<C, typename C::value_type, T, K>
204{
205 eina_container_common() : _container() {}
206 eina_container_common(typename C::native_handle_type raw) : _container(raw) {}
207
208 std::size_t size() const { return _container.size(); }
209 v8::Local<v8::String> to_string(v8::Isolate* isolate) const
210 {
211 return join(isolate, compatibility_new<v8::String>(isolate, ","));
212 }
213
214 v8::Local<v8::String> join(v8::Isolate* isolate, v8::Local<v8::Value> separator_js) const
215 {
216 std::string separator = ",";
217 typedef typename container_type::const_iterator iterator;
218 std::stringstream s;
219
220 if (separator_js->IsString())
221 {
222 v8::String::Utf8Value str(separator_js);
223 if (*str)
224 {
225 separator = *str;
226 }
227 else
228 {
229 eina::js::compatibility_throw(
230 isolate, v8::Exception::TypeError(
231 eina::js::compatibility_new<v8::String>(isolate, "Invalid separator.")));
232 return compatibility_new<v8::String>(isolate, "");
233 }
234 }
235 else if (!separator_js->IsUndefined()) // Called join without arguments.
236 {
237 eina::js::compatibility_throw(
238 isolate, v8::Exception::TypeError(
239 eina::js::compatibility_new<v8::String>(isolate, "Separator must be a string.")));
240 return compatibility_new<v8::String>(isolate, "");
241 }
242
243 for(iterator first = _container.begin()
244 , last = _container.end()
245 , last_elem = std::next(last, -1); first != last; ++first)
246 {
247 stream_element(s, *first);
248 if(first != last_elem)
249 s << separator;
250 }
251 return compatibility_new<v8::String>(isolate, s.str().c_str());
252 }
253
254 // Default implementation of some methods
255 int push(v8::Isolate* isolate, v8::Local<v8::Value>)
256 {
257 eina::js::compatibility_throw
258 (isolate, v8::Exception::TypeError
259 (eina::js::compatibility_new<v8::String>(isolate, "Push method was not implemented.")));
260 return -1;
261 }
262 v8::Local<v8::Value> pop(v8::Isolate* isolate)
263 {
264 eina::js::compatibility_throw
265 (isolate, v8::Exception::TypeError
266 (eina::js::compatibility_new<v8::String>(isolate, "Pop method was not implemented.")));
267 return v8::Undefined(isolate);
268 }
269 v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t, v8::Local<v8::Value>)
270 {
271 eina::js::compatibility_throw
272 (isolate, v8::Exception::TypeError
273 (eina::js::compatibility_new<v8::String>(isolate, "Indexed attribution was not implemented.")));
274 return v8::Undefined(isolate);
275 }
276 C _container;
277 typedef C container_type;
278};
279
280
281// Specialization for problematic types
282struct empty_container_base
283 : eina_container_base
284{
285 empty_container_base() {}
286 virtual ~empty_container_base() {}
287
288 std::size_t size() const
289 {
290 return 0;
291 }
292 eina_container_base* concat(eina_container_base const& ) const
293 {
294 return new empty_container_base;
295 }
296 eina_container_base* slice(std::int64_t , std::int64_t ) const
297 {
298 return new empty_container_base;
299 }
300 int index_of(v8::Isolate*, v8::Local<v8::Value>) const
301 {
302 return -1;
303 }
304 int last_index_of(v8::Isolate*, v8::Local<v8::Value>) const
305 {
306 return -1;
307 }
308 v8::Local<v8::Value> get(v8::Isolate* isolate, std::size_t) const
309 {
310 return v8::Undefined(isolate);
311 }
312 v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t, v8::Local<v8::Value>)
313 {
314 return v8::Undefined(isolate);
315 }
316 int push(v8::Isolate*, v8::Local<v8::Value>)
317 {
318 return -1;
319 }
320 v8::Local<v8::Value> pop(v8::Isolate* isolate)
321 {
322 return v8::Undefined(isolate);
323 }
324 v8::Local<v8::String> to_string(v8::Isolate* isolate) const
325 {
326 return compatibility_new<v8::String>(isolate, "");
327 }
328 v8::Local<v8::String> join(v8::Isolate* isolate, v8::Local<v8::Value>) const
329 {
330 return compatibility_new<v8::String>(isolate, "");
331 }
332 container_type get_container_type() const
333 {
334 throw std::runtime_error("get_container_type of container with unmanagable type");
335 return container_type_size;
336 }
337 void* get_container_native_handle()
338 {
339 return nullptr;
340 }
341 void const* get_container_native_handle() const
342 {
343 return nullptr;
344 }
345};
346
347} } }
348
349EAPI void eina_container_register(v8::Handle<v8::Object> exports, v8::Isolate* isolate);
350
351#endif
diff --git a/src/bindings/eina_js/eina_js_error.cc b/src/bindings/eina_js/eina_js_error.cc
new file mode 100644
index 0000000..89d69a1
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_error.cc
@@ -0,0 +1,24 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include <Eina_Js.hh>
6
7namespace efl { namespace eina {namespace js {
8
9EAPI
10js::compatibility_return_type convert_error_to_javascript_exception(v8::Isolate *isolate)
11{
12 Eina_Error err = eina_error_get();
13 if (!err)
14 return compatibility_return();
15
16 v8::Local<v8::Object> je = eina::js::compatibility_new<v8::Object>(isolate);
17 je->Set(compatibility_new<v8::String>(isolate, "code"),
18 compatibility_new<v8::String>(isolate, "Eina_Error"));
19 je->Set(compatibility_new<v8::String>(isolate, "value"),
20 compatibility_new<v8::String>(isolate, eina_error_msg_get(err)));
21 return compatibility_throw(isolate, je);
22}
23
24} } } // namespace efl { namespace js {
diff --git a/src/bindings/eina_js/eina_js_error.hh b/src/bindings/eina_js/eina_js_error.hh
new file mode 100644
index 0000000..49cef35
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_error.hh
@@ -0,0 +1,25 @@
1#ifndef EINA_JS_ERROR_HH
2#define EINA_JS_ERROR_HH
3
4#include <eina_js_compatibility.hh>
5
6namespace efl { namespace eina { namespace js {
7
8/**
9 * Converts the error value set through Eina's error tool to a JavaScript
10 * exception.
11 *
12 * The exception object will have a `code` string field with the `"Eina_Error"`
13 * string value and a `value` string field with the value extracted from
14 * `eina_error_msg_get`.
15 *
16 * It won't reset the error to NULL, so you can still access the error object,
17 * but if you keep calling this function without clearing the error, a new
18 * exception will be generated for each call after some error is reached. We,
19 * therefore, suggest you to call `eina_error_set(0)` afterwards.
20 */
21js::compatibility_return_type convert_error_to_javascript_exception(v8::Isolate *isolate);
22
23} } } // namespace efl::eina::js
24
25#endif /* EINA_JS_ERROR_HH */
diff --git a/src/bindings/eina_js/eina_js_get_value.hh b/src/bindings/eina_js/eina_js_get_value.hh
new file mode 100644
index 0000000..637b48a
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_get_value.hh
@@ -0,0 +1,449 @@
1#ifndef EFL_EINA_JS_GET_VALUE_HH
2#define EFL_EINA_JS_GET_VALUE_HH
3
4#include <eina_js_compatibility.hh>
5
6#include <type_traits>
7#include <cstdlib>
8#include <iostream>
9#include <typeinfo>
10
11namespace efl { namespace eina { namespace js {
12
13template <typename T>
14inline int get_value_from_javascript
15 (v8::Local<v8::Value> v
16 , v8::Isolate* isolate
17 , const char*
18 , value_tag<T>
19 , bool throw_js_exception = true
20 , typename std::enable_if<(std::is_integral<T>::value && !std::is_same<T, Eina_Bool>::value)>::type* = 0)
21{
22 if(v->IsInt32())
23 return v->Int32Value();
24 else if(v->IsUint32())
25 return v->Uint32Value();
26 else
27 {
28 if (throw_js_exception)
29 eina::js::compatibility_throw
30 (isolate, v8::Exception::TypeError
31 (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Integral type")));
32
33 throw std::logic_error("");
34 }
35 return 0;
36}
37
38inline char* get_value_from_javascript
39 (v8::Local<v8::Value> v
40 , v8::Isolate* isolate
41 , const char*
42 , value_tag<char*>
43 , bool throw_js_exception = true)
44{
45 if(v->IsNull())
46 return nullptr;
47 else if(v->IsString())
48 {
49 v8::String::Utf8Value str(v->ToString());
50 char* string = strdup(*str); // TODO: leaks
51 return string;
52 }
53 else
54 {
55 if (throw_js_exception)
56 eina::js::compatibility_throw
57 (isolate, v8::Exception::TypeError
58 (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected String type")));
59
60 throw std::logic_error("");
61 }
62 return 0;
63}
64
65inline const char* get_value_from_javascript
66 (v8::Local<v8::Value> v
67 , v8::Isolate* isolate
68 , const char* class_name
69 , value_tag<const char*>
70 , bool throw_js_exception = true)
71{
72 return get_value_from_javascript(v, isolate, class_name, value_tag<char*>(), throw_js_exception);
73}
74
75inline Eo* get_value_from_javascript
76 (v8::Local<v8::Value> v
77 , v8::Isolate* isolate
78 , const char*
79 , value_tag<Eo*>
80 , bool throw_js_exception = true)
81{
82 if(v->IsNull())
83 return nullptr;
84 else if(v->IsObject())
85 {
86 v8::Local<v8::Object> object = v->ToObject();
87 if(object->InternalFieldCount() == 1)
88 {
89 v8::Local<v8::Value> r = object->GetInternalField(0);
90 if(v8::External* external = v8::External::Cast(*r))
91 {
92 return static_cast<Eo*>(external->Value());
93 }
94 }
95 }
96 if (throw_js_exception)
97 eina::js::compatibility_throw
98 (isolate, v8::Exception::TypeError
99 (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Eolian object type")));
100 throw std::logic_error("");
101 return nullptr;
102}
103
104inline Eo* get_value_from_javascript
105 (v8::Local<v8::Value> v
106 , v8::Isolate* isolate
107 , const char* class_name
108 , value_tag<Eo* const>
109 , bool throw_js_exception = true)
110{
111 return get_value_from_javascript(v, isolate, class_name, value_tag<Eo*>(), throw_js_exception);
112}
113
114template <typename T>
115inline T get_value_from_javascript
116 (v8::Local<v8::Value> v
117 , v8::Isolate* isolate
118 , const char*
119 , value_tag<struct_ptr_tag<T>>
120 , bool throw_js_exception = true)
121{
122 if(v->IsNull())
123 return nullptr;
124 else if(v->IsObject())
125 {
126 v8::Local<v8::Object> object = v->ToObject();
127 if(object->InternalFieldCount() == 1)
128 {
129 return compatibility_get_pointer_internal_field<T>(object, 0);
130 }
131 }
132 if (throw_js_exception)
133 eina::js::compatibility_throw
134 (isolate, v8::Exception::TypeError
135 (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Eolian struct type")));
136 throw std::logic_error("");
137 return nullptr;
138}
139
140template <typename T>
141inline T get_value_from_javascript
142 (v8::Local<v8::Value> v
143 , v8::Isolate* isolate
144 , const char* class_name
145 , value_tag<struct_tag<T>>
146 , bool throw_js_exception = true)
147{
148 T* ptr = get_value_from_javascript(v, isolate, class_name, value_tag<struct_ptr_tag<T*>>(), throw_js_exception);
149 if (ptr)
150 return *ptr;
151
152 if (throw_js_exception)
153 eina::js::compatibility_throw
154 (isolate, v8::Exception::TypeError
155 (eina::js::compatibility_new<v8::String>(isolate, "Conversion of null pointer to by-value struct.")));
156 throw std::logic_error("");
157 return T{};
158}
159
160template <typename T>
161inline T get_value_from_javascript
162 (v8::Local<v8::Value> v
163 , v8::Isolate* isolate
164 , const char*
165 , value_tag<T>
166 , bool throw_js_exception = true
167 , typename std::enable_if<std::is_enum<T>::value>::type* = 0)
168{
169 if(v->IsInt32())
170 return static_cast<T>(v->Int32Value());
171 else if(v->IsUint32())
172 return static_cast<T>(v->Uint32Value());
173 else
174 {
175 if (throw_js_exception)
176 eina::js::compatibility_throw
177 (isolate, v8::Exception::TypeError
178 (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected enumeration type")));
179
180 throw std::logic_error("");
181 }
182 return T();
183}
184
185inline Eina_Bool get_value_from_javascript
186 (v8::Local<v8::Value> v
187 , v8::Isolate* isolate
188 , const char*
189 , value_tag<Eina_Bool>
190 , bool throw_js_exception = true)
191{
192 if(v->IsBoolean() || v->IsBooleanObject())
193 {
194 return v->BooleanValue() ? EINA_TRUE : EINA_FALSE;
195 }
196 else
197 {
198 if (throw_js_exception)
199 eina::js::compatibility_throw
200 (isolate, v8::Exception::TypeError
201 (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Boolean type")));
202
203 throw std::logic_error("");
204 }
205 return 0;
206}
207
208template <typename T>
209inline double get_value_from_javascript
210 (v8::Local<v8::Value> v
211 , v8::Isolate* isolate
212 , const char*
213 , value_tag<T>
214 , bool throw_js_exception = true
215 , typename std::enable_if<std::is_floating_point<T>::value>::type* = 0)
216{
217 if(v->IsNumber())
218 {
219 return v->NumberValue();
220 }
221 else
222 {
223 if (throw_js_exception)
224 eina::js::compatibility_throw
225 (isolate, v8::Exception::TypeError
226 (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected floating point type")));
227 throw std::logic_error("");
228 }
229 return 0.0;
230}
231
232template <typename T>
233inline T get_value_from_javascript
234 (v8::Local<v8::Value>, v8::Isolate* isolate, const char*, value_tag<T>
235 , bool throw_js_exception = true
236 , typename std::enable_if<
237 !std::is_floating_point<T>::value &&
238 !std::is_integral<T>::value &&
239 !std::is_enum<T>::value &&
240 !js::is_struct_tag<T>::value &&
241 !js::is_struct_ptr_tag<T>::value &&
242 !js::is_complex_tag<T>::value &&
243 !std::is_same<T, Eina_Accessor*>::value &&
244 !std::is_same<T, Eina_Array*>::value &&
245 !std::is_same<T, Eina_Iterator*>::value &&
246 !std::is_same<T, Eina_Hash*>::value &&
247 !std::is_same<T, Eina_List*>::value &&
248 !std::is_same<T, const Eina_Accessor*>::value &&
249 !std::is_same<T, const Eina_Array*>::value &&
250 !std::is_same<T, const Eina_Iterator*>::value &&
251 !std::is_same<T, const Eina_Hash*>::value &&
252 !std::is_same<T, const Eina_List*>::value
253 >::type* = 0)
254{
255 if (throw_js_exception)
256 eina::js::compatibility_throw
257 (isolate, v8::Exception::TypeError
258 (eina::js::compatibility_new<v8::String>(isolate, "Not implemented yet")));
259 throw std::logic_error("");
260}
261
262// TODO: Fix for const types
263template <typename T, typename K>
264inline Eina_Accessor* get_value_from_javascript(
265 v8::Local<v8::Value> v,
266 v8::Isolate* isolate,
267 const char*,
268 value_tag<complex_tag<Eina_Accessor *, T, K>>,
269 bool throw_js_exception = true)
270{
271 if(v->IsNull())
272 return nullptr;
273 else if(v->IsObject())
274 {
275 using wrapped_type = typename container_wrapper<T>::type;
276 v8::Local<v8::Object> object = v->ToObject();
277 auto& acc = import_accessor<wrapped_type>(object);
278 return acc.native_handle();
279 }
280 if (throw_js_exception)
281 eina::js::compatibility_throw
282 (isolate, v8::Exception::TypeError
283 (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Eolian accessor type")));
284 throw std::logic_error("");
285}
286
287template <typename...I>
288inline const Eina_Accessor* get_value_from_javascript(
289 v8::Local<v8::Value> v,
290 v8::Isolate* isolate,
291 const char* class_name,
292 value_tag<complex_tag<const Eina_Accessor *, I...>>,
293 bool throw_js_exception = true)
294{
295 return get_value_from_javascript(v, isolate, class_name, value_tag<complex_tag<Eina_Accessor *, I...>>{}, throw_js_exception);
296}
297
298template <typename...I>
299inline Eina_Array* get_value_from_javascript(
300 v8::Local<v8::Value> v,
301 v8::Isolate* isolate,
302 const char*,
303 value_tag<complex_tag<Eina_Array *, I...>>,
304 bool throw_js_exception = true)
305{
306 if(v->IsNull())
307 return nullptr;
308 else if(v->IsObject())
309 {
310 v8::Local<v8::Object> object = v->ToObject();
311 if(object->InternalFieldCount() == 1)
312 {
313 eina_container_base* cbase = compatibility_get_pointer_internal_field<eina_container_base*>(object, 0);
314 return static_cast<Eina_Array*>(cbase->get_container_native_handle());
315 }
316 }
317 if (throw_js_exception)
318 eina::js::compatibility_throw
319 (isolate, v8::Exception::TypeError
320 (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Eolian list type")));
321 throw std::logic_error("");
322 return nullptr;
323}
324
325template <typename...I>
326inline const Eina_Array* get_value_from_javascript(
327 v8::Local<v8::Value> v,
328 v8::Isolate* isolate,
329 const char* class_name,
330 value_tag<complex_tag<const Eina_Array *, I...>>,
331 bool throw_js_exception = true)
332{
333 return get_value_from_javascript(v, isolate, class_name, value_tag<complex_tag<Eina_Array *, I...>>{}, throw_js_exception);
334}
335
336template <typename...I>
337inline Eina_Iterator* get_value_from_javascript(
338 v8::Local<v8::Value>,
339 v8::Isolate* isolate,
340 const char*,
341 value_tag<complex_tag<Eina_Iterator *, I...>> tag,
342 bool throw_js_exception = true)
343{
344 if (throw_js_exception)
345 eina::js::compatibility_throw
346 (isolate, v8::Exception::TypeError
347 (eina::js::compatibility_new<v8::String>(isolate, "Not implemented yet")));
348 throw std::logic_error("");
349}
350
351template <typename...I>
352inline const Eina_Iterator* get_value_from_javascript(
353 v8::Local<v8::Value> v,
354 v8::Isolate* isolate,
355 const char* class_name,
356 value_tag<complex_tag<const Eina_Iterator *, I...>>,
357 bool throw_js_exception = true)
358{
359 return get_value_from_javascript(v, isolate, class_name, value_tag<complex_tag<Eina_Iterator *, I...>>{}, throw_js_exception);
360}
361
362template <typename T, typename...U>
363inline Eina_Hash* get_value_from_javascript(
364 v8::Local<v8::Value>,
365 v8::Isolate* isolate,
366 const char*,
367 value_tag<complex_tag<Eina_Hash *, T, U...>> tag,
368 bool throw_js_exception = true)
369{
370 if (throw_js_exception)
371 eina::js::compatibility_throw
372 (isolate, v8::Exception::TypeError
373 (eina::js::compatibility_new<v8::String>(isolate, "Not implemented yet")));
374 throw std::logic_error("");
375}
376
377template <typename T, typename...U>
378inline const Eina_Hash* get_value_from_javascript(
379 v8::Local<v8::Value> v,
380 v8::Isolate* isolate,
381 const char* class_name,
382 value_tag<complex_tag<const Eina_Hash *, T, U...>>,
383 bool throw_js_exception = true)
384{
385 return get_value_from_javascript(v, isolate, class_name, value_tag<complex_tag<Eina_Hash *, T, U...>>{}, throw_js_exception);
386}
387
388template <typename...I>
389inline Eina_List* get_value_from_javascript(
390 v8::Local<v8::Value> v,
391 v8::Isolate* isolate,
392 const char*,
393 value_tag<complex_tag<Eina_List *, I...>> /*tag*/,
394 bool throw_js_exception = true)
395{
396 if(v->IsNull())
397 return nullptr;
398 else if(v->IsObject())
399 {
400 v8::Local<v8::Object> object = v->ToObject();
401 if(object->InternalFieldCount() == 1)
402 {
403 eina_container_base* cbase = compatibility_get_pointer_internal_field<eina_container_base*>(object, 0);
404 return static_cast<Eina_List*>(cbase->get_container_native_handle());
405 }
406 }
407 if (throw_js_exception)
408 eina::js::compatibility_throw
409 (isolate, v8::Exception::TypeError
410 (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Eolian list type")));
411 throw std::logic_error("");
412 return nullptr;
413}
414
415template <typename...I>
416inline const Eina_List* get_value_from_javascript(
417 v8::Local<v8::Value> v,
418 v8::Isolate* isolate,
419 const char* class_name,
420 value_tag<complex_tag<const Eina_List *, I...>>,
421 bool throw_js_exception = true)
422{
423 return get_value_from_javascript(v, isolate, class_name, value_tag<complex_tag<Eina_List *, I...>>{}, throw_js_exception);
424}
425
426inline const void* get_value_from_javascript
427 (v8::Local<v8::Value>,
428 v8::Isolate*,
429 const char*,
430 value_tag<const void *>)
431{
432 return nullptr;
433}
434
435
436typedef void (*Evas_Smart_Cb)(void*, _Eo_Opaque*, void*);
437
438inline Evas_Smart_Cb get_value_from_javascript (
439 v8::Local<v8::Value>,
440 v8::Isolate*,
441 const char*,
442 value_tag<Evas_Smart_Cb>)
443{
444 return nullptr;
445}
446
447} } }
448
449#endif
diff --git a/src/bindings/eina_js/eina_js_get_value_from_c.hh b/src/bindings/eina_js/eina_js_get_value_from_c.hh
new file mode 100644
index 0000000..655b1b1
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_get_value_from_c.hh
@@ -0,0 +1,261 @@
1#ifndef EFL_EINA_JS_GET_VALUE_FROM_C_HH
2#define EFL_EINA_JS_GET_VALUE_FROM_C_HH
3
4#include <eina_js_compatibility.hh>
5
6#include <type_traits>
7#include <cstdlib>
8#include <typeinfo>
9#include <memory>
10
11namespace efl { namespace eina { namespace js {
12
13template <typename T> struct print_tag {};
14
15template <typename T>
16inline v8::Local<v8::Value>
17get_value_from_c(T v, v8::Isolate* isolate, const char*
18 , typename std::enable_if<std::is_integral<typename std::remove_reference<T>::type>::value && !std::is_same<T, Eina_Bool>::value>::type* = 0)
19{
20 return eina::js::compatibility_new<v8::Integer>(isolate, v);
21}
22
23template <typename T>
24inline v8::Local<v8::Value>
25get_value_from_c(T v, v8::Isolate* isolate, const char*
26 , typename std::enable_if<std::is_enum<typename std::remove_reference<T>::type>::value>::type* = 0)
27{
28 return eina::js::compatibility_new<v8::Integer>(isolate, v);
29}
30
31template <typename T>
32inline v8::Local<v8::Value>
33get_value_from_c(T v, v8::Isolate* isolate, const char*
34 , typename std::enable_if<std::is_same<typename std::remove_reference<T>::type, Eina_Bool>::value>::type* = 0)
35{
36 return eina::js::compatibility_new<v8::Boolean>(isolate, v);
37}
38
39template <typename T>
40inline v8::Local<T>
41get_value_from_c(v8::Local<T> v, v8::Isolate*, const char*)
42{
43 return v;
44}
45
46template <typename T>
47inline v8::Local<v8::Value>
48get_value_from_c(T v, v8::Isolate* isolate, const char*
49 , typename std::enable_if<std::is_floating_point<typename std::remove_reference<T>::type>::value>::type* = 0)
50{
51 return eina::js::compatibility_new<v8::Number>(isolate, v);
52}
53
54inline v8::Local<v8::Value>
55get_value_from_c(const char* v, v8::Isolate* isolate, const char*)
56{
57 if (!v)
58 return v8::Null(isolate);
59
60 return eina::js::compatibility_new<v8::String>(isolate, v);
61}
62
63inline v8::Local<v8::Value>
64get_value_from_c(char* v, v8::Isolate* isolate, const char* class_name)
65{
66 return js::get_value_from_c(const_cast<const char*>(v), isolate, class_name);
67}
68
69inline v8::Local<v8::Value>
70get_value_from_c(void*, v8::Isolate*, const char*)
71{
72 // TODO: create Extern?
73 std::cerr << "aborting because we don't know the type void*" << std::endl;
74 std::abort();
75}
76
77inline v8::Local<v8::Value>
78get_value_from_c(const void*, v8::Isolate*, const char*)
79{
80 // TODO: create Extern?
81 std::cerr << "aborting because we don't know the type void*" << std::endl;
82 std::abort();
83}
84
85// For function pointer types
86template <typename T>
87inline v8::Local<v8::Value>
88get_value_from_c(T, v8::Isolate*, const char*
89 , typename std::enable_if
90 <std::is_pointer<typename std::remove_reference<T>::type>::value
91 && std::is_function<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value
92 >::type* = 0)
93{
94 // TODO: create Extern?
95 std::cerr << "aborting because we don't know the type " << typeid(print_tag<T>).name() << std::endl;
96 std::abort();
97}
98
99// For all non-pointer types that are not handled
100template <typename T>
101inline v8::Local<v8::Value>
102get_value_from_c(T, v8::Isolate*, const char*
103 , typename std::enable_if
104 <!std::is_pointer<typename std::remove_reference<T>::type>::value
105 && !std::is_integral<typename std::remove_reference<T>::type>::value
106 && !std::is_floating_point<typename std::remove_reference<T>::type>::value
107 && !std::is_enum<typename std::remove_reference<T>::type>::value
108 && !std::is_same<typename std::remove_reference<T>::type, Eina_Bool>::value
109 && !js::is_struct_tag<typename std::remove_reference<T>::type>::value
110 && !js::is_struct_ptr_tag<typename std::remove_reference<T>::type>::value
111 && !js::is_complex_tag<typename std::remove_reference<T>::type>::value
112 >::type* = 0)
113{
114 std::cerr << "aborting because we don't know the type " << typeid(print_tag<T>).name() << std::endl;
115 std::abort();
116}
117
118// For all non-handled pointer types (which are not function pointers):
119// - we try to dereference it in the SFINAE
120// - if it matches we call get_value_from_c for the dereferenced type
121// - if it fails (probably because it is opaque) the void* or const void*
122// overload will take place (implicit conversion)
123template <typename T>
124inline auto
125get_value_from_c(T object, v8::Isolate* isolate, const char* class_name
126 , typename std::enable_if<
127 (std::is_pointer<typename std::remove_reference<T>::type>::value
128 && !std::is_function<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value
129 )
130 && !(std::is_same<typename std::remove_reference<T>::type, char*>::value ||
131 std::is_same<typename std::remove_reference<T>::type, const char*>::value ||
132 std::is_same<typename std::remove_reference<T>::type, void*>::value ||
133 std::is_same<typename std::remove_reference<T>::type, const void*>::value ||
134 std::is_same<typename std::remove_reference<T>::type, Eo*>::value ||
135 std::is_same<typename std::remove_reference<T>::type, const Eo*>::value
136 )>::type* = 0) -> decltype(get_value_from_c(*object, isolate, class_name))
137{
138 std::cerr << "dereferencing " << typeid(print_tag<T>).name() << std::endl;
139 return get_value_from_c(*object, isolate, class_name);
140}
141
142inline v8::Local<v8::Value>
143get_value_from_c(Eo* v, v8::Isolate* isolate, const char* class_name)
144{
145 auto ctor = ::efl::eina::js::get_class_constructor(class_name);
146 return new_v8_external_instance(ctor, v, isolate);
147}
148
149inline v8::Local<v8::Value>
150get_value_from_c(const Eo* v, v8::Isolate* isolate, const char* class_name)
151{
152 // TODO: implement const objects?
153 auto ctor = ::efl::eina::js::get_class_constructor(class_name);
154 return new_v8_external_instance(ctor, const_cast<Eo*>(v), isolate);
155}
156
157template <typename T>
158inline v8::Local<v8::Value>
159get_value_from_c(struct_ptr_tag<T> v, v8::Isolate* isolate, const char* class_name)
160{
161 // TODO: implement const structs?
162 auto ctor = ::efl::eina::js::get_class_constructor(class_name);
163 return new_v8_external_instance(ctor, const_cast<typename std::remove_const<T>::type>(v.value), isolate);
164}
165
166template <typename T>
167inline v8::Local<v8::Value>
168get_value_from_c(struct_tag<T> v, v8::Isolate* isolate, const char* class_name)
169{
170 return get_value_from_c(struct_ptr_tag<T*>{new T(v.value)}, isolate, class_name);
171}
172
173template <typename T, typename K>
174inline v8::Local<v8::Value>
175get_value_from_c(efl::eina::js::complex_tag<Eina_Accessor *, T, K> v, v8::Isolate* isolate, const char*)
176{
177 using wrapped_type = typename container_wrapper<T>::type;
178 auto a = new ::efl::eina::accessor<wrapped_type>{v.value};
179 return export_accessor<T>(*a , isolate, K::class_name());
180}
181
182template <typename T, typename K>
183inline v8::Local<v8::Value>
184get_value_from_c(efl::eina::js::complex_tag<const Eina_Accessor *, T, K> v, v8::Isolate* isolate, const char* class_name)
185{
186 // TODO implement const accessor?
187 return get_value_from_c(efl::eina::js::complex_tag<Eina_Accessor*, T, K>{const_cast<Eina_Accessor*>(v.value)}, isolate, class_name);
188}
189
190template <typename T, typename K>
191inline v8::Local<v8::Value>
192get_value_from_c(efl::eina::js::complex_tag<Eina_Array *, T, K> v, v8::Isolate* isolate, const char*)
193{
194 // TODO: use unique_ptr for eina_array to avoid leak ?
195 auto o = new ::efl::eina::js::range_eina_array<T, K>(v.value);
196 auto ctor = get_array_instance_template();
197 return new_v8_external_instance(ctor, o, isolate);
198}
199
200template <typename T, typename K>
201inline v8::Local<v8::Value>
202get_value_from_c(efl::eina::js::complex_tag<const Eina_Array *, T, K> v, v8::Isolate* isolate, const char* class_name)
203{
204 // TODO: implement const array?
205 return get_value_from_c(efl::eina::js::complex_tag<Eina_Array *, T, K>{const_cast<Eina_Array*>(v.value)}, isolate, class_name);
206}
207
208template <typename T, typename K>
209inline v8::Local<v8::Value>
210get_value_from_c(efl::eina::js::complex_tag<Eina_Iterator *, T, K>, v8::Isolate*, const char*)
211{
212 std::cerr << "get_value_from_c for Eina_Iterator not implemented. Aborting..." << std::endl;
213 std::abort();
214}
215
216template <typename T, typename K>
217inline v8::Local<v8::Value>
218get_value_from_c(efl::eina::js::complex_tag<const Eina_Iterator *, T, K>, v8::Isolate*, const char*)
219{
220 std::cerr << "get_value_from_c for Eina_Iterator not implemented. Aborting..." << std::endl;
221 std::abort();
222}
223
224template <typename T, typename U, typename K>
225inline v8::Local<v8::Value>
226get_value_from_c(efl::eina::js::complex_tag<Eina_Hash *, T, U, K>, v8::Isolate*, const char*)
227{
228 std::cerr << "get_value_from_c for Eina_Hash not implemented. Aborting..." << std::endl;
229 std::abort();
230}
231
232template <typename T, typename U, typename K>
233inline v8::Local<v8::Value>
234get_value_from_c(efl::eina::js::complex_tag<const Eina_Hash *, T, U, K>, v8::Isolate*, const char*)
235{
236 std::cerr << "get_value_from_c for Eina_Hash not implemented. Aborting..." << std::endl;
237 std::abort();
238}
239
240template <typename T, typename K>
241inline v8::Local<v8::Value>
242get_value_from_c(efl::eina::js::complex_tag<Eina_List *, T, K> v, v8::Isolate* isolate, const char*)
243{
244 // TODO: ensure eina_list ownership ???
245 auto o = new ::efl::eina::js::range_eina_list<T, K>(v.value);
246 auto ctor = get_list_instance_template();
247 return new_v8_external_instance(ctor, o, isolate);
248}
249
250template <typename T, typename K>
251inline v8::Local<v8::Value>
252get_value_from_c(efl::eina::js::complex_tag<const Eina_List *, T, K> v, v8::Isolate* isolate, const char* class_name)
253{
254 // TODO: implement const list?
255 return get_value_from_c(efl::eina::js::complex_tag<Eina_List *, T, K>{const_cast<Eina_List*>(v.value)}, isolate, class_name);
256}
257
258
259} } }
260
261#endif
diff --git a/src/bindings/eina_js/eina_js_iterator.cc b/src/bindings/eina_js/eina_js_iterator.cc
new file mode 100644
index 0000000..d2480b8
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_iterator.cc
@@ -0,0 +1,32 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include <Eina.hh>
6#include <Eina_Js.hh>
7
8namespace efl { namespace eina { namespace js {
9
10EAPI
11void register_destroy_iterator(v8::Isolate *isolate,
12 v8::Handle<v8::Object> global,
13 v8::Handle<v8::String> name)
14{
15 typedef void (*deleter_t)(void*);
16
17 auto f = [](compatibility_callback_info_type info) -> compatibility_return_type
18 {
19 if (info.Length() != 1 || !info[0]->IsObject())
20 return compatibility_return();
21
22 v8::Handle<v8::Object> o = info[0]->ToObject();
23
24 deleter_t deleter = compatibility_get_pointer_internal_field<deleter_t>(o, 1);
25 deleter(compatibility_get_pointer_internal_field<>(o, 0));
26 return compatibility_return();
27 };
28
29 global->Set(name, compatibility_new<v8::FunctionTemplate>(isolate, f)->GetFunction());
30}
31
32} } } // namespace efl { namespace js {
diff --git a/src/bindings/eina_js/eina_js_iterator.hh b/src/bindings/eina_js/eina_js_iterator.hh
new file mode 100644
index 0000000..ed0066b
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_iterator.hh
@@ -0,0 +1,81 @@
1#ifndef EINA_JS_ITERATOR_HH
2#define EINA_JS_ITERATOR_HH
3
4#include <type_traits>
5
6#include <eina_js_value.hh>
7
8namespace efl { namespace eina { namespace js {
9
10/* Exports the \p iterator to be manipulated by the JS code. The iterator should
11 remain alive as long as there is JS code referencing it. The JS code is able
12 to destroy the iterator by itself if you register the appropriate function
13 through `register_destroy_iterator`.
14
15 The exported JS object models part the [iterator concept from ECMAScript
16 6](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/The_Iterator_protocol).
17
18 The iterator will have the `next` function, but the returned object won't
19 have a `done` attribute, because the eina_iterator itself doesn't expose this
20 information.*/
21template<class T>
22v8::Local<v8::Object> export_iterator(::efl::eina::iterator<T> *i,
23 v8::Isolate *isolate)
24{
25 typedef ::efl::eina::iterator<T> value_type;
26 typedef value_type *ptr_type;
27 typedef void (*deleter_t)(void*);
28
29 auto obj_tpl = compatibility_new<v8::ObjectTemplate>(isolate);
30 obj_tpl->SetInternalFieldCount(2);
31
32 auto ret = obj_tpl->NewInstance();
33
34 auto next = [](js::compatibility_callback_info_type info) -> compatibility_return_type
35 {
36 if (info.Length() != 0)
37 return compatibility_return();
38
39 void *ptr = compatibility_get_pointer_internal_field(info.This(), 0);
40 auto &value = *static_cast<ptr_type>(ptr);
41 v8::Local<v8::Object> o = compatibility_new<v8::Object>(info.GetIsolate());
42 o->Set(compatibility_new<v8::String>(info.GetIsolate(), "value"),
43 value_cast<v8::Local<v8::Value>>(*value, info.GetIsolate()));
44 ++value;
45 return compatibility_return(o, info);
46 };
47
48 ret->Set(compatibility_new<v8::String>(isolate, "next"),
49 compatibility_new<v8::FunctionTemplate>(isolate, next)->GetFunction());
50
51 {
52 deleter_t deleter = [](void *i) {
53 delete static_cast<ptr_type>(i);
54 };
55 compatibility_set_pointer_internal_field(ret, 0, i);
56 compatibility_set_pointer_internal_field
57 (ret, 1, reinterpret_cast<void*>(deleter));
58 }
59
60 return ret;
61}
62
63/* Extracts and returns a copy from the internal iterator object from the JS
64 object. */
65template<class T>
66::efl::eina::iterator<T> *import_iterator(v8::Handle<v8::Object> o)
67 ;
68// {
69// typedef ::efl::eina::iterator<T> value_type;
70// typedef value_type *ptr_type;
71
72// return reinterpret_cast<ptr_type>(o->GetAlignedPointerFromInternalField(0));
73// }
74
75void register_destroy_iterator(v8::Isolate *isolate,
76 v8::Handle<v8::Object> global,
77 v8::Handle<v8::String> name);
78
79} } } // namespace efl::js
80
81#endif /* EINA_JS_ITERATOR_HH */
diff --git a/src/bindings/eina_js/eina_js_list.hh b/src/bindings/eina_js/eina_js_list.hh
new file mode 100644
index 0000000..6ab0521
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_list.hh
@@ -0,0 +1,132 @@
1#ifndef EINA_JS_LIST_HH
2#define EINA_JS_LIST_HH
3
4#include <iostream>
5
6#include <eina_js_container.hh>
7#include <eina_js_compatibility.hh>
8
9#include <iterator>
10
11namespace efl { namespace eina { namespace js {
12
13template <typename T, typename K, typename W>
14struct eina_list : eina_container_common<efl::eina::list
15 <W
16 , typename std::conditional
17 <std::is_base_of<efl::eo::concrete, W>::value
18 , efl::eina::eo_clone_allocator
19 , efl::eina::malloc_clone_allocator
20 >::type>, T, K>
21{
22 typedef eina_container_common<efl::eina::list<W
23 , typename std::conditional
24 <std::is_base_of<efl::eo::concrete, W>::value
25 , efl::eina::eo_clone_allocator
26 , efl::eina::malloc_clone_allocator
27 >::type>, T, K> base_type;
28 using base_type::base_type;
29 typedef typename base_type::container_type container_type;
30
31 eina_container_base* concat(eina_container_base const& other) const
32 {
33 return detail::concat(*this, other);
34 }
35 eina_container_base* slice(std::int64_t i, std::int64_t j) const
36 {
37 return detail::slice(*this, i, j);
38 }
39 v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t index, v8::Local<v8::Value> v)
40 {
41 return detail::set<T,W>(isolate, *this, index, v);
42 }
43 int push(v8::Isolate* isolate, v8::Local<v8::Value> v)
44 {
45 return detail::push<T,W>(isolate, *this, v);
46 }
47 v8::Local<v8::Value> pop(v8::Isolate* isolate)
48 {
49 return detail::pop<T,W,K>(isolate, *this);
50 }
51 js::container_type get_container_type() const { return list_container_type; }
52};
53
54template <typename T, typename K, typename W>
55struct range_eina_list : eina_container_common<typename efl::eina::range_list<W>, T, K>
56{
57 typedef eina_container_common<efl::eina::range_list<W>, T, K> base_type;
58 using base_type::base_type;
59 typedef typename base_type::container_type container_type;
60 typedef typename std::conditional
61 <std::is_base_of<efl::eo::concrete, W>::value
62 , efl::eina::eo_clone_allocator
63 , efl::eina::malloc_clone_allocator
64 >::type clone_allocator_type;
65
66 eina_container_base* concat(eina_container_base const& other) const
67 {
68 range_eina_list<T, K, W>const& rhs = static_cast<range_eina_list<T, K, W>const&>(other);
69 efl::eina::list<W, clone_allocator_type>
70 list(this->_container.begin(), this->_container.end());
71 list.insert(list.end(), rhs._container.begin(), rhs._container.end());
72 return new eina::js::eina_list<T, K, W>(list.release_native_handle());
73 }
74 eina_container_base* slice(std::int64_t i, std::int64_t j) const
75 {
76 efl::eina::list<W, clone_allocator_type>
77 list(std::next(this->_container.begin(), i), std::next(this->_container.begin(), j));
78 return new eina::js::eina_list<T, K, W>(list.release_native_handle());
79 }
80 v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t, v8::Local<v8::Value>)
81 {
82 return v8::Undefined(isolate);
83 }
84 int push(v8::Isolate*, v8::Local<v8::Value>)
85 {
86 return this->size();
87 }
88 v8::Local<v8::Value> pop(v8::Isolate* isolate)
89 {
90 return v8::Undefined(isolate);
91 }
92 js::container_type get_container_type() const { return list_container_type; }
93};
94
95// Problematic types.
96template <>
97struct eina_list<_Elm_Calendar_Mark*, js::nonclass_cls_name_getter, _Elm_Calendar_Mark>
98 : empty_container_base
99{ eina_list(Eina_List const*){} };
100template <>
101struct eina_list<Elm_Gen_Item*, js::nonclass_cls_name_getter, Elm_Gen_Item>
102 : empty_container_base
103{ eina_list(Eina_List const*){} };
104template <>
105struct eina_list<_Evas_Textblock_Rectangle*, js::nonclass_cls_name_getter, _Evas_Textblock_Rectangle>
106 : empty_container_base
107{ eina_list(Eina_List const*){} };
108template <>
109struct eina_list<_Elm_Map_Overlay*, js::nonclass_cls_name_getter, _Elm_Map_Overlay>
110 : empty_container_base
111{ eina_list(Eina_List const*){} };
112
113template <>
114struct range_eina_list<_Elm_Calendar_Mark*, js::nonclass_cls_name_getter, _Elm_Calendar_Mark>
115 : empty_container_base
116{ range_eina_list(Eina_List const*){} };
117template <>
118struct range_eina_list<Elm_Gen_Item*, js::nonclass_cls_name_getter, Elm_Gen_Item>
119 : empty_container_base
120{ range_eina_list(Eina_List const*){} };
121template <>
122struct range_eina_list<_Evas_Textblock_Rectangle*, js::nonclass_cls_name_getter, _Evas_Textblock_Rectangle>
123 : empty_container_base
124{ range_eina_list(Eina_List const*){} };
125template <>
126struct range_eina_list<_Elm_Map_Overlay*, js::nonclass_cls_name_getter, _Elm_Map_Overlay>
127 : empty_container_base
128{ range_eina_list(Eina_List const*){} };
129
130} } }
131
132#endif
diff --git a/src/bindings/eina_js/eina_js_log.cc b/src/bindings/eina_js/eina_js_log.cc
new file mode 100644
index 0000000..415a827
--- /dev/null
+++ b/src/bindings/eina_js/eina_js_log.cc
@@ -0,0 +1,742 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include <string>
6#include <map>
7#include <Eina_Js.hh>
8
9namespace efl { namespace eina { namespace js {
10
11v8::Local<v8::String> to_v8_string(v8::Isolate *isolate, const char *fmt,
12 va_list args)
13{
14 using v8::String;
15#if 0
16 /* TODO: unfortunately, the elegant and exception-safe version isn't
17 compiling (yet!) */
18 efl::eina::stringshare s(eina_stringshare_vprintf(fmt, args),
19 efl::eina::steal_stringshare_ref);
20 return compatibility_new<String>(isolate, s.data(), String::kNormalString,
21 s.size());
22#else
23 auto s = eina_stringshare_vprintf(fmt, args);
24 auto ret = compatibility_new<String>(isolate, s);
25 eina_stringshare_del(s);
26 return ret;
27#endif
28}
29
30static global_ref<v8::Value> js_eina_log_print_cb_data;
31static std::map<int, std::string> js_eina_log_color_map;
32
33static void js_eina_log_print_cb(const Eina_Log_Domain *d, Eina_Log_Level level,
34 const char *file, const char *fnc, int line,
35 const char *fmt, void */*data*/, va_list args)
36{
37 using v8::String;
38 using v8::Integer;
39 using v8::Isolate;
40
41 Isolate *const isolate = Isolate::GetCurrent();
42 constexpr unsigned argc = 7;
43
44 v8::Handle<v8::Value> argv[argc] = {
45 compatibility_new<String>(isolate, d->name ? d->name : ""),
46 compatibility_new<String>(isolate, d->color ? d->color : ""),
47 compatibility_new<Integer>(isolate, static_cast<int>(level)),
48 compatibility_new<String>(isolate, file),
49 compatibility_new<String>(isolate, fnc),
50 compatibility_new<Integer>(isolate, line),
51 to_v8_string(isolate, fmt, args)
52 };
53
54 auto o = js_eina_log_print_cb_data.handle();
55 v8::Function::Cast(*o)->Call(o->ToObject(), argc, argv);
56}
57
58static bool valid_level_conversion(int src, Eina_Log_Level &dst)
59{
60 if (src != EINA_LOG_LEVEL_CRITICAL && src != EINA_LOG_LEVEL_ERR
61 && src != EINA_LOG_LEVEL_WARN && src != EINA_LOG_LEVEL_INFO
62 && src != EINA_LOG_LEVEL_DBG)
63 return false;
64
65 dst = static_cast<Eina_Log_Level>(src);
66 return true;
67}
68
69EAPI
70void register_log_print(v8::Isolate *isolate, v8::Handle<v8::Object> global,
71 v8::Handle<v8::String> name)
72{
73 using v8::Value;
74 using v8::String;
75 using v8::StackTrace;
76 using v8::FunctionTemplate;
77
78 auto print = [](compatibility_callback_info_type args)
79 -> compatibility_return_type {
80 if (args.Length() != 3 || !args[0]->IsNumber() || !args[1]->IsNumber()
81 || !args[2]->IsString())
82 return compatibility_return();
83
84 Eina_Log_Level level;
85 if (!valid_level_conversion(args[1]->NumberValue(), level))
86 return compatibility_return();
87
88 auto frame = compatibility_current_stack_trace<>(args.GetIsolate(), 1,
89 StackTrace::kDetailed)->GetFrame(0);
90
91 eina_log_print(args[0]->NumberValue(), level,
92 *String::Utf8Value(frame->GetScriptNameOrSourceURL()),
93 *String::Utf8Value(frame->GetFunctionName()),
94 frame->GetLineNumber(), "%s",
95 *String::Utf8Value(args[2]));
96 return compatibility_return();
97 };
98
99 global->Set(name,
100 compatibility_new<FunctionTemplate>(isolate, print)
101 ->GetFunction());
102}
103
104EAPI
105void register_log_domain_register(v8::Isolate *isolate,
106 v8::Handle<v8::Object> global,
107 v8::Handle<v8::String> name)
108{
109 using v8::Value;
110 using v8::Local;
111 using v8::String;
112 using v8::FunctionTemplate;
113
114 auto f = [](compatibility_callback_info_type args)
115 -> compatibility_return_type {
116 if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString())
117 return compatibility_return();
118
119 // We duplicate the color string as eina takes a const char* but does take care of
120 // its lifetime, assuming a ever lasting string.
121 std::string color = *String::Utf8Value(args[1]);
122 int d = eina_log_domain_register(*String::Utf8Value(args[0]),
123 color.c_str());
124 js_eina_log_color_map[d] = color;
125
126 auto isolate = args.GetIsolate();
127 return compatibility_return(value_cast<Local<Value>>(d, isolate), args);
128 };
129
130 global->Set(name,
131 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
132}
133
134EAPI
135void register_log_domain_unregister(v8::Isolate *isolate,
136 v8::Handle<v8::Object> global,
137 v8::Handle<v8::String> name)
138{
139 using v8::Value;
140 using v8::FunctionTemplate;
141
142 auto f = [](compatibility_callback_info_type args)
143 -> compatibility_return_type {
144 if (args.Length() != 1 || !args[0]->IsNumber())
145 return compatibility_return();
146
147 int domain = args[0]->NumberValue();
148 eina_log_domain_unregister(domain);
149 js_eina_log_color_map.erase(domain);
150 return compatibility_return();
151 };
152
153 global->Set(name,
154 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
155}
156
157EAPI
158void register_log_domain_registered_level_get(v8::Isolate *isolate,
159 v8::Handle<v8::Object> global,
160 v8::Handle<v8::String> name)
161{
162 using v8::Value;
163 using v8::Local;
164 using v8::FunctionTemplate;
165
166 auto f = [](compatibility_callback_info_type args)
167 -> compatibility_return_type {
168 if (args.Length() != 1 || !args[0]->IsNumber())
169 return compatibility_return();
170
171 int l = eina_log_domain_registered_level_get(args[0]->NumberValue());
172 auto isolate = args.GetIsolate();
173 return compatibility_return(value_cast<Local<Value>>(l, isolate), args);
174 };
175
176 global->Set(name,
177 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
178}
179
180EAPI
181void register_log_domain_registered_level_set(v8::Isolate *isolate,
182 v8::Handle<v8::Object> global,
183 v8::Handle<v8::String> name)
184{
185 using v8::Value;
186 using v8::FunctionTemplate;
187
188 auto f = [](compatibility_callback_info_type args)
189 -> compatibility_return_type {
190 if (args.Length() != 2 || !args[0]->IsNumber() || !args[1]->IsNumber())
191 return compatibility_return();
192
193 eina_log_domain_registered_level_set(args[0]->NumberValue(),
194 args[1]->NumberValue());
195 return compatibility_return();
196 };
197
198 global->Set(name,
199 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
200}
201
202EAPI
203void register_log_print_cb_set(v8::Isolate *isolate,
204 v8::Handle<v8::Object> global,
205 v8::Handle<v8::String> name)
206{
207 using v8::Value;
208 using v8::FunctionTemplate;
209
210 auto f = [](compatibility_callback_info_type args)
211 -> compatibility_return_type {
212 if (args.Length() != 1 || !args[0]->IsFunction())
213 return compatibility_return();
214
215 js_eina_log_print_cb_data
216 = global_ref<v8::Value>(args.GetIsolate(), args[0]);
217 eina_log_print_cb_set(js_eina_log_print_cb, NULL);
218 return compatibility_return();
219 };
220
221 global->Set(name,
222 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
223}
224
225EAPI
226void register_log_level_set(v8::Isolate *isolate, v8::Handle<v8::Object> global,
227 v8::Handle<v8::String> name)
228{
229 using v8::Value;
230 using v8::FunctionTemplate;
231
232 auto f = [](compatibility_callback_info_type args)
233 -> compatibility_return_type {
234 if (args.Length() != 1 || !args[0]->IsNumber())
235 return compatibility_return();
236
237 eina_log_level_set(args[0]->NumberValue());
238 return compatibility_return();
239 };
240
241 global->Set(name,
242 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
243}
244
245EAPI
246void register_log_level_get(v8::Isolate *isolate, v8::Handle<v8::Object> global,
247 v8::Handle<v8::String> name)
248{
249 using v8::Value;
250 using v8::FunctionTemplate;
251 using v8::Integer;
252
253 auto f = [](compatibility_callback_info_type args)
254 -> compatibility_return_type {
255 if (args.Length() != 0)
256 return compatibility_return();
257
258 int l = eina_log_level_get();
259 auto ret = compatibility_new<Integer>(args.GetIsolate(), l);
260 return compatibility_return(ret, args);
261 };
262
263 global->Set(name,
264 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
265}
266
267EAPI
268void register_log_level_check(v8::Isolate *isolate,
269 v8::Handle<v8::Object> global,
270 v8::Handle<v8::String> name)
271{
272 using v8::Value;
273 using v8::FunctionTemplate;
274 using v8::Boolean;
275
276 auto f = [](compatibility_callback_info_type args)
277 -> compatibility_return_type {
278 if (args.Length() != 1 || !args[0]->IsNumber())
279 return compatibility_return();
280
281 bool b = eina_log_level_check(args[0]->NumberValue());
282 auto ret = compatibility_new<Boolean>(args.GetIsolate(), b);
283 return compatibility_return(ret, args);
284 };
285
286 global->Set(name,
287 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
288}
289
290EAPI
291void register_log_color_disable_set(v8::Isolate *isolate,
292 v8::Handle<v8::Object> global,
293 v8::Handle<v8::String> name)
294{
295 using v8::Value;
296 using v8::FunctionTemplate;
297
298 auto f = [](compatibility_callback_info_type args)
299 -> compatibility_return_type {
300 if (args.Length() != 1 || !args[0]->IsBoolean())
301 return compatibility_return();
302
303 eina_log_color_disable_set(args[0]->BooleanValue());
304 return compatibility_return();
305 };
306
307 global->Set(name,
308 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
309}
310
311EAPI
312void register_log_color_disable_get(v8::Isolate *isolate,
313 v8::Handle<v8::Object> global,
314 v8::Handle<v8::String> name)
315{
316 using v8::Value;
317 using v8::Boolean;
318 using v8::FunctionTemplate;
319
320 auto f = [](compatibility_callback_info_type args)
321 -> compatibility_return_type {
322 if (args.Length() != 0)
323 return compatibility_return();
324
325 bool b = eina_log_color_disable_get();
326 auto ret = compatibility_new<Boolean>(args.GetIsolate(), b);
327 return compatibility_return(ret, args);
328 };
329
330 global->Set(name,
331 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
332}
333
334EAPI
335void register_log_file_disable_set(v8::Isolate *isolate,
336 v8::Handle<v8::Object> global,
337 v8::Handle<v8::String> name)
338{
339 using v8::Value;
340 using v8::FunctionTemplate;
341
342 auto f = [](compatibility_callback_info_type args)
343 -> compatibility_return_type {
344 if (args.Length() != 1 || !args[0]->IsBoolean())
345 return compatibility_return();
346
347 eina_log_file_disable_set(args[0]->BooleanValue());
348 return compatibility_return();
349 };
350
351 global->Set(name,
352 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
353}
354
355EAPI
356void register_log_file_disable_get(v8::Isolate *isolate,
357 v8::Handle<v8::Object> global,
358 v8::Handle<v8::String> name)
359{
360 using v8::Value;
361 using v8::Boolean;
362 using v8::FunctionTemplate;
363
364 auto f = [](compatibility_callback_info_type args)
365 -> compatibility_return_type {
366 if (args.Length() != 0)
367 return compatibility_return();
368
369 bool b = eina_log_file_disable_get();
370 auto ret = compatibility_new<Boolean>(args.GetIsolate(), b);
371 return compatibility_return(ret, args);
372 };
373
374 global->Set(name,
375 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
376}
377
378EAPI
379void register_log_function_disable_set(v8::Isolate *isolate,
380 v8::Handle<v8::Object> global,
381 v8::Handle<v8::String> name)
382{
383 using v8::Value;
384 using v8::FunctionTemplate;
385
386 auto f = [](compatibility_callback_info_type args)
387 -> compatibility_return_type {
388 if (args.Length() != 1 || !args[0]->IsBoolean())
389 return compatibility_return();
390
391 eina_log_function_disable_set(args[0]->BooleanValue());
392 return compatibility_return();
393 };
394
395 global->Set(name,
396 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
397}
398
399EAPI
400void register_log_function_disable_get(v8::Isolate *isolate,
401 v8::Handle<v8::Object> global,
402 v8::Handle<v8::String> name)
403{
404 using v8::Value;
405 using v8::Boolean;
406 using v8::FunctionTemplate;
407
408 auto f = [](compatibility_callback_info_type args)
409 -> compatibility_return_type {
410 if (args.Length() != 0)
411 return compatibility_return();
412
413 bool b = eina_log_function_disable_get();
414 auto ret = compatibility_new<Boolean>(args.GetIsolate(), b);
415 return compatibility_return(ret, args);
416 };
417
418 global->Set(name,
419 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
420}
421
422EAPI
423void register_log_abort_on_critical_set(v8::Isolate *isolate,
424 v8::Handle<v8::Object> global,
425 v8::Handle<v8::String> name)
426{
427 using v8::Value;
428 using v8::FunctionTemplate;
429
430 auto f = [](compatibility_callback_info_type args)
431 -> compatibility_return_type {
432 if (args.Length() != 1 || !args[0]->IsBoolean())
433 return compatibility_return();
434
435 eina_log_abort_on_critical_set(args[0]->BooleanValue());
436 return compatibility_return();
437 };
438
439 global->Set(name,
440 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
441}
442
443EAPI
444void register_log_abort_on_critical_get(v8::Isolate *isolate,
445 v8::Handle<v8::Object> global,
446 v8::Handle<v8::String> name)
447{
448 using v8::Value;
449 using v8::Boolean;
450 using v8::FunctionTemplate;
451
452 auto f = [](compatibility_callback_info_type args)
453 -> compatibility_return_type {
454 if (args.Length() != 0)
455 return compatibility_return();
456
457 bool b = eina_log_abort_on_critical_get();
458 auto ret = compatibility_new<Boolean>(args.GetIsolate(), b);
459 return compatibility_return(ret, args);
460 };
461
462 global->Set(name,
463 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
464}
465
466EAPI
467void register_log_abort_on_critical_level_set(v8::Isolate *isolate,
468 v8::Handle<v8::Object> global,
469 v8::Handle<v8::String> name)
470{
471 using v8::Value;
472 using v8::FunctionTemplate;
473
474 auto f = [](compatibility_callback_info_type args)
475 -> compatibility_return_type {
476 if (args.Length() != 1 || !args[0]->IsNumber())
477 return compatibility_return();
478
479 eina_log_abort_on_critical_level_set(args[0]->NumberValue());
480 return compatibility_return();
481 };
482
483 global->Set(name,
484 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
485}
486
487EAPI
488void register_log_abort_on_critical_level_get(v8::Isolate *isolate,
489 v8::Handle<v8::Object> global,
490 v8::Handle<v8::String> name)
491{
492 using v8::Value;
493 using v8::FunctionTemplate;
494 using v8::Integer;
495
496 auto f = [](compatibility_callback_info_type args)
497 -> compatibility_return_type {
498 if (args.Length() != 0)
499 return compatibility_return();
500
501 int l = eina_log_abort_on_critical_level_get();
502 auto ret = compatibility_new<Integer>(args.GetIsolate(), l);
503 return compatibility_return(ret, args);
504 };
505
506 global->Set(name,
507 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
508}
509
510EAPI
511void register_log_domain_level_set(v8::Isolate *isolate,
512 v8::Handle<v8::Object> global,
513 v8::Handle<v8::String> name)
514{
515 using v8::Value;
516 using v8::FunctionTemplate;
517 using v8::String;
518
519 auto f = [](compatibility_callback_info_type args)
520 -> compatibility_return_type {
521 if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsNumber())
522 return compatibility_return();
523
524 eina_log_domain_level_set(*String::Utf8Value(args[0]),
525 args[1]->NumberValue());
526 return compatibility_return();
527 };
528
529 global->Set(name,
530 compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
531}