summaryrefslogtreecommitdiff
path: root/src/bindings/js
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousasilva@gmail.com>2016-03-16 19:46:22 -0300
committerVitor Sousa <vitorsousasilva@gmail.com>2016-03-18 17:47:09 -0300
commitafb66463937a8d08e2bf1d538641a9520ba457d6 (patch)
tree10a0a55ee9301ef195434a4411b7b0af02793365 /src/bindings/js
parenta6025b5d27f98b8595a1eb33f8f24fe998af8b90 (diff)
efl js: Add clean up callbacks to deallocate memory used in v8::External
Add several garbage collector callbacks for cleaning allocated C and C++ data used inside v8:External objects. Fix eo_unref of already freed object in eo_js_construct_from_eo.hh. Ensure all structs are allocated with malloc. Add test for garbage collection. Had to created .sh script because shebang clause do not support multiple arguments.
Diffstat (limited to 'src/bindings/js')
-rw-r--r--src/bindings/js/eina_js/eina_js_compatibility.hh5
-rw-r--r--src/bindings/js/eina_js/eina_js_container.cc16
-rw-r--r--src/bindings/js/eina_js/eina_js_container.hh5
-rw-r--r--src/bindings/js/eina_js/eina_js_get_value_from_c.hh89
-rw-r--r--src/bindings/js/eina_js/eina_js_value.cc3
-rw-r--r--src/bindings/js/eo_js/eo_js_construct_from_eo.hh1
-rw-r--r--src/bindings/js/eo_js/eo_js_event.hh1
-rw-r--r--src/bindings/js/eo_js/eo_js_struct.hh6
8 files changed, 101 insertions, 25 deletions
diff --git a/src/bindings/js/eina_js/eina_js_compatibility.hh b/src/bindings/js/eina_js/eina_js_compatibility.hh
index fb36e4ee3d..7a4671424c 100644
--- a/src/bindings/js/eina_js/eina_js_compatibility.hh
+++ b/src/bindings/js/eina_js/eina_js_compatibility.hh
@@ -927,8 +927,9 @@ compatibility_return_type cast_function(compatibility_callback_info_type args)
927 char* class_name = *str; 927 char* class_name = *str;
928 928
929 auto ctor = ::efl::eina::js::get_class_constructor(class_name); 929 auto ctor = ::efl::eina::js::get_class_constructor(class_name);
930 return compatibility_return 930 auto obj = new_v8_external_instance(ctor, ::eo_ref(eo), isolate);
931 (new_v8_external_instance(ctor, ::eo_ref(eo), isolate), args); 931 efl::eina::js::make_weak(isolate, obj, [eo]{ ::eo_unref(eo); });
932 return compatibility_return(obj, args);
932 } 933 }
933 else 934 else
934 { 935 {
diff --git a/src/bindings/js/eina_js/eina_js_container.cc b/src/bindings/js/eina_js/eina_js_container.cc
index 60c53e0e74..82246c5fcb 100644
--- a/src/bindings/js/eina_js/eina_js_container.cc
+++ b/src/bindings/js/eina_js/eina_js_container.cc
@@ -54,11 +54,14 @@ v8::Local<v8::Value> concat(eina_container_base& lhs, v8::Isolate* isolate, v8::
54 , &typeinfo_rhs = typeid(rhs); 54 , &typeinfo_rhs = typeid(rhs);
55 if(!typeinfo_lhs.before(typeinfo_rhs) && !typeinfo_rhs.before(typeinfo_lhs)) 55 if(!typeinfo_lhs.before(typeinfo_rhs) && !typeinfo_rhs.before(typeinfo_lhs))
56 { 56 {
57 auto ptr = rhs.concat(lhs);
57 v8::Handle<v8::Value> a[] = 58 v8::Handle<v8::Value> a[] =
58 {efl::eina::js::compatibility_new<v8::External>(isolate, rhs.concat(lhs))}; 59 {efl::eina::js::compatibility_new<v8::External>(isolate, ptr)};
59 assert(!!*instance_templates[lhs.get_container_type()].handle()); 60 assert(!!*instance_templates[lhs.get_container_type()].handle());
60 v8::Local<v8::Object> result = 61 v8::Local<v8::Object> result =
61 instance_templates[lhs.get_container_type()].handle()->NewInstance(1, a); 62 instance_templates[lhs.get_container_type()].handle()->NewInstance(1, a);
63 if (ptr)
64 efl::eina::js::make_weak(isolate, result, [ptr]{ delete ptr; });
62 return result; 65 return result;
63 } 66 }
64 else 67 else
@@ -95,9 +98,12 @@ v8::Local<v8::Value> slice(eina_container_base& self, v8::Isolate* isolate, v8::
95 else 98 else
96 return v8::Undefined(isolate); 99 return v8::Undefined(isolate);
97 100
98 v8::Handle<v8::Value> a[] = {efl::eina::js::compatibility_new<v8::External>(isolate, self.slice(i, j))}; 101 auto ptr = self.slice(i, j);
102 v8::Handle<v8::Value> a[] = {efl::eina::js::compatibility_new<v8::External>(isolate, ptr)};
99 v8::Local<v8::Object> result = instance_templates[self.get_container_type()].handle() 103 v8::Local<v8::Object> result = instance_templates[self.get_container_type()].handle()
100 ->NewInstance(1, a); 104 ->NewInstance(1, a);
105 if (ptr)
106 efl::eina::js::make_weak(isolate, result, [ptr]{ delete ptr; });
101 return result; 107 return result;
102} 108}
103 109
@@ -154,6 +160,7 @@ compatibility_return_type new_eina_list_internal(compatibility_callback_info_typ
154 eina_container_base* p = new eina_list<int>; 160 eina_container_base* p = new eina_list<int>;
155 compatibility_set_pointer_internal_field 161 compatibility_set_pointer_internal_field
156 (args.This(), 0, dynamic_cast<void*>(p)); 162 (args.This(), 0, dynamic_cast<void*>(p));
163 efl::eina::js::make_weak(args.GetIsolate(), args.This(), [p]{ delete p; });
157 } 164 }
158 else 165 else
159 { 166 {
@@ -182,6 +189,7 @@ compatibility_return_type new_eina_list(compatibility_callback_info_type args)
182 eina_container_base* p = new eina_list<int>; 189 eina_container_base* p = new eina_list<int>;
183 compatibility_set_pointer_internal_field 190 compatibility_set_pointer_internal_field
184 (args.This(), 0, dynamic_cast<void*>(p)); 191 (args.This(), 0, dynamic_cast<void*>(p));
192 efl::eina::js::make_weak(args.GetIsolate(), args.This(), [p]{ delete p; });
185 return compatibility_return(); 193 return compatibility_return();
186 } 194 }
187 else if (args.Length() == 1 && args[0]->IsString()) 195 else if (args.Length() == 1 && args[0]->IsString())
@@ -195,6 +203,7 @@ compatibility_return_type new_eina_list(compatibility_callback_info_type args)
195 } 203 }
196 compatibility_set_pointer_internal_field 204 compatibility_set_pointer_internal_field
197 (args.This(), 0, dynamic_cast<void*>(p)); 205 (args.This(), 0, dynamic_cast<void*>(p));
206 efl::eina::js::make_weak(args.GetIsolate(), args.This(), [p]{ delete p; });
198 return compatibility_return(); 207 return compatibility_return();
199 } 208 }
200 } 209 }
@@ -212,6 +221,7 @@ compatibility_return_type new_eina_array_internal(compatibility_callback_info_ty
212 eina_container_base* p = new eina_array<int>; 221 eina_container_base* p = new eina_array<int>;
213 compatibility_set_pointer_internal_field 222 compatibility_set_pointer_internal_field
214 (args.This(), 0, dynamic_cast<void*>(p)); 223 (args.This(), 0, dynamic_cast<void*>(p));
224 efl::eina::js::make_weak(args.GetIsolate(), args.This(), [p]{ delete p; });
215 } 225 }
216 else 226 else
217 { 227 {
@@ -240,6 +250,7 @@ compatibility_return_type new_eina_array(compatibility_callback_info_type args)
240 eina_container_base* p = new eina_array<int>; 250 eina_container_base* p = new eina_array<int>;
241 compatibility_set_pointer_internal_field 251 compatibility_set_pointer_internal_field
242 (args.This(), 0, dynamic_cast<void*>(p)); 252 (args.This(), 0, dynamic_cast<void*>(p));
253 efl::eina::js::make_weak(args.GetIsolate(), args.This(), [p]{ delete p; });
243 return compatibility_return(); 254 return compatibility_return();
244 } 255 }
245 else if (args.Length() == 1 && args[0]->IsString()) 256 else if (args.Length() == 1 && args[0]->IsString())
@@ -253,6 +264,7 @@ compatibility_return_type new_eina_array(compatibility_callback_info_type args)
253 } 264 }
254 compatibility_set_pointer_internal_field 265 compatibility_set_pointer_internal_field
255 (args.This(), 0, dynamic_cast<void*>(p)); 266 (args.This(), 0, dynamic_cast<void*>(p));
267 efl::eina::js::make_weak(args.GetIsolate(), args.This(), [p]{ delete p; });
256 return compatibility_return(); 268 return compatibility_return();
257 } 269 }
258 } 270 }
diff --git a/src/bindings/js/eina_js/eina_js_container.hh b/src/bindings/js/eina_js/eina_js_container.hh
index 21343fd6da..62fe22c0cd 100644
--- a/src/bindings/js/eina_js/eina_js_container.hh
+++ b/src/bindings/js/eina_js/eina_js_container.hh
@@ -273,6 +273,11 @@ struct eina_container_common : eina_container_type_specific<C, typename C::value
273 (eina::js::compatibility_new<v8::String>(isolate, "Indexed attribution was not implemented."))); 273 (eina::js::compatibility_new<v8::String>(isolate, "Indexed attribution was not implemented.")));
274 return v8::Undefined(isolate); 274 return v8::Undefined(isolate);
275 } 275 }
276
277 typename C::native_handle_type release_native_handle()
278 {
279 return _container.release_native_handle();
280 }
276 C _container; 281 C _container;
277 typedef C container_type; 282 typedef C container_type;
278}; 283};
diff --git a/src/bindings/js/eina_js/eina_js_get_value_from_c.hh b/src/bindings/js/eina_js/eina_js_get_value_from_c.hh
index 204c497431..653a96ebaf 100644
--- a/src/bindings/js/eina_js/eina_js_get_value_from_c.hh
+++ b/src/bindings/js/eina_js/eina_js_get_value_from_c.hh
@@ -143,7 +143,9 @@ inline v8::Local<v8::Value>
143get_value_from_c(Eo* v, v8::Isolate* isolate, const char* class_name) 143get_value_from_c(Eo* v, v8::Isolate* isolate, const char* class_name)
144{ 144{
145 auto ctor = ::efl::eina::js::get_class_constructor(class_name); 145 auto ctor = ::efl::eina::js::get_class_constructor(class_name);
146 return new_v8_external_instance(ctor, v, isolate); 146 auto obj = new_v8_external_instance(ctor, ::eo_ref(v), isolate);
147 efl::eina::js::make_weak(isolate, obj, [v]{ ::eo_unref(v); });
148 return obj;
147} 149}
148 150
149inline v8::Local<v8::Value> 151inline v8::Local<v8::Value>
@@ -151,23 +153,32 @@ get_value_from_c(const Eo* v, v8::Isolate* isolate, const char* class_name)
151{ 153{
152 // TODO: implement const objects? 154 // TODO: implement const objects?
153 auto ctor = ::efl::eina::js::get_class_constructor(class_name); 155 auto ctor = ::efl::eina::js::get_class_constructor(class_name);
154 return new_v8_external_instance(ctor, const_cast<Eo*>(v), isolate); 156 auto obj = new_v8_external_instance(ctor, ::eo_ref(v), isolate);
157 efl::eina::js::make_weak(isolate, obj, [v]{ ::eo_unref(v); });
158 return obj;
155} 159}
156 160
157template <typename T> 161template <typename T>
158inline v8::Local<v8::Value> 162inline v8::Local<v8::Value>
159get_value_from_c(struct_ptr_tag<T> v, v8::Isolate* isolate, const char* class_name) 163get_value_from_c(struct_ptr_tag<T*> v, v8::Isolate* isolate, const char* class_name)
160{ 164{
161 // TODO: implement const structs? 165 using nonconst_type = typename std::remove_const<T>::type;
166 bool own = false; // TODO: handle ownership
167 auto ptr = const_cast<nonconst_type*>(v.value);
162 auto ctor = ::efl::eina::js::get_class_constructor(class_name); 168 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); 169 auto obj = new_v8_external_instance(ctor, ptr, isolate);
170 if (own)
171 efl::eina::js::make_weak(isolate, obj, [ptr]{ free(ptr); });
172 return obj;
164} 173}
165 174
166template <typename T> 175template <typename T>
167inline v8::Local<v8::Value> 176inline v8::Local<v8::Value>
168get_value_from_c(struct_tag<T> v, v8::Isolate* isolate, const char* class_name) 177get_value_from_c(struct_tag<T> v, v8::Isolate* isolate, const char* class_name)
169{ 178{
170 return get_value_from_c(struct_ptr_tag<T*>{new T(v.value)}, isolate, class_name); 179 T* s = static_cast<T*>(malloc(sizeof(T)));
180 *s = v.value;
181 return get_value_from_c(struct_ptr_tag<T*>{s}, isolate, class_name);
171} 182}
172 183
173template <typename T, typename K> 184template <typename T, typename K>
@@ -175,8 +186,16 @@ inline v8::Local<v8::Value>
175get_value_from_c(efl::eina::js::complex_tag<Eina_Accessor *, T, K> v, v8::Isolate* isolate, const char*) 186get_value_from_c(efl::eina::js::complex_tag<Eina_Accessor *, T, K> v, v8::Isolate* isolate, const char*)
176{ 187{
177 using wrapped_type = typename container_wrapper<T>::type; 188 using wrapped_type = typename container_wrapper<T>::type;
189 bool own = false; // TODO: handle ownership
178 auto a = new ::efl::eina::accessor<wrapped_type>{v.value}; 190 auto a = new ::efl::eina::accessor<wrapped_type>{v.value};
179 return export_accessor<T>(*a , isolate, K::class_name()); 191 auto obj = export_accessor<T>(*a , isolate, K::class_name());
192 efl::eina::js::make_weak(isolate, obj, [a, own]
193 {
194 if (!own)
195 a->release_native_handle();
196 delete a;
197 });
198 return obj;
180} 199}
181 200
182template <typename T, typename K> 201template <typename T, typename K>
@@ -191,18 +210,34 @@ template <typename T, typename K>
191inline v8::Local<v8::Value> 210inline v8::Local<v8::Value>
192get_value_from_c(efl::eina::js::complex_tag<Eina_Array *, T, K> v, v8::Isolate* isolate, const char*) 211get_value_from_c(efl::eina::js::complex_tag<Eina_Array *, T, K> v, v8::Isolate* isolate, const char*)
193{ 212{
194 // TODO: use unique_ptr for eina_array to avoid leak ? 213 bool own = false; // TODO: handle ownership
195 auto o = new ::efl::eina::js::range_eina_array<T, K>(v.value); 214 auto o = new ::efl::eina::js::eina_array<T, K>(v.value);
196 auto ctor = get_array_instance_template(); 215 auto ctor = get_array_instance_template();
197 return new_v8_external_instance(ctor, o, isolate); 216 auto obj = new_v8_external_instance(ctor, o, isolate);
217 efl::eina::js::make_weak(isolate, obj, [o, own]
218 {
219 if (!own)
220 o->release_native_handle();
221 delete o;
222 });
223 return obj;
198} 224}
199 225
200template <typename T, typename K> 226template <typename T, typename K>
201inline v8::Local<v8::Value> 227inline 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) 228get_value_from_c(efl::eina::js::complex_tag<const Eina_Array *, T, K> v, v8::Isolate* isolate, const char*)
203{ 229{
204 // TODO: implement const array? 230 bool own = false; // TODO: handle ownership
205 return get_value_from_c(efl::eina::js::complex_tag<Eina_Array *, T, K>{const_cast<Eina_Array*>(v.value)}, isolate, class_name); 231 auto o = new ::efl::eina::js::range_eina_array<T, K>(const_cast<Eina_Array*>(v.value));
232 auto ctor = get_array_instance_template();
233 auto obj = new_v8_external_instance(ctor, o, isolate);
234 efl::eina::js::make_weak(isolate, obj, [o, own]
235 {
236 if (!own)
237 o->release_native_handle();
238 delete o;
239 });
240 return obj;
206} 241}
207 242
208template <typename T, typename K> 243template <typename T, typename K>
@@ -245,18 +280,34 @@ template <typename T, typename K>
245inline v8::Local<v8::Value> 280inline v8::Local<v8::Value>
246get_value_from_c(efl::eina::js::complex_tag<Eina_List *, T, K> v, v8::Isolate* isolate, const char*) 281get_value_from_c(efl::eina::js::complex_tag<Eina_List *, T, K> v, v8::Isolate* isolate, const char*)
247{ 282{
248 // TODO: ensure eina_list ownership ??? 283 bool own = false; // TODO: handle ownership
249 auto o = new ::efl::eina::js::range_eina_list<T, K>(v.value); 284 auto o = new ::efl::eina::js::eina_list<T, K>(v.value);
250 auto ctor = get_list_instance_template(); 285 auto ctor = get_list_instance_template();
251 return new_v8_external_instance(ctor, o, isolate); 286 auto obj = new_v8_external_instance(ctor, o, isolate);
287 efl::eina::js::make_weak(isolate, obj, [o, own]
288 {
289 if (!own)
290 o->release_native_handle();
291 delete o;
292 });
293 return obj;
252} 294}
253 295
254template <typename T, typename K> 296template <typename T, typename K>
255inline v8::Local<v8::Value> 297inline v8::Local<v8::Value>
256get_value_from_c(efl::eina::js::complex_tag<const Eina_List *, T, K> v, v8::Isolate* isolate, const char* class_name) 298get_value_from_c(efl::eina::js::complex_tag<const Eina_List *, T, K> v, v8::Isolate* isolate, const char*)
257{ 299{
258 // TODO: implement const list? 300 bool own = false; // TODO: handle ownership
259 return get_value_from_c(efl::eina::js::complex_tag<Eina_List *, T, K>{const_cast<Eina_List*>(v.value)}, isolate, class_name); 301 auto o = new ::efl::eina::js::range_eina_list<T, K>(const_cast<Eina_List*>(v.value));
302 auto ctor = get_list_instance_template();
303 auto obj = new_v8_external_instance(ctor, o, isolate);
304 efl::eina::js::make_weak(isolate, obj, [o, own]
305 {
306 if (!own)
307 o->release_native_handle();
308 delete o;
309 });
310 return obj;
260} 311}
261 312
262 313
diff --git a/src/bindings/js/eina_js/eina_js_value.cc b/src/bindings/js/eina_js/eina_js_value.cc
index 5b5b822160..c7377ae857 100644
--- a/src/bindings/js/eina_js/eina_js_value.cc
+++ b/src/bindings/js/eina_js/eina_js_value.cc
@@ -54,6 +54,9 @@ compatibility_return_type eina_value_constructor(compatibility_callback_info_typ
54 std::unique_ptr<value> 54 std::unique_ptr<value>
55 ptr(new value(value_cast<value>(args[0]))); 55 ptr(new value(value_cast<value>(args[0])));
56 compatibility_set_pointer_internal_field(args.This(), 0, ptr.get()); 56 compatibility_set_pointer_internal_field(args.This(), 0, ptr.get());
57 auto v = ptr.get();
58 if (v)
59 efl::eina::js::make_weak(isolate, args.This(), [v]{ delete v; });
57 ptr.release(); 60 ptr.release();
58 } catch(const std::bad_cast &e) { 61 } catch(const std::bad_cast &e) {
59 v8::Local<v8::Object> je = compatibility_new<v8::Object>(isolate); 62 v8::Local<v8::Object> je = compatibility_new<v8::Object>(isolate);
diff --git a/src/bindings/js/eo_js/eo_js_construct_from_eo.hh b/src/bindings/js/eo_js/eo_js_construct_from_eo.hh
index 287aaa748c..8008d16892 100644
--- a/src/bindings/js/eo_js/eo_js_construct_from_eo.hh
+++ b/src/bindings/js/eo_js/eo_js_construct_from_eo.hh
@@ -20,6 +20,7 @@ inline eina::js::compatibility_return_type construct_from_eo(eina::js::compatibi
20 { 20 {
21 Eo* eo = static_cast<Eo*>(v8::External::Cast(*args[0])->Value()); 21 Eo* eo = static_cast<Eo*>(v8::External::Cast(*args[0])->Value());
22 args.This()->SetInternalField(0, args[0]); 22 args.This()->SetInternalField(0, args[0]);
23 ::eo_ref(eo);
23 efl::eina::js::make_weak(args.GetIsolate(), args.This(), [eo] { eo_unref(eo); }); 24 efl::eina::js::make_weak(args.GetIsolate(), args.This(), [eo] { eo_unref(eo); });
24 return eina::js::compatibility_return(); 25 return eina::js::compatibility_return();
25 } 26 }
diff --git a/src/bindings/js/eo_js/eo_js_event.hh b/src/bindings/js/eo_js/eo_js_event.hh
index 280aeacae6..b589e5d6cc 100644
--- a/src/bindings/js/eo_js/eo_js_event.hh
+++ b/src/bindings/js/eo_js/eo_js_event.hh
@@ -100,6 +100,7 @@ inline eina::js::compatibility_return_type on_event(eina::js::compatibility_call
100 event_callback_information* i = new event_callback_information 100 event_callback_information* i = new event_callback_information
101 {event, {isolate, eina::js::compatibility_cast<v8::Function>(f)}}; 101 {event, {isolate, eina::js::compatibility_cast<v8::Function>(f)}};
102 eo_event_callback_add(eo, event->event, event->event_callback, i); 102 eo_event_callback_add(eo, event->event, event->event_callback, i);
103 efl::eina::js::make_weak(isolate, self, [i]{ delete i; });
103 } 104 }
104 else 105 else
105 { 106 {
diff --git a/src/bindings/js/eo_js/eo_js_struct.hh b/src/bindings/js/eo_js/eo_js_struct.hh
index 731f9d093c..eba0c74d37 100644
--- a/src/bindings/js/eo_js/eo_js_struct.hh
+++ b/src/bindings/js/eo_js/eo_js_struct.hh
@@ -42,8 +42,10 @@ eina::js::compatibility_return_type new_struct(eina::js::compatibility_callback_
42 42
43 if(args.Length() == 0) 43 if(args.Length() == 0)
44 { 44 {
45 S* p = new S{}; 45 void* p = std::malloc(sizeof(S));
46 eina::js::compatibility_set_pointer_internal_field(args.This(), 0, static_cast<void*>(p)); 46 std::memset(p, 0, sizeof(S));
47 eina::js::compatibility_set_pointer_internal_field(args.This(), 0, p);
48 efl::eina::js::make_weak(args.GetIsolate(), args.This(), [p]{ free(p); });
47 } 49 }
48 else 50 else
49 { 51 {