1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 
5 #include <Eina_Js.hh>
6 
7 namespace efl { namespace eina { namespace js {
8 
9 namespace {
10 
eina_value_set(compatibility_callback_info_type args)11 compatibility_return_type eina_value_set(compatibility_callback_info_type args)
12 {
13   if (args.Length() != 1)
14     return compatibility_return();
15 
16   void *ptr = js::compatibility_get_pointer_internal_field(args.Holder(), 0);
17   v8::Isolate *isolate = args.GetIsolate();
18   try {
19     *static_cast<value*>(ptr) = value_cast<value>(args[0]);
20   } catch(const std::bad_cast &e) {
21     v8::Local<v8::Object> je = compatibility_new<v8::Object>(isolate);
22     je->Set(compatibility_new<v8::String>(isolate, "code"),
23             compatibility_new<v8::String>(isolate, "std::bad_cast"));
24     return compatibility_throw(isolate, je);
25   } catch(const ::efl::eina::system_error &e) {
26     v8::Local<v8::Object> je = compatibility_new<v8::Object>(isolate);
27     je->Set(compatibility_new<v8::String>(isolate, "code"),
28             compatibility_new<v8::String>(isolate, "std::error_code"));
29     je->Set(compatibility_new<v8::String>(isolate, "category"),
30             compatibility_new<v8::String>(isolate, e.code().category().name()));
31     je->Set(compatibility_new<v8::String>(isolate, "value"),
32             compatibility_new<v8::Integer>(isolate, e.code().value()));
33     return compatibility_throw(isolate, je);
34   }
35   return compatibility_return();
36 }
37 
eina_value_get(compatibility_callback_info_type args)38 compatibility_return_type eina_value_get(compatibility_callback_info_type args)
39 {
40   void *ptr = compatibility_get_pointer_internal_field(args.Holder(), 0);
41   auto &value = *static_cast<eina::value*>(ptr);
42   return compatibility_return
43     (value_cast<v8::Local<v8::Value>>(value, args.GetIsolate()), args);
44 }
45 
eina_value_constructor(compatibility_callback_info_type args)46 compatibility_return_type eina_value_constructor(compatibility_callback_info_type args)
47 {
48   if (args.Length() != 1)
49     return compatibility_return();
50 
51   v8::Isolate* isolate = args.GetIsolate();
52 
53   try {
54     std::unique_ptr<value>
55       ptr(new value(value_cast<value>(args[0])));
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; });
60     ptr.release();
61   } catch(const std::bad_cast &e) {
62     v8::Local<v8::Object> je = compatibility_new<v8::Object>(isolate);
63     je->Set(compatibility_new<v8::String>(isolate, "code"),
64             compatibility_new<v8::String>(isolate, "std::bad_cast"));
65     return compatibility_throw(isolate,je);
66   } catch(const ::efl::eina::system_error &e) {
67     v8::Local<v8::Object> je = compatibility_new<v8::Object>(isolate);
68     je->Set(compatibility_new<v8::String>(isolate, "code"),
69             compatibility_new<v8::String>(isolate, "std::error_code"));
70     je->Set(compatibility_new<v8::String>(isolate, "category"),
71             compatibility_new<v8::String>(isolate, e.code().category().name()));
72     je->Set(compatibility_new<v8::String>(isolate, "value"),
73             compatibility_new<v8::Integer>(isolate, e.code().value()));
74     return compatibility_throw(isolate, je);
75   }
76   // makeweak
77   // {
78   //     typedef global_ref<v8::Object> persistent_t;
79   //     typedef v8::WeakCallbackData<v8::Object, persistent_t> cb_type;
80 
81   //     auto on_gc = [](const cb_type &data) {
82   //         typedef ::efl::eina::value value_type;
83   //         typedef value_type *ptr_type;
84 
85   //         auto o = data.GetValue();
86   //         delete static_cast<ptr_type>
87   //             (compatibility_get_pointer_internal_field(o, 0));
88   //         compatibility_set_pointer_internal_field<void*>(o, 0, nullptr);
89 
90   //         delete data.GetParameter();
91   //     };
92 
93   //     auto persistent = new persistent_t(isolate, args.This());
94   //     persistent->SetWeak<v8::Object>(persistent, on_gc);
95   // }
96 }
97 
98 }
99 
100 EAPI
register_value(v8::Isolate * isolate,v8::Handle<v8::Object> global,v8::Handle<v8::String> name)101 void register_value(v8::Isolate *isolate, v8::Handle<v8::Object> global,
102                          v8::Handle<v8::String> name)
103 {
104   using v8::Isolate;
105   using v8::Local;
106   using v8::Value;
107   using v8::Integer;
108   using v8::String;
109   using v8::Object;
110   using v8::FunctionTemplate;
111   using v8::FunctionCallbackInfo;
112 
113   v8::Local<v8::FunctionTemplate> constructor = compatibility_new<v8::FunctionTemplate>(isolate, &eina_value_constructor);
114 
115   v8::Local<v8::ObjectTemplate> instance = constructor->InstanceTemplate();
116   instance->SetInternalFieldCount(1);
117 
118   auto prototype = constructor->PrototypeTemplate();
119 
120   prototype->Set(compatibility_new<v8::String>(isolate, "set")
121                  , compatibility_new<FunctionTemplate>(isolate, &eina_value_set));
122   prototype->Set(compatibility_new<v8::String>(isolate, "get")
123                  , compatibility_new<FunctionTemplate>(isolate, &eina_value_get));
124 
125   global->Set(name, constructor->GetFunction());
126 }
127 
128 } } } // namespace efl { namespace js {
129 
130 EAPI
eina_value_register(v8::Handle<v8::Object> global,v8::Isolate * isolate)131 void eina_value_register(v8::Handle<v8::Object> global, v8::Isolate* isolate)
132 {
133   efl::eina::js::register_value(isolate, global
134                                 , efl::eina::js::compatibility_new<v8::String>(isolate, "value"));
135 }
136