#ifndef EFL_EO_JS_EVENT_HH #define EFL_EO_JS_EVENT_HH #include #include #include #include #include #include #include #include #include namespace efl { namespace eo { namespace js { struct event_information { eina::js::global_ref* constructor; Eo_Event_Description const* event; Eo_Event_Cb event_callback; const char* class_name; }; typedef std::map event_information_map; struct event_callback_information { event_information* event_info; eina::js::global_ref function; }; template v8::Local get_event_info(void* event_info, v8::Isolate* isolate, const char* class_name) { using no_tag_type = typename eina::js::remove_tag::type; return eina::js::get_value_from_c( eina::js::wrap_value(*static_cast(event_info), eina::js::value_tag{}), isolate, class_name); } // FIXME: This shouldn't be necessary. Reveiew Eolian standards. template <> inline v8::Local get_event_info(void* event_info, v8::Isolate* isolate, const char*) { return eina::js::get_value_from_c(static_cast(event_info), isolate, ""); } template <> inline v8::Local get_event_info(void*, v8::Isolate* isolate, const char*) { return v8::Undefined(isolate); } template inline Eina_Bool event_callback(void* data, Eo_Event const* eo_event) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope handle_scope(isolate); event_callback_information* event = static_cast(data); v8::Handle a[] = {eina::js::compatibility_new(isolate, eo_event->obj)}; v8::Local self = (event->info->constructor->handle())->NewInstance(1, a); v8::Local call_args[] = { self, get_event_info(eo_event->info, isolate, event->info->class_name) }; event->function.handle()->Call(eina::js::compatibility_global(), 2, call_args); return EO_CALLBACK_CONTINUE; } inline eina::js::compatibility_return_type on_event(eina::js::compatibility_callback_info_type args) { if (args.Length() >= 2) { v8::Local ev_name = args[0]; v8::Local f = args[1]; if (ev_name->IsString() && f->IsFunction()) { v8::Local data = args.Data(); auto ev_map = static_cast (v8::External::Cast(*data)->Value()); v8::String::Utf8Value str(ev_name->ToString()); auto found = ev_map->find(*str); if (found == ev_map->end()) return eina::js::compatibility_return(); auto event = found->second; v8::Local self = args.This(); v8::Local external = self->GetInternalField(0); Eo* eo = static_cast(v8::External::Cast(*external)->Value()); auto isolate = args.GetIsolate(); event_callback_information* i = new event_callback_information {event, {isolate, eina::js::compatibility_cast(f)}}; eo_event_callback_add(eo, event->event, event->event_callback, i); efl::eina::js::make_weak(isolate, self, [i]{ delete i; }); } else { eina::js::compatibility_throw (v8::Exception::TypeError (eina::js::compatibility_new(args.GetIsolate(), "Invalid argument type"))); throw std::logic_error(""); } } else { eina::js::compatibility_throw (v8::Exception::TypeError (eina::js::compatibility_new(args.GetIsolate(), "Expected more arguments for this call"))); throw std::logic_error(""); } return eina::js::compatibility_return(); } } } } #endif